Merge remote-tracking branch 'origin/main' into copilot/add-technical-documentation
4
.github/workflows/deploy-docs.yml
vendored
@@ -10,6 +10,7 @@ on:
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- 'apps/edit-docs/**'
|
||||
- 'apps/build-docs/**'
|
||||
- 'packages/share-theme/**'
|
||||
|
||||
# Allow manual triggering from Actions tab
|
||||
@@ -23,6 +24,7 @@ on:
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- 'apps/edit-docs/**'
|
||||
- 'apps/build-docs/**'
|
||||
- 'packages/share-theme/**'
|
||||
|
||||
jobs:
|
||||
@@ -60,6 +62,8 @@ jobs:
|
||||
- name: Validate Built Site
|
||||
run: |
|
||||
test -f site/index.html || (echo "ERROR: site/index.html not found" && exit 1)
|
||||
test -f site/developer-guide/index.html || (echo "ERROR: site/developer-guide/index.html not found" && exit 1)
|
||||
echo "✓ User Guide and Developer Guide built successfully"
|
||||
|
||||
- name: Deploy
|
||||
uses: ./.github/actions/deploy-to-cloudflare-pages
|
||||
|
||||
@@ -38,10 +38,10 @@
|
||||
"@playwright/test": "1.56.1",
|
||||
"@stylistic/eslint-plugin": "5.5.0",
|
||||
"@types/express": "5.0.5",
|
||||
"@types/node": "24.9.2",
|
||||
"@types/node": "24.10.0",
|
||||
"@types/yargs": "17.0.34",
|
||||
"@vitest/coverage-v8": "3.2.4",
|
||||
"eslint": "9.39.0",
|
||||
"eslint": "9.39.1",
|
||||
"eslint-plugin-simple-import-sort": "12.1.1",
|
||||
"esm": "3.2.25",
|
||||
"jsdoc": "4.0.5",
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"keywords": [],
|
||||
"author": "Elian Doran <contact@eliandoran.me>",
|
||||
"license": "AGPL-3.0-only",
|
||||
"packageManager": "pnpm@10.19.0",
|
||||
"packageManager": "pnpm@10.20.0",
|
||||
"devDependencies": {
|
||||
"@redocly/cli": "2.10.0",
|
||||
"archiver": "7.0.1",
|
||||
|
||||
@@ -14,17 +14,12 @@ import BuildContext from "./context.js";
|
||||
const DOCS_ROOT = "../../../docs";
|
||||
const OUTPUT_DIR = "../../site";
|
||||
|
||||
async function buildDocsInner() {
|
||||
const i18n = await import("@triliumnext/server/src/services/i18n.js");
|
||||
await i18n.initializeTranslations();
|
||||
async function importAndExportDocs(sourcePath: string, outputSubDir: string) {
|
||||
const note = await importData(sourcePath);
|
||||
|
||||
const sqlInit = (await import("../../server/src/services/sql_init.js")).default;
|
||||
await sqlInit.createInitialDatabase(true);
|
||||
|
||||
const note = await importData(join(__dirname, DOCS_ROOT, "User Guide"));
|
||||
|
||||
// Export
|
||||
const zipFilePath = "output.zip";
|
||||
// Use a meaningful name for the temporary zip file
|
||||
const zipName = outputSubDir || "user-guide";
|
||||
const zipFilePath = `output-${zipName}.zip`;
|
||||
try {
|
||||
const { exportToZip } = (await import("@triliumnext/server/src/services/export/zip.js")).default;
|
||||
const branch = note.getParentBranches()[0];
|
||||
@@ -36,25 +31,50 @@ async function buildDocsInner() {
|
||||
const fileOutputStream = fsExtra.createWriteStream(zipFilePath);
|
||||
await exportToZip(taskContext, branch, "share", fileOutputStream);
|
||||
await waitForStreamToFinish(fileOutputStream);
|
||||
await extractZip(zipFilePath, OUTPUT_DIR);
|
||||
|
||||
// Output to root directory if outputSubDir is empty, otherwise to subdirectory
|
||||
const outputPath = outputSubDir ? join(OUTPUT_DIR, outputSubDir) : OUTPUT_DIR;
|
||||
await extractZip(zipFilePath, outputPath);
|
||||
} finally {
|
||||
if (await fsExtra.exists(zipFilePath)) {
|
||||
await fsExtra.rm(zipFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function buildDocsInner() {
|
||||
const i18n = await import("@triliumnext/server/src/services/i18n.js");
|
||||
await i18n.initializeTranslations();
|
||||
|
||||
const sqlInit = (await import("../../server/src/services/sql_init.js")).default;
|
||||
await sqlInit.createInitialDatabase(true);
|
||||
|
||||
// Wait for becca to be loaded before importing data
|
||||
const beccaLoader = await import("../../server/src/becca/becca_loader.js");
|
||||
await beccaLoader.beccaLoaded;
|
||||
|
||||
// Build User Guide
|
||||
console.log("Building User Guide...");
|
||||
await importAndExportDocs(join(__dirname, DOCS_ROOT, "User Guide"), "user-guide");
|
||||
|
||||
// Build Developer Guide
|
||||
console.log("Building Developer Guide...");
|
||||
await importAndExportDocs(join(__dirname, DOCS_ROOT, "Developer Guide"), "developer-guide");
|
||||
|
||||
// Copy favicon.
|
||||
await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "favicon.ico"));
|
||||
await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "user-guide", "favicon.ico"));
|
||||
await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "developer-guide", "favicon.ico"));
|
||||
|
||||
console.log("Documentation built successfully!");
|
||||
}
|
||||
|
||||
export async function importData(path: string) {
|
||||
const buffer = await createImportZip(path);
|
||||
const importService = (await import("@triliumnext/server/src/services/import/zip.js")).default;
|
||||
const TaskContext = (await import("@triliumnext/server/src/services/task_context.js")).default;
|
||||
const importService = (await import("../../server/src/services/import/zip.js")).default;
|
||||
const TaskContext = (await import("../../server/src/services/task_context.js")).default;
|
||||
const context = new TaskContext("no-progress-reporting", "importNotes", null);
|
||||
const becca = (await import("@triliumnext/server/src/becca/becca.js")).default;
|
||||
const becca = (await import("../../server/src/becca/becca.js")).default;
|
||||
|
||||
const rootNote = becca.getRoot();
|
||||
if (!rootNote) {
|
||||
|
||||
10
apps/build-docs/src/index.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; url=/user-guide">
|
||||
<title>Redirecting...</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>If you are not redirected automatically, <a href="/user-guide">click here</a>.</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,7 +1,7 @@
|
||||
import { join } from "path";
|
||||
import BuildContext from "./context";
|
||||
import buildSwagger from "./swagger";
|
||||
import { existsSync, mkdirSync, rmSync } from "fs";
|
||||
import { cpSync, existsSync, mkdirSync, rmSync } from "fs";
|
||||
import buildDocs from "./build-docs";
|
||||
import buildScriptApi from "./script-api";
|
||||
|
||||
@@ -21,6 +21,10 @@ async function main() {
|
||||
await buildDocs(context);
|
||||
buildSwagger(context);
|
||||
buildScriptApi(context);
|
||||
|
||||
// Copy index and 404 files.
|
||||
cpSync(join(__dirname, "index.html"), join(context.baseDir, "index.html"));
|
||||
cpSync(join(context.baseDir, "user-guide/404.html"), join(context.baseDir, "404.html"));
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"circular-deps": "dpdm -T src/**/*.ts --tree=false --warning=false --skip-dynamic-imports=circular"
|
||||
},
|
||||
"dependencies": {
|
||||
"@eslint/js": "9.39.0",
|
||||
"@eslint/js": "9.39.1",
|
||||
"@excalidraw/excalidraw": "0.18.0",
|
||||
"@fullcalendar/core": "6.1.19",
|
||||
"@fullcalendar/daygrid": "6.1.19",
|
||||
@@ -39,7 +39,7 @@
|
||||
"color": "5.0.2",
|
||||
"dayjs": "1.11.19",
|
||||
"dayjs-plugin-utc": "0.1.2",
|
||||
"debounce": "2.2.0",
|
||||
"debounce": "3.0.0",
|
||||
"draggabilly": "3.0.0",
|
||||
"force-graph": "1.51.0",
|
||||
"globals": "16.5.0",
|
||||
@@ -59,7 +59,7 @@
|
||||
"normalize.css": "8.0.1",
|
||||
"panzoom": "9.4.3",
|
||||
"preact": "10.27.2",
|
||||
"react-i18next": "16.2.3",
|
||||
"react-i18next": "16.2.4",
|
||||
"reveal.js": "5.2.1",
|
||||
"svg-pan-zoom": "3.6.2",
|
||||
"tabulator-tables": "6.3.1",
|
||||
|
||||
@@ -109,7 +109,8 @@
|
||||
"export_type_single": "Solo questa nota, senza le sottostanti",
|
||||
"format_opml": "OPML - formato per scambio informazioni outline. Formattazione, immagini e files non sono inclusi.",
|
||||
"opml_version_1": "OPML v.1.0 - solo testo semplice",
|
||||
"opml_version_2": "OPML v2.0 - supporta anche HTML"
|
||||
"opml_version_2": "OPML v2.0 - supporta anche HTML",
|
||||
"share-format": "HTML per la pubblicazione sul web - utilizza lo stesso tema utilizzato per le note condivise, ma può essere pubblicato come sito web statico."
|
||||
},
|
||||
"password_not_set": {
|
||||
"body1": "Le note protette sono crittografate utilizzando una password utente, ma la password non è stata ancora impostata.",
|
||||
|
||||
@@ -13,8 +13,8 @@ export default function EditedNotesTab({ note }: TabContext) {
|
||||
useEffect(() => {
|
||||
if (!note) return;
|
||||
server.get<EditedNotesResponse>(`edited-notes/${note.getLabelValue("dateNote")}`).then(async editedNotes => {
|
||||
editedNotes = editedNotes.filter((n) => n.noteId !== note.noteId);
|
||||
const noteIds = editedNotes.flatMap((n) => n.noteId);
|
||||
editedNotes = editedNotes.filter((n) => n.noteId !== note.noteId);
|
||||
const noteIds = editedNotes.flatMap((n) => n.noteId);
|
||||
await froca.getNotes(noteIds, true); // preload all at once
|
||||
setEditedNotes(editedNotes);
|
||||
});
|
||||
@@ -41,11 +41,11 @@ export default function EditedNotesTab({ note }: TabContext) {
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
}))}
|
||||
}), " ")}
|
||||
</div>
|
||||
) : (
|
||||
<div className="no-edited-notes-found">{t("edited_notes.no_edited_notes_found")}</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -72,8 +72,8 @@ function EditorFeatures() {
|
||||
return (
|
||||
<OptionsSection title={t("editorfeatures.title")}>
|
||||
<EditorFeature name="emoji-completion-enabled" optionName="textNoteEmojiCompletionEnabled" label={t("editorfeatures.emoji_completion_enabled")} description={t("editorfeatures.emoji_completion_description")} />
|
||||
<EditorFeature name="note-completion-enabled" optionName="textNoteCompletionEnabled" label={t("editorfeatures.note_completion_enabled")} description={t("editorfeatures.emoji_completion_description")} />
|
||||
<EditorFeature name="slash-commands-enabled" optionName="textNoteSlashCommandsEnabled" label={t("editorfeatures.slash_commands_enabled")} description={t("editorfeatures.emoji_completion_description")} />
|
||||
<EditorFeature name="note-completion-enabled" optionName="textNoteCompletionEnabled" label={t("editorfeatures.note_completion_enabled")} description={t("editorfeatures.note_completion_description")} />
|
||||
<EditorFeature name="slash-commands-enabled" optionName="textNoteSlashCommandsEnabled" label={t("editorfeatures.slash_commands_enabled")} description={t("editorfeatures.slash_commands_description")} />
|
||||
</OptionsSection>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
"cookie-parser": "1.4.7",
|
||||
"csrf-csrf": "3.2.2",
|
||||
"dayjs": "1.11.19",
|
||||
"debounce": "2.2.0",
|
||||
"debounce": "3.0.0",
|
||||
"debug": "4.4.3",
|
||||
"ejs": "3.1.10",
|
||||
"electron": "38.5.0",
|
||||
@@ -110,12 +110,12 @@
|
||||
"multer": "2.0.2",
|
||||
"normalize-strings": "1.1.1",
|
||||
"ollama": "0.6.2",
|
||||
"openai": "6.7.0",
|
||||
"openai": "6.8.0",
|
||||
"rand-token": "1.0.1",
|
||||
"safe-compare": "1.1.4",
|
||||
"sanitize-filename": "1.6.3",
|
||||
"sanitize-html": "2.17.0",
|
||||
"sax": "1.4.1",
|
||||
"sax": "1.4.2",
|
||||
"serve-favicon": "2.5.1",
|
||||
"stream-throttle": "0.1.3",
|
||||
"strip-bom": "5.0.0",
|
||||
|
||||
2
apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json
generated
vendored
@@ -1,5 +1,5 @@
|
||||
<aside class="admonition tip">
|
||||
<p>For a quick start, consult the <a class="reference-link" href="#root/pgxEVkzLl1OP/_help_9qPsTWBorUhQ">API Reference</a>.</p>
|
||||
<p>For a quick start, consult the <a class="reference-link" href="#root/_help_9qPsTWBorUhQ">API Reference</a>.</p>
|
||||
</aside>
|
||||
<p>ETAPI is Trilium's public/external REST API. It is available since Trilium
|
||||
v0.50.</p>
|
||||
@@ -7,7 +7,7 @@
|
||||
<p>As an alternative to calling the API directly, there are client libraries
|
||||
to simplify this</p>
|
||||
<ul>
|
||||
<li data-list-item-id="e3342ddfa108f6c8c6c47d7d3da8b02fa"><a href="https://github.com/Nriver/trilium-py">trilium-py</a>, you can
|
||||
<li><a href="https://github.com/Nriver/trilium-py">trilium-py</a>, you can
|
||||
use Python to communicate with Trilium.</li>
|
||||
</ul>
|
||||
<h2>Obtaining a token</h2>
|
||||
@@ -25,10 +25,10 @@ Authorization: ETAPITOKEN</code></pre>
|
||||
<p>Since v0.56 you can also use basic auth format:</p><pre><code class="language-text-x-trilium-auto">GET https://myserver.com/etapi/app-info
|
||||
Authorization: Basic BATOKEN</code></pre>
|
||||
<ul>
|
||||
<li data-list-item-id="ec59ac570a3d2a846da38378a5f2428ed">Where <code>BATOKEN = BASE64(username + ':' + password)</code> - this is
|
||||
<li>Where <code>BATOKEN = BASE64(username + ':' + password)</code> - this is
|
||||
a standard Basic Auth serialization</li>
|
||||
<li data-list-item-id="e18e2e73ebecc949dd4a51cd9f8bb0b91">Where <code>username</code> is "etapi"</li>
|
||||
<li data-list-item-id="ee892223f95cef4a53caec5477ab31edb">And <code>password</code> is the generated ETAPI token described above.</li>
|
||||
<li>Where <code>username</code> is "etapi"</li>
|
||||
<li>And <code>password</code> is the generated ETAPI token described above.</li>
|
||||
</ul>
|
||||
<p>Basic Auth is meant to be used with tools which support only basic auth.</p>
|
||||
<h2>Interaction using Bash scripts</h2>
|
||||
@@ -44,10 +44,10 @@ NOTE_ID="i6ra4ZshJhgN"
|
||||
curl "$SERVER/etapi/notes/$NOTE_ID/content" -H "Authorization: $TOKEN" </code></pre>
|
||||
<p>Make sure to replace the values of:</p>
|
||||
<ul>
|
||||
<li data-list-item-id="e68020f83acc951e180bb405d149a64a5"><code>TOKEN</code> with your ETAPI token.</li>
|
||||
<li data-list-item-id="ef4c31df5f6d18811e7de0ee8ff95f3a7"><code>SERVER</code> with the correct protocol, host name and port to your
|
||||
<li><code>TOKEN</code> with your ETAPI token.</li>
|
||||
<li><code>SERVER</code> with the correct protocol, host name and port to your
|
||||
Trilium instance.</li>
|
||||
<li data-list-item-id="e25086bb4c54d32259f987f9366e22204"><code>NOTE_ID</code> with an existing note ID to download.</li>
|
||||
<li><code>NOTE_ID</code> with an existing note ID to download.</li>
|
||||
</ul>
|
||||
<p>As another example, to obtain a .zip export of a note and place it in
|
||||
a directory called <code>out</code>, simply replace the last statement in
|
||||
|
||||
35
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Nightly release.html
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<p>Nightly releases are versions built every day, containing the latest improvements
|
||||
and bugfixes, directly from the main development branch. These versions
|
||||
are generally useful in preparation for a release, to ensure that there
|
||||
are no significant bugs that need to be addressed first, or they can be
|
||||
used to confirm whether a particular bug is fixed or feature is well implemented.</p>
|
||||
<h2>Regarding the stability</h2>
|
||||
<p>Despite being on a development branch, generally the main branch is pretty
|
||||
stable since PRs are tested before they are merged. If you notice any issues,
|
||||
feel free to report them either via a ticket or via the Matrix.</p>
|
||||
<h2>Downloading the nightly release manually</h2>
|
||||
<p>Go to <a href="https://github.com/TriliumNext/Trilium/releases/tag/nightly">github.com/TriliumNext/Trilium/releases/tag/nightly</a> and
|
||||
look for the artifacts starting with <code>TriliumNotes-main</code>. Choose
|
||||
the appropriate one for your platform (e.g. <code>windows-x64.zip</code>).</p>
|
||||
<p>Depending on your use case, you can either test the portable version or
|
||||
even use the installer.</p>
|
||||
<aside class="admonition note">
|
||||
<p>If you choose the installable version (e.g. the .exe on Windows), it will
|
||||
replace your stable installation.</p>
|
||||
</aside>
|
||||
<aside class="admonition important">
|
||||
<p>By default, the nightly uses the same database as the production version.
|
||||
Generally you could easily downgrade if needed. However, if there are changes
|
||||
to the database or sync version, it will not be possible to downgrade without
|
||||
having to restore from a backup.</p>
|
||||
</aside>
|
||||
<h2>Automatically download and install the latest nightly</h2>
|
||||
<p>This is pretty useful if you are a beta tester that wants to periodically
|
||||
update their version:</p>
|
||||
<p>On Ubuntu:</p><pre><code class="language-text-x-trilium-auto">#!/usr/bin/env bash
|
||||
|
||||
name=TriliumNotes-linux-x64-nightly.deb
|
||||
rm -f $name*
|
||||
wget https://github.com/TriliumNext/Trilium/releases/download/nightly/$name
|
||||
sudo apt-get install ./$name
|
||||
rm $name</code></pre>
|
||||
12
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Safe mode.html
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<p>Safe mode is triggered by setting the <code>TRILIUM_SAFE_MODE</code> environment
|
||||
variable to a truthy value, usually <code>1</code>.</p>
|
||||
<p>In each artifact there is a <code>trilium-safe-mode.sh</code> (or <code>.bat</code>)
|
||||
script to enable it.</p>
|
||||
<p>What it does:</p>
|
||||
<ul>
|
||||
<li>Disables <code>customWidget</code> launcher types in <code>app/widgets/containers/launcher.js</code>.</li>
|
||||
<li>Disables the running of <code>mobileStartup</code> or <code>frontendStartup</code> scripts.</li>
|
||||
<li>Displays the root note instead of the previously saved session.</li>
|
||||
<li>Disables the running of <code>backendStartup</code>, <code>hourly</code>, <code>daily</code> scripts
|
||||
and checks for the hidden subtree.</li>
|
||||
</ul>
|
||||
64
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Desktop Installation/Nix flake.html
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
<p>Since TriliumNext 0.94.1, the desktop and server applications can be built
|
||||
using <a href="https://nixos.org/">Nix</a>.</p>
|
||||
<h2>System requirements</h2>
|
||||
<p>Installation of Nix on Mac or Linux (<a href="https://nixos.org/download/">download page</a>).
|
||||
About 3-4 gigabytes of additional storage space, for build artifacts.</p>
|
||||
<h2>Run directly</h2>
|
||||
<p>Using <a href="https://nix.dev/manual/nix/stable/command-ref/new-cli/nix3-run.html">nix run</a>,
|
||||
the desktop app can be started as: <code>nix run github:TriliumNext/Trilium/v0.95.0</code>
|
||||
</p>
|
||||
<p>Running the server requires explicitly specifying the desired package: <code>nix run github:TriliumNext/Trilium/v0.95.0#server</code>
|
||||
</p>
|
||||
<p>Instead of a version (<code>v0.95.0</code> above), you can also specify
|
||||
a commit hash (or a branch name). This makes it easy to test development
|
||||
builds.</p>
|
||||
<h2>Install on NixOS</h2>
|
||||
<p>Add to your <code>flake.nix</code>:</p><pre><code class="language-text-x-trilium-auto">{
|
||||
inputs = {
|
||||
nixpkgs.url = # ...;
|
||||
trilium-notes = {
|
||||
url = "github:TriliumNext/Trilium/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
|
||||
;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
</code></pre>
|
||||
<p>Add to your <code>configuration.nix</code>:</p><pre><code class="language-text-x-trilium-auto">{
|
||||
# ...
|
||||
trilium-notes,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
# ...
|
||||
|
||||
services.trilium-server.package = trilium-notes.packages.x86_64-linux.server;
|
||||
|
||||
environment.systemPackages = [
|
||||
trilium-notes.packages.x86_64-linux.desktop
|
||||
];
|
||||
}</code></pre>
|
||||
<p>The flake aims to be compatible with the latest NixOS stable and unstable.</p>
|
||||
1
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/Nix flake.clone.html
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<p>This is a clone of a note. Go to its <a href="../Desktop%20Installation/Nix%20flake.html">primary location</a>.</p>
|
||||
@@ -1,7 +1,6 @@
|
||||
<aside class="admonition tip">
|
||||
<p>For a quick understanding of the Mermaid syntax, see <a class="reference-link"
|
||||
href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/s1aBHPd79XYj/_help_WWgeUaBb7UfC">Syntax reference</a> (official
|
||||
documentation).</p>
|
||||
href="#root/_help_WWgeUaBb7UfC">Syntax reference</a> (official documentation).</p>
|
||||
</aside>
|
||||
<figure class="image image-style-align-center">
|
||||
<img style="aspect-ratio:886/663;" src="2_Mermaid Diagrams_image.png"
|
||||
@@ -15,9 +14,9 @@
|
||||
<p>Depending on the chart being edited and user preference, there are two
|
||||
layouts supported by the Mermaid note type:</p>
|
||||
<ul>
|
||||
<li data-list-item-id="e5998f20495a1079ee7b6e284dc4d14e4">Horizontal, where the source code (editable part) is on the left side
|
||||
<li>Horizontal, where the source code (editable part) is on the left side
|
||||
of the screen and the preview is to the right.</li>
|
||||
<li data-list-item-id="ebebfbd8cf2125c70056e3e9075d8681e">Vertical, where the source code is at the bottom of the screen and the
|
||||
<li>Vertical, where the source code is at the bottom of the screen and the
|
||||
preview is at the top.</li>
|
||||
</ul>
|
||||
<p>It's possible to switch between the two layouts at any time by pressing
|
||||
@@ -25,48 +24,44 @@
|
||||
<img src="Mermaid Diagrams_image.png">icon in the <a class="reference-link" href="#root/_help_XpOYSgsLkTJy">Floating buttons</a> area.</p>
|
||||
<h2>Interaction</h2>
|
||||
<ul>
|
||||
<li data-list-item-id="e67d8f093c4793e19e2ade2d58728ae81">The source code of the diagram (in Mermaid format) is displayed on the
|
||||
<li>The source code of the diagram (in Mermaid format) is displayed on the
|
||||
left or bottom side of the note (depending on the layout).
|
||||
<ul>
|
||||
<li data-list-item-id="e4d777ef787093815b961d734021ccc55">Changing the diagram code will refresh automatically the diagram.</li>
|
||||
<li>Changing the diagram code will refresh automatically the diagram.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li data-list-item-id="e6faf589831e3252f8cda42f62248377a">The preview of the diagram is displayed at the right or top side of the
|
||||
<li>The preview of the diagram is displayed at the right or top side of the
|
||||
note (depending on the layout):
|
||||
<ul>
|
||||
<li data-list-item-id="e1dc5994137e511eb29657629d9e729a3">There are dedicated buttons at the bottom-right of the preview to control
|
||||
<li>There are dedicated buttons at the bottom-right of the preview to control
|
||||
the zoom in, zoom out or re-center the diagram:
|
||||
<img src="1_Mermaid Diagrams_image.png">
|
||||
</li>
|
||||
<li data-list-item-id="e51812ca016db170ceb6814007a60eb10">The preview can be moved around by holding the left mouse button and dragging.</li>
|
||||
<li
|
||||
data-list-item-id="e617128e494ed43ca5d0f5c749a8c9208">Zooming can also be done by using the scroll wheel.</li>
|
||||
<li data-list-item-id="e7b87c55d329003996861f24d8d162b85">The zoom and position on the preview will remain fixed as the diagram
|
||||
changes, to be able to work more easily with large diagrams.</li>
|
||||
</ul>
|
||||
<li>The preview can be moved around by holding the left mouse button and dragging.</li>
|
||||
<li>Zooming can also be done by using the scroll wheel.</li>
|
||||
<li>The zoom and position on the preview will remain fixed as the diagram
|
||||
changes, to be able to work more easily with large diagrams.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li data-list-item-id="e11cf4ecd9d2408ce5a46b949dea40b06">The size of the source/preview panes can be adjusted by hovering over
|
||||
<li>The size of the source/preview panes can be adjusted by hovering over
|
||||
the border between them and dragging it with the mouse.</li>
|
||||
<li data-list-item-id="ebc96b0fe8366ef4e00561de1c866d53b">In the <a class="reference-link" href="#root/_help_XpOYSgsLkTJy">Floating buttons</a> area:
|
||||
<li>In the <a class="reference-link" href="#root/_help_XpOYSgsLkTJy">Floating buttons</a> area:
|
||||
<ul>
|
||||
<li data-list-item-id="e12f31dc31db3c8be1fe87822ca2f451e">The source/preview can be laid out left-right or bottom-top via the <em>Move editing pane to the left / bottom</em> option.</li>
|
||||
<li
|
||||
data-list-item-id="ed29e7616e6c77105103a68b1e8a6f7b3">Press <em>Lock editing</em> to automatically mark the note as read-only.
|
||||
<li>The source/preview can be laid out left-right or bottom-top via the <em>Move editing pane to the left / bottom</em> option.</li>
|
||||
<li>Press <em>Lock editing</em> to automatically mark the note as read-only.
|
||||
In this mode, the code pane is hidden and the diagram is displayed full-size.
|
||||
Similarly, press <em>Unlock editing</em> to mark a read-only note as editable.</li>
|
||||
<li
|
||||
data-list-item-id="e2bc7d5d8d1f8f02e61a6d86a3faae3b4">Press the <em>Copy image reference to the clipboard</em> to be able to insert
|
||||
the image representation of the diagram into a text note. See <a class="reference-link"
|
||||
href="#root/_help_0Ofbk1aSuVRu">Image references</a> for more information.</li>
|
||||
<li
|
||||
data-list-item-id="ecaac01dc52bce394f720be2826e82026">Press the <em>Export diagram as SVG</em> to download a scalable/vector rendering
|
||||
of the diagram. Can be used to present the diagram without degrading when
|
||||
zooming.</li>
|
||||
<li data-list-item-id="e9c815090884a394d60e06628b9e38add">Press the <em>Export diagram as PNG</em> to download a normal image (at
|
||||
<li>Press the <em>Copy image reference to the clipboard</em> to be able to insert
|
||||
the image representation of the diagram into a text note. See <a class="reference-link"
|
||||
href="#root/_help_0Ofbk1aSuVRu">Image references</a> for more information.</li>
|
||||
<li>Press the <em>Export diagram as SVG</em> to download a scalable/vector rendering
|
||||
of the diagram. Can be used to present the diagram without degrading when
|
||||
zooming.</li>
|
||||
<li>Press the <em>Export diagram as PNG</em> to download a normal image (at
|
||||
1x scale, raster) of the diagram. Can be used to send the diagram in more
|
||||
traditional channels such as e-mail.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<h2>Errors in the diagram</h2>
|
||||
<p>If there is an error in the source code, the error will be displayed in
|
||||
|
||||
7
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Scripting/Backend scripts/Server-side imports.html
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<p>Older versions of Trilium Notes allowed the use of Common.js module imports
|
||||
inside backend scripts, such as:</p><pre><code class="language-text-x-trilium-auto">const isBetween = require('dayjs/plugin/isBetween')
|
||||
api.dayjs.extend(isBetween)</code></pre>
|
||||
<p>For newer versions, Node.js imports are <strong>not officially supported anymore</strong>,
|
||||
since we've added a bundler which makes it more difficult to reuse dependencies.</p>
|
||||
<p>Theoretically it's still possible to use imports by manually setting up
|
||||
a <code>node_modules</code> in the server directory via <code>npm</code> or <code>pnpm</code>.</p>
|
||||
9
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/CSS.html
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<p>In <code>doRender()</code>:</p><pre><code class="language-text-x-trilium-auto">this.cssBlock(`#my-widget {
|
||||
position: absolute;
|
||||
bottom: 40px;
|
||||
left: 60px;
|
||||
z-index: 1;
|
||||
}`)</code></pre>
|
||||
<hr>
|
||||
<p>Reference: <a href="https://trilium.rocks/X7pxYpiu0lgU">https://trilium.rocks/X7pxYpiu0lgU</a>
|
||||
</p>
|
||||
30
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Right pane widget.html
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<ul>
|
||||
<li><code>doRender</code> must not be overridden, instead <code>doRenderBody()</code> has
|
||||
to be overridden.</li>
|
||||
<li><code>parentWidget()</code> must be set to <code>“rightPane”</code>.</li>
|
||||
<li><code>widgetTitle()</code> getter can optionally be overriden, otherwise
|
||||
the widget will be displayed as “Untitled widget”.</li>
|
||||
</ul><pre><code class="language-text-x-trilium-auto">const template = `<div>Hi</div>`;
|
||||
|
||||
class ToDoListWidget extends api.RightPanelWidget {
|
||||
|
||||
get widgetTitle() {
|
||||
return "Title goes here";
|
||||
}
|
||||
|
||||
get parentWidget() { return "right-pane" }
|
||||
|
||||
doRenderBody() {
|
||||
this.$body.empty().append($(template));
|
||||
}
|
||||
|
||||
async refreshWithNote(note) {
|
||||
this.toggleInt(false);
|
||||
this.triggerCommand("reEvaluateRightPaneVisibility");
|
||||
this.toggleInt(true);
|
||||
this.triggerCommand("reEvaluateRightPaneVisibility");
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new ToDoListWidget();</code></pre>
|
||||
<p>The implementation is in <code>src/public/app/widgets/right_panel_widget.js</code>.</p>
|
||||
@@ -16,11 +16,11 @@
|
||||
module.exports = new MyWidget();</code></pre>
|
||||
<p>To implement this widget:</p>
|
||||
<ol>
|
||||
<li>Create a new <code>JS Frontend</code> note in Trilium and paste in the code
|
||||
<li data-list-item-id="ee416db068caeb5aebc3edf8d313cdbbf">Create a new <code>JS Frontend</code> note in Trilium and paste in the code
|
||||
above.</li>
|
||||
<li>Assign the <code>#widget</code> <a href="#root/_help_zEY4DaJG4YT5">attribute</a> to
|
||||
<li data-list-item-id="ec82d101a82bd1bdbbc180294534aecaa">Assign the <code>#widget</code> <a href="#root/_help_zEY4DaJG4YT5">attribute</a> to
|
||||
the <a href="#root/_help_BFs8mudNFgCS">note</a>.</li>
|
||||
<li>Restart Trilium or reload the window.</li>
|
||||
<li data-list-item-id="ee1c3b9d316a04a986cc0be3b57d4c569">Restart Trilium or reload the window.</li>
|
||||
</ol>
|
||||
<p>To verify that the widget is working, open the developer tools (<code>Cmd</code> + <code>Shift</code> + <code>I</code>)
|
||||
and run <code>document.querySelector("#my-widget")</code>. If the element
|
||||
@@ -87,5 +87,18 @@ module.exports = new MyWidget();</code></pre>
|
||||
}
|
||||
|
||||
module.exports = new MyWidget();</code></pre>
|
||||
<p>Reload the application one last time. When you click the button, a "Hello
|
||||
World!" message should appear, confirming that your widget is fully functional.</p>
|
||||
<p><code>parentWidget()</code> can be given the following values:</p>
|
||||
<ul>
|
||||
<li data-list-item-id="ebf9bc7b43e420c012d4c72b3b95a8cf0"><code>left-pane</code> - This renders the widget on the left side of the
|
||||
screen where the note tree lives.</li>
|
||||
<li data-list-item-id="ec6ca6cd1ed1b9157edc99a61e4b9f336"><code>center-pane</code> - This renders the widget in the center of the
|
||||
layout in the same location that notes and splits appear.</li>
|
||||
<li data-list-item-id="e8575696a825b1dce0a62a3ffb6b59ae8"><code>note-detail-pane</code> - This renders the widget <em>with</em> the
|
||||
note in the center pane. This means it can appear multiple times with splits.</li>
|
||||
<li
|
||||
data-list-item-id="e064dfaa93f31a16d42c10c4c45d903be"><code>right-pane</code> - This renders the widget to the right of any opened
|
||||
notes.</li>
|
||||
</ul>
|
||||
<p><a href="#root/pOsGYCXsbNQG/BgmBlOIl72jZ/_help_s8alTXmpFR61">Reload</a> the application
|
||||
one last time. When you click the button, a "Hello World!" message should
|
||||
appear, confirming that your widget is fully functional.</p>
|
||||
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 222 B After Width: | Height: | Size: 222 B |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
@@ -420,7 +420,7 @@
|
||||
"end-time": "Ora di fine",
|
||||
"geolocation": "Geolocalizzazione",
|
||||
"built-in-templates": "Modelli integrati",
|
||||
"board": "Tavola",
|
||||
"board": "Kanban Board",
|
||||
"status": "Stato",
|
||||
"board_note_first": "Prima nota",
|
||||
"board_note_second": "Seconda nota",
|
||||
|
||||
@@ -417,7 +417,7 @@
|
||||
"end-time": "結束時間",
|
||||
"geolocation": "地理位置",
|
||||
"built-in-templates": "內建模版",
|
||||
"board": "儀表板",
|
||||
"board": "看板",
|
||||
"status": "狀態",
|
||||
"board_note_first": "第一個筆記",
|
||||
"board_note_second": "第二個筆記",
|
||||
|
||||
@@ -253,6 +253,10 @@ async function exportToZip(taskContext: TaskContext<"export">, branch: BBranch,
|
||||
|
||||
for (let i = 0; i < targetPath.length - 1; i++) {
|
||||
const meta = noteIdToMeta[targetPath[i]];
|
||||
if (meta === rootMeta && format === "share") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (meta.dirFileName) {
|
||||
url += `${encodeURIComponent(meta.dirFileName)}/`;
|
||||
}
|
||||
@@ -371,10 +375,12 @@ async function exportToZip(taskContext: TaskContext<"export">, branch: BBranch,
|
||||
}
|
||||
|
||||
if (noteMeta.children?.length || 0 > 0) {
|
||||
const directoryPath = filePathPrefix + noteMeta.dirFileName;
|
||||
const directoryPath = filePathPrefix !== "" || format !== "share" ? filePathPrefix + noteMeta.dirFileName : "";
|
||||
|
||||
// create directory
|
||||
archive.append("", { name: `${directoryPath}/`, date: dateUtils.parseDateTime(note.utcDateModified) });
|
||||
if (directoryPath) {
|
||||
archive.append("", { name: `${directoryPath}/`, date: dateUtils.parseDateTime(note.utcDateModified) });
|
||||
}
|
||||
|
||||
for (const childMeta of noteMeta.children || []) {
|
||||
saveNote(childMeta, `${directoryPath}/`);
|
||||
|
||||
@@ -27,6 +27,7 @@ export default class ShareThemeExportProvider extends ZipExportProvider {
|
||||
private assetsMeta: NoteMeta[] = [];
|
||||
private indexMeta: NoteMeta | null = null;
|
||||
private searchIndex: Map<string, SearchIndexEntry> = new Map();
|
||||
private rootMeta: NoteMeta | null = null;
|
||||
|
||||
prepareMeta(metaFile: NoteMetaFile): void {
|
||||
const assets = [
|
||||
@@ -50,6 +51,7 @@ export default class ShareThemeExportProvider extends ZipExportProvider {
|
||||
noImport: true,
|
||||
dataFileName: "index.html"
|
||||
};
|
||||
this.rootMeta = metaFile.files[0];
|
||||
|
||||
metaFile.files.push(this.indexMeta);
|
||||
}
|
||||
@@ -58,7 +60,7 @@ export default class ShareThemeExportProvider extends ZipExportProvider {
|
||||
if (!noteMeta?.notePath?.length) {
|
||||
throw new Error("Missing note path.");
|
||||
}
|
||||
const basePath = "../".repeat(noteMeta.notePath.length - 1);
|
||||
const basePath = "../".repeat(Math.max(0, noteMeta.notePath.length - 2));
|
||||
let searchContent = "";
|
||||
|
||||
if (note) {
|
||||
@@ -71,6 +73,9 @@ export default class ShareThemeExportProvider extends ZipExportProvider {
|
||||
if (typeof content === "string") {
|
||||
content = content.replace(/href="[^"]*\.\/([a-zA-Z0-9_\/]{12})[^"]*"/g, (match, id) => {
|
||||
if (match.includes("/assets/")) return match;
|
||||
if (id === this.rootMeta?.noteId) {
|
||||
return `href="${basePath}"`;
|
||||
}
|
||||
return `href="#root/${id}"`;
|
||||
});
|
||||
content = this.rewriteFn(content, noteMeta);
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
"preact": "10.27.2",
|
||||
"preact-iso": "2.11.0",
|
||||
"preact-render-to-string": "6.6.3",
|
||||
"react-i18next": "16.2.3"
|
||||
"react-i18next": "16.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@preact/preset-vite": "2.10.2",
|
||||
"eslint": "9.39.0",
|
||||
"eslint": "9.39.1",
|
||||
"eslint-config-preact": "2.0.0",
|
||||
"typescript": "5.9.3",
|
||||
"user-agent-data-types": "0.4.2",
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
"calendar_description": "Organizza i tuoi eventi personali o professionali utilizzando un calendario, con supporto per eventi di un giorno intero o di più giorni. Visualizza i tuoi eventi a colpo d'occhio con le viste settimanale, mensile e annuale. Interazione semplice per aggiungere o trascinare eventi.",
|
||||
"table_title": "Tabella",
|
||||
"table_description": "Visualizza e modifica le informazioni relative alle note in una struttura tabellare, con vari tipi di colonne quali testo, numeri, caselle di controllo, data e ora, collegamenti e colori, oltre al supporto per le relazioni. Facoltativamente, è possibile visualizzare le note all'interno di una gerarchia ad albero all'interno della tabella.",
|
||||
"board_title": "Board",
|
||||
"board_title": "Kanban Board",
|
||||
"board_description": "Organizza le tue attività o lo stato dei tuoi progetti in una lavagna Kanban con un modo semplice per creare nuovi elementi e colonne e modificare facilmente il loro stato trascinandoli sulla lavagna.",
|
||||
"geomap_title": "Geomappa",
|
||||
"geomap_description": "Pianifica le tue vacanze o segna i tuoi punti di interesse direttamente su una mappa geografica utilizzando indicatori personalizzabili. Visualizza le tracce GPX registrate per seguire gli itinerari.",
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
"calendar_description": "使用行事曆規劃個人或專業活動,支援全天及多日活動。透過週、月、年檢視模式,一覽所有活動。通過簡單互動即可新增或拖曳活動。",
|
||||
"table_title": "表格",
|
||||
"table_description": "以表格結構顯示並編輯筆記資訊,支援多種欄位類型,包括文字、數字、核取方塊、日期與時間、連結及顏色,並支援關聯功能。可選擇性地在表格內以樹狀層級結構顯示筆記內容。",
|
||||
"board_title": "儀表板",
|
||||
"board_title": "看板",
|
||||
"board_description": "將您的任務或專案狀態整理成看板,輕鬆建立新項目與欄位,並透過在看板上拖曳即可簡單變更狀態。",
|
||||
"geomap_title": "地理地圖",
|
||||
"geomap_description": "使用可自訂的標記,直接在地圖上規劃您的假期行程或標記感興趣的地點。顯示已記錄的GPX軌跡,以便追蹤行程路線。",
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
"jsxImportSource": "preact",
|
||||
"skipLibCheck": true,
|
||||
"types": [
|
||||
"vite/client"
|
||||
"vite/client",
|
||||
"vitest/config"
|
||||
],
|
||||
"paths": {
|
||||
"react": ["../../node_modules/preact/compat/"],
|
||||
|
||||
4083
docs/Developer Guide/!!!meta.json
vendored
4
docs/Developer Guide/Developer Guide.md
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# Developer Guide
|
||||
This documentation is intended for developers planning to implement new features or maintain the Trilium Notes application, as it describes the architecture of the application.
|
||||
|
||||
For the user-facing documentation, including how to write scripts and the various APIs, consult the [user guide](https://docs.triliumnotes.org/user-guide/) instead.
|
||||
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
@@ -2,7 +2,7 @@
|
||||
The main workflow of the CI:
|
||||
|
||||
* Builds the Docker image and publishes in the GitHub Docker registry.
|
||||
* Builds using a portion of the [delivery script](../../Build%20deliveries%20locally.md) artifacts for the following platforms:
|
||||
* Builds using a portion of the [delivery script](../../Building/Build%20deliveries%20locally.md) artifacts for the following platforms:
|
||||
* Windows `x86_64` as .zip file
|
||||
* Windows `x86_64` installer (using Squirrel)
|
||||
* macOS `x86_64` and `aarch64`.
|
||||
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
2
docs/Developer Guide/Developer Guide/Architecture/Database structure/attributes.md
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# attributes
|
||||
<table><thead><tr><th>Column Name</th><th>Data Type</th><th>Nullity</th><th>Default value</th><th>Description</th></tr></thead><tbody><tr><th><code>attributeId</code></th><td>Text</td><td>Non-null</td><td> </td><td>Unique Id of the attribute (e.g. <code>qhC1vzU4nwSE</code>), can also have a special unique ID for <a class="reference-link" href="#root/r11Bh3uxFGRj">Special notes</a> (e.g. <code>_lbToday_liconClass</code>).</td></tr><tr><th><code>noteId</code></th><td>Text</td><td>Non-null</td><td> </td><td>The ID of the <a href="notes.md">note</a> this atttribute belongs to</td></tr><tr><th><code>type</code></th><td>Text</td><td>Non-null</td><td> </td><td>The type of attribute (<code>label</code> or <code>relation</code>).</td></tr><tr><th><code>name</code></th><td>Text</td><td>Non-null</td><td> </td><td>The name/key of the attribute.</td></tr><tr><th><code>value</code></th><td>Text</td><td>Non-null</td><td><code>""</code></td><td><ul><li>For <code>label</code> attributes, a free-form value of the attribute.</li><li>For <code>relation</code> attributes, the ID of the <a href="notes.md">note</a> the relation is pointing to.</li></ul></td></tr><tr><th><code>position</code></th><td>Integer</td><td>Non-null</td><td>0</td><td>The position of the attribute compared to the other attributes. Some predefined attributes such as <code>originalFileName</code> have a value of 1000.</td></tr><tr><th><code>utcDateModified</code></th><td>Text</td><td>Non-null</td><td> </td><td>Modification date in UTC format (e.g. <code>2023-11-08 16:43:44.204Z</code>)</td></tr><tr><th><code>isDeleted</code></th><td>Integer</td><td>Non-null</td><td> </td><td><code>1</code> if the entity is <a href="../Deleted%20notes.md">deleted</a>, <code>0</code> otherwise.</td></tr><tr><th><code>deleteId</code></th><td>Text</td><td>Nullable</td><td><code>null</code></td><td> </td></tr><tr><th><code>isInheritable</code></th><td>Integer</td><td>Nullable</td><td>0</td><td> </td></tr></tbody></table>
|
||||
2
docs/Developer Guide/Developer Guide/Architecture/Database structure/blobs.md
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# blobs
|
||||
<table><thead><tr><th>Column Name</th><th>Data Type</th><th>Nullity</th><th>Default value</th><th>Description</th></tr></thead><tbody><tr><th><code>blobId</code></th><td>Text</td><td>Non-null</td><td> </td><td><p>The unique ID of the blob (e.g. <code>XXbfAJXqWrYnSXcelLFA</code>).</p><aside class="admonition important"><p>The ID is actually a hash of the content, see <code>AbstractBeccaEntity#saveBlob</code>! It is a logic error to modify an existing blob.</p></aside></td></tr><tr><th><code>content</code></th><td>Text</td><td>Nullable</td><td><code>null</code></td><td><p>The content of the blob, can be either:</p><ul><li data-list-item-id="e1f1b8623c64f95f19751bbe494063d0f">text (for plain text notes or HTML notes).</li><li data-list-item-id="e5bbdee6fe5e5b12361fc74e339c9f1db">binary (for images and other types of attachments)</li></ul></td></tr><tr><th><code>dateModified</code></th><td>Text</td><td>Non-null</td><td> </td><td>Creation date with timezone offset (e.g. <code>2023-11-08 18:43:44.204+0200</code>)</td></tr><tr><th><code>utcDateModified</code></th><td>Text</td><td>Non-null</td><td> </td><td><p>Creation date in UTC format (e.g. <code>2023-11-08 16:43:44.204Z</code>).</p><p>Blobs cannot be modified, so this timestamp specifies when the blob was created.</p></td></tr></tbody></table>
|
||||
22
docs/Developer Guide/Developer Guide/Architecture/Demo document.md
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# Demo document
|
||||
The demo document is an exported .zip that resides in `apps/server/src/assets/db/demo.zip`.
|
||||
|
||||
During on-boarding, if the user selects that they are a new user then the `demo.zip` is imported into the root note.
|
||||
|
||||
## Modifying the document
|
||||
|
||||
1. In the Git root, run `pnpm edit-docs:edit-demo`.
|
||||
2. Wait for the desktop application to show up with the docs.
|
||||
3. Simply make the needed modifications.
|
||||
4. Wait for a few seconds for the change to be processed in the background.
|
||||
5. Commit the change in Git.
|
||||
|
||||
## Testing the changes
|
||||
|
||||
1. Run:
|
||||
|
||||
```
|
||||
rm -r data
|
||||
pnpm server:start
|
||||
```
|
||||
2. And then do the on-boarding again.
|
||||
@@ -21,7 +21,7 @@ These are stored in `images`:
|
||||
|
||||
## App icons
|
||||
|
||||
<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>
|
||||
<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="../Building/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="../Building/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="../Building/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>
|
||||
|
||||
## Additional locations where the branding is used
|
||||
|
||||
@@ -41,7 +41,7 @@ Go to `src/becca/entities/rows.ts` and add the new note type to `ALLOWED_NOTE_TY
|
||||
|
||||
## Final steps
|
||||
|
||||
* Update the <a class="reference-link" href="../Demo%20document.md">Demo document</a> to showcase the new note type.
|
||||
* Update the <a class="reference-link" href="../../Demo%20document.md">Demo document</a> to showcase the new note type.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
43
docs/Developer Guide/Developer Guide/Architecture/Options.md
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
# Options
|
||||
## Read an option
|
||||
|
||||
Add the import to the service (make sure the relative path is correct):
|
||||
|
||||
```javascript
|
||||
import options from "../../services/options.js";
|
||||
```
|
||||
|
||||
Them simply read the option:
|
||||
|
||||
```javascript
|
||||
this.firstDayOfWeek = options.getInt("firstDayOfWeek");
|
||||
```
|
||||
|
||||
## Adding new options
|
||||
|
||||
### Checkbox option
|
||||
|
||||
Refer to this example in `backup.tsx`:
|
||||
|
||||
```javascript
|
||||
export function AutomaticBackup() {
|
||||
const [ dailyBackupEnabled, setDailyBackupEnabled ] = useTriliumOptionBool("dailyBackupEnabled");
|
||||
|
||||
return (
|
||||
<OptionsSection title={t("backup.automatic_backup")}>
|
||||
<FormMultiGroup label={t("backup.automatic_backup_description")}>
|
||||
<FormCheckbox
|
||||
name="daily-backup-enabled"
|
||||
label={t("backup.enable_daily_backup")}
|
||||
currentValue={dailyBackupEnabled} onChange={setDailyBackupEnabled}
|
||||
/>
|
||||
</FormMultiGroup>
|
||||
|
||||
<FormText>{t("backup.backup_recommendation")}</FormText>
|
||||
</OptionsSection>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> To trigger a UI refresh (e.g. `utils#reloadFrontendApp`), simply pass a `true` as the second argument to `useTriliumOption` methods.
|
||||
18
docs/Developer Guide/Developer Guide/Architecture/Printing and exporting to PDF.md
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
# Printing and exporting to PDF
|
||||
Note printing is handled by `note_detail.js`, in the `printActiveNoteEvent` method. Exporting to PDF works similarly.
|
||||
|
||||
## How it works
|
||||
|
||||
Both printing and exporting as PDF use the same mechanism: a note is rendered individually in a separate webpage that is then sent to the browser or the Electron application either for printing or exporting as PDF.
|
||||
|
||||
The webpage that renders a single note can actually be accessed in a web browser. For example `http://localhost:8080/#root/WWRGzqHUfRln/RRZsE9Al8AIZ?ntxId=0o4fzk` becomes `http://localhost:8080/?print#root/WWRGzqHUfRln/RRZsE9Al8AIZ`.
|
||||
|
||||
Accessing the print note in a web browser allows for easy debugging to understand why a particular note doesn't render well. The mechanism for rendering is similar to the one used in <a class="reference-link" href="#root/0ESUbbAxVnoK">Note List</a>.
|
||||
|
||||
## Syntax highlighting
|
||||
|
||||
Syntax highlighting for code blocks is supported as well:
|
||||
|
||||
* It works by injecting a Highlight.js stylesheet into the print.
|
||||
* The theme used is hard-coded (the _Visual Studio Light theme_, at the time of writing) in order not to have a dark background in print.
|
||||
* <a class="reference-link" href="Syntax%20highlighting.md">Syntax highlighting</a> is handled by the content renderer.
|
||||
6
docs/Developer Guide/Developer Guide/Architecture/Protected entities.md
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# Protected entities
|
||||
The following entities can be made protected, via their `isProtected` flag:
|
||||
|
||||
* <a class="reference-link" href="Database%20structure/attachments.md">attachments</a>
|
||||
* <a class="reference-link" href="Database%20structure/notes.md">notes</a>
|
||||
* <a class="reference-link" href="Database%20structure/revisions.md">revisions</a>
|
||||
34
docs/Developer Guide/Developer Guide/Building/Build deliveries locally.md
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
# Build deliveries locally
|
||||
## Building the desktop
|
||||
|
||||
Go to `apps/desktop`, and:
|
||||
|
||||
* To generate the packages, run `pnpm electron-forge:make`.
|
||||
* To only build the Flatpak, run `pnpm electron-forge:make-flatpak`.
|
||||
* To only build without packaging it, run `pnpm electron-forge:package`.
|
||||
|
||||
## Building the server
|
||||
|
||||
Go to `apps/server` and run `pnpm package` to run the build script. The built artifacts will appear in `apps/server/dist`, whereas the packaged build will be available in `apps/server/out`.
|
||||
|
||||
## On NixOS
|
||||
|
||||
Under NixOS the following `nix-shell` is needed:
|
||||
|
||||
```
|
||||
nix-shell -p jq
|
||||
```
|
||||
|
||||
For Linux builds:
|
||||
|
||||
```
|
||||
nix-shell -p jq fakeroot dpkg
|
||||
```
|
||||
|
||||
To test the Linux builds, use `steam-run`:
|
||||
|
||||
```javascript
|
||||
$ NIXPKGS_ALLOW_UNFREE=1 nix-shell -p steam-run
|
||||
[nix-shell] cd dist/trilium-linux-x64
|
||||
[nix-shell] steam-run ./trilium
|
||||
```
|
||||
4
docs/Developer Guide/Developer Guide/Building/Build information.md
vendored
Normal file
@@ -0,0 +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 `apps/server/src/services/build.ts`. This file is generated automatically via `chore:update-build-info` which itself is run automatically whenever making a build in the CI.
|
||||
8
docs/Developer Guide/Developer Guide/Building/Docker.md
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Docker
|
||||
To build the server for Docker:
|
||||
|
||||
* Go to `apps/server` and run:
|
||||
* `pnpm docker-build-debian` or
|
||||
* `pnpm docker-build-alpine`.
|
||||
* Similarly, to build the rootless versions: `pnpm docker-build-rootless-debian` or `pnpm docker-build-rootless-alpine`.
|
||||
* To not only build but also run the Docker container, simply replace `docker-build` with `docker-start` (e.g. `pnpm docker-start-debian`).
|
||||
10
docs/Developer Guide/Developer Guide/Building/Live reload (HMR).md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# Live reload (HMR)
|
||||
Trilium uses Vite's HMR (hot module reloading) mechanism.
|
||||
|
||||
## Server live reload
|
||||
|
||||
If running the server using `pnpm server:start`, the server will watch for changes. For React components, they will be hot-reloaded without requiring a refresh. For other services, it will reload the page.
|
||||
|
||||
## Desktop live reload
|
||||
|
||||
`pnpm desktop:start` acts the same as `pnpm server:start` with hot-reloading for client-side changes. Changes on the desktop side require a complete re-run of the `pnpm desktop:start` command.
|
||||
19
docs/Developer Guide/Developer Guide/Building/Releasing a new version.md
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
# Releasing a new version
|
||||
Releasing is mostly handled by the CI:
|
||||
|
||||
* The version on GitHub is published automatically, including the description with the change log which is taken from the documentation.
|
||||
* A PR is created automatically on the Winget repository to update to the new version.
|
||||
|
||||
Releases are usually made directly from the `main` branch.
|
||||
|
||||
The process is as follows:
|
||||
|
||||
1. Edit the <a class="reference-link" href="../Documentation.md">Documentation</a> to add a corresponding entry in the _Release notes_ section.
|
||||
2. In the root `package.json`, set `version` to the new version to be released.
|
||||
3. Run `chore:update-version` to automatically update the version of the rest of the `package.json` files.
|
||||
4. Run `pnpm i` to update the package lock as well.
|
||||
5. Commit the changes to the `package.json` files and the `package-lock.json`. The commit message is usually `chore(release): prepare for v1.2.3`.
|
||||
6. Tag the newly created commit: `git tag v1.2.3`
|
||||
7. Push the commit and the newly created tag: `git push; git push --tags`.
|
||||
8. Wait for the CI to finish.
|
||||
9. When the release is automatically created in GitHub, download it to make sure it works OK.
|
||||
33
docs/Developer Guide/Developer Guide/Building/Running a development build.md
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# Running a development build
|
||||
First, follow the <a class="reference-link" href="../Environment%20Setup.md">Environment Setup</a>.
|
||||
|
||||
## Client
|
||||
|
||||
The client is not meant to be run by itself, despite being described as an app. See the documentation on the server instead.
|
||||
|
||||
## Server
|
||||
|
||||
* To run the server in development mode, run `server:start`. The dev port is `8080`.
|
||||
* To run the server in production mode (with its own copy of the assets), run `server:start-prod`.
|
||||
* To build for Docker, see <a class="reference-link" href="Docker.md">Docker</a>.
|
||||
|
||||
To run with a custom port, change the `TRILIUM_PORT` environment variable from the `package.json`.
|
||||
|
||||
## Desktop
|
||||
|
||||
* To run in development mode, use `pnpm desktop:start`.
|
||||
* To run in production mode, use `pnpm desktop:start-prod`.
|
||||
|
||||
## Safe mode
|
||||
|
||||
Safe mode is off by default, to enable it temporarily on a Unix shell, prepend the environment variable setting:
|
||||
|
||||
```
|
||||
pnpm cross-env TRILIUM_SAFE_MODE=1 pnpm server:start
|
||||
```
|
||||
|
||||
## Running on NixOS
|
||||
|
||||
When doing development, the Electron binary retrieved from NPM is not going to be compatible with NixOS, resulting in errors when trying to run it. However Trilium handles it automatically when running `pnpm desktop:start`.
|
||||
|
||||
If there's no `electron` the system path it will attempt to use `nix-shell` to obtain it.
|
||||
@@ -1,5 +1,5 @@
|
||||
# Differences from upstream
|
||||
* Embeds [`~~isaul32/ckeditor5-math~~`](https://github.com/isaul32/ckeditor5-math) <a class="reference-link" href="../ckeditor5-math.md">ckeditor5-math</a>, which is a third-party plugin for adding math support. CKEditor itself also has a [math plugin](https://ckeditor.com/docs/ckeditor5/latest/features/math-equations.html) with MathType and ChemType but it's premium-only.
|
||||
* Embeds [`~~isaul32/ckeditor5-math~~`](https://github.com/isaul32/ckeditor5-math) <a class="reference-link" href="ckeditor5-math.md">ckeditor5-math</a>, which is a third-party plugin for adding math support. CKEditor itself also has a [math plugin](https://ckeditor.com/docs/ckeditor5/latest/features/math-equations.html) with MathType and ChemType but it's premium-only.
|
||||
* Zadam left a TODO in `findandreplaceUI`: `// FIXME: keyboard shortcut doesn't work:` [`https://github.com/ckeditor/ckeditor5/issues/10645`](https://github.com/ckeditor/ckeditor5/issues/10645)
|
||||
* `packages\ckeditor5-build-balloon-block\src\mention_customization.js` introduces note insertion via `@` character.
|
||||
|
||||
@@ -34,7 +34,7 @@ In the newly copied package, go to `package.json` and edit:
|
||||
2. In `peerDependencies`, change `ckeditor5` to the same version as from the previous step.
|
||||
3. Similarly, update `vitest` dependencies to match the monorepo one.
|
||||
4. Remove the `prepare` entry from the `scripts` section.
|
||||
5. Change `build:dist` to simply `build` in order to integrate it with NX.
|
||||
5. Change `build:dist` to simply `build`.
|
||||
6. In `tsconfig.dist.json`, change `typings/types` to `../typings/types.d.ts` to be compatible with the latest TypeScript version.
|
||||
|
||||
## Step 4. Install missing dependencies and build errors
|
||||
16
docs/Developer Guide/Developer Guide/Dependencies/CKEditor/ckeditor5-math.md
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
# ckeditor5-math
|
||||
<figure class="image image-style-align-right"><img src="ckeditor5-math_image.png"><figcaption><code>ckeditor5-math</code> in action.</figcaption></figure>
|
||||
|
||||
A fork of [isaul32/ckeditor5-math](https://github.com/isaul32/ckeditor5-math), which is the CKEditor5 plugin which adds the math functionality. We keep our own version to be able to use it on the latest version of CKEditor, alongside some custom improvements.
|
||||
|
||||
## Development environment
|
||||
|
||||
* Tested on Node.js 20.
|
||||
* The package manager is yarn 1 (v1.22.22 is known to be working fine for it at the time of writing).
|
||||
|
||||
Important commands:
|
||||
|
||||
* To check if the code has any formatting issues: `yarn lint`
|
||||
* To start a live preview: `yarn start`
|
||||
* To run the tests: `yarn test`
|
||||
* Note that this requires Chromium, on NixOS this can be achieved by running a `nix-shell -p chromium`, and running `CHROME_BIN=$(which chromium) yarn test` inside it.
|
||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
@@ -1,2 +1,2 @@
|
||||
# Updating dependencies
|
||||
<table class="ck-table-resized"><colgroup><col> <col> <col> <col> <col></colgroup><thead><tr><th>Dependency</th><th>Name in <code>library_loader</code></th><th>Things to check for a basic sanity check</th><th> </th><th>Protected by unit tests</th></tr></thead><tbody><tr><td><code>better-sqlite3</code></td><td> </td><td>See <a class="reference-link" href="Updating%20dependencies/bettersqlite%20binaries.md">bettersqlite binaries</a>.</td><td> </td><td> </td></tr><tr><td><code>jsdom</code></td><td> </td><td><ul><li>Note map</li><li>Clipper</li><li>Note similarity</li></ul></td><td>Protected by typings, should catch any potential changes in API.</td><td>Yes</td></tr><tr><td><code>async-mutex</code></td><td> </td><td><ul><li>Sync</li></ul></td><td> </td><td> </td></tr><tr><td><code>axios</code></td><td> </td><td><ul><li>Can't be directly tested, as it's exposed only via the backend script API.</li></ul></td><td> </td><td> </td></tr><tr><td><code>sax</code></td><td> </td><td><ul><li>EverNote imports</li></ul></td><td> </td><td> </td></tr><tr><td><ul><li><code>ws</code></li><li><code>debounce</code></li></ul></td><td> </td><td><ul><li>Check any action is reported from server to client (e.g. delete a note).</li></ul></td><td> </td><td> </td></tr><tr><td><code>ejs</code></td><td> </td><td><ul><li>Onboarding / first setup</li></ul></td><td> </td><td> </td></tr><tr><td><code>dayjs</code></td><td> </td><td><ul><li>Day notes</li></ul></td><td> </td><td> </td></tr><tr><td><code>semver</code></td><td> </td><td><ul><li>Application should start.</li></ul></td><td> </td><td> </td></tr><tr><td><code>https-proxy-agent</code></td><td> </td><td>???</td><td> </td><td> </td></tr><tr><td><code>sax</code></td><td> </td><td><ul><li>EverNote import</li></ul></td><td> </td><td> </td></tr><tr><td><code>ini</code></td><td> </td><td><ul><li>Affects config, generally if the application starts then it should be OK.</li></ul></td><td> </td><td> </td></tr><tr><td><code>jsplumb</code></td><td><code>RELATION_MAP</code></td><td><ul><li>Relation map note type</li></ul></td><td> </td><td> </td></tr><tr><td><code>jquery.mark.es6</code></td><td><code>MARKJS</code></td><td><ul><li>In search, when highlighting the text that matched.</li><li>In search in HTML, which might not actually be used since it seems to have been replaced by CKEditor's own find & replace dialog.</li></ul></td><td> </td><td> </td></tr><tr><td><code>knockout.js</code></td><td> </td><td><ul><li>Used in rendering the login and main layout of the application.</li></ul></td><td> </td><td> </td></tr><tr><td><code>normalize.min.css</code></td><td> </td><td><ul><li>Used in shared notes.</li></ul></td><td> </td><td> </td></tr><tr><td><code>wheel-zoom.min.js</code></td><td><code>WHEEL_ZOOM</code></td><td><ul><li>When opening a image that is in attachment.</li><li>When opening a stand-alone image note.</li><li>When zooming in a mermaid chart.</li></ul></td><td> </td><td> </td></tr><tr><td><code>fancytree</code></td><td> </td><td><ul><li>The note tree should be fully functional.</li></ul></td><td> </td><td> </td></tr><tr><td><code>bootstrap</code></td><td> </td><td><ul><li>Check mostly the on-boarding pages, when there is no database.</li></ul></td><td> </td><td> </td></tr><tr><td><code>electron-debug</code></td><td> </td><td><ul><li>Run electron using <code>npm run start-electron</code> and check that the debug hotkeys are still working (Ctrl+Shift+I on Windows/Linux, Cmd+Alt+I for dev tools, Cmd/Ctrl+R for reload).</li></ul></td><td> </td><td> </td></tr><tr><td><code>electron-dl</code></td><td> </td><td> </td><td> </td><td> </td></tr><tr><td><code>eslint</code></td><td> </td><td> </td><td> </td><td> </td></tr><tr><td><code>marked</code></td><td> </td><td><ul><li>Importing a markdown note.</li></ul></td><td> </td><td>Yes</td></tr><tr><td><code>force-graph</code></td><td> </td><td><ul><li>Note map</li></ul></td><td> </td><td> </td></tr></tbody></table>
|
||||
# Per-dependency checks
|
||||
<table class="ck-table-resized"><colgroup><col> <col> <col> <col> <col></colgroup><thead><tr><th>Dependency</th><th>Name in <code>library_loader</code></th><th>Things to check for a basic sanity check</th><th> </th><th>Protected by unit tests</th></tr></thead><tbody><tr><td><code>better-sqlite3</code></td><td> </td><td>See <a class="reference-link" href="Per-dependency%20checks/bettersqlite%20binaries.md">bettersqlite binaries</a>.</td><td> </td><td> </td></tr><tr><td><code>jsdom</code></td><td> </td><td><ul><li>Note map</li><li>Clipper</li><li>Note similarity</li></ul></td><td>Protected by typings, should catch any potential changes in API.</td><td>Yes</td></tr><tr><td><code>async-mutex</code></td><td> </td><td><ul><li>Sync</li></ul></td><td> </td><td> </td></tr><tr><td><code>axios</code></td><td> </td><td><ul><li>Can't be directly tested, as it's exposed only via the backend script API.</li></ul></td><td> </td><td> </td></tr><tr><td><code>sax</code></td><td> </td><td><ul><li>EverNote imports</li></ul></td><td> </td><td> </td></tr><tr><td><ul><li><code>ws</code></li><li><code>debounce</code></li></ul></td><td> </td><td><ul><li>Check any action is reported from server to client (e.g. delete a note).</li></ul></td><td> </td><td> </td></tr><tr><td><code>ejs</code></td><td> </td><td><ul><li>Onboarding / first setup</li></ul></td><td> </td><td> </td></tr><tr><td><code>dayjs</code></td><td> </td><td><ul><li>Day notes</li></ul></td><td> </td><td> </td></tr><tr><td><code>semver</code></td><td> </td><td><ul><li>Application should start.</li></ul></td><td> </td><td> </td></tr><tr><td><code>https-proxy-agent</code></td><td> </td><td>???</td><td> </td><td> </td></tr><tr><td><code>sax</code></td><td> </td><td><ul><li>EverNote import</li></ul></td><td> </td><td> </td></tr><tr><td><code>ini</code></td><td> </td><td><ul><li>Affects config, generally if the application starts then it should be OK.</li></ul></td><td> </td><td> </td></tr><tr><td><code>jsplumb</code></td><td><code>RELATION_MAP</code></td><td><ul><li>Relation map note type</li></ul></td><td> </td><td> </td></tr><tr><td><code>jquery.mark.es6</code></td><td><code>MARKJS</code></td><td><ul><li>In search, when highlighting the text that matched.</li><li>In search in HTML, which might not actually be used since it seems to have been replaced by CKEditor's own find & replace dialog.</li></ul></td><td> </td><td> </td></tr><tr><td><code>knockout.js</code></td><td> </td><td><ul><li>Used in rendering the login and main layout of the application.</li></ul></td><td> </td><td> </td></tr><tr><td><code>normalize.min.css</code></td><td> </td><td><ul><li>Used in shared notes.</li></ul></td><td> </td><td> </td></tr><tr><td><code>wheel-zoom.min.js</code></td><td><code>WHEEL_ZOOM</code></td><td><ul><li>When opening a image that is in attachment.</li><li>When opening a stand-alone image note.</li><li>When zooming in a mermaid chart.</li></ul></td><td> </td><td> </td></tr><tr><td><code>fancytree</code></td><td> </td><td><ul><li>The note tree should be fully functional.</li></ul></td><td> </td><td> </td></tr><tr><td><code>bootstrap</code></td><td> </td><td><ul><li>Check mostly the on-boarding pages, when there is no database.</li></ul></td><td> </td><td> </td></tr><tr><td><code>electron-debug</code></td><td> </td><td><ul><li>Run electron using <code>npm run start-electron</code> and check that the debug hotkeys are still working (Ctrl+Shift+I on Windows/Linux, Cmd+Alt+I for dev tools, Cmd/Ctrl+R for reload).</li></ul></td><td> </td><td> </td></tr><tr><td><code>electron-dl</code></td><td> </td><td> </td><td> </td><td> </td></tr><tr><td><code>eslint</code></td><td> </td><td> </td><td> </td><td> </td></tr><tr><td><code>marked</code></td><td> </td><td><ul><li>Importing a markdown note.</li></ul></td><td> </td><td>Yes</td></tr><tr><td><code>force-graph</code></td><td> </td><td><ul><li>Note map</li></ul></td><td> </td><td> </td></tr></tbody></table>
|
||||
25
docs/Developer Guide/Developer Guide/Dependencies/Per-dependency checks/bettersqlite binaries.md
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# bettersqlite binaries
|
||||
### The native node bindings
|
||||
|
||||
`better-sqlite3` has native Node bindings. With updates of `better-sqlite3`, but also of Electron and Node.js versions, these bindings need to be updated.
|
||||
|
||||
Note that Electron and Node.js versions need different versions of these bindings, since Electron usually packs a different version of Node.js.
|
||||
|
||||
During development, `pnpm install` tries to build or reuse prebuilt natives for the current Node.js version. This makes `npm run start-server` work out of the box. Trying to run `npm run start-electron` with these versions generally causes an error such as this:
|
||||
|
||||
```
|
||||
Uncaught Exception:
|
||||
Error: The module '/Users/elian/Projects/Notes/node_modules/better-sqlite3/build/Release/better_sqlite3.node'
|
||||
was compiled against a different Node.js version using
|
||||
NODE_MODULE_VERSION 108. This version of Node.js requires
|
||||
NODE_MODULE_VERSION 116. Please try re-compiling or re-installing
|
||||
the module (for instance, using `npm rebuild` or `npm install`).
|
||||
```
|
||||
|
||||
### How the natives are handled
|
||||
|
||||
To avoid issues between the `server` and the `desktop`, the `desktop` build gets its own copy of the `bettersqlite3` dependency in its `node_module`. This copy is then rebuilt automatically to match the Electron version.
|
||||
|
||||
This process of rebuilding is handled by `scripts/electron-rebuild.mts` which runs automatically after `pnpm install` (via `postinstall`).
|
||||
|
||||
If needed, the script can be run manually again via `pnpm postinstall`.
|
||||
@@ -1,4 +0,0 @@
|
||||
# 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](../Old%20documentation/Build%20deliveries%20locally.md).
|
||||
@@ -1,2 +0,0 @@
|
||||
# attributes
|
||||
<table><thead><tr><th>Column Name</th><th>Data Type</th><th>Nullity</th><th>Default value</th><th>Description</th></tr></thead><tbody><tr><th><code>attributeId</code></th><td>Text</td><td>Non-null</td><td> </td><td>Unique Id of the attribute (e.g. <code>qhC1vzU4nwSE</code>), can also have a special unique ID for <a class="reference-link" href="../Special%20notes.md">Special notes</a> (e.g. <code>_lbToday_liconClass</code>).</td></tr><tr><th><code>noteId</code></th><td>Text</td><td>Non-null</td><td> </td><td>The ID of the <a href="notes.md">note</a> this atttribute belongs to</td></tr><tr><th><code>type</code></th><td>Text</td><td>Non-null</td><td> </td><td>The type of attribute (<code>label</code> or <code>relation</code>).</td></tr><tr><th><code>name</code></th><td>Text</td><td>Non-null</td><td> </td><td>The name/key of the attribute.</td></tr><tr><th><code>value</code></th><td>Text</td><td>Non-null</td><td><code>""</code></td><td><ul><li>For <code>label</code> attributes, a free-form value of the attribute.</li><li>For <code>relation</code> attributes, the ID of the <a href="notes.md">note</a> the relation is pointing to.</li></ul></td></tr><tr><th><code>position</code></th><td>Integer</td><td>Non-null</td><td>0</td><td>The position of the attribute compared to the other attributes. Some predefined attributes such as <code>originalFileName</code> have a value of 1000.</td></tr><tr><th><code>utcDateModified</code></th><td>Text</td><td>Non-null</td><td> </td><td>Modification date in UTC format (e.g. <code>2023-11-08 16:43:44.204Z</code>)</td></tr><tr><th><code>isDeleted</code></th><td>Integer</td><td>Non-null</td><td> </td><td><code>1</code> if the entity is <a href="../Deleted%20notes.md">deleted</a>, <code>0</code> otherwise.</td></tr><tr><th><code>deleteId</code></th><td>Text</td><td>Nullable</td><td><code>null</code></td><td> </td></tr><tr><th><code>isInheritable</code></th><td>Integer</td><td>Nullable</td><td>0</td><td> </td></tr></tbody></table>
|
||||
@@ -1,2 +0,0 @@
|
||||
# blobs
|
||||
<table><thead><tr><th>Column Name</th><th>Data Type</th><th>Nullity</th><th>Default value</th><th>Description</th></tr></thead><tbody><tr><th><code>blobId</code></th><td>Text</td><td>Non-null</td><td> </td><td>The unique ID of the blob (e.g. <code>XXbfAJXqWrYnSXcelLFA</code>).<p>Important: this ID is actually a hash of the content, see <code>AbstractBeccaEntity#saveBlob</code>! It is a logic error to modify an existing blob.</p></td></tr><tr><th><code>content</code></th><td>Text</td><td>Nullable</td><td><code>null</code></td><td><p>The content of the blob, can be either:</p><ul><li>text (for plain text notes or HTML notes).</li><li>binary (for images and other types of attachments)</li></ul></td></tr><tr><th><code>dateModified</code></th><td>Text</td><td>Non-null</td><td> </td><td>Creation date with timezone offset (e.g. <code>2023-11-08 18:43:44.204+0200</code>)</td></tr><tr><th><code>utcDateModified</code></th><td>Text</td><td>Non-null</td><td> </td><td>Creation date in UTC format (e.g. <code>2023-11-08 16:43:44.204Z</code>).<p>Blobs cannot be modified, so this timestamp specifies when the blob was created.</p></td></tr></tbody></table>
|
||||
@@ -1,19 +0,0 @@
|
||||
# Demo document
|
||||
The demo document is an exported .zip that resides in `db/demo.zip`.
|
||||
|
||||
During on-boarding, if the user selects that they are a new user then the `demo.zip` is imported into the root note.
|
||||
|
||||
## Modifying the document
|
||||
|
||||
On a dev server, remove all your existing notes in order to ensure a clean setup. Right click → Import to note and select the .zip file in `db/demo.zip`. Make sure to disable “Safe import”.
|
||||
|
||||
After making the necessary modifications, simply export the “Trilium Demo” note as “HTML in ZIP archive” and replace `db/demo.zip` with the newly exported one.
|
||||
|
||||
## Testing the changes
|
||||
|
||||
```
|
||||
rm -r data
|
||||
npm run start-server
|
||||
```
|
||||
|
||||
And then do the on-boarding again.
|
||||
@@ -1,18 +0,0 @@
|
||||
# Docker
|
||||
To run a Docker build:
|
||||
|
||||
```
|
||||
./bin/builder-docker.sh
|
||||
```
|
||||
|
||||
To run the built Docker image:
|
||||
|
||||
```
|
||||
sudo docker run -p 8081:8080 triliumnext/trilium:v0.90.6-beta
|
||||
```
|
||||
|
||||
To enter a shell in the Docker container:
|
||||
|
||||
```
|
||||
sudo docker run -it --entrypoint=/bin/sh zadam/trilium:0.63-latest
|
||||
```
|
||||