Compare commits
191 Commits
copilot/fi
...
copilot/im
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff4cd7eae5 | ||
|
|
a62c9a1a2f | ||
|
|
cf406383c3 | ||
|
|
b1729ad7ec | ||
|
|
daec11b981 | ||
|
|
25ac9e2aa1 | ||
|
|
3b02eb8851 | ||
|
|
a5a90b582a | ||
|
|
510601037d | ||
|
|
b312b6f3bc | ||
|
|
0c1efd3402 | ||
|
|
69182a1a42 | ||
|
|
8a63f2028c | ||
|
|
947330ed73 | ||
|
|
4526455486 | ||
|
|
1d259aab9d | ||
|
|
5171675dee | ||
|
|
6bc54892a3 | ||
|
|
0a6670ce5e | ||
|
|
beb7c66ff5 | ||
|
|
966e5a2ef3 | ||
|
|
4f5be54030 | ||
|
|
68c6260e45 | ||
|
|
85bfd49d1c | ||
|
|
23f2e1eb45 | ||
|
|
9bbd6d146b | ||
|
|
37aa8ec176 | ||
|
|
05f3f9627d | ||
|
|
a9fa99cadf | ||
|
|
d5c1604a58 | ||
|
|
e99f821e88 | ||
|
|
6571ff9d84 | ||
|
|
9d63ef20fb | ||
|
|
71a3cf0cfe | ||
|
|
e5e55e1cf1 | ||
|
|
83b13cae92 | ||
|
|
6663c3abc1 | ||
|
|
738b28c2b3 | ||
|
|
4eec6021c3 | ||
|
|
39bda30853 | ||
|
|
6adcaca5e0 | ||
|
|
5a5f71fc71 | ||
|
|
f3765f95b5 | ||
|
|
6ebb0eb03e | ||
|
|
b42aa32b72 | ||
|
|
11e1ea7ea5 | ||
|
|
5f6fac994f | ||
|
|
d7460e9fe5 | ||
|
|
89585e38ce | ||
|
|
938c6e356b | ||
|
|
b7dd806d07 | ||
|
|
a1d86cef58 | ||
|
|
1fec5bb564 | ||
|
|
35e98addc8 | ||
|
|
79290633b1 | ||
|
|
ffc9e715ef | ||
|
|
8f8302c4a3 | ||
|
|
136b449f60 | ||
|
|
61319c3a14 | ||
|
|
104a1f0c3a | ||
|
|
16200312ce | ||
|
|
664de68d53 | ||
|
|
6190949dcc | ||
|
|
3ac248169f | ||
|
|
15e240ac33 | ||
|
|
d30fc09e73 | ||
|
|
6a2b9b748f | ||
|
|
b5e2187c0d | ||
|
|
d9a349a531 | ||
|
|
2c1cebfbc3 | ||
|
|
c6738ac52f | ||
|
|
604f2abf5a | ||
|
|
617703899f | ||
|
|
6322ca11c9 | ||
|
|
d62aecc551 | ||
|
|
953b376ce3 | ||
|
|
80f1707d8b | ||
|
|
4f9f8652e2 | ||
|
|
6e06d7169f | ||
|
|
ecf12a4063 | ||
|
|
64428ae761 | ||
|
|
3524c34ff9 | ||
|
|
3f99c8b337 | ||
|
|
27d9ae885f | ||
|
|
35efd2a680 | ||
|
|
19c6ae6fe5 | ||
|
|
bf0761a303 | ||
|
|
8391fd7534 | ||
|
|
6d4b87888a | ||
|
|
3f0b0f9b62 | ||
|
|
859d9dcd04 | ||
|
|
76dd9baea8 | ||
|
|
82ff5f6660 | ||
|
|
b52d30c55a | ||
|
|
99fd088ff5 | ||
|
|
945f29c759 | ||
|
|
98f42887d8 | ||
|
|
a1b589148b | ||
|
|
66bb639a15 | ||
|
|
1784b50990 | ||
|
|
5e9c271bfd | ||
|
|
70837fdc69 | ||
|
|
67d80512f6 | ||
|
|
dd8a1e8aca | ||
|
|
99f43e2280 | ||
|
|
bcffa77c90 | ||
|
|
8ab2069411 | ||
|
|
21fc61d132 | ||
|
|
552df50fe4 | ||
|
|
c058b663ee | ||
|
|
6c19370235 | ||
|
|
d332bb57ba | ||
|
|
3ef38e7f4e | ||
|
|
1abc3b5534 | ||
|
|
ddcd27ddf6 | ||
|
|
ff385c8c88 | ||
|
|
a641e452ce | ||
|
|
5f4fa25da5 | ||
|
|
ea177e972e | ||
|
|
7e3013bfdc | ||
|
|
5115baeb21 | ||
|
|
35a924a05a | ||
|
|
78f067965f | ||
|
|
413b16b51c | ||
|
|
59586c53b2 | ||
|
|
70ed1d7abb | ||
|
|
67de6c614c | ||
|
|
faf030ab3a | ||
|
|
6e20d4b5dd | ||
|
|
10e809af75 | ||
|
|
f1478f8149 | ||
|
|
9087adf254 | ||
|
|
f944c6d8e2 | ||
|
|
444e103047 | ||
|
|
1d6ab64ae5 | ||
|
|
0bc86d7c75 | ||
|
|
cfd55147df | ||
|
|
754bb61a52 | ||
|
|
4f103375b5 | ||
|
|
496091677b | ||
|
|
618b67f551 | ||
|
|
9c791df0ed | ||
|
|
ce4f46c226 | ||
|
|
44cfbcf7f4 | ||
|
|
a317331551 | ||
|
|
eeec3e440d | ||
|
|
b06aa29ea3 | ||
|
|
9c3f9a524e | ||
|
|
1c832182d6 | ||
|
|
b58e1f146c | ||
|
|
bc86fb95b5 | ||
|
|
6c43db692e | ||
|
|
6ffce824d1 | ||
|
|
f1f8f34ef8 | ||
|
|
a0b19ce526 | ||
|
|
4cc9ba824d | ||
|
|
08e66c18e7 | ||
|
|
cf8089b07f | ||
|
|
f8c61ecde9 | ||
|
|
6d51da9b88 | ||
|
|
0ad95d00dc | ||
|
|
9819a92b48 | ||
|
|
55a7017e92 | ||
|
|
1581568741 | ||
|
|
d7982c65dd | ||
|
|
39608a2815 | ||
|
|
f656c2caaa | ||
|
|
bd3e92f091 | ||
|
|
7ce7c66463 | ||
|
|
61d26fec60 | ||
|
|
1822eea77c | ||
|
|
28c0e4e802 | ||
|
|
88d90fdedd | ||
|
|
2a1ecdbdca | ||
|
|
5772046674 | ||
|
|
1e2c8b2ac4 | ||
|
|
955b202b8a | ||
|
|
be98a27439 | ||
|
|
54200fa0cb | ||
|
|
5d82a26c87 | ||
|
|
e51070e389 | ||
|
|
e0dc4fee20 | ||
|
|
e683dc1d66 | ||
|
|
14a3438a20 | ||
|
|
dd483fccbc | ||
|
|
5620e7f4a7 | ||
|
|
187e9b57de | ||
|
|
d6d67e7957 | ||
|
|
bde03e8378 | ||
|
|
4c3fcdba4a | ||
|
|
7a5c1277f1 |
73
.github/workflows/deploy-docs.yml
vendored
@@ -1,6 +1,4 @@
|
||||
# GitHub Actions workflow for deploying MkDocs documentation to Cloudflare Pages
|
||||
# This workflow builds and deploys your MkDocs site when changes are pushed to main
|
||||
name: Deploy MkDocs Documentation
|
||||
name: Deploy Documentation
|
||||
|
||||
on:
|
||||
# Trigger on push to main branch
|
||||
@@ -11,11 +9,8 @@ on:
|
||||
# Only run when docs files change
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- 'README.md' # README is synced to docs/index.md
|
||||
- 'mkdocs.yml'
|
||||
- 'requirements-docs.txt'
|
||||
- '.github/workflows/deploy-docs.yml'
|
||||
- 'scripts/fix-mkdocs-structure.ts'
|
||||
- 'apps/edit-docs/**'
|
||||
- 'packages/share-theme/**'
|
||||
|
||||
# Allow manual triggering from Actions tab
|
||||
workflow_dispatch:
|
||||
@@ -27,15 +22,12 @@ on:
|
||||
- master
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- 'README.md' # README is synced to docs/index.md
|
||||
- 'mkdocs.yml'
|
||||
- 'requirements-docs.txt'
|
||||
- '.github/workflows/deploy-docs.yml'
|
||||
- 'scripts/fix-mkdocs-structure.ts'
|
||||
- 'apps/edit-docs/**'
|
||||
- 'packages/share-theme/**'
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
name: Build and Deploy MkDocs
|
||||
name: Build and Deploy Documentation
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
@@ -49,72 +41,25 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0 # Fetch all history for git info and mkdocs-git-revision-date plugin
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: '3.14'
|
||||
cache: 'pip'
|
||||
cache-dependency-path: 'requirements-docs.txt'
|
||||
|
||||
- name: Install MkDocs and Dependencies
|
||||
run: |
|
||||
pip install --upgrade pip
|
||||
pip install -r requirements-docs.txt
|
||||
env:
|
||||
PIP_DISABLE_PIP_VERSION_CHECK: 1
|
||||
|
||||
# Setup pnpm before fixing docs structure
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
# Setup Node.js with pnpm
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '24'
|
||||
cache: 'pnpm'
|
||||
|
||||
# Install Node.js dependencies for the TypeScript script
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
pnpm install --frozen-lockfile
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Fix Documentation Structure
|
||||
run: |
|
||||
# Fix duplicate navigation entries by moving overview pages to index.md
|
||||
pnpm run chore:fix-mkdocs-structure
|
||||
|
||||
- name: Build MkDocs Site
|
||||
run: |
|
||||
# Build with strict mode but allow expected warnings
|
||||
mkdocs build --verbose || {
|
||||
EXIT_CODE=$?
|
||||
# Check if the only issue is expected warnings
|
||||
if mkdocs build 2>&1 | grep -E "WARNING.*(README|not found)" && \
|
||||
[ $(mkdocs build 2>&1 | grep -c "ERROR") -eq 0 ]; then
|
||||
echo "✅ Build succeeded with expected warnings"
|
||||
mkdocs build --verbose
|
||||
else
|
||||
echo "❌ Build failed with unexpected errors"
|
||||
exit $EXIT_CODE
|
||||
fi
|
||||
}
|
||||
|
||||
- name: Fix HTML Links
|
||||
run: |
|
||||
# Remove .md extensions from links in generated HTML
|
||||
pnpm tsx ./scripts/fix-html-links.ts site
|
||||
- name: Trigger build of documentation
|
||||
run: pnpm docs:build
|
||||
|
||||
- name: Validate Built Site
|
||||
run: |
|
||||
# Basic validation that important files exist
|
||||
test -f site/index.html || (echo "ERROR: site/index.html not found" && exit 1)
|
||||
test -f site/sitemap.xml || (echo "ERROR: site/sitemap.xml not found" && exit 1)
|
||||
test -d site/assets || (echo "ERROR: site/assets directory not found" && exit 1)
|
||||
echo "✅ Site validation passed"
|
||||
|
||||
- name: Deploy
|
||||
uses: ./.github/actions/deploy-to-cloudflare-pages
|
||||
|
||||
6
.github/workflows/main-docker.yml
vendored
@@ -116,6 +116,12 @@ jobs:
|
||||
- dockerfile: Dockerfile
|
||||
platform: linux/arm64
|
||||
image: ubuntu-24.04-arm
|
||||
- dockerfile: Dockerfile.legacy
|
||||
platform: linux/arm/v7
|
||||
image: ubuntu-24.04-arm
|
||||
- dockerfile: Dockerfile.legacy
|
||||
platform: linux/arm/v8
|
||||
image: ubuntu-24.04-arm
|
||||
runs-on: ${{ matrix.image }}
|
||||
needs:
|
||||
- test_docker
|
||||
|
||||
@@ -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.9.2",
|
||||
"@types/yargs": "17.0.34",
|
||||
"@vitest/coverage-v8": "3.2.4",
|
||||
"eslint": "9.38.0",
|
||||
"eslint": "9.39.0",
|
||||
"eslint-plugin-simple-import-sort": "12.1.1",
|
||||
"esm": "3.2.25",
|
||||
"jsdoc": "4.0.5",
|
||||
"lorem-ipsum": "2.0.8",
|
||||
"rcedit": "4.0.1",
|
||||
"rimraf": "6.0.1",
|
||||
"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
@@ -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.19.0",
|
||||
"devDependencies": {
|
||||
"@redocly/cli": "2.10.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
@@ -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, {});
|
||||
127
apps/build-docs/src/build-docs.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
process.env.TRILIUM_INTEGRATION_TEST = "memory-no-store";
|
||||
process.env.TRILIUM_RESOURCE_DIR = "../server/src";
|
||||
process.env.NODE_ENV = "development";
|
||||
|
||||
import cls from "@triliumnext/server/src/services/cls.js";
|
||||
import { dirname, join, resolve } from "path";
|
||||
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 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);
|
||||
|
||||
const note = await importData(join(__dirname, DOCS_ROOT, "User Guide"));
|
||||
|
||||
// Export
|
||||
const zipFilePath = "output.zip";
|
||||
try {
|
||||
const { exportToZip } = (await import("@triliumnext/server/src/services/export/zip.js")).default;
|
||||
const branch = note.getParentBranches()[0];
|
||||
const taskContext = new (await import("@triliumnext/server/src/services/task_context.js")).default(
|
||||
"no-progress-reporting",
|
||||
"export",
|
||||
null
|
||||
);
|
||||
const fileOutputStream = fsExtra.createWriteStream(zipFilePath);
|
||||
await exportToZip(taskContext, branch, "share", fileOutputStream);
|
||||
await waitForStreamToFinish(fileOutputStream);
|
||||
await extractZip(zipFilePath, OUTPUT_DIR);
|
||||
} finally {
|
||||
if (await fsExtra.exists(zipFilePath)) {
|
||||
await fsExtra.rm(zipFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy favicon.
|
||||
await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "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 context = new TaskContext("no-progress-reporting", "importNotes", null);
|
||||
const becca = (await import("@triliumnext/server/src/becca/becca.js")).default;
|
||||
|
||||
const rootNote = becca.getRoot();
|
||||
if (!rootNote) {
|
||||
throw new Error("Missing root note for import.");
|
||||
}
|
||||
return await importService.importZip(context, buffer, rootNote, {
|
||||
preserveIds: true
|
||||
});
|
||||
}
|
||||
|
||||
async function createImportZip(path: string) {
|
||||
const inputFile = "input.zip";
|
||||
const archive = archiver("zip", {
|
||||
zlib: { level: 0 }
|
||||
});
|
||||
|
||||
console.log("Archive path is ", resolve(path))
|
||||
archive.directory(path, "/");
|
||||
|
||||
const outputStream = fsExtra.createWriteStream(inputFile);
|
||||
archive.pipe(outputStream);
|
||||
archive.finalize();
|
||||
await waitForStreamToFinish(outputStream);
|
||||
|
||||
try {
|
||||
return await fsExtra.readFile(inputFile);
|
||||
} finally {
|
||||
await fsExtra.rm(inputFile);
|
||||
}
|
||||
}
|
||||
|
||||
function waitForStreamToFinish(stream: WriteStream) {
|
||||
return new Promise<void>((res, rej) => {
|
||||
stream.on("finish", () => res());
|
||||
stream.on("error", (err) => rej(err));
|
||||
});
|
||||
}
|
||||
|
||||
export async function extractZip(zipFilePath: string, outputPath: string, ignoredFiles?: Set<string>) {
|
||||
const { readZipFile, readContent } = (await import("@triliumnext/server/src/services/import/zip.js"));
|
||||
await readZipFile(await fs.readFile(zipFilePath), async (zip, entry) => {
|
||||
// We ignore directories since they can appear out of order anyway.
|
||||
if (!entry.fileName.endsWith("/") && !ignoredFiles?.has(entry.fileName)) {
|
||||
const destPath = join(outputPath, entry.fileName);
|
||||
const fileContent = await readContent(zip, entry);
|
||||
|
||||
await fsExtra.mkdirs(dirname(destPath));
|
||||
await fs.writeFile(destPath, fileContent);
|
||||
}
|
||||
|
||||
zip.readEntry();
|
||||
});
|
||||
}
|
||||
|
||||
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
@@ -0,0 +1,4 @@
|
||||
export default interface BuildContext {
|
||||
gitRootDir: string;
|
||||
baseDir: string;
|
||||
}
|
||||
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();
|
||||
26
apps/build-docs/src/main.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { join } from "path";
|
||||
import BuildContext from "./context";
|
||||
import buildSwagger from "./swagger";
|
||||
import { 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);
|
||||
}
|
||||
|
||||
main();
|
||||
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.0",
|
||||
"@excalidraw/excalidraw": "0.18.0",
|
||||
"@fullcalendar/core": "6.1.19",
|
||||
"@fullcalendar/daygrid": "6.1.19",
|
||||
@@ -37,12 +37,12 @@
|
||||
"bootstrap": "5.3.8",
|
||||
"boxicons": "2.1.4",
|
||||
"color": "5.0.2",
|
||||
"dayjs": "1.11.18",
|
||||
"dayjs": "1.11.19",
|
||||
"dayjs-plugin-utc": "0.1.2",
|
||||
"debounce": "2.2.0",
|
||||
"draggabilly": "3.0.0",
|
||||
"force-graph": "1.51.0",
|
||||
"globals": "16.4.0",
|
||||
"globals": "16.5.0",
|
||||
"i18next": "25.6.0",
|
||||
"i18next-http-backend": "3.0.2",
|
||||
"jquery": "3.7.1",
|
||||
@@ -59,7 +59,7 @@
|
||||
"normalize.css": "8.0.1",
|
||||
"panzoom": "9.4.3",
|
||||
"preact": "10.27.2",
|
||||
"react-i18next": "16.2.1",
|
||||
"react-i18next": "16.2.3",
|
||||
"reveal.js": "5.2.1",
|
||||
"svg-pan-zoom": "3.6.2",
|
||||
"tabulator-tables": "6.3.1",
|
||||
@@ -76,7 +76,7 @@
|
||||
"@types/reveal.js": "5.2.1",
|
||||
"@types/tabulator-tables": "6.3.0",
|
||||
"copy-webpack-plugin": "13.0.1",
|
||||
"happy-dom": "20.0.8",
|
||||
"happy-dom": "20.0.10",
|
||||
"script-loader": "0.7.2",
|
||||
"vite-plugin-static-copy": "3.1.4"
|
||||
}
|
||||
|
||||
@@ -270,6 +270,7 @@ export type CommandMappings = {
|
||||
closeThisNoteSplit: CommandData;
|
||||
moveThisNoteSplit: CommandData & { isMovingLeft: boolean };
|
||||
jumpToNote: CommandData;
|
||||
openTodayNote: CommandData;
|
||||
commandPalette: CommandData;
|
||||
|
||||
// Keyboard shortcuts
|
||||
|
||||
@@ -159,6 +159,16 @@ export default class Entrypoints extends Component {
|
||||
this.openInWindowCommand({ notePath: "", hoistedNoteId: "root" });
|
||||
}
|
||||
|
||||
async openTodayNoteCommand() {
|
||||
const todayNote = await dateNoteService.getTodayNote();
|
||||
if (!todayNote) {
|
||||
console.warn("Missing today note.");
|
||||
return;
|
||||
}
|
||||
|
||||
await appContext.tabManager.openInSameTab(todayNote.noteId);
|
||||
}
|
||||
|
||||
async runActiveNoteCommand() {
|
||||
const noteContext = appContext.tabManager.getActiveContext();
|
||||
if (!noteContext) {
|
||||
|
||||
@@ -417,7 +417,7 @@ export default class FNote {
|
||||
return notePaths;
|
||||
}
|
||||
|
||||
getSortedNotePathRecords(hoistedNoteId = "root"): NotePathRecord[] {
|
||||
getSortedNotePathRecords(hoistedNoteId = "root", activeNotePath: string | null = null): NotePathRecord[] {
|
||||
const isHoistedRoot = hoistedNoteId === "root";
|
||||
|
||||
const notePaths: NotePathRecord[] = this.getAllNotePaths().map((path) => ({
|
||||
@@ -428,7 +428,23 @@ export default class FNote {
|
||||
isHidden: path.includes("_hidden")
|
||||
}));
|
||||
|
||||
// Calculate the length of the prefix match between two arrays
|
||||
const prefixMatchLength = (path: string[], target: string[]) => {
|
||||
const diffIndex = path.findIndex((seg, i) => seg !== target[i]);
|
||||
return diffIndex === -1 ? Math.min(path.length, target.length) : diffIndex;
|
||||
};
|
||||
|
||||
notePaths.sort((a, b) => {
|
||||
if (activeNotePath) {
|
||||
const activeSegments = activeNotePath.split('/');
|
||||
const aOverlap = prefixMatchLength(a.notePath, activeSegments);
|
||||
const bOverlap = prefixMatchLength(b.notePath, activeSegments);
|
||||
// Paths with more matching prefix segments are prioritized
|
||||
// when the match count is equal, other criteria are used for sorting
|
||||
if (bOverlap !== aOverlap) {
|
||||
return bOverlap - aOverlap;
|
||||
}
|
||||
}
|
||||
if (a.isInHoistedSubTree !== b.isInHoistedSubTree) {
|
||||
return a.isInHoistedSubTree ? -1 : 1;
|
||||
} else if (a.isArchived !== b.isArchived) {
|
||||
@@ -449,10 +465,11 @@ export default class FNote {
|
||||
* Returns the note path considered to be the "best"
|
||||
*
|
||||
* @param {string} [hoistedNoteId='root']
|
||||
* @param {string|null} [activeNotePath=null]
|
||||
* @return {string[]} array of noteIds constituting the particular note path
|
||||
*/
|
||||
getBestNotePath(hoistedNoteId = "root") {
|
||||
return this.getSortedNotePathRecords(hoistedNoteId)[0]?.notePath;
|
||||
getBestNotePath(hoistedNoteId = "root", activeNotePath: string | null = null) {
|
||||
return this.getSortedNotePathRecords(hoistedNoteId, activeNotePath)[0]?.notePath;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -26,21 +26,12 @@ async function resolveNotePathToSegments(notePath: string, hoistedNoteId = "root
|
||||
}
|
||||
|
||||
const path = notePath.split("/").reverse();
|
||||
|
||||
if (!path.includes("root")) {
|
||||
path.push("root");
|
||||
}
|
||||
|
||||
const effectivePathSegments: string[] = [];
|
||||
let childNoteId: string | null = null;
|
||||
let i = 0;
|
||||
|
||||
while (true) {
|
||||
if (i >= path.length) {
|
||||
break;
|
||||
}
|
||||
|
||||
const parentNoteId = path[i++];
|
||||
for (let i = 0; i < path.length; i++) {
|
||||
const parentNoteId = path[i];
|
||||
|
||||
if (childNoteId !== null) {
|
||||
const child = await froca.getNote(childNoteId, !logErrors);
|
||||
@@ -65,7 +56,7 @@ async function resolveNotePathToSegments(notePath: string, hoistedNoteId = "root
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!parents.some((p) => p.noteId === parentNoteId)) {
|
||||
if (!parents.some(p => p.noteId === parentNoteId) || (i === path.length - 1 && parentNoteId !== 'root')) {
|
||||
if (logErrors) {
|
||||
const parent = froca.getNoteFromCache(parentNoteId);
|
||||
|
||||
@@ -77,7 +68,8 @@ async function resolveNotePathToSegments(notePath: string, hoistedNoteId = "root
|
||||
);
|
||||
}
|
||||
|
||||
const bestNotePath = child.getBestNotePath(hoistedNoteId);
|
||||
const activeNotePath = appContext.tabManager.getActiveContextNotePath();
|
||||
const bestNotePath = child.getBestNotePath(hoistedNoteId, activeNotePath);
|
||||
|
||||
if (bestNotePath) {
|
||||
const pathToRoot = bestNotePath.reverse().slice(1);
|
||||
@@ -108,7 +100,9 @@ async function resolveNotePathToSegments(notePath: string, hoistedNoteId = "root
|
||||
if (!note) {
|
||||
throw new Error(`Unable to find note: ${notePath}.`);
|
||||
}
|
||||
const bestNotePath = note.getBestNotePath(hoistedNoteId);
|
||||
|
||||
const activeNotePath = appContext.tabManager.getActiveContextNotePath();
|
||||
const bestNotePath = note.getBestNotePath(hoistedNoteId, activeNotePath);
|
||||
|
||||
if (!bestNotePath) {
|
||||
throw new Error(`Did not find any path segments for '${note.toString()}', hoisted note '${hoistedNoteId}'`);
|
||||
|
||||
@@ -11,7 +11,11 @@ export function reloadFrontendApp(reason?: string) {
|
||||
logInfo(`Frontend app reload: ${reason}`);
|
||||
}
|
||||
|
||||
window.location.reload();
|
||||
if (isElectron()) {
|
||||
dynamicRequire("@electron/remote").BrowserWindow.getFocusedWindow()?.reload();
|
||||
} else {
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
export function restartDesktopApp() {
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import "normalize.css";
|
||||
import "boxicons/css/boxicons.min.css";
|
||||
import "@triliumnext/ckeditor5/src/theme/ck-content.css";
|
||||
import "@triliumnext/share-theme/styles/index.css";
|
||||
import "@triliumnext/share-theme/scripts/index.js";
|
||||
|
||||
async function ensureJQuery() {
|
||||
const $ = (await import("jquery")).default;
|
||||
(window as any).$ = $;
|
||||
}
|
||||
|
||||
async function formatCodeBlocks() {
|
||||
const anyCodeBlock = document.querySelector("#content pre");
|
||||
if (!anyCodeBlock) {
|
||||
return;
|
||||
}
|
||||
await ensureJQuery();
|
||||
const { formatCodeBlocks } = await import("./services/syntax_highlight.js");
|
||||
await formatCodeBlocks($("#content"));
|
||||
}
|
||||
|
||||
async function setupTextNote() {
|
||||
formatCodeBlocks();
|
||||
}
|
||||
@@ -716,7 +716,6 @@
|
||||
"backup_database_now": "نسخ اختياطي لقاعدة البيانات الان"
|
||||
},
|
||||
"etapi": {
|
||||
"wiki": "ويكي",
|
||||
"created": "تم الأنشاء",
|
||||
"actions": "أجراءات",
|
||||
"title": "ETAPI",
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
"bulk_actions_executed": "批量操作已成功执行。",
|
||||
"none_yet": "暂无操作 ... 通过点击上方的可用操作添加一个操作。",
|
||||
"labels": "标签",
|
||||
"relations": "关联关系",
|
||||
"relations": "关系",
|
||||
"notes": "笔记",
|
||||
"other": "其它"
|
||||
},
|
||||
@@ -104,7 +104,8 @@
|
||||
"export_status": "导出状态",
|
||||
"export_in_progress": "导出进行中:{{progressCount}}",
|
||||
"export_finished_successfully": "导出成功完成。",
|
||||
"format_pdf": "PDF - 用于打印或共享目的。"
|
||||
"format_pdf": "PDF - 用于打印或共享目的。",
|
||||
"share-format": "HTML 网页发布——采用与共享笔记相同的主题,但可发布为静态网站。"
|
||||
},
|
||||
"help": {
|
||||
"noteNavigation": "笔记导航",
|
||||
@@ -184,7 +185,8 @@
|
||||
},
|
||||
"import-status": "导入状态",
|
||||
"in-progress": "导入进行中:{{progress}}",
|
||||
"successful": "导入成功完成。"
|
||||
"successful": "导入成功完成。",
|
||||
"importZipRecommendation": "导入 ZIP 文件时,笔记层级将反映压缩文件内的子目录结构。"
|
||||
},
|
||||
"include_note": {
|
||||
"dialog_title": "包含笔记",
|
||||
@@ -1287,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": "目前还没有令牌。点击上面的按钮创建一个。",
|
||||
@@ -1557,7 +1555,9 @@
|
||||
"window-on-top": "保持此窗口置顶"
|
||||
},
|
||||
"note_detail": {
|
||||
"could_not_find_typewidget": "找不到类型为 '{{type}}' 的 typeWidget"
|
||||
"could_not_find_typewidget": "找不到类型为 '{{type}}' 的 typeWidget",
|
||||
"printing": "正在打印…",
|
||||
"printing_pdf": "正在导出为PDF…"
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "请输入笔记标题..."
|
||||
|
||||
@@ -104,7 +104,8 @@
|
||||
"export_status": "Exportstatus",
|
||||
"export_in_progress": "Export läuft: {{progressCount}}",
|
||||
"export_finished_successfully": "Der Export wurde erfolgreich abgeschlossen.",
|
||||
"format_pdf": "PDF - für Ausdrucke oder Teilen."
|
||||
"format_pdf": "PDF - für Ausdrucke oder Teilen.",
|
||||
"share-format": "HTML für die Web-Veröffentlichung – verwendet dasselbe Theme wie bei freigegebenen Notizen, kann jedoch als statische Website veröffentlicht werden."
|
||||
},
|
||||
"help": {
|
||||
"noteNavigation": "Notiz Navigation",
|
||||
@@ -1285,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.",
|
||||
|
||||
@@ -1453,10 +1453,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.",
|
||||
|
||||
@@ -104,7 +104,8 @@
|
||||
"export_status": "Estado de exportación",
|
||||
"export_in_progress": "Exportación en curso: {{progressCount}}",
|
||||
"export_finished_successfully": "La exportación finalizó exitosamente.",
|
||||
"format_pdf": "PDF - para propósitos de impresión o compartición."
|
||||
"format_pdf": "PDF - para propósitos de impresión o compartición.",
|
||||
"share-format": "HTML para publicación web: utiliza el mismo tema que se utiliza en las notas compartidas, pero se puede publicar como un sitio web estático."
|
||||
},
|
||||
"help": {
|
||||
"noteNavigation": "Navegación de notas",
|
||||
@@ -184,7 +185,8 @@
|
||||
},
|
||||
"import-status": "Estado de importación",
|
||||
"in-progress": "Importación en progreso: {{progress}}",
|
||||
"successful": "Importación finalizada exitosamente."
|
||||
"successful": "Importación finalizada exitosamente.",
|
||||
"importZipRecommendation": "Al importar un archivo ZIP, la jerarquía de notas reflejará la estructura de subdirectorios dentro del archivo comprimido."
|
||||
},
|
||||
"include_note": {
|
||||
"dialog_title": "Incluir nota",
|
||||
@@ -1444,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.",
|
||||
@@ -1714,7 +1712,9 @@
|
||||
"window-on-top": "Mantener esta ventana en la parte superior"
|
||||
},
|
||||
"note_detail": {
|
||||
"could_not_find_typewidget": "No se pudo encontrar typeWidget para el tipo '{{type}}'"
|
||||
"could_not_find_typewidget": "No se pudo encontrar typeWidget para el tipo '{{type}}'",
|
||||
"printing": "Impresión en curso...",
|
||||
"printing_pdf": "Exportando a PDF en curso.."
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "escriba el título de la nota aquí..."
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -132,10 +132,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.",
|
||||
|
||||
@@ -254,7 +254,8 @@
|
||||
"export_status": "エクスポート状況",
|
||||
"export_in_progress": "エクスポート処理中: {{progressCount}}",
|
||||
"export_finished_successfully": "エクスポートが正常に完了しました。",
|
||||
"format_pdf": "PDF - 印刷または共有目的に。"
|
||||
"format_pdf": "PDF - 印刷または共有目的に。",
|
||||
"share-format": "Web 公開用の HTML - 共有ノートで使用されるのと同じテーマを使用しますが、静的 Web サイトとして公開できます。"
|
||||
},
|
||||
"help": {
|
||||
"title": "チートシート",
|
||||
@@ -656,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": "Переименовать этот токен",
|
||||
|
||||
@@ -104,7 +104,8 @@
|
||||
"export_in_progress": "正在匯出:{{progressCount}}",
|
||||
"export_finished_successfully": "成功匯出。",
|
||||
"format_html": "HTML - 推薦,因為它保留了所有格式",
|
||||
"format_pdf": "PDF - 用於列印或與他人分享。"
|
||||
"format_pdf": "PDF - 用於列印或與他人分享。",
|
||||
"share-format": "HTML 網頁發佈——使用與共享筆記相同的佈景主題,但可發佈為靜態網站。"
|
||||
},
|
||||
"help": {
|
||||
"noteNavigation": "筆記導航",
|
||||
@@ -1280,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": "目前還沒有令牌。點擊上面的按鈕新增一個。",
|
||||
@@ -1298,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": "Токенів поки що немає. Натисніть кнопку вище, щоб створити його.",
|
||||
|
||||
@@ -79,8 +79,8 @@ export default function ExportDialog() {
|
||||
values={[
|
||||
{ value: "html", label: t("export.format_html_zip") },
|
||||
{ value: "markdown", label: t("export.format_markdown") },
|
||||
{ value: "opml", label: t("export.format_opml") },
|
||||
{ value: "share", label: t("export.share-format") }
|
||||
{ value: "share", label: t("export.share-format") },
|
||||
{ value: "opml", label: t("export.format_opml") }
|
||||
]}
|
||||
/>
|
||||
|
||||
|
||||
@@ -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>;
|
||||
@@ -48,19 +49,13 @@ export default function EtapiSettings() {
|
||||
message: t("etapi.token_created_message"),
|
||||
defaultValue: authToken
|
||||
});
|
||||
}, []);
|
||||
}, []);
|
||||
|
||||
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>
|
||||
@@ -123,7 +119,7 @@ function TokenList({ tokens }: { tokens: EtapiToken[] }) {
|
||||
text={t("etapi.rename_token")}
|
||||
onClick={() => renameCallback(etapiTokenId, name)}
|
||||
/>
|
||||
|
||||
|
||||
<ActionButton
|
||||
icon="bx bx-trash"
|
||||
text={t("etapi.delete_token")}
|
||||
|
||||
@@ -74,7 +74,6 @@ export default defineConfig(() => ({
|
||||
mobile: join(__dirname, "src", "mobile.ts"),
|
||||
login: join(__dirname, "src", "login.ts"),
|
||||
setup: join(__dirname, "src", "setup.ts"),
|
||||
share: join(__dirname, "src", "share.ts"),
|
||||
set_password: join(__dirname, "src", "set_password.ts"),
|
||||
runtime: join(__dirname, "src", "runtime.ts"),
|
||||
print: join(__dirname, "src", "print.tsx")
|
||||
@@ -84,7 +83,8 @@ export default defineConfig(() => ({
|
||||
chunkFileNames: "src/[name].js",
|
||||
assetFileNames: "src/[name].[ext]",
|
||||
manualChunks: {
|
||||
"ckeditor5": [ "@triliumnext/ckeditor5" ]
|
||||
"ckeditor5": [ "@triliumnext/ckeditor5" ],
|
||||
"boxicons": [ "../../node_modules/boxicons/css/boxicons.min.css" ]
|
||||
},
|
||||
},
|
||||
onwarn(warning, rollupWarn) {
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"@triliumnext/desktop": "workspace:*",
|
||||
"@types/fs-extra": "11.0.4",
|
||||
"copy-webpack-plugin": "13.0.1",
|
||||
"electron": "38.4.0",
|
||||
"electron": "38.5.0",
|
||||
"fs-extra": "11.3.2"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -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
|
||||
|
||||
28
apps/server/Dockerfile.legacy
Normal file
@@ -0,0 +1,28 @@
|
||||
FROM node:22.21.0-bullseye-slim AS builder
|
||||
RUN corepack enable
|
||||
|
||||
# Install native dependencies since we might be building cross-platform.
|
||||
WORKDIR /usr/src/app/build
|
||||
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:22.21.0-bullseye-slim
|
||||
# Install only runtime dependencies
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
gosu && \
|
||||
rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/cache/apt/*
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
COPY ./dist /usr/src/app
|
||||
RUN rm -rf /usr/src/app/node_modules/better-sqlite3
|
||||
COPY --from=builder /usr/src/app/node_modules/better-sqlite3 /usr/src/app/node_modules/better-sqlite3
|
||||
COPY ./start-docker.sh /usr/src/app
|
||||
|
||||
# Configure container
|
||||
EXPOSE 8080
|
||||
CMD [ "sh", "./start-docker.sh" ]
|
||||
HEALTHCHECK --start-period=10s CMD exec gosu node node /usr/src/app/docker_healthcheck.cjs
|
||||
@@ -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
|
||||
@@ -26,17 +26,18 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"better-sqlite3": "12.4.1",
|
||||
"html-to-text": "9.0.5",
|
||||
"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",
|
||||
"@triliumnext/commons": "workspace:*",
|
||||
"@triliumnext/express-partial-content": "workspace:*",
|
||||
"@triliumnext/turndown-plugin-gfm": "workspace:*",
|
||||
"@triliumnext/highlightjs": "workspace:*",
|
||||
"@triliumnext/turndown-plugin-gfm": "workspace:*",
|
||||
"@types/archiver": "7.0.0",
|
||||
"@types/better-sqlite3": "7.6.13",
|
||||
"@types/cls-hooked": "4.3.9",
|
||||
@@ -60,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.1",
|
||||
"bindings": "1.5.0",
|
||||
"bootstrap": "5.3.8",
|
||||
"chardet": "2.1.0",
|
||||
"chardet": "2.1.1",
|
||||
"cheerio": "1.1.2",
|
||||
"chokidar": "4.0.3",
|
||||
"cls-hooked": "4.2.2",
|
||||
"compression": "1.8.1",
|
||||
"cookie-parser": "1.4.7",
|
||||
"csrf-csrf": "3.2.2",
|
||||
"dayjs": "1.11.18",
|
||||
"dayjs": "1.11.19",
|
||||
"debounce": "2.2.0",
|
||||
"debug": "4.4.3",
|
||||
"ejs": "3.1.10",
|
||||
"electron": "38.4.0",
|
||||
"electron": "38.5.0",
|
||||
"electron-debug": "4.1.0",
|
||||
"electron-window-state": "5.0.3",
|
||||
"escape-html": "1.0.3",
|
||||
"express": "5.1.0",
|
||||
"express-http-proxy": "2.1.2",
|
||||
"express-openid-connect": "2.19.2",
|
||||
"express-rate-limit": "8.1.0",
|
||||
"express-rate-limit": "8.2.1",
|
||||
"express-session": "1.18.2",
|
||||
"file-uri-to-path": "2.0.0",
|
||||
"fs-extra": "11.3.2",
|
||||
@@ -109,7 +109,7 @@
|
||||
"mime-types": "3.0.1",
|
||||
"multer": "2.0.2",
|
||||
"normalize-strings": "1.1.1",
|
||||
"ollama": "0.6.0",
|
||||
"ollama": "0.6.2",
|
||||
"openai": "6.7.0",
|
||||
"rand-token": "1.0.1",
|
||||
"safe-compare": "1.1.4",
|
||||
@@ -122,7 +122,6 @@
|
||||
"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",
|
||||
|
||||
2
apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json
generated
vendored
|
Before Width: | Height: | Size: 168 KiB After Width: | Height: | Size: 168 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 172 KiB |
|
Before Width: | Height: | Size: 167 KiB After Width: | Height: | Size: 167 KiB |
|
Before Width: | Height: | Size: 237 KiB After Width: | Height: | Size: 237 KiB |
|
Before Width: | Height: | Size: 202 KiB After Width: | Height: | Size: 202 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 191 KiB After Width: | Height: | Size: 191 KiB |
@@ -1,6 +1,6 @@
|
||||
<figure class="image image_resized" style="width:63.68%;">
|
||||
<img style="aspect-ratio:1363/1364;" src="Introduction_image.png" width="1363"
|
||||
height="1364">
|
||||
<img style="aspect-ratio:1363/1364;" src="AI_image.png"
|
||||
width="1363" height="1364">
|
||||
<figcaption>An example chat with an LLM</figcaption>
|
||||
</figure>
|
||||
<p>The AI / LLM features within Trilium Notes are designed to allow you to
|
||||
@@ -11,13 +11,13 @@
|
||||
<p>The quickest way to get started is to navigate to the “AI/LLM” settings:</p>
|
||||
<figure
|
||||
class="image image_resized" style="width:74.04%;">
|
||||
<img style="aspect-ratio:1916/1906;" src="5_Introduction_image.png" width="1916"
|
||||
height="1906">
|
||||
<img style="aspect-ratio:1916/1906;" src="5_AI_image.png"
|
||||
width="1916" height="1906">
|
||||
</figure>
|
||||
<p>Enable the feature:</p>
|
||||
<figure class="image image_resized" style="width:82.82%;">
|
||||
<img style="aspect-ratio:1911/997;" src="1_Introduction_image.png" width="1911"
|
||||
height="997">
|
||||
<img style="aspect-ratio:1911/997;" src="1_AI_image.png"
|
||||
width="1911" height="997">
|
||||
</figure>
|
||||
|
||||
<h2>Embeddings</h2>
|
||||
@@ -43,30 +43,30 @@ class="image image_resized" style="width:74.04%;">
|
||||
We will then hit the “refresh” button to have it fetch our models:</p>
|
||||
<figure
|
||||
class="image image_resized" style="width:82.28%;">
|
||||
<img style="aspect-ratio:1912/1075;" src="4_Introduction_image.png" width="1912"
|
||||
height="1075">
|
||||
<img style="aspect-ratio:1912/1075;" src="4_AI_image.png"
|
||||
width="1912" height="1075">
|
||||
</figure>
|
||||
<p>When selecting the dropdown for the “Embedding Model”, embedding models
|
||||
should be at the top of the list, separated by regular chat models with
|
||||
a horizontal line, as seen below:</p>
|
||||
<figure class="image image_resized"
|
||||
style="width:61.73%;">
|
||||
<img style="aspect-ratio:1232/959;" src="8_Introduction_image.png" width="1232"
|
||||
height="959">
|
||||
<img style="aspect-ratio:1232/959;" src="8_AI_image.png"
|
||||
width="1232" height="959">
|
||||
</figure>
|
||||
<p>After selecting an embedding model, embeddings should automatically begin
|
||||
to be generated by checking the embedding statistics at the top of the
|
||||
“AI/LLM” settings panel:</p>
|
||||
<figure class="image image_resized" style="width:67.06%;">
|
||||
<img style="aspect-ratio:1333/499;" src="7_Introduction_image.png" width="1333"
|
||||
height="499">
|
||||
<img style="aspect-ratio:1333/499;" src="7_AI_image.png"
|
||||
width="1333" height="499">
|
||||
</figure>
|
||||
<p>If you don't see any embeddings being created, you will want to scroll
|
||||
to the bottom of the settings, and hit “Recreate All Embeddings”:</p>
|
||||
<figure
|
||||
class="image image_resized" style="width:65.69%;">
|
||||
<img style="aspect-ratio:1337/1490;" src="3_Introduction_image.png" width="1337"
|
||||
height="1490">
|
||||
<img style="aspect-ratio:1337/1490;" src="3_AI_image.png"
|
||||
width="1337" height="1490">
|
||||
</figure>
|
||||
<p>Creating the embeddings will take some time, and will be regenerated when
|
||||
a Note is created, updated, or deleted (removed).</p>
|
||||
@@ -139,8 +139,8 @@ class="image image_resized" style="width:74.04%;">
|
||||
<p>When Tools are executed within your Chat, you'll see output like the following:</p>
|
||||
<figure
|
||||
class="image image_resized" style="width:66.88%;">
|
||||
<img style="aspect-ratio:1372/1591;" src="6_Introduction_image.png" width="1372"
|
||||
height="1591">
|
||||
<img style="aspect-ratio:1372/1591;" src="6_AI_image.png"
|
||||
width="1372" height="1591">
|
||||
</figure>
|
||||
<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>
|
||||
@@ -149,13 +149,13 @@ class="image image_resized" style="width:74.04%;">
|
||||
use the “Chat with Notes” button, where you can go ahead and start chatting!:</p>
|
||||
<figure
|
||||
class="image image_resized" style="width:60.77%;">
|
||||
<img style="aspect-ratio:1378/539;" src="2_Introduction_image.png" width="1378"
|
||||
height="539">
|
||||
<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%;">
|
||||
<img style="aspect-ratio:1765/1287;" src="9_Introduction_image.png" width="1765"
|
||||
height="1287">
|
||||
<img style="aspect-ratio:1765/1287;" src="9_AI_image.png"
|
||||
width="1765" height="1287">
|
||||
</figure>
|
||||
|
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 186 KiB |
@@ -11,12 +11,12 @@
|
||||
<p>To set your preferred chat model, you'll want to enter the provider's
|
||||
name here:</p>
|
||||
<figure class="image image_resized" style="width:88.38%;">
|
||||
<img style="aspect-ratio:1884/1267;" src="AI Provider Information_im.png"
|
||||
<img style="aspect-ratio:1884/1267;" src="Providers_image.png"
|
||||
width="1884" height="1267">
|
||||
</figure>
|
||||
<p>And to set your preferred embedding provider:</p>
|
||||
<figure class="image image_resized"
|
||||
style="width:93.47%;">
|
||||
<img style="aspect-ratio:1907/1002;" src="1_AI Provider Information_im.png"
|
||||
<img style="aspect-ratio:1907/1002;" src="1_Providers_image.png"
|
||||
width="1907" height="1002">
|
||||
</figure>
|
||||
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 270 KiB After Width: | Height: | Size: 270 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 89 KiB |
@@ -9,8 +9,8 @@ class="image image_resized" style="width:50.49%;">
|
||||
width="785" height="498">
|
||||
</figure>
|
||||
<figure class="image image_resized" style="width:40.54%;">
|
||||
<img style="aspect-ratio:467/100;" src="Installing Ollama_image.png" width="467"
|
||||
height="100">
|
||||
<img style="aspect-ratio:467/100;" src="Installing Ollama_image.png"
|
||||
width="467" height="100">
|
||||
</figure>
|
||||
<figure class="image image_resized" style="width:55.73%;">
|
||||
<img style="aspect-ratio:1296/1011;" src="1_Installing Ollama_image.png"
|
||||
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 198 KiB After Width: | Height: | Size: 198 KiB |
|
Before Width: | Height: | Size: 175 KiB After Width: | Height: | Size: 175 KiB |
@@ -10,9 +10,9 @@
|
||||
and arbitrary tags - whenever you change tag attribute in the task note,
|
||||
this task is then automatically moved to appropriate location.</p>
|
||||
<p>Task Manager also integrates with <a href="#root/_help_l0tKav7yLHGF">day notes</a> -
|
||||
notes are <a href="#root/_help_IakOLONlIfGI">cloned</a> into day note to
|
||||
both todoDate note and doneDate note (with <a href="#root/_help_kBrnXNG3Hplm">prefix</a> of
|
||||
either "TODO" or "DONE").</p>
|
||||
notes are <a href="#root/_help_IakOLONlIfGI">cloned</a> into day note to both todoDate
|
||||
note and doneDate note (with <a href="#root/_help_kBrnXNG3Hplm">prefix</a> of either
|
||||
"TODO" or "DONE").</p>
|
||||
<h2>Implementation</h2>
|
||||
<p>New tasks are created in the TODO note which has <code>~child:template</code>
|
||||
<a
|
||||
@@ -22,9 +22,9 @@
|
||||
<p>Task template defines several <a href="#root/_help_OFXdgB2nNk1F">promoted attributes</a> -
|
||||
todoDate, doneDate, tags, location. Importantly it also defines <code>~runOnAttributeChange</code> relation
|
||||
- <a href="#root/_help_GPERMystNGTB">event</a> handler which is run on attribute
|
||||
change. This <a href="#root/_help_CdNpE2pqjmI6">script</a> handles when e.g.
|
||||
we fill out the doneDate attribute - meaning the task is done and should
|
||||
be moved to "Done" note and removed from TODO, locations and tags.</p>
|
||||
change. This <a href="#root/_help_CdNpE2pqjmI6">script</a> handles when e.g. we
|
||||
fill out the doneDate attribute - meaning the task is done and should be
|
||||
moved to "Done" note and removed from TODO, locations and tags.</p>
|
||||
<h3>New task button</h3>
|
||||
<p>There's also "button" note which contains simple script which adds a button
|
||||
to create new note (task) in the TODO note.</p><pre><code class="language-text-x-trilium-auto">api.addButtonToToolbar({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<figure class="image">
|
||||
<img style="aspect-ratio:1071/146;" src="Attributes_image.png" width="1071"
|
||||
height="146">
|
||||
<img style="aspect-ratio:1071/146;" src="Attributes_image.png"
|
||||
width="1071" height="146">
|
||||
</figure>
|
||||
<p>In Trilium, attributes are key-value pairs assigned to notes, providing
|
||||
additional metadata or functionality. There are two primary types of attributes:</p>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<p>Inheritance refers to the process of having a <a href="#root/_help_HI6GBBIduIgv">label</a> or
|
||||
a <a href="#root/_help_Cq5X6iKQop6R">relation</a> shared across multiple
|
||||
notes, generally in parent-child relations (or anywhere if using templates).</p>
|
||||
a <a href="#root/_help_Cq5X6iKQop6R">relation</a> shared across multiple notes,
|
||||
generally in parent-child relations (or anywhere if using templates).</p>
|
||||
<h2>Standard Inheritance</h2>
|
||||
<p>In Trilium, attributes can be automatically inherited by child notes if
|
||||
they have the <code>isInheritable</code> flag set to <code>true</code>. This
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<p>A label is an <a href="#root/_help_zEY4DaJG4YT5">attribute</a> of a note
|
||||
which has a name and optionally a value.</p>
|
||||
<p>A label is an <a href="#root/_help_zEY4DaJG4YT5">attribute</a> of a note which
|
||||
has a name and optionally a value.</p>
|
||||
<h2>Common use cases</h2>
|
||||
<ul>
|
||||
<li><strong>Metadata for personal use</strong>: Assign labels with optional
|
||||
@@ -81,8 +81,7 @@
|
||||
<td><code>calendarRoot</code>
|
||||
</td>
|
||||
<td>Marks the note which should be used as root for <a class="reference-link"
|
||||
href="#root/_help_l0tKav7yLHGF">Day Notes</a>. Only one should be marked
|
||||
as such.</td>
|
||||
href="#root/_help_l0tKav7yLHGF">Day Notes</a>. Only one should be marked as such.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>archived</code>
|
||||
@@ -154,8 +153,8 @@
|
||||
<tr>
|
||||
<td><code>autoReadOnlyDisabled</code>
|
||||
</td>
|
||||
<td>Disables automatic <a href="#root/_help_CoFPLs3dRlXc">read-only mode</a> for
|
||||
the given note.</td>
|
||||
<td>Disables automatic <a href="#root/_help_CoFPLs3dRlXc">read-only mode</a> for the
|
||||
given note.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>appCss</code>
|
||||
@@ -177,8 +176,7 @@
|
||||
<td>Set to <code>next</code>, <code>next-light</code>, or <code>next-dark</code> to
|
||||
use the corresponding TriliumNext theme (auto, light or dark) as the base
|
||||
for a custom theme, instead of the legacy one. See <a class="reference-link"
|
||||
href="#root/_help_WFGzWeUK6arS">Customize the Next theme</a> for more
|
||||
information.</td>
|
||||
href="#root/_help_WFGzWeUK6arS">Customize the Next theme</a> for more information.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>cssClass</code>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<p>A relation is similar to a <a href="#root/_help_HI6GBBIduIgv">label</a>,
|
||||
but instead of having a text value it refers to another note.</p>
|
||||
<p>A relation is similar to a <a href="#root/_help_HI6GBBIduIgv">label</a>, but
|
||||
instead of having a text value it refers to another note.</p>
|
||||
<h2>Common use cases</h2>
|
||||
<ul>
|
||||
<li><strong>Metadata Relationships for personal use</strong>: For example,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<figure class="image">
|
||||
<img style="aspect-ratio:1425/654;" src="Bulk Actions_image.png" width="1425"
|
||||
height="654">
|
||||
<img style="aspect-ratio:1425/654;" src="Bulk Actions_image.png"
|
||||
width="1425" height="654">
|
||||
</figure>
|
||||
<p>The <em>Bulk Actions</em> dialog makes it easy to apply changes to multiple
|
||||
notes at once, ranging from simple actions such as adding or removing a
|
||||
@@ -8,8 +8,8 @@
|
||||
<h2>Interaction</h2>
|
||||
<ul>
|
||||
<li>The first step is to select the notes in the <a class="reference-link"
|
||||
href="#root/_help_oPVyFC7WL2Lp">Note Tree</a>. It's possible to apply bulk
|
||||
actions to:
|
||||
href="#root/_help_oPVyFC7WL2Lp">Note Tree</a>. It's possible to apply bulk actions
|
||||
to:
|
||||
<ul>
|
||||
<li>A single note (and potentially its child notes) simply by clicking on
|
||||
it (with a left click or a right click).</li>
|
||||
@@ -53,17 +53,17 @@
|
||||
</li>
|
||||
<li><strong>Update label value</strong>
|
||||
<ul>
|
||||
<li>For each note, if it has a <a href="#root/_help_HI6GBBIduIgv">label</a> of
|
||||
the given name, it will change its value to the specified one. Leave <em>New value</em> field
|
||||
<li>For each note, if it has a <a href="#root/_help_HI6GBBIduIgv">label</a> of the
|
||||
given name, it will change its value to the specified one. Leave <em>New value</em> field
|
||||
empty to create a label without a value.</li>
|
||||
<li>Notes without the label will not be affected.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><em><strong>Rename label</strong></em>
|
||||
<ul>
|
||||
<li>For each note, if it has a <a href="#root/_help_HI6GBBIduIgv">label</a> of
|
||||
the given name, it will be renamed/replaced with a label of the new name.
|
||||
The value of the label (if present) will be kept intact.</li>
|
||||
<li>For each note, if it has a <a href="#root/_help_HI6GBBIduIgv">label</a> of the
|
||||
given name, it will be renamed/replaced with a label of the new name. The
|
||||
value of the label (if present) will be kept intact.</li>
|
||||
<li>Notes without the label will not be affected.</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<p>A Trilium instance represents a server. If <a class="reference-link"
|
||||
href="#root/_help_cbkrhQjrkKrh">Synchronization</a> is set up, since
|
||||
multiple servers are involved (the one from the desktop client and the
|
||||
one the synchronisation is set up with), sometimes it can be useful to
|
||||
distinguish the instance you are running on.</p>
|
||||
href="#root/_help_cbkrhQjrkKrh">Synchronization</a> is set up, since multiple
|
||||
servers are involved (the one from the desktop client and the one the synchronisation
|
||||
is set up with), sometimes it can be useful to distinguish the instance
|
||||
you are running on.</p>
|
||||
<h2>Setting the instance name</h2>
|
||||
<p>To set up a name for the instance, modify the <code>config.ini</code>:</p><pre><code class="language-text-x-trilium-auto">[General]
|
||||
instanceName=Hello</code></pre>
|
||||
|
||||
@@ -23,5 +23,5 @@
|
||||
<p>If you do not need to preserve any configurations that might be stored
|
||||
in the <code>config.ini</code> file, you can just delete all of the <a href="#root/_help_tAassRL4RSQL">data directory's</a> contents
|
||||
to fully restore the application to its original state. You can also review
|
||||
the <a href="#root/_help_Gzjqa934BdH4">configuration</a> file to provide
|
||||
all <code>config.ini</code> values as environment variables instead.</p>
|
||||
the <a href="#root/_help_Gzjqa934BdH4">configuration</a> file to provide all <code>config.ini</code> values
|
||||
as environment variables instead.</p>
|
||||
@@ -1,11 +1,13 @@
|
||||
<aside class="admonition tip">
|
||||
<p>For a quick start, consult the <a class="reference-link" href="#root/pgxEVkzLl1OP/_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>
|
||||
<ul>
|
||||
<li><a href="https://github.com/Nriver/trilium-py">trilium-py</a>, you can
|
||||
<li data-list-item-id="e3342ddfa108f6c8c6c47d7d3da8b02fa"><a href="https://github.com/Nriver/trilium-py">trilium-py</a>, you can
|
||||
use Python to communicate with Trilium.</li>
|
||||
</ul>
|
||||
<h2>Obtaining a token</h2>
|
||||
@@ -23,10 +25,10 @@ Authorization: ETAPITOKEN</code></pre>
|
||||
<p>Since v0.56 you can also use basic auth format:</p><pre><code class="language-text-x-trilium-auto">GET https://myserver.com/etapi/app-info
|
||||
Authorization: Basic BATOKEN</code></pre>
|
||||
<ul>
|
||||
<li>Where <code>BATOKEN = BASE64(username + ':' + password)</code> - this is
|
||||
<li data-list-item-id="ec59ac570a3d2a846da38378a5f2428ed">Where <code>BATOKEN = BASE64(username + ':' + password)</code> - this is
|
||||
a standard Basic Auth serialization</li>
|
||||
<li>Where <code>username</code> is "etapi"</li>
|
||||
<li>And <code>password</code> is the generated ETAPI token described above.</li>
|
||||
<li data-list-item-id="e18e2e73ebecc949dd4a51cd9f8bb0b91">Where <code>username</code> is "etapi"</li>
|
||||
<li data-list-item-id="ee892223f95cef4a53caec5477ab31edb">And <code>password</code> is the generated ETAPI token described above.</li>
|
||||
</ul>
|
||||
<p>Basic Auth is meant to be used with tools which support only basic auth.</p>
|
||||
<h2>Interaction using Bash scripts</h2>
|
||||
@@ -42,10 +44,10 @@ NOTE_ID="i6ra4ZshJhgN"
|
||||
curl "$SERVER/etapi/notes/$NOTE_ID/content" -H "Authorization: $TOKEN" </code></pre>
|
||||
<p>Make sure to replace the values of:</p>
|
||||
<ul>
|
||||
<li><code>TOKEN</code> with your ETAPI token.</li>
|
||||
<li><code>SERVER</code> with the correct protocol, host name and port to your
|
||||
<li data-list-item-id="e68020f83acc951e180bb405d149a64a5"><code>TOKEN</code> with your ETAPI token.</li>
|
||||
<li data-list-item-id="ef4c31df5f6d18811e7de0ee8ff95f3a7"><code>SERVER</code> with the correct protocol, host name and port to your
|
||||
Trilium instance.</li>
|
||||
<li><code>NOTE_ID</code> with an existing note ID to download.</li>
|
||||
<li data-list-item-id="e25086bb4c54d32259f987f9366e22204"><code>NOTE_ID</code> with an existing note ID to download.</li>
|
||||
</ul>
|
||||
<p>As another example, to obtain a .zip export of a note and place it in
|
||||
a directory called <code>out</code>, simply replace the last statement in
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<figure class="image image-style-align-right">
|
||||
<img style="aspect-ratio:263/445;" src="Hidden Notes_image.png" width="263"
|
||||
height="445">
|
||||
<img style="aspect-ratio:263/445;" src="Hidden Notes_image.png"
|
||||
width="263" height="445">
|
||||
</figure>
|
||||
<p>For easy extensibility, a lot of features in Trilium make use of actual
|
||||
notes to store information as opposed to having them stored in a separate
|
||||
@@ -8,14 +8,13 @@
|
||||
href="#root/_help_zEY4DaJG4YT5">Attributes</a>, <a class="reference-link"
|
||||
href="#root/_help_Cq5X6iKQop6R">Relations</a> or even <a class="reference-link"
|
||||
href="#root/_help_eIg8jdvaoNNd">Search</a> and <a class="reference-link"
|
||||
href="#root/_help_QEAPj01N5f7w">Links</a> to be able to operate on
|
||||
them.</p>
|
||||
href="#root/_help_QEAPj01N5f7w">Links</a> to be able to operate on them.</p>
|
||||
<p>As the name suggests, these notes are hidden to the user by default to
|
||||
prevent cluttering the note tree and to prevent them from being accidentally
|
||||
deleted.</p>
|
||||
<p>The hidden notes are stored in the user's <a class="reference-link"
|
||||
href="#root/_help_wX4HbRucYSDD">Database</a> just like normal notes,
|
||||
but they have a unique <a class="reference-link" href="#root/_help_m1lbrzyKDaRB">Note ID</a> which
|
||||
href="#root/_help_wX4HbRucYSDD">Database</a> just like normal notes, but
|
||||
they have a unique <a class="reference-link" href="#root/_help_m1lbrzyKDaRB">Note ID</a> which
|
||||
allows them to be distinguished from the normal ones.</p>
|
||||
<h2>Accessing the hidden note tree</h2>
|
||||
<p>From the <a class="reference-link" href="#root/_help_x3i7MxGccDuM">Global menu</a>,
|
||||
@@ -51,8 +50,8 @@ class="ck-table-resized">
|
||||
</td>
|
||||
<td>
|
||||
<p>When SQL queries or commands are executed in the <a class="reference-link"
|
||||
href="#root/_help_YKWqdJhzi2VY">SQL Console</a>, they are stored here,
|
||||
grouped by month. Only the query is stored and not the results.</p>
|
||||
href="#root/_help_YKWqdJhzi2VY">SQL Console</a>, they are stored here, grouped
|
||||
by month. Only the query is stored and not the results.</p>
|
||||
<p>This section can be accessed without going to the hidden tree by simply
|
||||
going to the <a class="reference-link" href="#root/_help_x3i7MxGccDuM">Global menu</a> and
|
||||
selecting Advanced → Open SQL Console History.</p>
|
||||
@@ -65,9 +64,8 @@ class="ck-table-resized">
|
||||
</td>
|
||||
<td>
|
||||
<p>Whenever a search is executed from the full <a class="reference-link"
|
||||
href="#root/_help_eIg8jdvaoNNd">Search</a>, the query will be stored here,
|
||||
grouped by month. Only the search parameters are stored and not the results
|
||||
themselves.</p>
|
||||
href="#root/_help_eIg8jdvaoNNd">Search</a>, the query will be stored here, grouped
|
||||
by month. Only the search parameters are stored and not the results themselves.</p>
|
||||
<p>This section can be accessed without going to the hidden tree by simply
|
||||
going to the <a class="reference-link" href="#root/_help_x3i7MxGccDuM">Global menu</a> and
|
||||
selecting Advanced → Open Search History.</p>
|
||||
|
||||
12
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Metrics.html
generated
vendored
@@ -82,18 +82,18 @@ trilium_notes_total 1234 1701432000
|
||||
</ul>
|
||||
<h2><strong>Grafana Dashboard</strong></h2>
|
||||
<figure class="image">
|
||||
<img style="aspect-ratio:2594/1568;" src="1_Metrics_image.png" width="2594"
|
||||
height="1568">
|
||||
<img style="aspect-ratio:2594/1568;" src="1_Metrics_image.png"
|
||||
width="2594" height="1568">
|
||||
</figure>
|
||||
<p>You can also use the Grafana Dashboard that has been created for TriliumNext
|
||||
- just take the JSON from <a class="reference-link" href="#root/_help_bOP3TB56fL1V">grafana-dashboard.json</a> and
|
||||
then import the dashboard, following these screenshots:</p>
|
||||
<figure class="image">
|
||||
<img style="aspect-ratio:1881/282;" src="2_Metrics_image.png" width="1881"
|
||||
height="282">
|
||||
<img style="aspect-ratio:1881/282;" src="2_Metrics_image.png"
|
||||
width="1881" height="282">
|
||||
</figure>
|
||||
<p>Then paste the JSON, and hit load:</p>
|
||||
<figure class="image">
|
||||
<img style="aspect-ratio:1055/830;" src="Metrics_image.png" width="1055"
|
||||
height="830">
|
||||
<img style="aspect-ratio:1055/830;" src="Metrics_image.png"
|
||||
width="1055" height="830">
|
||||
</figure>
|
||||
@@ -6,7 +6,16 @@
|
||||
<li>Note Map, which shows the hierarchical tree structure.</li>
|
||||
</ul>
|
||||
<h2>Link Map</h2>
|
||||
<p>Shows <a href="#root/_help_zEY4DaJG4YT5">relations</a> between notes:</p>
|
||||
<p>The Link map is a visualization of links and <a class="reference-link"
|
||||
href="#root/_help_Cq5X6iKQop6R">Relations</a> incoming to and outgoing from
|
||||
a particular note.</p>
|
||||
<p>The map indicates the following types of relations:</p>
|
||||
<ul>
|
||||
<li><a class="reference-link" href="#root/_help_hrZ1D00cLbal">Internal (reference) links</a> between
|
||||
notes.</li>
|
||||
<li><a class="reference-link" href="#root/_help_Cq5X6iKQop6R">Relations</a>
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
<img src="1_Note Map (Link map, Tree m.png">
|
||||
</p>
|
||||
@@ -21,8 +30,8 @@
|
||||
in full screen. See <a href="#root/_help_bdUJEHsAPYQR">Note Map</a> for
|
||||
more information.</p>
|
||||
<h2>See also</h2>
|
||||
<p><a href="#root/_help_iRwzGnHPzonm">Relation map</a> is a similar concept,
|
||||
with some differences:</p>
|
||||
<p><a href="#root/_help_iRwzGnHPzonm">Relation map</a> is a similar concept, with
|
||||
some differences:</p>
|
||||
<ul>
|
||||
<li>note map is automatically generated while relation map must be created
|
||||
manually</li>
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
<ul>
|
||||
<li><a class="reference-link" href="#root/_help_iPIMuisry3hd">Text</a> notes are
|
||||
represented internally as HTML, using the <a class="reference-link"
|
||||
href="#root/_help_MI26XDLSAlCD">CKEditor</a> representation. Note
|
||||
that due to the custom plugins, some HTML elements are specific to Trilium
|
||||
only, for example the admonitions.</li>
|
||||
href="#root/_help_MI26XDLSAlCD">CKEditor</a> representation. Note that due
|
||||
to the custom plugins, some HTML elements are specific to Trilium only,
|
||||
for example the admonitions.</li>
|
||||
<li><a class="reference-link" href="#root/_help_6f9hih2hXXZk">Code</a> notes are
|
||||
plain text and are represented internally as-is.</li>
|
||||
<li><a class="reference-link" href="#root/_help_81SGnPGMk7Xc">Geo Map</a> notes
|
||||
@@ -22,10 +22,10 @@
|
||||
</ul>
|
||||
<p>Note that some information is also stored as <a class="reference-link"
|
||||
href="#root/_help_0vhv7lsOLy82">Attachments</a>. For example <a class="reference-link"
|
||||
href="#root/_help_grjYqerjn243">Canvas</a> notes use the attachments
|
||||
feature to store the custom libraries, and alongside with <a class="reference-link"
|
||||
href="#root/_help_gBbsAeiuUxI5">Mind Map</a> and other similar note
|
||||
types it stores an SVG representation of the content for use in other features
|
||||
href="#root/_help_grjYqerjn243">Canvas</a> notes use the attachments feature
|
||||
to store the custom libraries, and alongside with <a class="reference-link"
|
||||
href="#root/_help_gBbsAeiuUxI5">Mind Map</a> and other similar note types
|
||||
it stores an SVG representation of the content for use in other features
|
||||
such as including in other notes, shared notes, etc.</p>
|
||||
<p>Here's part of the HTML representation of this note, as it's stored in
|
||||
the database (but prettified).</p><pre><code class="language-text-x-trilium-auto"><h2>
|
||||
|
||||
144
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing.html
generated
vendored
@@ -3,8 +3,8 @@
|
||||
from your Trilium notes, making it accessible to others online.</p>
|
||||
<figure
|
||||
class="image">
|
||||
<img style="aspect-ratio:1144/660;" src="Sharing_image.png" width="1144"
|
||||
height="660">
|
||||
<img style="aspect-ratio:1144/660;" src="Sharing_image.png"
|
||||
width="1144" height="660">
|
||||
</figure>
|
||||
|
||||
<h2>Features, interaction and limitations</h2>
|
||||
@@ -149,7 +149,7 @@ class="image">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><a class="reference-link" href="#root/_help_81SGnPGMk7Xc">Geo Map View</a>
|
||||
<th><a class="reference-link" href="#root/_help_81SGnPGMk7Xc">Geo Map</a>
|
||||
</th>
|
||||
<td>Not supported.</td>
|
||||
<td> </td>
|
||||
@@ -177,8 +177,8 @@ class="image">
|
||||
<p>Some of these limitations may be addressed in future updates.</p>
|
||||
<h2>Prerequisites</h2>
|
||||
<p>To use the sharing feature, you must have a <a class="reference-link"
|
||||
href="#root/_help_WOcw2SLH6tbX">Server Installation</a> of Trilium.
|
||||
This is necessary because the notes will be hosted from the server.</p>
|
||||
href="#root/_help_WOcw2SLH6tbX">Server Installation</a> of Trilium. This
|
||||
is necessary because the notes will be hosted from the server.</p>
|
||||
<h2>Sharing a note</h2>
|
||||
<ol>
|
||||
<li>
|
||||
@@ -186,7 +186,8 @@ class="image">
|
||||
within the note's interface. Once sharing is enabled, an URL will appear,
|
||||
which you can click to access the shared note.</p>
|
||||
<p>
|
||||
<img src="Sharing_share-single-note.png" alt="Share Note">
|
||||
<img src="Sharing_share-single-note.png"
|
||||
alt="Share Note">
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
@@ -207,9 +208,19 @@ class="image">
|
||||
This allows you to manage and navigate through all the notes you have made
|
||||
public.</p>
|
||||
<h2>Security considerations</h2>
|
||||
<p>Shared notes are published on the open internet and can be accessed by
|
||||
anyone with the URL. The URL's randomness does not provide security, so
|
||||
it is crucial not to share sensitive information through this feature.</p>
|
||||
<ul>
|
||||
<li>Shared notes are published on the open internet and can be accessed by
|
||||
anyone with the URL unless the notes are password-protected.</li>
|
||||
<li>The URL's randomness does not provide security, so it is crucial not to
|
||||
share sensitive information through this feature.</li>
|
||||
<li>Trilium takes precautions to protect your publicly shared instance from
|
||||
leaking information for non-shared notes, including opening a separate
|
||||
read-only connection to the <a class="reference-link" href="#root/_help_wX4HbRucYSDD">Database</a>.
|
||||
Depending on your threat model, it might make more sense to use
|
||||
<a
|
||||
class="reference-link" href="#root/_help_ycBFjKrrwE9p">Exporting HTML for web publishing</a> and use battle-tested web servers
|
||||
such as Nginx or Apache to serve static content.</li>
|
||||
</ul>
|
||||
<h3>Password protection</h3>
|
||||
<p>To protect shared notes with a username and password, you can use the <code>#shareCredentials</code> attribute.
|
||||
Add this label to the note with the format <code>#shareCredentials="username:password"</code>.
|
||||
@@ -220,10 +231,10 @@ class="image">
|
||||
it using your own CSS:</p>
|
||||
<ul>
|
||||
<li><strong>Custom CSS</strong>: Link a CSS <a class="reference-link"
|
||||
href="#root/_help_6f9hih2hXXZk">Code</a> note to the shared page by
|
||||
adding a <code>~shareCss</code> relation to the note. If you want this style
|
||||
to apply to the entire subtree, make the label inheritable. You can hide
|
||||
the CSS code note from the tree navigation by adding the <code>#shareHiddenFromTree</code> label.</li>
|
||||
href="#root/_help_6f9hih2hXXZk">Code</a> note to the shared page by adding
|
||||
a <code>~shareCss</code> relation to the note. If you want this style to
|
||||
apply to the entire subtree, make the label inheritable. You can hide the
|
||||
CSS code note from the tree navigation by adding the <code>#shareHiddenFromTree</code> label.</li>
|
||||
<li><strong>Omitting Default CSS</strong>: For extensive styling changes,
|
||||
use the <code>#shareOmitDefaultCss</code> label to avoid conflicts with Trilium's
|
||||
<a
|
||||
@@ -279,6 +290,15 @@ for (const attr of parentNote.attributes) {
|
||||
<li>Using slashes (<code>/</code>) within aliases to create subpaths is not
|
||||
supported.</li>
|
||||
</ol>
|
||||
<aside class="admonition tip">
|
||||
<ul>
|
||||
<li>To easily identify pages that don't have a share alias, run a
|
||||
<a
|
||||
class="reference-link" href="#root/_help_eIg8jdvaoNNd">Search</a> with <code>#!shareAlias</code>.</li>
|
||||
<li>To be able to enter the share alias faster, consider using <a class="reference-link"
|
||||
href="#root/_help_OFXdgB2nNk1F">Promoted Attributes</a> (for example <code>#label:shareAlias(inheritable)="promoted,alias=Slug,single,text"</code>).</li>
|
||||
</ul>
|
||||
</aside>
|
||||
<h3>Setting a custom favicon</h3>
|
||||
<p>To customize the favicon for your shared pages, create a relation <code>~shareFavicon</code> pointing
|
||||
to a file note containing the favicon (e.g., in <code>.ico</code> format).</p>
|
||||
@@ -299,7 +319,11 @@ for (const attr of parentNote.attributes) {
|
||||
When viewed, the list of shared roots will be displayed at the bottom of
|
||||
the note.</p>
|
||||
<h2>Attribute reference</h2>
|
||||
<table>
|
||||
<table class="ck-table-resized">
|
||||
<colgroup>
|
||||
<col style="width:18.38%;">
|
||||
<col style="width:81.62%;">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Attribute</th>
|
||||
@@ -308,40 +332,40 @@ for (const attr of parentNote.attributes) {
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>shareHiddenFromTree</code>
|
||||
<td><code>#shareHiddenFromTree</code>
|
||||
</td>
|
||||
<td>this note is hidden from left navigation tree, but still accessible with
|
||||
its URL</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>shareExternalLink</code>
|
||||
<td><code>#shareExternalLink</code>
|
||||
</td>
|
||||
<td>note will act as a link to an external website in the share tree</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>shareAlias</code>
|
||||
<td><code>#shareAlias</code>
|
||||
</td>
|
||||
<td>define an alias using which the note will be available under <code>https://your_trilium_host/share/[your_alias]</code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>shareOmitDefaultCss</code>
|
||||
<td><code>#shareOmitDefaultCss</code>
|
||||
</td>
|
||||
<td>default share page CSS will be omitted. Use when you make extensive styling
|
||||
changes.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>shareRoot</code>
|
||||
<td><code>#shareRoot</code>
|
||||
</td>
|
||||
<td>marks note which is served on /share root.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>shareDescription</code>
|
||||
<td><code>#shareDescription</code>
|
||||
</td>
|
||||
<td>define text to be added to the HTML meta tag for description</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>shareRaw</code>
|
||||
<td><code>#shareRaw</code>
|
||||
</td>
|
||||
<td>Note will be served in its raw format, without HTML wrapper. See also
|
||||
<a
|
||||
@@ -349,7 +373,7 @@ for (const attr of parentNote.attributes) {
|
||||
without setting an attribute.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>shareDisallowRobotIndexing</code>
|
||||
<td><code>#shareDisallowRobotIndexing</code>
|
||||
</td>
|
||||
<td>
|
||||
<p>Indicates to web crawlers that the page should not be indexed of this
|
||||
@@ -361,19 +385,19 @@ for (const attr of parentNote.attributes) {
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>shareCredentials</code>
|
||||
<td><code>#shareCredentials</code>
|
||||
</td>
|
||||
<td>require credentials to access this shared note. Value is expected to be
|
||||
in format <code>username:password</code>. Don't forget to make this inheritable
|
||||
to apply to child-notes/images.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>shareIndex</code>
|
||||
<td><code>#shareIndex</code>
|
||||
</td>
|
||||
<td>Note with this label will list all roots of shared notes.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>shareHtmlLocation</code>
|
||||
<td><code>#shareHtmlLocation</code>
|
||||
</td>
|
||||
<td>defines where custom HTML injected via <code>~shareHtml</code> relation
|
||||
should be placed. Applied to the HTML snippet note itself. Format: <code>location:position</code> where
|
||||
@@ -383,6 +407,76 @@ for (const attr of parentNote.attributes) {
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3>Customizing logo</h3>
|
||||
<p>It's possible to adjust the logo which is displayed on the top-left of
|
||||
the left pane.</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Attribute</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>~shareLogo</code>
|
||||
</td>
|
||||
<td>Relation set to an image to use as logo. The image must be part of the
|
||||
share tree (it can be hidden if needed).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>#shareLogoWidth</code>
|
||||
</td>
|
||||
<td>The width (in pixels, without unit) to set for the logo. Default is <code>53</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>#shareLogoHeight</code>
|
||||
</td>
|
||||
<td>The height (in pixels, without unit) to set for the logo. Default is <code>40</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>#shareRootLink</code>
|
||||
</td>
|
||||
<td>URL to navigate to when the logo is pressed.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3>Customizing OpenGraph</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Attribute</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>#shareOpenGraphColor</code>
|
||||
</td>
|
||||
<td>This adjusts the <code>theme-color</code> meta-property.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>#shareOpenGraphURL</code>
|
||||
</td>
|
||||
<td>This adjusts the <code>og:url</code> and <code>twitter:url</code> meta-properties.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>#shareOpenGraphDomain</code>
|
||||
</td>
|
||||
<td>Adjusts the <code>twitter:domain</code> meta-property.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>#shareOpenGraphImage</code>
|
||||
<br><code>~shareOpenGraphImage</code>
|
||||
</td>
|
||||
<td>Can be either a label, case in which the value is passed on as-is, or
|
||||
it can be a relation to an image <a class="reference-link" href="#root/_help_W8vYD3Q1zjCR">File</a>.
|
||||
This controls the <code>og:image</code> meta-property.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>Credits</h2>
|
||||
<p>Since v0.95.0, a new theme was introduced (and enabled by default) which
|
||||
greatly improves the visual aspect of the Share feature, as well as its
|
||||
|
||||
58
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing/Exporting HTML for web publish.html
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
<p>As described in <a class="reference-link" href="#root/_help_R9pX4DGra2Vt">Sharing</a>,
|
||||
Trilium can act as a public server in which the shared notes are displayed
|
||||
in read-only mode. While this can work in most cases, it's generally not
|
||||
meant for high-traffic websites and since it's running on a Node.js server
|
||||
it can be potentially exploited.</p>
|
||||
<p>Another alternative is to generate static HTML files (just like other
|
||||
static site generators such as <a href="https://www.mkdocs.org/">MkDocs</a>).
|
||||
Since the normal HTML ZIP export does not contain any styling or additional
|
||||
functionality, Trilium provides a way to export the same layout and style
|
||||
as the <a class="reference-link" href="#root/_help_R9pX4DGra2Vt">Sharing</a> function
|
||||
into static HTML files.</p>
|
||||
<p>Apart from the enhanced security, these HTML files are also easy to deploy
|
||||
on “serverless” deployments such as GitHub Pages or CloudFlare Pages and
|
||||
cache very easily.</p>
|
||||
<aside class="admonition tip">
|
||||
<p>Trilium's documentation, available at <a href="https://docs.triliumnotes.org/">docs.triliumnotes.org</a> is
|
||||
built using this function of exporting to static HTML files which are then
|
||||
deployed automatically to CloudFlare Pages.</p>
|
||||
<p>The process is <a href="https://github.com/TriliumNext/Trilium/blob/main/apps/edit-docs/src/build-docs.ts">automated</a> by
|
||||
importing the Markdown documentation and exporting it via a script to the
|
||||
static web format.</p>
|
||||
</aside>
|
||||
<h2>Differences from normal sharing</h2>
|
||||
<p>Apart from normal <a class="reference-link" href="#root/_help_R9pX4DGra2Vt">Sharing</a>,
|
||||
exporting to static HTML files comes with a few subtle differences:</p>
|
||||
<ul>
|
||||
<li>The URL structure is different. Where in normal sharing it's something
|
||||
along the way of <code>example.com/share/noteid</code>, the notes follow
|
||||
an hierarchical structure, such as <code>docs.triliumnotes.org/user-guide/concepts/navigation/tree-concepts</code>.</li>
|
||||
<li>The <code>favicon.ico</code> is not handled automatically, it needs to be
|
||||
manually added on the server after the export is generated.</li>
|
||||
<li>The “Last updated” for notes is not available.</li>
|
||||
<li>The search functionality works slightly different since the normal one
|
||||
requires an active API to work. In the static export, search still works
|
||||
but uses a different mechanism so results might be different.</li>
|
||||
</ul>
|
||||
<h2>Differences from normal .zip export</h2>
|
||||
<ul>
|
||||
<li>The name of the files/URLs will prefer <code>shareAlias</code> to allow
|
||||
for clean URLs.</li>
|
||||
<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>
|
||||
</ul>
|
||||
<h2>Testing locally</h2>
|
||||
<p>As mentioned previously, the exported static pages require a website to
|
||||
function. In order to test locally, a web server needs to be used.</p>
|
||||
<p>One example is to use the Node.js-based <a href="https://www.npmjs.com/package/http-server"><code>http-server</code></a> which
|
||||
can be installed via:</p><pre><code class="language-text-x-trilium-auto">npm i -g http-server</code></pre>
|
||||
<p>Once installed simply:</p>
|
||||
<ol>
|
||||
<li>Extract the exported .zip file.</li>
|
||||
<li>Inside the extracted directory, run <code>http-server</code>.</li>
|
||||
<li>Access the indicated address (e.g. <a href="http://localhost:8080">http://localhost:8080</a>).</li>
|
||||
</ol>
|
||||
<h2>Automation</h2>
|
||||
<p><a class="reference-link" href="#root/_help_pgxEVkzLl1OP">ETAPI (REST API)</a> could
|
||||
potentially be used to automate an export on a scheduled task.</p>
|
||||
18
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing/Reverse proxy configuration.html
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<p>It might be desirable to only expose the share functionality of Trilium
|
||||
to the Internet, and keep the application accessible only within a local
|
||||
network or via VPN.</p>
|
||||
<p>To do so, a reverse proxy is required.</p>
|
||||
<h2>Caddy</h2><pre><code class="language-text-x-trilium-auto">http://domain.com {
|
||||
reverse_proxy /share http://localhost:8080/share
|
||||
}</code></pre>
|
||||
<p>This is for newer versions where the share functionality is isolated,
|
||||
for older versions it's required to also include <code>/assets</code>.<sup><a href="#fn2b8mg20aol8">[1]</a></sup>
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p><sup><strong><a href="#fnref2b8mg20aol8">^</a></strong></sup>
|
||||
</p>
|
||||
<p><a href="https://github.com/orgs/TriliumNext/discussions/7341#discussioncomment-14679897">https://github.com/orgs/TriliumNext/discussions/7341#discussioncomment-14679897</a>
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
@@ -39,7 +39,7 @@
|
||||
</li>
|
||||
<li><a href="#root/_help_QEAPj01N5f7w">Reference links</a>
|
||||
</li>
|
||||
<li><a href="#root/_help_NwBbFdNZ9h7O">Admonitions</a>, we ended up creating
|
||||
our own plugin but <a href="https://github.com/aarkue/ckeditor5-admonition">aarkue/ckeditor5-admonition</a> was
|
||||
<li><a href="#root/_help_NwBbFdNZ9h7O">Admonitions</a>, we ended up creating our
|
||||
own plugin but <a href="https://github.com/aarkue/ckeditor5-admonition">aarkue/ckeditor5-admonition</a> was
|
||||
a good inspiration (including the toolbar icon).</li>
|
||||
</ul>
|
||||
@@ -1,5 +1,5 @@
|
||||
<p><a href="https://excalidraw.com/">Excalidraw</a> is the technology behind
|
||||
the <a href="#root/_help_grjYqerjn243">Canvas</a> notes. The
|
||||
source code of the library is available on <a href="https://github.com/excalidraw/excalidraw">GitHub</a>.</p>
|
||||
the <a href="#root/_help_grjYqerjn243">Canvas</a> notes. The source
|
||||
code of the library is available on <a href="https://github.com/excalidraw/excalidraw">GitHub</a>.</p>
|
||||
<p>We are using an unmodified version of it, so it shares the same <a href="https://github.com/excalidraw/excalidraw/issues">issues</a> as
|
||||
the original.</p>
|
||||
11
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Templates.html
generated
vendored
@@ -3,10 +3,10 @@
|
||||
main effects:</p>
|
||||
<ol>
|
||||
<li><strong>Attribute Inheritance</strong>: All attributes from the template
|
||||
note are <a href="#root/_help_bwZpz2ajCEwO">inherited</a> by the instance
|
||||
notes. Even attributes with <code>#isInheritable=false</code> are inherited
|
||||
by the instance notes, although only inheritable attributes are further
|
||||
inherited by the children of the instance notes.</li>
|
||||
note are <a href="#root/_help_bwZpz2ajCEwO">inherited</a> by the instance notes.
|
||||
Even attributes with <code>#isInheritable=false</code> are inherited by the
|
||||
instance notes, although only inheritable attributes are further inherited
|
||||
by the children of the instance notes.</li>
|
||||
<li><strong>Content Duplication</strong>: The content of the template note
|
||||
is copied to the instance note, provided the instance note is empty at
|
||||
the time of template assignment.</li>
|
||||
@@ -32,7 +32,8 @@
|
||||
all attributes from the template are inherited.</p>
|
||||
<p>To create an instance note through the UI:</p>
|
||||
<p>
|
||||
<img src="Templates_template-create-.png" alt="show child note templates">
|
||||
<img src="Templates_template-create-.png"
|
||||
alt="show child note templates">
|
||||
</p>
|
||||
<p>For the template to appear in the menu, the template note must have the <code>#template</code> label.
|
||||
Do not confuse this with the <code>~template</code> relation, which links
|
||||
|
||||
30
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export.html
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<p>Trilium natively supports the following formats for both import and export.</p>
|
||||
<ul>
|
||||
<li>HTML:
|
||||
<ul>
|
||||
<li>This is the main format used by Trilium, where standard tags are used
|
||||
to represent basic formatting and layout (e.g. <code><strong></code>, <code><table></code>, <code><pre></code>).</li>
|
||||
<li>Note that HTML is not a standardized format so some more specific features
|
||||
such as admonitions or <a class="reference-link" href="#root/_help_hrZ1D00cLbal">Internal (reference) links</a> might
|
||||
not be supported by other applications.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference-link" href="#root/_help_Oau6X9rCuegd">Markdown</a>
|
||||
<ul>
|
||||
<li>Most of the formatting is preserved, see <a class="reference-link"
|
||||
href="#root/_help_rJ9grSgoExl9">Supported syntax</a>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>OPML (Outliner Interchange Format)
|
||||
<ul>
|
||||
<li>Supports both OPML v1.0 for plain text and v2.0 with HTML support.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p>To import from other applications, see the dedicated pages:</p>
|
||||
<ul>
|
||||
<li><a class="reference-link" href="#root/_help_syuSEKf2rUGr">Evernote</a>
|
||||
</li>
|
||||
<li><a class="reference-link" href="#root/_help_GnhlmrATVqcH">OneNote</a>
|
||||
</li>
|
||||
</ul>
|
||||