): string {
let fileName = baseFileName.trim();
if (!fileName) {
fileName = "note";
@@ -90,36 +96,14 @@ async function exportToZip(taskContext: TaskContext<"export">, branch: BBranch,
}
let existingExtension = path.extname(fileName).toLowerCase();
- let newExtension;
-
- // the following two are handled specifically since we always want to have these extensions no matter the automatic detection
- // and/or existing detected extensions in the note name
- if (type === "text" && format === "markdown") {
- newExtension = "md";
- } else if (type === "text" && format === "html") {
- newExtension = "html";
- } else if (mime === "application/x-javascript" || mime === "text/javascript") {
- newExtension = "js";
- } else if (type === "canvas" || mime === "application/json") {
- newExtension = "json";
- } else if (existingExtension.length > 0) {
- // if the page already has an extension, then we'll just keep it
- newExtension = null;
- } else {
- if (mime?.toLowerCase()?.trim() === "image/jpg") {
- newExtension = "jpg";
- } else if (mime?.toLowerCase()?.trim() === "text/mermaid") {
- newExtension = "txt";
- } else {
- newExtension = mimeTypes.extension(mime) || "dat";
- }
- }
+ const newExtension = provider.mapExtension(type, mime, existingExtension, format);
// if the note is already named with the extension (e.g. "image.jpg"), then it's silly to append the exact same extension again
if (newExtension && existingExtension !== `.${newExtension.toLowerCase()}`) {
fileName += `.${newExtension}`;
}
+
return getUniqueFilename(existingFileNames, fileName);
}
@@ -145,7 +129,8 @@ async function exportToZip(taskContext: TaskContext<"export">, branch: BBranch,
const notePath = parentMeta.notePath.concat([note.noteId]);
if (note.noteId in noteIdToMeta) {
- const fileName = getUniqueFilename(existingFileNames, `${baseFileName}.clone.${format === "html" ? "html" : "md"}`);
+ const extension = provider.mapExtension("text", "text/html", "", format);
+ const fileName = getUniqueFilename(existingFileNames, `${baseFileName}.clone.${extension}`);
const meta: NoteMeta = {
isClone: true,
@@ -155,7 +140,7 @@ async function exportToZip(taskContext: TaskContext<"export">, branch: BBranch,
prefix: branch.prefix,
dataFileName: fileName,
type: "text", // export will have text description
- format: format
+ format: (format === "markdown" ? "markdown" : "html")
};
return meta;
}
@@ -185,7 +170,7 @@ async function exportToZip(taskContext: TaskContext<"export">, branch: BBranch,
taskContext.increaseProgressCount();
if (note.type === "text") {
- meta.format = format;
+ meta.format = (format === "markdown" ? "markdown" : "html");
}
noteIdToMeta[note.noteId] = meta as NoteMeta;
@@ -194,10 +179,13 @@ async function exportToZip(taskContext: TaskContext<"export">, branch: BBranch,
note.sortChildren();
const childBranches = note.getChildBranches().filter((branch) => branch?.noteId !== "_hidden");
- const available = !note.isProtected || protectedSessionService.isProtectedSessionAvailable();
+ let shouldIncludeFile = (!note.isProtected || protectedSessionService.isProtectedSessionAvailable());
+ if (format !== "share") {
+ shouldIncludeFile = shouldIncludeFile && (note.getContent().length > 0 || childBranches.length === 0);
+ }
// if it's a leaf, then we'll export it even if it's empty
- if (available && (note.getContent().length > 0 || childBranches.length === 0)) {
+ if (shouldIncludeFile) {
meta.dataFileName = getDataFileName(note.type, note.mime, baseFileName, existingFileNames);
}
@@ -273,8 +261,6 @@ async function exportToZip(taskContext: TaskContext<"export">, branch: BBranch,
return url;
}
- const rewriteFn = (zipExportOptions?.customRewriteLinks ? zipExportOptions?.customRewriteLinks(rewriteLinks, getNoteTargetUrl) : rewriteLinks);
-
function rewriteLinks(content: string, noteMeta: NoteMeta): string {
content = content.replace(/src="[^"]*api\/images\/([a-zA-Z0-9_]+)\/[^"]*"/g, (match, targetNoteId) => {
const url = getNoteTargetUrl(targetNoteId, noteMeta);
@@ -316,53 +302,15 @@ async function exportToZip(taskContext: TaskContext<"export">, branch: BBranch,
}
}
- function prepareContent(title: string, content: string | Buffer, noteMeta: NoteMeta): string | Buffer {
- if (["html", "markdown"].includes(noteMeta?.format || "")) {
+ function prepareContent(title: string, content: string | Buffer, noteMeta: NoteMeta, note?: BNote): string | Buffer {
+ const isText = ["html", "markdown"].includes(noteMeta?.format || "");
+ if (isText) {
content = content.toString();
- content = rewriteFn(content, noteMeta);
}
- if (noteMeta.format === "html" && typeof content === "string") {
- if (!content.substr(0, 100).toLowerCase().includes(" element will make sure external links are openable - https://github.com/zadam/trilium/issues/1289#issuecomment-704066809
- content = `
-
-
-
-
-
- ${htmlTitle}
-
-
-
-
${htmlTitle}
-
-
${content}
-
-
-`;
- }
-
- return content.length < 100_000 ? html.prettyPrint(content, { indent_size: 2 }) : content;
- } else if (noteMeta.format === "markdown" && typeof content === "string") {
- let markdownContent = mdService.toMarkdown(content);
-
- if (markdownContent.trim().length > 0 && !markdownContent.startsWith("# ")) {
- markdownContent = `# ${title}\r
-${markdownContent}`;
- }
-
- return markdownContent;
- } else {
- return content;
- }
+ return content;
}
function saveNote(noteMeta: NoteMeta, filePathPrefix: string) {
@@ -377,7 +325,7 @@ ${markdownContent}`;
let content: string | Buffer = `This is a clone of a note. Go to its primary location.
`;
- content = prepareContent(noteMeta.title, content, noteMeta);
+ content = prepareContent(noteMeta.title, content, noteMeta, undefined);
archive.append(content, { name: filePathPrefix + noteMeta.dataFileName });
@@ -393,7 +341,7 @@ ${markdownContent}`;
}
if (noteMeta.dataFileName) {
- const content = prepareContent(noteMeta.title, note.getContent(), noteMeta);
+ const content = prepareContent(noteMeta.title, note.getContent(), noteMeta, note);
archive.append(content, {
name: filePathPrefix + noteMeta.dataFileName,
@@ -429,138 +377,21 @@ ${markdownContent}`;
}
}
- function saveNavigation(rootMeta: NoteMeta, navigationMeta: NoteMeta) {
- if (!navigationMeta.dataFileName) {
- return;
- }
-
- function saveNavigationInner(meta: NoteMeta) {
- let html = "";
-
- const escapedTitle = escapeHtml(`${meta.prefix ? `${meta.prefix} - ` : ""}${meta.title}`);
-
- if (meta.dataFileName && meta.noteId) {
- const targetUrl = getNoteTargetUrl(meta.noteId, rootMeta);
-
- html += `${escapedTitle}`;
- } else {
- html += escapedTitle;
- }
-
- if (meta.children && meta.children.length > 0) {
- html += "";
-
- for (const child of meta.children) {
- html += saveNavigationInner(child);
- }
-
- html += "
";
- }
-
- return `${html}`;
- }
-
- const fullHtml = `
-
-
-
-
-
- ${saveNavigationInner(rootMeta)}
-
-`;
- const prettyHtml = fullHtml.length < 100_000 ? html.prettyPrint(fullHtml, { indent_size: 2 }) : fullHtml;
-
- archive.append(prettyHtml, { name: navigationMeta.dataFileName });
+ const existingFileNames: Record = format === "html" ? { navigation: 0, index: 1 } : {};
+ const rootMeta = createNoteMeta(branch, { notePath: [] }, existingFileNames);
+ if (!rootMeta) {
+ throw new Error("Unable to create root meta.");
}
- function saveIndex(rootMeta: NoteMeta, indexMeta: NoteMeta) {
- let firstNonEmptyNote;
- let curMeta = rootMeta;
+ const metaFile: NoteMetaFile = {
+ formatVersion: 2,
+ appVersion: packageInfo.version,
+ files: [rootMeta]
+ };
- if (!indexMeta.dataFileName) {
- return;
- }
-
- while (!firstNonEmptyNote) {
- if (curMeta.dataFileName && curMeta.noteId) {
- firstNonEmptyNote = getNoteTargetUrl(curMeta.noteId, rootMeta);
- }
-
- if (curMeta.children && curMeta.children.length > 0) {
- curMeta = curMeta.children[0];
- } else {
- break;
- }
- }
-
- const fullHtml = `
-
-
-
-
-
-
-`;
-
- archive.append(fullHtml, { name: indexMeta.dataFileName });
- }
-
- function saveCss(rootMeta: NoteMeta, cssMeta: NoteMeta) {
- if (!cssMeta.dataFileName) {
- return;
- }
-
- const cssFile = isDev
- ? path.join(__dirname, "../../../../../node_modules/ckeditor5/dist/ckeditor5-content.css")
- : path.join(getResourceDir(), "ckeditor5-content.css");
-
- archive.append(fs.readFileSync(cssFile, "utf-8"), { name: cssMeta.dataFileName });
- }
+ provider.prepareMeta(metaFile);
try {
- const existingFileNames: Record = format === "html" ? { navigation: 0, index: 1 } : {};
- const rootMeta = createNoteMeta(branch, { notePath: [] }, existingFileNames);
- if (!rootMeta) {
- throw new Error("Unable to create root meta.");
- }
-
- const metaFile: NoteMetaFile = {
- formatVersion: 2,
- appVersion: packageInfo.version,
- 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);
-
- indexMeta = {
- noImport: true,
- dataFileName: "index.html"
- };
-
- metaFile.files.push(indexMeta);
-
- cssMeta = {
- noImport: true,
- dataFileName: "style.css"
- };
-
- metaFile.files.push(cssMeta);
- }
-
for (const noteMeta of Object.values(noteIdToMeta)) {
// filter out relations which are not inside this export
noteMeta.attributes = (noteMeta.attributes || []).filter((attr) => {
@@ -584,34 +415,6 @@ ${markdownContent}`;
}
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(null);
} catch (e: unknown) {
const message = `Export failed with error: ${e instanceof Error ? e.message : String(e)}`;
log.error(message);
@@ -623,9 +426,30 @@ ${markdownContent}`;
res.status(500).send(message);
}
}
+
+ const metaFileJson = JSON.stringify(metaFile, null, "\t");
+
+ archive.append(metaFileJson, { name: "!!!meta.json" });
+
+ saveNote(rootMeta, "");
+
+ provider.afterDone(rootMeta);
+
+ 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(null);
}
-async function exportToZipFile(noteId: string, format: "markdown" | "html", zipFilePath: string, zipExportOptions?: AdvancedExportOptions) {
+async function exportToZipFile(noteId: string, format: ExportFormat, zipFilePath: string, zipExportOptions?: AdvancedExportOptions) {
const fileOutputStream = fs.createWriteStream(zipFilePath);
const taskContext = new TaskContext("no-progress-reporting", "export", null);
diff --git a/apps/server/src/services/export/zip/abstract_provider.ts b/apps/server/src/services/export/zip/abstract_provider.ts
new file mode 100644
index 000000000..c9645a843
--- /dev/null
+++ b/apps/server/src/services/export/zip/abstract_provider.ts
@@ -0,0 +1,89 @@
+import { Archiver } from "archiver";
+import type { default as NoteMeta, NoteMetaFile } from "../../meta/note_meta.js";
+import type BNote from "../../../becca/entities/bnote.js";
+import type BBranch from "../../../becca/entities/bbranch.js";
+import mimeTypes from "mime-types";
+import { NoteType } from "@triliumnext/commons";
+
+type RewriteLinksFn = (content: string, noteMeta: NoteMeta) => string;
+
+export type ExportFormat = "html" | "markdown" | "share";
+
+export interface AdvancedExportOptions {
+ /**
+ * If `true`, then only the note's content will be kept. If `false` (default), then each page will have its own template.
+ */
+ skipHtmlTemplate?: boolean;
+
+ /**
+ * Provides a custom function to rewrite the links found in HTML or Markdown notes. This method is called for every note imported, if it's of the right type.
+ *
+ * @param originalRewriteLinks the original rewrite links function. Can be used to access the default behaviour without having to reimplement it.
+ * @param getNoteTargetUrl the method to obtain a note's target URL, used internally by `originalRewriteLinks` but can be used here as well.
+ * @returns a function to rewrite the links in HTML or Markdown notes.
+ */
+ customRewriteLinks?: (originalRewriteLinks: RewriteLinksFn, getNoteTargetUrl: (targetNoteId: string, sourceMeta: NoteMeta) => string | null) => RewriteLinksFn;
+}
+
+export interface ZipExportProviderData {
+ branch: BBranch;
+ getNoteTargetUrl: (targetNoteId: string, sourceMeta: NoteMeta) => string | null;
+ archive: Archiver;
+ zipExportOptions?: AdvancedExportOptions;
+ rewriteFn: RewriteLinksFn;
+}
+
+export abstract class ZipExportProvider {
+ branch: BBranch;
+ getNoteTargetUrl: (targetNoteId: string, sourceMeta: NoteMeta) => string | null;
+ archive: Archiver;
+ zipExportOptions?: AdvancedExportOptions;
+ rewriteFn: RewriteLinksFn;
+
+ constructor(data: ZipExportProviderData) {
+ this.branch = data.branch;
+ this.getNoteTargetUrl = data.getNoteTargetUrl;
+ this.archive = data.archive;
+ this.zipExportOptions = data.zipExportOptions;
+ this.rewriteFn = data.rewriteFn;
+ }
+
+ abstract prepareMeta(metaFile: NoteMetaFile): void;
+ abstract prepareContent(title: string, content: string | Buffer, noteMeta: NoteMeta, note: BNote | undefined, branch: BBranch): string | Buffer;
+ abstract afterDone(rootMeta: NoteMeta): void;
+
+ /**
+ * Determines the extension of the resulting file for a specific note type.
+ *
+ * @param type the type of the note.
+ * @param mime the mime type of the note.
+ * @param existingExtension the existing extension, including the leading period character.
+ * @param format the format requested for export (e.g. HTML, Markdown).
+ * @returns an extension *without* the leading period character, or `null` to preserve the existing extension instead.
+ */
+ mapExtension(type: NoteType | null, mime: string, existingExtension: string, format: ExportFormat) {
+ // the following two are handled specifically since we always want to have these extensions no matter the automatic detection
+ // and/or existing detected extensions in the note name
+ if (type === "text" && format === "markdown") {
+ return "md";
+ } else if (type === "text" && format === "html") {
+ return "html";
+ } else if (mime === "application/x-javascript" || mime === "text/javascript") {
+ return "js";
+ } else if (type === "canvas" || mime === "application/json") {
+ return "json";
+ } else if (existingExtension.length > 0) {
+ // if the page already has an extension, then we'll just keep it
+ return null;
+ } else {
+ if (mime?.toLowerCase()?.trim() === "image/jpg") {
+ return "jpg";
+ } else if (mime?.toLowerCase()?.trim() === "text/mermaid") {
+ return "txt";
+ } else {
+ return mimeTypes.extension(mime) || "dat";
+ }
+ }
+ }
+
+}
diff --git a/apps/server/src/services/export/zip/html.ts b/apps/server/src/services/export/zip/html.ts
new file mode 100644
index 000000000..0cab8193c
--- /dev/null
+++ b/apps/server/src/services/export/zip/html.ts
@@ -0,0 +1,176 @@
+import type NoteMeta from "../../meta/note_meta.js";
+import { escapeHtml, getResourceDir, isDev } from "../../utils";
+import html from "html";
+import { ZipExportProvider } from "./abstract_provider.js";
+import path from "path";
+import fs from "fs";
+
+export default class HtmlExportProvider extends ZipExportProvider {
+
+ private navigationMeta: NoteMeta | null = null;
+ private indexMeta: NoteMeta | null = null;
+ private cssMeta: NoteMeta | null = null;
+
+ prepareMeta(metaFile) {
+ this.navigationMeta = {
+ noImport: true,
+ dataFileName: "navigation.html"
+ };
+ metaFile.files.push(this.navigationMeta);
+
+ this.indexMeta = {
+ noImport: true,
+ dataFileName: "index.html"
+ };
+ metaFile.files.push(this.indexMeta);
+
+ this.cssMeta = {
+ noImport: true,
+ dataFileName: "style.css"
+ };
+ metaFile.files.push(this.cssMeta);
+ }
+
+ prepareContent(title: string, content: string | Buffer, noteMeta: NoteMeta): string | Buffer {
+ if (noteMeta.format === "html" && typeof content === "string") {
+ if (!content.substr(0, 100).toLowerCase().includes(" element will make sure external links are openable - https://github.com/zadam/trilium/issues/1289#issuecomment-704066809
+ content = `
+
+
+
+
+
+ ${htmlTitle}
+
+
+
+
${htmlTitle}
+
+
${content}
+
+
+`;
+ }
+
+ if (content.length < 100_000) {
+ content = html.prettyPrint(content, { indent_size: 2 })
+ }
+ content = this.rewriteFn(content as string, noteMeta);
+ return content;
+ } else {
+ return content;
+ }
+ }
+
+ afterDone(rootMeta: NoteMeta) {
+ if (!this.navigationMeta || !this.indexMeta || !this.cssMeta) {
+ throw new Error("Missing meta.");
+ }
+
+ this.#saveNavigation(rootMeta, this.navigationMeta);
+ this.#saveIndex(rootMeta, this.indexMeta);
+ this.#saveCss(rootMeta, this.cssMeta);
+ }
+
+ #saveNavigationInner(rootMeta: NoteMeta, meta: NoteMeta) {
+ let html = "";
+
+ const escapedTitle = escapeHtml(`${meta.prefix ? `${meta.prefix} - ` : ""}${meta.title}`);
+
+ if (meta.dataFileName && meta.noteId) {
+ const targetUrl = this.getNoteTargetUrl(meta.noteId, rootMeta);
+
+ html += `${escapedTitle}`;
+ } else {
+ html += escapedTitle;
+ }
+
+ if (meta.children && meta.children.length > 0) {
+ html += "";
+
+ for (const child of meta.children) {
+ html += this.#saveNavigationInner(rootMeta, child);
+ }
+
+ html += "
";
+ }
+
+ return `${html}`;
+ }
+
+ #saveNavigation(rootMeta: NoteMeta, navigationMeta: NoteMeta) {
+ if (!navigationMeta.dataFileName) {
+ return;
+ }
+
+ const fullHtml = `
+
+
+
+
+
+ ${this.#saveNavigationInner(rootMeta, rootMeta)}
+
+ `;
+ const prettyHtml = fullHtml.length < 100_000 ? html.prettyPrint(fullHtml, { indent_size: 2 }) : fullHtml;
+
+ this.archive.append(prettyHtml, { name: navigationMeta.dataFileName });
+ }
+
+ #saveIndex(rootMeta: NoteMeta, indexMeta: NoteMeta) {
+ let firstNonEmptyNote;
+ let curMeta = rootMeta;
+
+ if (!indexMeta.dataFileName) {
+ return;
+ }
+
+ while (!firstNonEmptyNote) {
+ if (curMeta.dataFileName && curMeta.noteId) {
+ firstNonEmptyNote = this.getNoteTargetUrl(curMeta.noteId, rootMeta);
+ }
+
+ if (curMeta.children && curMeta.children.length > 0) {
+ curMeta = curMeta.children[0];
+ } else {
+ break;
+ }
+ }
+
+ const fullHtml = `
+
+
+
+
+
+
+`;
+
+ this.archive.append(fullHtml, { name: indexMeta.dataFileName });
+ }
+
+ #saveCss(rootMeta: NoteMeta, cssMeta: NoteMeta) {
+ if (!cssMeta.dataFileName) {
+ return;
+ }
+
+ const cssFile = isDev
+ ? path.join(__dirname, "../../../../../../node_modules/ckeditor5/dist/ckeditor5-content.css")
+ : path.join(getResourceDir(), "ckeditor5-content.css");
+ const cssContent = fs.readFileSync(cssFile, "utf-8");
+ this.archive.append(cssContent, { name: cssMeta.dataFileName });
+ }
+
+}
+
diff --git a/apps/server/src/services/export/zip/markdown.ts b/apps/server/src/services/export/zip/markdown.ts
new file mode 100644
index 000000000..827f059d6
--- /dev/null
+++ b/apps/server/src/services/export/zip/markdown.ts
@@ -0,0 +1,27 @@
+import NoteMeta from "../../meta/note_meta"
+import { ZipExportProvider } from "./abstract_provider.js"
+import mdService from "../markdown.js";
+
+export default class MarkdownExportProvider extends ZipExportProvider {
+
+ prepareMeta() { }
+
+ prepareContent(title: string, content: string | Buffer, noteMeta: NoteMeta): string | Buffer {
+ if (noteMeta.format === "markdown" && typeof content === "string") {
+ let markdownContent = mdService.toMarkdown(content);
+
+ if (markdownContent.trim().length > 0 && !markdownContent.startsWith("# ")) {
+ markdownContent = `# ${title}\r
+${markdownContent}`;
+ }
+
+ markdownContent = this.rewriteFn(markdownContent, noteMeta);
+ return markdownContent;
+ } else {
+ return content;
+ }
+ }
+
+ afterDone() { }
+
+}
diff --git a/apps/server/src/services/export/zip/share_theme.ts b/apps/server/src/services/export/zip/share_theme.ts
new file mode 100644
index 000000000..bf989b06c
--- /dev/null
+++ b/apps/server/src/services/export/zip/share_theme.ts
@@ -0,0 +1,115 @@
+import { join } from "path";
+import NoteMeta, { NoteMetaFile } from "../../meta/note_meta";
+import { ExportFormat, ZipExportProvider } from "./abstract_provider.js";
+import { RESOURCE_DIR } from "../../resource_dir";
+import { getResourceDir, isDev } from "../../utils";
+import fs, { readdirSync } from "fs";
+import { renderNoteForExport } from "../../../share/content_renderer";
+import type BNote from "../../../becca/entities/bnote.js";
+import type BBranch from "../../../becca/entities/bbranch.js";
+import { getShareThemeAssetDir } from "../../../routes/assets";
+
+const shareThemeAssetDir = getShareThemeAssetDir();
+
+export default class ShareThemeExportProvider extends ZipExportProvider {
+
+ private assetsMeta: NoteMeta[] = [];
+ private indexMeta: NoteMeta | null = null;
+
+ prepareMeta(metaFile: NoteMetaFile): void {
+
+ const assets = [
+ "icon-color.svg"
+ ];
+
+ for (const file of readdirSync(shareThemeAssetDir)) {
+ assets.push(`assets/${file}`);
+ }
+
+ for (const asset of assets) {
+ const assetMeta = {
+ noImport: true,
+ dataFileName: asset
+ };
+ this.assetsMeta.push(assetMeta);
+ metaFile.files.push(assetMeta);
+ }
+
+ this.indexMeta = {
+ noImport: true,
+ dataFileName: "index.html"
+ };
+
+ metaFile.files.push(this.indexMeta);
+ }
+
+ prepareContent(title: string, content: string | Buffer, noteMeta: NoteMeta, note: BNote | undefined, branch: BBranch): string | Buffer {
+ if (!noteMeta?.notePath?.length) {
+ throw new Error("Missing note path.");
+ }
+ const basePath = "../".repeat(noteMeta.notePath.length - 1);
+
+ if (note) {
+ content = renderNoteForExport(note, branch, basePath, noteMeta.notePath.slice(0, -1));
+ if (typeof content === "string") {
+ content = content.replace(/href="[^"]*\.\/([a-zA-Z0-9_\/]{12})[^"]*"/g, (match, id) => {
+ if (match.includes("/assets/")) return match;
+ return `href="#root/${id}"`;
+ });
+ content = this.rewriteFn(content, noteMeta);
+ }
+ }
+
+ return content;
+ }
+
+ afterDone(rootMeta: NoteMeta): void {
+ this.#saveAssets(rootMeta, this.assetsMeta);
+ this.#saveIndex(rootMeta);
+ }
+
+ mapExtension(type: string | null, mime: string, existingExtension: string, format: ExportFormat): string | null {
+ if (mime.startsWith("image/")) {
+ return null;
+ }
+
+ return "html";
+ }
+
+ #saveIndex(rootMeta: NoteMeta) {
+ if (!this.indexMeta?.dataFileName) {
+ return;
+ }
+
+ const note = this.branch.getNote();
+ const fullHtml = this.prepareContent(rootMeta.title ?? "", note.getContent(), rootMeta, note, this.branch);
+ this.archive.append(fullHtml, { name: this.indexMeta.dataFileName });
+ }
+
+ #saveAssets(rootMeta: NoteMeta, assetsMeta: NoteMeta[]) {
+ for (const assetMeta of assetsMeta) {
+ if (!assetMeta.dataFileName) {
+ continue;
+ }
+
+ let cssContent = getShareThemeAssets(assetMeta.dataFileName);
+ this.archive.append(cssContent, { name: assetMeta.dataFileName });
+ }
+ }
+
+}
+
+function getShareThemeAssets(nameWithExtension: string) {
+ let path: string | undefined;
+ if (nameWithExtension === "icon-color.svg") {
+ path = join(RESOURCE_DIR, "images", nameWithExtension);
+ } else if (nameWithExtension.startsWith("assets")) {
+ path = join(shareThemeAssetDir, nameWithExtension.replace(/^assets\//, ""));
+ } else if (isDev) {
+ path = join(getResourceDir(), "..", "..", "client", "dist", "src", nameWithExtension);
+ } else {
+ path = join(getResourceDir(), "public", "src", nameWithExtension);
+ }
+
+ return fs.readFileSync(path);
+}
diff --git a/apps/server/src/services/meta/note_meta.ts b/apps/server/src/services/meta/note_meta.ts
index 33e7a7843..7a7a9f4b7 100644
--- a/apps/server/src/services/meta/note_meta.ts
+++ b/apps/server/src/services/meta/note_meta.ts
@@ -1,6 +1,7 @@
import type { NoteType } from "@triliumnext/commons";
import type AttachmentMeta from "./attachment_meta.js";
import type AttributeMeta from "./attribute_meta.js";
+import type { ExportFormat } from "../export/zip/abstract_provider.js";
export interface NoteMetaFile {
formatVersion: number;
@@ -19,7 +20,7 @@ export default interface NoteMeta {
type?: NoteType;
mime?: string;
/** 'html' or 'markdown', applicable to text notes only */
- format?: "html" | "markdown";
+ format?: ExportFormat;
dataFileName?: string;
dirFileName?: string;
/** this file should not be imported (e.g., HTML navigation) */
diff --git a/apps/server/src/share/content_renderer.ts b/apps/server/src/share/content_renderer.ts
index 83ddfde2e..3ab219f26 100644
--- a/apps/server/src/share/content_renderer.ts
+++ b/apps/server/src/share/content_renderer.ts
@@ -1,10 +1,23 @@
-import { parse, HTMLElement, TextNode } from "node-html-parser";
+import { parse, HTMLElement, TextNode, Options } from "node-html-parser";
import shaca from "./shaca/shaca.js";
-import assetPath from "../services/asset_path.js";
+import assetPath, { assetUrlFragment } from "../services/asset_path.js";
import shareRoot from "./share_root.js";
import escapeHtml from "escape-html";
import type SNote from "./shaca/entities/snote.js";
+import BNote from "../becca/entities/bnote.js";
+import type BBranch from "../becca/entities/bbranch.js";
import { t } from "i18next";
+import SBranch from "./shaca/entities/sbranch.js";
+import options from "../services/options.js";
+import utils, { getResourceDir, isDev, safeExtractMessageAndStackFromError } from "../services/utils.js";
+import ejs from "ejs";
+import log from "../services/log.js";
+import { join } from "path";
+import { readFileSync } from "fs";
+import { highlightAuto } from "@triliumnext/highlightjs";
+
+const shareAdjustedAssetPath = isDev ? assetPath : `../${assetPath}`;
+const templateCache: Map = new Map();
/**
* Represents the output of the content renderer.
@@ -16,7 +29,192 @@ export interface Result {
isEmpty?: boolean;
}
-export function getContent(note: SNote) {
+interface Subroot {
+ note?: SNote | BNote;
+ branch?: SBranch | BBranch
+}
+
+function getSharedSubTreeRoot(note: SNote | BNote | undefined): Subroot {
+ if (!note || note.noteId === shareRoot.SHARE_ROOT_NOTE_ID) {
+ // share root itself is not shared
+ return {};
+ }
+
+ // every path leads to share root, but which one to choose?
+ // for the sake of simplicity, URLs are not note paths
+ const parentBranch = note.getParentBranches()[0];
+
+ if (note instanceof BNote) {
+ return {
+ note,
+ branch: parentBranch
+ }
+ }
+
+ if (parentBranch.parentNoteId === shareRoot.SHARE_ROOT_NOTE_ID) {
+ return {
+ note,
+ branch: parentBranch
+ };
+ }
+
+ return getSharedSubTreeRoot(parentBranch.getParentNote());
+}
+
+export function renderNoteForExport(note: BNote, parentBranch: BBranch, basePath: string, ancestors: string[]) {
+ const subRoot: Subroot = {
+ branch: parentBranch,
+ note: parentBranch.getNote()
+ };
+
+ return renderNoteContentInternal(note, {
+ subRoot,
+ rootNoteId: parentBranch.noteId,
+ cssToLoad: [
+ `${basePath}assets/styles.css`,
+ `${basePath}assets/scripts.css`,
+ ],
+ jsToLoad: [
+ `${basePath}assets/scripts.js`
+ ],
+ logoUrl: `${basePath}icon-color.svg`,
+ ancestors
+ });
+}
+
+export function renderNoteContent(note: SNote) {
+ const subRoot = getSharedSubTreeRoot(note);
+
+ const ancestors: string[] = [];
+ let notePointer = note;
+ while (notePointer.parents[0]?.noteId !== subRoot.note?.noteId) {
+ const pointerParent = notePointer.parents[0];
+ if (!pointerParent) {
+ break;
+ }
+ ancestors.push(pointerParent.noteId);
+ notePointer = pointerParent;
+ }
+
+ // Determine CSS to load.
+ const cssToLoad: string[] = [];
+ if (!note.isLabelTruthy("shareOmitDefaultCss")) {
+ cssToLoad.push(`assets/styles.css`);
+ cssToLoad.push(`assets/scripts.css`);
+ }
+ for (const cssRelation of note.getRelations("shareCss")) {
+ cssToLoad.push(`api/notes/${cssRelation.value}/download`);
+ }
+
+ // Determine JS to load.
+ const jsToLoad: string[] = [
+ "assets/scripts.js"
+ ];
+ for (const jsRelation of note.getRelations("shareJs")) {
+ jsToLoad.push(`api/notes/${jsRelation.value}/download`);
+ }
+
+ const customLogoId = note.getRelation("shareLogo")?.value;
+ const logoUrl = customLogoId ? `api/images/${customLogoId}/image.png` : `../${assetUrlFragment}/images/icon-color.svg`;
+
+ return renderNoteContentInternal(note, {
+ subRoot,
+ rootNoteId: "_share",
+ cssToLoad,
+ jsToLoad,
+ logoUrl,
+ ancestors
+ });
+}
+
+interface RenderArgs {
+ subRoot: Subroot;
+ rootNoteId: string;
+ cssToLoad: string[];
+ jsToLoad: string[];
+ logoUrl: string;
+ ancestors: string[];
+}
+
+function renderNoteContentInternal(note: SNote | BNote, renderArgs: RenderArgs) {
+ const { header, content, isEmpty } = getContent(note);
+ const showLoginInShareTheme = options.getOption("showLoginInShareTheme");
+ const opts = {
+ note,
+ header,
+ content,
+ isEmpty,
+ assetPath: shareAdjustedAssetPath,
+ assetUrlFragment,
+ showLoginInShareTheme,
+ t,
+ isDev,
+ utils,
+ ...renderArgs
+ };
+
+ // Check if the user has their own template.
+ if (note.hasRelation("shareTemplate")) {
+ // Get the template note and content
+ const templateId = note.getRelation("shareTemplate")?.value;
+ const templateNote = templateId && shaca.getNote(templateId);
+
+ // Make sure the note type is correct
+ if (templateNote && templateNote.type === "code" && templateNote.mime === "application/x-ejs") {
+ // EJS caches the result of this so we don't need to pre-cache
+ const includer = (path: string) => {
+ const childNote = templateNote.children.find((n) => path === n.title);
+ if (!childNote) throw new Error(`Unable to find child note: ${path}.`);
+ if (childNote.type !== "code" || childNote.mime !== "application/x-ejs") throw new Error("Incorrect child note type.");
+
+ const template = childNote.getContent();
+ if (typeof template !== "string") throw new Error("Invalid template content type.");
+
+ return { template };
+ };
+
+ // Try to render user's template, w/ fallback to default view
+ try {
+ const content = templateNote.getContent();
+ if (typeof content === "string") {
+ return ejs.render(content, opts, { includer });
+ }
+ } catch (e: unknown) {
+ const [errMessage, errStack] = safeExtractMessageAndStackFromError(e);
+ log.error(`Rendering user provided share template (${templateId}) threw exception ${errMessage} with stacktrace: ${errStack}`);
+ }
+ }
+ }
+
+ // Render with the default view otherwise.
+ const templatePath = getDefaultTemplatePath("page");
+ return ejs.render(readTemplate(templatePath), opts, {
+ includer: (path) => {
+ // Path is relative to apps/server/dist/assets/views
+ return { template: readTemplate(getDefaultTemplatePath(path)) };
+ }
+ });
+}
+
+function getDefaultTemplatePath(template: string) {
+ // Path is relative to apps/server/dist/assets/views
+ return process.env.NODE_ENV === "development"
+ ? join(__dirname, `../../../../packages/share-theme/src/templates/${template}.ejs`)
+ : join(getResourceDir(), `share-theme/templates/${template}.ejs`);
+}
+
+function readTemplate(path: string) {
+ const cachedTemplate = templateCache.get(path);
+ if (cachedTemplate) {
+ return cachedTemplate;
+ }
+
+ const templateString = readFileSync(path, "utf-8");
+ templateCache.set(path, templateString);
+ return templateString;
+}
+
+export function getContent(note: SNote | BNote) {
if (note.isProtected) {
return {
header: "",
@@ -65,9 +263,12 @@ function renderIndex(result: Result) {
result.content += "";
}
-function renderText(result: Result, note: SNote) {
+function renderText(result: Result, note: SNote | BNote) {
if (typeof result.content !== "string") return;
- const document = parse(result.content || "");
+ const parseOpts: Partial = {
+ blockTextElements: {}
+ }
+ const document = parse(result.content || "", parseOpts);
// Process include notes.
for (const includeNoteEl of document.querySelectorAll("section.include-note")) {
@@ -80,7 +281,7 @@ function renderText(result: Result, note: SNote) {
const includedResult = getContent(note);
if (typeof includedResult.content !== "string") continue;
- const includedDocument = parse(includedResult.content).childNodes;
+ const includedDocument = parse(includedResult.content, parseOpts).childNodes;
if (includedDocument) {
includeNoteEl.replaceWith(...includedDocument);
}
@@ -89,6 +290,7 @@ function renderText(result: Result, note: SNote) {
result.isEmpty = document.textContent?.trim().length === 0 && document.querySelectorAll("img").length === 0;
if (!result.isEmpty) {
+ // Process attachment links.
for (const linkEl of document.querySelectorAll("a")) {
const href = linkEl.getAttribute("href");
@@ -102,21 +304,15 @@ function renderText(result: Result, note: SNote) {
}
}
- result.content = document.innerHTML ?? "";
-
- if (result.content.includes(``)) {
- result.header += `
-
-
-
-
-`;
+ // Apply syntax highlight.
+ for (const codeEl of document.querySelectorAll("pre code")) {
+ const highlightResult = highlightAuto(codeEl.innerText);
+ codeEl.innerHTML = highlightResult.value;
+ codeEl.classList.add("hljs");
}
+ result.content = document.innerHTML ?? "";
+
if (note.hasLabel("shareIndex")) {
renderIndex(result);
}
@@ -174,7 +370,7 @@ export function renderCode(result: Result) {
}
}
-function renderMermaid(result: Result, note: SNote) {
+function renderMermaid(result: Result, note: SNote | BNote) {
if (typeof result.content !== "string") {
return;
}
@@ -188,11 +384,11 @@ function renderMermaid(result: Result, note: SNote) {
`;
}
-function renderImage(result: Result, note: SNote) {
+function renderImage(result: Result, note: SNote | BNote) {
result.content = `
`;
}
-function renderFile(note: SNote, result: Result) {
+function renderFile(note: SNote | BNote, result: Result) {
if (note.mime === "application/pdf") {
result.content = ``;
} else {
diff --git a/apps/server/src/share/routes.ts b/apps/server/src/share/routes.ts
index 77f542ba2..275474c2d 100644
--- a/apps/server/src/share/routes.ts
+++ b/apps/server/src/share/routes.ts
@@ -4,41 +4,12 @@ import type { Request, Response, Router } from "express";
import shaca from "./shaca/shaca.js";
import shacaLoader from "./shaca/shaca_loader.js";
-import shareRoot from "./share_root.js";
-import contentRenderer from "./content_renderer.js";
-import assetPath, { assetUrlFragment } from "../services/asset_path.js";
-import appPath from "../services/app_path.js";
import searchService from "../services/search/services/search.js";
import SearchContext from "../services/search/search_context.js";
-import log from "../services/log.js";
import type SNote from "./shaca/entities/snote.js";
-import type SBranch from "./shaca/entities/sbranch.js";
import type SAttachment from "./shaca/entities/sattachment.js";
-import utils, { isDev, safeExtractMessageAndStackFromError } from "../services/utils.js";
-import options from "../services/options.js";
-import { t } from "i18next";
-import ejs from "ejs";
-import { join } from "path";
-
-function getSharedSubTreeRoot(note: SNote): { note?: SNote; branch?: SBranch } {
- if (note.noteId === shareRoot.SHARE_ROOT_NOTE_ID) {
- // share root itself is not shared
- return {};
- }
-
- // every path leads to share root, but which one to choose?
- // for the sake of simplicity, URLs are not note paths
- const parentBranch = note.getParentBranches()[0];
-
- if (parentBranch.parentNoteId === shareRoot.SHARE_ROOT_NOTE_ID) {
- return {
- note,
- branch: parentBranch
- };
- }
-
- return getSharedSubTreeRoot(parentBranch.getParentNote());
-}
+import { renderNoteContent } from "./content_renderer.js";
+import utils from "../services/utils.js";
function addNoIndexHeader(note: SNote, res: Response) {
if (note.isLabelTruthy("shareDisallowRobotIndexing")) {
@@ -109,8 +80,7 @@ function renderImageAttachment(image: SNote, res: Response, attachmentName: stri
let svgString = "";
const attachment = image.getAttachmentByTitle(attachmentName);
if (!attachment) {
- res.status(404);
- renderDefault(res, "404");
+
return;
}
const content = attachment.getContent();
@@ -138,12 +108,19 @@ function renderImageAttachment(image: SNote, res: Response, attachmentName: stri
res.send(svg);
}
+function render404(res: Response) {
+ res.status(404);
+ const shareThemePath = `../../share-theme/templates/404.ejs`;
+ res.render(shareThemePath);
+}
+
function register(router: Router) {
+
function renderNote(note: SNote, req: Request, res: Response) {
if (!note) {
console.log("Unable to find note ", note);
res.status(404);
- renderDefault(res, "404");
+ render404(res);
return;
}
@@ -161,63 +138,7 @@ function register(router: Router) {
return;
}
- const { header, content, isEmpty } = contentRenderer.getContent(note);
- const subRoot = getSharedSubTreeRoot(note);
- const showLoginInShareTheme = options.getOption("showLoginInShareTheme");
- const opts = {
- note,
- header,
- content,
- isEmpty,
- subRoot,
- assetPath: isDev ? assetPath : `../${assetPath}`,
- assetUrlFragment,
- appPath: isDev ? appPath : `../${appPath}`,
- showLoginInShareTheme,
- t,
- isDev,
- utils
- };
- let useDefaultView = true;
-
- // Check if the user has their own template
- if (note.hasRelation("shareTemplate")) {
- // Get the template note and content
- const templateId = note.getRelation("shareTemplate")?.value;
- const templateNote = templateId && shaca.getNote(templateId);
-
- // Make sure the note type is correct
- if (templateNote && templateNote.type === "code" && templateNote.mime === "application/x-ejs") {
- // EJS caches the result of this so we don't need to pre-cache
- const includer = (path: string) => {
- const childNote = templateNote.children.find((n) => path === n.title);
- if (!childNote) throw new Error(`Unable to find child note: ${path}.`);
- if (childNote.type !== "code" || childNote.mime !== "application/x-ejs") throw new Error("Incorrect child note type.");
-
- const template = childNote.getContent();
- if (typeof template !== "string") throw new Error("Invalid template content type.");
-
- return { template };
- };
-
- // Try to render user's template, w/ fallback to default view
- try {
- const content = templateNote.getContent();
- if (typeof content === "string") {
- const ejsResult = ejs.render(content, opts, { includer });
- res.send(ejsResult);
- useDefaultView = false; // Rendering went okay, don't use default view
- }
- } catch (e: unknown) {
- const [errMessage, errStack] = safeExtractMessageAndStackFromError(e);
- log.error(`Rendering user provided share template (${templateId}) threw exception ${errMessage} with stacktrace: ${errStack}`);
- }
- }
- }
-
- if (useDefaultView) {
- renderDefault(res, "page", opts);
- }
+ res.send(renderNoteContent(note));
}
router.get("/share/", (req, res) => {
@@ -401,14 +322,6 @@ function register(router: Router) {
});
}
-function renderDefault(res: Response>, template: "page" | "404", opts: any = {}) {
- // Path is relative to apps/server/dist/assets/views
- const shareThemePath = process.env.NODE_ENV === "development"
- ? join(__dirname, `../../../../packages/share-theme/src/templates/${template}.ejs`)
- : `../../share-theme/templates/${template}.ejs`;
- res.render(shareThemePath, opts);
-}
-
export default {
register
};
diff --git a/apps/server/src/types.d.ts b/apps/server/src/types.d.ts
index c302e27d8..8d6048a76 100644
--- a/apps/server/src/types.d.ts
+++ b/apps/server/src/types.d.ts
@@ -38,3 +38,9 @@ declare module "@triliumnext/share-theme/styles.css" {
const content: string;
export default content;
}
+
+declare module '*.css' {}
+declare module '*?raw' {
+ const src: string
+ export default src
+}
diff --git a/apps/website/src/translations/hi/translation.json b/apps/website/src/translations/hi/translation.json
new file mode 100644
index 000000000..d59189ed3
--- /dev/null
+++ b/apps/website/src/translations/hi/translation.json
@@ -0,0 +1,5 @@
+{
+ "get-started": {
+ "title": "शुरू करें"
+ }
+}
diff --git a/apps/website/src/translations/mr/translation.json b/apps/website/src/translations/mr/translation.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/apps/website/src/translations/mr/translation.json
@@ -0,0 +1 @@
+{}
diff --git a/docs/README-de.md b/docs/README-de.md
index 505f3adea..5da30911b 100644
--- a/docs/README-de.md
+++ b/docs/README-de.md
@@ -49,8 +49,8 @@ einen schnellen Überblick:
Unsere Dokumentation ist verfügbar in mehreren Formaten:
- **Online-Dokumentation**: Die vollständige Dokumentation finden man unter
[docs.triliumnotes.org](https://docs.triliumnotes.org/)
-- **In-App Help**: Press `F1` within Trilium to access the same documentation
- directly in the application
+- **In-App-Hilfe**: drücke `F1` in Trilium, um dieselbe Dokumentation direkt in
+ der Anwendung aufzurufen
- **GitHub**: Durchsuche das
[Benutzerhandbuch](./docs/User%20Guide/User%20Guide/) in diesem Repository
@@ -68,112 +68,119 @@ Unsere Dokumentation ist verfügbar in mehreren Formaten:
## 🎁 Funktionen
-* Notes can be arranged into arbitrarily deep tree. Single note can be placed
- into multiple places in the tree (see
- [cloning](https://triliumnext.github.io/Docs/Wiki/cloning-notes))
-* Rich WYSIWYG note editor including e.g. tables, images and
- [math](https://triliumnext.github.io/Docs/Wiki/text-notes) with markdown
- [autoformat](https://triliumnext.github.io/Docs/Wiki/text-notes#autoformat)
-* Support for editing [notes with source
- code](https://triliumnext.github.io/Docs/Wiki/code-notes), including syntax
- highlighting
-* Fast and easy [navigation between
- notes](https://triliumnext.github.io/Docs/Wiki/note-navigation), full text
- search and [note
- hoisting](https://triliumnext.github.io/Docs/Wiki/note-hoisting)
-* Seamless [note
- versioning](https://triliumnext.github.io/Docs/Wiki/note-revisions)
-* Note [attributes](https://triliumnext.github.io/Docs/Wiki/attributes) can be
- used for note organization, querying and advanced
- [scripting](https://triliumnext.github.io/Docs/Wiki/scripts)
-* UI available in English, German, Spanish, French, Romanian, and Chinese
- (simplified and traditional)
-* Direct [OpenID and TOTP
- integration](./docs/User%20Guide/User%20Guide/Installation%20%26%20Setup/Server%20Installation/Multi-Factor%20Authentication.md)
- for more secure login
-* [Synchronization](https://triliumnext.github.io/Docs/Wiki/synchronization)
- with self-hosted sync server
- * there's a [3rd party service for hosting synchronisation
- server](https://trilium.cc/paid-hosting)
-* [Sharing](https://triliumnext.github.io/Docs/Wiki/sharing) (publishing) notes
- to public internet
-* Strong [note
- encryption](https://triliumnext.github.io/Docs/Wiki/protected-notes) with
- per-note granularity
-* Sketching diagrams, based on [Excalidraw](https://excalidraw.com/) (note type
- "canvas")
-* [Relation maps](https://triliumnext.github.io/Docs/Wiki/relation-map) and
- [link maps](https://triliumnext.github.io/Docs/Wiki/link-map) for visualizing
- notes and their relations
-* Mind maps, based on [Mind Elixir](https://docs.mind-elixir.com/)
-* [Geo maps](./docs/User%20Guide/User%20Guide/Note%20Types/Geo%20Map.md) with
- location pins and GPX tracks
-* [Scripting](https://triliumnext.github.io/Docs/Wiki/scripts) - see [Advanced
- showcases](https://triliumnext.github.io/Docs/Wiki/advanced-showcases)
-* [REST API](https://triliumnext.github.io/Docs/Wiki/etapi) for automation
-* Scales well in both usability and performance upwards of 100 000 notes
-* Touch optimized [mobile
- frontend](https://triliumnext.github.io/Docs/Wiki/mobile-frontend) for
- smartphones and tablets
-* Built-in [dark theme](https://triliumnext.github.io/Docs/Wiki/themes), support
- for user themes
-* [Evernote](https://triliumnext.github.io/Docs/Wiki/evernote-import) and
- [Markdown import & export](https://triliumnext.github.io/Docs/Wiki/markdown)
-* [Web Clipper](https://triliumnext.github.io/Docs/Wiki/web-clipper) for easy
- saving of web content
-* Customizable UI (sidebar buttons, user-defined widgets, ...)
-* [Metrics](./docs/User%20Guide/User%20Guide/Advanced%20Usage/Metrics.md), along
- with a [Grafana
- Dashboard](./docs/User%20Guide/User%20Guide/Advanced%20Usage/Metrics/grafana-dashboard.json)
+* Notizen lassen sich in beliebig tiefe Baumstrukturen einordnen. Eine einzelne
+ Notiz kann an mehreren Stellen im Baum existieren (siehe
+ [Klonen](https://triliumnext.github.io/Docs/Wiki/cloning-notes))
+* Umfangreicher WYSIWYG-Editor für Notizen, z. B. mit Tabellen, Bildern und
+ [Mathematik](https://triliumnext.github.io/Docs/Wiki/text-notes) mit
+ Markdown-Autoformatierung
+* Unterstützung für das Bearbeiten von [Notizen mit
+ Quellcode](https://triliumnext.github.io/Docs/Wiki/code-notes), inkl.
+ Syntaxhervorhebung
+* Schnelle und einfache [Navigation zwischen
+ Notizen](https://triliumnext.github.io/Docs/Wiki/note-navigation),
+ Volltextsuche sowie
+ [Notizhervorhebung](https://triliumnext.github.io/Docs/Wiki/note-hoisting)
+* Nahtlose [Versionierung von
+ Notizen](https://triliumnext.github.io/Docs/Wiki/note-revisions)
+* Notiz [Attribute](https://triliumnext.github.io/Docs/Wiki/attributes) können
+ zur Organisation von Notizen, für Abfragen und erweiterte
+ [Skripterstellung](https://triliumnext.github.io/Docs/Wiki/scripts) verwendet
+ werden
+* Benutzeroberfläche verfügbar in Englisch, Deutsch, Spanisch, Französisch,
+ Rumänisch sowie Chinesisch (vereinfacht und traditionell)
+* Direkte [OpenID- und
+ TOTP-Integration](./docs/User%20Guide/User%20Guide/Installation%20%26%20Setup/Server%20Installation/Multi-Factor%20Authentication.md)
+ für eine sicherere Anmeldung
+* [Synchronisierung](https://triliumnext.github.io/Docs/Wiki/synchronization)
+ mit einem selbst gehosteten Synchronisierungsserver
+ * Es gibt einen [Drittanbieter-Dienst für das Hosten von
+ Synchronisationsservern](https://trilium.cc/paid-hosting)
+* [Freigabe](https://triliumnext.github.io/Docs/Wiki/sharing) (Veröffentlichung)
+ von Notizen im öffentlichen Internet
+* Starke
+ [Notizverschlüsselung](https://triliumnext.github.io/Docs/Wiki/protected-notes)
+ mit Granularität pro Notiz
+* Skizzieren von Diagrammen basierend auf [Excalidraw](https://excalidraw.com/)
+ (Notiztyp „Canvas“)
+* [Beziehungskarten](https://triliumnext.github.io/Docs/Wiki/relation-map) and
+ [Verknüpfungskarten](https://triliumnext.github.io/Docs/Wiki/link-map) zur
+ Visualisierung von Notizen und deren Beziehungen
+* Mindmaps, basierend auf [Mind Elixir](https://docs.mind-elixir.com/)
+* [Geokarten](./docs/User%20Guide/User%20Guide/Note%20Types/Geo%20Map.md) mit
+ Standortmarkierungen und GPX-Tracks
+* [Skripting](https://triliumnext.github.io/Docs/Wiki/scripts) – siehe
+ [Erweiterte
+ Showcases](https://triliumnext.github.io/Docs/Wiki/advanced-showcases)
+* [REST-API](https://triliumnext.github.io/Docs/Wiki/etapi) für die
+ Automatisierung
+* Skalierbar in Bedienbarkeit und Performance — geeignet für über 100.000
+ Notizen
+* Touch-optimiertes [mobiles
+ Frontend](https://triliumnext.github.io/Docs/Wiki/mobile-frontend) für
+ Smartphones und Tablets
+* Integriertes [dunkles Design](https://triliumnext.github.io/Docs/Wiki/themes),
+ Unterstützung für benutzerdefinierte Designs
+* [Evernote](https://triliumnext.github.io/Docs/Wiki/evernote-import) und
+ [Markdown importieren und
+ exportieren](https://triliumnext.github.io/Docs/Wiki/markdown)
+* [Web Clipper](https://triliumnext.github.io/Docs/Wiki/web-clipper) zum
+ einfachen Speichern von Webinhalten
+* Anpassbare Benutzeroberfläche (Seitenleisten-Schaltflächen, benutzerdefinierte
+ Widgets, ...)
+* [Metriken](./docs/User%20Guide/User%20Guide/Advanced%20Usage/Metrics.md),
+ zusammen mit einem
+ [Grafana-Dashboard](./docs/User%20Guide/User%20Guide/Advanced%20Usage/Metrics/grafana-dashboard.json)
-✨ Check out the following third-party resources/communities for more TriliumNext
-related goodies:
+✨ Weitere Informationen zu TriliumNext findet man in den folgenden
+Ressourcen/Communities von Drittanbietern:
-- [awesome-trilium](https://github.com/Nriver/awesome-trilium) for 3rd party
- themes, scripts, plugins and more.
-- [TriliumRocks!](https://trilium.rocks/) for tutorials, guides, and much more.
+- [awesome-trilium](https://github.com/Nriver/awesome-trilium) bietet von
+ Drittanbietern erstellte Themes, Skripte, Plugins und vieles mehr
+- [TriliumRocks!](https://trilium.rocks/) für Tutorials, Anleitungen und vieles
+ mehr.
-## ❓Why TriliumNext?
+## ❓ Warum TriliumNext?
-The original Trilium developer ([Zadam](https://github.com/zadam)) has
-graciously given the Trilium repository to the community project which resides
-at https://github.com/TriliumNext
+Der ursprüngliche Entwickler von Trilium ([Zadam](https://github.com/zadam)) hat
+das Trilium-Repository der Gemeinschaft übergeben, die nun unter
+https://github.com/TriliumNext agiert
### Migration von Zadam/Trilium?
-There are no special migration steps to migrate from a zadam/Trilium instance to
-a TriliumNext/Trilium instance. Simply [install
-TriliumNext/Trilium](#-installation) as usual and it will use your existing
-database.
+Es sind keine speziellen Migrationsschritte erforderlich, um von einer
+zadam/Trilium-Instanz auf eine TriliumNext/Trilium-Instanz umzustellen. Man
+[Installieret TriliumNext/Trilium](#-installation) einfach wie gewohnt, und die
+vorhandene Datenbank wird verwendet.
-Versions up to and including
-[v0.90.4](https://github.com/TriliumNext/Trilium/releases/tag/v0.90.4) are
-compatible with the latest zadam/trilium version of
-[v0.63.7](https://github.com/zadam/trilium/releases/tag/v0.63.7). Any later
-versions of TriliumNext/Trilium have their sync versions incremented which
-prevents direct migration.
+Versionen bis einschließlich
+[v0.90.4](https://github.com/TriliumNext/Trilium/releases/tag/v0.90.4) sind
+kompatibel mit der letzten zadam/trilium-Version
+[v0.63.7](https://github.com/zadam/trilium/releases/tag/v0.63.7). Alle späteren
+Versionen von TriliumNext/Trilium haben ihre Sync-Versionen erhöht, was eine
+direkte Migration verhindert
-## 💬 Discuss with us
+## 💬 Diskussion mit uns
-Feel free to join our official conversations. We would love to hear what
-features, suggestions, or issues you may have!
+Nehme gerne an den offiziellen Diskussionen teil. Feedback, Funktionsvorschläge
+oder Problemberichte sind jederzeit willkommen!
-- [Matrix](https://matrix.to/#/#triliumnext:matrix.org) (For synchronous
- discussions.)
- - The `General` Matrix room is also bridged to
- [XMPP](xmpp:discuss@trilium.thisgreat.party?join)
-- [Github Discussions](https://github.com/TriliumNext/Trilium/discussions) (For
- asynchronous discussions.)
-- [Github Issues](https://github.com/TriliumNext/Trilium/issues) (For bug
- reports and feature requests.)
+- [Matrix](https://matrix.to/#/#triliumnext:matrix.org) (für
+ Echtzeit-Diskussionen.)
+ - Der `allgemeine` Matrix-Raum ist zusätzlich mit
+ [XMPP](xmpp:discuss@trilium.thisgreat.party?join) verbunden
+- (Github Diskussionen)(https://github.com/TriliumNext/Trilium/discussions) (für
+ asynchrone Diskussionen)
+- [Github-Probleme](https://github.com/TriliumNext/Trilium/issues) (für
+ Fehlerberichte und Funktionsanfragen)
## 🏗 Installation
### Windows / MacOS
-Download the binary release for your platform from the [latest release
-page](https://github.com/TriliumNext/Trilium/releases/latest), unzip the package
-and run the `trilium` executable.
+Lade die Binärversion für deine Plattform von der Seite mit den [neuesten
+Versionen](https://github.com/TriliumNext/Trilium/releases/latest) herunter,
+entpacke das Paket und führe die ausführbare Datei `trilium` aus.
### Linux
diff --git a/docs/README-hi.md b/docs/README-hi.md
new file mode 100644
index 000000000..e3afddd5f
--- /dev/null
+++ b/docs/README-hi.md
@@ -0,0 +1,332 @@
+
+
+
+
+# ट्रिलियम नोट्स
+
+
+\
+
+\
+[](https://app.relative-ci.com/projects/Di5q7dz9daNDZ9UXi0Bp)
+[](https://hosted.weblate.org/engage/trilium/)
+
+[English](./README.md) | [Chinese (Simplified)](./docs/README-ZH_CN.md) |
+[Chinese (Traditional)](./docs/README-ZH_TW.md) | [Russian](./docs/README-ru.md)
+| [Japanese](./docs/README-ja.md) | [Italian](./docs/README-it.md) |
+[Spanish](./docs/README-es.md)
+
+Trilium Notes is a free and open-source, cross-platform hierarchical note taking
+application with focus on building large personal knowledge bases.
+
+See [screenshots](https://triliumnext.github.io/Docs/Wiki/screenshot-tour) for
+quick overview:
+
+
+
+## ⏬ Download
+- [Latest release](https://github.com/TriliumNext/Trilium/releases/latest) –
+ stable version, recommended for most users.
+- [Nightly build](https://github.com/TriliumNext/Trilium/releases/tag/nightly) –
+ unstable development version, updated daily with the latest features and
+ fixes.
+
+## 📚 Documentation
+
+**Visit our comprehensive documentation at
+[docs.triliumnotes.org](https://docs.triliumnotes.org/)**
+
+Our documentation is available in multiple formats:
+- **Online Documentation**: Browse the full documentation at
+ [docs.triliumnotes.org](https://docs.triliumnotes.org/)
+- **In-App Help**: Press `F1` within Trilium to access the same documentation
+ directly in the application
+- **GitHub**: Navigate through the [User
+ Guide](./docs/User%20Guide/User%20Guide/) in this repository
+
+### Quick Links
+- [Getting Started Guide](https://docs.triliumnotes.org/)
+- [Installation
+ Instructions](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation.md)
+- [Docker
+ Setup](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation/1.%20Installing%20the%20server/Using%20Docker.md)
+- [Upgrading
+ TriliumNext](./docs/User%20Guide/User%20Guide/Installation%20%26%20Setup/Upgrading%20TriliumNext.md)
+- [Basic Concepts and
+ Features](./docs/User%20Guide/User%20Guide/Basic%20Concepts%20and%20Features/Notes.md)
+- [Patterns of Personal Knowledge
+ Base](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge)
+
+## 🎁 Features
+
+* Notes can be arranged into arbitrarily deep tree. Single note can be placed
+ into multiple places in the tree (see
+ [cloning](https://triliumnext.github.io/Docs/Wiki/cloning-notes))
+* Rich WYSIWYG note editor including e.g. tables, images and
+ [math](https://triliumnext.github.io/Docs/Wiki/text-notes) with markdown
+ [autoformat](https://triliumnext.github.io/Docs/Wiki/text-notes#autoformat)
+* Support for editing [notes with source
+ code](https://triliumnext.github.io/Docs/Wiki/code-notes), including syntax
+ highlighting
+* Fast and easy [navigation between
+ notes](https://triliumnext.github.io/Docs/Wiki/note-navigation), full text
+ search and [note
+ hoisting](https://triliumnext.github.io/Docs/Wiki/note-hoisting)
+* Seamless [note
+ versioning](https://triliumnext.github.io/Docs/Wiki/note-revisions)
+* Note [attributes](https://triliumnext.github.io/Docs/Wiki/attributes) can be
+ used for note organization, querying and advanced
+ [scripting](https://triliumnext.github.io/Docs/Wiki/scripts)
+* UI available in English, German, Spanish, French, Romanian, and Chinese
+ (simplified and traditional)
+* Direct [OpenID and TOTP
+ integration](./docs/User%20Guide/User%20Guide/Installation%20%26%20Setup/Server%20Installation/Multi-Factor%20Authentication.md)
+ for more secure login
+* [Synchronization](https://triliumnext.github.io/Docs/Wiki/synchronization)
+ with self-hosted sync server
+ * there's a [3rd party service for hosting synchronisation
+ server](https://trilium.cc/paid-hosting)
+* [Sharing](https://triliumnext.github.io/Docs/Wiki/sharing) (publishing) notes
+ to public internet
+* Strong [note
+ encryption](https://triliumnext.github.io/Docs/Wiki/protected-notes) with
+ per-note granularity
+* Sketching diagrams, based on [Excalidraw](https://excalidraw.com/) (note type
+ "canvas")
+* [Relation maps](https://triliumnext.github.io/Docs/Wiki/relation-map) and
+ [link maps](https://triliumnext.github.io/Docs/Wiki/link-map) for visualizing
+ notes and their relations
+* Mind maps, based on [Mind Elixir](https://docs.mind-elixir.com/)
+* [Geo maps](./docs/User%20Guide/User%20Guide/Note%20Types/Geo%20Map.md) with
+ location pins and GPX tracks
+* [Scripting](https://triliumnext.github.io/Docs/Wiki/scripts) - see [Advanced
+ showcases](https://triliumnext.github.io/Docs/Wiki/advanced-showcases)
+* [REST API](https://triliumnext.github.io/Docs/Wiki/etapi) for automation
+* Scales well in both usability and performance upwards of 100 000 notes
+* Touch optimized [mobile
+ frontend](https://triliumnext.github.io/Docs/Wiki/mobile-frontend) for
+ smartphones and tablets
+* Built-in [dark theme](https://triliumnext.github.io/Docs/Wiki/themes), support
+ for user themes
+* [Evernote](https://triliumnext.github.io/Docs/Wiki/evernote-import) and
+ [Markdown import & export](https://triliumnext.github.io/Docs/Wiki/markdown)
+* [Web Clipper](https://triliumnext.github.io/Docs/Wiki/web-clipper) for easy
+ saving of web content
+* Customizable UI (sidebar buttons, user-defined widgets, ...)
+* [Metrics](./docs/User%20Guide/User%20Guide/Advanced%20Usage/Metrics.md), along
+ with a [Grafana
+ Dashboard](./docs/User%20Guide/User%20Guide/Advanced%20Usage/Metrics/grafana-dashboard.json)
+
+✨ Check out the following third-party resources/communities for more TriliumNext
+related goodies:
+
+- [awesome-trilium](https://github.com/Nriver/awesome-trilium) for 3rd party
+ themes, scripts, plugins and more.
+- [TriliumRocks!](https://trilium.rocks/) for tutorials, guides, and much more.
+
+## ❓Why TriliumNext?
+
+The original Trilium developer ([Zadam](https://github.com/zadam)) has
+graciously given the Trilium repository to the community project which resides
+at https://github.com/TriliumNext
+
+### ⬆️Migrating from Zadam/Trilium?
+
+There are no special migration steps to migrate from a zadam/Trilium instance to
+a TriliumNext/Trilium instance. Simply [install
+TriliumNext/Trilium](#-installation) as usual and it will use your existing
+database.
+
+Versions up to and including
+[v0.90.4](https://github.com/TriliumNext/Trilium/releases/tag/v0.90.4) are
+compatible with the latest zadam/trilium version of
+[v0.63.7](https://github.com/zadam/trilium/releases/tag/v0.63.7). Any later
+versions of TriliumNext/Trilium have their sync versions incremented which
+prevents direct migration.
+
+## 💬 Discuss with us
+
+Feel free to join our official conversations. We would love to hear what
+features, suggestions, or issues you may have!
+
+- [Matrix](https://matrix.to/#/#triliumnext:matrix.org) (For synchronous
+ discussions.)
+ - The `General` Matrix room is also bridged to
+ [XMPP](xmpp:discuss@trilium.thisgreat.party?join)
+- [Github Discussions](https://github.com/TriliumNext/Trilium/discussions) (For
+ asynchronous discussions.)
+- [Github Issues](https://github.com/TriliumNext/Trilium/issues) (For bug
+ reports and feature requests.)
+
+## 🏗 Installation
+
+### Windows / MacOS
+
+Download the binary release for your platform from the [latest release
+page](https://github.com/TriliumNext/Trilium/releases/latest), unzip the package
+and run the `trilium` executable.
+
+### Linux
+
+If your distribution is listed in the table below, use your distribution's
+package.
+
+[](https://repology.org/project/triliumnext/versions)
+
+You may also download the binary release for your platform from the [latest
+release page](https://github.com/TriliumNext/Trilium/releases/latest), unzip the
+package and run the `trilium` executable.
+
+TriliumNext is also provided as a Flatpak, but not yet published on FlatHub.
+
+### Browser (any OS)
+
+If you use a server installation (see below), you can directly access the web
+interface (which is almost identical to the desktop app).
+
+Currently only the latest versions of Chrome & Firefox are supported (and
+tested).
+
+### Mobile
+
+To use TriliumNext on a mobile device, you can use a mobile web browser to
+access the mobile interface of a server installation (see below).
+
+See issue https://github.com/TriliumNext/Trilium/issues/4962 for more
+information on mobile app support.
+
+If you prefer a native Android app, you can use
+[TriliumDroid](https://apt.izzysoft.de/fdroid/index/apk/eu.fliegendewurst.triliumdroid).
+Report bugs and missing features at [their
+repository](https://github.com/FliegendeWurst/TriliumDroid). Note: It is best to
+disable automatic updates on your server installation (see below) when using
+TriliumDroid since the sync version must match between Trilium and TriliumDroid.
+
+### Server
+
+To install TriliumNext on your own server (including via Docker from
+[Dockerhub](https://hub.docker.com/r/triliumnext/trilium)) follow [the server
+installation docs](https://triliumnext.github.io/Docs/Wiki/server-installation).
+
+
+## 💻 Contribute
+
+### Translations
+
+If you are a native speaker, help us translate Trilium by heading over to our
+[Weblate page](https://hosted.weblate.org/engage/trilium/).
+
+Here's the language coverage we have so far:
+
+[](https://hosted.weblate.org/engage/trilium/)
+
+### Code
+
+Download the repository, install dependencies using `pnpm` and then run the
+server (available at http://localhost:8080):
+```shell
+git clone https://github.com/TriliumNext/Trilium.git
+cd Trilium
+pnpm install
+pnpm run server:start
+```
+
+### Documentation
+
+Download the repository, install dependencies using `pnpm` and then run the
+environment required to edit the documentation:
+```shell
+git clone https://github.com/TriliumNext/Trilium.git
+cd Trilium
+pnpm install
+pnpm edit-docs:edit-docs
+```
+
+### Building the Executable
+Download the repository, install dependencies using `pnpm` and then build the
+desktop app for Windows:
+```shell
+git clone https://github.com/TriliumNext/Trilium.git
+cd Trilium
+pnpm install
+pnpm run --filter desktop electron-forge:make --arch=x64 --platform=win32
+```
+
+For more details, see the [development
+docs](https://github.com/TriliumNext/Trilium/tree/main/docs/Developer%20Guide/Developer%20Guide).
+
+### Developer Documentation
+
+Please view the [documentation
+guide](https://github.com/TriliumNext/Trilium/blob/main/docs/Developer%20Guide/Developer%20Guide/Environment%20Setup.md)
+for details. If you have more questions, feel free to reach out via the links
+described in the "Discuss with us" section above.
+
+## 👏 Shoutouts
+
+* [zadam](https://github.com/zadam) for the original concept and implementation
+ of the application.
+* [Sarah Hussein](https://github.com/Sarah-Hussein) for designing the
+ application icon.
+* [nriver](https://github.com/nriver) for his work on internationalization.
+* [Thomas Frei](https://github.com/thfrei) for his original work on the Canvas.
+* [antoniotejada](https://github.com/nriver) for the original syntax highlight
+ widget.
+* [Dosu](https://dosu.dev/) for providing us with the automated responses to
+ GitHub issues and discussions.
+* [Tabler Icons](https://tabler.io/icons) for the system tray icons.
+
+Trilium would not be possible without the technologies behind it:
+
+* [CKEditor 5](https://github.com/ckeditor/ckeditor5) - the visual editor behind
+ text notes. We are grateful for being offered a set of the premium features.
+* [CodeMirror](https://github.com/codemirror/CodeMirror) - code editor with
+ support for huge amount of languages.
+* [Excalidraw](https://github.com/excalidraw/excalidraw) - the infinite
+ whiteboard used in Canvas notes.
+* [Mind Elixir](https://github.com/SSShooter/mind-elixir-core) - providing the
+ mind map functionality.
+* [Leaflet](https://github.com/Leaflet/Leaflet) - for rendering geographical
+ maps.
+* [Tabulator](https://github.com/olifolkerd/tabulator) - for the interactive
+ table used in collections.
+* [FancyTree](https://github.com/mar10/fancytree) - feature-rich tree library
+ without real competition.
+* [jsPlumb](https://github.com/jsplumb/jsplumb) - visual connectivity library.
+ Used in [relation
+ maps](https://triliumnext.github.io/Docs/Wiki/relation-map.html) and [link
+ maps](https://triliumnext.github.io/Docs/Wiki/note-map.html#link-map)
+
+## 🤝 Support
+
+Trilium is built and maintained with [hundreds of hours of
+work](https://github.com/TriliumNext/Trilium/graphs/commit-activity). Your
+support keeps it open-source, improves features, and covers costs such as
+hosting.
+
+Consider supporting the main developer
+([eliandoran](https://github.com/eliandoran)) of the application via:
+
+- [GitHub Sponsors](https://github.com/sponsors/eliandoran)
+- [PayPal](https://paypal.me/eliandoran)
+- [Buy Me a Coffee](https://buymeacoffee.com/eliandoran)
+
+## 🔑 License
+
+Copyright 2017-2025 zadam, Elian Doran, and other contributors
+
+This program is free software: you can redistribute it and/or modify it under
+the terms of the GNU Affero General Public License as published by the Free
+Software Foundation, either version 3 of the License, or (at your option) any
+later version.
diff --git a/docs/README-mr.md b/docs/README-mr.md
new file mode 100644
index 000000000..bba139cc9
--- /dev/null
+++ b/docs/README-mr.md
@@ -0,0 +1,332 @@
+
+
+
+
+# Trilium Notes
+
+
+\
+
+\
+[](https://app.relative-ci.com/projects/Di5q7dz9daNDZ9UXi0Bp)
+[](https://hosted.weblate.org/engage/trilium/)
+
+[English](./README.md) | [Chinese (Simplified)](./docs/README-ZH_CN.md) |
+[Chinese (Traditional)](./docs/README-ZH_TW.md) | [Russian](./docs/README-ru.md)
+| [Japanese](./docs/README-ja.md) | [Italian](./docs/README-it.md) |
+[Spanish](./docs/README-es.md)
+
+Trilium Notes is a free and open-source, cross-platform hierarchical note taking
+application with focus on building large personal knowledge bases.
+
+See [screenshots](https://triliumnext.github.io/Docs/Wiki/screenshot-tour) for
+quick overview:
+
+
+
+## ⏬ Download
+- [Latest release](https://github.com/TriliumNext/Trilium/releases/latest) –
+ stable version, recommended for most users.
+- [Nightly build](https://github.com/TriliumNext/Trilium/releases/tag/nightly) –
+ unstable development version, updated daily with the latest features and
+ fixes.
+
+## 📚 Documentation
+
+**Visit our comprehensive documentation at
+[docs.triliumnotes.org](https://docs.triliumnotes.org/)**
+
+Our documentation is available in multiple formats:
+- **Online Documentation**: Browse the full documentation at
+ [docs.triliumnotes.org](https://docs.triliumnotes.org/)
+- **In-App Help**: Press `F1` within Trilium to access the same documentation
+ directly in the application
+- **GitHub**: Navigate through the [User
+ Guide](./docs/User%20Guide/User%20Guide/) in this repository
+
+### Quick Links
+- [Getting Started Guide](https://docs.triliumnotes.org/)
+- [Installation
+ Instructions](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation.md)
+- [Docker
+ Setup](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation/1.%20Installing%20the%20server/Using%20Docker.md)
+- [Upgrading
+ TriliumNext](./docs/User%20Guide/User%20Guide/Installation%20%26%20Setup/Upgrading%20TriliumNext.md)
+- [Basic Concepts and
+ Features](./docs/User%20Guide/User%20Guide/Basic%20Concepts%20and%20Features/Notes.md)
+- [Patterns of Personal Knowledge
+ Base](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge)
+
+## 🎁 Features
+
+* Notes can be arranged into arbitrarily deep tree. Single note can be placed
+ into multiple places in the tree (see
+ [cloning](https://triliumnext.github.io/Docs/Wiki/cloning-notes))
+* Rich WYSIWYG note editor including e.g. tables, images and
+ [math](https://triliumnext.github.io/Docs/Wiki/text-notes) with markdown
+ [autoformat](https://triliumnext.github.io/Docs/Wiki/text-notes#autoformat)
+* Support for editing [notes with source
+ code](https://triliumnext.github.io/Docs/Wiki/code-notes), including syntax
+ highlighting
+* Fast and easy [navigation between
+ notes](https://triliumnext.github.io/Docs/Wiki/note-navigation), full text
+ search and [note
+ hoisting](https://triliumnext.github.io/Docs/Wiki/note-hoisting)
+* Seamless [note
+ versioning](https://triliumnext.github.io/Docs/Wiki/note-revisions)
+* Note [attributes](https://triliumnext.github.io/Docs/Wiki/attributes) can be
+ used for note organization, querying and advanced
+ [scripting](https://triliumnext.github.io/Docs/Wiki/scripts)
+* UI available in English, German, Spanish, French, Romanian, and Chinese
+ (simplified and traditional)
+* Direct [OpenID and TOTP
+ integration](./docs/User%20Guide/User%20Guide/Installation%20%26%20Setup/Server%20Installation/Multi-Factor%20Authentication.md)
+ for more secure login
+* [Synchronization](https://triliumnext.github.io/Docs/Wiki/synchronization)
+ with self-hosted sync server
+ * there's a [3rd party service for hosting synchronisation
+ server](https://trilium.cc/paid-hosting)
+* [Sharing](https://triliumnext.github.io/Docs/Wiki/sharing) (publishing) notes
+ to public internet
+* Strong [note
+ encryption](https://triliumnext.github.io/Docs/Wiki/protected-notes) with
+ per-note granularity
+* Sketching diagrams, based on [Excalidraw](https://excalidraw.com/) (note type
+ "canvas")
+* [Relation maps](https://triliumnext.github.io/Docs/Wiki/relation-map) and
+ [link maps](https://triliumnext.github.io/Docs/Wiki/link-map) for visualizing
+ notes and their relations
+* Mind maps, based on [Mind Elixir](https://docs.mind-elixir.com/)
+* [Geo maps](./docs/User%20Guide/User%20Guide/Note%20Types/Geo%20Map.md) with
+ location pins and GPX tracks
+* [Scripting](https://triliumnext.github.io/Docs/Wiki/scripts) - see [Advanced
+ showcases](https://triliumnext.github.io/Docs/Wiki/advanced-showcases)
+* [REST API](https://triliumnext.github.io/Docs/Wiki/etapi) for automation
+* Scales well in both usability and performance upwards of 100 000 notes
+* Touch optimized [mobile
+ frontend](https://triliumnext.github.io/Docs/Wiki/mobile-frontend) for
+ smartphones and tablets
+* Built-in [dark theme](https://triliumnext.github.io/Docs/Wiki/themes), support
+ for user themes
+* [Evernote](https://triliumnext.github.io/Docs/Wiki/evernote-import) and
+ [Markdown import & export](https://triliumnext.github.io/Docs/Wiki/markdown)
+* [Web Clipper](https://triliumnext.github.io/Docs/Wiki/web-clipper) for easy
+ saving of web content
+* Customizable UI (sidebar buttons, user-defined widgets, ...)
+* [Metrics](./docs/User%20Guide/User%20Guide/Advanced%20Usage/Metrics.md), along
+ with a [Grafana
+ Dashboard](./docs/User%20Guide/User%20Guide/Advanced%20Usage/Metrics/grafana-dashboard.json)
+
+✨ Check out the following third-party resources/communities for more TriliumNext
+related goodies:
+
+- [awesome-trilium](https://github.com/Nriver/awesome-trilium) for 3rd party
+ themes, scripts, plugins and more.
+- [TriliumRocks!](https://trilium.rocks/) for tutorials, guides, and much more.
+
+## ❓Why TriliumNext?
+
+The original Trilium developer ([Zadam](https://github.com/zadam)) has
+graciously given the Trilium repository to the community project which resides
+at https://github.com/TriliumNext
+
+### ⬆️Migrating from Zadam/Trilium?
+
+There are no special migration steps to migrate from a zadam/Trilium instance to
+a TriliumNext/Trilium instance. Simply [install
+TriliumNext/Trilium](#-installation) as usual and it will use your existing
+database.
+
+Versions up to and including
+[v0.90.4](https://github.com/TriliumNext/Trilium/releases/tag/v0.90.4) are
+compatible with the latest zadam/trilium version of
+[v0.63.7](https://github.com/zadam/trilium/releases/tag/v0.63.7). Any later
+versions of TriliumNext/Trilium have their sync versions incremented which
+prevents direct migration.
+
+## 💬 Discuss with us
+
+Feel free to join our official conversations. We would love to hear what
+features, suggestions, or issues you may have!
+
+- [Matrix](https://matrix.to/#/#triliumnext:matrix.org) (For synchronous
+ discussions.)
+ - The `General` Matrix room is also bridged to
+ [XMPP](xmpp:discuss@trilium.thisgreat.party?join)
+- [Github Discussions](https://github.com/TriliumNext/Trilium/discussions) (For
+ asynchronous discussions.)
+- [Github Issues](https://github.com/TriliumNext/Trilium/issues) (For bug
+ reports and feature requests.)
+
+## 🏗 Installation
+
+### Windows / MacOS
+
+Download the binary release for your platform from the [latest release
+page](https://github.com/TriliumNext/Trilium/releases/latest), unzip the package
+and run the `trilium` executable.
+
+### Linux
+
+If your distribution is listed in the table below, use your distribution's
+package.
+
+[](https://repology.org/project/triliumnext/versions)
+
+You may also download the binary release for your platform from the [latest
+release page](https://github.com/TriliumNext/Trilium/releases/latest), unzip the
+package and run the `trilium` executable.
+
+TriliumNext is also provided as a Flatpak, but not yet published on FlatHub.
+
+### Browser (any OS)
+
+If you use a server installation (see below), you can directly access the web
+interface (which is almost identical to the desktop app).
+
+Currently only the latest versions of Chrome & Firefox are supported (and
+tested).
+
+### Mobile
+
+To use TriliumNext on a mobile device, you can use a mobile web browser to
+access the mobile interface of a server installation (see below).
+
+See issue https://github.com/TriliumNext/Trilium/issues/4962 for more
+information on mobile app support.
+
+If you prefer a native Android app, you can use
+[TriliumDroid](https://apt.izzysoft.de/fdroid/index/apk/eu.fliegendewurst.triliumdroid).
+Report bugs and missing features at [their
+repository](https://github.com/FliegendeWurst/TriliumDroid). Note: It is best to
+disable automatic updates on your server installation (see below) when using
+TriliumDroid since the sync version must match between Trilium and TriliumDroid.
+
+### Server
+
+To install TriliumNext on your own server (including via Docker from
+[Dockerhub](https://hub.docker.com/r/triliumnext/trilium)) follow [the server
+installation docs](https://triliumnext.github.io/Docs/Wiki/server-installation).
+
+
+## 💻 Contribute
+
+### Translations
+
+If you are a native speaker, help us translate Trilium by heading over to our
+[Weblate page](https://hosted.weblate.org/engage/trilium/).
+
+Here's the language coverage we have so far:
+
+[](https://hosted.weblate.org/engage/trilium/)
+
+### Code
+
+Download the repository, install dependencies using `pnpm` and then run the
+server (available at http://localhost:8080):
+```shell
+git clone https://github.com/TriliumNext/Trilium.git
+cd Trilium
+pnpm install
+pnpm run server:start
+```
+
+### Documentation
+
+Download the repository, install dependencies using `pnpm` and then run the
+environment required to edit the documentation:
+```shell
+git clone https://github.com/TriliumNext/Trilium.git
+cd Trilium
+pnpm install
+pnpm edit-docs:edit-docs
+```
+
+### Building the Executable
+Download the repository, install dependencies using `pnpm` and then build the
+desktop app for Windows:
+```shell
+git clone https://github.com/TriliumNext/Trilium.git
+cd Trilium
+pnpm install
+pnpm run --filter desktop electron-forge:make --arch=x64 --platform=win32
+```
+
+For more details, see the [development
+docs](https://github.com/TriliumNext/Trilium/tree/main/docs/Developer%20Guide/Developer%20Guide).
+
+### Developer Documentation
+
+Please view the [documentation
+guide](https://github.com/TriliumNext/Trilium/blob/main/docs/Developer%20Guide/Developer%20Guide/Environment%20Setup.md)
+for details. If you have more questions, feel free to reach out via the links
+described in the "Discuss with us" section above.
+
+## 👏 Shoutouts
+
+* [zadam](https://github.com/zadam) for the original concept and implementation
+ of the application.
+* [Sarah Hussein](https://github.com/Sarah-Hussein) for designing the
+ application icon.
+* [nriver](https://github.com/nriver) for his work on internationalization.
+* [Thomas Frei](https://github.com/thfrei) for his original work on the Canvas.
+* [antoniotejada](https://github.com/nriver) for the original syntax highlight
+ widget.
+* [Dosu](https://dosu.dev/) for providing us with the automated responses to
+ GitHub issues and discussions.
+* [Tabler Icons](https://tabler.io/icons) for the system tray icons.
+
+Trilium would not be possible without the technologies behind it:
+
+* [CKEditor 5](https://github.com/ckeditor/ckeditor5) - the visual editor behind
+ text notes. We are grateful for being offered a set of the premium features.
+* [CodeMirror](https://github.com/codemirror/CodeMirror) - code editor with
+ support for huge amount of languages.
+* [Excalidraw](https://github.com/excalidraw/excalidraw) - the infinite
+ whiteboard used in Canvas notes.
+* [Mind Elixir](https://github.com/SSShooter/mind-elixir-core) - providing the
+ mind map functionality.
+* [Leaflet](https://github.com/Leaflet/Leaflet) - for rendering geographical
+ maps.
+* [Tabulator](https://github.com/olifolkerd/tabulator) - for the interactive
+ table used in collections.
+* [FancyTree](https://github.com/mar10/fancytree) - feature-rich tree library
+ without real competition.
+* [jsPlumb](https://github.com/jsplumb/jsplumb) - visual connectivity library.
+ Used in [relation
+ maps](https://triliumnext.github.io/Docs/Wiki/relation-map.html) and [link
+ maps](https://triliumnext.github.io/Docs/Wiki/note-map.html#link-map)
+
+## 🤝 Support
+
+Trilium is built and maintained with [hundreds of hours of
+work](https://github.com/TriliumNext/Trilium/graphs/commit-activity). Your
+support keeps it open-source, improves features, and covers costs such as
+hosting.
+
+Consider supporting the main developer
+([eliandoran](https://github.com/eliandoran)) of the application via:
+
+- [GitHub Sponsors](https://github.com/sponsors/eliandoran)
+- [PayPal](https://paypal.me/eliandoran)
+- [Buy Me a Coffee](https://buymeacoffee.com/eliandoran)
+
+## 🔑 License
+
+Copyright 2017-2025 zadam, Elian Doran, and other contributors
+
+This program is free software: you can redistribute it and/or modify it under
+the terms of the GNU Affero General Public License as published by the Free
+Software Foundation, either version 3 of the License, or (at your option) any
+later version.
diff --git a/package.json b/package.json
index bb1a836c9..73c717334 100644
--- a/package.json
+++ b/package.json
@@ -42,7 +42,7 @@
"@playwright/test": "1.56.1",
"@triliumnext/server": "workspace:*",
"@types/express": "5.0.5",
- "@types/node": "22.18.12",
+ "@types/node": "24.9.1",
"@vitest/coverage-v8": "3.2.4",
"@vitest/ui": "3.2.4",
"chalk": "5.6.2",
diff --git a/packages/ckeditor5/src/augmentation.ts b/packages/ckeditor5/src/augmentation.ts
index c1018db37..6f05b9f2a 100644
--- a/packages/ckeditor5/src/augmentation.ts
+++ b/packages/ckeditor5/src/augmentation.ts
@@ -19,6 +19,5 @@ declare global {
getHeaders(): Promise>;
getReferenceLinkTitle(href: string): Promise;
getReferenceLinkTitleSync(href: string): string;
- importMarkdownInline(): void;
}
}
diff --git a/packages/ckeditor5/src/plugins/markdownimport.ts b/packages/ckeditor5/src/plugins/markdownimport.ts
index c00b9f7f6..02f208e1d 100644
--- a/packages/ckeditor5/src/plugins/markdownimport.ts
+++ b/packages/ckeditor5/src/plugins/markdownimport.ts
@@ -31,7 +31,10 @@ export default class MarkdownImportPlugin extends Plugin {
class ImportMarkdownCommand extends Command {
execute() {
- glob.importMarkdownInline();
+ const editorEl = this.editor.editing.view.getDomRoot();
+ const component = glob.getComponentByEl(editorEl);
+
+ component.triggerCommand('pasteMarkdownIntoText');
}
}
diff --git a/packages/commons/src/lib/server_api.ts b/packages/commons/src/lib/server_api.ts
index 74570c75f..294717bd8 100644
--- a/packages/commons/src/lib/server_api.ts
+++ b/packages/commons/src/lib/server_api.ts
@@ -29,7 +29,7 @@ export interface DeleteNotesPreview {
export interface RevisionItem {
noteId: string;
revisionId?: string;
- dateLastEdited?: string;
+ dateCreated?: string;
contentLength?: number;
type: NoteType;
title: string;
diff --git a/packages/share-theme/package.json b/packages/share-theme/package.json
index a521b66aa..68916cc3e 100644
--- a/packages/share-theme/package.json
+++ b/packages/share-theme/package.json
@@ -21,6 +21,11 @@
"Zerebos "
],
"license": "Apache-2.0",
+ "dependencies": {
+ "katex": "0.16.25",
+ "mermaid": "11.12.0",
+ "boxicons": "2.1.4"
+ },
"devDependencies": {
"@digitak/esrun": "3.2.26",
"@types/swagger-ui": "5.21.1",
diff --git a/packages/share-theme/scripts/build.ts b/packages/share-theme/scripts/build.ts
index 586005ea5..13b2ac493 100644
--- a/packages/share-theme/scripts/build.ts
+++ b/packages/share-theme/scripts/build.ts
@@ -1,4 +1,3 @@
-import fs from "node:fs";
import path from "node:path";
// import {fileURLToPath} from "node:url";
@@ -51,15 +50,18 @@ async function runBuild() {
await esbuild.build({
entryPoints: entryPoints,
bundle: true,
+ splitting: true,
outdir: path.join(rootDir, "dist"),
- format: "cjs",
+ format: "esm",
target: ["chrome96"],
loader: {
".png": "dataurl",
".gif": "dataurl",
- ".woff": "dataurl",
- ".woff2": "dataurl",
- ".ttf": "dataurl",
+ ".woff": "file",
+ ".woff2": "file",
+ ".ttf": "file",
+ ".eot": "empty",
+ ".svg": "empty",
".html": "text",
".css": "css"
},
diff --git a/packages/share-theme/src/scripts/index.ts b/packages/share-theme/src/scripts/index.ts
index 7b71fcb8f..a809962aa 100644
--- a/packages/share-theme/src/scripts/index.ts
+++ b/packages/share-theme/src/scripts/index.ts
@@ -3,6 +3,11 @@ import setupExpanders from "./modules/expanders";
import setupMobileMenu from "./modules/mobile";
import setupSearch from "./modules/search";
import setupThemeSelector from "./modules/theme";
+import setupMermaid from "./modules/mermaid";
+import setupMath from "./modules/math";
+import api from "./modules/api";
+import "boxicons/css/boxicons.min.css";
+import "highlight.js/styles/default.css";
function $try unknown>(func: T, ...args: Parameters) {
try {
@@ -13,8 +18,39 @@ function $try unknown>(func: T, ...args: Paramete
}
}
+Object.assign(window, api);
$try(setupThemeSelector);
$try(setupToC);
$try(setupExpanders);
$try(setupMobileMenu);
$try(setupSearch);
+
+function setupTextNote() {
+ $try(setupMermaid);
+ $try(setupMath);
+}
+
+document.addEventListener(
+ "DOMContentLoaded",
+ () => {
+ const noteType = determineNoteType();
+
+ if (noteType === "text") {
+ setupTextNote();
+ }
+
+ const toggleMenuButton = document.getElementById("toggleMenuButton");
+ const layout = document.getElementById("layout");
+
+ if (toggleMenuButton && layout) {
+ toggleMenuButton.addEventListener("click", () => layout.classList.toggle("showMenu"));
+ }
+ },
+ false
+);
+
+function determineNoteType() {
+ const bodyClass = document.body.className;
+ const match = bodyClass.match(/type-([^\s]+)/);
+ return match ? match[1] : null;
+}
diff --git a/packages/share-theme/src/scripts/modules/api.ts b/packages/share-theme/src/scripts/modules/api.ts
new file mode 100644
index 000000000..adaca77d1
--- /dev/null
+++ b/packages/share-theme/src/scripts/modules/api.ts
@@ -0,0 +1,18 @@
+/**
+ * Fetch note with given ID from backend
+ *
+ * @param noteId of the given note to be fetched. If false, fetches current note.
+ */
+async function fetchNote(noteId: string | null = null) {
+ if (!noteId) {
+ noteId = document.body.getAttribute("data-note-id");
+ }
+
+ const resp = await fetch(`api/notes/${noteId}`);
+
+ return await resp.json();
+}
+
+export default {
+ fetchNote
+};
diff --git a/packages/share-theme/src/scripts/modules/math.ts b/packages/share-theme/src/scripts/modules/math.ts
new file mode 100644
index 000000000..3893dbeed
--- /dev/null
+++ b/packages/share-theme/src/scripts/modules/math.ts
@@ -0,0 +1,16 @@
+import "katex/dist/katex.min.css";
+
+export default async function setupMath() {
+ const anyMathBlock = document.querySelector("#content .math-tex");
+ if (!anyMathBlock) {
+ return;
+ }
+
+ const renderMathInElement = (await import("katex/contrib/auto-render")).default;
+ await import("katex/contrib/mhchem");
+
+ const contentEl = document.getElementById("content");
+ if (!contentEl) return;
+ renderMathInElement(contentEl);
+ document.body.classList.add("math-loaded");
+}
diff --git a/apps/client/src/share/mermaid.ts b/packages/share-theme/src/scripts/modules/mermaid.ts
similarity index 53%
rename from apps/client/src/share/mermaid.ts
rename to packages/share-theme/src/scripts/modules/mermaid.ts
index 123f3816c..78ae5a573 100644
--- a/apps/client/src/share/mermaid.ts
+++ b/packages/share-theme/src/scripts/modules/mermaid.ts
@@ -1,7 +1,12 @@
-import mermaid from "mermaid";
+export default async function setupMermaid() {
+ const mermaidEls = document.querySelectorAll("#content pre code.language-mermaid");
+ if (mermaidEls.length === 0) {
+ return;
+ }
-export default function setupMermaid() {
- for (const codeBlock of document.querySelectorAll("#content pre code.language-mermaid")) {
+ const mermaid = (await import("mermaid")).default;
+
+ for (const codeBlock of mermaidEls) {
const parentPre = codeBlock.parentElement;
if (!parentPre) {
continue;
diff --git a/packages/share-theme/src/styles/content.css b/packages/share-theme/src/styles/content.css
index d500888a6..e67be725a 100644
--- a/packages/share-theme/src/styles/content.css
+++ b/packages/share-theme/src/styles/content.css
@@ -46,4 +46,8 @@
#content img {
max-width: 100%;
+}
+
+body:not(.math-loaded) .math-tex {
+ visibility: hidden;
}
\ No newline at end of file
diff --git a/packages/share-theme/src/templates/page.ejs b/packages/share-theme/src/templates/page.ejs
index 2fd07c8a7..0196bfddc 100644
--- a/packages/share-theme/src/templates/page.ejs
+++ b/packages/share-theme/src/templates/page.ejs
@@ -30,17 +30,11 @@
api/notes/<%= note.getRelation("shareFavicon").value %>/download<% } else { %>../favicon.ico<% } %>">
-
- <% if (!isDev && !note.isLabelTruthy("shareOmitDefaultCss")) { %>
-
-
+ <% for (const url of cssToLoad) { %>
+
<% } %>
-
- <% for (const cssRelation of note.getRelations("shareCss")) { %>
-
- <% } %>
- <% for (const jsRelation of note.getRelations("shareJs")) { %>
-
+ <% for (const url of jsToLoad) { %>
+
<% } %>
<% if (note.hasLabel("shareDisallowRobotIndexing")) { %>
@@ -80,8 +74,6 @@
<%- renderSnippets("head:end") %>
<%
-const customLogoId = subRoot.note.getRelation("shareLogo")?.value;
-const logoUrl = customLogoId ? `api/images/${customLogoId}/image.png` : `../${assetUrlFragment}/images/icon-color.svg`;
const logoWidth = subRoot.note.getLabelValue("shareLogoWidth") ?? 53;
const logoHeight = subRoot.note.getLabelValue("shareLogoHeight") ?? 40;
const mobileLogoHeight = logoHeight && logoWidth ? 32 / (logoWidth / logoHeight) : "";
@@ -131,16 +123,7 @@ content = content.replaceAll(headingRe, (...match) => {
<% if (hasTree) { %>
<% } %>
diff --git a/packages/share-theme/src/templates/tree_item.ejs b/packages/share-theme/src/templates/tree_item.ejs
index b033ad2bc..58d04a07b 100644
--- a/packages/share-theme/src/templates/tree_item.ejs
+++ b/packages/share-theme/src/templates/tree_item.ejs
@@ -1,7 +1,14 @@
<%
const linkClass = `type-${note.type}` + (activeNote.noteId === note.noteId ? " active" : "");
const isExternalLink = note.hasLabel("shareExternal");
-const linkHref = isExternalLink ? note.getLabelValue("shareExternal") : `./${note.shareId}`;
+let linkHref;
+
+if (isExternalLink) {
+ linkHref = note.getLabelValue("shareExternal");
+} else if (note.shareId) {
+ linkHref = `./${note.shareId}`;
+}
+
const target = isExternalLink ? ` target="_blank" rel="noopener noreferrer"` : "";
%>
diff --git a/packages/share-theme/src/types.d.ts b/packages/share-theme/src/types.d.ts
new file mode 100644
index 000000000..3fa19bd49
--- /dev/null
+++ b/packages/share-theme/src/types.d.ts
@@ -0,0 +1,5 @@
+declare module "katex/contrib/auto-render" {
+ export default function renderMathInElement(elem: HTMLElement, options?: {})
+}
+
+declare module "katex/contrib/mhchem" {}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 02b05ed04..3d2016b20 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -53,8 +53,8 @@ importers:
specifier: 5.0.5
version: 5.0.5
'@types/node':
- specifier: 22.18.12
- version: 22.18.12
+ specifier: 24.9.1
+ version: 24.9.1
'@vitest/coverage-v8':
specifier: 3.2.4
version: 3.2.4(@vitest/browser@3.2.4)(vitest@3.2.4)
@@ -99,7 +99,7 @@ importers:
version: 0.18.0
rollup-plugin-webpack-stats:
specifier: 2.1.6
- version: 2.1.6(rolldown@1.0.0-beta.29)(rollup@4.52.0)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
+ version: 2.1.6(rolldown@1.0.0-beta.29)(rollup@4.52.0)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
tslib:
specifier: 2.8.1
version: 2.8.1
@@ -117,13 +117,13 @@ importers:
version: 2.0.1
vite:
specifier: 7.1.12
- version: 7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ version: 7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
vite-plugin-dts:
specifier: ~4.5.0
- version: 4.5.4(@types/node@22.18.12)(rollup@4.52.0)(typescript@5.9.3)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
+ version: 4.5.4(@types/node@24.9.1)(rollup@4.52.0)(typescript@5.9.3)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
vitest:
specifier: 3.2.4
- version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.12)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ version: 3.2.4(@types/debug@4.1.12)(@types/node@24.9.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
apps/client:
dependencies:
@@ -480,6 +480,9 @@ importers:
'@triliumnext/express-partial-content':
specifier: workspace:*
version: link:../../packages/express-partial-content
+ '@triliumnext/highlightjs':
+ specifier: workspace:*
+ version: link:../../packages/highlightjs
'@triliumnext/turndown-plugin-gfm':
specifier: workspace:*
version: link:../../packages/turndown-plugin-gfm
@@ -853,7 +856,7 @@ importers:
version: 5.0.0
'@ckeditor/ckeditor5-package-tools':
specifier: 4.1.1
- version: 4.1.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.12)(bufferutil@4.0.9)(esbuild@0.25.11)(utf-8-validate@6.0.5)
+ version: 4.1.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.9.1)(bufferutil@4.0.9)(esbuild@0.25.11)(utf-8-validate@6.0.5)
'@typescript-eslint/eslint-plugin':
specifier: ~8.46.0
version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
@@ -862,7 +865,7 @@ importers:
version: 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
'@vitest/browser':
specifier: 3.2.4
- version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(playwright@1.56.1)(utf-8-validate@6.0.5)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))
+ version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(playwright@1.56.1)(utf-8-validate@6.0.5)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))
'@vitest/coverage-istanbul':
specifier: 3.2.4
version: 3.2.4(vitest@3.2.4)
@@ -889,16 +892,16 @@ importers:
version: 12.2.0(stylelint@16.25.0(typescript@5.9.3))
ts-node:
specifier: 10.9.2
- version: 10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.12)(typescript@5.9.3)
+ version: 10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.9.1)(typescript@5.9.3)
typescript:
specifier: 5.9.3
version: 5.9.3
vite-plugin-svgo:
specifier: ~2.0.0
- version: 2.0.0(typescript@5.9.3)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
+ version: 2.0.0(typescript@5.9.3)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
vitest:
specifier: 3.2.4
- version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.12)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ version: 3.2.4(@types/debug@4.1.12)(@types/node@24.9.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
webdriverio:
specifier: 9.20.0
version: 9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)
@@ -913,7 +916,7 @@ importers:
version: 5.0.0
'@ckeditor/ckeditor5-package-tools':
specifier: 4.1.1
- version: 4.1.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.12)(bufferutil@4.0.9)(esbuild@0.25.11)(utf-8-validate@6.0.5)
+ version: 4.1.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.9.1)(bufferutil@4.0.9)(esbuild@0.25.11)(utf-8-validate@6.0.5)
'@typescript-eslint/eslint-plugin':
specifier: ~8.46.0
version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
@@ -922,7 +925,7 @@ importers:
version: 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
'@vitest/browser':
specifier: 3.2.4
- version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(playwright@1.56.1)(utf-8-validate@6.0.5)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))
+ version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(playwright@1.56.1)(utf-8-validate@6.0.5)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))
'@vitest/coverage-istanbul':
specifier: 3.2.4
version: 3.2.4(vitest@3.2.4)
@@ -949,16 +952,16 @@ importers:
version: 12.2.0(stylelint@16.25.0(typescript@5.9.3))
ts-node:
specifier: 10.9.2
- version: 10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.12)(typescript@5.9.3)
+ version: 10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.9.1)(typescript@5.9.3)
typescript:
specifier: 5.9.3
version: 5.9.3
vite-plugin-svgo:
specifier: ~2.0.0
- version: 2.0.0(typescript@5.9.3)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
+ version: 2.0.0(typescript@5.9.3)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
vitest:
specifier: 3.2.4
- version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.12)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ version: 3.2.4(@types/debug@4.1.12)(@types/node@24.9.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
webdriverio:
specifier: 9.20.0
version: 9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)
@@ -973,7 +976,7 @@ importers:
version: 5.0.0
'@ckeditor/ckeditor5-package-tools':
specifier: 4.1.1
- version: 4.1.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.12)(bufferutil@4.0.9)(esbuild@0.25.11)(utf-8-validate@6.0.5)
+ version: 4.1.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.9.1)(bufferutil@4.0.9)(esbuild@0.25.11)(utf-8-validate@6.0.5)
'@typescript-eslint/eslint-plugin':
specifier: ~8.46.0
version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
@@ -982,7 +985,7 @@ importers:
version: 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
'@vitest/browser':
specifier: 3.2.4
- version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(playwright@1.56.1)(utf-8-validate@6.0.5)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))
+ version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(playwright@1.56.1)(utf-8-validate@6.0.5)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))
'@vitest/coverage-istanbul':
specifier: 3.2.4
version: 3.2.4(vitest@3.2.4)
@@ -1009,16 +1012,16 @@ importers:
version: 12.2.0(stylelint@16.25.0(typescript@5.9.3))
ts-node:
specifier: 10.9.2
- version: 10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.12)(typescript@5.9.3)
+ version: 10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.9.1)(typescript@5.9.3)
typescript:
specifier: 5.9.3
version: 5.9.3
vite-plugin-svgo:
specifier: ~2.0.0
- version: 2.0.0(typescript@5.9.3)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
+ version: 2.0.0(typescript@5.9.3)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
vitest:
specifier: 3.2.4
- version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.12)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ version: 3.2.4(@types/debug@4.1.12)(@types/node@24.9.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
webdriverio:
specifier: 9.20.0
version: 9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)
@@ -1040,7 +1043,7 @@ importers:
version: 5.0.0
'@ckeditor/ckeditor5-package-tools':
specifier: 4.1.1
- version: 4.1.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.12)(bufferutil@4.0.9)(esbuild@0.25.11)(utf-8-validate@6.0.5)
+ version: 4.1.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.9.1)(bufferutil@4.0.9)(esbuild@0.25.11)(utf-8-validate@6.0.5)
'@typescript-eslint/eslint-plugin':
specifier: ~8.46.0
version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
@@ -1049,7 +1052,7 @@ importers:
version: 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
'@vitest/browser':
specifier: 3.2.4
- version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(playwright@1.56.1)(utf-8-validate@6.0.5)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))
+ version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(playwright@1.56.1)(utf-8-validate@6.0.5)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))
'@vitest/coverage-istanbul':
specifier: 3.2.4
version: 3.2.4(vitest@3.2.4)
@@ -1076,16 +1079,16 @@ importers:
version: 12.2.0(stylelint@16.25.0(typescript@5.9.3))
ts-node:
specifier: 10.9.2
- version: 10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.12)(typescript@5.9.3)
+ version: 10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.9.1)(typescript@5.9.3)
typescript:
specifier: 5.9.3
version: 5.9.3
vite-plugin-svgo:
specifier: ~2.0.0
- version: 2.0.0(typescript@5.9.3)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
+ version: 2.0.0(typescript@5.9.3)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
vitest:
specifier: 3.2.4
- version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.12)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ version: 3.2.4(@types/debug@4.1.12)(@types/node@24.9.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
webdriverio:
specifier: 9.20.0
version: 9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)
@@ -1107,7 +1110,7 @@ importers:
version: 5.0.0
'@ckeditor/ckeditor5-package-tools':
specifier: 4.1.1
- version: 4.1.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.12)(bufferutil@4.0.9)(esbuild@0.25.11)(utf-8-validate@6.0.5)
+ version: 4.1.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.9.1)(bufferutil@4.0.9)(esbuild@0.25.11)(utf-8-validate@6.0.5)
'@typescript-eslint/eslint-plugin':
specifier: ~8.46.0
version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
@@ -1116,7 +1119,7 @@ importers:
version: 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
'@vitest/browser':
specifier: 3.2.4
- version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(playwright@1.56.1)(utf-8-validate@6.0.5)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))
+ version: 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(playwright@1.56.1)(utf-8-validate@6.0.5)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))
'@vitest/coverage-istanbul':
specifier: 3.2.4
version: 3.2.4(vitest@3.2.4)
@@ -1143,16 +1146,16 @@ importers:
version: 12.2.0(stylelint@16.25.0(typescript@5.9.3))
ts-node:
specifier: 10.9.2
- version: 10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.12)(typescript@5.9.3)
+ version: 10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.9.1)(typescript@5.9.3)
typescript:
specifier: 5.9.3
version: 5.9.3
vite-plugin-svgo:
specifier: ~2.0.0
- version: 2.0.0(typescript@5.9.3)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
+ version: 2.0.0(typescript@5.9.3)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
vitest:
specifier: 3.2.4
- version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.12)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ version: 3.2.4(@types/debug@4.1.12)(@types/node@24.9.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
webdriverio:
specifier: 9.20.0
version: 9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)
@@ -1325,6 +1328,16 @@ importers:
version: 1.2.0
packages/share-theme:
+ dependencies:
+ boxicons:
+ specifier: 2.1.4
+ version: 2.1.4
+ katex:
+ specifier: 0.16.25
+ version: 0.16.25
+ mermaid:
+ specifier: 11.12.1
+ version: 11.12.1
devDependencies:
'@digitak/esrun':
specifier: 3.2.26
@@ -1381,6 +1394,18 @@ importers:
specifier: 0.0.3
version: 0.0.3(bufferutil@4.0.9)(utf-8-validate@6.0.5)
+ packages/uikit:
+ dependencies:
+ '@triliumnext/commons':
+ specifier: workspace:*
+ version: link:../commons
+ '@triliumnext/highlightjs':
+ specifier: workspace:*
+ version: link:../highlightjs
+ jquery:
+ specifier: 3.7.1
+ version: 3.7.1
+
packages:
'@ampproject/remapping@2.3.0':
@@ -14856,8 +14881,6 @@ snapshots:
'@ckeditor/ckeditor5-core': 47.1.0
'@ckeditor/ckeditor5-upload': 47.1.0
ckeditor5: 47.1.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
- transitivePeerDependencies:
- - supports-color
'@ckeditor/ckeditor5-ai@47.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)':
dependencies:
@@ -15282,6 +15305,8 @@ snapshots:
'@ckeditor/ckeditor5-table': 47.1.0
'@ckeditor/ckeditor5-utils': 47.1.0
ckeditor5: 47.1.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
+ transitivePeerDependencies:
+ - supports-color
'@ckeditor/ckeditor5-emoji@47.1.0':
dependencies:
@@ -15644,7 +15669,7 @@ snapshots:
es-toolkit: 1.39.5
protobufjs: 7.5.0
- '@ckeditor/ckeditor5-package-tools@4.1.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.12)(bufferutil@4.0.9)(esbuild@0.25.11)(utf-8-validate@6.0.5)':
+ '@ckeditor/ckeditor5-package-tools@4.1.1(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.9.1)(bufferutil@4.0.9)(esbuild@0.25.11)(utf-8-validate@6.0.5)':
dependencies:
'@ckeditor/ckeditor5-dev-translations': 53.2.0(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.25.11)(typescript@5.0.4)(webpack@5.101.3(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.25.11))
'@ckeditor/ckeditor5-dev-utils': 53.2.0(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.25.11)(typescript@5.0.4)(webpack@5.101.3(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.25.11))
@@ -15663,7 +15688,7 @@ snapshots:
stylelint-config-ckeditor5: 2.0.1(stylelint@16.25.0(typescript@5.9.3))
terser-webpack-plugin: 5.3.14(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.25.11)(webpack@5.101.3(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.25.11))
ts-loader: 9.5.4(typescript@5.0.4)(webpack@5.101.3(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.25.11))
- ts-node: 10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.12)(typescript@5.0.4)
+ ts-node: 10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.9.1)(typescript@5.0.4)
typescript: 5.0.4
upath: 2.0.1
webpack: 5.101.3(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.25.11)
@@ -17212,26 +17237,26 @@ snapshots:
'@inquirer/core': 9.2.1
'@inquirer/type': 2.0.0
- '@inquirer/confirm@5.1.19(@types/node@22.18.12)':
+ '@inquirer/confirm@5.1.19(@types/node@24.9.1)':
dependencies:
- '@inquirer/core': 10.3.0(@types/node@22.18.12)
- '@inquirer/type': 3.0.9(@types/node@22.18.12)
+ '@inquirer/core': 10.3.0(@types/node@24.9.1)
+ '@inquirer/type': 3.0.9(@types/node@24.9.1)
optionalDependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
optional: true
- '@inquirer/core@10.3.0(@types/node@22.18.12)':
+ '@inquirer/core@10.3.0(@types/node@24.9.1)':
dependencies:
'@inquirer/ansi': 1.0.1
'@inquirer/figures': 1.0.14
- '@inquirer/type': 3.0.9(@types/node@22.18.12)
+ '@inquirer/type': 3.0.9(@types/node@24.9.1)
cli-width: 4.1.0
mute-stream: 2.0.0
signal-exit: 4.1.0
wrap-ansi: 6.2.0
yoctocolors-cjs: 2.1.3
optionalDependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
optional: true
'@inquirer/core@9.2.1':
@@ -17324,9 +17349,9 @@ snapshots:
dependencies:
mute-stream: 1.0.0
- '@inquirer/type@3.0.9(@types/node@22.18.12)':
+ '@inquirer/type@3.0.9(@types/node@24.9.1)':
optionalDependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
optional: true
'@isaacs/balanced-match@4.0.1': {}
@@ -17758,23 +17783,23 @@ snapshots:
dependencies:
langium: 3.3.1
- '@microsoft/api-extractor-model@7.30.6(@types/node@22.18.12)':
+ '@microsoft/api-extractor-model@7.30.6(@types/node@24.9.1)':
dependencies:
'@microsoft/tsdoc': 0.15.1
'@microsoft/tsdoc-config': 0.17.1
- '@rushstack/node-core-library': 5.13.1(@types/node@22.18.12)
+ '@rushstack/node-core-library': 5.13.1(@types/node@24.9.1)
transitivePeerDependencies:
- '@types/node'
- '@microsoft/api-extractor@7.52.8(@types/node@22.18.12)':
+ '@microsoft/api-extractor@7.52.8(@types/node@24.9.1)':
dependencies:
- '@microsoft/api-extractor-model': 7.30.6(@types/node@22.18.12)
+ '@microsoft/api-extractor-model': 7.30.6(@types/node@24.9.1)
'@microsoft/tsdoc': 0.15.1
'@microsoft/tsdoc-config': 0.17.1
- '@rushstack/node-core-library': 5.13.1(@types/node@22.18.12)
+ '@rushstack/node-core-library': 5.13.1(@types/node@24.9.1)
'@rushstack/rig-package': 0.5.3
- '@rushstack/terminal': 0.15.3(@types/node@22.18.12)
- '@rushstack/ts-command-line': 5.0.1(@types/node@22.18.12)
+ '@rushstack/terminal': 0.15.3(@types/node@24.9.1)
+ '@rushstack/ts-command-line': 5.0.1(@types/node@24.9.1)
lodash: 4.17.21
minimatch: 3.0.8
resolve: 1.22.10
@@ -18653,7 +18678,7 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.52.0':
optional: true
- '@rushstack/node-core-library@5.13.1(@types/node@22.18.12)':
+ '@rushstack/node-core-library@5.13.1(@types/node@24.9.1)':
dependencies:
ajv: 8.13.0
ajv-draft-04: 1.0.0(ajv@8.13.0)
@@ -18664,23 +18689,23 @@ snapshots:
resolve: 1.22.10
semver: 7.5.4
optionalDependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@rushstack/rig-package@0.5.3':
dependencies:
resolve: 1.22.10
strip-json-comments: 3.1.1
- '@rushstack/terminal@0.15.3(@types/node@22.18.12)':
+ '@rushstack/terminal@0.15.3(@types/node@24.9.1)':
dependencies:
- '@rushstack/node-core-library': 5.13.1(@types/node@22.18.12)
+ '@rushstack/node-core-library': 5.13.1(@types/node@24.9.1)
supports-color: 8.1.1
optionalDependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
- '@rushstack/ts-command-line@5.0.1(@types/node@22.18.12)':
+ '@rushstack/ts-command-line@5.0.1(@types/node@24.9.1)':
dependencies:
- '@rushstack/terminal': 0.15.3(@types/node@22.18.12)
+ '@rushstack/terminal': 0.15.3(@types/node@24.9.1)
'@types/argparse': 1.0.38
argparse: 1.0.10
string-argv: 0.3.2
@@ -19243,7 +19268,7 @@ snapshots:
'@types/appdmg@0.5.5':
dependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
optional: true
'@types/archiver@7.0.0':
@@ -19261,11 +19286,11 @@ snapshots:
'@types/body-parser@1.19.6':
dependencies:
'@types/connect': 3.4.38
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@types/bonjour@3.5.13':
dependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@types/bootstrap@5.2.10':
dependencies:
@@ -19279,7 +19304,7 @@ snapshots:
dependencies:
'@types/http-cache-semantics': 4.0.4
'@types/keyv': 3.1.4
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@types/responselike': 1.0.3
'@types/chai@5.2.2':
@@ -19304,11 +19329,11 @@ snapshots:
'@types/connect-history-api-fallback@1.5.4':
dependencies:
'@types/express-serve-static-core': 5.1.0
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@types/connect@3.4.38':
dependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@types/cookie-parser@1.4.10(@types/express@5.0.5)':
dependencies:
@@ -19321,7 +19346,7 @@ snapshots:
'@types/cors@2.8.19':
dependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@types/cssnano@5.1.3(postcss@8.5.6)':
dependencies:
@@ -19480,7 +19505,7 @@ snapshots:
'@types/express-serve-static-core@5.1.0':
dependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@types/qs': 6.14.0
'@types/range-parser': 1.2.7
'@types/send': 0.17.5
@@ -19506,7 +19531,7 @@ snapshots:
dependencies:
'@types/body-parser': 1.19.6
'@types/express-serve-static-core': 5.1.0
- '@types/serve-static': 2.2.0
+ '@types/serve-static': 1.15.10
'@types/fs-extra@11.0.4':
dependencies:
@@ -19515,7 +19540,7 @@ snapshots:
'@types/fs-extra@9.0.13':
dependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
optional: true
'@types/geojson-vt@3.2.5':
@@ -19527,7 +19552,7 @@ snapshots:
'@types/glob@7.2.0':
dependencies:
'@types/minimatch': 5.1.2
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@types/hast@3.0.4':
dependencies:
@@ -19541,7 +19566,7 @@ snapshots:
'@types/http-proxy@1.17.16':
dependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@types/ini@4.1.1': {}
@@ -19555,11 +19580,11 @@ snapshots:
'@types/jsonfile@6.1.4':
dependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@types/keyv@3.1.4':
dependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@types/leaflet-gpx@1.3.8':
dependencies:
@@ -19609,11 +19634,11 @@ snapshots:
'@types/mute-stream@0.0.4':
dependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@types/node-forge@1.3.14':
dependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@types/node@16.9.1': {}
@@ -19644,7 +19669,6 @@ snapshots:
'@types/node@24.9.1':
dependencies:
undici-types: 7.16.0
- optional: true
'@types/parse-json@4.0.2': {}
@@ -19670,13 +19694,13 @@ snapshots:
'@types/readdir-glob@1.1.5':
dependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@types/resolve@1.20.2': {}
'@types/responselike@1.0.3':
dependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@types/retry@0.12.2': {}
@@ -19695,7 +19719,7 @@ snapshots:
'@types/send@0.17.5':
dependencies:
'@types/mime': 1.3.5
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@types/serve-favicon@2.5.7':
dependencies:
@@ -19708,7 +19732,7 @@ snapshots:
'@types/serve-static@1.15.10':
dependencies:
'@types/http-errors': 2.0.4
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@types/send': 0.17.5
'@types/serve-static@2.2.0':
@@ -19722,7 +19746,7 @@ snapshots:
'@types/sockjs@0.3.36':
dependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@types/statuses@2.0.6':
optional: true
@@ -19735,7 +19759,7 @@ snapshots:
dependencies:
'@types/cookiejar': 2.1.5
'@types/methods': 1.1.4
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
form-data: 4.0.4
'@types/supercluster@7.1.3':
@@ -19758,7 +19782,7 @@ snapshots:
'@types/through2@2.0.41':
dependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
'@types/tmp@0.2.6': {}
@@ -19796,7 +19820,7 @@ snapshots:
'@types/yauzl@2.10.3':
dependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
optional: true
'@typescript-eslint/eslint-plugin@8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)':
@@ -19925,16 +19949,16 @@ snapshots:
- bufferutil
- utf-8-validate
- '@vitest/browser@3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(playwright@1.56.1)(utf-8-validate@6.0.5)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))':
+ '@vitest/browser@3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(playwright@1.56.1)(utf-8-validate@6.0.5)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))':
dependencies:
'@testing-library/dom': 10.4.0
'@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.0)
- '@vitest/mocker': 3.2.4(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
+ '@vitest/mocker': 3.2.4(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
'@vitest/utils': 3.2.4
magic-string: 0.30.18
sirv: 3.0.1
tinyrainbow: 2.0.0
- vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.12)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.9.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5)
optionalDependencies:
playwright: 1.56.1
@@ -19957,7 +19981,7 @@ snapshots:
magicast: 0.3.5
test-exclude: 7.0.1
tinyrainbow: 2.0.0
- vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.12)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.9.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
transitivePeerDependencies:
- supports-color
@@ -19976,9 +20000,9 @@ snapshots:
std-env: 3.9.0
test-exclude: 7.0.1
tinyrainbow: 2.0.0
- vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.12)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.9.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
optionalDependencies:
- '@vitest/browser': 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(playwright@1.56.1)(utf-8-validate@6.0.5)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))
+ '@vitest/browser': 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(playwright@1.56.1)(utf-8-validate@6.0.5)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))
transitivePeerDependencies:
- supports-color
@@ -19990,14 +20014,14 @@ snapshots:
chai: 5.2.0
tinyrainbow: 2.0.0
- '@vitest/mocker@3.2.4(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))':
+ '@vitest/mocker@3.2.4(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))':
dependencies:
'@vitest/spy': 3.2.4
estree-walker: 3.0.3
magic-string: 0.30.18
optionalDependencies:
- msw: 2.7.5(@types/node@22.18.12)(typescript@5.9.3)
- vite: 7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ msw: 2.7.5(@types/node@24.9.1)(typescript@5.9.3)
+ vite: 7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
'@vitest/pretty-format@3.2.4':
dependencies:
@@ -20028,7 +20052,7 @@ snapshots:
sirv: 3.0.1
tinyglobby: 0.2.15
tinyrainbow: 2.0.0
- vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.12)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.9.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
'@vitest/utils@3.2.4':
dependencies:
@@ -22597,7 +22621,7 @@ snapshots:
engine.io@6.6.4(bufferutil@4.0.9)(utf-8-validate@6.0.5):
dependencies:
'@types/cors': 2.8.19
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
accepts: 1.3.8
base64id: 2.0.0
cookie: 0.7.2
@@ -24721,13 +24745,13 @@ snapshots:
jest-worker@26.6.2:
dependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
merge-stream: 2.0.0
supports-color: 7.2.0
jest-worker@27.5.1:
dependencies:
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
merge-stream: 2.0.0
supports-color: 8.1.1
@@ -26095,12 +26119,12 @@ snapshots:
ms@2.1.3: {}
- msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3):
+ msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3):
dependencies:
'@bundled-es-modules/cookie': 2.0.1
'@bundled-es-modules/statuses': 1.0.1
'@bundled-es-modules/tough-cookie': 0.1.6
- '@inquirer/confirm': 5.1.19(@types/node@22.18.12)
+ '@inquirer/confirm': 5.1.19(@types/node@24.9.1)
'@mswjs/interceptors': 0.37.6
'@open-draft/deferred-promise': 2.2.0
'@open-draft/until': 2.1.0
@@ -27694,7 +27718,7 @@ snapshots:
'@protobufjs/path': 1.1.2
'@protobufjs/pool': 1.1.0
'@protobufjs/utf8': 1.1.0
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
long: 5.3.2
protocol-buffers-schema@3.6.0: {}
@@ -28219,11 +28243,11 @@ snapshots:
'@rolldown/binding-win32-x64-msvc': 1.0.0-beta.29
optional: true
- rollup-plugin-stats@1.5.1(rolldown@1.0.0-beta.29)(rollup@4.52.0)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)):
+ rollup-plugin-stats@1.5.1(rolldown@1.0.0-beta.29)(rollup@4.52.0)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)):
optionalDependencies:
rolldown: 1.0.0-beta.29
rollup: 4.52.0
- vite: 7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ vite: 7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
rollup-plugin-styles@4.0.0(rollup@4.40.0):
dependencies:
@@ -28252,13 +28276,13 @@ snapshots:
'@rollup/pluginutils': 5.1.4(rollup@4.40.0)
rollup: 4.40.0
- rollup-plugin-webpack-stats@2.1.6(rolldown@1.0.0-beta.29)(rollup@4.52.0)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)):
+ rollup-plugin-webpack-stats@2.1.6(rolldown@1.0.0-beta.29)(rollup@4.52.0)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)):
dependencies:
- rollup-plugin-stats: 1.5.1(rolldown@1.0.0-beta.29)(rollup@4.52.0)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
+ rollup-plugin-stats: 1.5.1(rolldown@1.0.0-beta.29)(rollup@4.52.0)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
optionalDependencies:
rolldown: 1.0.0-beta.29
rollup: 4.52.0
- vite: 7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ vite: 7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
rollup@4.40.0:
dependencies:
@@ -29755,14 +29779,14 @@ snapshots:
typescript: 5.0.4
webpack: 5.101.3(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.25.11)
- ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.12)(typescript@5.0.4):
+ ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.9.1)(typescript@5.0.4):
dependencies:
'@cspotcode/source-map-support': 0.8.1
'@tsconfig/node10': 1.0.11
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.4
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
acorn: 8.15.0
acorn-walk: 8.3.4
arg: 4.1.3
@@ -29775,14 +29799,14 @@ snapshots:
optionalDependencies:
'@swc/core': 1.11.29(@swc/helpers@0.5.17)
- ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.12)(typescript@5.9.3):
+ ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.9.1)(typescript@5.9.3):
dependencies:
'@cspotcode/source-map-support': 0.8.1
'@tsconfig/node10': 1.0.11
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.4
- '@types/node': 22.18.12
+ '@types/node': 24.9.1
acorn: 8.15.0
acorn-walk: 8.3.4
arg: 4.1.3
@@ -29939,8 +29963,7 @@ snapshots:
undici-types@6.21.0: {}
- undici-types@7.16.0:
- optional: true
+ undici-types@7.16.0: {}
undici@6.21.3: {}
@@ -30155,13 +30178,13 @@ snapshots:
'@types/unist': 3.0.3
vfile-message: 4.0.2
- vite-node@3.2.4(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1):
+ vite-node@3.2.4(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1):
dependencies:
cac: 6.7.14
debug: 4.4.3(supports-color@6.0.0)
es-module-lexer: 1.7.0
pathe: 2.0.3
- vite: 7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ vite: 7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
transitivePeerDependencies:
- '@types/node'
- jiti
@@ -30176,9 +30199,9 @@ snapshots:
- tsx
- yaml
- vite-plugin-dts@4.5.4(@types/node@22.18.12)(rollup@4.52.0)(typescript@5.9.3)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)):
+ vite-plugin-dts@4.5.4(@types/node@24.9.1)(rollup@4.52.0)(typescript@5.9.3)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)):
dependencies:
- '@microsoft/api-extractor': 7.52.8(@types/node@22.18.12)
+ '@microsoft/api-extractor': 7.52.8(@types/node@24.9.1)
'@rollup/pluginutils': 5.1.4(rollup@4.52.0)
'@volar/typescript': 2.4.13
'@vue/language-core': 2.2.0(typescript@5.9.3)
@@ -30189,7 +30212,7 @@ snapshots:
magic-string: 0.30.17
typescript: 5.9.3
optionalDependencies:
- vite: 7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ vite: 7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
transitivePeerDependencies:
- '@types/node'
- rollup
@@ -30203,11 +30226,11 @@ snapshots:
tinyglobby: 0.2.15
vite: 7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
- vite-plugin-svgo@2.0.0(typescript@5.9.3)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)):
+ vite-plugin-svgo@2.0.0(typescript@5.9.3)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)):
dependencies:
svgo: 3.3.2
typescript: 5.9.3
- vite: 7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ vite: 7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
vite-prerender-plugin@0.5.11(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)):
dependencies:
@@ -30219,26 +30242,6 @@ snapshots:
stack-trace: 1.0.0-pre2
vite: 7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
- vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1):
- dependencies:
- esbuild: 0.25.11
- fdir: 6.5.0(picomatch@4.0.3)
- picomatch: 4.0.3
- postcss: 8.5.6
- rollup: 4.52.0
- tinyglobby: 0.2.15
- optionalDependencies:
- '@types/node': 22.18.12
- fsevents: 2.3.3
- jiti: 2.6.1
- less: 4.1.3
- lightningcss: 1.30.1
- sass: 1.91.0
- sass-embedded: 1.91.0
- terser: 5.44.0
- tsx: 4.20.6
- yaml: 2.8.1
-
vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1):
dependencies:
esbuild: 0.25.11
@@ -30259,11 +30262,11 @@ snapshots:
tsx: 4.20.6
yaml: 2.8.1
- vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.18.12)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1):
+ vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.9.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1):
dependencies:
'@types/chai': 5.2.2
'@vitest/expect': 3.2.4
- '@vitest/mocker': 3.2.4(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
+ '@vitest/mocker': 3.2.4(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
'@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.2.4
'@vitest/snapshot': 3.2.4
@@ -30281,13 +30284,13 @@ snapshots:
tinyglobby: 0.2.15
tinypool: 1.1.1
tinyrainbow: 2.0.0
- vite: 7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
- vite-node: 3.2.4(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ vite: 7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ vite-node: 3.2.4(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/debug': 4.1.12
- '@types/node': 22.18.12
- '@vitest/browser': 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@22.18.12)(typescript@5.9.3))(playwright@1.56.1)(utf-8-validate@6.0.5)(vite@7.1.12(@types/node@22.18.12)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))
+ '@types/node': 24.9.1
+ '@vitest/browser': 3.2.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.9.1)(typescript@5.9.3))(playwright@1.56.1)(utf-8-validate@6.0.5)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)(webdriverio@9.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))
'@vitest/ui': 3.2.4(vitest@3.2.4)
happy-dom: 20.0.8
jsdom: 26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)