Merge branch 'main' into feat/note-map-filter

This commit is contained in:
Elian Doran 2025-07-02 23:37:56 +03:00 committed by GitHub
commit 63520c55b3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
44 changed files with 1117 additions and 761 deletions

View File

@ -120,7 +120,7 @@ jobs:
body_path: docs/Release Notes/Release Notes/${{ github.ref_name }}.md body_path: docs/Release Notes/Release Notes/${{ github.ref_name }}.md
fail_on_unmatched_files: true fail_on_unmatched_files: true
files: upload/*.* files: upload/*.*
discussion_category_name: Announcements discussion_category_name: Releases
make_latest: ${{ !contains(github.ref, 'rc') }} make_latest: ${{ !contains(github.ref, 'rc') }}
prerelease: ${{ contains(github.ref, 'rc') }} prerelease: ${{ contains(github.ref, 'rc') }}
token: ${{ secrets.RELEASE_PAT }} token: ${{ secrets.RELEASE_PAT }}

View File

@ -91,5 +91,5 @@ async function start() {
} }
// @TriliumNextTODO sqlInit.dbReady never seems to resolve so program hangs // @TriliumNextTODO sqlInit.dbReady never seems to resolve so program hangs
// see https://github.com/TriliumNext/Notes/issues/1020 // see https://github.com/TriliumNext/Trilium/issues/1020
sqlInit.dbReady.then(cls.wrap(start)).catch((err) => console.error(err)); sqlInit.dbReady.then(cls.wrap(start)).catch((err) => console.error(err));

View File

@ -8,5 +8,5 @@ test("Displays update badge when there is a version available", async ({ page })
await page.getByText(`Version ${expectedVersion} is available,`).click(); await page.getByText(`Version ${expectedVersion} is available,`).click();
const page1 = await page.waitForEvent("popup"); const page1 = await page.waitForEvent("popup");
expect(page1.url()).toBe(`https://github.com/TriliumNext/Notes/releases/tag/v${expectedVersion}`); expect(page1.url()).toBe(`https://github.com/TriliumNext/Trilium/releases/tag/v${expectedVersion}`);
}); });

View File

@ -35,13 +35,13 @@
"chore:generate-openapi": "tsx bin/generate-openapi.js" "chore:generate-openapi": "tsx bin/generate-openapi.js"
}, },
"devDependencies": { "devDependencies": {
"@playwright/test": "1.53.1", "@playwright/test": "1.53.2",
"@stylistic/eslint-plugin": "5.0.0", "@stylistic/eslint-plugin": "5.1.0",
"@types/express": "5.0.3", "@types/express": "5.0.3",
"@types/node": "22.15.33", "@types/node": "22.16.0",
"@types/yargs": "17.0.33", "@types/yargs": "17.0.33",
"@vitest/coverage-v8": "3.2.4", "@vitest/coverage-v8": "3.2.4",
"eslint": "9.29.0", "eslint": "9.30.0",
"eslint-plugin-simple-import-sort": "12.1.1", "eslint-plugin-simple-import-sort": "12.1.1",
"esm": "3.2.25", "esm": "3.2.25",
"jsdoc": "4.0.4", "jsdoc": "4.0.4",
@ -49,7 +49,7 @@
"rcedit": "4.0.1", "rcedit": "4.0.1",
"rimraf": "6.0.1", "rimraf": "6.0.1",
"tslib": "2.8.1", "tslib": "2.8.1",
"typedoc": "0.28.5", "typedoc": "0.28.7",
"typedoc-plugin-missing-exports": "4.0.0" "typedoc-plugin-missing-exports": "4.0.0"
}, },
"optionalDependencies": { "optionalDependencies": {

View File

@ -1,6 +1,6 @@
{ {
"name": "@triliumnext/client", "name": "@triliumnext/client",
"version": "0.95.0", "version": "0.96.0",
"description": "JQuery-based client for TriliumNext, used for both web and desktop (via Electron)", "description": "JQuery-based client for TriliumNext, used for both web and desktop (via Electron)",
"private": true, "private": true,
"license": "AGPL-3.0-only", "license": "AGPL-3.0-only",
@ -10,14 +10,14 @@
"url": "https://github.com/TriliumNext/Notes" "url": "https://github.com/TriliumNext/Notes"
}, },
"dependencies": { "dependencies": {
"@eslint/js": "9.29.0", "@eslint/js": "9.30.0",
"@excalidraw/excalidraw": "0.18.0", "@excalidraw/excalidraw": "0.18.0",
"@fullcalendar/core": "6.1.17", "@fullcalendar/core": "6.1.18",
"@fullcalendar/daygrid": "6.1.17", "@fullcalendar/daygrid": "6.1.18",
"@fullcalendar/interaction": "6.1.17", "@fullcalendar/interaction": "6.1.18",
"@fullcalendar/list": "6.1.17", "@fullcalendar/list": "6.1.18",
"@fullcalendar/multimonth": "6.1.17", "@fullcalendar/multimonth": "6.1.18",
"@fullcalendar/timegrid": "6.1.17", "@fullcalendar/timegrid": "6.1.18",
"@mermaid-js/layout-elk": "0.1.8", "@mermaid-js/layout-elk": "0.1.8",
"@mind-elixir/node-menu": "1.0.5", "@mind-elixir/node-menu": "1.0.5",
"@popperjs/core": "2.11.8", "@popperjs/core": "2.11.8",
@ -34,8 +34,8 @@
"debounce": "2.2.0", "debounce": "2.2.0",
"draggabilly": "3.0.0", "draggabilly": "3.0.0",
"force-graph": "1.49.6", "force-graph": "1.49.6",
"globals": "16.2.0", "globals": "16.3.0",
"i18next": "25.2.1", "i18next": "25.3.0",
"i18next-http-backend": "3.0.2", "i18next-http-backend": "3.0.2",
"jquery": "3.7.1", "jquery": "3.7.1",
"jquery-hotkeys": "0.2.2", "jquery-hotkeys": "0.2.2",
@ -46,9 +46,9 @@
"leaflet": "1.9.4", "leaflet": "1.9.4",
"leaflet-gpx": "2.2.0", "leaflet-gpx": "2.2.0",
"mark.js": "8.11.1", "mark.js": "8.11.1",
"marked": "15.0.12", "marked": "16.0.0",
"mermaid": "11.7.0", "mermaid": "11.7.0",
"mind-elixir": "4.6.1", "mind-elixir": "4.6.2",
"normalize.css": "8.0.1", "normalize.css": "8.0.1",
"panzoom": "9.4.3", "panzoom": "9.4.3",
"preact": "10.26.9", "preact": "10.26.9",

View File

@ -424,7 +424,7 @@ export default class GlobalMenuWidget extends BasicWidget {
} }
downloadLatestVersionCommand() { downloadLatestVersionCommand() {
window.open("https://github.com/TriliumNext/Notes/releases/latest"); window.open("https://github.com/TriliumNext/Trilium/releases/latest");
} }
activeContextChangedEvent() { activeContextChangedEvent() {

View File

@ -27,7 +27,7 @@ const TPL = /*html*/`
<table class="table table-borderless"> <table class="table table-borderless">
<tr> <tr>
<th>${t("about.homepage")}</th> <th>${t("about.homepage")}</th>
<td><a class="tn-link" href="https://github.com/TriliumNext/Notes" class="external">https://github.com/TriliumNext/Notes</a></td> <td><a class="tn-link" href="https://github.com/TriliumNext/Trilium" class="external">https://github.com/TriliumNext/Trilium</a></td>
</tr> </tr>
<tr> <tr>
<th>${t("about.app_version")}</th> <th>${t("about.app_version")}</th>
@ -92,7 +92,7 @@ export default class AboutDialog extends BasicWidget {
this.$syncVersion.text(appInfo.syncVersion.toString()); this.$syncVersion.text(appInfo.syncVersion.toString());
this.$buildDate.text(formatDateTime(appInfo.buildDate)); this.$buildDate.text(formatDateTime(appInfo.buildDate));
this.$buildRevision.text(appInfo.buildRevision); this.$buildRevision.text(appInfo.buildRevision);
this.$buildRevision.attr("href", `https://github.com/TriliumNext/Notes/commit/${appInfo.buildRevision}`); this.$buildRevision.attr("href", `https://github.com/TriliumNext/Trilium/commit/${appInfo.buildRevision}`);
if (utils.isElectron()) { if (utils.isElectron()) {
this.$dataDirectory.html( this.$dataDirectory.html(
$("<a></a>", { $("<a></a>", {

View File

@ -41,9 +41,9 @@ export default class IncorrectCpuArchDialog extends BasicWidget {
// Open the releases page where users can download the correct version // Open the releases page where users can download the correct version
if (utils.isElectron()) { if (utils.isElectron()) {
const { shell } = utils.dynamicRequire("electron"); const { shell } = utils.dynamicRequire("electron");
shell.openExternal("https://github.com/TriliumNext/Notes/releases/latest"); shell.openExternal("https://github.com/TriliumNext/Trilium/releases/latest");
} else { } else {
window.open("https://github.com/TriliumNext/Notes/releases/latest", "_blank"); window.open("https://github.com/TriliumNext/Trilium/releases/latest", "_blank");
} }
}); });

View File

@ -74,7 +74,7 @@ export const DEFAULT_ALLOWED_TAGS = [
"del", "del",
"ins", "ins",
"en-media", // for ENEX import "en-media", // for ENEX import
// Additional tags (https://github.com/TriliumNext/Notes/issues/567) // Additional tags (https://github.com/TriliumNext/Trilium/issues/567)
"acronym", "acronym",
"article", "article",
"big", "big",

View File

@ -1,6 +1,7 @@
{ {
"extends": "../../tsconfig.base.json", "extends": "../../tsconfig.base.json",
"compilerOptions": { "compilerOptions": {
"lib": [ "ESNext" ],
"outDir": "dist", "outDir": "dist",
"types": [ "types": [
"node" "node"

View File

@ -18,7 +18,7 @@
} }
}, },
"devDependencies": { "devDependencies": {
"dotenv": "16.6.0", "dotenv": "17.0.1",
"electron": "36.6.0" "electron": "37.1.0"
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@triliumnext/desktop", "name": "@triliumnext/desktop",
"version": "0.95.0", "version": "0.96.0",
"description": "Build your personal knowledge base with Trilium Notes", "description": "Build your personal knowledge base with Trilium Notes",
"private": true, "private": true,
"main": "main.cjs", "main": "main.cjs",
@ -17,7 +17,7 @@
"@types/electron-squirrel-startup": "1.0.2", "@types/electron-squirrel-startup": "1.0.2",
"@triliumnext/server": "workspace:*", "@triliumnext/server": "workspace:*",
"copy-webpack-plugin": "13.0.0", "copy-webpack-plugin": "13.0.0",
"electron": "36.6.0", "electron": "37.1.0",
"@electron-forge/cli": "7.8.1", "@electron-forge/cli": "7.8.1",
"@electron-forge/maker-deb": "7.8.1", "@electron-forge/maker-deb": "7.8.1",
"@electron-forge/maker-dmg": "7.8.1", "@electron-forge/maker-dmg": "7.8.1",

View File

@ -12,7 +12,7 @@
"@triliumnext/desktop": "workspace:*", "@triliumnext/desktop": "workspace:*",
"@types/fs-extra": "11.0.4", "@types/fs-extra": "11.0.4",
"copy-webpack-plugin": "13.0.0", "copy-webpack-plugin": "13.0.0",
"electron": "36.6.0", "electron": "37.1.0",
"fs-extra": "11.3.0" "fs-extra": "11.3.0"
}, },
"nx": { "nx": {

View File

@ -17,6 +17,6 @@
} }
}, },
"devDependencies": { "devDependencies": {
"dotenv": "16.6.0" "dotenv": "17.0.1"
} }
} }

View File

@ -1,5 +1,5 @@
{ {
"dependencies": { "dependencies": {
"better-sqlite3": "12.1.1" "better-sqlite3": "12.2.0"
} }
} }

View File

@ -1,10 +1,10 @@
{ {
"name": "@triliumnext/server", "name": "@triliumnext/server",
"version": "0.95.0", "version": "0.96.0",
"description": "The server-side component of TriliumNext, which exposes the client via the web, allows for sync and provides a REST API for both internal and external use.", "description": "The server-side component of TriliumNext, which exposes the client via the web, allows for sync and provides a REST API for both internal and external use.",
"private": true, "private": true,
"dependencies": { "dependencies": {
"better-sqlite3": "12.1.1" "better-sqlite3": "12.2.0"
}, },
"devDependencies": { "devDependencies": {
"@electron/remote": "2.1.2", "@electron/remote": "2.1.2",
@ -24,7 +24,7 @@
"@types/js-yaml": "4.0.9", "@types/js-yaml": "4.0.9",
"@types/jsdom": "21.1.7", "@types/jsdom": "21.1.7",
"@types/mime-types": "3.0.1", "@types/mime-types": "3.0.1",
"@types/multer": "1.4.13", "@types/multer": "2.0.0",
"@types/safe-compare": "1.1.2", "@types/safe-compare": "1.1.2",
"@types/sanitize-html": "2.16.0", "@types/sanitize-html": "2.16.0",
"@types/sax": "1.2.7", "@types/sax": "1.2.7",
@ -39,7 +39,7 @@
"@types/ws": "8.18.1", "@types/ws": "8.18.1",
"@types/xml2js": "0.4.14", "@types/xml2js": "0.4.14",
"express-http-proxy": "2.1.1", "express-http-proxy": "2.1.1",
"@anthropic-ai/sdk": "0.55.0", "@anthropic-ai/sdk": "0.55.1",
"@braintree/sanitize-url": "7.1.1", "@braintree/sanitize-url": "7.1.1",
"@triliumnext/commons": "workspace:*", "@triliumnext/commons": "workspace:*",
"@triliumnext/express-partial-content": "workspace:*", "@triliumnext/express-partial-content": "workspace:*",
@ -59,7 +59,7 @@
"debounce": "2.2.0", "debounce": "2.2.0",
"debug": "4.4.1", "debug": "4.4.1",
"ejs": "3.1.10", "ejs": "3.1.10",
"electron": "36.6.0", "electron": "37.1.0",
"electron-debug": "4.1.0", "electron-debug": "4.1.0",
"electron-window-state": "5.0.3", "electron-window-state": "5.0.3",
"escape-html": "1.0.3", "escape-html": "1.0.3",
@ -74,7 +74,7 @@
"html2plaintext": "2.1.4", "html2plaintext": "2.1.4",
"http-proxy-agent": "7.0.2", "http-proxy-agent": "7.0.2",
"https-proxy-agent": "7.0.6", "https-proxy-agent": "7.0.6",
"i18next": "25.2.1", "i18next": "25.3.0",
"i18next-fs-backend": "2.6.0", "i18next-fs-backend": "2.6.0",
"image-type": "6.0.0", "image-type": "6.0.0",
"ini": "5.0.0", "ini": "5.0.0",
@ -83,12 +83,12 @@
"jimp": "1.6.0", "jimp": "1.6.0",
"js-yaml": "4.1.0", "js-yaml": "4.1.0",
"jsdom": "26.1.0", "jsdom": "26.1.0",
"marked": "15.0.12", "marked": "16.0.0",
"mime-types": "3.0.1", "mime-types": "3.0.1",
"multer": "2.0.1", "multer": "2.0.1",
"normalize-strings": "1.1.1", "normalize-strings": "1.1.1",
"ollama": "0.5.16", "ollama": "0.5.16",
"openai": "5.8.1", "openai": "5.8.2",
"rand-token": "1.0.1", "rand-token": "1.0.1",
"safe-compare": "1.1.4", "safe-compare": "1.1.4",
"sanitize-filename": "1.6.3", "sanitize-filename": "1.6.3",
@ -105,7 +105,7 @@
"tmp": "0.2.3", "tmp": "0.2.3",
"turndown": "7.2.0", "turndown": "7.2.0",
"unescape": "1.0.1", "unescape": "1.0.1",
"ws": "8.18.2", "ws": "8.18.3",
"xml2js": "0.6.2", "xml2js": "0.6.2",
"yauzl": "3.2.0" "yauzl": "3.2.0"
}, },

View File

@ -42,5 +42,5 @@
This will export the notes in an unencrypted form, so if you reimport into This will export the notes in an unencrypted form, so if you reimport into
Trilium, make sure to re-protect these notes.</p> Trilium, make sure to re-protect these notes.</p>
<h2>Supported syntax</h2> <h2>Supported syntax</h2>
<p>See the dedicated page:&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/mHbBMPDPkVV5/Oau6X9rCuegd/_help_rJ9grSgoExl9">Supported syntax</a> <p>See the dedicated page:&nbsp;<a class="reference-link" href="#root/_help_rJ9grSgoExl9">Supported syntax</a>
</p> </p>

View File

@ -41,7 +41,7 @@
Trilium-compatible syntax, but it will not export Trilium Notes into Markdown Trilium-compatible syntax, but it will not export Trilium Notes into Markdown
files with this syntax.</p> files with this syntax.</p>
<aside class="admonition important"> <aside class="admonition important">
<p>The path to pages in wikilinks is resolved relatively to the <em>import root </em>and <p>The path to pages in wikilinks is resolved relatively to the <em>import root</em> and
not the current directory of the note. This is to be inline with other not the current directory of the note. This is to be inline with other
platforms that use wikilinks such as SilverBullet.</p> platforms that use wikilinks such as SilverBullet.</p>
<p>The root path of the import is determined as follows:</p> <p>The root path of the import is determined as follows:</p>

View File

@ -62,4 +62,4 @@ class="image image-style-align-center">
are currently no plans for adjusting it or allowing the user to customize are currently no plans for adjusting it or allowing the user to customize
them.</p> them.</p>
<h3>Markdown support</h3> <h3>Markdown support</h3>
<p>See&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/mHbBMPDPkVV5/Oau6X9rCuegd/_help_rJ9grSgoExl9">Supported syntax</a>.</p> <p>See&nbsp;<a class="reference-link" href="#root/_help_rJ9grSgoExl9">Supported syntax</a>.</p>

View File

@ -8,7 +8,7 @@ import appInfo from "../../services/app_info.js";
* operationId: app-info * operationId: app-info
* externalDocs: * externalDocs:
* description: Server implementation * description: Server implementation
* url: https://github.com/TriliumNext/Notes/blob/v0.91.6/src/services/app_info.ts * url: https://github.com/TriliumNext/Trilium/blob/v0.91.6/src/services/app_info.ts
* responses: * responses:
* '200': * '200':
* description: Installation info * description: Installation info

View File

@ -25,7 +25,7 @@ import type { Request } from "express";
* operationId: login-sync * operationId: login-sync
* externalDocs: * externalDocs:
* description: HMAC calculation * description: HMAC calculation
* url: https://github.com/TriliumNext/Notes/blob/v0.91.6/src/services/utils.ts#L62-L66 * url: https://github.com/TriliumNext/Trilium/blob/v0.91.6/src/services/utils.ts#L62-L66
* requestBody: * requestBody:
* content: * content:
* application/json: * application/json:

View File

@ -95,7 +95,7 @@ function forceFullSync() {
* operationId: sync-changed * operationId: sync-changed
* externalDocs: * externalDocs:
* description: Server implementation * description: Server implementation
* url: https://github.com/TriliumNext/Notes/blob/v0.91.6/src/routes/api/sync.ts * url: https://github.com/TriliumNext/Trilium/blob/v0.91.6/src/routes/api/sync.ts
* parameters: * parameters:
* - in: query * - in: query
* name: instanceId * name: instanceId
@ -214,7 +214,7 @@ const partialRequests: Record<
* operationId: sync-update * operationId: sync-update
* externalDocs: * externalDocs:
* description: Server implementation * description: Server implementation
* url: https://github.com/TriliumNext/Notes/blob/v0.91.6/src/routes/api/sync.ts * url: https://github.com/TriliumNext/Trilium/blob/v0.91.6/src/routes/api/sync.ts
* parameters: * parameters:
* - in: header * - in: header
* name: pageCount * name: pageCount

View File

@ -136,7 +136,7 @@ function getNotesAndBranchesAndAttributes(_noteIds: string[] | Set<string>) {
* operationId: tree * operationId: tree
* externalDocs: * externalDocs:
* description: Server implementation * description: Server implementation
* url: https://github.com/TriliumNext/Notes/blob/v0.91.6/src/routes/api/tree.ts * url: https://github.com/TriliumNext/Trilium/blob/v0.91.6/src/routes/api/tree.ts
* parameters: * parameters:
* - in: query * - in: query
* name: subTreeNoteId * name: subTreeNoteId

View File

@ -8,7 +8,7 @@ const doubleCsrfUtilities = doubleCsrf({
path: "/", path: "/",
secure: false, secure: false,
sameSite: "strict", sameSite: "strict",
httpOnly: !isElectron // set to false for Electron, see https://github.com/TriliumNext/Notes/pull/966 httpOnly: !isElectron // set to false for Electron, see https://github.com/TriliumNext/Trilium/pull/966
}, },
cookieName: "_csrf" cookieName: "_csrf"
}); });

View File

@ -77,7 +77,7 @@ function setPassword(req: Request, res: Response) {
* operationId: login-normal * operationId: login-normal
* externalDocs: * externalDocs:
* description: HMAC calculation * description: HMAC calculation
* url: https://github.com/TriliumNext/Notes/blob/v0.91.6/src/services/utils.ts#L62-L66 * url: https://github.com/TriliumNext/Trilium/blob/v0.91.6/src/services/utils.ts#L62-L66
* requestBody: * requestBody:
* content: * content:
* application/x-www-form-urlencoded: * application/x-www-form-urlencoded:

View File

@ -255,8 +255,12 @@ export interface Api {
/** /**
* Returns week note for given date. If such a note doesn't exist, it is created. * Returns week note for given date. If such a note doesn't exist, it is created.
* *
* <p>
* If the calendar does not support week notes, this method will return `null`.
*
* @param date in YYYY-MM-DD format * @param date in YYYY-MM-DD format
* @param rootNote - specify calendar root note, normally leave empty to use the default calendar * @param rootNote - specify calendar root note, normally leave empty to use the default calendar
* @return an existing or newly created week note, or `null` if the calendar does not support week notes.
*/ */
getWeekNote(date: string, rootNote: BNote): BNote | null; getWeekNote(date: string, rootNote: BNote): BNote | null;

View File

@ -293,25 +293,25 @@ describe("Markdown export", () => {
const html = trimIndentation`\ const html = trimIndentation`\
<ul> <ul>
<li><a href="https://github.com/JYC333">@JYC333</a> made their first contribution <li><a href="https://github.com/JYC333">@JYC333</a> made their first contribution
in <a href="https://github.com/TriliumNext/Notes/pull/294">#294</a> in <a href="https://github.com/TriliumNext/Trilium/pull/294">#294</a>
</li> </li>
<li> <li>
<p><a href="https://github.com/TriliumNext/Notes/issues/375">Note Tooltip isn't removed when clicking on internal trilium link in read-only mode</a> <p><a href="https://github.com/TriliumNext/Trilium/issues/375">Note Tooltip isn't removed when clicking on internal trilium link in read-only mode</a>
</p> </p>
</li> </li>
<li> <li>
<p><a href="https://github.com/TriliumNext/Notes/issues/384">Calendar dropdown won't close if click/right-click other button that open notes from launcher bar</a> <p><a href="https://github.com/TriliumNext/Trilium/issues/384">Calendar dropdown won't close if click/right-click other button that open notes from launcher bar</a>
</p> </p>
</li> </li>
</ul> </ul>
`; `;
const expected = trimIndentation`\ const expected = trimIndentation`\
* [@JYC333](https://github.com/JYC333) made their first contribution in [#294](https://github.com/TriliumNext/Notes/pull/294) * [@JYC333](https://github.com/JYC333) made their first contribution in [#294](https://github.com/TriliumNext/Trilium/pull/294)
* [Note Tooltip isn't removed when clicking on internal trilium link in read-only mode](https://github.com/TriliumNext/Notes/issues/375) * [Note Tooltip isn't removed when clicking on internal trilium link in read-only mode](https://github.com/TriliumNext/Trilium/issues/375)
* [Calendar dropdown won't close if click/right-click other button that open notes from launcher bar](https://github.com/TriliumNext/Notes/issues/384)`; * [Calendar dropdown won't close if click/right-click other button that open notes from launcher bar](https://github.com/TriliumNext/Trilium/issues/384)`;
expect(markdownExportService.toMarkdown(html)).toBe(expected); expect(markdownExportService.toMarkdown(html)).toBe(expected);
}); });

View File

@ -75,6 +75,9 @@ async function exportToZip(taskContext: TaskContext, branch: BBranch, format: "h
function getDataFileName(type: string | null, mime: string, baseFileName: string, existingFileNames: Record<string, number>): string { function getDataFileName(type: string | null, mime: string, baseFileName: string, existingFileNames: Record<string, number>): string {
let fileName = baseFileName.trim(); let fileName = baseFileName.trim();
if (!fileName) {
fileName = "note";
}
// Crop fileName to avoid its length exceeding 30 and prevent cutting into the extension. // Crop fileName to avoid its length exceeding 30 and prevent cutting into the extension.
if (fileName.length > 30) { if (fileName.length > 30) {
@ -366,7 +369,7 @@ ${markdownContent}`;
function saveNote(noteMeta: NoteMeta, filePathPrefix: string) { function saveNote(noteMeta: NoteMeta, filePathPrefix: string) {
log.info(`Exporting note '${noteMeta.noteId}'`); log.info(`Exporting note '${noteMeta.noteId}'`);
if (!noteMeta.noteId || !noteMeta.title) { if (!noteMeta.noteId || noteMeta.title === undefined) {
throw new Error("Missing note meta."); throw new Error("Missing note meta.");
} }
@ -515,97 +518,108 @@ ${markdownContent}`;
archive.append(cssContent, { name: cssMeta.dataFileName }); archive.append(cssContent, { name: cssMeta.dataFileName });
} }
const existingFileNames: Record<string, number> = format === "html" ? { navigation: 0, index: 1 } : {}; try {
const rootMeta = createNoteMeta(branch, { notePath: [] }, existingFileNames); const existingFileNames: Record<string, number> = format === "html" ? { navigation: 0, index: 1 } : {};
if (!rootMeta) { const rootMeta = createNoteMeta(branch, { notePath: [] }, existingFileNames);
throw new Error("Unable to create root meta."); if (!rootMeta) {
} throw new Error("Unable to create root meta.");
}
const metaFile: NoteMetaFile = { const metaFile: NoteMetaFile = {
formatVersion: 2, formatVersion: 2,
appVersion: packageInfo.version, appVersion: packageInfo.version,
files: [rootMeta] files: [rootMeta]
};
let navigationMeta: NoteMeta | null = null;
let indexMeta: NoteMeta | null = null;
let cssMeta: NoteMeta | null = null;
if (format === "html") {
navigationMeta = {
noImport: true,
dataFileName: "navigation.html"
}; };
metaFile.files.push(navigationMeta); let navigationMeta: NoteMeta | null = null;
let indexMeta: NoteMeta | null = null;
let cssMeta: NoteMeta | null = null;
indexMeta = { if (format === "html") {
noImport: true, navigationMeta = {
dataFileName: "index.html" noImport: true,
}; dataFileName: "navigation.html"
};
metaFile.files.push(indexMeta); metaFile.files.push(navigationMeta);
cssMeta = { indexMeta = {
noImport: true, noImport: true,
dataFileName: "style.css" dataFileName: "index.html"
}; };
metaFile.files.push(cssMeta); metaFile.files.push(indexMeta);
}
for (const noteMeta of Object.values(noteIdToMeta)) { cssMeta = {
// filter out relations which are not inside this export noImport: true,
noteMeta.attributes = (noteMeta.attributes || []).filter((attr) => { dataFileName: "style.css"
if (attr.type !== "relation") { };
return true;
} else if (attr.value in noteIdToMeta) { metaFile.files.push(cssMeta);
return true; }
} else if (attr.value === "root" || attr.value?.startsWith("_")) {
// relations to "named" noteIds can be preserved for (const noteMeta of Object.values(noteIdToMeta)) {
return true; // filter out relations which are not inside this export
} else { noteMeta.attributes = (noteMeta.attributes || []).filter((attr) => {
return false; if (attr.type !== "relation") {
return true;
} else if (attr.value in noteIdToMeta) {
return true;
} else if (attr.value === "root" || attr.value?.startsWith("_")) {
// relations to "named" noteIds can be preserved
return true;
} else {
return false;
}
});
}
if (!rootMeta) {
// corner case of disabled export for exported note
if ("sendStatus" in res) {
res.sendStatus(400);
} }
}); return;
} }
const metaFileJson = JSON.stringify(metaFile, null, "\t");
archive.append(metaFileJson, { name: "!!!meta.json" });
saveNote(rootMeta, "");
if (format === "html") {
if (!navigationMeta || !indexMeta || !cssMeta) {
throw new Error("Missing meta.");
}
saveNavigation(rootMeta, navigationMeta);
saveIndex(rootMeta, indexMeta);
saveCss(rootMeta, cssMeta);
}
const note = branch.getNote();
const zipFileName = `${branch.prefix ? `${branch.prefix} - ` : ""}${note.getTitleOrProtected() || "note"}.zip`;
if (setHeaders && "setHeader" in res) {
res.setHeader("Content-Disposition", getContentDisposition(zipFileName));
res.setHeader("Content-Type", "application/zip");
}
archive.pipe(res);
await archive.finalize();
taskContext.taskSucceeded();
} catch (e: unknown) {
const message = `Export failed with error: ${e instanceof Error ? e.message : String(e)}`;
log.error(message);
taskContext.reportError(message);
if (!rootMeta) {
// corner case of disabled export for exported note
if ("sendStatus" in res) { if ("sendStatus" in res) {
res.sendStatus(400); res.removeHeader("Content-Disposition");
res.removeHeader("Content-Type");
res.status(500).send(message);
} }
return;
} }
const metaFileJson = JSON.stringify(metaFile, null, "\t");
archive.append(metaFileJson, { name: "!!!meta.json" });
saveNote(rootMeta, "");
if (format === "html") {
if (!navigationMeta || !indexMeta || !cssMeta) {
throw new Error("Missing meta.");
}
saveNavigation(rootMeta, navigationMeta);
saveIndex(rootMeta, indexMeta);
saveCss(rootMeta, cssMeta);
}
const note = branch.getNote();
const zipFileName = `${branch.prefix ? `${branch.prefix} - ` : ""}${note.getTitleOrProtected()}.zip`;
if (setHeaders && "setHeader" in res) {
res.setHeader("Content-Disposition", getContentDisposition(zipFileName));
res.setHeader("Content-Type", "application/zip");
}
archive.pipe(res);
await archive.finalize();
taskContext.taskSucceeded();
} }
async function exportToZipFile(noteId: string, format: "markdown" | "html", zipFilePath: string, zipExportOptions?: AdvancedExportOptions) { async function exportToZipFile(noteId: string, format: "markdown" | "html", zipFilePath: string, zipExportOptions?: AdvancedExportOptions) {

View File

@ -84,7 +84,7 @@ export const DEFAULT_ALLOWED_TAGS = [
"del", "del",
"ins", "ins",
"en-media", // for ENEX import "en-media", // for ENEX import
// Additional tags (https://github.com/TriliumNext/Notes/issues/567) // Additional tags (https://github.com/TriliumNext/Trilium/issues/567)
"acronym", "acronym",
"article", "article",
"big", "big",

View File

@ -259,15 +259,15 @@ $$`;
const input = trimIndentation`\ const input = trimIndentation`\
### 🐞 Bugfixes ### 🐞 Bugfixes
* [v0.90.4 docker does not read USER\_UID and USER\_GID from environment](https://github.com/TriliumNext/Notes/issues/331) * [v0.90.4 docker does not read USER\_UID and USER\_GID from environment](https://github.com/TriliumNext/Trilium/issues/331)
* [Invalid CSRF token on Android phone](https://github.com/TriliumNext/Notes/issues/318) * [Invalid CSRF token on Android phone](https://github.com/TriliumNext/Trilium/issues/318)
* [Excess spacing in lists](https://github.com/TriliumNext/Notes/issues/341)`; * [Excess spacing in lists](https://github.com/TriliumNext/Trilium/issues/341)`;
const expected = [ const expected = [
/*html*/`<h3>🐞 Bugfixes</h3>`, /*html*/`<h3>🐞 Bugfixes</h3>`,
/*html*/`<ul>`, /*html*/`<ul>`,
/*html*/`<li><a href="https://github.com/TriliumNext/Notes/issues/331">v0.90.4 docker does not read USER_UID and USER_GID from environment</a></li>`, /*html*/`<li><a href="https://github.com/TriliumNext/Trilium/issues/331">v0.90.4 docker does not read USER_UID and USER_GID from environment</a></li>`,
/*html*/`<li><a href="https://github.com/TriliumNext/Notes/issues/318">Invalid CSRF token on Android phone</a></li>`, /*html*/`<li><a href="https://github.com/TriliumNext/Trilium/issues/318">Invalid CSRF token on Android phone</a></li>`,
/*html*/`<li><a href="https://github.com/TriliumNext/Notes/issues/341">Excess spacing in lists</a></li>`, /*html*/`<li><a href="https://github.com/TriliumNext/Trilium/issues/341">Excess spacing in lists</a></li>`,
/*html*/`</ul>` /*html*/`</ul>`
].join(""); ].join("");
expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected); expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected);

View File

@ -29,16 +29,18 @@
"tailwindcss": "^4.0.0", "tailwindcss": "^4.0.0",
"typescript": "^5.0.0", "typescript": "^5.0.0",
"typescript-eslint": "^8.20.0", "typescript-eslint": "^8.20.0",
"vite": "^6.2.6" "vite": "^7.0.0"
}, },
"dependencies": { "dependencies": {
"@inlang/paraglide-js": "^2.0.0" "@inlang/paraglide-js": "^2.0.0"
}, },
"nx": { "nx": {
"typecheck": { "targets": {
"dependsOn": [ "typecheck": {
"build" "dependsOn": [
] "build"
]
}
} }
} }
} }

View File

@ -117,11 +117,11 @@ export const downloadMatrix: DownloadMatrix = {
}, },
tarX64: { tarX64: {
name: "x86 (.tar.xz)", name: "x86 (.tar.xz)",
url: `https://github.com/TriliumNext/Notes/releases/download/v${version}/TriliumNotes-Server-v${version}-linux-x64.tar.xz` url: `https://github.com/TriliumNext/Trilium/releases/download/v${version}/TriliumNotes-Server-v${version}-linux-x64.tar.xz`
}, },
tarArm64: { tarArm64: {
name: "ARM (.tar.xz)", name: "ARM (.tar.xz)",
url: `https://github.com/TriliumNext/Notes/releases/download/v${version}/TriliumNotes-Server-v${version}-linux-arm64.tar.xz` url: `https://github.com/TriliumNext/Trilium/releases/download/v${version}/TriliumNotes-Server-v${version}-linux-arm64.tar.xz`
}, },
nixos: { nixos: {
name: "NixOS module", name: "NixOS module",
@ -150,7 +150,7 @@ export const downloadMatrix: DownloadMatrix = {
export function buildDownloadUrl(app: App, platform: Platform, format: string, architecture: Architecture): string { export function buildDownloadUrl(app: App, platform: Platform, format: string, architecture: Architecture): string {
if (app === "desktop") { if (app === "desktop") {
return downloadMatrix.desktop[platform]?.downloads[format].url ?? return downloadMatrix.desktop[platform]?.downloads[format].url ??
`https://github.com/TriliumNext/Notes/releases/download/v${version}/TriliumNotes-v${version}-${platform}-${architecture}.${format}`; `https://github.com/TriliumNext/Trilium/releases/download/v${version}/TriliumNotes-v${version}-${platform}-${architecture}.${format}`;
} else if (app === "server") { } else if (app === "server") {
return downloadMatrix.server[platform]?.downloads[format].url ?? "#"; return downloadMatrix.server[platform]?.downloads[format].url ?? "#";
} else { } else {

View File

@ -61,6 +61,32 @@
"attachments": [], "attachments": [],
"dirFileName": "Release Notes", "dirFileName": "Release Notes",
"children": [ "children": [
{
"isClone": false,
"noteId": "mYXFde3LuNR7",
"notePath": [
"hD3V4hiu2VW4",
"mYXFde3LuNR7"
],
"title": "v0.96.0",
"notePosition": 10,
"prefix": null,
"isExpanded": false,
"type": "text",
"mime": "text/html",
"attributes": [
{
"type": "relation",
"name": "template",
"value": "wyurrlcDl416",
"isInheritable": false,
"position": 60
}
],
"format": "markdown",
"dataFileName": "v0.96.0.md",
"attachments": []
},
{ {
"isClone": false, "isClone": false,
"noteId": "jthwbL0FdaeU", "noteId": "jthwbL0FdaeU",
@ -69,7 +95,7 @@
"jthwbL0FdaeU" "jthwbL0FdaeU"
], ],
"title": "v0.95.0", "title": "v0.95.0",
"notePosition": 10, "notePosition": 20,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -95,7 +121,7 @@
"7HGYsJbLuhnv" "7HGYsJbLuhnv"
], ],
"title": "v0.94.1", "title": "v0.94.1",
"notePosition": 20, "notePosition": 30,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -121,7 +147,7 @@
"Neq53ujRGBqv" "Neq53ujRGBqv"
], ],
"title": "v0.94.0", "title": "v0.94.0",
"notePosition": 30, "notePosition": 40,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -147,7 +173,7 @@
"VN3xnce1vLkX" "VN3xnce1vLkX"
], ],
"title": "v0.93.0", "title": "v0.93.0",
"notePosition": 40, "notePosition": 50,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -165,7 +191,7 @@
"WRaBfQqPr6qo" "WRaBfQqPr6qo"
], ],
"title": "v0.92.7", "title": "v0.92.7",
"notePosition": 50, "notePosition": 60,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -191,7 +217,7 @@
"a2rwfKNmUFU1" "a2rwfKNmUFU1"
], ],
"title": "v0.92.6", "title": "v0.92.6",
"notePosition": 60, "notePosition": 70,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -209,7 +235,7 @@
"fEJ8qErr0BKL" "fEJ8qErr0BKL"
], ],
"title": "v0.92.5-beta", "title": "v0.92.5-beta",
"notePosition": 70, "notePosition": 80,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -227,7 +253,7 @@
"kkkZQQGSXjwy" "kkkZQQGSXjwy"
], ],
"title": "v0.92.4", "title": "v0.92.4",
"notePosition": 80, "notePosition": 90,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -245,7 +271,7 @@
"vAroNixiezaH" "vAroNixiezaH"
], ],
"title": "v0.92.3-beta", "title": "v0.92.3-beta",
"notePosition": 90, "notePosition": 100,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -263,7 +289,7 @@
"mHEq1wxAKNZd" "mHEq1wxAKNZd"
], ],
"title": "v0.92.2-beta", "title": "v0.92.2-beta",
"notePosition": 100, "notePosition": 110,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -281,7 +307,7 @@
"IykjoAmBpc61" "IykjoAmBpc61"
], ],
"title": "v0.92.1-beta", "title": "v0.92.1-beta",
"notePosition": 110, "notePosition": 120,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -299,7 +325,7 @@
"dq2AJ9vSBX4Y" "dq2AJ9vSBX4Y"
], ],
"title": "v0.92.0-beta", "title": "v0.92.0-beta",
"notePosition": 120, "notePosition": 130,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -317,7 +343,7 @@
"3a8aMe4jz4yM" "3a8aMe4jz4yM"
], ],
"title": "v0.91.6", "title": "v0.91.6",
"notePosition": 130, "notePosition": 140,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -335,7 +361,7 @@
"8djQjkiDGESe" "8djQjkiDGESe"
], ],
"title": "v0.91.5", "title": "v0.91.5",
"notePosition": 140, "notePosition": 150,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -353,7 +379,7 @@
"OylxVoVJqNmr" "OylxVoVJqNmr"
], ],
"title": "v0.91.4-beta", "title": "v0.91.4-beta",
"notePosition": 150, "notePosition": 160,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -371,7 +397,7 @@
"tANGQDvnyhrj" "tANGQDvnyhrj"
], ],
"title": "v0.91.3-beta", "title": "v0.91.3-beta",
"notePosition": 160, "notePosition": 170,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -389,7 +415,7 @@
"hMoBfwSoj1SC" "hMoBfwSoj1SC"
], ],
"title": "v0.91.2-beta", "title": "v0.91.2-beta",
"notePosition": 170, "notePosition": 180,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -407,7 +433,7 @@
"a2XMSKROCl9z" "a2XMSKROCl9z"
], ],
"title": "v0.91.1-beta", "title": "v0.91.1-beta",
"notePosition": 180, "notePosition": 190,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -425,7 +451,7 @@
"yqXFvWbLkuMD" "yqXFvWbLkuMD"
], ],
"title": "v0.90.12", "title": "v0.90.12",
"notePosition": 190, "notePosition": 200,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -443,7 +469,7 @@
"veS7pg311yJP" "veS7pg311yJP"
], ],
"title": "v0.90.11-beta", "title": "v0.90.11-beta",
"notePosition": 200, "notePosition": 210,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -461,7 +487,7 @@
"sq5W9TQxRqMq" "sq5W9TQxRqMq"
], ],
"title": "v0.90.10-beta", "title": "v0.90.10-beta",
"notePosition": 210, "notePosition": 220,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -479,7 +505,7 @@
"yFEGVCUM9tPx" "yFEGVCUM9tPx"
], ],
"title": "v0.90.9-beta", "title": "v0.90.9-beta",
"notePosition": 220, "notePosition": 230,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -497,7 +523,7 @@
"o4wAGqOQuJtV" "o4wAGqOQuJtV"
], ],
"title": "v0.90.8", "title": "v0.90.8",
"notePosition": 230, "notePosition": 240,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -530,7 +556,7 @@
"i4A5g9iOg9I0" "i4A5g9iOg9I0"
], ],
"title": "v0.90.7-beta", "title": "v0.90.7-beta",
"notePosition": 240, "notePosition": 250,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -548,7 +574,7 @@
"ThNf2GaKgXUs" "ThNf2GaKgXUs"
], ],
"title": "v0.90.6-beta", "title": "v0.90.6-beta",
"notePosition": 250, "notePosition": 260,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -566,7 +592,7 @@
"G4PAi554kQUr" "G4PAi554kQUr"
], ],
"title": "v0.90.5-beta", "title": "v0.90.5-beta",
"notePosition": 260, "notePosition": 270,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -593,7 +619,7 @@
"zATRobGRCmBn" "zATRobGRCmBn"
], ],
"title": "v0.90.4", "title": "v0.90.4",
"notePosition": 270, "notePosition": 280,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -611,7 +637,7 @@
"sCDLf8IKn3Iz" "sCDLf8IKn3Iz"
], ],
"title": "v0.90.3", "title": "v0.90.3",
"notePosition": 280, "notePosition": 290,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -629,7 +655,7 @@
"VqqyBu4AuTjC" "VqqyBu4AuTjC"
], ],
"title": "v0.90.2-beta", "title": "v0.90.2-beta",
"notePosition": 290, "notePosition": 300,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -647,7 +673,7 @@
"RX3Nl7wInLsA" "RX3Nl7wInLsA"
], ],
"title": "v0.90.1-beta", "title": "v0.90.1-beta",
"notePosition": 300, "notePosition": 310,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -665,7 +691,7 @@
"GyueACukPWjk" "GyueACukPWjk"
], ],
"title": "v0.90.0-beta", "title": "v0.90.0-beta",
"notePosition": 310, "notePosition": 320,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",
@ -683,7 +709,7 @@
"wyurrlcDl416" "wyurrlcDl416"
], ],
"title": "Release Template", "title": "Release Template",
"notePosition": 320, "notePosition": 330,
"prefix": null, "prefix": null,
"isExpanded": false, "isExpanded": false,
"type": "text", "type": "text",

