Merge branch 'develop' into note-create
6
.gitignore
vendored
@ -1,11 +1,5 @@
|
||||
# See https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
|
||||
|
||||
# Workaround for Nx bug: parent .gitignore files with '*' can cause
|
||||
# `nx show projects` to return nothing by ignoring subprojects.
|
||||
# See: https://github.com/nrwl/nx/issues/27368
|
||||
# Unignore everything to ensure Nx detects all projects
|
||||
!*
|
||||
|
||||
# compiled output
|
||||
dist
|
||||
tmp
|
||||
|
@ -1 +1,6 @@
|
||||
VITE_CKEDITOR_ENABLE_INSPECTOR=false
|
||||
VITE_CKEDITOR_ENABLE_INSPECTOR=false
|
||||
|
||||
# The development license key for premium CKEditor features.
|
||||
# Note: This key must only be used for the Trilium Notes project.
|
||||
# Expires on: 2025-09-13
|
||||
VITE_CKEDITOR_KEY=eyJhbGciOiJFUzI1NiJ9.eyJleHAiOjE3NTc3MjE1OTksImp0aSI6ImFiN2E0NjZmLWJlZGMtNDNiYy1iMzU4LTk0NGQ0YWJhY2I3ZiIsImRpc3RyaWJ1dGlvbkNoYW5uZWwiOlsic2giLCJkcnVwYWwiXSwid2hpdGVMYWJlbCI6dHJ1ZSwiZmVhdHVyZXMiOlsiRFJVUCIsIkNNVCIsIkRPIiwiRlAiLCJTQyIsIlRPQyIsIlRQTCIsIlBPRSIsIkNDIiwiTUYiLCJTRUUiLCJFQ0giLCJFSVMiXSwidmMiOiI1MzlkOWY5YyJ9.2rvKPql4hmukyXhEtWPZ8MLxKvzPIwzCdykO653g7IxRRZy2QJpeRszElZx9DakKYZKXekVRAwQKgHxwkgbE_w
|
@ -281,6 +281,7 @@ export type CommandMappings = {
|
||||
buildIcon(name: string): NativeImage;
|
||||
};
|
||||
refreshTouchBar: CommandData;
|
||||
reloadTextEditor: CommandData;
|
||||
};
|
||||
|
||||
type EventMappings = {
|
||||
|
@ -245,6 +245,10 @@ class FrocaImpl implements Froca {
|
||||
}
|
||||
|
||||
async getNotes(noteIds: string[] | JQuery<string>, silentNotFoundError = false): Promise<FNote[]> {
|
||||
if (noteIds.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
noteIds = Array.from(new Set(noteIds)); // make unique
|
||||
const missingNoteIds = noteIds.filter((noteId) => !this.notes[noteId]);
|
||||
|
||||
|
@ -4,6 +4,8 @@ import { t } from "./i18n.js";
|
||||
import type { MenuItem } from "../menus/context_menu.js";
|
||||
import type { TreeCommandNames } from "../menus/tree_context_menu.js";
|
||||
|
||||
const SEPARATOR = { title: "----" };
|
||||
|
||||
async function getNoteTypeItems(command?: TreeCommandNames) {
|
||||
const items: MenuItem<TreeCommandNames>[] = [
|
||||
{ title: t("note_types.text"), command, type: "text", uiIcon: "bx bx-note" },
|
||||
@ -18,25 +20,59 @@ async function getNoteTypeItems(command?: TreeCommandNames) {
|
||||
{ title: t("note_types.web-view"), command, type: "webView", uiIcon: "bx bx-globe-alt" },
|
||||
{ title: t("note_types.mind-map"), command, type: "mindMap", uiIcon: "bx bx-sitemap" },
|
||||
{ title: t("note_types.geo-map"), command, type: "geoMap", uiIcon: "bx bx-map-alt" },
|
||||
...await getBuiltInTemplates(command),
|
||||
...await getUserTemplates(command)
|
||||
];
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
async function getUserTemplates(command?: TreeCommandNames) {
|
||||
const templateNoteIds = await server.get<string[]>("search-templates");
|
||||
const templateNotes = await froca.getNotes(templateNoteIds);
|
||||
|
||||
if (templateNotes.length > 0) {
|
||||
items.push({ title: "----" });
|
||||
|
||||
for (const templateNote of templateNotes) {
|
||||
items.push({
|
||||
title: templateNote.title,
|
||||
uiIcon: templateNote.getIcon(),
|
||||
command: command,
|
||||
type: templateNote.type,
|
||||
templateNoteId: templateNote.noteId
|
||||
});
|
||||
}
|
||||
if (templateNotes.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const items: MenuItem<TreeCommandNames>[] = [
|
||||
SEPARATOR
|
||||
];
|
||||
for (const templateNote of templateNotes) {
|
||||
items.push({
|
||||
title: templateNote.title,
|
||||
uiIcon: templateNote.getIcon(),
|
||||
command: command,
|
||||
type: templateNote.type,
|
||||
templateNoteId: templateNote.noteId
|
||||
});
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
async function getBuiltInTemplates(command?: TreeCommandNames) {
|
||||
const templatesRoot = await froca.getNote("_templates");
|
||||
if (!templatesRoot) {
|
||||
console.warn("Unable to find template root.");
|
||||
return [];
|
||||
}
|
||||
|
||||
const childNotes = await templatesRoot.getChildNotes();
|
||||
if (childNotes.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const items: MenuItem<TreeCommandNames>[] = [
|
||||
SEPARATOR
|
||||
];
|
||||
for (const templateNote of childNotes) {
|
||||
items.push({
|
||||
title: templateNote.title,
|
||||
uiIcon: templateNote.getIcon(),
|
||||
command: command,
|
||||
type: templateNote.type,
|
||||
templateNoteId: templateNote.noteId
|
||||
});
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
|
@ -1280,16 +1280,19 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
|
||||
padding: 0.5em 1em !important;
|
||||
}
|
||||
|
||||
.ck.ck-slash-command-button__text-part {
|
||||
.ck.ck-slash-command-button__text-part,
|
||||
.ck.ck-template-form__text-part {
|
||||
margin-left: 0.5em;
|
||||
line-height: 1.2em !important;
|
||||
}
|
||||
|
||||
.ck.ck-slash-command-button__text-part > span {
|
||||
.ck.ck-slash-command-button__text-part > span,
|
||||
.ck.ck-template-form__text-part > span {
|
||||
line-height: inherit !important;
|
||||
}
|
||||
|
||||
.ck.ck-slash-command-button__text-part .ck.ck-slash-command-button__description {
|
||||
.ck.ck-slash-command-button__text-part .ck.ck-slash-command-button__description,
|
||||
.ck.ck-template-form__text-part .ck-template-form__description {
|
||||
display: block;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
5
apps/client/src/types-assets.d.ts
vendored
@ -8,4 +8,9 @@ declare module "*?url" {
|
||||
export default path;
|
||||
}
|
||||
|
||||
declare module "*?raw" {
|
||||
var content: string;
|
||||
export default content;
|
||||
}
|
||||
|
||||
declare module "boxicons/css/boxicons.min.css" { }
|
||||
|
@ -7,13 +7,14 @@ import { ensureMimeTypesForHighlighting, isSyntaxHighlightEnabled } from "../../
|
||||
import utils from "../../../services/utils.js";
|
||||
import emojiDefinitionsUrl from "@triliumnext/ckeditor5/emoji_definitions/en.json?url";
|
||||
import { copyTextWithToast } from "../../../services/clipboard_ext.js";
|
||||
import getTemplates from "./snippets.js";
|
||||
|
||||
const TEXT_FORMATTING_GROUP = {
|
||||
label: "Text formatting",
|
||||
icon: "text"
|
||||
};
|
||||
|
||||
export function buildConfig(): EditorConfig {
|
||||
export async function buildConfig(): Promise<EditorConfig> {
|
||||
return {
|
||||
image: {
|
||||
styles: {
|
||||
@ -126,6 +127,9 @@ export function buildConfig(): EditorConfig {
|
||||
dropdownLimit: Number.MAX_SAFE_INTEGER,
|
||||
extraCommands: buildExtraCommands()
|
||||
},
|
||||
template: {
|
||||
definitions: await getTemplates()
|
||||
},
|
||||
// This value must be kept in sync with the language defined in webpack.config.js.
|
||||
language: "en"
|
||||
};
|
||||
@ -206,6 +210,7 @@ export function buildClassicToolbar(multilineToolbar: boolean) {
|
||||
"outdent",
|
||||
"indent",
|
||||
"|",
|
||||
"insertTemplate",
|
||||
"markdownImport",
|
||||
"cuttonote",
|
||||
"findAndReplace"
|
||||
@ -262,6 +267,7 @@ export function buildFloatingToolbar() {
|
||||
"outdent",
|
||||
"indent",
|
||||
"|",
|
||||
"insertTemplate",
|
||||
"imageUpload",
|
||||
"markdownImport",
|
||||
"specialCharacters",
|
||||
|
105
apps/client/src/widgets/type_widgets/ckeditor/snippets.ts
Normal file
@ -0,0 +1,105 @@
|
||||
import debounce from "debounce";
|
||||
import froca from "../../../services/froca.js";
|
||||
import type LoadResults from "../../../services/load_results.js";
|
||||
import search from "../../../services/search.js";
|
||||
import type { TemplateDefinition } from "@triliumnext/ckeditor5";
|
||||
import appContext from "../../../components/app_context.js";
|
||||
import TemplateIcon from "@ckeditor/ckeditor5-icons/theme/icons/template.svg?raw";
|
||||
import type FNote from "../../../entities/fnote.js";
|
||||
|
||||
interface TemplateData {
|
||||
title: string;
|
||||
description?: string;
|
||||
content?: string;
|
||||
}
|
||||
|
||||
let templateCache: Map<string, TemplateData> = new Map();
|
||||
const debouncedHandleContentUpdate = debounce(handleContentUpdate, 1000);
|
||||
|
||||
/**
|
||||
* Generates the list of snippets based on the user's notes to be passed down to the CKEditor configuration.
|
||||
*
|
||||
* @returns the list of templates.
|
||||
*/
|
||||
export default async function getTemplates() {
|
||||
// Build the definitions and populate the cache.
|
||||
const snippets = await search.searchForNotes("#textSnippet");
|
||||
const definitions: TemplateDefinition[] = [];
|
||||
for (const snippet of snippets) {
|
||||
const { description } = await invalidateCacheFor(snippet);
|
||||
|
||||
definitions.push({
|
||||
title: snippet.title,
|
||||
data: () => templateCache.get(snippet.noteId)?.content ?? "",
|
||||
icon: TemplateIcon,
|
||||
description
|
||||
});
|
||||
}
|
||||
return definitions;
|
||||
}
|
||||
|
||||
async function invalidateCacheFor(snippet: FNote) {
|
||||
const description = snippet.getLabelValue("textSnippetDescription");
|
||||
const data: TemplateData = {
|
||||
title: snippet.title,
|
||||
description: description ?? undefined,
|
||||
content: await snippet.getContent()
|
||||
};
|
||||
templateCache.set(snippet.noteId, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
function handleFullReload() {
|
||||
console.warn("Full text editor reload needed");
|
||||
appContext.triggerCommand("reloadTextEditor");
|
||||
}
|
||||
|
||||
async function handleContentUpdate(affectedNoteIds: string[]) {
|
||||
const updatedNoteIds = new Set(affectedNoteIds);
|
||||
const templateNoteIds = new Set(templateCache.keys());
|
||||
const affectedTemplateNoteIds = templateNoteIds.intersection(updatedNoteIds);
|
||||
|
||||
await froca.getNotes(affectedNoteIds);
|
||||
|
||||
let fullReloadNeeded = false;
|
||||
for (const affectedTemplateNoteId of affectedTemplateNoteIds) {
|
||||
try {
|
||||
const template = await froca.getNote(affectedTemplateNoteId);
|
||||
if (!template) {
|
||||
console.warn("Unable to obtain template with ID ", affectedTemplateNoteId);
|
||||
continue;
|
||||
}
|
||||
|
||||
const newTitle = template.title;
|
||||
if (templateCache.get(affectedTemplateNoteId)?.title !== newTitle) {
|
||||
fullReloadNeeded = true;
|
||||
break;
|
||||
}
|
||||
|
||||
await invalidateCacheFor(template);
|
||||
} catch (e) {
|
||||
// If a note was not found while updating the cache, it means we need to do a full reload.
|
||||
fullReloadNeeded = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fullReloadNeeded) {
|
||||
handleFullReload();
|
||||
}
|
||||
}
|
||||
|
||||
export function updateTemplateCache(loadResults: LoadResults): boolean {
|
||||
const affectedNoteIds = loadResults.getNoteIds();
|
||||
|
||||
// React to creation or deletion of text snippets.
|
||||
if (loadResults.getAttributeRows().find((attr) =>
|
||||
attr.type === "label" &&
|
||||
(attr.name === "textSnippet" || attr.name === "textSnippetDescription"))) {
|
||||
handleFullReload();
|
||||
} else if (affectedNoteIds.length > 0) {
|
||||
// Update content and titles if one of the template notes were updated.
|
||||
debouncedHandleContentUpdate(affectedNoteIds);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
@ -18,6 +18,7 @@ import { getMermaidConfig } from "../../services/mermaid.js";
|
||||
import { PopupEditor, ClassicEditor, EditorWatchdog, type CKTextEditor, type MentionFeed, type WatchdogConfig } from "@triliumnext/ckeditor5";
|
||||
import "@triliumnext/ckeditor5/index.css";
|
||||
import { normalizeMimeTypeForCKEditor } from "@triliumnext/commons";
|
||||
import { updateTemplateCache } from "./ckeditor/snippets.js";
|
||||
|
||||
const mentionSetup: MentionFeed[] = [
|
||||
{
|
||||
@ -193,7 +194,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
|
||||
|
||||
const finalConfig = {
|
||||
...editorConfig,
|
||||
...buildConfig(),
|
||||
...(await buildConfig()),
|
||||
...buildToolbarConfig(isClassicEditor),
|
||||
htmlSupport: {
|
||||
allow: JSON.parse(options.get("allowedHtmlTags")),
|
||||
@ -326,7 +327,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
|
||||
const data = blob?.content || "";
|
||||
const newContentLanguage = this.note?.getLabelValue("language");
|
||||
if (this.contentLanguage !== newContentLanguage) {
|
||||
await this.reinitialize(data);
|
||||
await this.reinitializeWithData(data);
|
||||
} else {
|
||||
this.watchdog.editor?.setData(data);
|
||||
}
|
||||
@ -562,7 +563,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
|
||||
this.refreshIncludedNote(this.$editor, noteId);
|
||||
}
|
||||
|
||||
async reinitialize(data: string) {
|
||||
async reinitializeWithData(data: string) {
|
||||
if (!this.watchdog) {
|
||||
return;
|
||||
}
|
||||
@ -572,9 +573,25 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
|
||||
this.watchdog.editor?.setData(data);
|
||||
}
|
||||
|
||||
async onLanguageChanged() {
|
||||
async reinitialize() {
|
||||
const data = this.watchdog.editor?.getData();
|
||||
await this.reinitialize(data ?? "");
|
||||
await this.reinitializeWithData(data ?? "");
|
||||
}
|
||||
|
||||
async reloadTextEditorEvent() {
|
||||
await this.reinitialize();
|
||||
}
|
||||
|
||||
async onLanguageChanged() {
|
||||
await this.reinitialize();
|
||||
}
|
||||
|
||||
async entitiesReloadedEvent(e: EventData<"entitiesReloaded">) {
|
||||
await super.entitiesReloadedEvent(e);
|
||||
|
||||
if (updateTemplateCache(e.loadResults)) {
|
||||
await this.reinitialize();
|
||||
}
|
||||
}
|
||||
|
||||
buildTouchBarCommand(data: CommandListenerData<"buildTouchBar">) {
|
||||
|
2
apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json
generated
vendored
52
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing.html
generated
vendored
@ -6,7 +6,8 @@ class="image">
|
||||
<img style="aspect-ratio:1144/660;" src="Sharing_image.png" width="1144"
|
||||
height="660">
|
||||
</figure>
|
||||
<h2>Features, interaction and limitations</h2>
|
||||
|
||||
<h2>Features, interaction and limitations</h2>
|
||||
<ul>
|
||||
<li>Searching by note title.</li>
|
||||
<li>Automatic dark/light mode based on the user's browser settings.</li>
|
||||
@ -34,7 +35,7 @@ class="image">
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th><a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_iPIMuisry3hd">Text</a>
|
||||
<th><a class="reference-link" href="#root/_help_iPIMuisry3hd">Text</a>
|
||||
</th>
|
||||
<td>
|
||||
<ul>
|
||||
@ -52,7 +53,7 @@ class="image">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_6f9hih2hXXZk">Code</a>
|
||||
<th><a class="reference-link" href="#root/_help_6f9hih2hXXZk">Code</a>
|
||||
</th>
|
||||
<td>
|
||||
<ul>
|
||||
@ -66,27 +67,27 @@ class="image">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_m523cpzocqaD">Saved Search</a>
|
||||
<th><a class="reference-link" href="#root/_help_m523cpzocqaD">Saved Search</a>
|
||||
</th>
|
||||
<td colspan="2">Not supported.</td>
|
||||
<td>Not supported.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_iRwzGnHPzonm">Relation Map</a>
|
||||
<th><a class="reference-link" href="#root/_help_iRwzGnHPzonm">Relation Map</a>
|
||||
</th>
|
||||
<td colspan="2">Not supported.</td>
|
||||
<td>Not supported.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_bdUJEHsAPYQR">Note Map</a>
|
||||
<th><a class="reference-link" href="#root/_help_bdUJEHsAPYQR">Note Map</a>
|
||||
</th>
|
||||
<td colspan="2">Not supported.</td>
|
||||
<td>Not supported.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_HcABDtFCkbFN">Render Note</a>
|
||||
<th><a class="reference-link" href="#root/_help_HcABDtFCkbFN">Render Note</a>
|
||||
</th>
|
||||
<td colspan="2">Not supported.</td>
|
||||
<td>Not supported.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_GTwFsgaA0lCt">Book</a>
|
||||
<th><a class="reference-link" href="#root/_help_GTwFsgaA0lCt">Book</a>
|
||||
</th>
|
||||
<td>
|
||||
<ul>
|
||||
@ -100,7 +101,7 @@ class="image">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_s1aBHPd79XYj">Mermaid Diagrams</a>
|
||||
<th><a class="reference-link" href="#root/_help_s1aBHPd79XYj">Mermaid Diagrams</a>
|
||||
</th>
|
||||
<td>
|
||||
<ul>
|
||||
@ -114,7 +115,7 @@ class="image">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_grjYqerjn243">Canvas</a>
|
||||
<th><a class="reference-link" href="#root/_help_grjYqerjn243">Canvas</a>
|
||||
</th>
|
||||
<td>
|
||||
<ul>
|
||||
@ -128,12 +129,12 @@ class="image">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_1vHRoWCEjj0L">Web View</a>
|
||||
<th><a class="reference-link" href="#root/_help_1vHRoWCEjj0L">Web View</a>
|
||||
</th>
|
||||
<td colspan="2">Not supported.</td>
|
||||
<td>Not supported.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_gBbsAeiuUxI5">Mind Map</a>
|
||||
<th><a class="reference-link" href="#root/_help_gBbsAeiuUxI5">Mind Map</a>
|
||||
</th>
|
||||
<td>The diagram is displayed as a vector image.</td>
|
||||
<td>
|
||||
@ -143,12 +144,12 @@ class="image">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_81SGnPGMk7Xc">Geo Map</a>
|
||||
<th><a class="reference-link" href="#root/_help_81SGnPGMk7Xc">Geo Map</a>
|
||||
</th>
|
||||
<td colspan="2">Not supported.</td>
|
||||
<td>Not supported.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_W8vYD3Q1zjCR">File</a>
|
||||
<th><a class="reference-link" href="#root/_help_W8vYD3Q1zjCR">File</a>
|
||||
</th>
|
||||
<td>Basic interaction (downloading the file).</td>
|
||||
<td>
|
||||
@ -183,9 +184,11 @@ class="image">
|
||||
<img src="Sharing_share-single-note.png" alt="Share Note">
|
||||
</p>
|
||||
</li>
|
||||
<li><strong>Access the Shared Note</strong>: The link provided will open the
|
||||
note in your browser. If your server is not configured with a public IP,
|
||||
the URL will refer to <code>localhost (127.0.0.1)</code>.</li>
|
||||
<li>
|
||||
<p><strong>Access the Shared Note</strong>: The link provided will open the
|
||||
note in your browser. If your server is not configured with a public IP,
|
||||
the URL will refer to <code>localhost (127.0.0.1)</code>.</p>
|
||||
</li>
|
||||
</ol>
|
||||
<h2>Sharing a Note Subtree</h2>
|
||||
<p>When you share a note, you actually share the entire subtree of notes
|
||||
@ -337,7 +340,8 @@ for (const attr of parentNote.attributes) {
|
||||
</tbody>
|
||||
</table>
|
||||
</figure>
|
||||
<h2>Credits</h2>
|
||||
|
||||
<h2>Credits</h2>
|
||||
<p>Since v0.95.0, a new theme was introduced (and enabled by default) which
|
||||
greatly improves the visual aspect of the Share feature, as well as its
|
||||
functionality (such as mobile support, dark/light mode, collapsible tree,
|
||||
|
@ -24,6 +24,7 @@
|
||||
</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 <em>raw</em> when accessed from the share URL.</p>
|
||||
|
@ -146,6 +146,8 @@
|
||||
<li><code>#publicationYear %= '19[0-9]{2}'</code>: Use the '%=' operator to
|
||||
match a regular expression (regex). This feature has been available since
|
||||
Trilium 0.52.</li>
|
||||
<li><code>note.content %= '\\d{2}:\\d{2} (PM|AM)'</code>: Find notes that
|
||||
mention a time. Backslashes in a regex must be escaped.</li>
|
||||
</ul>
|
||||
<h3>Advanced Use Cases</h3>
|
||||
<ul>
|
||||
|
22
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text.html
generated
vendored
@ -142,18 +142,32 @@ class="table">
|
||||
</td>
|
||||
<td>
|
||||
<ul>
|
||||
<li>Indentation</li>
|
||||
<li>Markdown import</li>
|
||||
<li>Indentation
|
||||
<ul>
|
||||
<li>Markdown import</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference-link" href="#root/_help_2x0ZAX9ePtzV">Cut to subnote</a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/iPIMuisry3hd/_help_gLt3vA97tMcp">Premium features</a>
|
||||
</td>
|
||||
<td>
|
||||
<ul>
|
||||
<li><a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/iPIMuisry3hd/gLt3vA97tMcp/_help_ZlN4nump6EbW">Slash Commands</a>
|
||||
</li>
|
||||
<li><a class="reference-link" href="#root/pOsGYCXsbNQG/tC7s2alapj8V/_help_KC1HB96bqqHX">Templates</a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</figure>
|
||||
|
||||
<h2>Read-Only vs. Editing Mode</h2>
|
||||
<h2>Read-Only vs. Editing Mode</h2>
|
||||
<p>Text notes are usually opened in edit mode. However, they may open in
|
||||
read-only mode if the note is too big or the note is explicitly marked
|
||||
as read-only. For more information, see <a class="reference-link"
|
||||
|
17
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features.html
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
<p>The text editor we are using for <a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_iPIMuisry3hd">Text</a> notes
|
||||
is called CKEditor and it's a commercial product. The core components are
|
||||
open-source, however they <a href="https://ckeditor.com/docs/trial/latest/index.html">offer quite a few features</a> that
|
||||
require a commercial license in order to be used.</p>
|
||||
<p>We have reached out to the CKEditor team in order to obtain a license
|
||||
in order to have some of these extra features and they have agreed, based
|
||||
on a signed agreement.</p>
|
||||
<h2>How the license works</h2>
|
||||
|
||||
<p>The license key is stored in the application and it enables the use of
|
||||
the previously described premium features. The license key has an expiration
|
||||
date which means that the features can become disabled if using an older
|
||||
version of the application for extended periods of time.</p>
|
||||
<h2>Can I opt out of these features?</h2>
|
||||
|
||||
<p>At this moment there is no way to disable this features, apart from manually
|
||||
modifying the source code. If this is a problem, <a href="#root/pOsGYCXsbNQG/BgmBlOIl72jZ/_help_wy8So3yZZlH9">let us know</a>.</p>
|
BIN
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/1_Text Snippets_image.png
generated
vendored
Normal file
After Width: | Height: | Size: 377 B |
35
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/Slash Commands.html
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<figure class="image image-style-align-right">
|
||||
<img style="aspect-ratio:419/571" src="Slash Commands_image.png" width="419"
|
||||
height="571" />
|
||||
</figure>
|
||||
<aside class="admonition note">
|
||||
<p>This is a premium feature of the editor we are using (CKEditor) and we
|
||||
benefit from it thanks to an written agreement with the team. See <a class="reference-link"
|
||||
href="#root/_help_gLt3vA97tMcp">Premium features</a> for more information.</p>
|
||||
</aside>
|
||||
<p>Slash commands is a feature of <a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_iPIMuisry3hd">Text</a> notes
|
||||
which allows easily accessing commonly used commands simply by using the
|
||||
keyboard, without having to remember dedicated <a class="reference-link"
|
||||
href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/_help_A9Oc6YKKc65v">Keyboard Shortcuts</a>.</p>
|
||||
<h2>Interaction</h2>
|
||||
|
||||
<ul>
|
||||
<li>As the name suggests, to trigger the slash commands simply press the <kbd>/</kbd> key
|
||||
to trigger it. Note that this can be anywhere in a paragraph as long as
|
||||
it's not part of the word, if it doesn't show up simply press a space and
|
||||
press the <kbd>/</kbd> key again.</li>
|
||||
<li>Use <kbd>↑</kbd> and <kbd>↓</kbd> keys to navigate between options.</li>
|
||||
<li>By default, the full list of commands is displayed.</li>
|
||||
<li>To search by title or description, simply start typing for an action.</li>
|
||||
<li>To trigger an action, press the <kbd>Enter</kbd> key.</li>
|
||||
</ul>
|
||||
<h2>Integration with other features</h2>
|
||||
|
||||
<p>Apart from the common set of commands, some features are specially integrated
|
||||
with the slash commands:</p>
|
||||
<ul>
|
||||
<li>For <a href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/iPIMuisry3hd/_help_NwBbFdNZ9h7O">admonitions</a>,
|
||||
each admonition type (e.g. note, tip) will be individually displayed.</li>
|
||||
<li>Every <a class="reference-link" href="#root/_help_pwc194wlRzcH">Text Snippets</a> will
|
||||
also appear individually, making it easy to insert them.</li>
|
||||
</ul>
|
BIN
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/Slash Commands_image.png
generated
vendored
Normal file
After Width: | Height: | Size: 38 KiB |
56
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/Text Snippets.html
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
<figure class="image image-style-align-right">
|
||||
<img style="aspect-ratio:265/108" src="Text Snippets_image.png" width="265"
|
||||
height="108" />
|
||||
</figure>
|
||||
<aside class="admonition note">
|
||||
<p>This is a premium feature of the editor we are using (CKEditor) and we
|
||||
benefit from it thanks to an written agreement with the team. See <a class="reference-link"
|
||||
href="#root/_help_gLt3vA97tMcp">Premium features</a> for more information.</p>
|
||||
</aside>
|
||||
<p>Text Snippets are closely related to <a class="reference-link" href="#root/pOsGYCXsbNQG/tC7s2alapj8V/_help_KC1HB96bqqHX">Templates</a>,
|
||||
but instead of defining the content of an entire note, text snippets are
|
||||
pieces of formatted text that can easily be inserted in a text note.</p>
|
||||
<h2>Creating a text snippet</h2>
|
||||
|
||||
<p>In the <a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_oPVyFC7WL2Lp">Note Tree</a>: </p>
|
||||
<ol>
|
||||
<li>Right click a note where to place the text snippet.</li>
|
||||
<li>Select <em>Insert child note</em>.</li>
|
||||
<li>Select <em>Text snippet</em>.</li>
|
||||
</ol>
|
||||
<p>Afterwards, simply type in the content of the note the desired text. The
|
||||
text can be formatted in the same manner as a normal text note.</p>
|
||||
<p>The title of the note will become the title of the template. Optionally,
|
||||
a description can be added in the <a class="reference-link" href="#root/pOsGYCXsbNQG/tC7s2alapj8V/zEY4DaJG4YT5/_help_OFXdgB2nNk1F">Promoted Attributes</a> section.</p>
|
||||
<h2>Inserting a snippet</h2>
|
||||
|
||||
<p>Once a snippet is created, there are two options to insert it:</p>
|
||||
<ol>
|
||||
<li>From the <a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/iPIMuisry3hd/_help_nRhnJkTT8cPs">Formatting toolbar</a>,
|
||||
by looking for the
|
||||
<img src="1_Text Snippets_image.png" width="19" height="19"
|
||||
/>button.</li>
|
||||
<li>Using <a class="reference-link" href="#root/_help_ZlN4nump6EbW">Slash Commands</a>:
|
||||
<ol>
|
||||
<li>To look for a specific template, start typing the name of the template
|
||||
(its title).</li>
|
||||
<li>To look for all the templates, type <code>template</code>.</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
<aside class="admonition tip">
|
||||
<p>A newly created snippet doesn't appear? Generally it takes up to a few
|
||||
seconds to refresh the list of templates once you make a change.</p>
|
||||
<p>If this doesn't happen, <a href="#root/pOsGYCXsbNQG/BgmBlOIl72jZ/_help_s8alTXmpFR61">reload the application</a> and
|
||||
<a
|
||||
href="#root/pOsGYCXsbNQG/BgmBlOIl72jZ/_help_wy8So3yZZlH9">report the issue</a>to us. </p>
|
||||
</aside>
|
||||
<h2>Limitations</h2>
|
||||
|
||||
<ul>
|
||||
<li>Whenever a snippet is created, deleted or its title/description are modified,
|
||||
all the open text notes will need to be refreshed. This causes a slight
|
||||
flash for usually under a second, but it can cause some discomfort.</li>
|
||||
<li>Unlike <a class="reference-link" href="#root/pOsGYCXsbNQG/tC7s2alapj8V/_help_KC1HB96bqqHX">Templates</a>,
|
||||
the snippets cannot be limited to a particular <a href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/wArbEsdSae6g/_help_9sRHySam5fXb">workspace</a>.</li>
|
||||
</ul>
|
BIN
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/Text Snippets_image.png
generated
vendored
Normal file
After Width: | Height: | Size: 6.2 KiB |
@ -8,6 +8,7 @@ import migrationService from "./migration.js";
|
||||
import { t } from "i18next";
|
||||
import { cleanUpHelp, getHelpHiddenSubtreeData } from "./in_app_help.js";
|
||||
import buildLaunchBarConfig from "./hidden_subtree_launcherbar.js";
|
||||
import buildHiddenSubtreeTemplates from "./hidden_subtree_templates.js";
|
||||
|
||||
const LBTPL_ROOT = "_lbTplRoot";
|
||||
const LBTPL_BASE = "_lbTplBase";
|
||||
@ -257,7 +258,8 @@ function buildHiddenSubtreeDefinition(helpSubtree: HiddenSubtreeItem[]): HiddenS
|
||||
icon: "bx-help-circle",
|
||||
children: helpSubtree,
|
||||
isExpanded: true
|
||||
}
|
||||
},
|
||||
buildHiddenSubtreeTemplates()
|
||||
]
|
||||
};
|
||||
}
|
||||
|
34
apps/server/src/services/hidden_subtree_templates.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { HiddenSubtreeItem } from "@triliumnext/commons";
|
||||
|
||||
export default function buildHiddenSubtreeTemplates() {
|
||||
const templates: HiddenSubtreeItem = {
|
||||
id: "_templates",
|
||||
title: "Built-in templates",
|
||||
type: "book",
|
||||
children: [
|
||||
{
|
||||
id: "_template_text_snippet",
|
||||
type: "text",
|
||||
title: "Text Snippet",
|
||||
icon: "bx-align-left",
|
||||
attributes: [
|
||||
{
|
||||
name: "template",
|
||||
type: "label"
|
||||
},
|
||||
{
|
||||
name: "textSnippet",
|
||||
type: "label"
|
||||
},
|
||||
{
|
||||
name: "label:textSnippetDescription",
|
||||
type: "label",
|
||||
value: "promoted,alias=Description,single,text"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
return templates;
|
||||
}
|
@ -257,7 +257,7 @@ async function configureWebContents(webContents: WebContents, spellcheckEnabled:
|
||||
}
|
||||
|
||||
function getIcon() {
|
||||
return path.join(RESOURCE_DIR, "images/app-icons/png/256x256" + (isDev ? "-dev" : "") + ".png");
|
||||
return path.join(RESOURCE_DIR, "../public/assets/icon.png");
|
||||
}
|
||||
|
||||
async function createSetupWindow() {
|
||||
|
@ -1,2 +1,10 @@
|
||||
@import 'tailwindcss';
|
||||
@plugin '@tailwindcss/typography';
|
||||
|
||||
main a {
|
||||
text-decoration: revert;
|
||||
}
|
||||
|
||||
a.rounded-full, a.rounded-xl {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
<body data-sveltekit-preload-data="hover" class="dark:bg-black dark:text-white">
|
||||
%sveltekit.body%
|
||||
</body>
|
||||
</html>
|
||||
|
@ -41,6 +41,14 @@ export const downloadMatrix: DownloadMatrix = {
|
||||
},
|
||||
zip: {
|
||||
name: "Portable (.zip)"
|
||||
},
|
||||
scoop: {
|
||||
name: "Scoop",
|
||||
url: "https://scoop.sh/#/apps?q=triliumnext"
|
||||
},
|
||||
winget: {
|
||||
name: "Winget",
|
||||
url: "https://github.com/microsoft/winget-pkgs/tree/master/manifests/t/TriliumNext/Notes/"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -66,6 +74,14 @@ export const downloadMatrix: DownloadMatrix = {
|
||||
},
|
||||
zip: {
|
||||
name: "Portable (.zip)"
|
||||
},
|
||||
nixpkgs: {
|
||||
name: "nixpkgs",
|
||||
url: "https://search.nixos.org/packages?query=trilium-next"
|
||||
},
|
||||
aur: {
|
||||
name: "AUR",
|
||||
url: "https://aur.archlinux.org/packages/triliumnext-bin"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -107,6 +123,10 @@ export const downloadMatrix: DownloadMatrix = {
|
||||
name: "ARM (.tar.xz)",
|
||||
url: `https://github.com/TriliumNext/Notes/releases/download/v${version}/TriliumNextNotes-Server-v${version}-linux-arm64.tar.xz`
|
||||
},
|
||||
nixos: {
|
||||
name: "NixOS module",
|
||||
url: "https://search.nixos.org/options?query=trilium-server"
|
||||
}
|
||||
}
|
||||
},
|
||||
pikapod: {
|
||||
@ -129,7 +149,8 @@ export const downloadMatrix: DownloadMatrix = {
|
||||
|
||||
export function buildDownloadUrl(app: App, platform: Platform, format: string, architecture: Architecture): string {
|
||||
if (app === "desktop") {
|
||||
return `https://github.com/TriliumNext/Notes/releases/download/v${version}/TriliumNextNotes-v${version}-${platform}-${architecture}.${format}`;
|
||||
return downloadMatrix.desktop[platform]?.downloads[format].url ??
|
||||
`https://github.com/TriliumNext/Notes/releases/download/v${version}/TriliumNextNotes-v${version}-${platform}-${architecture}.${format}`;
|
||||
} else if (app === "server") {
|
||||
return downloadMatrix.server[platform]?.downloads[format].url ?? "#";
|
||||
} else {
|
||||
|
@ -7,8 +7,10 @@
|
||||
|
||||
<Header />
|
||||
|
||||
<main>
|
||||
{@render children()}
|
||||
</main>
|
||||
|
||||
<footer class="container mx-auto bg-white mt-2 py-6 text-sm text-center text-gray-500">
|
||||
<footer class="container max-w-screen mx-0 w-full bg-white dark:bg-gray-900 mt-2 py-6 text-sm text-center text-gray-500">
|
||||
© 2024-2025 <a href="https://github.com/eliandoran" class="text-blue-500 hover:underline">Elian Doran</a> and the <a href="https://github.com/TriliumNext/Notes/graphs/contributors" class="text-blue-500 hover:underline">team</a>. <br/> © 2017-2024 <a href="https://github.com/zadam" class="text-blue-500 hover:underline">Adam Zivner</a>.
|
||||
</footer>
|
||||
</footer>
|
||||
|
@ -1,8 +1,16 @@
|
||||
<script>
|
||||
import DownloadNow from "./download-now.svelte";
|
||||
import FeatureBlock from "./feature-block.svelte";
|
||||
</script>
|
||||
|
||||
<section class="relative overflow-hidden bg-gradient-to-br from-white to-violet-50">
|
||||
<svelte:head>
|
||||
<title>Trilium Notes</title>
|
||||
<!-- TODO: description?
|
||||
<meta name="description" content="This is where the description goes for search engines" />
|
||||
-->
|
||||
</svelte:head>
|
||||
|
||||
<section class="relative overflow-hidden bg-gradient-to-br from-white dark:from-black to-violet-50 dark:to-violet-900">
|
||||
<!-- Bokeh background circles -->
|
||||
<div class="absolute inset-0 pointer-events-none z-0">
|
||||
<div class="absolute w-72 h-72 bg-violet-300 opacity-30 rounded-full blur-3xl top-[-50px] left-[-80px]"></div>
|
||||
@ -15,10 +23,12 @@
|
||||
|
||||
<!-- Left: Text Content -->
|
||||
<div class="md:w-1/3">
|
||||
<h2 class="text-4xl font-bold mb-4 text-gray-900">Organize Your Thoughts.<br/> Build Your Knowledge.</h2>
|
||||
<p class="text-lg mb-6 text-gray-700">
|
||||
<h2 class="text-4xl font-bold mb-4 text-gray-900 dark:text-white">Organize Your Thoughts.<br/> Build Your Knowledge.</h2>
|
||||
<p class="text-lg mb-6 text-gray-700 dark:text-gray-300">
|
||||
Trilium Notes helps you build and organize complex personal knowledge bases effortlessly.
|
||||
Its unique tree structure, rich editing tools, and powerful search features make managing your information intuitive and flexible.
|
||||
<!-- TODO: remove the squiggly autocorrect lines in the screenshot!! -->
|
||||
<!-- TODO: dark mode screenshot -->
|
||||
</p>
|
||||
<div class="flex items-center gap-6">
|
||||
<DownloadNow big />
|
||||
@ -40,48 +50,72 @@
|
||||
<h2 class="text-3xl font-bold text-center mb-12">Beyond Text: Smarter Note Types</h2>
|
||||
|
||||
<div class="grid md:grid-cols-2 gap-10">
|
||||
<!-- Canvas Notes -->
|
||||
<div class="bg-white rounded-xl shadow overflow-hidden">
|
||||
<img src="/note-types/canvas.png" alt="Canvas Note Screenshot" class="w-full h-56 object-cover object-top">
|
||||
<div class="p-6">
|
||||
<h3 class="text-xl font-semibold mb-2">Canvas Notes</h3>
|
||||
<p class="text-gray-600">Draw and arrange elements freely using an Excalidraw-powered canvas — ideal for diagrams, sketches, and visual planning.</p>
|
||||
</div>
|
||||
</div>
|
||||
<FeatureBlock
|
||||
imgSrc="/note-types/canvas.png"
|
||||
imgAlt="Canvas Note Screenshot"
|
||||
title="Canvas Notes"
|
||||
text="Draw and arrange elements freely using an Excalidraw-powered canvas — ideal for diagrams, sketches, and visual planning."
|
||||
/>
|
||||
|
||||
<!-- Mermaid Diagrams -->
|
||||
<div class="bg-white rounded-xl shadow overflow-hidden">
|
||||
<img src="/note-types/mermaid.png" alt="Mermaid Diagram Screenshot" class="w-full h-56 object-cover object-top">
|
||||
<div class="p-6">
|
||||
<h3 class="text-xl font-semibold mb-2">Mermaid Diagrams</h3>
|
||||
<p class="text-gray-600">Render flowcharts, Gantt charts, and sequence diagrams with Mermaid markdown syntax directly in your notes.</p>
|
||||
</div>
|
||||
</div>
|
||||
<FeatureBlock
|
||||
imgSrc="/note-types/mermaid.png"
|
||||
imgAlt="Mermaid Diagram Screenshot"
|
||||
title="Mermaid Diagrams"
|
||||
text="Render flowcharts, Gantt charts, and sequence diagrams with Mermaid markdown syntax directly in your notes."
|
||||
/>
|
||||
|
||||
<!-- Geo Maps -->
|
||||
<div class="bg-white rounded-xl shadow overflow-hidden">
|
||||
<img src="/note-types/geo-map.png" alt="Geo Map Screenshot" class="w-full h-56 object-cover">
|
||||
<div class="p-6">
|
||||
<h3 class="text-xl font-semibold mb-2">Geo Maps</h3>
|
||||
<p class="text-gray-600">Plot locations and GPX tracks to visualize geography-linked notes and movement patterns on interactive maps.</p>
|
||||
</div>
|
||||
</div>
|
||||
<FeatureBlock
|
||||
imgSrc="/note-types/geo-map.png"
|
||||
imgAlt="Geo Map Screenshot"
|
||||
title="Geo Maps"
|
||||
text="Plot locations and GPX tracks to visualize geography-linked notes and movement patterns on interactive maps."
|
||||
/>
|
||||
|
||||
<!-- Mind Maps -->
|
||||
<div class="bg-white rounded-xl shadow overflow-hidden">
|
||||
<img src="/note-types/mind-map.png" alt="Mind Map Screenshot" class="w-full h-56 object-cover">
|
||||
<div class="p-6">
|
||||
<h3 class="text-xl font-semibold mb-2">Mind Maps</h3>
|
||||
<p class="text-gray-600">Organize ideas visually using a drag-and-drop mind map editor powered by Mind Elixir.</p>
|
||||
</div>
|
||||
</div>
|
||||
<FeatureBlock
|
||||
imgSrc="/note-types/mind-map.png"
|
||||
imgAlt="Mind Map Screenshot"
|
||||
title="Mind Maps"
|
||||
text="Organize ideas visually using a drag-and-drop mind map editor powered by Mind Elixir."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h2 class="text-3xl font-bold text-center mb-12">Technical Features</h2>
|
||||
|
||||
<div class="grid md:grid-cols-2 gap-10">
|
||||
<FeatureBlock
|
||||
imgSrc="/technical-features/sync-server.png"
|
||||
imgAlt="TODO"
|
||||
title="Synchronization Server"
|
||||
text="Seamless mirroring of changes acroll all devices."
|
||||
/>
|
||||
|
||||
<FeatureBlock
|
||||
imgSrc="/technical-features/cross-platform.png"
|
||||
imgAlt="TODO, maybe some icons"
|
||||
title="Cross-platform App + Web UI"
|
||||
text="Use as Electron application or in your browser."
|
||||
/>
|
||||
|
||||
<FeatureBlock
|
||||
imgSrc="/technical-features/scripting.png"
|
||||
imgAlt="TODO"
|
||||
title="Scripting"
|
||||
text="Custom UI widgets and a REST API for automation."
|
||||
/>
|
||||
|
||||
<FeatureBlock
|
||||
imgSrc="/technical-features/grafana-metrics.png"
|
||||
imgAlt="Mind Map Screenshot"
|
||||
title="Grafana Metrics"
|
||||
text="Measure database metrics over time."
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mt-20 max-w-6xl mx-auto px-4">
|
||||
<h2 class="text-3xl font-bold text-center mb-12">Feature Highlights</h2>
|
||||
|
||||
<div class="grid gap-12 md:grid-cols-2 max-w-4xl mx-auto text-gray-700">
|
||||
<div class="grid gap-12 md:grid-cols-2 max-w-4xl mx-auto text-gray-700 dark:text-gray-300">
|
||||
<!-- Organization & Navigation -->
|
||||
<div>
|
||||
<h3 class="flex items-center text-xl font-semibold mb-6 text-violet-700">Organization & Navigation</h3>
|
||||
@ -109,7 +143,6 @@
|
||||
<h3 class="flex items-center text-xl font-semibold mb-6 text-violet-700">Security & Sync</h3>
|
||||
<ul class="list-disc list-inside space-y-3">
|
||||
<li>Direct OpenID and TOTP integration for secure login.</li>
|
||||
<li>Synchronization with self-hosted and third-party servers.</li>
|
||||
<li>Strong note encryption with per-note granularity.</li>
|
||||
<li>Sharing notes publicly on the internet.</li>
|
||||
</ul>
|
||||
@ -120,10 +153,8 @@
|
||||
<h3 class="flex items-center text-xl font-semibold mb-6 text-violet-700">Advanced & Customization</h3>
|
||||
<ul class="list-disc list-inside space-y-3">
|
||||
<li>Relation maps and link maps to visualize notes.</li>
|
||||
<li>Scripting support and REST API for automation.</li>
|
||||
<li>Touch-optimized mobile frontend and dark/user themes.</li>
|
||||
<li>Customizable UI with sidebar buttons and user widgets.</li>
|
||||
<li>Metrics with Grafana dashboard integration.</li>
|
||||
<li>Scales efficiently beyond 100,000 notes.</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -131,13 +162,13 @@
|
||||
</section>
|
||||
|
||||
|
||||
<section class="bg-violet-50 py-16 mt-24">
|
||||
<section class="bg-violet-50 dark:bg-black py-16 mt-24">
|
||||
<div class="container mx-auto text-center px-4">
|
||||
<h2 class="text-3xl font-bold mb-4">Ready to get started with Trilium Notes?</h2>
|
||||
<p class="text-lg text-gray-700 mb-8">Build your personal knowledge base with powerful features and full privacy.</p>
|
||||
<p class="text-lg text-gray-700 dark:text-gray-200 mb-8">Build your personal knowledge base with powerful features and full privacy.</p>
|
||||
|
||||
<div class="flex justify-center gap-6">
|
||||
<a href="#" class="py-3 px-6 bg-violet-600 text-white font-semibold rounded-full shadow hover:bg-violet-700 focus:outline-none focus:ring focus:ring-violet-400 focus:ring-opacity-75">
|
||||
<a href="download" class="py-3 px-6 bg-violet-600 text-white font-semibold rounded-full shadow hover:bg-violet-700 focus:outline-none focus:ring focus:ring-violet-400 focus:ring-opacity-75">
|
||||
Download Now
|
||||
</a>
|
||||
</div>
|
||||
|
@ -7,13 +7,20 @@
|
||||
let architecture = getArchitecture();
|
||||
</script>
|
||||
|
||||
<div class="bg-gray-50 py-20">
|
||||
<svelte:head>
|
||||
<title>Trilium Notes: Download</title>
|
||||
<!-- TODO: description?
|
||||
<meta name="description" content="This is where the description goes for search engines" />
|
||||
-->
|
||||
</svelte:head>
|
||||
|
||||
<div class="bg-gray-50 dark:bg-black py-20">
|
||||
<section class="max-w-6xl mx-auto px-4">
|
||||
<h2 class="text-4xl font-bold text-center text-gray-900 mb-12">Download the desktop application</h2>
|
||||
<h2 class="text-4xl font-bold text-center text-gray-900 dark:text-white mb-12">Download the desktop application</h2>
|
||||
|
||||
<!-- Architecture pill selector -->
|
||||
<div class="col-span-3 flex justify-center items-center gap-3 mb-6">
|
||||
<span class="text-gray-600 font-medium mr-2">Architecture:</span>
|
||||
<span class="text-gray-600 dark:text-gray-300 font-medium mr-2">Architecture:</span>
|
||||
<div class="inline-flex bg-violet-100 rounded-full shadow p-1">
|
||||
{#each architectures as arch}
|
||||
<button class="py-2 px-6 rounded-full font-semibold focus:outline-none transition
|
||||
@ -28,7 +35,7 @@
|
||||
|
||||
<div class="grid md:grid-cols-3 gap-10">
|
||||
{#each Object.entries(downloadMatrix.desktop) as [platformId, platform]}
|
||||
{@const textColor = (platformId === "windows" ? "text-blue-600" : platformId === "linux" ? "text-violet-600" : "text-gray-800")}
|
||||
{@const textColor = (platformId === "windows" ? "text-blue-600" : platformId === "linux" ? "text-violet-600" : "text-gray-800 dark:text-gray-100")}
|
||||
{@const bgColor = (platformId === "windows" ? "bg-blue-600" : platformId === "linux" ? "bg-violet-600" : "bg-gray-800")}
|
||||
{@const hoverColor = (platformId === "windows" ? "hover:bg-blue-700" : platformId === "linux" ? "hover:bg-violet-700" : "hover:bg-gray-900")}
|
||||
<DownloadCard app="desktop"
|
||||
@ -39,11 +46,11 @@
|
||||
</section>
|
||||
|
||||
<section class="max-w-4xl mx-auto px-4 mt-10">
|
||||
<h2 class="text-3xl font-bold text-center text-gray-900 mb-8">Set up a server for access on multiple devices</h2>
|
||||
<h2 class="text-3xl font-bold text-center text-gray-900 dark:text-white mb-8">Set up a server for access on multiple devices</h2>
|
||||
|
||||
<div class="grid md:grid-cols-2 gap-10">
|
||||
{#each Object.entries(downloadMatrix.server) as [platformId, platform]}
|
||||
{@const textColor = (platformId === "linux" ? "text-violet-600" : "text-gray-800")}
|
||||
{@const textColor = (platformId === "linux" ? "text-violet-600" : "text-gray-800 dark:text-gray-100")}
|
||||
{@const bgColor = (platformId === "linux" ? "bg-violet-600" : "bg-gray-800")}
|
||||
{@const hoverColor = (platformId === "linux" ? "hover:bg-violet-700" : "hover:bg-gray-900")}
|
||||
<DownloadCard app="server"
|
||||
@ -53,4 +60,6 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- TODO: mention mobile support here? (alpha Android app / mobile web view) -->
|
||||
|
||||
</div>
|
||||
|
@ -11,16 +11,16 @@
|
||||
const recommended = Object.entries(platform.downloads).find((e) => e[1].recommended);
|
||||
</script>
|
||||
|
||||
<div class="bg-white border border-gray-200 rounded-2xl shadow-lg p-8 flex flex-col items-start">
|
||||
<div class="bg-white dark:bg-gray-900 border border-gray-200 rounded-2xl shadow-lg p-8 flex flex-col items-start">
|
||||
<h3 class="text-2xl font-semibold {textColor} mb-2">{typeof platform.title === "object" ? platform.title[architecture] : platform.title}</h3>
|
||||
<p class="text-gray-700 mb-12">{typeof platform.title === "object" ? platform.description[architecture] : platform.description}</p>
|
||||
<p class="text-gray-700 dark:text-gray-200 mb-12">{typeof platform.title === "object" ? platform.description[architecture] : platform.description}</p>
|
||||
<div class="space-y-2 mt-auto w-full">
|
||||
{#if recommended}
|
||||
<a href={buildDownloadUrl(app, platformId as Platform, recommended[0], architecture)} class="mt-auto block text-center {bgColor} {hoverColor} text-white font-medium py-2 px-5 rounded-full shadow transition">
|
||||
{recommended[1].name}
|
||||
</a>
|
||||
{/if}
|
||||
<div class="flex justify-center gap-4 text-sm {textColor} mt-2">
|
||||
<div class="flex flex-wrap justify-center gap-4 text-sm {textColor} mt-2">
|
||||
{#each Object.entries(platform.downloads).filter((e) => !e[1].recommended) as [format, download]}
|
||||
<a href={buildDownloadUrl(app, platformId as Platform, format, architecture)} class="hover:underline block">
|
||||
{download.name}
|
||||
|
14
apps/website/src/routes/feature-block.svelte
Normal file
@ -0,0 +1,14 @@
|
||||
<script>
|
||||
export let imgSrc = "/404.png";
|
||||
export let imgAlt = "screenshot";
|
||||
export let title = "title";
|
||||
export let text = "text";
|
||||
</script>
|
||||
|
||||
<div class="bg-white dark:bg-gray-900 rounded-xl shadow overflow-hidden">
|
||||
<img src="{imgSrc}" alt="{imgAlt}" class="w-full h-56 object-cover object-top">
|
||||
<div class="p-6">
|
||||
<h3 class="text-xl font-semibold mb-2">{title}</h3>
|
||||
<p class="text-gray-600 dark:text-gray-300">{text}</p>
|
||||
</div>
|
||||
</div>
|
@ -2,7 +2,7 @@
|
||||
import DownloadNow from "./download-now.svelte";
|
||||
|
||||
</script>
|
||||
<header class="header bg-white sticky top-0 z-50 shadow">
|
||||
<header class="header bg-white dark:bg-gray-900 sticky dark:text-white top-0 z-50 shadow">
|
||||
<div class="container mx-auto flex items-center py-4">
|
||||
<a href="/" class="flex items-center gap-x-2 w-100">
|
||||
<img src="icon-color.svg" alt="Trilium Notes Logo" class="w-12 h-12">
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 40 B |
1
apps/website/static/favicon.png
Symbolic link
@ -0,0 +1 @@
|
||||
../../../apps/client/src/assets/icon.png
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 40 B |
BIN
apps/website/static/screenshots/macos/dark.png
Normal file
After Width: | Height: | Size: 804 KiB |
BIN
apps/website/static/screenshots/macos/light.png
Normal file
After Width: | Height: | Size: 785 KiB |
1
apps/website/static/technical-features/grafana-metrics.png
Symbolic link
@ -0,0 +1 @@
|
||||
../../../../docs/User Guide/User Guide/Advanced Usage/1_Metrics_image.png
|
3182
docs/Developer Guide/!!!meta.json
vendored
76
docs/Developer Guide/Developer Guide/Building and deployment/Nix flake.md
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
# Nix flake
|
||||
Since TriliumNext 0.94.1, the desktop and server applications can be built using [Nix](https://nixos.org/).
|
||||
|
||||
## System requirements
|
||||
|
||||
Installation of Nix on Mac or Linux ([download page](https://nixos.org/download/)). About 3-4 gigabytes of additional storage space, for build artifacts.
|
||||
|
||||
## Run directly
|
||||
|
||||
Using [nix run](https://nix.dev/manual/nix/stable/command-ref/new-cli/nix3-run.html), the desktop app can be started as: `nix run github:TriliumNext/Notes/v0.95.0`
|
||||
|
||||
Running the server requires explicitly specifying the desired package: `nix run github:TriliumNext/Notes/v0.95.0#server`
|
||||
|
||||
Instead of a version (`v0.95.0` above), you can also specify a commit hash (or a branch name). This makes it easy to test development builds.
|
||||
|
||||
## Install on NixOS
|
||||
|
||||
Add to your `flake.nix`:
|
||||
|
||||
```
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = # ...;
|
||||
trilium-notes = {
|
||||
url = "github:TriliumNext/Notes/v0.95.0";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
outputs =
|
||||
{
|
||||
self,
|
||||
# ...
|
||||
trilium-notes,
|
||||
...
|
||||
}:
|
||||
{
|
||||
nixosConfigurations = {
|
||||
"nixos" = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./configuration.nix
|
||||
];
|
||||
specialArgs = {
|
||||
inherit
|
||||
trilium-notes
|
||||
;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Add to your `configuration.nix`:
|
||||
|
||||
```
|
||||
{
|
||||
# ...
|
||||
trilium-notes,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
# ...
|
||||
|
||||
services.trilium-server.package = trilium-notes.packages.x86_64-linux.server;
|
||||
|
||||
environment.systemPackages = [
|
||||
trilium-notes.packages.x86_64-linux.desktop
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
The flake aims to be compatible with the latest NixOS stable and unstable.
|
@ -1,4 +1,4 @@
|
||||
# Build information
|
||||
* Provides context about when the build was made and the corresponding Git revision.
|
||||
* The information is displayed to the client when going in the about dialog.
|
||||
* The build information is hard-coded in `src/services/build.ts`. This file is generated automatically via `npm run update-build-info` which itself is run automatically whenever making a build in the CI, or a [local delivery](../Build%20deliveries%20locally.md).
|
||||
* The build information is hard-coded in `src/services/build.ts`. This file is generated automatically via `npm run update-build-info` which itself is run automatically whenever making a build in the CI, or a [local delivery](../Old%20documentation/Build%20deliveries%20locally.md).
|
@ -17,7 +17,7 @@ These are stored in `images`:
|
||||
|
||||
## App icons
|
||||
|
||||
<figure class="table"><table><thead><tr><th>Name</th><th>Resolution</th><th>Description</th></tr></thead><tbody><tr><td><code>ios/apple-touch-icon.png</code></td><td>180x180</td><td>Used as <code>apple-touch-icon</code>, but only in <code>login.ejs</code> and <code>set_password.ejs</code> for some reason.</td></tr><tr><td><code>mac/icon.icns</code></td><td>512x512</td><td>Provided as <code>--icon</code> to <code>electron-packager</code> for <code>mac-arm64</code> and <code>mac-x64</code> <a href="../Build%20deliveries%20locally.md">builds</a>.</td></tr><tr><td><code>png/128x128.png</code></td><td>128x128</td><td>Used in <code>linux-x64</code> <a href="../Build%20deliveries%20locally.md">build</a>, to provide an <code>icon.png</code>.</td></tr><tr><td><code>png/256x256-dev.png</code></td><td>256x256</td><td>Used by the Electron window icon, if in dev mode.</td></tr><tr><td><code>png/256x256.png</code></td><td>Used by the Electron window icon, if not in dev mode.</td></tr><tr><td><code>win/icon.ico</code></td><td><ul><li>ICO 16x16</li><li>ICO 32x32</li><li>ICO 48x48</li><li>ICO 64x64</li><li>ICO 128x128</li><li>PNG 256x256</li></ul></td><td><ul><li>Used by the <code>win-x64</code> <a href="../Build%20deliveries%20locally.md">build</a>.</li><li>Used by Squirrel Windows installer for: setup icon, app icon, control panel icon</li><li>Used as the favicon.</li></ul></td></tr><tr><td><code>win/setup-banner.gif</code></td><td>640x480</td><td>Used by the Squirrel Windows installer during the installation process. Has only one frame.</td></tr></tbody></table></figure>
|
||||
<figure class="table"><table><thead><tr><th>Name</th><th>Resolution</th><th>Description</th></tr></thead><tbody><tr><td><code>ios/apple-touch-icon.png</code></td><td>180x180</td><td>Used as <code>apple-touch-icon</code>, but only in <code>login.ejs</code> and <code>set_password.ejs</code> for some reason.</td></tr><tr><td><code>mac/icon.icns</code></td><td>512x512</td><td>Provided as <code>--icon</code> to <code>electron-packager</code> for <code>mac-arm64</code> and <code>mac-x64</code> <a href="../Old%20documentation/Build%20deliveries%20locally.md">builds</a>.</td></tr><tr><td><code>png/128x128.png</code></td><td>128x128</td><td>Used in <code>linux-x64</code> <a href="../Old%20documentation/Build%20deliveries%20locally.md">build</a>, to provide an <code>icon.png</code>.</td></tr><tr><td><code>png/256x256-dev.png</code></td><td>256x256</td><td>Used by the Electron window icon, if in dev mode.</td></tr><tr><td><code>png/256x256.png</code></td><td>Used by the Electron window icon, if not in dev mode.</td></tr><tr><td><code>win/icon.ico</code></td><td><ul><li>ICO 16x16</li><li>ICO 32x32</li><li>ICO 48x48</li><li>ICO 64x64</li><li>ICO 128x128</li><li>PNG 256x256</li></ul></td><td><ul><li>Used by the <code>win-x64</code> <a href="../Old%20documentation/Build%20deliveries%20locally.md">build</a>.</li><li>Used by Squirrel Windows installer for: setup icon, app icon, control panel icon</li><li>Used as the favicon.</li></ul></td></tr><tr><td><code>win/setup-banner.gif</code></td><td>640x480</td><td>Used by the Squirrel Windows installer during the installation process. Has only one frame.</td></tr></tbody></table></figure>
|
||||
|
||||
## Additional locations where the branding is used
|
||||
|
Before Width: | Height: | Size: 233 KiB After Width: | Height: | Size: 233 KiB |
Before Width: | Height: | Size: 233 KiB After Width: | Height: | Size: 233 KiB |
Before Width: | Height: | Size: 748 KiB After Width: | Height: | Size: 748 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 250 KiB After Width: | Height: | Size: 250 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 251 KiB After Width: | Height: | Size: 251 KiB |
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 716 KiB After Width: | Height: | Size: 716 KiB |
Before Width: | Height: | Size: 336 KiB After Width: | Height: | Size: 336 KiB |