Merge branch 'main' into electron_newwindow
Some checks are pending
Checks / main (push) Waiting to run

This commit is contained in:
SngAbc 2025-11-02 23:06:58 +08:00 committed by GitHub
commit 6f0a264869
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
51 changed files with 2096 additions and 804 deletions

2
.nvmrc
View File

@ -1 +1 @@
22.21.0
24.11.0

View File

@ -38,16 +38,16 @@
"@playwright/test": "1.56.1",
"@stylistic/eslint-plugin": "5.5.0",
"@types/express": "5.0.5",
"@types/node": "24.9.1",
"@types/node": "24.9.2",
"@types/yargs": "17.0.34",
"@vitest/coverage-v8": "3.2.4",
"eslint": "9.38.0",
"eslint": "9.39.0",
"eslint-plugin-simple-import-sort": "12.1.1",
"esm": "3.2.25",
"jsdoc": "4.0.5",
"lorem-ipsum": "2.0.8",
"rcedit": "4.0.1",
"rimraf": "6.0.1",
"rimraf": "6.1.0",
"tslib": "2.8.1",
"typedoc": "0.28.14",
"typedoc-plugin-missing-exports": "4.1.2"

View File

@ -15,7 +15,7 @@
"circular-deps": "dpdm -T src/**/*.ts --tree=false --warning=false --skip-dynamic-imports=circular"
},
"dependencies": {
"@eslint/js": "9.38.0",
"@eslint/js": "9.39.0",
"@excalidraw/excalidraw": "0.18.0",
"@fullcalendar/core": "6.1.19",
"@fullcalendar/daygrid": "6.1.19",
@ -37,12 +37,12 @@
"bootstrap": "5.3.8",
"boxicons": "2.1.4",
"color": "5.0.2",
"dayjs": "1.11.18",
"dayjs": "1.11.19",
"dayjs-plugin-utc": "0.1.2",
"debounce": "2.2.0",
"draggabilly": "3.0.0",
"force-graph": "1.51.0",
"globals": "16.4.0",
"globals": "16.5.0",
"i18next": "25.6.0",
"i18next-http-backend": "3.0.2",
"jquery": "3.7.1",
@ -59,7 +59,7 @@
"normalize.css": "8.0.1",
"panzoom": "9.4.3",
"preact": "10.27.2",
"react-i18next": "16.2.1",
"react-i18next": "16.2.3",
"reveal.js": "5.2.1",
"svg-pan-zoom": "3.6.2",
"tabulator-tables": "6.3.1",
@ -76,7 +76,7 @@
"@types/reveal.js": "5.2.1",
"@types/tabulator-tables": "6.3.0",
"copy-webpack-plugin": "13.0.1",
"happy-dom": "20.0.8",
"happy-dom": "20.0.10",
"script-loader": "0.7.2",
"vite-plugin-static-copy": "3.1.4"
}

View File