View File

@ -1,6 +1,6 @@
# v0.94.1 # v0.94.1
> [!NOTE] > [!NOTE]
> _Trilium Notes_ will rebrand itself back to Trilium Notes since @zadam was kind enough to give us the original name. See [#2190](https://github.com/orgs/TriliumNext/discussions/2190) for more info. This will probably be the "last" version branded as Trilium Notes_. > _Trilium Notes_ will rebrand itself back to Trilium Notes since @zadam was kind enough to give us the original name. See [#2190](https://github.com/orgs/TriliumNext/discussions/2190) for more info. This will probably be the "last" version branded as Trilium Notes\_.
> [!IMPORTANT] > [!IMPORTANT]
> If you enjoyed this release, consider showing a token of appreciation by: > If you enjoyed this release, consider showing a token of appreciation by:

View File

@ -0,0 +1,51 @@
# v0.96.0
> [!NOTE]
> The Docker image has been relocated to `triliumnext/trilium`. Please update your configuration accordingly.
> [!IMPORTANT]
> If you enjoyed this release, consider showing a token of appreciation by:
>
> * Pressing the “Star” button on [GitHub](https://github.com/TriliumNext/Notes) (top-right).
> * Considering a one-time or recurrent donation to the [lead developer](https://github.com/eliandoran) via [GitHub Sponsors](https://github.com/sponsors/eliandoran) or [PayPal](https://paypal.me/eliandoran).
## 💡 Key highlights
* Thanks to a partnership with CKEditor, we now have a set of features that would otherwise be available on a commercial license only.
* Slash commands for easy commands via the keyboard.
* Text snippets to insert reusable pieces of text (similar to templates, but for blocks of text content).
* For more information, see the user guide → Note Types → Text → Premium features.
## 🐞 Bugfixes
* [“Insert note after” long-press dialog doesnt create Note](https://github.com/TriliumNext/Notes/issues/2246)
* Code notes: user's font selection not respected.
* [Windows V0.95.0 Client Failed to sync with server (use of double-slashes)](https://github.com/TriliumNext/Notes/issues/2339) by @perfectra1n
* Desktop client not working on older Linux distros
* [NOT NULL constraint failed: revisions.title when saving an empty note](https://github.com/TriliumNext/Trilium/issues/6103)
## ✨ Improvements
* [Elixir language syntax highlighting for text notes](https://github.com/TriliumNext/Notes/pull/2327) (by @jshprentz) and code notes.
* [Autocomplete: support specifying path when creating a new note](https://github.com/TriliumNext/Notes/pull/2342) by @SiriusXT
* Markdown import: basic support for importing wikilinks
* Text notes:
* Allow disabling emoji auto-completion from settings.
* Allow disabling note auto-completion from settings.
* [Backend scripts: re-enable dayjs plugins by default](https://github.com/TriliumNext/Trilium/issues/6080)
## 📖 Documentation
* [regex search / Nix flake / restore dev docs](https://github.com/TriliumNext/Notes/pull/2341) by @FliegendeWurst
* New premium features in text note type.
## 🌍 Internationalization
* Spanish improvements by @hasecilu
## 🛠️ Technical updates
* flake: fix Electron version, fix Wayland support, fix source filter by @FliegendeWurst
* Improvements to the landing page (under development) by @FliegendeWurst
* Updated Node.js to v22.17.0
* Updated CKEditor to v45.2.1

View File

@ -4350,6 +4350,13 @@
"type": "text", "type": "text",
"mime": "text/markdown", "mime": "text/markdown",
"attributes": [ "attributes": [
{
"type": "relation",
"name": "internalLink",
"value": "rJ9grSgoExl9",
"isInheritable": false,
"position": 10
},
{ {
"type": "label", "type": "label",
"name": "shareAlias", "name": "shareAlias",
@ -4363,13 +4370,6 @@
"value": "bx bxl-markdown", "value": "bx bxl-markdown",
"isInheritable": false, "isInheritable": false,
"position": 50 "position": 50
},
{
"type": "relation",
"name": "internalLink",
"value": "rJ9grSgoExl9",
"isInheritable": false,
"position": 60
} }
], ],
"format": "markdown", "format": "markdown",
@ -5113,23 +5113,23 @@
{ {
"type": "relation", "type": "relation",
"name": "internalLink", "name": "internalLink",
"value": "nRhnJkTT8cPs", "value": "rJ9grSgoExl9",
"isInheritable": false, "isInheritable": false,
"position": 10 "position": 10
}, },
{
"type": "relation",
"name": "internalLink",
"value": "nRhnJkTT8cPs",
"isInheritable": false,
"position": 20
},
{ {
"type": "label", "type": "label",
"name": "iconClass", "name": "iconClass",
"value": "bx bx-info-circle", "value": "bx bx-info-circle",
"isInheritable": false, "isInheritable": false,
"position": 10 "position": 10
},
{
"type": "relation",
"name": "internalLink",
"value": "rJ9grSgoExl9",
"isInheritable": false,
"position": 20
} }
], ],
"format": "markdown", "format": "markdown",

View File

@ -1,6 +1,6 @@
{ {
"name": "@triliumnext/source", "name": "@triliumnext/source",
"version": "0.95.0", "version": "0.96.0",
"description": "Build your personal knowledge base with Trilium Notes", "description": "Build your personal knowledge base with Trilium Notes",
"directories": { "directories": {
"doc": "docs" "doc": "docs"
@ -40,7 +40,7 @@
"@playwright/test": "^1.36.0", "@playwright/test": "^1.36.0",
"@triliumnext/server": "workspace:*", "@triliumnext/server": "workspace:*",
"@types/express": "^5.0.0", "@types/express": "^5.0.0",
"@types/node": "22.15.33", "@types/node": "22.16.0",
"@vitest/coverage-v8": "^3.0.5", "@vitest/coverage-v8": "^3.0.5",
"@vitest/ui": "^3.0.0", "@vitest/ui": "^3.0.0",
"chalk": "5.4.1", "chalk": "5.4.1",
@ -56,13 +56,13 @@
"jsonc-eslint-parser": "^2.1.0", "jsonc-eslint-parser": "^2.1.0",
"nx": "21.2.1", "nx": "21.2.1",
"react-refresh": "^0.17.0", "react-refresh": "^0.17.0",
"rollup-plugin-webpack-stats": "2.0.7", "rollup-plugin-webpack-stats": "2.1.0",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"tsx": "4.20.3", "tsx": "4.20.3",
"typescript": "~5.8.0", "typescript": "~5.8.0",
"typescript-eslint": "^8.19.0", "typescript-eslint": "^8.19.0",
"upath": "2.0.1", "upath": "2.0.1",
"vite": "^6.0.0", "vite": "^7.0.0",
"vite-plugin-dts": "~4.5.0", "vite-plugin-dts": "~4.5.0",
"vitest": "^3.0.0" "vitest": "^3.0.0"
}, },

View File

@ -1,5 +1,5 @@
/** /**
* https://github.com/TriliumNext/Notes/issues/1002 * https://github.com/TriliumNext/Trilium/issues/1002
*/ */
import { Command, DocumentSelection, Element, Node, Plugin, Range } from 'ckeditor5'; import { Command, DocumentSelection, Element, Node, Plugin, Range } from 'ckeditor5';
@ -11,11 +11,11 @@ export default class MoveBlockUpDownPlugin extends Plugin {
editor.commands.add('moveBlockUp', new MoveBlockUpCommand(editor)); editor.commands.add('moveBlockUp', new MoveBlockUpCommand(editor));
editor.commands.add('moveBlockDown', new MoveBlockDownCommand(editor)); editor.commands.add('moveBlockDown', new MoveBlockDownCommand(editor));
// Use native DOM capturing to intercept Ctrl/Alt + ↑/↓, // Use native DOM capturing to intercept Ctrl/Alt + ↑/↓,
// as plugin-level keystroke handling may fail when the selection is near an object. // as plugin-level keystroke handling may fail when the selection is near an object.
this.bindMoveBlockShortcuts(editor); this.bindMoveBlockShortcuts(editor);
} }
bindMoveBlockShortcuts(editor: any) { bindMoveBlockShortcuts(editor: any) {
editor.editing.view.once('render', () => { editor.editing.view.once('render', () => {
const domRoot = editor.editing.view.getDomRoot(); const domRoot = editor.editing.view.getDomRoot();
@ -59,7 +59,7 @@ abstract class MoveBlockUpDownCommand extends Command {
if (!isEnabled) { if (!isEnabled) {
return; return;
} }
const movingBlocks = this.offset === 'before' const movingBlocks = this.offset === 'before'
? selectedBlocks ? selectedBlocks
: [...selectedBlocks].reverse(); : [...selectedBlocks].reverse();
@ -104,7 +104,7 @@ abstract class MoveBlockUpDownCommand extends Command {
this.scrollToSelection(); this.scrollToSelection();
}); });
} }
getSelectedBlocks(selection: DocumentSelection) { getSelectedBlocks(selection: DocumentSelection) {
const blocks = [...selection.getSelectedBlocks()]; const blocks = [...selection.getSelectedBlocks()];
const resolved: Element[] = []; const resolved: Element[] = [];
@ -129,7 +129,7 @@ abstract class MoveBlockUpDownCommand extends Command {
// Deduplicate adjacent duplicates (e.g., nested selections resolving to same block) // Deduplicate adjacent duplicates (e.g., nested selections resolving to same block)
return resolved.filter((blk, idx) => idx === 0 || blk !== resolved[idx - 1]); return resolved.filter((blk, idx) => idx === 0 || blk !== resolved[idx - 1]);
} }
scrollToSelection() { scrollToSelection() {
// Ensure scroll happens in sync with DOM updates // Ensure scroll happens in sync with DOM updates
requestAnimationFrame(() => { requestAnimationFrame(() => {

View File

@ -30,7 +30,7 @@
"@codemirror/lang-xml": "6.1.0", "@codemirror/lang-xml": "6.1.0",
"@codemirror/legacy-modes": "6.5.1", "@codemirror/legacy-modes": "6.5.1",
"@codemirror/search": "6.5.11", "@codemirror/search": "6.5.11",
"@codemirror/view": "6.37.2", "@codemirror/view": "6.38.0",
"@fsegurai/codemirror-theme-abcdef": "6.2.0", "@fsegurai/codemirror-theme-abcdef": "6.2.0",
"@fsegurai/codemirror-theme-abyss": "6.2.0", "@fsegurai/codemirror-theme-abyss": "6.2.0",
"@fsegurai/codemirror-theme-android-studio": "6.2.0", "@fsegurai/codemirror-theme-android-studio": "6.2.0",
@ -62,6 +62,6 @@
"codemirror-lang-elixir": "4.0.0", "codemirror-lang-elixir": "4.0.0",
"codemirror-lang-hcl": "0.1.0", "codemirror-lang-hcl": "0.1.0",
"codemirror-lang-mermaid": "0.5.0", "codemirror-lang-mermaid": "0.5.0",
"eslint-linter-browserify": "9.29.0" "eslint-linter-browserify": "9.30.1"
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@triliumnext/commons", "name": "@triliumnext/commons",
"version": "0.95.0", "version": "0.96.0",
"description": "Shared library between the clients (e.g. browser, Electron) and the server, mostly for type definitions and utility methods.", "description": "Shared library between the clients (e.g. browser, Electron) and the server, mostly for type definitions and utility methods.",
"private": true, "private": true,
"type": "module", "type": "module",

View File

@ -26,7 +26,7 @@
"@types/swagger-ui": "^5.0.0", "@types/swagger-ui": "^5.0.0",
"@typescript-eslint/eslint-plugin": "^8.0.0", "@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0", "@typescript-eslint/parser": "^8.0.0",
"dotenv": "^16.3.1", "dotenv": "^17.0.0",
"esbuild": "^0.25.0", "esbuild": "^0.25.0",
"eslint": "^9.0.0", "eslint": "^9.0.0",
"highlight.js": "^11.8.0", "highlight.js": "^11.8.0",

1344
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -23,10 +23,10 @@ const options = {
title: "Trilium Notes - Sync server API", title: "Trilium Notes - Sync server API",
version: packageJson["version"], version: packageJson["version"],
description: description:
"This is the internal sync server API used by Trilium Notes.\n\n_If you're looking for the officially supported External Trilium API, see [here](https://triliumnext.github.io/Docs/Wiki/etapi.html)._\n\nThis page does not yet list all routes. For a full list, see the [route controller](https://github.com/TriliumNext/Notes/blob/v0.91.6/src/routes/routes.ts).", "This is the internal sync server API used by Trilium Notes.\n\n_If you're looking for the officially supported External Trilium API, see [here](https://triliumnext.github.io/Docs/Wiki/etapi.html)._\n\nThis page does not yet list all routes. For a full list, see the [route controller](https://github.com/TriliumNext/Trilium/blob/v0.91.6/src/routes/routes.ts).",
contact: { contact: {
name: "TriliumNext issue tracker", name: "TriliumNext issue tracker",
url: "https://github.com/TriliumNext/Notes/issues" url: "https://github.com/TriliumNext/Trilium/issues"
}, },
license: { license: {
name: "GNU Free Documentation License 1.3 (or later)", name: "GNU Free Documentation License 1.3 (or later)",
@ -159,7 +159,7 @@ console.log("Saved to", outputPath);
* type: string * type: string
* example: "text" * example: "text"
* enum: ["text", "code", "render", "file", "image", "search", "relationMap", "book", "noteMap", "mermaid", "canvas", "webView", "launcher", "doc", "contentWidget", "mindMap", "geoMap"] * enum: ["text", "code", "render", "file", "image", "search", "relationMap", "book", "noteMap", "mermaid", "canvas", "webView", "launcher", "doc", "contentWidget", "mindMap", "geoMap"]
* description: "[Reference list](https://github.com/TriliumNext/Notes/blob/v0.91.6/src/services/note_types.ts)" * description: "[Reference list](https://github.com/TriliumNext/Trilium/blob/v0.91.6/src/services/note_types.ts)"
* mime: * mime:
* type: string * type: string
* example: "text/html" * example: "text/html"

View File

@ -10,7 +10,7 @@
import { type BrowserContext, chromium } from 'playwright'; import { type BrowserContext, chromium } from 'playwright';
import { createWriteStream, existsSync, readFileSync, writeFileSync } from 'fs'; import { createWriteStream, existsSync, readFileSync, writeFileSync } from 'fs';
const SOURCE_URL = "https://github.com/TriliumNext/Notes"; const SOURCE_URL = "https://github.com/TriliumNext/Trilium";
const TARGET_REPOSITORY_ID = 92111509; const TARGET_REPOSITORY_ID = 92111509;
const fsLog = createWriteStream('port-discussions.log', { flags: 'a' }); const fsLog = createWriteStream('port-discussions.log', { flags: 'a' });