Merge remote-tracking branch 'origin/main' into feature/table_view

This commit is contained in:
Elian Doran 2025-07-04 12:59:03 +03:00
commit d8cb5efd2d
No known key found for this signature in database
16 changed files with 942 additions and 663 deletions

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

@ -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

@ -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

@ -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

@ -4,7 +4,7 @@
"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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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