Merge remote-tracking branch 'origin/develop' into port/client_ts

This commit is contained in:
Elian Doran
2025-02-24 10:14:46 +02:00
338 changed files with 8874 additions and 2488 deletions

View File

@@ -12,6 +12,7 @@ import type { AttachmentRow, BlobRow, RevisionRow } from "./entities/rows.js";
import BBlob from "./entities/bblob.js";
import BRecentNote from "./entities/brecent_note.js";
import type AbstractBeccaEntity from "./entities/abstract_becca_entity.js";
import type BTask from "./entities/btask.js";
interface AttachmentOpts {
includeContentLength?: boolean;
@@ -32,6 +33,7 @@ export default class Becca {
attributeIndex!: Record<string, BAttribute[]>;
options!: Record<string, BOption>;
etapiTokens!: Record<string, BEtapiToken>;
tasks!: Record<string, BTask>;
allNoteSetCache: NoteSet | null;
@@ -48,6 +50,7 @@ export default class Becca {
this.attributeIndex = {};
this.options = {};
this.etapiTokens = {};
this.tasks = {};
this.dirtyNoteSetCache();
@@ -213,6 +216,14 @@ export default class Becca {
return this.etapiTokens[etapiTokenId];
}
getTasks(): BTask[] {
return Object.values(this.tasks);
}
getTask(taskId: string): BTask | null {
return this.tasks[taskId];
}
getEntity<T extends AbstractBeccaEntity<T>>(entityName: string, entityId: string): AbstractBeccaEntity<T> | null {
if (!entityName || !entityId) {
return null;

View File

@@ -11,9 +11,10 @@ import BOption from "./entities/boption.js";
import BEtapiToken from "./entities/betapi_token.js";
import cls from "../services/cls.js";
import entityConstructor from "../becca/entity_constructor.js";
import type { AttributeRow, BranchRow, EtapiTokenRow, NoteRow, OptionRow } from "./entities/rows.js";
import type { AttributeRow, BranchRow, EtapiTokenRow, NoteRow, OptionRow, TaskRow } from "./entities/rows.js";
import type AbstractBeccaEntity from "./entities/abstract_becca_entity.js";
import ws from "../services/ws.js";
import BTask from "./entities/btask.js";
const beccaLoaded = new Promise<void>(async (res, rej) => {
const sqlInit = (await import("../services/sql_init.js")).default;
@@ -63,6 +64,10 @@ function load() {
for (const row of sql.getRows<EtapiTokenRow>(`SELECT etapiTokenId, name, tokenHash, utcDateCreated, utcDateModified FROM etapi_tokens WHERE isDeleted = 0`)) {
new BEtapiToken(row);
}
for (const row of sql.getRows<TaskRow>(`SELECT taskId, parentNoteId, title, dueDate, isDone, isDeleted FROM tasks WHERE isDeleted = 0`)) {
new BTask(row);
}
});
for (const noteId in becca.notes) {

View File

@@ -159,7 +159,7 @@ class BBranch extends AbstractBeccaEntity<BBranch> {
}
}
if (this.noteId === "root" || this.noteId === cls.getHoistedNoteId()) {
if ((this.noteId === "root" || this.noteId === cls.getHoistedNoteId()) && !this.isWeak) {
throw new Error("Can't delete root or hoisted branch/note");
}

View File

@@ -0,0 +1,84 @@
import date_utils from "../../services/date_utils.js";
import AbstractBeccaEntity from "./abstract_becca_entity.js";
import type BOption from "./boption.js";
import type { TaskRow } from "./rows.js";
export default class BTask extends AbstractBeccaEntity<BOption> {
static get entityName() {
return "tasks";
}
static get primaryKeyName() {
return "taskId";
}
static get hashedProperties() {
return [ "taskId", "parentNoteId", "title", "dueDate", "isDone", "isDeleted" ];
}
taskId?: string;
parentNoteId!: string;
title!: string;
dueDate?: string;
isDone!: boolean;
private _isDeleted?: boolean;
constructor(row?: TaskRow) {
super();
if (!row) {
return;
}
this.updateFromRow(row);
this.init();
}
get isDeleted() {
return !!this._isDeleted;
}
updateFromRow(row: TaskRow) {
this.taskId = row.taskId;
this.parentNoteId = row.parentNoteId;
this.title = row.title;
this.dueDate = row.dueDate;
this.isDone = !!row.isDone;
this._isDeleted = !!row.isDeleted;
this.utcDateModified = row.utcDateModified;
if (this.taskId) {
this.becca.tasks[this.taskId] = this;
}
}
init() {
if (this.taskId) {
this.becca.tasks[this.taskId] = this;
}
}
protected beforeSaving(opts?: {}): void {
super.beforeSaving();
this.utcDateModified = date_utils.utcNowDateTime();
if (this.taskId) {
this.becca.tasks[this.taskId] = this;
}
}
getPojo() {
return {
taskId: this.taskId,
parentNoteId: this.parentNoteId,
title: this.title,
dueDate: this.dueDate,
isDone: this.isDone,
isDeleted: this.isDeleted,
utcDateModified: this.utcDateModified
};
}
}

View File

@@ -1,4 +1,5 @@
// TODO: Booleans should probably be numbers instead (as SQLite does not have booleans.);
// TODO: check against schema.sql which properties really are "optional"
export interface AttachmentRow {
attachmentId?: string;
@@ -12,6 +13,8 @@ export interface AttachmentRow {
dateModified?: string;
utcDateModified?: string;
utcDateScheduledForErasureSince?: string;
isDeleted?: boolean;
deleteId?: string;
contentLength?: number;
content?: Buffer | string;
}
@@ -136,3 +139,13 @@ export interface NoteRow {
utcDateModified: string;
content?: string | Buffer;
}
export interface TaskRow {
taskId?: string;
parentNoteId: string;
title: string;
dueDate?: string;
isDone?: boolean;
isDeleted?: boolean;
utcDateModified?: string;
}

View File

@@ -9,6 +9,7 @@ import BNote from "./entities/bnote.js";
import BOption from "./entities/boption.js";
import BRecentNote from "./entities/brecent_note.js";
import BRevision from "./entities/brevision.js";
import BTask from "./entities/btask.js";
type EntityClass = new (row?: any) => AbstractBeccaEntity<any>;
@@ -21,7 +22,8 @@ const ENTITY_NAME_TO_ENTITY: Record<string, ConstructorData<any> & EntityClass>
notes: BNote,
options: BOption,
recent_notes: BRecentNote,
revisions: BRevision
revisions: BRevision,
tasks: BTask
};
function getEntityFromEntityName(entityName: keyof typeof ENTITY_NAME_TO_ENTITY) {

View File

@@ -80,6 +80,7 @@ export type CommandMappings = {
};
closeTocCommand: CommandData;
showLaunchBarSubtree: CommandData;
showRevisions: CommandData;
showOptions: CommandData & {
section: string;
};
@@ -106,10 +107,6 @@ export type CommandMappings = {
showInfoDialog: ConfirmWithMessageOptions;
showConfirmDialog: ConfirmWithMessageOptions;
showRecentChanges: CommandData & { ancestorNoteId: string };
showExportDialog: CommandData & {
notePath: string;
defaultType: "subtree"
};
showImportDialog: CommandData & { noteId: string; };
openNewNoteSplit: NoteCommandData;
openInWindow: NoteCommandData;
@@ -119,6 +116,8 @@ export type CommandMappings = {
hideLeftPane: CommandData;
showLeftPane: CommandData;
hoistNote: CommandData & { noteId: string };
leaveProtectedSession: CommandData;
enterProtectedSession: CommandData;
openInTab: ContextMenuCommandData;
openNoteInSplit: ContextMenuCommandData;
@@ -225,10 +224,18 @@ export type CommandMappings = {
reEvaluateRightPaneVisibility: CommandData;
runActiveNote: CommandData;
scrollContainerToCommand: CommandData & {
position: number;
};
moveThisNoteSplit: CommandData & {
isMovingLeft: boolean;
};
// Geomap
deleteFromMap: { noteId: string },
openGeoLocation: { noteId: string, event: JQuery.MouseDownEvent }
toggleZenMode: CommandData;
};
type EventMappings = {
@@ -306,6 +313,7 @@ type EventMappings = {
noteContextReorderEvent: {
oldMainNtxId: string;
newMainNtxId: string;
ntxIdsInOrder: string[];
};
newNoteContextCreated: {
noteContext: NoteContext;
@@ -314,7 +322,7 @@ type EventMappings = {
ntxIds: string[];
};
exportSvg: {
ntxId: string;
ntxId: string | null | undefined;
};
geoMapCreateChildNote: {
ntxId: string | null | undefined; // TODO: deduplicate ntxId
@@ -330,6 +338,7 @@ type EventMappings = {
};
scrollToEnd: { ntxId: string };
noteTypeMimeChanged: { noteId: string };
zenModeChanged: { isEnabled: boolean };
};
export type EventListener<T extends EventNames> = {

View File

@@ -290,7 +290,7 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
return (
this.note &&
["default", "contextual-help"].includes(this.viewScope?.viewMode ?? "") &&
this.note.hasChildren() &&
(this.note.hasChildren() || this.note.getLabelValue("viewType") === "calendar") &&
["book", "text", "code"].includes(this.note.type) &&
this.note.mime !== "text/x-sqlite;schema=trilium" &&
!this.note.isLabelTruthy("hideChildrenOverview")

View File

@@ -178,6 +178,13 @@ export default class RootCommandExecutor extends Component {
for (const window of windows) window[action]();
}
toggleZenModeCommand() {
const $body = $("body");
$body.toggleClass("zen");
const isEnabled = $body.hasClass("zen");
appContext.triggerEvent("zenModeChanged", { isEnabled });
}
firstTabCommand() {
this.#goToTab(1);
}

View File

@@ -10,6 +10,7 @@ import { t } from "./services/i18n.js";
import options from "./services/options.js";
import type ElectronRemote from "@electron/remote";
import type Electron from "electron";
import "../stylesheets/bootstrap.scss";
await appContext.earlyInit();
@@ -50,6 +51,7 @@ function initOnElectron() {
const currentWindow = electronRemote.getCurrentWindow();
const style = window.getComputedStyle(document.body);
initDarkOrLightMode(style);
initTransparencyEffects(style, currentWindow);
if (options.get("nativeTitleBarVisible") !== "true") {
@@ -91,3 +93,21 @@ function initTransparencyEffects(style: CSSStyleDeclaration, currentWindow: Elec
}
}
}
/**
* Informs Electron that we prefer a dark or light theme. Apart from changing prefers-color-scheme at CSS level which is a side effect,
* this fixes color issues with background effects or native title bars.
*
* @param style the root CSS element to read variables from.
*/
function initDarkOrLightMode(style: CSSStyleDeclaration) {
let themeSource: typeof nativeTheme.themeSource = "system";
const themeStyle = style.getPropertyValue("--theme-style");
if (style.getPropertyValue("--theme-style-auto") !== "true" && (themeStyle === "light" || themeStyle === "dark")) {
themeSource = themeStyle;
}
const { nativeTheme } = utils.dynamicRequire("@electron/remote") as typeof ElectronRemote;
nativeTheme.themeSource = themeSource;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,56 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../style.css">
<base target="_parent">
<title data-trilium-title>Custom resource providers</title>
</head>
<body>
<div class="content">
<h1 data-trilium-h1>Custom resource providers</h1>
<div class="ck-content">
<p>A custom resource provider allows any file imported into Trilium (images,
fonts, stylesheets) to be publicly accessible via a URL.</p>
<p>A potential use case for this is to add embed a custom font alongside
a theme.</p>
<h2>Steps for creating a custom resource provider</h2>
<ol>
<li>Import a file such as an image or a font into Trilium by drag &amp; drop.</li>
<li>Select the file and go to the <i>Owned Attributes</i> section.</li>
<li>Add the label <code>#customResourceProvider=hello</code>.</li>
<li>To test if it is working, use a browser to navigate to <code>&lt;protocol&gt;://&lt;host&gt;/custom/hello</code> (where <code>&lt;protocol&gt;</code> is
either <code>http</code> or <code>https</code> based on your setup, and <code>&lt;host&gt;</code> is
the host or IP to your Trilium server instance). If you are running the
TriliumNext application without a server, use <code>http://localhost:37840</code> as
the base URL.</li>
<li>If everything went well, at the previous step the browser should have
downloaded the file uploaded in the first step.</li>
</ol>
<p>Instead of <code>hello</code>, the name can be:</p>
<ul>
<li>A path, such as <code>fonts/Roboto.ttf</code>, which would be accessible
via <code>&lt;host&gt;/custom/fonts/Roboto.ttf</code>.</li>
<li>As a more advanced use case, a regular expression to match multiple routes,
such as <code>hello/.*</code> which will be accessible via <code>/custom/hello/1</code>, <code>/custom/hello/2</code>, <code>/custom/hello/world</code>,
etc.</li>
</ul>
<h2>Using it in a theme</h2>
<p>For example, if you have a custom font to be imported by the theme, first
upload a font file into Trilium and assign it the <code>#customResourceProvider=fonts/myfont.ttf</code> attribute.</p>
<p>Then modify the theme CSS to point to:</p><pre><code class="language-text-css">@font-face {
font-family: customFont;
src: url("/custom/fonts/myfont.ttf");
}
div {
font-family: customFont;
}</code></pre>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

View File

@@ -5,32 +5,35 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../style.css">
<base target="_parent">
<title data-trilium-title>Exporting as PDF</title>
<title data-trilium-title>Export as PDF</title>
</head>
<body>
<div class="content">
<h1 data-trilium-h1>Exporting as PDF</h1>
<h1 data-trilium-h1>Export as PDF</h1>
<div class="ck-content">
<figure class="image image-style-align-right image_resized" style="width:47.17%;">
<img style="aspect-ratio:951/432;" src="1_Exporting as PDF_image.png"
width="951" height="432">
<figure class="image image-style-align-right image_resized" style="width:50.63%;">
<img style="aspect-ratio:951/432;" src="Export as PDF_image.png" width="951"
height="432">
<figcaption>Screenshot of the note contextual menu indicating the “Export as PDF”
option.</figcaption>
</figure>
<p>On the desktop application of Trilium it is possible to export a note
as PDF. On the server or PWA (mobile), the option is not available due
to technical constraints and it will be hidden.</p>
<p>To print a note, select the
<img src="Exporting as PDF_image.png" width="29"
<img src="2_Export as PDF_image.png" width="29"
height="31">button to the right of the note and select <i>Export as PDF</i>.</p>
<p>Afterwards you will be prompted to select where to save the PDF file.
Upon confirmation, the resulting PDF will be opened automatically.</p>
Upon confirmation, the resulting PDF will be opened automatically using
the default/system application configured for PDFs.</p>
<p>Should you encounter any visual issues in the resulting PDF file (e.g.
a table does not fit properly, there is cut off text, etc.) feel free to
<a
href="#root/OeKBfN6JbMIq/jRV1MPt4mNSP/hrC6xn7hnDq5">report the issue</a>. In this case, it's best to offer a sample note (click
on the
<img src="Exporting as PDF_image.png" width="29" height="31">button, select Export note → This note and all of its descendants → HTML
<img src="2_Export as PDF_image.png" width="29" height="31">button, select Export note → This note and all of its descendants → HTML
in ZIP archive). Make sure not to accidentally leak any personal information.</p>
<h2>Landscape mode</h2>
<p>When exporting to PDF, there are no customizable settings such as page

View File

@@ -0,0 +1,73 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../style.css">
<base target="_parent">
<title data-trilium-title>Zen mode</title>
</head>
<body>
<div class="content">
<h1 data-trilium-h1>Zen mode</h1>
<div class="ck-content">
<figure class="image image-style-align-center image_resized" style="width:62.15%;">
<img style="aspect-ratio:855/677;" src="5_Zen mode_image.png" width="855"
height="677">
<figcaption>Screenshot of Zen Mode activated on a Windows 11 system with native title
bar off and background effects on.</figcaption>
</figure>
<p>When Zen Mode is activated (pictured on the side), most of the user interface
of Trilium is hidden away in order to be able to focus on the content,
whether it's for reading or writing.</p>
<figure class="image image-style-align-right image_resized"
style="width:17.65%;">
<img style="aspect-ratio:265/386;" src="3_Zen mode_image.png" width="265"
height="386">
<figcaption>Screenshot of the Zen Mode option in the global menu.</figcaption>
</figure>
<h2>Activating &amp; deactivating</h2>
<p>The Zen Mode can be activated by accessing the global menu and selecting
the “Zen Mode” option:</p>
<p>Aside from the global menu, it's also possible to activate this mode by
using a keyboard shortcut which is Alt+Z by default. Look for <code>toggleZenMode</code> in
the shortcut configuration.</p>
<p>Once Zen Mode is activated, all the UI elements of the application will
be hidden away, including the global menu. In that case, the Zen Mode can
be deactivated either by pressing the
<img src="6_Zen mode_image.png" width="29"
height="31">icon in the top-right corner of the window or by pressing the keyboard
combination again.</p>
<p>Do note that, by design, activating or deactivating the Zen Mode applies
only to the current window. Restarting the application will also disable
the Zen Mode.</p>
<h2>Moving the window around</h2>
<p>If “Native title bar” is activated, then the operating system's default
title bar can be used to drag the window around. If deactivated, the window
can still be moved by dragging the mouse across the top part of the window
where the note titles are.</p>
<figure class="image image-style-align-left image_resized"
style="width:50%;">
<img style="aspect-ratio:1060/707;" src="7_Zen mode_image.png" width="1060"
height="707">
<figcaption>Screenshot of two notes side-by-side while Zen Mode is active, on Windows
11 with background effects off.</figcaption>
</figure>
<h2>Split windows and tabs</h2>
<p>Tabs are completely hidden, however it's still possible to use keyboard
shortcuts such as <code>firstTab</code> (Ctrl+1 by default), <code>secondTab</code> (Ctrl+2
by default). There are also some newer shortcuts such as <code>activateNextTab</code> (Ctrl+Tab)
or <code>activatePreviousTab</code> (Ctrl+Shift+Tab) that allow easy navigation,
however make sure that they are configured properly in the settings.</p>
<p>For the split view of notes, there are no keyboard shortcuts at the time
of writing, but it's still possible to have them in Zen Mode by creating
the split while the Zen Mode is off and then reactivating it afterwards.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@@ -0,0 +1,302 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../../style.css">
<base target="_parent">
<title data-trilium-title>Calendar View</title>
</head>
<body>
<div class="content">
<h1 data-trilium-h1>Calendar View</h1>
<div class="ck-content">
<figure class="image">
<img style="aspect-ratio:767/606;" src="6_Calendar View_image.png" width="767"
height="606">
</figure>
<p>The Calendar view of Book notes will display each child note in a calendar
that has a start date and optionally an end date, as an event.</p>
<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>
<h2>Creating a calendar</h2>
<figure class="table" style="width:100%;">
<table class="ck-table-resized">
<colgroup>
<col style="width:3.67%;">
<col style="width:61.57%;">
<col style="width:34.76%;">
</colgroup>
<tbody>
<tr>
<th>1</th>
<td>
<figure class="image">
<img style="aspect-ratio:545/299;" src="Calendar View_image.png" width="545"
height="299">
</figure>
<p>&nbsp;</p>
</td>
<td style="vertical-align:top;">
<p>The Calendar View works only for Book note types. To create a new note,
right click on the note tree on the left and select Insert note after,
or Insert child note and then select <i>Book</i>.</p>
<p>&nbsp;</p>
</td>
</tr>
<tr>
<th>2</th>
<td>
<figure class="image">
<img style="aspect-ratio:314/233;" src="1_Calendar View_image.png" width="314"
height="233">
</figure>
</td>
<td style="vertical-align:top;">Once created, the “View type” of the Book needs changed to “Calendar”,
by selecting the “Book Properties” tab in the ribbon.</td>
</tr>
</tbody>
</table>
</figure>
<h2>Creating a new event/note</h2>
<ul>
<li>Clicking on a day will create a new child note and assign it to that particular
day.
<ul>
<li>You will be asked for the name of the new note. If the popup is dismissed
by pressing the close button or escape, then the note will not be created.</li>
</ul>
</li>
<li>It's possible to drag across multiple days to set both the start and end
date of a particular note.
<br>
<img src="3_Calendar View_image.png" width="425" height="91">
</li>
<li>Creating new notes from the calendar will respect the <code>~child:template</code> relation
if set on the book note.</li>
</ul>
<h2>Interacting with events</h2>
<ul>
<li>Hovering the mouse over an event will display information about the note.
<br>
<img src="4_Calendar View_image.png" width="323" height="160">
</li>
<li>Left clicking the event will go to that note. Middle clicking will open
the note in a new tab and right click will offer more options including
opening the note in a new split or window.</li>
<li>Drag and drop an event on the calendar to move it to another day.</li>
<li>The length of an event can be changed by placing the mouse to the right
edge of the event and dragging the mouse around.</li>
</ul>
<h2>Configuring the calendar</h2>
<p>The following attributes can be added to the book type:</p>
<figure class="table"
style="width:100%;">
<table class="ck-table-resized">
<colgroup>
<col style="width:29.49%;">
<col style="width:70.51%;">
</colgroup>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>#calendar:hideWeekends</code>
</td>
<td>When present (regardless of value), it will hide Saturday and Sundays
from the calendar.</td>
</tr>
<tr>
<td><code>#calendar:weekNumbers</code>
</td>
<td>When present (regardless of value), it will show the number of the week
on the calendar.</td>
</tr>
</tbody>
</table>
</figure>
<p>In addition, the first day of the week can be either Sunday or Monday
and can be adjusted from the application settings.</p>
<h2>Configuring the calendar events</h2>
<p>For each note of the calendar, the following attributes can be used:</p>
<figure
class="table">
<table>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>#startDate</code>
</td>
<td>The date the event starts, which will display it in the calendar. The
format is <code>YYYY-MM-DD</code> (year, month and day separated by a minus
sign).</td>
</tr>
<tr>
<td><code>#endDate</code>
</td>
<td>Similar to <code>startDate</code>, mentions the end date if the event spans
across multiple days. The date is inclusive, so the end day is also considered.
The attribute can be missing for single-day events.</td>
</tr>
<tr>
<td><code>#color</code>
</td>
<td>Displays the event with a specified color (named such as <code>red</code>, <code>gray</code> or
hex such as <code>#FF0000</code>). This will also change the color of the
note in other places such as the note tree.</td>
</tr>
<tr>
<td><code>#calendar:color</code>
</td>
<td>Similar to <code>#color</code>, but applies the color only for the event
in the calendar and not for other places such as the note tree.</td>
</tr>
<tr>
<td><code>#iconClass</code>
</td>
<td>If present, the icon of the note will be displayed to the left of the
event title.</td>
</tr>
<tr>
<td><code>#calendar:title</code>
</td>
<td>Changes the title of an event to point to an attribute of the note other
than the title, either a label (e.g. <code>#assignee</code>) or a relation
(e.g. <code>~for</code>). See <i>Advanced use-cases</i> for more information.</td>
</tr>
</tbody>
</table>
</figure>
<h2>How the calendar works</h2>
<p>
<img class="image-style-align-left" src="7_Calendar View_image.png" width="329"
height="116">The calendar displays all the child notes of the book that have a <code>#startDate</code>.
An <code>#endDate</code> can optionally be added.</p>
<p>If editing the start date and end date from the note itself is desirable,
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>This will result in:</p>
<p>
<img src="9_Calendar View_image.png" width="264" height="164">
</p>
<p>When not used in a Journal, the calendar is recursive. That is, it will
look for events not just in its child notes but also in the children of
these child notes.</p>
<h2>Use-cases</h2>
<h3>Using with the Journal / calendar</h3>
<p>It is possible to integrate the calendar view into the Journal with day
notes. In order to do so change the note type of the Journal note (calendar
root) to Book and then select the Calendar View.</p>
<p>Based on the <code>#calendarRoot</code> (or <code>#workspaceCalendarRoot</code>)
attribute, the calendar will know that it's in a calendar and apply the
following:</p>
<ul>
<li>The calendar events are now rendered based on their <code>dateNote</code> attribute
rather than <code>startDate</code>.</li>
<li>Interactive editing such as dragging over an empty era or resizing an
event is no longer possible.</li>
<li>Clicking on the empty space on a date will automatically open that day's
note or create it if it does not exist.</li>
<li>Direct children of a day note will be displayed on the calendar despite
not having a <code>dateNote</code> attribute. Children of the child notes
will not be displayed.</li>
</ul>
<figure class="image">
<img style="aspect-ratio:1217/724;" src="18_Calendar View_image.png" width="1217"
height="724">
</figure>
<h3>Using a different attribute as event title</h3>
<p>By default, events are displayed on the calendar by their note title.
However, it is possible to configure a different attribute to be displayed
instead.</p>
<p>To do so, assign <code>#calendar:title</code> to the child note (not the
calendar/book note), with the value being <code>#name</code> where <code>name</code> can
be any label. The attribute can also come through inheritance such as a
template attribute. If the note does not have the requested label, the
title of the note will be used instead.</p>
<figure class="table">
<table>
<tbody>
<tr>
<td>
<figure class="image">
<img style="aspect-ratio:631/115;" src="10_Calendar View_image.png" width="631"
height="115">
</figure>
</td>
<td>
<figure class="image">
<img style="aspect-ratio:445/124;" src="11_Calendar View_image.png" width="445"
height="124">
</figure>
</td>
</tr>
</tbody>
</table>
</figure>
<h3>Using a relation attribute as event title</h3>
<p>Similarly to using an attribute, use <code>#calendar:title</code> and set
it to <code>~name</code> where <code>name</code> is the name of the relation
to use.</p>
<p>Moreover, if there are more relations of the same name, they will be displayed
as multiple events coming from the same note.</p>
<figure class="table">
<table>
<tbody>
<tr>
<td>
<figure class="image">
<img style="aspect-ratio:666/118;" src="15_Calendar View_image.png" width="666"
height="118">
</figure>
</td>
<td>
<figure class="image">
<img style="aspect-ratio:294/151;" src="13_Calendar View_image.png" width="294"
height="151">
</figure>
</td>
</tr>
</tbody>
</table>
</figure>
<p>Note that it's even possible to have a <code>#calendar:title</code> on the
target note (e.g. “John Smith”) which will try to render an attribute of
it. Note that it's not possible to use a relation here as well for safety
reasons (an accidental recursion &nbsp;of attributes could cause the application
to loop infinitely).</p>
<figure class="table">
<table>
<tbody>
<tr>
<td>
<figure class="image">
<img style="aspect-ratio:364/121;" src="16_Calendar View_image.png" width="364"
height="121">
</figure>
</td>
<td>
<figure class="image">
<img style="aspect-ratio:296/150;" src="17_Calendar View_image.png" width="296"
height="150">
</figure>
</td>
</tr>
</tbody>
</table>
</figure>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@@ -0,0 +1,19 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../style.css">
<base target="_parent">
<title data-trilium-title>Canvas</title>
</head>
<body>
<div class="content">
<h1 data-trilium-h1>Canvas</h1>
<div class="ck-content"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,19 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../style.css">
<base target="_parent">
<title data-trilium-title>Code</title>
</head>
<body>
<div class="content">
<h1 data-trilium-h1>Code</h1>
<div class="ck-content"></div>
</div>
</body>
</html>

View File

@@ -5,12 +5,12 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../style.css">
<base target="_parent">
<title data-trilium-title>Geo map</title>
<title data-trilium-title>Geo Map</title>
</head>
<body>
<div class="content">
<h1 data-trilium-h1>Geo map</h1>
<h1 data-trilium-h1>Geo Map</h1>
<div class="ck-content">
<h2>Creating a new geo map</h2>
@@ -26,7 +26,7 @@
<th>1</th>
<td>
<figure class="image image_resized" style="width:100%;">
<img style="aspect-ratio:1256/1044;" src="Geo map_image.png" width="1256"
<img style="aspect-ratio:1256/1044;" src="9_Geo Map_image.png" width="1256"
height="1044">
</figure>
</td>
@@ -36,7 +36,7 @@
<th>2</th>
<td>
<figure class="image image_resized" style="width:100%;">
<img style="aspect-ratio:1720/1396;" src="1_Geo map_image.png" width="1720"
<img style="aspect-ratio:1720/1396;" src="3_Geo Map_image.png" width="1720"
height="1396">
</figure>
</td>
@@ -51,8 +51,8 @@
<li>Use the mouse wheel, two-finger gesture on a touchpad or the +/- buttons
on the top-left to adjust the zoom.</li>
</ul>
<p>The position on the map and the zoom are saved inside the map note. When
visting again the note it will restore this position.</p>
<p>The position on the map and the zoom are saved inside the map note and
restored when visiting again the note.</p>
<h2>Adding a marker using the map</h2>
<figure class="table" style="width:100%;">
<table class="ck-table-resized">
@@ -69,18 +69,18 @@
<p>To create a marker, first navigate to the desired point on the map. Then
press the
<img class="image_resized" style="aspect-ratio:72/66;width:7.37%;"
src="2_Geo map_image.png" width="72" height="66">button on the top-right of the map.</p>
src="4_Geo Map_image.png" width="72" height="66">button on the top-right of the map.</p>
<p>If the button is not visible, make sure the button section is visible
by pressing the chevron button (
<img class="image_resized" style="aspect-ratio:72/66;width:7.51%;"
src="3_Geo map_image.png" width="72" height="66">) in the top-right of the map.</p>
src="10_Geo Map_image.png" width="72" height="66">) in the top-right of the map.</p>
</td>
</tr>
<tr>
<th>2</th>
<td>
<figure class="image image_resized" style="width:100%;">
<img style="aspect-ratio:1730/416;" src="4_Geo map_image.png" width="1730"
<img style="aspect-ratio:1730/416;" src="14_Geo Map_image.png" width="1730"
height="416">
</figure>
<p>&nbsp;</p>
@@ -96,7 +96,7 @@
<th>3</th>
<td>
<figure class="image">
<img style="aspect-ratio:1586/404;" src="5_Geo map_image.png" width="1586"
<img style="aspect-ratio:1586/404;" src="1_Geo Map_image.png" width="1586"
height="404">
</figure>
<p>&nbsp;</p>
@@ -107,7 +107,7 @@
<th>4</th>
<td>
<figure class="image">
<img style="aspect-ratio:1696/608;" src="6_Geo map_image.png" width="1696"
<img style="aspect-ratio:1696/608;" src="6_Geo Map_image.png" width="1696"
height="608">
</figure>
<p>&nbsp;</p>
@@ -118,6 +118,15 @@
</tbody>
</table>
</figure>
<h2>How the location of the markers is stored</h2>
<p>The location of a marker is stored in the <code>#geolocation</code> attribute
of the child notes:</p>
<figure class="image">
<img style="aspect-ratio:1288/278;" src="12_Geo Map_image.png" width="1288"
height="278">
</figure>
<p>This value can be added manually if needed. The value of the attribute
is made up of the latitude and longitude separated by a comma.</p>
<h2>Repositioning markers</h2>
<p>It's possible to reposition existing markers by simply drag and dropping
them to the new destination.</p>
@@ -125,13 +134,30 @@
<p>If moved by mistake, there is currently no way to undo the change. If
the mouse was not yet released, it's possible to force a refresh of the
page (Ctrl+R or Meta+R) to cancel it.</p>
<h2>Adding the geolocation manually</h2>
<p>The location of a marker is stored in the <code>#geolocation</code> attribute
of the child notes:</p>
<figure class="image">
<img style="aspect-ratio:1288/278;" src="7_Geo map_image.png" width="1288"
height="278">
</figure>
<h2>Interaction with the markers</h2>
<ul>
<li>Hovering over a marker will display the content of the note it belongs
to.
<ul>
<li>Clicking on the note title in the tooltip will navigate to the note in
the current view.</li>
</ul>
</li>
<li>Middle-clicking the marker will open the note in a new tab.</li>
<li>Right-clicking the marker will open a contextual menu allowing:
<ul>
<li>Opening the note in a new tab, split or window.</li>
<li>Opening the location using an external application (if the operating system
supports it).</li>
<li>Removing the marker from the map, which will remove the <code>#geolocation</code> attribute
of the note. To add it back again, the coordinates have to be manually
added back in.</li>
</ul>
</li>
</ul>
<h2>Adding the coordinates manually</h2>
<p>In a nutshell, create a child note and set the <code>#geolocation</code> attribute
to the coordinates.</p>
<p>The value of the attribute is made up of the latitude and longitude separated
by a comma.</p>
<h3>Adding from Google Maps</h3>
@@ -142,7 +168,7 @@
<th>1</th>
<td>
<figure class="image image-style-align-center image_resized" style="width:100%;">
<img style="aspect-ratio:732/918;" src="8_Geo map_image.png" width="732"
<img style="aspect-ratio:732/918;" src="16_Geo Map_image.png" width="732"
height="918">
</figure>
</td>
@@ -159,7 +185,7 @@
<th>2</th>
<td>
<figure class="image image_resized" style="width:100%;">
<img style="aspect-ratio:518/84;" src="11_Geo map_image.png" width="518"
<img style="aspect-ratio:518/84;" src="19_Geo Map_image.png" width="518"
height="84">
</figure>
</td>
@@ -173,7 +199,7 @@
<th>3</th>
<td>
<figure class="image image_resized" style="width:100%;">
<img style="aspect-ratio:1074/276;" src="9_Geo map_image.png" width="1074"
<img style="aspect-ratio:1074/276;" src="11_Geo Map_image.png" width="1074"
height="276">
</figure>
</td>
@@ -199,7 +225,7 @@
<th>1</th>
<td>
<figure class="image image_resized" style="width:100%;">
<img style="aspect-ratio:562/454;" src="12_Geo map_image.png" width="562"
<img style="aspect-ratio:562/454;" src="17_Geo Map_image.png" width="562"
height="454">
</figure>
</td>
@@ -210,7 +236,7 @@
<th>2</th>
<td>
<figure class="image image_resized" style="width:100%;">
<img style="aspect-ratio:696/480;" src="13_Geo map_image.png" width="696"
<img style="aspect-ratio:696/480;" src="13_Geo Map_image.png" width="696"
height="480">
</figure>
</td>
@@ -224,7 +250,7 @@
<th>3</th>
<td>
<figure class="image">
<img style="aspect-ratio:640/276;" src="14_Geo map_image.png" width="640"
<img style="aspect-ratio:640/276;" src="2_Geo Map_image.png" width="640"
height="276">
</figure>
</td>
@@ -249,7 +275,7 @@
<th>1</th>
<td>
<figure class="image">
<img style="aspect-ratio:226/74;" src="17_Geo map_image.png" width="226"
<img style="aspect-ratio:226/74;" src="7_Geo Map_image.png" width="226"
height="74">
</figure>
</td>
@@ -260,7 +286,7 @@
<th>2</th>
<td>
<figure class="image">
<img style="aspect-ratio:322/222;" src="18_Geo map_image.png" width="322"
<img style="aspect-ratio:322/222;" src="5_Geo Map_image.png" width="322"
height="222">
</figure>
</td>
@@ -271,7 +297,7 @@
<th>3</th>
<td>
<figure class="image image_resized" style="width:100%;">
<img style="aspect-ratio:620/530;" src="19_Geo map_image.png" width="620"
<img style="aspect-ratio:620/530;" src="15_Geo Map_image.png" width="620"
height="530">
</figure>
</td>

View File

@@ -0,0 +1,19 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../style.css">
<base target="_parent">
<title data-trilium-title>Mermaid Diagram</title>
</head>
<body>
<div class="content">
<h1 data-trilium-h1>Mermaid Diagram</h1>
<div class="ck-content"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,19 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../style.css">
<base target="_parent">
<title data-trilium-title>Mind Map</title>
</head>
<body>
<div class="content">
<h1 data-trilium-h1>Mind Map</h1>
<div class="ck-content"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,19 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../style.css">
<base target="_parent">
<title data-trilium-title>Note Map</title>
</head>
<body>
<div class="content">
<h1 data-trilium-h1>Note Map</h1>
<div class="ck-content"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,19 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../style.css">
<base target="_parent">
<title data-trilium-title>Relation Map</title>
</head>
<body>
<div class="content">
<h1 data-trilium-h1>Relation Map</h1>
<div class="ck-content"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,19 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../style.css">
<base target="_parent">
<title data-trilium-title>Render Note</title>
</head>
<body>
<div class="content">
<h1 data-trilium-h1>Render Note</h1>
<div class="ck-content"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,19 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../style.css">
<base target="_parent">
<title data-trilium-title>Saved Search</title>
</head>
<body>
<div class="content">
<h1 data-trilium-h1>Saved Search</h1>
<div class="ck-content"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,19 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../style.css">
<base target="_parent">
<title data-trilium-title>Text</title>
</head>
<body>
<div class="content">
<h1 data-trilium-h1>Text</h1>
<div class="ck-content"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,45 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../style.css">
<base target="_parent">
<title data-trilium-title>Web View</title>
</head>
<body>
<div class="content">
<h1 data-trilium-h1>Web View</h1>
<div class="ck-content">
<h2>Configuration</h2>
<p>A webview needs to know which URL to render, and it can be provided by
setting the <code>webViewSrc</code> attribute, such as:</p><pre><code class="language-text-x-trilium-auto">#webViewSrc="https://www.wikipedia.org"</code></pre>
<h2>Web view on the server vs. Electron</h2>
<p>When accessing Trilium via a browser instead of the desktop application,
the web view will still try to render the content of the desired webpage.
However, since it's running in a browser there are quite a few limitations
as opposed to the desktop one.</p>
<p>More specifically, quite a few websites oppose being embedded in another
website (technically they have a non-permisive <code>X-Frame-Options</code> header).
This is not bypassable by Trilium so the page will simply fail to render.</p>
<p>You can diagnose this by right clicking the Trilium web page → Inspect
(element) and looking in the “Console” tab for errors such as:</p>
<ul>
<li><code>Refused to display 'https://www.google.com/' in a frame because it set 'X-Frame-Options' to 'sameorigin'.</code>
</li>
<li><code>Refused to frame 'https://duckduckgo.com/' because an ancestor violates the following Content Security Policy directive: "frame-ancestors 'self' https://html.duckduckgo.com".</code>
</li>
</ul>
<p>There are a few websites that do render such as <code>wikipedia.org</code>.</p>
<p>Do note that we are also applying some sandboxing constraints on the server
side, so if you have any issues other than the unresolvable <code>X-Frame-Options</code> described
above, feel free to report them.</p>
<p>On the desktop side, a different technology is used which bypasses the
constraints of an <code>iframe</code> (<code>webview</code>).</p>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,65 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../../style.css">
<base target="_parent">
<title data-trilium-title>Downloading responses from Google Forms</title>
</head>
<body>
<div class="content">
<h1 data-trilium-h1>Downloading responses from Google Forms</h1>
<div class="ck-content">
<p>This tutorials showcases a basic integration with Google Forms, where
we are able to download the responses of a form using the “Link to Sheets"
functionality.</p>
<p>Note that the link will be publicly accessible to everyone (however the
link is in a hard-to-guess format such as <code>https://docs.google.com/spreadsheets/d/e/2PACX-1vTA8NU2_eZFhc8TFadCZPreBfvP7un8IHd6J0SchrLLw3ueGmntNZjwRmsH2ZRcp1pJYDAzMz1FmFaj/pub?output=csv</code>).
Make sure you are not accidentally publishing sensitive information.</p>
<h2>Obtaining the CSV link</h2>
<ol>
<li>Open the Google Forms in a browser.</li>
<li>Select the “Responses” tab and click on “Link to Sheets”.</li>
<li>Select “Create a new spreadsheet” and press “Create”.</li>
<li>In Google Sheets, select File → Share → Publish to web.</li>
<li>In the “Publish to the web” screen, make sure the “Link” tab is selected
and instead of “Web page”, select “Comma-separated values (.csv)”.</li>
<li>Copy the given link which will be used for the upcoming script.</li>
</ol>
<h2>Creating the script</h2>
<p>Create a “JS Frontend” script:</p><pre><code class="language-text-x-trilium-auto">const CSV_URL = "https://docs.google.com/spreadsheets/d/e/2PACX-1vTiwooLV2whjCSVa49dJ99p_G3_qhqHHRqttMjYCJVfLXVdTgUSNJu5K0rpqmaHYF2k7Vofi3o7gW82/pub?output=csv";
async function fetchData() {
try {
const response = await fetch(CSV_URL);
return await response.text();
} catch (e) {
api.showError(e.message);
}
}
const data = await fetchData();
console.log(data);
// Do something with the data.</code></pre>
<p>Note that the data will be received as a string and there is no library
to do the CSV parsing for us. To do a very simple parsing of CSV:</p><pre><code class="language-text-x-trilium-auto">const content = data
.split("\n")
.slice(1)
.map((row) =&gt; row.split(","));</code></pre>
<p>This will return the data as an array of arrays.</p>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -0,0 +1,60 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../style.css">
<base target="_parent">
<title data-trilium-title>Using promoted attributes to configure scripts</title>
</head>
<body>
<div class="content">
<h1 data-trilium-h1>Using promoted attributes to configure scripts</h1>
<div class="ck-content">
<p>A good use case of promoted attributes is to easily define the various
parameters a script might need, for example an input and output note if
it's processing data, or a checkbox to define a particular change in behavior
for the script.</p>
<p>
<img src="Using promoted attributes .png" width="425" height="179">
</p>
<h2>Using check boxes to toggle flags</h2>
<p>Instead of asking the user to modify a boolean value in the script, it's
much more intuitive to use a checkbox for it as a promoted attribute.</p>
<p>To do so, first define the promoted attribute:</p><pre><code class="language-text-x-trilium-auto">#label:groupByExtension="promoted,alias=Group by extension,single,boolean"</code></pre>
<p>Then use it:</p><pre><code class="language-application-javascript-env-frontend">const byExtension = api.currentNote.getLabelValue("groupByExtension") === "true";
if (byExtension) {
// Do something.
}</code></pre>
<p>This will work equally well in both front-end and back-end scripts.</p>
<h2>Using relations to select notes</h2>
<p>One common use case for a script is to read data from another note and
perhaps output its result in another note. To do so we need to define the
following promoted attributes:</p><pre><code class="language-text-x-trilium-auto">#relation:input="promoted,alias=Input,single" #relation:output="promoted,alias=Output,single"</code></pre>
<p>Once we have this, we can add some basic error handling to ensure that
the fields are completed by the user:</p><pre><code class="language-text-x-trilium-auto">const inputNoteId = api.currentNote.getRelationValue("input");
if (!inputNoteId) {
api.showError("Missing input.");
return;
}
const outputNoteId = api.currentNote.getRelationValue("output");
if (!outputNoteId) {
api.showError("Missing output.");
return;
}</code></pre>
<p>Note that here we are using <code>api.showError</code> which is only available
for frontend notes. If you are writing a backend note, simply remove <code>api.showError</code> but
the user will no feedback on why the script did not execute properly.</p>
<p>Afterwards we can simply read the note and do something with it:</p><pre><code class="language-text-x-trilium-auto">const note = api.getNote(inputNoteId);
if (!note) {
return;
}
const content = note.getContent().toString("utf-8");</code></pre>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,60 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../style.css">
<base target="_parent">
<title data-trilium-title>Serving directly the content of a note</title>
</head>
<body>
<div class="content">
<h1 data-trilium-h1>Serving directly the content of a note</h1>
<div class="ck-content">
<p>When accessing a shared note, Trilium will render it as a web page. Sometimes
it's desirable to serve the content directly so that it can be used in
a script or downloaded by the user.</p>
<figure class="table" style="width:100%;">
<table class="ck-table-resized">
<colgroup>
<col style="width:48.52%;">
<col style="width:51.48%;">
</colgroup>
<tbody>
<tr>
<td>
<figure class="image">
<img style="aspect-ratio:378/231;" src="Serving directly the conte.png"
width="378" height="231">
<figcaption>A note displayed as a web page (HTML)</figcaption>
</figure>
</td>
<td style="vertical-align:top;">
<figure class="image">
<img style="aspect-ratio:402/129;" src="1_Serving directly the conte.png"
width="402" height="129">
<figcaption>A note displayed as a raw format</figcaption>
</figure>
</td>
</tr>
</tbody>
</table>
</figure>
<h2>By adding an attribute to the note</h2>
<p>Simply add the <code>#shareRaw</code> attribute and the note will always
be rendered <i>raw</i> when accessed from the share URL.</p>
<h2>By altering the URL</h2>
<p>Append <code>?raw</code> to the URL to display a note in its raw format
regardless of whether the <code>#shareRaw</code> attribute is added on the
note.</p>
<p>
<img src="1_Serving directly the conte.png" width="402" height="129">
</p>
<p>&nbsp;</p>
</div>
</div>
</body>
</html>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../../style.css">
<link rel="stylesheet" href="../../style.css">
<base target="_parent">
<title data-trilium-title>Creating a custom theme</title>
</head>
@@ -19,7 +19,7 @@
keep them into one place.</p>
<p>As such, the first step is to create a new note to gather all the themes.</p>
<p>
<img src="Creating a custom theme_im.png" width="181" height="84">
<img src="5_Creating a custom theme_im.png" width="181" height="84">
</p>
<h2>Step 2. Create the theme</h2>
<figure class="table" style="width:100%;">
@@ -32,7 +32,7 @@
<tr>
<td>
<figure class="image">
<img style="aspect-ratio:651/220;" src="1_Creating a custom theme_im.png"
<img style="aspect-ratio:651/220;" src="3_Creating a custom theme_im.png"
width="651" height="220">
</figure>
</td>
@@ -42,7 +42,7 @@
<tr>
<td>
<figure class="image">
<img style="aspect-ratio:302/349;" src="2_Creating a custom theme_im.png"
<img style="aspect-ratio:302/349;" src="1_Creating a custom theme_im.png"
width="302" height="349">
</figure>
</td>
@@ -51,7 +51,7 @@
<tr>
<td>
<figure class="image">
<img style="aspect-ratio:316/133;" src="3_Creating a custom theme_im.png"
<img style="aspect-ratio:316/133;" src="Creating a custom theme_im.png"
width="316" height="133">
</figure>
</td>
@@ -72,15 +72,15 @@
<p>Refresh the application (Ctrl+Shift+R is a good way to do so) and go to
settings. You should see the newly created theme:</p>
<p>
<img src="4_Creating a custom theme_im.png" width="631" height="481">
<img src="2_Creating a custom theme_im.png" width="631" height="481">
</p>
<p>Afterwards the application will refresh itself with the new theme:</p>
<p>
<img src="5_Creating a custom theme_im.png" width="653" height="554">
<img src="4_Creating a custom theme_im.png" width="653" height="554">
</p>
<p>Do note that the theme will be based off of the legacy theme. To override
that and base the theme on the new TriliumNext theme, see:&nbsp;<a class="reference-link"
href="Theme%20base%20(legacy%20vs.%20next).html">Theme base (legacy vs. next)</a>
href="Customize%20the%20Next%20theme.html">Theme base (legacy vs. next)</a>
</p>
<h2>Step 5. Making changes</h2>
<p>Simply go back to the note and change according to needs. To apply the

View File

@@ -3,22 +3,22 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../../style.css">
<link rel="stylesheet" href="../../style.css">
<base target="_parent">
<title data-trilium-title>Theme base (legacy vs. next)</title>
<title data-trilium-title>Customize the Next theme</title>
</head>
<body>
<div class="content">
<h1 data-trilium-h1>Theme base (legacy vs. next)</h1>
<h1 data-trilium-h1>Customize the Next theme</h1>
<div class="ck-content">
<p>By default, any custom theme will be based on the legacy light theme.
To change the TriliumNext theme instead, add the <code>#appThemeBase=next</code> attribute
To use the TriliumNext theme instead, add the <code>#appThemeBase=next</code> attribute
onto the existing theme. The <code>appTheme</code> attribute must also be
present.</p>
<p>
<img src="1_Theme base (legacy vs. nex.png" width="424" height="140">
<img src="Customize the Next theme_i.png" width="424" height="140">
</p>
<p>When <code>appThemeBase</code> is set to <code>next</code> it will use the
“TriliumNext (auto)” theme. Any other value is ignored and will use the

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../../style.css">
<link rel="stylesheet" href="../../style.css">
<base target="_parent">
<title data-trilium-title>Reference</title>
</head>
@@ -13,6 +13,37 @@
<h1 data-trilium-h1>Reference</h1>
<div class="ck-content">
<h2>Detecting mobile vs. desktop</h2>
<p>The mobile layout is different than the one on the desktop. Use <code>body.mobile</code> and <code>body.desktop</code> to
differentiate between them.</p><pre><code class="language-text-css">body.mobile #root-widget {
/* Do something on mobile */
}
body.desktop #root-widget {
/* Do something on desktop */
}</code></pre>
<p>Do note that there is also a “tablet mode” in the mobile layout. For that
particular case media queries are required:</p><pre><code class="language-text-css">@media (max-width: 991px) {
#launcher-pane {
/* Do something on mobile layout */
}
}
@media (min-width: 992px) {
#launcher-pane {
/* Do something on mobile tablet + desktop layout */
}
}</code></pre>
<h2>Detecting horizontal vs. vertical layout</h2>
<p>The user can select between vertical layout (the classical one, where
the launcher bar is on the left) and a horizontal layout (where the launcher
@@ -85,14 +116,14 @@ body.electron:not(.native-titlebar) {
<h4>On macOS</h4>
<p>On macOS the semaphore window buttons are enabled by default when the
native title bar is disabled. The offset of the buttons can be adjusted
using:</p><pre><code class="language-text-x-trilium-auto">body {
using:</p><pre><code class="language-text-css">body {
--native-titlebar-darwin-x-offset: 12;
--native-titlebar-darwin-y-offset: 14 !important;
}</code></pre>
<h3>Background/transparency effects on Windows (Mica)</h3>
<p>Windows 11 offers a special background/transparency effect called Mica,
which can be enabled by themes by setting the <code>--background-material</code> variable
at <code>body</code> level:</p><pre><code class="language-text-x-trilium-auto">body.electron.platform-win32 {
at <code>body</code> level:</p><pre><code class="language-text-css">body.electron.platform-win32 {
--background-material: tabbed;
}</code></pre>
<p>The value can be either <code>tabbed</code> (especially useful for the horizontal
@@ -104,12 +135,12 @@ body.electron:not(.native-titlebar) {
<p>Theme capabilities are small adjustments done through CSS variables that
can affect the layout or the visual aspect of the application.</p>
<p>In the tab bar, to display the icons of notes instead of the icon of the
workspace:</p><pre><code class="language-text-x-trilium-auto">:root {
workspace:</p><pre><code class="language-text-css">:root {
--tab-note-icons: true;
}</code></pre>
<p>When a workspace is hoisted for a given tab, it is possible to get the
background color of that workspace, for example to apply a small strip
on the tab instead of the whole background color:</p><pre><code class="language-text-x-trilium-auto">.note-tab .note-tab-wrapper {
on the tab instead of the whole background color:</p><pre><code class="language-text-css">.note-tab .note-tab-wrapper {
--tab-background-color: initial !important;
}
@@ -122,6 +153,26 @@ body.electron:not(.native-titlebar) {
height: 3px;
background-color: var(--workspace-tab-background-color);
}</code></pre>
<h2>Custom fonts</h2>
<p>Currently the only way to include a custom font is to use&nbsp;<a class="reference-link"
href="../Advanced%20topics/Custom%20resource%20providers.html">Custom resource providers</a>.
Basically import a font into Trilium and assign it <code>#customResourceProvider=fonts/myfont.ttf</code> and
then import the font in CSS via <code>/custom/fonts/myfont.ttf</code>.</p>
<h2>Dark and light themes</h2>
<p>A light theme needs to have the following CSS:</p><pre><code class="language-text-css">:root {
--theme-style: light;
}</code></pre>
<p>if the theme is dark, then <code>--theme-style</code> needs to be <code>dark</code>.</p>
<p>If the theme is auto (e.g. supports both light or dark based on <code>prefers-color-scheme</code>)
it must also declare (in addition to setting <code>--theme-style</code> to
either <code>light</code> or <code>dark</code>):</p><pre><code class="language-text-css">:root {
--theme-style-auto: true;
}</code></pre>
<p>This will affect the behavior of the Electron application by informing
the operating system of the color preference (e.g. background effects will
appear correct on Windows).</p>
</div>
</div>
</body>

View File

@@ -6,6 +6,6 @@
</head>
<frameset cols="25%,75%">
<frame name="navigation" src="navigation.html">
<frame name="detail" src="User%20Guide/Types%20of%20notes/Geo%20map.html">
<frame name="detail" src="User%20Guide/Features/Export%20as%20PDF.html">
</frameset>
</html>

View File

@@ -9,31 +9,99 @@
<ul>
<li>User Guide
<ul>
<li>Types of notes
<li>Features
<ul>
<li><a href="User%20Guide/Types%20of%20notes/Geo%20map.html" target="detail">Geo map</a>
<li><a href="User%20Guide/Features/Export%20as%20PDF.html" target="detail">Export as PDF</a>
</li>
<li><a href="User%20Guide/Features/Zen%20mode.html" target="detail">Zen mode</a>
</li>
</ul>
</li>
<li>Working with notes
<li>Note Types
<ul>
<li><a href="User%20Guide/Working%20with%20notes/Exporting%20as%20PDF.html"
target="detail">Exporting as PDF</a>
<li><a href="User%20Guide/Note%20Types/Text.html" target="detail">Text</a>
</li>
</ul>
</li>
<li>Power users
<ul>
<li>Theme development
<li><a href="User%20Guide/Note%20Types/Code.html" target="detail">Code</a>
</li>
<li><a href="User%20Guide/Note%20Types/Saved%20Search.html" target="detail">Saved Search</a>
</li>
<li><a href="User%20Guide/Note%20Types/Relation%20Map.html" target="detail">Relation Map</a>
</li>
<li><a href="User%20Guide/Note%20Types/Note%20Map.html" target="detail">Note Map</a>
</li>
<li><a href="User%20Guide/Note%20Types/Render%20Note.html" target="detail">Render Note</a>
</li>
<li>Book
<ul>
<li><a href="User%20Guide/Power%20users/Theme%20development/Creating%20a%20custom%20theme.html"
target="detail">Creating a custom theme</a>
<li><a href="User%20Guide/Note%20Types/Book/Calendar%20View.html" target="detail">Calendar View</a>
</li>
<li><a href="User%20Guide/Power%20users/Theme%20development/Theme%20base%20(legacy%20vs.%20next).html"
target="detail">Theme base (legacy vs. next)</a>
</ul>
</li>
<li><a href="User%20Guide/Note%20Types/Mermaid%20Diagram.html" target="detail">Mermaid Diagram</a>
</li>
<li><a href="User%20Guide/Note%20Types/Canvas.html" target="detail">Canvas</a>
</li>
<li><a href="User%20Guide/Note%20Types/Web%20View.html" target="detail">Web View</a>
</li>
<li><a href="User%20Guide/Note%20Types/Mind%20Map.html" target="detail">Mind Map</a>
</li>
<li><a href="User%20Guide/Note%20Types/Geo%20Map.html" target="detail">Geo Map</a>
</li>
</ul>
</li>
<li>Shared notes
<ul>
<li><a href="User%20Guide/Shared%20notes/Serving%20directly%20the%20content%20o.html"
target="detail">Serving directly the content of a note</a>
</li>
</ul>
</li>
<li>Theme development
<ul>
<li><a href="User%20Guide/Theme%20development/Creating%20a%20custom%20theme.html"
target="detail">Creating a custom theme</a>
</li>
<li><a href="User%20Guide/Theme%20development/Customize%20the%20Next%20theme.html"
target="detail">Customize the Next theme</a>
</li>
<li><a href="User%20Guide/Theme%20development/Reference.html" target="detail">Reference</a>
</li>
</ul>
</li>
<li>Scripting
<ul>
<li>Examples
<ul>
<li><a href="User%20Guide/Scripting/Examples/Downloading%20responses%20from%20Goo.html"
target="detail">Downloading responses from Google Forms</a>
</li>
<li><a href="User%20Guide/Power%20users/Theme%20development/Reference.html"
target="detail">Reference</a>
</ul>
</li>
<li><a href="User%20Guide/Scripting/Using%20promoted%20attributes%20to%20c.html"
target="detail">Using promoted attributes to configure scripts</a>
</li>
</ul>
</li>
<li>Advanced topics
<ul>
<li><a href="User%20Guide/Advanced%20topics/Custom%20resource%20providers.html"
target="detail">Custom resource providers</a>
</li>
<li>REST API
<ul>
<li>ETAPI
<ul>
<li><a href="User%20Guide/Advanced%20topics/REST%20API/ETAPI/API%20Reference.dat"
target="detail">API Reference</a>
</li>
</ul>
</li>
<li>Internal API
<ul>
<li><a href="User%20Guide/Advanced%20topics/REST%20API/Internal%20API/API%20Reference.dat"
target="detail">API Reference</a>
</li>
</ul>
</li>
</ul>
</li>

View File

@@ -19,18 +19,18 @@ export interface FAttachmentRow {
class FAttachment {
private froca: Froca;
attachmentId!: string;
private ownerId!: string;
ownerId!: string;
role!: string;
mime!: string;
title!: string;
isProtected!: boolean; // TODO: Is this used?
private dateModified!: string;
utcDateModified!: string;
private utcDateScheduledForErasureSince!: string;
utcDateScheduledForErasureSince!: string;
/**
* optionally added to the entity
*/
private contentLength!: number;
contentLength!: number;
constructor(froca: Froca, row: FAttachmentRow) {
/** @type {Froca} */

View File

@@ -28,7 +28,8 @@ const NOTE_TYPE_ICONS = {
doc: "bx bxs-file-doc",
contentWidget: "bx bxs-widget",
mindMap: "bx bx-sitemap",
geoMap: "bx bx-map-alt"
geoMap: "bx bx-map-alt",
taskList: "bx bx-list-check"
};
/**
@@ -36,7 +37,7 @@ const NOTE_TYPE_ICONS = {
* end user. Those types should be used only for checking against, they are
* not for direct use.
*/
export type NoteType = "file" | "image" | "search" | "noteMap" | "launcher" | "doc" | "contentWidget" | "text" | "relationMap" | "render" | "canvas" | "mermaid" | "book" | "webView" | "code" | "mindMap" | "geoMap";
export type NoteType = "file" | "image" | "search" | "noteMap" | "launcher" | "doc" | "contentWidget" | "text" | "relationMap" | "render" | "canvas" | "mermaid" | "book" | "webView" | "code" | "mindMap" | "geoMap" | "taskList";
export interface NotePathRecord {
isArchived: boolean;

View File

@@ -0,0 +1,34 @@
import type { Froca } from "../services/froca-interface.js";
export interface FTaskRow {
taskId: string;
parentNoteId: string;
title: string;
dueDate?: string;
isDone?: boolean;
utcDateModified: string;
}
export default class FTask {
private froca: Froca;
taskId!: string;
parentNoteId!: string;
title!: string;
dueDate?: string;
isDone!: boolean;
utcDateModified!: string;
constructor(froca: Froca, row: FTaskRow) {
this.froca = froca;
this.update(row);
}
update(row: FTaskRow) {
this.taskId = row.taskId;
this.parentNoteId = row.parentNoteId;
this.title = row.title;
this.dueDate = row.dueDate;
this.isDone = !!row.isDone;
this.utcDateModified = row.utcDateModified;
}
}

Some files were not shown because too many files have changed in this diff Show More