mirror of
https://github.com/zadam/trilium.git
synced 2025-12-16 21:29:56 +01:00
Merge remote-tracking branch 'origin/main' into renovate/major-vitest-monorepo
This commit is contained in:
4
.github/workflows/deploy-docs.yml
vendored
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,19 +38,17 @@
|
||||
"@playwright/test": "1.56.1",
|
||||
"@stylistic/eslint-plugin": "5.5.0",
|
||||
"@types/express": "5.0.5",
|
||||
"@types/node": "24.9.1",
|
||||
"@types/node": "24.10.0",
|
||||
"@types/yargs": "17.0.34",
|
||||
"@vitest/coverage-v8": "4.0.6",
|
||||
"eslint": "9.38.0",
|
||||
"eslint": "9.39.1",
|
||||
"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",
|
||||
"tslib": "2.8.1",
|
||||
"typedoc": "0.28.14",
|
||||
"typedoc-plugin-missing-exports": "4.1.2"
|
||||
"rimraf": "6.1.0",
|
||||
"tslib": "2.8.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"appdmg": "0.6.6"
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"entryPoints": [
|
||||
"src/services/backend_script_entrypoint.ts",
|
||||
"src/public/app/services/frontend_script_entrypoint.ts"
|
||||
],
|
||||
"plugin": [
|
||||
"typedoc-plugin-missing-exports"
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "html",
|
||||
"path": "./docs/Script API"
|
||||
}
|
||||
]
|
||||
}
|
||||
22
apps/build-docs/package.json
Normal file
22
apps/build-docs/package.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "build-docs",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "src/main.ts",
|
||||
"scripts": {
|
||||
"start": "tsx ."
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Elian Doran <contact@eliandoran.me>",
|
||||
"license": "AGPL-3.0-only",
|
||||
"packageManager": "pnpm@10.20.0",
|
||||
"devDependencies": {
|
||||
"@redocly/cli": "2.11.0",
|
||||
"archiver": "7.0.1",
|
||||
"fs-extra": "11.3.2",
|
||||
"react": "19.2.0",
|
||||
"react-dom": "19.2.0",
|
||||
"typedoc": "0.28.14",
|
||||
"typedoc-plugin-missing-exports": "4.1.2"
|
||||
}
|
||||
}
|
||||
36
apps/build-docs/src/backend_script_entrypoint.ts
Normal file
36
apps/build-docs/src/backend_script_entrypoint.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* The backend script API is accessible to code notes with the "JS (backend)" language.
|
||||
*
|
||||
* The entire API is exposed as a single global: {@link api}
|
||||
*
|
||||
* @module Backend Script API
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file creates the entrypoint for TypeDoc that simulates the context from within a
|
||||
* script note on the server side.
|
||||
*
|
||||
* Make sure to keep in line with backend's `script_context.ts`.
|
||||
*/
|
||||
|
||||
export type { default as AbstractBeccaEntity } from "../../server/src/becca/entities/abstract_becca_entity.js";
|
||||
export type { default as BAttachment } from "../../server/src/becca/entities/battachment.js";
|
||||
export type { default as BAttribute } from "../../server/src/becca/entities/battribute.js";
|
||||
export type { default as BBranch } from "../../server/src/becca/entities/bbranch.js";
|
||||
export type { default as BEtapiToken } from "../../server/src/becca/entities/betapi_token.js";
|
||||
export type { BNote };
|
||||
export type { default as BOption } from "../../server/src/becca/entities/boption.js";
|
||||
export type { default as BRecentNote } from "../../server/src/becca/entities/brecent_note.js";
|
||||
export type { default as BRevision } from "../../server/src/becca/entities/brevision.js";
|
||||
|
||||
import BNote from "../../server/src/becca/entities/bnote.js";
|
||||
import BackendScriptApi, { type Api } from "../../server/src/services/backend_script_api.js";
|
||||
|
||||
export type { Api };
|
||||
|
||||
const fakeNote = new BNote();
|
||||
|
||||
/**
|
||||
* The `api` global variable allows access to the backend script API, which is documented in {@link Api}.
|
||||
*/
|
||||
export const api: Api = new BackendScriptApi(fakeNote, {});
|
||||
@@ -4,24 +4,22 @@ process.env.NODE_ENV = "development";
|
||||
|
||||
import cls from "@triliumnext/server/src/services/cls.js";
|
||||
import { dirname, join, resolve } from "path";
|
||||
import fs, { copyFile } from "fs/promises";
|
||||
import fsExtra, { createWriteStream, type WriteStream } from "fs-extra";
|
||||
import * as fs from "fs/promises";
|
||||
import * as fsExtra from "fs-extra";
|
||||
import archiver from "archiver";
|
||||
import { WriteStream } from "fs";
|
||||
import { execSync } from "child_process";
|
||||
import BuildContext from "./context.js";
|
||||
|
||||
const DOCS_ROOT = "../../../docs";
|
||||
const OUTPUT_DIR = "../../site";
|
||||
|
||||
async function main() {
|
||||
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];
|
||||
@@ -30,28 +28,53 @@ async function main() {
|
||||
"export",
|
||||
null
|
||||
);
|
||||
const fileOutputStream = createWriteStream(zipFilePath);
|
||||
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 copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "favicon.ico"));
|
||||
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) {
|
||||
@@ -106,4 +129,19 @@ export async function extractZip(zipFilePath: string, outputPath: string, ignore
|
||||
});
|
||||
}
|
||||
|
||||
cls.init(main);
|
||||
export default async function buildDocs({ gitRootDir }: BuildContext) {
|
||||
// Build the share theme.
|
||||
execSync(`pnpm run --filter share-theme build`, {
|
||||
stdio: "inherit",
|
||||
cwd: gitRootDir
|
||||
});
|
||||
|
||||
// Trigger the actual build.
|
||||
await new Promise((res, rej) => {
|
||||
cls.init(() => {
|
||||
buildDocsInner()
|
||||
.catch(rej)
|
||||
.then(res);
|
||||
});
|
||||
});
|
||||
}
|
||||
4
apps/build-docs/src/context.ts
Normal file
4
apps/build-docs/src/context.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export default interface BuildContext {
|
||||
gitRootDir: string;
|
||||
baseDir: string;
|
||||
}
|
||||
28
apps/build-docs/src/frontend_script_entrypoint.ts
Normal file
28
apps/build-docs/src/frontend_script_entrypoint.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* The front script API is accessible to code notes with the "JS (frontend)" language.
|
||||
*
|
||||
* The entire API is exposed as a single global: {@link api}
|
||||
*
|
||||
* @module Frontend Script API
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file creates the entrypoint for TypeDoc that simulates the context from within a
|
||||
* script note.
|
||||
*
|
||||
* Make sure to keep in line with frontend's `script_context.ts`.
|
||||
*/
|
||||
|
||||
export type { default as BasicWidget } from "../../client/src/widgets/basic_widget.js";
|
||||
export type { default as FAttachment } from "../../client/src/entities/fattachment.js";
|
||||
export type { default as FAttribute } from "../../client/src/entities/fattribute.js";
|
||||
export type { default as FBranch } from "../../client/src/entities/fbranch.js";
|
||||
export type { default as FNote } from "../../client/src/entities/fnote.js";
|
||||
export type { Api } from "../../client/src/services/frontend_script_api.js";
|
||||
export type { default as NoteContextAwareWidget } from "../../client/src/widgets/note_context_aware_widget.js";
|
||||
export type { default as RightPanelWidget } from "../../client/src/widgets/right_panel_widget.js";
|
||||
|
||||
import FrontendScriptApi, { type Api } from "../../client/src/services/frontend_script_api.js";
|
||||
|
||||
//@ts-expect-error
|
||||
export const api: Api = new FrontendScriptApi();
|
||||
10
apps/build-docs/src/index.html
Normal file
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>
|
||||
30
apps/build-docs/src/main.ts
Normal file
30
apps/build-docs/src/main.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { join } from "path";
|
||||
import BuildContext from "./context";
|
||||
import buildSwagger from "./swagger";
|
||||
import { cpSync, existsSync, mkdirSync, rmSync } from "fs";
|
||||
import buildDocs from "./build-docs";
|
||||
import buildScriptApi from "./script-api";
|
||||
|
||||
const context: BuildContext = {
|
||||
gitRootDir: join(__dirname, "../../../"),
|
||||
baseDir: join(__dirname, "../../../site")
|
||||
};
|
||||
|
||||
async function main() {
|
||||
// Clean input dir.
|
||||
if (existsSync(context.baseDir)) {
|
||||
rmSync(context.baseDir, { recursive: true });
|
||||
}
|
||||
mkdirSync(context.baseDir);
|
||||
|
||||
// Start building.
|
||||
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
apps/build-docs/src/script-api.ts
Normal file
15
apps/build-docs/src/script-api.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { execSync } from "child_process";
|
||||
import BuildContext from "./context";
|
||||
import { join } from "path";
|
||||
|
||||
export default function buildScriptApi({ baseDir, gitRootDir }: BuildContext) {
|
||||
// Generate types
|
||||
execSync(`pnpm typecheck`, { stdio: "inherit", cwd: gitRootDir });
|
||||
|
||||
for (const config of [ "backend", "frontend" ]) {
|
||||
const outDir = join(baseDir, "script-api", config);
|
||||
execSync(`pnpm typedoc --options typedoc.${config}.json --html "${outDir}"`, {
|
||||
stdio: "inherit"
|
||||
});
|
||||
}
|
||||
}
|
||||
32
apps/build-docs/src/swagger.ts
Normal file
32
apps/build-docs/src/swagger.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import BuildContext from "./context";
|
||||
import { join } from "path";
|
||||
import { execSync } from "child_process";
|
||||
import { mkdirSync } from "fs";
|
||||
|
||||
interface BuildInfo {
|
||||
specPath: string;
|
||||
outDir: string;
|
||||
}
|
||||
|
||||
const DIR_PREFIX = "rest-api";
|
||||
|
||||
const buildInfos: BuildInfo[] = [
|
||||
{
|
||||
// Paths are relative to Git root.
|
||||
specPath: "apps/server/internal.openapi.yaml",
|
||||
outDir: `${DIR_PREFIX}/internal`
|
||||
},
|
||||
{
|
||||
specPath: "apps/server/etapi.openapi.yaml",
|
||||
outDir: `${DIR_PREFIX}/etapi`
|
||||
}
|
||||
];
|
||||
|
||||
export default function buildSwagger({ baseDir, gitRootDir }: BuildContext) {
|
||||
for (const { specPath, outDir } of buildInfos) {
|
||||
const absSpecPath = join(gitRootDir, specPath);
|
||||
const targetDir = join(baseDir, outDir);
|
||||
mkdirSync(targetDir, { recursive: true });
|
||||
execSync(`pnpm redocly build-docs ${absSpecPath} -o ${targetDir}/index.html`, { stdio: "inherit" });
|
||||
}
|
||||
}
|
||||
36
apps/build-docs/tsconfig.app.json
Normal file
36
apps/build-docs/tsconfig.app.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"target": "ES2020",
|
||||
"outDir": "dist",
|
||||
"strict": false,
|
||||
"types": [
|
||||
"node",
|
||||
"express"
|
||||
],
|
||||
"rootDir": "src",
|
||||
"tsBuildInfoFile": "dist/tsconfig.app.tsbuildinfo"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"../server/src/*.d.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"eslint.config.js",
|
||||
"eslint.config.cjs",
|
||||
"eslint.config.mjs"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../server/tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "../desktop/tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "../client/tsconfig.app.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
15
apps/build-docs/tsconfig.json
Normal file
15
apps/build-docs/tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "../server"
|
||||
},
|
||||
{
|
||||
"path": "../client"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
10
apps/build-docs/typedoc.backend.json
Normal file
10
apps/build-docs/typedoc.backend.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"$schema": "https://typedoc.org/schema.json",
|
||||
"name": "Trilium Backend API",
|
||||
"entryPoints": [
|
||||
"src/backend_script_entrypoint.ts"
|
||||
],
|
||||
"plugin": [
|
||||
"typedoc-plugin-missing-exports"
|
||||
]
|
||||
}
|
||||
10
apps/build-docs/typedoc.frontend.json
Normal file
10
apps/build-docs/typedoc.frontend.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"$schema": "https://typedoc.org/schema.json",
|
||||
"name": "Trilium Frontend API",
|
||||
"entryPoints": [
|
||||
"src/frontend_script_entrypoint.ts"
|
||||
],
|
||||
"plugin": [
|
||||
"typedoc-plugin-missing-exports"
|
||||
]
|
||||
}
|
||||
@@ -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.1",
|
||||
"@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",
|
||||
"debounce": "3.0.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.4",
|
||||
"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"
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
|
||||
command: "editBranchPrefix",
|
||||
keyboardShortcut: "editBranchPrefix",
|
||||
uiIcon: "bx bx-rename",
|
||||
enabled: isNotRoot && parentNotSearch && noSelectedNotes && notOptionsOrHelp
|
||||
enabled: isNotRoot && parentNotSearch && notOptionsOrHelp
|
||||
},
|
||||
{ title: t("tree-context-menu.convert-to-attachment"), command: "convertNoteToAttachment", uiIcon: "bx bx-paperclip", enabled: isNotRoot && !isHoisted && notOptionsOrHelp },
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
/**
|
||||
* The front script API is accessible to code notes with the "JS (frontend)" language.
|
||||
*
|
||||
* The entire API is exposed as a single global: {@link api}
|
||||
*
|
||||
* @module Frontend Script API
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file creates the entrypoint for TypeDoc that simulates the context from within a
|
||||
* script note.
|
||||
*
|
||||
* Make sure to keep in line with frontend's `script_context.ts`.
|
||||
*/
|
||||
|
||||
export type { default as BasicWidget } from "../widgets/basic_widget.js";
|
||||
export type { default as FAttachment } from "../entities/fattachment.js";
|
||||
export type { default as FAttribute } from "../entities/fattribute.js";
|
||||
export type { default as FBranch } from "../entities/fbranch.js";
|
||||
export type { default as FNote } from "../entities/fnote.js";
|
||||
export type { Api } from "./frontend_script_api.js";
|
||||
export type { default as NoteContextAwareWidget } from "../widgets/note_context_aware_widget.js";
|
||||
export type { default as RightPanelWidget } from "../widgets/right_panel_widget.js";
|
||||
|
||||
import FrontendScriptApi, { type Api } from "./frontend_script_api.js";
|
||||
|
||||
//@ts-expect-error
|
||||
export const api: Api = new FrontendScriptApi();
|
||||
@@ -10,7 +10,7 @@ export const byNoteType: Record<Exclude<NoteType, "book">, string | null> = {
|
||||
file: null,
|
||||
image: null,
|
||||
launcher: null,
|
||||
mermaid: null,
|
||||
mermaid: "s1aBHPd79XYj",
|
||||
mindMap: null,
|
||||
noteMap: null,
|
||||
relationMap: null,
|
||||
|
||||
@@ -159,7 +159,7 @@ describe("shortcuts", () => {
|
||||
expect(matchesShortcut(event, "Shift+F1")).toBeTruthy();
|
||||
|
||||
// Special keys
|
||||
for (const keyCode of [ "Delete", "Enter" ]) {
|
||||
for (const keyCode of [ "Delete", "Enter", "NumpadEnter" ]) {
|
||||
event = createKeyboardEvent({ key: keyCode, code: keyCode });
|
||||
expect(matchesShortcut(event, keyCode), `Key ${keyCode}`).toBeTruthy();
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ for (let i = 1; i <= 19; i++) {
|
||||
const KEYCODES_WITH_NO_MODIFIER = new Set([
|
||||
"Delete",
|
||||
"Enter",
|
||||
"NumpadEnter",
|
||||
...functionKeyCodes
|
||||
]);
|
||||
|
||||
|
||||
@@ -716,7 +716,6 @@
|
||||
"backup_database_now": "نسخ اختياطي لقاعدة البيانات الان"
|
||||
},
|
||||
"etapi": {
|
||||
"wiki": "ويكي",
|
||||
"created": "تم الأنشاء",
|
||||
"actions": "أجراءات",
|
||||
"title": "ETAPI",
|
||||
|
||||
@@ -1289,10 +1289,6 @@
|
||||
"etapi": {
|
||||
"title": "ETAPI",
|
||||
"description": "ETAPI 是一个 REST API,用于以编程方式访问 Trilium 实例,而无需 UI。",
|
||||
"see_more": "有关更多详细信息,请参见 {{- link_to_wiki}} 和 {{- link_to_openapi_spec}} 或 {{- link_to_swagger_ui}}。",
|
||||
"wiki": "维基",
|
||||
"openapi_spec": "ETAPI OpenAPI 规范",
|
||||
"swagger_ui": "ETAPI Swagger UI",
|
||||
"create_token": "创建新的 ETAPI 令牌",
|
||||
"existing_tokens": "现有令牌",
|
||||
"no_tokens_yet": "目前还没有令牌。点击上面的按钮创建一个。",
|
||||
|
||||
@@ -1286,10 +1286,6 @@
|
||||
"etapi": {
|
||||
"title": "ETAPI",
|
||||
"description": "ETAPI ist eine REST-API, die für den programmgesteuerten Zugriff auf die Trilium-Instanz ohne Benutzeroberfläche verwendet wird.",
|
||||
"see_more": "Weitere Details können im {{- link_to_wiki}} und in der {{- link_to_openapi_spec}} oder der {{- link_to_swagger_ui }} gefunden werden.",
|
||||
"wiki": "Wiki",
|
||||
"openapi_spec": "ETAPI OpenAPI-Spezifikation",
|
||||
"swagger_ui": "ETAPI Swagger UI",
|
||||
"create_token": "Erstelle ein neues ETAPI-Token",
|
||||
"existing_tokens": "Vorhandene Token",
|
||||
"no_tokens_yet": "Es sind noch keine Token vorhanden. Klicke auf die Schaltfläche oben, um eine zu erstellen.",
|
||||
|
||||
@@ -36,10 +36,13 @@
|
||||
},
|
||||
"branch_prefix": {
|
||||
"edit_branch_prefix": "Edit branch prefix",
|
||||
"edit_branch_prefix_multiple": "Edit branch prefix for {{count}} branches",
|
||||
"help_on_tree_prefix": "Help on Tree prefix",
|
||||
"prefix": "Prefix: ",
|
||||
"save": "Save",
|
||||
"branch_prefix_saved": "Branch prefix has been saved."
|
||||
"branch_prefix_saved": "Branch prefix has been saved.",
|
||||
"branch_prefix_saved_multiple": "Branch prefix has been saved for {{count}} branches.",
|
||||
"affected_branches": "Affected branches ({{count}}):"
|
||||
},
|
||||
"bulk_actions": {
|
||||
"bulk_actions": "Bulk actions",
|
||||
@@ -1453,10 +1456,6 @@
|
||||
"etapi": {
|
||||
"title": "ETAPI",
|
||||
"description": "ETAPI is a REST API used to access Trilium instance programmatically, without UI.",
|
||||
"see_more": "See more details in the {{- link_to_wiki}} and the {{- link_to_openapi_spec}} or the {{- link_to_swagger_ui }}.",
|
||||
"wiki": "wiki",
|
||||
"openapi_spec": "ETAPI OpenAPI spec",
|
||||
"swagger_ui": "ETAPI Swagger UI",
|
||||
"create_token": "Create new ETAPI token",
|
||||
"existing_tokens": "Existing tokens",
|
||||
"no_tokens_yet": "There are no tokens yet. Click on the button above to create one.",
|
||||
|
||||
@@ -1446,10 +1446,6 @@
|
||||
"etapi": {
|
||||
"title": "ETAPI",
|
||||
"description": "ETAPI es una REST API que se utiliza para acceder a la instancia de Trilium mediante programación, sin interfaz de usuario.",
|
||||
"see_more": "Véa más detalles en el {{- link_to_wiki}} y el {{- link_to_openapi_spec}} o el {{- link_to_swagger_ui }}.",
|
||||
"wiki": "wiki",
|
||||
"openapi_spec": "Especificación ETAPI OpenAPI",
|
||||
"swagger_ui": "ETAPI Swagger UI",
|
||||
"create_token": "Crear nuevo token ETAPI",
|
||||
"existing_tokens": "Tokens existentes",
|
||||
"no_tokens_yet": "Aún no hay tokens. Dé clic en el botón de arriba para crear uno.",
|
||||
|
||||
@@ -1288,8 +1288,6 @@
|
||||
"etapi": {
|
||||
"title": "ETAPI",
|
||||
"description": "ETAPI est une API REST utilisée pour accéder à l'instance Trilium par programme, sans interface utilisateur.",
|
||||
"wiki": "wiki",
|
||||
"openapi_spec": "Spec ETAPI OpenAPI",
|
||||
"create_token": "Créer un nouveau jeton ETAPI",
|
||||
"existing_tokens": "Jetons existants",
|
||||
"no_tokens_yet": "Il n'y a pas encore de jetons. Cliquez sur le bouton ci-dessus pour en créer un.",
|
||||
@@ -1306,9 +1304,7 @@
|
||||
"delete_token": "Supprimer/désactiver ce token",
|
||||
"rename_token_title": "Renommer le jeton",
|
||||
"rename_token_message": "Veuillez saisir le nom du nouveau jeton",
|
||||
"delete_token_confirmation": "Êtes-vous sûr de vouloir supprimer le jeton ETAPI « {{name}} » ?",
|
||||
"see_more": "Voir plus de détails dans le {{- link_to_wiki}} et le {{- link_to_openapi_spec}} ou le {{- link_to_swagger_ui }}.",
|
||||
"swagger_ui": "Interface utilisateur ETAPI Swagger"
|
||||
"delete_token_confirmation": "Êtes-vous sûr de vouloir supprimer le jeton ETAPI « {{name}} » ?"
|
||||
},
|
||||
"options_widget": {
|
||||
"options_status": "Statut des options",
|
||||
|
||||
@@ -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.",
|
||||
@@ -132,10 +133,6 @@
|
||||
"new_token_message": "Inserisci il nome del nuovo token",
|
||||
"title": "ETAPI",
|
||||
"description": "ETAPI è un'API REST utilizzata per accedere alle istanze di Trilium in modo programmatico, senza interfaccia utente.",
|
||||
"see_more": "Per maggiori dettagli consulta {{- link_to_wiki}} e {{- link_to_openapi_spec}} o {{- link_to_swagger_ui}}.",
|
||||
"wiki": "wiki",
|
||||
"openapi_spec": "Specifiche ETAPI OpenAPI",
|
||||
"swagger_ui": "Interfaccia utente ETAPI Swagger",
|
||||
"create_token": "Crea un nuovo token ETAPI",
|
||||
"existing_tokens": "Token esistenti",
|
||||
"no_tokens_yet": "Non ci sono ancora token. Clicca sul pulsante qui sopra per crearne uno.",
|
||||
|
||||
@@ -657,10 +657,6 @@
|
||||
"created": "作成日時",
|
||||
"title": "ETAPI",
|
||||
"description": "ETAPI は、Trilium インスタンスに UI なしでプログラム的にアクセスするための REST API です。",
|
||||
"see_more": "詳細は{{- link_to_wiki}}と{{- link_to_openapi_spec}}または{{- link_to_swagger_ui }}を参照してください。",
|
||||
"wiki": "wiki",
|
||||
"openapi_spec": "ETAPI OpenAPIの仕様",
|
||||
"swagger_ui": "ETAPI Swagger UI",
|
||||
"create_token": "新しくETAPIトークンを作成",
|
||||
"existing_tokens": "既存のトークン",
|
||||
"no_tokens_yet": "トークンはまだありません。上のボタンをクリックして作成してください。",
|
||||
|
||||
@@ -1663,10 +1663,6 @@
|
||||
"etapi": {
|
||||
"title": "ETAPI",
|
||||
"description": "ETAPI to interfejs API REST używany do programowego dostępu do instancji Trilium, bez interfejsu użytkownika.",
|
||||
"see_more": "Zobacz więcej szczegółów w {{- link_to_wiki}} oraz w {{- link_to_openapi_spec}} lub {{- link_to_swagger_ui }}.",
|
||||
"wiki": "wiki",
|
||||
"openapi_spec": "specyfikacja ETAPI OpenAPI",
|
||||
"swagger_ui": "ETAPI Swagger UI",
|
||||
"create_token": "Utwórz nowy token ETAPI",
|
||||
"existing_tokens": "Istniejące tokeny",
|
||||
"no_tokens_yet": "Nie ma jeszcze żadnych tokenów. Kliknij przycisk powyżej, aby utworzyć jeden.",
|
||||
|
||||
@@ -1422,10 +1422,6 @@
|
||||
"etapi": {
|
||||
"title": "ETAPI",
|
||||
"description": "ETAPI é uma API REST usada para aceder a instância do Trilium programaticamente, sem interface gráfica.",
|
||||
"see_more": "Veja mais pormenores no {{- link_to_wiki}}, na {{- link_to_openapi_spec}} ou na {{- link_to_swagger_ui}}.",
|
||||
"wiki": "wiki",
|
||||
"openapi_spec": "Especificação OpenAPI do ETAPI",
|
||||
"swagger_ui": "ETAPI Swagger UI",
|
||||
"create_token": "Criar token ETAPI",
|
||||
"existing_tokens": "Tokens existentes",
|
||||
"no_tokens_yet": "Ainda não existem tokens. Clique no botão acima para criar um.",
|
||||
|
||||
@@ -1932,10 +1932,6 @@
|
||||
"etapi": {
|
||||
"title": "ETAPI",
|
||||
"description": "ETAPI é uma API REST usada para acessar a instância do Trilium programaticamente, sem interface gráfica.",
|
||||
"see_more": "Veja mais detalhes no {{- link_to_wiki}}, na {{- link_to_openapi_spec}} ou na {{- link_to_swagger_ui}}.",
|
||||
"wiki": "wiki",
|
||||
"openapi_spec": "Especificação OpenAPI do ETAPI",
|
||||
"swagger_ui": "ETAPI Swagger UI",
|
||||
"create_token": "Criar novo token ETAPI",
|
||||
"existing_tokens": "Tokens existentes",
|
||||
"no_tokens_yet": "Ainda não existem tokens. Clique no botão acima para criar um.",
|
||||
|
||||
@@ -507,17 +507,13 @@
|
||||
"new_token_message": "Introduceți denumirea noului token",
|
||||
"new_token_title": "Token ETAPI nou",
|
||||
"no_tokens_yet": "Nu există încă token-uri. Clic pe butonul de deasupra pentru a crea una.",
|
||||
"openapi_spec": "Specificația OpenAPI pentru ETAPI",
|
||||
"swagger_ui": "UI-ul Swagger pentru ETAPI",
|
||||
"rename_token": "Redenumește token-ul",
|
||||
"rename_token_message": "Introduceți denumirea noului token",
|
||||
"rename_token_title": "Redenumire token",
|
||||
"see_more": "Vedeți mai multe detalii în {{- link_to_wiki}} și în {{- link_to_openapi_spec}} sau în {{- link_to_swagger_ui }}.",
|
||||
"title": "ETAPI",
|
||||
"token_created_message": "Copiați token-ul creat în clipboard. Trilium stochează token-ul ca hash așadar această valoare poate fi văzută doar acum.",
|
||||
"token_created_title": "Token ETAPI creat",
|
||||
"token_name": "Denumire token",
|
||||
"wiki": "wiki"
|
||||
"token_name": "Denumire token"
|
||||
},
|
||||
"execute_script": {
|
||||
"example_1": "De exemplu, pentru a adăuga un șir de caractere la titlul unei notițe, se poate folosi acest mic script:",
|
||||
|
||||
@@ -1440,7 +1440,6 @@
|
||||
},
|
||||
"etapi": {
|
||||
"title": "ETAPI",
|
||||
"wiki": "вики",
|
||||
"created": "Создано",
|
||||
"actions": "Действия",
|
||||
"existing_tokens": "Существующие токены",
|
||||
@@ -1448,10 +1447,7 @@
|
||||
"default_token_name": "новый токен",
|
||||
"rename_token_title": "Переименовать токен",
|
||||
"description": "ETAPI — это REST API, используемый для программного доступа к экземпляру Trilium без пользовательского интерфейса.",
|
||||
"see_more": "Более подробную информацию смотрите в {{- link_to_wiki}} и {{- link_to_openapi_spec}} или {{- link_to_swagger_ui }}.",
|
||||
"create_token": "Создать новый токен ETAPI",
|
||||
"openapi_spec": "Спецификация ETAPI OpenAPI",
|
||||
"swagger_ui": "Пользовательский интерфейс ETAPI Swagger",
|
||||
"new_token_title": "Новый токен ETAPI",
|
||||
"token_created_title": "Создан токен ETAPI",
|
||||
"rename_token": "Переименовать этот токен",
|
||||
|
||||
@@ -1281,8 +1281,6 @@
|
||||
"etapi": {
|
||||
"title": "ETAPI",
|
||||
"description": "ETAPI 是一個 REST API,用於以編程方式訪問 Trilium 實例,而無需 UI。",
|
||||
"wiki": "維基",
|
||||
"openapi_spec": "ETAPI OpenAPI 規範",
|
||||
"create_token": "新增 ETAPI 令牌",
|
||||
"existing_tokens": "現有令牌",
|
||||
"no_tokens_yet": "目前還沒有令牌。點擊上面的按鈕新增一個。",
|
||||
@@ -1299,9 +1297,7 @@
|
||||
"delete_token": "刪除 / 停用此令牌",
|
||||
"rename_token_title": "重新命名令牌",
|
||||
"rename_token_message": "請輸入新的令牌名稱",
|
||||
"delete_token_confirmation": "您確定要刪除 ETAPI 令牌 \"{{name}}\" 嗎?",
|
||||
"see_more": "有關更多詳細資訊,請參閱 {{- link_to_wiki}} 和 {{- link_to_openapi_spec}} 或 {{- link_to_swagger_ui}}。",
|
||||
"swagger_ui": "ETAPI Swagger UI"
|
||||
"delete_token_confirmation": "您確定要刪除 ETAPI 令牌 \"{{name}}\" 嗎?"
|
||||
},
|
||||
"options_widget": {
|
||||
"options_status": "選項狀態",
|
||||
|
||||
@@ -1402,10 +1402,6 @@
|
||||
"etapi": {
|
||||
"title": "ETAPI",
|
||||
"description": "ETAPI — це REST API, який використовується для програмного доступу до екземпляра Trilium без інтерфейсу користувача.",
|
||||
"see_more": "Див. докладнішу інформацію у {{- link_to_wiki}} та {{- link_to_openapi_spec}} або {{- link_to_swagger_ui }}.",
|
||||
"wiki": "вікі",
|
||||
"openapi_spec": "ETAPI OpenAPI spec",
|
||||
"swagger_ui": "ETAPI Swagger UI",
|
||||
"create_token": "Створити новий токен ETAPI",
|
||||
"existing_tokens": "Існуючі токени",
|
||||
"no_tokens_yet": "Токенів поки що немає. Натисніть кнопку вище, щоб створити його.",
|
||||
|
||||
13
apps/client/src/widgets/dialogs/branch_prefix.css
Normal file
13
apps/client/src/widgets/dialogs/branch_prefix.css
Normal file
@@ -0,0 +1,13 @@
|
||||
.branch-prefix-dialog .branch-prefix-notes-list {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.branch-prefix-dialog .branch-prefix-notes-list ul {
|
||||
max-height: 200px;
|
||||
overflow: auto;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.branch-prefix-dialog .branch-prefix-current {
|
||||
opacity: 0.6;
|
||||
}
|
||||
@@ -10,14 +10,26 @@ import Button from "../react/Button.jsx";
|
||||
import FormGroup from "../react/FormGroup.js";
|
||||
import { useTriliumEvent } from "../react/hooks.jsx";
|
||||
import FBranch from "../../entities/fbranch.js";
|
||||
import type { ContextMenuCommandData } from "../../components/app_context.js";
|
||||
import "./branch_prefix.css";
|
||||
|
||||
// Virtual branches (e.g., from search results) start with this prefix
|
||||
const VIRTUAL_BRANCH_PREFIX = "virt-";
|
||||
|
||||
export default function BranchPrefixDialog() {
|
||||
const [ shown, setShown ] = useState(false);
|
||||
const [ branch, setBranch ] = useState<FBranch>();
|
||||
const [ branches, setBranches ] = useState<FBranch[]>([]);
|
||||
const [ prefix, setPrefix ] = useState("");
|
||||
const branchInput = useRef<HTMLInputElement>(null);
|
||||
|
||||
useTriliumEvent("editBranchPrefix", async () => {
|
||||
useTriliumEvent("editBranchPrefix", async (data?: ContextMenuCommandData) => {
|
||||
let branchIds: string[] = [];
|
||||
|
||||
if (data?.selectedOrActiveBranchIds && data.selectedOrActiveBranchIds.length > 0) {
|
||||
// Multi-select mode from tree context menu
|
||||
branchIds = data.selectedOrActiveBranchIds.filter((branchId) => !branchId.startsWith(VIRTUAL_BRANCH_PREFIX));
|
||||
} else {
|
||||
// Single branch mode from keyboard shortcut or when no selection
|
||||
const notePath = appContext.tabManager.getActiveContextNotePath();
|
||||
if (!notePath) {
|
||||
return;
|
||||
@@ -29,8 +41,8 @@ export default function BranchPrefixDialog() {
|
||||
return;
|
||||
}
|
||||
|
||||
const newBranchId = await froca.getBranchId(parentNoteId, noteId);
|
||||
if (!newBranchId) {
|
||||
const branchId = await froca.getBranchId(parentNoteId, noteId);
|
||||
if (!branchId) {
|
||||
return;
|
||||
}
|
||||
const parentNote = await froca.getNote(parentNoteId);
|
||||
@@ -38,25 +50,46 @@ export default function BranchPrefixDialog() {
|
||||
return;
|
||||
}
|
||||
|
||||
const newBranch = froca.getBranch(newBranchId);
|
||||
setBranch(newBranch);
|
||||
setPrefix(newBranch?.prefix ?? "");
|
||||
branchIds = [branchId];
|
||||
}
|
||||
|
||||
if (branchIds.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newBranches = branchIds
|
||||
.map(id => froca.getBranch(id))
|
||||
.filter((branch): branch is FBranch => branch !== null);
|
||||
|
||||
if (newBranches.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
setBranches(newBranches);
|
||||
// Use the prefix of the first branch as the initial value
|
||||
setPrefix(newBranches[0]?.prefix ?? "");
|
||||
setShown(true);
|
||||
});
|
||||
|
||||
async function onSubmit() {
|
||||
if (!branch) {
|
||||
if (branches.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
savePrefix(branch.branchId, prefix);
|
||||
if (branches.length === 1) {
|
||||
await savePrefix(branches[0].branchId, prefix);
|
||||
} else {
|
||||
await savePrefixBatch(branches.map(b => b.branchId), prefix);
|
||||
}
|
||||
setShown(false);
|
||||
}
|
||||
|
||||
const isSingleBranch = branches.length === 1;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className="branch-prefix-dialog"
|
||||
title={t("branch_prefix.edit_branch_prefix")}
|
||||
title={isSingleBranch ? t("branch_prefix.edit_branch_prefix") : t("branch_prefix.edit_branch_prefix_multiple", { count: branches.length })}
|
||||
size="lg"
|
||||
onShown={() => branchInput.current?.focus()}
|
||||
onHidden={() => setShown(false)}
|
||||
@@ -69,9 +102,27 @@ export default function BranchPrefixDialog() {
|
||||
<div class="input-group">
|
||||
<input class="branch-prefix-input form-control" value={prefix} ref={branchInput}
|
||||
onChange={(e) => setPrefix((e.target as HTMLInputElement).value)} />
|
||||
<div class="branch-prefix-note-title input-group-text"> - {branch && branch.getNoteFromCache().title}</div>
|
||||
{isSingleBranch && branches[0] && (
|
||||
<div class="branch-prefix-note-title input-group-text"> - {branches[0].getNoteFromCache().title}</div>
|
||||
)}
|
||||
</div>
|
||||
</FormGroup>
|
||||
{!isSingleBranch && (
|
||||
<div className="branch-prefix-notes-list">
|
||||
<strong>{t("branch_prefix.affected_branches", { count: branches.length })}</strong>
|
||||
<ul>
|
||||
{branches.map((branch) => {
|
||||
const note = branch.getNoteFromCache();
|
||||
return (
|
||||
<li key={branch.branchId}>
|
||||
{branch.prefix && <span className="branch-prefix-current">{branch.prefix} - </span>}
|
||||
{note.title}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
@@ -80,3 +131,8 @@ async function savePrefix(branchId: string, prefix: string) {
|
||||
await server.put(`branches/${branchId}/set-prefix`, { prefix: prefix });
|
||||
toast.showMessage(t("branch_prefix.branch_prefix_saved"));
|
||||
}
|
||||
|
||||
async function savePrefixBatch(branchIds: string[], prefix: string) {
|
||||
await server.put("branches/set-prefix-batch", { branchIds, prefix });
|
||||
toast.showMessage(t("branch_prefix.branch_prefix_saved_multiple", { count: branchIds.length }));
|
||||
}
|
||||
|
||||
@@ -1591,6 +1591,20 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
|
||||
this.clearSelectedNodes();
|
||||
}
|
||||
|
||||
async editBranchPrefixCommand({ node }: CommandListenerData<"editBranchPrefix">) {
|
||||
const branchIds = this.getSelectedOrActiveBranchIds(node).filter((branchId) => !branchId.startsWith("virt-"));
|
||||
|
||||
if (!branchIds.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Trigger the event with the selected branch IDs
|
||||
appContext.triggerEvent("editBranchPrefix", {
|
||||
selectedOrActiveBranchIds: branchIds,
|
||||
node: node
|
||||
});
|
||||
}
|
||||
|
||||
canBeMovedUpOrDown(node: Fancytree.FancytreeNode) {
|
||||
if (node.data.noteId === "root") {
|
||||
return false;
|
||||
|
||||
@@ -41,7 +41,7 @@ export default function EditedNotesTab({ note }: TabContext) {
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
}))}
|
||||
}), " ")}
|
||||
</div>
|
||||
) : (
|
||||
<div className="no-edited-notes-found">{t("edited_notes.no_edited_notes_found")}</div>
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { ComponentChildren } from "preact";
|
||||
import { CSSProperties } from "preact/compat";
|
||||
|
||||
interface OptionsSectionProps {
|
||||
title?: string;
|
||||
title?: ComponentChildren;
|
||||
children: ComponentChildren;
|
||||
noCard?: boolean;
|
||||
style?: CSSProperties;
|
||||
|
||||
@@ -11,6 +11,7 @@ import dialog from "../../../services/dialog";
|
||||
import { formatDateTime } from "../../../utils/formatters";
|
||||
import ActionButton from "../../react/ActionButton";
|
||||
import { useTriliumEvent } from "../../react/hooks";
|
||||
import HelpButton from "../../react/HelpButton";
|
||||
|
||||
type RenameTokenCallback = (tokenId: string, oldName: string) => Promise<void>;
|
||||
type DeleteTokenCallback = (tokenId: string, name: string ) => Promise<void>;
|
||||
@@ -53,14 +54,8 @@ export default function EtapiSettings() {
|
||||
return (
|
||||
<OptionsSection title={t("etapi.title")}>
|
||||
<FormText>
|
||||
{t("etapi.description")}<br />
|
||||
<RawHtml
|
||||
html={t("etapi.see_more", {
|
||||
link_to_wiki: `<a class="tn-link" href="https://triliumnext.github.io/Docs/Wiki/etapi.html">${t("etapi.wiki")}</a>`,
|
||||
// TODO: We use window.open src/public/app/services/link.ts -> prevents regular click behavior on "a" element here because it's a relative path
|
||||
link_to_openapi_spec: `<a class="tn-link" onclick="window.open('etapi/etapi.openapi.yaml')" href="etapi/etapi.openapi.yaml">${t("etapi.openapi_spec")}</a>`,
|
||||
link_to_swagger_ui: `<a class="tn-link" href="#_help_f3xpgx6H01PW">${t("etapi.swagger_ui")}</a>`
|
||||
})} />
|
||||
{t("etapi.description")}
|
||||
<HelpButton helpPage="pgxEVkzLl1OP" />
|
||||
</FormText>
|
||||
|
||||
<Button
|
||||
@@ -68,6 +63,7 @@ export default function EtapiSettings() {
|
||||
text={t("etapi.create_token")}
|
||||
onClick={createTokenCallback}
|
||||
/>
|
||||
|
||||
<hr />
|
||||
|
||||
<h5>{t("etapi.existing_tokens")}</h5>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
3
apps/edit-docs/demo/!!!meta.json
vendored
3
apps/edit-docs/demo/!!!meta.json
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"formatVersion": 2,
|
||||
"appVersion": "0.99.2",
|
||||
"appVersion": "0.99.3",
|
||||
"files": [
|
||||
{
|
||||
"isClone": false,
|
||||
@@ -2700,6 +2700,7 @@
|
||||
}
|
||||
],
|
||||
"format": "html",
|
||||
"dataFileName": "Note Types.html",
|
||||
"attachments": [],
|
||||
"dirFileName": "Note Types",
|
||||
"children": [
|
||||
|
||||
2
apps/edit-docs/demo/navigation.html
vendored
2
apps/edit-docs/demo/navigation.html
vendored
@@ -270,7 +270,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Note Types
|
||||
<li><a href="root/Trilium%20Demo/Note%20Types.html" target="detail">Note Types</a>
|
||||
<ul>
|
||||
<li><a href="root/Trilium%20Demo/Note%20Types/Canvas.json" target="detail">Canvas</a>
|
||||
</li>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
<div class="ck-content">
|
||||
<h2>☑️ Tasks</h2>
|
||||
|
||||
<ul>
|
||||
<li data-list-item-id="e4b26220d6ce48997f1116dc1d1d83dc0">[…]</li>
|
||||
</ul>
|
||||
|
||||
16
apps/edit-docs/demo/root/Trilium Demo.html
vendored
16
apps/edit-docs/demo/root/Trilium Demo.html
vendored
@@ -14,11 +14,10 @@
|
||||
|
||||
<div class="ck-content">
|
||||
<figure class="image image-style-align-right image_resized" style="width:29.84%;">
|
||||
<img style="aspect-ratio:150/150;" src="Trilium Demo_icon-color.svg" width="150"
|
||||
height="150">
|
||||
<img style="aspect-ratio:150/150;" src="Trilium Demo_icon-color.svg"
|
||||
width="150" height="150">
|
||||
</figure>
|
||||
<p><strong>Welcome to Trilium Notes!</strong>
|
||||
|
||||
</p>
|
||||
<p>This is a "demo" document packaged with Trilium to showcase some of its
|
||||
features and also give you some ideas on how you might structure your notes.
|
||||
@@ -26,22 +25,17 @@
|
||||
you wish.</p>
|
||||
<p>If you need any help, visit <a href="https://triliumnotes.org">triliumnotes.org</a> or
|
||||
our <a href="https://github.com/TriliumNext">GitHub repository</a>
|
||||
|
||||
</p>
|
||||
<h2>Cleanup</h2>
|
||||
|
||||
<p>Once you're finished with experimenting and want to cleanup these pages,
|
||||
you can simply delete them all.</p>
|
||||
<h2>Formatting</h2>
|
||||
|
||||
<p>Trilium supports classic formatting like <em>italic</em>, <strong>bold</strong>, <em><strong>bold and italic</strong></em>.
|
||||
You can add links pointing to <a href="https://triliumnotes.org/">external pages</a> or
|
||||
<a
|
||||
class="reference-link" href="Trilium%20Demo/Formatting%20examples">Formatting examples</a>.</p>
|
||||
<h3>Lists</h3>
|
||||
|
||||
<p><strong>Ordered:</strong>
|
||||
|
||||
</p>
|
||||
<ol>
|
||||
<li data-list-item-id="e877cc655d0239b8bb0f38696ad5d8abb">First Item</li>
|
||||
@@ -56,7 +50,6 @@
|
||||
</li>
|
||||
</ol>
|
||||
<p><strong>Unordered:</strong>
|
||||
|
||||
</p>
|
||||
<ul>
|
||||
<li data-list-item-id="e68bf4b518a16671c314a72073c3d900a">Item</li>
|
||||
@@ -67,7 +60,6 @@
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Block quotes</h3>
|
||||
|
||||
<blockquote>
|
||||
<p>Whereof one cannot speak, thereof one must be silent”</p>
|
||||
<p>– Ludwig Wittgenstein</p>
|
||||
@@ -75,9 +67,9 @@
|
||||
<hr>
|
||||
<p>See also other examples like <a href="Trilium%20Demo/Formatting%20examples/School%20schedule.html">tables</a>,
|
||||
<a
|
||||
href="Trilium%20Demo/Formatting%20examples/Checkbox%20lists.html">checkbox lists,</a> <a href="Trilium%20Demo/Formatting%20examples/Highlighting.html">highlighting</a>,
|
||||
href="Trilium%20Demo/Formatting%20examples/Checkbox%20lists.html">checkbox lists,</a> <a href="Trilium%20Demo/Formatting%20examples/Highlighting.html">highlighting</a>, <a href="Trilium%20Demo/Formatting%20examples/Code%20blocks.html">code blocks</a>and
|
||||
<a
|
||||
href="Trilium%20Demo/Formatting%20examples/Code%20blocks.html">code blocks</a>and <a href="Trilium%20Demo/Formatting%20examples/Math.html">math examples</a>.</p>
|
||||
href="Trilium%20Demo/Formatting%20examples/Math.html">math examples</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -21,8 +21,12 @@
|
||||
language, should that fail it is possible to manually adjust it. The color
|
||||
scheme for the syntax highlighting is adjustable in settings. </p><pre><code class="language-application-javascript-env-frontend">function helloWorld() {
|
||||
|
||||
|
||||
|
||||
alert("Hello world");
|
||||
|
||||
|
||||
|
||||
}</code></pre>
|
||||
<p>For larger pieces of code it is better to use a code note, which uses
|
||||
a fully-fledged code editor (CodeMirror). For an example of a code note,
|
||||
|
||||
21
apps/edit-docs/demo/root/Trilium Demo/Note Types.html
vendored
Normal file
21
apps/edit-docs/demo/root/Trilium Demo/Note Types.html
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="../../style.css">
|
||||
<base target="_parent">
|
||||
<title data-trilium-title>Note Types</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="content">
|
||||
<h1 data-trilium-h1>Note Types</h1>
|
||||
|
||||
<div class="ck-content">
|
||||
<p>T</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -13,9 +13,8 @@
|
||||
<h1 data-trilium-h1>Task manager</h1>
|
||||
|
||||
<div class="ck-content">
|
||||
<p>This is a simple TODO/Task manager. You can see some description and explanation
|
||||
here: <a href="https://github.com/zadam/trilium/wiki/Task-manager">https://github.com/zadam/trilium/wiki/Task-manager</a>
|
||||
</p>
|
||||
<p>This is a simple TODO/Task manager. See the <a href="https://docs.triliumnotes.org/user-guide/advanced-usage/advanced-showcases/task-manager">Trilium documentation</a> for
|
||||
information on how it works.</p>
|
||||
<p>Please note that this is meant as scripting example only and feature/bug
|
||||
support is very limited.</p>
|
||||
</div>
|
||||
|
||||
@@ -16,18 +16,32 @@
|
||||
<p>Documentation: <a href="http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_02.html">http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_02.html</a>
|
||||
</p><pre><code class="language-text-x-sh">#!/bin/bash
|
||||
|
||||
|
||||
|
||||
# This script opens 4 terminal windows.
|
||||
|
||||
|
||||
|
||||
i="0"
|
||||
|
||||
|
||||
|
||||
while [ $i -lt 4 ]
|
||||
|
||||
|
||||
|
||||
do
|
||||
|
||||
|
||||
|
||||
xterm &
|
||||
|
||||
|
||||
|
||||
i=$[$i+1]
|
||||
|
||||
|
||||
|
||||
done</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
"@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": {
|
||||
"edit-docs": "cross-env TRILIUM_PORT=37741 TRILIUM_DATA_DIR=data TRILIUM_INTEGRATION_TEST=memory-no-store DOCS_ROOT=../../../docs USER_GUIDE_ROOT=\"../../server/src/assets/doc_notes/en/User Guide\" tsx ../../scripts/electron-start.mts src/edit-docs.ts",
|
||||
"edit-demo": "cross-env TRILIUM_PORT=37741 TRILIUM_DATA_DIR=data TRILIUM_INTEGRATION_TEST=memory-no-store DOCS_ROOT=../../../docs USER_GUIDE_ROOT=\"../../server/src/assets/doc_notes/en/User Guide\" tsx ../../scripts/electron-start.mts src/edit-demo.ts"
|
||||
"edit-demo": "cross-env TRILIUM_PORT=37744 TRILIUM_DATA_DIR=data TRILIUM_INTEGRATION_TEST=memory-no-store DOCS_ROOT=../../../docs USER_GUIDE_ROOT=\"../../server/src/assets/doc_notes/en/User Guide\" tsx ../../scripts/electron-start.mts src/edit-demo.ts"
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,8 @@ if (!DOCS_ROOT || !USER_GUIDE_ROOT) {
|
||||
throw new Error("Missing DOCS_ROOT or USER_GUIDE_ROOT environment variable.");
|
||||
}
|
||||
|
||||
const BASE_URL = "https://docs.triliumnotes.org";
|
||||
|
||||
const NOTE_MAPPINGS: NoteMapping[] = [
|
||||
{
|
||||
rootNoteId: "pOsGYCXsbNQG",
|
||||
@@ -158,6 +160,14 @@ async function cleanUpMeta(outputPath: string, minify: boolean) {
|
||||
}
|
||||
|
||||
el.isExpanded = false;
|
||||
|
||||
// Rewrite web view URLs that point to root.
|
||||
if (el.type === "webView" && minify) {
|
||||
const srcAttr = el.attributes.find(attr => attr.name === "webViewSrc");
|
||||
if (srcAttr.value.startsWith("/")) {
|
||||
srcAttr.value = BASE_URL + srcAttr.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (minify) {
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -4,12 +4,12 @@ info:
|
||||
title: ETAPI
|
||||
description: External Trilium API
|
||||
contact:
|
||||
name: zadam
|
||||
email: zadam.apps@gmail.com
|
||||
url: https://github.com/zadam/trilium
|
||||
name: Trilium Notes Team
|
||||
email: contact@eliandoran.me
|
||||
url: https://triliumnotes.org
|
||||
license:
|
||||
name: Apache 2.0
|
||||
url: https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
name: GNU Affero General Public License v3.0 only
|
||||
url: https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
servers:
|
||||
- url: http://localhost:37740/etapi
|
||||
- url: http://localhost:8080/etapi
|
||||
@@ -1,7 +1,7 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: Trilium Notes Internal API
|
||||
version: 0.98.0
|
||||
title: Internal Trilium API
|
||||
version: 0.99.3
|
||||
description: |
|
||||
This is the internal API used by the Trilium Notes client application.
|
||||
|
||||
@@ -24,11 +24,12 @@ info:
|
||||
State-changing operations require CSRF tokens when using session authentication.
|
||||
|
||||
contact:
|
||||
name: TriliumNext Issue Tracker
|
||||
url: https://github.com/TriliumNext/Trilium/issues
|
||||
name: Trilium Notes Team
|
||||
email: contact@eliandoran.me
|
||||
url: https://triliumnotes.org
|
||||
license:
|
||||
name: GNU Affero General Public License v3.0
|
||||
url: https://www.gnu.org/licenses/agpl-3.0.html
|
||||
name: GNU Affero General Public License v3.0 only
|
||||
url: https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
servers:
|
||||
- url: http://localhost:8080
|
||||
@@ -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",
|
||||
@@ -61,35 +61,34 @@
|
||||
"@types/serve-static": "2.2.0",
|
||||
"@types/stream-throttle": "0.1.4",
|
||||
"@types/supertest": "6.0.3",
|
||||
"@types/swagger-ui-express": "4.1.8",
|
||||
"@types/tmp": "0.2.6",
|
||||
"@types/turndown": "5.0.6",
|
||||
"@types/ws": "8.18.1",
|
||||
"@types/xml2js": "0.4.14",
|
||||
"archiver": "7.0.1",
|
||||
"async-mutex": "0.5.0",
|
||||
"axios": "1.13.0",
|
||||
"axios": "1.13.2",
|
||||
"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",
|
||||
"debounce": "2.2.0",
|
||||
"dayjs": "1.11.19",
|
||||
"debounce": "3.0.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,20 +109,19 @@
|
||||
"mime-types": "3.0.1",
|
||||
"multer": "2.0.2",
|
||||
"normalize-strings": "1.1.1",
|
||||
"ollama": "0.6.0",
|
||||
"openai": "6.7.0",
|
||||
"ollama": "0.6.2",
|
||||
"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.3",
|
||||
"serve-favicon": "2.5.1",
|
||||
"stream-throttle": "0.1.3",
|
||||
"strip-bom": "5.0.0",
|
||||
"striptags": "3.2.0",
|
||||
"supertest": "7.1.4",
|
||||
"swagger-jsdoc": "6.2.8",
|
||||
"swagger-ui-express": "5.0.1",
|
||||
"time2fa": "1.4.2",
|
||||
"tmp": "0.2.5",
|
||||
"turndown": "7.2.2",
|
||||
|
||||
Binary file not shown.
2
apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json
generated
vendored
2
apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json
generated
vendored
File diff suppressed because one or more lines are too long
19
apps/server/src/assets/doc_notes/en/User Guide/User Guide/AI.html
generated
vendored
19
apps/server/src/assets/doc_notes/en/User Guide/User Guide/AI.html
generated
vendored
@@ -36,7 +36,7 @@ class="image image_resized" style="width:74.04%;">
|
||||
<p>To see what embedding models Ollama has available, you can check out
|
||||
<a
|
||||
href="https://ollama.com/search?c=embedding">this search</a>on their website, and then <code>pull</code> whichever one
|
||||
you want to try out. As of 4/15/25, my personal favorite is <code>mxbai-embed-large</code>.</p>
|
||||
you want to try out. A popular choice is <code>mxbai-embed-large</code>.</p>
|
||||
<p>First, we'll need to select the Ollama provider from the tabs of providers,
|
||||
then we will enter in the Base URL for our Ollama. Since our Ollama is
|
||||
running on our local machine, our Base URL is <code>http://localhost:11434</code>.
|
||||
@@ -145,17 +145,18 @@ class="image image_resized" style="width:74.04%;">
|
||||
<p>You don't need to tell the LLM to execute a certain tool, it should “smartly”
|
||||
call tools and automatically execute them as needed.</p>
|
||||
<h2>Overview</h2>
|
||||
<p>Now that you know about embeddings and tools, you can just go ahead and
|
||||
use the “Chat with Notes” button, where you can go ahead and start chatting!:</p>
|
||||
<figure
|
||||
class="image image_resized" style="width:60.77%;">
|
||||
<p>To start, simply press the <em>Chat with Notes</em> button in the
|
||||
<a
|
||||
class="reference-link" href="#root/_help_xYmIYSP6wE3F">Launch Bar</a>.</p>
|
||||
<figure class="image image_resized" style="width:60.77%;">
|
||||
<img style="aspect-ratio:1378/539;" src="2_AI_image.png"
|
||||
width="1378" height="539">
|
||||
</figure>
|
||||
<p>If you don't see the “Chat with Notes” button on your side launchbar,
|
||||
you might need to move it from the “Available Launchers” section to the
|
||||
“Visible Launchers” section:</p>
|
||||
<figure class="image image_resized" style="width:69.81%;">
|
||||
<p>If you don't see the button in the <a class="reference-link" href="#root/_help_xYmIYSP6wE3F">Launch Bar</a>,
|
||||
you might need to move it from the <em>Available Launchers</em> section to
|
||||
the <em>Visible Launchers</em> section:</p>
|
||||
<figure class="image image_resized"
|
||||
style="width:69.81%;">
|
||||
<img style="aspect-ratio:1765/1287;" src="9_AI_image.png"
|
||||
width="1765" height="1287">
|
||||
</figure>
|
||||
@@ -8,7 +8,7 @@
|
||||
<li>
|
||||
<p><a class="reference-link" href="#root/_help_HI6GBBIduIgv">Labels</a> can
|
||||
be used for a variety of purposes, such as storing metadata or configuring
|
||||
the behaviour of notes. Labels are also searchable, enhancing note retrieval.</p>
|
||||
the behavior of notes. Labels are also searchable, enhancing note retrieval.</p>
|
||||
<p>For more information, including predefined labels, see <a class="reference-link"
|
||||
href="#root/_help_HI6GBBIduIgv">Labels</a>.</p>
|
||||
</li>
|
||||
@@ -21,7 +21,7 @@
|
||||
class="reference-link" href="#root/_help_Cq5X6iKQop6R">Relations</a>.</p>
|
||||
</li>
|
||||
</ol>
|
||||
<p>These attributes play a crucial role in organizing, categorising, and
|
||||
<p>These attributes play a crucial role in organizing, categorizing, and
|
||||
enhancing the functionality of notes.</p>
|
||||
<h2>Viewing the list of attributes</h2>
|
||||
<p>Both the labels and relations for the current note are displayed in the <em>Owned Attributes</em> section
|
||||
|
||||
@@ -11,7 +11,7 @@ const {secret, title, content} = req.body;
|
||||
if (req.method == 'POST' && secret === 'secret-password') {
|
||||
// notes must be saved somewhere in the tree hierarchy specified by a parent note.
|
||||
// This is defined by a relation from this code note to the "target" parent note
|
||||
// alternetively you can just use constant noteId for simplicity (get that from "Note Info" dialog of the desired parent note)
|
||||
// alternatively you can just use constant noteId for simplicity (get that from "Note Info" dialog of the desired parent note)
|
||||
const targetParentNoteId = api.currentNote.getRelationValue('targetNote');
|
||||
|
||||
const {note} = api.createTextNote(targetParentNoteId, title, content);
|
||||
@@ -30,7 +30,7 @@ else {
|
||||
be saved</li>
|
||||
</ul>
|
||||
<h3>Explanation</h3>
|
||||
<p>Let's test this by using an HTTP client to send a request:</p><pre><code class="language-text-x-trilium-auto">POST http://my.trilium.org/custom/create-note
|
||||
<p>Let's test this by using an HTTP client to send a request:</p><pre><code class="language-text-x-trilium-auto">POST http://your-trilium-server/custom/create-note
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
@@ -64,12 +64,12 @@ Content-Type: application/json
|
||||
can always look into its <a href="https://expressjs.com/en/api.html">documentation</a> for
|
||||
details.</p>
|
||||
<h3>Parameters</h3>
|
||||
<p>REST request paths often contain parameters in the URL, e.g.:</p><pre><code class="language-text-x-trilium-auto">http://my.trilium.org/custom/notes/123</code></pre>
|
||||
<p>REST request paths often contain parameters in the URL, e.g.:</p><pre><code class="language-text-x-trilium-auto">http://your-trilium-server/custom/notes/123</code></pre>
|
||||
<p>The last part is dynamic so the matching of the URL must also be dynamic
|
||||
- for this reason the matching is done with regular expressions. Following <code>customRequestHandler</code> value
|
||||
would match it:</p><pre><code class="language-text-x-trilium-auto">notes/([0-9]+)</code></pre>
|
||||
<p>Additionally, this also defines a matching group with the use of parenthesis
|
||||
which then makes it easier to extract the value. The matched groups are
|
||||
available in <code>api.pathParams</code>:</p><pre><code class="language-text-x-trilium-auto">const noteId = api.pathParams[0];</code></pre>
|
||||
<p>Often you also need query params (as in e.g. <code>http://my.trilium.org/custom/notes?noteId=123</code>),
|
||||
<p>Often you also need query params (as in e.g. <code>http://your-trilium-server/custom/notes?noteId=123</code>),
|
||||
you can get those with standard express <code>req.query.noteId</code>.</p>
|
||||
@@ -1,6 +1,8 @@
|
||||
<aside class="admonition tip">
|
||||
<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>
|
||||
<p>The documentation is in OpenAPI format, available <a href="https://github.com/TriliumNext/Trilium/blob/master/src/etapi/etapi.openapi.yaml">here</a>.</p>
|
||||
<h2>API clients</h2>
|
||||
<p>As an alternative to calling the API directly, there are client libraries
|
||||
to simplify this</p>
|
||||
|
||||
35
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Nightly release.html
generated
vendored
Normal file
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>
|
||||
41
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Read-only database.html
generated
vendored
Normal file
41
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Read-only database.html
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<aside class="admonition warning">
|
||||
<p>This functionality is still in preview, expect possible issues or even
|
||||
the feature disappearing completely.
|
||||
<br>Feel free to <a href="#root/_help_wy8So3yZZlH9">report</a> any issues you might
|
||||
have.</p>
|
||||
</aside>
|
||||
<p>The read-only database is an alternative to <a class="reference-link"
|
||||
href="#root/_help_R9pX4DGra2Vt">Sharing</a> notes. Although the share functionality
|
||||
works pretty well to publish pages to the Internet in a wiki, blog-like
|
||||
format it does not offer the full functionality behind Trilium (such as
|
||||
the advanced <a class="reference-link" href="#root/_help_eIg8jdvaoNNd">Search</a> or
|
||||
the interactivity behind <a class="reference-link" href="#root/_help_GTwFsgaA0lCt">Collections</a> or
|
||||
the various <a class="reference-link" href="#root/_help_KSZ04uQ2D1St">Note Types</a>).</p>
|
||||
<p>When the database is in read-only mode, the Trilium application can be
|
||||
used as normal, but editing is disabled and changes are made in-memory
|
||||
only.</p>
|
||||
<h2>What it does</h2>
|
||||
<ul>
|
||||
<li>All notes are read-only, without the possibility of editing them.</li>
|
||||
<li>Features that would normally alter the database such as the list of recent
|
||||
notes are disabled.</li>
|
||||
</ul>
|
||||
<h2>Limitations</h2>
|
||||
<ul>
|
||||
<li>Some features might “slip through” and still end up creating a note, for
|
||||
example.
|
||||
<ul>
|
||||
<li>However, the database is still read-only, so all modifications will be
|
||||
reset if the server is restarted.</li>
|
||||
<li>Whenever this occurs, <code>ERROR: read-only DB ignored</code> will be shown
|
||||
in the logs.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<h2>Setting a database as read-only</h2>
|
||||
<p>First, make sure the database is initialized (e.g. the first set up is
|
||||
complete). Then modify the <a href="#root/_help_Gzjqa934BdH4">config.ini</a> by
|
||||
looking for the <code>[General]</code> section and adding a new <code>readOnly</code> field:</p><pre><code class="language-text-x-trilium-auto">[General]
|
||||
readOnly=true</code></pre>
|
||||
<p>If your server is already running, restart it to apply the changes.</p>
|
||||
<p>Similarly, to disable read-only remove the line or set it to <code>false</code>.</p>
|
||||
12
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Safe mode.html
generated
vendored
Normal file
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>
|
||||
@@ -41,6 +41,15 @@
|
||||
<li>The export requires a functional web server as the pages will not render
|
||||
properly if accessed locally via a web browser due to the use of module
|
||||
scripts.</li>
|
||||
<li>The directory structure is also slightly different:
|
||||
<ul>
|
||||
<li>A normal HTML export results in an index file and a single directory.</li>
|
||||
<li>Instead, for static exporting the top-root level becomes the index file
|
||||
and the child directories are on the root instead.</li>
|
||||
<li>This makes it possible to easily publish to a website, without forcing
|
||||
everything but the root note to be in a sub-directory.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<h2>Testing locally</h2>
|
||||
<p>As mentioned previously, the exported static pages require a website to
|
||||
@@ -21,7 +21,7 @@
|
||||
<ol>
|
||||
<li>Set the text to search for in the <em>Search string</em> field.
|
||||
<ol>
|
||||
<li>Apart from searching for words ad-literam, there is also the possibility
|
||||
<li>Apart from searching for words literally, there is also the possibility
|
||||
to search for attributes or properties of notes.</li>
|
||||
<li>See the examples below for more information.</li>
|
||||
</ol>
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
and you will see a list of all modified notes including the deleted ones.
|
||||
Notes available for undeletion have a link to do so. This is kind of "trash
|
||||
can" functionality known from e.g. Windows.</p>
|
||||
<p>Clicking an undelete will recover the note, it's content and attributes
|
||||
<p>Clicking an undelete will recover the note, its content and attributes
|
||||
- note should be just as before being deleted. This action will also undelete
|
||||
note's children which have been deleted in the same action.</p>
|
||||
<p>To be able to undelete a note, it is necessary that deleted note's parent
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<li><em><strong>Editable</strong></em> changes whether the current note:
|
||||
<ul>
|
||||
<li>Enters <a href="#root/_help_CoFPLs3dRlXc">read-only mode</a> automatically if
|
||||
the note is too big (default behaviour).</li>
|
||||
the note is too big (default behavior).</li>
|
||||
<li>Is always in read-only mode (however it can still be edited temporarily).</li>
|
||||
<li>Is always editable, regardless of its size.</li>
|
||||
</ul>
|
||||
|
||||
6
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Collections.html
generated
vendored
6
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Collections.html
generated
vendored
@@ -1,5 +1,5 @@
|
||||
<p>Collections are a unique type of notes that don't have a content, but
|
||||
instead display its child notes in various presentation methods.</p>
|
||||
<p>Collections are a unique type of note that don't have content, but instead
|
||||
display their child notes in various presentation methods.</p>
|
||||
<h2>Main collections</h2>
|
||||
<table>
|
||||
<thead>
|
||||
@@ -94,7 +94,7 @@
|
||||
in the <a class="reference-link" href="#root/_help_BlN9DFI679QC">Ribbon</a>.</p>
|
||||
<h2>Archived notes</h2>
|
||||
<p>By default, <a href="#root/_help_MKmLg5x6xkor">archived notes</a> will not be
|
||||
shown in collections. This behaviour can be changed by going to <em>Collection Properties</em> in
|
||||
shown in collections. This behavior can be changed by going to <em>Collection Properties</em> in
|
||||
the <a class="reference-link" href="#root/_help_BlN9DFI679QC">Ribbon</a> and
|
||||
checking <em>Show archived notes</em>.</p>
|
||||
<p>Archived notes will be generally indicated by being greyed out as opposed
|
||||
|
||||
@@ -28,20 +28,27 @@
|
||||
- it contains everything you need.</p>
|
||||
<h3>Changing the location of data directory</h3>
|
||||
<p>If you want to use some other location for the data directory than the
|
||||
default one, you may change it via TRILIUM_DATA_DIR environment variable
|
||||
to some other location:</p>
|
||||
default one, you may change it via <code>TRILIUM_DATA_DIR</code> environment
|
||||
variable to some other location:</p>
|
||||
<h3>Windows</h3>
|
||||
<ol>
|
||||
<li>Press the Windows key on your keyboard.</li>
|
||||
<li>Search and select “Edit the system variables”.</li>
|
||||
<li>Press the “Environment Variables…” button in the bottom-right of the newly
|
||||
opened screen.</li>
|
||||
<li>On the top section ("User variables for [user]"), press the “New…” button.</li>
|
||||
<li>In the <em>Variable name</em> field insert <code>TRILIUM_DATA_DIR</code>.</li>
|
||||
<li>Press the <em>Browse Directory…</em> button and select the new directory
|
||||
where to store the database.</li>
|
||||
<li>Close all the windows by pressing the <em>OK</em> button for each of them.</li>
|
||||
</ol>
|
||||
<h4>Linux</h4><pre><code class="language-text-x-trilium-auto">export TRILIUM_DATA_DIR=/home/myuser/data/my-trilium-data</code></pre>
|
||||
<h4>Mac OS X</h4>
|
||||
<p>You need to create a <code>.plist</code> file under <code>~/Library/LaunchAgents</code> to
|
||||
load it properly each login.</p>
|
||||
<p>To load it manually, you need to use <code>launchctl setenv TRILIUM_DATA_DIR <yourpath></code>
|
||||
</p>
|
||||
<p>Here is a pre-defined template, where you just need to add your path to:</p><pre><code class="language-text-x-trilium-auto">
|
||||
|
||||
|
||||
|
||||
|
||||
Label
|
||||
<p>Here is a pre-defined template, where you just need to add your path to:</p><pre><code class="language-text-x-trilium-auto"> Label
|
||||
set.trilium.env
|
||||
RunAtLoad
|
||||
|
||||
@@ -50,16 +57,13 @@
|
||||
launchctl
|
||||
setenv
|
||||
TRILIUM_DATA_DIR
|
||||
/Users/YourUserName/Library/Application Support/trilium-data
|
||||
|
||||
|
||||
</code></pre>
|
||||
/Users/YourUserName/Library/Application Support/trilium-data </code></pre>
|
||||
<h3>Create a script to run with specific data directory</h3>
|
||||
<p>An alternative to globally setting environment variable is to run only
|
||||
the Trilium Notes with this environment variable. This then allows for
|
||||
different setup styles like two <a href="#root/_help_wX4HbRucYSDD">database</a> instances
|
||||
or "portable" installation.</p>
|
||||
<p>To do this in unix based systems simply run trilium like this:</p><pre><code class="language-text-x-trilium-auto">TRILIUM_DATA_DIR=/home/myuser/data/my-trilium-data trilium</code></pre>
|
||||
<p>To do this in Unix-based systems simply run <code>trilium</code> like this:</p><pre><code class="language-text-x-trilium-auto">TRILIUM_DATA_DIR=/home/myuser/data/my-trilium-data trilium</code></pre>
|
||||
<p>You can then save the above command as a shell script on your path for
|
||||
convenience.</p>
|
||||
<h2>Fine-grained directory/path location</h2>
|
||||
|
||||
@@ -27,6 +27,6 @@
|
||||
any startup scripts that might cause the application to crash.</li>
|
||||
</ul>
|
||||
<h2>Synchronization</h2>
|
||||
<p>For Trilium desktp users who wish to synchronize their data with a server
|
||||
<p>For Trilium desktop users who wish to synchronize their data with a server
|
||||
instance, refer to the <a class="reference-link" href="#root/_help_cbkrhQjrkKrh">Synchronization</a> guide
|
||||
for detailed instructions.</p>
|
||||
64
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Desktop Installation/Nix flake.html
generated
vendored
Normal file
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,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). </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 </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>
|
||||
@@ -40,7 +40,7 @@
|
||||
<h3>Disabling / Modifying the Upload Limit</h3>
|
||||
<p>If you're running into the 250MB limit imposed on the server by default,
|
||||
and you'd like to increase the upload limit, you can set the <code>TRILIUM_NO_UPLOAD_LIMIT</code> environment
|
||||
variable to <code>true</code> disable it completely:</p><pre><code class="language-text-x-trilium-auto">export TRILIUM_NO_UPLOAD_LIMIT=true </code></pre>
|
||||
variable to <code>true</code> to disable it completely:</p><pre><code class="language-text-x-trilium-auto">export TRILIUM_NO_UPLOAD_LIMIT=true </code></pre>
|
||||
<p>Or, if you'd simply like to <em>increase</em> the upload limit size to something
|
||||
beyond 250MB, you can set the <code>MAX_ALLOWED_FILE_SIZE_MB</code> environment
|
||||
variable to something larger than the integer <code>250</code> (e.g. <code>450</code> in
|
||||
|
||||
1
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/Nix flake.clone.html
generated
vendored
Normal file
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 @@
|
||||
<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.
|
||||
|
||||
BIN
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Miscellaneous/Patterns of personal knowl.png
generated
vendored
Normal file
BIN
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Miscellaneous/Patterns of personal knowl.png
generated
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 102 KiB |
301
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Miscellaneous/Patterns of personal knowledge.html
generated
vendored
Normal file
301
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Miscellaneous/Patterns of personal knowledge.html
generated
vendored
Normal 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 <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 <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 <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
|
||||
<a
|
||||
class="reference-link" href="#root/_help_R7abl2fc6Mxi">Weight Tracker</a> 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 <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>
|
||||
20
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Miscellaneous/Privacy Policy.html
generated
vendored
Normal file
20
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Miscellaneous/Privacy Policy.html
generated
vendored
Normal 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>
|
||||
4
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types.html
generated
vendored
4
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types.html
generated
vendored
@@ -1,5 +1,5 @@
|
||||
<p>One core features of Trilium is that it supports multiple types of notes,
|
||||
depending on the need.</p>
|
||||
<p>One of the core features of Trilium is that it supports multiple types
|
||||
of notes, depending on the need.</p>
|
||||
<h2>Creating a new note with a different type via the note tree</h2>
|
||||
<p>The default note type in Trilium (e.g. when creating a new note) is
|
||||
<a
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<aside class="admonition tip">
|
||||
<p>For a quick understanding of the Mermaid syntax, see <a class="reference-link"
|
||||
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"
|
||||
width="886" height="663">
|
||||
@@ -6,7 +10,6 @@
|
||||
as flowchart, sequence diagram, class diagram, state diagram, pie charts,
|
||||
etc., all using a text description of the chart instead of manually drawing
|
||||
the diagram.</p>
|
||||
<p>For the official documentation of Mermaid.js see <a href="https://mermaid.js.org/intro/">mermaid.js.org/intro/</a>.</p>
|
||||
<h2>Layouts</h2>
|
||||
<p>Depending on the chart being edited and user preference, there are two
|
||||
layouts supported by the Mermaid note type:</p>
|
||||
|
||||
202
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Tables.html
generated
vendored
202
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Tables.html
generated
vendored
@@ -8,182 +8,178 @@
|
||||
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"
|
||||
height="100">
|
||||
</p>
|
||||
<img
|
||||
src="10_Tables_image.png" width="384"
|
||||
height="100">
|
||||
|
||||
<h2>Navigating a table</h2>
|
||||
<ul>
|
||||
<li data-list-item-id="e7f46134b097590227ab8def4844112be">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>Using the mouse:
|
||||
<ul>
|
||||
<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
|
||||
</ul>
|
||||
<h2>Resizing cells</h2>
|
||||
<ul>
|
||||
<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
|
||||
</ul>
|
||||
<h2>Inserting new rows and new columns</h2>
|
||||
<ul>
|
||||
<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>
|
||||
</ul>
|
||||
<h2>Merging cells</h2>
|
||||
<p>To merge two or more cells together, simply select them via drag &
|
||||
</ul>
|
||||
<h2>Merging cells</h2>
|
||||
<p>To merge two or more cells together, simply select them via drag &
|
||||
drop and press the
|
||||
<img src="1_Tables_image.png"
|
||||
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
|
||||
<p>More options are available by pressing the arrow next to it:</p>
|
||||
<ul>
|
||||
<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>
|
||||
<figure class="image image-style-align-right">
|
||||
</ul>
|
||||
<h2>Table properties</h2>
|
||||
<figure class="image image-style-align-right">
|
||||
<img style="aspect-ratio:312/311;" src="2_Tables_image.png"
|
||||
width="312" height="311">
|
||||
</figure>
|
||||
<p>The table properties can be accessed via the
|
||||
</figure>
|
||||
<p>The table properties can be accessed via the
|
||||
<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),
|
||||
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>)
|
||||
or pixels (must end with <code>px</code>).</li>
|
||||
<li data-list-item-id="e23ac3152d03898b653db8d3849f0f5cc">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>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>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>The alignment of the table.
|
||||
<ul>
|
||||
<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>
|
||||
</ul>
|
||||
<p>The table will immediately update to reflect the changes, but the <em>Save</em> button
|
||||
</ul>
|
||||
<p>The table will immediately update to reflect the changes, but the <em>Save</em> button
|
||||
must be pressed for the changes to persist.</p>
|
||||
<h2>Cell properties</h2>
|
||||
<figure class="image image-style-align-right">
|
||||
<h2>Cell properties</h2>
|
||||
<figure class="image image-style-align-right">
|
||||
<img style="aspect-ratio:320/386;" src="3_Tables_image.png"
|
||||
width="320" height="386">
|
||||
</figure>
|
||||
<p>Similarly to table properties, the
|
||||
</figure>
|
||||
<p>Similarly to table properties, the
|
||||
<img src="12_Tables_image.png"
|
||||
width="19" height="19">button opens a popup which adjusts the styling of one or more cells (based
|
||||
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
|
||||
<p>The following options can be adjusted:</p>
|
||||
<ul>
|
||||
<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
|
||||
</ul>
|
||||
<p>The cell will immediately update to reflect the changes, but the <em>Save</em> button
|
||||
must be pressed for the changes to persist.</p>
|
||||
<h2>Caption</h2>
|
||||
<p>Press the
|
||||
<h2>Caption</h2>
|
||||
<p>Press the
|
||||
<img src="4_Tables_image.png"
|
||||
width="18" height="17">button to insert a caption or a text description of the table, which is
|
||||
going to be displayed above the table.</p>
|
||||
<h2>Table borders</h2>
|
||||
<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 (
|
||||
<img
|
||||
src="14_Tables_image.png" width="21" height="21">).
|
||||
<h2>Table borders</h2>
|
||||
<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="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>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">).
|
||||
<ol>
|
||||
<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. </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>
|
||||
<h3>Tables with invisible borders</h3>
|
||||
<p>Tables can be set to have invisible borders in order to allow for basic
|
||||
</ol>
|
||||
<h3>Tables with invisible borders</h3>
|
||||
<p>Tables can be set to have invisible borders in order to allow for basic
|
||||
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:
|
||||
<ol>
|
||||
<li data-list-item-id="edef2e2e5a6a8ac73e36101f4429863d8"><em>Style</em> to <em>Single</em>
|
||||
<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><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>
|
||||
</ol>
|
||||
<h2>Markdown import/export</h2>
|
||||
<p>Simple tables are exported in GitHub-flavored Markdown format (e.g. a
|
||||
<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
|
||||
series of <code>|</code> items). If the table is found to be more complex
|
||||
(it contains HTML elements, has custom sizes or images), the table is converted
|
||||
to a HTML one instead.</p>
|
||||
<p>Generally formatting loss should be minimal when exported to Markdown
|
||||
<p>Generally formatting loss should be minimal when exported to Markdown
|
||||
due to the fallback to HTML formatting.</p>
|
||||
6
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Scripting.html
generated
vendored
6
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Scripting.html
generated
vendored
@@ -3,7 +3,7 @@
|
||||
it. Special case is JavaScript code notes which can also be executed inside
|
||||
Trilium which can in conjunction with <a class="reference-link" href="#root/_help_GLks18SNjxmC">Script API</a> provide
|
||||
extra functionality.</p>
|
||||
<h2>Scripting</h2>
|
||||
<h2>Architecture Overview</h2>
|
||||
<p>To go further I must explain basic architecture of Trilium - in its essence
|
||||
it is a classic web application - it has these two main components:</p>
|
||||
<ul>
|
||||
@@ -14,8 +14,8 @@
|
||||
</ul>
|
||||
<p>So we have frontend and backend, each with their own set of responsibilities,
|
||||
but their common feature is that they both run JavaScript code. Add to
|
||||
this the fact, that we're able to create JavaScript [[code notes]] and
|
||||
we're onto something.</p>
|
||||
this the fact, that we're able to create JavaScript <a class="reference-link"
|
||||
href="#root/_help_6f9hih2hXXZk">code notes</a> and we're onto something.</p>
|
||||
<h2>Use cases</h2>
|
||||
<ul>
|
||||
<li><a class="reference-link" href="#root/_help_TjLYAo3JMO8X">"New Task" launcher button</a>
|
||||
|
||||
7
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Scripting/Backend scripts/Server-side imports.html
generated
vendored
Normal file
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
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
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>
|
||||
@@ -8,7 +8,7 @@
|
||||
get parentWidget() { return "left-pane"; }
|
||||
|
||||
doRender() {
|
||||
this.$widget = $("");
|
||||
this.$widget = $("<div id='my-widget'>");
|
||||
return this.$widget;
|
||||
}
|
||||
}
|
||||
@@ -22,13 +22,13 @@ module.exports = new MyWidget();</code></pre>
|
||||
the <a href="#root/_help_BFs8mudNFgCS">note</a>.</li>
|
||||
<li>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>)
|
||||
<p>To verify that the widget is working, open the developer tools (<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>I</kbd>)
|
||||
and run <code>document.querySelector("#my-widget")</code>. If the element
|
||||
is found, the widget is functioning correctly. If <code>undefined</code> is
|
||||
returned, double-check that the <a href="#root/_help_BFs8mudNFgCS">note</a> has
|
||||
the <code>#widget</code> <a href="#root/_help_zEY4DaJG4YT5">attribute</a>.</p>
|
||||
<h3>Step 2: Adding an UI Element</h3>
|
||||
<p>Next, let's improve the widget by adding a button to it.</p><pre><code class="language-text-x-trilium-auto">const template = ``;
|
||||
<p>Next, let's improve the widget by adding a button to it.</p><pre><code class="language-text-x-trilium-auto">const template = `<div id="my-widget"><button>Click Me!</button></div>`;
|
||||
|
||||
class MyWidget extends api.BasicWidget {
|
||||
get position() {return 1;}
|
||||
@@ -47,7 +47,7 @@ module.exports = new MyWidget();</code></pre>
|
||||
<p>To make the button more visually appealing and position it correctly,
|
||||
we'll apply some custom styling. Trilium includes <a href="https://boxicons.com">Box Icons</a>,
|
||||
which we'll use to replace the button text with an icon. For example the <code>bx bxs-magic-wand</code> icon.</p>
|
||||
<p>Here's the updated template:</p><pre><code class="language-text-x-trilium-auto">const template = ``;</code></pre>
|
||||
<p>Here's the updated template:</p><pre><code class="language-text-x-trilium-auto">const template = `<div id="my-widget"><button class="tree-floating-button bx bxs-magic-wand tree-settings-button"></button></div>`;</code></pre>
|
||||
<p>Next, we'll adjust the button's position using CSS:</p><pre><code class="language-text-x-trilium-auto">class MyWidget extends api.BasicWidget {
|
||||
get position() { return 1; }
|
||||
get parentWidget() { return "left-pane"; }
|
||||
@@ -87,5 +87,17 @@ 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><code>left-pane</code> - This renders the widget on the left side of the
|
||||
screen where the note tree lives.</li>
|
||||
<li><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><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><code>right-pane</code> - This renders the widget to the right of any opened
|
||||
notes.</li>
|
||||
</ul>
|
||||
<p><a href="#root/_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 |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user