@ -270,6 +270,7 @@ export type CommandMappings = {
closeThisNoteSplit: CommandData;
moveThisNoteSplit: CommandData & { isMovingLeft: boolean };
jumpToNote: CommandData;
openTodayNote: CommandData;
commandPalette: CommandData;
// Keyboard shortcuts

View File

@ -159,6 +159,16 @@ export default class Entrypoints extends Component {
this.openInWindowCommand({ notePath: "", hoistedNoteId: "root" });
}
async openTodayNoteCommand() {
const todayNote = await dateNoteService.getTodayNote();
if (!todayNote) {
console.warn("Missing today note.");
return;
}
await appContext.tabManager.openInSameTab(todayNote.noteId);
}
async runActiveNoteCommand() {
const noteContext = appContext.tabManager.getActiveContext();
if (!noteContext) {

View File

@ -417,7 +417,7 @@ export default class FNote {
return notePaths;
}
getSortedNotePathRecords(hoistedNoteId = "root"): NotePathRecord[] {
getSortedNotePathRecords(hoistedNoteId = "root", activeNotePath: string | null = null): NotePathRecord[] {
const isHoistedRoot = hoistedNoteId === "root";
const notePaths: NotePathRecord[] = this.getAllNotePaths().map((path) => ({
@ -428,7 +428,23 @@ export default class FNote {
isHidden: path.includes("_hidden")
}));
// Calculate the length of the prefix match between two arrays
const prefixMatchLength = (path: string[], target: string[]) => {
const diffIndex = path.findIndex((seg, i) => seg !== target[i]);
return diffIndex === -1 ? Math.min(path.length, target.length) : diffIndex;
};
notePaths.sort((a, b) => {
if (activeNotePath) {
const activeSegments = activeNotePath.split('/');
const aOverlap = prefixMatchLength(a.notePath, activeSegments);
const bOverlap = prefixMatchLength(b.notePath, activeSegments);
// Paths with more matching prefix segments are prioritized
// when the match count is equal, other criteria are used for sorting
if (bOverlap !== aOverlap) {
return bOverlap - aOverlap;
}
}
if (a.isInHoistedSubTree !== b.isInHoistedSubTree) {
return a.isInHoistedSubTree ? -1 : 1;
} else if (a.isArchived !== b.isArchived) {
@ -449,10 +465,11 @@ export default class FNote {
* Returns the note path considered to be the "best"
*
* @param {string} [hoistedNoteId='root']
* @param {string|null} [activeNotePath=null]
* @return {string[]} array of noteIds constituting the particular note path
*/
getBestNotePath(hoistedNoteId = "root") {
return this.getSortedNotePathRecords(hoistedNoteId)[0]?.notePath;
getBestNotePath(hoistedNoteId = "root", activeNotePath: string | null = null) {
return this.getSortedNotePathRecords(hoistedNoteId, activeNotePath)[0]?.notePath;
}
/**

View File

@ -26,21 +26,12 @@ async function resolveNotePathToSegments(notePath: string, hoistedNoteId = "root
}
const path = notePath.split("/").reverse();
if (!path.includes("root")) {
path.push("root");
}
const effectivePathSegments: string[] = [];
let childNoteId: string | null = null;
let i = 0;
while (true) {
if (i >= path.length) {
break;
}
const parentNoteId = path[i++];
for (let i = 0; i < path.length; i++) {
const parentNoteId = path[i];
if (childNoteId !== null) {
const child = await froca.getNote(childNoteId, !logErrors);
@ -65,7 +56,7 @@ async function resolveNotePathToSegments(notePath: string, hoistedNoteId = "root
return null;
}
if (!parents.some((p) => p.noteId === parentNoteId)) {
if (!parents.some(p => p.noteId === parentNoteId) || (i === path.length - 1 && parentNoteId !== 'root')) {
if (logErrors) {
const parent = froca.getNoteFromCache(parentNoteId);
@ -77,7 +68,8 @@ async function resolveNotePathToSegments(notePath: string, hoistedNoteId = "root
);
}
const bestNotePath = child.getBestNotePath(hoistedNoteId);
const activeNotePath = appContext.tabManager.getActiveContextNotePath();
const bestNotePath = child.getBestNotePath(hoistedNoteId, activeNotePath);
if (bestNotePath) {
const pathToRoot = bestNotePath.reverse().slice(1);
@ -108,7 +100,9 @@ async function resolveNotePathToSegments(notePath: string, hoistedNoteId = "root
if (!note) {
throw new Error(`Unable to find note: ${notePath}.`);
}
const bestNotePath = note.getBestNotePath(hoistedNoteId);
const activeNotePath = appContext.tabManager.getActiveContextNotePath();
const bestNotePath = note.getBestNotePath(hoistedNoteId, activeNotePath);
if (!bestNotePath) {
throw new Error(`Did not find any path segments for '${note.toString()}', hoisted note '${hoistedNoteId}'`);

View File

@ -11,8 +11,12 @@ export function reloadFrontendApp(reason?: string) {
logInfo(`Frontend app reload: ${reason}`);
}
if (isElectron()) {
dynamicRequire("@electron/remote").BrowserWindow.getFocusedWindow()?.reload();
} else {
window.location.reload();
}
}
export function restartDesktopApp() {
if (!isElectron()) {

View File

@ -35,7 +35,7 @@
"@triliumnext/commons": "workspace:*",
"@triliumnext/server": "workspace:*",
"copy-webpack-plugin": "13.0.1",
"electron": "38.4.0",
"electron": "38.5.0",
"@electron-forge/cli": "7.10.2",
"@electron-forge/maker-deb": "7.10.2",
"@electron-forge/maker-dmg": "7.10.2",

View File

@ -12,7 +12,7 @@
"@triliumnext/desktop": "workspace:*",
"@types/fs-extra": "11.0.4",
"copy-webpack-plugin": "13.0.1",
"electron": "38.4.0",
"electron": "38.5.0",
"fs-extra": "11.3.2"
},
"scripts": {

View File

@ -1,4 +1,4 @@
FROM node:24.10.0-bullseye-slim AS builder
FROM node:24.11.0-bullseye-slim AS builder
RUN corepack enable
# Install native dependencies since we might be building cross-platform.
@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
# We have to use --no-frozen-lockfile due to CKEditor patches
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
FROM node:24.10.0-bullseye-slim
FROM node:24.11.0-bullseye-slim
# Install only runtime dependencies
RUN apt-get update && \
apt-get install -y --no-install-recommends \

View File

@ -1,4 +1,4 @@
FROM node:24.10.0-alpine AS builder
FROM node:24.11.0-alpine AS builder
RUN corepack enable
# Install native dependencies since we might be building cross-platform.
@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
# We have to use --no-frozen-lockfile due to CKEditor patches
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
FROM node:24.10.0-alpine
FROM node:24.11.0-alpine
# Install runtime dependencies
RUN apk add --no-cache su-exec shadow

View File

@ -1,4 +1,4 @@
FROM node:24.10.0-alpine AS builder
FROM node:24.11.0-alpine AS builder
RUN corepack enable
# Install native dependencies since we might be building cross-platform.
@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
# We have to use --no-frozen-lockfile due to CKEditor patches
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
FROM node:24.10.0-alpine
FROM node:24.11.0-alpine
# Create a non-root user with configurable UID/GID
ARG USER=trilium
ARG UID=1001

View File

@ -1,4 +1,4 @@
FROM node:24.10.0-bullseye-slim AS builder
FROM node:24.11.0-bullseye-slim AS builder
RUN corepack enable
# Install native dependencies since we might be building cross-platform.
@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
# We have to use --no-frozen-lockfile due to CKEditor patches
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
FROM node:24.10.0-bullseye-slim
FROM node:24.11.0-bullseye-slim
# Create a non-root user with configurable UID/GID
ARG USER=trilium
ARG UID=1001

View File

@ -30,7 +30,7 @@
"node-html-parser": "7.0.1"
},
"devDependencies": {
"@anthropic-ai/sdk": "0.67.0",
"@anthropic-ai/sdk": "0.68.0",
"@braintree/sanitize-url": "7.1.1",
"@electron/remote": "2.1.3",
"@preact/preset-vite": "2.10.2",
@ -68,28 +68,28 @@
"@types/xml2js": "0.4.14",
"archiver": "7.0.1",
"async-mutex": "0.5.0",
"axios": "1.13.0",
"axios": "1.13.1",
"bindings": "1.5.0",
"bootstrap": "5.3.8",
"chardet": "2.1.0",
"chardet": "2.1.1",
"cheerio": "1.1.2",
"chokidar": "4.0.3",
"cls-hooked": "4.2.2",
"compression": "1.8.1",
"cookie-parser": "1.4.7",
"csrf-csrf": "3.2.2",
"dayjs": "1.11.18",
"dayjs": "1.11.19",
"debounce": "2.2.0",
"debug": "4.4.3",
"ejs": "3.1.10",
"electron": "38.4.0",
"electron": "38.5.0",
"electron-debug": "4.1.0",
"electron-window-state": "5.0.3",
"escape-html": "1.0.3",
"express": "5.1.0",
"express-http-proxy": "2.1.2",
"express-openid-connect": "2.19.2",
"express-rate-limit": "8.1.0",
"express-rate-limit": "8.2.1",
"express-session": "1.18.2",
"file-uri-to-path": "2.0.0",
"fs-extra": "11.3.2",
@ -110,7 +110,7 @@
"mime-types": "3.0.1",
"multer": "2.0.2",
"normalize-strings": "1.1.1",
"ollama": "0.6.0",
"ollama": "0.6.2",
"openai": "6.7.0",
"rand-token": "1.0.1",
"safe-compare": "1.1.4",

File diff suppressed because one or more lines are too long

View File

@ -1,21 +1,21 @@
<p>The desktop version of Trilium supports all three main operating systems:</p>
<ul>
<li data-list-item-id="e9369fe00e2202eddd7638f9115592204">Windows
<li>Windows
<ul>
<li data-list-item-id="ecbf2fbdd331d51182332dd3d33aeab15">Windows 11 is officially supported.</li>
<li data-list-item-id="e029be961ae70031059602696f29f72bf">Windows on ARM is also supported</li>
<li>Windows 11 is officially supported.</li>
<li>Windows on ARM is also supported</li>
</ul>
</li>
<li data-list-item-id="e87f0cd97f723e8bd59f181622122906b">Linux:
<li>Linux:
<ul>
<li data-list-item-id="efa1b52fdb55980bee3f3482ee0f55dfa">Most modern distributions are supported, including NixOS.</li>
<li data-list-item-id="efe26984776dbcafc56afcc83a4d1b85b">ARM is supported in <code>aarch64</code> (no ARM v7 support).&nbsp;</li>
<li>Most modern distributions are supported, including NixOS.</li>
<li>ARM is supported in <code>aarch64</code> (no ARM v7 support).</li>
</ul>
</li>
<li data-list-item-id="eabb3c5c35295997be8b2579caa6cae1b">macOS
<li>macOS
<ul>
<li data-list-item-id="e2848f18f02ba6ded3f20f46e12fecc54">Minimum supported operating system: macOS Monterey&nbsp;</li>
<li data-list-item-id="ea709467c48e79ae0c7e4d3c5e9261505">Both Intel and Apple Silicon devices are supported.</li>
<li>Minimum supported operating system: macOS Monterey</li>
<li>Both Intel and Apple Silicon devices are supported.</li>
</ul>
</li>
</ul>

View File

@ -1,7 +1,6 @@
<ul>
<li data-list-item-id="edfd91483e74d0b747136f134131b9720">Using Docker, the server can be run on Windows, Linux and macOS devices.</li>
<li
data-list-item-id="efde3b56d3d4f5b167bad52f55637e111">Native binaries are provided for Linux x64 and ARM (<code>aarch64</code>).</li>
<li>Using Docker, the server can be run on Windows, Linux and macOS devices.</li>
<li>Native binaries are provided for Linux x64 and ARM (<code>aarch64</code>).</li>
</ul>
<h2>Legacy ARM support</h2>
<p>The Docker builds also provide <code>linux/arm/v7</code> and <code>linux/arm/v8</code> platforms.

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

View File

@ -0,0 +1,301 @@
<aside class="admonition note">
<p>This article is a description of the original author of Trilium (zadam)
in regards with his own knowledge base.</p>
</aside>
<p>This page contains description of some of the patterns I use to organize
information in my knowledge base. This is meant to give some inspiration
of how one might create and structure their knowledge base in general and
also specifically in Trilium Notes. It also gives some background and justification
for some of the design decisions.</p>
<h2>Meta patterns</h2>
<p>Just to be clear, meta patterns are "patterns of patterns", i.e. patterns
appearing in other patterns.</p>
<h3>Hierarchical organization of information</h3>
<p>Basic meta pattern is that I sort notes (units of information) into a
hierarchy - I have some "top level" notes which represent coarse grained
organization, these then split into sub-notes defining finer grained organization
and so on. I consider this hierarchical (tree) organization very efficient
for organization of large amounts of information. A lot of note taking
software (such as Evernote) are frustratingly limited in this regard which
limits scalability of the software to large amounts of notes.</p>
<h4>Scalability</h4>
<p>It's important to frame the following (meta) patterns with some idea of
how large amount of data are we talking about.</p>
<p>My rule of thumb for estimation of size of personal knowledge base is
that you can reasonably produce around 10 notes a day, which is 3650 in
a year. I plan to use my knowledge base long term (with or without Trilium
Notes), probably decades so you can easily get to number 100 000 or even
more. Right now, my personal knowledge base has around 10 000 notes.</p>
<p>100 000 is a number to which most note taking software doesn't scale well
(in both performance and UI). Yet I don't think it's really very much considering
a lifetime of knowledge.</p>
<h4>Lazy hierarchy</h4>
<p>My approach to creating the hierarchy is being lazy - I don't create the
structure first and then fill it with notes, instead I create single note
for some specific topic and start using this one note. Once the content
starts to grow, and I see how <em>some</em> parts could be split out, I move
them out into separate sub notes. As an example I have a book review for <em>The Fellowship of the Ring</em>:</p>
<ul>
<li>Book reviews
<ul>
<li>The Fellowship of the Ring</li>
</ul>
</li>
</ul>
<p>The note contains basic book info (author, publisher etc.), book highlights
with the comments and then overall review. Now it turns out there's far
too many book highlights and overall review is also rather long, so I want
to change the structure to the following:</p>
<ul>
<li>Book reviews
<ul>
<li>The Fellowship of the Ring &nbsp; &nbsp; &nbsp;&nbsp;<em>(still contains basic info)</em>
<ul>
<li>Highlights</li>
<li>Review</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>If I used standard text file stored in a filesystem I would soon run into
an annoying problem that in order to split out the Highlights and Review
into sub-notes I would also have to convert <em>The Fellowship of the Ring</em> from
text file into directory and split out all sections of the note into sub-notes.
Instead, Trilium treats all notes as equal - both leaf notes and inner
notes can have both text content which allows me to sub-structure only
content which needs it.</p>
<h3>Sorting notes into multiple places in the hierarchy</h3>
<p>While organizing the notes into the hierarchy, you very quickly run into
a dilemma - your note seem to belong to two places in the hierarchy equally.
As an example - you want to make a note about <a href="https://en.wikipedia.org/wiki/Bash_(Unix_shell)">bash</a> -
does it belong to "OS / Linux" or "Programming / Scripting languages"?
This is actually a false dichotomy forced down by the limits of the basic
tree hierarchy - the answer is <em>of course it belongs to both</em>. This
is the reason why Trilium doesn't use standard tree structure (which requires
every note to have exactly one parent), but an extension which allows every
note to have several parents, thus effectively allowing it to appear in
multiple places in the hierarchy. For lack of better term I call this "cloning".
The main problem with this term is that it suggests that each clone must
have an original, but here all clones are completely equal - effectively
there's no original.</p>
<p>In tech lingo, it might be better to describe it as a <a href="https://en.wikipedia.org/wiki/Hard_link">hard link</a> with
an important difference that it is possible to hard link (clone) a directory
(inner note).</p>
<h3>Protected notes</h3>
<p>I have Trilium Notes opened non-stop. Sometimes I forget to lock my computer
when going to the bathroom. Sometimes I let a friend or family member to
use my computer for a minute without supervision. They might click on (running)
Trilium and inadvertently see a note I really don't want anybody to see
(personal diary, credentials). To cover this, Trilium has a concept of
"<a href="https://github.com/zadam/trilium/wiki/Protected-notes">protected notes</a>"
- protected note is encrypted and on top of that requires the user to enter
the password every 5 minutes which guarantees that such note can be in
a readable state only for small amount of time. Working with ordinary (not
protected) notes don't require password so you're not bothered by extra
security when it's not needed.</p>
<h3>Archiving notes</h3>
<p>Notes can lose relevancy with time - let's say I switch jobs - all the
notes specific to the former employer immediately lose most of its import.
This doesn't mean I want to delete these notes though - typically I just
want them to somehow deprioritize - in Trilium I would do that by assigning
an <a href="https://github.com/zadam/trilium/wiki/Attribute-inheritance">inherited</a>
<a
href="https://github.com/zadam/trilium/wiki/Attributes">label</a> <code>archived</code> to the company root note. The main effect
of this label is that all the notes from this sub-tree are filtered out
from search results (fast search via note autocomplete is my main <a href="https://github.com/zadam/trilium/wiki/Note-navigation">navigation approach</a>).
Apart from this, I also typically move such outdated notes to some less
prominent place in the hierarchy.</p>
<p>I use archivation also for notes which are not very relevant from their
creation - an example might be automatically imported reddit comments.</p>
<p>Sometimes there's no clear <em>category</em> split between relevant and
non-relevant notes, in that case I just create "<em>OLD</em>" note with <code>archived</code> label
and move all irrelevant notes there. So my credentials note might look
something like this:</p>
<ul>
<li>Credentials
<ul>
<li>Personal
<ul>
<li>OLD &nbsp; &nbsp; &nbsp;&nbsp;<em>(contains a bunch of notes with credentials for services I don't use anymore)</em>
</li>
<li>Gmail</li>
<li>Github</li>
<li>...</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>Patterns</h2>
<h3>Day note</h3>
<p>Every day has its note which contains or references everything related
to the given day. Structure looks like this:</p>
<ul>
<li>2018
<ul>
<li>11 - November
<ul>
<li>26 - Monday</li>
<li>27 - Tuesday
<ul>
<li>subnote 1</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>Day note serves as a workspace and note inbox at the same time - it's
the default location to create a note when I don't have time to think about
proper placement. At the end of the day I typically review my day note
and clone the notes into suitable locations in the hierarchy.</p>
<p>Trilium has this pattern partly built-in - Trilium understands and can
create this Year / Month / Day structure semi-automatically (on API call).
There's also global keyboard shortcut <code>CTRL-ALT-P</code> which will
create new note in the day note.</p>
<p>What notes do I keep under this day note?</p>
<ul>
<li>TODO list for given day (this can be automated - see&nbsp;<a class="reference-link"
href="#root/_help_xYjQUYhpbUEW">Task Manager</a>)</li>
<li>Personal diary</li>
<li><a href="#root/_help_IakOLONlIfGI">clones</a> of notes I created during this
day (which kind of represents what I've been working on).</li>
<li>I often clone notes (or sub-trees) of e.g. projects I'm working on at
given day so they are at hand</li>
<li>I have some <a href="#root/_help_CdNpE2pqjmI6">scripts</a> which allow me to track
certain daily metrics (like weight). These are saved into one daily "data
note" (actually JSON <a href="#root/_help_6f9hih2hXXZk">code note</a>).
<ul>
<li>I have other scripts which then help me to visualize these data (see a&nbsp;
<a
class="reference-link" href="#root/_help_R7abl2fc6Mxi">Weight Tracker</a>&nbsp;example)</li>
<li>I have a script which automatically imports all my comments from reddit
into the day note.
<ul>
<li>People are sometimes wondering why. The answer is that I usually put some
effort and thought into a comment and that's why I feel it's worth preserving,
especially if it can be done automatically.</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>For most notes, this day note placement is <em>secondary</em> and their
primary location is somewhere else (e.g. for a book review I've been working
on it's <em>Book / Reviews</em>, not the day note). So for this pattern
to work, ability to <a href="#root/_help_IakOLONlIfGI">clone</a> notes into multiple
places is pretty fundamental.</p>
<h3>Projects</h3>
<p><em>Project</em> is pretty self-explanatory, for me specifically it also
means being long term (years) - an example of a project might be Trilium
Notes or university studies. Given their longevity, projects can be large
and deep, but their structure is very domain specific, and I don't see
any common patterns. What's pretty clear is they are often widely interconnected
with other parts of the knowledge base - e.g. university credentials are
cloned from "Credentials / University" top level notes and Trilium related
blog posts are in "Blog / [Name of the blog] / Trilium".</p>
<p><em>Epics</em> are the same thing as projects, but differ in scope - they
are typically several months long and as such are usually placed into a
year note (e.g. <em>2018 / Epics</em>). Epics are often of work nature (also
cloned into work note) and personal (e.g. currently I have large epic for
moving to a different city).</p>
<p>I don't have a term for short term projects (typically several days long),
but continuing the scrum analogy I might call them <em>story</em>. These
are often placed directly into day notes and manually moved from one day
to another (or place into a month note, e.g. <em>2018 / 11 - November</em>).</p>
<h3>Credentials</h3>
<p>I keep all my credentials in the knowledge base, they are sorted into
categories - work related, project related, personal per country etc. These
notes are of course <a href="#root/_help_bwg0e8ewQMak">protected</a> and are often
cloned into other places (e.g. project credentials are cloned into the
project itself). This is a pretty important advantage compared to traditional
tools like KeePass - all the relevant information is centralized into one
place without compromising security.</p>
<h3>People profiles</h3>
<p>This might seem creepy to some, but I keep a profile on most people. It
contains pretty standard things like date of birth, contacts, address,
but also current and previous employments, their hobbies and worldviews
and sometimes even important (IM/mail/meatspace) conversations. Just about
everything I find notable. It helps to refresh some basic info before meeting
people, especially if you haven't been in touch in a while. It gets pretty
awkward to ask for the tenth time where do they work for example, because
you keep forgetting it.</p>
<p>Naturally I have a lot of (extended) family members, friends, acquaintances
etc. so I need some way to sort them. My main method is to sort them by
social circle (work, high school, sports club etc.), sometimes also by
their town of residence. Family <em>circle</em> is still too large so the
further organization is by <em>clan</em> (as in "Smiths"). Some people are
members of several such circles, so they are just cloned into multiple
places.</p>
<p>For family specifically it's pretty useful to create <a href="#root/_help_iRwzGnHPzonm">relation map</a> to
visualize relationships:</p>
<figure class="image">
<img style="aspect-ratio:941/758;" src="Patterns of personal knowl.png"
width="941" height="758">
</figure>
<p><a class="reference-link" href="#root/_help_lQcnSv5DMSe1">[missing note]</a>
</p>
<h3>Books</h3>
<p>Of course, I keep standard "To read" list. I also keep a record on the
books I've read - typically one book has one subtree where the root has
some basic info like author, page count, publication date, date started,
date finished (in the form of&nbsp;<a class="reference-link" href="#root/_help_OFXdgB2nNk1F">Promoted Attributes</a>).
I also write a (private) review and keep list of highlights from Kindle,
optionally with some commentary, these are usually stored in sub notes
(unless they are pretty short).</p>
<p>To keep the list of books manageable, I sort them per year (of reading
them), this also gives me some basic overview of "reading performance"
for given year. I plan to create a <a href="#root/_help_CdNpE2pqjmI6">script</a> which
would show some timeline chart visualizing book attributes <code>dateStarted</code> - <code>dateFinished</code> to
have nicer view of my reading sprints and trends.</p>
<p>Some specific authors also have their own note which contains cloned book
reviews, links to interviews and other related resources.</p>
<p>I have similar system for movies and TV shows, but not as sophisticated.</p>
<h3>Personal diary</h3>
<p>This is a place to reflect on events, experiences, new findings etc. This
can help you get deeper understanding of your inner self, clarify your
thinking and make better decisions as a result.</p>
<p>I sort personal diary notes directly under <em>day note</em> (explained
above), but it can be cloned also to e.g. "trip note" (if the diary note
is about given trip) or to person's profile (if the person plays a role
in the diary note). All my diary notes are <a href="#root/_help_bwg0e8ewQMak">protected</a> since
they are usually pretty sensitive.</p>
<h3>Documents</h3>
<p>I keep all my personal documents (ID, passport, education certificates
...) scanned in the knowledge base. They are <a href="#root/_help_cbkrhQjrkKrh">synchronized</a> across
every PC which provides decent backup and makes them available everywhere.</p>
<p>Advantage compared to e.g. keeping them in Dropbox or Google Drive is
that they are not stored on some 3rd party server and they can be encrypted
(<a href="#root/_help_bwg0e8ewQMak">protected</a>).</p>
<h3>Inventory</h3>
<p>Inventory contains documents and other relevant importation for my important
belongings - e.g. for car you can keep the registration card, maintenance
record, related costs etc. I also keep inventory for some items personally
important to me - mainly computers, phones, cameras and similar electronics.
This can be practical at times but also provides sentimental value.</p>
<h3>Topic knowledge base</h3>
<p>This where I store hard "knowledge" - summarized topics and findings from
different domains. Topics can range from traditional sciences - physics,
history, economy to philosophy, mental models, apps (notes about specific
apps I use) etc. Of course this is very subjective - given what I do, my
Physics sub-tree is pretty sparse compared to my Programming subtree.</p>
<h3>Work knowledge base</h3>
<p>I usually keep top level note for the company I currently work at (past
jobs are moved elsewhere). I track basic organization of the company (divisions,
business units), who is who (<a href="#root/_help_iRwzGnHPzonm">relation maps</a>)
are again useful for visualization), projects I work at etc.</p>
<p>There's a number of credentials to various company services I need to
use. Companies usually have a bunch of complex processes and tools. I record
meeting minutes, link to the company wiki (which is usually difficult to
find relevant info). In general there's a lot of company specific information
I need to know or need have them at hand in a nice structure I can understand.
Often it's just copy pasting and reshuffling of existing information into
something more understandable for me.</p>
<p>From my experience, keeping this makes me more productive and even more
importantly dramatically reduces frustration and stress.</p>
<h2>Conclusion</h2>
<p>I could probably go on with more patterns (e.g. study notes, travelling),
but I think you get the idea. Whatever is important in your life, it probably
makes sense to document and track it.</p>

View File

@ -0,0 +1,20 @@
<h3>Trilium Notes</h3>
<p>Trilium Notes does not collect/send any data from the user's installation,
i.e. no analytics, no telemetry etc. The data flows only between user controlled
/ installed applications, without any intermediary.</p>
<p>Automatic network activity consists of:</p>
<ul>
<li>Trilium periodically queries URL <a href="https://github.com/TriliumNext/Trilium/releases">https://github.com/TriliumNext/Trilium/releases</a> to
see if there's a new stable version released. (check only, there's no automatic
download and/or installation).</li>
<li>Trilium will download spelling dictionaries automatically as needed based
on language settings</li>
</ul>
<h3>Trilium Web Clipper</h3>
<p>Trilium Web Clipper does not collect/send any data from the user's installation,
i.e. no analytics, no telemetry etc. The data flows only between user controlled
/ installed applications, without any intermediary.</p>
<h3>Trilium Sender for Android</h3>
<p>Trilium Sender for Android does not collect/send any data from the user's
installation, i.e. no analytics, no telemetry etc. The data flows only
between user controlled / installed applications, without any intermediary.</p>

View File

@ -8,59 +8,58 @@
the desired amount of columns and rows, as indicated in the adjacent figure.</p>
<h2>Formatting toolbar</h2>
<p>When a table is selected, a special formatting toolbar will appear:</p>
<p>
<img src="10_Tables_image.png" width="384"
<img
src="10_Tables_image.png" width="384"
height="100">
</p>
<h2>Navigating a table</h2>
<ul>
<li data-list-item-id="e7f46134b097590227ab8def4844112be">Using the mouse:
<li>Using the mouse:
<ul>
<li data-list-item-id="e62455762d7530b06d496e0ddb23d2e0f">Click on a cell to focus it.</li>
<li data-list-item-id="e5b8037a928ee05c9137083da09f3c5a4">Click the
<li>Click on a cell to focus it.</li>
<li>Click the
<img src="11_Tables_image.png"
width="28" height="27">button at the top or the bottom of a table to insert an empty paragraph
near it.</li>
<li data-list-item-id="e1d54454a8e1cbe7d5e29d7e262374052">Click the
<li>Click the
<img src="5_Tables_image.png"
width="24" height="26">button at the top-left of the table to select it entirely (for easy copy-pasting
or cutting) or drag and drop it to relocate the table.</li>
</ul>
</li>
<li data-list-item-id="eb3673372bf61d20c70aa4787bbb1db3b">Using the keyboard:
<li>Using the keyboard:
<ul>
<li data-list-item-id="e4eb9ecdc5852d23b7e1b76be1bffe8cf">Use the arrow keys on the keyboard to easily navigate between cells.</li>
<li
data-list-item-id="e010d5a3a937c26f80367271d69687ab6">It's also possible to use <kbd>Tab</kbd> to go to the next cell and Shift+Tab
<li>Use the arrow keys on the keyboard to easily navigate between cells.</li>
<li>It's also possible to use <kbd>Tab</kbd> to go to the next cell and Shift+Tab
to go to the previous cell.</li>
<li data-list-item-id="e5c75e2a259cd2d0aa1252f2452c28fd6">Unlike arrow keys, pressing <kbd>Tab</kbd> at the end of the table (last
<li>Unlike arrow keys, pressing <kbd>Tab</kbd> at the end of the table (last
row, last column) will create a new row automatically.</li>
<li data-list-item-id="e86d89dfc2818e132bc6d7f7f48295dba">To select multiple cells, hold <kbd>Shift</kbd> while using the arrow keys.</li>
<li>To select multiple cells, hold <kbd>Shift</kbd> while using the arrow keys.</li>
</ul>
</li>
</ul>
<h2>Resizing cells</h2>
<ul>
<li data-list-item-id="e327223f3de605b4ab196102167f22219">Columns can be resized by hovering the mouse over the border of two adjacent
<li>Columns can be resized by hovering the mouse over the border of two adjacent
cells and dragging it.</li>
<li data-list-item-id="e2a9150da21e9bd9ab3134c44c016b5cf">By default, the row height is not adjustable using the mouse, but it can
<li>By default, the row height is not adjustable using the mouse, but it can
be configured from the cell settings (see below).</li>
<li data-list-item-id="ee8e8edc219006eec516c1e813494ddb1">To adjust exactly the width (in pixels or percentages) of a cell, select
<li>To adjust exactly the width (in pixels or percentages) of a cell, select
the
<img src="8_Tables_image.png" width="19"
height="19">button.</li>
</ul>
<h2>Inserting new rows and new columns</h2>
<ul>
<li data-list-item-id="ebf4db28ad263fbce13bf056e90512914">To insert a new column, click on a desired location, then press the
<li>To insert a new column, click on a desired location, then press the
<img
src="Tables_image.png" width="18" height="20">button from the formatting toolbar and select <em>Insert column left or right.</em>
</li>
<li data-list-item-id="eb53e629e394d8a14c48dd39a61397271">To insert a new row, click on a desired location, then press the
<li>To insert a new row, click on a desired location, then press the
<img src="7_Tables_image.png"
width="20" height="18">button and select <em>Insert row above</em> or <em>below</em>.
<ul>
<li data-list-item-id="e3ba47144529996c9e4455970508a0a01">A quicker alternative to creating a new row while at the end of the table
<li>A quicker alternative to creating a new row while at the end of the table
is to press the <kbd>Tab</kbd> key.</li>
</ul>
</li>
@ -72,9 +71,9 @@
width="19" height="19">button from the formatting toolbar.</p>
<p>More options are available by pressing the arrow next to it:</p>
<ul>
<li data-list-item-id="e57e54996911ec8dbe17deeb300af481d">Click on a single cell and select Merge cell up/down/right/left to merge
<li>Click on a single cell and select Merge cell up/down/right/left to merge
with an adjacent cell.</li>
<li data-list-item-id="e4510ddae1afe524dab9bb5fa5c9edd88">Select <em>Split cell vertically</em> or <em>horizontally</em>, to split
<li>Select <em>Split cell vertically</em> or <em>horizontally</em>, to split
a cell into multiple cells (can also be used to undo a merge).</li>
</ul>
<h2>Table properties</h2>
@ -86,16 +85,15 @@
<img src="13_Tables_image.png"
width="19" height="19">button and allows for the following adjustments:</p>
<ul>
<li data-list-item-id="e421d2c037e3e17684b6c875f1d119515">Border (not the border of the cells, but the outer rim of the table),
<li>Border (not the border of the cells, but the outer rim of the table),
which includes the style (single, double), color and width.</li>
<li data-list-item-id="e2e29338b33b5aa3e5b63a914ae412d7d">The background color, with none set by default.</li>
<li data-list-item-id="ee585d003b2f922bbab05dd190070b3e7">The width and height of the table in percentage (must end with <code>%</code>)
<li>The background color, with none set by default.</li>
<li>The width and height of the table in percentage (must end with <code>%</code>)
or pixels (must end with <code>px</code>).</li>
<li data-list-item-id="e23ac3152d03898b653db8d3849f0f5cc">The alignment of the table.
<li>The alignment of the table.
<ul>
<li data-list-item-id="ed90eb8b2432a87fa1fd39fd26e9f2cda">Left or right-aligned, case in which the text will flow next to it.</li>
<li
data-list-item-id="e887b5ce3dc7e47f5e630fbdf0da29862">Centered, case in which text will avoid the table, regardless of the table
<li>Left or right-aligned, case in which the text will flow next to it.</li>
<li>Centered, case in which text will avoid the table, regardless of the table
width.</li>
</ul>
</li>
@ -113,14 +111,13 @@
on the user's selection).</p>
<p>The following options can be adjusted:</p>
<ul>
<li data-list-item-id="e9e0801ebcbbb763dc569814c922cde20">The border style, color and width (same as table properties), but applying
<li>The border style, color and width (same as table properties), but applying
to the current cell only.</li>
<li data-list-item-id="ec3f1f0bbae91f118bfc86c5bace6edc9">The background color, with none set by default.</li>
<li data-list-item-id="e93abf34e4f6f6a4732cd8a63577567f4">The width and height of the cell in percentage (must end with <code>%</code>)
<li>The background color, with none set by default.</li>
<li>The width and height of the cell in percentage (must end with <code>%</code>)
or pixels (must end with <code>px</code>).</li>
<li data-list-item-id="ed65a0f2554a5130beeb7d478710f7bfe">The padding (the distance of the text compared to the cell's borders).</li>
<li
data-list-item-id="e76d8603c089d10e807576cb2e535a388">The alignment of the text, both horizontally (left, centered, right, justified)
<li>The padding (the distance of the text compared to the cell's borders).</li>
<li>The alignment of the text, both horizontally (left, centered, right, justified)
and vertically (top, middle or bottom).</li>
</ul>
<p>The cell will immediately update to reflect the changes, but the <em>Save</em> button
@ -134,30 +131,30 @@
<p>By default, tables will come with a predefined gray border.</p>
<p>To adjust the borders, follow these steps:</p>
<ol>
<li data-list-item-id="e04c95cbf1d8480c634f7ba6310d5c66e">Select the table.</li>
<li data-list-item-id="e61b666fe10bca473400bd66f8fd11f36">In the floating panel, select the <em>Table properties</em> option (
<li>Select the table.</li>
<li>In the floating panel, select the <em>Table properties</em> option (
<img
src="14_Tables_image.png" width="21" height="21">).
src="14_Tables_image.png" width="21"
height="21">).
<ol>
<li data-list-item-id="e2ab1b3f540def81d55ec91fe8a313fb3">Look for the <em>Border</em> section at the top of the newly opened panel.</li>
<li
data-list-item-id="eef63fe5e16f8103d07a308b4b9147fbf">This will control the outer borders of the table.</li>
<li data-list-item-id="eca1a3d01633d7d2d32c854bb39e66a53">Select a style for the border. Generally <em>Single</em> is the desirable
<li>Look for the <em>Border</em> section at the top of the newly opened panel.</li>
<li>This will control the outer borders of the table.</li>
<li>Select a style for the border. Generally <em>Single</em> is the desirable
option.</li>
<li data-list-item-id="e7edbe51137f6a7d16d2ca9d7b3f553a2">Select a color for the border.</li>
<li data-list-item-id="e3ad74eae4fddb2fb4c60a1c1efc46950">Select a width for the border, expressed in pixels.&nbsp;</li>
<li>Select a color for the border.</li>
<li>Select a width for the border, expressed in pixels.</li>
</ol>
</li>
<li data-list-item-id="ed56e2883a25aa417c7f4bfddd7a07df6">Select all the cells of the table and then press the <em>Cell properties </em>option
<li>Select all the cells of the table and then press the <em>Cell properties</em> option
(
<img src="9_Tables_image.png" width="21" height="21">).
<img src="9_Tables_image.png" width="21"
height="21">).
<ol>
<li data-list-item-id="e93dc8de15098fd2c0c5674a24205b712">This will control the inner borders of the table, at cell level.</li>
<li
data-list-item-id="ee4f0deb1a42efa29e3b5147f79e92d3b">Note that it's possible to change the borders individually by selecting
<li>This will control the inner borders of the table, at cell level.</li>
<li>Note that it's possible to change the borders individually by selecting
one or more cells, case in which it will only change the borders that intersect
these cells.</li>
<li data-list-item-id="e3af86e5d6096d8afd7413012a9ecb6c6">Repeat the same steps as from step (2).</li>
<li>Repeat the same steps as from step (2).</li>
</ol>
</li>
</ol>
@ -166,19 +163,18 @@
layouts (columns, grids) of text or <a href="#root/_help_mT0HEkOsz6i1">images</a> without
the distraction of their border:</p>
<ol>
<li data-list-item-id="e078bac0af18c7fe8f4ac2272a312e49d">First insert a table with the desired number of columns and rows.</li>
<li
data-list-item-id="ee25683e809fd85e65db655dea9efece5">Select the entire table.</li>
<li data-list-item-id="e66342ca801e71a9aba89fc217fcc66a5">In <em>Table properties</em>, set:
<li>First insert a table with the desired number of columns and rows.</li>
<li>Select the entire table.</li>
<li>In <em>Table properties</em>, set:
<ol>
<li data-list-item-id="edef2e2e5a6a8ac73e36101f4429863d8"><em>Style</em> to <em>Single</em>
<li><em>Style</em> to <em>Single</em>
</li>
<li data-list-item-id="e6aaccfd6440d2999079364982c0b33fc"><em>Color</em> to <code>transparent</code>
<li><em>Color</em> to <code>transparent</code>
</li>
<li data-list-item-id="e13494edb598fd972373a368e79540ea1">Width to <code>1px</code>.</li>
<li>Width to <code>1px</code>.</li>
</ol>
</li>
<li data-list-item-id="e15221332e526341aefb8b87e715c0e32">In Cell Properties, set the same as on the previous step.</li>
<li>In Cell Properties, set the same as on the previous step.</li>
</ol>
<h2>Markdown import/export</h2>
<p>Simple tables are exported in GitHub-flavored Markdown format (e.g. a

View File

@ -2,9 +2,9 @@
an API that gives them access to various features of the application.</p>
<p>There are two APIs:</p>
<ul>
<li data-list-item-id="e85c7106495c24ab4dd38c430b0af87df">One for the front-end scripts:&nbsp;<a class="reference-link" href="#root/_help_Q2z6av6JZVWm">Frontend API</a>
<li>One for the front-end scripts:&nbsp;<a class="reference-link" href="#root/_help_Q2z6av6JZVWm">Frontend API</a>
</li>
<li data-list-item-id="e4f976e19004a21620ed1c6b58f9d1eb3">One for the back-end scripts:&nbsp;<a class="reference-link" href="#root/_help_MEtfsqa5VwNi">Backend API</a>
<li>One for the back-end scripts:&nbsp;<a class="reference-link" href="#root/_help_MEtfsqa5VwNi">Backend API</a>
</li>
</ul>
<p>In both cases, the API resides in a global variable, <code>api</code>,

View File

@ -4,6 +4,7 @@ import type { Application } from "express";
import dayjs from "dayjs";
import { type SQLiteSessionStore } from "./session_parser.js";
import { SessionData } from "express-session";
import cls from "../services/cls.js";
let app: Application;
let sessionStore: SQLiteSessionStore;
@ -106,7 +107,7 @@ describe("Login Route test", () => {
expect(expiry).toBeTruthy();
vi.setSystemTime(expiry!);
vi.advanceTimersByTime(CLEAN_UP_INTERVAL);
cls.init(() => vi.advanceTimersByTime(CLEAN_UP_INTERVAL));
({ session } = await getSessionFromCookie(setCookieHeader));
expect(session).toBeFalsy();
});

View File

@ -41,6 +41,14 @@ function getDefaultKeyboardActions() {
scope: "window",
ignoreFromCommandPalette: true
},
{
actionName: "openTodayNote",
friendlyName: t("hidden-subtree.open-today-journal-note-title"),
iconClass: "bx bx-calendar",
defaultShortcuts: [],
description: t("hidden-subtree.open-today-journal-note-title"),
scope: "window"
},
{
actionName: "commandPalette",
friendlyName: t("keyboard_action_names.command-palette"),

View File

@ -14,11 +14,11 @@
"preact": "10.27.2",
"preact-iso": "2.11.0",
"preact-render-to-string": "6.6.3",
"react-i18next": "16.2.1"
"react-i18next": "16.2.3"
},
"devDependencies": {
"@preact/preset-vite": "2.10.2",
"eslint": "9.38.0",
"eslint": "9.39.0",
"eslint-config-preact": "2.0.0",
"typescript": "5.9.3",
"user-agent-data-types": "0.4.2",

View File

@ -14,6 +14,9 @@
"screenshot_alt": "Captura de ecrã da aplicação Trilium Notes para computador"
},
"organization_benefits": {
"title": "Organização"
"title": "Organização",
"note_structure_description": "As notas podem ser organizadas de forma hierárquica. Não há necessidade de pastas, pois cada nota pode conter sub notas. Uma única nota pode ser adicionada em vários locais da hierarquia.",
"attributes_description": "Utiliza relações entre notas ou adiciona etiquetas para uma categorização fácil. Usa atributos promovidos para inserir informação estruturada, que pode ser utilizada em tabelas ou quadros.",
"hoisting_description": "Separa facilmente as tuas notas pessoais e de trabalho agrupando-as num espaço de trabalho, que focaliza a árvore de notas para mostrar apenas um conjunto específico de notas."
}
}

2
docs/README-pt.md vendored
View File

@ -54,7 +54,7 @@ A nossa documentação está disponível em múltiplos formatos:
- **GitHub**: Navigate through the [User
Guide](./docs/User%20Guide/User%20Guide/) in this repository
### Quick Links
### Links rápidos
- [Getting Started Guide](https://docs.triliumnotes.org/)
- [Installation
Instructions](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation.md)

View File

@ -935,6 +935,73 @@
"dataFileName": "v0.90.0-beta.md",
"attachments": []
},
{
"isClone": false,
"noteId": "kzjHexDTTeVB",
"notePath": [
"hD3V4hiu2VW4",
"kzjHexDTTeVB"
],
"title": "v0.48",
"notePosition": 420,
"prefix": null,
"isExpanded": false,
"type": "text",
"mime": "text/html",
"attributes": [
{
"type": "relation",
"name": "template",
"value": "wyurrlcDl416",
"isInheritable": false,
"position": 60
}
],
"format": "markdown",
"dataFileName": "v0.48.md",
"attachments": [
{
"attachmentId": "645H74UA4xwf",
"title": "note-map.png",
"role": "image",
"mime": "image/jpg",
"position": 10,
"dataFileName": "v0.48_note-map.png"
},
{
"attachmentId": "c74WFpjTo0p4",
"title": "screenshot.png",
"role": "image",
"mime": "image/jpg",
"position": 10,
"dataFileName": "v0.48_screenshot.png"
},
{
"attachmentId": "szlnTmTJL4HL",
"title": "split.png",
"role": "image",
"mime": "image/jpg",
"position": 10,
"dataFileName": "v0.48_split.png"
},
{
"attachmentId": "VQxrtpQTYmI6",
"title": "bookmarks.png",
"role": "image",
"mime": "image/jpg",
"position": 10,
"dataFileName": "v0.48_bookmarks.png"
},
{
"attachmentId": "ZRyEqxAv1MTd",
"title": "mermaid.png",
"role": "image",
"mime": "image/png",
"position": 10,
"dataFileName": "v0.48_mermaid.png"
}
]
},
{
"isClone": false,
"noteId": "wyurrlcDl416",
@ -943,7 +1010,7 @@
"wyurrlcDl416"
],
"title": "Release Template",
"notePosition": 420,
"notePosition": 430,
"prefix": null,
"isExpanded": false,
"type": "text",

View File

@ -0,0 +1,121 @@
# v0.48
0.48 is a big release and contains many changes, some of them breaking:
## Major frontend redesign
<img src="v0.48_screenshot.png" alt="" width="1047" height="772">
* right panel is no more, most of these widgets have been moved to the new ribbon-style widget under note title
* right panel is still possible to activate for scripts
* Trilium has a new icon (there might be further color changes)
## Vertical split window
<figure class="image"><img style="aspect-ratio:1047/779;" src="v0.48_split.png" alt="" width="1047" height="779"></figure>
## Link map re-implemented
Now supports also hierarchical view of the notes:
<figure class="image"><img style="aspect-ratio:1082/786;" src="v0.48_note-map.png" alt="" width="1082" height="786"></figure>
## Mermaid diagrams
Thanks to [@abitofevrything](https://github.com/abitofevrything) for this contribution!
<figure class="image"><img style="aspect-ratio:1052/779;" src="v0.48_mermaid.png" alt="" width="1052" height="779"></figure>
## Basic bookmark support
<figure class="image"><img style="aspect-ratio:1200/815;" src="v0.48_bookmarks.png" alt="" width="1200" height="815"></figure>
## Other changes
* persistence/entity layer in backend was largely refactored - "repository" and unified with note cache which should bring performance improvements for many operations
* search and SQL query notes now don't create “saved” notes by default
* added underline heading style and make it a default
* updated CKEditor to 30.0.0
## Migration
### Backup restore
Trilium v0.48 is currently in beta and may contain serious bugs.
Before migration to 0.48 Trilium will make automatically backup into `~/trilium-data/backup/backup-before-migration.db`. In case of problems you can restore this backup with this guide: [https://github.com/zadam/trilium/wiki/Backup#restoring-backup](https://github.com/zadam/trilium/wiki/Backup#restoring-backup)
### Direct upgrade only from 0.47.X
Direct upgrade to 0.48 is possible only from 0.47.X. If you want to upgrade from an older version, you need to upgrade to 0.47.X first and only then to 0.48. This is caused by extensive backend refactoring which broke older migration scripts.
### All backend script notes should avoid being async
Backend operations were in older versions used async/await because of the SQLite driver. But Trilium recently migrated to the synchronous (and much faster) `better-sqlite3`. As a consequence backend script notes which are wrapped in a transaction should to be converted to the sync variant.
e.g. old script looked like this:
```
const todayDateStr = api.formatDateISO(new Date());
const todayNote = await api.runOnBackend(async todayDateStr => {
const dateNote = await api.getDayNote(todayDateStr);
({note: logNote} = await api.createNote(dateNote.noteId, 'log'));
}, [todayDateStr]);
api.activateNote(todayNote.noteId);
```
all the `await` (and `async`) should disappear from the backend code, but should remain when calling backend from frontend (that's still async):
```
const todayDateStr = api.formatDateISO(new Date());
const todayNote = await api.runOnBackend(todayDateStr => {
const dateNote = api.getDayNote(todayDateStr);
({note: logNote} = api.createNote(dateNote.noteId, 'log'));
}, [todayDateStr]);
api.activateNote(todayNote.noteId);
```
### Migrate custom themes
With the redesign you might need to adjust your custom themes - check the modified list of available CSS variables in the [default theme](https://github.com/zadam/trilium/blob/master/src/public/stylesheets/theme-light.css). If your theme also uses CSS selectors then that will probably have to be rewritten as well.
Themes are annotated with `#appTheme` label, previously this label could but did not have to contain value - with this release the value is required so define the label as e.g. `#appTheme=my-theme-name`.
Additionally, CSS themes are now loaded differently than before - previously all themes were loaded at the startup and which one was active was decided by the active CSS class. Themes were then prefixed like this:
```
body.theme-steel-blue {
--main-font-family: 'Raleway' !important;
--main-font-size: normal;
--tree-font-family: inherit;
--tree-font-size: normal;
...
}
body.theme-steel-blue .note-detail-editable-text, body.theme-steel-blue .note-detail-readonly-text {
font-size: 120%;
}
```
This prefixing is not needed anymore (and also doesn't work anymore). Remove the prefixes like this:
```
:root {
--main-font-family: 'Raleway';
--main-font-size: normal;
--tree-font-family: 'Raleway';
--tree-font-size: normal;
...
}
body .note-detail-editable-text, body .note-detail-readonly-text {
font-size: 120%;
}
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

View File

@ -15107,6 +15107,167 @@
]
}
]
},
{
"isClone": false,
"noteId": "Fm0j45KqyHpU",
"notePath": [
"pOsGYCXsbNQG",
"Fm0j45KqyHpU"
],
"title": "Miscellaneous",
"notePosition": 370,
"prefix": null,
"isExpanded": false,
"type": "text",
"mime": "text/html",
"attributes": [
{
"type": "label",
"name": "shareAlias",
"value": "misc",
"isInheritable": false,
"position": 30
},
{
"type": "label",
"name": "iconClass",
"value": "bx bx-info-circle",
"isInheritable": false,
"position": 40
}
],
"format": "markdown",
"attachments": [],
"dirFileName": "Miscellaneous",
"children": [
{
"isClone": false,
"noteId": "WFbFXrgnDyyU",
"notePath": [
"pOsGYCXsbNQG",
"Fm0j45KqyHpU",
"WFbFXrgnDyyU"
],
"title": "Privacy Policy",
"notePosition": 10,
"prefix": null,
"isExpanded": false,
"type": "text",
"mime": "text/html",
"attributes": [
{
"type": "label",
"name": "shareAlias",
"value": "privacy-policy",
"isInheritable": false,
"position": 30
}
],
"format": "markdown",
"dataFileName": "Privacy Policy.md",
"attachments": []
},
{
"isClone": false,
"noteId": "NcsmUYZRWEW4",
"notePath": [
"pOsGYCXsbNQG",
"Fm0j45KqyHpU",
"NcsmUYZRWEW4"
],
"title": "Patterns of personal knowledge",
"notePosition": 20,
"prefix": null,
"isExpanded": false,
"type": "text",
"mime": "text/html",
"attributes": [
{
"type": "relation",
"name": "internalLink",
"value": "xYjQUYhpbUEW",
"isInheritable": false,
"position": 10
},
{
"type": "relation",
"name": "internalLink",
"value": "IakOLONlIfGI",
"isInheritable": false,
"position": 20
},
{
"type": "relation",
"name": "internalLink",
"value": "R7abl2fc6Mxi",
"isInheritable": false,
"position": 30
},
{
"type": "relation",
"name": "internalLink",
"value": "bwg0e8ewQMak",
"isInheritable": false,
"position": 40
},
{
"type": "relation",
"name": "internalLink",
"value": "OFXdgB2nNk1F",
"isInheritable": false,
"position": 50
},
{
"type": "relation",
"name": "internalLink",
"value": "cbkrhQjrkKrh",
"isInheritable": false,
"position": 60
},
{
"type": "relation",
"name": "internalLink",
"value": "CdNpE2pqjmI6",
"isInheritable": false,
"position": 70
},
{
"type": "relation",
"name": "internalLink",
"value": "6f9hih2hXXZk",
"isInheritable": false,
"position": 80
},
{
"type": "relation",
"name": "internalLink",
"value": "iRwzGnHPzonm",
"isInheritable": false,
"position": 90
},
{
"type": "label",
"name": "shareAlias",
"value": "patterns-of-personal-knowledge",
"isInheritable": false,
"position": 120
}
],
"format": "markdown",
"dataFileName": "Patterns of personal knowledge.md",
"attachments": [
{
"attachmentId": "amErpd38VEdQ",
"title": "relation-map-family.png",
"role": "image",
"mime": "image/png",
"position": 10,
"dataFileName": "Patterns of personal knowl.png"
}
]
}
]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

View File

@ -0,0 +1,157 @@
# Patterns of personal knowledge
> [!NOTE]
> This article is a description of the original author of Trilium (zadam) in regards with his own knowledge base.
This page contains description of some of the patterns I use to organize information in my knowledge base. This is meant to give some inspiration of how one might create and structure their knowledge base in general and also specifically in Trilium Notes. It also gives some background and justification for some of the design decisions.
## Meta patterns
Just to be clear, meta patterns are "patterns of patterns", i.e. patterns appearing in other patterns.
### Hierarchical organization of information
Basic meta pattern is that I sort notes (units of information) into a hierarchy - I have some "top level" notes which represent coarse grained organization, these then split into sub-notes defining finer grained organization and so on. I consider this hierarchical (tree) organization very efficient for organization of large amounts of information. A lot of note taking software (such as Evernote) are frustratingly limited in this regard which limits scalability of the software to large amounts of notes.
#### Scalability
It's important to frame the following (meta) patterns with some idea of how large amount of data are we talking about.
My rule of thumb for estimation of size of personal knowledge base is that you can reasonably produce around 10 notes a day, which is 3650 in a year. I plan to use my knowledge base long term (with or without Trilium Notes), probably decades so you can easily get to number 100 000 or even more. Right now, my personal knowledge base has around 10 000 notes.
100 000 is a number to which most note taking software doesn't scale well (in both performance and UI). Yet I don't think it's really very much considering a lifetime of knowledge.
#### Lazy hierarchy
My approach to creating the hierarchy is being lazy - I don't create the structure first and then fill it with notes, instead I create single note for some specific topic and start using this one note. Once the content starts to grow, and I see how _some_ parts could be split out, I move them out into separate sub notes. As an example I have a book review for _The Fellowship of the Ring_:
* Book reviews
* The Fellowship of the Ring
The note contains basic book info (author, publisher etc.), book highlights with the comments and then overall review. Now it turns out there's far too many book highlights and overall review is also rather long, so I want to change the structure to the following:
* Book reviews
* The Fellowship of the Ring       _(still contains basic info)_
* Highlights
* Review
If I used standard text file stored in a filesystem I would soon run into an annoying problem that in order to split out the Highlights and Review into sub-notes I would also have to convert _The Fellowship of the Ring_ from text file into directory and split out all sections of the note into sub-notes. Instead, Trilium treats all notes as equal - both leaf notes and inner notes can have both text content which allows me to sub-structure only content which needs it.
### Sorting notes into multiple places in the hierarchy
While organizing the notes into the hierarchy, you very quickly run into a dilemma - your note seem to belong to two places in the hierarchy equally. As an example - you want to make a note about [bash](https://en.wikipedia.org/wiki/Bash_\(Unix_shell\)) - does it belong to "OS / Linux" or "Programming / Scripting languages"? This is actually a false dichotomy forced down by the limits of the basic tree hierarchy - the answer is _of course it belongs to both_. This is the reason why Trilium doesn't use standard tree structure (which requires every note to have exactly one parent), but an extension which allows every note to have several parents, thus effectively allowing it to appear in multiple places in the hierarchy. For lack of better term I call this "cloning". The main problem with this term is that it suggests that each clone must have an original, but here all clones are completely equal - effectively there's no original.
In tech lingo, it might be better to describe it as a [hard link](https://en.wikipedia.org/wiki/Hard_link) with an important difference that it is possible to hard link (clone) a directory (inner note).
### Protected notes
I have Trilium Notes opened non-stop. Sometimes I forget to lock my computer when going to the bathroom. Sometimes I let a friend or family member to use my computer for a minute without supervision. They might click on (running) Trilium and inadvertently see a note I really don't want anybody to see (personal diary, credentials). To cover this, Trilium has a concept of "[protected notes](https://github.com/zadam/trilium/wiki/Protected-notes)" - protected note is encrypted and on top of that requires the user to enter the password every 5 minutes which guarantees that such note can be in a readable state only for small amount of time. Working with ordinary (not protected) notes don't require password so you're not bothered by extra security when it's not needed.
### Archiving notes
Notes can lose relevancy with time - let's say I switch jobs - all the notes specific to the former employer immediately lose most of its import. This doesn't mean I want to delete these notes though - typically I just want them to somehow deprioritize - in Trilium I would do that by assigning an [inherited](https://github.com/zadam/trilium/wiki/Attribute-inheritance) [label](https://github.com/zadam/trilium/wiki/Attributes) `archived` to the company root note. The main effect of this label is that all the notes from this sub-tree are filtered out from search results (fast search via note autocomplete is my main [navigation approach](https://github.com/zadam/trilium/wiki/Note-navigation)). Apart from this, I also typically move such outdated notes to some less prominent place in the hierarchy.
I use archivation also for notes which are not very relevant from their creation - an example might be automatically imported reddit comments.
Sometimes there's no clear _category_ split between relevant and non-relevant notes, in that case I just create "_OLD_" note with `archived` label and move all irrelevant notes there. So my credentials note might look something like this:
* Credentials
* Personal
* OLD       _(contains a bunch of notes with credentials for services I don't use anymore)_
* Gmail
* Github
* ...
## Patterns
### Day note
Every day has its note which contains or references everything related to the given day. Structure looks like this:
* 2018
* 11 - November
* 26 - Monday
* 27 - Tuesday
* subnote 1
Day note serves as a workspace and note inbox at the same time - it's the default location to create a note when I don't have time to think about proper placement. At the end of the day I typically review my day note and clone the notes into suitable locations in the hierarchy.
Trilium has this pattern partly built-in - Trilium understands and can create this Year / Month / Day structure semi-automatically (on API call). There's also global keyboard shortcut `CTRL-ALT-P` which will create new note in the day note.
What notes do I keep under this day note?
* TODO list for given day (this can be automated - see <a class="reference-link" href="../Advanced%20Usage/Advanced%20Showcases/Task%20Manager.md">Task Manager</a>)
* Personal diary
* [clones](../Basic%20Concepts%20and%20Features/Notes/Cloning%20Notes.md) of notes I created during this day (which kind of represents what I've been working on).
* I often clone notes (or sub-trees) of e.g. projects I'm working on at given day so they are at hand
* I have some [scripts](../Scripting.md) which allow me to track certain daily metrics (like weight). These are saved into one daily "data note" (actually JSON [code note](../Note%20Types/Code.md)).
* I have other scripts which then help me to visualize these data (see a <a class="reference-link" href="../Advanced%20Usage/Advanced%20Showcases/Weight%20Tracker.md">Weight Tracker</a> example)
* I have a script which automatically imports all my comments from reddit into the day note.
* People are sometimes wondering why. The answer is that I usually put some effort and thought into a comment and that's why I feel it's worth preserving, especially if it can be done automatically.
For most notes, this day note placement is _secondary_ and their primary location is somewhere else (e.g. for a book review I've been working on it's _Book / Reviews_, not the day note). So for this pattern to work, ability to [clone](../Basic%20Concepts%20and%20Features/Notes/Cloning%20Notes.md) notes into multiple places is pretty fundamental.
### Projects
_Project_ is pretty self-explanatory, for me specifically it also means being long term (years) - an example of a project might be Trilium Notes or university studies. Given their longevity, projects can be large and deep, but their structure is very domain specific, and I don't see any common patterns. What's pretty clear is they are often widely interconnected with other parts of the knowledge base - e.g. university credentials are cloned from "Credentials / University" top level notes and Trilium related blog posts are in "Blog / \[Name of the blog\] / Trilium".
_Epics_ are the same thing as projects, but differ in scope - they are typically several months long and as such are usually placed into a year note (e.g. _2018 / Epics_). Epics are often of work nature (also cloned into work note) and personal (e.g. currently I have large epic for moving to a different city).
I don't have a term for short term projects (typically several days long), but continuing the scrum analogy I might call them _story_. These are often placed directly into day notes and manually moved from one day to another (or place into a month note, e.g. _2018 / 11 - November_).
### Credentials
I keep all my credentials in the knowledge base, they are sorted into categories - work related, project related, personal per country etc. These notes are of course [protected](../Basic%20Concepts%20and%20Features/Notes/Protected%20Notes.md) and are often cloned into other places (e.g. project credentials are cloned into the project itself). This is a pretty important advantage compared to traditional tools like KeePass - all the relevant information is centralized into one place without compromising security.
### People profiles
This might seem creepy to some, but I keep a profile on most people. It contains pretty standard things like date of birth, contacts, address, but also current and previous employments, their hobbies and worldviews and sometimes even important (IM/mail/meatspace) conversations. Just about everything I find notable. It helps to refresh some basic info before meeting people, especially if you haven't been in touch in a while. It gets pretty awkward to ask for the tenth time where do they work for example, because you keep forgetting it.
Naturally I have a lot of (extended) family members, friends, acquaintances etc. so I need some way to sort them. My main method is to sort them by social circle (work, high school, sports club etc.), sometimes also by their town of residence. Family _circle_ is still too large so the further organization is by _clan_ (as in "Smiths"). Some people are members of several such circles, so they are just cloned into multiple places.
For family specifically it's pretty useful to create [relation map](../Note%20Types/Relation%20Map.md) to visualize relationships:
<figure class="image"><img style="aspect-ratio:941/758;" src="Patterns of personal knowl.png" width="941" height="758"></figure>
<a class="reference-link" href="#root/lQcnSv5DMSe1">[missing note]</a>
### Books
Of course, I keep standard "To read" list. I also keep a record on the books I've read - typically one book has one subtree where the root has some basic info like author, page count, publication date, date started, date finished (in the form of <a class="reference-link" href="../Advanced%20Usage/Attributes/Promoted%20Attributes.md">Promoted Attributes</a>). I also write a (private) review and keep list of highlights from Kindle, optionally with some commentary, these are usually stored in sub notes (unless they are pretty short).
To keep the list of books manageable, I sort them per year (of reading them), this also gives me some basic overview of "reading performance" for given year. I plan to create a [script](../Scripting.md) which would show some timeline chart visualizing book attributes `dateStarted` - `dateFinished` to have nicer view of my reading sprints and trends.
Some specific authors also have their own note which contains cloned book reviews, links to interviews and other related resources.
I have similar system for movies and TV shows, but not as sophisticated.
### Personal diary
This is a place to reflect on events, experiences, new findings etc. This can help you get deeper understanding of your inner self, clarify your thinking and make better decisions as a result.
I sort personal diary notes directly under _day note_ (explained above), but it can be cloned also to e.g. "trip note" (if the diary note is about given trip) or to person's profile (if the person plays a role in the diary note). All my diary notes are [protected](../Basic%20Concepts%20and%20Features/Notes/Protected%20Notes.md) since they are usually pretty sensitive.
### Documents
I keep all my personal documents (ID, passport, education certificates ...) scanned in the knowledge base. They are [synchronized](../Installation%20%26%20Setup/Synchronization.md) across every PC which provides decent backup and makes them available everywhere.
Advantage compared to e.g. keeping them in Dropbox or Google Drive is that they are not stored on some 3rd party server and they can be encrypted ([protected](../Basic%20Concepts%20and%20Features/Notes/Protected%20Notes.md)).
### Inventory
Inventory contains documents and other relevant importation for my important belongings - e.g. for car you can keep the registration card, maintenance record, related costs etc. I also keep inventory for some items personally important to me - mainly computers, phones, cameras and similar electronics. This can be practical at times but also provides sentimental value.
### Topic knowledge base
This where I store hard "knowledge" - summarized topics and findings from different domains. Topics can range from traditional sciences - physics, history, economy to philosophy, mental models, apps (notes about specific apps I use) etc. Of course this is very subjective - given what I do, my Physics sub-tree is pretty sparse compared to my Programming subtree.
### Work knowledge base
I usually keep top level note for the company I currently work at (past jobs are moved elsewhere). I track basic organization of the company (divisions, business units), who is who ([relation maps](../Note%20Types/Relation%20Map.md)) are again useful for visualization), projects I work at etc.
There's a number of credentials to various company services I need to use. Companies usually have a bunch of complex processes and tools. I record meeting minutes, link to the company wiki (which is usually difficult to find relevant info). In general there's a lot of company specific information I need to know or need have them at hand in a nice structure I can understand. Often it's just copy pasting and reshuffling of existing information into something more understandable for me.
From my experience, keeping this makes me more productive and even more importantly dramatically reduces frustration and stress.
## Conclusion
I could probably go on with more patterns (e.g. study notes, travelling), but I think you get the idea. Whatever is important in your life, it probably makes sense to document and track it.

View File

@ -0,0 +1,17 @@
# Privacy Policy
### Trilium Notes
Trilium Notes does not collect/send any data from the user's installation, i.e. no analytics, no telemetry etc. The data flows only between user controlled / installed applications, without any intermediary.
Automatic network activity consists of:
* Trilium periodically queries URL [https://github.com/TriliumNext/Trilium/releases](https://github.com/TriliumNext/Trilium/releases) to see if there's a new stable version released. (check only, there's no automatic download and/or installation).
* Trilium will download spelling dictionaries automatically as needed based on language settings
### Trilium Web Clipper
Trilium Web Clipper does not collect/send any data from the user's installation, i.e. no analytics, no telemetry etc. The data flows only between user controlled / installed applications, without any intermediary.
### Trilium Sender for Android
Trilium Sender for Android does not collect/send any data from the user's installation, i.e. no analytics, no telemetry etc. The data flows only between user controlled / installed applications, without any intermediary.

View File

@ -42,16 +42,16 @@
"@playwright/test": "1.56.1",
"@triliumnext/server": "workspace:*",
"@types/express": "5.0.5",
"@types/node": "24.9.1",
"@types/node": "24.9.2",
"@vitest/coverage-v8": "3.2.4",
"@vitest/ui": "3.2.4",
"chalk": "5.6.2",
"cross-env": "10.1.0",
"dpdm": "3.14.0",
"esbuild": "0.25.11",
"eslint": "9.38.0",
"esbuild": "0.25.12",
"eslint": "9.39.0",
"eslint-config-prettier": "10.1.8",
"eslint-plugin-playwright": "2.2.2",
"eslint-plugin-playwright": "2.3.0",
"eslint-plugin-react-hooks": "7.0.1",
"happy-dom": "~20.0.0",
"jiti": "2.6.1",
@ -81,7 +81,7 @@
"url": "https://github.com/TriliumNext/Trilium/issues"
},
"homepage": "https://triliumnotes.org",
"packageManager": "pnpm@10.19.0",
"packageManager": "pnpm@10.20.0",
"pnpm": {
"patchedDependencies": {
"@ckeditor/ckeditor5-mention": "patches/@ckeditor__ckeditor5-mention.patch",
@ -104,7 +104,7 @@
"on-headers@<1.1.0": ">=1.1.0",
"form-data@>=4.0.0 <4.0.4": ">=4.0.4",
"form-data@>=3.0.0 <3.0.4": ">=3.0.4",
"node-abi": "4.15.0"
"node-abi": "4.17.0"
},
"ignoredBuiltDependencies": [
"sqlite3"

View File

@ -29,7 +29,7 @@
"@vitest/browser": "3.2.4",
"@vitest/coverage-istanbul": "3.2.4",
"ckeditor5": "47.1.0",
"eslint": "9.38.0",
"eslint": "9.39.0",
"eslint-config-ckeditor5": ">=9.1.0",
"http-server": "14.1.1",
"lint-staged": "16.2.6",

View File

@ -30,7 +30,7 @@
"@vitest/browser": "3.2.4",
"@vitest/coverage-istanbul": "3.2.4",
"ckeditor5": "47.1.0",
"eslint": "9.38.0",
"eslint": "9.39.0",
"eslint-config-ckeditor5": ">=9.1.0",
"http-server": "14.1.1",
"lint-staged": "16.2.6",

View File

@ -32,7 +32,7 @@
"@vitest/browser": "3.2.4",
"@vitest/coverage-istanbul": "3.2.4",
"ckeditor5": "47.1.0",
"eslint": "9.38.0",
"eslint": "9.39.0",
"eslint-config-ckeditor5": ">=9.1.0",
"http-server": "14.1.1",
"lint-staged": "16.2.6",

View File

@ -33,7 +33,7 @@
"@vitest/browser": "3.2.4",
"@vitest/coverage-istanbul": "3.2.4",
"ckeditor5": "47.1.0",
"eslint": "9.38.0",
"eslint": "9.39.0",
"eslint-config-ckeditor5": ">=9.1.0",
"http-server": "14.1.1",
"lint-staged": "16.2.6",

View File

@ -32,7 +32,7 @@
"@vitest/browser": "3.2.4",
"@vitest/coverage-istanbul": "3.2.4",
"ckeditor5": "47.1.0",
"eslint": "9.38.0",
"eslint": "9.39.0",
"eslint-config-ckeditor5": ">=9.1.0",
"http-server": "14.1.1",
"lint-staged": "16.2.6",

View File

@ -15,7 +15,7 @@
"ckeditor5-premium-features": "47.1.0"
},
"devDependencies": {
"@smithy/middleware-retry": "4.4.5",
"@smithy/middleware-retry": "4.4.6",
"@types/jquery": "3.5.33"
}
}

View File

@ -50,6 +50,6 @@
"codemirror-lang-elixir": "4.0.0",
"codemirror-lang-hcl": "0.1.0",
"codemirror-lang-mermaid": "0.5.0",
"eslint-linter-browserify": "9.38.0"
"eslint-linter-browserify": "9.39.0"
}
}

View File

@ -35,6 +35,7 @@ const enum KeyboardActionNamesEnum {
activateNextTab,
activatePreviousTab,
openNewWindow,
openTodayNote,
toggleTray,
toggleZenMode,
firstTab,

View File

@ -36,8 +36,8 @@
"@typescript-eslint/eslint-plugin": "8.46.2",
"@typescript-eslint/parser": "8.46.2",
"dotenv": "17.2.3",
"esbuild": "0.25.11",
"eslint": "9.38.0",
"esbuild": "0.25.12",
"eslint": "9.39.0",
"highlight.js": "11.11.1",
"typescript": "5.9.3"
}

1513
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,8 @@
"**/node_modules/**",
"apps/edit-docs/demo/**",
"apps/server/src/assets/doc_notes/**",
"docs/**"
"docs/**",
"apps/server/Dockerfile.legacy"
],
"html": {
"enabled": false