From 585b6ccd3e3dbb4f9941824e566829aa882884b7 Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Wed, 11 Mar 2026 19:05:44 -0700 Subject: [PATCH 001/482] feat(search): try to improve performance --- apps/server/spec/search_profiling.spec.ts | 284 ++++++++++ .../src/services/search/services/search.ts | 19 +- .../search/services/search_profiling.spec.ts | 526 ++++++++++++++++++ 3 files changed, 819 insertions(+), 10 deletions(-) create mode 100644 apps/server/spec/search_profiling.spec.ts create mode 100644 apps/server/src/services/search/services/search_profiling.spec.ts diff --git a/apps/server/spec/search_profiling.spec.ts b/apps/server/spec/search_profiling.spec.ts new file mode 100644 index 0000000000..9f5f848034 --- /dev/null +++ b/apps/server/spec/search_profiling.spec.ts @@ -0,0 +1,284 @@ +/** + * Integration-level search profiling test. + * + * Uses the real SQLite database (spec/db/document.db loaded in-memory), + * real sql module, real becca cache, and the full app stack. + * + * Seeds a large number of notes via direct SQL (much faster than ETAPI) + * to create a realistic dataset for profiling. + */ +import { Application } from "express"; +import { beforeAll, describe, expect, it } from "vitest"; +import config from "../src/services/config.js"; + +let app: Application; + +function timed(fn: () => T): [T, number] { + const start = performance.now(); + const result = fn(); + return [result, performance.now() - start]; +} + +function randomId(len = 12): string { + const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + let id = ""; + for (let i = 0; i < len; i++) id += chars[Math.floor(Math.random() * chars.length)]; + return id; +} + +function randomWord(len = 8): string { + const chars = "abcdefghijklmnopqrstuvwxyz"; + let w = ""; + for (let i = 0; i < len; i++) w += chars[Math.floor(Math.random() * chars.length)]; + return w; +} + +function generateContent(wordCount: number, keyword?: string): string { + const paragraphs: string[] = []; + let remaining = wordCount; + let injected = false; + while (remaining > 0) { + const n = Math.min(remaining, 30 + Math.floor(Math.random() * 30)); + const words: string[] = []; + for (let i = 0; i < n; i++) words.push(randomWord(3 + Math.floor(Math.random() * 10))); + if (keyword && !injected && remaining < wordCount / 2) { + words[Math.floor(words.length / 2)] = keyword; + injected = true; + } + paragraphs.push(`

${words.join(" ")}

`); + remaining -= n; + } + return paragraphs.join("\n"); +} + +describe("Search profiling (integration)", () => { + beforeAll(async () => { + config.General.noAuthentication = true; + const buildApp = (await import("../src/app.js")).default; + app = await buildApp(); + }); + + it("seed and profile with realistic data", async () => { + const sql = (await import("../src/services/sql.js")).default; + const becca = (await import("../src/becca/becca.js")).default; + const beccaLoader = (await import("../src/becca/becca_loader.js")).default; + const cls = (await import("../src/services/cls.js")).default; + const searchService = (await import("../src/services/search/services/search.js")).default; + const SearchContext = (await import("../src/services/search/search_context.js")).default; + + await new Promise((resolve) => { + cls.init(() => { + const initialNoteCount = Object.keys(becca.notes).length; + console.log(`\n Initial becca notes: ${initialNoteCount}`); + + const configs = [ + { notes: 2000, words: 500, label: "2K notes × 500 words (~4KB)" }, + { notes: 2000, words: 2000, label: "2K notes × 2000 words (~15KB)" }, + { notes: 5000, words: 500, label: "5K notes × 500 words (~4KB)" }, + { notes: 5000, words: 2000, label: "5K notes × 2000 words (~15KB)" }, + { notes: 10000, words: 1000, label: "10K notes × 1000 words (~8KB)" }, + ]; + + for (const cfg of configs) { + // Reset DB: delete all seeded notes from prior iteration + sql.execute(`DELETE FROM blobs WHERE blobId LIKE 'seed%'`); + sql.execute(`DELETE FROM notes WHERE noteId LIKE 'seed%'`); + sql.execute(`DELETE FROM branches WHERE branchId LIKE 'seed%'`); + + const TOTAL_NOTES = cfg.notes; + const MATCH_FRACTION = 0.15; + const CONTENT_WORDS = cfg.words; + const matchCount = Math.floor(TOTAL_NOTES * MATCH_FRACTION); + + const now = new Date().toISOString().replace("T", " ").replace("Z", "+0000"); + + console.log(`\n ──── ${cfg.label} ────`); + console.log(` Seeding ${TOTAL_NOTES} notes (${matchCount} with keyword)...`); + + const [, seedMs] = timed(() => { + sql.transactional(() => { + for (let i = 0; i < TOTAL_NOTES; i++) { + const isMatch = i < matchCount; + const noteId = `seed${randomId(8)}`; + const branchId = `seed${randomId(8)}`; + const blobId = `seed${randomId(16)}`; + const title = isMatch + ? `Performance Doc ${i} ${randomWord(6)}` + : `General Note ${i} ${randomWord(6)} ${randomWord(5)}`; + const content = generateContent( + CONTENT_WORDS, + isMatch ? "performance" : undefined + ); + + sql.execute( + `INSERT INTO blobs (blobId, content, dateModified, utcDateModified) + VALUES (?, ?, ?, ?)`, + [blobId, content, now, now] + ); + + sql.execute( + `INSERT INTO notes (noteId, title, type, mime, blobId, isProtected, isDeleted, + dateCreated, dateModified, utcDateCreated, utcDateModified) + VALUES (?, ?, 'text', 'text/html', ?, 0, 0, ?, ?, ?, ?)`, + [noteId, title, blobId, now, now, now, now] + ); + + sql.execute( + `INSERT INTO branches (branchId, noteId, parentNoteId, notePosition, isDeleted, isExpanded, + utcDateModified) + VALUES (?, ?, 'root', ?, 0, 0, ?)`, + [branchId, noteId, i * 10, now] + ); + } + }); + }); + console.log(` SQL seeding: ${seedMs.toFixed(0)}ms`); + + // Reload becca to pick up new notes + const [, reloadMs] = timed(() => { + beccaLoader.load(); + }); + console.log(` Becca reload: ${reloadMs.toFixed(0)}ms`); + console.log(` Becca notes after seed: ${Object.keys(becca.notes).length}`); + + // Verify content is accessible + const sampleNote = Object.values(becca.notes).find(n => n.title.startsWith("Performance Doc")); + if (sampleNote) { + const content = sampleNote.getContent(); + console.log(` Sample content length: ${typeof content === 'string' ? content.length : 0} chars`); + } + + // ========================================== + // PROFILING + // ========================================== + + console.log(`\n --- PROFILING (${cfg.label}) ---\n`); + + // --- 1. Fast search (NoteFlatTextExp only) --- + searchService.findResultsWithQuery("performance", new SearchContext({ fastSearch: true })); + + const fastTimes: number[] = []; + let fastResultCount = 0; + for (let i = 0; i < 5; i++) { + const [r, ms] = timed(() => + searchService.findResultsWithQuery("performance", + new SearchContext({ fastSearch: true }) + ) + ); + fastTimes.push(ms); + fastResultCount = r.length; + } + const fastAvg = fastTimes.reduce((a, b) => a + b, 0) / fastTimes.length; + console.log(` Fast search (flat text only): avg ${fastAvg.toFixed(1)}ms (${fastResultCount} results)`); + + // --- 2. Full search (flat text + content fulltext via SQL) --- + const fullTimes: number[] = []; + let fullResultCount = 0; + for (let i = 0; i < 3; i++) { + const [r, ms] = timed(() => + searchService.findResultsWithQuery("performance", + new SearchContext({ fastSearch: false }) + ) + ); + fullTimes.push(ms); + fullResultCount = r.length; + } + const fullAvg = fullTimes.reduce((a, b) => a + b, 0) / fullTimes.length; + console.log(` Full search (flat + SQL content): avg ${fullAvg.toFixed(1)}ms (${fullResultCount} results)`); + + // --- 3. Content snippet extraction --- + const fastResults = searchService.findResultsWithQuery("performance", + new SearchContext({ fastSearch: true })); + const trimmed = fastResults.slice(0, 200); + const tokens = ["performance"]; + + const snippetTimes: number[] = []; + for (let i = 0; i < 3; i++) { + const [, ms] = timed(() => { + for (const r of trimmed) { + r.contentSnippet = searchService.extractContentSnippet(r.noteId, tokens); + } + }); + snippetTimes.push(ms); + } + const snippetAvg = snippetTimes.reduce((a, b) => a + b, 0) / snippetTimes.length; + console.log(` Content snippet (${trimmed.length} results): avg ${snippetAvg.toFixed(1)}ms (${(snippetAvg / trimmed.length).toFixed(3)}ms/note)`); + + // --- 4. Raw getContent() cost --- + const contentTimes: number[] = []; + const textNotes = trimmed + .map(r => becca.notes[r.noteId]) + .filter(n => n && ["text", "code"].includes(n.type)); + + for (let i = 0; i < 5; i++) { + const [, ms] = timed(() => { + for (const n of textNotes) n.getContent(); + }); + contentTimes.push(ms); + } + const contentAvg = contentTimes.reduce((a, b) => a + b, 0) / contentTimes.length; + console.log(` getContent() × ${textNotes.length} notes: avg ${contentAvg.toFixed(1)}ms (${(contentAvg / textNotes.length).toFixed(3)}ms/note)`); + + // --- 5. striptags + normalize cost (isolated) --- + const striptags = require("striptags"); + const normalizeString = require("normalize-strings"); + const contents = textNotes.map(n => n.getContent() as string).filter(Boolean); + + const [, stripMs] = timed(() => { + for (const c of contents) { + striptags(c); + } + }); + console.log(` striptags × ${contents.length} notes: ${stripMs.toFixed(1)}ms (${(stripMs / contents.length).toFixed(3)}ms/note)`); + + const stripped = contents.map(c => striptags(c)); + const [, normMs] = timed(() => { + for (const s of stripped) { + normalizeString(s.toLowerCase()); + } + }); + console.log(` normalizeString × ${stripped.length} notes: ${normMs.toFixed(1)}ms (${(normMs / stripped.length).toFixed(3)}ms/note)`); + + // --- 6. Full autocomplete --- + const autoTimes: number[] = []; + let autoResultCount = 0; + for (let i = 0; i < 3; i++) { + const [r, ms] = timed(() => + searchService.searchNotesForAutocomplete("performance", true) + ); + autoTimes.push(ms); + autoResultCount = r.length; + } + const autoAvg = autoTimes.reduce((a, b) => a + b, 0) / autoTimes.length; + console.log(`\n FULL AUTOCOMPLETE: avg ${autoAvg.toFixed(1)}ms (${autoResultCount} results)`); + + // --- 7. SQL content scan cost --- + const [scanCount, scanMs] = timed(() => { + let count = 0; + for (const row of sql.iterateRows<{ content: Buffer | string }>(` + SELECT noteId, type, mime, content, isProtected + FROM notes JOIN blobs USING (blobId) + WHERE type IN ('text', 'code', 'mermaid', 'canvas', 'mindMap') + AND isDeleted = 0 + AND LENGTH(content) < 2097152`)) { + count++; + } + return count; + }); + console.log(` SQL content scan (${scanCount} rows): ${scanMs.toFixed(1)}ms`); + + // --- Summary --- + console.log(`\n === SUMMARY (${cfg.label}, ${Object.keys(becca.notes).length} total notes) ===`); + console.log(` Fast search: ${fastAvg.toFixed(1)}ms`); + console.log(` Full search: ${fullAvg.toFixed(1)}ms`); + console.log(` Content snippets: ${snippetAvg.toFixed(1)}ms (${(snippetAvg / trimmed.length).toFixed(3)}ms/note)`); + console.log(` normalizeString: ${normMs.toFixed(1)}ms (${(normMs / stripped.length).toFixed(3)}ms/note)`); + console.log(` Full autocomplete: ${autoAvg.toFixed(1)}ms`); + console.log(` SQL scan: ${scanMs.toFixed(1)}ms (${scanCount} rows)`); + } + + resolve(); + }); + }); + }, 600_000); +}); diff --git a/apps/server/src/services/search/services/search.ts b/apps/server/src/services/search/services/search.ts index 5ca4bda4a1..4701964f5b 100644 --- a/apps/server/src/services/search/services/search.ts +++ b/apps/server/src/services/search/services/search.ts @@ -1,6 +1,5 @@ "use strict"; -import normalizeString from "normalize-strings"; import lex from "./lex.js"; import handleParens from "./handle_parens.js"; import parse from "./parse.js"; @@ -8,7 +7,7 @@ import SearchResult from "../search_result.js"; import SearchContext from "../search_context.js"; import becca from "../../../becca/becca.js"; import beccaService from "../../../becca/becca_service.js"; -import { normalize, escapeHtml, escapeRegExp } from "../../utils.js"; +import { normalize, removeDiacritic, escapeHtml, escapeRegExp } from "../../utils.js"; import log from "../../log.js"; import hoistedNoteService from "../../hoisted_note.js"; import type BNote from "../../../becca/entities/bnote.js"; @@ -482,12 +481,12 @@ function extractContentSnippet(noteId: string, searchTokens: string[], maxLength } // Try to find a snippet around the first matching token - const normalizedContent = normalizeString(content.toLowerCase()); + const normalizedContent = normalize(content); let snippetStart = 0; let matchFound = false; for (const token of searchTokens) { - const normalizedToken = normalizeString(token.toLowerCase()); + const normalizedToken = normalize(token); const matchIndex = normalizedContent.indexOf(normalizedToken); if (matchIndex !== -1) { @@ -505,8 +504,8 @@ function extractContentSnippet(noteId: string, searchTokens: string[], maxLength const lines = snippet.split('\n'); if (lines.length > 4) { // Find which lines contain the search tokens to ensure they're included - const normalizedLines = lines.map(line => normalizeString(line.toLowerCase())); - const normalizedTokens = searchTokens.map(token => normalizeString(token.toLowerCase())); + const normalizedLines = lines.map(line => normalize(line)); + const normalizedTokens = searchTokens.map(token => normalize(token)); // Find the first line that contains a search token let firstMatchLine = -1; @@ -582,7 +581,7 @@ function extractAttributeSnippet(noteId: string, searchTokens: string[], maxLeng // Check if any search token matches the attribute name or value const hasMatch = searchTokens.some(token => { - const normalizedToken = normalizeString(token.toLowerCase()); + const normalizedToken = normalize(token); return attrName.includes(normalizedToken) || attrValue.includes(normalizedToken); }); @@ -734,7 +733,7 @@ function highlightSearchResults(searchResults: SearchResult[], highlightedTokens // Highlight in note path title if (result.highlightedNotePathTitle) { const titleRegex = new RegExp(escapeRegExp(token), "gi"); - while ((match = titleRegex.exec(normalizeString(result.highlightedNotePathTitle))) !== null) { + while ((match = titleRegex.exec(removeDiacritic(result.highlightedNotePathTitle))) !== null) { result.highlightedNotePathTitle = wrapText(result.highlightedNotePathTitle, match.index, token.length, "{", "}"); // 2 characters are added, so we need to adjust the index titleRegex.lastIndex += 2; @@ -744,7 +743,7 @@ function highlightSearchResults(searchResults: SearchResult[], highlightedTokens // Highlight in content snippet if (result.highlightedContentSnippet) { const contentRegex = new RegExp(escapeRegExp(token), "gi"); - while ((match = contentRegex.exec(normalizeString(result.highlightedContentSnippet))) !== null) { + while ((match = contentRegex.exec(removeDiacritic(result.highlightedContentSnippet))) !== null) { result.highlightedContentSnippet = wrapText(result.highlightedContentSnippet, match.index, token.length, "{", "}"); // 2 characters are added, so we need to adjust the index contentRegex.lastIndex += 2; @@ -754,7 +753,7 @@ function highlightSearchResults(searchResults: SearchResult[], highlightedTokens // Highlight in attribute snippet if (result.highlightedAttributeSnippet) { const attributeRegex = new RegExp(escapeRegExp(token), "gi"); - while ((match = attributeRegex.exec(normalizeString(result.highlightedAttributeSnippet))) !== null) { + while ((match = attributeRegex.exec(removeDiacritic(result.highlightedAttributeSnippet))) !== null) { result.highlightedAttributeSnippet = wrapText(result.highlightedAttributeSnippet, match.index, token.length, "{", "}"); // 2 characters are added, so we need to adjust the index attributeRegex.lastIndex += 2; diff --git a/apps/server/src/services/search/services/search_profiling.spec.ts b/apps/server/src/services/search/services/search_profiling.spec.ts new file mode 100644 index 0000000000..96a414b257 --- /dev/null +++ b/apps/server/src/services/search/services/search_profiling.spec.ts @@ -0,0 +1,526 @@ +/** + * Search performance profiling tests. + * + * These tests measure where time is spent in the search pipeline. + * We monkeypatch note.getContent() to return synthetic HTML content + * since unit tests don't have a real SQLite database. + * + * KNOWN GAPS vs production: + * - note.getContent() is instant (monkeypatched) vs ~2ms SQL fetch + * - NoteContentFulltextExp.execute() is skipped (no sql.iterateRows) + * because fastSearch=true uses only NoteFlatTextExp + * - These tests focus on the in-memory/CPU-bound parts of the pipeline + */ +import { describe, it, expect, beforeEach, afterEach } from "vitest"; +import searchService from "./search.js"; +import BNote from "../../../becca/entities/bnote.js"; +import BBranch from "../../../becca/entities/bbranch.js"; +import SearchContext from "../search_context.js"; +import becca from "../../../becca/becca.js"; +import beccaService from "../../../becca/becca_service.js"; +import { NoteBuilder, note, id } from "../../../test/becca_mocking.js"; +import SearchResult from "../search_result.js"; +import { normalizeSearchText } from "../utils/text_utils.js"; + +// ── helpers ────────────────────────────────────────────────────────── + +function randomWord(len = 6): string { + const chars = "abcdefghijklmnopqrstuvwxyz"; + let word = ""; + for (let i = 0; i < len; i++) { + word += chars[Math.floor(Math.random() * chars.length)]; + } + return word; +} + +function generateHtmlContent(wordCount: number, includeTarget = false): string { + const paragraphs: string[] = []; + let wordsRemaining = wordCount; + + while (wordsRemaining > 0) { + const paraWords = Math.min(wordsRemaining, 20 + Math.floor(Math.random() * 40)); + const words: string[] = []; + for (let i = 0; i < paraWords; i++) { + words.push(randomWord(3 + Math.floor(Math.random() * 10))); + } + if (includeTarget && paragraphs.length === 2) { + words[Math.floor(words.length / 2)] = "target"; + } + paragraphs.push(`

${words.join(" ")}

`); + wordsRemaining -= paraWords; + } + + return `${paragraphs.join("\n")}`; +} + +function timed(fn: () => T): [T, number] { + const start = performance.now(); + const result = fn(); + return [result, performance.now() - start]; +} + +interface TimingEntry { label: string; ms: number; } + +function reportTimings(title: string, timings: TimingEntry[]) { + const total = timings.reduce((s, t) => s + t.ms, 0); + console.log(`\n=== ${title} (total: ${total.toFixed(1)}ms) ===`); + for (const { label, ms } of timings) { + const pct = total > 0 ? ((ms / total) * 100).toFixed(0) : "0"; + const bar = "#".repeat(Math.max(1, Math.round(ms / total * 40))); + console.log(` ${label.padEnd(55)} ${ms.toFixed(1).padStart(8)}ms ${pct.padStart(3)}% ${bar}`); + } +} + +// ── dataset builder ────────────────────────────────────────────────── + +const syntheticContent: Record = {}; + +function buildDataset(noteCount: number, opts: { + matchFraction?: number; + labelsPerNote?: number; + depth?: number; + contentWordCount?: number; +} = {}) { + const { + matchFraction = 0.1, + labelsPerNote = 3, + depth = 3, + contentWordCount = 200, + } = opts; + + becca.reset(); + for (const key of Object.keys(syntheticContent)) { + delete syntheticContent[key]; + } + + const rootNote = new NoteBuilder(new BNote({ noteId: "root", title: "root", type: "text" })); + new BBranch({ + branchId: "none_root", + noteId: "root", + parentNoteId: "none", + notePosition: 10 + }); + + const containers: NoteBuilder[] = []; + let parent = rootNote; + for (let d = 0; d < depth; d++) { + const container = note(`Container_${d}_${randomWord(4)}`); + parent.child(container); + containers.push(container); + parent = container; + } + + const matchCount = Math.floor(noteCount * matchFraction); + + for (let i = 0; i < noteCount; i++) { + const isMatch = i < matchCount; + const title = isMatch + ? `${randomWord(5)} target ${randomWord(5)} Document ${i}` + : `${randomWord(5)} ${randomWord(6)} ${randomWord(4)} Note ${i}`; + + const n = note(title); + + for (let l = 0; l < labelsPerNote; l++) { + const labelName = isMatch && l === 0 ? "category" : `label_${randomWord(4)}`; + const labelValue = isMatch && l === 0 ? "important target" : randomWord(8); + n.label(labelName, labelValue); + } + + syntheticContent[n.note.noteId] = generateHtmlContent(contentWordCount, isMatch); + + const containerIndex = i % containers.length; + containers[containerIndex].child(n); + } + + // Monkeypatch getContent() + for (const noteObj of Object.values(becca.notes)) { + const noteId = noteObj.noteId; + if (syntheticContent[noteId]) { + (noteObj as any).getContent = () => syntheticContent[noteId]; + } else { + (noteObj as any).getContent = () => ""; + } + } + + return { rootNote, matchCount }; +} + +// ── profiling tests ────────────────────────────────────────────────── + +describe("Search Profiling", () => { + + afterEach(() => { + becca.reset(); + }); + + /** + * Break down the autocomplete pipeline into every individual stage, + * including previously unmeasured operations like getBestNotePath, + * SearchResult construction, and getNoteTitleForPath. + */ + describe("Granular autocomplete pipeline", () => { + + for (const noteCount of [500, 2000, 5000, 10000]) { + it(`granular breakdown with ${noteCount} notes`, () => { + const timings: TimingEntry[] = []; + + const [, buildMs] = timed(() => buildDataset(noteCount, { + matchFraction: 0.2, + contentWordCount: 300, + depth: 5 + })); + timings.push({ label: `Dataset build (${noteCount} notes)`, ms: buildMs }); + + // === NoteFlatTextExp: getCandidateNotes === + // This calls getFlatText() + normalizeSearchText() for EVERY note + const allNotes = Object.values(becca.notes); + for (const n of allNotes) n.invalidateThisCache(); + + const [, candidateMs] = timed(() => { + const token = normalizeSearchText("target"); + let count = 0; + for (const n of allNotes) { + const flatText = normalizeSearchText(n.getFlatText()); + if (flatText.includes(token)) count++; + } + return count; + }); + timings.push({ label: `getCandidateNotes simulation (cold caches)`, ms: candidateMs }); + + // Warm cache version + const [candidateCount, candidateWarmMs] = timed(() => { + const token = normalizeSearchText("target"); + let count = 0; + for (const n of allNotes) { + const flatText = normalizeSearchText(n.getFlatText()); + if (flatText.includes(token)) count++; + } + return count; + }); + timings.push({ label: `getCandidateNotes simulation (warm caches)`, ms: candidateWarmMs }); + + // === getBestNotePath for each candidate === + const candidates = allNotes.filter(n => { + const flatText = normalizeSearchText(n.getFlatText()); + return flatText.includes("target"); + }); + + const [, pathMs] = timed(() => { + for (const n of candidates) { + n.getBestNotePath(); + } + }); + timings.push({ label: `getBestNotePath (${candidates.length} notes)`, ms: pathMs }); + + // === SearchResult construction (includes getNoteTitleForPath) === + const paths = candidates.map(n => n.getBestNotePath()).filter(Boolean); + + const [searchResults, srMs] = timed(() => { + return paths.map(p => new SearchResult(p)); + }); + timings.push({ label: `SearchResult construction (${paths.length} results)`, ms: srMs }); + + // === computeScore === + const [, scoreMs] = timed(() => { + for (const r of searchResults) { + r.computeScore("target", ["target"], true); + } + }); + timings.push({ label: `computeScore with fuzzy (${searchResults.length} results)`, ms: scoreMs }); + + const [, scoreNoFuzzyMs] = timed(() => { + for (const r of searchResults) { + r.computeScore("target", ["target"], false); + } + }); + timings.push({ label: `computeScore no-fuzzy`, ms: scoreNoFuzzyMs }); + + // === Sorting === + const [, sortMs] = timed(() => { + searchResults.sort((a, b) => { + if (a.score !== b.score) return b.score - a.score; + if (a.notePathArray.length === b.notePathArray.length) { + return a.notePathTitle < b.notePathTitle ? -1 : 1; + } + return a.notePathArray.length - b.notePathArray.length; + }); + }); + timings.push({ label: `Sort results`, ms: sortMs }); + + // === Trim + content snippet extraction === + const trimmed = searchResults.slice(0, 200); + + const [, snippetMs] = timed(() => { + for (const r of trimmed) { + r.contentSnippet = searchService.extractContentSnippet( + r.noteId, ["target"] + ); + } + }); + timings.push({ label: `Content snippet extraction (${trimmed.length} results)`, ms: snippetMs }); + + const [, attrMs] = timed(() => { + for (const r of trimmed) { + r.attributeSnippet = searchService.extractAttributeSnippet( + r.noteId, ["target"] + ); + } + }); + timings.push({ label: `Attribute snippet extraction`, ms: attrMs }); + + // === Highlighting === + const [, hlMs] = timed(() => { + searchService.highlightSearchResults(trimmed, ["target"]); + }); + timings.push({ label: `Highlighting`, ms: hlMs }); + + // === Final mapping (getNoteTitleAndIcon) === + const [, mapMs] = timed(() => { + for (const r of trimmed) { + beccaService.getNoteTitleAndIcon(r.noteId); + } + }); + timings.push({ label: `getNoteTitleAndIcon (${trimmed.length} results)`, ms: mapMs }); + + // === Full autocomplete for comparison === + const [autoResults, autoMs] = timed(() => { + return searchService.searchNotesForAutocomplete("target", true); + }); + timings.push({ label: `Full autocomplete call (end-to-end)`, ms: autoMs }); + + reportTimings(`Granular Autocomplete — ${noteCount} notes`, timings); + expect(autoResults.length).toBeGreaterThan(0); + }); + } + }); + + /** + * Test the specific cost of normalizeSearchText which is called + * pervasively throughout the pipeline. + */ + describe("normalizeSearchText cost", () => { + + it("profile normalizeSearchText at scale", () => { + buildDataset(5000, { matchFraction: 0.2, contentWordCount: 100 }); + + // Generate various text lengths to profile + const shortTexts = Array.from({ length: 5000 }, () => randomWord(10)); + const mediumTexts = Array.from({ length: 5000 }, () => + Array.from({ length: 20 }, () => randomWord(6)).join(" ") + ); + const longTexts = Object.values(becca.notes).map(n => n.getFlatText()); + + console.log("\n=== normalizeSearchText cost ==="); + + const [, shortMs] = timed(() => { + for (const t of shortTexts) normalizeSearchText(t); + }); + console.log(` 5000 short texts (10 chars): ${shortMs.toFixed(1)}ms (${(shortMs/5000*1000).toFixed(1)}µs/call)`); + + const [, medMs] = timed(() => { + for (const t of mediumTexts) normalizeSearchText(t); + }); + console.log(` 5000 medium texts (120 chars): ${medMs.toFixed(1)}ms (${(medMs/5000*1000).toFixed(1)}µs/call)`); + + const [, longMs] = timed(() => { + for (const t of longTexts) normalizeSearchText(t); + }); + console.log(` ${longTexts.length} flat texts (varying): ${longMs.toFixed(1)}ms (${(longMs/longTexts.length*1000).toFixed(1)}µs/call)`); + }); + }); + + /** + * Test the searchPathTowardsRoot recursive walk which runs + * for every candidate note in NoteFlatTextExp. + */ + describe("searchPathTowardsRoot cost", () => { + + it("profile recursive walk with varying hierarchy depth", () => { + console.log("\n=== Search path walk vs hierarchy depth ==="); + + for (const depth of [3, 5, 8, 12]) { + buildDataset(2000, { + matchFraction: 0.15, + depth, + contentWordCount: 50 + }); + + const [results, ms] = timed(() => { + const ctx = new SearchContext({ fastSearch: true }); + return searchService.findResultsWithQuery("target", ctx); + }); + console.log(` depth=${depth}: ${ms.toFixed(1)}ms (${results.length} results)`); + } + }); + }); + + /** + * Content snippet extraction scaling — the operation that calls + * note.getContent() for each result. + */ + describe("Content snippet extraction", () => { + + it("profile snippet extraction with varying content sizes", () => { + console.log("\n=== Content snippet extraction vs content size ==="); + + for (const wordCount of [50, 200, 500, 1000, 2000, 5000]) { + buildDataset(500, { + matchFraction: 0.5, + contentWordCount: wordCount + }); + + const ctx = new SearchContext({ fastSearch: true }); + const results = searchService.findResultsWithQuery("target", ctx); + const trimmed = results.slice(0, 200); + + const [, ms] = timed(() => { + for (const r of trimmed) { + r.contentSnippet = searchService.extractContentSnippet( + r.noteId, ["target"] + ); + } + }); + + const avgContentLen = Object.values(syntheticContent) + .slice(0, 100) + .reduce((s, c) => s + c.length, 0) / 100; + + console.log(` ${String(wordCount).padStart(5)} words/note (avg ${Math.round(avgContentLen)} chars) × ${trimmed.length} results: ${ms.toFixed(1)}ms (${(ms / trimmed.length).toFixed(3)}ms/note)`); + } + }); + + it("profile snippet extraction with varying result counts", () => { + console.log("\n=== Content snippet extraction vs result count ==="); + + buildDataset(2000, { + matchFraction: 0.5, + contentWordCount: 500 + }); + + const ctx = new SearchContext({ fastSearch: true }); + const allResults = searchService.findResultsWithQuery("target", ctx); + + for (const count of [5, 10, 20, 50, 100, 200]) { + const subset = allResults.slice(0, count); + + const [, ms] = timed(() => { + for (const r of subset) { + r.contentSnippet = searchService.extractContentSnippet( + r.noteId, ["target"] + ); + } + }); + + console.log(` ${String(count).padStart(3)} results: ${ms.toFixed(1)}ms (${(ms / count).toFixed(3)}ms/note)`); + } + }); + }); + + /** + * Two-phase exact/fuzzy search cost. + */ + describe("Two-phase search cost", () => { + + for (const noteCount of [1000, 5000, 10000]) { + it(`exact vs progressive with ${noteCount} notes`, () => { + const timings: TimingEntry[] = []; + + buildDataset(noteCount, { matchFraction: 0.005, contentWordCount: 50 }); + + const [exactR, exactMs] = timed(() => { + const ctx = new SearchContext({ fastSearch: true }); + ctx.enableFuzzyMatching = false; + return searchService.findResultsWithQuery("target", ctx); + }); + timings.push({ label: `Exact-only (${exactR.length} results)`, ms: exactMs }); + + const [progR, progMs] = timed(() => { + const ctx = new SearchContext({ fastSearch: true }); + return searchService.findResultsWithQuery("target", ctx); + }); + timings.push({ label: `Progressive exact→fuzzy (${progR.length} results)`, ms: progMs }); + + const overhead = progMs - exactMs; + timings.push({ label: `Fuzzy phase overhead`, ms: Math.max(0, overhead) }); + + reportTimings(`Two-phase — ${noteCount} notes`, timings); + }); + } + }); + + /** + * End-to-end scaling to give the full picture. + */ + describe("End-to-end scaling", () => { + + it("autocomplete at different scales", () => { + console.log("\n=== End-to-end autocomplete scaling ==="); + console.log(" (fastSearch=true, monkeypatched getContent, no real SQL)"); + + for (const noteCount of [100, 500, 1000, 2000, 5000, 10000, 20000]) { + buildDataset(noteCount, { + matchFraction: 0.2, + contentWordCount: 300, + depth: 4 + }); + + // Warm up + searchService.searchNotesForAutocomplete("target", true); + + const times: number[] = []; + for (let i = 0; i < 3; i++) { + const [, ms] = timed(() => searchService.searchNotesForAutocomplete("target", true)); + times.push(ms); + } + + const avg = times.reduce((a, b) => a + b, 0) / times.length; + const min = Math.min(...times); + + console.log( + ` ${String(noteCount).padStart(6)} notes: avg ${avg.toFixed(1)}ms ` + + `min ${min.toFixed(1)}ms` + ); + } + }); + + it("compare fast vs non-fast search", () => { + console.log("\n=== Fast vs non-fast search (no real SQL for content) ==="); + + for (const noteCount of [500, 2000, 5000]) { + buildDataset(noteCount, { + matchFraction: 0.2, + contentWordCount: 200, + depth: 4 + }); + + const [, fastMs] = timed(() => { + const ctx = new SearchContext({ fastSearch: true }); + return searchService.findResultsWithQuery("target", ctx); + }); + + // Non-fast search tries NoteContentFulltextExp which uses sql.iterateRows + // This will likely fail/return empty since there's no real DB, but we + // can still measure the overhead of attempting it + let nonFastMs: number; + let nonFastCount: number; + try { + const [results, ms] = timed(() => { + const ctx = new SearchContext({ fastSearch: false }); + return searchService.findResultsWithQuery("target", ctx); + }); + nonFastMs = ms; + nonFastCount = results.length; + } catch { + nonFastMs = -1; + nonFastCount = -1; + } + + console.log( + ` ${String(noteCount).padStart(5)} notes: fast=${fastMs.toFixed(1)}ms ` + + `non-fast=${nonFastMs >= 0 ? nonFastMs.toFixed(1) + 'ms' : 'FAILED (no real DB)'} ` + + `(non-fast results: ${nonFastCount})` + ); + } + }); + }); +}); From 77733ce2050953eeb927939becfcbdf97882a2eb Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Wed, 11 Mar 2026 21:11:55 -0700 Subject: [PATCH 002/482] feat(search): try to rice performance some more --- apps/server/spec/search_profiling.spec.ts | 380 +++++++++--------- apps/server/src/becca/becca-interface.ts | 30 ++ apps/server/src/becca/entities/bnote.ts | 3 + .../search/expressions/note_flat_text.ts | 48 ++- .../src/services/search/services/search.ts | 84 ++-- 5 files changed, 318 insertions(+), 227 deletions(-) diff --git a/apps/server/spec/search_profiling.spec.ts b/apps/server/spec/search_profiling.spec.ts index 9f5f848034..8099a322b4 100644 --- a/apps/server/spec/search_profiling.spec.ts +++ b/apps/server/spec/search_profiling.spec.ts @@ -4,8 +4,8 @@ * Uses the real SQLite database (spec/db/document.db loaded in-memory), * real sql module, real becca cache, and the full app stack. * - * Seeds a large number of notes via direct SQL (much faster than ETAPI) - * to create a realistic dataset for profiling. + * Profiles search at large scale (50K+ notes) to match real-world + * performance reports from users with 240K+ notes. */ import { Application } from "express"; import { beforeAll, describe, expect, it } from "vitest"; @@ -58,224 +58,246 @@ describe("Search profiling (integration)", () => { app = await buildApp(); }); - it("seed and profile with realistic data", async () => { + it("large-scale profiling (50K notes)", async () => { const sql = (await import("../src/services/sql.js")).default; const becca = (await import("../src/becca/becca.js")).default; const beccaLoader = (await import("../src/becca/becca_loader.js")).default; const cls = (await import("../src/services/cls.js")).default; const searchService = (await import("../src/services/search/services/search.js")).default; const SearchContext = (await import("../src/services/search/search_context.js")).default; + const beccaService = (await import("../src/becca/becca_service.js")).default; await new Promise((resolve) => { cls.init(() => { const initialNoteCount = Object.keys(becca.notes).length; console.log(`\n Initial becca notes: ${initialNoteCount}`); - const configs = [ - { notes: 2000, words: 500, label: "2K notes × 500 words (~4KB)" }, - { notes: 2000, words: 2000, label: "2K notes × 2000 words (~15KB)" }, - { notes: 5000, words: 500, label: "5K notes × 500 words (~4KB)" }, - { notes: 5000, words: 2000, label: "5K notes × 2000 words (~15KB)" }, - { notes: 10000, words: 1000, label: "10K notes × 1000 words (~8KB)" }, - ]; + // ── Seed 50K notes with hierarchy ── + // Some folders (depth), some with common keyword "test" in title + const TOTAL_NOTES = 50000; + const FOLDER_COUNT = 500; // 500 folders + const NOTES_PER_FOLDER = (TOTAL_NOTES - FOLDER_COUNT) / FOLDER_COUNT; // ~99 notes per folder + const MATCH_FRACTION = 0.10; // 10% match "test" — ~5000 notes + const CONTENT_WORDS = 500; - for (const cfg of configs) { - // Reset DB: delete all seeded notes from prior iteration - sql.execute(`DELETE FROM blobs WHERE blobId LIKE 'seed%'`); - sql.execute(`DELETE FROM notes WHERE noteId LIKE 'seed%'`); - sql.execute(`DELETE FROM branches WHERE branchId LIKE 'seed%'`); + const now = new Date().toISOString().replace("T", " ").replace("Z", "+0000"); + console.log(` Seeding ${TOTAL_NOTES} notes (${FOLDER_COUNT} folders, ~${NOTES_PER_FOLDER.toFixed(0)} per folder)...`); - const TOTAL_NOTES = cfg.notes; - const MATCH_FRACTION = 0.15; - const CONTENT_WORDS = cfg.words; - const matchCount = Math.floor(TOTAL_NOTES * MATCH_FRACTION); + const [, seedMs] = timed(() => { + sql.transactional(() => { + const folderIds: string[] = []; - const now = new Date().toISOString().replace("T", " ").replace("Z", "+0000"); + // Create folders under root + for (let f = 0; f < FOLDER_COUNT; f++) { + const noteId = `seed${randomId(8)}`; + const branchId = `seed${randomId(8)}`; + const blobId = `seed${randomId(16)}`; + folderIds.push(noteId); - console.log(`\n ──── ${cfg.label} ────`); - console.log(` Seeding ${TOTAL_NOTES} notes (${matchCount} with keyword)...`); + sql.execute( + `INSERT INTO blobs (blobId, content, dateModified, utcDateModified) VALUES (?, ?, ?, ?)`, + [blobId, `

Folder ${f}

`, now, now] + ); + sql.execute( + `INSERT INTO notes (noteId, title, type, mime, blobId, isProtected, isDeleted, + dateCreated, dateModified, utcDateCreated, utcDateModified) + VALUES (?, ?, 'text', 'text/html', ?, 0, 0, ?, ?, ?, ?)`, + [noteId, `Folder ${f} ${randomWord(5)}`, blobId, now, now, now, now] + ); + sql.execute( + `INSERT INTO branches (branchId, noteId, parentNoteId, notePosition, isDeleted, isExpanded, utcDateModified) + VALUES (?, ?, 'root', ?, 0, 0, ?)`, + [branchId, noteId, f * 10, now] + ); + } - const [, seedMs] = timed(() => { - sql.transactional(() => { - for (let i = 0; i < TOTAL_NOTES; i++) { - const isMatch = i < matchCount; + // Create notes under folders + let noteIdx = 0; + for (let f = 0; f < FOLDER_COUNT; f++) { + const parentId = folderIds[f]; + for (let n = 0; n < NOTES_PER_FOLDER; n++) { + const isMatch = noteIdx < TOTAL_NOTES * MATCH_FRACTION; const noteId = `seed${randomId(8)}`; const branchId = `seed${randomId(8)}`; const blobId = `seed${randomId(16)}`; const title = isMatch - ? `Performance Doc ${i} ${randomWord(6)}` - : `General Note ${i} ${randomWord(6)} ${randomWord(5)}`; - const content = generateContent( - CONTENT_WORDS, - isMatch ? "performance" : undefined - ); + ? `Test Document ${noteIdx} ${randomWord(6)}` + : `Note ${noteIdx} ${randomWord(6)} ${randomWord(5)}`; + const content = generateContent(CONTENT_WORDS, isMatch ? "test" : undefined); sql.execute( - `INSERT INTO blobs (blobId, content, dateModified, utcDateModified) - VALUES (?, ?, ?, ?)`, + `INSERT INTO blobs (blobId, content, dateModified, utcDateModified) VALUES (?, ?, ?, ?)`, [blobId, content, now, now] ); - sql.execute( `INSERT INTO notes (noteId, title, type, mime, blobId, isProtected, isDeleted, dateCreated, dateModified, utcDateCreated, utcDateModified) VALUES (?, ?, 'text', 'text/html', ?, 0, 0, ?, ?, ?, ?)`, [noteId, title, blobId, now, now, now, now] ); - sql.execute( - `INSERT INTO branches (branchId, noteId, parentNoteId, notePosition, isDeleted, isExpanded, - utcDateModified) - VALUES (?, ?, 'root', ?, 0, 0, ?)`, - [branchId, noteId, i * 10, now] + `INSERT INTO branches (branchId, noteId, parentNoteId, notePosition, isDeleted, isExpanded, utcDateModified) + VALUES (?, ?, ?, ?, 0, 0, ?)`, + [branchId, noteId, parentId, n * 10, now] ); + noteIdx++; } - }); - }); - console.log(` SQL seeding: ${seedMs.toFixed(0)}ms`); - - // Reload becca to pick up new notes - const [, reloadMs] = timed(() => { - beccaLoader.load(); - }); - console.log(` Becca reload: ${reloadMs.toFixed(0)}ms`); - console.log(` Becca notes after seed: ${Object.keys(becca.notes).length}`); - - // Verify content is accessible - const sampleNote = Object.values(becca.notes).find(n => n.title.startsWith("Performance Doc")); - if (sampleNote) { - const content = sampleNote.getContent(); - console.log(` Sample content length: ${typeof content === 'string' ? content.length : 0} chars`); - } - - // ========================================== - // PROFILING - // ========================================== - - console.log(`\n --- PROFILING (${cfg.label}) ---\n`); - - // --- 1. Fast search (NoteFlatTextExp only) --- - searchService.findResultsWithQuery("performance", new SearchContext({ fastSearch: true })); - - const fastTimes: number[] = []; - let fastResultCount = 0; - for (let i = 0; i < 5; i++) { - const [r, ms] = timed(() => - searchService.findResultsWithQuery("performance", - new SearchContext({ fastSearch: true }) - ) - ); - fastTimes.push(ms); - fastResultCount = r.length; - } - const fastAvg = fastTimes.reduce((a, b) => a + b, 0) / fastTimes.length; - console.log(` Fast search (flat text only): avg ${fastAvg.toFixed(1)}ms (${fastResultCount} results)`); - - // --- 2. Full search (flat text + content fulltext via SQL) --- - const fullTimes: number[] = []; - let fullResultCount = 0; - for (let i = 0; i < 3; i++) { - const [r, ms] = timed(() => - searchService.findResultsWithQuery("performance", - new SearchContext({ fastSearch: false }) - ) - ); - fullTimes.push(ms); - fullResultCount = r.length; - } - const fullAvg = fullTimes.reduce((a, b) => a + b, 0) / fullTimes.length; - console.log(` Full search (flat + SQL content): avg ${fullAvg.toFixed(1)}ms (${fullResultCount} results)`); - - // --- 3. Content snippet extraction --- - const fastResults = searchService.findResultsWithQuery("performance", - new SearchContext({ fastSearch: true })); - const trimmed = fastResults.slice(0, 200); - const tokens = ["performance"]; - - const snippetTimes: number[] = []; - for (let i = 0; i < 3; i++) { - const [, ms] = timed(() => { - for (const r of trimmed) { - r.contentSnippet = searchService.extractContentSnippet(r.noteId, tokens); - } - }); - snippetTimes.push(ms); - } - const snippetAvg = snippetTimes.reduce((a, b) => a + b, 0) / snippetTimes.length; - console.log(` Content snippet (${trimmed.length} results): avg ${snippetAvg.toFixed(1)}ms (${(snippetAvg / trimmed.length).toFixed(3)}ms/note)`); - - // --- 4. Raw getContent() cost --- - const contentTimes: number[] = []; - const textNotes = trimmed - .map(r => becca.notes[r.noteId]) - .filter(n => n && ["text", "code"].includes(n.type)); - - for (let i = 0; i < 5; i++) { - const [, ms] = timed(() => { - for (const n of textNotes) n.getContent(); - }); - contentTimes.push(ms); - } - const contentAvg = contentTimes.reduce((a, b) => a + b, 0) / contentTimes.length; - console.log(` getContent() × ${textNotes.length} notes: avg ${contentAvg.toFixed(1)}ms (${(contentAvg / textNotes.length).toFixed(3)}ms/note)`); - - // --- 5. striptags + normalize cost (isolated) --- - const striptags = require("striptags"); - const normalizeString = require("normalize-strings"); - const contents = textNotes.map(n => n.getContent() as string).filter(Boolean); - - const [, stripMs] = timed(() => { - for (const c of contents) { - striptags(c); } }); - console.log(` striptags × ${contents.length} notes: ${stripMs.toFixed(1)}ms (${(stripMs / contents.length).toFixed(3)}ms/note)`); + }); + console.log(` SQL seeding: ${seedMs.toFixed(0)}ms`); - const stripped = contents.map(c => striptags(c)); - const [, normMs] = timed(() => { - for (const s of stripped) { - normalizeString(s.toLowerCase()); - } - }); - console.log(` normalizeString × ${stripped.length} notes: ${normMs.toFixed(1)}ms (${(normMs / stripped.length).toFixed(3)}ms/note)`); + const [, reloadMs] = timed(() => beccaLoader.load()); + const totalNotes = Object.keys(becca.notes).length; + console.log(` Becca reload: ${reloadMs.toFixed(0)}ms Total notes: ${totalNotes}`); - // --- 6. Full autocomplete --- - const autoTimes: number[] = []; - let autoResultCount = 0; - for (let i = 0; i < 3; i++) { - const [r, ms] = timed(() => - searchService.searchNotesForAutocomplete("performance", true) - ); - autoTimes.push(ms); - autoResultCount = r.length; + // ── Warm caches ── + searchService.searchNotesForAutocomplete("test", true); + + // ════════════════════════════════════════════ + // PROFILING AT SCALE + // ════════════════════════════════════════════ + + console.log(`\n ════ PROFILING (${totalNotes} notes) ════\n`); + + // 1. getCandidateNotes cost (the full-scan bottleneck) + const allNotes = Object.values(becca.notes); + const [, flatScanMs] = timed(() => { + let count = 0; + for (const note of allNotes) { + const ft = note.getFlatText(); + if (ft.includes("test")) count++; } - const autoAvg = autoTimes.reduce((a, b) => a + b, 0) / autoTimes.length; - console.log(`\n FULL AUTOCOMPLETE: avg ${autoAvg.toFixed(1)}ms (${autoResultCount} results)`); + return count; + }); + console.log(` getFlatText + includes scan (${allNotes.length} notes): ${flatScanMs.toFixed(1)}ms`); - // --- 7. SQL content scan cost --- - const [scanCount, scanMs] = timed(() => { - let count = 0; - for (const row of sql.iterateRows<{ content: Buffer | string }>(` - SELECT noteId, type, mime, content, isProtected - FROM notes JOIN blobs USING (blobId) - WHERE type IN ('text', 'code', 'mermaid', 'canvas', 'mindMap') - AND isDeleted = 0 - AND LENGTH(content) < 2097152`)) { - count++; - } - return count; - }); - console.log(` SQL content scan (${scanCount} rows): ${scanMs.toFixed(1)}ms`); - - // --- Summary --- - console.log(`\n === SUMMARY (${cfg.label}, ${Object.keys(becca.notes).length} total notes) ===`); - console.log(` Fast search: ${fastAvg.toFixed(1)}ms`); - console.log(` Full search: ${fullAvg.toFixed(1)}ms`); - console.log(` Content snippets: ${snippetAvg.toFixed(1)}ms (${(snippetAvg / trimmed.length).toFixed(3)}ms/note)`); - console.log(` normalizeString: ${normMs.toFixed(1)}ms (${(normMs / stripped.length).toFixed(3)}ms/note)`); - console.log(` Full autocomplete: ${autoAvg.toFixed(1)}ms`); - console.log(` SQL scan: ${scanMs.toFixed(1)}ms (${scanCount} rows)`); + // 2. Full findResultsWithQuery (includes candidate scan + parent walk + scoring) + const findTimes: number[] = []; + let findResultCount = 0; + for (let i = 0; i < 3; i++) { + const [r, ms] = timed(() => + searchService.findResultsWithQuery("test", new SearchContext({ fastSearch: true })) + ); + findTimes.push(ms); + findResultCount = r.length; } + const findAvg = findTimes.reduce((a, b) => a + b, 0) / findTimes.length; + console.log(` findResultsWithQuery (fast): avg ${findAvg.toFixed(1)}ms (${findResultCount} results)`); + + // 3. Exact-only (no fuzzy) + const exactTimes: number[] = []; + for (let i = 0; i < 3; i++) { + const [, ms] = timed(() => + searchService.findResultsWithQuery("test", new SearchContext({ fastSearch: true, enableFuzzyMatching: false })) + ); + exactTimes.push(ms); + } + const exactAvg = exactTimes.reduce((a, b) => a + b, 0) / exactTimes.length; + console.log(` findResultsWithQuery (exact): avg ${exactAvg.toFixed(1)}ms`); + console.log(` Fuzzy overhead: ${(findAvg - exactAvg).toFixed(1)}ms`); + + // 4. SearchResult construction + computeScore cost (isolated) + const results = searchService.findResultsWithQuery("test", new SearchContext({ fastSearch: true })); + console.log(` Total results before trim: ${results.length}`); + + const [, scoreAllMs] = timed(() => { + for (const r of results) r.computeScore("test", ["test"], true); + }); + console.log(` computeScore × ${results.length}: ${scoreAllMs.toFixed(1)}ms (${(scoreAllMs / results.length).toFixed(3)}ms/result)`); + + // 5. getNoteTitleForPath for all results + const [, pathTitleMs] = timed(() => { + for (const r of results) beccaService.getNoteTitleForPath(r.notePathArray); + }); + console.log(` getNoteTitleForPath × ${results.length}: ${pathTitleMs.toFixed(1)}ms`); + + // 6. Content snippet extraction (only 200) + const trimmed = results.slice(0, 200); + const [, snippetMs] = timed(() => { + for (const r of trimmed) { + r.contentSnippet = searchService.extractContentSnippet(r.noteId, ["test"]); + } + }); + console.log(` extractContentSnippet × 200: ${snippetMs.toFixed(1)}ms`); + + // 7. Highlighting (only 200) + const [, hlMs] = timed(() => { + searchService.highlightSearchResults(trimmed, ["test"]); + }); + console.log(` highlightSearchResults × 200: ${hlMs.toFixed(1)}ms`); + + // 7b. getBestNotePath cost (used by fast path) + const sampleNotes = Object.values(becca.notes).filter(n => n.title.startsWith("Test Document")).slice(0, 1000); + const [, bestPathMs] = timed(() => { + for (const n of sampleNotes) n.getBestNotePath(); + }); + console.log(` getBestNotePath × ${sampleNotes.length}: ${bestPathMs.toFixed(1)}ms (${(bestPathMs/sampleNotes.length).toFixed(3)}ms/note)`); + + // 8. Full autocomplete end-to-end + const autoTimes: number[] = []; + let autoCount = 0; + for (let i = 0; i < 3; i++) { + const [r, ms] = timed(() => + searchService.searchNotesForAutocomplete("test", true) + ); + autoTimes.push(ms); + autoCount = r.length; + } + const autoAvg = autoTimes.reduce((a, b) => a + b, 0) / autoTimes.length; + const autoMin = Math.min(...autoTimes); + console.log(`\n ★ FULL AUTOCOMPLETE: avg ${autoAvg.toFixed(1)}ms min ${autoMin.toFixed(1)}ms (${autoCount} results)`); + + // 9. With a less common search term (fewer matches) + const rareTimes: number[] = []; + let rareCount = 0; + for (let i = 0; i < 3; i++) { + const [r, ms] = timed(() => + searchService.searchNotesForAutocomplete("leitfaden", true) + ); + rareTimes.push(ms); + rareCount = r.length; + } + const rareAvg = rareTimes.reduce((a, b) => a + b, 0) / rareTimes.length; + console.log(` Autocomplete "leitfaden": avg ${rareAvg.toFixed(1)}ms (${rareCount} results)`); + + // 10. Full search (fastSearch=false) — the 2.7s bottleneck + console.log(`\n ── Full search (fastSearch=false) ──`); + const fullTimes: number[] = []; + let fullCount = 0; + for (let i = 0; i < 2; i++) { + const [r, ms] = timed(() => + searchService.findResultsWithQuery("test", new SearchContext({ fastSearch: false })) + ); + fullTimes.push(ms); + fullCount = r.length; + } + const fullAvg = fullTimes.reduce((a, b) => a + b, 0) / fullTimes.length; + console.log(` Full search (flat + SQL): avg ${fullAvg.toFixed(1)}ms (${fullCount} results)`); + + // 11. SQL content scan alone + const [scanCount, scanMs] = timed(() => { + let count = 0; + for (const row of sql.iterateRows<{ content: Buffer | string }>(` + SELECT noteId, type, mime, content, isProtected + FROM notes JOIN blobs USING (blobId) + WHERE type IN ('text', 'code', 'mermaid', 'canvas', 'mindMap') + AND isDeleted = 0 + AND LENGTH(content) < 2097152`)) { + count++; + } + return count; + }); + console.log(` Raw SQL scan (${scanCount} rows): ${scanMs.toFixed(1)}ms`); + + // ── Summary ── + console.log(`\n ════ SUMMARY ════`); + console.log(` Notes: ${totalNotes} | Matches: ${findResultCount} | Hierarchy depth: 3 (root → folder → note)`); + console.log(` ──────────────────────────────────`); + console.log(` Autocomplete (fast): ${autoAvg.toFixed(1)}ms`); + console.log(` findResults: ${findAvg.toFixed(1)}ms (${((findAvg/autoAvg)*100).toFixed(0)}%)`); + console.log(` snippets+highlight: ${(snippetMs + hlMs).toFixed(1)}ms (${(((snippetMs+hlMs)/autoAvg)*100).toFixed(0)}%)`); + console.log(` Full search: ${fullAvg.toFixed(1)}ms`); resolve(); }); diff --git a/apps/server/src/becca/becca-interface.ts b/apps/server/src/becca/becca-interface.ts index 1a8203f436..6619ed30b9 100644 --- a/apps/server/src/becca/becca-interface.ts +++ b/apps/server/src/becca/becca-interface.ts @@ -31,9 +31,17 @@ export default class Becca { allNoteSetCache: NoteSet | null; + /** + * Pre-built parallel arrays for fast flat text scanning in search. + * Avoids per-note property access overhead when iterating 50K+ notes. + * Dirtied when notes change (along with allNoteSetCache). + */ + flatTextIndex: { notes: BNote[], flatTexts: string[] } | null; + constructor() { this.reset(); this.allNoteSetCache = null; + this.flatTextIndex = null; } reset() { @@ -239,6 +247,28 @@ export default class Becca { /** Should be called when the set of all non-skeleton notes changes (added/removed) */ dirtyNoteSetCache() { this.allNoteSetCache = null; + this.flatTextIndex = null; + } + + /** + * Returns pre-built parallel arrays of notes and their flat texts for fast scanning. + * The flat texts are already normalized (lowercase, diacritics removed). + */ + getFlatTextIndex(): { notes: BNote[], flatTexts: string[] } { + if (!this.flatTextIndex) { + const allNoteSet = this.getAllNoteSet(); + const notes: BNote[] = []; + const flatTexts: string[] = []; + + for (const note of allNoteSet.notes) { + notes.push(note); + flatTexts.push(note.getFlatText()); + } + + this.flatTextIndex = { notes, flatTexts }; + } + + return this.flatTextIndex; } getAllNoteSet() { diff --git a/apps/server/src/becca/entities/bnote.ts b/apps/server/src/becca/entities/bnote.ts index 112543a603..4e78974b4e 100644 --- a/apps/server/src/becca/entities/bnote.ts +++ b/apps/server/src/becca/entities/bnote.ts @@ -790,6 +790,9 @@ class BNote extends AbstractBeccaEntity { this.__attributeCache = null; this.__inheritableAttributeCache = null; this.__ancestorCache = null; + + // Dirty the becca-level flat text index since this note's flat text may have changed + this.becca.flatTextIndex = null; } invalidateSubTree(path: string[] = []) { diff --git a/apps/server/src/services/search/expressions/note_flat_text.ts b/apps/server/src/services/search/expressions/note_flat_text.ts index b9ad19c36c..93213d164e 100644 --- a/apps/server/src/services/search/expressions/note_flat_text.ts +++ b/apps/server/src/services/search/expressions/note_flat_text.ts @@ -99,6 +99,22 @@ class NoteFlatTextExp extends Expression { const candidateNotes = this.getCandidateNotes(inputNoteSet, searchContext); + // Fast path for single-token searches with a limit (e.g. autocomplete): + // Skip the expensive recursive parent walk and just use getBestNotePath(). + // The flat text already matched, so we know the token is present. + if (this.tokens.length === 1 && searchContext.limit) { + for (const note of candidateNotes) { + if (!resultNoteSet.hasNoteId(note.noteId)) { + const notePath = note.getBestNotePath(); + if (notePath) { + executionContext.noteIdToNotePath[note.noteId] = notePath; + resultNoteSet.add(note); + } + } + } + return resultNoteSet; + } + for (const note of candidateNotes) { // autocomplete should be able to find notes by their noteIds as well (only leafs) if (this.tokens.length === 1 && note.noteId.toLowerCase() === this.tokens[0]) { @@ -112,7 +128,7 @@ class NoteFlatTextExp extends Expression { // Add defensive checks for undefined properties const typeMatches = note.type && note.type.includes(token); const mimeMatches = note.mime && note.mime.includes(token); - + if (typeMatches || mimeMatches) { foundAttrTokens.push(token); } @@ -165,14 +181,38 @@ class NoteFlatTextExp extends Expression { getCandidateNotes(noteSet: NoteSet, searchContext?: SearchContext): BNote[] { const candidateNotes: BNote[] = []; - for (const note of noteSet.notes) { - const normalizedFlatText = normalizeSearchText(note.getFlatText()); + // For limited searches (e.g. autocomplete), cap candidates to avoid + // processing thousands of matches when only a few hundred are needed. + // Use 5x the limit to ensure enough quality candidates for scoring. + const maxCandidates = searchContext?.limit ? searchContext.limit * 5 : Infinity; + + // Use the pre-built flat text index for fast scanning. + // This provides pre-computed flat texts in a parallel array, avoiding + // per-note property access overhead at large scale (50K+ notes). + const { notes: indexNotes, flatTexts } = becca.getFlatTextIndex(); + + // Build a set for quick membership check when noteSet isn't the full set + const isFullSet = noteSet.notes.length === indexNotes.length; + + for (let i = 0; i < indexNotes.length; i++) { + const note = indexNotes[i]; + + // Skip notes not in the input set (only check when not using the full set) + if (!isFullSet && !noteSet.hasNoteId(note.noteId)) { + continue; + } + + const flatText = flatTexts[i]; for (const token of this.tokens) { - if (this.smartMatch(normalizedFlatText, token, searchContext)) { + if (this.smartMatch(flatText, token, searchContext)) { candidateNotes.push(note); break; } } + + if (candidateNotes.length >= maxCandidates) { + break; + } } return candidateNotes; diff --git a/apps/server/src/services/search/services/search.ts b/apps/server/src/services/search/services/search.ts index 4701964f5b..7ee3e494f4 100644 --- a/apps/server/src/services/search/services/search.ts +++ b/apps/server/src/services/search/services/search.ts @@ -16,7 +16,6 @@ import type { SearchParams, TokenStructure } from "./types.js"; import type Expression from "../expressions/expression.js"; import sql from "../../sql.js"; import scriptService from "../../script.js"; -import striptags from "striptags"; import protectedSessionService from "../../protected_session.js"; export interface SearchNoteResult { @@ -249,23 +248,30 @@ function findResultsWithExpression(expression: Expression, searchContext: Search return performSearch(expression, searchContext, false); } + // For limited searches (e.g. autocomplete), skip the expensive two-phase + // fuzzy fallback. The user is typing and will refine their query — exact + // matching is sufficient and avoids a second full scan of all notes. + if (searchContext.limit) { + return performSearch(expression, searchContext, false); + } + // Phase 1: Try exact matches first (without fuzzy matching) const exactResults = performSearch(expression, searchContext, false); - + // Check if we have sufficient high-quality results const minResultThreshold = 5; const minScoreForQuality = 10; // Minimum score to consider a result "high quality" - + const highQualityResults = exactResults.filter(result => result.score >= minScoreForQuality); - + // If we have enough high-quality exact matches, return them if (highQualityResults.length >= minResultThreshold) { return exactResults; } - + // Phase 2: Add fuzzy matching as fallback when exact matches are insufficient const fuzzyResults = performSearch(expression, searchContext, true); - + // Merge results, ensuring exact matches always rank higher than fuzzy matches return mergeExactAndFuzzyResults(exactResults, fuzzyResults); } @@ -447,7 +453,7 @@ function extractContentSnippet(noteId: string, searchTokens: string[], maxLength try { let content = note.getContent(); - + if (!content || typeof content !== "string") { return ""; } @@ -463,77 +469,66 @@ function extractContentSnippet(noteId: string, searchTokens: string[], maxLength return ""; // Protected but no session available } - // Strip HTML tags for text notes + // Strip HTML tags for text notes — use fast regex for snippet extraction + // (striptags library is ~18x slower and not needed for search snippets) if (note.type === "text") { - content = striptags(content); + content = content.replace(/<[^>]*>/g, ""); } - // Normalize whitespace while preserving paragraph breaks - // First, normalize multiple newlines to double newlines (paragraph breaks) - content = content.replace(/\n\s*\n/g, "\n\n"); - // Then normalize spaces within lines - content = content.split('\n').map(line => line.replace(/\s+/g, " ").trim()).join('\n'); - // Finally trim the whole content - content = content.trim(); - if (!content) { return ""; } - // Try to find a snippet around the first matching token + // Find match position using normalize on the raw stripped content. + // We use a single normalize() pass — no need for expensive whitespace + // normalization just to find the match index. const normalizedContent = normalize(content); + const normalizedTokens = searchTokens.map(token => normalize(token)); let snippetStart = 0; - let matchFound = false; - for (const token of searchTokens) { - const normalizedToken = normalize(token); + for (const normalizedToken of normalizedTokens) { const matchIndex = normalizedContent.indexOf(normalizedToken); - + if (matchIndex !== -1) { // Center the snippet around the match snippetStart = Math.max(0, matchIndex - maxLength / 2); - matchFound = true; break; } } - // Extract snippet - let snippet = content.substring(snippetStart, snippetStart + maxLength); + // Extract a snippet region from the raw content, then clean only that + const snippetRegion = content.substring(snippetStart, snippetStart + maxLength + 100); - // If snippet contains linebreaks, limit to max 4 lines and override character limit + // Normalize whitespace only on the small snippet region + let snippet = snippetRegion + .replace(/\n\s*\n/g, "\n\n") + .replace(/[ \t]+/g, " ") + .trim() + .substring(0, maxLength); + + // If snippet contains linebreaks, limit to max 4 lines const lines = snippet.split('\n'); if (lines.length > 4) { - // Find which lines contain the search tokens to ensure they're included - const normalizedLines = lines.map(line => normalize(line)); - const normalizedTokens = searchTokens.map(token => normalize(token)); - // Find the first line that contains a search token let firstMatchLine = -1; - for (let i = 0; i < normalizedLines.length; i++) { - if (normalizedTokens.some(token => normalizedLines[i].includes(token))) { + for (let i = 0; i < lines.length; i++) { + const normalizedLine = normalize(lines[i]); + if (normalizedTokens.some(token => normalizedLine.includes(token))) { firstMatchLine = i; break; } } if (firstMatchLine !== -1) { - // Center the 4-line window around the first match - // Try to show 1 line before and 2 lines after the match const startLine = Math.max(0, firstMatchLine - 1); const endLine = Math.min(lines.length, startLine + 4); snippet = lines.slice(startLine, endLine).join('\n'); } else { - // No match found in lines (shouldn't happen), just take first 4 snippet = lines.slice(0, 4).join('\n'); } - // Add ellipsis if we truncated lines snippet = snippet + "..."; - } else if (lines.length > 1) { - // For multi-line snippets that are 4 or fewer lines, keep them as-is - // No need to truncate - } else { - // Single line content - apply original word boundary logic - // Try to start/end at word boundaries + } else if (lines.length <= 1) { + // Single line content - apply word boundary logic if (snippetStart > 0) { const firstSpace = snippet.search(/\s/); if (firstSpace > 0 && firstSpace < 20) { @@ -541,7 +536,7 @@ function extractContentSnippet(noteId: string, searchTokens: string[], maxLength } snippet = "..." + snippet; } - + if (snippetStart + maxLength < content.length) { const lastSpace = snippet.search(/\s[^\s]*$/); if (lastSpace > snippet.length - 20 && lastSpace > 0) { @@ -649,7 +644,8 @@ function searchNotesForAutocomplete(query: string, fastSearch: boolean = true) { includeHiddenNotes: true, fuzzyAttributeSearch: true, ignoreInternalAttributes: true, - ancestorNoteId: hoistedNoteService.isHoistedInHiddenSubtree() ? "root" : hoistedNoteService.getHoistedNoteId() + ancestorNoteId: hoistedNoteService.isHoistedInHiddenSubtree() ? "root" : hoistedNoteService.getHoistedNoteId(), + limit: 200 }); const allSearchResults = findResultsWithQuery(query, searchContext); From 6a06fc79956914f1b437dd5131886ccaa14fb60c Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Thu, 12 Mar 2026 14:02:23 -0700 Subject: [PATCH 003/482] feat(search): get rid of candidate capping --- .../src/services/search/expressions/note_flat_text.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/apps/server/src/services/search/expressions/note_flat_text.ts b/apps/server/src/services/search/expressions/note_flat_text.ts index 93213d164e..eff3622a76 100644 --- a/apps/server/src/services/search/expressions/note_flat_text.ts +++ b/apps/server/src/services/search/expressions/note_flat_text.ts @@ -181,11 +181,6 @@ class NoteFlatTextExp extends Expression { getCandidateNotes(noteSet: NoteSet, searchContext?: SearchContext): BNote[] { const candidateNotes: BNote[] = []; - // For limited searches (e.g. autocomplete), cap candidates to avoid - // processing thousands of matches when only a few hundred are needed. - // Use 5x the limit to ensure enough quality candidates for scoring. - const maxCandidates = searchContext?.limit ? searchContext.limit * 5 : Infinity; - // Use the pre-built flat text index for fast scanning. // This provides pre-computed flat texts in a parallel array, avoiding // per-note property access overhead at large scale (50K+ notes). @@ -210,10 +205,7 @@ class NoteFlatTextExp extends Expression { } } - if (candidateNotes.length >= maxCandidates) { - break; - } - } +} return candidateNotes; } From 9403efa9a1a99be6afe365eaf4fff1859555a760 Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Thu, 12 Mar 2026 14:21:36 -0700 Subject: [PATCH 004/482] feat(search): add even some more robust tests --- .../search/services/search_profiling.spec.ts | 151 +++++++++++++++++- 1 file changed, 145 insertions(+), 6 deletions(-) diff --git a/apps/server/src/services/search/services/search_profiling.spec.ts b/apps/server/src/services/search/services/search_profiling.spec.ts index 96a414b257..6ed5d9fbb7 100644 --- a/apps/server/src/services/search/services/search_profiling.spec.ts +++ b/apps/server/src/services/search/services/search_profiling.spec.ts @@ -33,9 +33,10 @@ function randomWord(len = 6): string { return word; } -function generateHtmlContent(wordCount: number, includeTarget = false): string { +function generateHtmlContent(wordCount: number, includeKeywords = false, keywords?: string[]): string { const paragraphs: string[] = []; let wordsRemaining = wordCount; + const kws = keywords ?? ["target"]; while (wordsRemaining > 0) { const paraWords = Math.min(wordsRemaining, 20 + Math.floor(Math.random() * 40)); @@ -43,8 +44,12 @@ function generateHtmlContent(wordCount: number, includeTarget = false): string { for (let i = 0; i < paraWords; i++) { words.push(randomWord(3 + Math.floor(Math.random() * 10))); } - if (includeTarget && paragraphs.length === 2) { - words[Math.floor(words.length / 2)] = "target"; + if (includeKeywords && paragraphs.length === 2) { + // Inject all keywords into the paragraph at spaced positions + for (let k = 0; k < kws.length; k++) { + const pos = Math.min(words.length - 1, Math.floor((words.length / (kws.length + 1)) * (k + 1))); + words[pos] = kws[k]; + } } paragraphs.push(`

${words.join(" ")}

`); wordsRemaining -= paraWords; @@ -80,12 +85,21 @@ function buildDataset(noteCount: number, opts: { labelsPerNote?: number; depth?: number; contentWordCount?: number; + /** When set, contentWordCount is treated as a median and actual sizes vary from 0.2x to 3x */ + varyContentSize?: boolean; + /** Keywords to inject into matching notes' titles (default: ["target"]) */ + titleKeywords?: string[]; + /** Keywords to inject into matching notes' content (default: same as titleKeywords) */ + contentKeywords?: string[]; } = {}) { const { matchFraction = 0.1, labelsPerNote = 3, depth = 3, contentWordCount = 200, + varyContentSize = false, + titleKeywords = ["target"], + contentKeywords = titleKeywords, } = opts; becca.reset(); @@ -115,18 +129,39 @@ function buildDataset(noteCount: number, opts: { for (let i = 0; i < noteCount; i++) { const isMatch = i < matchCount; const title = isMatch - ? `${randomWord(5)} target ${randomWord(5)} Document ${i}` + ? `${randomWord(5)} ${titleKeywords.join(" ")} ${randomWord(5)} Document ${i}` : `${randomWord(5)} ${randomWord(6)} ${randomWord(4)} Note ${i}`; const n = note(title); for (let l = 0; l < labelsPerNote; l++) { const labelName = isMatch && l === 0 ? "category" : `label_${randomWord(4)}`; - const labelValue = isMatch && l === 0 ? "important target" : randomWord(8); + const labelValue = isMatch && l === 0 ? `important ${titleKeywords[0]}` : randomWord(8); n.label(labelName, labelValue); } - syntheticContent[n.note.noteId] = generateHtmlContent(contentWordCount, isMatch); + // Vary content size: 0.2x to 3x the median, producing a realistic + // mix of short stubs, medium notes, and long documents. + let noteWordCount = contentWordCount; + if (varyContentSize) { + const r = Math.random(); + if (r < 0.2) { + noteWordCount = Math.floor(contentWordCount * (0.2 + Math.random() * 0.3)); // 20-50% (short stubs) + } else if (r < 0.7) { + noteWordCount = Math.floor(contentWordCount * (0.7 + Math.random() * 0.6)); // 70-130% (medium) + } else if (r < 0.9) { + noteWordCount = Math.floor(contentWordCount * (1.3 + Math.random() * 0.7)); // 130-200% (long) + } else { + noteWordCount = Math.floor(contentWordCount * (2.0 + Math.random() * 1.0)); // 200-300% (very long) + } + } + + const includeContentKeyword = isMatch && contentKeywords.length > 0; + syntheticContent[n.note.noteId] = generateHtmlContent( + noteWordCount, + includeContentKeyword, + includeContentKeyword ? contentKeywords : undefined + ); const containerIndex = i % containers.length; containers[containerIndex].child(n); @@ -451,6 +486,110 @@ describe("Search Profiling", () => { /** * End-to-end scaling to give the full picture. */ + /** + * Multi-token search with varying content sizes. + * Real users search things like "meeting notes january" — this exercises + * the multi-token path (which doesn't use the single-token fast path) + * with a realistic mix of note sizes. + */ + describe("Multi-token search with varying content sizes", () => { + + it("single vs multi-token autocomplete at scale", () => { + console.log("\n=== Single vs multi-token autocomplete (varying content sizes) ==="); + + for (const noteCount of [1000, 5000, 10000, 20000]) { + buildDataset(noteCount, { + matchFraction: 0.15, + contentWordCount: 400, + varyContentSize: true, + depth: 5, + titleKeywords: ["meeting", "notes", "january"], + contentKeywords: ["meeting", "notes", "january"], + }); + + // Warm up + searchService.searchNotesForAutocomplete("meeting", true); + + // Single token + const singleTimes: number[] = []; + for (let i = 0; i < 3; i++) { + const [, ms] = timed(() => searchService.searchNotesForAutocomplete("meeting", true)); + singleTimes.push(ms); + } + const singleAvg = singleTimes.reduce((a, b) => a + b, 0) / singleTimes.length; + + // Two tokens + const twoTimes: number[] = []; + for (let i = 0; i < 3; i++) { + const [, ms] = timed(() => searchService.searchNotesForAutocomplete("meeting notes", true)); + twoTimes.push(ms); + } + const twoAvg = twoTimes.reduce((a, b) => a + b, 0) / twoTimes.length; + + // Three tokens + const threeTimes: number[] = []; + for (let i = 0; i < 3; i++) { + const [, ms] = timed(() => searchService.searchNotesForAutocomplete("meeting notes january", true)); + threeTimes.push(ms); + } + const threeAvg = threeTimes.reduce((a, b) => a + b, 0) / threeTimes.length; + + console.log( + ` ${String(noteCount).padStart(6)} notes: ` + + `1-token ${singleAvg.toFixed(1)}ms ` + + `2-token ${twoAvg.toFixed(1)}ms ` + + `3-token ${threeAvg.toFixed(1)}ms` + ); + } + }); + + it("multi-token with realistic content size distribution", () => { + console.log("\n=== Multi-token search — content size distribution ==="); + + buildDataset(5000, { + matchFraction: 0.15, + contentWordCount: 400, + varyContentSize: true, + depth: 5, + titleKeywords: ["project", "review"], + contentKeywords: ["project", "review"], + }); + + // Report the actual content size distribution + const sizes = Object.values(syntheticContent).map(c => c.length); + sizes.sort((a, b) => a - b); + const p10 = sizes[Math.floor(sizes.length * 0.1)]; + const p50 = sizes[Math.floor(sizes.length * 0.5)]; + const p90 = sizes[Math.floor(sizes.length * 0.9)]; + const p99 = sizes[Math.floor(sizes.length * 0.99)]; + console.log(` Content sizes: p10=${p10} p50=${p50} p90=${p90} p99=${p99} chars`); + + // Warm up + searchService.searchNotesForAutocomplete("project", true); + + const queries = [ + "project", + "project review", + "project review document", + `${randomWord(7)}`, // no-match single token + `${randomWord(5)} ${randomWord(6)}`, // no-match multi token + ]; + + for (const query of queries) { + const times: number[] = []; + let resultCount = 0; + for (let i = 0; i < 3; i++) { + const [r, ms] = timed(() => searchService.searchNotesForAutocomplete(query, true)); + times.push(ms); + resultCount = r.length; + } + const avg = times.reduce((a, b) => a + b, 0) / times.length; + const label = `"${query}"`.padEnd(35); + console.log(` ${label} ${avg.toFixed(1)}ms (${resultCount} results)`); + } + }); + }); + describe("End-to-end scaling", () => { it("autocomplete at different scales", () => { From 1c148f407cc8c397374b87575c984c15f0fae1da Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Thu, 12 Mar 2026 14:35:17 -0700 Subject: [PATCH 005/482] feat(search): don't toss the entire index after each note change --- apps/server/src/becca/becca-interface.ts | 46 +++++++++++++++++-- apps/server/src/becca/entities/battribute.ts | 10 ++++ apps/server/src/becca/entities/bnote.ts | 4 +- .../search/expressions/note_flat_text.ts | 9 ++-- 4 files changed, 56 insertions(+), 13 deletions(-) diff --git a/apps/server/src/becca/becca-interface.ts b/apps/server/src/becca/becca-interface.ts index 6619ed30b9..1a95408d9b 100644 --- a/apps/server/src/becca/becca-interface.ts +++ b/apps/server/src/becca/becca-interface.ts @@ -34,14 +34,19 @@ export default class Becca { /** * Pre-built parallel arrays for fast flat text scanning in search. * Avoids per-note property access overhead when iterating 50K+ notes. - * Dirtied when notes change (along with allNoteSetCache). + * Supports incremental updates: when individual notes change, only their + * entries are rebuilt rather than the entire index. */ - flatTextIndex: { notes: BNote[], flatTexts: string[] } | null; + flatTextIndex: { notes: BNote[], flatTexts: string[], noteIdToIdx: Map } | null; + + /** NoteIds whose flat text needs to be recomputed in the index. */ + dirtyFlatTextNoteIds: Set; constructor() { - this.reset(); + this.dirtyFlatTextNoteIds = new Set(); this.allNoteSetCache = null; this.flatTextIndex = null; + this.reset(); } reset() { @@ -247,25 +252,56 @@ export default class Becca { /** Should be called when the set of all non-skeleton notes changes (added/removed) */ dirtyNoteSetCache() { this.allNoteSetCache = null; + // Full rebuild needed since the note set itself changed this.flatTextIndex = null; + this.dirtyFlatTextNoteIds.clear(); + } + + /** Mark a single note's flat text as needing recomputation in the index. */ + dirtyNoteFlatText(noteId: string) { + if (this.flatTextIndex) { + // Index exists — schedule an incremental update + this.dirtyFlatTextNoteIds.add(noteId); + } + // If flatTextIndex is null, full rebuild will happen on next access anyway } /** * Returns pre-built parallel arrays of notes and their flat texts for fast scanning. * The flat texts are already normalized (lowercase, diacritics removed). + * Supports incremental updates: when individual notes are dirtied, only their + * entries are recomputed rather than rebuilding the entire index. */ - getFlatTextIndex(): { notes: BNote[], flatTexts: string[] } { + getFlatTextIndex(): { notes: BNote[], flatTexts: string[], noteIdToIdx: Map } { if (!this.flatTextIndex) { const allNoteSet = this.getAllNoteSet(); const notes: BNote[] = []; const flatTexts: string[] = []; + const noteIdToIdx = new Map(); for (const note of allNoteSet.notes) { + noteIdToIdx.set(note.noteId, notes.length); notes.push(note); flatTexts.push(note.getFlatText()); } - this.flatTextIndex = { notes, flatTexts }; + this.flatTextIndex = { notes, flatTexts, noteIdToIdx }; + this.dirtyFlatTextNoteIds.clear(); + } else if (this.dirtyFlatTextNoteIds.size > 0) { + // Incremental update: only recompute flat texts for dirtied notes + const { flatTexts, noteIdToIdx } = this.flatTextIndex; + + for (const noteId of this.dirtyFlatTextNoteIds) { + const idx = noteIdToIdx.get(noteId); + if (idx !== undefined) { + const note = this.notes[noteId]; + if (note) { + flatTexts[idx] = note.getFlatText(); + } + } + } + + this.dirtyFlatTextNoteIds.clear(); } return this.flatTextIndex; diff --git a/apps/server/src/becca/entities/battribute.ts b/apps/server/src/becca/entities/battribute.ts index 6ff1246fcf..77a15c2fd1 100644 --- a/apps/server/src/becca/entities/battribute.ts +++ b/apps/server/src/becca/entities/battribute.ts @@ -6,6 +6,7 @@ import dateUtils from "../../services/date_utils.js"; import promotedAttributeDefinitionParser from "../../services/promoted_attribute_definition_parser.js"; import sanitizeAttributeName from "../../services/sanitize_attribute_name.js"; import type { AttributeRow, AttributeType } from "@triliumnext/commons"; +import { normalize } from "../../services/utils.js"; interface SavingOpts { skipValidation?: boolean; @@ -34,6 +35,11 @@ class BAttribute extends AbstractBeccaEntity { value!: string; isInheritable!: boolean; + /** Pre-normalized (lowercase, diacritics removed) name for search. */ + normalizedName!: string; + /** Pre-normalized (lowercase, diacritics removed) value for search. */ + normalizedValue!: string; + constructor(row?: AttributeRow) { super(); @@ -59,6 +65,10 @@ class BAttribute extends AbstractBeccaEntity { this.isInheritable = !!isInheritable; this.utcDateModified = utcDateModified; + // Pre-compute normalized forms for search (avoids repeated normalize() calls in hot loops) + this.normalizedName = normalize(this.name); + this.normalizedValue = normalize(this.value); + return this; } diff --git a/apps/server/src/becca/entities/bnote.ts b/apps/server/src/becca/entities/bnote.ts index 4e78974b4e..10750efc32 100644 --- a/apps/server/src/becca/entities/bnote.ts +++ b/apps/server/src/becca/entities/bnote.ts @@ -791,8 +791,8 @@ class BNote extends AbstractBeccaEntity { this.__inheritableAttributeCache = null; this.__ancestorCache = null; - // Dirty the becca-level flat text index since this note's flat text may have changed - this.becca.flatTextIndex = null; + // Mark only this note's flat text as dirty for incremental index update + this.becca.dirtyNoteFlatText(this.noteId); } invalidateSubTree(path: string[] = []) { diff --git a/apps/server/src/services/search/expressions/note_flat_text.ts b/apps/server/src/services/search/expressions/note_flat_text.ts index eff3622a76..ff54287d91 100644 --- a/apps/server/src/services/search/expressions/note_flat_text.ts +++ b/apps/server/src/services/search/expressions/note_flat_text.ts @@ -7,7 +7,7 @@ import Expression from "./expression.js"; import NoteSet from "../note_set.js"; import becca from "../../../becca/becca.js"; import { normalize } from "../../utils.js"; -import { normalizeSearchText, fuzzyMatchWord, fuzzyMatchWordWithResult } from "../utils/text_utils.js"; +import { normalizeSearchText, fuzzyMatchWordWithResult } from "../utils/text_utils.js"; import beccaService from "../../../becca/becca_service.js"; class NoteFlatTextExp extends Expression { @@ -67,11 +67,8 @@ class NoteFlatTextExp extends Expression { } for (const attribute of note.getOwnedAttributes()) { - const normalizedName = normalizeSearchText(attribute.name); - const normalizedValue = normalizeSearchText(attribute.value); - for (const token of remainingTokens) { - if (normalizedName.includes(token) || normalizedValue.includes(token)) { + if (attribute.normalizedName.includes(token) || attribute.normalizedValue.includes(token)) { foundAttrTokens.push(token); } } @@ -134,7 +131,7 @@ class NoteFlatTextExp extends Expression { } for (const attribute of note.ownedAttributes) { - if (normalizeSearchText(attribute.name).includes(token) || normalizeSearchText(attribute.value).includes(token)) { + if (attribute.normalizedName.includes(token) || attribute.normalizedValue.includes(token)) { foundAttrTokens.push(token); } } From b533546236a4264d64697ae9a76fb8a9f63c25a3 Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Thu, 12 Mar 2026 14:35:47 -0700 Subject: [PATCH 006/482] fix(search): fix flying bracket --- apps/server/src/services/search/expressions/note_flat_text.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/server/src/services/search/expressions/note_flat_text.ts b/apps/server/src/services/search/expressions/note_flat_text.ts index ff54287d91..b1ceac991e 100644 --- a/apps/server/src/services/search/expressions/note_flat_text.ts +++ b/apps/server/src/services/search/expressions/note_flat_text.ts @@ -201,8 +201,7 @@ class NoteFlatTextExp extends Expression { break; } } - -} + } return candidateNotes; } From 5718631889ecb8fa01e72d2c2f374ebdc0de44a7 Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Wed, 18 Mar 2026 09:46:24 -0700 Subject: [PATCH 007/482] fix(search): resolve issue with autocomplete with search performance enhancements --- .../src/services/search/expressions/note_flat_text.ts | 4 ++-- apps/server/src/services/search/search_context.ts | 3 +++ apps/server/src/services/search/services/search.ts | 10 +++++----- apps/server/src/services/search/services/types.ts | 2 ++ 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/apps/server/src/services/search/expressions/note_flat_text.ts b/apps/server/src/services/search/expressions/note_flat_text.ts index b1ceac991e..ef3efbf66f 100644 --- a/apps/server/src/services/search/expressions/note_flat_text.ts +++ b/apps/server/src/services/search/expressions/note_flat_text.ts @@ -96,10 +96,10 @@ class NoteFlatTextExp extends Expression { const candidateNotes = this.getCandidateNotes(inputNoteSet, searchContext); - // Fast path for single-token searches with a limit (e.g. autocomplete): + // Fast path for single-token autocomplete searches: // Skip the expensive recursive parent walk and just use getBestNotePath(). // The flat text already matched, so we know the token is present. - if (this.tokens.length === 1 && searchContext.limit) { + if (this.tokens.length === 1 && searchContext.autocomplete) { for (const note of candidateNotes) { if (!resultNoteSet.hasNoteId(note.noteId)) { const notePath = note.getBestNotePath(); diff --git a/apps/server/src/services/search/search_context.ts b/apps/server/src/services/search/search_context.ts index 314c7e7ce6..55d4df5d2f 100644 --- a/apps/server/src/services/search/search_context.ts +++ b/apps/server/src/services/search/search_context.ts @@ -18,6 +18,8 @@ class SearchContext { debug?: boolean; debugInfo: {} | null; fuzzyAttributeSearch: boolean; + /** When true, skip the two-phase fuzzy fallback and use the single-token fast path. */ + autocomplete: boolean; enableFuzzyMatching: boolean; // Controls whether fuzzy matching is enabled for this search phase highlightedTokens: string[]; originalQuery: string; @@ -46,6 +48,7 @@ class SearchContext { this.debug = params.debug; this.debugInfo = null; this.fuzzyAttributeSearch = !!params.fuzzyAttributeSearch; + this.autocomplete = !!params.autocomplete; this.enableFuzzyMatching = true; // Default to true for backward compatibility this.highlightedTokens = []; this.originalQuery = ""; diff --git a/apps/server/src/services/search/services/search.ts b/apps/server/src/services/search/services/search.ts index 7ee3e494f4..b533c185fe 100644 --- a/apps/server/src/services/search/services/search.ts +++ b/apps/server/src/services/search/services/search.ts @@ -248,10 +248,10 @@ function findResultsWithExpression(expression: Expression, searchContext: Search return performSearch(expression, searchContext, false); } - // For limited searches (e.g. autocomplete), skip the expensive two-phase - // fuzzy fallback. The user is typing and will refine their query — exact - // matching is sufficient and avoids a second full scan of all notes. - if (searchContext.limit) { + // For autocomplete searches, skip the expensive two-phase fuzzy fallback. + // The user is typing and will refine their query — exact matching is + // sufficient and avoids a second full scan of all notes. + if (searchContext.autocomplete) { return performSearch(expression, searchContext, false); } @@ -645,7 +645,7 @@ function searchNotesForAutocomplete(query: string, fastSearch: boolean = true) { fuzzyAttributeSearch: true, ignoreInternalAttributes: true, ancestorNoteId: hoistedNoteService.isHoistedInHiddenSubtree() ? "root" : hoistedNoteService.getHoistedNoteId(), - limit: 200 + autocomplete: true }); const allSearchResults = findResultsWithQuery(query, searchContext); diff --git a/apps/server/src/services/search/services/types.ts b/apps/server/src/services/search/services/types.ts index 7edc3b4ae5..60d00540c6 100644 --- a/apps/server/src/services/search/services/types.ts +++ b/apps/server/src/services/search/services/types.ts @@ -21,4 +21,6 @@ export interface SearchParams { limit?: number | null; debug?: boolean; fuzzyAttributeSearch?: boolean; + /** When true, skip the two-phase fuzzy fallback and use the single-token fast path. */ + autocomplete?: boolean; } From f23a7b48429223ed21f0b944920f28b5edb6b675 Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Wed, 18 Mar 2026 11:43:28 -0700 Subject: [PATCH 008/482] feat(settings): also allow for fuzzy searching to just be disabled --- apps/client/src/translations/en/translation.json | 4 ++++ .../src/widgets/type_widgets/options/other.tsx | 16 ++++++++++++++++ apps/server/src/routes/api/options.ts | 1 + apps/server/src/services/options_init.ts | 3 +++ .../server/src/services/search/search_context.ts | 7 ++++++- packages/commons/src/lib/options_interface.ts | 4 ++++ 6 files changed, 34 insertions(+), 1 deletion(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index fdd6f9fb2d..f9ba8f8743 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -1292,6 +1292,10 @@ "erase_excess_revision_snapshots": "Erase excess revision snapshots now", "erase_excess_revision_snapshots_prompt": "Excess revision snapshots have been erased." }, + "search": { + "title": "Search", + "enable_fuzzy_matching": "Enable fuzzy matching in search (matches similar words when exact matches are insufficient)" + }, "search_engine": { "title": "Search Engine", "custom_search_engine_info": "Custom search engine requires both a name and a URL to be set. If either of these is not set, DuckDuckGo will be used as the default search engine.", diff --git a/apps/client/src/widgets/type_widgets/options/other.tsx b/apps/client/src/widgets/type_widgets/options/other.tsx index e6813f8d2b..8cb99bace4 100644 --- a/apps/client/src/widgets/type_widgets/options/other.tsx +++ b/apps/client/src/widgets/type_widgets/options/other.tsx @@ -21,6 +21,7 @@ import TimeSelector from "./components/TimeSelector"; export default function OtherSettings() { return ( <> + {isElectron() && <> @@ -36,6 +37,21 @@ export default function OtherSettings() { ); } +function SearchSettings() { + const [ fuzzyEnabled, setFuzzyEnabled ] = useTriliumOptionBool("searchEnableFuzzyMatching"); + + return ( + + + + ); +} + function SearchEngineSettings() { const [ customSearchEngineName, setCustomSearchEngineName ] = useTriliumOption("customSearchEngineName"); const [ customSearchEngineUrl, setCustomSearchEngineUrl ] = useTriliumOption("customSearchEngineUrl"); diff --git a/apps/server/src/routes/api/options.ts b/apps/server/src/routes/api/options.ts index bb6ffb00d6..049a898fca 100644 --- a/apps/server/src/routes/api/options.ts +++ b/apps/server/src/routes/api/options.ts @@ -97,6 +97,7 @@ const ALLOWED_OPTIONS = new Set([ "layoutOrientation", "backgroundEffects", "allowedHtmlTags", + "searchEnableFuzzyMatching", "redirectBareDomain", "showLoginInShareTheme", "splitEditorOrientation", diff --git a/apps/server/src/services/options_init.ts b/apps/server/src/services/options_init.ts index a49672019d..17ea5a1f0b 100644 --- a/apps/server/src/services/options_init.ts +++ b/apps/server/src/services/options_init.ts @@ -198,6 +198,9 @@ const defaultOptions: DefaultOption[] = [ isSynced: true }, + // Search settings + { name: "searchEnableFuzzyMatching", value: "true", isSynced: true }, + // Share settings { name: "redirectBareDomain", value: "false", isSynced: true }, { name: "showLoginInShareTheme", value: "false", isSynced: true }, diff --git a/apps/server/src/services/search/search_context.ts b/apps/server/src/services/search/search_context.ts index 55d4df5d2f..79b0b6db3d 100644 --- a/apps/server/src/services/search/search_context.ts +++ b/apps/server/src/services/search/search_context.ts @@ -1,6 +1,7 @@ "use strict"; import hoistedNoteService from "../hoisted_note.js"; +import optionService from "../options.js"; import type { SearchParams } from "./services/types.js"; class SearchContext { @@ -49,7 +50,11 @@ class SearchContext { this.debugInfo = null; this.fuzzyAttributeSearch = !!params.fuzzyAttributeSearch; this.autocomplete = !!params.autocomplete; - this.enableFuzzyMatching = true; // Default to true for backward compatibility + try { + this.enableFuzzyMatching = optionService.getOptionBool("searchEnableFuzzyMatching"); + } catch { + this.enableFuzzyMatching = true; // Default to true if option not yet initialized + } this.highlightedTokens = []; this.originalQuery = ""; this.fulltextQuery = ""; // complete fulltext part diff --git a/packages/commons/src/lib/options_interface.ts b/packages/commons/src/lib/options_interface.ts index 5582df79d2..6e36ebd7a3 100644 --- a/packages/commons/src/lib/options_interface.ts +++ b/packages/commons/src/lib/options_interface.ts @@ -134,6 +134,10 @@ export interface OptionDefinitions extends KeyboardShortcutsOptions Date: Fri, 20 Mar 2026 11:26:19 -0700 Subject: [PATCH 009/482] feat(tests): implement search benchmark test... --- .../search/services/search_benchmark.spec.ts | 675 ++++++++++++++++++ 1 file changed, 675 insertions(+) create mode 100644 apps/server/src/services/search/services/search_benchmark.spec.ts diff --git a/apps/server/src/services/search/services/search_benchmark.spec.ts b/apps/server/src/services/search/services/search_benchmark.spec.ts new file mode 100644 index 0000000000..53319ff9cd --- /dev/null +++ b/apps/server/src/services/search/services/search_benchmark.spec.ts @@ -0,0 +1,675 @@ +/** + * Comprehensive search benchmark suite. + * + * Covers many scenarios: + * - Single-token, multi-token, phrase-like queries + * - Fuzzy matching enabled vs disabled + * - Autocomplete vs full search + * - Diacritics / unicode queries + * - No-match queries + * - Varying note counts (1K, 5K, 10K, 20K) + * - Warm cache vs cold cache + * + * All times are in-memory (monkeypatched getContent, no real SQL). + */ +import { describe, it, expect, afterEach } from "vitest"; +import searchService from "./search.js"; +import BNote from "../../../becca/entities/bnote.js"; +import BBranch from "../../../becca/entities/bbranch.js"; +import SearchContext from "../search_context.js"; +import becca from "../../../becca/becca.js"; +import { NoteBuilder, note } from "../../../test/becca_mocking.js"; + +// ── helpers ────────────────────────────────────────────────────────── + +function randomWord(len = 6): string { + const chars = "abcdefghijklmnopqrstuvwxyz"; + let word = ""; + for (let i = 0; i < len; i++) { + word += chars[Math.floor(Math.random() * chars.length)]; + } + return word; +} + +function generateHtmlContent(wordCount: number, includeKeywords = false, keywords?: string[]): string { + const paragraphs: string[] = []; + let wordsRemaining = wordCount; + const kws = keywords ?? []; + + while (wordsRemaining > 0) { + const paraWords = Math.min(wordsRemaining, 20 + Math.floor(Math.random() * 40)); + const words: string[] = []; + for (let i = 0; i < paraWords; i++) { + words.push(randomWord(3 + Math.floor(Math.random() * 10))); + } + if (includeKeywords && paragraphs.length === 2) { + for (let k = 0; k < kws.length; k++) { + const pos = Math.min(words.length - 1, Math.floor((words.length / (kws.length + 1)) * (k + 1))); + words[pos] = kws[k]; + } + } + paragraphs.push(`

${words.join(" ")}

`); + wordsRemaining -= paraWords; + } + + return `${paragraphs.join("\n")}`; +} + +function timed(fn: () => T): [T, number] { + const start = performance.now(); + const result = fn(); + return [result, performance.now() - start]; +} + +function avg(nums: number[]): number { + return nums.reduce((a, b) => a + b, 0) / nums.length; +} + +function min(nums: number[]): number { + return Math.min(...nums); +} + +// ── dataset builder ────────────────────────────────────────────────── + +const syntheticContent: Record = {}; + +function buildDataset(noteCount: number, opts: { + matchFraction?: number; + labelsPerNote?: number; + depth?: number; + contentWordCount?: number; + varyContentSize?: boolean; + titleKeywords?: string[]; + contentKeywords?: string[]; + /** Include notes with diacritics in titles */ + includeDiacritics?: boolean; +} = {}) { + const { + matchFraction = 0.1, + labelsPerNote = 3, + depth = 4, + contentWordCount = 300, + varyContentSize = true, + titleKeywords = ["target"], + contentKeywords = titleKeywords, + includeDiacritics = false, + } = opts; + + becca.reset(); + for (const key of Object.keys(syntheticContent)) { + delete syntheticContent[key]; + } + + const rootNote = new NoteBuilder(new BNote({ noteId: "root", title: "root", type: "text" })); + new BBranch({ + branchId: "none_root", + noteId: "root", + parentNoteId: "none", + notePosition: 10 + }); + + const containers: NoteBuilder[] = []; + let parent = rootNote; + for (let d = 0; d < depth; d++) { + const container = note(`Container_${d}_${randomWord(4)}`); + parent.child(container); + containers.push(container); + parent = container; + } + + const matchCount = Math.floor(noteCount * matchFraction); + const diacriticTitles = [ + "résumé", "naïve", "café", "über", "ñoño", "exposé", + "Ångström", "Üntersuchung", "São Paulo", "François" + ]; + + for (let i = 0; i < noteCount; i++) { + const isMatch = i < matchCount; + let title: string; + + if (includeDiacritics && i % 20 === 0) { + // Every 20th note gets a diacritics-heavy title + const dTitle = diacriticTitles[i % diacriticTitles.length]; + title = isMatch + ? `${dTitle} ${titleKeywords.join(" ")} Document ${i}` + : `${dTitle} ${randomWord(5)} Note ${i}`; + } else { + title = isMatch + ? `${randomWord(5)} ${titleKeywords.join(" ")} ${randomWord(5)} Document ${i}` + : `${randomWord(5)} ${randomWord(6)} ${randomWord(4)} Note ${i}`; + } + + const n = note(title); + + for (let l = 0; l < labelsPerNote; l++) { + const labelName = isMatch && l === 0 ? "category" : `label_${randomWord(4)}`; + const labelValue = isMatch && l === 0 ? `important ${titleKeywords[0]}` : randomWord(8); + n.label(labelName, labelValue); + } + + let noteWordCount = contentWordCount; + if (varyContentSize) { + const r = Math.random(); + if (r < 0.2) noteWordCount = Math.floor(contentWordCount * (0.2 + Math.random() * 0.3)); + else if (r < 0.7) noteWordCount = Math.floor(contentWordCount * (0.7 + Math.random() * 0.6)); + else if (r < 0.9) noteWordCount = Math.floor(contentWordCount * (1.3 + Math.random() * 0.7)); + else noteWordCount = Math.floor(contentWordCount * (2.0 + Math.random() * 1.0)); + } + + const includeContentKeyword = isMatch && contentKeywords.length > 0; + syntheticContent[n.note.noteId] = generateHtmlContent( + noteWordCount, + includeContentKeyword, + includeContentKeyword ? contentKeywords : undefined + ); + + const containerIndex = i % containers.length; + containers[containerIndex].child(n); + } + + // Monkeypatch getContent() + for (const noteObj of Object.values(becca.notes)) { + const noteId = noteObj.noteId; + if (syntheticContent[noteId]) { + (noteObj as any).getContent = () => syntheticContent[noteId]; + } else { + (noteObj as any).getContent = () => ""; + } + } + + return { rootNote, matchCount }; +} + +// ── benchmark runner ───────────────────────────────────────────────── + +interface BenchmarkResult { + query: string; + mode: string; + noteCount: number; + avgMs: number; + minMs: number; + resultCount: number; +} + +function runBenchmark( + query: string, + mode: "autocomplete" | "fullSearch", + fuzzyEnabled: boolean, + iterations = 5 +): BenchmarkResult { + const noteCount = Object.keys(becca.notes).length; + + // Warm up + if (mode === "autocomplete") { + searchService.searchNotesForAutocomplete(query, true); + } else { + const ctx = new SearchContext({ fastSearch: false }); + ctx.enableFuzzyMatching = fuzzyEnabled; + searchService.findResultsWithQuery(query, ctx); + } + + const times: number[] = []; + let resultCount = 0; + + for (let i = 0; i < iterations; i++) { + if (mode === "autocomplete") { + // For autocomplete, fuzzy is controlled by the global option + // We'll manipulate enableFuzzyMatching after construction + const [results, ms] = timed(() => { + // searchNotesForAutocomplete creates its own SearchContext internally + // so we need to test via findResultsWithQuery for fuzzy control + const ctx = new SearchContext({ + fastSearch: true, + includeHiddenNotes: true, + fuzzyAttributeSearch: true, + ignoreInternalAttributes: true, + autocomplete: true + }); + ctx.enableFuzzyMatching = fuzzyEnabled; + return searchService.findResultsWithQuery(query, ctx); + }); + times.push(ms); + resultCount = results.length; + } else { + const [results, ms] = timed(() => { + const ctx = new SearchContext({ fastSearch: false }); + ctx.enableFuzzyMatching = fuzzyEnabled; + return searchService.findResultsWithQuery(query, ctx); + }); + times.push(ms); + resultCount = results.length; + } + } + + return { + query, + mode: `${mode}${fuzzyEnabled ? "+fuzzy" : ""}`, + noteCount, + avgMs: avg(times), + minMs: min(times), + resultCount + }; +} + +function printTable(title: string, results: BenchmarkResult[]) { + console.log(`\n${"═".repeat(110)}`); + console.log(` ${title}`); + console.log(`${"═".repeat(110)}`); + console.log( + " " + + "Query".padEnd(35) + + "Mode".padEnd(22) + + "Notes".padStart(7) + + "Avg (ms)".padStart(12) + + "Min (ms)".padStart(12) + + "Results".padStart(10) + ); + console.log(` ${"─".repeat(98)}`); + for (const r of results) { + console.log( + " " + + `"${r.query}"`.padEnd(35) + + r.mode.padEnd(22) + + String(r.noteCount).padStart(7) + + r.avgMs.toFixed(1).padStart(12) + + r.minMs.toFixed(1).padStart(12) + + String(r.resultCount).padStart(10) + ); + } + console.log(`${"═".repeat(110)}\n`); +} + +// ── tests ──────────────────────────────────────────────────────────── + +describe("Comprehensive Search Benchmark", () => { + + afterEach(() => { + becca.reset(); + }); + + describe("Single-token queries", () => { + for (const noteCount of [1000, 5000, 10000, 20000]) { + it(`single token @ ${noteCount} notes — fuzzy on vs off, autocomplete vs full`, () => { + buildDataset(noteCount, { + matchFraction: 0.15, + titleKeywords: ["meeting"], + contentKeywords: ["meeting"], + contentWordCount: 300, + }); + + const results: BenchmarkResult[] = [ + runBenchmark("meeting", "autocomplete", false), + runBenchmark("meeting", "autocomplete", true), + runBenchmark("meeting", "fullSearch", false), + runBenchmark("meeting", "fullSearch", true), + ]; + + printTable(`Single Token "meeting" — ${noteCount} notes`, results); + expect(results[0].resultCount).toBeGreaterThan(0); + }); + } + }); + + describe("Multi-token queries", () => { + for (const noteCount of [1000, 5000, 10000, 20000]) { + it(`multi token @ ${noteCount} notes — fuzzy on vs off`, () => { + buildDataset(noteCount, { + matchFraction: 0.15, + titleKeywords: ["meeting", "notes", "january"], + contentKeywords: ["meeting", "notes", "january"], + contentWordCount: 400, + }); + + const results: BenchmarkResult[] = [ + // 2-token + runBenchmark("meeting notes", "autocomplete", false), + runBenchmark("meeting notes", "autocomplete", true), + runBenchmark("meeting notes", "fullSearch", false), + runBenchmark("meeting notes", "fullSearch", true), + // 3-token + runBenchmark("meeting notes january", "autocomplete", false), + runBenchmark("meeting notes january", "autocomplete", true), + runBenchmark("meeting notes january", "fullSearch", false), + runBenchmark("meeting notes january", "fullSearch", true), + ]; + + printTable(`Multi Token — ${noteCount} notes`, results); + expect(results[0].resultCount).toBeGreaterThan(0); + }); + } + }); + + describe("No-match queries (worst case — full scan, zero results)", () => { + for (const noteCount of [1000, 5000, 10000, 20000]) { + it(`no-match @ ${noteCount} notes`, () => { + buildDataset(noteCount, { + matchFraction: 0.1, + titleKeywords: ["target"], + contentKeywords: ["target"], + contentWordCount: 300, + }); + + const results: BenchmarkResult[] = [ + runBenchmark("xyznonexistent", "autocomplete", false), + runBenchmark("xyznonexistent", "autocomplete", true), + runBenchmark("xyznonexistent", "fullSearch", false), + runBenchmark("xyznonexistent", "fullSearch", true), + runBenchmark("xyzfoo xyzbar", "autocomplete", false), + runBenchmark("xyzfoo xyzbar", "autocomplete", true), + runBenchmark("xyzfoo xyzbar", "fullSearch", false), + runBenchmark("xyzfoo xyzbar", "fullSearch", true), + ]; + + printTable(`No-Match Queries — ${noteCount} notes`, results); + // All should return 0 results + for (const r of results) { + expect(r.resultCount).toBe(0); + } + }); + } + }); + + describe("Diacritics / Unicode queries", () => { + for (const noteCount of [1000, 5000, 10000]) { + it(`diacritics @ ${noteCount} notes`, () => { + buildDataset(noteCount, { + matchFraction: 0.15, + titleKeywords: ["résumé"], + contentKeywords: ["résumé"], + contentWordCount: 300, + includeDiacritics: true, + }); + + const results: BenchmarkResult[] = [ + // Exact diacritics + runBenchmark("résumé", "autocomplete", false), + runBenchmark("résumé", "autocomplete", true), + // ASCII equivalent (should still match via normalize) + runBenchmark("resume", "autocomplete", false), + runBenchmark("resume", "autocomplete", true), + // Full search + runBenchmark("résumé", "fullSearch", false), + runBenchmark("resume", "fullSearch", false), + ]; + + printTable(`Diacritics "résumé" / "resume" — ${noteCount} notes`, results); + }); + } + }); + + describe("Partial / prefix queries (simulating typing)", () => { + for (const noteCount of [5000, 10000, 20000]) { + it(`typing progression @ ${noteCount} notes`, () => { + buildDataset(noteCount, { + matchFraction: 0.15, + titleKeywords: ["documentation"], + contentKeywords: ["documentation"], + contentWordCount: 300, + }); + + const results: BenchmarkResult[] = [ + runBenchmark("d", "autocomplete", false), + runBenchmark("do", "autocomplete", false), + runBenchmark("doc", "autocomplete", false), + runBenchmark("docu", "autocomplete", false), + runBenchmark("docum", "autocomplete", false), + runBenchmark("document", "autocomplete", false), + runBenchmark("documentation", "autocomplete", false), + // Same with fuzzy + runBenchmark("d", "autocomplete", true), + runBenchmark("doc", "autocomplete", true), + runBenchmark("document", "autocomplete", true), + runBenchmark("documentation", "autocomplete", true), + ]; + + printTable(`Typing Progression "documentation" — ${noteCount} notes`, results); + }); + } + }); + + describe("Attribute-matching queries", () => { + for (const noteCount of [5000, 10000]) { + it(`attribute search @ ${noteCount} notes`, () => { + buildDataset(noteCount, { + matchFraction: 0.15, + labelsPerNote: 5, + titleKeywords: ["important"], + contentKeywords: ["important"], + contentWordCount: 200, + }); + + const results: BenchmarkResult[] = [ + // "category" is a label name on matching notes + runBenchmark("category", "autocomplete", false), + runBenchmark("category", "autocomplete", true), + runBenchmark("category", "fullSearch", false), + runBenchmark("category", "fullSearch", true), + // "important" appears in both title and label value + runBenchmark("important", "autocomplete", false), + runBenchmark("important", "autocomplete", true), + ]; + + printTable(`Attribute Matching — ${noteCount} notes`, results); + }); + } + }); + + describe("Long queries (4-5 tokens)", () => { + for (const noteCount of [5000, 10000]) { + it(`long query @ ${noteCount} notes`, () => { + buildDataset(noteCount, { + matchFraction: 0.10, + titleKeywords: ["quarterly", "budget", "review", "report"], + contentKeywords: ["quarterly", "budget", "review", "report"], + contentWordCount: 500, + }); + + const results: BenchmarkResult[] = [ + runBenchmark("quarterly", "autocomplete", false), + runBenchmark("quarterly budget", "autocomplete", false), + runBenchmark("quarterly budget review", "autocomplete", false), + runBenchmark("quarterly budget review report", "autocomplete", false), + // Same with fuzzy + runBenchmark("quarterly budget review report", "autocomplete", true), + // Full search + runBenchmark("quarterly budget review report", "fullSearch", false), + runBenchmark("quarterly budget review report", "fullSearch", true), + ]; + + printTable(`Long Queries (4 tokens) — ${noteCount} notes`, results); + }); + } + }); + + describe("Mixed scenario — realistic user session", () => { + it("simulates a user session with varied queries @ 10K notes", () => { + buildDataset(10000, { + matchFraction: 0.15, + titleKeywords: ["project", "planning"], + contentKeywords: ["project", "planning", "timeline", "budget"], + contentWordCount: 400, + varyContentSize: true, + includeDiacritics: true, + depth: 6, + }); + + const results: BenchmarkResult[] = [ + // Quick autocomplete lookups (user typing in search bar) + runBenchmark("pro", "autocomplete", false), + runBenchmark("project", "autocomplete", false), + runBenchmark("project plan", "autocomplete", false), + + // Full search (user hits Enter) + runBenchmark("project", "fullSearch", false), + runBenchmark("project planning", "fullSearch", false), + runBenchmark("project planning", "fullSearch", true), + + // Typo / near-miss with fuzzy + runBenchmark("projct", "autocomplete", false), + runBenchmark("projct", "autocomplete", true), + runBenchmark("projct planing", "fullSearch", false), + runBenchmark("projct planing", "fullSearch", true), + + // No results + runBenchmark("xyznonexistent", "autocomplete", false), + runBenchmark("xyznonexistent foo", "fullSearch", true), + + // Short common substring + runBenchmark("note", "autocomplete", false), + runBenchmark("document", "autocomplete", false), + ]; + + printTable("Realistic User Session — 10K notes", results); + }); + }); + + describe("Cache warmth impact", () => { + it("cold vs warm flat text index @ 10K notes", () => { + buildDataset(10000, { + matchFraction: 0.15, + titleKeywords: ["target"], + contentKeywords: ["target"], + contentWordCount: 300, + }); + + console.log(`\n${"═".repeat(80)}`); + console.log(" Cold vs Warm Cache — 10K notes"); + console.log(`${"═".repeat(80)}`); + + // Cold: first search after dataset build (flat text index not yet built) + becca.flatTextIndex = null; + becca.dirtyFlatTextNoteIds.clear(); + const [coldResults, coldMs] = timed(() => { + const ctx = new SearchContext({ fastSearch: true, autocomplete: true }); + ctx.enableFuzzyMatching = false; + return searchService.findResultsWithQuery("target", ctx); + }); + console.log(` Cold (index build + search): ${coldMs.toFixed(1)}ms (${coldResults.length} results)`); + + // Warm: subsequent searches reuse the index + const warmTimes: number[] = []; + for (let i = 0; i < 5; i++) { + const [, ms] = timed(() => { + const ctx = new SearchContext({ fastSearch: true, autocomplete: true }); + ctx.enableFuzzyMatching = false; + return searchService.findResultsWithQuery("target", ctx); + }); + warmTimes.push(ms); + } + console.log(` Warm (reuse index, 5 runs): avg ${avg(warmTimes).toFixed(1)}ms min ${min(warmTimes).toFixed(1)}ms`); + + // Incremental: dirty a few notes and search again + const noteIds = Object.keys(becca.notes).slice(0, 50); + for (const nid of noteIds) { + becca.dirtyNoteFlatText(nid); + } + const [, incrMs] = timed(() => { + const ctx = new SearchContext({ fastSearch: true, autocomplete: true }); + ctx.enableFuzzyMatching = false; + return searchService.findResultsWithQuery("target", ctx); + }); + console.log(` Incremental (50 dirty notes): ${incrMs.toFixed(1)}ms`); + + // Full rebuild + becca.flatTextIndex = null; + const [, rebuildMs] = timed(() => { + const ctx = new SearchContext({ fastSearch: true, autocomplete: true }); + ctx.enableFuzzyMatching = false; + return searchService.findResultsWithQuery("target", ctx); + }); + console.log(` Full rebuild (index = null): ${rebuildMs.toFixed(1)}ms`); + + console.log(`${"═".repeat(80)}\n`); + }); + }); + + describe("Fuzzy matching effectiveness comparison", () => { + it("exact vs fuzzy result quality @ 10K notes", () => { + buildDataset(10000, { + matchFraction: 0.10, + titleKeywords: ["performance"], + contentKeywords: ["performance", "optimization"], + contentWordCount: 300, + }); + + console.log(`\n${"═".repeat(90)}`); + console.log(" Fuzzy Matching Effectiveness — 10K notes"); + console.log(`${"═".repeat(90)}`); + console.log( + " " + + "Query".padEnd(30) + + "Fuzzy".padEnd(8) + + "Time (ms)".padStart(12) + + "Results".padStart(10) + + " Notes" + ); + console.log(` ${"─".repeat(70)}`); + + const queries = [ + "performance", // exact match + "performanc", // truncated + "preformance", // typo + "performence", // common misspelling + "optimization", // exact match + "optimzation", // typo + "perf optim", // abbreviated multi + ]; + + for (const query of queries) { + for (const fuzzy of [false, true]) { + const times: number[] = []; + let resultCount = 0; + for (let i = 0; i < 3; i++) { + const [results, ms] = timed(() => { + const ctx = new SearchContext({ fastSearch: true }); + ctx.enableFuzzyMatching = fuzzy; + return searchService.findResultsWithQuery(query, ctx); + }); + times.push(ms); + resultCount = results.length; + } + console.log( + " " + + `"${query}"`.padEnd(30) + + (fuzzy ? "ON" : "OFF").padEnd(8) + + avg(times).toFixed(1).padStart(12) + + String(resultCount).padStart(10) + ); + } + } + + console.log(`${"═".repeat(90)}\n`); + }); + }); + + describe("Scale comparison summary", () => { + it("summary table across all note counts", () => { + const summaryResults: BenchmarkResult[] = []; + + for (const noteCount of [1000, 5000, 10000, 20000]) { + buildDataset(noteCount, { + matchFraction: 0.15, + titleKeywords: ["meeting", "notes"], + contentKeywords: ["meeting", "notes"], + contentWordCount: 400, + varyContentSize: true, + depth: 5, + }); + + // Core scenarios + summaryResults.push(runBenchmark("meeting", "autocomplete", false)); + summaryResults.push(runBenchmark("meeting", "autocomplete", true)); + summaryResults.push(runBenchmark("meeting notes", "autocomplete", false)); + summaryResults.push(runBenchmark("meeting notes", "autocomplete", true)); + summaryResults.push(runBenchmark("meeting", "fullSearch", false)); + summaryResults.push(runBenchmark("meeting", "fullSearch", true)); + summaryResults.push(runBenchmark("meeting notes", "fullSearch", false)); + summaryResults.push(runBenchmark("meeting notes", "fullSearch", true)); + summaryResults.push(runBenchmark("xyznonexistent", "autocomplete", false)); + summaryResults.push(runBenchmark("xyznonexistent", "fullSearch", true)); + } + + printTable("Scale Comparison Summary", summaryResults); + }); + }); +}); From ac13af73c50d7ece3009129d8b560e882f0b3f7a Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Fri, 20 Mar 2026 11:38:56 -0700 Subject: [PATCH 010/482] feat(search): add FTS5 migration for content search index --- .../migrations/0235__add_fts5_content_search.ts | 14 ++++++++++++++ apps/server/src/migrations/migrations.ts | 5 +++++ 2 files changed, 19 insertions(+) create mode 100644 apps/server/src/migrations/0235__add_fts5_content_search.ts diff --git a/apps/server/src/migrations/0235__add_fts5_content_search.ts b/apps/server/src/migrations/0235__add_fts5_content_search.ts new file mode 100644 index 0000000000..d0767d51b4 --- /dev/null +++ b/apps/server/src/migrations/0235__add_fts5_content_search.ts @@ -0,0 +1,14 @@ +import sql from "../services/sql.js"; +import log from "../services/log.js"; + +export default () => { + sql.execute(/*sql*/` + CREATE VIRTUAL TABLE IF NOT EXISTS note_content_fts USING fts5( + noteId UNINDEXED, + content, + tokenize='unicode61 remove_diacritics 2' + ) + `); + + log.info("Created note_content_fts table. FTS index will be populated on first search."); +}; diff --git a/apps/server/src/migrations/migrations.ts b/apps/server/src/migrations/migrations.ts index 7aca1f802b..e9f8b8d72d 100644 --- a/apps/server/src/migrations/migrations.ts +++ b/apps/server/src/migrations/migrations.ts @@ -6,6 +6,11 @@ // Migrations should be kept in descending order, so the latest migration is first. const MIGRATIONS: (SqlMigration | JsMigration)[] = [ + // Add FTS5 virtual table for full-text content search + { + version: 235, + module: async () => import("./0235__add_fts5_content_search.js") + }, // Migrate aiChat notes to code notes since LLM integration has been removed { version: 234, From dcaebeea8312f7b1175ebae9a916b89a6fee118b Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Fri, 20 Mar 2026 11:39:54 -0700 Subject: [PATCH 011/482] feat(search): add FTS5 index service for content search --- .../src/services/search/fts_index.spec.ts | 13 ++ apps/server/src/services/search/fts_index.ts | 178 ++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 apps/server/src/services/search/fts_index.spec.ts create mode 100644 apps/server/src/services/search/fts_index.ts diff --git a/apps/server/src/services/search/fts_index.spec.ts b/apps/server/src/services/search/fts_index.spec.ts new file mode 100644 index 0000000000..983c972a0b --- /dev/null +++ b/apps/server/src/services/search/fts_index.spec.ts @@ -0,0 +1,13 @@ +import { describe, it, expect } from "vitest"; + +describe("FTS Index Service", () => { + it("should export buildIndex, updateNote, removeNote, searchContent functions", async () => { + const ftsIndex = await import("./fts_index.js"); + expect(typeof ftsIndex.default.buildIndex).toBe("function"); + expect(typeof ftsIndex.default.updateNote).toBe("function"); + expect(typeof ftsIndex.default.removeNote).toBe("function"); + expect(typeof ftsIndex.default.searchContent).toBe("function"); + expect(typeof ftsIndex.default.isIndexBuilt).toBe("function"); + expect(typeof ftsIndex.default.resetIndex).toBe("function"); + }); +}); diff --git a/apps/server/src/services/search/fts_index.ts b/apps/server/src/services/search/fts_index.ts new file mode 100644 index 0000000000..83c7616999 --- /dev/null +++ b/apps/server/src/services/search/fts_index.ts @@ -0,0 +1,178 @@ +"use strict"; + +import sql from "../sql.js"; +import log from "../log.js"; +import protectedSessionService from "../protected_session.js"; +import preprocessContent from "./expressions/note_content_fulltext_preprocessor.js"; + +interface ContentRow { + noteId: string; + type: string; + mime: string; + content: string | Buffer | null; + isProtected: number; + isDeleted: number; +} + +const MAX_CONTENT_SIZE = 2 * 1024 * 1024; + +let indexBuilt = false; + +function prepareContent(row: ContentRow): string | null { + if (!row.content) return null; + if (row.isDeleted) return null; + + let content: string | undefined; + + if (row.isProtected) { + if (!protectedSessionService.isProtectedSessionAvailable()) { + return null; + } + try { + content = protectedSessionService.decryptString(row.content as string) || undefined; + } catch { + return null; + } + } else { + content = typeof row.content === "string" ? row.content : row.content.toString(); + } + + if (!content || content.length > MAX_CONTENT_SIZE) return null; + + try { + content = preprocessContent(content, row.type, row.mime); + } catch { + return null; + } + + return content || null; +} + +function ftsTableExists(): boolean { + try { + const result = sql.getValue( + "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='note_content_fts'" + ); + return result > 0; + } catch { + return false; + } +} + +function buildIndex(): void { + if (!ftsTableExists()) { + log.info("FTS5 table does not exist, skipping index build."); + return; + } + + const startTime = Date.now(); + log.info("Building FTS content index..."); + + sql.execute("DELETE FROM note_content_fts"); + + const count = sql.transactional(() => { + let count = 0; + + for (const row of sql.iterateRows(` + SELECT noteId, type, mime, content, isProtected, isDeleted + FROM notes JOIN blobs USING (blobId) + WHERE type IN ('text', 'code', 'mermaid', 'canvas', 'mindMap') + AND isDeleted = 0 + AND content IS NOT NULL + AND LENGTH(content) < ${MAX_CONTENT_SIZE} + `)) { + const processedContent = prepareContent(row); + if (processedContent) { + sql.execute( + "INSERT INTO note_content_fts (noteId, content) VALUES (?, ?)", + [row.noteId, processedContent] + ); + count++; + } + } + + return count; + }); + + const elapsed = Date.now() - startTime; + log.info(`FTS content index built: ${count} notes indexed in ${elapsed}ms`); + indexBuilt = true; +} + +function updateNote(noteId: string): void { + if (!indexBuilt || !ftsTableExists()) return; + + sql.execute("DELETE FROM note_content_fts WHERE noteId = ?", [noteId]); + + const row = sql.getRowOrNull(` + SELECT noteId, type, mime, content, isProtected, isDeleted + FROM notes JOIN blobs USING (blobId) + WHERE noteId = ? + `, [noteId]); + + if (!row) return; + + const processedContent = prepareContent(row); + if (processedContent) { + sql.execute( + "INSERT INTO note_content_fts (noteId, content) VALUES (?, ?)", + [row.noteId, processedContent] + ); + } +} + +function removeNote(noteId: string): void { + if (!indexBuilt || !ftsTableExists()) return; + sql.execute("DELETE FROM note_content_fts WHERE noteId = ?", [noteId]); +} + +function searchContent(tokens: string[], operator: string = "*=*"): string[] { + if (!ftsTableExists()) return []; + + if (!indexBuilt) { + buildIndex(); + } + + const escapedTokens = tokens.map(t => { + const cleaned = t.replace(/["*^(){}:]/g, ""); + if (!cleaned) return null; + return `"${cleaned}"`; + }).filter(Boolean); + + if (escapedTokens.length === 0) return []; + + let ftsQuery: string; + if (operator === "=") { + ftsQuery = escapedTokens.join(" "); + } else { + ftsQuery = escapedTokens.join(" AND "); + } + + try { + const results = sql.getColumn( + "SELECT noteId FROM note_content_fts WHERE note_content_fts MATCH ? ORDER BY rank", + [ftsQuery] + ); + return results; + } catch (e) { + log.info(`FTS5 query failed for "${ftsQuery}": ${e}`); + return []; + } +} + +function isIndexBuilt(): boolean { + return indexBuilt; +} + +function resetIndex(): void { + indexBuilt = false; +} + +export default { + buildIndex, + updateNote, + removeNote, + searchContent, + isIndexBuilt, + resetIndex +}; From f358563c27de16781e3da9a37594520be507a44d Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Fri, 20 Mar 2026 11:40:33 -0700 Subject: [PATCH 012/482] feat(search): wire FTS index updates to note content changes --- apps/server/src/services/handlers.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/apps/server/src/services/handlers.ts b/apps/server/src/services/handlers.ts index f32bf6ddd0..89647d8d83 100644 --- a/apps/server/src/services/handlers.ts +++ b/apps/server/src/services/handlers.ts @@ -60,6 +60,17 @@ eventService.subscribe([eventService.ENTITY_CHANGED, eventService.ENTITY_DELETED } else if (entityName === "notes") { // ENTITY_DELETED won't trigger anything since all branches/attributes are already deleted at this point runAttachedRelations(entity, "runOnNoteChange", entity); + + if (entity.isDeleted) { + try { + const ftsIndex = require("./search/fts_index.js").default; + if (ftsIndex.isIndexBuilt()) { + ftsIndex.removeNote(entity.noteId); + } + } catch { + // FTS index update failure should not block note operations + } + } } }); @@ -81,6 +92,16 @@ eventService.subscribe(eventService.ENTITY_CHANGED, ({ entityName, entity }) => eventService.subscribe(eventService.NOTE_CONTENT_CHANGE, ({ entity }) => { runAttachedRelations(entity, "runOnNoteContentChange", entity); + + // Update FTS content index incrementally + try { + const ftsIndex = require("./search/fts_index.js").default; + if (ftsIndex.isIndexBuilt()) { + ftsIndex.updateNote(entity.noteId); + } + } catch { + // FTS index update failure should not block note saves + } }); eventService.subscribe(eventService.ENTITY_CREATED, ({ entityName, entity }) => { From bc0942180e97c6af915d9d4b5f428adb86e019a0 Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Fri, 20 Mar 2026 11:42:20 -0700 Subject: [PATCH 013/482] feat(search): use FTS5 index in NoteContentFulltextExp with sequential fallback For operators =, !=, and *=*, the search now tries the FTS5 index first via searchViaFts(). If FTS is unavailable or fails, it falls back to the original sequential scan. The flat text attribute search is extracted into its own searchFlatTextAttributes() method and runs after both paths. --- .../expressions/note_content_fulltext.ts | 112 +++++++++++++----- 1 file changed, 81 insertions(+), 31 deletions(-) diff --git a/apps/server/src/services/search/expressions/note_content_fulltext.ts b/apps/server/src/services/search/expressions/note_content_fulltext.ts index f3e0a39333..86aa40e36a 100644 --- a/apps/server/src/services/search/expressions/note_content_fulltext.ts +++ b/apps/server/src/services/search/expressions/note_content_fulltext.ts @@ -79,7 +79,17 @@ class NoteContentFulltextExp extends Expression { const resultNoteSet = new NoteSet(); - // Search through notes with content + // Try FTS5 index first for supported operators + if (this.canUseFts()) { + const ftsWorked = this.searchViaFts(inputNoteSet, resultNoteSet); + if (ftsWorked) { + this.searchFlatTextAttributes(inputNoteSet, resultNoteSet); + return resultNoteSet; + } + // FTS unavailable or failed — fall through to sequential scan + } + + // Fallback: sequential scan (original behavior) for (const row of sql.iterateRows(` SELECT noteId, type, mime, content, isProtected FROM notes JOIN blobs USING (blobId) @@ -89,43 +99,83 @@ class NoteContentFulltextExp extends Expression { this.findInText(row, inputNoteSet, resultNoteSet); } - // For exact match with flatText, also search notes WITHOUT content (they may have matching attributes) - if (this.flatText && (this.operator === "=" || this.operator === "!=")) { - for (const note of inputNoteSet.notes) { - // Skip if already found or doesn't exist - if (resultNoteSet.hasNoteId(note.noteId) || !(note.noteId in becca.notes)) { - continue; - } + this.searchFlatTextAttributes(inputNoteSet, resultNoteSet); + return resultNoteSet; + } - const noteFromBecca = becca.notes[note.noteId]; - const flatText = noteFromBecca.getFlatText(); + /** + * Whether this operator can be served by FTS5. + */ + private canUseFts(): boolean { + return ["=", "!=", "*=*"].includes(this.operator); + } - // For flatText, only check attribute values (format: #name=value or ~name=value) - // Don't match against noteId, type, mime, or title which are also in flatText - let matches = false; - const phrase = this.tokens.join(" "); - const normalizedPhrase = normalizeSearchText(phrase); - const normalizedFlatText = normalizeSearchText(flatText); + /** + * Attempts to use the FTS5 index for content search. + * Returns true if FTS was used successfully, false to fall back to sequential scan. + */ + private searchViaFts(inputNoteSet: NoteSet, resultNoteSet: NoteSet): boolean { + try { + const ftsIndex = require("../fts_index.js").default; + const matchingNoteIds = ftsIndex.searchContent(this.tokens, this.operator); - // Check if =phrase appears in flatText (indicates attribute value match) - // For single words, use word-boundary matching to avoid substring matches - if (!normalizedPhrase.includes(' ')) { - // Single word: look for =word with word boundaries - // Split by = to get attribute values, then check each value for exact word match - const parts = normalizedFlatText.split('='); - matches = parts.slice(1).some(part => this.exactWordMatch(normalizedPhrase, part)); - } else { - // Multi-word phrase: check for substring match - matches = normalizedFlatText.includes(`=${normalizedPhrase}`); - } - - if ((this.operator === "=" && matches) || (this.operator === "!=" && !matches)) { - resultNoteSet.add(noteFromBecca); + for (const noteId of matchingNoteIds) { + if (inputNoteSet.hasNoteId(noteId) && noteId in becca.notes) { + if (this.operator === "!=") { + continue; + } + resultNoteSet.add(becca.notes[noteId]); } } + + if (this.operator === "!=") { + const matchingSet = new Set(matchingNoteIds); + for (const note of inputNoteSet.notes) { + if (!matchingSet.has(note.noteId) && note.noteId in becca.notes) { + resultNoteSet.add(becca.notes[note.noteId]); + } + } + } + + return true; + } catch { + return false; + } + } + + /** + * Searches flat text attributes for = and != operators. + * Extracted from the old execute() tail. + */ + private searchFlatTextAttributes(inputNoteSet: NoteSet, resultNoteSet: NoteSet): void { + if (!this.flatText || (this.operator !== "=" && this.operator !== "!=")) { + return; } - return resultNoteSet; + for (const note of inputNoteSet.notes) { + if (resultNoteSet.hasNoteId(note.noteId) || !(note.noteId in becca.notes)) { + continue; + } + + const noteFromBecca = becca.notes[note.noteId]; + const flatText = noteFromBecca.getFlatText(); + + let matches = false; + const phrase = this.tokens.join(" "); + const normalizedPhrase = normalizeSearchText(phrase); + const normalizedFlatText = normalizeSearchText(flatText); + + if (!normalizedPhrase.includes(' ')) { + const parts = normalizedFlatText.split('='); + matches = parts.slice(1).some(part => this.exactWordMatch(normalizedPhrase, part)); + } else { + matches = normalizedFlatText.includes(`=${normalizedPhrase}`); + } + + if ((this.operator === "=" && matches) || (this.operator === "!=" && !matches)) { + resultNoteSet.add(noteFromBecca); + } + } } /** From 06fb9c0a6bf9efae5a70a41389159152d3674e3d Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Fri, 20 Mar 2026 11:43:23 -0700 Subject: [PATCH 014/482] test(search): add FTS5 integration test --- apps/server/spec/fts5_search.spec.ts | 76 ++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 apps/server/spec/fts5_search.spec.ts diff --git a/apps/server/spec/fts5_search.spec.ts b/apps/server/spec/fts5_search.spec.ts new file mode 100644 index 0000000000..7d6ed7483a --- /dev/null +++ b/apps/server/spec/fts5_search.spec.ts @@ -0,0 +1,76 @@ +import { Application } from "express"; +import { beforeAll, describe, expect, it } from "vitest"; +import config from "../src/services/config.js"; + +let app: Application; + +function timed(fn: () => T): [T, number] { + const start = performance.now(); + const result = fn(); + return [result, performance.now() - start]; +} + +describe("FTS5 Content Search (integration)", () => { + beforeAll(async () => { + config.General.noAuthentication = true; + const buildApp = (await import("../src/app.js")).default; + app = await buildApp(); + }); + + it("FTS5 index builds and searches correctly", async () => { + const sql = (await import("../src/services/sql.js")).default; + const becca = (await import("../src/becca/becca.js")).default; + const ftsIndex = (await import("../src/services/search/fts_index.js")).default; + const cls = (await import("../src/services/cls.js")).default; + + await new Promise((resolve) => { + cls.init(() => { + // Check if FTS table exists (migration may not have run on test DB) + const tableExists = sql.getValue( + "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='note_content_fts'" + ); + + if (!tableExists) { + // Create the table for testing + sql.execute(` + CREATE VIRTUAL TABLE IF NOT EXISTS note_content_fts USING fts5( + noteId UNINDEXED, + content, + tokenize='unicode61 remove_diacritics 2' + ) + `); + } + + const noteCount = Object.keys(becca.notes).length; + console.log(`\n Notes in becca: ${noteCount}`); + + // Build the index + ftsIndex.resetIndex(); + const [, buildMs] = timed(() => ftsIndex.buildIndex()); + console.log(` FTS index build: ${buildMs.toFixed(0)}ms`); + + // Verify index has content + const indexedCount = sql.getValue("SELECT COUNT(*) FROM note_content_fts"); + console.log(` Notes indexed: ${indexedCount}`); + expect(indexedCount).toBeGreaterThanOrEqual(0); + + // If we have indexed content, test search + if (indexedCount > 0) { + const [results, searchMs] = timed(() => ftsIndex.searchContent(["note"], "*=*")); + console.log(` FTS search "note": ${searchMs.toFixed(1)}ms (${results.length} results)`); + expect(results).toBeInstanceOf(Array); + } + + // Test update and remove don't throw + expect(() => ftsIndex.updateNote("nonexistent")).not.toThrow(); + expect(() => ftsIndex.removeNote("nonexistent")).not.toThrow(); + + // Clean up + sql.execute("DELETE FROM note_content_fts"); + ftsIndex.resetIndex(); + + resolve(); + }); + }); + }); +}); From 24a01aefe2f674f0362e8e0f207b10af1669f0bd Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Fri, 20 Mar 2026 11:44:19 -0700 Subject: [PATCH 015/482] feat(search): add user option to enable/disable FTS5 content index --- apps/client/src/translations/en/translation.json | 3 ++- apps/client/src/widgets/type_widgets/options/other.tsx | 7 +++++++ apps/server/src/routes/api/options.ts | 1 + apps/server/src/services/options_init.ts | 1 + .../services/search/expressions/note_content_fulltext.ts | 8 ++++++++ packages/commons/src/lib/options_interface.ts | 2 ++ 6 files changed, 21 insertions(+), 1 deletion(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index f9ba8f8743..5232fa1dc1 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -1294,7 +1294,8 @@ }, "search": { "title": "Search", - "enable_fuzzy_matching": "Enable fuzzy matching in search (matches similar words when exact matches are insufficient)" + "enable_fuzzy_matching": "Enable fuzzy matching in search (matches similar words when exact matches are insufficient)", + "enable_fts5": "Use content index for faster full-text search (applies on next search)" }, "search_engine": { "title": "Search Engine", diff --git a/apps/client/src/widgets/type_widgets/options/other.tsx b/apps/client/src/widgets/type_widgets/options/other.tsx index 8cb99bace4..c16fffc891 100644 --- a/apps/client/src/widgets/type_widgets/options/other.tsx +++ b/apps/client/src/widgets/type_widgets/options/other.tsx @@ -39,6 +39,7 @@ export default function OtherSettings() { function SearchSettings() { const [ fuzzyEnabled, setFuzzyEnabled ] = useTriliumOptionBool("searchEnableFuzzyMatching"); + const [ fts5Enabled, setFts5Enabled ] = useTriliumOptionBool("searchEnableFts5"); return ( @@ -48,6 +49,12 @@ function SearchSettings() { currentValue={fuzzyEnabled} onChange={setFuzzyEnabled} /> + ); } diff --git a/apps/server/src/routes/api/options.ts b/apps/server/src/routes/api/options.ts index 049a898fca..5491fbf31e 100644 --- a/apps/server/src/routes/api/options.ts +++ b/apps/server/src/routes/api/options.ts @@ -98,6 +98,7 @@ const ALLOWED_OPTIONS = new Set([ "backgroundEffects", "allowedHtmlTags", "searchEnableFuzzyMatching", + "searchEnableFts5", "redirectBareDomain", "showLoginInShareTheme", "splitEditorOrientation", diff --git a/apps/server/src/services/options_init.ts b/apps/server/src/services/options_init.ts index 17ea5a1f0b..de22bbaafd 100644 --- a/apps/server/src/services/options_init.ts +++ b/apps/server/src/services/options_init.ts @@ -200,6 +200,7 @@ const defaultOptions: DefaultOption[] = [ // Search settings { name: "searchEnableFuzzyMatching", value: "true", isSynced: true }, + { name: "searchEnableFts5", value: "true", isSynced: true }, // Share settings { name: "redirectBareDomain", value: "false", isSynced: true }, diff --git a/apps/server/src/services/search/expressions/note_content_fulltext.ts b/apps/server/src/services/search/expressions/note_content_fulltext.ts index 86aa40e36a..f2e0122d32 100644 --- a/apps/server/src/services/search/expressions/note_content_fulltext.ts +++ b/apps/server/src/services/search/expressions/note_content_fulltext.ts @@ -107,6 +107,14 @@ class NoteContentFulltextExp extends Expression { * Whether this operator can be served by FTS5. */ private canUseFts(): boolean { + try { + const optionService = require("../../options.js").default; + if (!optionService.getOptionBool("searchEnableFts5")) { + return false; + } + } catch { + // Option not available yet — allow FTS + } return ["=", "!=", "*=*"].includes(this.operator); } diff --git a/packages/commons/src/lib/options_interface.ts b/packages/commons/src/lib/options_interface.ts index 6e36ebd7a3..555fd20a5b 100644 --- a/packages/commons/src/lib/options_interface.ts +++ b/packages/commons/src/lib/options_interface.ts @@ -137,6 +137,8 @@ export interface OptionDefinitions extends KeyboardShortcutsOptions Date: Fri, 20 Mar 2026 11:56:49 -0700 Subject: [PATCH 016/482] fix(search): fix busy connection error in FTS5 index build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Collect rows before inserting — iterateRows() holds an open cursor that conflicts with writes on the same connection. --- apps/server/src/services/search/fts_index.ts | 42 +++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/apps/server/src/services/search/fts_index.ts b/apps/server/src/services/search/fts_index.ts index 83c7616999..30359f7d19 100644 --- a/apps/server/src/services/search/fts_index.ts +++ b/apps/server/src/services/search/fts_index.ts @@ -70,28 +70,32 @@ function buildIndex(): void { sql.execute("DELETE FROM note_content_fts"); - const count = sql.transactional(() => { - let count = 0; + // Collect all rows first, then batch-insert in a transaction. + // iterateRows() holds an open cursor that conflicts with writes on the same connection. + const prepared: { noteId: string; content: string }[] = []; - for (const row of sql.iterateRows(` - SELECT noteId, type, mime, content, isProtected, isDeleted - FROM notes JOIN blobs USING (blobId) - WHERE type IN ('text', 'code', 'mermaid', 'canvas', 'mindMap') - AND isDeleted = 0 - AND content IS NOT NULL - AND LENGTH(content) < ${MAX_CONTENT_SIZE} - `)) { - const processedContent = prepareContent(row); - if (processedContent) { - sql.execute( - "INSERT INTO note_content_fts (noteId, content) VALUES (?, ?)", - [row.noteId, processedContent] - ); - count++; - } + for (const row of sql.iterateRows(` + SELECT noteId, type, mime, content, isProtected, isDeleted + FROM notes JOIN blobs USING (blobId) + WHERE type IN ('text', 'code', 'mermaid', 'canvas', 'mindMap') + AND isDeleted = 0 + AND content IS NOT NULL + AND LENGTH(content) < ${MAX_CONTENT_SIZE} + `)) { + const processedContent = prepareContent(row); + if (processedContent) { + prepared.push({ noteId: row.noteId, content: processedContent }); } + } - return count; + const count = sql.transactional(() => { + for (const { noteId, content } of prepared) { + sql.execute( + "INSERT INTO note_content_fts (noteId, content) VALUES (?, ?)", + [noteId, content] + ); + } + return prepared.length; }); const elapsed = Date.now() - startTime; From 87fc4e12811c01ea7d01ee9b32ceb54963c83803 Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Fri, 20 Mar 2026 12:00:16 -0700 Subject: [PATCH 017/482] docs(search): add FTS5 benchmark results to performance comparison Adds real SQLite benchmarks showing FTS5 is 15-33x faster for the raw content query, though end-to-end improvement is masked by JS pipeline overhead (scoring, snippets, path walking). --- docs/search-performance-benchmarks.md | 465 ++++++++++++++++++++++++++ 1 file changed, 465 insertions(+) create mode 100644 docs/search-performance-benchmarks.md diff --git a/docs/search-performance-benchmarks.md b/docs/search-performance-benchmarks.md new file mode 100644 index 0000000000..bb7411230c --- /dev/null +++ b/docs/search-performance-benchmarks.md @@ -0,0 +1,465 @@ +# Search Performance Benchmarks: `main` vs `feat/search-perf-take1` + +> **Date:** 2026-03-20 +> **Environment:** In-memory benchmarks (monkeypatched `getContent()`, no real SQLite I/O). Both branches tested on the same machine in the same session for fair comparison. All times are avg of 5 iterations with warm caches unless noted. +> **Benchmark source:** `apps/server/src/services/search/services/search_benchmark.spec.ts` + +--- + +## Table of Contents + +- [Single-Token Autocomplete](#single-token-autocomplete) +- [Multi-Token Autocomplete](#multi-token-autocomplete) +- [No-Match Queries (worst case)](#no-match-queries-worst-case) +- [Diacritics / Unicode](#diacritics--unicode) +- [Typing Progression (keystroke simulation)](#typing-progression-keystroke-simulation) +- [Long Queries (4 tokens)](#long-queries-4-tokens) +- [Attribute Matching](#attribute-matching) +- [Fuzzy Matching Effectiveness (typos & misspellings)](#fuzzy-matching-effectiveness-typos--misspellings) +- [Cache Warmth Impact (feature branch only)](#cache-warmth-impact-feature-branch-only) +- [Realistic User Session](#realistic-user-session) +- [Scale Comparison Summary](#scale-comparison-summary) + +--- + +## Single-Token Autocomplete + +The most common case — user typing in the search bar. Query: `"meeting"`. + +### Autocomplete (fuzzy OFF) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 3.6ms | 2.8ms | **-22%** | +| 5,000 | 11.9ms | 10.6ms | **-11%** | +| 10,000 | 27.5ms | 22.8ms | **-17%** | +| 20,000 | 53.7ms | 46.2ms | **-14%** | + +### Autocomplete (fuzzy ON) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 2.4ms | 2.3ms | -4% | +| 5,000 | 11.7ms | 10.7ms | **-9%** | +| 10,000 | 28.9ms | 21.6ms | **-25%** | +| 20,000 | 58.6ms | 44.5ms | **-24%** | + +### Full Search (fuzzy OFF) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 2.7ms | 4.3ms | +59% | +| 5,000 | 14.3ms | 10.8ms | **-24%** | +| 10,000 | 30.8ms | 26.9ms | **-13%** | +| 20,000 | 63.1ms | 56.7ms | **-10%** | + +### Full Search (fuzzy ON) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 2.5ms | 2.4ms | -4% | +| 5,000 | 13.0ms | 11.4ms | **-12%** | +| 10,000 | 29.8ms | 25.6ms | **-14%** | +| 20,000 | 63.4ms | 54.5ms | **-14%** | + +--- + +## Multi-Token Autocomplete + +### 2-Token: `"meeting notes"` (autocomplete, fuzzy OFF) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 3.7ms | 3.5ms | -5% | +| 5,000 | 19.0ms | 19.3ms | +2% | +| 10,000 | 40.2ms | 40.4ms | 0% | +| 20,000 | 86.1ms | 80.7ms | **-6%** | + +### 3-Token: `"meeting notes january"` (autocomplete, fuzzy OFF) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 4.1ms | 4.3ms | +5% | +| 5,000 | 25.7ms | 24.9ms | -3% | +| 10,000 | 50.9ms | 50.5ms | -1% | +| 20,000 | 104.5ms | 107.2ms | +3% | + +### 2-Token: `"meeting notes"` (full search, fuzzy OFF) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 3.4ms | 3.3ms | -3% | +| 5,000 | 22.3ms | 21.9ms | -2% | +| 10,000 | 42.9ms | 40.2ms | **-6%** | +| 20,000 | 95.8ms | 88.3ms | **-8%** | + +### 3-Token: `"meeting notes january"` (full search, fuzzy ON) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 4.4ms | 4.3ms | -2% | +| 5,000 | 26.3ms | 25.5ms | -3% | +| 10,000 | 51.7ms | 52.6ms | +2% | +| 20,000 | 113.9ms | 114.0ms | 0% | + +--- + +## No-Match Queries (worst case) + +These are the worst case — every note must be scanned with no early exit. + +### Single token: `"xyznonexistent"` (autocomplete) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 0.7ms | 0.5ms | **-29%** | +| 5,000 | 4.0ms | 3.4ms | **-15%** | +| 10,000 | 11.3ms | 7.0ms | **-38%** | +| 20,000 | 28.9ms | 19.0ms | **-34%** | + +### Single token: `"xyznonexistent"` (autocomplete, fuzzy ON) + +This is the biggest behavioral change. On `main`, autocomplete with fuzzy ON triggers the expensive two-phase search. On the feature branch, autocomplete **always skips** the fuzzy fallback phase. + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 1.7ms | 0.5ms | **-71%** | +| 5,000 | 12.8ms | 2.3ms | **-82%** | +| 10,000 | 26.4ms | 6.0ms | **-77%** | +| 20,000 | 60.4ms | 20.0ms | **-67%** | + +### Multi token: `"xyzfoo xyzbar"` (autocomplete, fuzzy ON) + +Same effect — autocomplete no longer triggers the fuzzy fallback: + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 6.5ms | 0.4ms | **-94%** | +| 5,000 | 33.9ms | 2.5ms | **-93%** | +| 10,000 | 134.5ms | 6.0ms | **-96%** | +| 20,000 | 151.8ms | 19.8ms | **-87%** | + +### Multi token: `"xyzfoo xyzbar"` (full search, fuzzy ON) + +Full search still does two-phase fuzzy on both branches, so improvement here is from the flat text index and pre-normalized attributes: + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 5.9ms | 5.8ms | -2% | +| 5,000 | 35.0ms | 33.7ms | -4% | +| 10,000 | 144.0ms | 68.8ms | **-52%** | +| 20,000 | 165.5ms | 140.6ms | **-15%** | + +--- + +## Diacritics / Unicode + +Searching `"résumé"` (with diacritics) vs `"resume"` (ASCII equivalent). Both forms find the same results thanks to diacritic normalization. + +### Autocomplete (fuzzy OFF) + +| Notes | Query | main | feature | Change | +|------:|:------|-----:|--------:|-------:| +| 1,000 | `"résumé"` | 4.1ms | 2.4ms | **-41%** | +| 1,000 | `"resume"` | 2.9ms | 2.4ms | **-17%** | +| 5,000 | `"résumé"` | 20.4ms | 15.0ms | **-26%** | +| 5,000 | `"resume"` | 18.1ms | 16.3ms | **-10%** | +| 10,000 | `"résumé"` | 40.6ms | 29.0ms | **-29%** | +| 10,000 | `"resume"` | 40.6ms | 29.5ms | **-27%** | + +--- + +## Typing Progression (keystroke simulation) + +Simulates a user typing `"documentation"` character by character. Autocomplete, fuzzy OFF. + +### 5,000 notes + +| Prefix | main | feature | Change | +|:-------|-----:|--------:|-------:| +| `"d"` | 44.7ms | 35.9ms | **-20%** | +| `"do"` | 12.9ms | 11.6ms | **-10%** | +| `"doc"` | 12.0ms | 10.2ms | **-15%** | +| `"docu"` | 10.9ms | 9.4ms | **-14%** | +| `"document"` | 9.1ms | 7.3ms | **-20%** | +| `"documentation"` | 10.3ms | 8.1ms | **-21%** | + +### 10,000 notes + +| Prefix | main | feature | Change | +|:-------|-----:|--------:|-------:| +| `"d"` | 85.4ms | 70.1ms | **-18%** | +| `"do"` | 30.0ms | 24.1ms | **-20%** | +| `"doc"` | 28.3ms | 20.8ms | **-27%** | +| `"docu"` | 24.3ms | 20.1ms | **-17%** | +| `"document"` | 19.2ms | 15.9ms | **-17%** | +| `"documentation"` | 23.0ms | 16.8ms | **-27%** | + +### 20,000 notes + +| Prefix | main | feature | Change | +|:-------|-----:|--------:|-------:| +| `"d"` | 178.3ms | 142.8ms | **-20%** | +| `"do"` | 63.7ms | 50.6ms | **-21%** | +| `"doc"` | 59.1ms | 44.0ms | **-26%** | +| `"docu"` | 59.3ms | 40.6ms | **-32%** | +| `"document"` | 45.7ms | 34.1ms | **-25%** | +| `"documentation"` | 47.4ms | 33.7ms | **-29%** | + +--- + +## Long Queries (4 tokens) + +Query: `"quarterly budget review report"` — autocomplete, fuzzy OFF. + +| Notes | Tokens | main | feature | Change | +|------:|-------:|-----:|--------:|-------:| +| 5,000 | 1 | 8.8ms | 6.5ms | **-26%** | +| 5,000 | 2 | 13.7ms | 11.0ms | **-20%** | +| 5,000 | 3 | 16.7ms | 15.1ms | **-10%** | +| 5,000 | 4 | 18.9ms | 22.3ms | +18% | +| 10,000 | 1 | 18.5ms | 15.6ms | **-16%** | +| 10,000 | 2 | 25.4ms | 24.9ms | -2% | +| 10,000 | 3 | 31.7ms | 33.3ms | +5% | +| 10,000 | 4 | 39.0ms | 40.7ms | +4% | + +--- + +## Attribute Matching + +Searching by label name (`"category"`) and label value (`"important"`). Notes have 5 labels each. + +### `"category"` (autocomplete) + +| Notes | main (fuzzy OFF) | feature (fuzzy OFF) | Change | main (fuzzy ON) | feature (fuzzy ON) | Change | +|------:|------------------:|--------------------:|-------:|----------------:|-------------------:|-------:| +| 5,000 | 12.0ms | 9.5ms | **-21%** | 34.4ms | 9.7ms | **-72%** | +| 10,000 | 26.7ms | 22.7ms | **-15%** | 77.5ms | 21.0ms | **-73%** | + +### `"important"` (autocomplete) + +| Notes | main (fuzzy OFF) | feature (fuzzy OFF) | Change | main (fuzzy ON) | feature (fuzzy ON) | Change | +|------:|------------------:|--------------------:|-------:|----------------:|-------------------:|-------:| +| 5,000 | 11.1ms | 9.2ms | **-17%** | 11.6ms | 8.8ms | **-24%** | +| 10,000 | 25.4ms | 18.7ms | **-26%** | 24.2ms | 19.4ms | **-20%** | + +--- + +## Fuzzy Matching Effectiveness (typos & misspellings) + +10K notes, keyword: `"performance"`. Shows both time and result quality. + +| Query | Fuzzy | main (time) | feature (time) | Change | main (results) | feature (results) | +|:------|:------|------------:|---------------:|-------:|---------------:|------------------:| +| `"performance"` (exact) | OFF | 26.8ms | 22.3ms | **-17%** | 1,000 | 1,000 | +| `"performance"` (exact) | ON | 18.7ms | 16.3ms | **-13%** | 1,000 | 1,000 | +| `"performanc"` (truncated) | OFF | 18.6ms | 16.4ms | **-12%** | 1,000 | 1,000 | +| `"performanc"` (truncated) | ON | 18.5ms | 15.6ms | **-16%** | 1,000 | 1,000 | +| `"preformance"` (typo) | OFF | 10.6ms | 7.9ms | **-25%** | 0 | 0 | +| `"preformance"` (typo) | ON | 55.1ms | 43.4ms | **-21%** | 1,000 | 1,000 | +| `"performence"` (misspelling) | OFF | 11.5ms | 8.8ms | **-23%** | 0 | 0 | +| `"performence"` (misspelling) | ON | 56.2ms | 48.3ms | **-14%** | 1,000 | 1,000 | +| `"optimization"` | OFF | 12.6ms | 9.9ms | **-21%** | 0 | 0 | +| `"optimization"` | ON | 37.2ms | 31.6ms | **-15%** | 0 | 0 | +| `"optimzation"` (typo) | OFF | 11.6ms | 8.1ms | **-30%** | 0 | 0 | +| `"optimzation"` (typo) | ON | 44.5ms | 31.3ms | **-30%** | 0 | 0 | +| `"perf optim"` (abbreviated) | OFF | 16.5ms | 11.8ms | **-28%** | 0 | 0 | +| `"perf optim"` (abbreviated) | ON | 74.9ms | 67.2ms | **-10%** | 0 | 0 | + +**Key insight:** Fuzzy matching is equally effective on both branches (same result counts). The feature branch is simply faster at executing it. + +--- + +## Cache Warmth Impact (feature branch only) + +This section only applies to the feature branch, which introduces a new flat text index cache in Becca. `main` does not have this cache. + +| Scenario | Time | +|:---------|------:| +| Cold (first search, builds index + search) | 61.7ms | +| Warm (reuse existing index, avg of 5 runs) | 25.6ms (avg), 19.8ms (min) | +| Incremental (50 notes dirtied, then search) | 21.1ms | +| Full rebuild (index invalidated, then search) | 20.7ms | + +The first search after startup pays a one-time index build cost (~2.4x). All subsequent searches reuse the cached index. When individual notes change, only their entries are recomputed. + +--- + +## Realistic User Session + +Simulates a typical user session at 10K notes with mixed query types and typos. + +| Query | Mode | main | feature | Change | +|:------|:-----|-----:|--------:|-------:| +| `"pro"` | autocomplete | 26.9ms | 24.6ms | **-9%** | +| `"project"` | autocomplete | 28.3ms | 24.1ms | **-15%** | +| `"project plan"` | autocomplete | 35.6ms | 35.0ms | -2% | +| `"project"` | fullSearch | 32.8ms | 30.0ms | **-9%** | +| `"project planning"` | fullSearch | 37.2ms | 36.4ms | -2% | +| `"project planning"` | fullSearch+fuzzy | 36.5ms | 35.9ms | -2% | +| `"projct"` (typo) | autocomplete | 11.4ms | 6.0ms | **-47%** | +| `"projct"` (typo) | autocomplete+fuzzy | **81.2ms** | **6.7ms** | **-92%** | +| `"projct planing"` (typo) | fullSearch | 12.5ms | 8.8ms | **-30%** | +| `"projct planing"` (typo) | fullSearch+fuzzy | 116.6ms | 113.2ms | -3% | +| `"xyznonexistent"` | autocomplete | 11.4ms | 6.7ms | **-41%** | +| `"xyznonexistent foo"` | fullSearch+fuzzy | 37.4ms | 23.2ms | **-38%** | +| `"note"` (very common) | autocomplete | **106.0ms** | **92.3ms** | **-13%** | +| `"document"` | autocomplete | 24.7ms | 20.7ms | **-16%** | + +**Biggest win:** `"projct"` autocomplete+fuzzy goes from 81.2ms to 6.7ms (**-92%**) because the feature branch skips the fuzzy fallback phase for autocomplete entirely. + +--- + +## Scale Comparison Summary + +Side-by-side comparison across all note counts for the most common query patterns. + +### `"meeting"` autocomplete (fuzzy OFF) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 3.6ms | 2.3ms | **-36%** | +| 5,000 | 11.4ms | 12.2ms | +7% | +| 10,000 | 25.1ms | 22.9ms | **-9%** | +| 20,000 | 59.4ms | 52.3ms | **-12%** | + +### `"meeting notes"` autocomplete (fuzzy OFF) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 4.0ms | 2.7ms | **-33%** | +| 5,000 | 15.9ms | 17.2ms | +8% | +| 10,000 | 36.1ms | 34.2ms | **-5%** | +| 20,000 | 71.0ms | 72.9ms | +3% | + +### `"meeting"` fullSearch (fuzzy ON) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 2.5ms | 2.4ms | -4% | +| 5,000 | 12.1ms | 13.1ms | +8% | +| 10,000 | 27.8ms | 27.1ms | -3% | +| 20,000 | 67.2ms | 57.8ms | **-14%** | + +### `"xyznonexistent"` autocomplete (fuzzy OFF) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 1.3ms | 0.5ms | **-62%** | +| 5,000 | 3.1ms | 2.5ms | **-19%** | +| 10,000 | 7.7ms | 9.4ms | +22% | +| 20,000 | 22.4ms | 16.6ms | **-26%** | + +### `"xyznonexistent"` fullSearch (fuzzy ON) — worst case path + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 2.7ms | 2.5ms | -7% | +| 5,000 | 11.2ms | 9.7ms | **-13%** | +| 10,000 | 25.4ms | 30.3ms | +19% | +| 20,000 | 68.7ms | 55.2ms | **-20%** | + +--- + +## Summary of Improvements + +### Where the feature branch clearly wins (consistent 10-30% improvement): +- **Single-token autocomplete** at all scales (10-25% faster) +- **Diacritics queries** (26-41% faster at 10K notes) +- **Typing progression** (17-32% faster per keystroke at 20K notes) +- **Fuzzy typo searches** (14-30% faster while finding same results) +- **Broad term autocomplete** (e.g., `"note"` matching 8,500 results: 13% faster) + +### Where the feature branch dramatically wins (50%+ improvement): +- **Autocomplete with fuzzy ON, no-match queries** (67-96% faster — fuzzy fallback skipped entirely) +- **Autocomplete typo queries** (e.g., `"projct"` + fuzzy: 81ms -> 7ms, **-92%**) + +### Where performance is roughly equal (within noise): +- Multi-token queries at smaller scales (1-5K notes) +- Full search with fuzzy ON when there are sufficient exact matches (fuzzy phase skipped on both branches) + +### Trade-offs: +- Some individual data points show slight regressions at 5K scale (+2-8%), likely noise from shared-machine benchmarking +- Long queries (4 tokens) at 5K notes show a small regression (+18%), but this evens out at 10K +- The new flat text index has a one-time build cost on first search (~62ms at 10K notes), amortized across all subsequent searches + +--- + +## FTS5 Content Index Benchmarks + +> These benchmarks use the **real SQLite database** with actual blob content (not monkeypatched). They test the `fastSearch=false` path that users hit when pressing Enter in search or using saved searches. This is the path that was taking **seconds** in production. + +### The Architecture + +When `fastSearch=false`, the expression tree is `OrExp([NoteFlatTextExp, NoteContentFulltextExp])`. Both expressions run: +- **NoteFlatTextExp**: In-memory scan of titles/attributes (fast — 5-25ms) +- **NoteContentFulltextExp**: Scans ALL note content from SQLite blobs (slow — the bottleneck) + +FTS5 replaces the sequential blob scan in `NoteContentFulltextExp` with an indexed FTS5 MATCH query. + +### FTS5 Query-Only Performance (isolating the content scan) + +This measures just the content search portion, stripped of the expression tree, scoring, and snippet extraction overhead. + +| Notes | FTS5 MATCH query | Sequential SQL scan | FTS5 Speedup | +|------:|-----------------:|--------------------:|-------------:| +| 1,000 | **0.2ms** | 3.6ms | **15x** | +| 5,000 | **0.5ms** | 16.0ms | **33x** | +| 10,000 | **1.1ms** | 36.4ms | **32x** | + +FTS5 is **15-33x faster** than the sequential scan for the raw content query. + +### Why Full Search Doesn't Show the Same Speedup + +When measured end-to-end through `findResultsWithQuery()` with `fastSearch=false`: + +| Notes | Query | FTS5 | Sequential | Speedup | +|------:|:------|-----:|-----------:|--------:| +| 1,000 | `"performance"` | 52.1ms | 48.3ms | 0.9x | +| 5,000 | `"performance"` | 233.4ms | 227.6ms | 1.0x | +| 10,000 | `"performance"` | 517.3ms | 515.9ms | 1.0x | +| 1,000 | `"xyznonexistent"` | 46.2ms | 57.6ms | 1.2x | +| 5,000 | `"xyznonexistent"` | 272.9ms | 229.3ms | 0.8x | +| 10,000 | `"xyznonexistent"` | 460.3ms | 468.3ms | 1.0x | + +The FTS5 query itself is 32x faster, but it's **drowned out by the rest of the pipeline**: + +| Component | Time at 10K notes | % of total | +|:----------|------------------:|-----------:| +| `NoteFlatTextExp` (in-memory scan) | ~25ms | ~5% | +| `NoteContentFulltextExp` content scan | 1-36ms | ~1-7% | +| Scoring (`computeScore` per result) | ~100-200ms | ~20-40% | +| Snippet extraction | ~50-100ms | ~10-20% | +| Highlighting | ~50ms | ~10% | +| `searchPathTowardsRoot` recursion | ~100-200ms | ~20-40% | + +The content scan (which FTS5 replaces) is only **1-7% of total search time** in this benchmark. The real bottleneck at this scale is scoring, snippet extraction, and the recursive parent-path walk — all JavaScript operations that FTS5 doesn't affect. + +### Where FTS5 Will Matter Most + +FTS5 will show significant real-world improvement when: +1. **Database is large (50K-200K+ notes)** — The sequential scan reads every blob from disk. At 200K notes with varying content sizes, the I/O cost dominates. FTS5 eliminates this entirely. +2. **Notes have large content** — The benchmark uses 300-word notes (~2KB each). Real notes can be 10KB-100KB+. The sequential scan reads and preprocesses ALL of that content; FTS5 returns noteIds without touching content blobs. +3. **Disk is slow** — These benchmarks run on fast local SSD. On slower storage (network drives, spinning disks, Docker volumes), the I/O savings from FTS5 will be dramatic. + +### FTS5 Index Build Cost + +| Notes | Build time | Notes indexed | +|------:|-----------:|--------------:| +| 1,000 | 213ms | 1,015 | +| 5,000 | 943ms | 5,015 | +| 10,000 | 2,720ms | 10,015 | + +The index builds lazily on first search and is maintained incrementally via `NOTE_CONTENT_CHANGE` events. Users using `unicode61` tokenizer (not trigram) keeps the index compact. + +### Reference: Autocomplete (fastSearch=true) — Not Affected by FTS5 + +For comparison, the in-memory autocomplete path remains fast: + +| Notes | `"performance"` | `"performance optimization"` | +|------:|-----------------:|-----------------------------:| +| 1,000 | 5.2ms | 1.4ms | +| 5,000 | 10.1ms | 3.7ms | +| 10,000 | 24.4ms | 10.4ms | + +These don't use FTS5 at all — they use the `NoteFlatTextExp` in-memory path optimized by the earlier commits in this PR. From ac231374f69d44a8c960a95998c7774aca8a80bb Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Fri, 20 Mar 2026 12:07:28 -0700 Subject: [PATCH 018/482] perf(search): optimize scoring, highlighting, and tree walk - Remove redundant toLowerCase() before normalizeSearchText() in search_result.ts (normalizeSearchText already lowercases) - Pre-normalize tokens once in addScoreForStrings instead of per-chunk - Skip edit distance computation entirely when fuzzy matching is disabled - Move removeDiacritic() outside the regex while-loop in highlighting - Cache normalized parent titles per search execution in note_flat_text.ts - Use Set for token lookup in searchPathTowardsRoot (O(1) vs O(n)) - Remove redundant toLowerCase in fuzzyMatchWordWithResult (inputs from smartMatch are already normalized) --- .../search/expressions/note_flat_text.ts | 36 ++++++++++------- .../src/services/search/search_result.ts | 39 ++++++++++--------- .../src/services/search/services/search.ts | 19 +++++---- .../src/services/search/utils/text_utils.ts | 24 ++++++------ 4 files changed, 65 insertions(+), 53 deletions(-) diff --git a/apps/server/src/services/search/expressions/note_flat_text.ts b/apps/server/src/services/search/expressions/note_flat_text.ts index ef3efbf66f..b12413738e 100644 --- a/apps/server/src/services/search/expressions/note_flat_text.ts +++ b/apps/server/src/services/search/expressions/note_flat_text.ts @@ -23,6 +23,18 @@ class NoteFlatTextExp extends Expression { execute(inputNoteSet: NoteSet, executionContext: any, searchContext: SearchContext) { const resultNoteSet = new NoteSet(); + // Cache normalized titles to avoid redundant normalize+getNoteTitle calls + const titleCache = new Map(); + const getNormalizedTitle = (noteId: string, parentNoteId: string): string => { + const key = `${noteId}-${parentNoteId}`; + let cached = titleCache.get(key); + if (cached === undefined) { + cached = normalizeSearchText(beccaService.getNoteTitle(noteId, parentNoteId)); + titleCache.set(key, cached); + } + return cached; + }; + /** * @param note * @param remainingTokens - tokens still needed to be found in the path towards root @@ -38,10 +50,8 @@ class NoteFlatTextExp extends Expression { const noteId = resultPath[resultPath.length - 1]; if (!resultNoteSet.hasNoteId(noteId)) { - // we could get here from multiple paths, the first one wins because the paths - // are sorted by importance + // Snapshot takenPath since it's mutable executionContext.noteIdToNotePath[noteId] = resultPath; - resultNoteSet.add(becca.notes[noteId]); } } @@ -50,18 +60,14 @@ class NoteFlatTextExp extends Expression { } if (note.parents.length === 0 || note.noteId === "root") { - // we've reached root, but there are still remaining tokens -> this candidate note produced no result return; } const foundAttrTokens: string[] = []; for (const token of remainingTokens) { - // Add defensive checks for undefined properties - const typeMatches = note.type && note.type.includes(token); - const mimeMatches = note.mime && note.mime.includes(token); - - if (typeMatches || mimeMatches) { + if ((note.type && note.type.includes(token)) || + (note.mime && note.mime.includes(token))) { foundAttrTokens.push(token); } } @@ -75,17 +81,19 @@ class NoteFlatTextExp extends Expression { } for (const parentNote of note.parents) { - const title = normalizeSearchText(beccaService.getNoteTitle(note.noteId, parentNote.noteId)); - const foundTokens: string[] = foundAttrTokens.slice(); + const title = getNormalizedTitle(note.noteId, parentNote.noteId); + + // Use Set for O(1) lookup instead of Array.includes() which is O(n) + const foundTokenSet = new Set(foundAttrTokens); for (const token of remainingTokens) { if (this.smartMatch(title, token, searchContext)) { - foundTokens.push(token); + foundTokenSet.add(token); } } - if (foundTokens.length > 0) { - const newRemainingTokens = remainingTokens.filter((token) => !foundTokens.includes(token)); + if (foundTokenSet.size > 0) { + const newRemainingTokens = remainingTokens.filter((token) => !foundTokenSet.has(token)); searchPathTowardsRoot(parentNote, newRemainingTokens, [note.noteId, ...takenPath]); } else { diff --git a/apps/server/src/services/search/search_result.ts b/apps/server/src/services/search/search_result.ts index bf8a33524b..57e2417cf7 100644 --- a/apps/server/src/services/search/search_result.ts +++ b/apps/server/src/services/search/search_result.ts @@ -59,8 +59,9 @@ class SearchResult { this.fuzzyScore = 0; // Reset fuzzy score tracking const note = becca.notes[this.noteId]; - const normalizedQuery = normalizeSearchText(fulltextQuery.toLowerCase()); - const normalizedTitle = normalizeSearchText(note.title.toLowerCase()); + // normalizeSearchText already lowercases — no need for .toLowerCase() first + const normalizedQuery = normalizeSearchText(fulltextQuery); + const normalizedTitle = normalizeSearchText(note.title); // Note ID exact match, much higher score if (note.noteId.toLowerCase() === fulltextQuery) { @@ -91,35 +92,37 @@ class SearchResult { } addScoreForStrings(tokens: string[], str: string, factor: number, enableFuzzyMatching: boolean = true) { - const normalizedStr = normalizeSearchText(str.toLowerCase()); + // normalizeSearchText already lowercases — no need for .toLowerCase() first + const normalizedStr = normalizeSearchText(str); const chunks = normalizedStr.split(" "); + // Pre-normalize tokens once instead of per-chunk + const normalizedTokens = tokens.map(t => normalizeSearchText(t)); + let tokenScore = 0; for (const chunk of chunks) { - for (const token of tokens) { - const normalizedToken = normalizeSearchText(token.toLowerCase()); - + for (let ti = 0; ti < normalizedTokens.length; ti++) { + const normalizedToken = normalizedTokens[ti]; + if (chunk === normalizedToken) { - tokenScore += SCORE_WEIGHTS.TOKEN_EXACT_MATCH * token.length * factor; + tokenScore += SCORE_WEIGHTS.TOKEN_EXACT_MATCH * tokens[ti].length * factor; } else if (chunk.startsWith(normalizedToken)) { - tokenScore += SCORE_WEIGHTS.TOKEN_PREFIX_MATCH * token.length * factor; + tokenScore += SCORE_WEIGHTS.TOKEN_PREFIX_MATCH * tokens[ti].length * factor; } else if (chunk.includes(normalizedToken)) { - tokenScore += SCORE_WEIGHTS.TOKEN_CONTAINS_MATCH * token.length * factor; - } else { - // Try fuzzy matching for individual tokens with caps applied + tokenScore += SCORE_WEIGHTS.TOKEN_CONTAINS_MATCH * tokens[ti].length * factor; + } else if (enableFuzzyMatching && + normalizedToken.length >= FUZZY_SEARCH_CONFIG.MIN_FUZZY_TOKEN_LENGTH && + this.fuzzyScore < SCORE_WEIGHTS.MAX_TOTAL_FUZZY_SCORE) { + // Only compute edit distance when fuzzy matching is enabled const editDistance = calculateOptimizedEditDistance(chunk, normalizedToken, FUZZY_SEARCH_CONFIG.MAX_EDIT_DISTANCE); - if (editDistance <= FUZZY_SEARCH_CONFIG.MAX_EDIT_DISTANCE && - normalizedToken.length >= FUZZY_SEARCH_CONFIG.MIN_FUZZY_TOKEN_LENGTH && - this.fuzzyScore < SCORE_WEIGHTS.MAX_TOTAL_FUZZY_SCORE) { - + if (editDistance <= FUZZY_SEARCH_CONFIG.MAX_EDIT_DISTANCE) { const fuzzyWeight = SCORE_WEIGHTS.TOKEN_FUZZY_MATCH * (1 - editDistance / FUZZY_SEARCH_CONFIG.MAX_EDIT_DISTANCE); - // Apply caps: limit token length multiplier and per-token contribution - const cappedTokenLength = Math.min(token.length, SCORE_WEIGHTS.MAX_FUZZY_TOKEN_LENGTH_MULTIPLIER); + const cappedTokenLength = Math.min(tokens[ti].length, SCORE_WEIGHTS.MAX_FUZZY_TOKEN_LENGTH_MULTIPLIER); const fuzzyTokenScore = Math.min( fuzzyWeight * cappedTokenLength * factor, SCORE_WEIGHTS.MAX_FUZZY_SCORE_PER_TOKEN ); - + tokenScore += fuzzyTokenScore; this.fuzzyScore += fuzzyTokenScore; } diff --git a/apps/server/src/services/search/services/search.ts b/apps/server/src/services/search/services/search.ts index b533c185fe..49eb6d0d71 100644 --- a/apps/server/src/services/search/services/search.ts +++ b/apps/server/src/services/search/services/search.ts @@ -722,37 +722,40 @@ function highlightSearchResults(searchResults: SearchResult[], highlightedTokens } for (const result of searchResults) { - // Reset token - const tokenRegex = new RegExp(escapeRegExp(token), "gi"); let match; // Highlight in note path title if (result.highlightedNotePathTitle) { const titleRegex = new RegExp(escapeRegExp(token), "gi"); - while ((match = titleRegex.exec(removeDiacritic(result.highlightedNotePathTitle))) !== null) { + // Compute diacritic-free version ONCE before the loop, not on every iteration + let titleNoDiacritics = removeDiacritic(result.highlightedNotePathTitle); + while ((match = titleRegex.exec(titleNoDiacritics)) !== null) { result.highlightedNotePathTitle = wrapText(result.highlightedNotePathTitle, match.index, token.length, "{", "}"); - // 2 characters are added, so we need to adjust the index + // 2 characters are added, so we need to adjust the index and re-derive titleRegex.lastIndex += 2; + titleNoDiacritics = removeDiacritic(result.highlightedNotePathTitle); } } // Highlight in content snippet if (result.highlightedContentSnippet) { const contentRegex = new RegExp(escapeRegExp(token), "gi"); - while ((match = contentRegex.exec(removeDiacritic(result.highlightedContentSnippet))) !== null) { + let contentNoDiacritics = removeDiacritic(result.highlightedContentSnippet); + while ((match = contentRegex.exec(contentNoDiacritics)) !== null) { result.highlightedContentSnippet = wrapText(result.highlightedContentSnippet, match.index, token.length, "{", "}"); - // 2 characters are added, so we need to adjust the index contentRegex.lastIndex += 2; + contentNoDiacritics = removeDiacritic(result.highlightedContentSnippet); } } // Highlight in attribute snippet if (result.highlightedAttributeSnippet) { const attributeRegex = new RegExp(escapeRegExp(token), "gi"); - while ((match = attributeRegex.exec(removeDiacritic(result.highlightedAttributeSnippet))) !== null) { + let attrNoDiacritics = removeDiacritic(result.highlightedAttributeSnippet); + while ((match = attributeRegex.exec(attrNoDiacritics)) !== null) { result.highlightedAttributeSnippet = wrapText(result.highlightedAttributeSnippet, match.index, token.length, "{", "}"); - // 2 characters are added, so we need to adjust the index attributeRegex.lastIndex += 2; + attrNoDiacritics = removeDiacritic(result.highlightedAttributeSnippet); } } } diff --git a/apps/server/src/services/search/utils/text_utils.ts b/apps/server/src/services/search/utils/text_utils.ts index 9274241cbc..94df2f3dd1 100644 --- a/apps/server/src/services/search/utils/text_utils.ts +++ b/apps/server/src/services/search/utils/text_utils.ts @@ -275,21 +275,19 @@ export function fuzzyMatchWordWithResult(token: string, text: string, maxDistanc } try { - // Normalize both strings for comparison - const normalizedToken = token.toLowerCase(); - const normalizedText = text.toLowerCase(); - + // Inputs from smartMatch() are already normalized (lowercased, diacritics removed). + // Skip redundant toLowerCase() — just use the inputs directly. + // Exact match check first (most common case) - if (normalizedText.includes(normalizedToken)) { - // Find the exact match in the original text to preserve case - const exactMatch = text.match(new RegExp(escapeRegExp(token), 'i')); - return exactMatch ? exactMatch[0] : token; + if (text.includes(token)) { + return token; } - - // For fuzzy matching, we need to check individual words in the text - // Split the text into words and check each word against the token - const words = normalizedText.split(/\s+/).filter(word => word.length > 0); - const originalWords = text.split(/\s+/).filter(word => word.length > 0); + + // For fuzzy matching, we need to check individual words in the text. + // Split into words and check each word against the token. + // Inputs are already normalized so we don't need a separate originalWords array. + const words = text.split(/\s+/); + const originalWords = words; for (let i = 0; i < words.length; i++) { const word = words[i]; From 48dd93b94b87e717bbcd0adb6d3d1b993b909015 Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Fri, 20 Mar 2026 12:16:40 -0700 Subject: [PATCH 019/482] revert: remove FTS5 content search (no measured end-to-end improvement) FTS5 query was 32x faster in isolation, but the content scan is only 1-7% of total search time. The JS pipeline (scoring, snippets, highlighting, tree walk) dominates. The in-memory optimizations in this PR provide the real gains. Removes: migration, fts_index service, event wiring, UI option, integration test. Keeps all in-memory performance optimizations. --- .../src/translations/en/translation.json | 3 +- .../widgets/type_widgets/options/other.tsx | 7 - apps/server/spec/fts5_search.spec.ts | 76 -------- .../0235__add_fts5_content_search.ts | 14 -- apps/server/src/migrations/migrations.ts | 5 - apps/server/src/routes/api/options.ts | 1 - apps/server/src/services/handlers.ts | 21 -- apps/server/src/services/options_init.ts | 1 - .../expressions/note_content_fulltext.ts | 132 ++++--------- .../src/services/search/fts_index.spec.ts | 13 -- apps/server/src/services/search/fts_index.ts | 182 ------------------ docs/search-performance-benchmarks.md | 81 -------- packages/commons/src/lib/options_interface.ts | 2 - 13 files changed, 38 insertions(+), 500 deletions(-) delete mode 100644 apps/server/spec/fts5_search.spec.ts delete mode 100644 apps/server/src/migrations/0235__add_fts5_content_search.ts delete mode 100644 apps/server/src/services/search/fts_index.spec.ts delete mode 100644 apps/server/src/services/search/fts_index.ts diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 5232fa1dc1..f9ba8f8743 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -1294,8 +1294,7 @@ }, "search": { "title": "Search", - "enable_fuzzy_matching": "Enable fuzzy matching in search (matches similar words when exact matches are insufficient)", - "enable_fts5": "Use content index for faster full-text search (applies on next search)" + "enable_fuzzy_matching": "Enable fuzzy matching in search (matches similar words when exact matches are insufficient)" }, "search_engine": { "title": "Search Engine", diff --git a/apps/client/src/widgets/type_widgets/options/other.tsx b/apps/client/src/widgets/type_widgets/options/other.tsx index c16fffc891..8cb99bace4 100644 --- a/apps/client/src/widgets/type_widgets/options/other.tsx +++ b/apps/client/src/widgets/type_widgets/options/other.tsx @@ -39,7 +39,6 @@ export default function OtherSettings() { function SearchSettings() { const [ fuzzyEnabled, setFuzzyEnabled ] = useTriliumOptionBool("searchEnableFuzzyMatching"); - const [ fts5Enabled, setFts5Enabled ] = useTriliumOptionBool("searchEnableFts5"); return ( @@ -49,12 +48,6 @@ function SearchSettings() { currentValue={fuzzyEnabled} onChange={setFuzzyEnabled} /> - ); } diff --git a/apps/server/spec/fts5_search.spec.ts b/apps/server/spec/fts5_search.spec.ts deleted file mode 100644 index 7d6ed7483a..0000000000 --- a/apps/server/spec/fts5_search.spec.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { Application } from "express"; -import { beforeAll, describe, expect, it } from "vitest"; -import config from "../src/services/config.js"; - -let app: Application; - -function timed(fn: () => T): [T, number] { - const start = performance.now(); - const result = fn(); - return [result, performance.now() - start]; -} - -describe("FTS5 Content Search (integration)", () => { - beforeAll(async () => { - config.General.noAuthentication = true; - const buildApp = (await import("../src/app.js")).default; - app = await buildApp(); - }); - - it("FTS5 index builds and searches correctly", async () => { - const sql = (await import("../src/services/sql.js")).default; - const becca = (await import("../src/becca/becca.js")).default; - const ftsIndex = (await import("../src/services/search/fts_index.js")).default; - const cls = (await import("../src/services/cls.js")).default; - - await new Promise((resolve) => { - cls.init(() => { - // Check if FTS table exists (migration may not have run on test DB) - const tableExists = sql.getValue( - "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='note_content_fts'" - ); - - if (!tableExists) { - // Create the table for testing - sql.execute(` - CREATE VIRTUAL TABLE IF NOT EXISTS note_content_fts USING fts5( - noteId UNINDEXED, - content, - tokenize='unicode61 remove_diacritics 2' - ) - `); - } - - const noteCount = Object.keys(becca.notes).length; - console.log(`\n Notes in becca: ${noteCount}`); - - // Build the index - ftsIndex.resetIndex(); - const [, buildMs] = timed(() => ftsIndex.buildIndex()); - console.log(` FTS index build: ${buildMs.toFixed(0)}ms`); - - // Verify index has content - const indexedCount = sql.getValue("SELECT COUNT(*) FROM note_content_fts"); - console.log(` Notes indexed: ${indexedCount}`); - expect(indexedCount).toBeGreaterThanOrEqual(0); - - // If we have indexed content, test search - if (indexedCount > 0) { - const [results, searchMs] = timed(() => ftsIndex.searchContent(["note"], "*=*")); - console.log(` FTS search "note": ${searchMs.toFixed(1)}ms (${results.length} results)`); - expect(results).toBeInstanceOf(Array); - } - - // Test update and remove don't throw - expect(() => ftsIndex.updateNote("nonexistent")).not.toThrow(); - expect(() => ftsIndex.removeNote("nonexistent")).not.toThrow(); - - // Clean up - sql.execute("DELETE FROM note_content_fts"); - ftsIndex.resetIndex(); - - resolve(); - }); - }); - }); -}); diff --git a/apps/server/src/migrations/0235__add_fts5_content_search.ts b/apps/server/src/migrations/0235__add_fts5_content_search.ts deleted file mode 100644 index d0767d51b4..0000000000 --- a/apps/server/src/migrations/0235__add_fts5_content_search.ts +++ /dev/null @@ -1,14 +0,0 @@ -import sql from "../services/sql.js"; -import log from "../services/log.js"; - -export default () => { - sql.execute(/*sql*/` - CREATE VIRTUAL TABLE IF NOT EXISTS note_content_fts USING fts5( - noteId UNINDEXED, - content, - tokenize='unicode61 remove_diacritics 2' - ) - `); - - log.info("Created note_content_fts table. FTS index will be populated on first search."); -}; diff --git a/apps/server/src/migrations/migrations.ts b/apps/server/src/migrations/migrations.ts index e9f8b8d72d..7aca1f802b 100644 --- a/apps/server/src/migrations/migrations.ts +++ b/apps/server/src/migrations/migrations.ts @@ -6,11 +6,6 @@ // Migrations should be kept in descending order, so the latest migration is first. const MIGRATIONS: (SqlMigration | JsMigration)[] = [ - // Add FTS5 virtual table for full-text content search - { - version: 235, - module: async () => import("./0235__add_fts5_content_search.js") - }, // Migrate aiChat notes to code notes since LLM integration has been removed { version: 234, diff --git a/apps/server/src/routes/api/options.ts b/apps/server/src/routes/api/options.ts index 5491fbf31e..049a898fca 100644 --- a/apps/server/src/routes/api/options.ts +++ b/apps/server/src/routes/api/options.ts @@ -98,7 +98,6 @@ const ALLOWED_OPTIONS = new Set([ "backgroundEffects", "allowedHtmlTags", "searchEnableFuzzyMatching", - "searchEnableFts5", "redirectBareDomain", "showLoginInShareTheme", "splitEditorOrientation", diff --git a/apps/server/src/services/handlers.ts b/apps/server/src/services/handlers.ts index 89647d8d83..f32bf6ddd0 100644 --- a/apps/server/src/services/handlers.ts +++ b/apps/server/src/services/handlers.ts @@ -60,17 +60,6 @@ eventService.subscribe([eventService.ENTITY_CHANGED, eventService.ENTITY_DELETED } else if (entityName === "notes") { // ENTITY_DELETED won't trigger anything since all branches/attributes are already deleted at this point runAttachedRelations(entity, "runOnNoteChange", entity); - - if (entity.isDeleted) { - try { - const ftsIndex = require("./search/fts_index.js").default; - if (ftsIndex.isIndexBuilt()) { - ftsIndex.removeNote(entity.noteId); - } - } catch { - // FTS index update failure should not block note operations - } - } } }); @@ -92,16 +81,6 @@ eventService.subscribe(eventService.ENTITY_CHANGED, ({ entityName, entity }) => eventService.subscribe(eventService.NOTE_CONTENT_CHANGE, ({ entity }) => { runAttachedRelations(entity, "runOnNoteContentChange", entity); - - // Update FTS content index incrementally - try { - const ftsIndex = require("./search/fts_index.js").default; - if (ftsIndex.isIndexBuilt()) { - ftsIndex.updateNote(entity.noteId); - } - } catch { - // FTS index update failure should not block note saves - } }); eventService.subscribe(eventService.ENTITY_CREATED, ({ entityName, entity }) => { diff --git a/apps/server/src/services/options_init.ts b/apps/server/src/services/options_init.ts index de22bbaafd..17ea5a1f0b 100644 --- a/apps/server/src/services/options_init.ts +++ b/apps/server/src/services/options_init.ts @@ -200,7 +200,6 @@ const defaultOptions: DefaultOption[] = [ // Search settings { name: "searchEnableFuzzyMatching", value: "true", isSynced: true }, - { name: "searchEnableFts5", value: "true", isSynced: true }, // Share settings { name: "redirectBareDomain", value: "false", isSynced: true }, diff --git a/apps/server/src/services/search/expressions/note_content_fulltext.ts b/apps/server/src/services/search/expressions/note_content_fulltext.ts index f2e0122d32..f3e0a39333 100644 --- a/apps/server/src/services/search/expressions/note_content_fulltext.ts +++ b/apps/server/src/services/search/expressions/note_content_fulltext.ts @@ -79,17 +79,7 @@ class NoteContentFulltextExp extends Expression { const resultNoteSet = new NoteSet(); - // Try FTS5 index first for supported operators - if (this.canUseFts()) { - const ftsWorked = this.searchViaFts(inputNoteSet, resultNoteSet); - if (ftsWorked) { - this.searchFlatTextAttributes(inputNoteSet, resultNoteSet); - return resultNoteSet; - } - // FTS unavailable or failed — fall through to sequential scan - } - - // Fallback: sequential scan (original behavior) + // Search through notes with content for (const row of sql.iterateRows(` SELECT noteId, type, mime, content, isProtected FROM notes JOIN blobs USING (blobId) @@ -99,93 +89,45 @@ class NoteContentFulltextExp extends Expression { this.findInText(row, inputNoteSet, resultNoteSet); } - this.searchFlatTextAttributes(inputNoteSet, resultNoteSet); + // For exact match with flatText, also search notes WITHOUT content (they may have matching attributes) + if (this.flatText && (this.operator === "=" || this.operator === "!=")) { + for (const note of inputNoteSet.notes) { + // Skip if already found or doesn't exist + if (resultNoteSet.hasNoteId(note.noteId) || !(note.noteId in becca.notes)) { + continue; + } + + const noteFromBecca = becca.notes[note.noteId]; + const flatText = noteFromBecca.getFlatText(); + + // For flatText, only check attribute values (format: #name=value or ~name=value) + // Don't match against noteId, type, mime, or title which are also in flatText + let matches = false; + const phrase = this.tokens.join(" "); + const normalizedPhrase = normalizeSearchText(phrase); + const normalizedFlatText = normalizeSearchText(flatText); + + // Check if =phrase appears in flatText (indicates attribute value match) + // For single words, use word-boundary matching to avoid substring matches + if (!normalizedPhrase.includes(' ')) { + // Single word: look for =word with word boundaries + // Split by = to get attribute values, then check each value for exact word match + const parts = normalizedFlatText.split('='); + matches = parts.slice(1).some(part => this.exactWordMatch(normalizedPhrase, part)); + } else { + // Multi-word phrase: check for substring match + matches = normalizedFlatText.includes(`=${normalizedPhrase}`); + } + + if ((this.operator === "=" && matches) || (this.operator === "!=" && !matches)) { + resultNoteSet.add(noteFromBecca); + } + } + } + return resultNoteSet; } - /** - * Whether this operator can be served by FTS5. - */ - private canUseFts(): boolean { - try { - const optionService = require("../../options.js").default; - if (!optionService.getOptionBool("searchEnableFts5")) { - return false; - } - } catch { - // Option not available yet — allow FTS - } - return ["=", "!=", "*=*"].includes(this.operator); - } - - /** - * Attempts to use the FTS5 index for content search. - * Returns true if FTS was used successfully, false to fall back to sequential scan. - */ - private searchViaFts(inputNoteSet: NoteSet, resultNoteSet: NoteSet): boolean { - try { - const ftsIndex = require("../fts_index.js").default; - const matchingNoteIds = ftsIndex.searchContent(this.tokens, this.operator); - - for (const noteId of matchingNoteIds) { - if (inputNoteSet.hasNoteId(noteId) && noteId in becca.notes) { - if (this.operator === "!=") { - continue; - } - resultNoteSet.add(becca.notes[noteId]); - } - } - - if (this.operator === "!=") { - const matchingSet = new Set(matchingNoteIds); - for (const note of inputNoteSet.notes) { - if (!matchingSet.has(note.noteId) && note.noteId in becca.notes) { - resultNoteSet.add(becca.notes[note.noteId]); - } - } - } - - return true; - } catch { - return false; - } - } - - /** - * Searches flat text attributes for = and != operators. - * Extracted from the old execute() tail. - */ - private searchFlatTextAttributes(inputNoteSet: NoteSet, resultNoteSet: NoteSet): void { - if (!this.flatText || (this.operator !== "=" && this.operator !== "!=")) { - return; - } - - for (const note of inputNoteSet.notes) { - if (resultNoteSet.hasNoteId(note.noteId) || !(note.noteId in becca.notes)) { - continue; - } - - const noteFromBecca = becca.notes[note.noteId]; - const flatText = noteFromBecca.getFlatText(); - - let matches = false; - const phrase = this.tokens.join(" "); - const normalizedPhrase = normalizeSearchText(phrase); - const normalizedFlatText = normalizeSearchText(flatText); - - if (!normalizedPhrase.includes(' ')) { - const parts = normalizedFlatText.split('='); - matches = parts.slice(1).some(part => this.exactWordMatch(normalizedPhrase, part)); - } else { - matches = normalizedFlatText.includes(`=${normalizedPhrase}`); - } - - if ((this.operator === "=" && matches) || (this.operator === "!=" && !matches)) { - resultNoteSet.add(noteFromBecca); - } - } - } - /** * Helper method to check if a single word appears as an exact match in text * @param wordToFind - The word to search for (should be normalized) diff --git a/apps/server/src/services/search/fts_index.spec.ts b/apps/server/src/services/search/fts_index.spec.ts deleted file mode 100644 index 983c972a0b..0000000000 --- a/apps/server/src/services/search/fts_index.spec.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { describe, it, expect } from "vitest"; - -describe("FTS Index Service", () => { - it("should export buildIndex, updateNote, removeNote, searchContent functions", async () => { - const ftsIndex = await import("./fts_index.js"); - expect(typeof ftsIndex.default.buildIndex).toBe("function"); - expect(typeof ftsIndex.default.updateNote).toBe("function"); - expect(typeof ftsIndex.default.removeNote).toBe("function"); - expect(typeof ftsIndex.default.searchContent).toBe("function"); - expect(typeof ftsIndex.default.isIndexBuilt).toBe("function"); - expect(typeof ftsIndex.default.resetIndex).toBe("function"); - }); -}); diff --git a/apps/server/src/services/search/fts_index.ts b/apps/server/src/services/search/fts_index.ts deleted file mode 100644 index 30359f7d19..0000000000 --- a/apps/server/src/services/search/fts_index.ts +++ /dev/null @@ -1,182 +0,0 @@ -"use strict"; - -import sql from "../sql.js"; -import log from "../log.js"; -import protectedSessionService from "../protected_session.js"; -import preprocessContent from "./expressions/note_content_fulltext_preprocessor.js"; - -interface ContentRow { - noteId: string; - type: string; - mime: string; - content: string | Buffer | null; - isProtected: number; - isDeleted: number; -} - -const MAX_CONTENT_SIZE = 2 * 1024 * 1024; - -let indexBuilt = false; - -function prepareContent(row: ContentRow): string | null { - if (!row.content) return null; - if (row.isDeleted) return null; - - let content: string | undefined; - - if (row.isProtected) { - if (!protectedSessionService.isProtectedSessionAvailable()) { - return null; - } - try { - content = protectedSessionService.decryptString(row.content as string) || undefined; - } catch { - return null; - } - } else { - content = typeof row.content === "string" ? row.content : row.content.toString(); - } - - if (!content || content.length > MAX_CONTENT_SIZE) return null; - - try { - content = preprocessContent(content, row.type, row.mime); - } catch { - return null; - } - - return content || null; -} - -function ftsTableExists(): boolean { - try { - const result = sql.getValue( - "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='note_content_fts'" - ); - return result > 0; - } catch { - return false; - } -} - -function buildIndex(): void { - if (!ftsTableExists()) { - log.info("FTS5 table does not exist, skipping index build."); - return; - } - - const startTime = Date.now(); - log.info("Building FTS content index..."); - - sql.execute("DELETE FROM note_content_fts"); - - // Collect all rows first, then batch-insert in a transaction. - // iterateRows() holds an open cursor that conflicts with writes on the same connection. - const prepared: { noteId: string; content: string }[] = []; - - for (const row of sql.iterateRows(` - SELECT noteId, type, mime, content, isProtected, isDeleted - FROM notes JOIN blobs USING (blobId) - WHERE type IN ('text', 'code', 'mermaid', 'canvas', 'mindMap') - AND isDeleted = 0 - AND content IS NOT NULL - AND LENGTH(content) < ${MAX_CONTENT_SIZE} - `)) { - const processedContent = prepareContent(row); - if (processedContent) { - prepared.push({ noteId: row.noteId, content: processedContent }); - } - } - - const count = sql.transactional(() => { - for (const { noteId, content } of prepared) { - sql.execute( - "INSERT INTO note_content_fts (noteId, content) VALUES (?, ?)", - [noteId, content] - ); - } - return prepared.length; - }); - - const elapsed = Date.now() - startTime; - log.info(`FTS content index built: ${count} notes indexed in ${elapsed}ms`); - indexBuilt = true; -} - -function updateNote(noteId: string): void { - if (!indexBuilt || !ftsTableExists()) return; - - sql.execute("DELETE FROM note_content_fts WHERE noteId = ?", [noteId]); - - const row = sql.getRowOrNull(` - SELECT noteId, type, mime, content, isProtected, isDeleted - FROM notes JOIN blobs USING (blobId) - WHERE noteId = ? - `, [noteId]); - - if (!row) return; - - const processedContent = prepareContent(row); - if (processedContent) { - sql.execute( - "INSERT INTO note_content_fts (noteId, content) VALUES (?, ?)", - [row.noteId, processedContent] - ); - } -} - -function removeNote(noteId: string): void { - if (!indexBuilt || !ftsTableExists()) return; - sql.execute("DELETE FROM note_content_fts WHERE noteId = ?", [noteId]); -} - -function searchContent(tokens: string[], operator: string = "*=*"): string[] { - if (!ftsTableExists()) return []; - - if (!indexBuilt) { - buildIndex(); - } - - const escapedTokens = tokens.map(t => { - const cleaned = t.replace(/["*^(){}:]/g, ""); - if (!cleaned) return null; - return `"${cleaned}"`; - }).filter(Boolean); - - if (escapedTokens.length === 0) return []; - - let ftsQuery: string; - if (operator === "=") { - ftsQuery = escapedTokens.join(" "); - } else { - ftsQuery = escapedTokens.join(" AND "); - } - - try { - const results = sql.getColumn( - "SELECT noteId FROM note_content_fts WHERE note_content_fts MATCH ? ORDER BY rank", - [ftsQuery] - ); - return results; - } catch (e) { - log.info(`FTS5 query failed for "${ftsQuery}": ${e}`); - return []; - } -} - -function isIndexBuilt(): boolean { - return indexBuilt; -} - -function resetIndex(): void { - indexBuilt = false; -} - -export default { - buildIndex, - updateNote, - removeNote, - searchContent, - isIndexBuilt, - resetIndex -}; diff --git a/docs/search-performance-benchmarks.md b/docs/search-performance-benchmarks.md index bb7411230c..614abfb917 100644 --- a/docs/search-performance-benchmarks.md +++ b/docs/search-performance-benchmarks.md @@ -382,84 +382,3 @@ Side-by-side comparison across all note counts for the most common query pattern - Some individual data points show slight regressions at 5K scale (+2-8%), likely noise from shared-machine benchmarking - Long queries (4 tokens) at 5K notes show a small regression (+18%), but this evens out at 10K - The new flat text index has a one-time build cost on first search (~62ms at 10K notes), amortized across all subsequent searches - ---- - -## FTS5 Content Index Benchmarks - -> These benchmarks use the **real SQLite database** with actual blob content (not monkeypatched). They test the `fastSearch=false` path that users hit when pressing Enter in search or using saved searches. This is the path that was taking **seconds** in production. - -### The Architecture - -When `fastSearch=false`, the expression tree is `OrExp([NoteFlatTextExp, NoteContentFulltextExp])`. Both expressions run: -- **NoteFlatTextExp**: In-memory scan of titles/attributes (fast — 5-25ms) -- **NoteContentFulltextExp**: Scans ALL note content from SQLite blobs (slow — the bottleneck) - -FTS5 replaces the sequential blob scan in `NoteContentFulltextExp` with an indexed FTS5 MATCH query. - -### FTS5 Query-Only Performance (isolating the content scan) - -This measures just the content search portion, stripped of the expression tree, scoring, and snippet extraction overhead. - -| Notes | FTS5 MATCH query | Sequential SQL scan | FTS5 Speedup | -|------:|-----------------:|--------------------:|-------------:| -| 1,000 | **0.2ms** | 3.6ms | **15x** | -| 5,000 | **0.5ms** | 16.0ms | **33x** | -| 10,000 | **1.1ms** | 36.4ms | **32x** | - -FTS5 is **15-33x faster** than the sequential scan for the raw content query. - -### Why Full Search Doesn't Show the Same Speedup - -When measured end-to-end through `findResultsWithQuery()` with `fastSearch=false`: - -| Notes | Query | FTS5 | Sequential | Speedup | -|------:|:------|-----:|-----------:|--------:| -| 1,000 | `"performance"` | 52.1ms | 48.3ms | 0.9x | -| 5,000 | `"performance"` | 233.4ms | 227.6ms | 1.0x | -| 10,000 | `"performance"` | 517.3ms | 515.9ms | 1.0x | -| 1,000 | `"xyznonexistent"` | 46.2ms | 57.6ms | 1.2x | -| 5,000 | `"xyznonexistent"` | 272.9ms | 229.3ms | 0.8x | -| 10,000 | `"xyznonexistent"` | 460.3ms | 468.3ms | 1.0x | - -The FTS5 query itself is 32x faster, but it's **drowned out by the rest of the pipeline**: - -| Component | Time at 10K notes | % of total | -|:----------|------------------:|-----------:| -| `NoteFlatTextExp` (in-memory scan) | ~25ms | ~5% | -| `NoteContentFulltextExp` content scan | 1-36ms | ~1-7% | -| Scoring (`computeScore` per result) | ~100-200ms | ~20-40% | -| Snippet extraction | ~50-100ms | ~10-20% | -| Highlighting | ~50ms | ~10% | -| `searchPathTowardsRoot` recursion | ~100-200ms | ~20-40% | - -The content scan (which FTS5 replaces) is only **1-7% of total search time** in this benchmark. The real bottleneck at this scale is scoring, snippet extraction, and the recursive parent-path walk — all JavaScript operations that FTS5 doesn't affect. - -### Where FTS5 Will Matter Most - -FTS5 will show significant real-world improvement when: -1. **Database is large (50K-200K+ notes)** — The sequential scan reads every blob from disk. At 200K notes with varying content sizes, the I/O cost dominates. FTS5 eliminates this entirely. -2. **Notes have large content** — The benchmark uses 300-word notes (~2KB each). Real notes can be 10KB-100KB+. The sequential scan reads and preprocesses ALL of that content; FTS5 returns noteIds without touching content blobs. -3. **Disk is slow** — These benchmarks run on fast local SSD. On slower storage (network drives, spinning disks, Docker volumes), the I/O savings from FTS5 will be dramatic. - -### FTS5 Index Build Cost - -| Notes | Build time | Notes indexed | -|------:|-----------:|--------------:| -| 1,000 | 213ms | 1,015 | -| 5,000 | 943ms | 5,015 | -| 10,000 | 2,720ms | 10,015 | - -The index builds lazily on first search and is maintained incrementally via `NOTE_CONTENT_CHANGE` events. Users using `unicode61` tokenizer (not trigram) keeps the index compact. - -### Reference: Autocomplete (fastSearch=true) — Not Affected by FTS5 - -For comparison, the in-memory autocomplete path remains fast: - -| Notes | `"performance"` | `"performance optimization"` | -|------:|-----------------:|-----------------------------:| -| 1,000 | 5.2ms | 1.4ms | -| 5,000 | 10.1ms | 3.7ms | -| 10,000 | 24.4ms | 10.4ms | - -These don't use FTS5 at all — they use the `NoteFlatTextExp` in-memory path optimized by the earlier commits in this PR. diff --git a/packages/commons/src/lib/options_interface.ts b/packages/commons/src/lib/options_interface.ts index 555fd20a5b..6e36ebd7a3 100644 --- a/packages/commons/src/lib/options_interface.ts +++ b/packages/commons/src/lib/options_interface.ts @@ -137,8 +137,6 @@ export interface OptionDefinitions extends KeyboardShortcutsOptions Date: Sat, 21 Mar 2026 18:28:35 +0200 Subject: [PATCH 020/482] client: create a Vite plugin to generate a contributor list JSON at the build time --- apps/client/src/services/contributors_list.ts | 3 +++ apps/client/vite.config.mts | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 apps/client/src/services/contributors_list.ts diff --git a/apps/client/src/services/contributors_list.ts b/apps/client/src/services/contributors_list.ts new file mode 100644 index 0000000000..d2daf1921a --- /dev/null +++ b/apps/client/src/services/contributors_list.ts @@ -0,0 +1,3 @@ +export default async function getContributors() { + return {contributors: []} +} \ No newline at end of file diff --git a/apps/client/vite.config.mts b/apps/client/vite.config.mts index 8c6debfc08..e9577ac2e0 100644 --- a/apps/client/vite.config.mts +++ b/apps/client/vite.config.mts @@ -1,13 +1,28 @@ /// import prefresh from '@prefresh/vite'; -import { join } from 'path'; +import { join, resolve } from "path"; import webpackStatsPlugin from 'rollup-plugin-webpack-stats'; import { defineConfig } from 'vite'; import { viteStaticCopy } from 'vite-plugin-static-copy' +import { writeFileSync, mkdirSync } from "fs"; +import getContributors from "./src/services/contributors_list"; const assets = [ "assets", "stylesheets", "fonts", "translations" ]; const isDev = process.env.NODE_ENV === "development"; + +const buildContributorListPlugin = { + name: "build-contributor-list-plugin", + writeBundle: async () => { + console.log("Retrieving the contributors list..."); + const jsonData = await getContributors(); + + const assetsDir = resolve(__dirname, "dist/assets"); + mkdirSync(assetsDir, {recursive: true}); + writeFileSync(resolve(assetsDir, "contributors.json"), JSON.stringify(jsonData, null, 2)); + } +}; + let plugins: any = []; if (isDev) { @@ -17,6 +32,7 @@ if (isDev) { ]; } else { plugins = [ + buildContributorListPlugin, viteStaticCopy({ targets: assets.map((asset) => ({ src: `src/${asset}/*`, From 4d753398c1ae60be64b6bf593a0099a9ef1ace2d Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sat, 21 Mar 2026 18:30:33 +0200 Subject: [PATCH 021/482] refactor: normalize to double quotes --- apps/client/vite.config.mts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/client/vite.config.mts b/apps/client/vite.config.mts index e9577ac2e0..29ad43db20 100644 --- a/apps/client/vite.config.mts +++ b/apps/client/vite.config.mts @@ -1,9 +1,9 @@ -/// -import prefresh from '@prefresh/vite'; +/// +import prefresh from "@prefresh/vite"; import { join, resolve } from "path"; -import webpackStatsPlugin from 'rollup-plugin-webpack-stats'; -import { defineConfig } from 'vite'; -import { viteStaticCopy } from 'vite-plugin-static-copy' +import webpackStatsPlugin from "rollup-plugin-webpack-stats"; +import { defineConfig } from "vite"; +import { viteStaticCopy } from "vite-plugin-static-copy" import { writeFileSync, mkdirSync } from "fs"; import getContributors from "./src/services/contributors_list"; @@ -54,17 +54,17 @@ if (isDev) { export default defineConfig(() => ({ root: __dirname, - cacheDir: '../../.cache/vite', + cacheDir: "../../.cache/vite", base: "", plugins, // Use esbuild for JSX transformation (much faster than Babel) esbuild: { - jsx: 'automatic', - jsxImportSource: 'preact', + jsx: "automatic", + jsxImportSource: "preact", jsxDev: isDev }, css: { - transformer: 'lightningcss', + transformer: "lightningcss", devSourcemap: isDev }, resolve: { @@ -95,7 +95,7 @@ export default defineConfig(() => ({ }, build: { target: "esnext", - outDir: './dist', + outDir: "./dist", emptyOutDir: true, reportCompressedSize: true, sourcemap: false, From 6481b90daf22aec878b41b0f2fa6040daf7fe4d2 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sat, 21 Mar 2026 19:59:19 +0200 Subject: [PATCH 022/482] client: retrieve the contributor list --- apps/client/src/services/contributors_list.ts | 29 ++++++++++++++++++- apps/client/vite.config.mts | 10 +++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/apps/client/src/services/contributors_list.ts b/apps/client/src/services/contributors_list.ts index d2daf1921a..060b9c6dda 100644 --- a/apps/client/src/services/contributors_list.ts +++ b/apps/client/src/services/contributors_list.ts @@ -1,3 +1,30 @@ +export interface ContributorList { + contributors: Contributor[]; +} + +export interface Contributor { + name: string; + url: string; +} + export default async function getContributors() { - return {contributors: []} + const response = await fetch("https://api.github.com/repos/TriliumNext/Trilium/contributors"); + + if (response.ok) { + return { + contributors: getList(await response.json()) + } as ContributorList + } else { + throw new Error(`Unable to request the contributor list from GitHub. Reason: ${response.statusText}`); + } +} + +function getList(contributorInfo: any[]) { + return contributorInfo + .filter((c) => c.type === "User" && c.user_view_type === "public") + .sort((a, b) => b.contributions - a.contributions) + .map((c) => {return { + name: c.login, + url: c.html_url + } as Contributor}); } \ No newline at end of file diff --git a/apps/client/vite.config.mts b/apps/client/vite.config.mts index 29ad43db20..08effeea2f 100644 --- a/apps/client/vite.config.mts +++ b/apps/client/vite.config.mts @@ -14,8 +14,14 @@ const isDev = process.env.NODE_ENV === "development"; const buildContributorListPlugin = { name: "build-contributor-list-plugin", writeBundle: async () => { - console.log("Retrieving the contributors list..."); - const jsonData = await getContributors(); + console.log("Retrieving the contributor list..."); + + let jsonData: any = {}; + try { + jsonData = await getContributors(); + } catch (ex) { + console.error(ex); + } const assetsDir = resolve(__dirname, "dist/assets"); mkdirSync(assetsDir, {recursive: true}); From 92f10489115f410541a1da74a4d30fcfc502c2d3 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sat, 21 Mar 2026 20:19:17 +0200 Subject: [PATCH 023/482] client/contributor list: add support for honorific contributors --- apps/client/src/services/contributors_list.ts | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/apps/client/src/services/contributors_list.ts b/apps/client/src/services/contributors_list.ts index 060b9c6dda..ab1f6c1755 100644 --- a/apps/client/src/services/contributors_list.ts +++ b/apps/client/src/services/contributors_list.ts @@ -7,6 +7,10 @@ export interface Contributor { url: string; } +// Keep honorific contributors at top of the list, even if their commit count +// is exceeded by another users. +const PINNED_CONTRIBUTORS = ["eliandoran", "zadam"]; + export default async function getContributors() { const response = await fetch("https://api.github.com/repos/TriliumNext/Trilium/contributors"); @@ -21,10 +25,25 @@ export default async function getContributors() { function getList(contributorInfo: any[]) { return contributorInfo + // Filter out bots and private profiles .filter((c) => c.type === "User" && c.user_view_type === "public") - .sort((a, b) => b.contributions - a.contributions) + // Sort by the commit count. Honorific contributors are always first. + .sort(contributorOrderer) .map((c) => {return { name: c.login, url: c.html_url } as Contributor}); +} + +function contributorOrderer(a, b) { + const isAPinned = PINNED_CONTRIBUTORS.includes(a.login); + const isBPinned = PINNED_CONTRIBUTORS.includes(b.login); + + // Pinned contributors come first + if (isAPinned !== isBPinned) { + return isAPinned ? -1 : 1; + } + + // Within each group, sort by contributions + return b.contributions - a.contributions; } \ No newline at end of file From fb691f6ade854d300562a42f088299d3bda97a5d Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sat, 21 Mar 2026 20:28:36 +0200 Subject: [PATCH 024/482] client/contributor list: add extra bot exclusion --- apps/client/src/services/contributors_list.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/client/src/services/contributors_list.ts b/apps/client/src/services/contributors_list.ts index ab1f6c1755..7e1a4fb98a 100644 --- a/apps/client/src/services/contributors_list.ts +++ b/apps/client/src/services/contributors_list.ts @@ -11,6 +11,9 @@ export interface Contributor { // is exceeded by another users. const PINNED_CONTRIBUTORS = ["eliandoran", "zadam"]; +// Bots marked as users on the GitHub profile info to exclude from the listing +const BOTS = ["weblate"]; + export default async function getContributors() { const response = await fetch("https://api.github.com/repos/TriliumNext/Trilium/contributors"); @@ -26,7 +29,7 @@ export default async function getContributors() { function getList(contributorInfo: any[]) { return contributorInfo // Filter out bots and private profiles - .filter((c) => c.type === "User" && c.user_view_type === "public") + .filter((c) => c.type === "User" && c.user_view_type === "public" && !BOTS.includes(c.login)) // Sort by the commit count. Honorific contributors are always first. .sort(contributorOrderer) .map((c) => {return { From 5bc9840825fbd858964acb087f14d8112cf887b6 Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Sat, 21 Mar 2026 09:17:27 -0700 Subject: [PATCH 025/482] fix(search): restore toLowerCase in fuzzyMatchWordWithResult The function has multiple callers (not just smartMatch) so it must normalize inputs itself. Removing toLowerCase broke fuzzy matching for the two-phase search path. --- .../src/services/search/utils/text_utils.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/server/src/services/search/utils/text_utils.ts b/apps/server/src/services/search/utils/text_utils.ts index 94df2f3dd1..7528571f86 100644 --- a/apps/server/src/services/search/utils/text_utils.ts +++ b/apps/server/src/services/search/utils/text_utils.ts @@ -275,19 +275,19 @@ export function fuzzyMatchWordWithResult(token: string, text: string, maxDistanc } try { - // Inputs from smartMatch() are already normalized (lowercased, diacritics removed). - // Skip redundant toLowerCase() — just use the inputs directly. + // Normalize for comparison — some callers pass pre-normalized text, + // others don't, so this function must be self-contained. + const normalizedToken = token.toLowerCase(); + const normalizedText = text.toLowerCase(); // Exact match check first (most common case) - if (text.includes(token)) { + if (normalizedText.includes(normalizedToken)) { return token; } - // For fuzzy matching, we need to check individual words in the text. - // Split into words and check each word against the token. - // Inputs are already normalized so we don't need a separate originalWords array. - const words = text.split(/\s+/); - const originalWords = words; + // For fuzzy matching, split into words and check each against the token + const words = normalizedText.split(/\s+/).filter(word => word.length > 0); + const originalWords = text.split(/\s+/).filter(word => word.length > 0); for (let i = 0; i < words.length; i++) { const word = words[i]; From 90ac727250510cf20577f3d9a8a336fa32095a9d Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Sat, 21 Mar 2026 09:19:42 -0700 Subject: [PATCH 026/482] docs(search): update benchmark comparison with final optimized numbers All numbers re-measured on the same machine/session after the scoring, highlighting, and tree walk optimizations. Multi-token autocomplete now shows 50-70% improvement over main. --- docs/search-performance-benchmarks.md | 356 +++++++------------------- 1 file changed, 97 insertions(+), 259 deletions(-) diff --git a/docs/search-performance-benchmarks.md b/docs/search-performance-benchmarks.md index 614abfb917..efa5f7b6e2 100644 --- a/docs/search-performance-benchmarks.md +++ b/docs/search-performance-benchmarks.md @@ -1,6 +1,6 @@ # Search Performance Benchmarks: `main` vs `feat/search-perf-take1` -> **Date:** 2026-03-20 +> **Date:** 2026-03-21 > **Environment:** In-memory benchmarks (monkeypatched `getContent()`, no real SQLite I/O). Both branches tested on the same machine in the same session for fair comparison. All times are avg of 5 iterations with warm caches unless noted. > **Benchmark source:** `apps/server/src/services/search/services/search_benchmark.spec.ts` @@ -13,54 +13,23 @@ - [No-Match Queries (worst case)](#no-match-queries-worst-case) - [Diacritics / Unicode](#diacritics--unicode) - [Typing Progression (keystroke simulation)](#typing-progression-keystroke-simulation) -- [Long Queries (4 tokens)](#long-queries-4-tokens) -- [Attribute Matching](#attribute-matching) - [Fuzzy Matching Effectiveness (typos & misspellings)](#fuzzy-matching-effectiveness-typos--misspellings) -- [Cache Warmth Impact (feature branch only)](#cache-warmth-impact-feature-branch-only) - [Realistic User Session](#realistic-user-session) - [Scale Comparison Summary](#scale-comparison-summary) +- [Summary of Improvements](#summary-of-improvements) --- ## Single-Token Autocomplete -The most common case — user typing in the search bar. Query: `"meeting"`. - -### Autocomplete (fuzzy OFF) +The most common case — user typing in the search bar. Query: `"meeting"`, autocomplete, fuzzy OFF. | Notes | main | feature | Change | |------:|-----:|--------:|-------:| -| 1,000 | 3.6ms | 2.8ms | **-22%** | -| 5,000 | 11.9ms | 10.6ms | **-11%** | -| 10,000 | 27.5ms | 22.8ms | **-17%** | -| 20,000 | 53.7ms | 46.2ms | **-14%** | - -### Autocomplete (fuzzy ON) - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 2.4ms | 2.3ms | -4% | -| 5,000 | 11.7ms | 10.7ms | **-9%** | -| 10,000 | 28.9ms | 21.6ms | **-25%** | -| 20,000 | 58.6ms | 44.5ms | **-24%** | - -### Full Search (fuzzy OFF) - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 2.7ms | 4.3ms | +59% | -| 5,000 | 14.3ms | 10.8ms | **-24%** | -| 10,000 | 30.8ms | 26.9ms | **-13%** | -| 20,000 | 63.1ms | 56.7ms | **-10%** | - -### Full Search (fuzzy ON) - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 2.5ms | 2.4ms | -4% | -| 5,000 | 13.0ms | 11.4ms | **-12%** | -| 10,000 | 29.8ms | 25.6ms | **-14%** | -| 20,000 | 63.4ms | 54.5ms | **-14%** | +| 1,000 | 2.5ms | 1.6ms | **-36%** | +| 5,000 | 9.5ms | 6.7ms | **-29%** | +| 10,000 | 24.7ms | 14.3ms | **-42%** | +| 20,000 | 45.1ms | 29.6ms | **-34%** | --- @@ -70,37 +39,19 @@ The most common case — user typing in the search bar. Query: `"meeting"`. | Notes | main | feature | Change | |------:|-----:|--------:|-------:| -| 1,000 | 3.7ms | 3.5ms | -5% | -| 5,000 | 19.0ms | 19.3ms | +2% | -| 10,000 | 40.2ms | 40.4ms | 0% | -| 20,000 | 86.1ms | 80.7ms | **-6%** | +| 1,000 | 2.7ms | 1.1ms | **-59%** | +| 5,000 | 15.8ms | 5.9ms | **-63%** | +| 10,000 | 33.0ms | 15.6ms | **-53%** | +| 20,000 | 67.3ms | 33.6ms | **-50%** | ### 3-Token: `"meeting notes january"` (autocomplete, fuzzy OFF) | Notes | main | feature | Change | |------:|-----:|--------:|-------:| -| 1,000 | 4.1ms | 4.3ms | +5% | -| 5,000 | 25.7ms | 24.9ms | -3% | -| 10,000 | 50.9ms | 50.5ms | -1% | -| 20,000 | 104.5ms | 107.2ms | +3% | - -### 2-Token: `"meeting notes"` (full search, fuzzy OFF) - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 3.4ms | 3.3ms | -3% | -| 5,000 | 22.3ms | 21.9ms | -2% | -| 10,000 | 42.9ms | 40.2ms | **-6%** | -| 20,000 | 95.8ms | 88.3ms | **-8%** | - -### 3-Token: `"meeting notes january"` (full search, fuzzy ON) - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 4.4ms | 4.3ms | -2% | -| 5,000 | 26.3ms | 25.5ms | -3% | -| 10,000 | 51.7ms | 52.6ms | +2% | -| 20,000 | 113.9ms | 114.0ms | 0% | +| 1,000 | 3.7ms | 1.1ms | **-70%** | +| 5,000 | 20.7ms | 7.3ms | **-65%** | +| 10,000 | 43.2ms | 17.7ms | **-59%** | +| 20,000 | 91.2ms | 35.6ms | **-61%** | --- @@ -108,180 +59,75 @@ The most common case — user typing in the search bar. Query: `"meeting"`. These are the worst case — every note must be scanned with no early exit. -### Single token: `"xyznonexistent"` (autocomplete) - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 0.7ms | 0.5ms | **-29%** | -| 5,000 | 4.0ms | 3.4ms | **-15%** | -| 10,000 | 11.3ms | 7.0ms | **-38%** | -| 20,000 | 28.9ms | 19.0ms | **-34%** | - ### Single token: `"xyznonexistent"` (autocomplete, fuzzy ON) -This is the biggest behavioral change. On `main`, autocomplete with fuzzy ON triggers the expensive two-phase search. On the feature branch, autocomplete **always skips** the fuzzy fallback phase. +On `main`, autocomplete with fuzzy ON triggers the expensive two-phase search. On the feature branch, autocomplete **always skips** the fuzzy fallback phase. | Notes | main | feature | Change | |------:|-----:|--------:|-------:| -| 1,000 | 1.7ms | 0.5ms | **-71%** | -| 5,000 | 12.8ms | 2.3ms | **-82%** | -| 10,000 | 26.4ms | 6.0ms | **-77%** | -| 20,000 | 60.4ms | 20.0ms | **-67%** | +| 1,000 | 1.6ms | 0.4ms | **-75%** | +| 5,000 | 8.1ms | 2.1ms | **-74%** | +| 10,000 | 18.2ms | 6.0ms | **-67%** | +| 20,000 | 49.2ms | 17.1ms | **-65%** | ### Multi token: `"xyzfoo xyzbar"` (autocomplete, fuzzy ON) -Same effect — autocomplete no longer triggers the fuzzy fallback: - | Notes | main | feature | Change | |------:|-----:|--------:|-------:| -| 1,000 | 6.5ms | 0.4ms | **-94%** | -| 5,000 | 33.9ms | 2.5ms | **-93%** | -| 10,000 | 134.5ms | 6.0ms | **-96%** | -| 20,000 | 151.8ms | 19.8ms | **-87%** | - -### Multi token: `"xyzfoo xyzbar"` (full search, fuzzy ON) - -Full search still does two-phase fuzzy on both branches, so improvement here is from the flat text index and pre-normalized attributes: - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 5.9ms | 5.8ms | -2% | -| 5,000 | 35.0ms | 33.7ms | -4% | -| 10,000 | 144.0ms | 68.8ms | **-52%** | -| 20,000 | 165.5ms | 140.6ms | **-15%** | +| 1,000 | 5.1ms | 0.4ms | **-92%** | +| 5,000 | 29.0ms | 2.2ms | **-92%** | +| 10,000 | 63.4ms | 7.1ms | **-89%** | +| 20,000 | 128.8ms | 19.1ms | **-85%** | --- ## Diacritics / Unicode -Searching `"résumé"` (with diacritics) vs `"resume"` (ASCII equivalent). Both forms find the same results thanks to diacritic normalization. - -### Autocomplete (fuzzy OFF) +Searching `"résumé"` (with diacritics) vs `"resume"` (ASCII equivalent). Both forms find the same results thanks to diacritic normalization. Autocomplete, fuzzy OFF. | Notes | Query | main | feature | Change | |------:|:------|-----:|--------:|-------:| -| 1,000 | `"résumé"` | 4.1ms | 2.4ms | **-41%** | -| 1,000 | `"resume"` | 2.9ms | 2.4ms | **-17%** | -| 5,000 | `"résumé"` | 20.4ms | 15.0ms | **-26%** | -| 5,000 | `"resume"` | 18.1ms | 16.3ms | **-10%** | -| 10,000 | `"résumé"` | 40.6ms | 29.0ms | **-29%** | -| 10,000 | `"resume"` | 40.6ms | 29.5ms | **-27%** | +| 1,000 | `"résumé"` | 2.8ms | 1.7ms | **-39%** | +| 1,000 | `"resume"` | 2.9ms | 1.5ms | **-48%** | +| 5,000 | `"résumé"` | 15.7ms | 10.4ms | **-34%** | +| 5,000 | `"resume"` | 16.3ms | 7.7ms | **-53%** | +| 10,000 | `"résumé"` | 32.4ms | 23.3ms | **-28%** | +| 10,000 | `"resume"` | 30.7ms | 20.4ms | **-34%** | --- ## Typing Progression (keystroke simulation) -Simulates a user typing `"documentation"` character by character. Autocomplete, fuzzy OFF. - -### 5,000 notes +Simulates a user typing `"documentation"` character by character at 10K notes. Autocomplete, fuzzy OFF. | Prefix | main | feature | Change | |:-------|-----:|--------:|-------:| -| `"d"` | 44.7ms | 35.9ms | **-20%** | -| `"do"` | 12.9ms | 11.6ms | **-10%** | -| `"doc"` | 12.0ms | 10.2ms | **-15%** | -| `"docu"` | 10.9ms | 9.4ms | **-14%** | -| `"document"` | 9.1ms | 7.3ms | **-20%** | -| `"documentation"` | 10.3ms | 8.1ms | **-21%** | - -### 10,000 notes - -| Prefix | main | feature | Change | -|:-------|-----:|--------:|-------:| -| `"d"` | 85.4ms | 70.1ms | **-18%** | -| `"do"` | 30.0ms | 24.1ms | **-20%** | -| `"doc"` | 28.3ms | 20.8ms | **-27%** | -| `"docu"` | 24.3ms | 20.1ms | **-17%** | -| `"document"` | 19.2ms | 15.9ms | **-17%** | -| `"documentation"` | 23.0ms | 16.8ms | **-27%** | - -### 20,000 notes - -| Prefix | main | feature | Change | -|:-------|-----:|--------:|-------:| -| `"d"` | 178.3ms | 142.8ms | **-20%** | -| `"do"` | 63.7ms | 50.6ms | **-21%** | -| `"doc"` | 59.1ms | 44.0ms | **-26%** | -| `"docu"` | 59.3ms | 40.6ms | **-32%** | -| `"document"` | 45.7ms | 34.1ms | **-25%** | -| `"documentation"` | 47.4ms | 33.7ms | **-29%** | - ---- - -## Long Queries (4 tokens) - -Query: `"quarterly budget review report"` — autocomplete, fuzzy OFF. - -| Notes | Tokens | main | feature | Change | -|------:|-------:|-----:|--------:|-------:| -| 5,000 | 1 | 8.8ms | 6.5ms | **-26%** | -| 5,000 | 2 | 13.7ms | 11.0ms | **-20%** | -| 5,000 | 3 | 16.7ms | 15.1ms | **-10%** | -| 5,000 | 4 | 18.9ms | 22.3ms | +18% | -| 10,000 | 1 | 18.5ms | 15.6ms | **-16%** | -| 10,000 | 2 | 25.4ms | 24.9ms | -2% | -| 10,000 | 3 | 31.7ms | 33.3ms | +5% | -| 10,000 | 4 | 39.0ms | 40.7ms | +4% | - ---- - -## Attribute Matching - -Searching by label name (`"category"`) and label value (`"important"`). Notes have 5 labels each. - -### `"category"` (autocomplete) - -| Notes | main (fuzzy OFF) | feature (fuzzy OFF) | Change | main (fuzzy ON) | feature (fuzzy ON) | Change | -|------:|------------------:|--------------------:|-------:|----------------:|-------------------:|-------:| -| 5,000 | 12.0ms | 9.5ms | **-21%** | 34.4ms | 9.7ms | **-72%** | -| 10,000 | 26.7ms | 22.7ms | **-15%** | 77.5ms | 21.0ms | **-73%** | - -### `"important"` (autocomplete) - -| Notes | main (fuzzy OFF) | feature (fuzzy OFF) | Change | main (fuzzy ON) | feature (fuzzy ON) | Change | -|------:|------------------:|--------------------:|-------:|----------------:|-------------------:|-------:| -| 5,000 | 11.1ms | 9.2ms | **-17%** | 11.6ms | 8.8ms | **-24%** | -| 10,000 | 25.4ms | 18.7ms | **-26%** | 24.2ms | 19.4ms | **-20%** | +| `"d"` | 66.9ms | 44.8ms | **-33%** | +| `"do"` | 22.9ms | 17.0ms | **-26%** | +| `"doc"` | 20.9ms | 14.7ms | **-30%** | +| `"docu"` | 20.0ms | 13.0ms | **-35%** | +| `"docum"` | 23.0ms | 11.8ms | **-49%** | +| `"document"` | 16.8ms | 11.8ms | **-30%** | +| `"documentation"` | 17.5ms | 11.0ms | **-37%** | --- ## Fuzzy Matching Effectiveness (typos & misspellings) -10K notes, keyword: `"performance"`. Shows both time and result quality. +10K notes, keyword: `"performance"`. Shows both time improvement and result correctness. | Query | Fuzzy | main (time) | feature (time) | Change | main (results) | feature (results) | |:------|:------|------------:|---------------:|-------:|---------------:|------------------:| -| `"performance"` (exact) | OFF | 26.8ms | 22.3ms | **-17%** | 1,000 | 1,000 | -| `"performance"` (exact) | ON | 18.7ms | 16.3ms | **-13%** | 1,000 | 1,000 | -| `"performanc"` (truncated) | OFF | 18.6ms | 16.4ms | **-12%** | 1,000 | 1,000 | -| `"performanc"` (truncated) | ON | 18.5ms | 15.6ms | **-16%** | 1,000 | 1,000 | -| `"preformance"` (typo) | OFF | 10.6ms | 7.9ms | **-25%** | 0 | 0 | -| `"preformance"` (typo) | ON | 55.1ms | 43.4ms | **-21%** | 1,000 | 1,000 | -| `"performence"` (misspelling) | OFF | 11.5ms | 8.8ms | **-23%** | 0 | 0 | -| `"performence"` (misspelling) | ON | 56.2ms | 48.3ms | **-14%** | 1,000 | 1,000 | -| `"optimization"` | OFF | 12.6ms | 9.9ms | **-21%** | 0 | 0 | -| `"optimization"` | ON | 37.2ms | 31.6ms | **-15%** | 0 | 0 | -| `"optimzation"` (typo) | OFF | 11.6ms | 8.1ms | **-30%** | 0 | 0 | -| `"optimzation"` (typo) | ON | 44.5ms | 31.3ms | **-30%** | 0 | 0 | -| `"perf optim"` (abbreviated) | OFF | 16.5ms | 11.8ms | **-28%** | 0 | 0 | -| `"perf optim"` (abbreviated) | ON | 74.9ms | 67.2ms | **-10%** | 0 | 0 | +| `"performance"` (exact) | OFF | 22.0ms | 25.9ms | +18% | 1,000 | 1,000 | +| `"performance"` (exact) | ON | 14.1ms | 18.2ms | +29% | 1,000 | 1,000 | +| `"performanc"` (truncated) | OFF | 16.6ms | 16.8ms | +1% | 1,000 | 1,000 | +| `"performanc"` (truncated) | ON | 16.0ms | 13.5ms | **-16%** | 1,000 | 1,000 | +| `"preformance"` (typo) | OFF | 9.0ms | 9.4ms | +4% | 0 | 0 | +| `"preformance"` (typo) | ON | 46.3ms | 51.7ms | +12% | 1,000 | 1,000 | +| `"performence"` (misspelling) | OFF | 9.0ms | 10.8ms | +20% | 0 | 0 | +| `"performence"` (misspelling) | ON | 45.4ms | 49.4ms | +9% | 1,000 | 1,000 | -**Key insight:** Fuzzy matching is equally effective on both branches (same result counts). The feature branch is simply faster at executing it. - ---- - -## Cache Warmth Impact (feature branch only) - -This section only applies to the feature branch, which introduces a new flat text index cache in Becca. `main` does not have this cache. - -| Scenario | Time | -|:---------|------:| -| Cold (first search, builds index + search) | 61.7ms | -| Warm (reuse existing index, avg of 5 runs) | 25.6ms (avg), 19.8ms (min) | -| Incremental (50 notes dirtied, then search) | 21.1ms | -| Full rebuild (index invalidated, then search) | 20.7ms | - -The first search after startup pays a one-time index build cost (~2.4x). All subsequent searches reuse the cached index. When individual notes change, only their entries are recomputed. +**Note:** The full-search fuzzy path (non-autocomplete, `fastSearch=true`) shows slight regressions because this PR's optimizations target the autocomplete and in-memory paths. Fuzzy matching correctness is preserved — same result counts on both branches. --- @@ -291,22 +137,15 @@ Simulates a typical user session at 10K notes with mixed query types and typos. | Query | Mode | main | feature | Change | |:------|:-----|-----:|--------:|-------:| -| `"pro"` | autocomplete | 26.9ms | 24.6ms | **-9%** | -| `"project"` | autocomplete | 28.3ms | 24.1ms | **-15%** | -| `"project plan"` | autocomplete | 35.6ms | 35.0ms | -2% | -| `"project"` | fullSearch | 32.8ms | 30.0ms | **-9%** | -| `"project planning"` | fullSearch | 37.2ms | 36.4ms | -2% | -| `"project planning"` | fullSearch+fuzzy | 36.5ms | 35.9ms | -2% | -| `"projct"` (typo) | autocomplete | 11.4ms | 6.0ms | **-47%** | -| `"projct"` (typo) | autocomplete+fuzzy | **81.2ms** | **6.7ms** | **-92%** | -| `"projct planing"` (typo) | fullSearch | 12.5ms | 8.8ms | **-30%** | -| `"projct planing"` (typo) | fullSearch+fuzzy | 116.6ms | 113.2ms | -3% | -| `"xyznonexistent"` | autocomplete | 11.4ms | 6.7ms | **-41%** | -| `"xyznonexistent foo"` | fullSearch+fuzzy | 37.4ms | 23.2ms | **-38%** | -| `"note"` (very common) | autocomplete | **106.0ms** | **92.3ms** | **-13%** | -| `"document"` | autocomplete | 24.7ms | 20.7ms | **-16%** | +| `"pro"` | autocomplete | 24.3ms | 14.1ms | **-42%** | +| `"project"` | autocomplete | 25.7ms | 13.6ms | **-47%** | +| `"project"` | fullSearch | 27.4ms | 17.3ms | **-37%** | +| `"projct"` (typo) | autocomplete | 8.9ms | 5.9ms | **-34%** | +| `"projct"` (typo) | autocomplete+fuzzy | **100.7ms** | **6.0ms** | **-94%** | +| `"note"` (very common) | autocomplete | **90.8ms** | **46.4ms** | **-49%** | +| `"document"` | autocomplete | 22.7ms | 15.2ms | **-33%** | -**Biggest win:** `"projct"` autocomplete+fuzzy goes from 81.2ms to 6.7ms (**-92%**) because the feature branch skips the fuzzy fallback phase for autocomplete entirely. +**Biggest wins:** `"projct"` autocomplete+fuzzy goes from 100.7ms to 6.0ms (**-94%**) because the feature branch skips the fuzzy fallback phase for autocomplete entirely. `"note"` (matching 8,500 of 10K notes) drops from 91ms to 46ms (**-49%**). --- @@ -318,67 +157,66 @@ Side-by-side comparison across all note counts for the most common query pattern | Notes | main | feature | Change | |------:|-----:|--------:|-------:| -| 1,000 | 3.6ms | 2.3ms | **-36%** | -| 5,000 | 11.4ms | 12.2ms | +7% | -| 10,000 | 25.1ms | 22.9ms | **-9%** | -| 20,000 | 59.4ms | 52.3ms | **-12%** | +| 1,000 | 2.5ms | 1.6ms | **-36%** | +| 5,000 | 10.3ms | 7.6ms | **-26%** | +| 10,000 | 22.5ms | 14.4ms | **-36%** | +| 20,000 | 53.7ms | 33.2ms | **-38%** | ### `"meeting notes"` autocomplete (fuzzy OFF) | Notes | main | feature | Change | |------:|-----:|--------:|-------:| -| 1,000 | 4.0ms | 2.7ms | **-33%** | -| 5,000 | 15.9ms | 17.2ms | +8% | -| 10,000 | 36.1ms | 34.2ms | **-5%** | -| 20,000 | 71.0ms | 72.9ms | +3% | - -### `"meeting"` fullSearch (fuzzy ON) - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 2.5ms | 2.4ms | -4% | -| 5,000 | 12.1ms | 13.1ms | +8% | -| 10,000 | 27.8ms | 27.1ms | -3% | -| 20,000 | 67.2ms | 57.8ms | **-14%** | +| 1,000 | 4.6ms | 1.1ms | **-76%** | +| 5,000 | 17.5ms | 6.7ms | **-62%** | +| 10,000 | 32.7ms | 16.8ms | **-49%** | +| 20,000 | 71.6ms | 38.9ms | **-46%** | ### `"xyznonexistent"` autocomplete (fuzzy OFF) | Notes | main | feature | Change | |------:|-----:|--------:|-------:| -| 1,000 | 1.3ms | 0.5ms | **-62%** | -| 5,000 | 3.1ms | 2.5ms | **-19%** | -| 10,000 | 7.7ms | 9.4ms | +22% | -| 20,000 | 22.4ms | 16.6ms | **-26%** | +| 1,000 | 0.4ms | 0.4ms | 0% | +| 5,000 | 2.2ms | 2.3ms | +5% | +| 10,000 | 6.3ms | 8.4ms | +33% | +| 20,000 | 21.9ms | 19.3ms | **-12%** | ### `"xyznonexistent"` fullSearch (fuzzy ON) — worst case path | Notes | main | feature | Change | |------:|-----:|--------:|-------:| -| 1,000 | 2.7ms | 2.5ms | -7% | -| 5,000 | 11.2ms | 9.7ms | **-13%** | -| 10,000 | 25.4ms | 30.3ms | +19% | -| 20,000 | 68.7ms | 55.2ms | **-20%** | +| 1,000 | 1.2ms | 1.0ms | **-17%** | +| 5,000 | 8.6ms | 8.7ms | +1% | +| 10,000 | 22.4ms | 22.2ms | -1% | +| 20,000 | 72.2ms | 64.5ms | **-11%** | --- ## Summary of Improvements -### Where the feature branch clearly wins (consistent 10-30% improvement): -- **Single-token autocomplete** at all scales (10-25% faster) -- **Diacritics queries** (26-41% faster at 10K notes) -- **Typing progression** (17-32% faster per keystroke at 20K notes) -- **Fuzzy typo searches** (14-30% faster while finding same results) -- **Broad term autocomplete** (e.g., `"note"` matching 8,500 results: 13% faster) +### Where the feature branch clearly wins (consistent 25-60% improvement): +- **Single-token autocomplete** at all scales (29-42% faster) +- **Multi-token autocomplete** — the biggest consistent gains (50-70% faster) +- **Typing progression** (26-49% faster per keystroke at 10K notes) +- **Diacritics queries** (28-53% faster) +- **Broad term autocomplete** (e.g., `"note"` matching 8,500 results: 49% faster) +- **Realistic user session queries** (33-47% faster for typical searches) -### Where the feature branch dramatically wins (50%+ improvement): -- **Autocomplete with fuzzy ON, no-match queries** (67-96% faster — fuzzy fallback skipped entirely) -- **Autocomplete typo queries** (e.g., `"projct"` + fuzzy: 81ms -> 7ms, **-92%**) +### Where the feature branch dramatically wins (80%+ improvement): +- **Autocomplete with fuzzy ON, no-match queries** (65-92% faster — fuzzy fallback skipped entirely) +- **Autocomplete typo queries** (e.g., `"projct"` + fuzzy: 101ms -> 6ms, **-94%**) -### Where performance is roughly equal (within noise): -- Multi-token queries at smaller scales (1-5K notes) -- Full search with fuzzy ON when there are sufficient exact matches (fuzzy phase skipped on both branches) +### Where performance is roughly equal: +- Full search fuzzy typo path — slight regression (+9-12%) because the two-phase fuzzy scan still runs +- No-match queries without fuzzy at smaller scales (within noise) -### Trade-offs: -- Some individual data points show slight regressions at 5K scale (+2-8%), likely noise from shared-machine benchmarking -- Long queries (4 tokens) at 5K notes show a small regression (+18%), but this evens out at 10K -- The new flat text index has a one-time build cost on first search (~62ms at 10K notes), amortized across all subsequent searches +### Key optimizations in this PR: +1. **Pre-built flat text index** with incremental updates in Becca +2. **Skip two-phase fuzzy fallback** for autocomplete searches +3. **Pre-normalized attribute names/values** on BAttribute +4. **Cached normalized parent titles** per search execution +5. **Set-based token lookup** in searchPathTowardsRoot (O(1) vs O(n)) +6. **Removed redundant toLowerCase()** throughout scoring pipeline +7. **Skip edit distance** when fuzzy matching is disabled +8. **Faster content snippet extraction** — regex strip, window normalization +9. **removeDiacritic() outside regex while-loop** in highlighting +10. **Single-token autocomplete fast path** — skips recursive parent walk From 9aec8be1c064bf52e3f2b075ee16ca818f59670b Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Sat, 21 Mar 2026 10:13:59 -0700 Subject: [PATCH 027/482] docs(search): add full search + fuzzy benchmark sections Adds end-to-end full search (fastSearch=false) comparison tables for both fuzzy ON and OFF, plus long queries and realistic typo recovery benchmarks. Full search multi-token shows 45-65% improvement. --- docs/search-performance-benchmarks.md | 149 +++++++++++++++++++++++--- 1 file changed, 135 insertions(+), 14 deletions(-) diff --git a/docs/search-performance-benchmarks.md b/docs/search-performance-benchmarks.md index efa5f7b6e2..b11270e203 100644 --- a/docs/search-performance-benchmarks.md +++ b/docs/search-performance-benchmarks.md @@ -15,6 +15,9 @@ - [Typing Progression (keystroke simulation)](#typing-progression-keystroke-simulation) - [Fuzzy Matching Effectiveness (typos & misspellings)](#fuzzy-matching-effectiveness-typos--misspellings) - [Realistic User Session](#realistic-user-session) +- [Full Search (fastSearch=false)](#full-search-fastsearchfalse) +- [Full Search with Fuzzy](#full-search-with-fuzzy) +- [Long Queries (4 tokens)](#long-queries-4-tokens) - [Scale Comparison Summary](#scale-comparison-summary) - [Summary of Improvements](#summary-of-improvements) @@ -149,6 +152,115 @@ Simulates a typical user session at 10K notes with mixed query types and typos. --- +## Full Search (fastSearch=false) + +This is the path hit when the user presses Enter in the search bar, or uses saved searches. It runs `NoteFlatTextExp` + `NoteContentFulltextExp` via `OrExp`. + +> Note: These benchmarks use in-memory data (monkeypatched `getContent()`), so the `NoteContentFulltextExp` sequential blob scan is not measured here. In production with real SQLite I/O, the full search path would be slower and improvements would be more pronounced. + +### Single token: `"meeting"` (fuzzy OFF) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 2.3ms | 3.3ms | +43% | +| 5,000 | 9.6ms | 9.7ms | +1% | +| 10,000 | 22.9ms | 19.6ms | **-14%** | +| 20,000 | 47.6ms | 37.9ms | **-20%** | + +### 2-Token: `"meeting notes"` (fuzzy OFF) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 3.3ms | 1.2ms | **-64%** | +| 5,000 | 16.1ms | 6.9ms | **-57%** | +| 10,000 | 35.7ms | 17.4ms | **-51%** | +| 20,000 | 71.9ms | 38.2ms | **-47%** | + +### 3-Token: `"meeting notes january"` (fuzzy OFF) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 3.9ms | 1.3ms | **-67%** | +| 5,000 | 20.9ms | 8.9ms | **-57%** | +| 10,000 | 43.4ms | 21.0ms | **-52%** | +| 20,000 | 91.7ms | 41.9ms | **-54%** | + +--- + +## Full Search with Fuzzy + +### Single token: `"meeting"` (fuzzy ON) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 1.8ms | 2.8ms | +56% | +| 5,000 | 11.1ms | 8.2ms | **-26%** | +| 10,000 | 23.3ms | 17.8ms | **-24%** | +| 20,000 | 48.7ms | 35.1ms | **-28%** | + +### 2-Token: `"meeting notes"` (fuzzy ON) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 3.3ms | 1.2ms | **-64%** | +| 5,000 | 16.4ms | 7.1ms | **-57%** | +| 10,000 | 33.8ms | 18.6ms | **-45%** | +| 20,000 | 70.7ms | 37.2ms | **-47%** | + +### 3-Token: `"meeting notes january"` (fuzzy ON) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 3.7ms | 1.3ms | **-65%** | +| 5,000 | 21.2ms | 8.7ms | **-59%** | +| 10,000 | 43.2ms | 18.0ms | **-58%** | +| 20,000 | 92.8ms | 40.1ms | **-57%** | + +### No-match with fuzzy — worst case (full scan + fuzzy phase) + +| Notes | Query | main | feature | Change | +|------:|:------|-----:|--------:|-------:| +| 5,000 | `"xyzfoo xyzbar"` | 31.7ms | 28.6ms | **-10%** | +| 10,000 | `"xyzfoo xyzbar"` | 64.2ms | 61.4ms | -4% | +| 20,000 | `"xyzfoo xyzbar"` | 142.9ms | 127.5ms | **-11%** | + +### Realistic typo recovery (full search + fuzzy) + +| Query | main | feature | Change | +|:------|-----:|--------:|-------:| +| `"project planning"` | 32.8ms | 18.6ms | **-43%** | +| `"projct planing"` (typo, fuzzy OFF) | 10.5ms | 7.8ms | **-26%** | +| `"projct planing"` (typo, fuzzy ON — recovers 1,500 results) | 133.8ms | 94.8ms | **-29%** | + +--- + +## Long Queries (4 tokens) + +Query: `"quarterly budget review report"`. + +### Autocomplete + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 5,000 | 17.2ms | 11.9ms | **-31%** | +| 10,000 | 36.8ms | 15.9ms | **-57%** | + +### Full search (fuzzy OFF) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 5,000 | 17.6ms | 25.4ms | +44% | +| 10,000 | 37.1ms | 18.3ms | **-51%** | + +### Full search (fuzzy ON) + +| Notes | main | feature | Change | +|------:|-----:|--------:|-------:| +| 5,000 | 18.2ms | 17.9ms | -2% | +| 10,000 | 39.5ms | 17.2ms | **-56%** | + +--- + ## Scale Comparison Summary Side-by-side comparison across all note counts for the most common query patterns. @@ -193,21 +305,28 @@ Side-by-side comparison across all note counts for the most common query pattern ## Summary of Improvements -### Where the feature branch clearly wins (consistent 25-60% improvement): -- **Single-token autocomplete** at all scales (29-42% faster) -- **Multi-token autocomplete** — the biggest consistent gains (50-70% faster) +### Autocomplete (typing in search bar) — 30-70% faster: +- **Single-token** at all scales (29-42% faster) +- **Multi-token** — the biggest consistent gains (50-70% faster) - **Typing progression** (26-49% faster per keystroke at 10K notes) - **Diacritics queries** (28-53% faster) -- **Broad term autocomplete** (e.g., `"note"` matching 8,500 results: 49% faster) -- **Realistic user session queries** (33-47% faster for typical searches) +- **Broad term** (e.g., `"note"` matching 8,500 results: 49% faster) -### Where the feature branch dramatically wins (80%+ improvement): +### Full search (pressing Enter) — 25-58% faster: +- **Multi-token full search** (fuzzy OFF): 47-64% faster at all scales +- **Multi-token full search** (fuzzy ON): 45-65% faster at all scales +- **4-token full search** at 10K: 51-56% faster +- **Typo recovery** (`"projct planing"` + fuzzy): 134ms → 95ms (**-29%**) +- **Realistic queries** (`"project planning"` full search): 33ms → 19ms (**-43%**) + +### Dramatic wins (80%+ improvement): - **Autocomplete with fuzzy ON, no-match queries** (65-92% faster — fuzzy fallback skipped entirely) -- **Autocomplete typo queries** (e.g., `"projct"` + fuzzy: 101ms -> 6ms, **-94%**) +- **Autocomplete typo queries** (e.g., `"projct"` + fuzzy: 101ms → 6ms, **-94%**) -### Where performance is roughly equal: -- Full search fuzzy typo path — slight regression (+9-12%) because the two-phase fuzzy scan still runs -- No-match queries without fuzzy at smaller scales (within noise) +### Where performance is roughly equal or slightly slower: +- Single-token full search at 1K notes (small dataset noise) +- No-match queries without fuzzy at smaller scales +- Full-search worst case (no-match + multi-token + fuzzy): 4-11% improvement ### Key optimizations in this PR: 1. **Pre-built flat text index** with incremental updates in Becca @@ -216,7 +335,9 @@ Side-by-side comparison across all note counts for the most common query pattern 4. **Cached normalized parent titles** per search execution 5. **Set-based token lookup** in searchPathTowardsRoot (O(1) vs O(n)) 6. **Removed redundant toLowerCase()** throughout scoring pipeline -7. **Skip edit distance** when fuzzy matching is disabled -8. **Faster content snippet extraction** — regex strip, window normalization -9. **removeDiacritic() outside regex while-loop** in highlighting -10. **Single-token autocomplete fast path** — skips recursive parent walk +7. **Pre-normalize tokens once** in addScoreForStrings instead of per-chunk +8. **Skip edit distance** when fuzzy matching is disabled +9. **Faster content snippet extraction** — regex strip, window normalization +10. **removeDiacritic() outside regex while-loop** in highlighting +11. **Single-token autocomplete fast path** — skips recursive parent walk +12. **User option** to disable fuzzy matching entirely for fastest mode From bd25ae77fc0c0ed2e929ce10c348e484fa8d10ce Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Sat, 21 Mar 2026 11:27:50 -0700 Subject: [PATCH 028/482] docs(search): rewrite benchmark doc for clarity Consolidated from 12 sections to 4. Leads with the e2e results a reviewer cares about, follows with scaling data, then lists what changed and known limitations. Removed redundant tables and internal-only details. --- docs/search-performance-benchmarks.md | 384 +++++--------------------- 1 file changed, 76 insertions(+), 308 deletions(-) diff --git a/docs/search-performance-benchmarks.md b/docs/search-performance-benchmarks.md index b11270e203..17b9427ba5 100644 --- a/docs/search-performance-benchmarks.md +++ b/docs/search-performance-benchmarks.md @@ -1,343 +1,111 @@ -# Search Performance Benchmarks: `main` vs `feat/search-perf-take1` +# Search Performance Benchmarks -> **Date:** 2026-03-21 -> **Environment:** In-memory benchmarks (monkeypatched `getContent()`, no real SQLite I/O). Both branches tested on the same machine in the same session for fair comparison. All times are avg of 5 iterations with warm caches unless noted. +Comparison of `main` vs `feat/search-perf-take1` branch. + +> **Methodology:** In-memory benchmarks using synthetic datasets with monkeypatched `getContent()`. Both branches tested on the same machine in the same session. Times are avg of 5 iterations with warm caches. Note content I/O (`NoteContentFulltextExp` blob scan) is not measured — these numbers reflect the in-memory pipeline only. +> > **Benchmark source:** `apps/server/src/services/search/services/search_benchmark.spec.ts` --- -## Table of Contents +## End-to-End Results at 10K Notes -- [Single-Token Autocomplete](#single-token-autocomplete) -- [Multi-Token Autocomplete](#multi-token-autocomplete) -- [No-Match Queries (worst case)](#no-match-queries-worst-case) -- [Diacritics / Unicode](#diacritics--unicode) -- [Typing Progression (keystroke simulation)](#typing-progression-keystroke-simulation) -- [Fuzzy Matching Effectiveness (typos & misspellings)](#fuzzy-matching-effectiveness-typos--misspellings) -- [Realistic User Session](#realistic-user-session) -- [Full Search (fastSearch=false)](#full-search-fastsearchfalse) -- [Full Search with Fuzzy](#full-search-with-fuzzy) -- [Long Queries (4 tokens)](#long-queries-4-tokens) -- [Scale Comparison Summary](#scale-comparison-summary) -- [Summary of Improvements](#summary-of-improvements) +### Autocomplete (typing in the search bar, `fastSearch=true`) + +| Query | main | this PR | Change | +|:------|-----:|--------:|-------:| +| `"meeting"` | 24.7ms | 14.3ms | **-42%** | +| `"meeting notes"` | 33.0ms | 15.6ms | **-53%** | +| `"meeting notes january"` | 43.2ms | 17.7ms | **-59%** | +| `"documentation"` | 17.5ms | 11.0ms | **-37%** | +| `"note"` (matches 85% of notes) | 90.8ms | 46.4ms | **-49%** | +| `"projct"` (typo, fuzzy ON) | 100.7ms | 6.0ms | **-94%** | +| `"xyznonexistent"` (no match, fuzzy ON) | 18.2ms | 6.0ms | **-67%** | +| `"xyzfoo xyzbar"` (no match, fuzzy ON) | 63.4ms | 7.1ms | **-89%** | + +### Full Search (pressing Enter, `fastSearch=false`) + +| Query | main | this PR | Change | +|:------|-----:|--------:|-------:| +| `"meeting"` | 22.9ms | 19.6ms | **-14%** | +| `"meeting notes"` | 35.7ms | 17.4ms | **-51%** | +| `"meeting notes january"` | 43.4ms | 21.0ms | **-52%** | +| `"quarterly budget review report"` | 37.1ms | 18.3ms | **-51%** | +| `"project planning"` | 27.4ms | 17.3ms | **-37%** | + +### Full Search with Fuzzy Matching + +| Query | main | this PR | Change | +|:------|-----:|--------:|-------:| +| `"meeting"` | 23.3ms | 17.8ms | **-24%** | +| `"meeting notes"` | 33.8ms | 18.6ms | **-45%** | +| `"meeting notes january"` | 43.2ms | 18.0ms | **-58%** | +| `"quarterly budget review report"` | 39.5ms | 17.2ms | **-56%** | +| `"project planning"` | 32.8ms | 18.6ms | **-43%** | +| `"projct planing"` (typo, recovers 1,500 results) | 133.8ms | 94.8ms | **-29%** | +| `"xyzfoo xyzbar"` (no match, worst case) | 64.2ms | 61.4ms | -4% | --- -## Single-Token Autocomplete +## Scaling Behavior -The most common case — user typing in the search bar. Query: `"meeting"`, autocomplete, fuzzy OFF. +### Autocomplete: `"meeting notes"` (fuzzy OFF) -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 2.5ms | 1.6ms | **-36%** | -| 5,000 | 9.5ms | 6.7ms | **-29%** | -| 10,000 | 24.7ms | 14.3ms | **-42%** | -| 20,000 | 45.1ms | 29.6ms | **-34%** | - ---- - -## Multi-Token Autocomplete - -### 2-Token: `"meeting notes"` (autocomplete, fuzzy OFF) - -| Notes | main | feature | Change | +| Notes | main | this PR | Change | |------:|-----:|--------:|-------:| | 1,000 | 2.7ms | 1.1ms | **-59%** | | 5,000 | 15.8ms | 5.9ms | **-63%** | | 10,000 | 33.0ms | 15.6ms | **-53%** | | 20,000 | 67.3ms | 33.6ms | **-50%** | -### 3-Token: `"meeting notes january"` (autocomplete, fuzzy OFF) +### Full search: `"meeting notes january"` (fuzzy ON) -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 3.7ms | 1.1ms | **-70%** | -| 5,000 | 20.7ms | 7.3ms | **-65%** | -| 10,000 | 43.2ms | 17.7ms | **-59%** | -| 20,000 | 91.2ms | 35.6ms | **-61%** | - ---- - -## No-Match Queries (worst case) - -These are the worst case — every note must be scanned with no early exit. - -### Single token: `"xyznonexistent"` (autocomplete, fuzzy ON) - -On `main`, autocomplete with fuzzy ON triggers the expensive two-phase search. On the feature branch, autocomplete **always skips** the fuzzy fallback phase. - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 1.6ms | 0.4ms | **-75%** | -| 5,000 | 8.1ms | 2.1ms | **-74%** | -| 10,000 | 18.2ms | 6.0ms | **-67%** | -| 20,000 | 49.2ms | 17.1ms | **-65%** | - -### Multi token: `"xyzfoo xyzbar"` (autocomplete, fuzzy ON) - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 5.1ms | 0.4ms | **-92%** | -| 5,000 | 29.0ms | 2.2ms | **-92%** | -| 10,000 | 63.4ms | 7.1ms | **-89%** | -| 20,000 | 128.8ms | 19.1ms | **-85%** | - ---- - -## Diacritics / Unicode - -Searching `"résumé"` (with diacritics) vs `"resume"` (ASCII equivalent). Both forms find the same results thanks to diacritic normalization. Autocomplete, fuzzy OFF. - -| Notes | Query | main | feature | Change | -|------:|:------|-----:|--------:|-------:| -| 1,000 | `"résumé"` | 2.8ms | 1.7ms | **-39%** | -| 1,000 | `"resume"` | 2.9ms | 1.5ms | **-48%** | -| 5,000 | `"résumé"` | 15.7ms | 10.4ms | **-34%** | -| 5,000 | `"resume"` | 16.3ms | 7.7ms | **-53%** | -| 10,000 | `"résumé"` | 32.4ms | 23.3ms | **-28%** | -| 10,000 | `"resume"` | 30.7ms | 20.4ms | **-34%** | - ---- - -## Typing Progression (keystroke simulation) - -Simulates a user typing `"documentation"` character by character at 10K notes. Autocomplete, fuzzy OFF. - -| Prefix | main | feature | Change | -|:-------|-----:|--------:|-------:| -| `"d"` | 66.9ms | 44.8ms | **-33%** | -| `"do"` | 22.9ms | 17.0ms | **-26%** | -| `"doc"` | 20.9ms | 14.7ms | **-30%** | -| `"docu"` | 20.0ms | 13.0ms | **-35%** | -| `"docum"` | 23.0ms | 11.8ms | **-49%** | -| `"document"` | 16.8ms | 11.8ms | **-30%** | -| `"documentation"` | 17.5ms | 11.0ms | **-37%** | - ---- - -## Fuzzy Matching Effectiveness (typos & misspellings) - -10K notes, keyword: `"performance"`. Shows both time improvement and result correctness. - -| Query | Fuzzy | main (time) | feature (time) | Change | main (results) | feature (results) | -|:------|:------|------------:|---------------:|-------:|---------------:|------------------:| -| `"performance"` (exact) | OFF | 22.0ms | 25.9ms | +18% | 1,000 | 1,000 | -| `"performance"` (exact) | ON | 14.1ms | 18.2ms | +29% | 1,000 | 1,000 | -| `"performanc"` (truncated) | OFF | 16.6ms | 16.8ms | +1% | 1,000 | 1,000 | -| `"performanc"` (truncated) | ON | 16.0ms | 13.5ms | **-16%** | 1,000 | 1,000 | -| `"preformance"` (typo) | OFF | 9.0ms | 9.4ms | +4% | 0 | 0 | -| `"preformance"` (typo) | ON | 46.3ms | 51.7ms | +12% | 1,000 | 1,000 | -| `"performence"` (misspelling) | OFF | 9.0ms | 10.8ms | +20% | 0 | 0 | -| `"performence"` (misspelling) | ON | 45.4ms | 49.4ms | +9% | 1,000 | 1,000 | - -**Note:** The full-search fuzzy path (non-autocomplete, `fastSearch=true`) shows slight regressions because this PR's optimizations target the autocomplete and in-memory paths. Fuzzy matching correctness is preserved — same result counts on both branches. - ---- - -## Realistic User Session - -Simulates a typical user session at 10K notes with mixed query types and typos. - -| Query | Mode | main | feature | Change | -|:------|:-----|-----:|--------:|-------:| -| `"pro"` | autocomplete | 24.3ms | 14.1ms | **-42%** | -| `"project"` | autocomplete | 25.7ms | 13.6ms | **-47%** | -| `"project"` | fullSearch | 27.4ms | 17.3ms | **-37%** | -| `"projct"` (typo) | autocomplete | 8.9ms | 5.9ms | **-34%** | -| `"projct"` (typo) | autocomplete+fuzzy | **100.7ms** | **6.0ms** | **-94%** | -| `"note"` (very common) | autocomplete | **90.8ms** | **46.4ms** | **-49%** | -| `"document"` | autocomplete | 22.7ms | 15.2ms | **-33%** | - -**Biggest wins:** `"projct"` autocomplete+fuzzy goes from 100.7ms to 6.0ms (**-94%**) because the feature branch skips the fuzzy fallback phase for autocomplete entirely. `"note"` (matching 8,500 of 10K notes) drops from 91ms to 46ms (**-49%**). - ---- - -## Full Search (fastSearch=false) - -This is the path hit when the user presses Enter in the search bar, or uses saved searches. It runs `NoteFlatTextExp` + `NoteContentFulltextExp` via `OrExp`. - -> Note: These benchmarks use in-memory data (monkeypatched `getContent()`), so the `NoteContentFulltextExp` sequential blob scan is not measured here. In production with real SQLite I/O, the full search path would be slower and improvements would be more pronounced. - -### Single token: `"meeting"` (fuzzy OFF) - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 2.3ms | 3.3ms | +43% | -| 5,000 | 9.6ms | 9.7ms | +1% | -| 10,000 | 22.9ms | 19.6ms | **-14%** | -| 20,000 | 47.6ms | 37.9ms | **-20%** | - -### 2-Token: `"meeting notes"` (fuzzy OFF) - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 3.3ms | 1.2ms | **-64%** | -| 5,000 | 16.1ms | 6.9ms | **-57%** | -| 10,000 | 35.7ms | 17.4ms | **-51%** | -| 20,000 | 71.9ms | 38.2ms | **-47%** | - -### 3-Token: `"meeting notes january"` (fuzzy OFF) - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 3.9ms | 1.3ms | **-67%** | -| 5,000 | 20.9ms | 8.9ms | **-57%** | -| 10,000 | 43.4ms | 21.0ms | **-52%** | -| 20,000 | 91.7ms | 41.9ms | **-54%** | - ---- - -## Full Search with Fuzzy - -### Single token: `"meeting"` (fuzzy ON) - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 1.8ms | 2.8ms | +56% | -| 5,000 | 11.1ms | 8.2ms | **-26%** | -| 10,000 | 23.3ms | 17.8ms | **-24%** | -| 20,000 | 48.7ms | 35.1ms | **-28%** | - -### 2-Token: `"meeting notes"` (fuzzy ON) - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 3.3ms | 1.2ms | **-64%** | -| 5,000 | 16.4ms | 7.1ms | **-57%** | -| 10,000 | 33.8ms | 18.6ms | **-45%** | -| 20,000 | 70.7ms | 37.2ms | **-47%** | - -### 3-Token: `"meeting notes january"` (fuzzy ON) - -| Notes | main | feature | Change | +| Notes | main | this PR | Change | |------:|-----:|--------:|-------:| | 1,000 | 3.7ms | 1.3ms | **-65%** | | 5,000 | 21.2ms | 8.7ms | **-59%** | | 10,000 | 43.2ms | 18.0ms | **-58%** | | 20,000 | 92.8ms | 40.1ms | **-57%** | -### No-match with fuzzy — worst case (full scan + fuzzy phase) +### Autocomplete no-match: `"xyzfoo xyzbar"` (fuzzy ON) -| Notes | Query | main | feature | Change | -|------:|:------|-----:|--------:|-------:| -| 5,000 | `"xyzfoo xyzbar"` | 31.7ms | 28.6ms | **-10%** | -| 10,000 | `"xyzfoo xyzbar"` | 64.2ms | 61.4ms | -4% | -| 20,000 | `"xyzfoo xyzbar"` | 142.9ms | 127.5ms | **-11%** | +| Notes | main | this PR | Change | +|------:|-----:|--------:|-------:| +| 1,000 | 5.1ms | 0.4ms | **-92%** | +| 5,000 | 29.0ms | 2.2ms | **-92%** | +| 10,000 | 63.4ms | 7.1ms | **-89%** | +| 20,000 | 128.8ms | 19.1ms | **-85%** | -### Realistic typo recovery (full search + fuzzy) +### Typing progression at 10K notes (autocomplete, fuzzy OFF) -| Query | main | feature | Change | -|:------|-----:|--------:|-------:| -| `"project planning"` | 32.8ms | 18.6ms | **-43%** | -| `"projct planing"` (typo, fuzzy OFF) | 10.5ms | 7.8ms | **-26%** | -| `"projct planing"` (typo, fuzzy ON — recovers 1,500 results) | 133.8ms | 94.8ms | **-29%** | +| Prefix typed | main | this PR | Change | +|:-------------|-----:|--------:|-------:| +| `"d"` | 66.9ms | 44.8ms | **-33%** | +| `"doc"` | 20.9ms | 14.7ms | **-30%** | +| `"document"` | 16.8ms | 11.8ms | **-30%** | +| `"documentation"` | 17.5ms | 11.0ms | **-37%** | --- -## Long Queries (4 tokens) +## What Changed -Query: `"quarterly budget review report"`. - -### Autocomplete - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 5,000 | 17.2ms | 11.9ms | **-31%** | -| 10,000 | 36.8ms | 15.9ms | **-57%** | - -### Full search (fuzzy OFF) - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 5,000 | 17.6ms | 25.4ms | +44% | -| 10,000 | 37.1ms | 18.3ms | **-51%** | - -### Full search (fuzzy ON) - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 5,000 | 18.2ms | 17.9ms | -2% | -| 10,000 | 39.5ms | 17.2ms | **-56%** | +1. **Pre-built flat text index** with incremental dirty-marking in Becca — avoids rebuilding per-note flat text on every search +2. **Skip two-phase fuzzy fallback for autocomplete** — the user is still typing, fuzzy adds latency for no benefit +3. **Pre-normalized attribute names/values** cached on `BAttribute` at construction time +4. **Cached normalized parent titles** per search execution via `Map` in `NoteFlatTextExp` +5. **Set-based token lookup** in `searchPathTowardsRoot` (O(1) vs O(n) `Array.includes`) +6. **Removed redundant `toLowerCase()`** — `normalizeSearchText` already lowercases; callers were double-lowering +7. **Pre-normalize tokens once** in `addScoreForStrings` instead of re-normalizing per chunk +8. **Skip edit distance computation** when fuzzy matching is disabled +9. **Faster content snippet extraction** — regex `/<[^>]*>/g` instead of `striptags` library; normalize only the snippet window, not full content +10. **`removeDiacritic()` hoisted outside regex while-loop** in highlighting +11. **Single-token autocomplete fast path** — skips the recursive parent walk entirely, uses `getBestNotePath()` directly +12. **User option `searchEnableFuzzyMatching`** — lets users disable fuzzy matching for fastest possible search --- -## Scale Comparison Summary +## Known Limitations -Side-by-side comparison across all note counts for the most common query patterns. - -### `"meeting"` autocomplete (fuzzy OFF) - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 2.5ms | 1.6ms | **-36%** | -| 5,000 | 10.3ms | 7.6ms | **-26%** | -| 10,000 | 22.5ms | 14.4ms | **-36%** | -| 20,000 | 53.7ms | 33.2ms | **-38%** | - -### `"meeting notes"` autocomplete (fuzzy OFF) - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 4.6ms | 1.1ms | **-76%** | -| 5,000 | 17.5ms | 6.7ms | **-62%** | -| 10,000 | 32.7ms | 16.8ms | **-49%** | -| 20,000 | 71.6ms | 38.9ms | **-46%** | - -### `"xyznonexistent"` autocomplete (fuzzy OFF) - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 0.4ms | 0.4ms | 0% | -| 5,000 | 2.2ms | 2.3ms | +5% | -| 10,000 | 6.3ms | 8.4ms | +33% | -| 20,000 | 21.9ms | 19.3ms | **-12%** | - -### `"xyznonexistent"` fullSearch (fuzzy ON) — worst case path - -| Notes | main | feature | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 1.2ms | 1.0ms | **-17%** | -| 5,000 | 8.6ms | 8.7ms | +1% | -| 10,000 | 22.4ms | 22.2ms | -1% | -| 20,000 | 72.2ms | 64.5ms | **-11%** | - ---- - -## Summary of Improvements - -### Autocomplete (typing in search bar) — 30-70% faster: -- **Single-token** at all scales (29-42% faster) -- **Multi-token** — the biggest consistent gains (50-70% faster) -- **Typing progression** (26-49% faster per keystroke at 10K notes) -- **Diacritics queries** (28-53% faster) -- **Broad term** (e.g., `"note"` matching 8,500 results: 49% faster) - -### Full search (pressing Enter) — 25-58% faster: -- **Multi-token full search** (fuzzy OFF): 47-64% faster at all scales -- **Multi-token full search** (fuzzy ON): 45-65% faster at all scales -- **4-token full search** at 10K: 51-56% faster -- **Typo recovery** (`"projct planing"` + fuzzy): 134ms → 95ms (**-29%**) -- **Realistic queries** (`"project planning"` full search): 33ms → 19ms (**-43%**) - -### Dramatic wins (80%+ improvement): -- **Autocomplete with fuzzy ON, no-match queries** (65-92% faster — fuzzy fallback skipped entirely) -- **Autocomplete typo queries** (e.g., `"projct"` + fuzzy: 101ms → 6ms, **-94%**) - -### Where performance is roughly equal or slightly slower: -- Single-token full search at 1K notes (small dataset noise) -- No-match queries without fuzzy at smaller scales -- Full-search worst case (no-match + multi-token + fuzzy): 4-11% improvement - -### Key optimizations in this PR: -1. **Pre-built flat text index** with incremental updates in Becca -2. **Skip two-phase fuzzy fallback** for autocomplete searches -3. **Pre-normalized attribute names/values** on BAttribute -4. **Cached normalized parent titles** per search execution -5. **Set-based token lookup** in searchPathTowardsRoot (O(1) vs O(n)) -6. **Removed redundant toLowerCase()** throughout scoring pipeline -7. **Pre-normalize tokens once** in addScoreForStrings instead of per-chunk -8. **Skip edit distance** when fuzzy matching is disabled -9. **Faster content snippet extraction** — regex strip, window normalization -10. **removeDiacritic() outside regex while-loop** in highlighting -11. **Single-token autocomplete fast path** — skips recursive parent walk -12. **User option** to disable fuzzy matching entirely for fastest mode +- These benchmarks measure the **in-memory pipeline only** (titles, attributes, scoring, highlighting). The `NoteContentFulltextExp` sequential blob scan from SQLite is not exercised because `getContent()` is monkeypatched. In production, the full search path (`fastSearch=false`) includes reading every note's content from disk, which adds significant time at scale. +- Fuzzy matching on the full-search two-phase path shows slight regressions (+9-12%) for single-token queries because edit distance computation cost hasn't changed on that path. Multi-token queries still improve because the token normalization and tree walk optimizations apply to both paths. +- At 1K notes, some results show noise-level regressions. The optimizations target 5K+ note scales where overhead is measurable. From 8d5e82fa5e1263df3bb281827950eded8bf0c44a Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 22 Mar 2026 10:25:35 +0200 Subject: [PATCH 029/482] client/contributor list: refine filtering --- apps/client/src/services/contributors_list.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/client/src/services/contributors_list.ts b/apps/client/src/services/contributors_list.ts index 7e1a4fb98a..902d0538ca 100644 --- a/apps/client/src/services/contributors_list.ts +++ b/apps/client/src/services/contributors_list.ts @@ -28,8 +28,8 @@ export default async function getContributors() { function getList(contributorInfo: any[]) { return contributorInfo - // Filter out bots and private profiles - .filter((c) => c.type === "User" && c.user_view_type === "public" && !BOTS.includes(c.login)) + // Filter out bots + .filter((c) => c.type === "User" && !BOTS.includes(c.login)) // Sort by the commit count. Honorific contributors are always first. .sort(contributorOrderer) .map((c) => {return { From 31578521cfa66ed61923092feffdb70bf6b009d2 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 22 Mar 2026 10:27:27 +0200 Subject: [PATCH 030/482] client/about dialog: create a new UI --- .../src/translations/en/translation.json | 8 +- apps/client/src/widgets/dialogs/about.css | 11 +++ apps/client/src/widgets/dialogs/about.tsx | 80 +++++++++---------- 3 files changed, 57 insertions(+), 42 deletions(-) create mode 100644 apps/client/src/widgets/dialogs/about.css diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 27891a02ab..fa10640cc8 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -7,7 +7,13 @@ "sync_version": "Sync version:", "build_date": "Build date:", "build_revision": "Build revision:", - "data_directory": "Data directory:" + "data_directory": "Data directory:", + + "version_label": "Version", + "version": "app: {{appVersion}}, database: {{dbVersion}}, sync protocol: {{syncVersion}}", + "build_info": "{{buildDate}}, revision: {{buildRevision}}", + "contributors_label": "Contributors" + }, "toast": { "critical-error": { diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css new file mode 100644 index 0000000000..2ea9eeb628 --- /dev/null +++ b/apps/client/src/widgets/dialogs/about.css @@ -0,0 +1,11 @@ +.property-sheet-card { + font-size: .85em; + + .tn-card-section { + display: flex; + + > :first-child { + width: 100px; + } + } +} \ No newline at end of file diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index f09cca3191..47da8e9cf8 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -8,18 +8,19 @@ import { useState } from "preact/hooks"; import type { CSSProperties } from "preact/compat"; import type { AppInfo } from "@triliumnext/commons"; import { useTriliumEvent } from "../react/hooks.jsx"; +import logo from "../../assets/icon.png"; +import { Card, CardSection } from "../react/Card.js"; +import "./about.css"; export default function AboutDialog() { const [appInfo, setAppInfo] = useState(null); const [shown, setShown] = useState(false); - const forceWordBreak: CSSProperties = { wordBreak: "break-all" }; useTriliumEvent("openAboutDialog", () => setShown(true)); return ( { const appInfo = await server.get("app-info"); @@ -27,44 +28,41 @@ export default function AboutDialog() { }} onHidden={() => setShown(false)} > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{t("about.homepage")}https://github.com/TriliumNext/Trilium
{t("about.app_version")}{appInfo?.appVersion}
{t("about.db_version")}{appInfo?.dbVersion}
{t("about.sync_version")}{appInfo?.syncVersion}
{t("about.build_date")} - {appInfo?.buildDate ? formatDateTime(appInfo.buildDate) : ""} -
{t("about.build_revision")} - {appInfo?.buildRevision && {appInfo.buildRevision}} -
{t("about.data_directory")} - {appInfo?.dataDirectory && ()} -
+
+ +

Trilium Notes

+ + triliumnotes.org + + + + +
{t("about.version_label")}
+
+ {t("about.version", { + appVersion: appInfo?.appVersion, + dbVersion: appInfo?.dbVersion, + syncVersion: appInfo?.syncVersion + })} +
+ {t("about.build_info", { + buildDate: appInfo?.buildDate ? formatDateTime(appInfo.buildDate) : "", + buildRevision: appInfo?.buildRevision ? appInfo.buildRevision.substring(0, 6) : "" + })} +
+
+
+ +
{t("about.contributors_label")}
+
+ +
{t("about.data_directory")}
+
+ {appInfo?.dataDirectory && ()} +
+
+
+
); } From 19dfbaacce1ffc7ccc0167cfaf9388c95b5bfb68 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 22 Mar 2026 11:14:16 +0200 Subject: [PATCH 031/482] client/about dialog: improve, add GitHub and donate buttons --- .../src/translations/en/translation.json | 18 +++------ apps/client/src/widgets/dialogs/about.css | 38 ++++++++++++++++--- apps/client/src/widgets/dialogs/about.tsx | 18 ++++++++- 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index fa10640cc8..5732fb857f 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -1,19 +1,11 @@ { - "about": { - "title": "About Trilium Notes", - "homepage": "Homepage:", - "app_version": "App version:", - "db_version": "DB version:", - "sync_version": "Sync version:", - "build_date": "Build date:", - "build_revision": "Build revision:", - "data_directory": "Data directory:", - - "version_label": "Version", + "about": { + "version_label": "Version:", "version": "app: {{appVersion}}, database: {{dbVersion}}, sync protocol: {{syncVersion}}", "build_info": "{{buildDate}}, revision: {{buildRevision}}", - "contributors_label": "Contributors" - + "contributors_label": "Contributors:", + "data_directory": "Data directory:", + "donate": "Donate" }, "toast": { "critical-error": { diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css index 2ea9eeb628..09b22b9ead 100644 --- a/apps/client/src/widgets/dialogs/about.css +++ b/apps/client/src/widgets/dialogs/about.css @@ -1,11 +1,37 @@ -.property-sheet-card { - font-size: .85em; - - .tn-card-section { +.about-dialog { + .about-dialog-content { display: flex; + flex-direction: column; + align-items: center; + } - > :first-child { - width: 100px; + .property-sheet-card { + margin-block: 30px; + font-size: .85em; + + .tn-card-section { + display: flex; + + > :first-child { + width: 100px; + } + } + } + + footer { + display: flex; + justify-content: center; + gap: 20px; + margin-bottom: 30px; + + a { + display: flex; + flex-direction: column; + align-items: center; + + &::after { + display: none; + } } } } \ No newline at end of file diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index 47da8e9cf8..a8bce73e48 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -28,13 +28,14 @@ export default function AboutDialog() { }} onHidden={() => setShown(false)} > -
+
+

Trilium Notes

triliumnotes.org - +
{t("about.version_label")}
@@ -63,6 +64,19 @@ export default function AboutDialog() {
+ + ); } From 75da044bbefc6b033fd8ffdddea8adb3eff21815 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 22 Mar 2026 17:21:20 +0200 Subject: [PATCH 032/482] client/about dialog: add a link for the build revision --- .../src/translations/en/translation.json | 2 +- apps/client/src/widgets/dialogs/about.tsx | 23 ++++++++++++++----- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 5732fb857f..e1271388b3 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -2,7 +2,7 @@ "about": { "version_label": "Version:", "version": "app: {{appVersion}}, database: {{dbVersion}}, sync protocol: {{syncVersion}}", - "build_info": "{{buildDate}}, revision: {{buildRevision}}", + "build_info": "{{buildDate}}, revision: ", "contributors_label": "Contributors:", "data_directory": "Data directory:", "donate": "Donate" diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index a8bce73e48..bb6238108f 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -11,6 +11,8 @@ import { useTriliumEvent } from "../react/hooks.jsx"; import logo from "../../assets/icon.png"; import { Card, CardSection } from "../react/Card.js"; import "./about.css"; +import { Trans } from "react-i18next"; +import type React from "react"; export default function AboutDialog() { const [appInfo, setAppInfo] = useState(null); @@ -39,17 +41,26 @@ export default function AboutDialog() {
{t("about.version_label")}
-
+
{t("about.version", { appVersion: appInfo?.appVersion, dbVersion: appInfo?.dbVersion, syncVersion: appInfo?.syncVersion })}
- {t("about.build_info", { - buildDate: appInfo?.buildDate ? formatDateTime(appInfo.buildDate) : "", - buildRevision: appInfo?.buildRevision ? appInfo.buildRevision.substring(0, 6) : "" - })} + + {appInfo?.buildRevision && + {appInfo.buildRevision.substring(0, 7)} + } + as React.ReactElement + }} + />
@@ -58,7 +69,7 @@ export default function AboutDialog() {
{t("about.data_directory")}
-
+
{appInfo?.dataDirectory && ()}
From 8f2387462871e225c27b8312a94c1982c568e1a7 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 22 Mar 2026 18:17:13 +0200 Subject: [PATCH 033/482] client/about dialog: add an indication for the nightly version, use SVG icons --- apps/client/src/assets/icon-alt.svg | 17 ++++++++++++++ apps/client/src/assets/icon.svg | 28 +++++++++++++++++++++++ apps/client/src/widgets/dialogs/about.tsx | 13 ++++++++--- 3 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 apps/client/src/assets/icon-alt.svg create mode 100644 apps/client/src/assets/icon.svg diff --git a/apps/client/src/assets/icon-alt.svg b/apps/client/src/assets/icon-alt.svg new file mode 100644 index 0000000000..dae45a4222 --- /dev/null +++ b/apps/client/src/assets/icon-alt.svg @@ -0,0 +1,17 @@ + + + Trilium Notes + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/client/src/assets/icon.svg b/apps/client/src/assets/icon.svg new file mode 100644 index 0000000000..943f1bfe89 --- /dev/null +++ b/apps/client/src/assets/icon.svg @@ -0,0 +1,28 @@ + + + Trilium Notes + + + + + + + + + + + + + + + diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index bb6238108f..f9ba761e2d 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -8,18 +8,25 @@ import { useState } from "preact/hooks"; import type { CSSProperties } from "preact/compat"; import type { AppInfo } from "@triliumnext/commons"; import { useTriliumEvent } from "../react/hooks.jsx"; -import logo from "../../assets/icon.png"; import { Card, CardSection } from "../react/Card.js"; import "./about.css"; import { Trans } from "react-i18next"; import type React from "react"; +import icon from "../../assets/icon.svg"; +import iconAlt from "../../assets/icon-alt.svg"; +import { useEffect } from "react"; export default function AboutDialog() { const [appInfo, setAppInfo] = useState(null); const [shown, setShown] = useState(false); + const [isNightly, setNightly] = useState(false); useTriliumEvent("openAboutDialog", () => setShown(true)); + useEffect(() => { + setNightly(!!appInfo?.appVersion.includes("test")); + }, [appInfo]) + return (
- -

Trilium Notes

+ +

Trilium Notes {isNightly && Nightly}

triliumnotes.org From 1b9124422a29f96af80440a9bdedbd782f4e5ce8 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 22 Mar 2026 18:40:26 +0200 Subject: [PATCH 034/482] client/about dialog: switch to boxicons --- apps/client/src/widgets/dialogs/about.css | 4 ++++ apps/client/src/widgets/dialogs/about.tsx | 6 ++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css index 09b22b9ead..d6113c9bc1 100644 --- a/apps/client/src/widgets/dialogs/about.css +++ b/apps/client/src/widgets/dialogs/about.css @@ -32,6 +32,10 @@ &::after { display: none; } + + i { + font-size: 32px; + } } } } \ No newline at end of file diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index f9ba761e2d..69783e198c 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -85,13 +85,11 @@ export default function AboutDialog() { From 555d997e34a37f5af14a41fa3565bf14f425f170 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 22 Mar 2026 18:53:23 +0200 Subject: [PATCH 035/482] client/about dialog: show the dialog only after the required information is ready --- apps/client/src/widgets/dialogs/about.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index 69783e198c..d47e8167a4 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -14,14 +14,21 @@ import { Trans } from "react-i18next"; import type React from "react"; import icon from "../../assets/icon.svg"; import iconAlt from "../../assets/icon-alt.svg"; -import { useEffect } from "react"; +import { useCallback, useEffect } from "react"; export default function AboutDialog() { const [appInfo, setAppInfo] = useState(null); const [shown, setShown] = useState(false); const [isNightly, setNightly] = useState(false); - useTriliumEvent("openAboutDialog", () => setShown(true)); + const onLoad = useCallback(async () => { + if (!appInfo) { + setAppInfo(await server.get("app-info")); + } + setShown(true); + }, []); + + useTriliumEvent("openAboutDialog", onLoad); useEffect(() => { setNightly(!!appInfo?.appVersion.includes("test")); @@ -31,10 +38,6 @@ export default function AboutDialog() { { - const appInfo = await server.get("app-info"); - setAppInfo(appInfo); - }} onHidden={() => setShown(false)} >
From b4d0af6eb2da7e6ca3f016aacf0b6698009ab43b Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 22 Mar 2026 18:55:46 +0200 Subject: [PATCH 036/482] client/modals: make the title optional --- apps/client/src/widgets/react/Modal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/client/src/widgets/react/Modal.tsx b/apps/client/src/widgets/react/Modal.tsx index e7a7c721f8..91bc690049 100644 --- a/apps/client/src/widgets/react/Modal.tsx +++ b/apps/client/src/widgets/react/Modal.tsx @@ -16,7 +16,7 @@ interface CustomTitleBarButton { export interface ModalProps { className: string; - title: string | ComponentChildren; + title?: string | ComponentChildren; customTitleBarButtons?: (CustomTitleBarButton | null)[]; size: "xl" | "lg" | "md" | "sm"; children: ComponentChildren; From 978e02350c9f589a83726e549350190ca8c401c1 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 22 Mar 2026 19:14:44 +0200 Subject: [PATCH 037/482] client: revert the Vite build script --- apps/client/vite.config.mts | 44 ++++++++++--------------------------- 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/apps/client/vite.config.mts b/apps/client/vite.config.mts index 08effeea2f..8c6debfc08 100644 --- a/apps/client/vite.config.mts +++ b/apps/client/vite.config.mts @@ -1,34 +1,13 @@ -/// -import prefresh from "@prefresh/vite"; -import { join, resolve } from "path"; -import webpackStatsPlugin from "rollup-plugin-webpack-stats"; -import { defineConfig } from "vite"; -import { viteStaticCopy } from "vite-plugin-static-copy" -import { writeFileSync, mkdirSync } from "fs"; -import getContributors from "./src/services/contributors_list"; +/// +import prefresh from '@prefresh/vite'; +import { join } from 'path'; +import webpackStatsPlugin from 'rollup-plugin-webpack-stats'; +import { defineConfig } from 'vite'; +import { viteStaticCopy } from 'vite-plugin-static-copy' const assets = [ "assets", "stylesheets", "fonts", "translations" ]; const isDev = process.env.NODE_ENV === "development"; - -const buildContributorListPlugin = { - name: "build-contributor-list-plugin", - writeBundle: async () => { - console.log("Retrieving the contributor list..."); - - let jsonData: any = {}; - try { - jsonData = await getContributors(); - } catch (ex) { - console.error(ex); - } - - const assetsDir = resolve(__dirname, "dist/assets"); - mkdirSync(assetsDir, {recursive: true}); - writeFileSync(resolve(assetsDir, "contributors.json"), JSON.stringify(jsonData, null, 2)); - } -}; - let plugins: any = []; if (isDev) { @@ -38,7 +17,6 @@ if (isDev) { ]; } else { plugins = [ - buildContributorListPlugin, viteStaticCopy({ targets: assets.map((asset) => ({ src: `src/${asset}/*`, @@ -60,17 +38,17 @@ if (isDev) { export default defineConfig(() => ({ root: __dirname, - cacheDir: "../../.cache/vite", + cacheDir: '../../.cache/vite', base: "", plugins, // Use esbuild for JSX transformation (much faster than Babel) esbuild: { - jsx: "automatic", - jsxImportSource: "preact", + jsx: 'automatic', + jsxImportSource: 'preact', jsxDev: isDev }, css: { - transformer: "lightningcss", + transformer: 'lightningcss', devSourcemap: isDev }, resolve: { @@ -101,7 +79,7 @@ export default defineConfig(() => ({ }, build: { target: "esnext", - outDir: "./dist", + outDir: './dist', emptyOutDir: true, reportCompressedSize: true, sourcemap: false, From 7646d8be0727791139f62816d8141520863dbb62 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 22 Mar 2026 19:37:22 +0200 Subject: [PATCH 038/482] client: update the contributor list via a script, persist the list into the repo --- contributors.json | 117 ++++++++++++++++++ package.json | 3 +- .../update-contributor-list.ts | 22 +++- 3 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 contributors.json rename apps/client/src/services/contributors_list.ts => scripts/update-contributor-list.ts (77%) diff --git a/contributors.json b/contributors.json new file mode 100644 index 0000000000..38350f4c5d --- /dev/null +++ b/contributors.json @@ -0,0 +1,117 @@ +{ + "⚠️": "NOTE: this is an auto-generated list. Do not modify it.", + "contributors": [ + { + "name": "eliandoran", + "url": "https://github.com/eliandoran" + }, + { + "name": "zadam", + "url": "https://github.com/zadam" + }, + { + "name": "adoriandoran", + "url": "https://github.com/adoriandoran" + }, + { + "name": "pano9000", + "url": "https://github.com/pano9000" + }, + { + "name": "perfectra1n", + "url": "https://github.com/perfectra1n" + }, + { + "name": "JYC333", + "url": "https://github.com/JYC333" + }, + { + "name": "SiriusXT", + "url": "https://github.com/SiriusXT" + }, + { + "name": "tony", + "url": "https://github.com/tony" + }, + { + "name": "Nriver", + "url": "https://github.com/Nriver" + }, + { + "name": "francistw", + "url": "https://github.com/francistw" + }, + { + "name": "isaul32", + "url": "https://github.com/isaul32" + }, + { + "name": "thfrei", + "url": "https://github.com/thfrei" + }, + { + "name": "nathancahill", + "url": "https://github.com/nathancahill" + }, + { + "name": "contributor", + "url": "https://github.com/contributor" + }, + { + "name": "FliegendeWurst", + "url": "https://github.com/FliegendeWurst" + }, + { + "name": "hasecilu", + "url": "https://github.com/hasecilu" + }, + { + "name": "Meinzzzz", + "url": "https://github.com/Meinzzzz" + }, + { + "name": "Sarah-Hussein", + "url": "https://github.com/Sarah-Hussein" + }, + { + "name": "zerebos", + "url": "https://github.com/zerebos" + }, + { + "name": "meichthys", + "url": "https://github.com/meichthys" + }, + { + "name": "questamor", + "url": "https://github.com/questamor" + }, + { + "name": "SukantGujar", + "url": "https://github.com/SukantGujar" + }, + { + "name": "soulsands", + "url": "https://github.com/soulsands" + }, + { + "name": "noobhjy", + "url": "https://github.com/noobhjy" + }, + { + "name": "laurent22", + "url": "https://github.com/laurent22" + }, + { + "name": "mlewand", + "url": "https://github.com/mlewand" + }, + { + "name": "lzinga", + "url": "https://github.com/lzinga" + }, + { + "name": "ytrkptl", + "url": "https://github.com/ytrkptl" + } + ] +} \ No newline at end of file diff --git a/package.json b/package.json index daca67fc3f..fa84898edd 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,8 @@ "dev:linter-check": "cross-env NODE_OPTIONS=--max_old_space_size=4096 eslint .", "dev:linter-fix": "cross-env NODE_OPTIONS=--max_old_space_size=4096 eslint . --fix", "postinstall": "tsx scripts/electron-rebuild.mts && pnpm prepare", - "prepare": "pnpm run --filter pdfjs-viewer --filter share-theme build && pnpm run --filter web-clipper postinstall" + "prepare": "pnpm run --filter pdfjs-viewer --filter share-theme build && pnpm run --filter web-clipper postinstall", + "update-contributor-list": "tsx ./scripts/update-contributor-list.ts" }, "private": true, "devDependencies": { diff --git a/apps/client/src/services/contributors_list.ts b/scripts/update-contributor-list.ts similarity index 77% rename from apps/client/src/services/contributors_list.ts rename to scripts/update-contributor-list.ts index 902d0538ca..e41d1bdf8a 100644 --- a/apps/client/src/services/contributors_list.ts +++ b/scripts/update-contributor-list.ts @@ -1,3 +1,5 @@ +import { writeFileSync } from "fs"; + export interface ContributorList { contributors: Contributor[]; } @@ -14,11 +16,25 @@ const PINNED_CONTRIBUTORS = ["eliandoran", "zadam"]; // Bots marked as users on the GitHub profile info to exclude from the listing const BOTS = ["weblate"]; -export default async function getContributors() { +async function main() { + console.log("Retrieving the contributor list..."); + + let jsonData: any = {}; + try { + jsonData = await getContributors(); + } catch (ex) { + console.error(ex); + } + + writeFileSync("contributors.json", JSON.stringify(jsonData, null, 2)); +} + +async function getContributors() { const response = await fetch("https://api.github.com/repos/TriliumNext/Trilium/contributors"); if (response.ok) { return { + "⚠️": "NOTE: this is an auto-generated list. Do not modify it.", contributors: getList(await response.json()) } as ContributorList } else { @@ -49,4 +65,6 @@ function contributorOrderer(a, b) { // Within each group, sort by contributions return b.contributions - a.contributions; -} \ No newline at end of file +} + +main(); \ No newline at end of file From e7adf08854c74f3c5d79b1fb2b826207bff153f8 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 22 Mar 2026 19:55:46 +0200 Subject: [PATCH 039/482] scripts/update contributor list: add role for pinned contributors --- contributors.json | 2 ++ scripts/update-contributor-list.ts | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/contributors.json b/contributors.json index 38350f4c5d..eb91307d48 100644 --- a/contributors.json +++ b/contributors.json @@ -3,10 +3,12 @@ "contributors": [ { "name": "eliandoran", + "role": "lead-dev", "url": "https://github.com/eliandoran" }, { "name": "zadam", + "role": "original-dev", "url": "https://github.com/zadam" }, { diff --git a/scripts/update-contributor-list.ts b/scripts/update-contributor-list.ts index e41d1bdf8a..1f134f12eb 100644 --- a/scripts/update-contributor-list.ts +++ b/scripts/update-contributor-list.ts @@ -7,11 +7,15 @@ export interface ContributorList { export interface Contributor { name: string; url: string; + role?: "lead-dev" | "original-dev"; } // Keep honorific contributors at top of the list, even if their commit count // is exceeded by another users. -const PINNED_CONTRIBUTORS = ["eliandoran", "zadam"]; +const PINNED_CONTRIBUTORS = { + "eliandoran": "lead-dev", + "zadam": "original-dev" +}; // Bots marked as users on the GitHub profile info to exclude from the listing const BOTS = ["weblate"]; @@ -50,13 +54,14 @@ function getList(contributorInfo: any[]) { .sort(contributorOrderer) .map((c) => {return { name: c.login, + role: (c.login in PINNED_CONTRIBUTORS) ? PINNED_CONTRIBUTORS[c.login]: undefined, url: c.html_url } as Contributor}); } function contributorOrderer(a, b) { - const isAPinned = PINNED_CONTRIBUTORS.includes(a.login); - const isBPinned = PINNED_CONTRIBUTORS.includes(b.login); + const isAPinned = (a.login in PINNED_CONTRIBUTORS); + const isBPinned = (b.login in PINNED_CONTRIBUTORS); // Pinned contributors come first if (isAPinned !== isBPinned) { From f00e051e758fca4bdf99cd8b693ad829c0423fac Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 22 Mar 2026 20:05:47 +0200 Subject: [PATCH 040/482] scripts/update contributor list: add completion feedback --- scripts/update-contributor-list.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/update-contributor-list.ts b/scripts/update-contributor-list.ts index 1f134f12eb..e8dcbcf515 100644 --- a/scripts/update-contributor-list.ts +++ b/scripts/update-contributor-list.ts @@ -28,9 +28,11 @@ async function main() { jsonData = await getContributors(); } catch (ex) { console.error(ex); + return; } writeFileSync("contributors.json", JSON.stringify(jsonData, null, 2)); + console.log("Done."); } async function getContributors() { From 015e50cdb8fd8700e25e826e26fe8abe23adbe73 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 22 Mar 2026 22:11:35 +0200 Subject: [PATCH 041/482] scripts/update contributor list: refactor --- packages/commons/src/index.ts | 3 ++- packages/commons/src/lib/shared_types.ts | 9 +++++++++ scripts/update-contributor-list.ts | 10 +--------- 3 files changed, 12 insertions(+), 10 deletions(-) create mode 100644 packages/commons/src/lib/shared_types.ts diff --git a/packages/commons/src/index.ts b/packages/commons/src/index.ts index b208bfd3b6..ab0a71677a 100644 --- a/packages/commons/src/index.ts +++ b/packages/commons/src/index.ts @@ -8,6 +8,7 @@ export * from "./lib/mime_type.js"; export * from "./lib/bulk_actions.js"; export * from "./lib/server_api.js"; export * from "./lib/shared_constants.js"; +export * from "./lib/shared_types.js"; export * from "./lib/ws_api.js"; export * from "./lib/attribute_names.js"; export * from "./lib/utils.js"; @@ -15,4 +16,4 @@ export * from "./lib/dayjs.js"; export * from "./lib/notes.js"; export * from "./lib/week_utils.js"; export { default as BUILTIN_ATTRIBUTES } from "./lib/builtin_attributes.js"; -export * from "./lib/spreadsheet/render_to_html.js"; +export * from "./lib/spreadsheet/render_to_html.js"; \ No newline at end of file diff --git a/packages/commons/src/lib/shared_types.ts b/packages/commons/src/lib/shared_types.ts new file mode 100644 index 0000000000..571506d2d9 --- /dev/null +++ b/packages/commons/src/lib/shared_types.ts @@ -0,0 +1,9 @@ +export interface ContributorList { + contributors: Contributor[]; +} + +export interface Contributor { + name: string; + url: string; + role?: "lead-dev" | "original-dev"; +} \ No newline at end of file diff --git a/scripts/update-contributor-list.ts b/scripts/update-contributor-list.ts index e8dcbcf515..56f6e444b4 100644 --- a/scripts/update-contributor-list.ts +++ b/scripts/update-contributor-list.ts @@ -1,14 +1,6 @@ import { writeFileSync } from "fs"; -export interface ContributorList { - contributors: Contributor[]; -} - -export interface Contributor { - name: string; - url: string; - role?: "lead-dev" | "original-dev"; -} +import {Contributor, ContributorList} from "../packages/commons/"; // Keep honorific contributors at top of the list, even if their commit count // is exceeded by another users. From b32dd949d738e103d2e999968a888f85f4d34c9d Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 22 Mar 2026 22:35:59 +0200 Subject: [PATCH 042/482] scripts/update contributor list: add full name support for pinned contributors --- contributors.json | 10 ++++++---- packages/commons/src/lib/shared_types.ts | 1 + scripts/update-contributor-list.ts | 23 +++++++++++++++-------- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/contributors.json b/contributors.json index eb91307d48..6174022b78 100644 --- a/contributors.json +++ b/contributors.json @@ -3,13 +3,15 @@ "contributors": [ { "name": "eliandoran", - "role": "lead-dev", - "url": "https://github.com/eliandoran" + "url": "https://github.com/eliandoran", + "fullName": "Elian Doran", + "role": "lead-dev" }, { "name": "zadam", - "role": "original-dev", - "url": "https://github.com/zadam" + "url": "https://github.com/zadam", + "fullName": "Zadam", + "role": "original-dev" }, { "name": "adoriandoran", diff --git a/packages/commons/src/lib/shared_types.ts b/packages/commons/src/lib/shared_types.ts index 571506d2d9..17b701eca2 100644 --- a/packages/commons/src/lib/shared_types.ts +++ b/packages/commons/src/lib/shared_types.ts @@ -4,6 +4,7 @@ export interface ContributorList { export interface Contributor { name: string; + fullName?: string; url: string; role?: "lead-dev" | "original-dev"; } \ No newline at end of file diff --git a/scripts/update-contributor-list.ts b/scripts/update-contributor-list.ts index 56f6e444b4..6c8e9ea1fa 100644 --- a/scripts/update-contributor-list.ts +++ b/scripts/update-contributor-list.ts @@ -4,9 +4,9 @@ import {Contributor, ContributorList} from "../packages/commons/"; // Keep honorific contributors at top of the list, even if their commit count // is exceeded by another users. -const PINNED_CONTRIBUTORS = { - "eliandoran": "lead-dev", - "zadam": "original-dev" +const PINNED_CONTRIBUTORS: Record> = { + "eliandoran": {fullName: "Elian Doran", role: "lead-dev"}, + "zadam": {fullName: "Zadam", role: "original-dev"} }; // Bots marked as users on the GitHub profile info to exclude from the listing @@ -46,11 +46,18 @@ function getList(contributorInfo: any[]) { .filter((c) => c.type === "User" && !BOTS.includes(c.login)) // Sort by the commit count. Honorific contributors are always first. .sort(contributorOrderer) - .map((c) => {return { - name: c.login, - role: (c.login in PINNED_CONTRIBUTORS) ? PINNED_CONTRIBUTORS[c.login]: undefined, - url: c.html_url - } as Contributor}); + .map((c) => { + let result = { + name: c.login, + url: c.html_url + } as Contributor; + + if (c.login in PINNED_CONTRIBUTORS) { + result = {...result, ...PINNED_CONTRIBUTORS[c.login]}; + } + + return result; + }); } function contributorOrderer(a, b) { From a7a1e5c48059476853f45a0e1fa7e951ec0d32bc Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Mon, 23 Mar 2026 08:53:52 +0200 Subject: [PATCH 043/482] scripts/update contributor list: optimize --- contributors.json | 4 ++-- scripts/update-contributor-list.ts | 14 ++++++-------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/contributors.json b/contributors.json index 6174022b78..6add5804ed 100644 --- a/contributors.json +++ b/contributors.json @@ -3,14 +3,14 @@ "contributors": [ { "name": "eliandoran", - "url": "https://github.com/eliandoran", "fullName": "Elian Doran", + "url": "https://github.com/eliandoran", "role": "lead-dev" }, { "name": "zadam", - "url": "https://github.com/zadam", "fullName": "Zadam", + "url": "https://github.com/zadam", "role": "original-dev" }, { diff --git a/scripts/update-contributor-list.ts b/scripts/update-contributor-list.ts index 6c8e9ea1fa..2070575fe4 100644 --- a/scripts/update-contributor-list.ts +++ b/scripts/update-contributor-list.ts @@ -47,16 +47,14 @@ function getList(contributorInfo: any[]) { // Sort by the commit count. Honorific contributors are always first. .sort(contributorOrderer) .map((c) => { - let result = { + let pinnedInfo = PINNED_CONTRIBUTORS[c.login]; + + return { name: c.login, - url: c.html_url + fullName: pinnedInfo?.fullName, + url: c.html_url, + role: pinnedInfo?.role } as Contributor; - - if (c.login in PINNED_CONTRIBUTORS) { - result = {...result, ...PINNED_CONTRIBUTORS[c.login]}; - } - - return result; }); } From db98884ae4e554e856e34d6183286da896c6912c Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Mon, 23 Mar 2026 09:00:30 +0200 Subject: [PATCH 044/482] scripts/update contributor list: refactor --- scripts/update-contributor-list.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/scripts/update-contributor-list.ts b/scripts/update-contributor-list.ts index 2070575fe4..fcbf415530 100644 --- a/scripts/update-contributor-list.ts +++ b/scripts/update-contributor-list.ts @@ -1,7 +1,6 @@ +import { Contributor, ContributorList } from "../packages/commons/"; import { writeFileSync } from "fs"; -import {Contributor, ContributorList} from "../packages/commons/"; - // Keep honorific contributors at top of the list, even if their commit count // is exceeded by another users. const PINNED_CONTRIBUTORS: Record> = { @@ -10,37 +9,39 @@ const PINNED_CONTRIBUTORS: Record }; // Bots marked as users on the GitHub profile info to exclude from the listing -const BOTS = ["weblate"]; +const BOTS = [ + "weblate" +]; async function main() { console.log("Retrieving the contributor list..."); - let jsonData: any = {}; + let data: any = {}; try { - jsonData = await getContributors(); + data = await fetchContributors(); } catch (ex) { console.error(ex); return; } - writeFileSync("contributors.json", JSON.stringify(jsonData, null, 2)); + writeFileSync("contributors.json", JSON.stringify(data, null, 4)); console.log("Done."); } -async function getContributors() { +async function fetchContributors() { const response = await fetch("https://api.github.com/repos/TriliumNext/Trilium/contributors"); if (response.ok) { return { "⚠️": "NOTE: this is an auto-generated list. Do not modify it.", - contributors: getList(await response.json()) + contributors: processContributorList(await response.json()) } as ContributorList } else { throw new Error(`Unable to request the contributor list from GitHub. Reason: ${response.statusText}`); } } -function getList(contributorInfo: any[]) { +function processContributorList(contributorInfo: any[]) { return contributorInfo // Filter out bots .filter((c) => c.type === "User" && !BOTS.includes(c.login)) From f6e92c411e68e42bc11a112b398fe8c23607066b Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Mon, 23 Mar 2026 09:38:23 +0200 Subject: [PATCH 045/482] client/about dialog: show the contributor list --- .../src/translations/en/translation.json | 4 +++ apps/client/src/widgets/dialogs/about.tsx | 30 ++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index e1271388b3..8f9e559e30 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -4,6 +4,10 @@ "version": "app: {{appVersion}}, database: {{dbVersion}}, sync protocol: {{syncVersion}}", "build_info": "{{buildDate}}, revision: ", "contributors_label": "Contributors:", + "contributor_roles": { + "lead-dev": "lead developer", + "original-dev": "original developer" + }, "data_directory": "Data directory:", "donate": "Donate" }, diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index d47e8167a4..1978e33eec 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -6,7 +6,7 @@ import utils from "../../services/utils.js"; import openService from "../../services/open.js"; import { useState } from "preact/hooks"; import type { CSSProperties } from "preact/compat"; -import type { AppInfo } from "@triliumnext/commons"; +import type { AppInfo, Contributor, ContributorList } from "@triliumnext/commons"; import { useTriliumEvent } from "../react/hooks.jsx"; import { Card, CardSection } from "../react/Card.js"; import "./about.css"; @@ -15,6 +15,7 @@ import type React from "react"; import icon from "../../assets/icon.svg"; import iconAlt from "../../assets/icon-alt.svg"; import { useCallback, useEffect } from "react"; +import contributors from "../../../../../contributors.json"; export default function AboutDialog() { const [appInfo, setAppInfo] = useState(null); @@ -76,6 +77,9 @@ export default function AboutDialog() {
{t("about.contributors_label")}
+
+ +
{t("about.data_directory")}
@@ -112,3 +116,27 @@ function DirectoryLink({ directory, style }: { directory: string, style?: CSSPro return {directory}; } } + +function Contributors(params: {data: ContributorList}) { + return params.data.contributors.map((c, index, array) => { + return <> + + + {/* Add a comma between items */} + {(index < array.length - 1) ? ", " : undefined} + + }); +} + +function ContributorListItem({data}: {data: Contributor}) { + let roleString = ""; + if (data.role) { + roleString = t(`about.contributor_roles.${data.role}`); + } + + return <> + {data.fullName ?? data.name} + + {roleString &&  ({roleString})} + +} \ No newline at end of file From 129f1ccd8d9d6887fec1f88fc5fbfe7636ab5a92 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Mon, 23 Mar 2026 09:52:04 +0200 Subject: [PATCH 046/482] client/about dialog: add a full list link, improve layout --- apps/client/src/translations/en/translation.json | 1 + apps/client/src/widgets/dialogs/about.css | 6 ++++++ apps/client/src/widgets/dialogs/about.tsx | 7 +++++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 8f9e559e30..a7aa1777f7 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -8,6 +8,7 @@ "lead-dev": "lead developer", "original-dev": "original developer" }, + "contributor_full_list": "See the full list", "data_directory": "Data directory:", "donate": "Donate" }, diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css index d6113c9bc1..d17e4f6d07 100644 --- a/apps/client/src/widgets/dialogs/about.css +++ b/apps/client/src/widgets/dialogs/about.css @@ -18,6 +18,12 @@ } } + .contributor-list { + a, span { + white-space: nowrap; + } + } + footer { display: flex; justify-content: center; diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index 1978e33eec..498d196cf0 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -77,8 +77,11 @@ export default function AboutDialog() {
{t("about.contributors_label")}
-
+ @@ -123,7 +126,7 @@ function Contributors(params: {data: ContributorList}) { {/* Add a comma between items */} - {(index < array.length - 1) ? ", " : undefined} + {(index < array.length - 1) ? ", " : ". "} }); } From fc6bdb56df75134c5ad30a534eb06d29d4484a10 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Mon, 23 Mar 2026 10:06:53 +0200 Subject: [PATCH 047/482] client/about dialog: refactor --- apps/client/src/widgets/dialogs/about.tsx | 43 +++++++++++++---------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index 498d196cf0..9baf417077 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -5,7 +5,6 @@ import server from "../../services/server.js"; import utils from "../../services/utils.js"; import openService from "../../services/open.js"; import { useState } from "preact/hooks"; -import type { CSSProperties } from "preact/compat"; import type { AppInfo, Contributor, ContributorList } from "@triliumnext/commons"; import { useTriliumEvent } from "../react/hooks.jsx"; import { Card, CardSection } from "../react/Card.js"; @@ -36,13 +35,13 @@ export default function AboutDialog() { }, [appInfo]) return ( - setShown(false)} >
+
{t("about.contributors_label")}
@@ -84,6 +80,7 @@ export default function AboutDialog() {
+
{t("about.data_directory")}
@@ -107,17 +104,12 @@ export default function AboutDialog() { ); } -function DirectoryLink({ directory, style }: { directory: string, style?: CSSProperties }) { - if (utils.isElectron()) { - const onClick = (e: MouseEvent) => { - e.preventDefault(); - openService.openDirectory(directory); - }; - - return {directory} - } else { - return {directory}; - } +function revisionLink(appInfo: AppInfo | null) { + return <> + {appInfo?.buildRevision && + {appInfo.buildRevision.substring(0, 7)} + } + as React.ReactElement; } function Contributors(params: {data: ContributorList}) { @@ -142,4 +134,17 @@ function ContributorListItem({data}: {data: Contributor}) { {roleString &&  ({roleString})} +} + +function DirectoryLink({ directory }: { directory: string}) { + if (utils.isElectron()) { + const onClick = (e: MouseEvent) => { + e.preventDefault(); + openService.openDirectory(directory); + }; + + return {directory} + } else { + return {directory}; + } } \ No newline at end of file From dfd68ca8a30b0e6ccb24ac766bb50e0c0399626f Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Mon, 23 Mar 2026 10:07:47 +0200 Subject: [PATCH 048/482] scripts/update contributor list: update indentation size --- contributors.json | 238 +++++++++++++++++++++++----------------------- 1 file changed, 119 insertions(+), 119 deletions(-) diff --git a/contributors.json b/contributors.json index 6add5804ed..59057dfa33 100644 --- a/contributors.json +++ b/contributors.json @@ -1,121 +1,121 @@ { - "⚠️": "NOTE: this is an auto-generated list. Do not modify it.", - "contributors": [ - { - "name": "eliandoran", - "fullName": "Elian Doran", - "url": "https://github.com/eliandoran", - "role": "lead-dev" - }, - { - "name": "zadam", - "fullName": "Zadam", - "url": "https://github.com/zadam", - "role": "original-dev" - }, - { - "name": "adoriandoran", - "url": "https://github.com/adoriandoran" - }, - { - "name": "pano9000", - "url": "https://github.com/pano9000" - }, - { - "name": "perfectra1n", - "url": "https://github.com/perfectra1n" - }, - { - "name": "JYC333", - "url": "https://github.com/JYC333" - }, - { - "name": "SiriusXT", - "url": "https://github.com/SiriusXT" - }, - { - "name": "tony", - "url": "https://github.com/tony" - }, - { - "name": "Nriver", - "url": "https://github.com/Nriver" - }, - { - "name": "francistw", - "url": "https://github.com/francistw" - }, - { - "name": "isaul32", - "url": "https://github.com/isaul32" - }, - { - "name": "thfrei", - "url": "https://github.com/thfrei" - }, - { - "name": "nathancahill", - "url": "https://github.com/nathancahill" - }, - { - "name": "contributor", - "url": "https://github.com/contributor" - }, - { - "name": "FliegendeWurst", - "url": "https://github.com/FliegendeWurst" - }, - { - "name": "hasecilu", - "url": "https://github.com/hasecilu" - }, - { - "name": "Meinzzzz", - "url": "https://github.com/Meinzzzz" - }, - { - "name": "Sarah-Hussein", - "url": "https://github.com/Sarah-Hussein" - }, - { - "name": "zerebos", - "url": "https://github.com/zerebos" - }, - { - "name": "meichthys", - "url": "https://github.com/meichthys" - }, - { - "name": "questamor", - "url": "https://github.com/questamor" - }, - { - "name": "SukantGujar", - "url": "https://github.com/SukantGujar" - }, - { - "name": "soulsands", - "url": "https://github.com/soulsands" - }, - { - "name": "noobhjy", - "url": "https://github.com/noobhjy" - }, - { - "name": "laurent22", - "url": "https://github.com/laurent22" - }, - { - "name": "mlewand", - "url": "https://github.com/mlewand" - }, - { - "name": "lzinga", - "url": "https://github.com/lzinga" - }, - { - "name": "ytrkptl", - "url": "https://github.com/ytrkptl" - } - ] + "⚠️": "NOTE: this is an auto-generated list. Do not modify it.", + "contributors": [ + { + "name": "eliandoran", + "fullName": "Elian Doran", + "url": "https://github.com/eliandoran", + "role": "lead-dev" + }, + { + "name": "zadam", + "fullName": "Zadam", + "url": "https://github.com/zadam", + "role": "original-dev" + }, + { + "name": "adoriandoran", + "url": "https://github.com/adoriandoran" + }, + { + "name": "pano9000", + "url": "https://github.com/pano9000" + }, + { + "name": "perfectra1n", + "url": "https://github.com/perfectra1n" + }, + { + "name": "JYC333", + "url": "https://github.com/JYC333" + }, + { + "name": "SiriusXT", + "url": "https://github.com/SiriusXT" + }, + { + "name": "tony", + "url": "https://github.com/tony" + }, + { + "name": "Nriver", + "url": "https://github.com/Nriver" + }, + { + "name": "francistw", + "url": "https://github.com/francistw" + }, + { + "name": "isaul32", + "url": "https://github.com/isaul32" + }, + { + "name": "thfrei", + "url": "https://github.com/thfrei" + }, + { + "name": "nathancahill", + "url": "https://github.com/nathancahill" + }, + { + "name": "contributor", + "url": "https://github.com/contributor" + }, + { + "name": "FliegendeWurst", + "url": "https://github.com/FliegendeWurst" + }, + { + "name": "hasecilu", + "url": "https://github.com/hasecilu" + }, + { + "name": "Meinzzzz", + "url": "https://github.com/Meinzzzz" + }, + { + "name": "Sarah-Hussein", + "url": "https://github.com/Sarah-Hussein" + }, + { + "name": "zerebos", + "url": "https://github.com/zerebos" + }, + { + "name": "meichthys", + "url": "https://github.com/meichthys" + }, + { + "name": "questamor", + "url": "https://github.com/questamor" + }, + { + "name": "SukantGujar", + "url": "https://github.com/SukantGujar" + }, + { + "name": "soulsands", + "url": "https://github.com/soulsands" + }, + { + "name": "noobhjy", + "url": "https://github.com/noobhjy" + }, + { + "name": "laurent22", + "url": "https://github.com/laurent22" + }, + { + "name": "mlewand", + "url": "https://github.com/mlewand" + }, + { + "name": "lzinga", + "url": "https://github.com/lzinga" + }, + { + "name": "ytrkptl", + "url": "https://github.com/ytrkptl" + } + ] } \ No newline at end of file From 97e52e53bf46224a2b41bf141d6b1dee1edbd8a6 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Mon, 23 Mar 2026 10:34:03 +0200 Subject: [PATCH 049/482] Update scripts/update-contributor-list.ts Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- scripts/update-contributor-list.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update-contributor-list.ts b/scripts/update-contributor-list.ts index fcbf415530..d6478c2da4 100644 --- a/scripts/update-contributor-list.ts +++ b/scripts/update-contributor-list.ts @@ -41,7 +41,7 @@ async function fetchContributors() { } } -function processContributorList(contributorInfo: any[]) { +function processContributorList(contributorInfo: GithubContributor[]) { return contributorInfo // Filter out bots .filter((c) => c.type === "User" && !BOTS.includes(c.login)) From 35023243891e635afd1b9a29a0f67f5486a0e3f9 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Mon, 23 Mar 2026 10:36:32 +0200 Subject: [PATCH 050/482] client/about dialog: add keys to the contributor list --- apps/client/src/widgets/dialogs/about.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index 9baf417077..5fd33cb6dc 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -15,6 +15,7 @@ import icon from "../../assets/icon.svg"; import iconAlt from "../../assets/icon-alt.svg"; import { useCallback, useEffect } from "react"; import contributors from "../../../../../contributors.json"; +import { Fragment } from "preact/jsx-runtime"; export default function AboutDialog() { const [appInfo, setAppInfo] = useState(null); @@ -114,12 +115,12 @@ function revisionLink(appInfo: AppInfo | null) { function Contributors(params: {data: ContributorList}) { return params.data.contributors.map((c, index, array) => { - return <> + return {/* Add a comma between items */} {(index < array.length - 1) ? ", " : ". "} - + }); } From 0a0157a1ef22847bc7832c8d16498d851e3bc152 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Mon, 23 Mar 2026 11:41:13 +0200 Subject: [PATCH 051/482] style/about dialog: improve appearance --- apps/client/src/widgets/dialogs/about.css | 28 +++++++++++++++++++++-- apps/client/src/widgets/dialogs/about.tsx | 4 ++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css index d17e4f6d07..c761432aa6 100644 --- a/apps/client/src/widgets/dialogs/about.css +++ b/apps/client/src/widgets/dialogs/about.css @@ -1,4 +1,11 @@ .about-dialog { + h2 { + all: unset; + font-size: 2em; + font-weight: 300; + letter-spacing: 1pt; + } + .about-dialog-content { display: flex; flex-direction: column; @@ -18,6 +25,11 @@ } } + .build-info { + color: var(--muted-text-color); + font-size: .9em; + } + .contributor-list { a, span { white-space: nowrap; @@ -27,20 +39,32 @@ footer { display: flex; justify-content: center; - gap: 20px; + gap: 10px; margin-bottom: 30px; a { display: flex; flex-direction: column; align-items: center; + padding: 8px 10px; + border-radius: 6px; + font-size: .9rem; + color: var(--main-text-color); + &:hover { + background: var(--icon-button-hover-background); + } + &::after { display: none; } i { - font-size: 32px; + font-size: 28px; + } + + &.donate-link { + color: #E33F3B; } } } diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index 5fd33cb6dc..99510bdda3 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -58,7 +58,7 @@ export default function AboutDialog() { dbVersion: appInfo?.dbVersion, syncVersion: appInfo?.syncVersion })} -
+
GitHub - + {t("about.donate")} From 11a46f0f581e5cbeb32fcf6d7fe4a55523d95ca9 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Tue, 24 Mar 2026 18:54:48 +0200 Subject: [PATCH 052/482] client/about dialog: reduce the contributor list length to 10 --- apps/client/src/translations/en/translation.json | 2 +- apps/client/src/widgets/dialogs/about.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index a7aa1777f7..1dd00bd710 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -8,7 +8,7 @@ "lead-dev": "lead developer", "original-dev": "original developer" }, - "contributor_full_list": "See the full list", + "contributor_full_list": "See the entire community", "data_directory": "Data directory:", "donate": "Donate" }, diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index 99510bdda3..731707b73d 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -114,7 +114,7 @@ function revisionLink(appInfo: AppInfo | null) { } function Contributors(params: {data: ContributorList}) { - return params.data.contributors.map((c, index, array) => { + return params.data.contributors.splice(0, 10).map((c, index, array) => { return From 1c74a019ab93975b0052979ca6910d02bbde0eff Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Tue, 24 Mar 2026 19:32:14 +0200 Subject: [PATCH 053/482] style/about dialog: create a card-like table style --- apps/client/src/widgets/dialogs/about.css | 47 ++++++++++++++++++----- apps/client/src/widgets/dialogs/about.tsx | 34 ++++++++-------- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css index c761432aa6..cf9ac12b68 100644 --- a/apps/client/src/widgets/dialogs/about.css +++ b/apps/client/src/widgets/dialogs/about.css @@ -1,4 +1,6 @@ .about-dialog { + --bs-modal-width: 650px; + h2 { all: unset; font-size: 2em; @@ -12,17 +14,10 @@ align-items: center; } - .property-sheet-card { + .property-sheet-table { margin-block: 30px; font-size: .85em; - - .tn-card-section { - display: flex; - - > :first-child { - width: 100px; - } - } + margin-inline: 20px; } .build-info { @@ -68,4 +63,38 @@ } } } +} + +/* TODO: move to global styles */ +.property-sheet-table { + border-spacing: 0 2px; + border-collapse: separate; + + tr { + --_br: 8px; + + background: var(--card-background-color); + + &:first-child { + clip-path: inset(0 round var(--_br) var(--_br) 0 0); + } + + &:last-child { + clip-path: inset(0 round 0 0 var(--_br) var(--_br)); + } + } + + td { + padding: 8px 16px; + vertical-align: top; + + &:first-child { + white-space: nowrap; + color: var(--muted-text-color); + } + + &:last-child { + width: 100%; + } + } } \ No newline at end of file diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index 731707b73d..ea13ec8b74 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -49,10 +49,10 @@ export default function AboutDialog() { triliumnotes.org - - -
{t("about.version_label")}
-
+ + + + + - -
{t("about.contributors_label")}
-
+
+ + + - -
{t("about.data_directory")}
-
+
+ + + +
{t("about.version_label")} {t("about.version", { appVersion: appInfo?.appVersion, dbVersion: appInfo?.dbVersion, @@ -69,26 +69,26 @@ export default function AboutDialog() { }} /> - - +
{t("about.contributors_label")} {t("about.contributor_full_list")} - - +
{t("about.data_directory")} {appInfo?.dataDirectory && ()} - - - +
@@ -91,27 +92,37 @@ export default function AboutDialog() {
); } -function revisionLink(appInfo: AppInfo | null) { +function RevisionLink(appInfo: AppInfo | null) { return <> {appInfo?.buildRevision && {appInfo.buildRevision.substring(0, 7)} @@ -119,8 +130,15 @@ function revisionLink(appInfo: AppInfo | null) { as React.ReactElement; } -function Contributors(params: {data: ContributorList}) { - return params.data.contributors.slice(0, 10).map((c, index, array) => { +function FooterLink(props: {children: ComponentChildren, text: string, url: string, tooltip: string, className?: string}) { + return + {props.children} + {props.text} + +} + +function Contributors({data}: {data: ContributorList}) { + return data.contributors.slice(0, 10).map((c, index, array) => { return From a6b1af6a16ce512fe22f25b75e9a3f8939dc3f57 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Tue, 24 Mar 2026 23:57:44 +0200 Subject: [PATCH 059/482] style/about dialog: improve appearance --- apps/client/src/widgets/dialogs/about.css | 2 +- apps/client/src/widgets/dialogs/about.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css index eb33ef0800..ef98b26f78 100644 --- a/apps/client/src/widgets/dialogs/about.css +++ b/apps/client/src/widgets/dialogs/about.css @@ -105,7 +105,7 @@ } td { - padding: 8px 16px; + padding: 10px 16px; vertical-align: top; &:first-child { diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index a8ae1781c2..b70f4ef7f5 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -131,7 +131,7 @@ function RevisionLink(appInfo: AppInfo | null) { } function FooterLink(props: {children: ComponentChildren, text: string, url: string, tooltip: string, className?: string}) { - return + return {props.children} {props.text} From d370ee2d99083e9159bf9a194407a95d9440a8fd Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Wed, 25 Mar 2026 00:28:38 +0200 Subject: [PATCH 060/482] style/about dialog: select the icon using CSS class names --- apps/client/src/assets/icon-classic.svg | 1 + .../assets/{icon-alt.svg => icon-nightly.svg} | 0 apps/client/src/widgets/dialogs/about.css | 18 ++++++++++++++++++ apps/client/src/widgets/dialogs/about.tsx | 10 ++++++++-- 4 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 apps/client/src/assets/icon-classic.svg rename apps/client/src/assets/{icon-alt.svg => icon-nightly.svg} (100%) diff --git a/apps/client/src/assets/icon-classic.svg b/apps/client/src/assets/icon-classic.svg new file mode 100644 index 0000000000..0fbc903d8a --- /dev/null +++ b/apps/client/src/assets/icon-classic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/client/src/assets/icon-alt.svg b/apps/client/src/assets/icon-nightly.svg similarity index 100% rename from apps/client/src/assets/icon-alt.svg rename to apps/client/src/assets/icon-nightly.svg diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css index ef98b26f78..20182f1104 100644 --- a/apps/client/src/widgets/dialogs/about.css +++ b/apps/client/src/widgets/dialogs/about.css @@ -10,6 +10,24 @@ --bs-modal-width: 680px; + .icon { + width: 160px; + height: 160px; + + &.icon-default { + background-image: url(../../assets/icon.svg); + } + + &.icon-nightly { + background-image: url(../../assets/icon-nightly.svg); + } + + &.icon-classic { + mask-image: url(../../assets/icon-classic.svg); + background-color: var(--muted-text-color); + } + } + h2 { all: unset; font-size: 2em; diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index b70f4ef7f5..b45cd19905 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -16,11 +16,13 @@ import { useCallback, useEffect } from "react"; import contributors from "../../../../../contributors.json"; import { Fragment } from "preact/jsx-runtime"; import { ComponentChildren } from "preact"; +import clsx from "clsx"; export default function AboutDialog() { const [appInfo, setAppInfo] = useState(null); const [shown, setShown] = useState(false); const [isNightly, setNightly] = useState(false); + const [iconClassName, setIconClassName] = useState("icon-default"); const onLoad = useCallback(async () => { if (!appInfo) { @@ -33,17 +35,21 @@ export default function AboutDialog() { useEffect(() => { setNightly(!!appInfo?.appVersion.includes("test")); + if (isNightly) { + setIconClassName("icon-nightly"); + } }, [appInfo]) return ( setShown(false)} >
- + +

Trilium Notes {isNightly && Nightly}

triliumnotes.org From a81dae2ad005cdd41fb37dc6f49a98e9eccebaaf Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Wed, 25 Mar 2026 01:01:16 +0200 Subject: [PATCH 061/482] client/about dialog: allow toggling to the classic icon --- apps/client/src/widgets/dialogs/about.tsx | 30 +++++++++++++++++------ 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index b45cd19905..f2df3dad83 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -10,8 +10,6 @@ import { useTriliumEvent } from "../react/hooks.jsx"; import "./about.css"; import { Trans } from "react-i18next"; import type React from "react"; -import icon from "../../assets/icon.svg"; -import iconAlt from "../../assets/icon-alt.svg"; import { useCallback, useEffect } from "react"; import contributors from "../../../../../contributors.json"; import { Fragment } from "preact/jsx-runtime"; @@ -23,6 +21,8 @@ export default function AboutDialog() { const [shown, setShown] = useState(false); const [isNightly, setNightly] = useState(false); const [iconClassName, setIconClassName] = useState("icon-default"); + const [altIconClassName, setAltIconClassName] = useState(null); + const onLoad = useCallback(async () => { if (!appInfo) { @@ -49,7 +49,7 @@ export default function AboutDialog() { >
-
+

Trilium Notes {isNightly && Nightly}

triliumnotes.org @@ -81,7 +81,11 @@ export default function AboutDialog() { {t("about.contributors_label")} - + {setAltIconClassName((isHovering && contributor.role === "original-dev") ? "icon-classic" : null)}} + /> + {t("about.contributor_full_list")} @@ -143,10 +147,12 @@ function FooterLink(props: {children: ComponentChildren, text: string, url: stri } -function Contributors({data}: {data: ContributorList}) { +type HoverCallback = (contributor: Contributor, isHovering: boolean) => void; + +function Contributors({data, onHover}: {data: ContributorList, onHover?: HoverCallback}) { return data.contributors.slice(0, 10).map((c, index, array) => { return - + {/* Add a comma between items */} {(index < array.length - 1) ? ", " : ". "} @@ -154,14 +160,22 @@ function Contributors({data}: {data: ContributorList}) { }); } -function ContributorListItem({data}: {data: Contributor}) { + +function ContributorListItem({data, onHover}: {data: Contributor, onHover?: HoverCallback}) { let roleString = ""; if (data.role) { roleString = t(`about.contributor_roles.${data.role}`); } return <> - {data.fullName ?? data.name} + onHover?.(data, true)} + onMouseLeave={(e) => onHover?.(data, false)}> + + {data.fullName ?? data.name} + {roleString &&  ({roleString})} From 591b3a121f8c6d23691a8427df5943c0788e2e98 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Wed, 25 Mar 2026 01:41:00 +0200 Subject: [PATCH 062/482] style/about dialog: add icon animation --- apps/client/src/widgets/dialogs/about.css | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css index 20182f1104..e8a0c8233e 100644 --- a/apps/client/src/widgets/dialogs/about.css +++ b/apps/client/src/widgets/dialogs/about.css @@ -22,9 +22,17 @@ background-image: url(../../assets/icon-nightly.svg); } + &.icon-default, + &.icon-nightly { + animation: icon-intro 500ms ease-out; + will-change: opacity, transform; + } + &.icon-classic { mask-image: url(../../assets/icon-classic.svg); background-color: var(--muted-text-color); + animation: icon-classic-intro 300ms ease-in-out; + will-change: opacity, transform; } } @@ -103,6 +111,26 @@ } } +@keyframes icon-intro { + from { + opacity: 0; + transform: scale(.5); + } to { + opacity: 1; + transform: scale(1); + } +} + +@keyframes icon-classic-intro { + from { + opacity: 0; + transform: rotate(50deg) scale(.5); + } to { + opacity: 1; + transform: rotate(0deg) scale(1.25); + } +} + /* TODO: move to global styles */ .property-sheet-table { border-spacing: 0 2px; From 496405d922ed9fd7a8c17e314068fa1ede491e4c Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Wed, 25 Mar 2026 11:19:54 +0200 Subject: [PATCH 063/482] client/about dialog: add custom tooltips --- .../src/translations/en/translation.json | 4 ++ apps/client/src/widgets/dialogs/about.css | 10 +-- apps/client/src/widgets/dialogs/about.tsx | 66 +++++++++++++------ 3 files changed, 55 insertions(+), 25 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index dd658a2c32..2491e37801 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -8,6 +8,10 @@ "lead-dev": "lead developer", "original-dev": "original developer" }, + "role_brief_history": { + "lead-dev": "TODO", + "original-dev": "TODO" + }, "contributor_full_list": "See the entire community", "data_directory": "Data directory:", "github_tooltip": "Report bugs, suggest features, or contribute on GitHub", diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css index e8a0c8233e..97c8cc093c 100644 --- a/apps/client/src/widgets/dialogs/about.css +++ b/apps/client/src/widgets/dialogs/about.css @@ -14,21 +14,21 @@ width: 160px; height: 160px; - &.icon-default { + &:not([data-alt-icon]) { background-image: url(../../assets/icon.svg); } - &.icon-nightly { + &[data-alt-icon="nightly"] { background-image: url(../../assets/icon-nightly.svg); } - &.icon-default, - &.icon-nightly { + &:not([data-alt-icon]), + &[data-alt-icon="nightly"] { animation: icon-intro 500ms ease-out; will-change: opacity, transform; } - &.icon-classic { + &[data-alt-icon="classic"] { mask-image: url(../../assets/icon-classic.svg); background-color: var(--muted-text-color); animation: icon-classic-intro 300ms ease-in-out; diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index f2df3dad83..456bf94d6c 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -4,41 +4,52 @@ import { formatDateTime } from "../../utils/formatters.js"; import server from "../../services/server.js"; import utils from "../../services/utils.js"; import openService from "../../services/open.js"; -import { useState } from "preact/hooks"; +import { useState, useCallback, useRef } from "preact/hooks"; import type { AppInfo, Contributor, ContributorList } from "@triliumnext/commons"; -import { useTriliumEvent } from "../react/hooks.jsx"; +import { useTooltip, useTriliumEvent } from "../react/hooks.jsx"; import "./about.css"; import { Trans } from "react-i18next"; import type React from "react"; -import { useCallback, useEffect } from "react"; import contributors from "../../../../../contributors.json"; import { Fragment } from "preact/jsx-runtime"; import { ComponentChildren } from "preact"; -import clsx from "clsx"; export default function AboutDialog() { const [appInfo, setAppInfo] = useState(null); const [shown, setShown] = useState(false); const [isNightly, setNightly] = useState(false); - const [iconClassName, setIconClassName] = useState("icon-default"); - const [altIconClassName, setAltIconClassName] = useState(null); - + const iconRef = useRef(null); const onLoad = useCallback(async () => { if (!appInfo) { - setAppInfo(await server.get("app-info")); + const info = await server.get("app-info"); + if (info.appVersion.includes("test")) { + setNightly(true); + setAltIcon("nightly"); + } + setAppInfo(info); } setShown(true); }, []); useTriliumEvent("openAboutDialog", onLoad); - useEffect(() => { - setNightly(!!appInfo?.appVersion.includes("test")); - if (isNightly) { - setIconClassName("icon-nightly"); + const setAltIcon = useCallback((iconId: string | null) => { + /* The alternate icon is set by directly accessing the DOM to prevent the dialog being + * rerendered. A rerender while an element is hovered and displaying a tooltip in the same + * time, will cause the tooltip to break. */ + if (iconId) { + iconRef.current?.setAttribute("data-alt-icon", iconId); + } else { + iconRef.current?.removeAttribute("data-alt-icon"); } - }, [appInfo]) + }, []); + + const onContributorHovered = useCallback((contributor: Contributor, isHovering: boolean) => { + if (contributor.role === "original-dev") { + setAltIcon((isHovering) ? "classic": null); + } + }, []); return (
-
+

Trilium Notes {isNightly && Nightly}

triliumnotes.org @@ -83,7 +94,7 @@ export default function AboutDialog() { {setAltIconClassName((isHovering && contributor.role === "original-dev") ? "icon-classic" : null)}} + onHover={onContributorHovered} /> @@ -141,7 +152,16 @@ function RevisionLink(appInfo: AppInfo | null) { } function FooterLink(props: {children: ComponentChildren, text: string, url: string, tooltip: string, className?: string}) { - return + + const linkRef = useRef(null); + + useTooltip(linkRef, { + title: props.tooltip, + delay: 250, + placement: "bottom" + }) + + return {props.children} {props.text} @@ -162,13 +182,19 @@ function Contributors({data, onHover}: {data: ContributorList, onHover?: HoverCa function ContributorListItem({data, onHover}: {data: Contributor, onHover?: HoverCallback}) { - let roleString = ""; - if (data.role) { - roleString = t(`about.contributor_roles.${data.role}`); - } + const linkRef = useRef(null); + const roleString = (data.role) ? t(`about.contributor_roles.${data.role}`) : ""; + + useTooltip(linkRef, (data.role) ? { + title: t(`about.role_brief_history.${data.role}`), + placement: "bottom", + offset: [0, 10], + delay: 500 + }: {}); return <> onHover?.(data, true)} From 573ab077ac211993a307c79ccf64b2b6d24accb2 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Wed, 25 Mar 2026 11:30:50 +0200 Subject: [PATCH 064/482] client/about dialog: add a delay for contributor link hover event --- apps/client/src/widgets/dialogs/about.tsx | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index 456bf94d6c..35c95eee47 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -45,9 +45,19 @@ export default function AboutDialog() { } }, []); - const onContributorHovered = useCallback((contributor: Contributor, isHovering: boolean) => { - if (contributor.role === "original-dev") { - setAltIcon((isHovering) ? "classic": null); + const createContributorHoverHandler = useCallback(() => { + let timeoutID; + return (contributor: Contributor, isHovering: boolean) => { + if (contributor.role === "original-dev") { + if (isHovering) { + timeoutID = setTimeout(() => { + setAltIcon("classic"); + }, 500); + } else { + clearTimeout(timeoutID); + setAltIcon(null); + } + } } }, []); @@ -94,7 +104,7 @@ export default function AboutDialog() { From 0386e7dd4f30e7cdb0fd37e9be0da0fac870d884 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Wed, 25 Mar 2026 11:41:50 +0200 Subject: [PATCH 065/482] style/about dialog: add a clue about contributor links with a tooltip --- apps/client/src/widgets/dialogs/about.css | 4 ++++ apps/client/src/widgets/dialogs/about.tsx | 2 ++ 2 files changed, 6 insertions(+) diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css index 97c8cc093c..92f04a9909 100644 --- a/apps/client/src/widgets/dialogs/about.css +++ b/apps/client/src/widgets/dialogs/about.css @@ -68,6 +68,10 @@ a, span { white-space: nowrap; } + + a.has-tooltip { + text-decoration: underline dotted var(--main-text-color) !important; + } } footer { diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index 35c95eee47..668d8ab907 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -13,6 +13,7 @@ import type React from "react"; import contributors from "../../../../../contributors.json"; import { Fragment } from "preact/jsx-runtime"; import { ComponentChildren } from "preact"; +import clsx from "clsx"; export default function AboutDialog() { const [appInfo, setAppInfo] = useState(null); @@ -205,6 +206,7 @@ function ContributorListItem({data, onHover}: {data: Contributor, onHover?: Hove return <> onHover?.(data, true)} From d4552fa07596acb181c80a5c8c1de6b4c39ecb7b Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Fri, 27 Mar 2026 18:08:36 +0200 Subject: [PATCH 066/482] client/about dialog: refactor --- apps/client/src/widgets/dialogs/about.css | 10 +++--- apps/client/src/widgets/dialogs/about.tsx | 39 +++++++++++------------ 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css index 92f04a9909..5644431d5d 100644 --- a/apps/client/src/widgets/dialogs/about.css +++ b/apps/client/src/widgets/dialogs/about.css @@ -14,21 +14,21 @@ width: 160px; height: 160px; - &:not([data-alt-icon]) { + &[data-icon="default"] { background-image: url(../../assets/icon.svg); } - &[data-alt-icon="nightly"] { + &[data-icon="nightly"] { background-image: url(../../assets/icon-nightly.svg); } - &:not([data-alt-icon]), - &[data-alt-icon="nightly"] { + &[data-icon="default"], + &[data-icon="nightly"] { animation: icon-intro 500ms ease-out; will-change: opacity, transform; } - &[data-alt-icon="classic"] { + &[data-icon="classic"] { mask-image: url(../../assets/icon-classic.svg); background-color: var(--muted-text-color); animation: icon-classic-intro 300ms ease-in-out; diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index 668d8ab907..22220b0cfe 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -14,19 +14,22 @@ import contributors from "../../../../../contributors.json"; import { Fragment } from "preact/jsx-runtime"; import { ComponentChildren } from "preact"; import clsx from "clsx"; +import { useMemo } from "react"; +import { memo } from "preact/compat"; export default function AboutDialog() { const [appInfo, setAppInfo] = useState(null); const [shown, setShown] = useState(false); const [isNightly, setNightly] = useState(false); - const iconRef = useRef(null); + const [iconName, setIconName] = useState("default"); + const [altIconName, setAltIconName] = useState(null); const onLoad = useCallback(async () => { if (!appInfo) { const info = await server.get("app-info"); if (info.appVersion.includes("test")) { setNightly(true); - setAltIcon("nightly"); + setIconName("nightly"); } setAppInfo(info); } @@ -35,33 +38,32 @@ export default function AboutDialog() { useTriliumEvent("openAboutDialog", onLoad); - const setAltIcon = useCallback((iconId: string | null) => { - /* The alternate icon is set by directly accessing the DOM to prevent the dialog being - * rerendered. A rerender while an element is hovered and displaying a tooltip in the same - * time, will cause the tooltip to break. */ - if (iconId) { - iconRef.current?.setAttribute("data-alt-icon", iconId); - } else { - iconRef.current?.removeAttribute("data-alt-icon"); - } - }, []); - const createContributorHoverHandler = useCallback(() => { let timeoutID; return (contributor: Contributor, isHovering: boolean) => { if (contributor.role === "original-dev") { if (isHovering) { timeoutID = setTimeout(() => { - setAltIcon("classic"); + setAltIconName("classic"); }, 500); } else { clearTimeout(timeoutID); - setAltIcon(null); + setAltIconName(null); } } } }, []); + /* Cache the contributor list to prevent its rerendering. + * When the icon changes, it triggers a rerender of the dialog. If this happens while an + * element with a tooltip is hovered, its tooltip will break. */ + const CachedContributors = useMemo(() => memo(function CachedContributors() { + return + }), []); + return (
-
+

Trilium Notes {isNightly && Nightly}

triliumnotes.org @@ -103,10 +105,7 @@ export default function AboutDialog() { {t("about.contributors_label")} - + {t("about.contributor_full_list")} From 72cc5cc5ead841a61bc25e6d2813e6cc7496a8e0 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Fri, 27 Mar 2026 18:23:05 +0200 Subject: [PATCH 067/482] style/about dialog: update the donate button link on light theme --- apps/client/src/widgets/dialogs/about.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css index 5644431d5d..de7a18f1b9 100644 --- a/apps/client/src/widgets/dialogs/about.css +++ b/apps/client/src/widgets/dialogs/about.css @@ -1,7 +1,7 @@ .about-dialog { body.light-theme & { - --donate-button-color: #d78382; + --donate-button-color: #e33f3b; } body.dark-theme & { From 355209769f0554438584950143a6c29dab9c85bc Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Fri, 27 Mar 2026 18:30:24 +0200 Subject: [PATCH 068/482] style/tooltips: use higher contrast on the light theme --- apps/client/src/stylesheets/theme-next-light.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/client/src/stylesheets/theme-next-light.css b/apps/client/src/stylesheets/theme-next-light.css index fe604906dc..05211e4e02 100644 --- a/apps/client/src/stylesheets/theme-next-light.css +++ b/apps/client/src/stylesheets/theme-next-light.css @@ -269,9 +269,9 @@ --timeline-connector-active-color: #ddd; --timeline-connector-hover-blend-mode: multiply; - --tooltip-background-color: rgba(255, 255, 255, 0.85); - --tooltip-foreground-color: #000000ba; - --tooltip-shadow-color: rgba(0, 0, 0, 0.15); + --tooltip-background-color: rgba(0, 0, 0, 0.818); + --tooltip-foreground-color: #ffffffeb; + --tooltip-shadow-color: rgba(0, 0, 0, 0.2); --help-background-color: #fffc; --help-card-background: var(--card-background-color); From 87fb568995d8f66602e3f4d563c2ff1b6eb8f1a7 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Fri, 27 Mar 2026 18:42:26 +0200 Subject: [PATCH 069/482] style/about dialog: customize the style of tooltips used for brief history --- apps/client/src/widgets/dialogs/about.css | 4 ++++ apps/client/src/widgets/dialogs/about.tsx | 1 + 2 files changed, 5 insertions(+) diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css index de7a18f1b9..5c907510e8 100644 --- a/apps/client/src/widgets/dialogs/about.css +++ b/apps/client/src/widgets/dialogs/about.css @@ -115,6 +115,10 @@ } } +.about-dialog-brief-history-tooltip { + --main-font-size: .85em; +} + @keyframes icon-intro { from { opacity: 0; diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index 22220b0cfe..3555dd18a7 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -197,6 +197,7 @@ function ContributorListItem({data, onHover}: {data: Contributor, onHover?: Hove useTooltip(linkRef, (data.role) ? { title: t(`about.role_brief_history.${data.role}`), + customClass: "about-dialog-brief-history-tooltip", placement: "bottom", offset: [0, 10], delay: 500 From 2432bb11c7781015a12b4330373648a3dfa8a933 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Fri, 27 Mar 2026 19:13:05 +0200 Subject: [PATCH 070/482] style/about dialog: allow long directory paths to be wrapped --- apps/client/src/widgets/dialogs/about.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index 3555dd18a7..dba0ed7bb5 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -115,7 +115,7 @@ export default function AboutDialog() { {t("about.data_directory")} - + {appInfo?.dataDirectory && ()} From 601f246bdc13dd2f1742355d593949b5ffe980dd Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Tue, 31 Mar 2026 21:29:32 +0300 Subject: [PATCH 071/482] style/about dialog: move the brief history tooltip from the contributor name link to the role string --- apps/client/src/widgets/dialogs/about.css | 7 +++--- apps/client/src/widgets/dialogs/about.tsx | 28 +++++++++++++---------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css index 5c907510e8..9b707cb365 100644 --- a/apps/client/src/widgets/dialogs/about.css +++ b/apps/client/src/widgets/dialogs/about.css @@ -68,9 +68,10 @@ a, span { white-space: nowrap; } - - a.has-tooltip { - text-decoration: underline dotted var(--main-text-color) !important; + + .contributor-role { + text-decoration: underline dotted var(--main-text-color); + cursor: help; } } diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index dba0ed7bb5..cf0aad263f 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -13,7 +13,6 @@ import type React from "react"; import contributors from "../../../../../contributors.json"; import { Fragment } from "preact/jsx-runtime"; import { ComponentChildren } from "preact"; -import clsx from "clsx"; import { useMemo } from "react"; import { memo } from "preact/compat"; @@ -40,8 +39,8 @@ export default function AboutDialog() { const createContributorHoverHandler = useCallback(() => { let timeoutID; - return (contributor: Contributor, isHovering: boolean) => { - if (contributor.role === "original-dev") { + return (contributor: Contributor, isHovering: boolean, part: "name" | "role") => { + if (part === "role" && contributor.role === "original-dev") { if (isHovering) { timeoutID = setTimeout(() => { setAltIconName("classic"); @@ -177,7 +176,7 @@ function FooterLink(props: {children: ComponentChildren, text: string, url: stri } -type HoverCallback = (contributor: Contributor, isHovering: boolean) => void; +type HoverCallback = (contributor: Contributor, isHovering: boolean, part: "name" | "role") => void; function Contributors({data, onHover}: {data: ContributorList, onHover?: HoverCallback}) { return data.contributors.slice(0, 10).map((c, index, array) => { @@ -192,10 +191,10 @@ function Contributors({data, onHover}: {data: ContributorList, onHover?: HoverCa function ContributorListItem({data, onHover}: {data: Contributor, onHover?: HoverCallback}) { - const linkRef = useRef(null); + const roleRef = useRef(null); const roleString = (data.role) ? t(`about.contributor_roles.${data.role}`) : ""; - useTooltip(linkRef, (data.role) ? { + useTooltip(roleRef, (data.role) ? { title: t(`about.role_brief_history.${data.role}`), customClass: "about-dialog-brief-history-tooltip", placement: "bottom", @@ -205,17 +204,22 @@ function ContributorListItem({data, onHover}: {data: Contributor, onHover?: Hove return <> onHover?.(data, true)} - onMouseLeave={(e) => onHover?.(data, false)}> - + onMouseEnter={(e) => onHover?.(data, true, "name")} + onMouseLeave={(e) => onHover?.(data, false, "name")}> + {data.fullName ?? data.name} - {roleString &&  ({roleString})} + {roleString && onHover?.(data, true, "role")} + onMouseLeave={(e) => onHover?.(data, false, "role")}> + + ({roleString}) + } } From d61e399c67dbde0a87422e9990579e35ad0856e7 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Tue, 31 Mar 2026 21:48:14 +0300 Subject: [PATCH 072/482] style/about dialog: add an animation to the donate button --- apps/client/src/widgets/dialogs/about.css | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css index 9b707cb365..d3dcf55d61 100644 --- a/apps/client/src/widgets/dialogs/about.css +++ b/apps/client/src/widgets/dialogs/about.css @@ -111,6 +111,11 @@ &.donate-link { color: var(--donate-button-color); + + &:hover i { + animation: heartbeat 600ms ease-in-out; + animation-iteration-count: 3; + } } } } @@ -140,6 +145,18 @@ } } +@keyframes heartbeat { + 0% { + transform: scale(1); + } 50% { + transform: scale(1.15); + } 75% { + transform: scale(1); + } 100% { + transform: scale(1); + } +} + /* TODO: move to global styles */ .property-sheet-table { border-spacing: 0 2px; From 32a2834bf350ed25e7827f49a3d97029a6a647a3 Mon Sep 17 00:00:00 2001 From: Elias Soares Date: Sat, 11 Apr 2026 14:25:49 -0300 Subject: [PATCH 073/482] fix(etapi): correct calendar year/month endpoint descriptions and year pattern; docs: add trilium-fastmcp integration --- apps/server/etapi.openapi.yaml | 8 ++++---- docs/User Guide/User Guide/AI.md | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/server/etapi.openapi.yaml b/apps/server/etapi.openapi.yaml index 8b8a65f2b3..882c069941 100644 --- a/apps/server/etapi.openapi.yaml +++ b/apps/server/etapi.openapi.yaml @@ -870,7 +870,7 @@ paths: $ref: "#/components/schemas/Error" /calendar/months/{month}: get: - description: returns a week note for a given date. Gets created if doesn't exist. + description: returns a month note for a given month. Gets created if doesn't exist. operationId: getMonthNote parameters: - name: month @@ -895,7 +895,7 @@ paths: $ref: "#/components/schemas/Error" /calendar/years/{year}: get: - description: returns a week note for a given date. Gets created if doesn't exist. + description: returns a year note for a given year. Gets created if doesn't exist. operationId: getYearNote parameters: - name: year @@ -903,8 +903,8 @@ paths: required: true schema: type: string - pattern: "[0-9]{4}-[0-9]{2}" - example: 2022-02 + pattern: "[0-9]{4}" + example: "2022" responses: "200": description: year note diff --git a/docs/User Guide/User Guide/AI.md b/docs/User Guide/User Guide/AI.md index 4ca2d07abd..8c848f1163 100644 --- a/docs/User Guide/User Guide/AI.md +++ b/docs/User Guide/User Guide/AI.md @@ -13,6 +13,7 @@ As such, there are third-party solutions that integrate an MCP server that can b * [tan-yong-sheng/triliumnext-mcp](https://github.com/tan-yong-sheng/triliumnext-mcp) * [perfectra1n/triliumnext-mcp](https://github.com/perfectra1n/triliumnext-mcp) +* [eliassoares/trilium-fastmcp](https://github.com/eliassoares/trilium-fastmcp) > [!IMPORTANT] > These solutions are third-party and thus not endorsed or supported directly by the Trilium Notes team. Please address questions and issues on their corresponding repository instead. \ No newline at end of file From e2043c14f2eb23e0ebcd51a472dd07988d1b8188 Mon Sep 17 00:00:00 2001 From: Elias Soares Date: Sat, 11 Apr 2026 20:41:08 -0300 Subject: [PATCH 074/482] improv: applying Gemini's suggestions --- apps/server/etapi.openapi.yaml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/server/etapi.openapi.yaml b/apps/server/etapi.openapi.yaml index 882c069941..99e5a98c70 100644 --- a/apps/server/etapi.openapi.yaml +++ b/apps/server/etapi.openapi.yaml @@ -870,7 +870,8 @@ paths: $ref: "#/components/schemas/Error" /calendar/months/{month}: get: - description: returns a month note for a given month. Gets created if doesn't exist. + summary: Get a month note + description: Returns a month note for a given month (format YYYY-MM, e.g., 2022-02). The note is created if it doesn't exist. operationId: getMonthNote parameters: - name: month @@ -895,7 +896,8 @@ paths: $ref: "#/components/schemas/Error" /calendar/years/{year}: get: - description: returns a year note for a given year. Gets created if doesn't exist. + summary: Get a year note + description: Returns a year note for a given year (format YYYY, e.g., 2022). The note is created if it doesn't exist. operationId: getYearNote parameters: - name: year @@ -903,7 +905,7 @@ paths: required: true schema: type: string - pattern: "[0-9]{4}" + pattern: "^[0-9]{4}$" example: "2022" responses: "200": From d3c927ed88a19d2c35224b791bda47c8e5e0b29c Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 12 Apr 2026 20:59:29 +0300 Subject: [PATCH 075/482] style/about dialog: exclude the brackets from the contributor role tooltip cue --- apps/client/src/widgets/dialogs/about.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index cf0aad263f..37ddbc6ac8 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -213,12 +213,11 @@ function ContributorListItem({data, onHover}: {data: Contributor, onHover?: Hove {roleString && onHover?.(data, true, "role")} onMouseLeave={(e) => onHover?.(data, false, "role")}> - ({roleString}) + ({roleString}) } } From e6db4a51d14c83f585ffc1d608057912a20cec43 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 12 Apr 2026 21:13:00 +0300 Subject: [PATCH 076/482] client/about dialog: update the version format --- apps/client/src/translations/en/translation.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 43b99652e4..17a283b09d 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -1,8 +1,8 @@ { "about": { "version_label": "Version:", - "version": "app: {{appVersion}}, database: {{dbVersion}}, sync protocol: {{syncVersion}}", - "build_info": "{{buildDate}}, revision: ", + "version": "{{appVersion}} (database: {{dbVersion}}, sync protocol: {{syncVersion}})", + "build_info": "Build: {{buildDate}}, revision: ", "contributors_label": "Contributors:", "contributor_roles": { "lead-dev": "lead developer", From f9aaccdfe2dc7e5b11aea9def7f59d3b50a7bdb9 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 13 Apr 2026 01:06:34 +0300 Subject: [PATCH 077/482] chore(docker): set up tooling for building better-sqlite3 from scratch --- apps/server/Dockerfile | 8 ++++++++ apps/server/Dockerfile.alpine | 3 +++ apps/server/Dockerfile.alpine.rootless | 3 +++ apps/server/Dockerfile.legacy | 8 ++++++++ apps/server/Dockerfile.rootless | 8 ++++++++ 5 files changed, 30 insertions(+) diff --git a/apps/server/Dockerfile b/apps/server/Dockerfile index 1db1be8182..f61f4971cc 100644 --- a/apps/server/Dockerfile +++ b/apps/server/Dockerfile @@ -1,6 +1,14 @@ FROM node:24.14.1-bullseye-slim AS builder RUN corepack enable +# Install build tools required to compile native addons (e.g. better-sqlite3) on ARM +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + python3 \ + make \ + g++ && \ + rm -rf /var/lib/apt/lists/* + # Install native dependencies since we might be building cross-platform. WORKDIR /usr/src/app/build COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/ diff --git a/apps/server/Dockerfile.alpine b/apps/server/Dockerfile.alpine index bf8039e224..67e2bafe5f 100644 --- a/apps/server/Dockerfile.alpine +++ b/apps/server/Dockerfile.alpine @@ -1,6 +1,9 @@ FROM node:24.14.1-alpine AS builder RUN corepack enable +# Install build tools required to compile native addons (e.g. better-sqlite3) on ARM +RUN apk add --no-cache python3 make g++ + # Install native dependencies since we might be building cross-platform. WORKDIR /usr/src/app COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/ diff --git a/apps/server/Dockerfile.alpine.rootless b/apps/server/Dockerfile.alpine.rootless index 21c0cb664c..3e4d33c555 100644 --- a/apps/server/Dockerfile.alpine.rootless +++ b/apps/server/Dockerfile.alpine.rootless @@ -1,6 +1,9 @@ FROM node:24.14.1-alpine AS builder RUN corepack enable +# Install build tools required to compile native addons (e.g. better-sqlite3) on ARM +RUN apk add --no-cache python3 make g++ + # Install native dependencies since we might be building cross-platform. WORKDIR /usr/src/app COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/ diff --git a/apps/server/Dockerfile.legacy b/apps/server/Dockerfile.legacy index ef6ddfcb06..8f514c81cd 100644 --- a/apps/server/Dockerfile.legacy +++ b/apps/server/Dockerfile.legacy @@ -1,6 +1,14 @@ FROM node:22.21.0-bullseye-slim AS builder RUN corepack enable +# Install build tools required to compile native addons (e.g. better-sqlite3) on ARM +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + python3 \ + make \ + g++ && \ + rm -rf /var/lib/apt/lists/* + # Install native dependencies since we might be building cross-platform. WORKDIR /usr/src/app/build COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/ diff --git a/apps/server/Dockerfile.rootless b/apps/server/Dockerfile.rootless index 5b82d2ab1d..ea4b6085ec 100644 --- a/apps/server/Dockerfile.rootless +++ b/apps/server/Dockerfile.rootless @@ -1,6 +1,14 @@ FROM node:24.14.1-bullseye-slim AS builder RUN corepack enable +# Install build tools required to compile native addons (e.g. better-sqlite3) on ARM +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + python3 \ + make \ + g++ && \ + rm -rf /var/lib/apt/lists/* + # Install native dependencies since we might be building cross-platform. WORKDIR /usr/src/app/build COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/ From a44ff4c78b633837dd067231fbd6dd6bdf948b02 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 01:36:07 +0000 Subject: [PATCH 078/482] chore(deps): update vitest monorepo to v4.1.4 --- apps/website/package.json | 2 +- package.json | 8 +- packages/ckeditor5-admonition/package.json | 6 +- packages/ckeditor5-footnotes/package.json | 6 +- .../ckeditor5-keyboard-marker/package.json | 6 +- packages/ckeditor5-math/package.json | 6 +- packages/ckeditor5-mermaid/package.json | 6 +- packages/splitjs/package.json | 2 +- packages/turndown-plugin-gfm/package.json | 2 +- pnpm-lock.yaml | 248 +++++++++--------- 10 files changed, 146 insertions(+), 146 deletions(-) diff --git a/apps/website/package.json b/apps/website/package.json index 0f603e930e..4e546b4ee4 100644 --- a/apps/website/package.json +++ b/apps/website/package.json @@ -22,7 +22,7 @@ "typescript": "6.0.2", "user-agent-data-types": "0.4.3", "vite": "8.0.7", - "vitest": "4.1.3" + "vitest": "4.1.4" }, "eslintConfig": { "extends": "preact" diff --git a/package.json b/package.json index d8f8803e56..6e8cc64a5f 100644 --- a/package.json +++ b/package.json @@ -53,9 +53,9 @@ "@types/express": "5.0.6", "@types/js-yaml": "4.0.9", "@types/node": "24.12.2", - "@vitest/browser-webdriverio": "4.1.3", - "@vitest/coverage-v8": "4.1.3", - "@vitest/ui": "4.1.3", + "@vitest/browser-webdriverio": "4.1.4", + "@vitest/coverage-v8": "4.1.4", + "@vitest/ui": "4.1.4", "chalk": "5.6.2", "cross-env": "10.1.0", "dpdm": "4.0.1", @@ -78,7 +78,7 @@ "typescript-eslint": "8.58.1", "vite": "8.0.7", "vite-plugin-dts": "4.5.4", - "vitest": "4.1.3" + "vitest": "4.1.4" }, "license": "AGPL-3.0-only", "author": { diff --git a/packages/ckeditor5-admonition/package.json b/packages/ckeditor5-admonition/package.json index c51e6bfec5..4fba27aa46 100644 --- a/packages/ckeditor5-admonition/package.json +++ b/packages/ckeditor5-admonition/package.json @@ -20,8 +20,8 @@ "@ckeditor/ckeditor5-inspector": ">=4.1.0", "@typescript-eslint/eslint-plugin": "8.58.1", "@typescript-eslint/parser": "8.58.1", - "@vitest/browser": "4.1.3", - "@vitest/coverage-istanbul": "4.1.3", + "@vitest/browser": "4.1.4", + "@vitest/coverage-istanbul": "4.1.4", "ckeditor5": "48.0.0", "eslint": "10.2.0", "eslint-config-ckeditor5": ">=9.1.0", @@ -29,7 +29,7 @@ "stylelint-config-ckeditor5": ">=9.1.0", "typescript": "6.0.2", "vite-plugin-svgo": "2.0.0", - "vitest": "4.1.3", + "vitest": "4.1.4", "webdriverio": "9.27.0" }, "peerDependencies": { diff --git a/packages/ckeditor5-footnotes/package.json b/packages/ckeditor5-footnotes/package.json index 26de370c6f..78314231e0 100644 --- a/packages/ckeditor5-footnotes/package.json +++ b/packages/ckeditor5-footnotes/package.json @@ -21,8 +21,8 @@ "@ckeditor/ckeditor5-inspector": ">=4.1.0", "@typescript-eslint/eslint-plugin": "8.58.1", "@typescript-eslint/parser": "8.58.1", - "@vitest/browser": "4.1.3", - "@vitest/coverage-istanbul": "4.1.3", + "@vitest/browser": "4.1.4", + "@vitest/coverage-istanbul": "4.1.4", "ckeditor5": "48.0.0", "eslint": "10.2.0", "eslint-config-ckeditor5": ">=9.1.0", @@ -30,7 +30,7 @@ "stylelint-config-ckeditor5": ">=9.1.0", "typescript": "6.0.2", "vite-plugin-svgo": "2.0.0", - "vitest": "4.1.3", + "vitest": "4.1.4", "webdriverio": "9.27.0" }, "peerDependencies": { diff --git a/packages/ckeditor5-keyboard-marker/package.json b/packages/ckeditor5-keyboard-marker/package.json index ce8e598fe3..b21c0b7fc0 100644 --- a/packages/ckeditor5-keyboard-marker/package.json +++ b/packages/ckeditor5-keyboard-marker/package.json @@ -23,8 +23,8 @@ "@ckeditor/ckeditor5-inspector": ">=4.1.0", "@typescript-eslint/eslint-plugin": "8.58.1", "@typescript-eslint/parser": "8.58.1", - "@vitest/browser": "4.1.3", - "@vitest/coverage-istanbul": "4.1.3", + "@vitest/browser": "4.1.4", + "@vitest/coverage-istanbul": "4.1.4", "ckeditor5": "48.0.0", "eslint": "10.2.0", "eslint-config-ckeditor5": ">=9.1.0", @@ -32,7 +32,7 @@ "stylelint-config-ckeditor5": ">=9.1.0", "typescript": "6.0.2", "vite-plugin-svgo": "2.0.0", - "vitest": "4.1.3", + "vitest": "4.1.4", "webdriverio": "9.27.0" }, "peerDependencies": { diff --git a/packages/ckeditor5-math/package.json b/packages/ckeditor5-math/package.json index 2b510a8bda..2e44c0e5cb 100644 --- a/packages/ckeditor5-math/package.json +++ b/packages/ckeditor5-math/package.json @@ -23,8 +23,8 @@ "@ckeditor/ckeditor5-inspector": ">=4.1.0", "@typescript-eslint/eslint-plugin": "8.58.1", "@typescript-eslint/parser": "8.58.1", - "@vitest/browser": "4.1.3", - "@vitest/coverage-istanbul": "4.1.3", + "@vitest/browser": "4.1.4", + "@vitest/coverage-istanbul": "4.1.4", "ckeditor5": "48.0.0", "eslint": "10.2.0", "eslint-config-ckeditor5": ">=9.1.0", @@ -32,7 +32,7 @@ "stylelint-config-ckeditor5": ">=9.1.0", "typescript": "6.0.2", "vite-plugin-svgo": "2.0.0", - "vitest": "4.1.3", + "vitest": "4.1.4", "webdriverio": "9.27.0" }, "peerDependencies": { diff --git a/packages/ckeditor5-mermaid/package.json b/packages/ckeditor5-mermaid/package.json index f4679f8d1b..5812e83972 100644 --- a/packages/ckeditor5-mermaid/package.json +++ b/packages/ckeditor5-mermaid/package.json @@ -23,8 +23,8 @@ "@ckeditor/ckeditor5-inspector": ">=4.1.0", "@typescript-eslint/eslint-plugin": "8.58.1", "@typescript-eslint/parser": "8.58.1", - "@vitest/browser": "4.1.3", - "@vitest/coverage-istanbul": "4.1.3", + "@vitest/browser": "4.1.4", + "@vitest/coverage-istanbul": "4.1.4", "ckeditor5": "48.0.0", "eslint": "10.2.0", "eslint-config-ckeditor5": ">=9.1.0", @@ -32,7 +32,7 @@ "stylelint-config-ckeditor5": ">=9.1.0", "typescript": "6.0.2", "vite-plugin-svgo": "2.0.0", - "vitest": "4.1.3", + "vitest": "4.1.4", "webdriverio": "9.27.0" }, "peerDependencies": { diff --git a/packages/splitjs/package.json b/packages/splitjs/package.json index ab77cb8bee..951d1e6e80 100644 --- a/packages/splitjs/package.json +++ b/packages/splitjs/package.json @@ -39,6 +39,6 @@ "devDependencies": { "@rollup/plugin-buble": "1.0.3", "happy-dom": "20.8.9", - "vitest": "4.1.3" + "vitest": "4.1.4" } } diff --git a/packages/turndown-plugin-gfm/package.json b/packages/turndown-plugin-gfm/package.json index ec1e5dd255..c570fea017 100644 --- a/packages/turndown-plugin-gfm/package.json +++ b/packages/turndown-plugin-gfm/package.json @@ -27,6 +27,6 @@ "devDependencies": { "happy-dom": "20.8.9", "turndown": "7.2.4", - "vitest": "4.1.3" + "vitest": "4.1.4" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bf50a09222..a3a5442fd4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -106,14 +106,14 @@ importers: specifier: 24.12.2 version: 24.12.2 '@vitest/browser-webdriverio': - specifier: 4.1.3 - version: 4.1.3(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.3)(webdriverio@9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) + specifier: 4.1.4 + version: 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4)(webdriverio@9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) '@vitest/coverage-v8': - specifier: 4.1.3 - version: 4.1.3(@vitest/browser@4.1.3)(vitest@4.1.3) + specifier: 4.1.4 + version: 4.1.4(@vitest/browser@4.1.4)(vitest@4.1.4) '@vitest/ui': - specifier: 4.1.3 - version: 4.1.3(vitest@4.1.3) + specifier: 4.1.4 + version: 4.1.4(vitest@4.1.4) chalk: specifier: 5.6.2 version: 5.6.2 @@ -181,8 +181,8 @@ importers: specifier: 4.5.4 version: 4.5.4(@types/node@24.12.2)(rollup@4.60.1)(typescript@6.0.2)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) vitest: - specifier: 4.1.3 - version: 4.1.3(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.3)(@vitest/coverage-istanbul@4.1.3)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + specifier: 4.1.4 + version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) apps/build-docs: devDependencies: @@ -932,8 +932,8 @@ importers: specifier: 8.0.7 version: 8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) vitest: - specifier: 4.1.3 - version: 4.1.3(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.3)(@vitest/coverage-istanbul@4.1.3)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + specifier: 4.1.4 + version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ckeditor5: dependencies: @@ -974,11 +974,11 @@ importers: specifier: 8.58.1 version: 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) '@vitest/browser': - specifier: 4.1.3 - version: 4.1.3(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.3) + specifier: 4.1.4 + version: 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) '@vitest/coverage-istanbul': - specifier: 4.1.3 - version: 4.1.3(vitest@4.1.3) + specifier: 4.1.4 + version: 4.1.4(vitest@4.1.4) ckeditor5: specifier: 48.0.0 version: 48.0.0 @@ -1001,8 +1001,8 @@ importers: specifier: 2.0.0 version: 2.0.0(typescript@6.0.2)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) vitest: - specifier: 4.1.3 - version: 4.1.3(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.3)(@vitest/coverage-istanbul@4.1.3)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + specifier: 4.1.4 + version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) webdriverio: specifier: 9.27.0 version: 9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) @@ -1019,11 +1019,11 @@ importers: specifier: 8.58.1 version: 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) '@vitest/browser': - specifier: 4.1.3 - version: 4.1.3(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.3) + specifier: 4.1.4 + version: 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) '@vitest/coverage-istanbul': - specifier: 4.1.3 - version: 4.1.3(vitest@4.1.3) + specifier: 4.1.4 + version: 4.1.4(vitest@4.1.4) ckeditor5: specifier: 48.0.0 version: 48.0.0 @@ -1046,8 +1046,8 @@ importers: specifier: 2.0.0 version: 2.0.0(typescript@6.0.2)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) vitest: - specifier: 4.1.3 - version: 4.1.3(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.3)(@vitest/coverage-istanbul@4.1.3)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + specifier: 4.1.4 + version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) webdriverio: specifier: 9.27.0 version: 9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) @@ -1064,11 +1064,11 @@ importers: specifier: 8.58.1 version: 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) '@vitest/browser': - specifier: 4.1.3 - version: 4.1.3(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.3) + specifier: 4.1.4 + version: 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) '@vitest/coverage-istanbul': - specifier: 4.1.3 - version: 4.1.3(vitest@4.1.3) + specifier: 4.1.4 + version: 4.1.4(vitest@4.1.4) ckeditor5: specifier: 48.0.0 version: 48.0.0 @@ -1091,8 +1091,8 @@ importers: specifier: 2.0.0 version: 2.0.0(typescript@6.0.2)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) vitest: - specifier: 4.1.3 - version: 4.1.3(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.3)(@vitest/coverage-istanbul@4.1.3)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + specifier: 4.1.4 + version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) webdriverio: specifier: 9.27.0 version: 9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) @@ -1116,11 +1116,11 @@ importers: specifier: 8.58.1 version: 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) '@vitest/browser': - specifier: 4.1.3 - version: 4.1.3(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.3) + specifier: 4.1.4 + version: 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) '@vitest/coverage-istanbul': - specifier: 4.1.3 - version: 4.1.3(vitest@4.1.3) + specifier: 4.1.4 + version: 4.1.4(vitest@4.1.4) ckeditor5: specifier: 48.0.0 version: 48.0.0 @@ -1143,8 +1143,8 @@ importers: specifier: 2.0.0 version: 2.0.0(typescript@6.0.2)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) vitest: - specifier: 4.1.3 - version: 4.1.3(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.3)(@vitest/coverage-istanbul@4.1.3)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + specifier: 4.1.4 + version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) webdriverio: specifier: 9.27.0 version: 9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) @@ -1161,11 +1161,11 @@ importers: specifier: 8.58.1 version: 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) '@vitest/browser': - specifier: 4.1.3 - version: 4.1.3(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.3) + specifier: 4.1.4 + version: 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) '@vitest/coverage-istanbul': - specifier: 4.1.3 - version: 4.1.3(vitest@4.1.3) + specifier: 4.1.4 + version: 4.1.4(vitest@4.1.4) ckeditor5: specifier: 48.0.0 version: 48.0.0 @@ -1188,8 +1188,8 @@ importers: specifier: 2.0.0 version: 2.0.0(typescript@6.0.2)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) vitest: - specifier: 4.1.3 - version: 4.1.3(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.3)(@vitest/coverage-istanbul@4.1.3)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + specifier: 4.1.4 + version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) webdriverio: specifier: 9.27.0 version: 9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) @@ -1450,8 +1450,8 @@ importers: specifier: 20.8.9 version: 20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5) vitest: - specifier: 4.1.3 - version: 4.1.3(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.3)(@vitest/coverage-istanbul@4.1.3)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + specifier: 4.1.4 + version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) packages/turndown-plugin-gfm: devDependencies: @@ -1462,8 +1462,8 @@ importers: specifier: 7.2.4 version: 7.2.4 vitest: - specifier: 4.1.3 - version: 4.1.3(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.3)(@vitest/coverage-istanbul@4.1.3)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + specifier: 4.1.4 + version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) packages: @@ -6344,36 +6344,36 @@ packages: resolution: {integrity: sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==} engines: {node: '>= 20'} - '@vitest/browser-webdriverio@4.1.3': - resolution: {integrity: sha512-EeCY0116zZk5uedmwkVdW2dfpv1JEVtK1n+3WeNnyjBVWnBzDlqY1Kkf8Z3Re1qb5Nki8LgnQgQp1VT+q/ZaMQ==} + '@vitest/browser-webdriverio@4.1.4': + resolution: {integrity: sha512-AhBipo9kfFpZ11Vx+kLD6rwJ+pnp/TpYm7tA1jOh1t1DMoj4IrofW82vW9EUY4Tmx2s/aWDxPDjrYMSoyilt8w==} peerDependencies: - vitest: 4.1.3 + vitest: 4.1.4 webdriverio: '*' - '@vitest/browser@4.1.3': - resolution: {integrity: sha512-CS9KjO2vijuBlbwz0JIgC0YuoI1BuqWI5ziD3Nll6jkpNYtWdjPMVgGynQ9vZovjsECeUqEeNjWrypP414d0CQ==} + '@vitest/browser@4.1.4': + resolution: {integrity: sha512-TrNaY/yVOwxtrxNsDUC/wQ56xSwplpytTeRAqF/197xV/ZddxxulBsxR6TrhVMyniJmp9in8d5u0AcDaNRY30w==} peerDependencies: - vitest: 4.1.3 + vitest: 4.1.4 - '@vitest/coverage-istanbul@4.1.3': - resolution: {integrity: sha512-IjlvIg2MaFDgeYOXgqxWwTh8c8Y8HkR/36SN0Iq5XtmsmbEau7a5i7g1F+Lv7G9R+vDzOt+HyNOmKqg/8kKzug==} + '@vitest/coverage-istanbul@4.1.4': + resolution: {integrity: sha512-Pyi4F8RnqU6hBGiIDhS/e8gVD4FRcUvZJ2AbFiIlmIxHlEIsKyCxGOqufCECobty/dXELcN8oIH4Gms3hVOCYA==} peerDependencies: - vitest: 4.1.3 + vitest: 4.1.4 - '@vitest/coverage-v8@4.1.3': - resolution: {integrity: sha512-/MBdrkA8t6hbdCWFKs09dPik774xvs4Z6L4bycdCxYNLHM8oZuRyosumQMG19LUlBsB6GeVpL1q4kFFazvyKGA==} + '@vitest/coverage-v8@4.1.4': + resolution: {integrity: sha512-x7FptB5oDruxNPDNY2+S8tCh0pcq7ymCe1gTHcsp733jYjrJl8V1gMUlVysuCD9Kz46Xz9t1akkv08dPcYDs1w==} peerDependencies: - '@vitest/browser': 4.1.3 - vitest: 4.1.3 + '@vitest/browser': 4.1.4 + vitest: 4.1.4 peerDependenciesMeta: '@vitest/browser': optional: true - '@vitest/expect@4.1.3': - resolution: {integrity: sha512-CW8Q9KMtXDGHj0vCsqui0M5KqRsu0zm0GNDW7Gd3U7nZ2RFpPKSCpeCXoT+/+5zr1TNlsoQRDEz+LzZUyq6gnQ==} + '@vitest/expect@4.1.4': + resolution: {integrity: sha512-iPBpra+VDuXmBFI3FMKHSFXp3Gx5HfmSCE8X67Dn+bwephCnQCaB7qWK2ldHa+8ncN8hJU8VTMcxjPpyMkUjww==} - '@vitest/mocker@4.1.3': - resolution: {integrity: sha512-XN3TrycitDQSzGRnec/YWgoofkYRhouyVQj4YNsJ5r/STCUFqMrP4+oxEv3e7ZbLi4og5kIHrZwekDJgw6hcjw==} + '@vitest/mocker@4.1.4': + resolution: {integrity: sha512-R9HTZBhW6yCSGbGQnDnH3QHfJxokKN4KB+Yvk9Q1le7eQNYwiCyKxmLmurSpFy6BzJanSLuEUDrD+j97Q+ZLPg==} peerDependencies: msw: ^2.4.9 vite: '>=7.3.2' @@ -6383,25 +6383,25 @@ packages: vite: optional: true - '@vitest/pretty-format@4.1.3': - resolution: {integrity: sha512-hYqqwuMbpkkBodpRh4k4cQSOELxXky1NfMmQvOfKvV8zQHz8x8Dla+2wzElkMkBvSAJX5TRGHJAQvK0TcOafwg==} + '@vitest/pretty-format@4.1.4': + resolution: {integrity: sha512-ddmDHU0gjEUyEVLxtZa7xamrpIefdEETu3nZjWtHeZX4QxqJ7tRxSteHVXJOcr8jhiLoGAhkK4WJ3WqBpjx42A==} - '@vitest/runner@4.1.3': - resolution: {integrity: sha512-VwgOz5MmT0KhlUj40h02LWDpUBVpflZ/b7xZFA25F29AJzIrE+SMuwzFf0b7t4EXdwRNX61C3B6auIXQTR3ttA==} + '@vitest/runner@4.1.4': + resolution: {integrity: sha512-xTp7VZ5aXP5ZJrn15UtJUWlx6qXLnGtF6jNxHepdPHpMfz/aVPx+htHtgcAL2mDXJgKhpoo2e9/hVJsIeFbytQ==} - '@vitest/snapshot@4.1.3': - resolution: {integrity: sha512-9l+k/J9KG5wPJDX9BcFFzhhwNjwkRb8RsnYhaT1vPY7OufxmQFc9sZzScRCPTiETzl37mrIWVY9zxzmdVeJwDQ==} + '@vitest/snapshot@4.1.4': + resolution: {integrity: sha512-MCjCFgaS8aZz+m5nTcEcgk/xhWv0rEH4Yl53PPlMXOZ1/Ka2VcZU6CJ+MgYCZbcJvzGhQRjVrGQNZqkGPttIKw==} - '@vitest/spy@4.1.3': - resolution: {integrity: sha512-ujj5Uwxagg4XUIfAUyRQxAg631BP6e9joRiN99mr48Bg9fRs+5mdUElhOoZ6rP5mBr8Bs3lmrREnkrQWkrsTCw==} + '@vitest/spy@4.1.4': + resolution: {integrity: sha512-XxNdAsKW7C+FLydqFJLb5KhJtl3PGCMmYwFRfhvIgxJvLSXhhVI1zM8f1qD3Zg7RCjTSzDVyct6sghs9UEgBEQ==} - '@vitest/ui@4.1.3': - resolution: {integrity: sha512-xBPy+43o1fgMLUDlufUXh7tlT/Es8uS5eiyBY2PyPfFYSGpApZskLw65DROoDz+rgYkPuAmb20Mv9Z9g1WQE7w==} + '@vitest/ui@4.1.4': + resolution: {integrity: sha512-EgFR7nlj5iTDYZYCvavjFokNYwr3c3ry0sFiCg+N7B233Nwp+NNx7eoF/XvMWDCKY71xXAG3kFkt97ZHBJVL8A==} peerDependencies: - vitest: 4.1.3 + vitest: 4.1.4 - '@vitest/utils@4.1.3': - resolution: {integrity: sha512-Pc/Oexse/khOWsGB+w3q4yzA4te7W4gpZZAvk+fr8qXfTURZUMj5i7kuxsNK5mP/dEB6ao3jfr0rs17fHhbHdw==} + '@vitest/utils@4.1.4': + resolution: {integrity: sha512-13QMT+eysM5uVGa1rG4kegGYNp6cnQcsTc67ELFbhNLQO+vgsygtYJx2khvdt4gVQqSSpC/KT5FZZxUpP3Oatw==} '@volar/language-core@2.4.13': resolution: {integrity: sha512-MnQJ7eKchJx5Oz+YdbqyFUk8BN6jasdJv31n/7r6/WwlOOv7qzvot6B66887l2ST3bUW4Mewml54euzpJWA6bg==} @@ -13626,20 +13626,20 @@ packages: yaml: optional: true - vitest@4.1.3: - resolution: {integrity: sha512-DBc4Tx0MPNsqb9isoyOq00lHftVx/KIU44QOm2q59npZyLUkENn8TMFsuzuO+4U2FUa9rgbbPt3udrP25GcjXw==} + vitest@4.1.4: + resolution: {integrity: sha512-tFuJqTxKb8AvfyqMfnavXdzfy3h3sWZRWwfluGbkeR7n0HUev+FmNgZ8SDrRBTVrVCjgH5cA21qGbCffMNtWvg==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@opentelemetry/api': ^1.9.0 '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.1.3 - '@vitest/browser-preview': 4.1.3 - '@vitest/browser-webdriverio': 4.1.3 - '@vitest/coverage-istanbul': 4.1.3 - '@vitest/coverage-v8': 4.1.3 - '@vitest/ui': 4.1.3 + '@vitest/browser-playwright': 4.1.4 + '@vitest/browser-preview': 4.1.4 + '@vitest/browser-webdriverio': 4.1.4 + '@vitest/coverage-istanbul': 4.1.4 + '@vitest/coverage-v8': 4.1.4 + '@vitest/ui': 4.1.4 happy-dom: '*' jsdom: '*' vite: '>=7.3.2' @@ -20930,10 +20930,10 @@ snapshots: '@vercel/oidc@3.1.0': {} - '@vitest/browser-webdriverio@4.1.3(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.3)(webdriverio@9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))': + '@vitest/browser-webdriverio@4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4)(webdriverio@9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))': dependencies: - '@vitest/browser': 4.1.3(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.3) - vitest: 4.1.3(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.3)(@vitest/coverage-istanbul@4.1.3)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/browser': 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) + vitest: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) webdriverio: 9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) transitivePeerDependencies: - bufferutil @@ -20941,16 +20941,16 @@ snapshots: - utf-8-validate - vite - '@vitest/browser@4.1.3(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.3)': + '@vitest/browser@4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4)': dependencies: '@blazediff/core': 1.9.1 - '@vitest/mocker': 4.1.3(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/utils': 4.1.3 + '@vitest/mocker': 4.1.4(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/utils': 4.1.4 magic-string: 0.30.21 pngjs: 7.0.0 sirv: 3.0.2 tinyrainbow: 3.1.0 - vitest: 4.1.3(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.3)(@vitest/coverage-istanbul@4.1.3)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) ws: 8.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) transitivePeerDependencies: - bufferutil @@ -20958,7 +20958,7 @@ snapshots: - utf-8-validate - vite - '@vitest/coverage-istanbul@4.1.3(vitest@4.1.3)': + '@vitest/coverage-istanbul@4.1.4(vitest@4.1.4)': dependencies: '@babel/core': 7.29.0 '@istanbuljs/schema': 0.1.3 @@ -20970,14 +20970,14 @@ snapshots: magicast: 0.5.2 obug: 2.1.1 tinyrainbow: 3.1.0 - vitest: 4.1.3(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.3)(@vitest/coverage-istanbul@4.1.3)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) transitivePeerDependencies: - supports-color - '@vitest/coverage-v8@4.1.3(@vitest/browser@4.1.3)(vitest@4.1.3)': + '@vitest/coverage-v8@4.1.4(@vitest/browser@4.1.4)(vitest@4.1.4)': dependencies: '@bcoe/v8-coverage': 1.0.2 - '@vitest/utils': 4.1.3 + '@vitest/utils': 4.1.4 ast-v8-to-istanbul: 1.0.0 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 @@ -20986,60 +20986,60 @@ snapshots: obug: 2.1.1 std-env: 4.0.0 tinyrainbow: 3.1.0 - vitest: 4.1.3(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.3)(@vitest/coverage-istanbul@4.1.3)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) optionalDependencies: - '@vitest/browser': 4.1.3(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.3) + '@vitest/browser': 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) - '@vitest/expect@4.1.3': + '@vitest/expect@4.1.4': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.2 - '@vitest/spy': 4.1.3 - '@vitest/utils': 4.1.3 + '@vitest/spy': 4.1.4 + '@vitest/utils': 4.1.4 chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.3(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))': + '@vitest/mocker@4.1.4(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))': dependencies: - '@vitest/spy': 4.1.3 + '@vitest/spy': 4.1.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: msw: 2.7.5(@types/node@24.12.2)(typescript@6.0.2) vite: 8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) - '@vitest/pretty-format@4.1.3': + '@vitest/pretty-format@4.1.4': dependencies: tinyrainbow: 3.1.0 - '@vitest/runner@4.1.3': + '@vitest/runner@4.1.4': dependencies: - '@vitest/utils': 4.1.3 + '@vitest/utils': 4.1.4 pathe: 2.0.3 - '@vitest/snapshot@4.1.3': + '@vitest/snapshot@4.1.4': dependencies: - '@vitest/pretty-format': 4.1.3 - '@vitest/utils': 4.1.3 + '@vitest/pretty-format': 4.1.4 + '@vitest/utils': 4.1.4 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@4.1.3': {} + '@vitest/spy@4.1.4': {} - '@vitest/ui@4.1.3(vitest@4.1.3)': + '@vitest/ui@4.1.4(vitest@4.1.4)': dependencies: - '@vitest/utils': 4.1.3 + '@vitest/utils': 4.1.4 fflate: 0.8.2 flatted: 3.4.2 pathe: 2.0.3 sirv: 3.0.2 tinyglobby: 0.2.15 tinyrainbow: 3.1.0 - vitest: 4.1.3(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.3)(@vitest/coverage-istanbul@4.1.3)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/utils@4.1.3': + '@vitest/utils@4.1.4': dependencies: - '@vitest/pretty-format': 4.1.3 + '@vitest/pretty-format': 4.1.4 convert-source-map: 2.0.0 tinyrainbow: 3.1.0 @@ -29651,15 +29651,15 @@ snapshots: tsx: 4.21.0 yaml: 2.8.3 - vitest@4.1.3(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.3)(@vitest/coverage-istanbul@4.1.3)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)): + vitest@4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)): dependencies: - '@vitest/expect': 4.1.3 - '@vitest/mocker': 4.1.3(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/pretty-format': 4.1.3 - '@vitest/runner': 4.1.3 - '@vitest/snapshot': 4.1.3 - '@vitest/spy': 4.1.3 - '@vitest/utils': 4.1.3 + '@vitest/expect': 4.1.4 + '@vitest/mocker': 4.1.4(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/pretty-format': 4.1.4 + '@vitest/runner': 4.1.4 + '@vitest/snapshot': 4.1.4 + '@vitest/spy': 4.1.4 + '@vitest/utils': 4.1.4 es-module-lexer: 2.0.0 expect-type: 1.3.0 magic-string: 0.30.21 @@ -29676,10 +29676,10 @@ snapshots: optionalDependencies: '@opentelemetry/api': 1.9.0 '@types/node': 24.12.2 - '@vitest/browser-webdriverio': 4.1.3(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.3)(webdriverio@9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) - '@vitest/coverage-istanbul': 4.1.3(vitest@4.1.3) - '@vitest/coverage-v8': 4.1.3(@vitest/browser@4.1.3)(vitest@4.1.3) - '@vitest/ui': 4.1.3(vitest@4.1.3) + '@vitest/browser-webdriverio': 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4)(webdriverio@9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) + '@vitest/coverage-istanbul': 4.1.4(vitest@4.1.4) + '@vitest/coverage-v8': 4.1.4(@vitest/browser@4.1.4)(vitest@4.1.4) + '@vitest/ui': 4.1.4(vitest@4.1.4) happy-dom: 20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5) jsdom: 26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) transitivePeerDependencies: From 2411d7bc76c500ade010009cd5c626bba91eb652 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 01:36:47 +0000 Subject: [PATCH 079/482] fix(deps): update ai sdk --- apps/server/package.json | 4 ++-- pnpm-lock.yaml | 28 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/apps/server/package.json b/apps/server/package.json index ab31391524..1570db2e0c 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -31,10 +31,10 @@ }, "dependencies": { "@ai-sdk/anthropic": "3.0.68", - "@ai-sdk/google": "3.0.60", + "@ai-sdk/google": "3.0.61", "@ai-sdk/openai": "3.0.52", "@modelcontextprotocol/sdk": "^1.12.1", - "ai": "6.0.154", + "ai": "6.0.156", "better-sqlite3": "12.8.0", "html-to-text": "9.0.5", "js-yaml": "4.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bf50a09222..5ed19204ca 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -572,8 +572,8 @@ importers: specifier: 3.0.68 version: 3.0.68(zod@4.3.6) '@ai-sdk/google': - specifier: 3.0.60 - version: 3.0.60(zod@4.3.6) + specifier: 3.0.61 + version: 3.0.61(zod@4.3.6) '@ai-sdk/openai': specifier: 3.0.52 version: 3.0.52(zod@4.3.6) @@ -581,8 +581,8 @@ importers: specifier: ^1.12.1 version: 1.29.0(zod@4.3.6) ai: - specifier: 6.0.154 - version: 6.0.154(zod@4.3.6) + specifier: 6.0.156 + version: 6.0.156(zod@4.3.6) better-sqlite3: specifier: 12.8.0 version: 12.8.0 @@ -1479,14 +1479,14 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/gateway@3.0.94': - resolution: {integrity: sha512-uDDwLZhCkvC89crVS3S90D5L7AcVN8WriGuYVNYgVAaVcvy3Mthy3R9ICfzG75BObhz6pm2FWnhxDfNRK+t69Q==} + '@ai-sdk/gateway@3.0.95': + resolution: {integrity: sha512-ZmUNNbZl3V42xwQzPaNUi+s8eqR2lnrxf0bvB6YbLXpLjHYv0k2Y78t12cNOfY0bxGeuVVTLyk856uLuQIuXEQ==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/google@3.0.60': - resolution: {integrity: sha512-ye/hG0LeO24VmjLbfgkFZV8V8k/l4nVBODutpJQkFPyUiGOCbFtFUTgxSeC7+njrk5+HhgyHrzJay4zmhwMH+w==} + '@ai-sdk/google@3.0.61': + resolution: {integrity: sha512-jEKU1Mjcy5CoicejdJQIzM0ntYwyXR8vtYgAZYriKaOuLAiAhiiU538++fGU3CC9HJH/mL1OfsCwMM3gFiCNsw==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 @@ -6630,8 +6630,8 @@ packages: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} - ai@6.0.154: - resolution: {integrity: sha512-HfKJKCTJsDZxqrIUDSVnBQ7DpQlx5WI4ExqtLd7Bl70epLmvkpc/HYMzU1hP9W+g9VEAcvZo4fbMqc3v5D+9gQ==} + ai@6.0.156: + resolution: {integrity: sha512-uyi/5LYbugHQxZsR2PeAFOZEL4WqKkzZw4pv0nQvvdgxgVOsM7snOmGrYkp5fShxH/vnd08SXvHCVTX7oUW7xQ==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 @@ -14107,14 +14107,14 @@ snapshots: '@ai-sdk/provider-utils': 4.0.23(zod@4.3.6) zod: 4.3.6 - '@ai-sdk/gateway@3.0.94(zod@4.3.6)': + '@ai-sdk/gateway@3.0.95(zod@4.3.6)': dependencies: '@ai-sdk/provider': 3.0.8 '@ai-sdk/provider-utils': 4.0.23(zod@4.3.6) '@vercel/oidc': 3.1.0 zod: 4.3.6 - '@ai-sdk/google@3.0.60(zod@4.3.6)': + '@ai-sdk/google@3.0.61(zod@4.3.6)': dependencies: '@ai-sdk/provider': 3.0.8 '@ai-sdk/provider-utils': 4.0.23(zod@4.3.6) @@ -21322,9 +21322,9 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 - ai@6.0.154(zod@4.3.6): + ai@6.0.156(zod@4.3.6): dependencies: - '@ai-sdk/gateway': 3.0.94(zod@4.3.6) + '@ai-sdk/gateway': 3.0.95(zod@4.3.6) '@ai-sdk/provider': 3.0.8 '@ai-sdk/provider-utils': 4.0.23(zod@4.3.6) '@opentelemetry/api': 1.9.0 From c1596d2a2532d6ffb924b610d55f3a76f7055191 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 01:37:28 +0000 Subject: [PATCH 080/482] chore(deps): update ckeditor5 config packages to v14.1.0 --- pnpm-lock.yaml | 374 ++++++++++--------------------------------------- 1 file changed, 71 insertions(+), 303 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bf50a09222..3119cab301 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -987,13 +987,13 @@ importers: version: 10.2.0(jiti@2.6.1) eslint-config-ckeditor5: specifier: '>=9.1.0' - version: 14.0.0(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) + version: 14.1.0(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) stylelint: specifier: 17.6.0 version: 17.6.0(typescript@6.0.2) stylelint-config-ckeditor5: specifier: '>=9.1.0' - version: 14.0.0(stylelint@17.6.0(typescript@6.0.2)) + version: 14.1.0(stylelint@17.6.0(typescript@6.0.2)) typescript: specifier: 6.0.2 version: 6.0.2 @@ -1032,13 +1032,13 @@ importers: version: 10.2.0(jiti@2.6.1) eslint-config-ckeditor5: specifier: '>=9.1.0' - version: 14.0.0(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) + version: 14.1.0(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) stylelint: specifier: 17.6.0 version: 17.6.0(typescript@6.0.2) stylelint-config-ckeditor5: specifier: '>=9.1.0' - version: 14.0.0(stylelint@17.6.0(typescript@6.0.2)) + version: 14.1.0(stylelint@17.6.0(typescript@6.0.2)) typescript: specifier: 6.0.2 version: 6.0.2 @@ -1077,13 +1077,13 @@ importers: version: 10.2.0(jiti@2.6.1) eslint-config-ckeditor5: specifier: '>=9.1.0' - version: 14.0.0(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) + version: 14.1.0(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) stylelint: specifier: 17.6.0 version: 17.6.0(typescript@6.0.2) stylelint-config-ckeditor5: specifier: '>=9.1.0' - version: 14.0.0(stylelint@17.6.0(typescript@6.0.2)) + version: 14.1.0(stylelint@17.6.0(typescript@6.0.2)) typescript: specifier: 6.0.2 version: 6.0.2 @@ -1129,13 +1129,13 @@ importers: version: 10.2.0(jiti@2.6.1) eslint-config-ckeditor5: specifier: '>=9.1.0' - version: 14.0.0(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) + version: 14.1.0(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) stylelint: specifier: 17.6.0 version: 17.6.0(typescript@6.0.2) stylelint-config-ckeditor5: specifier: '>=9.1.0' - version: 14.0.0(stylelint@17.6.0(typescript@6.0.2)) + version: 14.1.0(stylelint@17.6.0(typescript@6.0.2)) typescript: specifier: 6.0.2 version: 6.0.2 @@ -1174,13 +1174,13 @@ importers: version: 10.2.0(jiti@2.6.1) eslint-config-ckeditor5: specifier: '>=9.1.0' - version: 14.0.0(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) + version: 14.1.0(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) stylelint: specifier: 17.6.0 version: 17.6.0(typescript@6.0.2) stylelint-config-ckeditor5: specifier: '>=9.1.0' - version: 14.0.0(stylelint@17.6.0(typescript@6.0.2)) + version: 14.1.0(stylelint@17.6.0(typescript@6.0.2)) typescript: specifier: 6.0.2 version: 6.0.2 @@ -3680,8 +3680,8 @@ packages: '@mapbox/point-geometry@0.1.0': resolution: {integrity: sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==} - '@mapbox/tiny-sdf@2.0.7': - resolution: {integrity: sha512-25gQLQMcpivjOSA40g3gO6qgiFPDpWRoMfd+G/GoppPIeP6JDaMMkMrEJnMZhKyyS6iKwVt5YKu02vCUyJM3Ug==} + '@mapbox/tiny-sdf@2.1.0': + resolution: {integrity: sha512-uFJhNh36BR4OCuWIEiWaEix9CA2WzT6CAIcqVjWYpnx8+QDtS+oC4QehRrx5cX4mgWs37MmKnwUejeHxVymzNg==} '@mapbox/unitbezier@0.0.1': resolution: {integrity: sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==} @@ -5362,8 +5362,8 @@ packages: '@types/debounce@1.2.4': resolution: {integrity: sha512-jBqiORIzKDOToaF63Fm//haOCHuwQuLa2202RK4MozpA6lh93eCBc+/8+wZn5OzjJt3ySdc+74SXWXB55Ewtyw==} - '@types/debug@4.1.12': - resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + '@types/debug@4.1.13': + resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} @@ -5628,14 +5628,6 @@ packages: '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@typescript-eslint/eslint-plugin@8.57.1': - resolution: {integrity: sha512-Gn3aqnvNl4NGc6x3/Bqk1AOn0thyTU9bqDRhiRnUWezgvr2OnhYCWCgC8zXXRVqBsIL1pSDt7T9nJUe0oM0kDQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/parser': ^8.57.1 - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/eslint-plugin@8.58.1': resolution: {integrity: sha512-eSkwoemjo76bdXl2MYqtxg51HNwUSkWfODUOQ3PaTLZGh9uIWWFZIjyjaJnex7wXDu+TRx+ATsnSxdN9YWfRTQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -5644,13 +5636,6 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.57.1': - resolution: {integrity: sha512-k4eNDan0EIMTT/dUKc/g+rsJ6wcHYhNPdY19VoX/EOtaAG8DLtKCykhrUnuHPYvinn5jhAPgD2Qw9hXBwrahsw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.58.1': resolution: {integrity: sha512-gGkiNMPqerb2cJSVcruigx9eHBlLG14fSdPdqMoOcBfh+vvn4iCq2C8MzUB89PrxOXk0y3GZ1yIWb9aOzL93bw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -5658,61 +5643,22 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.57.1': - resolution: {integrity: sha512-vx1F37BRO1OftsYlmG9xay1TqnjNVlqALymwWVuYTdo18XuKxtBpCj1QlzNIEHlvlB27osvXFWptYiEWsVdYsg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/project-service@8.58.0': - resolution: {integrity: sha512-8Q/wBPWLQP1j16NxoPNIKpDZFMaxl7yWIoqXWYeWO+Bbd2mjgvoF0dxP2jKZg5+x49rgKdf7Ck473M8PC3V9lg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.58.1': resolution: {integrity: sha512-gfQ8fk6cxhtptek+/8ZIqw8YrRW5048Gug8Ts5IYcMLCw18iUgrZAEY/D7s4hkI0FxEfGakKuPK/XUMPzPxi5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.57.1': - resolution: {integrity: sha512-hs/QcpCwlwT2L5S+3fT6gp0PabyGk4Q0Rv2doJXA0435/OpnSR3VRgvrp8Xdoc3UAYSg9cyUjTeFXZEPg/3OKg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/scope-manager@8.58.0': - resolution: {integrity: sha512-W1Lur1oF50FxSnNdGp3Vs6P+yBRSmZiw4IIjEeYxd8UQJwhUF0gDgDD/W/Tgmh73mxgEU3qX0Bzdl/NGuSPEpQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/scope-manager@8.58.1': resolution: {integrity: sha512-TPYUEqJK6avLcEjumWsIuTpuYODTTDAtoMdt8ZZa93uWMTX13Nb8L5leSje1NluammvU+oI3QRr5lLXPgihX3w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.57.1': - resolution: {integrity: sha512-0lgOZB8cl19fHO4eI46YUx2EceQqhgkPSuCGLlGi79L2jwYY1cxeYc1Nae8Aw1xjgW3PKVDLlr3YJ6Bxx8HkWg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/tsconfig-utils@8.58.0': - resolution: {integrity: sha512-doNSZEVJsWEu4htiVC+PR6NpM+pa+a4ClH9INRWOWCUzMst/VA9c4gXq92F8GUD1rwhNvRLkgjfYtFXegXQF7A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/tsconfig-utils@8.58.1': resolution: {integrity: sha512-JAr2hOIct2Q+qk3G+8YFfqkqi7sC86uNryT+2i5HzMa2MPjw4qNFvtjnw1IiA1rP7QhNKVe21mSSLaSjwA1Olw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.57.1': - resolution: {integrity: sha512-+Bwwm0ScukFdyoJsh2u6pp4S9ktegF98pYUU0hkphOOqdMB+1sNQhIz8y5E9+4pOioZijrkfNO/HUJVAFFfPKA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.58.1': resolution: {integrity: sha512-HUFxvTJVroT+0rXVJC7eD5zol6ID+Sn5npVPWoFuHGg9Ncq5Q4EYstqR+UOqaNRFXi5TYkpXXkLhoCHe3G0+7w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -5720,50 +5666,16 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.57.1': - resolution: {integrity: sha512-S29BOBPJSFUiblEl6RzPPjJt6w25A6XsBqRVDt53tA/tlL8q7ceQNZHTjPeONt/3S7KRI4quk+yP9jK2WjBiPQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/types@8.58.0': - resolution: {integrity: sha512-O9CjxypDT89fbHxRfETNoAnHj/i6IpRK0CvbVN3qibxlLdo5p5hcLmUuCCrHMpxiWSwKyI8mCP7qRNYuOJ0Uww==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.58.1': resolution: {integrity: sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.57.1': - resolution: {integrity: sha512-ybe2hS9G6pXpqGtPli9Gx9quNV0TWLOmh58ADlmZe9DguLq0tiAKVjirSbtM1szG6+QH6rVXyU6GTLQbWnMY+g==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/typescript-estree@8.58.0': - resolution: {integrity: sha512-7vv5UWbHqew/dvs+D3e1RvLv1v2eeZ9txRHPnEEBUgSNLx5ghdzjHa0sgLWYVKssH+lYmV0JaWdoubo0ncGYLA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/typescript-estree@8.58.1': resolution: {integrity: sha512-w4w7WR7GHOjqqPnvAYbazq+Y5oS68b9CzasGtnd6jIeOIeKUzYzupGTB2T4LTPSv4d+WPeccbxuneTFHYgAAWg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.57.1': - resolution: {integrity: sha512-XUNSJ/lEVFttPMMoDVA2r2bwrl8/oPx8cURtczkSEswY5T3AeLmCy+EKWQNdL4u0MmAHOjcWrqJp2cdvgjn8dQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/utils@8.58.0': - resolution: {integrity: sha512-RfeSqcFeHMHlAWzt4TBjWOAtoW9lnsAGiP3GbaX9uVgTYYrMbVnGONEfUCiSss+xMHFl+eHZiipmA8WkQ7FuNA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.58.1': resolution: {integrity: sha512-Ln8R0tmWC7pTtLOzgJzYTXSCjJ9rDNHAqTaVONF4FEi2qwce8mD9iSOxOpLFFvWp/wBFlew0mjM1L1ihYWfBdQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -5771,14 +5683,6 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.57.1': - resolution: {integrity: sha512-YWnmJkXbofiz9KbnbbwuA2rpGkFPLbAIetcCNO6mJ8gdhdZ/v7WDXsoGFAJuM6ikUFKTlSQnjWnVO4ux+UzS6A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/visitor-keys@8.58.0': - resolution: {integrity: sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/visitor-keys@8.58.1': resolution: {integrity: sha512-y+vH7QE8ycjoa0bWciFg7OpFcipUuem1ujhrdLtq1gByKwfbC7bPeKsiny9e0urg93DqwGcHey+bGRKCnF1nZQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -8365,8 +8269,8 @@ packages: engines: {node: '>=6.0'} hasBin: true - eslint-config-ckeditor5@14.0.0: - resolution: {integrity: sha512-MM/1u0PAFMWD878H3NZ5oSNppWrwOO4WuWyFFr1oyEKtnMT/3q9JK47XeHm2IKoq9SIaQFcI47cmQIffxnXKGg==} + eslint-config-ckeditor5@14.1.0: + resolution: {integrity: sha512-mDDu0YB/GnoIXbXKCldUaEsC+Z/5lZVrHetEvpP8MI0zuWChbNBrPIokeQ829Yz7uSF7PEk8bFPXktwAK2ccQA==} engines: {node: '>=24.11.0'} peerDependencies: eslint: ^9.0.0 @@ -8386,8 +8290,8 @@ packages: eslint-linter-browserify@10.2.0: resolution: {integrity: sha512-3EI7WAce/YTRTyRmqYUKX7VRROyIoKacg3625Ler+079JvCU5YGQwVJLa/ifvBxr95bxv7gTsy4zw3is+hHpBg==} - eslint-plugin-ckeditor5-rules@14.0.0: - resolution: {integrity: sha512-TLdFs+qhiEzVO4LQgVrJmc/49ZQ62qKq0fx+M+231tzGXSqioRV6LpRLHvF7XxEuG3+3LblMUJTLM+pBm5fXMg==} + eslint-plugin-ckeditor5-rules@14.1.0: + resolution: {integrity: sha512-ssewEesRNL0MVfNTraM7l8xtTfBKmlNIjK0kCXsiJgLanmoRn0CZ1LEepICZifNx2eKzCf5tF+6phYVleh88PA==} engines: {node: '>=24.11.0'} eslint-plugin-compat@6.0.2: @@ -9092,8 +8996,8 @@ packages: grapheme-splitter@1.0.4: resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} - graphql@16.13.1: - resolution: {integrity: sha512-gGgrVCoDKlIZ8fIqXBBb0pPKqDgki0Z/FSKNiQzSGj2uEYHr1tq5wmBegGwJx6QB5S5cM0khSBpi/JFHMCvsmQ==} + graphql@16.13.2: + resolution: {integrity: sha512-5bJ+nf/UCpAjHM8i06fl7eLyVC9iuNAjm9qzkiu2ZGhM0VscSvS6WDPfAwkdkBuoXGM9FJSbKl6wylMwP9Ktig==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} growly@1.3.0: @@ -10665,6 +10569,10 @@ packages: resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} engines: {node: '>= 8'} + minipass-flush@1.0.7: + resolution: {integrity: sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==} + engines: {node: '>= 8'} + minipass-pipeline@1.2.4: resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} engines: {node: '>=8'} @@ -11516,6 +11424,10 @@ packages: resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} engines: {node: ^10 || ^12 || >=14} + postcss@8.5.9: + resolution: {integrity: sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==} + engines: {node: ^10 || ^12 || >=14} + postject@1.0.0-alpha.6: resolution: {integrity: sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==} engines: {node: '>=14.0.0'} @@ -11615,8 +11527,8 @@ packages: resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==} engines: {node: '>=12.0.0'} - protocol-buffers-schema@3.6.0: - resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==} + protocol-buffers-schema@3.6.1: + resolution: {integrity: sha512-VG2K63Igkiv9p76tk1lilczEK1cT+kCjKtkdhw1dQZV3k3IXJbd3o6Ho8b9zJZaHSnT2hKe4I+ObmX9w6m5SmQ==} proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} @@ -12834,8 +12746,8 @@ packages: react-dom: optional: true - stylelint-config-ckeditor5@14.0.0: - resolution: {integrity: sha512-RrT7Zc2siW6bvbG22Svfi3/tcqhTCuxeJ0BgwCpD67bDTmysK7mdM422FrrF03HVa35RJ78aeHsSWqQxQE+KQA==} + stylelint-config-ckeditor5@14.1.0: + resolution: {integrity: sha512-/fGcg0+G9WrsaQoFYQdd+4cYmbE6TqB8xWQOJOv5v/AeThdYPAqQmnsks2SlFD8ulCInVn7r7shz8KeOG8hpMA==} engines: {node: '>=24.11.0'} peerDependencies: stylelint: '>=16.0.0' @@ -12846,8 +12758,8 @@ packages: peerDependencies: stylelint: ^16.16.0 - stylelint-plugin-ckeditor5-rules@14.0.0: - resolution: {integrity: sha512-Hiv4qbntPHf/MDXMk6MpWJOiQfsgwl6W5Ema74DyydJfxKd3IaEL3fFZmGAe0EOT+vrC8i2cVOdgMg/+1jqjGA==} + stylelint-plugin-ckeditor5-rules@14.1.0: + resolution: {integrity: sha512-Y0rm/5rf0VCbp5o4aLGboclVnBj4E6nIHHcIG8ji9BPC+bh+K9KMxjlbN3bl6wRN7RpHqpEEiWaPGmBPY5jIkw==} engines: {node: '>=24.11.0'} peerDependencies: stylelint: '>=16.0.0' @@ -12944,6 +12856,10 @@ packages: resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} + tapable@2.3.2: + resolution: {integrity: sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==} + engines: {node: '>=6'} + tar-fs@3.1.1: resolution: {integrity: sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==} @@ -13212,13 +13128,6 @@ packages: peerDependencies: typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x || 6.0.x - typescript-eslint@8.57.1: - resolution: {integrity: sha512-fLvZWf+cAGw3tqMCYzGIU6yR8K+Y9NT2z23RwOjlNFF2HwSB3KhdEFI5lSBv8tNmFkkBShSjsCjzx1vahZfISA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' - typescript-eslint@8.58.1: resolution: {integrity: sha512-gf6/oHChByg9HJvhMO1iBexJh12AqqTfnuxscMDOVqfJW3htsdRJI/GfPpHTTcyeB8cSTUY2JcZmVgoyPqcrDg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -16021,7 +15930,7 @@ snapshots: '@es-joy/jsdoccomment@0.50.2': dependencies: '@types/estree': 1.0.8 - '@typescript-eslint/types': 8.58.0 + '@typescript-eslint/types': 8.58.1 comment-parser: 1.4.1 esquery: 1.7.0 jsdoc-type-pratt-parser: 4.1.0 @@ -17266,7 +17175,7 @@ snapshots: '@mapbox/point-geometry@0.1.0': {} - '@mapbox/tiny-sdf@2.0.7': {} + '@mapbox/tiny-sdf@2.1.0': {} '@mapbox/unitbezier@0.0.1': {} @@ -18743,7 +18652,7 @@ snapshots: '@stylistic/eslint-plugin@4.4.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2)': dependencies: - '@typescript-eslint/utils': 8.58.0(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) + '@typescript-eslint/utils': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) eslint: 10.2.0(jiti@2.6.1) eslint-visitor-keys: 4.2.1 espree: 10.4.0 @@ -18759,7 +18668,7 @@ snapshots: '@csstools/css-tokenizer': 3.0.4 '@csstools/media-query-list-parser': 3.0.1(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) is-plain-object: 5.0.0 - postcss: 8.5.8 + postcss: 8.5.9 postcss-selector-parser: 6.1.2 postcss-value-parser: 4.2.0 style-search: 0.1.0 @@ -18977,7 +18886,7 @@ snapshots: '@types/debounce@1.2.4': {} - '@types/debug@4.1.12': + '@types/debug@4.1.13': dependencies: '@types/ms': 2.1.0 @@ -19272,22 +19181,6 @@ snapshots: '@types/node': 24.12.2 optional: true - '@typescript-eslint/eslint-plugin@8.57.1(@typescript-eslint/parser@8.57.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2))(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2)': - dependencies: - '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.57.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) - '@typescript-eslint/scope-manager': 8.57.1 - '@typescript-eslint/type-utils': 8.57.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) - '@typescript-eslint/utils': 8.57.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) - '@typescript-eslint/visitor-keys': 8.57.1 - eslint: 10.2.0(jiti@2.6.1) - ignore: 7.0.5 - natural-compare: 1.4.0 - ts-api-utils: 2.5.0(typescript@6.0.2) - typescript: 6.0.2 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/eslint-plugin@8.58.1(@typescript-eslint/parser@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2))(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2)': dependencies: '@eslint-community/regexpp': 4.12.2 @@ -19304,18 +19197,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.57.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2)': - dependencies: - '@typescript-eslint/scope-manager': 8.57.1 - '@typescript-eslint/types': 8.57.1 - '@typescript-eslint/typescript-estree': 8.57.1(typescript@6.0.2) - '@typescript-eslint/visitor-keys': 8.57.1 - debug: 4.4.3 - eslint: 10.2.0(jiti@2.6.1) - typescript: 6.0.2 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/parser@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2)': dependencies: '@typescript-eslint/scope-manager': 8.58.1 @@ -19328,24 +19209,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.57.1(typescript@6.0.2)': - dependencies: - '@typescript-eslint/tsconfig-utils': 8.58.0(typescript@6.0.2) - '@typescript-eslint/types': 8.58.0 - debug: 4.4.3 - typescript: 6.0.2 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/project-service@8.58.0(typescript@6.0.2)': - dependencies: - '@typescript-eslint/tsconfig-utils': 8.58.0(typescript@6.0.2) - '@typescript-eslint/types': 8.58.0 - debug: 4.4.3 - typescript: 6.0.2 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/project-service@8.58.1(typescript@6.0.2)': dependencies: '@typescript-eslint/tsconfig-utils': 8.58.1(typescript@6.0.2) @@ -19355,45 +19218,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.57.1': - dependencies: - '@typescript-eslint/types': 8.57.1 - '@typescript-eslint/visitor-keys': 8.57.1 - - '@typescript-eslint/scope-manager@8.58.0': - dependencies: - '@typescript-eslint/types': 8.58.0 - '@typescript-eslint/visitor-keys': 8.58.0 - '@typescript-eslint/scope-manager@8.58.1': dependencies: '@typescript-eslint/types': 8.58.1 '@typescript-eslint/visitor-keys': 8.58.1 - '@typescript-eslint/tsconfig-utils@8.57.1(typescript@6.0.2)': - dependencies: - typescript: 6.0.2 - - '@typescript-eslint/tsconfig-utils@8.58.0(typescript@6.0.2)': - dependencies: - typescript: 6.0.2 - '@typescript-eslint/tsconfig-utils@8.58.1(typescript@6.0.2)': dependencies: typescript: 6.0.2 - '@typescript-eslint/type-utils@8.57.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2)': - dependencies: - '@typescript-eslint/types': 8.57.1 - '@typescript-eslint/typescript-estree': 8.57.1(typescript@6.0.2) - '@typescript-eslint/utils': 8.57.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) - debug: 4.4.3 - eslint: 10.2.0(jiti@2.6.1) - ts-api-utils: 2.5.0(typescript@6.0.2) - typescript: 6.0.2 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/type-utils@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2)': dependencies: '@typescript-eslint/types': 8.58.1 @@ -19406,42 +19239,8 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.57.1': {} - - '@typescript-eslint/types@8.58.0': {} - '@typescript-eslint/types@8.58.1': {} - '@typescript-eslint/typescript-estree@8.57.1(typescript@6.0.2)': - dependencies: - '@typescript-eslint/project-service': 8.57.1(typescript@6.0.2) - '@typescript-eslint/tsconfig-utils': 8.57.1(typescript@6.0.2) - '@typescript-eslint/types': 8.57.1 - '@typescript-eslint/visitor-keys': 8.57.1 - debug: 4.4.3 - minimatch: 10.2.4 - semver: 7.7.4 - tinyglobby: 0.2.15 - ts-api-utils: 2.5.0(typescript@6.0.2) - typescript: 6.0.2 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/typescript-estree@8.58.0(typescript@6.0.2)': - dependencies: - '@typescript-eslint/project-service': 8.58.0(typescript@6.0.2) - '@typescript-eslint/tsconfig-utils': 8.58.0(typescript@6.0.2) - '@typescript-eslint/types': 8.58.0 - '@typescript-eslint/visitor-keys': 8.58.0 - debug: 4.4.3 - minimatch: 10.2.4 - semver: 7.7.4 - tinyglobby: 0.2.15 - ts-api-utils: 2.5.0(typescript@6.0.2) - typescript: 6.0.2 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/typescript-estree@8.58.1(typescript@6.0.2)': dependencies: '@typescript-eslint/project-service': 8.58.1(typescript@6.0.2) @@ -19457,28 +19256,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.57.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2)': - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.6.1)) - '@typescript-eslint/scope-manager': 8.57.1 - '@typescript-eslint/types': 8.57.1 - '@typescript-eslint/typescript-estree': 8.57.1(typescript@6.0.2) - eslint: 10.2.0(jiti@2.6.1) - typescript: 6.0.2 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@8.58.0(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2)': - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.6.1)) - '@typescript-eslint/scope-manager': 8.58.0 - '@typescript-eslint/types': 8.58.0 - '@typescript-eslint/typescript-estree': 8.58.0(typescript@6.0.2) - eslint: 10.2.0(jiti@2.6.1) - typescript: 6.0.2 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/utils@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2)': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.6.1)) @@ -19490,16 +19267,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.57.1': - dependencies: - '@typescript-eslint/types': 8.57.1 - eslint-visitor-keys: 5.0.1 - - '@typescript-eslint/visitor-keys@8.58.0': - dependencies: - '@typescript-eslint/types': 8.58.0 - eslint-visitor-keys: 5.0.1 - '@typescript-eslint/visitor-keys@8.58.1': dependencies: '@typescript-eslint/types': 8.58.1 @@ -21853,7 +21620,7 @@ snapshots: lru-cache: 7.18.3 minipass: 3.3.6 minipass-collect: 1.0.2 - minipass-flush: 1.0.5 + minipass-flush: 1.0.7 minipass-pipeline: 1.2.4 mkdirp: 1.0.4 p-map: 4.0.0 @@ -23226,7 +22993,7 @@ snapshots: enhanced-resolve@5.20.1: dependencies: graceful-fs: 4.2.11 - tapable: 2.3.0 + tapable: 2.3.2 entities@2.2.0: {} @@ -23527,17 +23294,17 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-config-ckeditor5@14.0.0(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2): + eslint-config-ckeditor5@14.1.0(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2): dependencies: '@eslint/js': 9.39.4 '@eslint/markdown': 6.6.0 '@stylistic/eslint-plugin': 4.4.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) eslint: 10.2.0(jiti@2.6.1) - eslint-plugin-ckeditor5-rules: 14.0.0 + eslint-plugin-ckeditor5-rules: 14.1.0 eslint-plugin-mocha: 11.2.0(eslint@10.2.0(jiti@2.6.1)) globals: 16.5.0 typescript: 6.0.2 - typescript-eslint: 8.57.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) + typescript-eslint: 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) transitivePeerDependencies: - supports-color @@ -23562,7 +23329,7 @@ snapshots: eslint-linter-browserify@10.2.0: {} - eslint-plugin-ckeditor5-rules@14.0.0: + eslint-plugin-ckeditor5-rules@14.1.0: dependencies: '@es-joy/jsdoccomment': 0.50.2 enhanced-resolve: 5.20.1 @@ -24424,7 +24191,7 @@ snapshots: grapheme-splitter@1.0.4: {} - graphql@16.13.1: + graphql@16.13.2: optional: true growly@1.3.0: {} @@ -25731,7 +25498,7 @@ snapshots: minipass: 3.3.6 minipass-collect: 1.0.2 minipass-fetch: 2.1.2 - minipass-flush: 1.0.5 + minipass-flush: 1.0.7 minipass-pipeline: 1.2.4 negotiator: 0.6.4 promise-retry: 2.0.1 @@ -25785,7 +25552,7 @@ snapshots: '@mapbox/geojson-rewind': 0.5.2 '@mapbox/jsonlint-lines-primitives': 2.0.2 '@mapbox/point-geometry': 0.1.0 - '@mapbox/tiny-sdf': 2.0.7 + '@mapbox/tiny-sdf': 2.1.0 '@mapbox/unitbezier': 0.0.1 '@mapbox/vector-tile': 1.3.1 '@mapbox/whoots-js': 3.1.0 @@ -26201,7 +25968,7 @@ snapshots: micromark@4.0.2: dependencies: - '@types/debug': 4.1.12 + '@types/debug': 4.1.13 debug: 4.4.3 decode-named-character-reference: 1.3.0 devlop: 1.1.0 @@ -26309,6 +26076,10 @@ snapshots: dependencies: minipass: 3.3.6 + minipass-flush@1.0.7: + dependencies: + minipass: 3.3.6 + minipass-pipeline@1.2.4: dependencies: minipass: 3.3.6 @@ -26397,7 +26168,7 @@ snapshots: '@open-draft/until': 2.1.0 '@types/cookie': 0.6.0 '@types/statuses': 2.0.6 - graphql: 16.13.1 + graphql: 16.13.2 headers-polyfill: 4.0.3 is-node-process: 1.2.0 outvariant: 1.4.3 @@ -27214,6 +26985,12 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + postcss@8.5.9: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + postject@1.0.0-alpha.6: dependencies: commander: 9.5.0 @@ -27310,7 +27087,7 @@ snapshots: '@types/node': 24.12.2 long: 5.3.2 - protocol-buffers-schema@3.6.0: {} + protocol-buffers-schema@3.6.1: {} proxy-addr@2.0.7: dependencies: @@ -27790,7 +27567,7 @@ snapshots: resolve-protobuf-schema@2.1.0: dependencies: - protocol-buffers-schema: 3.6.0 + protocol-buffers-schema: 3.6.1 resolve.exports@2.0.3: {} @@ -28743,18 +28520,18 @@ snapshots: optionalDependencies: react-dom: 19.2.4(react@19.2.4) - stylelint-config-ckeditor5@14.0.0(stylelint@17.6.0(typescript@6.0.2)): + stylelint-config-ckeditor5@14.1.0(stylelint@17.6.0(typescript@6.0.2)): dependencies: '@stylistic/stylelint-plugin': 3.1.3(stylelint@17.6.0(typescript@6.0.2)) stylelint: 17.6.0(typescript@6.0.2) stylelint-config-recommended: 16.0.0(stylelint@17.6.0(typescript@6.0.2)) - stylelint-plugin-ckeditor5-rules: 14.0.0(stylelint@17.6.0(typescript@6.0.2)) + stylelint-plugin-ckeditor5-rules: 14.1.0(stylelint@17.6.0(typescript@6.0.2)) stylelint-config-recommended@16.0.0(stylelint@17.6.0(typescript@6.0.2)): dependencies: stylelint: 17.6.0(typescript@6.0.2) - stylelint-plugin-ckeditor5-rules@14.0.0(stylelint@17.6.0(typescript@6.0.2)): + stylelint-plugin-ckeditor5-rules@14.1.0(stylelint@17.6.0(typescript@6.0.2)): dependencies: stylelint: 17.6.0(typescript@6.0.2) @@ -28920,6 +28697,8 @@ snapshots: tapable@2.3.0: {} + tapable@2.3.2: {} + tar-fs@3.1.1: dependencies: pump: 3.0.3 @@ -29219,17 +28998,6 @@ snapshots: typescript: 6.0.2 yaml: 2.8.3 - typescript-eslint@8.57.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2): - dependencies: - '@typescript-eslint/eslint-plugin': 8.57.1(@typescript-eslint/parser@8.57.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2))(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) - '@typescript-eslint/parser': 8.57.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) - '@typescript-eslint/typescript-estree': 8.57.1(typescript@6.0.2) - '@typescript-eslint/utils': 8.57.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) - eslint: 10.2.0(jiti@2.6.1) - typescript: 6.0.2 - transitivePeerDependencies: - - supports-color - typescript-eslint@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2): dependencies: '@typescript-eslint/eslint-plugin': 8.58.1(@typescript-eslint/parser@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2))(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) From 7e30b8c02939610becbe869e412dce92bf7eb79e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 01:37:35 +0000 Subject: [PATCH 081/482] chore(deps): update actions/github-script action to v9 --- .github/actions/deploy-to-cloudflare-pages/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/deploy-to-cloudflare-pages/action.yml b/.github/actions/deploy-to-cloudflare-pages/action.yml index 4f7a4a177a..a3a22f9fef 100644 --- a/.github/actions/deploy-to-cloudflare-pages/action.yml +++ b/.github/actions/deploy-to-cloudflare-pages/action.yml @@ -55,7 +55,7 @@ runs: # Post deployment URL as PR comment - name: Comment PR with Preview URL if: github.event_name == 'pull_request' - uses: actions/github-script@v8 + uses: actions/github-script@v9 env: COMMENT_BODY: ${{ inputs.comment_body }} PRODUCTION_URL: ${{ inputs.production_url }} From b67bd018584e7f2e654f21e6663ca2b3564948da Mon Sep 17 00:00:00 2001 From: noobhjy Date: Sun, 12 Apr 2026 10:52:56 +0200 Subject: [PATCH 082/482] Translated using Weblate (Chinese (Simplified Han script)) Currently translated at 97.5% (1818 of 1864 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/ --- apps/client/src/translations/cn/translation.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/client/src/translations/cn/translation.json b/apps/client/src/translations/cn/translation.json index 6d2b66ebd3..4a95006b9c 100644 --- a/apps/client/src/translations/cn/translation.json +++ b/apps/client/src/translations/cn/translation.json @@ -95,7 +95,8 @@ "notes_to_be_deleted": "将删除以下笔记 ({{notesCount}})", "no_note_to_delete": "没有笔记将被删除(仅克隆)。", "broken_relations_to_be_deleted": "将删除以下关系并断开连接 ({{ relationCount}})", - "cancel": "取消" + "cancel": "取消", + "title": "删除笔记" }, "export": { "export_note_title": "导出笔记", From 224c31d16b57b1d9b12dea887f99db973dea8e92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aindri=C3=BA=20Mac=20Giolla=20Eoin?= Date: Sun, 12 Apr 2026 14:26:12 +0200 Subject: [PATCH 083/482] Translated using Weblate (Irish) Currently translated at 100.0% (402 of 402 strings) Translation: Trilium Notes/Server Translate-URL: https://hosted.weblate.org/projects/trilium/server/ga/ --- apps/server/src/assets/translations/ga/server.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/apps/server/src/assets/translations/ga/server.json b/apps/server/src/assets/translations/ga/server.json index c03d9fad11..00e9c2ef9f 100644 --- a/apps/server/src/assets/translations/ga/server.json +++ b/apps/server/src/assets/translations/ga/server.json @@ -445,5 +445,18 @@ }, "desktop": { "instance_already_running": "Tá sampla ag rith cheana féin, agus tá fócas á chur ar an sampla sin ina ionad." + }, + "script": { + "wrong-environment": "Ní féidir an nóta \"{{- noteTitle}}\" ({{- noteId}}) a fhorghníomhú. Is script {{- actualEnv}} é seo, ach rinneadh iarracht é a fhorghníomhú sa {{- expectedEnv}}." + }, + "search": { + "error": { + "in-context": "Earráid i {{- context}}: {{- message}}", + "reserved-keyword": "Is eochairfhocal curtha in áirithe é \"{{- token}}\". Chun luach liteartha a chuardach, bain úsáid as comharthaí athfhriotail: \"{{- token}}\"", + "cannot-compare-with": "ní féidir comparáid a dhéanamh le \"{{- token}}\". Chun luach liteartha a chuardach, bain úsáid as comharthaí athfhriotail: \"{{- token}}\"", + "misplaced-expression": "Slonn mí-áitithe nó neamhiomlán \"{{- token}}\"", + "fulltext-after-expression": "Ní abairt bhailí í \"{{- token}}\". Chun téacs a chuardach, cuir é roimh scagairí tréithe (m.sh., \"{{- token}} #label\" in ionad \"#label {{- token}}\").", + "unrecognized-expression": "Sloinneadh neamhaitheanta \"{{- token}}\"" + } } } From d41d7279509c197ca9c89a17d25704ad8d1c7f56 Mon Sep 17 00:00:00 2001 From: green Date: Sun, 12 Apr 2026 04:48:01 +0200 Subject: [PATCH 084/482] Translated using Weblate (Japanese) Currently translated at 99.9% (1863 of 1864 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/ --- .../src/translations/ja/translation.json | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/apps/client/src/translations/ja/translation.json b/apps/client/src/translations/ja/translation.json index e808ec0118..8a6e83c721 100644 --- a/apps/client/src/translations/ja/translation.json +++ b/apps/client/src/translations/ja/translation.json @@ -106,13 +106,21 @@ }, "delete_notes": { "delete_all_clones_description": "すべてのクローンも削除(最近の変更では元に戻すことができる)", - "erase_notes_description": "通常の(ソフト)削除では、ノートは削除されたものとしてマークされ、一定期間内に(最近の変更で)削除を取り消すことができます。このオプションをオンにすると、ノートは即座に削除され、削除を取り消すことはできません。", + "erase_notes_description": "ノートを一時保存せずに完全に削除します。この操作は元に戻すことができず、アプリケーションが再読み込みされます。", "erase_notes_warning": "すべてのクローンを含め、ノートを完全に消去します(元に戻せません)。これにより、アプリケーションは強制的にリロードされます。", - "notes_to_be_deleted": "以下のノートが削除されます ({{notesCount}})", + "notes_to_be_deleted": "削除対象のノート ({{notesCount}})", "no_note_to_delete": "ノートは削除されません(クローンのみ)。", "cancel": "キャンセル", "close": "閉じる", - "broken_relations_to_be_deleted": "次のリレーション ({{relationCount}})は壊れているので消去されます" + "broken_relations_to_be_deleted": "壊れたリレーション ({{relationCount}})", + "title": "ノートを削除", + "clones_label": "クローン", + "delete_clones_description_other": "他の {{count}} 件のクローンも削除します。最近の変更履歴から元に戻すことができます。", + "erase_notes_label": "完全に消去", + "table_note_with_relation": "リレーションがあるノート", + "table_relation": "リレーション", + "table_points_to": "参照先 (削除済み)", + "delete": "削除" }, "calendar": { "mon": "月", @@ -809,7 +817,8 @@ "label_note": "ノート", "box_size_small": "スモール (~ 10 行)", "box_size_medium": "ミディアム (~ 30 行)", - "box_size_full": "フル (ボックスに全文が表示されます)" + "box_size_full": "フル (ボックスに全文が表示されます)", + "box_size_expandable": "展開可能 (デフォルトでは折りたたまれています)" }, "ancestor": { "placeholder": "ノート名で検索", @@ -1354,7 +1363,8 @@ "theme_none": "シンタックスハイライトなし", "theme_group_light": "ライトテーマ", "theme_group_dark": "ダークテーマ", - "copy_title": "クリップボードにコピー" + "copy_title": "クリップボードにコピー", + "click_to_copy": "クリックしてコピー" }, "editor": { "title": "エディター" @@ -2274,7 +2284,8 @@ "note_context_disabled": "クリックして現在のノートをコンテキストに含める", "no_provider_message": "AI プロバイダーが設定されていません。チャットを開始するには、プロバイダーを追加してください。", "add_provider": "AI プロバイダーを追加", - "sources_summary": "{{count}} 件のソースを {{sites}} サイトから取得" + "sources_summary": "{{count}} 件のソースを {{sites}} サイトから取得", + "stop": "停止" }, "sidebar_chat": { "title": "AI チャット", @@ -2338,7 +2349,11 @@ "web_search": "Web 検索", "note_in_parent": "", "get_attachment": "添付ファイルを取得", - "get_attachment_content": "添付ファイルの内容を読み取る" + "get_attachment_content": "添付ファイルの内容を読み取る", + "rename_note": "ノート名を変更", + "delete_note": "ノートを削除", + "move_note": "ノートを移動", + "clone_note": "ノートをクローン" } }, "ocr": { From 0150b5b61e39de17fc05ac8f2f4acc281d6635e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aindri=C3=BA=20Mac=20Giolla=20Eoin?= Date: Sun, 12 Apr 2026 14:51:00 +0200 Subject: [PATCH 085/482] Translated using Weblate (Irish) Currently translated at 99.9% (1863 of 1864 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/ga/ --- .../src/translations/ga/translation.json | 49 ++++++++++++++----- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/apps/client/src/translations/ga/translation.json b/apps/client/src/translations/ga/translation.json index 6854c3ff77..69819a83b2 100644 --- a/apps/client/src/translations/ga/translation.json +++ b/apps/client/src/translations/ga/translation.json @@ -121,12 +121,24 @@ "delete_notes": { "close": "Dún", "delete_all_clones_description": "Scrios gach clón freisin (is féidir é seo a chealú in athruithe le déanaí)", - "erase_notes_description": "Ní mharcálann scriosadh gnáth (bog) ach na nótaí mar scriosta agus is féidir iad a dhíscriosadh (sa dialóg athruithe le déanaí) laistigh de thréimhse ama. Scriosfar na nótaí láithreach má sheiceálann tú an rogha seo agus ní bheidh sé indéanta na nótaí a dhíscriosadh.", + "erase_notes_description": "Scrios nótaí láithreach in ionad scriosadh bog. Ní féidir é seo a chealú agus cuirfidh sé iallach ort an feidhmchlár a athlódáil.", "erase_notes_warning": "Scrios nótaí go buan (ní féidir é seo a chealú), lena n-áirítear na clónanna go léir. Cuirfidh sé seo iallach ar an bhfeidhmchlár athlódáil.", - "notes_to_be_deleted": "Scriosfar na nótaí seo a leanas ({{notesCount}})", + "notes_to_be_deleted": "Nótaí le scriosadh ({{notesCount}})", "no_note_to_delete": "Ní scriosfar aon nóta (clóin amháin).", - "broken_relations_to_be_deleted": "Brisfear agus scriosfar na caidrimh seo a leanas ({{ relationCount}})", - "cancel": "Cealaigh" + "broken_relations_to_be_deleted": "Caidrimh bhriste ({{relationCount}})", + "cancel": "Cealaigh", + "title": "Scrios nótaí", + "clones_label": "Clóin", + "delete_clones_description_one": "Scrios {{count}} clón eile freisin. Is féidir é seo a chealú sna hathruithe is déanaí.", + "delete_clones_description_two": "Scrios {{count}} clóin eile freisin. Is féidir é seo a chealú sna hathruithe is déanaí.", + "delete_clones_description_few": "Scrios {{count}} clóin eile freisin. Is féidir é seo a chealú sna hathruithe is déanaí.", + "delete_clones_description_many": "Scrios {{count}} clóin eile freisin. Is féidir é seo a chealú sna hathruithe is déanaí.", + "delete_clones_description_other": "Scrios {{count}} clóin eile freisin. Is féidir é seo a chealú sna hathruithe is déanaí.", + "erase_notes_label": "Scrios go buan", + "table_note_with_relation": "Nóta le gaol", + "table_relation": "Gaol", + "table_points_to": "Pointí chuig (scriosta)", + "delete": "Scrios" }, "export": { "export_note_title": "Nóta easpórtála", @@ -237,7 +249,8 @@ "box_size_small": "beag (~ 10 líne)", "box_size_medium": "meánach (~ 30 líne)", "box_size_full": "lán (taispeánann an bosca an téacs iomlán)", - "button_include": "Cuir nóta san áireamh" + "button_include": "Cuir nóta san áireamh", + "box_size_expandable": "inleathnaithe (fillte de réir réamhshocraithe)" }, "info": { "modalTitle": "Teachtaireacht eolais", @@ -809,7 +822,10 @@ "board": "Bord", "presentation": "Cur i Láthair", "include_archived_notes": "Taispeáin nótaí cartlannaithe", - "hide_child_notes": "Folaigh nótaí leanaí sa chrann" + "hide_child_notes": "Folaigh nótaí leanaí sa chrann", + "open_all_in_tabs": "Oscail gach rud", + "open_all_in_tabs_tooltip": "Oscail na torthaí go léir i gcluaisíní nua", + "open_all_confirm": "Osclóidh sé seo {{count}} nótaí i gcluaisíní nua. Lean ar aghaidh?" }, "edited_notes": { "no_edited_notes_found": "Gan aon nótaí eagarthóireachta ar an lá seo go fóill...", @@ -863,7 +879,8 @@ "collapse": "Laghdaigh go dtí an gnáthmhéid", "title": "Léarscáil Nótaí", "fix-nodes": "Deisigh nóid", - "link-distance": "Fad naisc" + "link-distance": "Fad naisc", + "too-many-notes": "Tá {{count}} nótaí sa fho-chrann seo, rud a sháraíonn an teorainn {{max}} is féidir a thaispeáint sa léarscáil nótaí." }, "note_paths": { "title": "Cosáin Nótaí", @@ -1368,7 +1385,8 @@ "date-and-time": "Dáta & am", "path": "Cosán", "database_backed_up_to": "Tá cúltaca déanta den bhunachar sonraí chuig {{backupFilePath}}", - "no_backup_yet": "gan aon chúltaca fós" + "no_backup_yet": "gan aon chúltaca fós", + "download": "Íoslódáil" }, "etapi": { "title": "ETAPI", @@ -1489,7 +1507,8 @@ "test_title": "Tástáil Sioncrónaithe", "test_description": "Déanfaidh sé seo tástáil ar an nasc agus ar an gcroitheadh láimhe leis an bhfreastalaí sioncrónaithe. Mura bhfuil an freastalaí sioncrónaithe tosaithe, socróidh sé seo é chun sioncrónú leis an doiciméad áitiúil.", "test_button": "Tástáil sioncrónaithe", - "handshake_failed": "Theip ar chroitheadh láimhe an fhreastalaí sioncrónaithe, earráid: {{message}}" + "handshake_failed": "Theip ar chroitheadh láimhe an fhreastalaí sioncrónaithe, earráid: {{message}}", + "timeout_description": "Cé chomh fada is ceart fanacht sula dtugann tú suas ar nasc sioncrónaithe mall. Méadaigh an méid ama má tá líonra éagobhsaí agat." }, "api_log": { "close": "Dún" @@ -1803,7 +1822,8 @@ "theme_none": "Gan aon aibhsiú comhréire", "theme_group_light": "Téamaí éadroma", "theme_group_dark": "Téamaí dorcha", - "copy_title": "Cóipeáil chuig an ghearrthaisce" + "copy_title": "Cóipeáil chuig an ghearrthaisce", + "click_to_copy": "Cliceáil chun cóipeáil" }, "classic_editor_toolbar": { "title": "Formáidiú" @@ -2328,7 +2348,8 @@ "note_context_disabled": "Cliceáil chun an nóta reatha a chur san áireamh i gcomhthéacs", "no_provider_message": "Níl aon soláthraí AI cumraithe. Cuir ceann leis chun comhrá a thosú.", "add_provider": "Cuir Soláthraí AI leis", - "sources_summary": "{{count}} foinsí ó {{sites}} suíomhanna" + "sources_summary": "{{count}} foinsí ó {{sites}} suíomhanna", + "stop": "Stop" }, "sidebar_chat": { "title": "Comhrá AI", @@ -2392,7 +2413,11 @@ "web_search": "Cuardach gréasáin", "note_in_parent": " i ", "get_attachment": "Faigh ceangaltán", - "get_attachment_content": "Léigh ábhar an cheangail" + "get_attachment_content": "Léigh ábhar an cheangail", + "rename_note": "Athainmnigh an nóta", + "delete_note": "Scrios nóta", + "move_note": "Bog nóta", + "clone_note": "Nóta clón" } }, "ocr": { From 7ec5945517a02d1bfdc31eb62db25c9ea9b5cb58 Mon Sep 17 00:00:00 2001 From: green Date: Sun, 12 Apr 2026 04:46:30 +0200 Subject: [PATCH 086/482] Translated using Weblate (Japanese) Currently translated at 100.0% (402 of 402 strings) Translation: Trilium Notes/Server Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/ --- apps/server/src/assets/translations/ja/server.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/server/src/assets/translations/ja/server.json b/apps/server/src/assets/translations/ja/server.json index fb6fbf5686..c1f65d4cd4 100644 --- a/apps/server/src/assets/translations/ja/server.json +++ b/apps/server/src/assets/translations/ja/server.json @@ -455,5 +455,8 @@ "fulltext-after-expression": "\"{{- token}}\" は有効な式ではありません。テキストを検索するには、属性フィルターの前に記述してください(例: \"#label {{- token}}\" ではなく \"{{- token}} #label\")。", "unrecognized-expression": "認識されない式 \"{{- token}}\"" } + }, + "script": { + "wrong-environment": "ノート \"{{- noteTitle}}\" ({{- noteId}}) を実行できません。これは {{- actualEnv}} スクリプトですが、{{- expectedEnv}} で実行しようとしました。" } } From 37df2dd9b2113d3faebf3c539a70c0bcdcd51c8d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 06:57:10 +0000 Subject: [PATCH 087/482] chore(deps): update dependency vite to v8.0.8 --- apps/server/package.json | 2 +- apps/website/package.json | 2 +- package.json | 2 +- pnpm-lock.yaml | 384 +++++++++++++++++++++++++++++--------- 4 files changed, 301 insertions(+), 89 deletions(-) diff --git a/apps/server/package.json b/apps/server/package.json index ab31391524..d117a24a74 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -130,7 +130,7 @@ "tmp": "0.2.5", "turnish": "1.8.0", "unescape": "1.0.1", - "vite": "8.0.7", + "vite": "8.0.8", "ws": "8.20.0", "xml2js": "0.6.2", "yauzl": "3.3.0" diff --git a/apps/website/package.json b/apps/website/package.json index 4e546b4ee4..e0f95b7596 100644 --- a/apps/website/package.json +++ b/apps/website/package.json @@ -21,7 +21,7 @@ "eslint-config-preact": "2.0.0", "typescript": "6.0.2", "user-agent-data-types": "0.4.3", - "vite": "8.0.7", + "vite": "8.0.8", "vitest": "4.1.4" }, "eslintConfig": { diff --git a/package.json b/package.json index 6e8cc64a5f..9044cd6aba 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "tsx": "4.21.0", "typescript": "6.0.2", "typescript-eslint": "8.58.1", - "vite": "8.0.7", + "vite": "8.0.8", "vite-plugin-dts": "4.5.4", "vitest": "4.1.4" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8ffe1ba222..0178434b7d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -107,7 +107,7 @@ importers: version: 24.12.2 '@vitest/browser-webdriverio': specifier: 4.1.4 - version: 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4)(webdriverio@9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) + version: 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4)(webdriverio@9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) '@vitest/coverage-v8': specifier: 4.1.4 version: 4.1.4(@vitest/browser@4.1.4)(vitest@4.1.4) @@ -161,7 +161,7 @@ importers: version: 0.18.0 rollup-plugin-webpack-stats: specifier: 3.1.0 - version: 3.1.0(rolldown@1.0.0-rc.13)(rollup@4.60.1)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 3.1.0(rolldown@1.0.0-rc.15)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) tslib: specifier: 2.8.1 version: 2.8.1 @@ -175,14 +175,14 @@ importers: specifier: 8.58.1 version: 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) vite: - specifier: 8.0.7 - version: 8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) + specifier: 8.0.8 + version: 8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) vite-plugin-dts: specifier: 4.5.4 - version: 4.5.4(@types/node@24.12.2)(rollup@4.60.1)(typescript@6.0.2)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.5.4(@types/node@24.12.2)(rollup@4.60.1)(typescript@6.0.2)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) vitest: specifier: 4.1.4 - version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) apps/build-docs: devDependencies: @@ -384,7 +384,7 @@ importers: version: 5.0.0 '@prefresh/vite': specifier: 3.0.0 - version: 3.0.0(preact@10.29.1)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 3.0.0(preact@10.29.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) '@types/bootstrap': specifier: 5.2.10 version: 5.2.10 @@ -417,7 +417,7 @@ importers: version: 0.7.2 vite-plugin-static-copy: specifier: 4.0.1 - version: 4.0.1(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.0.1(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) apps/db-compare: dependencies: @@ -864,8 +864,8 @@ importers: specifier: 1.0.1 version: 1.0.1 vite: - specifier: 8.0.7 - version: 8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) + specifier: 8.0.8 + version: 8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) ws: specifier: 8.20.0 version: 8.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) @@ -915,7 +915,7 @@ importers: devDependencies: '@preact/preset-vite': specifier: 2.10.5 - version: 2.10.5(@babel/core@7.29.0)(preact@10.29.1)(rollup@4.60.1)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 2.10.5(@babel/core@7.29.0)(preact@10.29.1)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) eslint: specifier: 10.2.0 version: 10.2.0(jiti@2.6.1) @@ -929,11 +929,11 @@ importers: specifier: 0.4.3 version: 0.4.3 vite: - specifier: 8.0.7 - version: 8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) + specifier: 8.0.8 + version: 8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) vitest: specifier: 4.1.4 - version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ckeditor5: dependencies: @@ -975,7 +975,7 @@ importers: version: 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) '@vitest/browser': specifier: 4.1.4 - version: 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) + version: 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) '@vitest/coverage-istanbul': specifier: 4.1.4 version: 4.1.4(vitest@4.1.4) @@ -999,10 +999,10 @@ importers: version: 6.0.2 vite-plugin-svgo: specifier: 2.0.0 - version: 2.0.0(typescript@6.0.2)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 2.0.0(typescript@6.0.2)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) vitest: specifier: 4.1.4 - version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) webdriverio: specifier: 9.27.0 version: 9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) @@ -1020,7 +1020,7 @@ importers: version: 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) '@vitest/browser': specifier: 4.1.4 - version: 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) + version: 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) '@vitest/coverage-istanbul': specifier: 4.1.4 version: 4.1.4(vitest@4.1.4) @@ -1044,10 +1044,10 @@ importers: version: 6.0.2 vite-plugin-svgo: specifier: 2.0.0 - version: 2.0.0(typescript@6.0.2)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 2.0.0(typescript@6.0.2)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) vitest: specifier: 4.1.4 - version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) webdriverio: specifier: 9.27.0 version: 9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) @@ -1065,7 +1065,7 @@ importers: version: 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) '@vitest/browser': specifier: 4.1.4 - version: 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) + version: 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) '@vitest/coverage-istanbul': specifier: 4.1.4 version: 4.1.4(vitest@4.1.4) @@ -1089,10 +1089,10 @@ importers: version: 6.0.2 vite-plugin-svgo: specifier: 2.0.0 - version: 2.0.0(typescript@6.0.2)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 2.0.0(typescript@6.0.2)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) vitest: specifier: 4.1.4 - version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) webdriverio: specifier: 9.27.0 version: 9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) @@ -1117,7 +1117,7 @@ importers: version: 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) '@vitest/browser': specifier: 4.1.4 - version: 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) + version: 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) '@vitest/coverage-istanbul': specifier: 4.1.4 version: 4.1.4(vitest@4.1.4) @@ -1141,10 +1141,10 @@ importers: version: 6.0.2 vite-plugin-svgo: specifier: 2.0.0 - version: 2.0.0(typescript@6.0.2)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 2.0.0(typescript@6.0.2)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) vitest: specifier: 4.1.4 - version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) webdriverio: specifier: 9.27.0 version: 9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) @@ -1162,7 +1162,7 @@ importers: version: 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) '@vitest/browser': specifier: 4.1.4 - version: 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) + version: 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) '@vitest/coverage-istanbul': specifier: 4.1.4 version: 4.1.4(vitest@4.1.4) @@ -1186,10 +1186,10 @@ importers: version: 6.0.2 vite-plugin-svgo: specifier: 2.0.0 - version: 2.0.0(typescript@6.0.2)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 2.0.0(typescript@6.0.2)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) vitest: specifier: 4.1.4 - version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) webdriverio: specifier: 9.27.0 version: 9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) @@ -1451,7 +1451,7 @@ importers: version: 20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5) vitest: specifier: 4.1.4 - version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) packages/turndown-plugin-gfm: devDependencies: @@ -1463,7 +1463,7 @@ importers: version: 7.2.4 vitest: specifier: 4.1.4 - version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) packages: @@ -2312,15 +2312,24 @@ packages: '@emnapi/core@1.9.1': resolution: {integrity: sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==} + '@emnapi/core@1.9.2': + resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==} + '@emnapi/runtime@1.9.0': resolution: {integrity: sha512-QN75eB0IH2ywSpRpNddCRfQIhmJYBCJ1x5Lb3IscKAL8bMnVAKnRg8dCoXbHzVLLH7P38N2Z3mtulB7W0J0FKw==} '@emnapi/runtime@1.9.1': resolution: {integrity: sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==} + '@emnapi/runtime@1.9.2': + resolution: {integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==} + '@emnapi/wasi-threads@1.2.0': resolution: {integrity: sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==} + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + '@emotion/is-prop-valid@1.4.0': resolution: {integrity: sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==} @@ -3964,6 +3973,9 @@ packages: '@oxc-project/types@0.123.0': resolution: {integrity: sha512-YtECP/y8Mj1lSHiUWGSRzy/C6teUKlS87dEfuVKT09LgQbUsBW1rNg+MiJ4buGu3yuADV60gbIvo9/HplA56Ew==} + '@oxc-project/types@0.124.0': + resolution: {integrity: sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==} + '@panva/asn1.js@1.0.0': resolution: {integrity: sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==} engines: {node: '>=10.13.0'} @@ -4853,30 +4865,60 @@ packages: cpu: [arm64] os: [android] + '@rolldown/binding-android-arm64@1.0.0-rc.15': + resolution: {integrity: sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + '@rolldown/binding-darwin-arm64@1.0.0-rc.13': resolution: {integrity: sha512-tz/v/8G77seu8zAB3A5sK3UFoOl06zcshEzhUO62sAEtrEuW/H1CcyoupOrD+NbQJytYgA4CppXPzlrmp4JZKA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] + '@rolldown/binding-darwin-arm64@1.0.0-rc.15': + resolution: {integrity: sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + '@rolldown/binding-darwin-x64@1.0.0-rc.13': resolution: {integrity: sha512-8DakphqOz8JrMYWTJmWA+vDJxut6LijZ8Xcdc4flOlAhU7PNVwo2MaWBF9iXjJAPo5rC/IxEFZDhJ3GC7NHvug==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] + '@rolldown/binding-darwin-x64@1.0.0-rc.15': + resolution: {integrity: sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + '@rolldown/binding-freebsd-x64@1.0.0-rc.13': resolution: {integrity: sha512-4wBQFfjDuXYN/SVI8inBF3Aa+isq40rc6VMFbk5jcpolUBTe5cYnMsHZ51nFWsx3PVyyNN3vgoESki0Hmr/4BA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] + '@rolldown/binding-freebsd-x64@1.0.0-rc.15': + resolution: {integrity: sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.13': resolution: {integrity: sha512-JW/e4yPIXLms+jmnbwwy5LA/LxVwZUWLN8xug+V200wzaVi5TEGIWQlh8o91gWYFxW609euI98OCCemmWGuPrw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15': + resolution: {integrity: sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.13': resolution: {integrity: sha512-ZfKWpXiUymDnavepCaM6KG/uGydJ4l2nBmMxg60Ci4CbeefpqjPWpfaZM7PThOhk2dssqBAcwLc6rAyr0uTdXg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4884,6 +4926,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15': + resolution: {integrity: sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.13': resolution: {integrity: sha512-bmRg3O6Z0gq9yodKKWCIpnlH051sEfdVwt+6m5UDffAQMUUqU0xjnQqqAUm+Gu7ofAAly9DqiQDtKu2nPDEABA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4891,6 +4940,13 @@ packages: os: [linux] libc: [musl] + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.15': + resolution: {integrity: sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.13': resolution: {integrity: sha512-8Wtnbw4k7pMYN9B/mOEAsQ8HOiq7AZ31Ig4M9BKn2So4xRaFEhtCSa4ZJaOutOWq50zpgR4N5+L/opnlaCx8wQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4898,6 +4954,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15': + resolution: {integrity: sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.13': resolution: {integrity: sha512-D/0Nlo8mQuxSMohNJUF2lDXWRsFDsHldfRRgD9bRgktj+EndGPj4DOV37LqDKPYS+osdyhZEH7fTakTAEcW7qg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4905,6 +4968,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15': + resolution: {integrity: sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.13': resolution: {integrity: sha512-eRrPvat2YaVQcwwKi/JzOP6MKf1WRnOCr+VaI3cTWz3ZoLcP/654z90lVCJ4dAuMEpPdke0n+qyAqXDZdIC4rA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4912,6 +4982,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.15': + resolution: {integrity: sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-x64-musl@1.0.0-rc.13': resolution: {integrity: sha512-PsdONiFRp8hR8KgVjTWjZ9s7uA3uueWL0t74/cKHfM4dR5zXYv4AjB8BvA+QDToqxAFg4ZkcVEqeu5F7inoz5w==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4919,32 +4996,65 @@ packages: os: [linux] libc: [musl] + '@rolldown/binding-linux-x64-musl@1.0.0-rc.15': + resolution: {integrity: sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + '@rolldown/binding-openharmony-arm64@1.0.0-rc.13': resolution: {integrity: sha512-hCNXgC5dI3TVOLrPT++PKFNZ+1EtS0mLQwfXXXSUD/+rGlB65gZDwN/IDuxLpQP4x8RYYHqGomlUXzpO8aVI2w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] + '@rolldown/binding-openharmony-arm64@1.0.0-rc.15': + resolution: {integrity: sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + '@rolldown/binding-wasm32-wasi@1.0.0-rc.13': resolution: {integrity: sha512-viLS5C5et8NFtLWw9Sw3M/w4vvnVkbWkO7wSNh3C+7G1+uCkGpr6PcjNDSFcNtmXY/4trjPBqUfcOL+P3sWy/g==} engines: {node: '>=14.0.0'} cpu: [wasm32] + '@rolldown/binding-wasm32-wasi@1.0.0-rc.15': + resolution: {integrity: sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.13': resolution: {integrity: sha512-Fqa3Tlt1xL4wzmAYxGNFV36Hb+VfPc9PYU+E25DAnswXv3ODDu/yyWjQDbXMo5AGWkQVjLgQExuVu8I/UaZhPQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15': + resolution: {integrity: sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.13': resolution: {integrity: sha512-/pLI5kPkGEi44TDlnbio3St/5gUFeN51YWNAk/Gnv6mEQBOahRBh52qVFVBpmrnU01n2yysvBML9Ynu7K4kGAQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.15': + resolution: {integrity: sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@rolldown/pluginutils@1.0.0-rc.13': resolution: {integrity: sha512-3ngTAv6F/Py35BsYbeeLeecvhMKdsKm4AoOETVhAA+Qc8nrA2I0kF7oa93mE9qnIurngOSpMnQ0x2nQY2FPviA==} + '@rolldown/pluginutils@1.0.0-rc.15': + resolution: {integrity: sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==} + '@rollup/plugin-buble@1.0.3': resolution: {integrity: sha512-QYD9BKkJoof0FdCFeSYYhF6/Y8e0Mnf+098xGgmWOFJ4UPHlWujjqOYeVwEm2hJPOmlR5k7HPUdAjqtOWhN64Q==} engines: {node: '>=14.0.0'} @@ -11992,6 +12102,11 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + rolldown@1.0.0-rc.15: + resolution: {integrity: sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + rollup-plugin-stats@2.1.0: resolution: {integrity: sha512-mkthlSVb8T2AKfdt/FEJqB/1Nvsr4G+otKZ4dhPKjyWQA6fdL7STRPA4epwVOBsj1yYYv/dcgAmfwfNtMpZ6sw==} engines: {node: '>=18'} @@ -13492,8 +13607,8 @@ packages: peerDependencies: vite: '>=7.3.2' - vite@8.0.7: - resolution: {integrity: sha512-P1PbweD+2/udplnThz3btF4cf6AgPky7kk23RtHUkJIU5BIxwPprhRGmOAHs6FTI7UiGbTNrgNP6jSYD6JaRnw==} + vite@8.0.8: + resolution: {integrity: sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -15902,6 +16017,12 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/core@1.9.2': + dependencies: + '@emnapi/wasi-threads': 1.2.1 + tslib: 2.8.1 + optional: true + '@emnapi/runtime@1.9.0': dependencies: tslib: 2.8.1 @@ -15912,11 +16033,21 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/runtime@1.9.2': + dependencies: + tslib: 2.8.1 + optional: true + '@emnapi/wasi-threads@1.2.0': dependencies: tslib: 2.8.1 optional: true + '@emnapi/wasi-threads@1.2.1': + dependencies: + tslib: 2.8.1 + optional: true + '@emotion/is-prop-valid@1.4.0': dependencies: '@emotion/memoize': 0.9.0 @@ -17345,6 +17476,13 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true + '@napi-rs/wasm-runtime@1.1.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': + dependencies: + '@emnapi/core': 1.9.2 + '@emnapi/runtime': 1.9.2 + '@tybys/wasm-util': 0.10.1 + optional: true + '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': dependencies: eslint-scope: 5.1.1 @@ -17490,6 +17628,8 @@ snapshots: '@oxc-project/types@0.123.0': {} + '@oxc-project/types@0.124.0': {} + '@panva/asn1.js@1.0.0': {} '@paralleldrive/cuid2@2.2.2': @@ -17579,19 +17719,19 @@ snapshots: '@popperjs/core@2.11.8': {} - '@preact/preset-vite@2.10.5(@babel/core@7.29.0)(preact@10.29.1)(rollup@4.60.1)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))': + '@preact/preset-vite@2.10.5(@babel/core@7.29.0)(preact@10.29.1)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.29.0) '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.29.0) - '@prefresh/vite': 2.4.12(preact@10.29.1)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + '@prefresh/vite': 2.4.12(preact@10.29.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) '@rollup/pluginutils': 5.1.4(rollup@4.60.1) babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.29.0) debug: 4.4.3 magic-string: 0.30.21 picocolors: 1.1.1 - vite: 8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) - vite-prerender-plugin: 0.5.11(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) + vite-prerender-plugin: 0.5.11(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) zimmerframe: 1.1.4 transitivePeerDependencies: - preact @@ -17611,19 +17751,19 @@ snapshots: dependencies: preact: 10.29.1 - '@prefresh/rolldown@0.1.0(rolldown@1.0.0-rc.13)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))': + '@prefresh/rolldown@0.1.0(rolldown@1.0.0-rc.13)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))': dependencies: oxc-unshadowed-visitor: 0.0.1(rolldown@1.0.0-rc.13) rolldown: 1.0.0-rc.13 rolldown-string: 0.3.0(rolldown@1.0.0-rc.13) optionalDependencies: - vite: 8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) transitivePeerDependencies: - oxc-parser '@prefresh/utils@1.2.1': {} - '@prefresh/vite@2.4.12(preact@10.29.1)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))': + '@prefresh/vite@2.4.12(preact@10.29.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@babel/core': 7.29.0 '@prefresh/babel-plugin': 0.5.2 @@ -17631,21 +17771,21 @@ snapshots: '@prefresh/utils': 1.2.1 '@rollup/pluginutils': 4.2.1 preact: 10.29.1 - vite: 8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) transitivePeerDependencies: - supports-color - '@prefresh/vite@3.0.0(preact@10.29.1)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))': + '@prefresh/vite@3.0.0(preact@10.29.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@babel/core': 7.29.0 '@prefresh/babel-plugin': 0.5.2 '@prefresh/core': 1.5.5(preact@10.29.1) - '@prefresh/rolldown': 0.1.0(rolldown@1.0.0-rc.13)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + '@prefresh/rolldown': 0.1.0(rolldown@1.0.0-rc.13)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) '@prefresh/utils': 1.2.1 '@rollup/pluginutils': 4.2.1 preact: 10.29.1 rolldown: 1.0.0-rc.13 - vite: 8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) transitivePeerDependencies: - oxc-parser - supports-color @@ -18423,39 +18563,75 @@ snapshots: '@rolldown/binding-android-arm64@1.0.0-rc.13': optional: true + '@rolldown/binding-android-arm64@1.0.0-rc.15': + optional: true + '@rolldown/binding-darwin-arm64@1.0.0-rc.13': optional: true + '@rolldown/binding-darwin-arm64@1.0.0-rc.15': + optional: true + '@rolldown/binding-darwin-x64@1.0.0-rc.13': optional: true + '@rolldown/binding-darwin-x64@1.0.0-rc.15': + optional: true + '@rolldown/binding-freebsd-x64@1.0.0-rc.13': optional: true + '@rolldown/binding-freebsd-x64@1.0.0-rc.15': + optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.13': optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15': + optional: true + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.13': optional: true + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15': + optional: true + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.13': optional: true + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.15': + optional: true + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.13': optional: true + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15': + optional: true + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.13': optional: true + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15': + optional: true + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.13': optional: true + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.15': + optional: true + '@rolldown/binding-linux-x64-musl@1.0.0-rc.13': optional: true + '@rolldown/binding-linux-x64-musl@1.0.0-rc.15': + optional: true + '@rolldown/binding-openharmony-arm64@1.0.0-rc.13': optional: true + '@rolldown/binding-openharmony-arm64@1.0.0-rc.15': + optional: true + '@rolldown/binding-wasm32-wasi@1.0.0-rc.13': dependencies: '@emnapi/core': 1.9.1 @@ -18463,14 +18639,29 @@ snapshots: '@napi-rs/wasm-runtime': 1.1.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1) optional: true + '@rolldown/binding-wasm32-wasi@1.0.0-rc.15': + dependencies: + '@emnapi/core': 1.9.2 + '@emnapi/runtime': 1.9.2 + '@napi-rs/wasm-runtime': 1.1.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + optional: true + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.13': optional: true + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15': + optional: true + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.13': optional: true + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.15': + optional: true + '@rolldown/pluginutils@1.0.0-rc.13': {} + '@rolldown/pluginutils@1.0.0-rc.15': {} + '@rollup/plugin-buble@1.0.3(rollup@4.60.1)': dependencies: '@rollup/pluginutils': 5.1.4(rollup@4.60.1) @@ -20697,10 +20888,10 @@ snapshots: '@vercel/oidc@3.1.0': {} - '@vitest/browser-webdriverio@4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4)(webdriverio@9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))': + '@vitest/browser-webdriverio@4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4)(webdriverio@9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))': dependencies: - '@vitest/browser': 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) - vitest: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/browser': 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) + vitest: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) webdriverio: 9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) transitivePeerDependencies: - bufferutil @@ -20708,16 +20899,16 @@ snapshots: - utf-8-validate - vite - '@vitest/browser@4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4)': + '@vitest/browser@4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4)': dependencies: '@blazediff/core': 1.9.1 - '@vitest/mocker': 4.1.4(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/mocker': 4.1.4(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) '@vitest/utils': 4.1.4 magic-string: 0.30.21 pngjs: 7.0.0 sirv: 3.0.2 tinyrainbow: 3.1.0 - vitest: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) ws: 8.20.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) transitivePeerDependencies: - bufferutil @@ -20737,7 +20928,7 @@ snapshots: magicast: 0.5.2 obug: 2.1.1 tinyrainbow: 3.1.0 - vitest: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) transitivePeerDependencies: - supports-color @@ -20753,9 +20944,9 @@ snapshots: obug: 2.1.1 std-env: 4.0.0 tinyrainbow: 3.1.0 - vitest: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) optionalDependencies: - '@vitest/browser': 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) + '@vitest/browser': 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4) '@vitest/expect@4.1.4': dependencies: @@ -20766,14 +20957,14 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.4(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))': + '@vitest/mocker@4.1.4(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 4.1.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: msw: 2.7.5(@types/node@24.12.2)(typescript@6.0.2) - vite: 8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) '@vitest/pretty-format@4.1.4': dependencies: @@ -20802,7 +20993,7 @@ snapshots: sirv: 3.0.2 tinyglobby: 0.2.15 tinyrainbow: 3.1.0 - vitest: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) '@vitest/utils@4.1.4': dependencies: @@ -27666,19 +27857,40 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.13 '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.13 - rollup-plugin-stats@2.1.0(rolldown@1.0.0-rc.13)(rollup@4.60.1)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)): - optionalDependencies: - rolldown: 1.0.0-rc.13 - rollup: 4.60.1 - vite: 8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) - - rollup-plugin-webpack-stats@3.1.0(rolldown@1.0.0-rc.13)(rollup@4.60.1)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)): + rolldown@1.0.0-rc.15: dependencies: - rollup-plugin-stats: 2.1.0(rolldown@1.0.0-rc.13)(rollup@4.60.1)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + '@oxc-project/types': 0.124.0 + '@rolldown/pluginutils': 1.0.0-rc.15 optionalDependencies: - rolldown: 1.0.0-rc.13 + '@rolldown/binding-android-arm64': 1.0.0-rc.15 + '@rolldown/binding-darwin-arm64': 1.0.0-rc.15 + '@rolldown/binding-darwin-x64': 1.0.0-rc.15 + '@rolldown/binding-freebsd-x64': 1.0.0-rc.15 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.15 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.15 + '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.15 + '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.15 + '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.15 + '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.15 + '@rolldown/binding-linux-x64-musl': 1.0.0-rc.15 + '@rolldown/binding-openharmony-arm64': 1.0.0-rc.15 + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.15 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.15 + '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.15 + + rollup-plugin-stats@2.1.0(rolldown@1.0.0-rc.15)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)): + optionalDependencies: + rolldown: 1.0.0-rc.15 rollup: 4.60.1 - vite: 8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) + + rollup-plugin-webpack-stats@3.1.0(rolldown@1.0.0-rc.15)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)): + dependencies: + rollup-plugin-stats: 2.1.0(rolldown@1.0.0-rc.15)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + optionalDependencies: + rolldown: 1.0.0-rc.15 + rollup: 4.60.1 + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) rollup@4.60.1: dependencies: @@ -29323,7 +29535,7 @@ snapshots: es-module-lexer: 2.0.0 obug: 2.1.1 pathe: 2.0.3 - vite: 8.0.7(@types/node@24.12.2)(esbuild@0.27.4)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.4)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) transitivePeerDependencies: - '@types/node' - '@vitejs/devtools' @@ -29338,7 +29550,7 @@ snapshots: - tsx - yaml - vite-plugin-dts@4.5.4(@types/node@24.12.2)(rollup@4.60.1)(typescript@6.0.2)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)): + vite-plugin-dts@4.5.4(@types/node@24.12.2)(rollup@4.60.1)(typescript@6.0.2)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@microsoft/api-extractor': 7.52.8(@types/node@24.12.2) '@rollup/pluginutils': 5.1.4(rollup@4.60.1) @@ -29351,27 +29563,27 @@ snapshots: magic-string: 0.30.21 typescript: 6.0.2 optionalDependencies: - vite: 8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) transitivePeerDependencies: - '@types/node' - rollup - supports-color - vite-plugin-static-copy@4.0.1(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)): + vite-plugin-static-copy@4.0.1(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)): dependencies: chokidar: 3.6.0 p-map: 7.0.4 picocolors: 1.1.1 tinyglobby: 0.2.15 - vite: 8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) - vite-plugin-svgo@2.0.0(typescript@6.0.2)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)): + vite-plugin-svgo@2.0.0(typescript@6.0.2)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)): dependencies: svgo: 4.0.1 typescript: 6.0.2 - vite: 8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) - vite-prerender-plugin@0.5.11(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)): + vite-prerender-plugin@0.5.11(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)): dependencies: kolorist: 1.8.0 magic-string: 0.30.21 @@ -29379,14 +29591,14 @@ snapshots: simple-code-frame: 1.3.0 source-map: 0.7.6 stack-trace: 1.0.0-pre2 - vite: 8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) - vite@8.0.7(@types/node@24.12.2)(esbuild@0.27.4)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3): + vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.4)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3): dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 - postcss: 8.5.8 - rolldown: 1.0.0-rc.13 + postcss: 8.5.9 + rolldown: 1.0.0-rc.15 tinyglobby: 0.2.15 optionalDependencies: '@types/node': 24.12.2 @@ -29400,12 +29612,12 @@ snapshots: tsx: 4.21.0 yaml: 2.8.3 - vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3): + vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3): dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 - postcss: 8.5.8 - rolldown: 1.0.0-rc.13 + postcss: 8.5.9 + rolldown: 1.0.0-rc.15 tinyglobby: 0.2.15 optionalDependencies: '@types/node': 24.12.2 @@ -29419,10 +29631,10 @@ snapshots: tsx: 4.21.0 yaml: 2.8.3 - vitest@4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)): + vitest@4.1.4(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-webdriverio@4.1.4)(@vitest/coverage-istanbul@4.1.4)(@vitest/coverage-v8@4.1.4)(@vitest/ui@4.1.4)(happy-dom@20.8.9(bufferutil@4.0.9)(utf-8-validate@6.0.5))(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@vitest/expect': 4.1.4 - '@vitest/mocker': 4.1.4(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/mocker': 4.1.4(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) '@vitest/pretty-format': 4.1.4 '@vitest/runner': 4.1.4 '@vitest/snapshot': 4.1.4 @@ -29439,12 +29651,12 @@ snapshots: tinyexec: 1.0.4 tinyglobby: 0.2.15 tinyrainbow: 3.1.0 - vite: 8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) why-is-node-running: 2.3.0 optionalDependencies: '@opentelemetry/api': 1.9.0 '@types/node': 24.12.2 - '@vitest/browser-webdriverio': 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.7(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4)(webdriverio@9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) + '@vitest/browser-webdriverio': 4.1.4(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.2)(typescript@6.0.2))(utf-8-validate@6.0.5)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4)(webdriverio@9.27.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) '@vitest/coverage-istanbul': 4.1.4(vitest@4.1.4) '@vitest/coverage-v8': 4.1.4(@vitest/browser@4.1.4)(vitest@4.1.4) '@vitest/ui': 4.1.4(vitest@4.1.4) @@ -29841,7 +30053,7 @@ snapshots: scule: 1.3.0 tinyglobby: 0.2.15 unimport: 5.6.0 - vite: 8.0.7(@types/node@24.12.2)(esbuild@0.27.4)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.4)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) vite-node: 5.3.0(@types/node@24.12.2)(esbuild@0.27.4)(jiti@2.6.1)(less@4.1.3)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) web-ext-run: 0.2.4 optionalDependencies: From ef9002dedea9101697869bf52e155a2b36087261 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 13 Apr 2026 09:58:13 +0300 Subject: [PATCH 088/482] Apply suggestion from @gemini-code-assist[bot] Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- apps/client/src/translations/ga/translation.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/client/src/translations/ga/translation.json b/apps/client/src/translations/ga/translation.json index 69819a83b2..ee66bc7593 100644 --- a/apps/client/src/translations/ga/translation.json +++ b/apps/client/src/translations/ga/translation.json @@ -2417,7 +2417,7 @@ "rename_note": "Athainmnigh an nóta", "delete_note": "Scrios nóta", "move_note": "Bog nóta", - "clone_note": "Nóta clón" + "clone_note": "Clónáil nóta" } }, "ocr": { From 9b2be5736586b6b0122e01d11334266ca00632ed Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 13 Apr 2026 12:56:50 +0300 Subject: [PATCH 089/482] docs: remove search analysis --- docs/search-performance-benchmarks.md | 111 -------------------------- 1 file changed, 111 deletions(-) delete mode 100644 docs/search-performance-benchmarks.md diff --git a/docs/search-performance-benchmarks.md b/docs/search-performance-benchmarks.md deleted file mode 100644 index 17b9427ba5..0000000000 --- a/docs/search-performance-benchmarks.md +++ /dev/null @@ -1,111 +0,0 @@ -# Search Performance Benchmarks - -Comparison of `main` vs `feat/search-perf-take1` branch. - -> **Methodology:** In-memory benchmarks using synthetic datasets with monkeypatched `getContent()`. Both branches tested on the same machine in the same session. Times are avg of 5 iterations with warm caches. Note content I/O (`NoteContentFulltextExp` blob scan) is not measured — these numbers reflect the in-memory pipeline only. -> -> **Benchmark source:** `apps/server/src/services/search/services/search_benchmark.spec.ts` - ---- - -## End-to-End Results at 10K Notes - -### Autocomplete (typing in the search bar, `fastSearch=true`) - -| Query | main | this PR | Change | -|:------|-----:|--------:|-------:| -| `"meeting"` | 24.7ms | 14.3ms | **-42%** | -| `"meeting notes"` | 33.0ms | 15.6ms | **-53%** | -| `"meeting notes january"` | 43.2ms | 17.7ms | **-59%** | -| `"documentation"` | 17.5ms | 11.0ms | **-37%** | -| `"note"` (matches 85% of notes) | 90.8ms | 46.4ms | **-49%** | -| `"projct"` (typo, fuzzy ON) | 100.7ms | 6.0ms | **-94%** | -| `"xyznonexistent"` (no match, fuzzy ON) | 18.2ms | 6.0ms | **-67%** | -| `"xyzfoo xyzbar"` (no match, fuzzy ON) | 63.4ms | 7.1ms | **-89%** | - -### Full Search (pressing Enter, `fastSearch=false`) - -| Query | main | this PR | Change | -|:------|-----:|--------:|-------:| -| `"meeting"` | 22.9ms | 19.6ms | **-14%** | -| `"meeting notes"` | 35.7ms | 17.4ms | **-51%** | -| `"meeting notes january"` | 43.4ms | 21.0ms | **-52%** | -| `"quarterly budget review report"` | 37.1ms | 18.3ms | **-51%** | -| `"project planning"` | 27.4ms | 17.3ms | **-37%** | - -### Full Search with Fuzzy Matching - -| Query | main | this PR | Change | -|:------|-----:|--------:|-------:| -| `"meeting"` | 23.3ms | 17.8ms | **-24%** | -| `"meeting notes"` | 33.8ms | 18.6ms | **-45%** | -| `"meeting notes january"` | 43.2ms | 18.0ms | **-58%** | -| `"quarterly budget review report"` | 39.5ms | 17.2ms | **-56%** | -| `"project planning"` | 32.8ms | 18.6ms | **-43%** | -| `"projct planing"` (typo, recovers 1,500 results) | 133.8ms | 94.8ms | **-29%** | -| `"xyzfoo xyzbar"` (no match, worst case) | 64.2ms | 61.4ms | -4% | - ---- - -## Scaling Behavior - -### Autocomplete: `"meeting notes"` (fuzzy OFF) - -| Notes | main | this PR | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 2.7ms | 1.1ms | **-59%** | -| 5,000 | 15.8ms | 5.9ms | **-63%** | -| 10,000 | 33.0ms | 15.6ms | **-53%** | -| 20,000 | 67.3ms | 33.6ms | **-50%** | - -### Full search: `"meeting notes january"` (fuzzy ON) - -| Notes | main | this PR | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 3.7ms | 1.3ms | **-65%** | -| 5,000 | 21.2ms | 8.7ms | **-59%** | -| 10,000 | 43.2ms | 18.0ms | **-58%** | -| 20,000 | 92.8ms | 40.1ms | **-57%** | - -### Autocomplete no-match: `"xyzfoo xyzbar"` (fuzzy ON) - -| Notes | main | this PR | Change | -|------:|-----:|--------:|-------:| -| 1,000 | 5.1ms | 0.4ms | **-92%** | -| 5,000 | 29.0ms | 2.2ms | **-92%** | -| 10,000 | 63.4ms | 7.1ms | **-89%** | -| 20,000 | 128.8ms | 19.1ms | **-85%** | - -### Typing progression at 10K notes (autocomplete, fuzzy OFF) - -| Prefix typed | main | this PR | Change | -|:-------------|-----:|--------:|-------:| -| `"d"` | 66.9ms | 44.8ms | **-33%** | -| `"doc"` | 20.9ms | 14.7ms | **-30%** | -| `"document"` | 16.8ms | 11.8ms | **-30%** | -| `"documentation"` | 17.5ms | 11.0ms | **-37%** | - ---- - -## What Changed - -1. **Pre-built flat text index** with incremental dirty-marking in Becca — avoids rebuilding per-note flat text on every search -2. **Skip two-phase fuzzy fallback for autocomplete** — the user is still typing, fuzzy adds latency for no benefit -3. **Pre-normalized attribute names/values** cached on `BAttribute` at construction time -4. **Cached normalized parent titles** per search execution via `Map` in `NoteFlatTextExp` -5. **Set-based token lookup** in `searchPathTowardsRoot` (O(1) vs O(n) `Array.includes`) -6. **Removed redundant `toLowerCase()`** — `normalizeSearchText` already lowercases; callers were double-lowering -7. **Pre-normalize tokens once** in `addScoreForStrings` instead of re-normalizing per chunk -8. **Skip edit distance computation** when fuzzy matching is disabled -9. **Faster content snippet extraction** — regex `/<[^>]*>/g` instead of `striptags` library; normalize only the snippet window, not full content -10. **`removeDiacritic()` hoisted outside regex while-loop** in highlighting -11. **Single-token autocomplete fast path** — skips the recursive parent walk entirely, uses `getBestNotePath()` directly -12. **User option `searchEnableFuzzyMatching`** — lets users disable fuzzy matching for fastest possible search - ---- - -## Known Limitations - -- These benchmarks measure the **in-memory pipeline only** (titles, attributes, scoring, highlighting). The `NoteContentFulltextExp` sequential blob scan from SQLite is not exercised because `getContent()` is monkeypatched. In production, the full search path (`fastSearch=false`) includes reading every note's content from disk, which adds significant time at scale. -- Fuzzy matching on the full-search two-phase path shows slight regressions (+9-12%) for single-token queries because edit distance computation cost hasn't changed on that path. Multi-token queries still improve because the token normalization and tree walk optimizations apply to both paths. -- At 1K notes, some results show noise-level regressions. The optimizations target 5K+ note scales where overhead is measurable. From 6e90a4168e56e50fc06821eb11c1f694a9d42b06 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 13 Apr 2026 13:02:28 +0300 Subject: [PATCH 090/482] feat(autocomplete): toggle for fuzzy matching (closes #8360) --- CLAUDE.md | 5 +++-- apps/client/src/translations/en/translation.json | 3 ++- apps/client/src/widgets/type_widgets/options/other.tsx | 7 +++++++ apps/server/src/routes/api/options.ts | 1 + apps/server/src/services/options_init.ts | 1 + apps/server/src/services/search/services/search.ts | 9 +++++---- packages/commons/src/lib/options_interface.ts | 2 ++ 7 files changed, 21 insertions(+), 7 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 1b90b02881..a395f985bf 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -162,8 +162,9 @@ Trilium provides powerful user scripting capabilities: - To add a new user preference: 1. Add the option type to `OptionDefinitions` in `packages/commons/src/lib/options_interface.ts` 2. Add a default value in `apps/server/src/services/options_init.ts` in the `defaultOptions` array - 3. **Whitelist the option** in `apps/server/src/routes/api/options.ts` by adding it to `ALLOWED_OPTIONS` (required for client updates) - 4. Use `useTriliumOption("optionName")` hook in React components to read/write the option + 3. **Whitelist the option** in `apps/server/src/routes/api/options.ts` by adding it to the `ALLOWED_OPTIONS` array — **without this, the API will reject changes with "Option 'X' is not allowed to be changed"** + 4. If the option should be user-editable in the UI, add a control in the appropriate settings component (e.g., `apps/client/src/widgets/type_widgets/options/other.tsx`) and a translation key in `apps/client/src/translations/en/translation.json` + 5. Use `useTriliumOption("optionName")` hook in React components to read/write the option - Available hooks: `useTriliumOption` (string), `useTriliumOptionBool`, `useTriliumOptionInt`, `useTriliumOptionJson` - See `docs/Developer Guide/Developer Guide/Concepts/Options/Creating a new option.md` for detailed documentation diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 2c1e1ae19a..abc3de3de4 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -1326,7 +1326,8 @@ }, "search": { "title": "Search", - "enable_fuzzy_matching": "Enable fuzzy matching in search (matches similar words when exact matches are insufficient)" + "enable_fuzzy_matching": "Enable fuzzy matching in search (matches similar words when exact matches are insufficient)", + "enable_autocomplete_fuzzy": "Enable fuzzy matching for autocomplete (slower, but tolerates typos while typing)" }, "search_engine": { "title": "Search Engine", diff --git a/apps/client/src/widgets/type_widgets/options/other.tsx b/apps/client/src/widgets/type_widgets/options/other.tsx index 8cb99bace4..b75c81b711 100644 --- a/apps/client/src/widgets/type_widgets/options/other.tsx +++ b/apps/client/src/widgets/type_widgets/options/other.tsx @@ -39,6 +39,7 @@ export default function OtherSettings() { function SearchSettings() { const [ fuzzyEnabled, setFuzzyEnabled ] = useTriliumOptionBool("searchEnableFuzzyMatching"); + const [ autocompleteFuzzy, setAutocompleteFuzzy ] = useTriliumOptionBool("searchAutocompleteFuzzy"); return ( @@ -48,6 +49,12 @@ function SearchSettings() { currentValue={fuzzyEnabled} onChange={setFuzzyEnabled} /> + ); } diff --git a/apps/server/src/routes/api/options.ts b/apps/server/src/routes/api/options.ts index 384c975eba..9be9ba0670 100644 --- a/apps/server/src/routes/api/options.ts +++ b/apps/server/src/routes/api/options.ts @@ -100,6 +100,7 @@ const ALLOWED_OPTIONS = new Set([ "backgroundEffects", "allowedHtmlTags", "searchEnableFuzzyMatching", + "searchAutocompleteFuzzy", "redirectBareDomain", "showLoginInShareTheme", "splitEditorOrientation", diff --git a/apps/server/src/services/options_init.ts b/apps/server/src/services/options_init.ts index 9ac33d4e31..4bff15d91e 100644 --- a/apps/server/src/services/options_init.ts +++ b/apps/server/src/services/options_init.ts @@ -236,6 +236,7 @@ const defaultOptions: DefaultOption[] = [ // Search settings { name: "searchEnableFuzzyMatching", value: "true", isSynced: true }, + { name: "searchAutocompleteFuzzy", value: "false", isSynced: true }, // Share settings { name: "redirectBareDomain", value: "false", isSynced: true }, diff --git a/apps/server/src/services/search/services/search.ts b/apps/server/src/services/search/services/search.ts index 226c809d7d..660c46119b 100644 --- a/apps/server/src/services/search/services/search.ts +++ b/apps/server/src/services/search/services/search.ts @@ -17,6 +17,7 @@ import type Expression from "../expressions/expression.js"; import sql from "../../sql.js"; import scriptService from "../../script.js"; import protectedSessionService from "../../protected_session.js"; +import optionService from "../../options.js"; export interface SearchNoteResult { searchResultNoteIds: string[]; @@ -248,11 +249,11 @@ function findResultsWithExpression(expression: Expression, searchContext: Search return performSearch(expression, searchContext, false); } - // For autocomplete searches, skip the expensive two-phase fuzzy fallback. - // The user is typing and will refine their query — exact matching is - // sufficient and avoids a second full scan of all notes. + // For autocomplete searches, use the dedicated autocomplete fuzzy option. + // Default is off for faster response; users can enable if they want typo tolerance. if (searchContext.autocomplete) { - return performSearch(expression, searchContext, false); + const autocompleteFuzzy = optionService.getOptionBool("searchAutocompleteFuzzy"); + return performSearch(expression, searchContext, autocompleteFuzzy); } // Phase 1: Try exact matches first (without fuzzy matching) diff --git a/packages/commons/src/lib/options_interface.ts b/packages/commons/src/lib/options_interface.ts index d57217712e..a00666677a 100644 --- a/packages/commons/src/lib/options_interface.ts +++ b/packages/commons/src/lib/options_interface.ts @@ -138,6 +138,8 @@ export interface OptionDefinitions extends KeyboardShortcutsOptions Date: Mon, 13 Apr 2026 13:05:54 +0300 Subject: [PATCH 091/482] refactor(search): simplify branching for autocomplete --- apps/server/src/services/search/services/search.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/apps/server/src/services/search/services/search.ts b/apps/server/src/services/search/services/search.ts index 660c46119b..f9581aa170 100644 --- a/apps/server/src/services/search/services/search.ts +++ b/apps/server/src/services/search/services/search.ts @@ -236,6 +236,12 @@ function findResultsWithExpression(expression: Expression, searchContext: Search loadNeededInfoFromDatabase(); } + // For autocomplete searches, use the dedicated autocomplete fuzzy option + // instead of the global fuzzy setting. + if (searchContext.autocomplete) { + searchContext.enableFuzzyMatching = optionService.getOptionBool("searchAutocompleteFuzzy"); + } + // If there's an explicit orderBy clause, skip progressive search // as it would interfere with the ordering if (searchContext.orderBy) { @@ -249,13 +255,6 @@ function findResultsWithExpression(expression: Expression, searchContext: Search return performSearch(expression, searchContext, false); } - // For autocomplete searches, use the dedicated autocomplete fuzzy option. - // Default is off for faster response; users can enable if they want typo tolerance. - if (searchContext.autocomplete) { - const autocompleteFuzzy = optionService.getOptionBool("searchAutocompleteFuzzy"); - return performSearch(expression, searchContext, autocompleteFuzzy); - } - // Phase 1: Try exact matches first (without fuzzy matching) const exactResults = performSearch(expression, searchContext, false); From 597c6eb15b86346bb620f6f7e9946e743a81a957 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 13 Apr 2026 13:13:29 +0300 Subject: [PATCH 092/482] chore(options): improve descriptions for search --- .../src/translations/en/translation.json | 6 ++-- .../widgets/type_widgets/options/other.tsx | 33 +++++++++++++------ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index abc3de3de4..25e6940e9a 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -1326,8 +1326,10 @@ }, "search": { "title": "Search", - "enable_fuzzy_matching": "Enable fuzzy matching in search (matches similar words when exact matches are insufficient)", - "enable_autocomplete_fuzzy": "Enable fuzzy matching for autocomplete (slower, but tolerates typos while typing)" + "fuzzy_matching_label": "Typo tolerance in search", + "fuzzy_matching_description": "Affects quick search and full search. Finds similar words when exact matches are insufficient.", + "autocomplete_fuzzy_label": "Typo tolerance in autocomplete", + "autocomplete_fuzzy_description": "Affects jump-to-note and note selectors. Slower but tolerates typos." }, "search_engine": { "title": "Search Engine", diff --git a/apps/client/src/widgets/type_widgets/options/other.tsx b/apps/client/src/widgets/type_widgets/options/other.tsx index b75c81b711..b1ccfcfcc0 100644 --- a/apps/client/src/widgets/type_widgets/options/other.tsx +++ b/apps/client/src/widgets/type_widgets/options/other.tsx @@ -14,7 +14,9 @@ import FormGroup from "../../react/FormGroup"; import FormSelect from "../../react/FormSelect"; import FormText from "../../react/FormText"; import FormTextBox, { FormTextBoxWithUnit } from "../../react/FormTextBox"; +import FormToggle from "../../react/FormToggle"; import { useTriliumOption, useTriliumOptionBool, useTriliumOptionJson } from "../../react/hooks"; +import OptionsRow from "./components/OptionsRow"; import OptionsSection from "./components/OptionsSection"; import TimeSelector from "./components/TimeSelector"; @@ -43,18 +45,29 @@ function SearchSettings() { return ( - - + + + + + label={t("search.autocomplete_fuzzy_label")} + description={t("search.autocomplete_fuzzy_description")} + > + + ); } From ead70ad39411248fc020c24d0d46f0308745a3ba Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 13 Apr 2026 13:20:42 +0300 Subject: [PATCH 093/482] fix(autocomplete): fuzzy search not working if the search one was not enabled --- apps/server/src/services/search/services/search.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/server/src/services/search/services/search.ts b/apps/server/src/services/search/services/search.ts index f9581aa170..ea1d20c263 100644 --- a/apps/server/src/services/search/services/search.ts +++ b/apps/server/src/services/search/services/search.ts @@ -236,12 +236,6 @@ function findResultsWithExpression(expression: Expression, searchContext: Search loadNeededInfoFromDatabase(); } - // For autocomplete searches, use the dedicated autocomplete fuzzy option - // instead of the global fuzzy setting. - if (searchContext.autocomplete) { - searchContext.enableFuzzyMatching = optionService.getOptionBool("searchAutocompleteFuzzy"); - } - // If there's an explicit orderBy clause, skip progressive search // as it would interfere with the ordering if (searchContext.orderBy) { @@ -415,6 +409,12 @@ function findResultsWithQuery(query: string, searchContext: SearchContext): Sear query = query || ""; searchContext.originalQuery = query; + // For autocomplete searches, use the dedicated autocomplete fuzzy option + // instead of the global fuzzy setting. Do this early so it applies to all code paths. + if (searchContext.autocomplete) { + searchContext.enableFuzzyMatching = optionService.getOptionBool("searchAutocompleteFuzzy"); + } + const expression = parseQueryToExpression(query, searchContext); if (!expression) { From 6763f4f40396f871f3c614f7d12aa780d516599b Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 13 Apr 2026 13:29:58 +0300 Subject: [PATCH 094/482] chore(becca): add log for cache memory consumption --- apps/server/src/becca/becca-interface.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/apps/server/src/becca/becca-interface.ts b/apps/server/src/becca/becca-interface.ts index 6d5d13d07b..f1e7c7fde3 100644 --- a/apps/server/src/becca/becca-interface.ts +++ b/apps/server/src/becca/becca-interface.ts @@ -1,4 +1,6 @@ import sql from "../services/sql.js"; +import log from "../services/log.js"; +import { formatSize } from "../services/utils.js"; import NoteSet from "../services/search/note_set.js"; import NotFoundError from "../errors/not_found_error.js"; import type BOption from "./entities/boption.js"; @@ -277,6 +279,9 @@ export default class Becca { */ getFlatTextIndex(): { notes: BNote[], flatTexts: string[], noteIdToIdx: Map } { if (!this.flatTextIndex) { + // Measure heap before building + const heapBefore = process.memoryUsage().heapUsed; + const allNoteSet = this.getAllNoteSet(); const notes: BNote[] = []; const flatTexts: string[] = []; @@ -290,6 +295,11 @@ export default class Becca { this.flatTextIndex = { notes, flatTexts, noteIdToIdx }; this.dirtyFlatTextNoteIds.clear(); + + // Measure heap after building and log + const heapAfter = process.memoryUsage().heapUsed; + const heapDelta = heapAfter - heapBefore; + log.info(`Flat text search index built: ${notes.length} notes, ${formatSize(heapDelta)}`); } else if (this.dirtyFlatTextNoteIds.size > 0) { // Incremental update: only recompute flat texts for dirtied notes const { flatTexts, noteIdToIdx } = this.flatTextIndex; From 885e94cf5873dabdcc0c553ed43bef197f0879f8 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 13 Apr 2026 13:30:53 +0300 Subject: [PATCH 095/482] test(server): migrate database --- apps/server/spec/db/document.db | Bin 8589312 -> 8597504 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/server/spec/db/document.db b/apps/server/spec/db/document.db index 371c3a132913b09d17f1697f7082db6787b77190..f5cf761826cf91e826c1d2b4cee48fed49c75cf9 100644 GIT binary patch delta 26394 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 delta 13264 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 J)s8Fd{{gPW;z|Gj From 301f23cd2d2f73e63c388e13758e438a804583aa Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 13 Apr 2026 13:38:06 +0300 Subject: [PATCH 096/482] test(server): clean up search scripts --- apps/server/spec/search_profiling.spec.ts | 306 ------------------ .../search/services/search_benchmark.spec.ts | 4 +- 2 files changed, 3 insertions(+), 307 deletions(-) delete mode 100644 apps/server/spec/search_profiling.spec.ts diff --git a/apps/server/spec/search_profiling.spec.ts b/apps/server/spec/search_profiling.spec.ts deleted file mode 100644 index 8099a322b4..0000000000 --- a/apps/server/spec/search_profiling.spec.ts +++ /dev/null @@ -1,306 +0,0 @@ -/** - * Integration-level search profiling test. - * - * Uses the real SQLite database (spec/db/document.db loaded in-memory), - * real sql module, real becca cache, and the full app stack. - * - * Profiles search at large scale (50K+ notes) to match real-world - * performance reports from users with 240K+ notes. - */ -import { Application } from "express"; -import { beforeAll, describe, expect, it } from "vitest"; -import config from "../src/services/config.js"; - -let app: Application; - -function timed(fn: () => T): [T, number] { - const start = performance.now(); - const result = fn(); - return [result, performance.now() - start]; -} - -function randomId(len = 12): string { - const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - let id = ""; - for (let i = 0; i < len; i++) id += chars[Math.floor(Math.random() * chars.length)]; - return id; -} - -function randomWord(len = 8): string { - const chars = "abcdefghijklmnopqrstuvwxyz"; - let w = ""; - for (let i = 0; i < len; i++) w += chars[Math.floor(Math.random() * chars.length)]; - return w; -} - -function generateContent(wordCount: number, keyword?: string): string { - const paragraphs: string[] = []; - let remaining = wordCount; - let injected = false; - while (remaining > 0) { - const n = Math.min(remaining, 30 + Math.floor(Math.random() * 30)); - const words: string[] = []; - for (let i = 0; i < n; i++) words.push(randomWord(3 + Math.floor(Math.random() * 10))); - if (keyword && !injected && remaining < wordCount / 2) { - words[Math.floor(words.length / 2)] = keyword; - injected = true; - } - paragraphs.push(`

${words.join(" ")}

`); - remaining -= n; - } - return paragraphs.join("\n"); -} - -describe("Search profiling (integration)", () => { - beforeAll(async () => { - config.General.noAuthentication = true; - const buildApp = (await import("../src/app.js")).default; - app = await buildApp(); - }); - - it("large-scale profiling (50K notes)", async () => { - const sql = (await import("../src/services/sql.js")).default; - const becca = (await import("../src/becca/becca.js")).default; - const beccaLoader = (await import("../src/becca/becca_loader.js")).default; - const cls = (await import("../src/services/cls.js")).default; - const searchService = (await import("../src/services/search/services/search.js")).default; - const SearchContext = (await import("../src/services/search/search_context.js")).default; - const beccaService = (await import("../src/becca/becca_service.js")).default; - - await new Promise((resolve) => { - cls.init(() => { - const initialNoteCount = Object.keys(becca.notes).length; - console.log(`\n Initial becca notes: ${initialNoteCount}`); - - // ── Seed 50K notes with hierarchy ── - // Some folders (depth), some with common keyword "test" in title - const TOTAL_NOTES = 50000; - const FOLDER_COUNT = 500; // 500 folders - const NOTES_PER_FOLDER = (TOTAL_NOTES - FOLDER_COUNT) / FOLDER_COUNT; // ~99 notes per folder - const MATCH_FRACTION = 0.10; // 10% match "test" — ~5000 notes - const CONTENT_WORDS = 500; - - const now = new Date().toISOString().replace("T", " ").replace("Z", "+0000"); - console.log(` Seeding ${TOTAL_NOTES} notes (${FOLDER_COUNT} folders, ~${NOTES_PER_FOLDER.toFixed(0)} per folder)...`); - - const [, seedMs] = timed(() => { - sql.transactional(() => { - const folderIds: string[] = []; - - // Create folders under root - for (let f = 0; f < FOLDER_COUNT; f++) { - const noteId = `seed${randomId(8)}`; - const branchId = `seed${randomId(8)}`; - const blobId = `seed${randomId(16)}`; - folderIds.push(noteId); - - sql.execute( - `INSERT INTO blobs (blobId, content, dateModified, utcDateModified) VALUES (?, ?, ?, ?)`, - [blobId, `

Folder ${f}

`, now, now] - ); - sql.execute( - `INSERT INTO notes (noteId, title, type, mime, blobId, isProtected, isDeleted, - dateCreated, dateModified, utcDateCreated, utcDateModified) - VALUES (?, ?, 'text', 'text/html', ?, 0, 0, ?, ?, ?, ?)`, - [noteId, `Folder ${f} ${randomWord(5)}`, blobId, now, now, now, now] - ); - sql.execute( - `INSERT INTO branches (branchId, noteId, parentNoteId, notePosition, isDeleted, isExpanded, utcDateModified) - VALUES (?, ?, 'root', ?, 0, 0, ?)`, - [branchId, noteId, f * 10, now] - ); - } - - // Create notes under folders - let noteIdx = 0; - for (let f = 0; f < FOLDER_COUNT; f++) { - const parentId = folderIds[f]; - for (let n = 0; n < NOTES_PER_FOLDER; n++) { - const isMatch = noteIdx < TOTAL_NOTES * MATCH_FRACTION; - const noteId = `seed${randomId(8)}`; - const branchId = `seed${randomId(8)}`; - const blobId = `seed${randomId(16)}`; - const title = isMatch - ? `Test Document ${noteIdx} ${randomWord(6)}` - : `Note ${noteIdx} ${randomWord(6)} ${randomWord(5)}`; - const content = generateContent(CONTENT_WORDS, isMatch ? "test" : undefined); - - sql.execute( - `INSERT INTO blobs (blobId, content, dateModified, utcDateModified) VALUES (?, ?, ?, ?)`, - [blobId, content, now, now] - ); - sql.execute( - `INSERT INTO notes (noteId, title, type, mime, blobId, isProtected, isDeleted, - dateCreated, dateModified, utcDateCreated, utcDateModified) - VALUES (?, ?, 'text', 'text/html', ?, 0, 0, ?, ?, ?, ?)`, - [noteId, title, blobId, now, now, now, now] - ); - sql.execute( - `INSERT INTO branches (branchId, noteId, parentNoteId, notePosition, isDeleted, isExpanded, utcDateModified) - VALUES (?, ?, ?, ?, 0, 0, ?)`, - [branchId, noteId, parentId, n * 10, now] - ); - noteIdx++; - } - } - }); - }); - console.log(` SQL seeding: ${seedMs.toFixed(0)}ms`); - - const [, reloadMs] = timed(() => beccaLoader.load()); - const totalNotes = Object.keys(becca.notes).length; - console.log(` Becca reload: ${reloadMs.toFixed(0)}ms Total notes: ${totalNotes}`); - - // ── Warm caches ── - searchService.searchNotesForAutocomplete("test", true); - - // ════════════════════════════════════════════ - // PROFILING AT SCALE - // ════════════════════════════════════════════ - - console.log(`\n ════ PROFILING (${totalNotes} notes) ════\n`); - - // 1. getCandidateNotes cost (the full-scan bottleneck) - const allNotes = Object.values(becca.notes); - const [, flatScanMs] = timed(() => { - let count = 0; - for (const note of allNotes) { - const ft = note.getFlatText(); - if (ft.includes("test")) count++; - } - return count; - }); - console.log(` getFlatText + includes scan (${allNotes.length} notes): ${flatScanMs.toFixed(1)}ms`); - - // 2. Full findResultsWithQuery (includes candidate scan + parent walk + scoring) - const findTimes: number[] = []; - let findResultCount = 0; - for (let i = 0; i < 3; i++) { - const [r, ms] = timed(() => - searchService.findResultsWithQuery("test", new SearchContext({ fastSearch: true })) - ); - findTimes.push(ms); - findResultCount = r.length; - } - const findAvg = findTimes.reduce((a, b) => a + b, 0) / findTimes.length; - console.log(` findResultsWithQuery (fast): avg ${findAvg.toFixed(1)}ms (${findResultCount} results)`); - - // 3. Exact-only (no fuzzy) - const exactTimes: number[] = []; - for (let i = 0; i < 3; i++) { - const [, ms] = timed(() => - searchService.findResultsWithQuery("test", new SearchContext({ fastSearch: true, enableFuzzyMatching: false })) - ); - exactTimes.push(ms); - } - const exactAvg = exactTimes.reduce((a, b) => a + b, 0) / exactTimes.length; - console.log(` findResultsWithQuery (exact): avg ${exactAvg.toFixed(1)}ms`); - console.log(` Fuzzy overhead: ${(findAvg - exactAvg).toFixed(1)}ms`); - - // 4. SearchResult construction + computeScore cost (isolated) - const results = searchService.findResultsWithQuery("test", new SearchContext({ fastSearch: true })); - console.log(` Total results before trim: ${results.length}`); - - const [, scoreAllMs] = timed(() => { - for (const r of results) r.computeScore("test", ["test"], true); - }); - console.log(` computeScore × ${results.length}: ${scoreAllMs.toFixed(1)}ms (${(scoreAllMs / results.length).toFixed(3)}ms/result)`); - - // 5. getNoteTitleForPath for all results - const [, pathTitleMs] = timed(() => { - for (const r of results) beccaService.getNoteTitleForPath(r.notePathArray); - }); - console.log(` getNoteTitleForPath × ${results.length}: ${pathTitleMs.toFixed(1)}ms`); - - // 6. Content snippet extraction (only 200) - const trimmed = results.slice(0, 200); - const [, snippetMs] = timed(() => { - for (const r of trimmed) { - r.contentSnippet = searchService.extractContentSnippet(r.noteId, ["test"]); - } - }); - console.log(` extractContentSnippet × 200: ${snippetMs.toFixed(1)}ms`); - - // 7. Highlighting (only 200) - const [, hlMs] = timed(() => { - searchService.highlightSearchResults(trimmed, ["test"]); - }); - console.log(` highlightSearchResults × 200: ${hlMs.toFixed(1)}ms`); - - // 7b. getBestNotePath cost (used by fast path) - const sampleNotes = Object.values(becca.notes).filter(n => n.title.startsWith("Test Document")).slice(0, 1000); - const [, bestPathMs] = timed(() => { - for (const n of sampleNotes) n.getBestNotePath(); - }); - console.log(` getBestNotePath × ${sampleNotes.length}: ${bestPathMs.toFixed(1)}ms (${(bestPathMs/sampleNotes.length).toFixed(3)}ms/note)`); - - // 8. Full autocomplete end-to-end - const autoTimes: number[] = []; - let autoCount = 0; - for (let i = 0; i < 3; i++) { - const [r, ms] = timed(() => - searchService.searchNotesForAutocomplete("test", true) - ); - autoTimes.push(ms); - autoCount = r.length; - } - const autoAvg = autoTimes.reduce((a, b) => a + b, 0) / autoTimes.length; - const autoMin = Math.min(...autoTimes); - console.log(`\n ★ FULL AUTOCOMPLETE: avg ${autoAvg.toFixed(1)}ms min ${autoMin.toFixed(1)}ms (${autoCount} results)`); - - // 9. With a less common search term (fewer matches) - const rareTimes: number[] = []; - let rareCount = 0; - for (let i = 0; i < 3; i++) { - const [r, ms] = timed(() => - searchService.searchNotesForAutocomplete("leitfaden", true) - ); - rareTimes.push(ms); - rareCount = r.length; - } - const rareAvg = rareTimes.reduce((a, b) => a + b, 0) / rareTimes.length; - console.log(` Autocomplete "leitfaden": avg ${rareAvg.toFixed(1)}ms (${rareCount} results)`); - - // 10. Full search (fastSearch=false) — the 2.7s bottleneck - console.log(`\n ── Full search (fastSearch=false) ──`); - const fullTimes: number[] = []; - let fullCount = 0; - for (let i = 0; i < 2; i++) { - const [r, ms] = timed(() => - searchService.findResultsWithQuery("test", new SearchContext({ fastSearch: false })) - ); - fullTimes.push(ms); - fullCount = r.length; - } - const fullAvg = fullTimes.reduce((a, b) => a + b, 0) / fullTimes.length; - console.log(` Full search (flat + SQL): avg ${fullAvg.toFixed(1)}ms (${fullCount} results)`); - - // 11. SQL content scan alone - const [scanCount, scanMs] = timed(() => { - let count = 0; - for (const row of sql.iterateRows<{ content: Buffer | string }>(` - SELECT noteId, type, mime, content, isProtected - FROM notes JOIN blobs USING (blobId) - WHERE type IN ('text', 'code', 'mermaid', 'canvas', 'mindMap') - AND isDeleted = 0 - AND LENGTH(content) < 2097152`)) { - count++; - } - return count; - }); - console.log(` Raw SQL scan (${scanCount} rows): ${scanMs.toFixed(1)}ms`); - - // ── Summary ── - console.log(`\n ════ SUMMARY ════`); - console.log(` Notes: ${totalNotes} | Matches: ${findResultCount} | Hierarchy depth: 3 (root → folder → note)`); - console.log(` ──────────────────────────────────`); - console.log(` Autocomplete (fast): ${autoAvg.toFixed(1)}ms`); - console.log(` findResults: ${findAvg.toFixed(1)}ms (${((findAvg/autoAvg)*100).toFixed(0)}%)`); - console.log(` snippets+highlight: ${(snippetMs + hlMs).toFixed(1)}ms (${(((snippetMs+hlMs)/autoAvg)*100).toFixed(0)}%)`); - console.log(` Full search: ${fullAvg.toFixed(1)}ms`); - - resolve(); - }); - }); - }, 600_000); -}); diff --git a/apps/server/src/services/search/services/search_benchmark.spec.ts b/apps/server/src/services/search/services/search_benchmark.spec.ts index 53319ff9cd..c3ece17fb5 100644 --- a/apps/server/src/services/search/services/search_benchmark.spec.ts +++ b/apps/server/src/services/search/services/search_benchmark.spec.ts @@ -281,7 +281,9 @@ function printTable(title: string, results: BenchmarkResult[]) { // ── tests ──────────────────────────────────────────────────────────── -describe("Comprehensive Search Benchmark", () => { +// Skipped by default - this is a benchmark, not a test. +// Remove .skip to run manually for performance analysis. +describe.skip("Comprehensive Search Benchmark", () => { afterEach(() => { becca.reset(); From e40504b7f06adab6f8147f072d62d559da275177 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 13 Apr 2026 13:43:25 +0300 Subject: [PATCH 097/482] chore(search): address requested changes --- apps/server/src/becca/entities/battribute.ts | 5 +++++ apps/server/src/services/search/services/search.ts | 7 ++++--- apps/server/src/services/search/utils/text_utils.ts | 4 +++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/apps/server/src/becca/entities/battribute.ts b/apps/server/src/becca/entities/battribute.ts index 77a15c2fd1..dbb6502113 100644 --- a/apps/server/src/becca/entities/battribute.ts +++ b/apps/server/src/becca/entities/battribute.ts @@ -202,6 +202,11 @@ class BAttribute extends AbstractBeccaEntity { this.utcDateModified = dateUtils.utcNowDateTime(); + // Recompute normalized fields in case name/value were modified directly + // (e.g., attr.value = "..." followed by attr.save()) + this.normalizedName = normalize(this.name); + this.normalizedValue = normalize(this.value); + super.beforeSaving(); this.becca.attributes[this.attributeId] = this; diff --git a/apps/server/src/services/search/services/search.ts b/apps/server/src/services/search/services/search.ts index ea1d20c263..0523aeb98f 100644 --- a/apps/server/src/services/search/services/search.ts +++ b/apps/server/src/services/search/services/search.ts @@ -595,10 +595,11 @@ function extractAttributeSnippet(noteId: string, searchTokens: string[], maxLeng // Look for attributes that match the search tokens for (const attr of attributes) { - const attrName = attr.name?.toLowerCase() || ""; - const attrValue = attr.value?.toLowerCase() || ""; + // Use pre-normalized fields from BAttribute for diacritic-insensitive matching + const attrName = attr.normalizedName || normalize(attr.name || ""); + const attrValue = attr.normalizedValue || normalize(attr.value || ""); const attrType = attr.type || ""; - + // Check if any search token matches the attribute name or value const hasMatch = searchTokens.some(token => { const normalizedToken = normalize(token); diff --git a/apps/server/src/services/search/utils/text_utils.ts b/apps/server/src/services/search/utils/text_utils.ts index 7528571f86..1993924555 100644 --- a/apps/server/src/services/search/utils/text_utils.ts +++ b/apps/server/src/services/search/utils/text_utils.ts @@ -282,7 +282,9 @@ export function fuzzyMatchWordWithResult(token: string, text: string, maxDistanc // Exact match check first (most common case) if (normalizedText.includes(normalizedToken)) { - return token; + // Find the exact match position and return the original substring with case preserved + const matchIndex = normalizedText.indexOf(normalizedToken); + return text.substring(matchIndex, matchIndex + normalizedToken.length); } // For fuzzy matching, split into words and check each against the token From f58dd12983cbdd1cdf47b9e72991b721271df4c9 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 13 Apr 2026 14:03:17 +0300 Subject: [PATCH 098/482] chore(search): use loop to prevent nested strip tags injection --- .../src/services/search/services/search.ts | 6 +- .../services/search/utils/text_utils.spec.ts | 67 ++++++++++++++++++- .../src/services/search/utils/text_utils.ts | 24 +++++++ 3 files changed, 93 insertions(+), 4 deletions(-) diff --git a/apps/server/src/services/search/services/search.ts b/apps/server/src/services/search/services/search.ts index 0523aeb98f..97bfc457a4 100644 --- a/apps/server/src/services/search/services/search.ts +++ b/apps/server/src/services/search/services/search.ts @@ -8,6 +8,7 @@ import SearchContext from "../search_context.js"; import becca from "../../../becca/becca.js"; import beccaService from "../../../becca/becca_service.js"; import { normalize, removeDiacritic, escapeHtml, escapeRegExp } from "../../utils.js"; +import { stripHtmlTags } from "../utils/text_utils.js"; import log from "../../log.js"; import hoistedNoteService from "../../hoisted_note.js"; import type BNote from "../../../becca/entities/bnote.js"; @@ -494,10 +495,9 @@ function extractContentSnippet(noteId: string, searchTokens: string[], maxLength return ""; // Protected but no session available } - // Strip HTML tags for text notes — use fast regex for snippet extraction - // (striptags library is ~18x slower and not needed for search snippets) + // Strip HTML tags for text notes if (note.type === "text") { - content = content.replace(/<[^>]*>/g, ""); + content = stripHtmlTags(content); } if (!content) { diff --git a/apps/server/src/services/search/utils/text_utils.spec.ts b/apps/server/src/services/search/utils/text_utils.spec.ts index a5f1da129d..146f5cc0fe 100644 --- a/apps/server/src/services/search/utils/text_utils.spec.ts +++ b/apps/server/src/services/search/utils/text_utils.spec.ts @@ -1,5 +1,5 @@ import { describe, it, expect } from "vitest"; -import { calculateOptimizedEditDistance, validateFuzzySearchTokens, fuzzyMatchWord } from './text_utils.js'; +import { calculateOptimizedEditDistance, validateFuzzySearchTokens, fuzzyMatchWord, stripHtmlTags } from './text_utils.js'; describe('Fuzzy Search Core', () => { describe('calculateOptimizedEditDistance', () => { @@ -62,4 +62,69 @@ describe('Fuzzy Search Core', () => { expect(fuzzyMatchWord('a', 'b')).toBe(false); // Very short tokens }); }); + + describe('stripHtmlTags', () => { + it('strips simple HTML tags', () => { + expect(stripHtmlTags('

Hello

')).toBe('Hello'); + expect(stripHtmlTags('
World
')).toBe('World'); + expect(stripHtmlTags('Bold and italic')).toBe('Bold and italic'); + }); + + it('handles self-closing tags', () => { + expect(stripHtmlTags('Line1
Line2')).toBe('Line1Line2'); + expect(stripHtmlTags('Image: ')).toBe('Image: '); + }); + + it('handles tags with attributes', () => { + expect(stripHtmlTags('Link')).toBe('Link'); + expect(stripHtmlTags('
Content
')).toBe('Content'); + }); + + it('handles nested tag patterns securely', () => { + // Security property: no complete patterns remain after stripping + // Residual `>` chars are harmless for XSS + + // Nested tags: inner tag removed, then outer tag removed + // c> → → '' (but leaves residual `c>`) + const result1 = stripHtmlTags('c>text'); + expect(result1).not.toMatch(/<[a-z]/i); // No opening tags remain + expect(result1).toBe('c>text'); // Residual text is safe + + // Complex nesting leaves no exploitable patterns + const result2 = stripHtmlTags('ipt>alert(1)'); + expect(result2).not.toMatch(/ + + diff --git a/scripts/electron-repros/printpdf-page-range/main.js b/scripts/electron-repros/printpdf-page-range/main.js new file mode 100644 index 0000000000..7c7a283d88 --- /dev/null +++ b/scripts/electron-repros/printpdf-page-range/main.js @@ -0,0 +1,53 @@ +const { app, BrowserWindow, ipcMain } = require("electron"); + +let mainWindow; + +app.whenReady().then(() => { + mainWindow = new BrowserWindow({ + width: 800, + height: 600, + webPreferences: { + nodeIntegration: true, + contextIsolation: false, + }, + }); + mainWindow.loadFile("index.html"); +}); + +ipcMain.handle("print-test", async (_e, { pageRanges, step }) => { + const printWindow = new BrowserWindow({ + show: false, + width: 1, + height: 1, + webPreferences: { offscreen: process.platform !== "linux" }, + }); + + await printWindow.loadFile("print-page.html"); + + // Wait for content to be ready. + await printWindow.webContents.executeJavaScript( + `new Promise(r => requestAnimationFrame(() => requestAnimationFrame(r)))` + ); + + const opts = { + landscape: false, + pageSize: "A4", + scale: 1, + printBackground: true, + // Only include pageRanges if truthy (non-empty string). + ...(pageRanges ? { pageRanges } : {}), + }; + + console.log(`[Step ${step}] printToPDF called with:`, JSON.stringify(opts)); + + try { + const buffer = await printWindow.webContents.printToPDF(opts); + console.log(`[Step ${step}] SUCCESS - buffer size: ${buffer.length}`); + printWindow.destroy(); + return { ok: true, size: buffer.length }; + } catch (err) { + console.error(`[Step ${step}] FAILED: ${err.message}`); + printWindow.destroy(); + return { ok: false, error: err.message }; + } +}); diff --git a/scripts/electron-repros/printpdf-page-range/package.json b/scripts/electron-repros/printpdf-page-range/package.json new file mode 100644 index 0000000000..5c380d9a96 --- /dev/null +++ b/scripts/electron-repros/printpdf-page-range/package.json @@ -0,0 +1,13 @@ +{ + "name": "electron-printpdf-page-range-repro", + "version": "1.0.0", + "private": true, + "description": "Minimal repro for Electron printToPDF state corruption after an invalid pageRanges failure", + "main": "main.js", + "scripts": { + "start": "electron ." + }, + "devDependencies": { + "electron": "^35.0.0" + } +} diff --git a/scripts/electron-repros/printpdf-page-range/print-page.html b/scripts/electron-repros/printpdf-page-range/print-page.html new file mode 100644 index 0000000000..04eb11623d --- /dev/null +++ b/scripts/electron-repros/printpdf-page-range/print-page.html @@ -0,0 +1,8 @@ + + +Print Test + +

Test Page

+

This is a single-page document used to reproduce the printToPDF bug.

+ + From 9bd78c5f837a566a0a3e4923d384e169d064de7c Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Wed, 15 Apr 2026 22:45:23 +0300 Subject: [PATCH 210/482] feat(print): display detailed error on print failure --- apps/client/src/widgets/dialogs/print_preview.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/client/src/widgets/dialogs/print_preview.tsx b/apps/client/src/widgets/dialogs/print_preview.tsx index 4720349d6a..c99e63cd17 100644 --- a/apps/client/src/widgets/dialogs/print_preview.tsx +++ b/apps/client/src/widgets/dialogs/print_preview.tsx @@ -170,7 +170,7 @@ export default function PrintPreviewDialog() { toast.showPersistent({ id: "print-preview-error", icon: "bx bx-error-circle", - message: t("print_preview.render_error") + message: `${t("print_preview.render_error")}\n\n${error}` }); return; } From 98d718031b7e965f36dd02edfa175a702416cb2e Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Wed, 15 Apr 2026 22:46:15 +0300 Subject: [PATCH 211/482] test(commons): fix failure in locale --- packages/commons/src/lib/dayjs.spec.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/commons/src/lib/dayjs.spec.ts b/packages/commons/src/lib/dayjs.spec.ts index 3f3d9e5dad..37d9ff9435 100644 --- a/packages/commons/src/lib/dayjs.spec.ts +++ b/packages/commons/src/lib/dayjs.spec.ts @@ -14,6 +14,8 @@ import { describe, expect, it } from "vitest"; describe("dayjs", () => { it("all dayjs locales are valid", async () => { for (const locale of LOCALES) { + if (locale.contentOnly) continue; + const dayjsLoader = DAYJS_LOADER[locale.id]; expect(dayjsLoader, `Locale ${locale.id} missing.`).toBeDefined(); From 3bd98d6a1b67e85f92a5fd6c6aca445d42f15fc8 Mon Sep 17 00:00:00 2001 From: Ulices Date: Tue, 14 Apr 2026 22:09:58 +0200 Subject: [PATCH 212/482] Translated using Weblate (Spanish) Currently translated at 100.0% (403 of 403 strings) Translation: Trilium Notes/Server Translate-URL: https://hosted.weblate.org/projects/trilium/server/es/ --- .../src/assets/translations/es/server.json | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/apps/server/src/assets/translations/es/server.json b/apps/server/src/assets/translations/es/server.json index 36ba41a88f..a08f131b93 100644 --- a/apps/server/src/assets/translations/es/server.json +++ b/apps/server/src/assets/translations/es/server.json @@ -200,7 +200,8 @@ }, "quarterNumber": "Cuarto {quarterNumber}", "special_notes": { - "search_prefix": "Buscar:" + "search_prefix": "Buscar:", + "llm_chat_prefix": "Chat:" }, "test_sync": { "not-configured": "El servidor de sincronización no está configurado. Por favor configure primero la sincronización.", @@ -242,7 +243,7 @@ "shortcuts-title": "Atajos", "text-notes": "Notas de texto", "code-notes-title": "Notas de código", - "images-title": "Imágenes", + "images-title": "Medios", "spellcheck-title": "Corrección ortográfica", "password-title": "Contraseña", "multi-factor-authentication-title": "MFA", @@ -258,7 +259,11 @@ "jump-to-note-title": "Saltar a...", "command-palette": "Abrir paleta de comandos", "zen-mode": "Modo Zen", - "tab-switcher-title": "Conmutador de pestañas" + "tab-switcher-title": "Conmutador de pestañas", + "llm-chat-history-title": "Historial del chat de AI", + "custom-dictionary-title": "Diccionario personalizado", + "llm-title": "IA / LLM", + "sidebar-chat-title": "Chat de IA" }, "notes": { "new-note": "Nueva nota", @@ -304,7 +309,10 @@ "last-updated": "Última actualización en {{-date}}", "subpages": "Subpáginas:", "on-this-page": "En esta página", - "expand": "Expandir" + "expand": "Expandir", + "toggle-navigation": "Alternar navegación", + "toggle-toc": "Alternar tabla de contenido", + "logo-alt": "Logo" }, "keyboard_action_names": { "jump-to-note": "Saltar a...", @@ -437,5 +445,21 @@ }, "desktop": { "instance_already_running": "Ya hay una instancia en ejecución, enfocando esa instancia en su lugar." + }, + "password": { + "incorrect": "La contraseña que ha introducido es incorrecta." + }, + "script": { + "wrong-environment": "No se puede ejecutar la nota \"{{- noteTitle}}\" ({{- noteId}}). Este es un script de {{- actualEnv}}, pero la ejecución se intentó en {{- expectedEnv}}." + }, + "search": { + "error": { + "in-context": "Error en {{- context}}: {{- message}}", + "reserved-keyword": "\"{{- token}}\" es una palabra clave reservada. Para buscar un valor literal, utilice comillas: \"{{- token}}\"", + "cannot-compare-with": "no se puede comparar con \"{{- token}}\". Para buscar un valor literal, utilice ccomillas: \"{{- token}}\"", + "misplaced-expression": "Expresión errónea o incompleta \"{{- token}}\"", + "fulltext-after-expression": "\"{{- token}}\" no es una expresión válida. Para buscar texto, colóquela antes de filtros de atributo (por ejemplo, \"{{- token}} #label\" en lugar de \"#label {{- token}}\").", + "unrecognized-expression": "Expresión no reconocida \"{{- token}}\"" + } } } From 3ed62970111dded74001865e423038b1d5c0c516 Mon Sep 17 00:00:00 2001 From: Marcel Date: Tue, 14 Apr 2026 22:42:59 +0200 Subject: [PATCH 213/482] Translated using Weblate (German) Currently translated at 91.8% (1726 of 1880 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/ --- .../src/translations/de/translation.json | 216 ++++++++++++++---- 1 file changed, 172 insertions(+), 44 deletions(-) diff --git a/apps/client/src/translations/de/translation.json b/apps/client/src/translations/de/translation.json index 24b3915b36..1efdafdc6e 100644 --- a/apps/client/src/translations/de/translation.json +++ b/apps/client/src/translations/de/translation.json @@ -92,10 +92,18 @@ "delete_all_clones_description": "auch alle Klone löschen (kann bei letzte Änderungen rückgängig gemacht werden)", "erase_notes_description": "Beim normalen (vorläufigen) Löschen werden die Notizen nur als gelöscht markiert und sie können innerhalb eines bestimmten Zeitraums (im Dialogfeld „Letzte Änderungen“) wiederhergestellt werden. Wenn du diese Option aktivierst, werden die Notizen sofort gelöscht und es ist nicht möglich, die Notizen wiederherzustellen.", "erase_notes_warning": "Notizen dauerhaft löschen (kann nicht rückgängig gemacht werden), einschließlich aller Klone. Dadurch wird ein Neuladen der Anwendung erzwungen.", - "notes_to_be_deleted": "Folgende Notizen werden gelöscht ({{notesCount}})", + "notes_to_be_deleted": "({{notesCount}}) Notizen werden gelöscht", "no_note_to_delete": "Es werden keine Notizen gelöscht (nur Klone).", - "broken_relations_to_be_deleted": "Folgende Beziehungen werden gelöst und gelöscht ({{ relationCount}})", - "cancel": "Abbrechen" + "broken_relations_to_be_deleted": "Unterbrochene Beziehungen ({{relationCount}})", + "cancel": "Abbrechen", + "title": "Notizen löschen", + "clones_label": "Duplikate", + "delete_clones_description_one": "Löscht {{count}} weiteres Duplikat. Kann unter „Letzte Änderungen“ rückgängig gemacht werden.", + "delete_clones_description_other": "Löscht {{count}} weitere Duplikate. Kann unter „Letzte Änderungen“ rückgängig gemacht werden.", + "erase_notes_label": "Permanent löschen", + "table_note_with_relation": "Notiz mit Beziehung", + "table_relation": "Beziehung", + "delete": "Löschen" }, "export": { "export_note_title": "Notiz exportieren", @@ -338,7 +346,7 @@ "calendar_root": "Markiert eine Notiz, die als Basis für Tagesnotizen verwendet werden soll. Nur einer sollte als solcher gekennzeichnet sein.", "archived": "Notizen mit dieser Bezeichnung werden standardmäßig nicht in den Suchergebnissen angezeigt (auch nicht in den Dialogen „Springen zu“, „Link hinzufügen“ usw.).", "exclude_from_export": "Notizen (mit ihrem Unterbaum) werden nicht im Notizexport inkludiert", - "run": "Definiert, bei welchen Ereignissen das Skript ausgeführt werden soll. Mögliche Werte sind:\n
    \n
  • frontendStartup - wenn das Trilium-Frontend startet (oder aktualisiert wird), außer auf mobilen Geräten.
  • \n
  • mobileStartup - wenn das Trilium-Frontend auf einem mobilen Gerät startet (oder aktualisiert wird).
  • \n
  • backendStartup - wenn das Trilium-Backend startet
  • \n
  • hourly - einmal pro Stunde ausführen. Du kannst das zusätzliche Label runAtHour verwenden, um die genaue Stunde festzulegen.
  • \n
  • daily - einmal pro Tag ausführen
  • \n
", + "run": "Definiert bei welchen Ereignissen das Skript ausgeführt werden soll. Mögliche Werte sind:\n
    \n
  • frontendStartup - wenn das Trilium-Frontend startet (oder aktualisiert wird), außer auf mobilen Geräten.
  • \n
  • mobileStartup - wenn das Trilium-Frontend auf einem mobilen Gerät startet (oder aktualisiert wird).
  • \n
  • backendStartup - wenn das Trilium-Backend startet.
  • \n
  • hourly - einmal pro Stunde ausführen. Du kannst das zusätzliche Label runAtHour verwenden, um die genaue Stunde festzulegen.
  • \n
  • daily - einmal pro Tag ausführen
  • \n
", "run_on_instance": "Definiere, auf welcher Trilium-Instanz dies ausgeführt werden soll. Standardmäßig alle Instanzen.", "run_at_hour": "Zu welcher Stunde soll das laufen? Sollte zusammen mit #runu003dhourly verwendet werden. Kann für mehr Läufe im Laufe des Tages mehrfach definiert werden.", "disable_inclusion": "Skripte mit dieser Bezeichnung werden nicht in die Ausführung des übergeordneten Skripts einbezogen.", @@ -676,7 +684,8 @@ "export_as_image_svg": "SVG (Vektor)", "note_map": "Notizen Karte", "view_revisions": "Notizrevisionen...", - "advanced": "Erweitert" + "advanced": "Erweitert", + "view_ocr_text": "OCR text anzeigen" }, "onclick_button": { "no_click_handler": "Das Schaltflächen-Widget „{{componentId}}“ hat keinen definierten Klick-Handler" @@ -772,7 +781,10 @@ "expand_tooltip": "Erweitert die direkten Unterelemente dieser Sammlung (eine Ebene tiefer). Für weitere Optionen auf den Pfeil rechts klicken.", "expand_first_level": "Direkte Unterelemente erweitern", "expand_nth_level": "{{depth}} Ebenen erweitern", - "hide_child_notes": "Untergeordnete Notizen im Baum ausblenden" + "hide_child_notes": "Untergeordnete Notizen im Baum ausblenden", + "open_all_in_tabs": "Alle öffnen", + "open_all_in_tabs_tooltip": "Alle Resultate in neuen Tabs öffnen", + "open_all_confirm": "Dies öffnet {{count}} Notizen in neuen Tabs. Fortfahren?" }, "edited_notes": { "no_edited_notes_found": "An diesem Tag wurden noch keine Notizen bearbeitet...", @@ -826,7 +838,8 @@ "collapse": "Auf normale Größe reduzieren", "title": "Notizkarte", "fix-nodes": "Knoten fixieren", - "link-distance": "Verbindungslänge" + "link-distance": "Verbindungslänge", + "too-many-notes": "Dieser Unterbaum enthält {{count}} Notizen, welche die Limitierung von {{max}} überschreitet die in der Notizkarte dargestellt werden können." }, "note_paths": { "title": "Notizpfade", @@ -874,7 +887,7 @@ "limit": "Limit", "limit_description": "Begrenze die Anzahl der Ergebnisse", "debug": "debuggen", - "debug_description": "Debug gibt zusätzliche Debuginformationen in die Konsole aus, um das Debuggen komplexer Abfragen zu erleichtern", + "debug_description": "Debug gibt zusätzliche Protokolleinträge in der Konsole aus, um die Fehlerdiagnose komplexer Abfragen zu erleichtern", "action": "Aktion", "search_button": "Suchen", "search_execute": "Aktionen suchen und ausführen", @@ -906,7 +919,7 @@ }, "debug": { "debug": "Debuggen", - "debug_info": "Debug gibt zusätzliche Debuginformationen in die Konsole aus, um das Debuggen komplexer Abfragen zu erleichtern.", + "debug_info": "Debug gibt zusätzliche Protokolleinträge in der Konsole aus, um die Fehlerdiagnose komplexer Abfragen zu erleichtern.", "access_info": "Um auf die Debug-Informationen zuzugreifen, führe die Abfrage aus und klicke oben links auf \"Backend-Log anzeigen\"." }, "fast_search": { @@ -1031,7 +1044,8 @@ "note_already_in_diagram": "Die Notiz \"{{title}}\" ist schon im Diagram.", "enter_title_of_new_note": "Gebe den Titel der neuen Notiz ein", "default_new_note_title": "neue Notiz", - "click_on_canvas_to_place_new_note": "Klicke auf den Canvas, um eine neue Notiz zu platzieren" + "click_on_canvas_to_place_new_note": "Klicke auf den Canvas, um eine neue Notiz zu platzieren", + "rename_relation": "Beziehung umbenennen" }, "backend_log": { "refresh": "Aktualisieren" @@ -1040,15 +1054,17 @@ "title": "Konsistenzprüfungen", "find_and_fix_button": "Finde und behebe die Konsistenzprobleme", "finding_and_fixing_message": "Konsistenzprobleme finden und beheben...", - "issues_fixed_message": "Konsistenzprobleme sollten behoben werden." + "issues_fixed_message": "Konsistenzprobleme sollten behoben werden.", + "find_and_fix_label": "Finde und behebe Konsistenzprobleme", + "find_and_fix_description": "Suche nach Probleme mit der Datenkonsistenz in der Datenbank und repariere diese automatisch." }, "database_anonymization": { "title": "Datenbankanonymisierung", "full_anonymization": "Vollständige Anonymisierung", - "full_anonymization_description": "Durch diese Aktion wird eine neue Kopie der Datenbank erstellt und anonymisiert (der gesamte Notizinhalt wird entfernt und nur die Struktur und einige nicht vertrauliche Metadaten bleiben übrig), sodass sie zu Debugging-Zwecken online geteilt werden kann, ohne befürchten zu müssen, dass Ihre persönlichen Daten verloren gehen.", + "full_anonymization_description": "Erstellt eine Kopie der Datenbank, wo der Inhalt der Notizen entfernt wurde. Es vergleicht lediglich die Struktur sowie nicht-kritische Metadaten. Sicher zum teilen für die Fehlerdiagnose.", "save_fully_anonymized_database": "Speichere eine vollständig anonymisierte Datenbank", "light_anonymization": "Leichte Anonymisierung", - "light_anonymization_description": "Durch diese Aktion wird eine neue Kopie der Datenbank erstellt und eine leichte Anonymisierung vorgenommen – insbesondere wird nur der Inhalt aller Notizen entfernt, Titel und Attribute bleiben jedoch erhalten. Darüber hinaus bleiben benutzerdefinierte JS-Frontend-/Backend-Skriptnotizen und benutzerdefinierte Widgets erhalten. Dies bietet mehr Kontext zum Debuggen der Probleme.", + "light_anonymization_description": "Erstellt eine Kopie wo der Inhalt der Notiz entfernt ist, jedoch Title, Attribute und benutzerdefinierte Skripte erhalten bleiben. Hilfreich zur Fehlerdiagnose.", "choose_anonymization": "Du kannst selbst entscheiden, ob du eine vollständig oder leicht anonymisierte Datenbank bereitstellen möchten. Selbst eine vollständig anonymisierte Datenbank ist sehr nützlich. In einigen Fällen kann jedoch eine leicht anonymisierte Datenbank den Prozess der Fehlererkennung und -behebung beschleunigen.", "save_lightly_anonymized_database": "Speichere eine leicht anonymisierte Datenbank", "existing_anonymized_databases": "Vorhandene anonymisierte Datenbanken", @@ -1057,14 +1073,17 @@ "error_creating_anonymized_database": "Die anonymisierte Datenbank konnte nicht erstellt werden. Überprüfe die Backend-Protokolle auf Details", "successfully_created_fully_anonymized_database": "Vollständig anonymisierte Datenbank in {{anonymizedFilePath}} erstellt", "successfully_created_lightly_anonymized_database": "Leicht anonymisierte Datenbank in {{anonymizedFilePath}} erstellt", - "no_anonymized_database_yet": "Noch keine anonymisierte Datenbank." + "no_anonymized_database_yet": "Noch keine anonymisierte Datenbank.", + "description": "Erstellt eine anonymisierte Kopie deiner Datenbank für den Austausch mit Entwicklern zur Fehlerdiagnose, ohne persönliche Daten preiszugeben." }, "database_integrity_check": { "title": "Datenbankintegritätsprüfung", "check_button": "Überprüfe die Datenbankintegrität", "checking_integrity": "Datenbankintegrität prüfen...", "integrity_check_succeeded": "Integritätsprüfung erfolgreich – keine Probleme gefunden.", - "integrity_check_failed": "Integritätsprüfung fehlgeschlagen: {{results}}" + "integrity_check_failed": "Integritätsprüfung fehlgeschlagen: {{results}}", + "check_integrity_label": "Überprüfe die Datenbankintegrität", + "check_integrity_description": "Überprüfe die Datenbank auf SQLite Ebene auf Fehler." }, "sync": { "title": "Synchronisieren", @@ -1074,14 +1093,18 @@ "filling_entity_changes": "Entitätsänderungszeilen werden gefüllt...", "sync_rows_filled_successfully": "Synchronisierungszeilen erfolgreich gefüllt", "finished-successfully": "Synchronisierung erfolgreich beendet.", - "failed": "Synchronisierung fehlgeschlagen: {{message}}" + "failed": "Synchronisierung fehlgeschlagen: {{message}}", + "force_full_sync_label": "Vollständige Synchronisierung erzwingen", + "force_full_sync_description": "Vollständige Synchronisation mit dem Sync-Server auslösen, lädt alle Änderungen erneut hoch." }, "vacuum_database": { "title": "Datenbank aufräumen", "description": "Dadurch wird die Datenbank neu erstellt, was normalerweise zu einer kleineren Datenbankdatei führt. Es werden keine Daten tatsächlich geändert.", "button_text": "Datenbank aufräumen", "vacuuming_database": "Datenbank wird geleert...", - "database_vacuumed": "Die Datenbank wurde geleert" + "database_vacuumed": "Die Datenbank wurde geleert", + "vacuum_label": "Datenbank bereinigen", + "vacuum_description": "Datenbank neu aufbauen um die Dateigröße zu reduzieren. Keine Daten werden verändert." }, "fonts": { "theme_defined": "Thema definiert", @@ -1092,7 +1115,7 @@ "note_tree_font": "Notizbaum-Schriftart", "note_detail_font": "Notiz-Detail-Schriftart", "monospace_font": "Minivan (Code) Schriftart", - "not_all_fonts_available": "Möglicherweise sind nicht alle aufgelisteten Schriftarten auf Ihrem System verfügbar.", + "not_all_fonts_available": "Möglicherweise sind nicht alle aufgelisteten Schriftarten auf Ihrem System verfügbar", "generic-fonts": "Generische Schriftarten", "sans-serif-system-fonts": "Sans-serif Systemschriftarten", "serif-system-fonts": "Serif Systemschriftarten", @@ -1101,7 +1124,9 @@ "serif": "Serif", "sans-serif": "Sans Serif", "monospace": "Monospace", - "system-default": "System Standard" + "system-default": "System Standard", + "custom_fonts": "Benutzerdefinierte Schriftarten verwenden", + "preview": "Vorschau" }, "max_content_width": { "title": "Inhaltsbreite", @@ -1134,7 +1159,10 @@ "layout-horizontal-description": "Startleiste ist unter der Tableiste. Die Tableiste wird dadurch auf die ganze Breite erweitert.", "auto_theme": "Alt (Folge dem Farbschema des Systems)", "light_theme": "Alt (Hell)", - "dark_theme": "Alt (Dunkel)" + "dark_theme": "Alt (Dunkel)", + "modern_themes": "Modern", + "legacy_themes": "Veraltet", + "custom_themes": "Benutzerdefiniert" }, "zoom_factor": { "title": "Zoomfaktor (nur Desktop-Build)", @@ -1162,17 +1190,25 @@ }, "images": { "images_section_title": "Bilder", - "download_images_automatically": "Lade Bilder automatisch herunter, um sie offline zu verwenden.", - "download_images_description": "Eingefügter HTML-Code kann Verweise auf Online-Bilder enthalten. Trilium findet diese Verweise und lädt die Bilder herunter, sodass sie offline verfügbar sind.", - "enable_image_compression": "Bildkomprimierung aktivieren", - "max_image_dimensions": "Maximale Breite/Höhe eines Bildes in Pixel (die Größe des Bildes wird geändert, wenn es diese Einstellung überschreitet).", - "jpeg_quality_description": "JPEG-Qualität (10 – schlechteste Qualität, 100 – beste Qualität, 50 – 85 wird empfohlen)", - "max_image_dimensions_unit": "Pixel" + "download_images_automatically": "Bilder automatisch herunterladen", + "download_images_description": "Referenzierte online Bilder vom eingefügten HTML-Code herunterladen, damit diese offline zur Verfügung stehen.", + "enable_image_compression": "Bildkomprimierung", + "max_image_dimensions": "Maximale Maße eines Bildes", + "jpeg_quality_description": "Empfohlener Bereich liegt zwischen 50-85. Niedrige Werte reduzieren die Dateigröße, höhere Werte bewahren Details.", + "max_image_dimensions_unit": "Pixel", + "enable_image_compression_description": "Komprimieren und skalieren Bilder, wenn diese hochgeladen oder eingefügt werden.", + "max_image_dimensions_description": "Bilder, die diese Größe überschreiten, werden automatisch verkleinert.", + "jpeg_quality": "JPEG Qualität", + "ocr_section_title": "Text Extrahierung (OCR)", + "ocr_related_content_languages": "Inhaltssprachen (für Textextrahierung verwendet)", + "ocr_auto_process": "Neue Dateien automatisch verarbeiten", + "ocr_auto_process_description": "Text automatisch extrahieren von neu hochgeladenen oder eingefügten Dateien.", + "ocr_min_confidence": "Minimale Sicherheit" }, "attachment_erasure_timeout": { "attachment_erasure_timeout": "Zeitüberschreitung beim Löschen von Anhängen", - "erase_attachments_after": "Nicht verwendete Anhänge löschen nach:", - "manual_erasing_description": "Du kannst das Löschen auch manuell auslösen (ohne Berücksichtigung des oben definierten Timeouts):", + "erase_attachments_after": "Nicht verwendete Anhänge löschen nach", + "manual_erasing_description": "Manuelle Löschung aktivieren, ignoriert den obigen Zeitpunkt.", "erase_unused_attachments_now": "Lösche jetzt nicht verwendete Anhangnotizen", "unused_attachments_erased": "Nicht verwendete Anhänge wurden gelöscht." }, @@ -1182,27 +1218,29 @@ }, "note_erasure_timeout": { "note_erasure_timeout_title": "Beachte das Zeitlimit für die Löschung", - "erase_notes_after": "Notizen löschen nach:", - "manual_erasing_description": "Du kannst das Löschen auch manuell auslösen (ohne Berücksichtigung des oben definierten Timeouts):", + "erase_notes_after": "Notizen löschen nach", + "manual_erasing_description": "Manuelle Löschung aktivieren, ignoriert den obigen Zeitpunkt.", "erase_deleted_notes_now": "Jetzt gelöschte Notizen löschen", "deleted_notes_erased": "Gelöschte Notizen wurden gelöscht." }, "revisions_snapshot_interval": { "note_revisions_snapshot_interval_title": "Snapshot-Intervall für Notizrevisionen", "note_revisions_snapshot_description": "Das Snapshot-Zeitintervall für Notizrevisionen ist die Zeit, nach der eine neue Notizrevision erstellt wird. Weitere Informationen findest du im Wiki.", - "snapshot_time_interval_label": "Zeitintervall für Notiz-Revisions-Snapshot:" + "snapshot_time_interval_label": "Snapshot Intervall" }, "revisions_snapshot_limit": { "note_revisions_snapshot_limit_title": "Limit für Notizrevision-Snapshots", "note_revisions_snapshot_limit_description": "Das Limit für Notizrevision-Snapshots bezieht sich auf die maximale Anzahl von Revisionen, die für jede Notiz gespeichert werden können. Dabei bedeutet -1, dass es kein Limit gibt, und 0 bedeutet, dass alle Revisionen gelöscht werden. Du kannst das maximale Limit für Revisionen einer einzelnen Notiz über das Label #versioningLimit festlegen.", - "snapshot_number_limit_label": "Limit der Notizrevision-Snapshots:", + "snapshot_number_limit_label": "Maximale Revisionen", "erase_excess_revision_snapshots": "Überschüssige Revision-Snapshots jetzt löschen", "erase_excess_revision_snapshots_prompt": "Überschüssige Revision-Snapshots wurden gelöscht.", - "snapshot_number_limit_unit": "Momentaufnahmen" + "snapshot_number_limit_unit": "Momentaufnahmen", + "note_revisions_snapshot_limit_description_short": "Maximale Anzahl an Revisionen pro Notiz. Nutze -1 für unlimitiert oder 0 zum deaktivieren.", + "erase_excess_revision_snapshots_description": "Lösche Revisionen aller Notizen die das Limit überschreiten." }, "search_engine": { "title": "Suchmaschine", - "custom_search_engine_info": "Für eine benutzerdefinierte Suchmaschine müssen sowohl ein Name als auch eine URL festgelegt werden. Wenn keine dieser Optionen festgelegt ist, wird DuckDuckGo als Standardsuchmaschine verwendet.", + "custom_search_engine_info": "Wird verwendet bei der Suche im Web für den ausgewählten Text. Wenn nicht konfiguriert, wird DuckDuckGo verwendet.", "predefined_templates_label": "Vordefinierte Suchmaschinenvorlagen", "bing": "Bing", "baidu": "Baidu", @@ -1282,7 +1320,9 @@ "date-and-time": "Datum & Uhrzeit", "path": "Pfad", "database_backed_up_to": "Die Datenbank wurde gesichert unter {{backupFilePath}}", - "no_backup_yet": "noch kein Backup" + "no_backup_yet": "noch kein Backup", + "title": "Sicherung", + "download": "Download" }, "etapi": { "title": "ETAPI", @@ -1321,14 +1361,17 @@ "protected_session_timeout_description": "Das Zeitlimit für geschützte Sitzungen ist ein Zeitraum, nach dem die geschützte Sitzung aus dem Speicher des Browsers gelöscht wird. Dies wird ab der letzten Interaktion mit geschützten Notizen gemessen. Sehen", "wiki": "Wiki", "for_more_info": "für weitere Informationen.", - "protected_session_timeout_label": "Zeitüberschreitung der geschützten Sitzung:", + "protected_session_timeout_label": "Automatisches beenden der Sitzung nach", "reset_confirmation": "Durch das Zurücksetzen des Passworts verlierst du für immer den Zugriff auf alle Ihre bestehenden geschützten Notizen. Möchtest du das Passwort wirklich zurücksetzen?", "reset_success_message": "Das Passwort wurde zurückgesetzt. Bitte lege ein neues Passwort fest", "change_password_heading": "Kennwort ändern", "set_password_heading": "Passwort festlegen", "set_password": "Passwort festlegen", "password_mismatch": "Neue Passwörter sind nicht dasselbe.", - "password_changed_success": "Das Passwort wurde geändert. Trilium wird neu geladen, nachdem du auf OK geklickt hast." + "password_changed_success": "Das Passwort wurde geändert. Trilium wird neu geladen, nachdem du auf OK geklickt hast.", + "change_password_description": "Aktualisiere dein aktuelles Passwort", + "reset_password": "Passwort zurücksetzen", + "cancel": "Abbrechen" }, "shortcuts": { "keyboard_shortcuts": "Tastaturkürzel", @@ -1349,7 +1392,10 @@ "description": "Diese Optionen gelten nur für Desktop-Builds. Browser verwenden ihre eigene native Rechtschreibprüfung.", "enable": "Aktiviere die Rechtschreibprüfung", "language_code_label": "Sprachcode(s)", - "restart-required": "Änderungen an den Rechtschreibprüfungsoptionen werden nach dem Neustart der Anwendung wirksam." + "restart-required": "Änderungen an den Rechtschreibprüfungsoptionen werden nach dem Neustart der Anwendung wirksam.", + "custom_dictionary_title": "Benutzerdefiniertes Wörterbuch", + "custom_dictionary_edit": "Benutzerdefiniert Wörter", + "custom_dictionary_open": "Wörterbuch bearbeiten" }, "sync_2": { "config_title": "Synchronisierungskonfiguration", @@ -1458,7 +1504,8 @@ "task-list": "Aufgabenliste", "new-feature": "Neu", "collections": "Sammlungen", - "spreadsheet": "Tabelle" + "spreadsheet": "Tabelle", + "llm-chat": "KI-Chat" }, "protect_note": { "toggle-on": "Notiz schützen", @@ -1660,7 +1707,8 @@ "theme_none": "Keine Syntaxhervorhebung", "theme_group_light": "Helle Themen", "theme_group_dark": "Dunkle Themen", - "copy_title": "Kopiere in Zwischenablage" + "copy_title": "Kopiere in Zwischenablage", + "click_to_copy": "Klicke zum kopieren" }, "classic_editor_toolbar": { "title": "Format" @@ -1679,7 +1727,7 @@ "title": "Fixiert", "description": "Werkzeuge erscheinen im \"Format\" Tab." }, - "multiline-toolbar": "Toolbar wenn nötig in mehreren Zeilen darstellen." + "multiline-toolbar": "Toolbar wenn nötig in mehreren Zeilen darstellen" } }, "electron_context_menu": { @@ -1770,8 +1818,9 @@ "custom_date_time_format": { "title": "Benutzerdefiniertes Datums-/Zeitformat", "description": "Passe das Format des Datums und der Uhrzeit an, die über oder die Symbolleiste eingefügt werden. Die verfügbaren Format-Tokens sind unter Day.js docs zu finden.", - "format_string": "Format Zeichenfolge:", - "formatted_time": "Formatiertes Datum/Uhrzeit:" + "format_string": "Format Zeichenfolge", + "formatted_time": "Formatiertes Datum/Uhrzeit", + "preview": "Vorschau: {{preview}}" }, "multi_factor_authentication": { "title": "Multi-Faktor-Authentifizierung", @@ -2002,7 +2051,9 @@ "title": "Experimentelle Optionen", "disclaimer": "Diese Optionen sind experimentell und können Instabilitäten verursachen. Achtsam zu verwenden.", "new_layout_name": "Neues Layout", - "new_layout_description": "Probiere das neue Layout für eine modernere Darstellung und verbesserte Benutzbarkeit aus. Kann sich in Zukunft stark ändern." + "new_layout_description": "Probiere das neue Layout für eine modernere Darstellung und verbesserte Benutzbarkeit aus. Kann sich in Zukunft stark ändern.", + "llm_name": "KI- / LLM-Chat", + "llm_description": "Aktiviert die KI-Chat Seitenleiste sowie LLM-Chat Notizen die von einem Sprachmodell betrieben werden." }, "server": { "unknown_http_error_title": "Kommunikationsfehler mit dem Server", @@ -2186,5 +2237,82 @@ "sample_xy": "XY", "sample_venn": "Mengen", "sample_ishikawa": "Ursache-Wirkung" + }, + "revisions": { + "title": "Notizrevisionen" + }, + "database": { + "title": "Datenbank" + }, + "search": { + "title": "Suche", + "fuzzy_matching_label": "Fehlertoleranz bei Suche" + }, + "text_editor": { + "title": "Editor" + }, + "llm_chat": { + "placeholder": "Schreibe eine Nachricht...", + "send": "Senden", + "sending": "Sende...", + "empty_state": "Starte eine Unterhaltung indem du unten eine Nachricht schreibst.", + "searching_web": "Suche im Web...", + "web_search": "Websuche", + "note_tools": "Notizzugriff", + "sources": "Quellen", + "legacy_models": "Veraltete Modelle", + "thinking": "Denke...", + "thought_process": "Denkprozess", + "result": "Ergebnis", + "error": "Fehler", + "tool_error": "Fehlgeschlagen", + "total_tokens": "{{total}} Token", + "tokens": "Token", + "context_used": "{{percentage}}% verwendet", + "no_provider_message": "Kein KI-Anbieter konfiguriert. Fügen einen hinzu, um zu chatten.", + "add_provider": "KI-Anbieter hinzufügen", + "stop": "Stopp" + }, + "sidebar_chat": { + "title": "KI-Chat", + "launcher_title": "KI-Chat öffnen", + "new_chat": "Neuen Chat starten", + "save_chat": "Chat in Notiz sichern", + "empty_state": "Starte Unterhaltung", + "history": "Chathistorie", + "recent_chats": "Kürzliche Chats", + "no_chats": "Keine vorherigen Chats" + }, + "llm": { + "tools": { + "clone_note": "Notiz duplizieren", + "move_note": "Notiz verschieben", + "delete_note": "Notiz löschen", + "rename_note": "Notiz umbenennen", + "web_search": "Websuche", + "create_note": "Notiz erstellen", + "append_to_note": "An Notiz anhängen", + "get_note": "Notiz beziehen", + "search_notes": "Notizen durchsuchen" + }, + "cancel": "Abbrechen", + "api_key": "API Schlüssel", + "delete_provider": "Löschen", + "actions": "Aktionen", + "provider_type": "Anbieter", + "provider_name": "Name", + "settings_title": "KI / LLM" + }, + "mind-map": { + "summary": "Zusammenfassung", + "link": "Link" + }, + "ocr": { + "view_extracted_text": "Extrahierten Text anzeigen (OCR)", + "open_media_settings": "Öffne Einstellungen", + "processing": "Verarbeite...", + "loading_text": "Lädt OCR Text...", + "extracted_text_title": "Extrahierter Text (OCR)", + "extracted_text": "Extrahierter Text (OCR)" } } From 1bf36574e2356f9b48ba458830f90a25ff95af3e Mon Sep 17 00:00:00 2001 From: Artyom Rybakov Date: Tue, 14 Apr 2026 08:02:32 +0200 Subject: [PATCH 214/482] Translated using Weblate (Russian) Currently translated at 91.8% (1726 of 1880 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/ --- .../src/translations/ru/translation.json | 110 ++++++++++++------ 1 file changed, 73 insertions(+), 37 deletions(-) diff --git a/apps/client/src/translations/ru/translation.json b/apps/client/src/translations/ru/translation.json index bcf8b6f506..9065c615da 100644 --- a/apps/client/src/translations/ru/translation.json +++ b/apps/client/src/translations/ru/translation.json @@ -77,18 +77,28 @@ }, "delete_notes": { "close": "Закрыть", - "erase_notes_description": "Обычное (мягкое) удаление только отмечает заметки как удалённые, и их можно восстановить (в диалоговом окне последних изменений) в течение определённого времени. Если выбрать этот параметр, заметки будут удалены немедленно, и восстановить их будет невозможно.", + "erase_notes_description": "Стереть заметки немедленно вместо мягкого удаления. Это действие необратимо и вызовет перезагрузку приложения.", "delete_all_clones_description": "Удалить также все клоны (можно отменить в последних изменениях)", "erase_notes_warning": "Удалить заметки без возможности восстановления, включая все клоны. Это приведёт к принудительной перезагрузке приложения.", - "notes_to_be_deleted": "Следующие заметки будут удалены ({{notesCount}})", + "notes_to_be_deleted": "Заметки, подлежащие удалению ({{notesCount}})", "no_note_to_delete": "Заметка не будет удалена (только клоны).", - "broken_relations_to_be_deleted": "Следующие отношения будут разорваны и удалены ({{relationCount}})", - "cancel": "Отмена" + "broken_relations_to_be_deleted": "Разорванные отношения ({{relationCount}})", + "cancel": "Отмена", + "title": "Удалить заметки", + "clones_label": "Клоны", + "delete_clones_description_one": "Также удалить {{count}} другой клон. Можно отменить в последних изменениях.", + "delete_clones_description_few": "Также удалить {{count}} других клона. Можно отменить в последних изменениях.", + "delete_clones_description_many": "Также удалить {{count}} других клонов. Можно отменить в последних изменениях.", + "erase_notes_label": "Стереть навсегда", + "table_note_with_relation": "Заметка с отношением", + "table_relation": "Отношение", + "table_points_to": "Указывает на (удалено)", + "delete": "Удалить" }, "database_anonymization": { - "light_anonymization_description": "Это действие создаст новую копию базы данных и выполнит её лёгкую анонимизацию — в частности, будет удалён только контент всех заметок, но заголовки и атрибуты останутся. Кроме того, будут сохранены пользовательские заметки, содержащие JavaScript-скрипты frontend/backend и пользовательские виджеты. Это даёт больше контекста для отладки проблем.", + "light_anonymization_description": "Создает копию с удалением содержимого заметок, но заголовками, атрибутами и пользовательскими скриптами/виджетами. Даёт больше контекста для отладки.", "choose_anonymization": "Вы можете самостоятельно решить, хотите ли вы предоставить полностью или частично анонимизированную базу данных. Даже полностью анонимизированная база данных очень полезна, однако в некоторых случаях частично анонимизированная база данных может ускорить процесс выявления и исправления ошибок.", - "full_anonymization_description": "Это действие создаст новую копию базы данных и анонимизирует ее (удалит все содержимое заметок и оставит только структуру и некоторые неконфиденциальные метаданные) для совместного использования в Интернете в целях отладки без опасения утечки ваших личных данных.", + "full_anonymization_description": "Создает копию базы данных с удалением всего содержимого заметок, оставляя только структуру и неконфиденциальные метаданные. Безопасно для обмена в сети при отладке проблем.", "title": "Анонимизация базы данных", "full_anonymization": "Полная анонимизация", "light_anonymization": "Легкая анонимизация", @@ -136,20 +146,23 @@ "title": "Языки контента" }, "theme": { - "theme_label": "Тема", + "theme_label": "Тема приложения", "override_theme_fonts_label": "Переопределить шрифты темы", - "triliumnext": "Trilium (следует системной цветовой схеме)", - "triliumnext-light": "Trilium (Светлая)", - "triliumnext-dark": "Trilium (Темная)", - "title": "Тема приложения", + "triliumnext": "Использовать цветовую схему системы", + "triliumnext-light": "Светлая", + "triliumnext-dark": "Тёмная", + "title": "Пользовательский интерфейс", "layout": "Макет", "layout-vertical-title": "Вертикальный", "layout-horizontal-title": "Горизонтальный", - "auto_theme": "Legacy (следует системной цветовой схеме)", - "light_theme": "Legacy (светлая)", - "dark_theme": "Legacy (темная)", + "auto_theme": "Использовать цветовую схему системы", + "light_theme": "Светлая", + "dark_theme": "Тёмная", "layout-horizontal-description": "панель запуска находится под панелью вкладок, панель вкладок теперь занимает всю ширину.", - "layout-vertical-description": "панель запуска находится слева (по умолчанию)" + "layout-vertical-description": "панель запуска находится слева (по умолчанию)", + "modern_themes": "Современные", + "legacy_themes": "Устаревшие", + "custom_themes": "Пользовательские" }, "tasks": { "due": { @@ -1038,7 +1051,10 @@ "expand_nth_level": "Развернуть уровни: {{depth}} шт.", "expand_first_level": "Развернуть прямые дочерние уровни", "expand_tooltip": "Разщвернуть дочерние элементы этой коллекции (на один уровень вложенности). Для получения дополнительных параметров нажмите стрелку справа.", - "hide_child_notes": "Скрыть дочерние заметки в дереве" + "hide_child_notes": "Скрыть дочерние заметки в дереве", + "open_all_in_tabs": "Открыть все", + "open_all_in_tabs_tooltip": "Открыть все результаты в новых вкладках", + "open_all_confirm": "Это откроет заметки ({{count}}) в новых вкладках. Продолжить?" }, "edited_notes": { "deleted": "(удалено)", @@ -1209,20 +1225,24 @@ "size": "Размер", "serif": "С засечками", "monospace": "Моноширинный", - "main_font": "Основной шрифт", + "main_font": "Текст интерфейса", "font_family": "Семейство шрифтов", "sans-serif": "Без засечек", "system-default": "Системный по умолчанию", "theme_defined": "Определяется темой", "generic-fonts": "Стандартные шрифты", - "note_tree_font": "Шрифт дерева заметок", - "note_detail_font": "Шрифт заметки", - "monospace_font": "Моноширинный шрифт (для кода)", + "note_tree_font": "Текст дерева заметок", + "note_detail_font": "Текст документа", + "monospace_font": "Моноширинный текст", "sans-serif-system-fonts": "Системные шрифты без засечек", "serif-system-fonts": "Системные шрифты с засечками", "monospace-system-fonts": "Моноширинные системные шрифты", "handwriting-system-fonts": "Шрифты системы рукописного ввода", - "not_all_fonts_available": "Не все перечисленные шрифты могут быть доступны в вашей системе." + "not_all_fonts_available": "Не все перечисленные шрифты могут быть доступны в вашей системе", + "preview": "Предпросмотр", + "monospace_font_description": "Используется для заметок кода и блоков кода", + "size_relative_to_general": "Размер относительно общего размера шрифта", + "apply_changes": "Перезагрузить, чтобы применить изменения" }, "max_content_width": { "max_width_unit": "пикселей", @@ -1242,11 +1262,14 @@ "images": { "images_section_title": "Изображения", "max_image_dimensions_unit": "пикселей", - "download_images_automatically": "Автоматическая загрузка изображений для использования в автономном режиме.", - "download_images_description": "Вставленный HTML-код может содержать ссылки на онлайн-изображения. Trilium найдет эти ссылки и загрузит изображения, чтобы они были доступны офлайн.", - "enable_image_compression": "Включить сжатие изображений", - "max_image_dimensions": "Максимальная ширина/высота изображения (размер изображения будет изменен, если он превысит этот параметр).", - "jpeg_quality_description": "Качество JPEG (10 — худшее качество, 100 — наилучшее качество, рекомендуется 50 — 85)" + "download_images_automatically": "Автоматическая загрузка изображений", + "download_images_description": "Скачивать изображения указанные в вставленном HTML-коде, чтобы они были доступны офлайн.", + "enable_image_compression": "Сжатие изображений", + "max_image_dimensions": "Максимальные размеры изображения", + "jpeg_quality_description": "Рекомендуемый диапазон - 50–85. Более низкие значения уменьшают размер файла, более высокие - сохраняют детализацию.", + "enable_image_compression_description": "Сжимать и изменять размер изображений при их загрузке или вставке.", + "max_image_dimensions_description": "Размер изображений, превышающих этот размер, будет изменен автоматически.", + "jpeg_quality": "Качество JPEG" }, "search_engine": { "bing": "Bing", @@ -1540,7 +1563,7 @@ "unit": "символов", "title": "Автоматическое переключение в режим \"только для чтения\"", "description": "Максимальный размер заметки до переключения в режим только для чтения — это размер, после которого заметки будут отображаться в режиме «только для чтения» (из соображений производительности).", - "label": "Максимальный размер заметки до переключения в режим только для чтения (заметки с кодом)" + "label": "Максимальный размер заметки до переключения в режим только для чтения" }, "inherited_attribute_list": { "title": "Унаследованные атрибуты", @@ -1598,14 +1621,16 @@ "note_already_in_diagram": "Заметка \"{{title}}\" уже есть на диаграмме.", "connection_exists": "Связь '{{name}}' между этими заметками уже существует.", "specify_new_relation_name": "Укажите новое имя связи (допустимые символы: буквы, цифры, двоеточие и подчеркивание):", - "start_dragging_relations": "Начните перетягивать отношения отсюда на другую заметку." + "start_dragging_relations": "Начните перетягивать отношения отсюда на другую заметку.", + "rename_relation": "Переименовать отношение" }, "vacuum_database": { "title": "Уменьшение размера файла базы данных", "description": "Это приведет к перестройке базы данных, что, скорее всего, уменьшит размер её файла. Данные не будут изменены.", "button_text": "Уменьшить размер файла базы данных", "vacuuming_database": "Уменьшение размера файла базы данных...", - "database_vacuumed": "База данных была перестроена" + "database_vacuumed": "База данных была перестроена", + "vacuum_label": "Уменьшить размер файла базы данных" }, "vim_key_bindings": { "use_vim_keybindings_in_code_notes": "Сочетания клавиш Vim", @@ -1726,13 +1751,15 @@ "check_button": "Проверить целостность базы данных", "checking_integrity": "Проверка целостности базы данных...", "integrity_check_succeeded": "Проверка целостности прошла успешно - проблем не обнаружено.", - "integrity_check_failed": "Проверка целостности завершена с ошибками: {{results}}" + "integrity_check_failed": "Проверка целостности завершена с ошибками: {{results}}", + "check_integrity_label": "Проверить целостность базы данных" }, "consistency_checks": { "find_and_fix_button": "Найти и устранить проблемы целостности", "finding_and_fixing_message": "Поиск и устранение проблем целостности...", "title": "Проверки целостности", - "issues_fixed_message": "Все обнаруженные проблемы с согласованностью теперь устранены." + "issues_fixed_message": "Все обнаруженные проблемы с согласованностью теперь устранены.", + "find_and_fix_label": "Найти и устранить проблемы целостности" }, "call_to_action": { "next_theme_message": "В настоящее время вы используете старую тему оформления. Хотите попробовать новую тему?", @@ -1969,11 +1996,11 @@ }, "ui-performance": { "title": "Производительность", - "enable-motion": "Включить визуальные эффекты и анимации", - "enable-shadows": "Включить тени", - "enable-backdrop-effects": "Включить эффекты размытия фона меню, всплывающих окон и панелей", - "enable-smooth-scroll": "Включить плавную прокрутку", - "app-restart-required": "(для вступления изменений в силу требуется перезапуск приложения)" + "enable-motion": "Визуальные эффекты и анимации", + "enable-shadows": "Тени", + "enable-backdrop-effects": "Эффекты размытия фона меню, всплывающих окон и панелей", + "enable-smooth-scroll": "Плавная прокрутку", + "app-restart-required": "Требуется перезапуск приложения" }, "collections": { "rendering_error": "Невозможно отобразить содержимое из-за ошибки." @@ -2274,6 +2301,15 @@ "delete_provider_confirmation": "Вы уверены, что желаете удалить провайдера \"{{name}}\"?", "api_key": "Ключ API", "api_key_placeholder": "Введите ваш ключ API", - "cancel": "Отмена" + "cancel": "Отмена", + "tools": { + "clone_note": "Клонировать заметку", + "move_note": "Переместить заметку", + "delete_note": "Удалить заметку", + "rename_note": "Переименовать заметку" + } + }, + "database": { + "title": "База данных" } } From c0c0cea376bb8032184c06f8a3532410d6fd117c Mon Sep 17 00:00:00 2001 From: Artyom Rybakov Date: Tue, 14 Apr 2026 07:57:24 +0200 Subject: [PATCH 215/482] Translated using Weblate (Russian) Currently translated at 100.0% (403 of 403 strings) Translation: Trilium Notes/Server Translate-URL: https://hosted.weblate.org/projects/trilium/server/ru/ --- .../src/assets/translations/ru/server.json | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/apps/server/src/assets/translations/ru/server.json b/apps/server/src/assets/translations/ru/server.json index cf1b01bcbb..170b0a34a0 100644 --- a/apps/server/src/assets/translations/ru/server.json +++ b/apps/server/src/assets/translations/ru/server.json @@ -114,7 +114,7 @@ "options-title": "Опции", "appearance-title": "Оформление", "shortcuts-title": "Сочетания клавиш", - "images-title": "Изображения", + "images-title": "Медиа", "spellcheck-title": "Проверка орфографии", "password-title": "Пароль", "etapi-title": "ETAPI", @@ -160,7 +160,8 @@ "tab-switcher-title": "Переключатель вкладок", "llm-chat-history-title": "История чата с ИИ", "llm-title": "ИИ / LLM", - "sidebar-chat-title": "Чат с ИИ" + "sidebar-chat-title": "Чат с ИИ", + "custom-dictionary-title": "Пользовательский словарь" }, "tray": { "bookmarks": "Закладки", @@ -361,7 +362,10 @@ "site-theme": "Тема оформления сайта", "image_alt": "Изображение статьи", "on-this-page": "На текущей странице", - "last-updated": "Последнее обновление: {{- date}}" + "last-updated": "Последнее обновление: {{- date}}", + "logo-alt": "Логотип", + "toggle-toc": "Переключение оглавления", + "toggle-navigation": "Переключение навигации" }, "hidden_subtree_templates": { "description": "Описание", @@ -441,5 +445,21 @@ }, "desktop": { "instance_already_running": "Приложение уже запущено, фокус переключен на него." + }, + "password": { + "incorrect": "Вы ввели неверный пароль." + }, + "script": { + "wrong-environment": "Не удается выполнить заметку \"{{- noteTitle}}\" ({{- noteId}}). Это скрипт {{- actualEnv}}, но попытка выполнения была предпринята в {{- expectedEnv}}." + }, + "search": { + "error": { + "in-context": "Ошибка в {{- context}}: {{- message}}", + "reserved-keyword": "\"{{- token}}\" - зарезервированное ключевое слово. Для поиска буквального значения используйте кавычки: \"{{- token}}\"", + "cannot-compare-with": "невозможно сравнить с \"{{- token}}\". Для поиска буквального значения используйте кавычки: \"{{- token}}\"", + "misplaced-expression": "Неподходящее или неполное выражение \"{{- token}}\"", + "fulltext-after-expression": "\"{{- token}}\" - неверное выражение. Для поиска текста поместите его перед фильтрами атрибутов (например, \"{{- token}} #метка\" вместо \"#метка {{- token}}\").", + "unrecognized-expression": "Нераспознанное выражение \"{{- token}}\"" + } } } From 263479adeed24d9ba533d5e2291fa3038eaed55b Mon Sep 17 00:00:00 2001 From: green Date: Tue, 14 Apr 2026 07:30:33 +0200 Subject: [PATCH 216/482] Translated using Weblate (Japanese) Currently translated at 100.0% (403 of 403 strings) Translation: Trilium Notes/Server Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/ --- apps/server/src/assets/translations/ja/server.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/server/src/assets/translations/ja/server.json b/apps/server/src/assets/translations/ja/server.json index c1f65d4cd4..2197272282 100644 --- a/apps/server/src/assets/translations/ja/server.json +++ b/apps/server/src/assets/translations/ja/server.json @@ -458,5 +458,8 @@ }, "script": { "wrong-environment": "ノート \"{{- noteTitle}}\" ({{- noteId}}) を実行できません。これは {{- actualEnv}} スクリプトですが、{{- expectedEnv}} で実行しようとしました。" + }, + "password": { + "incorrect": "入力されたパスワードが間違っています。" } } From a4c419de6f637377bc944f4ae4cd7e5688186f6e Mon Sep 17 00:00:00 2001 From: Ulices Date: Tue, 14 Apr 2026 23:25:59 +0200 Subject: [PATCH 217/482] Translated using Weblate (Spanish) Currently translated at 87.0% (1637 of 1880 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/es/ --- .../src/translations/es/translation.json | 72 +++++++++++++------ 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/apps/client/src/translations/es/translation.json b/apps/client/src/translations/es/translation.json index 990b541636..f3588aac03 100644 --- a/apps/client/src/translations/es/translation.json +++ b/apps/client/src/translations/es/translation.json @@ -90,12 +90,22 @@ "delete_notes": { "close": "Cerrar", "delete_all_clones_description": "Eliminar también todos los clones (se puede deshacer en cambios recientes)", - "erase_notes_description": "La eliminación normal (suave) solo marca las notas como eliminadas y se pueden recuperar (en el cuadro de diálogo de cambios recientes) dentro de un periodo de tiempo. Al marcar esta opción se borrarán las notas inmediatamente y no será posible recuperarlas.", + "erase_notes_description": "Borrar notas inmediatamente en lugar de la eliminación con respaldo. Esto no se puede deshacer y forzará la recarga de la aplicación.", "erase_notes_warning": "Eliminar notas permanentemente (no se puede deshacer), incluidos todos los clones. Esto forzará la recarga de la aplicación.", - "notes_to_be_deleted": "Las siguientes notas serán eliminadas ({{notesCount}})", + "notes_to_be_deleted": "Notas a ser eliminadas ({{notesCount}})", "no_note_to_delete": "No se eliminará ninguna nota (solo clones).", - "broken_relations_to_be_deleted": "Las siguientes relaciones se romperán y serán eliminadas ({{ relationCount}})", - "cancel": "Cancelar" + "broken_relations_to_be_deleted": "Relaciones rotas ({{ relationCount}})", + "cancel": "Cancelar", + "title": "Eliminar notas", + "clones_label": "Clones", + "delete_clones_description_one": "También eliminar otro clon. Puede deshacerse en los cambios recientes.", + "delete_clones_description_many": "También eliminar otros {{count}} clones. Puede deshacerse en los cambios recientes.", + "delete_clones_description_other": "También eliminar otros {{count}} clones. Puede deshacerse en los cambios recientes.", + "erase_notes_label": "Borrar permanentemente", + "table_note_with_relation": "Nota con relación", + "table_relation": "Relación", + "table_points_to": "Apunta a (eliminado)", + "delete": "Eliminar" }, "export": { "export_note_title": "Exportar nota", @@ -206,7 +216,8 @@ "box_size_small": "pequeño (~ 10 líneas)", "box_size_medium": "medio (~ 30 líneas)", "box_size_full": "completo (el cuadro muestra el texto completo)", - "button_include": "Incluir nota" + "button_include": "Incluir nota", + "box_size_expandable": "expandible (colapsado por defecto)" }, "info": { "modalTitle": "Mensaje informativo", @@ -338,7 +349,7 @@ "calendar_root": "marca la nota que debe usarse como raíz para las notas del día. Sólo uno debe estar marcado como tal.", "archived": "las notas con esta etiqueta no serán visibles de forma predeterminada en los resultados de búsqueda (tampoco en los cuadros de diálogo Saltar a, Agregar vínculo, etc.).", "exclude_from_export": "las notas (con su subárbol) no se incluirán en ninguna exportación de notas", - "run": "define en qué eventos debe ejecutarse el script. Los valores posibles son:\n
    \n
  • frontendStartup - cuando Trilium frontend se inicia (o se actualiza), pero no en móvil.
  • \n
  • mobileStartup - cuando Trilium frontend se inicia (o se actualiza), en móvil.
  • \n
  • backendStartup - cuando Trilium backend se inicia
  • \n
  • hourly - se ejecuta una vez por hora. Se puede usar la etiqueta adicional runAtHour para especificar a qué hora.
  • \n
  • daily - se ejecuta una vez al día
  • \n
", + "run": "define en qué eventos debe ejecutarse el script. Los valores posibles son:\n
    \n
  • frontendStartup - cuando el frontend de Trilium se inicia (o se actualiza), pero no en móvil.
  • \n
  • mobileStartup - cuando el frontend de Trilium se inicia (o se actualiza), en móvil.
  • \n
  • backendStartup - cuando el backend de Trilium se inicia
  • \n
  • hourly - se ejecuta una vez por hora. Se puede usar la etiqueta adicional runAtHour para especificar a qué hora.
  • \n
  • daily - se ejecuta una vez al día
  • \n
", "run_on_instance": "Definir en qué instancia de Trilium se debe ejecutar esto. Predeterminado para todas las instancias.", "run_at_hour": "¿A qué hora debería funcionar? Debe usarse junto con #run=hourly. Se puede definir varias veces para varias ejecuciones durante el día.", "disable_inclusion": "los scripts con esta etiqueta no se incluirán en la ejecución del script principal.", @@ -416,7 +427,8 @@ "and_more": "... y {{count}} más.", "print_landscape": "Al exportar a PDF, cambia la orientación de la página a paisaje en lugar de retrato.", "print_page_size": "Al exportar a PDF, cambia el tamaño de la página. Valores soportados: A0, A1, A2, A3, A4, A5, A6, Legal, Letter, Tabloid, Ledger.", - "color_type": "Color" + "color_type": "Color", + "textarea": "Texto multilínea" }, "attribute_editor": { "help_text_body1": "Para agregar una etiqueta, simplemente escriba, por ejemplo. #rock o si desea agregar también valor, p.e. #año = 2020", @@ -678,7 +690,8 @@ "export_as_image": "Exportar como imagen", "export_as_image_png": "PNG (ráster)", "export_as_image_svg": "SVG (vectorial)", - "note_map": "Mapa de la nota" + "note_map": "Mapa de la nota", + "view_ocr_text": "Ver texto OCR" }, "onclick_button": { "no_click_handler": "El widget de botón '{{componentId}}' no tiene un controlador de clics definido" @@ -776,7 +789,10 @@ "expand_first_level": "Expandir hijos inmediatos", "expand_nth_level": "Expandir {{depth}} niveles", "expand_all_levels": "Expandir todos los niveles", - "hide_child_notes": "Ocultar subnotas en el árbol" + "hide_child_notes": "Ocultar subnotas en el árbol", + "open_all_in_tabs": "Abrir todo", + "open_all_in_tabs_tooltip": "Abrir todos los resultados en nuevas pestañas", + "open_all_confirm": "Esto abrirá {{count}} notas en nuevas pestañas. ¿Continuar?" }, "edited_notes": { "no_edited_notes_found": "Aún no hay notas editadas en este día...", @@ -830,7 +846,8 @@ "collapse": "Contraer al tamaño normal", "title": "Mapa de notas", "fix-nodes": "Fijar nodos", - "link-distance": "Distancia de enlace" + "link-distance": "Distancia de enlace", + "too-many-notes": "Este subárbol contiene {{count}} notas, lo que excede el límite de {{max}} que se puede mostrar en el mapa de notas." }, "note_paths": { "title": "Rutas de nota", @@ -1035,7 +1052,8 @@ "note_already_in_diagram": "La nota \"{{title}}\" ya está en el diagrama.", "enter_title_of_new_note": "Ingrese el título de la nueva nota", "default_new_note_title": "nueva nota", - "click_on_canvas_to_place_new_note": "Haga clic en el lienzo para colocar una nueva nota" + "click_on_canvas_to_place_new_note": "Haga clic en el lienzo para colocar una nueva nota", + "rename_relation": "Renombrar relación" }, "backend_log": { "refresh": "Refrescar" @@ -1044,15 +1062,17 @@ "title": "Comprobación de coherencia", "find_and_fix_button": "Buscar y solucionar problemas de coherencia", "finding_and_fixing_message": "Buscando y solucionando problemas de coherencia...", - "issues_fixed_message": "Los problemas de coherencia han sido solucionados." + "issues_fixed_message": "Los problemas de coherencia han sido solucionados.", + "find_and_fix_label": "Buscar y solucionar problemas de coherencia", + "find_and_fix_description": "Escanear y reparar automáticamente cualquier problema de consistencia de datos en la base de datos." }, "database_anonymization": { "title": "Anonimización de bases de datos", "full_anonymization": "Anonimización total", - "full_anonymization_description": "Esta acción creará una nueva copia de la base de datos y la anonimizará (eliminará todo el contenido de las notas y dejará solo la estructura y algunos metadatos no confidenciales) para compartirla en línea con fines de depuración sin temor a filtrar sus datos personales.", + "full_anonymization_description": "Crea una copia de la base de datos con todo el contenido eliminado, dejando solo la estructura y algunos metadatos no confidenciales. Seguro para compartirla en línea con fines de depuración de problemas.", "save_fully_anonymized_database": "Guarde la base de datos completamente anónima", "light_anonymization": "Anonimización ligera", - "light_anonymization_description": "Esta acción creará una nueva copia de la base de datos y realizará una ligera anonimización en ella; específicamente, solo se eliminará el contenido de todas las notas, pero los títulos y atributos permanecerán. Además, se mantendrán las notas de script JS frontend/backend personalizadas y los widgets personalizados. Esto proporciona más contexto para depurar los problemas.", + "light_anonymization_description": "Crea una copia con el contenido de las notas eliminado, excepto los títulos, atributos y scripts/widgets personalizados que permanecerán. Esto proporciona más contexto para el depurado.", "choose_anonymization": "Puede decidir usted mismo si desea proporcionar una base de datos total o ligeramente anónima. Incluso una base de datos totalmente anónima es muy útil; sin embargo, en algunos casos, una base de datos ligeramente anónima puede acelerar el proceso de identificación y corrección de errores.", "save_lightly_anonymized_database": "Guarde una base de datos ligeramente anónima", "existing_anonymized_databases": "Bases de datos anónimas existentes", @@ -1061,14 +1081,17 @@ "error_creating_anonymized_database": "No se pudo crear una base de datos anónima; consulte los registros de backend para obtener más detalles", "successfully_created_fully_anonymized_database": "Se creó una base de datos completamente anónima en {{anonymizedFilePath}}", "successfully_created_lightly_anonymized_database": "Se creó una base de datos ligeramente anónima en {{anonymizedFilePath}}", - "no_anonymized_database_yet": "Aún no hay base de datos anónima." + "no_anonymized_database_yet": "Aún no hay base de datos anónima.", + "description": "Crear una copia anónima de su base de datos para compartir con los desarrolladores cuando depuren problemas, sin exponer datos personales." }, "database_integrity_check": { "title": "Verificación de integridad de la base de datos", "check_button": "Verificar la integridad de la base de datos", "checking_integrity": "Comprobando la integridad de la base de datos...", "integrity_check_succeeded": "La verificación de integridad fue exitosa; no se encontraron problemas.", - "integrity_check_failed": "La verificación de integridad falló: {{results}}" + "integrity_check_failed": "La verificación de integridad falló: {{results}}", + "check_integrity_label": "Verificar la integridad de la base de datos", + "check_integrity_description": "Verifcar que la base de datos no está dañada en el nivel SQLite." }, "sync": { "title": "Sincronizar", @@ -1078,7 +1101,10 @@ "filling_entity_changes": "Rellenar filas de cambios de entidad...", "sync_rows_filled_successfully": "Sincronizar filas completadas correctamente", "finished-successfully": "La sincronización finalizó exitosamente.", - "failed": "La sincronización falló: {{message}}" + "failed": "La sincronización falló: {{message}}", + "force_full_sync_label": "Forzar sincronización completa", + "force_full_sync_description": "Activa una sincronización completa con el servidor de sincronización, resubiendo todos los cambios.", + "fill_entity_changes_label": "Llenar cambios de entidad" }, "vacuum_database": { "title": "Limpiar base de datos", @@ -1169,12 +1195,15 @@ }, "images": { "images_section_title": "Imágenes", - "download_images_automatically": "Descargar imágenes automáticamente para usarlas sin conexión.", + "download_images_automatically": "Descargar imágenes automáticamente", "download_images_description": "El HTML pegado puede contener referencias a imágenes en línea; Trilium encontrará esas referencias y descargará las imágenes para que estén disponibles sin conexión.", "enable_image_compression": "Habilitar la compresión de imágenes", - "max_image_dimensions": "Ancho/alto máximo de una imagen en píxeles (la imagen cambiará de tamaño si excede esta configuración).", + "max_image_dimensions": "Dimensiones máximas de imagen", "max_image_dimensions_unit": "píxeles", - "jpeg_quality_description": "Calidad JPEG (10 - peor calidad, 100 - mejor calidad, se recomienda 50 - 85)" + "jpeg_quality_description": "Se recomienda un rango 50-85. Valores más pequeños reducen el tamaño del archivo, valores más altos preservan los detalles.", + "enable_image_compression_description": "Comprimir y ajustar el tamaño de las imágenes cuando son subidas o pegadas.", + "max_image_dimensions_description": "Las imágenes que excedan el límite de tamaño serán ajustadas automáticamente.", + "jpeg_quality": "Calidad JPEG" }, "attachment_erasure_timeout": { "attachment_erasure_timeout": "Tiempo de espera para borrar archivos adjuntos", @@ -2201,5 +2230,8 @@ "sample_venn": "Venn", "sample_ishikawa": "Ishikawa", "sample_treemap": "Mapa de árbol" + }, + "revisions": { + "title": "Revisiones de nota" } } From 7e1090c59d65fd4d59a1bba6aa7cec6479e77f7c Mon Sep 17 00:00:00 2001 From: Marcel Date: Tue, 14 Apr 2026 22:40:57 +0200 Subject: [PATCH 218/482] Translated using Weblate (German) Currently translated at 100.0% (403 of 403 strings) Translation: Trilium Notes/Server Translate-URL: https://hosted.weblate.org/projects/trilium/server/de/ --- .../src/assets/translations/de/server.json | 34 ++++++++++++++++--- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/apps/server/src/assets/translations/de/server.json b/apps/server/src/assets/translations/de/server.json index 8dc060b456..124ed7b670 100644 --- a/apps/server/src/assets/translations/de/server.json +++ b/apps/server/src/assets/translations/de/server.json @@ -198,7 +198,8 @@ "december": "Dezember" }, "special_notes": { - "search_prefix": "Suche:" + "search_prefix": "Suche:", + "llm_chat_prefix": "Chat:" }, "test_sync": { "not-configured": "Der Synchronisations-Server-Host ist nicht konfiguriert. Bitte konfiguriere zuerst die Synchronisation.", @@ -226,7 +227,7 @@ "go-to-previous-note-title": "Zur vorherigen Notiz gehen", "go-to-next-note-title": "Zur nächsten Notiz gehen", "new-note-title": "Neue Notiz", - "search-notes-title": "Notizen durchsuchen", + "search-notes-title": "Suche Notiz", "calendar-title": "Kalender", "recent-changes-title": "neue Änderungen", "bookmarks-title": "Lesezeichen", @@ -240,7 +241,7 @@ "shortcuts-title": "Tastenkürzel", "text-notes": "Text Notizen", "code-notes-title": "Code Notizen", - "images-title": "Bilder", + "images-title": "Medien", "spellcheck-title": "Rechtschreibprüfung", "password-title": "Passwort", "etapi-title": "ETAPI", @@ -256,7 +257,11 @@ "inbox-title": "Posteingang", "zen-mode": "Zen-Modus", "command-palette": "Befehlspalette öffnen", - "tab-switcher-title": "Tabauswahl" + "tab-switcher-title": "Tabauswahl", + "llm-chat-history-title": "KI-Chat Historie", + "custom-dictionary-title": "Benutzerdefiniertes Verzeichnis", + "llm-title": "KI / LLM", + "sidebar-chat-title": "KI-Chat" }, "notes": { "new-note": "Neue Notiz", @@ -429,7 +434,10 @@ "last-updated": "Zuletzt aktualisiert am {{- date}}", "subpages": "Unterseiten:", "on-this-page": "Auf dieser Seite", - "expand": "Erweitern" + "expand": "Erweitern", + "toggle-navigation": "Navigation umschalten", + "toggle-toc": "Inhaltsverzeichnis umschalten", + "logo-alt": "Logo" }, "sql_init": { "db_not_initialized_desktop": "Datenbank nicht initialisiert, bitte folge den Anweisungen auf dem Bildschirm.", @@ -437,5 +445,21 @@ }, "desktop": { "instance_already_running": "Es läuft bereits eine Instanz, bitte beachte stattdessen diese Instanz." + }, + "password": { + "incorrect": "Das eingegebene Passwort ist nicht korrekt." + }, + "script": { + "wrong-environment": "Kann die Notiz \"{{- noteTitle}}\" ({{- noteId}}) nicht ausführen. Dies ist ein {{- actualEnv}} Skript, aber die Ausführung wurde im {{- expectedEnv}} versucht." + }, + "search": { + "error": { + "in-context": "Fehler in {{- context}}: {{- message}}", + "reserved-keyword": "\"{{- token}}\" ist ein reserviertes Stichwort. Um eine Wortgenaue Suche durchzuführen, verwende Anführungszeichen \"{{- token}}\"", + "cannot-compare-with": "Vergleich mit \"{{- token}}\" nicht möglich. Um eine Wortgenaue Suche durchzuführen, verwende Anführungszeichen \"{{- token}}\"", + "misplaced-expression": "Fehlplatzierter oder unvollständiger Ausdruck \"{{- token}}\"", + "fulltext-after-expression": "\"{{- token}}\" ist kein valider Ausdruck. Um einen Text zu suchen, platziere ihn vor den Attributfiltern (z.B. \"{{- token}} #label\" anstatt \"#label {{- token}}\").", + "unrecognized-expression": "Nicht erkannter Ausdruck \"{{- token}}\"" + } } } From 2bf2d977ad61d2ecb398e7ad7dbed7bde27a8913 Mon Sep 17 00:00:00 2001 From: green Date: Tue, 14 Apr 2026 08:26:52 +0200 Subject: [PATCH 219/482] Translated using Weblate (Japanese) Currently translated at 99.9% (1879 of 1880 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/ --- .../src/translations/ja/translation.json | 219 +++++++++++------- 1 file changed, 140 insertions(+), 79 deletions(-) diff --git a/apps/client/src/translations/ja/translation.json b/apps/client/src/translations/ja/translation.json index 3c7d396362..c310f1e846 100644 --- a/apps/client/src/translations/ja/translation.json +++ b/apps/client/src/translations/ja/translation.json @@ -183,10 +183,10 @@ "monday": "月曜日", "first-week-of-the-year": "年の最初の週", "first-week-contains-first-day": "最初の週には、元日が含まれる", - "first-week-contains-first-thursday": "最初の週には、その年の最初の木曜日が含まれる", + "first-week-contains-first-thursday": "最初の週には、最初の木曜日が含まれる(ISO 8601)", "first-week-has-minimum-days": "最初の週は最低日数", "min-days-in-first-week": "最初の週の最低日数", - "first-week-warning": "最初の週のオプションを変更すると、既存のウィークノートと重複する可能性があり、既存のウィークノートはそれに応じて更新されません。", + "first-week-warning": "この設定を変更すると、既存のウィークノートと重複が発生する可能性があります。", "formatting-locale": "日付と数値のフォーマット", "formatting-locale-auto": "アプリケーションの言語に基づいて", "tuesday": "火曜日", @@ -822,17 +822,21 @@ "filling_entity_changes": "エンティティ変更行を入力中...", "sync_rows_filled_successfully": "同期行が正常に入力されました", "finished-successfully": "同期が正常に完了しました。", - "failed": "同期に失敗しました: {{message}}" + "failed": "同期に失敗しました: {{message}}", + "force_full_sync_label": "強制的な完全同期", + "force_full_sync_description": "同期サーバーとの完全同期を実行し、すべての変更を再アップロードします。", + "fill_entity_changes_label": "エンティティの変更を反映", + "fill_entity_changes_description": "エンティティの変更履歴を再構築します。同期処理で一部の変更が反映されていない場合に使用してください。" }, "fonts": { "fonts": "フォント", - "main_font": "メインフォント", + "main_font": "インターフェース テキスト", "font_family": "フォントファミリー", "size": "サイズ", - "note_tree_font": "ノートツリーフォント", - "note_detail_font": "ノート詳細フォント", - "monospace_font": "等幅(コード)フォント", - "not_all_fonts_available": "リストされているすべてのフォントが、お使いのシステムで利用できるとは限りません。", + "note_tree_font": "ノートツリー テキスト", + "note_detail_font": "ドキュメント テキスト", + "monospace_font": "等幅フォント", + "not_all_fonts_available": "リストにあるすべてのフォントが、お使いのシステムで利用できるとは限りません", "generic-fonts": "一般的なフォント", "sans-serif-system-fonts": "サンセリフのシステムフォント", "serif-system-fonts": "セリフのシステムフォント", @@ -842,7 +846,12 @@ "sans-serif": "サンセリフ", "monospace": "等幅", "system-default": "システムのデフォルト", - "theme_defined": "テーマが定義されました" + "theme_defined": "テーマが定義されました", + "custom_fonts": "カスタムフォントを使用", + "preview": "プレビュー", + "monospace_font_description": "コードノートとコードブロックに使用されます", + "size_relative_to_general": "サイズは一般的なフォントサイズを基準としています", + "apply_changes": "変更を適用するには再読み込みしてください" }, "max_content_width": { "title": "コンテンツ幅", @@ -852,20 +861,23 @@ "centerContent": "コンテンツを中央に配置" }, "theme": { - "title": "アプリのテーマ", - "theme_label": "テーマ", + "title": "ユーザーインターフェース", + "theme_label": "アプリケーションのテーマ", "override_theme_fonts_label": "テーマのフォントを上書き", - "auto_theme": "レガシー(システムの配色に従う)", - "light_theme": "レガシー(ライト)", - "dark_theme": "レガシー(ダーク)", - "triliumnext": "Trilium(システムの配色に従う)", - "triliumnext-light": "Trilium(ライト)", - "triliumnext-dark": "Trilium(ダーク)", + "auto_theme": "システムの配色に従う", + "light_theme": "ライト", + "dark_theme": "ダーク", + "triliumnext": "システムの配色に従う", + "triliumnext-light": "ライト", + "triliumnext-dark": "ダーク", "layout": "レイアウト", "layout-vertical-title": "垂直", "layout-horizontal-title": "水平", "layout-vertical-description": "ランチャーバーは左側(デフォルト)", - "layout-horizontal-description": "ランチャーバーはタブバーの下にあり、タブバーは全幅に。" + "layout-horizontal-description": "ランチャーバーはタブバーの下にあり、タブバーは全幅に。", + "modern_themes": "モダン", + "legacy_themes": "レガシー", + "custom_themes": "カスタム" }, "vim_key_bindings": { "use_vim_keybindings_in_code_notes": "Vimキーバインド", @@ -902,27 +914,30 @@ }, "search_engine": { "title": "検索エンジン", - "custom_search_engine_info": "カスタム検索エンジンは、名前とURLの両方を設定する必要があります。どちらも設定されていない場合、DuckDuckGoがデフォルトの検索エンジンとして使用されます。", - "predefined_templates_label": "定義済みの検索エンジンのテンプレート", + "custom_search_engine_info": "選択したテキストをウェブ上で検索する際に使用します。設定されていない場合は、DuckDuckGo が使用されます。", + "predefined_templates_label": "プリセット", "bing": "Bing", "baidu": "Baidu", "duckduckgo": "DuckDuckGo", "google": "Google", - "custom_name_label": "カスタム検索エンジンの名前", - "custom_name_placeholder": "カスタム検索エンジンの名前", - "custom_url_label": "カスタム検索エンジンのURLには、検索語句のプレースホルダーとして {keyword} を含める必要があります。", - "custom_url_placeholder": "検索エンジンの URL をカスタマイズ", - "save_button": "保存" + "custom_name_label": "名前", + "custom_name_placeholder": "検索エンジン名", + "custom_url_label": "URL", + "custom_url_placeholder": "検索エンジンの URL", + "save_button": "保存", + "custom_url_description": "検索語句の代わりに {keyword} を使用してください。" }, "tray": { "title": "システムトレイ", - "enable_tray": "トレイを有効にする (この変更を適用にするには、Triliumを再起動する必要があります)" + "enable_tray": "トレイアイコン", + "enable_tray_description": "この変更を有効にするには、Trilium を再起動する必要があります。" }, "heading_style": { "title": "見出しのスタイル", "plain": "プレーン", "underline": "下線", - "markdown": "Markdownスタイル" + "markdown": "Markdownスタイル", + "description": "テキストノート内の見出しの表示スタイル。" }, "highlights_list": { "title": "ハイライトリスト", @@ -951,20 +966,22 @@ "text_auto_read_only_size": { "title": "自動読み取り専用のサイズ", "description": "自動読み取り専用のノートサイズは、ノートが読み取り専用モード(パフォーマンス上の理由)で表示されるようになるサイズです。", - "label": "自動読み取り専用のサイズ(テキストノート)", + "label": "自動で読み取り専用になるサイズ", "unit": "文字" }, "code_auto_read_only_size": { "title": "自動読み取り専用のサイズ", "description": "自動読み取り専用のノートサイズは、ノートが読み取り専用モード(パフォーマンス上の理由)で表示されるようになるサイズです。", "unit": "文字", - "label": "自動読み取り専用のサイズ(コードノート)" + "label": "自動で読み取り専用になるサイズ" }, "custom_date_time_format": { - "title": "日付/時刻フォーマットのカスタム", + "title": "日付/時刻の形式", "description": "またはツールバーから挿入される日付と時刻のフォーマットをカスタマイズする。 利用可能なトークンについては Day.js ドキュメント を参照してください。", - "format_string": "文字列形式:", - "formatted_time": "日付/時刻形式:" + "format_string": "書式文字列", + "formatted_time": "日付/時刻の形式", + "description_short": "ツールバーから挿入する日付と時刻の形式をカスタマイズできます。", + "preview": "プレビュー: {{preview}}" }, "backup": { "automatic_backup": "自動バックアップ", @@ -980,7 +997,8 @@ "path": "パス", "database_backed_up_to": "データベースは{{backupFilePath}}にバックアップされました", "no_backup_yet": "バックアップがありません", - "download": "ダウンロード" + "download": "ダウンロード", + "title": "バックアップ" }, "password": { "wiki": "wiki", @@ -992,16 +1010,20 @@ "new_password_confirmation": "新パスワードの確認", "change_password": "パスワードの変更", "change_password_heading": "パスワードの変更", - "protected_session_timeout": "保護されたセッションのタイムアウト", - "protected_session_timeout_description": "保護されたセッションのタイムアウトは、保護されたセッションがブラウザのメモリから消去される時間です。これは、保護されたノートとの最後のやり取りから測定されます。参照", + "protected_session_timeout": "保護されたセッション", + "protected_session_timeout_description": "ブラウザのメモリからセッションが削除されるまでの非アクティブ時間。詳細はこちら", "for_more_info": "詳細はこちら。", - "protected_session_timeout_label": "保護されたセッションのタイムアウト:", + "protected_session_timeout_label": "セッションが自動で終了するまでの時間", "reset_confirmation": "パスワードをリセットすると、保護されているすべてのノートにアクセスできなくなります。本当にパスワードをリセットしますか?", "reset_success_message": "パスワードがリセットされました。新しいパスワードを設定してください", "set_password_heading": "パスワードの設定", "set_password": "パスワードの設定", "password_mismatch": "新しいパスワードが同じではありません。", - "password_changed_success": "パスワードが変更されました。OKを押すとTriliumがリロードされます。" + "password_changed_success": "パスワードが変更されました。OKを押すとTriliumがリロードされます。", + "change_password_description": "現在のパスワードを更新", + "reset_password": "パスワードをリセット", + "reset_password_description": "保護されたノートへのアクセス権を完全に失います", + "cancel": "キャンセル" }, "spellcheck": { "title": "スペルチェック", @@ -1017,17 +1039,19 @@ "related_description": "スペルチェック対応言語とカスタム辞書を設定します。" }, "sync_2": { - "config_title": "同期設定", - "server_address": "サーバーインスタンスのアドレス", - "timeout": "同期タイムアウト", - "proxy_label": "同期プロキシサーバー(任意)", + "config_title": "同期サーバー", + "server_address": "サーバーアドレス", + "timeout": "接続タイムアウト", + "proxy_label": "プロキシサーバー", "save": "保存", "help": "ヘルプ", - "test_title": "同期のテスト", - "test_description": "これは同期サーバとの接続とハンドシェイクをテストします。同期サーバーが初期化されていない場合、ローカルドキュメントと同期するように設定します。", + "test_title": "接続テスト", + "test_description": "同期サーバーへの接続をテストします。初期化されていない場合は、同期の設定を行います。", "test_button": "同期試行", "handshake_failed": "同期サーバーのハンドシェイクに失敗しました。エラー: {{message}}", - "timeout_description": "同期接続が遅い場合に、接続を諦めるまでの待機時間。ネットワークが不安定な場合は、この時間を長く設定してください。" + "timeout_description": "接続が遅い場合に接続を断念するまでの待機時間。", + "server_address_description": "同期先の Trilium サーバーの URL。", + "proxy_description": "システムのプロキシを使用する場合は空欄のままにしてください(デスクトップ版のみ)。すべてのプロキシをバイパスするには \"noproxy\" を使用してください。" }, "api_log": { "close": "閉じる" @@ -1346,7 +1370,8 @@ "title": "固定", "description": "編集ツールは「書式設定」のリボンタブに表示されます。" }, - "multiline-toolbar": "ツールバーが収まりきらない場合は、複数行で表示する。" + "multiline-toolbar": "ツールバーが収まりきらない場合は複数行で表示", + "toolbar_style": "ツールバーのスタイル" } }, "electron_context_menu": { @@ -1367,7 +1392,7 @@ "days": "日" }, "share": { - "title": "共有設定", + "title": "共有", "redirect_bare_domain": "ネイキッドドメインを共有ページにリダイレクト", "redirect_bare_domain_description": "匿名のユーザーをログイン画面ではなく共有ページにリダイレクトします", "show_login_link_description": "共有ページの下部にログインリンクを追加", @@ -1412,12 +1437,12 @@ "message_macos": "TriliumNext は現在、Rosetta 2による翻訳環境で実行されています。つまり、Apple Silicon MacではIntel (x64)バージョンを使用していることになります。これはパフォーマンスとバッテリー寿命に重大な影響を及ぼします。" }, "editorfeatures": { - "emoji_completion_enabled": "絵文字のオートコンプリートを有効", - "note_completion_enabled": "ノートのオートコンプリートを有効", - "emoji_completion_description": "有効にすると、「:」に続けて絵文字の名前を入力することで、テキストに絵文字を簡単に挿入できます。", - "note_completion_description": "有効にすると、「@」 に続けてノートのタイトルを入力することで、ノートへのリンクを作成できます。", - "slash_commands_enabled": "スラッシュコマンドを有効", - "slash_commands_description": "有効にすると、改行や見出しの挿入などの編集コマンドは、「/」 と入力して切り替えることができます。", + "emoji_completion_enabled": "絵文字のオートコンプリート", + "note_completion_enabled": "ノートのオートコンプリート", + "emoji_completion_description": "絵文字は \":\" の後に絵文字の名前を入力することで、テキストに絵文字を簡単に挿入できます。", + "note_completion_description": "ノートへのリンクは \"@\" の後にノートのタイトルを入力することで作成できます。", + "slash_commands_enabled": "スラッシュコマンド", + "slash_commands_description": "改行や見出しの挿入などの編集コマンドは \"/\" を入力して切り替えることができます。", "title": "機能" }, "table_context_menu": { @@ -1556,11 +1581,11 @@ }, "database_anonymization": { "title": "データベースの匿名化", - "full_anonymization": "完全匿名化", - "full_anonymization_description": "この操作により、データベースの新しいコピーが作成され、匿名化されます(すべてのノートの内容を削除し、構造と一部の非機密メタデータのみを残します)。これにより、個人データが漏洩する心配なく、デバッグ目的でオンライン共有できます。", + "full_anonymization": "完全な匿名化", + "full_anonymization_description": "ノートの内容をすべて削除し、構造と機密性の低いメタデータのみを残したデータベースのコピーを作成します。問題のデバッグ時にオンラインで共有しても安全です。", "save_fully_anonymized_database": "完全に匿名化されたデータベースを保存", "light_anonymization": "軽い匿名化", - "light_anonymization_description": "この操作により、データベースの新しいコピーが作成され、軽い匿名化が適用されます。具体的には、すべてのノートの内容のみが削除され、タイトルと属性はそのまま残ります。さらに、カスタムJSフロントエンド/バックエンドスクリプトノートとカスタムウィジェットもそのまま残ります。これにより、問題のデバッグのためのコンテキストがより多く提供されます。", + "light_anonymization_description": "ノートの内容は削除しますが、タイトル、属性、カスタムスクリプト/ウィジェットは残します。デバッグのためのコンテキストがより多く提供されます。", "choose_anonymization": "完全に匿名化したデータベースを提供するか、軽く匿名化したデータベースを提供するかは、あなた自身が決めることができます。完全に匿名化されたDBであっても非常に有用ですが、場合によっては軽く匿名化されたDBの方がバグの特定と修正のプロセスを速めることができます。", "save_lightly_anonymized_database": "軽く匿名化されたデータベースを保存", "existing_anonymized_databases": "既存の匿名化データベース", @@ -1569,14 +1594,17 @@ "error_creating_anonymized_database": "匿名化データベースの作成に失敗しました。詳細はバックエンドログを確認してください", "successfully_created_fully_anonymized_database": "完全に匿名化されたデータベースを {{anonymizedFilePath}} に作成", "successfully_created_lightly_anonymized_database": "軽く匿名化されたデータベースを {{anonymizedFilePath}} に作成", - "no_anonymized_database_yet": "匿名化されたデータベースはまだありません。" + "no_anonymized_database_yet": "匿名化されたデータベースはまだありません。", + "description": "問題のデバッグ時に開発者と共有するために、個人データを公開することなく、データベースの匿名化されたコピーを作成します。" }, "database_integrity_check": { "title": "データベースの整合性チェック", "check_button": "データベースの整合性をチェック", "checking_integrity": "データベースの整合性をチェックしています...", "integrity_check_succeeded": "整合性チェックに成功 - 問題は見つかりませんでした。", - "integrity_check_failed": "整合性チェックに失敗: {{results}}" + "integrity_check_failed": "整合性チェックに失敗: {{results}}", + "check_integrity_label": "データベースの整合性チェック", + "check_integrity_description": "SQLite レベルでデータベースが破損していないことを確認します。" }, "code-editor-options": { "title": "エディター" @@ -1723,14 +1751,18 @@ "find_and_fix_button": "一貫性の問題を見つけて修正する", "finding_and_fixing_message": "一貫性の問題を見つけて修正中…", "title": "一貫性をチェック", - "issues_fixed_message": "発見された可能性のある一貫性の問題はすべて修正されました。" + "issues_fixed_message": "発見された可能性のある一貫性の問題はすべて修正されました。", + "find_and_fix_label": "整合性の問題を検出して修正", + "find_and_fix_description": "データベース内のデータ整合性の問題をスキャンし、自動的に修復します。" }, "vacuum_database": { "title": "データベースのバキューム", "description": "これによりデータベースが再構築され、通常はデータベースファイルのサイズが小さくなります。実際のデータは変更されません。", "button_text": "データベースをバキューム", "vacuuming_database": "データベースのバキュームを実行中...", - "database_vacuumed": "データベースのバキューム処理が完了しました" + "database_vacuumed": "データベースのバキューム処理が完了しました", + "vacuum_label": "データベースのバキューム", + "vacuum_description": "データベースを再構築してファイルサイズを削減します。データは変更されません。" }, "ribbon": { "promoted_attributes_message": "プロモート属性がノートに存在する場合、プロモート属性のリボンタブが自動的に開きます", @@ -1738,12 +1770,12 @@ "widgets": "リボンウィジェット" }, "ui-performance": { - "enable-motion": "トランジションとアニメーションを有効にする", - "enable-shadows": "影を有効にする", - "enable-backdrop-effects": "メニュー、ポップアップ、パネルの背景効果を有効にする", + "enable-motion": "画面遷移とアニメーション", + "enable-shadows": "影", + "enable-backdrop-effects": "メニュー、ポップアップ、パネルの背景効果", "title": "パフォーマンス", - "enable-smooth-scroll": "スムーズスクロールを有効にする", - "app-restart-required": "(変更を有効にするにはアプリケーションの再起動が必要です)" + "enable-smooth-scroll": "スムーズスクロール", + "app-restart-required": "アプリの再起動が必要です" }, "code_mime_types": { "title": "ドロップダウンで利用可能なMIMEタイプ", @@ -1752,35 +1784,43 @@ "tooltip_code_note_syntax": "コードノート" }, "attachment_erasure_timeout": { - "attachment_erasure_timeout": "添付ファイル消去のタイムアウト", - "erase_attachments_after": "使用されていない添付ファイルを消去する期間:", - "manual_erasing_description": "手動で消去をトリガーすることもできます (上記で定義したタイムアウトを考慮せずに):", - "erase_unused_attachments_now": "使用されていない添付ノートを今すぐ消去", - "unused_attachments_erased": "使用されていない添付ファイルは削除されました。" + "attachment_erasure_timeout": "未使用の添付ファイル", + "erase_attachments_after": "未使用の添付ファイルを削除するまでの期間", + "manual_erasing_description": "上記のタイムアウト設定を無視して、手動で削除を実行する。", + "erase_unused_attachments_now": "未使用の添付ノートを今すぐ削除", + "unused_attachments_erased": "使用されていない添付ファイルは削除されました。", + "description": "どのノートからも参照されていない添付ファイルは未使用とみなされ、一定期間経過後に自動的に削除されます。", + "erase_attachments_after_description": "未使用の添付ファイルが完全に削除されるまでの時間。" }, "network_connections": { - "network_connections_title": "ネットワーク接続", - "check_for_updates": "アップデートを自動的に確認する" + "network_connections_title": "ネットワーク", + "check_for_updates": "アップデートを自動的に確認する", + "check_for_updates_description": "GitHub で新しいバージョンをチェックし、利用可能な場合はグローバルメニューに通知を表示します。" }, "note_erasure_timeout": { - "note_erasure_timeout_title": "ノート消去のタイムアウト", - "erase_notes_after": "ノートを消去する間隔:", - "manual_erasing_description": "手動で消去をトリガーすることもできます (上記で定義したタイムアウトを考慮せずに):", + "note_erasure_timeout_title": "削除されたノート", + "erase_notes_after": "ノートを削除するまでの期間", + "manual_erasing_description": "上記のタイムアウト設定を無視して、手動で削除を実行する。", "erase_deleted_notes_now": "削除したノートを今すぐ消去", - "deleted_notes_erased": "削除されたノートは消去されました。" + "deleted_notes_erased": "削除されたノートは消去されました。", + "description": "削除されたノートは、最初は削除済みとしてマークされるだけで最近の変更から復元できます。一定期間が経過すると、完全に削除されます。", + "erase_notes_after_description": "削除されたノートが完全に削除されるまでの時間。" }, "revisions_snapshot_interval": { "note_revisions_snapshot_interval_title": "ノートの変更履歴の記録間隔", "note_revisions_snapshot_description": "ノートの変更履歴の記録間隔は、そのノートに対して新しい変更が作成されるまでの時間です。詳細については、wiki をご覧ください。", - "snapshot_time_interval_label": "ノートの変更履歴が記憶される時間:" + "snapshot_time_interval_label": "スナップショットの間隔", + "note_revisions_snapshot_description_short": "新しいノートの変更履歴が作成されるまでの時間。" }, "revisions_snapshot_limit": { "note_revisions_snapshot_limit_title": "ノートの変更履歴の記録制限", "note_revisions_snapshot_limit_description": "ノートの変更履歴の記録制限とは、各ノートに保存できる変更履歴の最大数を指します。-1 は制限なし、0 はすべての変更履歴を削除することを意味します。#versioningLimit ラベルを使用して、1 つのノートの最大変更数を設定できます。", - "snapshot_number_limit_label": "ノートの変更履歴の記録数の制限:", + "snapshot_number_limit_label": "最大変更履歴数", "snapshot_number_limit_unit": "スナップショット", "erase_excess_revision_snapshots": "余分な変更履歴を今すぐ消去", - "erase_excess_revision_snapshots_prompt": "余分な変更履歴が消去されました。" + "erase_excess_revision_snapshots_prompt": "余分な変更履歴が消去されました。", + "note_revisions_snapshot_limit_description_short": "ノートごとの最大変更履歴数。無制限の場合は -1、無効にする場合は 0 を指定してください。", + "erase_excess_revision_snapshots_description": "すべてのノートで、制限を超えた変更履歴を削除します。" }, "editability_select": { "note_is_read_only": "ノートは読み取り専用ですが、ボタンをクリックすると編集できます。", @@ -1916,7 +1956,9 @@ "related_code_notes": "コードノートの配色", "ui": "ユーザーインターフェース", "ui_old_layout": "旧レイアウト", - "ui_new_layout": "新しいレイアウト" + "ui_new_layout": "新しいレイアウト", + "ui_layout_style": "レイアウトスタイル", + "ui_layout_orientation": "ランチャーバーの方向" }, "units": { "percentage": "%" @@ -2334,5 +2376,24 @@ "processing_complete": "OCR 処理が完了しました。", "text_filtered_low_confidence": "OCR は {{confidence}}% の信頼度でテキストを検出しましたが、最小しきい値が {{threshold}}% であるため、破棄されました。", "open_media_settings": "設定を開く" + }, + "revisions": { + "title": "ノートの変更履歴" + }, + "database": { + "title": "データベース" + }, + "search": { + "title": "検索", + "fuzzy_matching_label": "検索時の入力ミス許容度", + "fuzzy_matching_description": "クイック検索とフル検索に影響します。完全一致しない場合でも類似語を検索します。", + "autocomplete_fuzzy_label": "オートコンプリート時の入力ミス許容度", + "autocomplete_fuzzy_description": "ノートへのジャンプとノートの選択に影響します。処理速度は低下しますが、入力ミスを許容します。" + }, + "text_editor": { + "title": "エディター" + }, + "link": { + "failed_to_open": "'{{- href}}' のリンクを開けなせんでした: {{- message}}" } } From f0293b7f0742b42f062f8af6e8988e6426b1e377 Mon Sep 17 00:00:00 2001 From: passkal4 Date: Wed, 15 Apr 2026 03:56:43 +0200 Subject: [PATCH 220/482] Added translation using Weblate (Uyghur) --- apps/client/src/translations/ug/translation.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/client/src/translations/ug/translation.json diff --git a/apps/client/src/translations/ug/translation.json b/apps/client/src/translations/ug/translation.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/apps/client/src/translations/ug/translation.json @@ -0,0 +1 @@ +{} From 3c0d5b761435ce6300ac9906f6ffe941c25cb524 Mon Sep 17 00:00:00 2001 From: passkal4 Date: Wed, 15 Apr 2026 03:56:45 +0200 Subject: [PATCH 221/482] Added translation using Weblate (Uyghur) --- docs/README-ug.md | 337 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 337 insertions(+) create mode 100644 docs/README-ug.md diff --git a/docs/README-ug.md b/docs/README-ug.md new file mode 100644 index 0000000000..0da3a37bf9 --- /dev/null +++ b/docs/README-ug.md @@ -0,0 +1,337 @@ +
+ Special thanks to:
+ + Warp sponsorship
+ Warp, built for coding with multiple AI agents
+
+ Available for macOS, Linux and Windows +
+ +
+ +# Trilium Notes + +![GitHub Sponsors](https://img.shields.io/github/sponsors/eliandoran) +![LiberaPay patrons](https://img.shields.io/liberapay/patrons/ElianDoran)\ +![Docker Pulls](https://img.shields.io/docker/pulls/triliumnext/trilium) +![GitHub Downloads (all assets, all +releases)](https://img.shields.io/github/downloads/triliumnext/trilium/total)\ +[![RelativeCI](https://badges.relative-ci.com/badges/Di5q7dz9daNDZ9UXi0Bp?branch=develop)](https://app.relative-ci.com/projects/Di5q7dz9daNDZ9UXi0Bp) +[![Translation +status](https://hosted.weblate.org/widget/trilium/svg-badge.svg)](https://hosted.weblate.org/engage/trilium/) + + + +[Chinese (Simplified Han script)](./README-ZH_CN.md) | [Chinese (Traditional Han +script)](./README-ZH_TW.md) | [English](../README.md) | [French](./README-fr.md) +| [German](./README-de.md) | [Greek](./README-el.md) | [Italian](./README-it.md) +| [Japanese](./README-ja.md) | [Romanian](./README-ro.md) | +[Spanish](./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. + +Trilium Screenshot + +## ⏬ 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](./User%20Guide/User%20Guide/) in + this repository + +### Quick Links +- [Getting Started Guide](https://docs.triliumnotes.org/) +- [Installation Instructions](https://docs.triliumnotes.org/user-guide/setup) +- [Docker + Setup](https://docs.triliumnotes.org/user-guide/setup/server/installation/docker) +- [Upgrading + TriliumNext](https://docs.triliumnotes.org/user-guide/setup/upgrading) +- [Basic Concepts and + Features](https://docs.triliumnotes.org/user-guide/concepts/notes) +- [Patterns of Personal Knowledge + Base](https://docs.triliumnotes.org/user-guide/misc/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://docs.triliumnotes.org/user-guide/concepts/notes/cloning)) +* Rich WYSIWYG note editor including e.g. tables, images and + [math](https://docs.triliumnotes.org/user-guide/note-types/text) with markdown + [autoformat](https://docs.triliumnotes.org/user-guide/note-types/text/markdown-formatting) +* Support for editing [notes with source + code](https://docs.triliumnotes.org/user-guide/note-types/code), including + syntax highlighting +* Fast and easy [navigation between + notes](https://docs.triliumnotes.org/user-guide/concepts/navigation/note-navigation), + full text search and [note + hoisting](https://docs.triliumnotes.org/user-guide/concepts/navigation/note-hoisting) +* Seamless [note + versioning](https://docs.triliumnotes.org/user-guide/concepts/notes/note-revisions) +* Note + [attributes](https://docs.triliumnotes.org/user-guide/advanced-usage/attributes) + can be used for note organization, querying and advanced + [scripting](https://docs.triliumnotes.org/user-guide/scripts) +* UI available in English, German, Spanish, French, Romanian, and Chinese + (simplified and traditional) +* Direct [OpenID and TOTP + integration](https://docs.triliumnotes.org/user-guide/setup/server/mfa) for + more secure login +* [Synchronization](https://docs.triliumnotes.org/user-guide/setup/synchronization) + with self-hosted sync server + * there are [3rd party services for hosting synchronisation + server](https://docs.triliumnotes.org/user-guide/setup/server/cloud-hosting) +* [Sharing](https://docs.triliumnotes.org/user-guide/advanced-usage/sharing) + (publishing) notes to public internet +* Strong [note + encryption](https://docs.triliumnotes.org/user-guide/concepts/notes/protected-notes) + with per-note granularity +* Sketching diagrams, based on [Excalidraw](https://excalidraw.com/) (note type + "canvas") +* [Relation + maps](https://docs.triliumnotes.org/user-guide/note-types/relation-map) and + [note/link maps](https://docs.triliumnotes.org/user-guide/note-types/note-map) + for visualizing notes and their relations +* Mind maps, based on [Mind Elixir](https://docs.mind-elixir.com/) +* [Geo maps](https://docs.triliumnotes.org/user-guide/collections/geomap) with + location pins and GPX tracks +* [Scripting](https://docs.triliumnotes.org/user-guide/scripts) - see [Advanced + showcases](https://docs.triliumnotes.org/user-guide/advanced-usage/advanced-showcases) +* [REST API](https://docs.triliumnotes.org/user-guide/advanced-usage/etapi) for + automation +* Scales well in both usability and performance upwards of 100 000 notes +* Touch optimized [mobile + frontend](https://docs.triliumnotes.org/user-guide/setup/mobile-frontend) for + smartphones and tablets +* Built-in [dark + theme](https://docs.triliumnotes.org/user-guide/concepts/themes), support for + user themes +* [Evernote](https://docs.triliumnotes.org/user-guide/concepts/import-export/evernote) + and [Markdown import & + export](https://docs.triliumnotes.org/user-guide/concepts/import-export/markdown) +* [Web Clipper](https://docs.triliumnotes.org/user-guide/setup/web-clipper) for + easy saving of web content +* Customizable UI (sidebar buttons, user-defined widgets, ...) +* [Metrics](https://docs.triliumnotes.org/user-guide/advanced-usage/metrics), + along with a Grafana Dashboard. + +✨ 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. + +[![Packaging +status](https://repology.org/badge/vertical-allrepos/triliumnext.svg)](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://docs.triliumnotes.org/user-guide/setup/server). + + +## 💻 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: + +[![Translation +status](https://hosted.weblate.org/widget/trilium/multi-auto.svg)](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://docs.triliumnotes.org/user-guide/note-types/relation-map) and + [link + maps](https://docs.triliumnotes.org/user-guide/advanced-usage/note-map#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. From 4b9d2537451fd3442480e0c95d9fbb947d1943b6 Mon Sep 17 00:00:00 2001 From: passkal4 Date: Wed, 15 Apr 2026 03:56:46 +0200 Subject: [PATCH 222/482] Added translation using Weblate (Uyghur) --- apps/server/src/assets/translations/ug/server.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/server/src/assets/translations/ug/server.json diff --git a/apps/server/src/assets/translations/ug/server.json b/apps/server/src/assets/translations/ug/server.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/apps/server/src/assets/translations/ug/server.json @@ -0,0 +1 @@ +{} From 1442041cda35980cc070887df9c78f2878b05d16 Mon Sep 17 00:00:00 2001 From: passkal4 Date: Wed, 15 Apr 2026 03:56:47 +0200 Subject: [PATCH 223/482] Added translation using Weblate (Uyghur) --- apps/website/src/translations/ug/translation.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/website/src/translations/ug/translation.json diff --git a/apps/website/src/translations/ug/translation.json b/apps/website/src/translations/ug/translation.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/apps/website/src/translations/ug/translation.json @@ -0,0 +1 @@ +{} From a0e9082364ed49cee2417910d2263e258b3f6550 Mon Sep 17 00:00:00 2001 From: passkal4 Date: Wed, 15 Apr 2026 04:47:19 +0200 Subject: [PATCH 224/482] Translated using Weblate (Uyghur) Currently translated at 1.4% (28 of 1880 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/ug/ --- .../src/translations/ug/translation.json | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/apps/client/src/translations/ug/translation.json b/apps/client/src/translations/ug/translation.json index 0967ef424b..5167ad0305 100644 --- a/apps/client/src/translations/ug/translation.json +++ b/apps/client/src/translations/ug/translation.json @@ -1 +1,46 @@ -{} +{ + "about": { + "title": "ھەققىدە Trilium Notes", + "homepage": "پروگرامما باش بېتى:", + "app_version": "نۇسخىسىApp:", + "db_version": "ساندان نۇسخىسى:", + "sync_version": "ماسلاش نۇسخىسى:", + "build_date": "قۇرۇلغان ۋاقىت:", + "build_revision": "قۇرۇلۇش نۇسخىسى:", + "data_directory": "سانلىق مەلۇمات مۇندەرىجىسى:" + }, + "toast": { + "critical-error": { + "title": "ئېغىر خاتالىق", + "message": "قوللىنىشچان پروگراممىنىڭ قوزغىلىشىغا توسالغۇ بولىدىغان ئېغىر خاتالىق كۆرۈلدى:\n\n{{message}}\n\nبۇ ئادەتتە script نىڭ كۈتۈلمىگەن خاتالىقىدىن كېلىپ چىقىدۇ. پروگراممىنى بىخەتەر ھالەتتە (safe mode) قوزغىتىپ مەسىلىنى ھەل قىلىپ بېقىڭ。" + }, + "widget-error": { + "title": "كىچىك زاپچاسلار دەسلەپكى قەدەمدە مەغلۇپ بولدى", + "message-custom": "ID نومۇرى \"{{id}}\"، تېمىسى \"{{title}}\" بولغان خاتىرىدىن كەلگەن ئۆزلەشتۈرۈلگەن ۋىجېت (Custom widget) تۆۋەندىكى سەۋەب تۈپەيلىدىن قوزغىتىلمىدى:\n\n{{message}}", + "message-unknown": "نامەلۇم كىچىك زاپچاسلار تۆۋەندىكى سەۋەبلەر تۈپەيلىدىن دەسلەپكى قەدەمدە بولالمايدۇ:\n\n{{message}}" + }, + "bundle-error": { + "title": "scriptنى يۈكلەش مەغلۇپ بولدى", + "message": "scriptنى ئىجرا قىلغىلى بولمىدى:\n\n{{message}}" + }, + "widget-list-error": { + "title": "serverدىن تىزىملىكىنى ئالغىلى بولمىدى" + }, + "widget-render-error": { + "title": "ئۆزلەشتۈرۈلگەن React ۋىجېتىنى تەقدىم قىلىش (Render) مەغلۇپ بولدى" + }, + "widget-missing-parent": "ئۆزگەرتىلگەن كىچىك زاپچاستا زۆرۈر بولغان’{{property}}‘ خاسلىقى بەلگىلەنمىگەن.\n\nئەگەر بۇ سكريپت UI ئېلېمېنتلىرىسىز ئىجرا بولۇشقا مەجبۇر بولسا، \"#run=frontendStartup\" نى ئىشلىتىڭ.", + "open-script-note": "script خاتىرىنى ئېچىش", + "scripting-error": "Custom script خاتالىقى: {{title}}" + }, + "add_link": { + "add_link": "ئۇلىنىش قوشۇش", + "help_on_links": "ئۇلىنىش ياردىمى", + "note": "خاتىرە", + "search_note": "خاتىرىنى نامى بويىچە ئىزدەش", + "link_title_mirrors": "ئۇلىنىش تېمىسى خاتىرىنىڭ ھازىرقى تېمىسى بىلەن ماس قەدەم بولىدۇ", + "link_title_arbitrary": "ئۇلىنىش تېمىسىنى خالىغانچە ئۆزگەرتىشكە بولىدۇ", + "link_title": "ئۇلىنىش تېمىسى", + "button_add_link": "ئۇلىنىش قوشۇش" + } +} From 5ad0cb2b4b2835e9a4dfad5f915e90ea9f410ac5 Mon Sep 17 00:00:00 2001 From: passkal4 Date: Wed, 15 Apr 2026 08:39:37 +0200 Subject: [PATCH 225/482] Translated using Weblate (Uyghur) Currently translated at 3.1% (5 of 158 strings) Translation: Trilium Notes/Website Translate-URL: https://hosted.weblate.org/projects/trilium/website/ug/ --- apps/website/src/translations/ug/translation.json | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/website/src/translations/ug/translation.json b/apps/website/src/translations/ug/translation.json index 0967ef424b..a7fb8b96c0 100644 --- a/apps/website/src/translations/ug/translation.json +++ b/apps/website/src/translations/ug/translation.json @@ -1 +1,11 @@ -{} +{ + "get-started": { + "title": "باشلاش", + "architecture": "قۇرۇلما:", + "older_releases": "كونا نۇسخىلىرىنى كۆرۈش" + }, + "hero_section": { + "title": "ئويلىرىڭىزنى رەتلەڭ. شەخسىي بىلىم ئامبىرىڭىزنى قۇرۇپ چىقىڭ.", + "subtitle": "Trilium — خاتىرە قالدۇرۇش ۋە شەخسىي بىلىم ئامبىرىنى رەتلەش ئۈچۈن لايىھەلەنگەن ئوچۇق كودلۇق ھەل قىلىش چارىسىدۇر. ئۇنى ئۆزىڭىزنىڭ ئۈستەلئۈستى كومپيۇتېرىدا بىۋاسىتە ئىشلىتەلەيسىز ياكى ئۆزىڭىز قۇرغان (self-hosted) مۇلازىمېتىر بىلەن ماسقەدەملەپ، خاتىرىلىرىڭىزنى ھەر ۋاقىت، ھەر قانداق يەردە زىيارەت قىلالايسىز." + } +} From a82d9dad1bb22abee44830bad3a4456ac56e2949 Mon Sep 17 00:00:00 2001 From: passkal4 Date: Wed, 15 Apr 2026 08:47:49 +0200 Subject: [PATCH 226/482] Translated using Weblate (Uyghur) Currently translated at 6.7% (8 of 119 strings) Translation: Trilium Notes/README Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ug/ --- docs/README-ug.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/README-ug.md b/docs/README-ug.md index 0da3a37bf9..1dd96d5ed3 100644 --- a/docs/README-ug.md +++ b/docs/README-ug.md @@ -29,19 +29,20 @@ script)](./README-ZH_TW.md) | [English](../README.md) | [French](./README-fr.md) [Spanish](./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. +Trilium Notes بولسا ھەقسىز، ئوچۇق كودلۇق، سىستېما ھالقىغان، قاتلاملىق خاتىرە +قالدۇرۇش ئەپى بولۇپ، ئۇ ئاساسلىقى چوڭ تىپتىكى شەخسىي بىلىم ئامبىرى قۇرۇشقا +ئەھمىيەت بېرىدۇ. Trilium Screenshot -## ⏬ 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/)** From d147bbe63de5a830e14509650a2c7f14ac5f0f90 Mon Sep 17 00:00:00 2001 From: passkal4 Date: Wed, 15 Apr 2026 08:37:03 +0200 Subject: [PATCH 227/482] Translated using Weblate (Uyghur) Currently translated at 1.4% (6 of 403 strings) Translation: Trilium Notes/Server Translate-URL: https://hosted.weblate.org/projects/trilium/server/ug/ --- apps/server/src/assets/translations/ug/server.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/server/src/assets/translations/ug/server.json b/apps/server/src/assets/translations/ug/server.json index 0967ef424b..ffc7858ad1 100644 --- a/apps/server/src/assets/translations/ug/server.json +++ b/apps/server/src/assets/translations/ug/server.json @@ -1 +1,10 @@ -{} +{ + "keyboard_actions": { + "back-in-note-history": "تارىختىكى ئالدىنقى خاتىرىگە قايتىش", + "forward-in-note-history": "تارىختىكى كېيىنكى خاتىرىگە ئۆتۈش", + "open-jump-to-note-dialog": "\"خاتىرىگە تېز ئۆتۈش\" كۆزنىكىنى ئېچىش", + "open-command-palette": "بۇيرۇق تىزىملىكىنى ئېچىش", + "quick-search": "تېز ئىزدەشنى قوزغىتىش", + "search-in-subtree": "ھازىرقى خاتىرىنىڭ تارماقلىرىدىن ئىزدەش" + } +} From 48e90396bd0025b0023791e9bdde6c4d5a2ae72d Mon Sep 17 00:00:00 2001 From: passkal4 Date: Wed, 15 Apr 2026 08:46:05 +0200 Subject: [PATCH 228/482] Translated using Weblate (Uyghur) Currently translated at 8.4% (159 of 1880 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/ug/ --- .../src/translations/ug/translation.json | 169 +++++++++++++++++- 1 file changed, 161 insertions(+), 8 deletions(-) diff --git a/apps/client/src/translations/ug/translation.json b/apps/client/src/translations/ug/translation.json index 5167ad0305..7d3a4d0e32 100644 --- a/apps/client/src/translations/ug/translation.json +++ b/apps/client/src/translations/ug/translation.json @@ -1,8 +1,8 @@ { "about": { - "title": "ھەققىدە Trilium Notes", + "title": "Trilium خاتىرە ھەققىدە", "homepage": "پروگرامما باش بېتى:", - "app_version": "نۇسخىسىApp:", + "app_version": "App نۇسخىسى:", "db_version": "ساندان نۇسخىسى:", "sync_version": "ماسلاش نۇسخىسى:", "build_date": "قۇرۇلغان ۋاقىت:", @@ -34,13 +34,166 @@ "scripting-error": "Custom script خاتالىقى: {{title}}" }, "add_link": { - "add_link": "ئۇلىنىش قوشۇش", - "help_on_links": "ئۇلىنىش ياردىمى", + "add_link": "ئۇلانما قوشۇش", + "help_on_links": "ئۇلانما ياردىمى", "note": "خاتىرە", "search_note": "خاتىرىنى نامى بويىچە ئىزدەش", - "link_title_mirrors": "ئۇلىنىش تېمىسى خاتىرىنىڭ ھازىرقى تېمىسى بىلەن ماس قەدەم بولىدۇ", - "link_title_arbitrary": "ئۇلىنىش تېمىسىنى خالىغانچە ئۆزگەرتىشكە بولىدۇ", - "link_title": "ئۇلىنىش تېمىسى", - "button_add_link": "ئۇلىنىش قوشۇش" + "link_title_mirrors": "ئۇلانما تېمىسى خاتىرىنىڭ ھازىرقى تېمىسى بىلەن ماس قەدەم بولىدۇ", + "link_title_arbitrary": "ئۇلانما تېمىسىنى خالىغانچە ئۆزگەرتىشكە بولىدۇ", + "link_title": "ئۇلانما تېمىسى", + "button_add_link": "ئۇلانما قوشۇش" + }, + "branch_prefix": { + "edit_branch_prefix": "شاخچە ئالدى قوشۇمچىسىنى تەھرىرلەش", + "edit_branch_prefix_multiple": "{{count}} دانە شاخچىنىڭ ئالدى قوشۇمچىسىنى تەھرىرلەش", + "help_on_tree_prefix": "دەرەخ ئالدى قوشۇمچىسى ياردىمى", + "prefix": "ئالدى قوشۇمچە:· ", + "save": "ساقلاش", + "branch_prefix_saved": "شاخچە ئالدى قوشۇمچىسى ساقلاندى.", + "branch_prefix_saved_multiple": "{{count}} دانە شاخچىغا ئالدى قوشۇمچە ساقلاندى.", + "affected_branches": "تەسىرگە ئۇچرىغان شاخچىلار {{count}}:" + }, + "bulk_actions": { + "bulk_actions": "تۈركۈملاپ بىر تەرەپ قىلىش", + "affected_notes": "تەسىرگە ئۇچرايدىغان خاتىرىلەر", + "include_descendants": "تاللانغان خاتىرىلەرنىڭ تارماق خاتىرىلىرىنى ئۆز ئىچىگە ئالسۇن", + "available_actions": "ئىشلەتكىلى بولىدىغان مەشغۇلاتلار", + "chosen_actions": "تاللانغان مەشغۇلاتلار", + "execute_bulk_actions": "تۈركۈملەپ بىر تەرەپ قىلىشنى ئىجرا قىلىش", + "bulk_actions_executed": "تۈركۈملەپ بىر تەرەپ قىلىش مۇۋەپپەقىيەتلىك تاماملاندى.", + "none_yet": "ھازىرچە مەشغۇلات يوق... ئۈستىدىكى مەشغۇلاتتىن تاللاڭ.", + "labels": "بەلگە", + "relations": "مۇناسىۋەتلەر", + "notes": "خاتىرىلەر", + "other": "باشقىلار" + }, + "clone_to": { + "clone_notes_to": "خاتىرىلەرنى كۆچۈرۈش...", + "help_on_links": "ئۇلانما ياردىمى", + "notes_to_clone": "كۆچۈرۈلىدىغان خاتىرىلەر", + "target_parent_note": "نىشان تۈپ خاتىرە", + "search_for_note_by_its_name": "نامى بويىچە خاتىرە ئىزدەش", + "cloned_note_prefix_title": "كۆچۈرۈلگەن خاتىرىگە ئالدى قوشۇمچە بېرىلىدۇ", + "prefix_optional": "ئالدى قوشۇمچە (ئىختىيارىي)", + "clone_to_selected_note": "تاللانغان خاتىرىگە كۆچۈرۈش", + "no_path_to_clone_to": "كۆچۈرۈش يولى يوق.", + "note_cloned": "\"{{clonedTitle}}\" خاتىرە\"{{targetTitle}}\" غا كۆچۈرۈلدى" + }, + "confirm": { + "confirmation": "جەزملەشتۈرۈش", + "cancel": "بىكار قىلىش", + "ok": "تامام", + "are_you_sure_remove_note": "\"{{title}}\" ناملىق خاتىرىنى مۇناسىۋەت خەرىتىسىدىن ئۆچۈرۈۋېتىشنى جەزملەشتۈرەمسىز؟ ", + "if_you_dont_check": "ئەگەر بۇنى تاللىمىسىڭىز، خاتىرە پەقەت مۇناسىۋەت خەرىتىسىدىنلا ئۆچۈرۈلىدۇ (خاتىرىنىڭ ئۆزى ئۆچۈرۈلمەيدۇ).", + "also_delete_note": "خاتىرىنىمۇ ئۆچۈرۈۋېتىش" + }, + "delete_notes": { + "title": "خاتىرىلەرنى ئۆچۈرۈش", + "close": "ياپ", + "clones_label": "كۆچۈرۈلمىلەر", + "delete_clones_description_one": "يەنە {{count}} دانە باشقا كۆچۈرۈلمىنىمۇ ئۆچۈرىدۇ. يېقىنقى ئۆزگىرىشلەردىن ئەسلىگە كەلتۈرگىلى بولىدۇ.", + "delete_clones_description_other": "يەنە {{count}} دانە باشقا كۆچۈرۈلمىلەرنىمۇ ئۆچۈرىدۇ. يېقىنقى ئۆزگىرىشلەردىن ئەسلىگە كەلتۈرگىلى بولىدۇ.", + "delete_all_clones_description": "بارلىق كۆچۈرۈلمىلەرنىمۇ ئۆچۈرۈش (يېقىنقى ئۆزگىرىشلەردىن ئەسلىگە كەلتۈرگىلى بولىدۇ)", + "erase_notes_label": "مەڭگۈلۈك ئۆچۈرۈش", + "erase_notes_description": "يۇمشاق ئۆچۈرۈشنىڭ ئورنىغا خاتىرىنى دەرھال مەڭگۈلۈك ئۆچۈرىدۇ. بۇنى قايتۇرغىلى بولمايدۇ ۋە قوللىنىشنى قايتا يۈكلەيدۇ.", + "erase_notes_warning": "خاتىرىلەرنى مەڭگۈلۈك ئۆچۈرۈش (قايتۇرغىلى بولمايدۇ)، بارلىق كۆچۈرۈلمىلەرنىمۇ ئۆز ئىچىگە ئالىدۇ. بۇ قوللىنىشنى قايتا يۈكلەيدۇ.", + "notes_to_be_deleted": "ئۆچۈرۈلىدىغان خاتىرىلەر ({{notesCount}})", + "no_note_to_delete": "ھېچقانداق خاتىرە ئۆچۈرۈلمەيدۇ (پەقەت كۆچۈرۈلمىلەر).", + "broken_relations_to_be_deleted": "بۇزۇلغان مۇناسىۋەتلە ({{relationCount}})", + "table_note_with_relation": "مۇناسىۋەتلىك خاتىرە", + "table_relation": "مۇناسىۋەت", + "table_points_to": "ئورۇنغا ئۇلىنىدۇ(ئۆچۈرۈلگەن)", + "cancel": "بىكار قىلىش", + "delete": "ئۆچۈرۈش" + }, + "export": { + "export_note_title": "خاتىرىنى چىقىرىش", + "close": "يېپىش", + "export_type_subtree": "بۇ خاتىرە ۋە ئۇنىڭ بارلىق تارماقلىرى", + "format_html": "HTML - بارلىق فورماتلارنى ساقلاپ قالىدىغان بولغاچقا تەۋسىيە قىلىنىدۇ", + "format_html_zip": "ZIP ئارخىپىدىكى HTML - بارلىق پىچىملارنى ساقلاپ قالىدىغان بولغاچقا، بۇ تاللاش تەۋسىيە قىلىنىدۇ.", + "format_markdown": "Markdown - بۇ كۆپ قىسىم فورماتلارنى ساقلاپ قالىدۇ.", + "format_opml": "OPML - پەقەت تېكىست ئۈچۈن ئىشلىتىلىدىغان پىلان (outliner) ئالماشتۇرۇش فورماتى. بۇنىڭغا فورماتلار، رەسىملەر ۋە ھۆججەتلەر كىرمەيدۇ.", + "opml_version_1": "OPML v1.0 - پەقەت ساپ تېكىستلا", + "opml_version_2": "HTML OPMLv2 - نىمۇ قوللايدۇ", + "export_type_single": "تارماقلىرىنى ئۆز ئىچىگە ئالمايدۇ، پەقەت مۇشۇ خاتىرىنىڭ ئۆزىلا", + "export": "چىقىرىش", + "choose_export_type": "ئالدى بىلەن چىقىرىش تۈرىنى تاللاڭ", + "export_status": "چىقىرىش ھالىتى", + "export_in_progress": "چىقىرىلىۋاتىدۇ: {{progressCount}}", + "export_finished_successfully": "چىقىرىش مۇۋەپپەقىيەتلىك تاماملاندى.", + "format_pdf": "PDF - بېسىپ چىقىرىش ياكى ھەمبەھرلەش مەقسىتىدە ئىشلىتىلىدۇ.", + "share-format": "توردا ئېلان قىلىش ئۈچۈن HTML - ھەمبەھرلەنگەن خاتىرىلەر بىلەن ئوخشاش تېمىنى ئىشلىتىدۇ، لېكىن تۇراقلىق تور بېكەت سۈپىتىدە ئېلان قىلىشقا بولىدۇ." + }, + "help": { + "title": "ئاساسىي كۇنۇپكىلار", + "editShortcuts": "كۇنۇپكا تېزلەتمىلىرىنى تەھرىرلەش", + "noteNavigation": "خاتىرە يولباشچىسى", + "goUpDown": "خاتىرە تىزىملىكىدە يۇقىرى/تۆۋەنگە يۆتكىلىش", + "collapseExpand": "تۈرنى قاتلاش/يېيىش", + "notSet": "بېكىتىلمىگەن", + "goBackForwards": "تارىختا كەينىگە/ئالدىغا يۆتكىلىش", + "showJumpToNoteDialog": "", + "scrollToActiveNote": "نۆۋەتتىكى خاتىرىگە سىيرىپ بېرىش", + "jumpToParentNote": "تۈپ خاتىرىگە تېز يۆتكىلىش", + "collapseWholeTree": "بارلىق خاتىرە دەرىخىنى يىغىش", + "collapseSubTree": "تارماق تۈرلەرنى يىغىش", + "tabShortcuts": "بەتكۈچ تېزلەتمىلىرى", + "newTabNoteLink": "خاتىرە ئۇلىنىشىنى چەككەندە، خاتىرىنى يېڭى بەتكۈچتە ئېچىش", + "newTabWithActivationNoteLink": "خاتىرە ئۇلىنىشىنى يېڭى بەتكۈچتە ئېچىش ۋە ئاكتىپلاش", + "openEmptyTab": "بوش بەتكۈچ ئېچىش", + "creatingNotes": "خاتىرە قۇرۇش", + "createNoteAfter": "ئاكتىپ خاتىرىدىن كېيىن يېڭى خاتىرە قۇرۇش", + "createNoteInto": "ئاكتىپ خاتىرىنىڭ ئىچىگە يېڭى تارماق خاتىرە قۇرۇش", + "movingCloningNotes": "خاتىرە يۆتكەش / كۆچۈرۈش", + "moveNoteUpDown": "خاتىرىنى تىزىملىكتە ئاستىغا/ئۈستىگە يۆتكەش", + "moveNoteUpHierarchy": "خاتىرىنى دەرىجە بويىچە ئۈستىگە يۆتكەش", + "multiSelectNote": "ئۈستى/ئاستىدىكى خاتىرىلەرنى كۆپ تاللاش", + "selectAllNotes": "ھازىرقى دەرىجىدىكى بارلىق خاتىرىلەرنى تاللاش", + "selectNote": "خاتىرىنى تاللاش", + "cutNotes": "نۆۋەتتىكى خاتىرىنى (ياكى تاللانغانلارنى) كېسىپ چاپلاش تاختىسىغا ئېلىش (يۆتكەش ئۈچۈن ئىشلىتىلىدۇ)", + "pasteNotes": "خاتىرىنى ئاكتىپ خاتىرىنىڭ ئىچىگە تارماق خاتىرە قىلىپ چاپلاش", + "deleteNotes": "خاتىرە ياكى تارماق تۈرلەرنى ئۆچۈرۈش", + "editingNotes": "خاتىرىلەرنى تەھرىرلەش", + "createEditLink": "سىرتقى ئۇلانما قۇرۇش / تەھرىرلەش", + "createInternalLink": "ئىچكى ئۇلانما قۇرۇش", + "followLink": "نۇر بەلگىسى ئاستىدىكى ئۇلانمىغا ئەگىشىش", + "insertDateTime": "نۆۋەتتىكى ۋاقىت ۋە كۈننى قىستۇرۇش", + "jumpToTreePane": "خاتىرە تىزىملىكىگە ئۆتۈش ۋە ئاكتىپ خاتىرىنى كۆرسىتىش", + "markdownAutoformat": "Markdown شەكىللىك ئاپتوماتىك فورماتلاش", + "troubleshooting": "مەسىلە ھەل قىلىش", + "reloadFrontend": "Trilium نىڭ ئالدى يۈزىنى قايتا يۈكلەش", + "showDevTools": "تەتقىقاتچى قوراللىرىنى كۆرسىتىش", + "showSQLConsole": "SQL كونترول سۇپىسىنى كۆرسىتىش", + "other": "باشقىلار", + "quickSearch": "نۇر بەلگىسىنى تېز ئىزدەش رامكىسىغا يۆتكەش", + "inPageSearch": "بەت ئىچىدە ئىزدەش" + }, + "import": { + "importIntoNote": "خاتىرىگە كىرگۈزۈش", + "chooseImportFile": "كىرگۈزىدىغان ھۆججەتنى تاللاش", + "importDescription": "تاللانغان ھۆججەت مەزمۇنلىرى تارماق خاتىرە سۈپىتىدە كىرگۈزۈلىدىغان ئورۇن", + "importZipRecommendation": "ZIP ھۆججىتىنى كىرگۈزگەندە، ھۆججەت قىسقۇچلارنىڭ ئورۇنلاشتۇرۇلۇشىغا ئاساسەن ئاپتوماتىك تارماق خاتىرىلەر قۇرۇلىدۇ.", + "options": "تاللانمىلار", + "safeImport": "بىخەتەر كىرگۈزۈش", + "shrinkImages": "«رەسىملەرنى كىچىكلىتىش", + "textImportedAsText": "ئۇچۇرى ئېنىق بولمىغان HTML، Markdown ۋە TXT لارنى تېكىست خاتىرىسىگە ئايلاندۇرۇش", + "replaceUnderscoresWithSpaces": "ئەكىرىلگەن خاتىرە ناملىرىدىكى ئاستى سىزىقلارنى بوشلۇققا ئالماشتۇرۇش", + "import": "كىرگۈزۈش", + "failed": "ئەكىرىش مەغلۇپ بولدى: {{message}}.", + "html_import_tags": { + "title": "HTML ئەكىرىش بەلگىلىرى", + "description": "خاتىرىلەرنى ئەكىرگەندە قايسى HTML بەلگىلىرىنى ساقلاپ قېلىشنى سەپلەڭ. بۇ تىزىملىكتە بولمىغان بەلگىلەر ئەكىرىش جەريانىدا ئۆچۈرۈۋېتىلىدۇ. بەزى بەلگىلەر (مەسىلەن 'script') بىخەتەرلىك ئۈچۈن ھەمىشە ئۆچۈرۈۋېتىلىدۇ.", + "placeholder": "ھەر بىر قۇرغا بىر HTML بەلگىسىدىن كىرگۈزۈڭ", + "reset_button": "ئەسلىدىكى تىزىملىككە ئەسلىگە قايتۇرۇش" + }, + "import-status": "كىرگۈزۈش ھالىتى", + "in-progress": "ئەكىرىلىۋاتىدۇ: {{progress}}", + "successful": "كىرگۈزۈش مۇۋەپپەقىيەتلىك تاماملاندى." + }, + "include_note": { + "dialog_title": "خاتىرىنى ئۆز ئىچىگە ئېلىش", + "label_note": "خاتىرە", + "placeholder_search": "خاتىرىنى نامى بويىچە ئىزدەش" } } From c34df3a17a04ce4fb221ca4e0cfbfa88da5629b7 Mon Sep 17 00:00:00 2001 From: seb2020 Date: Wed, 15 Apr 2026 07:17:49 +0200 Subject: [PATCH 229/482] Translated using Weblate (French) Currently translated at 88.8% (1671 of 1880 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/fr/ --- apps/client/src/translations/fr/translation.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/client/src/translations/fr/translation.json b/apps/client/src/translations/fr/translation.json index 5e0ef3a6c8..de1a84f60b 100644 --- a/apps/client/src/translations/fr/translation.json +++ b/apps/client/src/translations/fr/translation.json @@ -95,7 +95,10 @@ "notes_to_be_deleted": "Les notes suivantes seront supprimées ({{notesCount}})", "no_note_to_delete": "Aucune note ne sera supprimée (uniquement les clones).", "broken_relations_to_be_deleted": "Les relations suivantes seront rompues et supprimées ({{ relationCount}})", - "cancel": "Annuler" + "cancel": "Annuler", + "title": "Notes supprimées", + "clones_label": "Clone", + "erase_notes_label": "Supprimer définitivement" }, "export": { "export_note_title": "Exporter la note", @@ -1176,7 +1179,7 @@ }, "attachment_erasure_timeout": { "attachment_erasure_timeout": "Délai d'effacement des pièces jointes", - "erase_attachments_after": "Effacer les pièces jointes inutilisées après :", + "erase_attachments_after": "Effacer les pièces jointes inutilisées après :", "manual_erasing_description": "Vous pouvez également déclencher l'effacement manuellement (sans tenir compte du délai défini ci-dessus) :", "erase_unused_attachments_now": "Effacez maintenant les pièces jointes inutilisées", "unused_attachments_erased": "Les pièces jointes inutilisées ont été effacées." From e50ef8552b7137dbf9e045061561ee9a22d97ba9 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Wed, 15 Apr 2026 09:29:37 +0200 Subject: [PATCH 230/482] Update translation files Updated by "Remove blank strings" add-on in Weblate. Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/ --- apps/client/src/translations/ug/translation.json | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/client/src/translations/ug/translation.json b/apps/client/src/translations/ug/translation.json index 7d3a4d0e32..e0b866dd10 100644 --- a/apps/client/src/translations/ug/translation.json +++ b/apps/client/src/translations/ug/translation.json @@ -133,7 +133,6 @@ "collapseExpand": "تۈرنى قاتلاش/يېيىش", "notSet": "بېكىتىلمىگەن", "goBackForwards": "تارىختا كەينىگە/ئالدىغا يۆتكىلىش", - "showJumpToNoteDialog": "", "scrollToActiveNote": "نۆۋەتتىكى خاتىرىگە سىيرىپ بېرىش", "jumpToParentNote": "تۈپ خاتىرىگە تېز يۆتكىلىش", "collapseWholeTree": "بارلىق خاتىرە دەرىخىنى يىغىش", From a32eeb27e363a6323173a48441335c3531049563 Mon Sep 17 00:00:00 2001 From: passkal4 Date: Wed, 15 Apr 2026 14:38:36 +0200 Subject: [PATCH 231/482] Translated using Weblate (Uyghur) Currently translated at 87.9% (139 of 158 strings) Translation: Trilium Notes/Website Translate-URL: https://hosted.weblate.org/projects/trilium/website/ug/ --- .../src/translations/ug/translation.json | 182 +++++++++++++++++- 1 file changed, 180 insertions(+), 2 deletions(-) diff --git a/apps/website/src/translations/ug/translation.json b/apps/website/src/translations/ug/translation.json index a7fb8b96c0..6f7382faba 100644 --- a/apps/website/src/translations/ug/translation.json +++ b/apps/website/src/translations/ug/translation.json @@ -2,10 +2,188 @@ "get-started": { "title": "باشلاش", "architecture": "قۇرۇلما:", - "older_releases": "كونا نۇسخىلىرىنى كۆرۈش" + "older_releases": "كونا نۇسخىلىرىنى كۆرۈش", + "desktop_title": "ئېكران نۇسخىسىنى چۈشۈرۈش (v{{version}})", + "server_title": "كۆپ خىل ئۈسكۈنىلەردە ئىشلىتىش ئۈچۈن مۇلازىمېتىر تەڭشەش" }, "hero_section": { "title": "ئويلىرىڭىزنى رەتلەڭ. شەخسىي بىلىم ئامبىرىڭىزنى قۇرۇپ چىقىڭ.", - "subtitle": "Trilium — خاتىرە قالدۇرۇش ۋە شەخسىي بىلىم ئامبىرىنى رەتلەش ئۈچۈن لايىھەلەنگەن ئوچۇق كودلۇق ھەل قىلىش چارىسىدۇر. ئۇنى ئۆزىڭىزنىڭ ئۈستەلئۈستى كومپيۇتېرىدا بىۋاسىتە ئىشلىتەلەيسىز ياكى ئۆزىڭىز قۇرغان (self-hosted) مۇلازىمېتىر بىلەن ماسقەدەملەپ، خاتىرىلىرىڭىزنى ھەر ۋاقىت، ھەر قانداق يەردە زىيارەت قىلالايسىز." + "subtitle": "Trilium — خاتىرە قالدۇرۇش ۋە شەخسىي بىلىم ئامبىرىنى رەتلەش ئۈچۈن لايىھەلەنگەن ئوچۇق كودلۇق ھەل قىلىش چارىسىدۇر. ئۇنى ئۆزىڭىزنىڭ ئۈستەلئۈستى كومپيۇتېرىدا بىۋاسىتە ئىشلىتەلەيسىز ياكى ئۆزىڭىز قۇرغان (self-hosted) مۇلازىمېتىر بىلەن ماسقەدەملەپ، خاتىرىلىرىڭىزنى ھەر ۋاقىت، ھەر قانداق يەردە زىيارەت قىلالايسىز.", + "get_started": "باشلاش", + "github": "GitHub", + "dockerhub": "Docker Hub", + "screenshot_alt": "Trilium Notes ئېكران نۇسخىسىنىڭ ئېكران سۈرىتى" + }, + "organization_benefits": { + "title": "تەشكىلات", + "note_structure_title": "خاتىرە قۇرۇلمىسى", + "note_structure_description": "خاتىرىلەرنى دەرىجە (قاتلام) بويىچە تىزىشقا بولىدۇ. ھەر بىر خاتىرە ئۆز ئىچىگە تارماق خاتىرىلەرنى ئالالايدىغان بولغاچقا، قىسقۇچ (folder) ئىشلىتىشنىڭ ھاجىتى يوق. بىرلا خاتىرىنى قاتلاملىق قۇرۇلمىنىڭ كۆپلىگەن ئورۇنلىرىغا قوشقىلى بولىدۇ.", + "attributes_title": "خاتىرە بەلگىلىرى ۋە مۇناسىۋەتلىرى", + "attributes_description": "خاتىرىلەر ئارىسىدىكى مۇناسىۋەت ياكى بەلگىلەر ئارقىلىق تۈرگە ئايرىشنى قولايلاشتۇرۇڭ. يۇقىرى كۆتۈرۈلگەن خاسلىقلار (Promoted attributes) ئارقىلىق قۇرۇلمىلىق ئۇچۇرلارنى كىرگۈزۈڭ، بۇ ئۇچۇرلارنى جەدۋەل ۋە كانبان (Kanban) لاردا ئىشلەتكىلى بولىدۇ.", + "hoisting_title": "خىزمەت رايونى ۋە يۇقىرى كۆتۈرۈش", + "hoisting_description": "شەخسىي ۋە خىزمەت خاتىرىلىرىڭىزنى ئوخشىمىغان خىزمەت رايونلىرىغا گۇرۇپپىلاش ئارقىلىق، ئۇلارنى ئاسانلا بىر-بىرىدىن ئايرىۋەتەلەيسىز. ھەر بىر خىزمەت رايونى مەلۇم بىر خاتىرە توپلىمىغا مەركەزلەشكەن بولۇپ، خاتىرە دەرىخىڭىزدە پەقەت شۇنىڭغا مۇناسىۋەتلىك مەزمۇنلارنىلا كۆرسىتىدۇ." + }, + "productivity_benefits": { + "title": "يۇقىرى ئۈنۈملۈك ۋە بىخەتەر", + "revisions_title": "خاتىرە نۇسخا تارىخى", + "revisions_content": "خاتىرىلەر ئارقا سىپتا قەرەللىك ساقلىنىپ تۇرىدۇ، تۈزىتىلگەن نۇسخىلىرى ئارقىلىق بۇرۇنقى مەزمۇنلارنى كۆرگىلى ياكى خاتالاشقان ئۆزگەرتىشلەرنى ئەسلىگە كەلتۈرگىلى بولىدۇ. سىز يەنە ئېھتىياجغا قاراپ ئۆزىڭىز تۈزىتىلگەن نۇسخا قۇرالايسىز.", + "sync_title": "ماسقەدەملەش", + "sync_content": "ئۆزىڭىز قۇرغان ياكى بۇلۇتتىكى مۇلازىمېتىر ئارقىلىق، خاتىرىلىرىڭىزنى كۆپ ئۈسكۈنىلەر ئارىسىدا ئاسانلا ماسقەدەملىيەلەيسىز ھەمدە PWA ئارقىلىق تېلېفونىڭىزدا زىيارەت قىلالايسىز.", + "protected_notes_title": "قوغدالغان خاتىرىلەر", + "protected_notes_content": "سېزىمچان شەخسىي ئۇچۇرلىرىڭىزنى قوغداش ئۈچۈن، خاتىرىنى شىفىرلاڭ ھەمدە ئۇنى پارول بىلەن قوغدىلىدىغان مەخسۇس مەشغۇلات باسقۇچى (session) ئىچىگە قۇلۇپلاڭ.", + "jump_to_title": "تېز ئىزدەش ۋە بۇيرۇقلار", + "jump_to_content": "ماۋزۇ ئارقىلىق ئىزدەش ئارقىلىق، قاتلاملىق قۇرۇلمىدىكى خاتىرىلەرگە ياكى UI بۇيرۇقلىرىغا تېز سۈرئەتتە سەكرىگىلى بولىدۇ؛ تۇتۇق ماسلاشتۇرۇش (fuzzy matching) ئىقتىدارى ئىملا خاتالىقى ياكى ئازراق پەرقنى قوبۇل قىلالايدۇ.", + "search_title": "كۈچلۈك ئىزدەش ئىقتىدارى", + "search_content": "ياكى خاتىرىلەردىن تېكىست ئىزدەڭ ھەمدە تۈپ خاتىرە ياكى ئىزدەش چوڭقۇرلۇقىنى سۈزۈش ئارقىلىق ئىزدەش دائىرىسىنى كىچىكلىتىڭ.", + "web_clipper_title": "تور بەت تۇتۇپ ئېلىش", + "web_clipper_content": "تور بەت مەزمۇنىنى تۇتۇپ ئېلىڭ (ياكى ئېكران رەسىمىنى تۇتۇڭ) ھەمدە تور بەت كېسىپ ئالغۇچ (Web Clipper) قىستۇرمىسى ئارقىلىق بىۋاسىتە Trilium غا ساقلاڭ." + }, + "extensibility_benefits": { + "import_export_description": "Markdown، ENEX ۋە OPML فورماتلىرىدىن پايدىلىنىپ، باشقا ئەپ پروگراممىلىرى بىلەن ئاسانلا سانلىق مەلۇمات ئالماشتۇرغىلى بولىدۇ.", + "share_title": "خاتىرىلەرنى توردا ھەمبەھرىلەش", + "share_description": "ئەگەر سىزدە بىر مۇلازىمەت ماشىنىسى بولسا، ئۇنىڭدىن پايدىلىنىپ خاتىرىلىرىڭىزنىڭ بىر قىسمىنى باشقىلار بىلەن ھەمبەھرىلىيەلەيسىز.", + "scripting_title": "يۇقىرى دەرىجىلىك كود يېزىش", + "scripting_description": "Trilium دا ئۆزىڭىز ياسىغان كىچىك قوراللار ياكى Server تەرەپتىكى لوگىكا ئارقىلىق، ئۆزىڭىزگە خاس بىر گەۋدىلەشكەن ھەل قىلىش لايىھەسىنى قۇرۇپ چىقىڭ.", + "api_title": "REST API", + "api_description": "ئىچىگە ئورۇنلاشتۇرۇلغان REST API ئارقىلىق، پروگرامما تۈزۈش (كود يېزىش) ئۇسۇلىدا Trilium بىلەن سانلىق مەلۇمات ئالماشتۇرۇڭ.", + "title": "ھەمبەھىرلىنىش ۋە كېڭەيتىشچانلىقى", + "import_export_title": "كىرگۈزۈش / چىقىرىش" + }, + "collections": { + "title": "توپلىمىلار", + "calendar_title": "كالىندار", + "calendar_description": "شەخسىي ياكى خىزمەت پائالىيەتلىرىڭىزنى كالىندار ئارقىلىق باشقۇرۇڭ؛ پۈتۈن كۈنلۈك ۋە كۆپ كۈنلۈك پائالىيەتلىرىڭىزنى قوللايدۇ. ھەپتىلىك، ئايلىق ۋە يىللىق كۆرۈنۈشلەر ئارقىلىق بارلىق پائالىيەتلەرنى تېز سۈرئەتتە كۆرەلەيسىز. ئاددىي مەشغۇلات ئارقىلىقلا پائالىيەت قوشالايسىز ياكى سۆرەپ ئورنىنى ئۆزگەرتەلەيسىز.", + "table_title": "جەدۋەل", + "table_description": "خاتىرە ئۇچۇرلىرىنى جەدۋەل قۇرۇلمىسىدا كۆرسىتىڭ ۋە تەھرىرلەڭ؛ تېكىست، سان، تاللاش كۆزنەكچىسى (checkbox)،چېسلا ۋە ۋاقىت، ئۇلىنىش ھەمدە رەڭ قاتارلىق كۆپ خىل ئىستون تىپلىرىنى، شۇنداقلا مۇناسىۋەت (relation) ئىقتىدارىنى قوللايدۇ. ئېھتىياجغا قاراپ، جەدۋەل ئىچىدە خاتىرىلەرنى دەرەخسىمان قاتلاملىق قۇرۇلمىدا كۆرسىتىشكە بولىدۇ.", + "board_title": "كانبان تاختىسى", + "board_description": "ۋەزىپە ياكى تۈر ھالىتىنى كانبان تاختىسى شەكلىدە رەتلەڭ؛ يېڭى تۈرلەرنى ۋە ستونلارنى ئاسانلا قۇرۇڭ، كارتىلارنى سۆرىەپلا ئۇلارنىڭ بېجىرىلىش ھالىتىنى ئاددىي ئۇسۇلدا ئۆزگەرتىڭ.", + "geomap_title": "جۇغراپىيەلىك خەرىتە", + "geomap_description": "ئىختىيارىي بەلگىلەر ئارقىلىق، جۇغراپىيەلىك خەرىتە ئۈستىدە تەتىل پىلانىڭىزنى تۈزۈڭ ياكى قىزىقىش نۇقتىلىرىنى بەلگىلەڭ. خاتىرىلەنگەن GPX يولىنى كۆرسىتىش ئارقىلىق، سەپەر لىنىيەسىنى ئىز قوغلاپ كۆزەتكىلى بولىدۇ.", + "presentation_title": "تەقدىمات", + "presentation_description": "ئۇچۇرلارنى سلايد شەكلىدە رەتلەڭ ھەمدە راۋان ئۆتۈش ئۈنۈملىرى بىلەن پۈتۈن ئېكران ئەندىزىسىدە نامايان قىلىڭ. سلايدلارنى يەنە PDF شەكلىدە چىقىرىپ، باشقىلار بىلەن ئاسانلا ھەمبەھىرلىنىشكە بولىدۇ." + }, + "note_types": { + "title": "ئۇچۇرلارنى كۆرسىتىشنىڭ كۆپ خىل ئۇسۇللىرى", + "text_title": "تېكىستلىك خاتىرە", + "text_description": "خاتىرىلەرنى كۆرۈنۈشلۈك (ئېكراندا نېمىنى كۆرسىڭىز شۇ چىقىدىغان - WYSIWYG) تەھرىرلىگۈچ ئارقىلىق تەھرىرلىگىلى بولىدۇ؛ جەدۋەل، رەسىم، ماتېماتىكىلىق ئىپادىلەر ۋە كود نۇرى يورۇتۇلغان (syntax highlighting) كود بۆلەكلىرىنى قوللايدۇ. سىز Markdown غا ئوخشاش گرامماتىكا ياكى قىيپاش سىزىق (/) بۇيرۇقى ئارقىلىق تېكىست پىچىمىنى تېز سۈرئەتتە تەڭشىيەلەيسىز.", + "code_title": "كود خاتىرىسى", + "code_description": "كۆپ مىقداردىكى ئەسلى كودلار ياكى سىناق تېكىستلەر (scripts) ئادەتتە مەخسۇس تەھرىرلىگۈچتە يېزىلىدۇ؛ بۇ خىل تەھرىرلىگۈچلەر كۆپ خىل پروگرامما تىللىرىنى گرامماتىكىلىق نۇر بېرىش (syntax highlighting) بىلەن تەمىنلەيدۇ ھەمدە كۆپ خىل رەڭ تېمىلىرىنى قوللايدۇ.", + "file_title": "ھۆججەتلىك خاتىرە", + "file_description": "كۆپ ۋاسىتىلىك ھۆججەتلەرنى (PDF، رەسىم، سىن دېگەندەك) سىڭدۈرۈڭ ھەمدە ئەپ ئىچىدىلا ئالدىن كۆرۈڭ.", + "canvas_title": "سىزمىچىلىق تاختىسى", + "canvas_description": "چەكسىز سىزمىچىلىق تاختىسىدا شەكىللەرنى، رەسىملەرنى ۋە تېكىستلەرنى ئەركىن ئورۇنلاشتۇرۇڭ؛ ئۇ excalidraw.com بىلەن ئوخشاش تېخنىكىنى قوللىنىدۇ. ئۇ دىئاگرامما سىزىش، نۇسخا سىزما (draft) تەييارلاش ۋە كۆرۈنۈشلۈك پىلان تۈزۈش ئۈچۈن ئىنتايىن ماس كېلىدۇ.", + "mermaid_title": "Mermaid دىئاگراممىسى", + "mermaid_description": "Mermaid گرامماتىكىسىدىن پايدىلىنىپ جەريان خەرىتىسى، تۈر (class) دىئاگراممىسى، تەرتىپ دىئاگراممىسى ۋە گانت جەدۋىلى قاتارلىق تۈرلۈك دىئاگراممىلارنى قۇرۇڭ.", + "mindmap_title": "تەپەككۇر خەرىتىسى", + "mindmap_description": "ئوي-خىياللىرىڭىزنى كۆرۈنۈشلۈك ئۇسۇلدا رەتلەڭ ياكى بىر قېتىملىق پىكىر قوزغىتىش (brainstorming) ئېلىپ بېرىڭ.", + "others_list": "ۋە باشقىلار: <0>خاتىرىلەر خەرىتىسى، <1>مۇناسىۋەتلەر خەرىتىسى، <2>ساقلانغان ئىزدەشلەر، <3>خاتىرىنى رەڭلەش ۋە <4>تور كۆرۈنۈشلىرى." + }, + "faq": { + "title": "دائىم سورىلىدىغان سوئاللار", + "mobile_question": "كۆچمە ئەپ بارمۇ؟", + "mobile_answer": "ھازىرچە رەسمىي كۆچمە ئەپ يوق. ئەمما سىزدە مۇلازىمەت ماشىنىسى مىسالى (Server Instance) بولسا، تور كۆرگۈچ ئارقىلىق زىيارەت قىلالايسىز، ھەتتا ئۇنى ئىلگىرىلىگەن تور ئەپى (PWA) سۈپىتىدە قاچىلىۋالالايسىز. ئاندروئىد ئىشلەتكۈچىلىرى بولسا TriliumDroid ناملىق غەيرىي رەسمىي ئەپنى ئىشلەتسە بولىدۇ، بۇ ئەپ تورسىز ئىشلىتىشنى قوللايدۇ (ئىقتىدارى كومپيۇتېر نۇسخىسى بىلەن ئوخشاش).", + "database_question": "سانلىق مەلۇماتلار نەگە ساقلىنىدۇ؟", + "database_answer": "بارلىق خاتىرىلەر ئەپ قىسقۇچى ئىچىدىكى SQLite ساندانىدا ساقلىنىدۇ. Trilium نىڭ ساپ تېكىستلىك ھۆججەت ئەمەس، بەلكى ساندان ئىشلىتىشىدىكى سەۋەب: ساندان ئىقتىدارنى يۇقىرى كۆتۈرىدۇ، شۇنداقلا بەزى ئىقتىدارلارنى (مەسىلەن، كىلونلاش ئىقتىدارى — يەنى بىر خاتىرىنى دەرەخسىمان قۇرۇلمىنىڭ كۆپ يېرىدە كۆرسىتىش) تېكىستلىك ھۆججەت ئارقىلىق ئىشقا ئاشۇرۇش بىر قەدەر قىيىن. ئەپ قىسقۇچىنى تېپىش ئۈچۈن، <ھەققىدە> (About) كۆزنىكىگە كىرسىڭىزلا بولىدۇ.", + "server_question": "Trilium نى ئىشلىتىش ئۈچۈن مۇلازىمەت ماشىنىسى لازىممۇ؟", + "server_answer": "ياق، مۇلازىمېتىر تور كۆرگۈچ ئارقىلىق زىيارەت قىلىشنى قوللايدۇ ھەمدە سىزدە كۆپ ئۈسكۈنىلەر بولغاندا ماسقەدەملەشنى باشقۇرىدۇ. ئەگەر ماسقەدەملەش ئېھتىياجىڭىز بولمىسا، پەقەت كومپيۇتېر نۇسخىسىنى (Desktop App) چۈشۈرۈپ ئىشلەتسىڭىزلا كاپايە.", + "scaling_question": "بۇ ئەپ نۇرغۇن مىقداردىكى خاتىرىلەرنى بىر تەرەپ قىلىشتا قانچىلىك كېڭەيمىچىلىككە ئىگە؟", + "scaling_answer": "ئىشلىتىش ئەھۋالىغا ئاساسلانغاندا، بۇ ئەپ ئاز دېگەندىمۇ 100 مىڭ خاتىرىنى ھېچقانداق توسالغۇسىز بىر تەرەپ قىلالايدۇ. ئەمما شۇنىڭغا دىققەت قىلىڭكى، ئەگەر سىز ناھايىتى كۆپ مىقداردىكى چوڭ ھۆججەتلەرنى (مەسىلەن، بىر دانە ھۆججەتنىڭ چوڭلۇقى 1 GB غا يەتسە) يۈكلىسىڭىز، ماسقەدەملەش جەريانى مەغلۇپ بولۇشى مۇمكىن. چۈنكى Trilium ھۆججەت ساقلاش (مەسىلەن: NextCloud) ئەمەس، بەلكى بىلىم ئامبىرى قورالى بولۇشقا بەكرەك ئەھمىيەت بېرىدۇ.", + "network_share_question": "ساندانىمنى تور دېسكىسى (Cloud Drive) ئارقىلىق ھەمبەھىرلىيەلەمدىم؟", + "network_share_answer": "ياق، ئادەتتە SQLite ساندانىنى تور دېسكىسى ئارقىلىق ھەمبەھىرلەش تەۋسىيە قىلىنمايدۇ. گەرچە بەزىدە ئۈنۈم بەرگەندەك قىلسىمۇ، لېكىن تور مۇھىتىدىكى ھۆججەت قۇلۇپلاش مېخانىزمىنىڭ مۇكەممەل بولماسلىقى سەۋەبىدىن، سانداننىڭ بۇزۇلۇپ كېتىش خەۋپى بار.", + "security_question": "سانلىق مەلۇماتلىرىم قانداق قوغدىلىدۇ؟", + "security_answer": "سۈكۈتتىكى ھالەتتە، خاتىرىلەر شىفىرلانمايدۇ، سانداندىن بىۋاسىتە ئوقۇشقا بولىدۇ. ئەگەر خاتىرە شىفىرلانغان ھالەت دەپ بەلگىلەنسە، ئۇنداقتا شۇ خاتىرە AES-128-CBC ئالگورىزىمى بىلەن شىفىرلىنىدۇ." + }, + "final_cta": { + "title": "Trilium Notes نى ئىشلەتكىلى تەييار بولدىڭىزمۇ؟", + "description": "كۈچلۈك ئىقتىدار ۋە تولۇق شەخسىيەتنى قوغداشقا تايىنىپ، ئۆزىڭىزنىڭ شەخسىي بىلىم ئامبىرىنى قۇرۇپ چىقىڭ.", + "get_started": "ئىشلىتىشنى باشلاش" + }, + "components": { + "link_learn_more": "تەپسىلاتىنى كۆرۈش..." + }, + "download_now": { + "text": "ھازىر چۈشۈرۈش ", + "platform_big": "{{platform}} ئۈچۈن v{{version}}", + "platform_small": "{{platform}} ئۈچۈن", + "linux_big": "Linux ئۈچۈن v{{version}}", + "linux_small": "Linux ئۈچۈن", + "more_platforms": "باشقا سۇپىلار ۋە مۇلازىمېتىر تەڭشەكلىرى" + }, + "header": { + "get-started": "ئىشلىتىشنى باشلاش", + "documentation": "ھۆججەتلەر", + "resources": "مەنبەلەر", + "support-us": "بىزنى قوللاڭ" + }, + "footer": { + "copyright_and_the": " ھەمدە ", + "copyright_community": "جامائەت" + }, + "social_buttons": { + "github": "GitHub", + "github_discussions": "GitHub مۇنازىرىسى", + "matrix": "Matrix", + "reddit": "Reddit" + }, + "support_us": { + "title": "بىزنى قوللاڭ", + "financial_donations_title": "ئىقتىسادىي ياردەم", + "financial_donations_description": "Trilium نى ئېچىش ۋە قوغداشقا يۈزلىگەن سائەتلىك خىزمەت سىڭدۈرۈلدى. سىزنىڭ قوللىشىڭىز ئۇنىڭ ئوچۇق مەنبەلىك خاراكتېرىنىڭ داۋاملىشىشىغا كاپالەتلىك قىلىدۇ، ئىقتىدارلىرىنىڭ ئۈزلۈكسىز ئەلالىشىشىنى ئىلگىرى سۈرىدۇ ھەمدە باشقۇرۇش (Hosting) قاتارلىق تىجارەت تەننەرخلىرىنى قامدايدۇ.", + "financial_donations_cta": "تۆۋەندىكى ئۇسۇللار ئارقىلىق بۇ ئەپنىڭ ئاساسلىق ئاچقۇچىسىنى (eliandoran) قوللاشنى ئويلىشىپ كۆرۈڭ:", + "github_sponsors": "GitHub Sponsors", + "paypal": "PayPal", + "buy_me_a_coffee": "Buy Me A Coffee" + }, + "contribute": { + "title": "تۆھپە قوشۇشنىڭ باشقا ئۇسۇللىرى", + "way_translate": "Weblate ئارقىلىق بۇ ئەپنى ئۆز ئانا تىلىڭىزغا تەرجىمە قىلىڭ.", + "way_community": "GitHub مۇنازىرىسى ياكى Matrix سۇپىسىدا جامائەت بىلەن ئۆزئارا ئالاقە قىلىڭ.", + "way_reports": "GitHub issues ئارقىلىق خاتالىق مەلۇم قىلىڭ.", + "way_document": "تۆھپە قوشۇش قوللانمىسى، كۆپ كۆرۈلىدىغان سوئاللارغا جاۋاب ياكى دەرسلىكلەرنى تەمىنلەش، شۇنداقلا قوللانمىدىكى كەم قالغان مەزمۇنلارنى مەلۇم قىلىش ئارقىلىق قوللانمىنى مۇكەممەللەشتۈرۈڭ.", + "way_market": "كەڭ تەرغىب قىلىڭ: Trilium Notes نى دوستلىرىڭىزغا تەۋسىيە قىلىڭ ياكى بىلوگ ۋە ئىجتىمائىي تاراتقۇلاردا ھەمبەھىرلىنىڭ." + }, + "404": { + "title": "404: تېپىلمىدى", + "description": "سىز ئىزدىگەن بەت تېپىلمىدى. بۇ بەت ئۆچۈرۈلگەن بولۇشى ياكى تور ئادرېسىدا خاتالىق بولۇشى مۇمكىن." + }, + "download_helper_desktop_windows": { + "title_x64": "Windows 64-bit", + "title_arm64": "Windows on ARM", + "description_x64": "Windows 10 ۋە 11 ئىجرا قىلىنىدىغان Intel ياكى AMD ئۈسكۈنىلىرىگە ماس كېلىدۇ.", + "description_arm64": "ARM ئۈسكۈنىلىرىگە ماس كېلىدۇ (مەسىلەنQualcomm Snapdragonبىر تەرەپ قىلغۇچ سەپلەنگەن ئۈسكۈنىلەر).", + "quick_start": "Winget ئارقىلىق قاچىلاش:", + "download_exe": "قاچىلاش پروگراممىسىنى چۈشۈرۈش (.exe)", + "download_zip": "Portable (.zip)", + "download_scoop": "Scoop" + }, + "download_helper_desktop_linux": { + "title_x64": "Linux 64-bit", + "title_arm64": "Linux on ARM", + "description_x64": "كۆپىنچە Linux تارقاتما نۇسخىلىرىغا ماس كېلىدۇ، x86_64 ئارخىتېكتۇرىسى بىلەن ماسلىشىشچانلىقى بار.", + "description_arm64": "ARM ئارخىتېكتۇرىسىنى ئاساس قىلغان Linux تارقاتما نۇسخىلىرىغا ماس كېلىدۇ، aarch64 ئارخىتېكتۇرىسى بىلەن ماسلىشىشچانلىقى بار.", + "quick_start": "ئۆزىڭىز ئىشلىتىۋاتقان تارقاتما نۇسخاغا ئاساسەن مۇۋاپىق بولغان يۇمشاق دېتال فورماتىنى تاللاڭ:", + "download_deb": ".deb" + }, + "download_helper_desktop_macos": { + "description_x64": "macOS Monterey ياكى ئۇنىڭدىن كېيىنكى سىستېما ئىجرا قىلىنىدىغان Intel يادرولۇق Mac كومپيۇتېرلىرىغا ماس كېلىدۇ.", + "description_arm64": "M1 ۋە M2 ئۆزەكلىرى سەپلەنگەن Apple Silicon Mac كومپيۇتېرلىرىغا ماس كېلىدۇ.", + "quick_start": "Homebrew ئارقىلىق قاچىلاش:", + "download_dmg": "قاچىلاش پروگراممىسىنى چۈشۈرۈش (.dmg)" + }, + "download_helper_server_docker": { + "title": "Docker ئارقىلىق ئۆزىڭىز قۇرۇپ ئىشلىتىش (Self-hosted)", + "description": "Docker كونتېينېرى (Container) ئارقىلىق Windows، Linux ياكى macOS سىستېمىلىرىغا ئاسانلا ئورۇنلاشتۇرۇشقا بولىدۇ." + }, + "download_helper_server_linux": { + "title": "Linuxدا ئۆزىڭىز قۇرۇپ ئىشلىتىش (Self-hosted)", + "description": "Trilium Notes نى ئۆزىڭىزنىڭ مۇلازىمەتچىسىگە ياكى VPS غا ئورۇنلاشتۇرۇڭ، كۆپىنچە تارقاتما نۇسخىلار بىلەن ماسلىشىشچانلىقى بار." + }, + "download_helper_server_hosted": { + "description": "Trilium Notes نىڭ بېكەت تۇرالغۇسى PikaPods تەرىپىدىن تەمىنلىنىدۇ، بۇ ھەقلىق مۇلازىمەت قولايلىق زىيارەت ۋە باشقۇرۇش ئىقتىدارلىرىغا ئىگە. مەزكۇر مۇلازىمەت بىلەن Trilium گۇرۇپپىسى ئوتتۇرىسىدا بىۋاسىتە باغلىنىش يوق.", + "download_pikapod": "PikaPods تا تەڭشەش", + "download_triliumcc": "يەنە trilium.cc غا كىرسىڭىزمۇ بولىدۇ" + }, + "resources": { + "title": "مەنبەلەر" } } From 0ece1270c7a04e9ee6dca6a0e0dfa75c7442cd7f Mon Sep 17 00:00:00 2001 From: green Date: Wed, 15 Apr 2026 14:12:42 +0200 Subject: [PATCH 232/482] Translated using Weblate (Japanese) Currently translated at 99.9% (1919 of 1920 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/ --- .../src/translations/ja/translation.json | 50 +++++++++++++++++-- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/apps/client/src/translations/ja/translation.json b/apps/client/src/translations/ja/translation.json index c310f1e846..5884ece190 100644 --- a/apps/client/src/translations/ja/translation.json +++ b/apps/client/src/translations/ja/translation.json @@ -1202,7 +1202,9 @@ "and_more": "...その他 {{count}} 件。", "print_landscape": "PDF にエクスポートするときに、ページの向きを縦向きではなく横向きに変更します。", "print_page_size": "PDF にエクスポートするときに、ページのサイズを変更します。サポートされる値: A0, A1, A2, A3, A4, A5, A6, Legal, Letter, Tabloid, Ledger。", - "textarea": "複数行テキスト" + "textarea": "複数行テキスト", + "print_scale": "PDF にエクスポートする際に、レンダリングされるコンテンツの縮尺を変更します。値の範囲は 0.1(10%)から 2(200%)までで、デフォルト値は 1(100%)です。", + "print_margins": "PDF に書き出す際に、ページ余白を設定します。デフォルト, なし, 最小, または 上、右、下、左 のようなカスタム値をミリメートル単位で指定できます。" }, "link_context_menu": { "open_note_in_popup": "クイック編集", @@ -1354,7 +1356,9 @@ "theme_group_light": "ライトテーマ", "theme_group_dark": "ダークテーマ", "copy_title": "クリップボードにコピー", - "click_to_copy": "クリックしてコピー" + "click_to_copy": "クリックしてコピー", + "tab_width": "タブ幅", + "tab_width_unit": "スペース" }, "editor": { "title": "エディター" @@ -1607,7 +1611,9 @@ "check_integrity_description": "SQLite レベルでデータベースが破損していないことを確認します。" }, "code-editor-options": { - "title": "エディター" + "title": "エディター", + "tab_width": "タブ幅", + "tab_width_unit": "スペース" }, "search_string": { "title_column": "文字列検索:", @@ -2130,7 +2136,19 @@ "code_note_switcher": "言語モードを変更", "backlinks_other": "{{count}} バックリンク", "attachments_other": "{{count}} 件の添付ファイル", - "note_paths_other": "{{count}} 個のパス" + "note_paths_other": "{{count}} 個のパス", + "tab_width": "タブ幅: {{width}}", + "tab_width_title": "タブ幅を変更", + "tab_width_spaces": "{{count}} スペース", + "tab_width_spaces_short": "スペース: {{width}}", + "tab_width_tabs": "タブ ({{width}})", + "tab_width_use_default": "デフォルトを使用 ({{width}})", + "tab_width_use_default_style": "デフォルトを使用 ({{style}})", + "tab_width_display_header": "表示幅", + "tab_width_reindent_header": "コンテンツのインデントを再設定", + "tab_width_style_header": "インデントを使用", + "tab_width_style_spaces": "スペース", + "tab_width_style_tabs": "タブ" }, "breadcrumb": { "hoisted_badge": "ホイスト", @@ -2395,5 +2413,29 @@ }, "link": { "failed_to_open": "'{{- href}}' のリンクを開けなせんでした: {{- message}}" + }, + "print_preview": { + "title": "印刷プレビュー", + "close": "閉じる", + "save": "PDF として保存", + "orientation": "向き", + "portrait": "縦向き", + "landscape": "横向き", + "page_size": "ページサイズ", + "scale": "縮尺", + "margins": "余白", + "render_error": "現在の設定では PDF を生成できません。余白と縮尺を確認してください。", + "margins_default": "デフォルト", + "margins_none": "なし", + "margins_minimum": "最小", + "margins_custom": "カスタム", + "margin_top": "上", + "margin_right": "右", + "margin_bottom": "下", + "margin_left": "左", + "page_ranges": "ページ", + "page_ranges_hint": "全ページを印刷する場合は空欄のままにしてください。", + "page_ranges_invalid": "無効な形式です。例: 1-5, 8, 11-13 のように指定してください。", + "page_ranges_placeholder": "例: 1-5, 8, 11-13" } } From 60f3ddd35444827252494880a2039af123fd3dfa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 20:48:53 +0000 Subject: [PATCH 233/482] Update dependency @ai-sdk/google to v3.0.62 --- apps/server/package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/server/package.json b/apps/server/package.json index 766b6234d2..3410dd7ee5 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -31,7 +31,7 @@ }, "dependencies": { "@ai-sdk/anthropic": "3.0.69", - "@ai-sdk/google": "3.0.61", + "@ai-sdk/google": "3.0.62", "@ai-sdk/openai": "3.0.52", "@modelcontextprotocol/sdk": "^1.12.1", "ai": "6.0.158", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 37746a1459..a61dde5251 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -572,8 +572,8 @@ importers: specifier: 3.0.69 version: 3.0.69(zod@4.3.6) '@ai-sdk/google': - specifier: 3.0.61 - version: 3.0.61(zod@4.3.6) + specifier: 3.0.62 + version: 3.0.62(zod@4.3.6) '@ai-sdk/openai': specifier: 3.0.52 version: 3.0.52(zod@4.3.6) @@ -1485,8 +1485,8 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/google@3.0.61': - resolution: {integrity: sha512-jEKU1Mjcy5CoicejdJQIzM0ntYwyXR8vtYgAZYriKaOuLAiAhiiU538++fGU3CC9HJH/mL1OfsCwMM3gFiCNsw==} + '@ai-sdk/google@3.0.62': + resolution: {integrity: sha512-cC9HAjR5WZxjqGyEJrJqFTlVqyPE9UOFmmGdf5dINaimgfPmzqXYN1qTYEJ+1knbyTVsNMub0KAF5SOqqtO8IQ==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 @@ -14138,7 +14138,7 @@ snapshots: '@vercel/oidc': 3.1.0 zod: 4.3.6 - '@ai-sdk/google@3.0.61(zod@4.3.6)': + '@ai-sdk/google@3.0.62(zod@4.3.6)': dependencies: '@ai-sdk/provider': 3.0.8 '@ai-sdk/provider-utils': 4.0.23(zod@4.3.6) From 794ad9410bbdb1fab10b923d0f5eabe81d0a6433 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 20:49:25 +0000 Subject: [PATCH 234/482] Update dependency ejs to v5.0.2 --- apps/server/package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/server/package.json b/apps/server/package.json index 766b6234d2..4d352702f2 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -87,7 +87,7 @@ "csrf-csrf": "4.0.3", "debounce": "3.0.0", "debug": "4.4.3", - "ejs": "5.0.1", + "ejs": "5.0.2", "electron": "41.2.0", "electron-window-state": "5.0.3", "escape-html": "1.0.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 37746a1459..ed1131de31 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -735,8 +735,8 @@ importers: specifier: 4.4.3 version: 4.4.3 ejs: - specifier: 5.0.1 - version: 5.0.1 + specifier: 5.0.2 + version: 5.0.2 electron: specifier: 41.2.0 version: 41.2.0 @@ -8137,8 +8137,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - ejs@5.0.1: - resolution: {integrity: sha512-COqBPFMxuPTPspXl2DkVYaDS3HtrD1GpzOGkNTJ1IYkifq/r9h8SVEFrjA3D9/VJGOEoMQcrlhpntcSUrM8k6A==} + ejs@5.0.2: + resolution: {integrity: sha512-IpbUaI/CAW86l3f+T8zN0iggSc0LmMZLcIW5eRVStLVNCoTXkE0YlncbbH50fp8Cl6zHIky0sW2uUbhBqGw0Jw==} engines: {node: '>=0.12.18'} hasBin: true @@ -23017,7 +23017,7 @@ snapshots: ee-first@1.1.1: {} - ejs@5.0.1: {} + ejs@5.0.2: {} electron-debug@4.1.0: dependencies: From f285f7e14ff388f5fa482e88e311765351b7afbe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 20:49:57 +0000 Subject: [PATCH 235/482] Update dependency reveal.js to v6.0.1 --- apps/client/package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/client/package.json b/apps/client/package.json index 7cff4e1ed0..cc5c87a923 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -68,7 +68,7 @@ "preact": "10.29.1", "react-i18next": "17.0.2", "react-window": "2.2.7", - "reveal.js": "6.0.0", + "reveal.js": "6.0.1", "rrule": "2.8.1", "svg-pan-zoom": "3.6.2", "tabulator-tables": "6.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 37746a1459..6a2e909500 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -364,8 +364,8 @@ importers: specifier: 2.2.7 version: 2.2.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4) reveal.js: - specifier: 6.0.0 - version: 6.0.0 + specifier: 6.0.1 + version: 6.0.1 rrule: specifier: 2.8.1 version: 2.8.1 @@ -12062,8 +12062,8 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - reveal.js@6.0.0: - resolution: {integrity: sha512-RayDr1FL3Jglnf6p9xHGJ0U18va96PiuLs/JHnd1cdDOXvC+3lsXKe6ujl7PX0pvnhNW2Tpqnr6PEKpJVO2exw==} + reveal.js@6.0.1: + resolution: {integrity: sha512-9eacArNIgqO2HGWOK+93gJNn+gvdGDVbSq+i2u3Ja9kjiHps0XNLpgYTZTYjKRH91uXy3clGimeGiw4umHG/tg==} rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} @@ -27803,7 +27803,7 @@ snapshots: reusify@1.1.0: {} - reveal.js@6.0.0: {} + reveal.js@6.0.1: {} rfdc@1.4.1: {} From 0b5332fbb3dad1ad409be7d48f34c8b40ff89b8f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 20:50:32 +0000 Subject: [PATCH 236/482] Update dependency typedoc to v0.28.19 --- apps/build-docs/package.json | 2 +- pnpm-lock.yaml | 26 +++++++++++++++++--------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/apps/build-docs/package.json b/apps/build-docs/package.json index 3be2fb44ac..631578d9ec 100644 --- a/apps/build-docs/package.json +++ b/apps/build-docs/package.json @@ -20,7 +20,7 @@ "archiver": "7.0.1", "fs-extra": "11.3.4", "js-yaml": "4.1.1", - "typedoc": "0.28.18", + "typedoc": "0.28.19", "typedoc-plugin-missing-exports": "4.1.3" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 37746a1459..b6e33e3e8f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -199,11 +199,11 @@ importers: specifier: 4.1.1 version: 4.1.1 typedoc: - specifier: 0.28.18 - version: 0.28.18(typescript@6.0.2) + specifier: 0.28.19 + version: 0.28.19(typescript@6.0.2) typedoc-plugin-missing-exports: specifier: 4.1.3 - version: 4.1.3(typedoc@0.28.18(typescript@6.0.2)) + version: 4.1.3(typedoc@0.28.19(typescript@6.0.2)) apps/client: dependencies: @@ -10641,6 +10641,10 @@ packages: resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} engines: {node: 18 || 20 || >=22} + minimatch@10.2.5: + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + engines: {node: 18 || 20 || >=22} + minimatch@3.1.5: resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} @@ -13236,8 +13240,8 @@ packages: peerDependencies: typedoc: ^0.28.1 - typedoc@0.28.18: - resolution: {integrity: sha512-NTWTUOFRQ9+SGKKTuWKUioUkjxNwtS3JDRPVKZAXGHZy2wCA8bdv2iJiyeePn0xkmK+TCCqZFT0X7+2+FLjngA==} + typedoc@0.28.19: + resolution: {integrity: sha512-wKh+lhdmMFivMlc6vRRcMGXeGEHGU2g8a2CkPTJjJlwRf1iXbimWIPcFolCqe4E0d/FRtGszpIrsp3WLpDB8Pw==} engines: {node: '>= 18', pnpm: '>= 10'} hasBin: true peerDependencies: @@ -26216,6 +26220,10 @@ snapshots: dependencies: brace-expansion: 5.0.5 + minimatch@10.2.5: + dependencies: + brace-expansion: 5.0.5 + minimatch@3.1.5: dependencies: brace-expansion: 1.1.13 @@ -29197,16 +29205,16 @@ snapshots: typedarray@0.0.6: {} - typedoc-plugin-missing-exports@4.1.3(typedoc@0.28.18(typescript@6.0.2)): + typedoc-plugin-missing-exports@4.1.3(typedoc@0.28.19(typescript@6.0.2)): dependencies: - typedoc: 0.28.18(typescript@6.0.2) + typedoc: 0.28.19(typescript@6.0.2) - typedoc@0.28.18(typescript@6.0.2): + typedoc@0.28.19(typescript@6.0.2): dependencies: '@gerrit0/mini-shiki': 3.23.0 lunr: 2.3.9 markdown-it: 14.1.1 - minimatch: 10.2.4 + minimatch: 10.2.5 typescript: 6.0.2 yaml: 2.8.3 From ff3b6c40112300a2b5ad2bff8bdaa920531b3d4a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 20:51:08 +0000 Subject: [PATCH 237/482] Update univer monorepo to v0.20.1 --- apps/client/package.json | 16 +- pnpm-lock.yaml | 1769 +++++++++++++++++++------------------- 2 files changed, 894 insertions(+), 891 deletions(-) diff --git a/apps/client/package.json b/apps/client/package.json index 7cff4e1ed0..2704c3f25e 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -34,14 +34,14 @@ "@triliumnext/highlightjs": "workspace:*", "@triliumnext/share-theme": "workspace:*", "@triliumnext/split.js": "workspace:*", - "@univerjs/preset-sheets-conditional-formatting": "0.20.0", - "@univerjs/preset-sheets-core": "0.20.0", - "@univerjs/preset-sheets-data-validation": "0.20.0", - "@univerjs/preset-sheets-filter": "0.20.0", - "@univerjs/preset-sheets-find-replace": "0.20.0", - "@univerjs/preset-sheets-note": "0.20.0", - "@univerjs/preset-sheets-sort": "0.20.0", - "@univerjs/presets": "0.20.0", + "@univerjs/preset-sheets-conditional-formatting": "0.20.1", + "@univerjs/preset-sheets-core": "0.20.1", + "@univerjs/preset-sheets-data-validation": "0.20.1", + "@univerjs/preset-sheets-filter": "0.20.1", + "@univerjs/preset-sheets-find-replace": "0.20.1", + "@univerjs/preset-sheets-note": "0.20.1", + "@univerjs/preset-sheets-sort": "0.20.1", + "@univerjs/presets": "0.20.1", "@zumer/snapdom": "2.8.0", "autocomplete.js": "0.38.1", "bootstrap": "5.3.8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 37746a1459..5630120129 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -262,29 +262,29 @@ importers: specifier: workspace:* version: link:../../packages/splitjs '@univerjs/preset-sheets-conditional-formatting': - specifier: 0.20.0 - version: 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + specifier: 0.20.1 + version: 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) '@univerjs/preset-sheets-core': - specifier: 0.20.0 - version: 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + specifier: 0.20.1 + version: 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) '@univerjs/preset-sheets-data-validation': - specifier: 0.20.0 - version: 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + specifier: 0.20.1 + version: 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) '@univerjs/preset-sheets-filter': - specifier: 0.20.0 - version: 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + specifier: 0.20.1 + version: 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) '@univerjs/preset-sheets-find-replace': - specifier: 0.20.0 - version: 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + specifier: 0.20.1 + version: 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) '@univerjs/preset-sheets-note': - specifier: 0.20.0 - version: 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + specifier: 0.20.1 + version: 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) '@univerjs/preset-sheets-sort': - specifier: 0.20.0 - version: 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + specifier: 0.20.1 + version: 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) '@univerjs/presets': - specifier: 0.20.0 - version: 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + specifier: 0.20.1 + version: 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) '@zumer/snapdom': specifier: 2.8.0 version: 2.8.0 @@ -5800,199 +5800,199 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} - '@univerjs-pro/collaboration-client-ui@0.20.0': - resolution: {integrity: sha512-7FFM/9VdeFHioxSJ6r+t67kurzLA1w57O/J71ZC9goHxCf/rC61p/iwNKCSwlnrc73DCey39TFcZ2QdC/I9g2g==} + '@univerjs-pro/collaboration-client-ui@0.20.1': + resolution: {integrity: sha512-uPwtmx+/smG/Vcu7tfktNeSMdP6tY1l+o0lsaCJBe5pSaooDEQI6qe8qCX2Ndt7Ij11w/kleKHF3mcQHL2HNbA==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs-pro/collaboration-client@0.20.0': - resolution: {integrity: sha512-dcBuRj5IodiIgGm6fWKW49CSvAqNJf6SjupSJaRDDisRF546hsS4IlulFEhlRaARgIlstqoM9aRDCjN4CPlfDw==} + '@univerjs-pro/collaboration-client@0.20.1': + resolution: {integrity: sha512-nZTtXLtR8mh556HgkHINxVfxZVO72YsN8hIAqgoVJeJFsAavcEypQ+ohlXvuIL9hxGo/Q3YJBnHZmgJmoZGfuA==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs-pro/collaboration@0.20.0': - resolution: {integrity: sha512-iCsyTAArvtvh6e4a2xIt6AvA5uHFUkh/t6mCXHR2AuBo1ZZud5jZTPnV9HkdLpf7VIV3qe+6KI7/N8MTOdemjA==} + '@univerjs-pro/collaboration@0.20.1': + resolution: {integrity: sha512-e6DupTLljB2VrQU0qiZI6CeMF3q4/PnBx5pxebsr5EmnJb7z4mZEmFijqccrdX148b7FlfWTmoEF9jEbKvkV/w==} - '@univerjs-pro/docs-exchange-client@0.20.0': - resolution: {integrity: sha512-/Ioyox2kFk6S8kwvmgPx5vscuccoee/8mpK4As7DAMxibFGbGvfWUfIbgnFm9k7FFNrwX4c/K6o30EekxTy77A==} + '@univerjs-pro/docs-exchange-client@0.20.1': + resolution: {integrity: sha512-wAguVjCF5PjpH7AAzrtjRv6Trnxy16iO5cMrlvV5C9ao09LWiz+QGdsDkLGXNqnVX3vSvGzalPquOJD889c10g==} - '@univerjs-pro/docs-print@0.20.0': - resolution: {integrity: sha512-CdcBxekBgLMJyMVq2kz523lbfxDXca/4j8oycIx8zI+RBDCRW2M+RDy2OcHaJ8Djhy9pnpCDOdD2k/FRvaJHlA==} + '@univerjs-pro/docs-print@0.20.1': + resolution: {integrity: sha512-eDBwg/tksTgCsrnX4ylI9WPSXEoylFSSeC4URE8HE9eoypzZcgAVNCgYM++lBR5w6jJl8W78vH6/DnyroAlfRA==} - '@univerjs-pro/edit-history-loader@0.20.0': - resolution: {integrity: sha512-0OvhK/z+lpSB4pvPhmzVLHEIva3tJ2y8QwsxEfTJ//V/cTPQFyLc3Iv9oLPlK/EeHurJq0eFiRskvtCfgaF5Jg==} + '@univerjs-pro/edit-history-loader@0.20.1': + resolution: {integrity: sha512-aIdbPguBNlhcKDWYqESD+XH6qq7VI2iWUhnFEZFe/aVRulJ7cesu2jOt6VrFNxOrEJQ7hdfj9LqKMnOgycS0Kg==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs-pro/edit-history-viewer@0.20.0': - resolution: {integrity: sha512-tfZqyY3Sin0XwCHYmbza8w7bWhySUWc78RPMElzqgoQtJ5wHw8yQiKsK3kDj1piBTOkV1vzKpO116izXvqJaBQ==} + '@univerjs-pro/edit-history-viewer@0.20.1': + resolution: {integrity: sha512-nNS75RTZnqm4LREcj/pm9Bi3F+0wSltStfD+JOtwGxROQfAKDVt2d4xL7zMu0dEYKUee9U9LfD1tC5/cHL/I7w==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs-pro/engine-chart@0.20.0': - resolution: {integrity: sha512-PmBPBYe7MdTTi53oxiKxUur08wK1kKdMlpmAfbRKHM8iQ1jKiX+jppsiWW6DG4Zc/FUWhgTSo5Mvqp+EiX/wUA==} + '@univerjs-pro/engine-chart@0.20.1': + resolution: {integrity: sha512-YuX+iVKNcWWbAsV8bGsSzGEQpXvweSwRXLpXzQl7T51eoine/UoBfGuuwWVUDM2mKh+yh9vAJxjewXEzdx129Q==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs-pro/engine-formula@0.20.0': - resolution: {integrity: sha512-iHbQPkUsweym+APtkKR9Tvg6x9bkQMH1vWtEo2IBZRykG6Cg2ZH+m2mBjfGd+yar7hgsNybAvcGuST1NaIcKYA==} + '@univerjs-pro/engine-formula@0.20.1': + resolution: {integrity: sha512-2A90/aox3oBhX8uUwtPRULkKlE0LoimN8Gy59inY1gvuPddsys9OdBBCiuouxlOdGCCypZB/15G6L4NlQrfI/Q==} - '@univerjs-pro/engine-pivot@0.20.0': - resolution: {integrity: sha512-6eEceMhiMKkAwujDvcSjkgg/V513TpitItvvodfYk8RzCaS12XgCBtXcG4Hw4ckyzulFB4BgHZd5FjKH0sy6yg==} + '@univerjs-pro/engine-pivot@0.20.1': + resolution: {integrity: sha512-sULQneX4oAZwr/VlCoeFfvMjPww6mDMXuL5YsqZqQUh/0/hWjXj/XdWOxLh/RBuHeTd52s5NBiVXGoueqCynFQ==} - '@univerjs-pro/engine-shape@0.20.0': - resolution: {integrity: sha512-4fivQmgiAsc5UoAK9ZQSlRW+KtRztr1+NDDuz3WrXxmsIIcLEBRAv6aQbXOGA7TNOJitipnyIT3m3P/o2lL+6Q==} + '@univerjs-pro/engine-shape@0.20.1': + resolution: {integrity: sha512-XHQZzSBZf+gko9q8gfKg8VXZbndX8/02MqxAbqyGlJzDafBlSQ+o/R/D5C73bpH7EEx7+VVX0EZt+MossG/n1Q==} - '@univerjs-pro/exchange-client@0.20.0': - resolution: {integrity: sha512-sLSd/DX7InjDy5psH9zNzCxI5eTuaH6JkEECaf7L10Prmur7ug74FDZdV5ulfB7+xOcqVqT4Yd4UKVEIZYcfMQ==} + '@univerjs-pro/exchange-client@0.20.1': + resolution: {integrity: sha512-N2iPiGk+DLQyORd/uEPJ9lYrBu7unAVIOCqgQmiDKInyj1MXEdaagB2qsoC5b6ZvO7sjevRosdtHC1lYWbDivA==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs-pro/license@0.20.0': - resolution: {integrity: sha512-JoppYlkQUuxhvuWWuGrGruOZTOI+ur08GNIFika5OhcSZBz8PTuvMNhSSxIPsSzv+ndK4y0uMUt9YYmRi6np2A==} + '@univerjs-pro/license@0.20.1': + resolution: {integrity: sha512-4sRYBA9PH1WnlDaLq1nh7W8q+5gHxkIkjjoMgeXrUK3JSJtLb+BeCR+AmMV5u6eKWwLVtB5ZpSjBFDvzILX0mg==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs-pro/print@0.20.0': - resolution: {integrity: sha512-4Yd+auUSgLQ3QpVaHF1gAzrwjAp/lQD4u3vEP6lkPLBB4/rAhQchTq7LMg4fjALUFewYDJ8eCpg+dtpl7RE9IQ==} + '@univerjs-pro/print@0.20.1': + resolution: {integrity: sha512-OgS9YkqGe45z7/yFbq+bcp9br4gQxFb/XARrCGU1cdDB8MpSHm+5R0n7XXhz3YkFThPhZMh62FsLkkXagjlaRw==} - '@univerjs-pro/sheets-chart-ui@0.20.0': - resolution: {integrity: sha512-MlzmLm49u4wLpghsLFmDw7mHygeLZZh95AsMmdK5mU7SXv5Tles6b1pw2X3uJilX9vobLcLXuYVPcDzSZiqCuQ==} + '@univerjs-pro/sheets-chart-ui@0.20.1': + resolution: {integrity: sha512-awHhh5YDFW8+OcD+a0YBsgGRrkmp2srh3Ez9LoNBTHiOiqQoBmL0uL+cpQxww3XsJa2urt4g2RJECw1/05t60A==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs-pro/sheets-chart@0.20.0': - resolution: {integrity: sha512-AXTuqzfycKh0MJ05glVlD1uYmO3zPptkzu1VuPHlhFH12xdM+R1TK6f963K7apsZLuBWe3ZMA0pyQiiql5MQvQ==} + '@univerjs-pro/sheets-chart@0.20.1': + resolution: {integrity: sha512-ljEjVlCjMNlJ2gis1MQhedBk0EKaQWiW4LT47Uh7zj8Iir1qxlDVgnGeJwUipxMIt/4387k+c6CwFcrhhNyo+A==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs-pro/sheets-exchange-client@0.20.0': - resolution: {integrity: sha512-OqsqDnAKgOTLfqZpPfWAcf5+qTSfIN1He5Jk5ItqRFYZlok8aWwbH8fhsDPbfrg1Wq9e7Y/rljkvHFblXbFP1w==} + '@univerjs-pro/sheets-exchange-client@0.20.1': + resolution: {integrity: sha512-aXxFIMUQi+lO8+HaZvHvmS03YOV9Dg/+gVCTW3v1EeWTMtqr2OjepMmdR/ywOQn9fC0XgAOrIPzL/0F5qls+zw==} - '@univerjs-pro/sheets-pivot-ui@0.20.0': - resolution: {integrity: sha512-MfaJFY2hl9j3aiZaQmoTS7pnA/HtjqOcUnck26fQyMnA1GBkGFtNI4GXIXFCZRNukn16pIeSHPg+x5YBLNCw5A==} + '@univerjs-pro/sheets-pivot-ui@0.20.1': + resolution: {integrity: sha512-mBcYiyu0EAZohvkqCOBIVRggGJGTztG6c0A7L8DiY7OinOVx5eHn8vEO1+1SDH3wCYY+uzGRzoFamtXeqw2zww==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs-pro/sheets-pivot@0.20.0': - resolution: {integrity: sha512-P71zkINalbuzVoYsfOgBBoG7sJeeAZO96sAAfBPzh3wuPGIc3U2sSS72ZuNc1yJOEab9WWZk6vJ6e2r8YthX3w==} + '@univerjs-pro/sheets-pivot@0.20.1': + resolution: {integrity: sha512-GpVV4ORdKvMJR7yJH99LoWAk9ryEDiXEFX45xx0wsG2SKu1yRpJeDYyk63pcOHK19W53EebgRlHxfDoEs4QLqA==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs-pro/sheets-print@0.20.0': - resolution: {integrity: sha512-I014PqYG6a15hpLql7tPJOPP6A+Kf6BHgS4K4a5t5mk49f88mukpOxrA+vCFAl9UMa5xx9xF839mCJpc6c4eDw==} + '@univerjs-pro/sheets-print@0.20.1': + resolution: {integrity: sha512-x0u9KoI9ZzOGz9MQYOGkOiaUpOreJG0f4WJ4YqibINBPEEWMN9nXVpytyjK0PfUVv2Y7/8rKk9nvo0f12RqwZQ==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs-pro/sheets-shape-ui@0.20.0': - resolution: {integrity: sha512-rwOhfxBPdI3cuArXebDJI63/6o3iZNNatiNJBweZtLBx+x/dljc9CsLq1fitfxtnre0Tu4hS3ZvgRM9nOzHkdA==} + '@univerjs-pro/sheets-shape-ui@0.20.1': + resolution: {integrity: sha512-dyaJ9M/BGAamTnEhRsGfBPoNoIBeIwb+XOKhCjkZcN87Cb4zLWXV6rngiXClIQZTnxphD0B3g74sCFYSVG8j6g==} engines: {node: '>=16.0.0', npm: '>=8.0.0'} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs-pro/sheets-shape@0.20.0': - resolution: {integrity: sha512-dSrxLta1r18IkfD+iAOHgdzY34F3xXPc+k3p/HsT//GMMh9o+KNYX/L0WURwgCgg7u9oJnKHec4HQx6Od8sJ3A==} + '@univerjs-pro/sheets-shape@0.20.1': + resolution: {integrity: sha512-HjXIm3uW8KX8zwpVABEQCEipDJgSsUEME9Eud7hiGhG22gBVMTtzmNUuSQWY/WDddrR8eSOus2rDVUqqJLi/tw==} engines: {node: '>=16.0.0', npm: '>=8.0.0'} - '@univerjs-pro/sheets-sparkline-ui@0.20.0': - resolution: {integrity: sha512-lFEcIRkWaMdTAojNJpepavP1eutH2cKCHmMyvBsyRKxLJPiShb8qGIsQGlAfVLtJJM7ms/ZrvQZpDRrf/C1v4Q==} + '@univerjs-pro/sheets-sparkline-ui@0.20.1': + resolution: {integrity: sha512-KbzL8pIf3kILolzvwaHfGTlQWClMKVRxb6Aart0kI3Qp73Q/Wx+KJd1R8m86bSt0T671MLhoClnwIkC1Qq6KHw==} engines: {node: '>=16.0.0', npm: '>=8.0.0'} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs-pro/sheets-sparkline@0.20.0': - resolution: {integrity: sha512-A86oJHWgLWRZz86PbIH73wkt6vblWY6bFkutcrAkNpMOahveVIsfbdBZHPPoUrzF1dZKnVwvfMg66qIWVqdJcQ==} + '@univerjs-pro/sheets-sparkline@0.20.1': + resolution: {integrity: sha512-bIvEK/cAf6cyVfPeYE1esa/GgNI0KnWFVfP3qoz2fPVVH8wU+prUounP2I4kHOoStAdiZixjfaGheYpyD5oLKg==} engines: {node: '>=16.0.0', npm: '>=8.0.0'} peerDependencies: rxjs: '>=7.0.0' - '@univerjs-pro/thread-comment-datasource@0.20.0': - resolution: {integrity: sha512-dWAKNE9wtKiaWArclHS4Cxd1XEEEqR09eo4Vs4yYTcQuv4xY+2Ha9sRbyc20eUWswtUO4hX+NE3b/9oalYT4ww==} + '@univerjs-pro/thread-comment-datasource@0.20.1': + resolution: {integrity: sha512-pcmSZ+DKrtGDJ/BfQS325jfhpJrCnisJ6XYPttVA1G4y5tBfOmRgG+wBeAmGqXg0IhAelyYEIvqXTxB4YMVaoA==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/core@0.20.0': - resolution: {integrity: sha512-sXz0qf0aWI9rEBZ24/+vUw/uMMwMQhKbBQz9YDafZF8MXl2ey1/n3GqXNBHrCKSpo25vB8rGT3sPk3PvZ7jWeQ==} + '@univerjs/core@0.20.1': + resolution: {integrity: sha512-grP1xH2KO/rmNyzSdmuryEnHI/4jH9Qo2yvvJhTup5950QNSX6UKXA/E3NnVj3TpflKY3kDnwugLJ+1Suw4IxA==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/data-validation@0.20.0': - resolution: {integrity: sha512-OZjXC+nsrnmlPXSrCsYQfgJjuAmZdzPfunx1zExSKrAcsvCdJHjvEAZZhURcGbJcPG4CRJiGafcm/htjxxwFEA==} + '@univerjs/data-validation@0.20.1': + resolution: {integrity: sha512-dlrb2kdFjL1sQzRhpluCSfGZsXEcq9UBr/ROhOA6EAQ2pMIP5Ndsj3ooChmGlqwZPwwQyCZ7YWKc9R1zEYEL/w==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/design@0.20.0': - resolution: {integrity: sha512-wXRi5Lnafnpw1SDij3zGjqmV+gwL3qj7+LOWXB9QQ6WTl0Tk6IILz/KMyUuEyPCOTryLQruJ3FlE7++y0ocALw==} + '@univerjs/design@0.20.1': + resolution: {integrity: sha512-VN/AQgqKrXzINc7TvTbbU1uTydaohkmhcdoPxdF2Iefh/ERkKiYRwW9hGkzRIzWi8eT/l/LX/nHf9hRo3NJ8xg==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - '@univerjs/docs-drawing-ui@0.20.0': - resolution: {integrity: sha512-kjNZWW1LklzEKM1BaCWTjH8wv8cqdxSiOBcBsr+SlsOmkqEUCh7EiLSoShIzKBNrGbz/fjEBCXh76upy0+jjpw==} + '@univerjs/docs-drawing-ui@0.20.1': + resolution: {integrity: sha512-MVeuO1zs5/sqn3exsrOZFZvLtmxuR2rP4bdDZ4WTnymLgMafXXqbeIpAB2KFNO3ybaydWrYyR3kLjVfMixlH/Q==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/docs-drawing@0.20.0': - resolution: {integrity: sha512-U1AeJFuPktZTWdT41gKMdmLfNxEBe4SvTnCsubl2nuwHxYud0RnXAywqD596MP04uDRjYknOh1vZ4i1Ba0pJcQ==} + '@univerjs/docs-drawing@0.20.1': + resolution: {integrity: sha512-xd9aPtA/VsVvItjuxsj2nC1lG0KqpLG7AQxbv/9b6YjGAVNf2Y/UR+4NjW6D0YQ8y9P63ls3rdhNGg0rS7epRg==} - '@univerjs/docs-hyper-link-ui@0.20.0': - resolution: {integrity: sha512-0jLJrssCuYZenCOFDJ1eMOgssU7HGDpjR3PByIfUca2nFSuAnLn5E/iSvYT+EZzUyB99gwiW/Tc5TS2Yj0IY+A==} + '@univerjs/docs-hyper-link-ui@0.20.1': + resolution: {integrity: sha512-2z2GX2/CT8LZ/hpN0XHKu9A/5VE8NGHkI8MmlVVNShxmGhxp3763maILC9Wx4Ji/QRz/5BgdL7kH+2ut+zzCpw==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/docs-hyper-link@0.20.0': - resolution: {integrity: sha512-YrKFbL80evv9oeIjIFPkbYJKj3i5/V3/WB/rAQd2jQqqJ8sMt+8bPEv9y0s2n3ULoLEQoKwdQZ3Pqml/CVgTPA==} + '@univerjs/docs-hyper-link@0.20.1': + resolution: {integrity: sha512-WZF2esfWx3S3W7tj7MS3OvTpei/mpTkxN81ttaoUlHE/m8VfvJXFBIwDaqteRBp2FyOv8cxRWSE2ZCB1KackGw==} - '@univerjs/docs-thread-comment-ui@0.20.0': - resolution: {integrity: sha512-xW1vqIbmfLa74anstw55wdcZ7jzuKt9wR0a/1TZiECXRt9oY6QzVFNLJ7xA1cINGFbjRIiGfeG2vtvDAafmkIA==} + '@univerjs/docs-thread-comment-ui@0.20.1': + resolution: {integrity: sha512-V10nqNEObPjMESjqvTfG7G0LjZBJCExLxN04vWHocupQS8ao48I81D4Bl0j3/BhwCQ/+BRoPaAEU2DftX/iGNA==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/docs-ui@0.20.0': - resolution: {integrity: sha512-CAkmK9BUt6ZNXpqSRvqbXX2rJ3jQLhQM38WvrMhebpmaHxi0eFMRGOJ3AHTwUne03weLLSK59JkyAl5CXa60yA==} + '@univerjs/docs-ui@0.20.1': + resolution: {integrity: sha512-UoF5mab+qXIiJfXasJKrfSa1Vcg4hdSBOj+xRLk5H3vV65PLoHa5apiA5MHanD46RPXyz58R9iSRplCbB1FCmg==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/docs@0.20.0': - resolution: {integrity: sha512-mLGOQEj7MUzWc4gDoH/l2phFyYjOHPCf9Jj8KSlQAOw97wvjSnXHXaRdpr7e6IM22481XVIR8kLW0j3NRmkUjQ==} + '@univerjs/docs@0.20.1': + resolution: {integrity: sha512-fHH4U1zGTz7LNjFz2YfyN6ppe19xTsJymsqbe3dvwL5rHp77+s/S2Tm7ObgI5TABN127N7sXZ0HlvulcZUNhhQ==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/drawing-ui@0.20.0': - resolution: {integrity: sha512-KrIGOeYYUbO5wXe7NLYg0RNW4Bi+Zwj2+xxiLjNd+KPvfmxOMnVZ0qy8T7La6ivPvXf255je4aLKNBir+RStXw==} + '@univerjs/drawing-ui@0.20.1': + resolution: {integrity: sha512-BL2DkE1OJ/b0k/vl01pLBNl5Z3LNBhoZ+2iBdPvPA05fwIJe0/S6IPuNOQ5JAGneh+y0hwoMr8KKX+yQ6IQxeQ==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/drawing@0.20.0': - resolution: {integrity: sha512-Uto+4m8WLCp3OaTrXObNG6SoTymgS1nz5LCwUk23FBrcd2JCfRiTBZ7wXEYbf90P8KSx32XBKUDtmyRQNR5bNw==} + '@univerjs/drawing@0.20.1': + resolution: {integrity: sha512-7DMc6U4tHGWK37EJS1vIaaFdqBf22WrOlAS4A9tbqyQLlqE+WhJf1nxtiO7EMAPZEfIHbIDsABUAHEDBHBQGVg==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/engine-formula@0.20.0': - resolution: {integrity: sha512-2ZCz9lNIFie1ZXMTI6UWqwHQicjv8t/ixruSdXbecqW8+zDIktoI999Sm7EFEgK5KX3bUyhWI/NcEK4OWHERLw==} + '@univerjs/engine-formula@0.20.1': + resolution: {integrity: sha512-Fpc6F7PVLhWxlkNY2VMYssWfuc4TT0IcGemzRh12/HYeIEPsyBvDAnBzJ1OCEeFfP2ZvpoEC0QkhQJlv7UY2rA==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/engine-render@0.20.0': - resolution: {integrity: sha512-gIuYe41N/YIXwr6zvYn4+WIryeE37Xu0gUiopP5dbB2ls3fZX3mdBdw9VvP1DsZ/GE8Cz19OmtOePKnZbMIqjQ==} + '@univerjs/engine-render@0.20.1': + resolution: {integrity: sha512-kfPTAfJ7tMrVhLBIkvSZASAfB1m/s+TR0Gv8mv9S5lvUiNd+Thtlku/ZuDC0KFygHFLNXUqmXAOT+MMVJh7iqw==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/find-replace@0.20.0': - resolution: {integrity: sha512-PeG4FwTKzVq4ybZUqXHr3APuYHxRcBC1KTdlacAwbpzIW7nrTfkXP7+8ZK64VyL5pdfVi3wMOv7Usrra8XQk3Q==} + '@univerjs/find-replace@0.20.1': + resolution: {integrity: sha512-ACcZy+w8T/FW6DeGWxeejFY21m52InsO20qELZQqlSZsLaFCqKefYiZ//faq8kXKZiXNJQHVsXEPhHZu6OKsRQ==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' @@ -6003,156 +6003,156 @@ packages: react: '*' react-dom: '*' - '@univerjs/network@0.20.0': - resolution: {integrity: sha512-OKdkMmRTorIunrlijkWWkRfSHP1exy6JR5KLJDmZBG1x1xdTaSRtFb2Jo7bUQpZUP41yMnnEZDDHiV1ub+fnJg==} + '@univerjs/network@0.20.1': + resolution: {integrity: sha512-x2ySyo2qhoZ3FTk2L2Emko/kLoikldvTFdTD19iZrIqjReCz+B7lWeo1M7Biag3+AL5SpT1vaHnSjfIzYjeSkw==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/preset-docs-advanced@0.20.0': - resolution: {integrity: sha512-wrfOU8/iEi2IlJ3uEUybwVtDQVE+6VqBw2lg4BlaYkUs7GyAe12ou0eBjrnElN86C3GdVQPFUhST7IEDkcZtJw==} + '@univerjs/preset-docs-advanced@0.20.1': + resolution: {integrity: sha512-N2F7XVuD8HBOXWpkiowBq+OxE4O74AGx2QXEaj4FLLpOycnzUIiO4vgQLkikgQErSmY6TtqeYO2+u/sfo/dmHA==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/preset-docs-collaboration@0.20.0': - resolution: {integrity: sha512-GqqYfGmTpH1Z5q2won80aAVBG7VXMtLUa0GCSj5jmSN/Z4uOXPy432waymEz2+/4FxPWWWup/hmpBqLDKnsg0Q==} + '@univerjs/preset-docs-collaboration@0.20.1': + resolution: {integrity: sha512-tnHSWrRsIq99yYNhbHN975V1qXpkoUzyx+pZA+wtDNIxe/eWw9PYgapun7PmuVmcp/LB9D7oliPSQKubAGgbQg==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/preset-docs-core@0.20.0': - resolution: {integrity: sha512-IVEwvZE9LmoRn+nLhJPolAId/PqgyxBCPOoD5u5dySQMY0aHUSGo+s2gEolK2neqSoF/PLQZZ495rqD/JrPCiA==} + '@univerjs/preset-docs-core@0.20.1': + resolution: {integrity: sha512-qwNEjqIpm6ypuao495YDmxzRIL5hqbZ/eqUCnzGkvy7LBBf8Yseh6wySroSdQ3CiBVAh9MtI/ndslGIlKMvJpg==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/preset-docs-drawing@0.20.0': - resolution: {integrity: sha512-b+WTsR2Eh0L8t7cpFngUwfnapMg4NvEZ/K8m8Bmyq4WB1kkExvTUuHqcpHP3IlVLRSFYyuMAQme7JbO3rC2MnA==} + '@univerjs/preset-docs-drawing@0.20.1': + resolution: {integrity: sha512-5xTglZKKVxgzjAvzFntyU7ewBk88Wiib2CUiHTYG7/zfbkrv2PguzAB1iqKlZHFp3jnaJEDwKoOVoatTLwHaxQ==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/preset-docs-hyper-link@0.20.0': - resolution: {integrity: sha512-8gA4BCqImWQ/FLzdnpc5OeHh6DKuP1FPgqyYufQ0XfT7QXDn2YGy5tgMjo6wpNxOl9ztZ4PRXyGG05tVq84ywA==} + '@univerjs/preset-docs-hyper-link@0.20.1': + resolution: {integrity: sha512-5ZK4ZwD6lEcqWYgs9bgvS73GmKO9bib7pE/X0dwqSwjXI82gZvCa0+46KpaK66dMlb/VC3BzXvOJjSpEwUnUQw==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/preset-docs-node-core@0.20.0': - resolution: {integrity: sha512-unsiv8aMsr+MF0uPwH0vwuRWeNlhnm58TFTmrRrNcjyV/jloxdQHFXu72kWJsmOOxDmkTgZW3Hb218dfGAtUWA==} + '@univerjs/preset-docs-node-core@0.20.1': + resolution: {integrity: sha512-orRgG/8iz0PkikemuPU6e42qx+pmdfhW0xxJdTLVi4yq1wCt/r8+j4Y3dCS4Be6ktbmCPPrGVVL+0PCSXpQaDg==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/preset-docs-thread-comment@0.20.0': - resolution: {integrity: sha512-zNrH1NNMBmM8Hh1Se6kERQF+m8QcmSuwafxSLt35LZE8SWD4QiDkGLTqmXD86Q8C0q8R+Js2ubQAy38Y/S1XRw==} + '@univerjs/preset-docs-thread-comment@0.20.1': + resolution: {integrity: sha512-VdWfRyutjpHqnH9uvSkYREeoPQh2B01ptzfDWpyqfsqlDrR9/botv+edlelE7/gmdj2P6sbvz1Bo75ABurmLQw==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/preset-sheets-advanced@0.20.0': - resolution: {integrity: sha512-5+spZkgX6poD425SzLvIq9zIjCCAVkNqdJNPTY0VBf2JAT673VeFfclUiPlPUSi96OC1CgSJkOrab1c0zz0R6g==} + '@univerjs/preset-sheets-advanced@0.20.1': + resolution: {integrity: sha512-dzFNvkzreLqi1tb5V43GRRsho0qcXT4GLY01O7/L+c7WwwSdbi0gkVWuu/ovXYNj4c5Cg698bE/dYT0818NHrw==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/preset-sheets-collaboration@0.20.0': - resolution: {integrity: sha512-kGtr9BFnuqUhuPb8hbb+9rtGF7c5Yxnaz+qcVLpcG1SA/Hqj83Zyp8x+JRElS4FpcJnHSLx9OD74QhQgo93vMA==} + '@univerjs/preset-sheets-collaboration@0.20.1': + resolution: {integrity: sha512-+YKa/R8UDjvIzSjYcpVMC6TSxPLctpqoAoCz44vqOF9Ny9qex9Qv4OMbHvHIFoJ3fq6Bztaw9cKZ4tjoJXqf6g==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/preset-sheets-conditional-formatting@0.20.0': - resolution: {integrity: sha512-vpT2KGFKRZEPHJ7mtSFNm/AaW3lyr7jvmOG9XnH8/rzhTmzE+XrN/uy8N+5SPRgl6MTg/czUlE4YaeZs4UwE/w==} + '@univerjs/preset-sheets-conditional-formatting@0.20.1': + resolution: {integrity: sha512-ziF6RcYBpbPFCPIgnY72PVZzYCfL+NCTQVJY4uN8gEKmGwIVR64q23mL2+WD1a+Xpc8KA3FAOl65YZybDAsdiw==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/preset-sheets-core@0.20.0': - resolution: {integrity: sha512-UkVhdOyswfDfkB5WyvGocVgUfAvWrvcC8JLgw1VBV04ck43g5RzXQGy2h/Fyxztl+6FaznimPH3QuPuVYjEN3Q==} + '@univerjs/preset-sheets-core@0.20.1': + resolution: {integrity: sha512-dlY1wvy2IUTo/ij8JkHYl0lBTRGktrtaOVKK3RunO65Fwq5S2EQ6Ub1xKMotrh5Mbk/GkU+qNIkQzdt4vThVjA==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/preset-sheets-data-validation@0.20.0': - resolution: {integrity: sha512-qGQUnhveNgzWvk0PFS+bbv8iz0EfQGMiNUXBfCwUcH1jnsYZlPPHy+BBMxexEh5mnz2heHTDR24tbBk3oeG2yA==} + '@univerjs/preset-sheets-data-validation@0.20.1': + resolution: {integrity: sha512-9AgmEp+25u/H3X7SMJH/nk1NX1jwcXA6DY65UP6giWIT+F9UrrxLN3lrSon+aWnBgrK0BlRYYt7uL5JaBboYpQ==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/preset-sheets-drawing@0.20.0': - resolution: {integrity: sha512-4duVTQkYbvh+En+89cE3Ip00OuXhemIsglEM7TBPywUg1v3F4zNBAgzS64SWf1CLZMo1UYjouemCPOuNWalnJw==} + '@univerjs/preset-sheets-drawing@0.20.1': + resolution: {integrity: sha512-MCMPI4QAnAldwqu4td8r60yBJljYBwAzk4qOuFxQ953veizQu8LINg2Af48J4G6Xqrv5u7FWsIznbsfgRKzx9w==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/preset-sheets-filter@0.20.0': - resolution: {integrity: sha512-WqqxuRhiIFE2pbsf43SvIddUzt9riRFS74/Lf4UOqXrm/SYa6BtwM+cFfLnxr5fZxBRl6iOFUNBByHDclcIbxQ==} + '@univerjs/preset-sheets-filter@0.20.1': + resolution: {integrity: sha512-PJT9T/NmjngvME9p1Ivfrx8Tyc6y7IslGLXewAJNk5AcWKD2VYXvCX8IlDHLcZX4iGD4YhVFtwhn+F7lrXuAOw==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/preset-sheets-find-replace@0.20.0': - resolution: {integrity: sha512-pRNe7RxiijgAgyqEs2eis7UpMRm7vEWIJeA2F5ZeVvNh7Po+RWgpZR4ZBX939nampc/AtK+zD0Pt4/L1Op4X7w==} + '@univerjs/preset-sheets-find-replace@0.20.1': + resolution: {integrity: sha512-JFLA2yIlc8S1e/VEsuqHGS1EIjiLtXstngEqKOdZX5WzZuP+8v9CwHmV7Bpu9UkGGfz7aMYHFxb2PPWcQI+9lQ==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/preset-sheets-hyper-link@0.20.0': - resolution: {integrity: sha512-z2r/ffTjetkAH6H6slWoq5YJ6iivT4fEJ8w7kdoXLWUVCBaCOocfVj/oKoWsQ6A63yAKzoQcKWOBstKAY/knEQ==} + '@univerjs/preset-sheets-hyper-link@0.20.1': + resolution: {integrity: sha512-W2s7kB7CLxFRWBHmA30QlHo8eUz2GRsHL5eW77D+dpNGgyLmzcQHVGSSwDFtx9z4nl1mjA+VU8HVsvCjElpnpQ==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/preset-sheets-node-core@0.20.0': - resolution: {integrity: sha512-sJVOc7jTUAPSQgpLCBjek4DlNwblSWGrtGUS/aeprKtNIYXnykXvSpHAXm6Y56VEM1RunTev/kqXQtzVnw8trg==} + '@univerjs/preset-sheets-node-core@0.20.1': + resolution: {integrity: sha512-8cAAT3a8tEuPaMUSqvz0f5cacZQ3d4PKG3PGVBnFVo3W/dACfeLj63MR9qUQ69fYckRVdP8mZPe8+czLx8dUaA==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/preset-sheets-note@0.20.0': - resolution: {integrity: sha512-zFNLPSoHdMQvn2Z+s5c9YTMtMagxtbas7yF/fRuA0AQZdkIzuM+OdPwV1TztWcGKhAmFfhaabDW9eTofwCBENw==} + '@univerjs/preset-sheets-note@0.20.1': + resolution: {integrity: sha512-tmM2J5MN1fdr8nIxY0VWBfJ32osfUxMhTVJCtrs2OdwJhUsecK0Ne2tVZPNhjPbTscO3IXCRAZvTsfBDUQqmuw==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/preset-sheets-sort@0.20.0': - resolution: {integrity: sha512-SmtU01v6XLYukhJdiAwJ4ubDy7fcCC7dWGcLoxtpZwqo7KegsQnICW+2ZqpvyWqgZwSFyG7s+st6Tp7NI0+3BQ==} + '@univerjs/preset-sheets-sort@0.20.1': + resolution: {integrity: sha512-TpPaI64fQyN6a2XQk1Ytgfi6N2Y1hy0H4KYfmdcUTjhfqWwCsu1f+TGvbxCIOaxfkHRKKvWAlQ/sX0+UMGZihg==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/preset-sheets-table@0.20.0': - resolution: {integrity: sha512-seFq1ptOzPuu05y1JXBysGjNHzpfuAUA2v3zquEVlC1QAc7gE6xRyq7tDxlkF9UKd1RSl0ZBJHKHEeIkVuBGYw==} + '@univerjs/preset-sheets-table@0.20.1': + resolution: {integrity: sha512-uvgHLQpvl5n3jhe1jlS8L+ml0RSqBS6Le0V5heFnibxV3s0RL8M+NpeogXtGZAcR1s78RLxwvhL59FVnW45eHA==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/preset-sheets-thread-comment@0.20.0': - resolution: {integrity: sha512-dDr18hv+e00lkiSMKbeisKa4qCTkFI1b6uvGKAfpjem3Td75AqCo0aldliu9bdQGNMDFhTyz3n776rF/9+zIIA==} + '@univerjs/preset-sheets-thread-comment@0.20.1': + resolution: {integrity: sha512-FXOm89Lx9nYi8ntFUONy1UysDzcfBMth+wGT5iHrQrF8wIMHMAxRuM5fm3Wi6EbaYb4IZZ7g7iyP8+M4f0reTw==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/presets@0.20.0': - resolution: {integrity: sha512-nwry3E0W/rz4z+Q4QXHm+f0om+wo5xK+gd6cw/hSMF+cFzQfPwW1FLx20wxHvb1MlgIYF73cMgan93VhpJ2/dQ==} + '@univerjs/presets@0.20.1': + resolution: {integrity: sha512-t9nsFZxzjr/aQT/7RGPum0SRvI8D8647tL55+Is7D1D9H2J2A0syUt5W55tBZpodl8S3bCMwIGHCR+JYpckqNQ==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc @@ -6161,171 +6161,174 @@ packages: '@univerjs/protocol@0.1.48': resolution: {integrity: sha512-nFHNtGAWOV0u1+IqoznH9K7hV/M9OZ61Vqwy8JMWKlgLLsx12m3vJqodkrVlLkI2YU5WuwjaUT1+J8/nM+kcUg==} - '@univerjs/rpc-node@0.20.0': - resolution: {integrity: sha512-ZZJkkpLg+lZbloxY00oOCwHTdgnXMJU56OMMDcbYXjhMtPTgUvlOhU7IdaYoqj9aFAe8VDoCQERo4ypwuUlImg==} + '@univerjs/protocol@0.1.49': + resolution: {integrity: sha512-xVKSmSCQTElzozs8+zCWDdx3OJU7u/s/O25r7h9r9/Xot5tr0yTOwdjeEpjwjUCn1L1e67iBPKLkqegq9h4U/Q==} + + '@univerjs/rpc-node@0.20.1': + resolution: {integrity: sha512-kR7IDVmeNHw7fk4IHTnXaeSUQJNEKzJ8HeyZu5xv1AcKmq85eCU+AA3ZgF9BPGMhnat9FBTqRfHg61GSTvHKwg==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/rpc@0.20.0': - resolution: {integrity: sha512-9sLzahk/zSlS5ajJjOMD5T/f6IeUUOiR4IZiHfLWFYRBr0EUHr+SxnnveiPwc5kWCER39Z7DGyqYCC7Z0c0NBA==} + '@univerjs/rpc@0.20.1': + resolution: {integrity: sha512-4l0uyHWKD0dDl1YT+7YaBUxV9DdKRBO+WSpKtPxW2dLIuBgEwN0JAbqnVC7DpXUalrzWtqMUba7MM5p3Z347rw==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/sheets-conditional-formatting-ui@0.20.0': - resolution: {integrity: sha512-fUeL8u9SspV/K+ZXxLojS5jvDbpYa53uvyytoX9sZeHm+UUTQ3k5omW4JGmzW1lTmu+VWVZPFIsPgDN+CYOOvg==} + '@univerjs/sheets-conditional-formatting-ui@0.20.1': + resolution: {integrity: sha512-K6Z9e143hjBb0UD2s0v6xnvxYN6mUjt0secNWHbYQDvsPUBISkv+E/wKb5EkwxgFtwTmufzWnMu+CtQhe2On1w==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/sheets-conditional-formatting@0.20.0': - resolution: {integrity: sha512-BqgAi/H8iKME6G6geRItaUUEoGliafN7tJAyOAx7pjjJlfDsZ0gI9crTnttUDvqOFcaJcWZZz8fWL3HCIlQigQ==} + '@univerjs/sheets-conditional-formatting@0.20.1': + resolution: {integrity: sha512-Ifo0NqVV8R5uQva7ribBIHzGl8ZPzgHKG1ujHy97+u7tGVX8PgOAi//hGkgbzRyjId2Yyeweb+OZc2FRJML/2Q==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/sheets-data-validation-ui@0.20.0': - resolution: {integrity: sha512-b42nbURw/CrRSQWmxL0/FkJ1eQl/FAb4IM5bwRVcBV3al1ucD/qKjKa3S/zbdeSNv/uk9ymu1syipUGJYCbikA==} + '@univerjs/sheets-data-validation-ui@0.20.1': + resolution: {integrity: sha512-vvLQ3e/5LjIo9LK9nil0xVHR4yAZcurq4UtUrfk01QumxVcdX2NDiYGidMVSYYotUOn56iWnUtV6oALWeIXSOA==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/sheets-data-validation@0.20.0': - resolution: {integrity: sha512-w3rRKLhXr3Ce9UAy/WenCmVeN3Jg6OgayNYORq0SCCppoqJbLMzjWHz0mU0T2ZPrgioalfxdbKYPGlCIxbDluA==} + '@univerjs/sheets-data-validation@0.20.1': + resolution: {integrity: sha512-uryXRc755GB+dIMPA3erBuzH8ZFgLn6hcUjmUJVd/5qJf+Gz7PBbsgq19xqZizuLWAgLnValemtx5+oo9VUszg==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/sheets-drawing-ui@0.20.0': - resolution: {integrity: sha512-c3vnt5cNm8ZL7UjZOyYawF82oCm9pQG1ld8g9j+NgP7hbsiJlsJRyNk0rHKfxBbsvADC96RXy7KJDL0yxJTx1Q==} + '@univerjs/sheets-drawing-ui@0.20.1': + resolution: {integrity: sha512-dq/1c0kgiK2n5FVYXm1YeWaxgqIZTi+HWANR2KPnWcBq5NkEPk4lqnPjEHllXjJJVzLm2TCH4FapOWk/vT9jTQ==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/sheets-drawing@0.20.0': - resolution: {integrity: sha512-/8/P+hayAL4Yp6CsPwKv3OiyD/tBbWHIE122qbU4QoOZgyscD9DVzV+K0M7940T7EcJ0xZbxZHlGzHhl54MmOA==} + '@univerjs/sheets-drawing@0.20.1': + resolution: {integrity: sha512-wHV28DPmkDy5r3uRVk+5I0pNciaeUwHQ0OOfHtRRHVZNCyEe1DRMd0UWIbW74dwNOz5Y5v542nSYTGmbBk12tg==} - '@univerjs/sheets-filter-ui@0.20.0': - resolution: {integrity: sha512-hgdhdBSe2W5H08tef/2Tgr0m+VrtNtHbiCWNacJf6z6p9iZ1t1rWMI3XheijqH/MX6W6/FidLJxK3i9iC51Cvw==} + '@univerjs/sheets-filter-ui@0.20.1': + resolution: {integrity: sha512-7dnrH363+Wjk6YHl7GLiQuPTJZsXtKSYGT8FGnrA0TUmgr787rtsSlzGNLEWlkHut+Xw7+0/mT8hdDpkIbSE7g==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/sheets-filter@0.20.0': - resolution: {integrity: sha512-WJKOjHz/3Ol/j5mkM/h475wWzWqfY5mVo8q0y0OzO7aOCu4mjHF4xOPr+X6Q4m7CTnK7j++UMWEF6XIBPSPEGg==} + '@univerjs/sheets-filter@0.20.1': + resolution: {integrity: sha512-RqSt1TJLYUZTSka6/ypdY/lDVNsrh7fmSNaM1GGR+98D7WSkY3nzeEVcKVovU4Errrr2FmWQADlZj8wKM0ok+w==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/sheets-find-replace@0.20.0': - resolution: {integrity: sha512-foz/7cRPvTmu5EwALfIecDAyYVMxmEdBe+iHruRc0WCcnRuSdi1l44g0/GPdzJbZalWejGw0ocHnKgYVPptgHg==} + '@univerjs/sheets-find-replace@0.20.1': + resolution: {integrity: sha512-w0r4JRDr9yXUa6OOm8+CceRNfvOAttPoFCR05FxkkDRwcqrPK3azGZbS4F/Q0LXv7A4E8tFg8OPHtSnHBTpwtA==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/sheets-formula-ui@0.20.0': - resolution: {integrity: sha512-2085X4qBcMWm3DQxJDzVUHWBJotPg1aacGPg97MBIRjfk62Afc+Szj60r4n5xOMt3EwSMnipyuidzkgLqWwXag==} + '@univerjs/sheets-formula-ui@0.20.1': + resolution: {integrity: sha512-VhSthFtDXhK/B7cqpu2hxUkAc927U4GOY/vPJQlZoEDq4xM4yq0U719BEr7xI+FKfgYLA1j4USwX2Z2OffO75g==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/sheets-formula@0.20.0': - resolution: {integrity: sha512-ERF8O9itqpEcVuz5hH0HHe/UQP0o12zJptk5TgWN7QaZottcZ/mZ4iJjo1FPI1Rv/MsfZtWEFpooUjaPRqXMQw==} + '@univerjs/sheets-formula@0.20.1': + resolution: {integrity: sha512-AESehaGW0PFaS5x8maEc0WzjmIcM0ZGvO4UPw6841ROSf7yVHpVSxgAfiLrO59yyYc6fQ1P9rF95mrkqpl23yg==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/sheets-graphics@0.20.0': - resolution: {integrity: sha512-oDR/4pTQ/eTW/uKSmkppZOeXgBVN44D1pX6c7F7YSXAlTV3JU3HZ3FeGEB/fpxmjUV512q+HiCoG7VQnyYZcEA==} + '@univerjs/sheets-graphics@0.20.1': + resolution: {integrity: sha512-lOkOddCcIddxlc18wjoJQfEVr8IrqMXcZe0jdOM2BIenfa2jo0JzbEGlIBmEHE6yB6YGlE178BqlA+MNKKoRZQ==} - '@univerjs/sheets-hyper-link-ui@0.20.0': - resolution: {integrity: sha512-9RqnKqbQnI8F1hrkdD2IIw4zm2IpzNqROSFTbZub6puhNWBgffF5MlK2mk1tG9wiEBScBxfwVEa2X8xdYriUqA==} + '@univerjs/sheets-hyper-link-ui@0.20.1': + resolution: {integrity: sha512-1fJxbBhi/E8krAAtdNaE2C+wgVjy4iQNkGHdXxc0UIBw278V32sQ1b9Zp1ezZ8osz3hVNrkvXz0TPBJM8moqVA==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/sheets-hyper-link@0.20.0': - resolution: {integrity: sha512-VidctE2XcmgEYxzjn0piVtlhnbJzdZSZa3Y1Jb1XnusDh2Kv6RukYma3vyact1gBlWg9QX08kaZzQhJqJ5LlVg==} + '@univerjs/sheets-hyper-link@0.20.1': + resolution: {integrity: sha512-qlDaU6ggk1rWkxl+LKHNQnqtMHXpFetoT2xvzgLveCSja6wWDP8HEHWoujtd19S2P3ia4NJutJ+r3QEZZtU4DQ==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/sheets-note-ui@0.20.0': - resolution: {integrity: sha512-H9ez9hpRL0tOycZDPnZF7195TmSMFi3YNrZymc/VtqLPsYOMl4tfHub4VVDQ97EWbKpgh5nLgVDD17Y29kHsbA==} + '@univerjs/sheets-note-ui@0.20.1': + resolution: {integrity: sha512-znI7bZ39M7F2oWHOeLKhbf+u3MIOVLUP/MsADH+EllVbVAx4nas+S9RJJogD9LWaTvetcs+jd101iFZBgFPVFQ==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/sheets-note@0.20.0': - resolution: {integrity: sha512-PsjUtaw/69wlKNcSUdDmZhQp1NIXMwQbwyP6fl1MyvZRlj6t9YS0wfyIt1Duy3L4e+AvPwL5E3hNdyTIyl+u6g==} + '@univerjs/sheets-note@0.20.1': + resolution: {integrity: sha512-kPUnkcWlqVthz/2r8A+avEd3XersGZ8GVXgzj+eYr8iPoJXoZBJVABD4iezAOHgt3aM/q8uwWWU86CnoaqaLcw==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/sheets-numfmt-ui@0.20.0': - resolution: {integrity: sha512-0ClpQx9jM2k3Yk+hDu6RXVpDQ+cXT64jis0dfCazblBnwNPVzKHk+wMYFQGT1sdJTVeD5/VzsPVgQVxhpsfloQ==} + '@univerjs/sheets-numfmt-ui@0.20.1': + resolution: {integrity: sha512-VnCMPVI8qgG/sMCMmayG4e7MCf8+v0O5W05U8tuxP1kdJxuBc+RLgllRNLHJ6Ca+Rxm0ONSi6Dqd7A3otxeIFA==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/sheets-numfmt@0.20.0': - resolution: {integrity: sha512-3USGuBFf/IS4Ui7IpFmStcj89Jnv7N37d2dhzzYQWADS0xHn1FzHbIZUizQ/kLMMacE3758ZlhEwYnkcKWHJ7A==} + '@univerjs/sheets-numfmt@0.20.1': + resolution: {integrity: sha512-cugnl9dHrrOhTg0EeKIubQ1wBkbN4qYu5pqM2C1F0/KmyZgnHj10coGxMc6nwvoTrFJxbU+BugR60xA2dDIkoQ==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/sheets-sort-ui@0.20.0': - resolution: {integrity: sha512-tyB0yTpMrj6ZTV6TXTRtt0hAWcJ1if8sIMJBfGI2Jhx+2VzXjYn5d+SzvVYgiLNOXkBFtex/J+jLA876SGlEmQ==} + '@univerjs/sheets-sort-ui@0.20.1': + resolution: {integrity: sha512-wFPP8gHqbDgtjnCwybr4QMWD3xhkxdgtJq0lCY3IXzrSLutGEoiUyNWIdEFUKx9C9uV39Md3q+MxV13mqewA9g==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/sheets-sort@0.20.0': - resolution: {integrity: sha512-Z6eeGRhQZyNfnQ2sfdV6qTHUdlcadQNAg9An4qB2nFn5QS5uvm2OcLd+sRteVqA2TXzP6KlZxQmFV+waiENaWQ==} + '@univerjs/sheets-sort@0.20.1': + resolution: {integrity: sha512-+hqCd9GOcZTSpVpPm+gsVOpE0grV49hgg16mtnlr24Gf1dFcReWEZSVYGtIY2Ha8dfsDfoR8oiiYU0c2LEyQjQ==} - '@univerjs/sheets-table-ui@0.20.0': - resolution: {integrity: sha512-nycmmfgfNdGxsYTqZmAxA93QsHcCImRm8dVFVWy+WLWle/1i3Ol9EfiS1Us9Tau8QDjvtm3iuzi8IPm/nfVluA==} + '@univerjs/sheets-table-ui@0.20.1': + resolution: {integrity: sha512-JcWxA40Q/Fg1YAnMCdc3W9WaIdHu2FElTZ61m6W4EFzrgzefIpOstlqoPdyGg3+76eqyTnxcY5BFYFYeZwxeUA==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/sheets-table@0.20.0': - resolution: {integrity: sha512-mZGVpQYRTApPC1qr2rRhrZJMG9fJ8U9M30y6r2ZEBRIwpZJLIo3Wpt2dfhDP7RsPEV42BgInMDiasxOpMbaaJA==} + '@univerjs/sheets-table@0.20.1': + resolution: {integrity: sha512-pC61Dn6ZChYvC3VNo6TLJ/GmuCtfJ8P/PbWkbygI7KlqxiNmMaGGq7auBTAPbUeDswV7mimeh4/0c1llQntaog==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/sheets-thread-comment-ui@0.20.0': - resolution: {integrity: sha512-aqB/UPJFxyJLd7FUAJbAFIP23FBBXwuMiHTjIC5UX9IS0J54NhJRgxoiAAxMXDf7nspUKo1/hI2oLyfvpD8zLQ==} + '@univerjs/sheets-thread-comment-ui@0.20.1': + resolution: {integrity: sha512-x+7+LJAftvwbokFdofGU3UwIsMZE+W3koDhthe+tr9MXC23HLOe18nN2XpJtihlxCAOfqUMYvCUziG+Mr4u7Cw==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/sheets-thread-comment@0.20.0': - resolution: {integrity: sha512-SczsVh6O+ueNKScRRzFpslMJiTTowJWdaKgK51pYspNx47GvPwhLRVBW267jds0VTzVSlG24oC+JxKFFHgwgxw==} + '@univerjs/sheets-thread-comment@0.20.1': + resolution: {integrity: sha512-o24gis9YKsGyX3XkuJ6lZAaH35m3Yti3egMAaXB5FxwrP+G0Y7M14GYEKXvWSCrj0DuDGt/fKfQxAAOh2B4hMg==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/sheets-ui@0.20.0': - resolution: {integrity: sha512-HdLBYjJQXq5QhAlpW1srUe1K9TuHFh4t+LqknFb1Ep2OQ6naHbb38bIXOPDktOQrmtwuWGyHNGJxbwC7nfGDoA==} + '@univerjs/sheets-ui@0.20.1': + resolution: {integrity: sha512-jZlmCVpPJoXL1v6z0MsGDT0XWgKgcEZvifFr0UaYJsFoTMzu1LkqZw5YCudrQKY+lURprLzkI2lT1T0npSXwkg==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/sheets@0.20.0': - resolution: {integrity: sha512-1Z02wg0zhigqwvJ0FWDnH55jFpOo04JrTUZQckYymgLyHazLHkJZAy/+ixyVcAj83xNKPYMaj1Q+Y3iHG+V35Q==} + '@univerjs/sheets@0.20.1': + resolution: {integrity: sha512-wxEXUJ0hJkkIifzbyxNBUgHiY07v71EIb501ltcnT8d2JUoP6JiS9tLyOvHsLK6OvvBKXNvohN0WbIUHLlXiFg==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/telemetry@0.20.0': - resolution: {integrity: sha512-zDwdeBl2vDnQwmbPSrMfNbef8fgzHVbnhSEItl5thvQQ7KIZr0sR7XeRXlI9VJGOGHg1WruJQ5zDdWeNQhP+Ig==} + '@univerjs/telemetry@0.20.1': + resolution: {integrity: sha512-84BYQ80jiKU2sYEdfNMXk+3lANTWjGu4nDYNMeilTOlHLjpL925BnAxM0owAnql7jgzohRG62d6gtfukH/Qp/w==} - '@univerjs/themes@0.20.0': - resolution: {integrity: sha512-dJ9m3mY1uhyhvozK6m0qsnRF406cIAMBOAh4qBo7N1h4G9Ff9TnUTN/ebF1AQmwOoAcJkxmDeiD0Ordt1KLA8g==} + '@univerjs/themes@0.20.1': + resolution: {integrity: sha512-/CK4jt59WeY+WkpXJxY9eVknGM/yFZOgMvprRyEAS0Vp+VYfV5w9dqLm/Z8zZBdWtgToteU8XfBQNNKYuaefpQ==} - '@univerjs/thread-comment-ui@0.20.0': - resolution: {integrity: sha512-wBGDtRXcHCW+7hN/bSnxtLggWVkTjKt245G0FUCcWzMQV2+H7Lnlt8zpsGE4kfILIbZHjzefuPpX4qlfZcwBSQ==} + '@univerjs/thread-comment-ui@0.20.1': + resolution: {integrity: sha512-Ci8IUblnBRPYzFvngTIpn7sXyeu+tTgoZDp9t+v3UwZTVf+RO0hq63cTKGc1jfLOC9C+3icQGoaEPfgRYw3cuQ==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc rxjs: '>=7.0.0' - '@univerjs/thread-comment@0.20.0': - resolution: {integrity: sha512-F4iARrow5esrb3uog1IPSKwb1WaZCCBTunNpgGKxhic4LClyZW3tx9oO0QdUaaQWBCNiY++J2jBs/ktTD+rdmg==} + '@univerjs/thread-comment@0.20.1': + resolution: {integrity: sha512-jiDS+pQ5d1312tz2AO2ry0bLd0qkjjAaqjsSH9a87H4vSYwAVgbrK19m4UrTadYouL6LspxqwylXa7xsf9YXNg==} peerDependencies: rxjs: '>=7.0.0' - '@univerjs/ui@0.20.0': - resolution: {integrity: sha512-XKxcH3hsYAOhL9wswyMglrHDRzCweUFetzwdlulaaztgwp5mKC7qNp1qgy6HUBb9OaB1yZYa8raBg7dN49DVvQ==} + '@univerjs/ui@0.20.1': + resolution: {integrity: sha512-EsDteeB9G4URTVRt3u5rSC8M5xEnOllHDEq77LCqLY34fZxQX5qpnb3z8IjcRCnQWBFM+aFfzMwqmQ1Y2cqZ0w==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc @@ -19465,24 +19468,24 @@ snapshots: '@ungap/structured-clone@1.3.0': {} - '@univerjs-pro/collaboration-client-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/collaboration-client-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/collaboration': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/collaboration-client': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/docs': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/collaboration': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/collaboration-client': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/docs': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/network': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/protocol': 0.1.48 - '@univerjs/rpc': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/network': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/protocol': 0.1.49 + '@univerjs/rpc': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) crypto-js: 4.2.0 react: 19.2.4 rxjs: 7.8.2 @@ -19491,46 +19494,46 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs-pro/collaboration-client@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/collaboration-client@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/collaboration': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/license': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/network': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/protocol': 0.1.48 - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/telemetry': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/collaboration': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/license': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/network': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/protocol': 0.1.49 + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/telemetry': 0.20.1(react@19.2.4)(rxjs@7.8.2) crypto-js: 4.2.0 rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs-pro/collaboration@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/collaboration@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/license': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/data-validation': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/protocol': 0.1.48 - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-conditional-formatting': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-filter': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-hyper-link': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/thread-comment': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/license': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/data-validation': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/protocol': 0.1.49 + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-conditional-formatting': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-filter': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-hyper-link': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/thread-comment': 0.20.1(react@19.2.4)(rxjs@7.8.2) uuid: 13.0.0 transitivePeerDependencies: - react - rxjs - '@univerjs-pro/docs-exchange-client@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/docs-exchange-client@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/exchange-client': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/exchange-client': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) transitivePeerDependencies: - '@types/react' - '@types/react-dom' @@ -19538,17 +19541,17 @@ snapshots: - react-dom - rxjs - '@univerjs-pro/docs-print@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/docs-print@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/license': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/print': 0.20.0 - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/license': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/print': 0.20.1 + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/network': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/network': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) transitivePeerDependencies: - '@types/react' - '@types/react-dom' @@ -19556,50 +19559,50 @@ snapshots: - react-dom - rxjs - '@univerjs-pro/edit-history-loader@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/edit-history-loader@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/collaboration': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/collaboration-client': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/collaboration-client-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/edit-history-viewer': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/license': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-chart': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-chart-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-pivot': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-shape': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-shape-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-sparkline': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-sparkline-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/data-validation': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/docs': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/drawing-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/collaboration': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/collaboration-client': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/collaboration-client-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/edit-history-viewer': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/license': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-chart': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-chart-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-pivot': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-shape': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-shape-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-sparkline': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-sparkline-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/data-validation': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/docs': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/drawing-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/network': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/protocol': 0.1.48 - '@univerjs/rpc': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-conditional-formatting': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-conditional-formatting-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-data-validation': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-data-validation-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-drawing-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-filter': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-filter-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-formula-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-hyper-link': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-hyper-link-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-numfmt': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-table': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/network': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/protocol': 0.1.49 + '@univerjs/rpc': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-conditional-formatting': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-conditional-formatting-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-data-validation': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-data-validation-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-drawing-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-filter': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-filter-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-formula-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-hyper-link': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-hyper-link-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-numfmt': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-table': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - '@types/react' @@ -19607,31 +19610,31 @@ snapshots: - react - react-dom - '@univerjs-pro/edit-history-viewer@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/edit-history-viewer@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/collaboration': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/collaboration-client': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/collaboration-client-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-chart': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-pivot': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-shape': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-sparkline': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/data-validation': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/collaboration': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/collaboration-client': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/collaboration-client-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-chart': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-pivot': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-shape': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-sparkline': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/data-validation': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/network': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/protocol': 0.1.48 - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-conditional-formatting': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-data-validation': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-filter': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-table': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/network': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/protocol': 0.1.49 + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-conditional-formatting': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-data-validation': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-filter': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-table': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -19639,37 +19642,37 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs-pro/engine-chart@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/engine-chart@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs-pro/engine-formula@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/engine-formula@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/license': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/license': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) transitivePeerDependencies: - react - rxjs - '@univerjs-pro/engine-pivot@0.20.0': {} + '@univerjs-pro/engine-pivot@0.20.1': {} - '@univerjs-pro/engine-shape@0.20.0': {} + '@univerjs-pro/engine-shape@0.20.1': {} - '@univerjs-pro/exchange-client@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/exchange-client@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/collaboration': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/license': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs-pro/collaboration': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/license': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/network': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/protocol': 0.1.48 - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/network': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/protocol': 0.1.49 + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) pako: 2.1.0 react: 19.2.4 rxjs: 7.8.2 @@ -19678,34 +19681,34 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs-pro/license@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/license@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: '@noble/ed25519': 2.3.0 '@noble/hashes': 1.8.0 - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs-pro/print@0.20.0': {} + '@univerjs-pro/print@0.20.1': {} - '@univerjs-pro/sheets-chart-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/sheets-chart-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/engine-chart': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-chart': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/engine-chart': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-chart': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-drawing-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-formula-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-drawing-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-formula-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -19713,25 +19716,25 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs-pro/sheets-chart@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/sheets-chart@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/engine-chart': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/license': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/engine-chart': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/license': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs-pro/sheets-exchange-client@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/sheets-exchange-client@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/exchange-client': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/exchange-client': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) transitivePeerDependencies: - '@types/react' - '@types/react-dom' @@ -19739,20 +19742,20 @@ snapshots: - react-dom - rxjs - '@univerjs-pro/sheets-pivot-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/sheets-pivot-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/engine-pivot': 0.20.0 - '@univerjs-pro/sheets-pivot': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/docs-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/engine-pivot': 0.20.1 + '@univerjs-pro/sheets-pivot': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/docs-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-formula-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-formula-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -19760,35 +19763,35 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs-pro/sheets-pivot@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/sheets-pivot@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/engine-pivot': 0.20.0 - '@univerjs-pro/license': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/rpc': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-filter': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/engine-pivot': 0.20.1 + '@univerjs-pro/license': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/rpc': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-filter': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs-pro/sheets-print@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/sheets-print@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/collaboration-client': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/license': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/print': 0.20.0 - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/docs': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/collaboration-client': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/license': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/print': 0.20.1 + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/docs': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/network': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/network': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -19796,23 +19799,23 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs-pro/sheets-shape-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/sheets-shape-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/engine-shape': 0.20.0 - '@univerjs-pro/sheets-shape': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/docs': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/drawing-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/engine-shape': 0.20.1 + '@univerjs-pro/sheets-shape': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/docs': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/drawing-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-drawing-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-drawing-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -19820,31 +19823,31 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs-pro/sheets-shape@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/sheets-shape@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/engine-shape': 0.20.0 - '@univerjs-pro/license': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/engine-shape': 0.20.1 + '@univerjs-pro/license': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) transitivePeerDependencies: - react - rxjs - '@univerjs-pro/sheets-sparkline-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/sheets-sparkline-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/sheets-sparkline': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-sparkline': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-formula-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-graphics': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-formula-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-graphics': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -19852,24 +19855,24 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs-pro/sheets-sparkline@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/sheets-sparkline@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/license': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/license': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs-pro/thread-comment-datasource@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs-pro/thread-comment-datasource@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/collaboration-client': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/license': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/network': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/protocol': 0.1.48 - '@univerjs/thread-comment': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/thread-comment-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/collaboration-client': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/license': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/network': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/protocol': 0.1.49 + '@univerjs/thread-comment': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/thread-comment-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - '@types/react' @@ -19877,13 +19880,12 @@ snapshots: - react - react-dom - '@univerjs/core@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/core@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: '@univerjs/protocol': 0.1.48 - '@univerjs/themes': 0.20.0 + '@univerjs/themes': 0.20.1 '@wendellhu/redi': 1.1.1(react@19.2.4) async-lock: 1.4.1 - dayjs: 1.11.20 fast-diff: 1.3.0 kdbush: 4.0.2 lodash-es: 4.18.1 @@ -19895,14 +19897,14 @@ snapshots: transitivePeerDependencies: - react - '@univerjs/data-validation@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/data-validation@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/design@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@univerjs/design@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@radix-ui/react-dropdown-menu': 2.1.16(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -19913,7 +19915,6 @@ snapshots: '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) class-variance-authority: 0.7.1 clsx: 2.1.1 - dayjs: 1.11.20 react: 19.2.4 react-dom: 19.2.4(react@19.2.4) react-transition-group: 4.4.5(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -19923,17 +19924,17 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/docs-drawing-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/docs-drawing-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/docs': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/drawing-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/docs': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/drawing-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -19941,24 +19942,24 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs/docs-drawing@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/docs-drawing@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) transitivePeerDependencies: - react - rxjs - '@univerjs/docs-hyper-link-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/docs-hyper-link-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/docs': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-hyper-link': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/docs': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-hyper-link': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -19966,23 +19967,23 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs/docs-hyper-link@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/docs-hyper-link@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) transitivePeerDependencies: - react - rxjs - '@univerjs/docs-thread-comment-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/docs-thread-comment-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/thread-comment': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/thread-comment-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/thread-comment': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/thread-comment-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -19990,15 +19991,15 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs/docs-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/docs-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/docs': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/docs': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -20006,22 +20007,22 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs/docs@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/docs@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/drawing-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/drawing-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -20029,29 +20030,29 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs/drawing@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/drawing@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) ot-json1: 1.0.2 rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/engine-formula@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/engine-formula@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: '@flatten-js/interval-tree': 1.1.3 - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/rpc': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/rpc': 0.20.1(react@19.2.4)(rxjs@7.8.2) decimal.js: 10.6.0 rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/engine-render@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/engine-render@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: '@floating-ui/dom': 1.7.6 '@floating-ui/utils': 0.2.11 - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) cjk-regex: 3.4.0 franc-min: 6.2.0 opentype.js: 1.3.4 @@ -20059,13 +20060,13 @@ snapshots: transitivePeerDependencies: - react - '@univerjs/find-replace@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/find-replace@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -20078,19 +20079,19 @@ snapshots: react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@univerjs/network@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/network@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/preset-docs-advanced@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-docs-advanced@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/docs-exchange-client': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/docs-print': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/exchange-client': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/license': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/docs-exchange-client': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/docs-print': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/exchange-client': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/license': 0.20.1(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20098,11 +20099,11 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/preset-docs-collaboration@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-docs-collaboration@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/collaboration': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/collaboration-client': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/collaboration-client-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/collaboration': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/collaboration-client': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/collaboration-client-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20110,15 +20111,15 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/preset-docs-core@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-docs-core@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/docs': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/network': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/docs': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/network': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20126,12 +20127,12 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/preset-docs-drawing@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-docs-drawing@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/docs-drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-drawing-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/drawing-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-drawing-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/drawing-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20139,10 +20140,10 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/preset-docs-hyper-link@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-docs-hyper-link@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/docs-hyper-link': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-hyper-link-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-hyper-link': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-hyper-link-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20150,25 +20151,25 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/preset-docs-node-core@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-docs-node-core@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/docs': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-hyper-link': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/rpc-node': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/thread-comment': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-hyper-link': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/rpc-node': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/thread-comment': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/preset-docs-thread-comment@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-docs-thread-comment@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/docs-thread-comment-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/thread-comment': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/thread-comment-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-thread-comment-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/thread-comment': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/thread-comment-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20176,24 +20177,24 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/preset-sheets-advanced@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-sheets-advanced@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/engine-chart': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/engine-shape': 0.20.0 - '@univerjs-pro/exchange-client': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/license': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-chart': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-chart-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-exchange-client': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-pivot': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-pivot-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-print': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-shape': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-shape-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-sparkline': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/sheets-sparkline-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-graphics': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/engine-chart': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/engine-shape': 0.20.1 + '@univerjs-pro/exchange-client': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/license': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-chart': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-chart-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-exchange-client': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-pivot': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-pivot-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-print': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-shape': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-shape-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-sparkline': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/sheets-sparkline-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-graphics': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20201,15 +20202,15 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/preset-sheets-collaboration@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-sheets-collaboration@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs-pro/collaboration': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/collaboration-client': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/collaboration-client-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/edit-history-loader': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/edit-history-viewer': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs-pro/thread-comment-datasource': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-sheets-advanced': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/collaboration': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/collaboration-client': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/collaboration-client-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/edit-history-loader': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/edit-history-viewer': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs-pro/thread-comment-datasource': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-sheets-advanced': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20217,10 +20218,10 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/preset-sheets-conditional-formatting@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-sheets-conditional-formatting@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/sheets-conditional-formatting': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-conditional-formatting-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-conditional-formatting': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-conditional-formatting-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20228,22 +20229,22 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/preset-sheets-core@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-sheets-core@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/docs': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/network': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/rpc': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-formula-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-numfmt': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-numfmt-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/docs': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/network': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/rpc': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-formula-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-numfmt': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-numfmt-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20251,11 +20252,11 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/preset-sheets-data-validation@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-sheets-data-validation@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/data-validation': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-data-validation': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-data-validation-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/data-validation': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-data-validation': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-data-validation-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20263,13 +20264,13 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/preset-sheets-drawing@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-sheets-drawing@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/docs-drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/drawing-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-drawing-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/drawing-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-drawing-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20277,10 +20278,10 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/preset-sheets-filter@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-sheets-filter@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/sheets-filter': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-filter-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-filter': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-filter-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20288,10 +20289,10 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/preset-sheets-find-replace@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-sheets-find-replace@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/find-replace': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-find-replace': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/find-replace': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-find-replace': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20299,10 +20300,10 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/preset-sheets-hyper-link@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-sheets-hyper-link@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/sheets-hyper-link': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-hyper-link-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-hyper-link': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-hyper-link-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20310,30 +20311,30 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/preset-sheets-node-core@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-sheets-node-core@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/docs': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/rpc-node': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-data-validation': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-filter': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-hyper-link': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-numfmt': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-sort': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-thread-comment': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/thread-comment': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/rpc-node': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-data-validation': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-filter': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-hyper-link': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-numfmt': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-sort': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-thread-comment': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/thread-comment': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/preset-sheets-note@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-sheets-note@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/sheets-note': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-note-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-note': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-note-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20341,10 +20342,10 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/preset-sheets-sort@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-sheets-sort@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/sheets-sort': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-sort-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-sort': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-sort-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20352,10 +20353,10 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/preset-sheets-table@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-sheets-table@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/sheets-table': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-table-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-table': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-table-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20363,12 +20364,12 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/preset-sheets-thread-comment@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/preset-sheets-thread-comment@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/sheets-thread-comment': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-thread-comment-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/thread-comment': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/thread-comment-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-thread-comment': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-thread-comment-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/thread-comment': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/thread-comment-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20376,30 +20377,30 @@ snapshots: - '@types/react' - '@types/react-dom' - '@univerjs/presets@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/presets@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-docs-advanced': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-docs-collaboration': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-docs-core': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-docs-drawing': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-docs-hyper-link': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-docs-node-core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-docs-thread-comment': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-sheets-advanced': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-sheets-collaboration': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-sheets-conditional-formatting': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-sheets-core': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-sheets-data-validation': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-sheets-drawing': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-sheets-filter': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-sheets-find-replace': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-sheets-hyper-link': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-sheets-node-core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-sheets-note': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-sheets-sort': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-sheets-table': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/preset-sheets-thread-comment': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-docs-advanced': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-docs-collaboration': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-docs-core': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-docs-drawing': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-docs-hyper-link': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-docs-node-core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-docs-thread-comment': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-sheets-advanced': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-sheets-collaboration': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-sheets-conditional-formatting': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-sheets-core': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-sheets-data-validation': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-sheets-drawing': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-sheets-filter': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-sheets-find-replace': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-sheets-hyper-link': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-sheets-node-core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-sheets-note': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-sheets-sort': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-sheets-table': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/preset-sheets-thread-comment': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) rxjs: 7.8.2 @@ -20409,34 +20410,36 @@ snapshots: '@univerjs/protocol@0.1.48': {} - '@univerjs/rpc-node@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/protocol@0.1.49': {} + + '@univerjs/rpc-node@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/rpc': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/rpc': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/rpc@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/rpc@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/sheets-conditional-formatting-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-conditional-formatting-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-conditional-formatting': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-formula-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-conditional-formatting': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-formula-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -20444,30 +20447,30 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs/sheets-conditional-formatting@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-conditional-formatting@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/sheets-data-validation-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-data-validation-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/data-validation': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/data-validation': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-data-validation': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-formula-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-numfmt': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-data-validation': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-formula-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-numfmt': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -20475,31 +20478,31 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs/sheets-data-validation@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-data-validation@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/data-validation': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/data-validation': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/protocol': 0.1.48 - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/sheets-drawing-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-drawing-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/docs-drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/drawing-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/docs-drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/drawing-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -20507,27 +20510,27 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs/sheets-drawing@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-drawing@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/drawing': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/drawing': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) transitivePeerDependencies: - react - rxjs - '@univerjs/sheets-filter-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-filter-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/rpc': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-filter': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/rpc': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-filter': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -20535,24 +20538,24 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs/sheets-filter@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-filter@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/rpc': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/rpc': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/sheets-find-replace@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-find-replace@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/find-replace': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/find-replace': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - '@types/react' @@ -20560,19 +20563,19 @@ snapshots: - react - react-dom - '@univerjs/sheets-formula-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-formula-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/docs': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/docs': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -20580,21 +20583,21 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs/sheets-formula@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-formula@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/rpc': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/rpc': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/sheets-graphics@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-graphics@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) transitivePeerDependencies: - '@types/react' - '@types/react-dom' @@ -20602,21 +20605,21 @@ snapshots: - react-dom - rxjs - '@univerjs/sheets-hyper-link-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-hyper-link-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/docs': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/docs': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-data-validation': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-formula-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-hyper-link': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-data-validation': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-formula-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-hyper-link': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -20624,26 +20627,26 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs/sheets-hyper-link@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-hyper-link@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/sheets-note-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-note-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-note': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-note': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -20651,25 +20654,25 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs/sheets-note@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-note@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/sheets-numfmt-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-numfmt-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-numfmt': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-numfmt': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -20677,25 +20680,25 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs/sheets-numfmt@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-numfmt@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/sheets-sort-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-sort-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-sort': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-sort': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -20703,28 +20706,28 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs/sheets-sort@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-sort@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) transitivePeerDependencies: - react - rxjs - '@univerjs/sheets-table-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-table-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-formula-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-sort': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-table': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-formula-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-sort': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-table': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -20732,27 +20735,27 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs/sheets-table@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-table@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/sheets-thread-comment-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-thread-comment-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-thread-comment': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/thread-comment': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/thread-comment-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-thread-comment': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/thread-comment': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/thread-comment-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -20760,29 +20763,29 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs/sheets-thread-comment@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-thread-comment@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/thread-comment': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/thread-comment': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/sheets-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/docs': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/docs-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/docs': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/docs-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@univerjs/protocol': 0.1.48 - '@univerjs/sheets': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/telemetry': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/sheets': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/telemetry': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -20790,34 +20793,34 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs/sheets@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/sheets@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-formula': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-formula': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/protocol': 0.1.48 - '@univerjs/rpc': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/rpc': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/telemetry@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/telemetry@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) transitivePeerDependencies: - react - rxjs - '@univerjs/themes@0.20.0': {} + '@univerjs/themes@0.20.1': {} - '@univerjs/thread-comment-ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/thread-comment-ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/docs-ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/docs-ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/thread-comment': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/ui': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) + '@univerjs/thread-comment': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/ui': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2) react: 19.2.4 rxjs: 7.8.2 transitivePeerDependencies: @@ -20825,18 +20828,18 @@ snapshots: - '@types/react-dom' - react-dom - '@univerjs/thread-comment@0.20.0(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/thread-comment@0.20.1(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) rxjs: 7.8.2 transitivePeerDependencies: - react - '@univerjs/ui@0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': + '@univerjs/ui@0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)': dependencies: - '@univerjs/core': 0.20.0(react@19.2.4)(rxjs@7.8.2) - '@univerjs/design': 0.20.0(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@univerjs/engine-render': 0.20.0(react@19.2.4)(rxjs@7.8.2) + '@univerjs/core': 0.20.1(react@19.2.4)(rxjs@7.8.2) + '@univerjs/design': 0.20.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@univerjs/engine-render': 0.20.1(react@19.2.4)(rxjs@7.8.2) '@univerjs/icons': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@wendellhu/redi': 1.1.1(react@19.2.4) localforage: 1.10.0 From 0df186ef7db2c18878ecfc0a1f44cb5eb5765eef Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 04:07:11 +0000 Subject: [PATCH 238/482] Update dependency dompurify to v3.4.0 [SECURITY] --- apps/client/package.json | 2 +- pnpm-lock.yaml | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/client/package.json b/apps/client/package.json index 7cff4e1ed0..ff8fc3b56f 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -49,7 +49,7 @@ "clsx": "2.1.1", "color": "5.0.3", "debounce": "3.0.0", - "dompurify": "3.3.3", + "dompurify": "3.4.0", "draggabilly": "3.0.0", "force-graph": "1.51.2", "i18next": "26.0.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 37746a1459..32f8497d26 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -307,8 +307,8 @@ importers: specifier: 3.0.0 version: 3.0.0 dompurify: - specifier: 3.3.3 - version: 3.3.3 + specifier: 3.4.0 + version: 3.4.0 draggabilly: specifier: 3.0.0 version: 3.0.0 @@ -8080,8 +8080,8 @@ packages: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} - dompurify@3.3.3: - resolution: {integrity: sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==} + dompurify@3.4.0: + resolution: {integrity: sha512-nolgK9JcaUXMSmW+j1yaSvaEaoXYHwWyGJlkoCTghc97KgGDDSnpoU/PlEnw63Ah+TGKFOyY+X5LnxaWbCSfXg==} domutils@2.8.0: resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} @@ -22936,7 +22936,7 @@ snapshots: dependencies: domelementtype: 2.3.0 - dompurify@3.3.3: + dompurify@3.4.0: optionalDependencies: '@types/trusted-types': 2.0.7 @@ -25969,7 +25969,7 @@ snapshots: d3-sankey: 0.12.3 dagre-d3-es: 7.0.14 dayjs: 1.11.20 - dompurify: 3.3.3 + dompurify: 3.4.0 katex: 0.16.45 khroma: 2.1.0 lodash-es: 4.18.1 @@ -27583,7 +27583,7 @@ snapshots: classnames: 2.5.1 core-js: 3.46.0 decko: 1.2.0 - dompurify: 3.3.3 + dompurify: 3.4.0 eventemitter3: 5.0.1 json-pointer: 0.6.2 lunr: 2.3.9 From 7e3683b8c262da9c8550df41a9142c53fb2f275a Mon Sep 17 00:00:00 2001 From: contributor Date: Thu, 16 Apr 2026 08:09:34 +0300 Subject: [PATCH 239/482] fix revisions dialog shows translation keys instead of values --- apps/client/src/translations/en/translation.json | 2 +- apps/client/src/widgets/type_widgets/options/other.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index e6c88a6c19..190edb998d 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -1341,7 +1341,7 @@ "erase_deleted_notes_now": "Erase deleted notes now", "deleted_notes_erased": "Deleted notes have been erased." }, - "revisions": { + "revisions_snapshot": { "title": "Note Revisions" }, "revisions_snapshot_interval": { diff --git a/apps/client/src/widgets/type_widgets/options/other.tsx b/apps/client/src/widgets/type_widgets/options/other.tsx index 44466cb620..1ab94476c4 100644 --- a/apps/client/src/widgets/type_widgets/options/other.tsx +++ b/apps/client/src/widgets/type_widgets/options/other.tsx @@ -177,7 +177,7 @@ function RevisionSettings() { const [ revisionSnapshotNumberLimit, setRevisionSnapshotNumberLimit ] = useTriliumOption("revisionSnapshotNumberLimit"); return ( - + Date: Thu, 16 Apr 2026 07:47:25 +0200 Subject: [PATCH 240/482] Update translation files Updated by "Cleanup translation files" add-on in Weblate. Translation: Trilium Notes/README Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ --- docs/README-ug.md | 235 ++++++++++++++++++++++++---------------------- 1 file changed, 121 insertions(+), 114 deletions(-) diff --git a/docs/README-ug.md b/docs/README-ug.md index 1dd96d5ed3..e44e6217e6 100644 --- a/docs/README-ug.md +++ b/docs/README-ug.md @@ -14,11 +14,11 @@ ![GitHub Sponsors](https://img.shields.io/github/sponsors/eliandoran) ![LiberaPay patrons](https://img.shields.io/liberapay/patrons/ElianDoran)\ ![Docker Pulls](https://img.shields.io/docker/pulls/triliumnext/trilium) -![GitHub Downloads (all assets, all -releases)](https://img.shields.io/github/downloads/triliumnext/trilium/total)\ +![GitHub Downloads (بارلىق ماتېرىياللار، بارلىق تارىخىي +نۇسخىلار)](https://img.shields.io/github/downloads/triliumnext/trilium/total)\ [![RelativeCI](https://badges.relative-ci.com/badges/Di5q7dz9daNDZ9UXi0Bp?branch=develop)](https://app.relative-ci.com/projects/Di5q7dz9daNDZ9UXi0Bp) -[![Translation -status](https://hosted.weblate.org/widget/trilium/svg-badge.svg)](https://hosted.weblate.org/engage/trilium/) +[![تەرجىمە قىلىنىش +ئەھۋالى](https://hosted.weblate.org/widget/trilium/svg-badge.svg)](https://hosted.weblate.org/engage/trilium/) @@ -36,135 +36,142 @@ Trilium Notes بولسا ھەقسىز، ئوچۇق كودلۇق، سىستېما Trilium Screenshot ## چۈشۈرۈش⏬ -- [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. +- [ئەڭ يېڭى نۇسخىسى](https://github.com/TriliumNext/Trilium/releases/latest) – + مۇقىم نۇسخا، كۆپ ساندىكى ئابونتلارنىڭ ئىشلىتىشى تەۋسىيە قىلىنىدۇ. +- [كۈندىلىك + قۇرۇلما](https://github.com/TriliumNext/Trilium/releases/tag/nightly) – مۇقىم + بولمىغان ئېچىش نۇسخىسى، ھەر كۈنى يېڭىلىنىدۇ، ئەڭ يېڭى ئىقتىدارلار ۋە + تۈزىتىشلەرنى ئۆز ئىچىگە ئالىدۇ. ## ھۆججەتلەر📚 -**Visit our comprehensive documentation at -[docs.triliumnotes.org](https://docs.triliumnotes.org/)** +بىزنىڭ تولۇق قوللانمىمىزنى كۆرۈڭ: +[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](./User%20Guide/User%20Guide/) in - this repository +- **پروگرامما ئىچىدىكى ياردەم**: Trilium دا` F1` نى باسسىڭىزلا، پروگرامما ئىچىدە + ئوخشاش بىر قوللانمىنى بىۋاسىتە كۆرەلەيسىز +- **GitHub**:بۇ ئامباردىكى [ئابونت قوللانمىسىنى](./User%20Guide/User%20Guide/) + كۆرۈڭ -### Quick Links -- [Getting Started Guide](https://docs.triliumnotes.org/) -- [Installation Instructions](https://docs.triliumnotes.org/user-guide/setup) +### تېز ئۇلانمىلار +- [ئابونت چۈشەندۈرۈشى](https://docs.triliumnotes.org/) +- [قاچىلاش چۈشەندۈرۈشى](https://docs.triliumnotes.org/user-guide/setup) - [Docker - Setup](https://docs.triliumnotes.org/user-guide/setup/server/installation/docker) -- [Upgrading - TriliumNext](https://docs.triliumnotes.org/user-guide/setup/upgrading) -- [Basic Concepts and - Features](https://docs.triliumnotes.org/user-guide/concepts/notes) -- [Patterns of Personal Knowledge - Base](https://docs.triliumnotes.org/user-guide/misc/patterns-of-personal-knowledge) + تەڭشەكلىرى](https://docs.triliumnotes.org/user-guide/setup/server/installation/docker) +- [TriliumNext نى دەرىجىسىنى + ئۆستۈرۈش](https://docs.triliumnotes.org/user-guide/setup/upgrading) +- [ئاساسىي ئۇقۇملار ۋە + ئالاھىدىلىكلەر](https://docs.triliumnotes.org/user-guide/concepts/notes) +- [شەخسىي بىلىم ئامبىرى + ئەندىزىسى](https://docs.triliumnotes.org/user-guide/misc/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://docs.triliumnotes.org/user-guide/concepts/notes/cloning)) -* Rich WYSIWYG note editor including e.g. tables, images and - [math](https://docs.triliumnotes.org/user-guide/note-types/text) with markdown - [autoformat](https://docs.triliumnotes.org/user-guide/note-types/text/markdown-formatting) -* Support for editing [notes with source - code](https://docs.triliumnotes.org/user-guide/note-types/code), including - syntax highlighting -* Fast and easy [navigation between - notes](https://docs.triliumnotes.org/user-guide/concepts/navigation/note-navigation), - full text search and [note - hoisting](https://docs.triliumnotes.org/user-guide/concepts/navigation/note-hoisting) -* Seamless [note - versioning](https://docs.triliumnotes.org/user-guide/concepts/notes/note-revisions) -* Note - [attributes](https://docs.triliumnotes.org/user-guide/advanced-usage/attributes) - can be used for note organization, querying and advanced - [scripting](https://docs.triliumnotes.org/user-guide/scripts) -* UI available in English, German, Spanish, French, Romanian, and Chinese - (simplified and traditional) -* Direct [OpenID and TOTP - integration](https://docs.triliumnotes.org/user-guide/setup/server/mfa) for - more secure login -* [Synchronization](https://docs.triliumnotes.org/user-guide/setup/synchronization) - with self-hosted sync server - * there are [3rd party services for hosting synchronisation - server](https://docs.triliumnotes.org/user-guide/setup/server/cloud-hosting) -* [Sharing](https://docs.triliumnotes.org/user-guide/advanced-usage/sharing) - (publishing) notes to public internet -* Strong [note - encryption](https://docs.triliumnotes.org/user-guide/concepts/notes/protected-notes) - with per-note granularity -* Sketching diagrams, based on [Excalidraw](https://excalidraw.com/) (note type - "canvas") -* [Relation - maps](https://docs.triliumnotes.org/user-guide/note-types/relation-map) and - [note/link maps](https://docs.triliumnotes.org/user-guide/note-types/note-map) - for visualizing notes and their relations -* Mind maps, based on [Mind Elixir](https://docs.mind-elixir.com/) -* [Geo maps](https://docs.triliumnotes.org/user-guide/collections/geomap) with - location pins and GPX tracks -* [Scripting](https://docs.triliumnotes.org/user-guide/scripts) - see [Advanced - showcases](https://docs.triliumnotes.org/user-guide/advanced-usage/advanced-showcases) -* [REST API](https://docs.triliumnotes.org/user-guide/advanced-usage/etapi) for - automation -* Scales well in both usability and performance upwards of 100 000 notes -* Touch optimized [mobile - frontend](https://docs.triliumnotes.org/user-guide/setup/mobile-frontend) for - smartphones and tablets -* Built-in [dark - theme](https://docs.triliumnotes.org/user-guide/concepts/themes), support for - user themes -* [Evernote](https://docs.triliumnotes.org/user-guide/concepts/import-export/evernote) - and [Markdown import & - export](https://docs.triliumnotes.org/user-guide/concepts/import-export/markdown) -* [Web Clipper](https://docs.triliumnotes.org/user-guide/setup/web-clipper) for - easy saving of web content -* Customizable UI (sidebar buttons, user-defined widgets, ...) -* [Metrics](https://docs.triliumnotes.org/user-guide/advanced-usage/metrics), - along with a Grafana Dashboard. +* خاتىرىلەرنى ھەر قانداق چوڭقۇرلۇقتىكى دەرەخسىمان قۇرۇلمىغا تەشكىللەشكە بولىدۇ. + بىرلا خاتىرىنى دەرەخنىڭ كۆپلىگەن ئورنىغا قويۇشقا بولىدۇ ([خاتىرىنى + كۆپەيتىش/كلونلاش](https://docs.triliumnotes.org/user-guide/concepts/notes/cloning) + غا قاراڭ) +* تۆت تەرەپتىن كۆرۈنىدىغان (WYSIWYG) بېيىتىلغان خاتىرە تەھرىرلىگۈچ، جەدۋەل، + رەسىم ۋە [ماتېماتىكىلىق + فورمۇلا](https://docs.triliumnotes.org/user-guide/note-types/text)نى قوللايدۇ، + ھەمدە Markdown نىڭ [ئاپتوماتىك + فورماتى](https://docs.triliumnotes.org/user-guide/note-types/text/markdown-formatting)غا + ئىگە +* [پروگرامما كودى + خاتىرىسى](https://docs.triliumnotes.org/user-guide/note-types/code)نى + تەھرىرلەشنى قوللايدۇ، كود نۇرىنى ئۆز ئىچىگە ئالىدۇ +* خاتىرىلەر ئارىسىدا تېز ۋە ئوڭاي + [يېتەكلەش](https://docs.triliumnotes.org/user-guide/concepts/navigation/note-navigation)، + پۈتۈن تېكىستلىك ئىزدەش، ھەمدە [خاتىرىگە فوكۇسلىنىش + (hoisting)](https://docs.triliumnotes.org/user-guide/concepts/navigation/note-hoisting) +* ئۈزۈلۈپ قالمايدىغان [خاتىرە نۇسخىسىنى + باشقۇرۇش](https://docs.triliumnotes.org/user-guide/concepts/notes/note-revisions) +* خاتىرە + [خاسلىقى](https://docs.triliumnotes.org/user-guide/advanced-usage/attributes) + خاتىرىلەرنى تەشكىللەش، سۈرۈشتۈرۈش ۋە يۇقىرى دەرىجىلىك + [script](https://docs.triliumnotes.org/user-guide/scripts)لەرگە ئىشلىتىلىدۇ +* UI ئىنگلىزچە، گېرمانچە، ئىسپانچە، فىرانسۇزچە، رۇمىنىيەچە ۋە خەنزۇچە تىللىرىدا + تەمىنلىنىدۇ +* تېخىمۇ بىخەتەر كىرىش ئۈچۈن [OpenID ۋە + TOTP](https://docs.triliumnotes.org/user-guide/setup/server/mfa) بىۋاسىتە بىر + گەۋدىلەشتۈرۈلگەن +* ئۆزى قۇرغان ماسقەدەملەش مۇلازىمىتىرى بىلەن + [ماسقەدەملەش](https://docs.triliumnotes.org/user-guide/setup/synchronization) + * [ماسقەدەملەش مۇلازىمىتىرىنى ئورۇنلاشتۇرۇش ئۈچۈن ئۈچىنچى تەرەپ + مۇلازىمىتى](https://docs.triliumnotes.org/user-guide/setup/server/cloud-hosting) + بار +* خاتىرىنى ئىنتېرنېت تورىغا + [ھەمبەھرىلەش](https://docs.triliumnotes.org/user-guide/advanced-usage/sharing) + (ئاشكارە ئېلان قىلىش +* ھەر بىر خاتىرە بىرلىك قىلىنغان كۈچلۈك [خاتىرە + شىفىرلاش](https://docs.triliumnotes.org/user-guide/concepts/notes/protected-notes) +* قولدا سىزىلغان/ئىزاھلىق رەسىم: [Excalidraw](https://excalidraw.com/) غا + ئاساسلانغان (خاتىرە تىپى «canvas») +* خاتىرە ۋە ئۇلارنىڭ مۇناسىۋىتىنى كۆرسىتىپ بېرىدىغان [مۇناسىۋەت + خەرىتىسى](https://docs.triliumnotes.org/user-guide/note-types/relation-map) ۋە + [خاتىرە/ئۇلانما + خەرىتىسى](https://docs.triliumnotes.org/user-guide/note-types/note-map) +* تەپەككۇر خەرىتىسى: [Mind Elixir](https://docs.mind-elixir.com/) غا ئاساسلانغان +* ئورۇن بەلگىلەش بەلگىسى ۋە GPX يۆنىلىش لىنىيىسى بولغان [جۇغراپىيىلىك + خەرىتە](https://docs.triliumnotes.org/user-guide/collections/geomap) +* [Script](https://docs.triliumnotes.org/user-guide/scripts) - [ئىلغار + كۆرسىتىش](https://docs.triliumnotes.org/user-guide/advanced-usage/advanced-showcases)گە + قاراڭ +* ئاپتوماتلاشتۇرۇش ئۈچۈن ئىشلىتىلىدىغان [REST + API](https://docs.triliumnotes.org/user-guide/advanced-usage/etapi) +* ئىشلىتىشچانلىقى ۋە ئۈنۈمى جەھەتتە ياخشى كېڭىيىشچانلىققا ئىگە، 100,000 دىن + ئارتۇق خاتىرىنى قوللايدۇ +* يانفون ۋە تاختا كومپيۇتېر ئۈچۈن ئەلالاشتۇرۇلغان [كۆچمە + تەرەپ](https://docs.triliumnotes.org/user-guide/setup/mobile-frontend) +* ئىچىگە ئورۇنلاشتۇرۇلغان [قېنىق رەڭلىك + تېما](https://docs.triliumnotes.org/user-guide/concepts/themes) +* [Evernote دىن + ئەكىرىش](https://docs.triliumnotes.org/user-guide/concepts/import-export/evernote) + ۋە [Markdown نى ئەكىرىش ھەم + چىقىرىش](https://docs.triliumnotes.org/user-guide/concepts/import-export/markdown) +* توردىكى مەزمۇنلارنى تېز ساقلاشقا ئىشلىتىلىدىغان [Web + Clipper](https://docs.triliumnotes.org/user-guide/setup/web-clipper) +* ئىختىيارىي تەڭشىگىلى بولىدىغان UI (يان تىزىملىك كۇنۇپكىلىرى، ئىشلەتكۈچى ئۆزى + بەلگىلىگەن كىچىك قوراللار قاتارلىقلار) +* [Metrics ](https://docs.triliumnotes.org/user-guide/advanced-usage/metrics)، + شۇنداقلا Grafana كۆرسىتىش تاختىسى. -✨ Check out the following third-party resources/communities for more TriliumNext -related goodies: +✨ تېخىمۇ كۆپ TriliumNext تېمىلىرى، قوليازما، قىستۇرما ۋە مەنبەلەرگە ئېرىشمەكچى +بولسىڭىز، تۆۋەندىكى ئۈچىنچى تەرەپ مەنبەلىرى ياكى جەمئىيەتلىرىدىن پايدىلانسىڭىز +بولىدۇ: -- [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) (ئۈچىنچى تەرەپ + تېمىلىرى، قوليازمىلار، قىستۇرمىلار ۋە باشقىلار). +- [TriliumRocks!](https://trilium.rocks/) (دەرسلىكلەر، يېتەكچىلەر ۋە باشقىلار). -## ❓Why TriliumNext? +## ⚠️ نېمە ئۈچۈن 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 +Trilium نىڭ ئەسلى ئىجادچىسى ([Zadam](https://github.com/zadam)) سېخىيلىق بىلەن +Trilium كود ئامبىرىنى جەمئىيەت تۈرىگە ئۆتكۈزۈپ بەردى، بۇ تۈر ھازىر مۇشۇ ئادرېستا +ساقلىنىۋاتىدۇ: https://github.com/TriliumNext -### ⬆️Migrating from Zadam/Trilium? +### ⬆️ 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. +zadam/Trilium نۇسخىسىدىن TriliumNext/Notes غا كۆچۈش ئۈچۈن ئالاھىدە كۆچۈرۈش +باسقۇچلىرى كېرەك ئەمەس. [TriliumNext/Notes نى ئادەتتىكى ئۇسۇلدا +قاچىلىسىڭىزلا](#-installation)(#-install)، ئۇ بىۋاسىتە ھازىرقى ساندانىڭىزنى +ئىشلىتىدۇ. -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. +[v0.90.4](https://github.com/TriliumNext/Trilium/releases/tag/v0.90.4) غىچە +بولغان نەشرلىرى zadam/trilium نىڭ ئەڭ يېڭى +[v0.63.7](https://github.com/zadam/trilium/releases/tag/v0.63.7) نەشرى بىلەن +ماسلىشىدۇ. ئۇنىڭدىن كېيىنكى TriliumNext نەشرلىرىدە ماسقەدەملەش نەشر نومۇرى +ئۆستۈرۈلگەن بولۇپ، يۇقىرىقىلار بىلەن ماسلاشمايدۇ. -## 💬 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.) +- [Matrix](https://matrix.to/#/#triliumnext:matrix.org) (ماسقەدەملىك مۇنازىرە) - The `General` Matrix room is also bridged to [XMPP](xmpp:discuss@trilium.thisgreat.party?join) - [Github Discussions](https://github.com/TriliumNext/Trilium/discussions) (For From 2fc907e7568fcd3037d170328194f9442e27453c Mon Sep 17 00:00:00 2001 From: Ulices Date: Thu, 16 Apr 2026 01:06:32 +0200 Subject: [PATCH 241/482] Translated using Weblate (Spanish) Currently translated at 85.3% (1649 of 1932 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/es/ --- .../src/translations/es/translation.json | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/apps/client/src/translations/es/translation.json b/apps/client/src/translations/es/translation.json index f3588aac03..2f26db1ba8 100644 --- a/apps/client/src/translations/es/translation.json +++ b/apps/client/src/translations/es/translation.json @@ -428,7 +428,9 @@ "print_landscape": "Al exportar a PDF, cambia la orientación de la página a paisaje en lugar de retrato.", "print_page_size": "Al exportar a PDF, cambia el tamaño de la página. Valores soportados: A0, A1, A2, A3, A4, A5, A6, Legal, Letter, Tabloid, Ledger.", "color_type": "Color", - "textarea": "Texto multilínea" + "textarea": "Texto multilínea", + "print_scale": "Al exportar a PDF, cambia la escala del contenido renderizado. Los valores varían de 0.1 (10%) a 2 (200%), por defecto es 1 (100%).", + "print_margins": "Al exportar a PDF, establece márgenes de página. Use default, none, minimum, o valores personalizados como top,right,bottom,left en milímetros." }, "attribute_editor": { "help_text_body1": "Para agregar una etiqueta, simplemente escriba, por ejemplo. #rock o si desea agregar también valor, p.e. #año = 2020", @@ -691,7 +693,11 @@ "export_as_image_png": "PNG (ráster)", "export_as_image_svg": "SVG (vectorial)", "note_map": "Mapa de la nota", - "view_ocr_text": "Ver texto OCR" + "view_ocr_text": "Ver texto OCR", + "word_wrap_auto": "Automático", + "word_wrap_auto_description": "Seguir el ajuste global", + "word_wrap_on": "Encendido", + "word_wrap_off": "Apagado" }, "onclick_button": { "no_click_handler": "El widget de botón '{{componentId}}' no tiene un controlador de clics definido" @@ -792,7 +798,10 @@ "hide_child_notes": "Ocultar subnotas en el árbol", "open_all_in_tabs": "Abrir todo", "open_all_in_tabs_tooltip": "Abrir todos los resultados en nuevas pestañas", - "open_all_confirm": "Esto abrirá {{count}} notas en nuevas pestañas. ¿Continuar?" + "open_all_confirm": "Esto abrirá {{count}} notas en nuevas pestañas. ¿Continuar?", + "open_all_too_one": " ", + "open_all_too_many": " ", + "open_all_too_other": " " }, "edited_notes": { "no_edited_notes_found": "Aún no hay notas editadas en este día...", @@ -1122,7 +1131,7 @@ "note_tree_font": "Fuente del árbol de notas", "note_detail_font": "Fuente de detalle de nota", "monospace_font": "Fuente Monospace (código)", - "not_all_fonts_available": "Es posible que no todas las fuentes enumeradas estén disponibles en su sistema.", + "not_all_fonts_available": "Es posible que no todas las fuentes enumeradas estén disponibles en su sistema", "generic-fonts": "Fuentes genéricas", "sans-serif-system-fonts": "Fuentes Sans-serif del sistema", "serif-system-fonts": "Fuentes Serif del sistema", @@ -1208,7 +1217,7 @@ "attachment_erasure_timeout": { "attachment_erasure_timeout": "Tiempo de espera para borrar archivos adjuntos", "erase_attachments_after": "Borrar archivos adjuntos después de:", - "manual_erasing_description": "También puede activar el borrado manualmente (sin considerar el tiempo de espera definido anteriormente):", + "manual_erasing_description": "Activar el borrado manualmente, ignorando el tiempo de espera definido anteriormente.", "erase_unused_attachments_now": "Borrar ahora los archivos adjuntos no utilizados en la nota", "unused_attachments_erased": "Los archivos adjuntos no utilizados se han eliminado." }, @@ -1219,7 +1228,7 @@ "note_erasure_timeout": { "note_erasure_timeout_title": "Tiempo de espera de borrado de notas", "erase_notes_after": "Borrar notas después de:", - "manual_erasing_description": "También puede activar el borrado manualmente (sin considerar el tiempo de espera definido anteriormente):", + "manual_erasing_description": "Activar el borrado manualmente, ignorando el tiempo de espera definido anteriormente.", "erase_deleted_notes_now": "Borrar notas eliminadas ahora", "deleted_notes_erased": "Las notas eliminadas han sido borradas." }, @@ -1238,7 +1247,7 @@ }, "search_engine": { "title": "Motor de búsqueda", - "custom_search_engine_info": "El motor de búsqueda personalizado requiere que se establezcan un nombre y una URL. Si alguno de estos no está configurado, DuckDuckGo se utilizará como motor de búsqueda predeterminado.", + "custom_search_engine_info": "Utilizado al buscar la web para el texto seleccionado. Si no está configurado, DuckDuckGo será utilizado.", "predefined_templates_label": "Plantillas de motor de búsqueda predefinidas", "bing": "Bing", "baidu": "Baidu", @@ -1613,7 +1622,7 @@ "note_detail": { "could_not_find_typewidget": "No se pudo encontrar typeWidget para el tipo '{{type}}'", "printing": "Impresión en curso...", - "printing_pdf": "Exportando a PDF en curso..", + "printing_pdf": "Preparando vista preliminar de impresión...", "print_report_collection_content_one": "{{count}} nota en la colección no se puede imprimir porque no son compatibles o está protegida.", "print_report_collection_content_many": "{{count}} notas en la colección no se pueden imprimir porque no son compatibles o están protegidas.", "print_report_collection_content_other": "{{count}} notas en la colección no se pueden imprimir porque no son compatibles o están protegidas.", @@ -1758,7 +1767,7 @@ "title": "Fijo", "description": "las herramientas de edición aparecen en la pestaña de la cinta \"Formato\")." }, - "multiline-toolbar": "Mostrar la barra de herramientas en múltiples líneas si no cabe." + "multiline-toolbar": "Mostrar la barra de herramientas en múltiples líneas si no cabe" } }, "electron_context_menu": { From 8b202b676027d89a2c331b6c03bacccd24d2f446 Mon Sep 17 00:00:00 2001 From: passkal4 Date: Thu, 16 Apr 2026 07:47:50 +0200 Subject: [PATCH 242/482] Translated using Weblate (Uyghur) Currently translated at 14.1% (57 of 403 strings) Translation: Trilium Notes/Server Translate-URL: https://hosted.weblate.org/projects/trilium/server/ug/ --- .../src/assets/translations/ug/server.json | 53 ++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/apps/server/src/assets/translations/ug/server.json b/apps/server/src/assets/translations/ug/server.json index ffc7858ad1..d97651fe0d 100644 --- a/apps/server/src/assets/translations/ug/server.json +++ b/apps/server/src/assets/translations/ug/server.json @@ -5,6 +5,57 @@ "open-jump-to-note-dialog": "\"خاتىرىگە تېز ئۆتۈش\" كۆزنىكىنى ئېچىش", "open-command-palette": "بۇيرۇق تىزىملىكىنى ئېچىش", "quick-search": "تېز ئىزدەشنى قوزغىتىش", - "search-in-subtree": "ھازىرقى خاتىرىنىڭ تارماقلىرىدىن ئىزدەش" + "search-in-subtree": "ھازىرقى خاتىرىنىڭ تارماقلىرىدىن ئىزدەش", + "scroll-to-active-note": "خاتىرە دەرىخىنى نۆۋەتتىكى خاتىرىگە سىيرىش", + "expand-subtree": "نۆۋەتتىكى خاتىرىنىڭ تارماق دەرىخىنى يېيىش", + "collapse-tree": "تولۇق خاتىرە دەرىخىنى يىغىش", + "collapse-subtree": "نۆۋەتتىكى خاتىرىنىڭ تارماق دەرىخىنى يىغىش", + "sort-child-notes": "تارماق خاتىرىلەرنى تەرتىپلەش", + "creating-and-moving-notes": "خاتىرە قۇرۇش ۋە يۆتكەش", + "create-note-after": "نۆۋەتتىكى خاتىرىنىڭ كەينىگە خاتىرە قۇرۇش", + "create-note-into": "نۆۋەتتىكى خاتىرىگە تارماق خاتىرە قۇرۇش", + "create-note-into-inbox": "Inbox ساندۇقى (ئەگەر بېكىتىلگەن بولسا) ياكى كۈندىلىك خاتىرىدە خاتىرە قۇرۇش", + "delete-note": "خاتىرىنى ئۆچۈرۈش", + "move-note-up": "خاتىرىنى يۇقىرىغا يۆتكەش", + "move-note-down": "خاتىرىنى تۆۋەنگە يۆتكەش", + "move-note-up-in-hierarchy": "خاتىرىنى قاتلام بويىچە يۇقىرىغا يۆتكەش", + "move-note-down-in-hierarchy": "خاتىرىنى قاتلام بويىچە تۆۋەنگە يۆتكەش", + "edit-note-title": "دەرەخسىمان قۇرۇلمىدىن خاتىرە تەپسىلاتىغا سەكرەش ۋە تېمىنى تەھرىرلەش", + "edit-branch-prefix": "تارماق ئالدى قوشۇلغۇچىنى تەھرىرلەش سۆزلىشىش كۆزنىكىنى كۆرسىتىش", + "clone-notes-to": "تاللانغان خاتىرىنى كۆچۈرۈپ قويۇش ئورنى", + "move-notes-to": "تاللانغان خاتىرىنى يۆتكەش ئورنى", + "note-clipboard": "خاتىرە چاپلاش تاختىسى", + "copy-notes-to-clipboard": "تاللانغان خاتىرىنى چاپلاش تاختىسىغا كۆچۈرۈش", + "paste-notes-from-clipboard": "چاپلاش تاختىسىدىكى خاتىرىنى نۆۋەتتىكى خاتىرىگە چاپلاش", + "cut-notes-to-clipboard": "تاللانغان خاتىرىنى چاپلاش تاختىسىغا كېسىپ ئېلىش", + "select-all-notes-in-parent": "نۆۋەتتىكى خاتىرە دەرىجىسىدىكى بارلىق خاتىرىلەرنى تاللاش", + "add-note-above-to-the-selection": "ئۈستىدىكى خاتىرىنى تاللانمىغا قوشۇش", + "add-note-below-to-selection": "ئاستىدىكى خاتىرىنى تاللانمىغا قوشۇش", + "duplicate-subtree": "تارماق دەرەخنى كۆچۈرۈش", + "tabs-and-windows": "بەتكۈچ ۋە كۆزنەك", + "open-new-tab": "يېڭى بەتكۈچ ئېچىش", + "close-active-tab": "نۆۋەتتىكى بەتكۈچنى يېپىش", + "reopen-last-tab": "ئەڭ ئاخىرقى يېپىلغان بەتكۈچنى قايتا ئېچىش", + "activate-next-tab": "كېيىنكى بەتكۈچكە ئالماشتۇرۇش", + "activate-previous-tab": "ئالدىنقى بەتكۈچكە ئالماشتۇرۇش", + "open-new-window": "يېڭى كۆزنەك ئېچىش", + "toggle-tray": "سىستېما تەخسىسى سىنبەلگىسىنى كۆرسىتىش/يوشۇرۇش", + "first-tab": "بىرىنچى بەتكۈچكە ئالماشتۇرۇش", + "second-tab": "ئىككىنچى بەتكۈچكە ئالماشتۇرۇش", + "third-tab": "ئۈچىنچى بەتكۈچكە ئالماشتۇرۇش", + "fourth-tab": "تۆتىنچى بەتكۈچكە ئالماشتۇرۇش", + "fifth-tab": "بەشىنچى بەتكۈچكە ئالماشتۇرۇش", + "sixth-tab": "ئالتىنچى بەتكۈچكە ئالماشتۇرۇش", + "seventh-tab": "يەتتىنچى بەتكۈچكە ئالماشتۇرۇش", + "eight-tab": "سەككىزىنچى بەتكۈچكە ئالماشتۇرۇش", + "ninth-tab": "توققۇزىنچى بەتكۈچكە ئالماشتۇرۇش", + "last-tab": "ئەڭ ئاخىرقى بەتكۈچكە ئالماشتۇرۇش", + "dialogs": "سۆھبەت رامكىلىرى", + "show-note-source": "خاتىرە ئەسلى كودى سۆھبەت رامكىسىنى كۆرسىتىش", + "show-options": "تاللانما سۆھبەت رامكىسىنى كۆرسىتىش", + "show-revisions": "تۈزىتىش تارىخى سۆھبەت رامكىسىنى كۆرسىتىش", + "show-recent-changes": "يېقىنقى ئۆزگىرىشلەر سۆھبەت رامكىسىنى كۆرسىتىش", + "show-sql-console": "SQL كونترول سۇپىسى سۆھبەت رامكىسىنى كۆرسىتىش", + "show-backend-log": "ئارقا سۇپا خاتىرىسى سۆھبەت رامكىسىنى كۆرسىتىش" } } From 062d0863a1dbb949da06b2dc2046172321040570 Mon Sep 17 00:00:00 2001 From: green Date: Thu, 16 Apr 2026 02:51:05 +0200 Subject: [PATCH 243/482] Translated using Weblate (Japanese) Currently translated at 99.9% (1931 of 1932 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/ --- .../src/translations/ja/translation.json | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/apps/client/src/translations/ja/translation.json b/apps/client/src/translations/ja/translation.json index 5884ece190..3f8408c640 100644 --- a/apps/client/src/translations/ja/translation.json +++ b/apps/client/src/translations/ja/translation.json @@ -491,7 +491,12 @@ "export_as_image": "画像としてエクスポート", "export_as_image_png": "PNG (raster)", "export_as_image_svg": "SVG (vector)", - "view_ocr_text": "OCR テキストを表示" + "view_ocr_text": "OCR テキストを表示", + "word_wrap": "行の折り返し", + "word_wrap_auto": "自動", + "word_wrap_auto_description": "グローバル設定に従う", + "word_wrap_on": "オン", + "word_wrap_off": "オフ" }, "command_palette": { "export_note_title": "ノートをエクスポート", @@ -1850,7 +1855,7 @@ "note_detail": { "could_not_find_typewidget": "タイプ {{type}} の typeWidget が見つかりませんでした", "printing": "印刷中です...", - "printing_pdf": "PDF へのエクスポート中です...", + "printing_pdf": "印刷プレビューを準備中...", "print_report_title": "レポートを印刷", "print_report_collection_content_other": "コレクション内の {{count}} 件のノートは、サポートされていないか保護されているため、印刷できませんでした。", "print_report_collection_details_button": "詳細を見る", @@ -2141,7 +2146,7 @@ "tab_width_title": "タブ幅を変更", "tab_width_spaces": "{{count}} スペース", "tab_width_spaces_short": "スペース: {{width}}", - "tab_width_tabs": "タブ ({{width}})", + "tab_width_tabs": "タブ: {{width}}", "tab_width_use_default": "デフォルトを使用 ({{width}})", "tab_width_use_default_style": "デフォルトを使用 ({{style}})", "tab_width_display_header": "表示幅", @@ -2436,6 +2441,13 @@ "page_ranges": "ページ", "page_ranges_hint": "全ページを印刷する場合は空欄のままにしてください。", "page_ranges_invalid": "無効な形式です。例: 1-5, 8, 11-13 のように指定してください。", - "page_ranges_placeholder": "例: 1-5, 8, 11-13" + "page_ranges_placeholder": "例: 1-5, 8, 11-13", + "print": "印刷", + "export_pdf": "PDF としてエクスポート", + "system_print": "システムダイアログを使用して印刷", + "destination": "出力先", + "destination_pdf": "PDF として保存", + "destination_printers": "プリンター", + "destination_default": "デフォルト" } } From 1154a1f7bfdd095502ff1ed897c48467b9225385 Mon Sep 17 00:00:00 2001 From: passkal4 Date: Thu, 16 Apr 2026 07:48:45 +0200 Subject: [PATCH 244/482] Translated using Weblate (Uyghur) Currently translated at 51.2% (61 of 119 strings) Translation: Trilium Notes/README Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ug/ --- docs/README-ug.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README-ug.md b/docs/README-ug.md index e44e6217e6..ed99cc583d 100644 --- a/docs/README-ug.md +++ b/docs/README-ug.md @@ -172,8 +172,8 @@ zadam/Trilium نۇسخىسىدىن TriliumNext/Notes غا كۆچۈش ئۈچۈن ياكى مەسىلىلەر ھەققىدىكى پىكىرلىرىڭىزنى ئاڭلاشنى ئارزۇ قىلىمىز! - [Matrix](https://matrix.to/#/#triliumnext:matrix.org) (ماسقەدەملىك مۇنازىرە) - - The `General` Matrix room is also bridged to - [XMPP](xmpp:discuss@trilium.thisgreat.party?join) + - `General `Matrix ئۆيىمۇ [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 From 0e76f412ec43e78fe87b9c0246335ad52ad02a20 Mon Sep 17 00:00:00 2001 From: passkal4 Date: Thu, 16 Apr 2026 07:49:14 +0200 Subject: [PATCH 245/482] Translated using Weblate (Uyghur) Currently translated at 14.3% (58 of 403 strings) Translation: Trilium Notes/Server Translate-URL: https://hosted.weblate.org/projects/trilium/server/ug/ --- apps/server/src/assets/translations/ug/server.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/server/src/assets/translations/ug/server.json b/apps/server/src/assets/translations/ug/server.json index d97651fe0d..593275bcb8 100644 --- a/apps/server/src/assets/translations/ug/server.json +++ b/apps/server/src/assets/translations/ug/server.json @@ -56,6 +56,7 @@ "show-revisions": "تۈزىتىش تارىخى سۆھبەت رامكىسىنى كۆرسىتىش", "show-recent-changes": "يېقىنقى ئۆزگىرىشلەر سۆھبەت رامكىسىنى كۆرسىتىش", "show-sql-console": "SQL كونترول سۇپىسى سۆھبەت رامكىسىنى كۆرسىتىش", - "show-backend-log": "ئارقا سۇپا خاتىرىسى سۆھبەت رامكىسىنى كۆرسىتىش" + "show-backend-log": "ئارقا سۇپا خاتىرىسى سۆھبەت رامكىسىنى كۆرسىتىش", + "show-help": "ياردەمنى كۆرسىتىش" } } From 093e671fb5e54ebda4ae76bf5524c9d4a2147fea Mon Sep 17 00:00:00 2001 From: passkal4 Date: Thu, 16 Apr 2026 07:49:44 +0200 Subject: [PATCH 246/482] Translated using Weblate (Uyghur) Currently translated at 52.1% (62 of 119 strings) Translation: Trilium Notes/README Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ug/ --- docs/README-ug.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README-ug.md b/docs/README-ug.md index ed99cc583d..0c4c59b054 100644 --- a/docs/README-ug.md +++ b/docs/README-ug.md @@ -174,8 +174,8 @@ zadam/Trilium نۇسخىسىدىن TriliumNext/Notes غا كۆچۈش ئۈچۈن - [Matrix](https://matrix.to/#/#triliumnext:matrix.org) (ماسقەدەملىك مۇنازىرە) - `General `Matrix ئۆيىمۇ [XMPP](xmpp:discuss@trilium.thisgreat.party?join) غا ئۇلانغان -- [Github Discussions](https://github.com/TriliumNext/Trilium/discussions) (For - asynchronous discussions.) +- [GitHub Discussions](https://github.com/TriliumNext/Trilium/discussions) + (ئاسىنكرون مۇنازىرە). - [Github Issues](https://github.com/TriliumNext/Trilium/issues) (For bug reports and feature requests.) From c36264203f9f008009099aa19382b187baa58744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aindri=C3=BA=20Mac=20Giolla=20Eoin?= Date: Thu, 16 Apr 2026 12:10:27 +0200 Subject: [PATCH 247/482] Translated using Weblate (Irish) Currently translated at 100.0% (403 of 403 strings) Translation: Trilium Notes/Server Translate-URL: https://hosted.weblate.org/projects/trilium/server/ga/ --- apps/server/src/assets/translations/ga/server.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/server/src/assets/translations/ga/server.json b/apps/server/src/assets/translations/ga/server.json index 00e9c2ef9f..d5dc6d23ca 100644 --- a/apps/server/src/assets/translations/ga/server.json +++ b/apps/server/src/assets/translations/ga/server.json @@ -458,5 +458,8 @@ "fulltext-after-expression": "Ní abairt bhailí í \"{{- token}}\". Chun téacs a chuardach, cuir é roimh scagairí tréithe (m.sh., \"{{- token}} #label\" in ionad \"#label {{- token}}\").", "unrecognized-expression": "Sloinneadh neamhaitheanta \"{{- token}}\"" } + }, + "password": { + "incorrect": "Tá an focal faire a chuir tú isteach mícheart." } } From cd6f63a908748224b68f79fa352562d265e680e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aindri=C3=BA=20Mac=20Giolla=20Eoin?= Date: Thu, 16 Apr 2026 12:34:56 +0200 Subject: [PATCH 248/482] Translated using Weblate (Irish) Currently translated at 99.9% (1931 of 1932 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/ga/ --- .../src/translations/ga/translation.json | 295 ++++++++++++------ 1 file changed, 205 insertions(+), 90 deletions(-) diff --git a/apps/client/src/translations/ga/translation.json b/apps/client/src/translations/ga/translation.json index a6facbbf36..7326807d26 100644 --- a/apps/client/src/translations/ga/translation.json +++ b/apps/client/src/translations/ga/translation.json @@ -461,7 +461,9 @@ "print_landscape": "Agus é á onnmhairiú go PDF, athraítear treoshuíomh an leathanaigh go tírdhreach seachas portráid.", "print_page_size": "Agus é á easpórtáil go PDF, athraítear méid an leathanaigh. Luachanna tacaithe: A0, A1, A2, A3, A4, A5, A6, Legal, Letter, Tabloid, Ledger.", "color_type": "Dath", - "textarea": "Téacs Il-líne" + "textarea": "Téacs Il-líne", + "print_scale": "Agus é á onnmhairiú go PDF, athraítear scála an ábhair rindreáilte. Tá na luachanna idir 0.1 (10%) agus 2 (200%), is é 1 (100%) an réamhshocrú.", + "print_margins": "Agus é á onnmhairiú go PDF, socraítear corrlaigh leathanaigh. Úsáid luachanna réamhshocraithe, gan aon cheann, íosmhéid, nó luachanna saincheaptha mar barr, deas, bun, clé i milliméadair." }, "attribute_editor": { "help_text_body1": "Chun lipéad a chur leis, clóscríobh m.sh. #rock nó más mian leat luach a chur leis freisin ansin m.sh. #year = 2020", @@ -693,7 +695,12 @@ "export_as_image_png": "PNG (rastar)", "export_as_image_svg": "SVG (veicteoir)", "note_map": "Léarscáil nótaí", - "view_ocr_text": "Féach ar théacs OCR" + "view_ocr_text": "Féach ar théacs OCR", + "word_wrap": "Timfhill focal", + "word_wrap_auto": "Uathoibríoch", + "word_wrap_auto_description": "Lean an suíomh domhanda", + "word_wrap_on": "Ar", + "word_wrap_off": "As" }, "onclick_button": { "no_click_handler": "Níl aon láimhseálaí cliceáil sainithe ag an ngiuirléid cnaipe '{{componentId}}'" @@ -1068,15 +1075,17 @@ "title": "Seiceálacha Comhsheasmhachta", "find_and_fix_button": "Fadhbanna comhsheasmhachta a aimsiú agus a shocrú", "finding_and_fixing_message": "Fadhbanna comhsheasmhachta a aimsiú agus a shocrú...", - "issues_fixed_message": "Tá aon fhadhb chomhsheasmhachta a d'fhéadfadh a bheith aimsithe socraithe anois." + "issues_fixed_message": "Tá aon fhadhb chomhsheasmhachta a d'fhéadfadh a bheith aimsithe socraithe anois.", + "find_and_fix_label": "Fadhbanna comhsheasmhachta a aimsiú agus a shocrú", + "find_and_fix_description": "Déan scanadh le haghaidh aon fhadhbanna comhsheasmhachta sonraí sa bhunachar sonraí agus déan iad a dheisiú go huathoibríoch." }, "database_anonymization": { "title": "Anaithnidiú Bunachar Sonraí", - "full_anonymization": "Anaithnidiú Iomlán", - "full_anonymization_description": "Cruthóidh an gníomh seo cóip nua den bhunachar sonraí agus déanfaidh sé anaithnidiú air (bainfear gach ábhar nótaí agus fágfar struchtúr agus roinnt meiteashonraí neamhíogaire amháin) le go mbeidh sé in ann é a roinnt ar líne chun críocha dífhabhtaithe gan eagla go sceithfidh tú do shonraí pearsanta.", + "full_anonymization": "Anaithnidiú iomlán", + "full_anonymization_description": "Cruthaíonn sé cóip den bhunachar sonraí agus gach ábhar nótaí bainte, rud a fhágann struchtúr agus meiteashonraí neamhíogaire amháin. Sábháilte le roinnt ar líne agus fadhbanna dífhabhtaithe á ndífhabhtú.", "save_fully_anonymized_database": "Sábháil bunachar sonraí lán-anaithnid", - "light_anonymization": "Anaithnidiú Éadrom", - "light_anonymization_description": "Cruthóidh an gníomh seo cóip nua den bhunachar sonraí agus déanfaidh sé beagán anaithnidithe air — go sonrach ní bhainfear ach ábhar na nótaí go léir, ach fanfaidh teidil agus tréithe. Ina theannta sin, fanfaidh nótaí scripte tosaigh/cúil JS saincheaptha agus giuirléidí saincheaptha. Soláthraíonn sé seo níos mó comhthéacs chun na fadhbanna a dhífhabhtú.", + "light_anonymization": "Anaithnidiú éadrom", + "light_anonymization_description": "Cruthaíonn sé cóip agus ábhar na nótaí bainte de, ach fanann teidil, tréithe, agus scripteanna/giuirléidí saincheaptha ann. Soláthraíonn sé níos mó comhthéacs le haghaidh dífhabhtaithe.", "choose_anonymization": "Is féidir leat cinneadh a dhéanamh duit féin an mian leat bunachar sonraí atá anaithnid go hiomlán nó beagán gan ainm a sholáthar. Tá fiú bunachar sonraí atá anaithnid go hiomlán an-úsáideach, ach i gcásanna áirithe is féidir le bunachar sonraí atá anaithnid go héadrom an próiseas chun fabhtanna a aithint agus a shocrú a bhrostú.", "save_lightly_anonymized_database": "Sábháil bunachar sonraí atá anaithnidithe go héadrom", "existing_anonymized_databases": "Bunachair shonraí gan ainm atá ann cheana féin", @@ -1085,14 +1094,17 @@ "error_creating_anonymized_database": "Níorbh fhéidir bunachar sonraí gan ainm a chruthú, seiceáil logaí an chúltaca le haghaidh sonraí", "successfully_created_fully_anonymized_database": "Cruthaíodh bunachar sonraí lán-anaithnid i {{anonymizedFilePath}}", "successfully_created_lightly_anonymized_database": "Cruthaíodh bunachar sonraí atá beagán anaithnid i {{anonymizedFilePath}}", - "no_anonymized_database_yet": "Gan aon bhunachar sonraí anaithnidithe go fóill." + "no_anonymized_database_yet": "Gan aon bhunachar sonraí anaithnidithe go fóill.", + "description": "Cruthaigh cóip gan ainm de do bhunachar sonraí le roinnt le forbróirí agus fadhbanna á ndífhabhtú, gan sonraí pearsanta a nochtadh." }, "database_integrity_check": { "title": "Seiceáil Ionracais Bunachar Sonraí", "check_button": "Seiceáil sláine an bhunachair shonraí", "checking_integrity": "Ag seiceáil sláine an bhunachair shonraí...", "integrity_check_succeeded": "D’éirigh leis an tseiceáil ionracais - níor aimsíodh aon fhadhbanna.", - "integrity_check_failed": "Theip ar an tseiceáil ionracais: {{results}}" + "integrity_check_failed": "Theip ar an tseiceáil ionracais: {{results}}", + "check_integrity_label": "Seiceáil sláine an bhunachair shonraí", + "check_integrity_description": "Fíoraigh nach bhfuil an bunachar sonraí truaillithe ar leibhéal SQLite." }, "sync": { "title": "Sioncrónaigh", @@ -1102,14 +1114,20 @@ "filling_entity_changes": "Líonadh sraitheanna athruithe eintiteas...", "sync_rows_filled_successfully": "Líontar na sraitheanna sioncrónaithe go rathúil", "finished-successfully": "Críochnaíodh an sioncrónú go rathúil.", - "failed": "Theip ar an sioncrónú: {{message}}" + "failed": "Theip ar an sioncrónú: {{message}}", + "force_full_sync_label": "Fórsaigh sioncrónú iomlán", + "force_full_sync_description": "Spreag sioncrónú iomlán leis an bhfreastalaí sioncrónaithe, ag ath-uaslódáil na hathruithe go léir.", + "fill_entity_changes_label": "Athruithe eintitis líonta", + "fill_entity_changes_description": "Athchruthaigh taifid athraithe eintitis. Bain úsáid as seo má tá roinnt athruithe ar iarraidh sa sioncrónú." }, "vacuum_database": { "title": "Bunachar Sonraí Folúis", "description": "Déanfaidh sé seo an bunachar sonraí a atógáil agus de ghnáth beidh comhad bunachar sonraí níos lú mar thoradh air. Ní athrófar aon sonraí i ndáiríre.", "button_text": "Bunachar sonraí folúis", "vacuuming_database": "Bunachar sonraí folúsghlanadh...", - "database_vacuumed": "Tá an bunachar sonraí folúsghlanaithe" + "database_vacuumed": "Tá an bunachar sonraí folúsghlanaithe", + "vacuum_label": "Bunachar sonraí folúis", + "vacuum_description": "Athchruthaigh an bunachar sonraí chun méid an chomhaid a laghdú. Ní athrófar aon sonraí." }, "experimental_features": { "title": "Roghanna Turgnamhacha", @@ -1122,13 +1140,13 @@ "fonts": { "theme_defined": "Téama sainmhínithe", "fonts": "Clónna", - "main_font": "Príomhchló", + "main_font": "Téacs comhéadain", "font_family": "Teaghlach clónna", "size": "Méid", - "note_tree_font": "Cló Crann Nótaí", - "note_detail_font": "Cló Sonraí Nóta", - "monospace_font": "Cló Aonspáis (cód)", - "not_all_fonts_available": "B’fhéidir nach bhfuil na clónna uile atá liostaithe ar fáil ar do chóras.", + "note_tree_font": "Téacs crann nótaí", + "note_detail_font": "Téacs an doiciméid", + "monospace_font": "Téacs aonspáis", + "not_all_fonts_available": "B’fhéidir nach bhfuil na clónna uile atá liostaithe ar fáil ar do chóras", "generic-fonts": "Clónna ginearálta", "sans-serif-system-fonts": "Clónna córais Sans-serif", "serif-system-fonts": "Clónna córais Serif", @@ -1137,7 +1155,12 @@ "serif": "Serif", "sans-serif": "Sans Serif", "monospace": "Aonspás", - "system-default": "Réamhshocrú an chórais" + "system-default": "Réamhshocrú an chórais", + "custom_fonts": "Úsáid clónna saincheaptha", + "preview": "Réamhamharc", + "monospace_font_description": "Úsáidte le haghaidh nótaí cóid agus bloic cóid", + "size_relative_to_general": "Tá an méid i gcoibhneas leis an méid cló ginearálta", + "apply_changes": "Athlódáil chun na hathruithe a chur i bhfeidhm" }, "max_content_width": { "title": "Leithead an Ábhair", @@ -1157,28 +1180,31 @@ "edited_notes_message": "Osclófar an cluaisín ribín Nótaí Eagarthóireachta go huathoibríoch ar nótaí lae" }, "theme": { - "title": "Téama an Iarratais", - "theme_label": "Téama", + "title": "Comhéadan Úsáideora", + "theme_label": "Téama an iarratais", "override_theme_fonts_label": "Sáraigh clónna téama", - "auto_theme": "Seanchóras (Lean scéim dathanna an chórais)", - "light_theme": "Oidhreacht (Éadrom)", - "dark_theme": "Oidhreacht (Dorcha)", - "triliumnext": "Trilium (Lean scéim dathanna an chórais)", - "triliumnext-light": "Trilium (Éadrom)", - "triliumnext-dark": "Trilium (Dorcha)", + "auto_theme": "Lean scéim dathanna an chórais", + "light_theme": "Solas", + "dark_theme": "Dorcha", + "triliumnext": "Lean scéim dathanna an chórais", + "triliumnext-light": "Solas", + "triliumnext-dark": "Dorcha", "layout": "Leagan Amach", "layout-vertical-title": "Ingearach", "layout-horizontal-title": "Cothrománach", "layout-vertical-description": "tá barra lainseála ar chlé (réamhshocraithe)", - "layout-horizontal-description": "Tá barra an lainseálaí faoin mbarra cluaisín, tá an barra cluaisín lánleithead anois." + "layout-horizontal-description": "Tá barra an lainseálaí faoin mbarra cluaisín, tá an barra cluaisín lánleithead anois.", + "modern_themes": "Nua-Aimseartha", + "legacy_themes": "Oidhreacht", + "custom_themes": "Saincheaptha" }, "ui-performance": { "title": "Feidhmíocht", - "enable-motion": "Cumasaigh aistrithe agus beochana", - "enable-shadows": "Cumasaigh scáthanna", - "enable-backdrop-effects": "Cumasaigh éifeachtaí cúlra do bhiachláir, fuinneoga aníos agus painéil", - "enable-smooth-scroll": "Cumasaigh scrollú réidh", - "app-restart-required": "(tá atosú an fheidhmchláir ag teastáil chun an t-athrú a chur i bhfeidhm)" + "enable-motion": "Aistrithe agus beochana", + "enable-shadows": "Scáthanna", + "enable-backdrop-effects": "Éifeachtaí cúlra do bhiachláir, fuinneoga aníos agus painéil", + "enable-smooth-scroll": "Scrolláil réidh", + "app-restart-required": "Éilíonn atosú an aip" }, "zoom_factor": { "title": "Fachtóir Súmáil (leagan deisce amháin)", @@ -1187,11 +1213,13 @@ "code_auto_read_only_size": { "title": "Méid Uathoibríoch Léite Amháin", "description": "Is é méid uathoibríoch nótaí inléite amháin an méid tar éis a dtaispeánfar nótaí i mód inléite amháin (ar chúiseanna feidhmíochta).", - "label": "Méid inléite amháin uathoibríoch (nótaí cóid)", + "label": "Méid inléite amháin uathoibríoch", "unit": "carachtair" }, "code-editor-options": { - "title": "Eagarthóir" + "title": "Eagarthóir", + "tab_width": "Leithead an chluaisín", + "tab_width_unit": "spásanna" }, "code_mime_types": { "title": "Cineálacha MIME atá ar fáil sa roghchlár anuas", @@ -1233,59 +1261,70 @@ "batch_ocr_error": "Earráid le linn próiseála baisce: {{error}}" }, "attachment_erasure_timeout": { - "attachment_erasure_timeout": "Am Teorann Scriosadh Ceangaltáin", - "erase_attachments_after": "Scrios ceangaltáin neamhúsáidte tar éis:", - "manual_erasing_description": "Is féidir leat scriosadh a spreagadh de láimh freisin (gan an t-am críochnaithe a shainmhínítear thuas a chur san áireamh):", - "erase_unused_attachments_now": "Scrios nótaí ceangaltáin neamhúsáidte anois", - "unused_attachments_erased": "Scriosadh ceangaltáin neamhúsáidte." + "attachment_erasure_timeout": "Ceangaltáin Neamhúsáidte", + "erase_attachments_after": "Scrios ceangaltáin neamhúsáidte ina dhiaidh sin", + "manual_erasing_description": "Spreag scriosadh de láimh, ag neamhaird den am scoir thuas.", + "erase_unused_attachments_now": "Scrios ceangaltáin neamhúsáidte anois", + "unused_attachments_erased": "Scriosadh ceangaltáin neamhúsáidte.", + "description": "Meastar nach n-úsáidtear ceangaltáin nach ndéantar tagairt dóibh a thuilleadh in aon nóta agus is féidir iad a scriosadh go huathoibríoch tar éis tréimhse ama.", + "erase_attachments_after_description": "Am sula scriostar ceangaltáin neamhúsáidte go buan." }, "network_connections": { - "network_connections_title": "Naisc Líonra", - "check_for_updates": "Seiceáil le haghaidh nuashonruithe go huathoibríoch" + "network_connections_title": "Líonra", + "check_for_updates": "Seiceáil le haghaidh nuashonruithe go huathoibríoch", + "check_for_updates_description": "Seiceálann sé le haghaidh leaganacha nua ar GitHub agus taispeánann sé fógra sa roghchlár domhanda nuair a bhíonn sé ar fáil." }, "note_erasure_timeout": { - "note_erasure_timeout_title": "Am Scriosadh Nótaí", - "erase_notes_after": "Scrios nótaí tar éis:", - "manual_erasing_description": "Is féidir leat scriosadh a spreagadh de láimh freisin (gan an t-am críochnaithe a shainmhínítear thuas a chur san áireamh):", + "note_erasure_timeout_title": "Nótaí Scriosta", + "erase_notes_after": "Scrios nótaí ina dhiaidh", + "manual_erasing_description": "Spreag scriosadh de láimh, ag neamhaird den am scoir thuas.", "erase_deleted_notes_now": "Scrios nótaí scriosta anois", - "deleted_notes_erased": "Tá nótaí scriosta scriosta." + "deleted_notes_erased": "Tá nótaí scriosta scriosta.", + "description": "Ní dhéantar nótaí scriosta a mharcáil ach mar scriosta ar dtús agus is féidir iad a aisghabháil ó Nótaí Le Déanaí. Tar éis tamaill, scriostar go buan iad.", + "erase_notes_after_description": "An t-am sula scriostar nótaí scriosta go buan." }, "revisions_snapshot_interval": { "note_revisions_snapshot_interval_title": "Eatramh Léirmheasa ar Nóta", "note_revisions_snapshot_description": "Is é an t-eatramh pictiúr athbhreithnithe nóta an t-am ina dhiaidh a chruthófar athbhreithniú nóta nua don nóta. Féach vicí le haghaidh tuilleadh eolais.", - "snapshot_time_interval_label": "Eatramh ama pictiúr athbhreithnithe nóta:" + "snapshot_time_interval_label": "Eatramh pictiúr", + "note_revisions_snapshot_description_short": "An t-am a gcruthófar athbhreithniú nóta nua ina dhiaidh." }, "revisions_snapshot_limit": { "note_revisions_snapshot_limit_title": "Teorainn ar Ghrianghraf Athbhreithnithe Nóta", "note_revisions_snapshot_limit_description": "Tagraíonn an teorainn ar líon na n-athbhreithnithe nótaí don líon uasta athbhreithnithe is féidir a shábháil do gach nóta. Ciallaíonn -1 gan aon teorainn, ciallaíonn 0 scriosadh na hathbhreithnithe go léir. Is féidir leat an líon uasta athbhreithnithe a shocrú do nóta aonair tríd an lipéad #versioningLimit.", - "snapshot_number_limit_label": "Teorainn líon na n-íomhánna athbhreithnithe nóta:", + "snapshot_number_limit_label": "Uasmhéid athbhreithnithe", "snapshot_number_limit_unit": "léargais", "erase_excess_revision_snapshots": "Scrios na léargais athbhreithnithe breise anois", - "erase_excess_revision_snapshots_prompt": "Scriosadh na léargais bhreise athbhreithnithe." + "erase_excess_revision_snapshots_prompt": "Scriosadh na léargais bhreise athbhreithnithe.", + "note_revisions_snapshot_limit_description_short": "Uasmhéid athbhreithnithe in aghaidh an nóta. Úsáid -1 le haghaidh neamhtheoranta, 0 le díchumasú.", + "erase_excess_revision_snapshots_description": "Scrios athbhreithnithe a sháraíonn an teorainn do na nótaí uile." }, "search_engine": { "title": "Inneall Cuardaigh", - "custom_search_engine_info": "Éilíonn inneall cuardaigh saincheaptha go socrófar ainm agus URL araon. Mura socraítear ceachtar acu seo, úsáidfear DuckDuckGo mar an t-inneall cuardaigh réamhshocraithe.", - "predefined_templates_label": "Teimpléid inneall cuardaigh réamhshainithe", + "custom_search_engine_info": "Úsáidtear é seo agus téacs roghnaithe á chuardach ar an ngréasán. Mura bhfuil sé cumraithe, úsáidfear DuckDuckGo.", + "predefined_templates_label": "Réamhshocruithe", "bing": "Bing", "baidu": "Baidu", "duckduckgo": "DuckDuckGo", "google": "Google", - "custom_name_label": "Ainm innill chuardaigh saincheaptha", - "custom_name_placeholder": "Saincheap ainm an innill chuardaigh", - "custom_url_label": "Ba chóir go mbeadh {keyword} san áireamh mar áitchoinneálaí don téarma cuardaigh i URL inneall cuardaigh saincheaptha.", - "custom_url_placeholder": "Saincheap URL an innill chuardaigh", - "save_button": "Sábháil" + "custom_name_label": "Ainm", + "custom_name_placeholder": "Ainm an innill chuardaigh", + "custom_url_label": "URL", + "custom_url_placeholder": "URL inneall cuardaigh", + "save_button": "Sábháil", + "custom_url_description": "Úsáid {keyword} mar áitchoinneálaí don téarma cuardaigh." }, "tray": { "title": "Tráidire an Chórais", - "enable_tray": "Cumasaigh an tráidire (ní mór Trilium a atosú le go dtiocfaidh an t-athrú seo i bhfeidhm)" + "enable_tray": "Deilbhín tráidire", + "enable_tray_description": "Caithfear Trilium a atosú chun go dtiocfaidh an t-athrú seo i bhfeidhm." }, "heading_style": { - "title": "Stíl Ceannteidil", + "title": "Stíl ceannteidil", "plain": "Simplí", "underline": "Folínigh", - "markdown": "Stíl marcála síos" + "markdown": "Stíl marcála síos", + "description": "Stíl amhairc do cheannteidil i nótaí téacs." }, "highlights_list": { "title": "Liosta Buaicphointí", @@ -1309,14 +1348,16 @@ "text_auto_read_only_size": { "title": "Méid Uathoibríoch Léite Amháin", "description": "Is é méid uathoibríoch nótaí inléite amháin an méid tar éis a dtaispeánfar nótaí i mód inléite amháin (ar chúiseanna feidhmíochta).", - "label": "Méid inléite amháin uathoibríoch (nótaí téacs)", + "label": "Méid inléite amháin uathoibríoch", "unit": "carachtair" }, "custom_date_time_format": { - "title": "Formáid Dáta/Am Saincheaptha", + "title": "Formáid dáta/ama", "description": "Saincheap formáid an dáta agus an ama a chuirtear isteach trí nó an barra uirlisí. Féach ar doiciméid Day.js le haghaidh na gcomharthaí formáide atá ar fáil.", - "format_string": "Formáid teaghrán:", - "formatted_time": "Dáta/am formáidithe:" + "format_string": "Formáid teaghrán", + "formatted_time": "Dáta/am formáidithe", + "description_short": "Saincheap formáid an dáta agus an ama a chuirtear isteach tríd an mbarra uirlisí.", + "preview": "Réamhamharc: {{preview}}" }, "i18n": { "title": "Logánú", @@ -1331,19 +1372,19 @@ "sunday": "Dé Domhnaigh", "first-week-of-the-year": "An chéad seachtain den bhliain", "first-week-contains-first-day": "Tá an chéad lá den bhliain sa chéad seachtain", - "first-week-contains-first-thursday": "Tá an chéad Déardaoin den bhliain sa chéad seachtain", + "first-week-contains-first-thursday": "Tá an chéad Déardaoin sa chéad seachtain (ISO 8601)", "first-week-has-minimum-days": "Tá an chéad seachtain ag an íosmhéid laethanta", "min-days-in-first-week": "Íosmhéid laethanta sa chéad seachtain", - "first-week-warning": "D’fhéadfadh sé go mbeadh dúblach le Nótaí Seachtaine atá ann cheana féin mar thoradh ar athrú roghanna na chéad seachtaine agus ní dhéanfar na Nótaí Seachtaine atá ann cheana a nuashonrú dá réir.", + "first-week-warning": "D’fhéadfadh sé go mbeadh dúblaigh le Nótaí Seachtaine atá ann cheana féin mar thoradh ar athrú seo.", "formatting-locale": "Formáid dáta agus uimhreach", "formatting-locale-auto": "Bunaithe ar theanga an fheidhmchláir" }, "backup": { "automatic_backup": "Cúltaca uathoibríoch", "automatic_backup_description": "Is féidir le Trilium cúltaca den bhunachar sonraí a dhéanamh go huathoibríoch:", - "enable_daily_backup": "Cumasaigh cúltaca laethúil", - "enable_weekly_backup": "Cumasaigh cúltaca seachtainiúil", - "enable_monthly_backup": "Cumasaigh cúltaca míosúil", + "enable_daily_backup": "Cúltaca laethúil", + "enable_weekly_backup": "Cúltaca seachtainiúil", + "enable_monthly_backup": "Cúltaca míosúil", "backup_recommendation": "Moltar an cúltaca a choinneáil casta air, ach is féidir leis seo moill a chur ar thosú feidhmchlár le bunachair shonraí móra agus/nó gléasanna stórála mall.", "backup_now": "Cúltaca anois", "backup_database_now": "Cúltaca bunachar sonraí anois", @@ -1352,7 +1393,8 @@ "path": "Cosán", "database_backed_up_to": "Tá cúltaca déanta den bhunachar sonraí chuig {{backupFilePath}}", "no_backup_yet": "gan aon chúltaca fós", - "download": "Íoslódáil" + "download": "Íoslódáil", + "title": "Cúltaca" }, "etapi": { "title": "ETAPI", @@ -1387,18 +1429,22 @@ "new_password": "Pasfhocal nua", "new_password_confirmation": "Deimhniú pasfhocail nua", "change_password": "Athraigh an focal faire", - "protected_session_timeout": "Am Teorann Seisiúin Chosanta", - "protected_session_timeout_description": "Is tréimhse ama í an t-am scoir seisiúin chosanta a scriostar an seisiún cosanta ó chuimhne an bhrabhsálaí ina dhiaidh. Déantar é seo a thomhas ón idirghníomhaíocht dheireanach le nótaí cosanta. Féach", + "protected_session_timeout": "Seisiún faoi Chosaint", + "protected_session_timeout_description": "Am neamhghníomhaíochta sula nglanfar an seisiún ó chuimhne an bhrabhsálaí. Féach", "wiki": "vicí", "for_more_info": "le haghaidh tuilleadh eolais.", - "protected_session_timeout_label": "Am scoir seisiúin faoi chosaint:", + "protected_session_timeout_label": "Dún seisiún go huathoibríoch ina dhiaidh sin", "reset_confirmation": "Trí an focal faire a athshocrú caillfidh tú rochtain go deo ar do nótaí cosanta go léir atá ann cheana féin. An bhfuil tú cinnte gur mhaith leat an focal faire a athshocrú?", "reset_success_message": "Athshocraíodh an focal faire. Socraigh focal faire nua le do thoil", "change_password_heading": "Athraigh Pasfhocal", "set_password_heading": "Socraigh Pasfhocal", "set_password": "Socraigh Pasfhocal", "password_mismatch": "Ní hionann pasfhocail nua.", - "password_changed_success": "Athraíodh an focal faire. Athlódálfar Trilium tar éis duit brúigh OK." + "password_changed_success": "Athraíodh an focal faire. Athlódálfar Trilium tar éis duit brúigh OK.", + "change_password_description": "Nuashonraigh do phasfhocal reatha", + "reset_password": "Athshocraigh an focal faire", + "reset_password_description": "Caill rochtain ar nótaí faoi chosaint go buan", + "cancel": "Cealaigh" }, "multi_factor_authentication": { "title": "Fíordheimhniú Ilfhachtóireach", @@ -1461,17 +1507,19 @@ "related_description": "Cumraigh teangacha seiceála litrithe agus foclóir saincheaptha." }, "sync_2": { - "config_title": "Cumraíocht Sioncrónaithe", - "server_address": "Seoladh sampla an fhreastalaí", - "timeout": "Am scoir sioncrónaithe", - "proxy_label": "Sioncrónaigh freastalaí seachfhreastalaí (roghnach)", + "config_title": "Freastalaí Sioncrónaithe", + "server_address": "Seoladh an fhreastalaí", + "timeout": "Am críochnaithe nasc", + "proxy_label": "Freastalaí seachfhreastalaí", "save": "Sábháil", "help": "Cabhair", - "test_title": "Tástáil Sioncrónaithe", - "test_description": "Déanfaidh sé seo tástáil ar an nasc agus ar an gcroitheadh láimhe leis an bhfreastalaí sioncrónaithe. Mura bhfuil an freastalaí sioncrónaithe tosaithe, socróidh sé seo é chun sioncrónú leis an doiciméad áitiúil.", + "test_title": "Tástáil Ceangal", + "test_description": "Déan tástáil ar an nasc leis an bhfreastalaí sioncrónaithe. Mura ndéantar é a thosú, socróidh sé seo sioncrónú.", "test_button": "Tástáil sioncrónaithe", "handshake_failed": "Theip ar chroitheadh láimhe an fhreastalaí sioncrónaithe, earráid: {{message}}", - "timeout_description": "Cé chomh fada is ceart fanacht sula dtugann tú suas ar nasc sioncrónaithe mall. Méadaigh an méid ama má tá líonra éagobhsaí agat." + "timeout_description": "Am fanacht sula dtugann tú suas ar nasc mall.", + "server_address_description": "URL an fhreastalaí Trilium le sioncrónú leis.", + "proxy_description": "Fág bán chun seachfhreastalaí córais a úsáid (deasc amháin). Bain úsáid as \"noproxy\" chun na seachfhreastalaithe go léir a sheachaint." }, "api_log": { "close": "Dún" @@ -1657,7 +1705,7 @@ "note_detail": { "could_not_find_typewidget": "Níorbh fhéidir typeWidget a aimsiú don chineál '{{type}}'", "printing": "Priontáil ar siúl...", - "printing_pdf": "Ag easpórtáil go PDF ar siúl...", + "printing_pdf": "Réamhamharc priontála á ullmhú...", "print_report_title": "Tuarascáil a phriontáil", "print_report_collection_content_one": "Níorbh fhéidir nóta {{count}} sa bhailiúchán a phriontáil mar nach dtacaítear leo nó mar go bhfuil siad faoi chosaint.", "print_report_collection_content_two": "Níorbh fhéidir {{count}} nótaí sa bhailiúchán a phriontáil mar nach dtacaítear leo nó mar go bhfuil siad faoi chosaint.", @@ -1786,7 +1834,9 @@ "theme_group_light": "Téamaí éadroma", "theme_group_dark": "Téamaí dorcha", "copy_title": "Cóipeáil chuig an ghearrthaisce", - "click_to_copy": "Cliceáil chun cóipeáil" + "click_to_copy": "Cliceáil chun cóipeáil", + "tab_width": "Leithead an chluaisín", + "tab_width_unit": "spásanna" }, "classic_editor_toolbar": { "title": "Formáidiú" @@ -1805,7 +1855,8 @@ "title": "Seasta", "description": "Feictear uirlisí eagarthóireachta sa chluaisín ribín \"Formáidiú\"." }, - "multiline-toolbar": "Taispeáin an barra uirlisí ar illínte mura n-oireann sé." + "multiline-toolbar": "Taispeáin an barra uirlisí ar illínte mura n-oireann sé", + "toolbar_style": "Stíl an bharra uirlisí" } }, "electron_context_menu": { @@ -1872,7 +1923,7 @@ "days": "Laethanta" }, "share": { - "title": "Socruithe Comhroinnte", + "title": "Comhroinn", "redirect_bare_domain": "Atreoraigh fearann lom chuig an leathanach Comhroinnte", "redirect_bare_domain_description": "Atreoraigh úsáideoirí gan ainm chuig an leathanach Comhroinnte in ionad Logáil Isteach a thaispeáint", "show_login_link": "Taispeáin nasc Logála Isteach sa téama Comhroinnte", @@ -1936,12 +1987,12 @@ }, "editorfeatures": { "title": "Gnéithe", - "emoji_completion_enabled": "Cumasaigh uath-chomhlánú Emoji", - "emoji_completion_description": "Más cumasaithe é, is féidir emojis a chur isteach i dtéacs go héasca trí `:` a chlóscríobh, agus ainm emoji ina dhiaidh sin.", - "note_completion_enabled": "Cumasaigh uath-chríochnú nótaí", - "note_completion_description": "Más cumasaithe é, is féidir naisc chuig nótaí a chruthú trí `@` a chlóscríobh agus teideal an nóta ina dhiaidh sin.", - "slash_commands_enabled": "Cumasaigh orduithe slaise", - "slash_commands_description": "Más cumasaithe é, is féidir orduithe eagarthóireachta amhail briseadh líne nó ceannteidil a chur isteach a athrú trí `/` a chlóscríobh." + "emoji_completion_enabled": "Uath-chomhlánú emoji", + "emoji_completion_description": "Uath-líonadh emoji Is féidir emojis a chur isteach i dtéacs go héasca trí `:` a chlóscríobh, agus ainm emoji ina dhiaidh sin.", + "note_completion_enabled": "Uath-chomhlánú nótaí", + "note_completion_description": "Is féidir naisc chuig nótaí a chruthú trí `@` a chlóscríobh agus teideal an nóta ina dhiaidh sin.", + "slash_commands_enabled": "Orduithe slaise", + "slash_commands_description": "Is féidir orduithe eagarthóireachta amhail briseadh líne nó ceannteidil a chur isteach a athrú trí `/` a chlóscríobh." }, "table_view": { "new-row": "Sraith nua", @@ -2045,7 +2096,9 @@ "related_code_notes": "Scéim dathanna le haghaidh nótaí cóid", "ui": "Comhéadan úsáideora", "ui_old_layout": "Leagan amach sean", - "ui_new_layout": "Leagan amach nua" + "ui_new_layout": "Leagan amach nua", + "ui_layout_style": "Stíl leagan amach", + "ui_layout_orientation": "Treoshuíomh an bharra lainseálaí" }, "units": { "percentage": "%" @@ -2144,7 +2197,19 @@ "note_paths_many": "{{count}} cosáin", "note_paths_other": "{{count}} cosáin", "note_paths_title": "Cosáin nótaí", - "code_note_switcher": "Athraigh mód teanga" + "code_note_switcher": "Athraigh mód teanga", + "tab_width": "Leithead an Chluaisín: {{width}}", + "tab_width_title": "Athraigh leithead an chluaisín", + "tab_width_spaces": "{{count}} spásanna", + "tab_width_spaces_short": "Spásanna: {{width}}", + "tab_width_tabs": "Cluaisíní: {{width}}", + "tab_width_use_default": "Úsáid an réamhshocrú ({{width}})", + "tab_width_use_default_style": "Úsáid réamhshocraithe ({{style}})", + "tab_width_display_header": "Leithead taispeána", + "tab_width_reindent_header": "Ath-eangaigh ábhar go", + "tab_width_style_header": "Líon isteach ag baint úsáide as", + "tab_width_style_spaces": "Spásanna", + "tab_width_style_tabs": "Cluaisíní" }, "attributes_panel": { "title": "Tréithe Nóta" @@ -2398,5 +2463,55 @@ "processing_complete": "Próiseáil OCR críochnaithe.", "text_filtered_low_confidence": "Bhraith OCR téacs le muinín {{confidence}}%, ach caitheadh leis é mar is é {{threshold}}% an tairseach íosta atá agat.", "open_media_settings": "Oscail Socruithe" + }, + "revisions": { + "title": "Athbhreithnithe Nótaí" + }, + "database": { + "title": "Bunachar Sonraí" + }, + "search": { + "title": "Cuardaigh", + "fuzzy_matching_label": "Caoinfhulaingt clóscríofa sa chuardach", + "fuzzy_matching_description": "Bíonn tionchar aige ar chuardach tapa agus ar chuardach iomlán. Faightear focail chomhchosúla nuair nach leor na meaitseáil chruinne.", + "autocomplete_fuzzy_label": "Caoinfhulaingt clóscríofa in uathchríochnú", + "autocomplete_fuzzy_description": "Bíonn tionchar aige ar léim-go-nóta agus ar roghnóirí nótaí. Níos moille ach glactar le clóscríobh." + }, + "text_editor": { + "title": "Eagarthóir" + }, + "link": { + "failed_to_open": "Theip ar oscailt an nasc '{{- href}}': {{- message}}" + }, + "print_preview": { + "title": "Réamhamharc priontála", + "close": "Dún", + "save": "Sábháil mar PDF", + "print": "Priontáil", + "export_pdf": "Easpórtáil mar PDF", + "system_print": "Priontáil ag baint úsáide as dialóg an chórais", + "destination": "Ceann Scríbe", + "destination_pdf": "Sábháil mar PDF", + "destination_printers": "Printéirí", + "destination_default": "Réamhshocrú", + "orientation": "Treoshuíomh", + "portrait": "Portráid", + "landscape": "Tírdhreach", + "page_size": "Méid leathanaigh", + "scale": "Scála", + "margins": "Imill", + "render_error": "Ní féidir PDF a rindreáil leis na socruithe reatha. Seiceáil na corrlaigh agus an scála le do thoil.", + "margins_default": "Réamhshocrú", + "margins_none": "Dada", + "margins_minimum": "Íosmhéid", + "margins_custom": "Saincheaptha", + "margin_top": "Barr", + "margin_right": "Ar dheis", + "margin_bottom": "Bun", + "margin_left": "Ar chlé", + "page_ranges": "Leathanaigh", + "page_ranges_hint": "Fág folamh chun na leathanaigh go léir a phriontáil.", + "page_ranges_invalid": "Formáid neamhbhailí. Úsáid m.sh. 1-5, 8, 11-13.", + "page_ranges_placeholder": "m.sh. 1-5, 8, 11-13" } } From c8888261925195101387099094b1e7ca9b196823 Mon Sep 17 00:00:00 2001 From: Zaki Ur Rehman Date: Thu, 16 Apr 2026 18:06:14 +0500 Subject: [PATCH 249/482] fex: UI overlap in attribute editing --- .../ribbon/components/AttributeEditor.tsx | 495 +++++++++++------- 1 file changed, 315 insertions(+), 180 deletions(-) diff --git a/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx b/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx index edae4f014f..2c694c4e70 100644 --- a/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx +++ b/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx @@ -1,19 +1,39 @@ -import { AttributeEditor as CKEditorAttributeEditor, MentionFeed, ModelElement, ModelNode, ModelPosition } from "@triliumnext/ckeditor5"; +import { + AttributeEditor as CKEditorAttributeEditor, + MentionFeed, + ModelElement, + ModelNode, + ModelPosition, +} from "@triliumnext/ckeditor5"; import { AttributeType } from "@triliumnext/commons"; import { createPortal } from "preact/compat"; -import { MutableRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from "preact/hooks"; +import { + MutableRef, + useEffect, + useImperativeHandle, + useMemo, + useRef, + useState, +} from "preact/hooks"; -import type { CommandData, FilteredCommandNames } from "../../../components/app_context"; +import type { + CommandData, + FilteredCommandNames, +} from "../../../components/app_context"; import FAttribute from "../../../entities/fattribute"; import FNote from "../../../entities/fnote"; import contextMenu from "../../../menus/context_menu"; -import attribute_parser, { Attribute } from "../../../services/attribute_parser"; +import attribute_parser, { + Attribute, +} from "../../../services/attribute_parser"; import attribute_renderer from "../../../services/attribute_renderer"; import attributes from "../../../services/attributes"; import froca from "../../../services/froca"; import { t } from "../../../services/i18n"; import link from "../../../services/link"; -import note_autocomplete, { Suggestion } from "../../../services/note_autocomplete"; +import note_autocomplete, { + Suggestion, +} from "../../../services/note_autocomplete"; import note_create from "../../../services/note_create"; import server from "../../../services/server"; import { isIMEComposing } from "../../../services/shortcuts"; @@ -21,7 +41,13 @@ import { escapeQuotes, getErrorMessage } from "../../../services/utils"; import AttributeDetailWidget from "../../attribute_widgets/attribute_detail"; import ActionButton from "../../react/ActionButton"; import CKEditor, { CKEditorApi } from "../../react/CKEditor"; -import { useLegacyImperativeHandlers, useLegacyWidget, useTooltip, useTriliumEvent, useTriliumOption } from "../../react/hooks"; +import { + useLegacyImperativeHandlers, + useLegacyWidget, + useTooltip, + useTriliumEvent, + useTriliumOption, +} from "../../react/hooks"; type AttributeCommandNames = FilteredCommandNames; @@ -35,7 +61,8 @@ const HELP_TEXT = ` const mentionSetup: MentionFeed[] = [ { marker: "@", - feed: (queryText) => note_autocomplete.autocompleteSourceForCKEditor(queryText), + feed: (queryText) => + note_autocomplete.autocompleteSourceForCKEditor(queryText), itemRenderer: (_item) => { const item = _item as Suggestion; const itemElement = document.createElement("button"); @@ -44,39 +71,42 @@ const mentionSetup: MentionFeed[] = [ return itemElement; }, - minimumCharacters: 0 + minimumCharacters: 0, }, { marker: "#", feed: async (queryText) => { - const names = await server.get(`attribute-names/?type=label&query=${encodeURIComponent(queryText)}`); + const names = await server.get( + `attribute-names/?type=label&query=${encodeURIComponent(queryText)}`, + ); return names.map((name) => { return { id: `#${name}`, - name + name, }; }); }, - minimumCharacters: 0 + minimumCharacters: 0, }, { marker: "~", feed: async (queryText) => { - const names = await server.get(`attribute-names/?type=relation&query=${encodeURIComponent(queryText)}`); + const names = await server.get( + `attribute-names/?type=relation&query=${encodeURIComponent(queryText)}`, + ); return names.map((name) => { return { id: `~${name}`, - name + name, }; }); }, - minimumCharacters: 0 - } + minimumCharacters: 0, + }, ]; - interface AttributeEditorProps { api: MutableRef; note: FNote; @@ -93,27 +123,38 @@ export interface AttributeEditorImperativeHandlers { renderOwnedAttributes(ownedAttributes: FAttribute[]): Promise; } -export default function AttributeEditor({ api, note, componentId, notePath, ntxId, hidden }: AttributeEditorProps) { - const [ currentValue, setCurrentValue ] = useState(""); - const [ state, setState ] = useState<"normal" | "showHelpTooltip" | "showAttributeDetail">(); - const [ error, setError ] = useState(); - const [ needsSaving, setNeedsSaving ] = useState(false); - +export default function AttributeEditor({ + api, + note, + componentId, + notePath, + ntxId, + hidden, +}: AttributeEditorProps) { + const [currentValue, setCurrentValue] = useState(""); + const [state, setState] = useState< + "normal" | "showHelpTooltip" | "showAttributeDetail" + >(); + const [error, setError] = useState(); + const [needsSaving, setNeedsSaving] = useState(false); + const [isMenuOpen, setIsMenuOpen] = useState(false); const lastSavedContent = useRef(); const currentValueRef = useRef(currentValue); const wrapperRef = useRef(null); const editorRef = useRef(); - const [ locale ] = useTriliumOption("locale"); + const [locale] = useTriliumOption("locale"); const { showTooltip, hideTooltip } = useTooltip(wrapperRef, { trigger: "focus", html: true, title: HELP_TEXT, placement: "bottom", - offset: "0,30" + offset: "0,30", }); - const [ attributeDetailWidgetEl, attributeDetailWidget ] = useLegacyWidget(() => new AttributeDetailWidget()); + const [attributeDetailWidgetEl, attributeDetailWidget] = useLegacyWidget( + () => new AttributeDetailWidget(), + ); useEffect(() => { if (state === "showHelpTooltip") { @@ -121,13 +162,16 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI } else { hideTooltip(); } - }, [ state ]); + }, [state]); - async function renderOwnedAttributes(ownedAttributes: FAttribute[], saved: boolean) { + async function renderOwnedAttributes( + ownedAttributes: FAttribute[], + saved: boolean, + ) { // attrs are not resorted if position changes after the initial load ownedAttributes.sort((a, b) => a.position - b.position); - let htmlAttrs = (`

${(await attribute_renderer.renderAttributes(ownedAttributes, true)).html()}

`); + let htmlAttrs = `

${(await attribute_renderer.renderAttributes(ownedAttributes, true)).html()}

`; if (saved) { lastSavedContent.current = htmlAttrs; @@ -144,7 +188,9 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI function parseAttributes() { try { - return attribute_parser.lexAndParse(getPreprocessedData(currentValueRef.current)); + return attribute_parser.lexAndParse( + getPreprocessedData(currentValueRef.current), + ); } catch (e: unknown) { setError(e); } @@ -157,7 +203,11 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI return; } - await server.put(`notes/${note.noteId}/attributes`, attributes, componentId); + await server.put( + `notes/${note.noteId}/attributes`, + attributes, + componentId, + ); setNeedsSaving(false); // blink the attribute text to give a visual hint that save has been executed @@ -171,7 +221,9 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI } } - async function handleAddNewAttributeCommand(command: AttributeCommandNames | undefined) { + async function handleAddNewAttributeCommand( + command: AttributeCommandNames | undefined, + ) { // TODO: Not sure what the relation between FAttribute[] and Attribute[] is. const attrs = parseAttributes() as FAttribute[]; @@ -208,7 +260,7 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI type, name, value, - isInheritable: false + isInheritable: false, }); await renderOwnedAttributes(attrs, false); @@ -224,7 +276,7 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI isOwned: true, x: rect ? (rect.left + rect.right) / 2 : 0, y: rect?.bottom ?? 0, - focus: "name" + focus: "name", }); }, 100); } @@ -234,34 +286,51 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI renderOwnedAttributes(note.getOwnedAttributes(), true); } - useEffect(() => refresh(), [ note ]); + useEffect(() => refresh(), [note]); useTriliumEvent("entitiesReloaded", ({ loadResults }) => { - if (loadResults.getAttributeRows(componentId).find((attr) => attributes.isAffecting(attr, note))) { + if ( + loadResults + .getAttributeRows(componentId) + .find((attr) => attributes.isAffecting(attr, note)) + ) { refresh(); } }); // Interaction with CKEditor. - useLegacyImperativeHandlers(useMemo(() => ({ - loadReferenceLinkTitle: async ($el: JQuery, href: string) => { - const { noteId } = link.parseNavigationStateFromUrl(href); - const note = noteId ? await froca.getNote(noteId, true) : null; - const title = note ? note.title : "[missing]"; + useLegacyImperativeHandlers( + useMemo( + () => ({ + loadReferenceLinkTitle: async ( + $el: JQuery, + href: string, + ) => { + const { noteId } = link.parseNavigationStateFromUrl(href); + const note = noteId + ? await froca.getNote(noteId, true) + : null; + const title = note ? note.title : "[missing]"; - $el.text(title); - }, - createNoteForReferenceLink: async (title: string) => { - let result; - if (notePath) { - result = await note_create.createNoteWithTypePrompt(notePath, { - activate: false, - title - }); - } + $el.text(title); + }, + createNoteForReferenceLink: async (title: string) => { + let result; + if (notePath) { + result = await note_create.createNoteWithTypePrompt( + notePath, + { + activate: false, + title, + }, + ); + } - return result?.note?.getBestNotePathString(); - } - }), [ notePath ])); + return result?.note?.getBestNotePathString(); + }, + }), + [notePath], + ), + ); // Keyboard shortcuts useTriliumEvent("addNewLabel", ({ ntxId: eventNtxId }) => { @@ -274,140 +343,206 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI }); // Imperative API - useImperativeHandle(api, () => ({ - save, - refresh, - renderOwnedAttributes: (attributes) => renderOwnedAttributes(attributes as FAttribute[], false), - focus: () => editorRef.current?.focus() - }), [ save, refresh, renderOwnedAttributes ]); + useImperativeHandle( + api, + () => ({ + save, + refresh, + renderOwnedAttributes: (attributes) => + renderOwnedAttributes(attributes as FAttribute[], false), + focus: () => editorRef.current?.focus(), + }), + [save, refresh, renderOwnedAttributes], + ); return ( <> - {!hidden &&
{ - // Skip processing during IME composition - if (isIMEComposing(e)) { - return; - } + {!hidden && ( +
{ + // Skip processing during IME composition + if (isIMEComposing(e)) { + return; + } - if (e.key === "Enter") { - // allow autocomplete to fill the result textarea - setTimeout(() => save(), 100); - } - }} - >
- { - currentValueRef.current = currentValue ?? ""; - - const oldValue = getPreprocessedData(lastSavedContent.current ?? "").trimEnd(); - const newValue = getPreprocessedData(currentValue ?? "").trimEnd(); - setNeedsSaving(oldValue !== newValue); - setError(undefined); - }} - onClick={(e, pos) => { - if (pos && pos.textNode && pos.textNode.data) { - const clickIndex = getClickIndex(pos); - - let parsedAttrs: Attribute[]; - - try { - parsedAttrs = attribute_parser.lexAndParse(getPreprocessedData(currentValueRef.current), true); - } catch (e: unknown) { - // the input is incorrect because the user messed up with it and now needs to fix it manually - console.log(e); - return null; - } - - let matchedAttr: Attribute | null = null; - - for (const attr of parsedAttrs) { - if (attr.startIndex !== undefined && clickIndex > attr.startIndex && - attr.endIndex !== undefined && clickIndex <= attr.endIndex) { - matchedAttr = attr; - break; - } - } - - setTimeout(() => { - if (matchedAttr) { - attributeDetailWidget.showAttributeDetail({ - allAttributes: parsedAttrs, - attribute: matchedAttr, - isOwned: true, - x: e.pageX, - y: e.pageY - }); - setState("showAttributeDetail"); - } else { - setState("showHelpTooltip"); - } - }, 100); - } else { - setState("showHelpTooltip"); - } - }} - onKeyDown={() => attributeDetailWidget.hide()} - onBlur={() => save()} - onInitialized={() => editorRef.current?.focus()} - disableNewlines disableSpellcheck - /> - -
- { needsSaving && } - - { - // Prevent automatic hiding of the context menu due to the button being clicked. - e.stopPropagation(); - - contextMenu.show({ - x: e.pageX, - y: e.pageY, - orientation: "left", - items: [ - { title: t("attribute_editor.add_new_label"), command: "addNewLabel", uiIcon: "bx bx-hash" }, - { title: t("attribute_editor.add_new_relation"), command: "addNewRelation", uiIcon: "bx bx-transfer" }, - { kind: "separator" }, - { title: t("attribute_editor.add_new_label_definition"), command: "addNewLabelDefinition", uiIcon: "bx bx-empty" }, - { title: t("attribute_editor.add_new_relation_definition"), command: "addNewRelationDefinition", uiIcon: "bx bx-empty" } - ], - selectMenuItemHandler: (item) => handleAddNewAttributeCommand(item.command) - }); + if (e.key === "Enter") { + // allow autocomplete to fill the result textarea + setTimeout(() => save(), 100); + } + }} + > + {" "} +
+ -
-
+ onChange={(currentValue) => { + currentValueRef.current = currentValue ?? ""; - { error && ( -
- {getErrorMessage(error)} + const oldValue = getPreprocessedData( + lastSavedContent.current ?? "", + ).trimEnd(); + const newValue = getPreprocessedData( + currentValue ?? "", + ).trimEnd(); + setNeedsSaving(oldValue !== newValue); + setError(undefined); + }} + onClick={(e, pos) => { + if (pos && pos.textNode && pos.textNode.data) { + const clickIndex = getClickIndex(pos); + + let parsedAttrs: Attribute[]; + + try { + parsedAttrs = + attribute_parser.lexAndParse( + getPreprocessedData( + currentValueRef.current, + ), + true, + ); + } catch (e: unknown) { + // the input is incorrect because the user messed up with it and now needs to fix it manually + console.log(e); + return null; + } + + let matchedAttr: Attribute | null = null; + + for (const attr of parsedAttrs) { + if ( + attr.startIndex !== undefined && + clickIndex > attr.startIndex && + attr.endIndex !== undefined && + clickIndex <= attr.endIndex + ) { + matchedAttr = attr; + break; + } + } + + setTimeout(() => { + if (matchedAttr) { + attributeDetailWidget.showAttributeDetail( + { + allAttributes: parsedAttrs, + attribute: matchedAttr, + isOwned: true, + x: e.pageX, + y: e.pageY, + }, + ); + setState("showAttributeDetail"); + } else { + setState("showHelpTooltip"); + } + }, 100); + } else { + setState("showHelpTooltip"); + } + }} + onKeyDown={() => attributeDetailWidget.hide()} + onBlur={() => save()} + onInitialized={() => editorRef.current?.focus()} + disableNewlines + disableSpellcheck + /> + +
+ {needsSaving && ( + + )} + + { + // Prevent automatic hiding of the context menu due to the button being clicked. + e.stopPropagation(); + setIsMenuOpen(true); + + contextMenu.show({ + x: e.pageX, + y: e.pageY, + orientation: "left", + + items: [ + { + title: t( + "attribute_editor.add_new_label", + ), + command: "addNewLabel", + uiIcon: "bx bx-hash", + }, + { + title: t( + "attribute_editor.add_new_relation", + ), + command: "addNewRelation", + uiIcon: "bx bx-transfer", + }, + { kind: "separator" }, + { + title: t( + "attribute_editor.add_new_label_definition", + ), + command: + "addNewLabelDefinition", + uiIcon: "bx bx-empty", + }, + { + title: t( + "attribute_editor.add_new_relation_definition", + ), + command: + "addNewRelationDefinition", + uiIcon: "bx bx-empty", + }, + ], + selectMenuItemHandler: (item) => + handleAddNewAttributeCommand( + item.command, + ), + onHide: () => setIsMenuOpen(false), + }); + }} + /> +
- )} -
} + {error && ( +
+ {getErrorMessage(error)} +
+ )} +
+ )} {createPortal(attributeDetailWidgetEl, document.body)} From 6bc3176251f3a967aba6d40c616090c8462a856f Mon Sep 17 00:00:00 2001 From: Zaki Ur Rehman Date: Thu, 16 Apr 2026 18:29:57 +0500 Subject: [PATCH 250/482] fix: resolve context menu state reset issue causing UI text overlap --- .../widgets/ribbon/components/AttributeEditor.tsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx b/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx index 2c694c4e70..83d27df1ee 100644 --- a/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx +++ b/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx @@ -138,6 +138,7 @@ export default function AttributeEditor({ const [error, setError] = useState(); const [needsSaving, setNeedsSaving] = useState(false); const [isMenuOpen, setIsMenuOpen] = useState(false); + const suppressNextOnHide = useRef(false); const lastSavedContent = useRef(); const currentValueRef = useRef(currentValue); const wrapperRef = useRef(null); @@ -486,6 +487,11 @@ export default function AttributeEditor({ onClick={(e) => { // Prevent automatic hiding of the context menu due to the button being clicked. e.stopPropagation(); + if (isMenuOpen) { + // If we re-show the menu, ContextMenu.show() will call hide() + // and immediately trigger onHide. Suppress that transient hide. + suppressNextOnHide.current = true; + } setIsMenuOpen(true); contextMenu.show({ @@ -530,7 +536,13 @@ export default function AttributeEditor({ handleAddNewAttributeCommand( item.command, ), - onHide: () => setIsMenuOpen(false), + onHide: () => { + if (suppressNextOnHide.current) { + suppressNextOnHide.current = false; + return; + } + setIsMenuOpen(false); + }, }); }} /> From 09d1c85bd36395479ac5fab67907ea064679f784 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Thu, 16 Apr 2026 17:06:42 +0200 Subject: [PATCH 251/482] Update translation files Updated by "Cleanup translation files" add-on in Weblate. Translation: Trilium Notes/README Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ --- docs/README-ug.md | 99 +++++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 47 deletions(-) diff --git a/docs/README-ug.md b/docs/README-ug.md index 0c4c59b054..b20038be1e 100644 --- a/docs/README-ug.md +++ b/docs/README-ug.md @@ -176,77 +176,81 @@ zadam/Trilium نۇسخىسىدىن TriliumNext/Notes غا كۆچۈش ئۈچۈن ئۇلانغان - [GitHub Discussions](https://github.com/TriliumNext/Trilium/discussions) (ئاسىنكرون مۇنازىرە). -- [Github Issues](https://github.com/TriliumNext/Trilium/issues) (For bug - reports and feature requests.) +- [GitHub Issues](https://github.com/TriliumNext/Trilium/issues) (خاتالىق مەلۇم + قىلىش ۋە ئىقتىدار ئېھتىياجىنى ئوتتۇرىغا قويۇش). -## 🏗 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. +[ئەڭ يېڭى نەشرى بېتى](https://github.com/TriliumNext/Trilium/releases/latest)دىن +سۇپىڭىزغا ماس كېلىدىغان سىستېما ھۆججىتىنى چۈشۈرۈڭ، پرېستىن يەشكەندىن كېيىن +`trilium` ئىجرا ھۆججىتىنى قوزغىتىڭ.) ### Linux -If your distribution is listed in the table below, use your distribution's -package. +ئەگەر سىز ئىشلىتىۋاتقان نەشرى تۆۋەندىكى جەدۋەلدە بولسا، شۇ نەشرىنىڭ يۇمشاق دېتال +بوغچىسىنى ئىشلىتىڭ. [![Packaging status](https://repology.org/badge/vertical-allrepos/triliumnext.svg)](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. +سىز يەنە [ئەڭ يېڭى ئېلان قىلىنغان +بەت](https://github.com/TriliumNext/Trilium/releases/latest)تىن مۇناسىپ سۇپىنىڭ +سىستېما ھۆججىتىنى چۈشۈرۈپ، پرېستىن يېشىپ بولغاندىن كېيىن trilium ئىجرا ھۆججىتىنى +قوزغاتسىڭىز بولىدۇ. -TriliumNext is also provided as a Flatpak, but not yet published on FlatHub. +TriliumNext يەنە Flatpak نۇسخىسى بىلەن تەمىنلەيدۇ، ئەمما تېخى 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). +نۆۋەتتە پەقەت Chrome ۋە Firefox نىڭ ئەڭ يېڭى نەشرىنىلا قوللايدۇ (ھەمدە ئەمەلىي +سىناقتىن ئۆتكەن). ### 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). +ئەگەر كۆچمە ئۈسكۈنىلەردە TriliumNext نى ئىشلەتمەكچى بولسىڭىز، كۆچمە كۆرگۈچ +ئارقىلىق مۇلازىمىتىرغا قاچىلانغان كۆچمە نۇسخا كۆرۈنمە يۈزىنى زىيارەت قىلالايسىز +(تۆۋەنگە قاراڭ). -See issue https://github.com/TriliumNext/Trilium/issues/4962 for more -information on mobile app support. +كۆچمە دېتال قوللاشقا ئائىت تېخىمۇ كۆپ ئۇچۇرلار ئۈچۈن، +https://github.com/TriliumNext/Trilium/issues/4962 مەسىلە بېتىگە قاراڭ. -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. +ئەگەر سىز ئەسلى Android دېتالىنى ئىشلىتىشكە ئامراق بولسىڭىز، +[TriliumDroid](https://apt.izzysoft.de/fdroid/index/apk/eu.fliegendewurst.triliumdroid) +نى ئىشلەتسىڭىز بولىدۇ. مەسىلە ياكى كەم بولغان ئىقتىدارلارنى مەلۇم قىلماقچى +بولسىڭىز، [ئۇنىڭ ئامبىرى](https://github.com/FliegendeWurst/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://docs.triliumnotes.org/user-guide/setup/server). +ئەگەر ئۆزىڭىزنىڭ مۇلازىمىتىرىغا TriliumNext نى قاچىلىماقچى بولسىڭىز ([Docker +Hub](https://hub.docker.com/r/triliumnext/trilium) دىن Docker ئارقىلىق +ئورۇنلاشتۇرۇشنىمۇ ئۆز ئىچىگە ئالىدۇ)، [مۇلازىمىتىر قاچىلاش +ھۆججىتى](https://docs.triliumnotes.org/user-guide/setup/server) گە ئەمەل قىلىڭ. -## 💻 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/). +ئەگەر سىز شۇ تىلنىڭ ئىگىسى بولسىڭىز، بىزنىڭ [Weblate +بېتىمىز](https://hosted.weblate.org/engage/trilium/)گە كىرىپ Trilium نىڭ تەرجىمە +قىلىنىشىغا ياردەم بېرىشىڭىزنى قارشى ئالىمىز. -Here's the language coverage we have so far: +تۆۋەندىكىسى نۆۋەتتىكى تىللارنىڭ قاپلىنىش ئەھۋالى: -[![Translation -status](https://hosted.weblate.org/widget/trilium/multi-auto.svg)](https://hosted.weblate.org/engage/trilium/) +[![تەرجىمە +ئەھۋالى](https://hosted.weblate.org/widget/trilium/multi-auto.svg)](https://hosted.weblate.org/engage/trilium/) -### Code +### پروگرامما كودى -Download the repository, install dependencies using `pnpm` and then run the -server (available at http://localhost:8080): +ئامبارنى چۈشۈرۈڭ، `pnpm` ئارقىلىق بېقىندى زاپچاسلارنى قاچىلاڭ، ئاندىن +مۇلازىمىتىرنى قوزغىتىڭ (مۇلازىمەت ئادرېسى: http://localhost:8080): ```shell git clone https://github.com/TriliumNext/Trilium.git cd Trilium @@ -254,10 +258,10 @@ pnpm install pnpm run server:start ``` -### Documentation +### ھۆججەت -Download the repository, install dependencies using `pnpm` and then run the -environment required to edit the documentation: +ئامبارنى چۈشۈرۈڭ، `pnpm` ئارقىلىق بېقىندى زاپچاسلارنى قاچىلاڭ، ئاندىن ھۆججەت +تەھرىرلەشكە ئېھتىياجلىق مۇھىتنى قوزغىتىڭ: ```shell git clone https://github.com/TriliumNext/Trilium.git cd Trilium @@ -266,8 +270,8 @@ pnpm edit-docs:edit-docs ``` ### Building the Executable -Download the repository, install dependencies using `pnpm` and then build the -desktop app for Windows: +ئامبارنى چۈشۈرۈڭ، `pnpm` ئارقىلىق بېقىندى زاپچاسلارنى قاچىلاڭ، ئاندىن Windows +ئۈچۈن ئۈستەلئۈستى ئەپىنى قۇرۇپ چىقىڭ: ```shell git clone https://github.com/TriliumNext/Trilium.git cd Trilium @@ -275,10 +279,11 @@ 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). +تېخىمۇ كۆپ تەپسىلاتلار ئۈچۈن [تەتقىقات +ھۆججەت](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) From d8db862c22167f5513e2cf2af62fb70d46541124 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Thu, 16 Apr 2026 18:25:37 +0300 Subject: [PATCH 252/482] test(client,server): guard against duplicate JSON keys --- apps/client/src/services/i18n.spec.ts | 11 +++- apps/server/src/services/i18n.spec.ts | 11 +++- packages/commons/src/lib/test-utils.spec.ts | 25 ++++++++- packages/commons/src/lib/test-utils.ts | 61 +++++++++++++++++++++ 4 files changed, 103 insertions(+), 5 deletions(-) diff --git a/apps/client/src/services/i18n.spec.ts b/apps/client/src/services/i18n.spec.ts index e408816436..3216c6cf0c 100644 --- a/apps/client/src/services/i18n.spec.ts +++ b/apps/client/src/services/i18n.spec.ts @@ -1,10 +1,10 @@ -import { LOCALES } from "@triliumnext/commons"; +import { findDuplicateJsonKeys, LOCALES } from "@triliumnext/commons"; import { readFileSync } from "fs"; import { join } from "path"; import { describe, expect, it } from "vitest"; describe("i18n", () => { - it("translations are valid JSON", () => { + it("translations are valid JSON with no duplicate keys", () => { for (const locale of LOCALES) { if (locale.contentOnly || locale.id === "en_rtl") { continue; @@ -14,6 +14,13 @@ describe("i18n", () => { const translationFile = readFileSync(translationPath, { encoding: "utf-8" }); expect(() => JSON.parse(translationFile), `JSON error while parsing locale '${locale.id}' at "${translationPath}"`) .not.toThrow(); + + const duplicates = findDuplicateJsonKeys(translationFile); + expect( + duplicates, + `Duplicate keys in locale '${locale.id}' at "${translationPath}":\n${ + duplicates.map((d) => ` - "${d.key}" (line ${d.line})`).join("\n")}` + ).toEqual([]); } }); }); diff --git a/apps/server/src/services/i18n.spec.ts b/apps/server/src/services/i18n.spec.ts index e9be7efc81..fba64cdb7b 100644 --- a/apps/server/src/services/i18n.spec.ts +++ b/apps/server/src/services/i18n.spec.ts @@ -1,4 +1,4 @@ -import { LOCALES } from "@triliumnext/commons"; +import { findDuplicateJsonKeys, LOCALES } from "@triliumnext/commons"; import { readFileSync } from "fs"; import { join } from "path"; // eslint-disable-next-line @typescript-eslint/no-require-imports @@ -6,7 +6,7 @@ const { languages } = require("tesseract.js"); import { describe, expect, it } from "vitest"; describe("i18n", () => { - it("translations are valid JSON", () => { + it("translations are valid JSON with no duplicate keys", () => { for (const locale of LOCALES) { if (locale.contentOnly || locale.id === "en_rtl") { continue; @@ -16,6 +16,13 @@ describe("i18n", () => { const translationFile = readFileSync(translationPath, { encoding: "utf-8" }); expect(() => JSON.parse(translationFile), `JSON error while parsing locale '${locale.id}' at "${translationPath}"`) .not.toThrow(); + + const duplicates = findDuplicateJsonKeys(translationFile); + expect( + duplicates, + `Duplicate keys in locale '${locale.id}' at "${translationPath}":\n` + + duplicates.map((d) => ` - "${d.key}" (line ${d.line})`).join("\n") + ).toEqual([]); } }); diff --git a/packages/commons/src/lib/test-utils.spec.ts b/packages/commons/src/lib/test-utils.spec.ts index 4d02fc90d1..90388f5814 100644 --- a/packages/commons/src/lib/test-utils.spec.ts +++ b/packages/commons/src/lib/test-utils.spec.ts @@ -1,5 +1,5 @@ import { describe, it, expect } from "vitest"; -import { trimIndentation } from "./test-utils.js"; +import { findDuplicateJsonKeys, trimIndentation } from "./test-utils.js"; describe("Utils", () => { it("trims indentation", () => { @@ -11,4 +11,27 @@ Hello world 123`); }); + + describe("findDuplicateJsonKeys", () => { + it("returns empty for valid JSON without duplicates", () => { + expect(findDuplicateJsonKeys(`{"a": 1, "b": {"c": 2}}`)).toEqual([]); + }); + + it("detects duplicates at the top level and reports line numbers", () => { + const text = `{\n "a": 1,\n "b": 2,\n "a": 3\n}`; + expect(findDuplicateJsonKeys(text)).toEqual([{ key: "a", line: 4 }]); + }); + + it("scopes keys per object — same name at different levels is not a duplicate", () => { + expect(findDuplicateJsonKeys(`{"a": {"x": 1}, "b": {"x": 2}}`)).toEqual([]); + }); + + it("does not treat string values containing a colon as keys", () => { + expect(findDuplicateJsonKeys(`{"a": "b:c", "d": "a:e"}`)).toEqual([]); + }); + + it("does not treat strings inside arrays as keys", () => { + expect(findDuplicateJsonKeys(`{"items": ["a", "a", "b"]}`)).toEqual([]); + }); + }); }); diff --git a/packages/commons/src/lib/test-utils.ts b/packages/commons/src/lib/test-utils.ts index 86ebfb0d60..a570d00440 100644 --- a/packages/commons/src/lib/test-utils.ts +++ b/packages/commons/src/lib/test-utils.ts @@ -62,3 +62,64 @@ export function flushPromises() { export function sleepFor(duration: number) { return new Promise(resolve => setTimeout(resolve, duration)); } + +/** + * Scans raw JSON text for keys that are duplicated within the same object. + * + * `JSON.parse` silently collapses duplicate keys (the last one wins), which makes + * it impossible to detect them from the parsed value. This scanner walks the raw + * text, pushing/popping a scope for each `{`/`}`, and identifies a string as a + * key when the next non-whitespace char is `:`. + * + * Intended for validating hand-maintained JSON files (e.g. translation files) + * at test level. + */ +export function findDuplicateJsonKeys(text: string): Array<{ key: string; line: number }> { + const duplicates: Array<{ key: string; line: number }> = []; + const stack: Set[] = []; + let line = 1; + let i = 0; + + while (i < text.length) { + const c = text[i]; + if (c === "\n") { + line++; + i++; + } else if (c === "{") { + stack.push(new Set()); + i++; + } else if (c === "}") { + stack.pop(); + i++; + } else if (c === '"') { + const start = i; + const startLine = line; + i++; + while (i < text.length && text[i] !== '"') { + if (text[i] === "\\") { + i += 2; + } else { + if (text[i] === "\n") line++; + i++; + } + } + i++; + // A string is a key iff the next non-whitespace char is ':'. + let j = i; + while (j < text.length && /\s/.test(text[j])) j++; + if (text[j] === ":" && stack.length > 0) { + const key = JSON.parse(text.substring(start, i)) as string; + const frame = stack[stack.length - 1]; + if (frame.has(key)) { + duplicates.push({ key, line: startLine }); + } else { + frame.add(key); + } + } + } else { + i++; + } + } + + return duplicates; +} From 603b232d1f0928c2cf35dd1746695c16f83edd9b Mon Sep 17 00:00:00 2001 From: passkal4 Date: Thu, 16 Apr 2026 15:10:23 +0200 Subject: [PATCH 253/482] Translated using Weblate (Uyghur) Currently translated at 21.3% (86 of 403 strings) Translation: Trilium Notes/Server Translate-URL: https://hosted.weblate.org/projects/trilium/server/ug/ --- .../src/assets/translations/ug/server.json | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/apps/server/src/assets/translations/ug/server.json b/apps/server/src/assets/translations/ug/server.json index 593275bcb8..7f7380ddaa 100644 --- a/apps/server/src/assets/translations/ug/server.json +++ b/apps/server/src/assets/translations/ug/server.json @@ -57,6 +57,34 @@ "show-recent-changes": "يېقىنقى ئۆزگىرىشلەر سۆھبەت رامكىسىنى كۆرسىتىش", "show-sql-console": "SQL كونترول سۇپىسى سۆھبەت رامكىسىنى كۆرسىتىش", "show-backend-log": "ئارقا سۇپا خاتىرىسى سۆھبەت رامكىسىنى كۆرسىتىش", - "show-help": "ياردەمنى كۆرسىتىش" + "show-help": "ياردەمنى كۆرسىتىش", + "show-cheatsheet": "تېز كۇنۇپكا يېتەكچىسىنى كۆرسىتىش", + "text-note-operations": "تېكىستلىك خاتىرە مەشغۇلاتى", + "add-link-to-text": "تېكىستكە ئۇلانما قوشۇش سۆھبەت رامكىسىنى ئېچىش", + "follow-link-under-cursor": "كۇرسور ئاستىدىكى ئۇلانمىنى ئېچىش", + "edit-readonly-note": "پەقەت ئوقۇشقىلا بولىدىغان خاتىرىنى تەھرىرلەش", + "attributes-labels-and-relations": "خاسلىق (بەلگە ۋە مۇناسىۋەت)", + "add-new-label": "يېڭى بەلگە قۇرۇش", + "insert-date-and-time-to-text": "تېكىستكە چېسلا ۋە ۋاقىت قىستۇرۇش", + "paste-markdown-into-text": "چاپلاش تاختىسىدىكى Markdown نى تېكىستلىك خاتىرىگە چاپلاش", + "cut-into-note": "نۆۋەتتىكى خاتىرىنىڭ تاللانغان قىسمىنى كېسىۋېلىش ھەمدە تاللانغان تېكىستنى ئۆز ئىچىگە ئالغان تارماق خاتىرە قۇرۇش", + "create-new-relation": "يېڭى مۇناسىۋەت قۇرۇش", + "ribbon-tabs": "ئىقتىدار رايونى بەتلىرى", + "toggle-link-map": "ئۇلىنىش خەرىتىسىنى ئالماشتۇرۇش", + "toggle-note-info": "خاتىرە ئۇچۇرلىرىنى ئالماشتۇرۇش", + "toggle-note-paths": "خاتىرە يولىنى ئالماشتۇرۇش", + "toggle-similar-notes": "ئوخشاش خاتىرىلەرنى ئالماشتۇرۇش", + "other": "باشقىلار", + "toggle-right-pane": "مۇندەرىجە ۋە يارقىنلىتىشنى ئۆز ئىچىگە ئالغان ئوڭ تەرەپ كۆزنەك تاختىسىنىڭ كۆرۈنۈشىنى ئالماشتۇرۇش", + "print-active-note": "نۆۋەتتىكى خاتىرىنى بېسىپ چىقىرىش", + "add-include-note-to-text": "خاتىرە ئۆز ئىچىگە ئالغان سۆزلىشىش رامكىسىنى ئېچىش", + "open-note-externally": "خاتىرە ھۆججىتىنى ئەپ ئارقىلىق ئېچىش", + "run-active-note": "نۆۋەتتىكى JavaScript (ئالدى/كەينى تەرەپ) كود خاتىرىسىنى ئىجرا قىلىش", + "toggle-note-hoisting": "خاتىرىنى يۇقىرى كۆتۈرۈش", + "unhoist": "خاتىرىنى يۇقىرى كۆتۈرۈشتىن ۋاز كېچىش", + "reload-frontend-app": "ئالدى تەرەپ ئەپىنى قايتا يۈكلەش", + "open-dev-tools": "تەتقىقاتچى قوراللىرىنى ئېچىش", + "find-in-text": "تېكىست ئىچىدىن ئىزدەش", + "toggle-left-note-tree-panel": "سول تەرەپ (خاتىرە دەرىخى) تاختىسىنى ئالماشتۇرۇش" } } From 735712123c0027165a8037af3f1920021a1e78da Mon Sep 17 00:00:00 2001 From: noobhjy Date: Thu, 16 Apr 2026 13:34:16 +0200 Subject: [PATCH 254/482] Translated using Weblate (Chinese (Simplified Han script)) Currently translated at 88.8% (1716 of 1932 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/ --- apps/client/src/translations/cn/translation.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/client/src/translations/cn/translation.json b/apps/client/src/translations/cn/translation.json index ce4595d477..fccfc95676 100644 --- a/apps/client/src/translations/cn/translation.json +++ b/apps/client/src/translations/cn/translation.json @@ -97,7 +97,8 @@ "broken_relations_to_be_deleted": "将删除以下关系并断开连接 ({{ relationCount}})", "cancel": "取消", "title": "删除笔记", - "delete": "删除" + "delete": "删除", + "clones_label": "克隆" }, "export": { "export_note_title": "导出笔记", From 011cce05af8e6793825f5aa444acc32487045e8a Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Thu, 16 Apr 2026 17:23:05 +0200 Subject: [PATCH 255/482] Update translation files Updated by "Cleanup translation files" add-on in Weblate. Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/ --- apps/client/src/translations/de/translation.json | 3 --- apps/client/src/translations/es/translation.json | 3 --- apps/client/src/translations/ga/translation.json | 3 --- apps/client/src/translations/ja/translation.json | 3 --- 4 files changed, 12 deletions(-) diff --git a/apps/client/src/translations/de/translation.json b/apps/client/src/translations/de/translation.json index 1efdafdc6e..5f3003dddb 100644 --- a/apps/client/src/translations/de/translation.json +++ b/apps/client/src/translations/de/translation.json @@ -2238,9 +2238,6 @@ "sample_venn": "Mengen", "sample_ishikawa": "Ursache-Wirkung" }, - "revisions": { - "title": "Notizrevisionen" - }, "database": { "title": "Datenbank" }, diff --git a/apps/client/src/translations/es/translation.json b/apps/client/src/translations/es/translation.json index 2f26db1ba8..640d1af367 100644 --- a/apps/client/src/translations/es/translation.json +++ b/apps/client/src/translations/es/translation.json @@ -2239,8 +2239,5 @@ "sample_venn": "Venn", "sample_ishikawa": "Ishikawa", "sample_treemap": "Mapa de árbol" - }, - "revisions": { - "title": "Revisiones de nota" } } diff --git a/apps/client/src/translations/ga/translation.json b/apps/client/src/translations/ga/translation.json index 7326807d26..688cd23896 100644 --- a/apps/client/src/translations/ga/translation.json +++ b/apps/client/src/translations/ga/translation.json @@ -2464,9 +2464,6 @@ "text_filtered_low_confidence": "Bhraith OCR téacs le muinín {{confidence}}%, ach caitheadh leis é mar is é {{threshold}}% an tairseach íosta atá agat.", "open_media_settings": "Oscail Socruithe" }, - "revisions": { - "title": "Athbhreithnithe Nótaí" - }, "database": { "title": "Bunachar Sonraí" }, diff --git a/apps/client/src/translations/ja/translation.json b/apps/client/src/translations/ja/translation.json index 3f8408c640..562c2fedf8 100644 --- a/apps/client/src/translations/ja/translation.json +++ b/apps/client/src/translations/ja/translation.json @@ -2400,9 +2400,6 @@ "text_filtered_low_confidence": "OCR は {{confidence}}% の信頼度でテキストを検出しましたが、最小しきい値が {{threshold}}% であるため、破棄されました。", "open_media_settings": "設定を開く" }, - "revisions": { - "title": "ノートの変更履歴" - }, "database": { "title": "データベース" }, From 7f75ab063811983dc94b0203906a336d70db78f1 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Thu, 16 Apr 2026 20:47:30 +0300 Subject: [PATCH 256/482] client/about dialog: define the strings for a brief history --- apps/client/src/translations/en/translation.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 17a283b09d..17e7d113ac 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -9,8 +9,8 @@ "original-dev": "original developer" }, "role_brief_history": { - "lead-dev": "TODO", - "original-dev": "TODO" + "lead-dev": "Elian Doran founded TriliumNext in 2024, a community fork created after Zadam stepped back from the project. Zadam later transferred the original repository to the TriliumNext team, merging both projects back into one.", + "original-dev": "On 25th December 2017, Zadam released the first beta of Trilium (written with a single \"i\", unlike the flower). Dissatisfied with existing note organizers, he built a powerful self-hosted hierarchical knowledge base that gathered over 22,000 GitHub stars. In 2024, as life got busier, he placed the project into maintenance mode." }, "contributor_full_list": "See the entire community", "data_directory": "Data directory:", From 262c89d252e872b250fd3e881ec38850b9dd1093 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Thu, 16 Apr 2026 20:48:53 +0300 Subject: [PATCH 257/482] style/about dialog: tweak the tooltip clues --- apps/client/src/widgets/dialogs/about.css | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css index d3dcf55d61..c3d67c09d7 100644 --- a/apps/client/src/widgets/dialogs/about.css +++ b/apps/client/src/widgets/dialogs/about.css @@ -71,6 +71,8 @@ .contributor-role { text-decoration: underline dotted var(--main-text-color); + text-underline-offset: 3px; + text-decoration-color: var(--muted-text-color); cursor: help; } } @@ -122,7 +124,11 @@ } .about-dialog-brief-history-tooltip { - --main-font-size: .85em; + --main-font-size: .9em; + + .tooltip-inner { + max-width: 600px; + } } @keyframes icon-intro { From b2f02962fc977f2316890ac54bd7e9fa8cfabb04 Mon Sep 17 00:00:00 2001 From: Zaki Ur Rehman Date: Thu, 16 Apr 2026 22:54:48 +0500 Subject: [PATCH 258/482] refactor: show only modified lines --- .../ribbon/components/AttributeEditor.tsx | 492 ++++++------------ 1 file changed, 171 insertions(+), 321 deletions(-) diff --git a/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx b/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx index 83d27df1ee..dd5eb8895b 100644 --- a/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx +++ b/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx @@ -1,39 +1,19 @@ -import { - AttributeEditor as CKEditorAttributeEditor, - MentionFeed, - ModelElement, - ModelNode, - ModelPosition, -} from "@triliumnext/ckeditor5"; +import { AttributeEditor as CKEditorAttributeEditor, MentionFeed, ModelElement, ModelNode, ModelPosition } from "@triliumnext/ckeditor5"; import { AttributeType } from "@triliumnext/commons"; import { createPortal } from "preact/compat"; -import { - MutableRef, - useEffect, - useImperativeHandle, - useMemo, - useRef, - useState, -} from "preact/hooks"; +import { MutableRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from "preact/hooks"; -import type { - CommandData, - FilteredCommandNames, -} from "../../../components/app_context"; +import type { CommandData, FilteredCommandNames } from "../../../components/app_context"; import FAttribute from "../../../entities/fattribute"; import FNote from "../../../entities/fnote"; import contextMenu from "../../../menus/context_menu"; -import attribute_parser, { - Attribute, -} from "../../../services/attribute_parser"; +import attribute_parser, { Attribute } from "../../../services/attribute_parser"; import attribute_renderer from "../../../services/attribute_renderer"; import attributes from "../../../services/attributes"; import froca from "../../../services/froca"; import { t } from "../../../services/i18n"; import link from "../../../services/link"; -import note_autocomplete, { - Suggestion, -} from "../../../services/note_autocomplete"; +import note_autocomplete, { Suggestion } from "../../../services/note_autocomplete"; import note_create from "../../../services/note_create"; import server from "../../../services/server"; import { isIMEComposing } from "../../../services/shortcuts"; @@ -41,13 +21,7 @@ import { escapeQuotes, getErrorMessage } from "../../../services/utils"; import AttributeDetailWidget from "../../attribute_widgets/attribute_detail"; import ActionButton from "../../react/ActionButton"; import CKEditor, { CKEditorApi } from "../../react/CKEditor"; -import { - useLegacyImperativeHandlers, - useLegacyWidget, - useTooltip, - useTriliumEvent, - useTriliumOption, -} from "../../react/hooks"; +import { useLegacyImperativeHandlers, useLegacyWidget, useTooltip, useTriliumEvent, useTriliumOption } from "../../react/hooks"; type AttributeCommandNames = FilteredCommandNames; @@ -61,8 +35,7 @@ const HELP_TEXT = ` const mentionSetup: MentionFeed[] = [ { marker: "@", - feed: (queryText) => - note_autocomplete.autocompleteSourceForCKEditor(queryText), + feed: (queryText) => note_autocomplete.autocompleteSourceForCKEditor(queryText), itemRenderer: (_item) => { const item = _item as Suggestion; const itemElement = document.createElement("button"); @@ -71,42 +44,39 @@ const mentionSetup: MentionFeed[] = [ return itemElement; }, - minimumCharacters: 0, + minimumCharacters: 0 }, { marker: "#", feed: async (queryText) => { - const names = await server.get( - `attribute-names/?type=label&query=${encodeURIComponent(queryText)}`, - ); + const names = await server.get(`attribute-names/?type=label&query=${encodeURIComponent(queryText)}`); return names.map((name) => { return { id: `#${name}`, - name, + name }; }); }, - minimumCharacters: 0, + minimumCharacters: 0 }, { marker: "~", feed: async (queryText) => { - const names = await server.get( - `attribute-names/?type=relation&query=${encodeURIComponent(queryText)}`, - ); + const names = await server.get(`attribute-names/?type=relation&query=${encodeURIComponent(queryText)}`); return names.map((name) => { return { id: `~${name}`, - name, + name }; }); }, - minimumCharacters: 0, - }, + minimumCharacters: 0 + } ]; + interface AttributeEditorProps { api: MutableRef; note: FNote; @@ -123,39 +93,29 @@ export interface AttributeEditorImperativeHandlers { renderOwnedAttributes(ownedAttributes: FAttribute[]): Promise; } -export default function AttributeEditor({ - api, - note, - componentId, - notePath, - ntxId, - hidden, -}: AttributeEditorProps) { - const [currentValue, setCurrentValue] = useState(""); - const [state, setState] = useState< - "normal" | "showHelpTooltip" | "showAttributeDetail" - >(); - const [error, setError] = useState(); - const [needsSaving, setNeedsSaving] = useState(false); +export default function AttributeEditor({ api, note, componentId, notePath, ntxId, hidden }: AttributeEditorProps) { + const [ currentValue, setCurrentValue ] = useState(""); + const [ state, setState ] = useState<"normal" | "showHelpTooltip" | "showAttributeDetail">(); + const [ error, setError ] = useState(); + const [ needsSaving, setNeedsSaving ] = useState(false); const [isMenuOpen, setIsMenuOpen] = useState(false); const suppressNextOnHide = useRef(false); + const lastSavedContent = useRef(); const currentValueRef = useRef(currentValue); const wrapperRef = useRef(null); const editorRef = useRef(); - const [locale] = useTriliumOption("locale"); + const [ locale ] = useTriliumOption("locale"); const { showTooltip, hideTooltip } = useTooltip(wrapperRef, { trigger: "focus", html: true, title: HELP_TEXT, placement: "bottom", - offset: "0,30", + offset: "0,30" }); - const [attributeDetailWidgetEl, attributeDetailWidget] = useLegacyWidget( - () => new AttributeDetailWidget(), - ); + const [ attributeDetailWidgetEl, attributeDetailWidget ] = useLegacyWidget(() => new AttributeDetailWidget()); useEffect(() => { if (state === "showHelpTooltip") { @@ -163,16 +123,13 @@ export default function AttributeEditor({ } else { hideTooltip(); } - }, [state]); + }, [ state ]); - async function renderOwnedAttributes( - ownedAttributes: FAttribute[], - saved: boolean, - ) { + async function renderOwnedAttributes(ownedAttributes: FAttribute[], saved: boolean) { // attrs are not resorted if position changes after the initial load ownedAttributes.sort((a, b) => a.position - b.position); - let htmlAttrs = `

${(await attribute_renderer.renderAttributes(ownedAttributes, true)).html()}

`; + let htmlAttrs = (`

${(await attribute_renderer.renderAttributes(ownedAttributes, true)).html()}

`); if (saved) { lastSavedContent.current = htmlAttrs; @@ -189,9 +146,7 @@ export default function AttributeEditor({ function parseAttributes() { try { - return attribute_parser.lexAndParse( - getPreprocessedData(currentValueRef.current), - ); + return attribute_parser.lexAndParse(getPreprocessedData(currentValueRef.current)); } catch (e: unknown) { setError(e); } @@ -204,11 +159,7 @@ export default function AttributeEditor({ return; } - await server.put( - `notes/${note.noteId}/attributes`, - attributes, - componentId, - ); + await server.put(`notes/${note.noteId}/attributes`, attributes, componentId); setNeedsSaving(false); // blink the attribute text to give a visual hint that save has been executed @@ -222,9 +173,7 @@ export default function AttributeEditor({ } } - async function handleAddNewAttributeCommand( - command: AttributeCommandNames | undefined, - ) { + async function handleAddNewAttributeCommand(command: AttributeCommandNames | undefined) { // TODO: Not sure what the relation between FAttribute[] and Attribute[] is. const attrs = parseAttributes() as FAttribute[]; @@ -261,7 +210,7 @@ export default function AttributeEditor({ type, name, value, - isInheritable: false, + isInheritable: false }); await renderOwnedAttributes(attrs, false); @@ -277,7 +226,7 @@ export default function AttributeEditor({ isOwned: true, x: rect ? (rect.left + rect.right) / 2 : 0, y: rect?.bottom ?? 0, - focus: "name", + focus: "name" }); }, 100); } @@ -287,51 +236,34 @@ export default function AttributeEditor({ renderOwnedAttributes(note.getOwnedAttributes(), true); } - useEffect(() => refresh(), [note]); + useEffect(() => refresh(), [ note ]); useTriliumEvent("entitiesReloaded", ({ loadResults }) => { - if ( - loadResults - .getAttributeRows(componentId) - .find((attr) => attributes.isAffecting(attr, note)) - ) { + if (loadResults.getAttributeRows(componentId).find((attr) => attributes.isAffecting(attr, note))) { refresh(); } }); // Interaction with CKEditor. - useLegacyImperativeHandlers( - useMemo( - () => ({ - loadReferenceLinkTitle: async ( - $el: JQuery, - href: string, - ) => { - const { noteId } = link.parseNavigationStateFromUrl(href); - const note = noteId - ? await froca.getNote(noteId, true) - : null; - const title = note ? note.title : "[missing]"; + useLegacyImperativeHandlers(useMemo(() => ({ + loadReferenceLinkTitle: async ($el: JQuery, href: string) => { + const { noteId } = link.parseNavigationStateFromUrl(href); + const note = noteId ? await froca.getNote(noteId, true) : null; + const title = note ? note.title : "[missing]"; - $el.text(title); - }, - createNoteForReferenceLink: async (title: string) => { - let result; - if (notePath) { - result = await note_create.createNoteWithTypePrompt( - notePath, - { - activate: false, - title, - }, - ); - } + $el.text(title); + }, + createNoteForReferenceLink: async (title: string) => { + let result; + if (notePath) { + result = await note_create.createNoteWithTypePrompt(notePath, { + activate: false, + title + }); + } - return result?.note?.getBestNotePathString(); - }, - }), - [notePath], - ), - ); + return result?.note?.getBestNotePathString(); + } + }), [ notePath ])); // Keyboard shortcuts useTriliumEvent("addNewLabel", ({ ntxId: eventNtxId }) => { @@ -344,217 +276,135 @@ export default function AttributeEditor({ }); // Imperative API - useImperativeHandle( - api, - () => ({ - save, - refresh, - renderOwnedAttributes: (attributes) => - renderOwnedAttributes(attributes as FAttribute[], false), - focus: () => editorRef.current?.focus(), - }), - [save, refresh, renderOwnedAttributes], - ); + useImperativeHandle(api, () => ({ + save, + refresh, + renderOwnedAttributes: (attributes) => renderOwnedAttributes(attributes as FAttribute[], false), + focus: () => editorRef.current?.focus() + }), [ save, refresh, renderOwnedAttributes ]); return ( <> - {!hidden && ( -
{ - // Skip processing during IME composition - if (isIMEComposing(e)) { - return; - } + {!hidden &&
{ + // Skip processing during IME composition + if (isIMEComposing(e)) { + return; + } - if (e.key === "Enter") { - // allow autocomplete to fill the result textarea - setTimeout(() => save(), 100); - } - }} - > - {" "} -
- { - currentValueRef.current = currentValue ?? ""; + if (e.key === "Enter") { + // allow autocomplete to fill the result textarea + setTimeout(() => save(), 100); + } + }} + >
+ { + currentValueRef.current = currentValue ?? ""; - const oldValue = getPreprocessedData( - lastSavedContent.current ?? "", - ).trimEnd(); - const newValue = getPreprocessedData( - currentValue ?? "", - ).trimEnd(); - setNeedsSaving(oldValue !== newValue); - setError(undefined); - }} - onClick={(e, pos) => { - if (pos && pos.textNode && pos.textNode.data) { - const clickIndex = getClickIndex(pos); + const oldValue = getPreprocessedData(lastSavedContent.current ?? "").trimEnd(); + const newValue = getPreprocessedData(currentValue ?? "").trimEnd(); + setNeedsSaving(oldValue !== newValue); + setError(undefined); + }} + // onClick={(e, pos) => { + // if (pos && pos.textNode && pos.textNode.data) { + // const clickIndex = getClickIndex(pos); - let parsedAttrs: Attribute[]; + // let parsedAttrs: Attribute[]; - try { - parsedAttrs = - attribute_parser.lexAndParse( - getPreprocessedData( - currentValueRef.current, - ), - true, - ); - } catch (e: unknown) { - // the input is incorrect because the user messed up with it and now needs to fix it manually - console.log(e); - return null; - } - - let matchedAttr: Attribute | null = null; - - for (const attr of parsedAttrs) { - if ( - attr.startIndex !== undefined && - clickIndex > attr.startIndex && - attr.endIndex !== undefined && - clickIndex <= attr.endIndex - ) { - matchedAttr = attr; - break; - } - } - - setTimeout(() => { - if (matchedAttr) { - attributeDetailWidget.showAttributeDetail( - { - allAttributes: parsedAttrs, - attribute: matchedAttr, - isOwned: true, - x: e.pageX, - y: e.pageY, - }, - ); - setState("showAttributeDetail"); - } else { - setState("showHelpTooltip"); - } - }, 100); - } else { - setState("showHelpTooltip"); - } - }} - onKeyDown={() => attributeDetailWidget.hide()} - onBlur={() => save()} - onInitialized={() => editorRef.current?.focus()} - disableNewlines - disableSpellcheck - /> - -
- {needsSaving && ( - - )} - - { - // Prevent automatic hiding of the context menu due to the button being clicked. - e.stopPropagation(); - if (isMenuOpen) { - // If we re-show the menu, ContextMenu.show() will call hide() - // and immediately trigger onHide. Suppress that transient hide. - suppressNextOnHide.current = true; - } - setIsMenuOpen(true); + // try { + // parsedAttrs = attribute_parser.lexAndParse(getPreprocessedData(currentValueRef.current), true); + // } catch (e: unknown) { + // // the input is incorrect because the user messed up with it and now needs to fix it manually + // console.log(e); + // return null; + // } + onClick={(e) => { + // Prevent automatic hiding of the context menu due to the button being clicked. + e.stopPropagation(); + if (isMenuOpen) { + // If we re-show the menu, ContextMenu.show() will call hide() + // and immediately trigger onHide. Suppress that transient hide. + suppressNextOnHide.current = true; + } + setIsMenuOpen(true); - contextMenu.show({ - x: e.pageX, - y: e.pageY, - orientation: "left", + contextMenu.show({ + x: e.pageX, + y: e.pageY, + orientation: "left", - items: [ - { - title: t( - "attribute_editor.add_new_label", - ), - command: "addNewLabel", - uiIcon: "bx bx-hash", - }, - { - title: t( - "attribute_editor.add_new_relation", - ), - command: "addNewRelation", - uiIcon: "bx bx-transfer", - }, - { kind: "separator" }, - { - title: t( - "attribute_editor.add_new_label_definition", - ), - command: + items: [ + { + title: t( + "attribute_editor.add_new_label", + ), + command: "addNewLabel", + uiIcon: "bx bx-hash", + }, + { + title: t( + "attribute_editor.add_new_relation", + ), + command: "addNewRelation", + uiIcon: "bx bx-transfer", + }, + { kind: "separator" }, + { + title: t( + "attribute_editor.add_new_label_definition", + ), + command: "addNewLabelDefinition", - uiIcon: "bx bx-empty", - }, - { - title: t( - "attribute_editor.add_new_relation_definition", - ), - command: + uiIcon: "bx bx-empty", + }, + { + title: t( + "attribute_editor.add_new_relation_definition", + ), + command: "addNewRelationDefinition", - uiIcon: "bx bx-empty", - }, - ], - selectMenuItemHandler: (item) => - handleAddNewAttributeCommand( - item.command, - ), - onHide: () => { - if (suppressNextOnHide.current) { - suppressNextOnHide.current = false; - return; - } - setIsMenuOpen(false); - }, - }); - }} - /> -
-
- {error && ( -
- {getErrorMessage(error)} -
- )} + uiIcon: "bx bx-empty", + }, + ], + selectMenuItemHandler: (item) => + handleAddNewAttributeCommand( + item.command, + ), + onHide: () => { + if (suppressNextOnHide.current) { + suppressNextOnHide.current = false; + return; + } + setIsMenuOpen(false); + }, + }); + }} + />
- )} + + { error && ( +
+ {getErrorMessage(error)} +
+ )} +
} {createPortal(attributeDetailWidgetEl, document.body)} @@ -585,4 +435,4 @@ function getClickIndex(pos: ModelPosition) { } return clickIndex; -} +} \ No newline at end of file From 12a83510ed442ead6beb4ad6941f95350f166cfa Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Thu, 16 Apr 2026 20:59:05 +0300 Subject: [PATCH 259/482] style/about dialog: add a different background color for nightly builds --- apps/client/src/widgets/dialogs/about.css | 8 ++++++++ apps/client/src/widgets/dialogs/about.tsx | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css index c3d67c09d7..023a62d8e7 100644 --- a/apps/client/src/widgets/dialogs/about.css +++ b/apps/client/src/widgets/dialogs/about.css @@ -2,10 +2,18 @@ body.light-theme & { --donate-button-color: #e33f3b; + + &.nightly { + --modal-background-color: #f2e1ff; + } } body.dark-theme & { --donate-button-color: #fba6a5; + + &.nightly { + --modal-background-color: #23182b; + } } --bs-modal-width: 680px; diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index 37ddbc6ac8..5dbeb7d3b2 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -15,6 +15,7 @@ import { Fragment } from "preact/jsx-runtime"; import { ComponentChildren } from "preact"; import { useMemo } from "react"; import { memo } from "preact/compat"; +import clsx from "clsx"; export default function AboutDialog() { const [appInfo, setAppInfo] = useState(null); @@ -65,7 +66,7 @@ export default function AboutDialog() { return ( setShown(false)} From d65d7dba3fb6f2f0494f445e5cc3d856ef39972d Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Thu, 16 Apr 2026 21:04:06 +0300 Subject: [PATCH 260/482] client/about dialog: refactor --- apps/client/src/widgets/dialogs/about.tsx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index 5dbeb7d3b2..4cc3963864 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -19,21 +19,21 @@ import clsx from "clsx"; export default function AboutDialog() { const [appInfo, setAppInfo] = useState(null); - const [shown, setShown] = useState(false); + const [isShown, setIsShown] = useState(false); const [isNightly, setNightly] = useState(false); - const [iconName, setIconName] = useState("default"); - const [altIconName, setAltIconName] = useState(null); + const [icon, setIcon] = useState("default"); + const [altIcon, setAltIcon] = useState(null); const onLoad = useCallback(async () => { if (!appInfo) { const info = await server.get("app-info"); if (info.appVersion.includes("test")) { setNightly(true); - setIconName("nightly"); + setIcon("nightly"); } setAppInfo(info); } - setShown(true); + setIsShown(true); }, []); useTriliumEvent("openAboutDialog", onLoad); @@ -44,11 +44,11 @@ export default function AboutDialog() { if (part === "role" && contributor.role === "original-dev") { if (isHovering) { timeoutID = setTimeout(() => { - setAltIconName("classic"); + setAltIcon("classic"); }, 500); } else { clearTimeout(timeoutID); - setAltIconName(null); + setAltIcon(null); } } } @@ -68,12 +68,12 @@ export default function AboutDialog() { setShown(false)} + show={isShown} + onHidden={() => setIsShown(false)} >
-
+

Trilium Notes {isNightly && Nightly}

triliumnotes.org From f64b0290092edcc65af9edec06a35392f0246d04 Mon Sep 17 00:00:00 2001 From: Zaki Ur Rehman Date: Thu, 16 Apr 2026 23:04:29 +0500 Subject: [PATCH 261/482] refactor: ensure only the changed lines are shown --- .../ribbon/components/AttributeEditor.tsx | 158 ++++++++++-------- 1 file changed, 88 insertions(+), 70 deletions(-) diff --git a/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx b/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx index dd5eb8895b..1e5bb77500 100644 --- a/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx +++ b/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx @@ -322,81 +322,99 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI setNeedsSaving(oldValue !== newValue); setError(undefined); }} - // onClick={(e, pos) => { - // if (pos && pos.textNode && pos.textNode.data) { - // const clickIndex = getClickIndex(pos); + onClick={(e, pos) => { + if (pos && pos.textNode && pos.textNode.data) { + const clickIndex = getClickIndex(pos); - // let parsedAttrs: Attribute[]; + let parsedAttrs: Attribute[]; - // try { - // parsedAttrs = attribute_parser.lexAndParse(getPreprocessedData(currentValueRef.current), true); - // } catch (e: unknown) { - // // the input is incorrect because the user messed up with it and now needs to fix it manually - // console.log(e); - // return null; - // } - onClick={(e) => { - // Prevent automatic hiding of the context menu due to the button being clicked. - e.stopPropagation(); - if (isMenuOpen) { + try { + parsedAttrs = attribute_parser.lexAndParse(getPreprocessedData(currentValueRef.current), true); + } catch (e: unknown) { + // the input is incorrect because the user messed up with it and now needs to fix it manually + console.log(e); + return null; + } + + let matchedAttr: Attribute | null = null; + + for (const attr of parsedAttrs) { + if (attr.startIndex !== undefined && clickIndex > attr.startIndex && + attr.endIndex !== undefined && clickIndex <= attr.endIndex) { + matchedAttr = attr; + break; + } + } + + setTimeout(() => { + if (matchedAttr) { + attributeDetailWidget.showAttributeDetail({ + allAttributes: parsedAttrs, + attribute: matchedAttr, + isOwned: true, + x: e.pageX, + y: e.pageY + }); + setState("showAttributeDetail"); + } else { + setState("showHelpTooltip"); + } + }, 100); + } else { + setState("showHelpTooltip"); + } + }} + onKeyDown={() => attributeDetailWidget.hide()} + onBlur={() => save()} + onInitialized={() => editorRef.current?.focus()} + disableNewlines disableSpellcheck + /> + +
+ { needsSaving && } + + { + // Prevent automatic hiding of the context menu due to the button being clicked. + e.stopPropagation(); + if (isMenuOpen) { // If we re-show the menu, ContextMenu.show() will call hide() // and immediately trigger onHide. Suppress that transient hide. - suppressNextOnHide.current = true; - } - setIsMenuOpen(true); - - contextMenu.show({ - x: e.pageX, - y: e.pageY, - orientation: "left", - - items: [ - { - title: t( - "attribute_editor.add_new_label", - ), - command: "addNewLabel", - uiIcon: "bx bx-hash", + suppressNextOnHide.current = true; + } + setIsMenuOpen(true); + + contextMenu.show({ + x: e.pageX, + y: e.pageY, + orientation: "left", + items: [ + { title: t("attribute_editor.add_new_label"), command: "addNewLabel", uiIcon: "bx bx-hash" }, + { title: t("attribute_editor.add_new_relation"), command: "addNewRelation", uiIcon: "bx bx-transfer" }, + { kind: "separator" }, + { title: t("attribute_editor.add_new_label_definition"), command: "addNewLabelDefinition", uiIcon: "bx bx-empty" }, + { title: t("attribute_editor.add_new_relation_definition"), command: "addNewRelationDefinition", uiIcon: "bx bx-empty" } + ], + selectMenuItemHandler: (item) => handleAddNewAttributeCommand(item.command), + onHide: () => { + if (suppressNextOnHide.current) { + suppressNextOnHide.current = false; + return; + } + setIsMenuOpen(false); }, - { - title: t( - "attribute_editor.add_new_relation", - ), - command: "addNewRelation", - uiIcon: "bx bx-transfer", - }, - { kind: "separator" }, - { - title: t( - "attribute_editor.add_new_label_definition", - ), - command: - "addNewLabelDefinition", - uiIcon: "bx bx-empty", - }, - { - title: t( - "attribute_editor.add_new_relation_definition", - ), - command: - "addNewRelationDefinition", - uiIcon: "bx bx-empty", - }, - ], - selectMenuItemHandler: (item) => - handleAddNewAttributeCommand( - item.command, - ), - onHide: () => { - if (suppressNextOnHide.current) { - suppressNextOnHide.current = false; - return; - } - setIsMenuOpen(false); - }, - }); - }} - /> + }); + }} + /> +
{ error && ( From 4bc1d93b75cc414efcff200ffd8701551293288f Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Thu, 16 Apr 2026 21:07:47 +0300 Subject: [PATCH 262/482] style/about dialog: lower CSS selector specificity --- apps/client/src/widgets/dialogs/about.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css index 023a62d8e7..06e4d9f47c 100644 --- a/apps/client/src/widgets/dialogs/about.css +++ b/apps/client/src/widgets/dialogs/about.css @@ -1,6 +1,6 @@ .about-dialog { - body.light-theme & { + :where(body.light-theme &) { --donate-button-color: #e33f3b; &.nightly { @@ -8,9 +8,9 @@ } } - body.dark-theme & { + :where(body.dark-theme &) { --donate-button-color: #fba6a5; - + &.nightly { --modal-background-color: #23182b; } From 889e44363ac55b4e0f184145a40ed864b111b3b6 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Thu, 16 Apr 2026 22:26:56 +0300 Subject: [PATCH 263/482] feat(client): make view source searchable --- apps/client/src/widgets/ribbon/NoteActions.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/client/src/widgets/ribbon/NoteActions.tsx b/apps/client/src/widgets/ribbon/NoteActions.tsx index 679b624c10..6490542d78 100644 --- a/apps/client/src/widgets/ribbon/NoteActions.tsx +++ b/apps/client/src/widgets/ribbon/NoteActions.tsx @@ -75,7 +75,8 @@ export function NoteContextMenu({ note, noteContext, itemsAtStart, itemsNearNote const noteType = useNoteProperty(note, "type") ?? ""; const [viewType] = useNoteLabel(note, "viewType"); const canBeConvertedToAttachment = note?.isEligibleForConversionToAttachment(); - const isSearchable = ["text", "code", "book", "mindMap", "doc", "spreadsheet"].includes(noteType); + const isSourceView = noteContext?.viewScope?.viewMode === "source"; + const isSearchable = isSourceView || ["text", "code", "book", "mindMap", "doc", "spreadsheet"].includes(noteType); const isInOptionsOrHelp = note?.noteId.startsWith("_options") || note?.noteId.startsWith("_help"); const isExportableToImage = ["mermaid", "mindMap"].includes(noteType); const isContentAvailable = note.isContentAvailable(); From 999bfbc1185da4896993d9d05cabcf9e0b239719 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Thu, 16 Apr 2026 22:52:02 +0300 Subject: [PATCH 264/482] feat(launch_bar): add a context menu to every option to easily remove them --- .../src/menus/launcher_button_context_menu.ts | 101 ++++++++++++++++++ .../src/translations/en/translation.json | 3 + .../widgets/launch_bar/BookmarkButtons.tsx | 18 +++- .../src/widgets/launch_bar/CalendarWidget.tsx | 1 + .../src/widgets/launch_bar/GenericButtons.tsx | 19 ++-- .../widgets/launch_bar/HistoryNavigation.tsx | 80 ++++++++------ .../widgets/launch_bar/LauncherContainer.tsx | 14 +-- .../launch_bar/LauncherDefinitions.tsx | 10 +- .../ProtectedSessionStatusWidget.tsx | 6 +- .../widgets/launch_bar/SidebarChatButton.tsx | 5 +- .../src/widgets/launch_bar/SpacerWidget.tsx | 29 +++-- .../src/widgets/launch_bar/SyncStatus.tsx | 8 +- .../widgets/launch_bar/launch_bar_widgets.tsx | 17 ++- .../widgets/mobile_widgets/TabSwitcher.tsx | 5 +- 14 files changed, 237 insertions(+), 79 deletions(-) create mode 100644 apps/client/src/menus/launcher_button_context_menu.ts diff --git a/apps/client/src/menus/launcher_button_context_menu.ts b/apps/client/src/menus/launcher_button_context_menu.ts new file mode 100644 index 0000000000..1272deb859 --- /dev/null +++ b/apps/client/src/menus/launcher_button_context_menu.ts @@ -0,0 +1,101 @@ +import type { ToggleInParentResponse } from "@triliumnext/commons"; + +import type FNote from "../entities/fnote.js"; +import branchService from "../services/branches.js"; +import { t } from "../services/i18n.js"; +import server from "../services/server.js"; +import toast from "../services/toast.js"; +import contextMenu, { type ContextMenuEvent, type MenuItem } from "./context_menu.js"; + +const VISIBLE_LAUNCHER_PARENTS = ["_lbVisibleLaunchers", "_lbMobileVisibleLaunchers"]; + +function getVisibleLauncherBranch(launcherNote: FNote) { + return launcherNote.getParentBranches().find((b) => VISIBLE_LAUNCHER_PARENTS.includes(b.parentNoteId)); +} + +function getBookmarkBranch(launcherNote: FNote) { + return launcherNote.getParentBranches().find((b) => b.parentNoteId === "_lbBookmarks"); +} + +async function removeFromLaunchBar(launcherNote: FNote) { + const bookmarkBranch = getBookmarkBranch(launcherNote); + if (bookmarkBranch) { + // Individual bookmarks are represented via a branch under `_lbBookmarks`; removing them + // from the launch bar is the same as unbookmarking the note. + const resp = await server.put( + `notes/${launcherNote.noteId}/toggle-in-parent/_lbBookmarks/false` + ); + if (!resp.success && resp.message) { + toast.showError(resp.message); + } + return; + } + + const launcherBranch = getVisibleLauncherBranch(launcherNote); + if (!launcherBranch) return; + + const isMobileLauncher = launcherBranch.parentNoteId === "_lbMobileVisibleLaunchers"; + // Branch IDs in the hidden subtree follow the `${parentNoteId}_${noteId}` convention, + // so the branch linking `_lb(Mobile)?Root` to the "available" launchers root is predictable. + const targetBranchId = isMobileLauncher + ? "_lbMobileRoot__lbMobileAvailableLaunchers" + : "_lbRoot__lbAvailableLaunchers"; + await branchService.moveToParentNote([launcherBranch.branchId], targetBranchId); +} + +export function canRemoveFromLaunchBar(launcherNote: FNote | null | undefined) { + if (!launcherNote) return false; + return !!(getVisibleLauncherBranch(launcherNote) || getBookmarkBranch(launcherNote)); +} + +export interface ShowLauncherContextMenuOptions { + /** Menu items specific to this launcher (e.g. "Open in new tab" for note-based launchers). They appear above the "Remove from launch bar" item. */ + extraItems?: MenuItem[]; + /** Handler for the {@link extraItems}. The "Remove from launch bar" item is handled internally and will not be forwarded. */ + onCommand?: (command: T | undefined) => void; +} + +const REMOVE_COMMAND = "__removeFromLaunchBar__"; + +/** + * Displays the launch bar icon context menu. When the launcher can be removed (i.e. it is a direct + * child of the visible launchers root or of `_lbBookmarks`), a "Remove from launch bar" entry is + * appended. Extra items can be supplied to preserve launcher-specific actions (e.g. "Open in new tab"). + */ +export async function showLauncherContextMenu( + launcherNote: FNote | null | undefined, + e: ContextMenuEvent, + options: ShowLauncherContextMenuOptions = {} +) { + e.preventDefault(); + + const items = [...(options.extraItems ?? [])] as MenuItem[]; + + if (canRemoveFromLaunchBar(launcherNote)) { + if (items.length > 0) { + items.push({ kind: "separator" }); + } + items.push({ + title: t("launcher_button_context_menu.remove_from_launch_bar"), + command: REMOVE_COMMAND, + uiIcon: "bx bx-x-circle" + }); + } + + if (items.length === 0) return; + + contextMenu.show({ + x: e.pageX ?? 0, + y: e.pageY ?? 0, + items, + selectMenuItemHandler: ({ command }) => { + if (command === REMOVE_COMMAND) { + if (launcherNote) { + void removeFromLaunchBar(launcherNote); + } + return; + } + options.onCommand?.(command as T | undefined); + } + }); +} diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 190edb998d..2efdf6b542 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -1928,6 +1928,9 @@ "move-to-available-launchers": "Move to available launchers", "duplicate-launcher": "Duplicate launcher " }, + "launcher_button_context_menu": { + "remove_from_launch_bar": "Remove from launch bar" + }, "highlighting": { "title": "Code Blocks", "description": "Controls the syntax highlighting for code blocks inside text notes, code notes will not be affected.", diff --git a/apps/client/src/widgets/launch_bar/BookmarkButtons.tsx b/apps/client/src/widgets/launch_bar/BookmarkButtons.tsx index 81f2c6e878..d4e761fd9d 100644 --- a/apps/client/src/widgets/launch_bar/BookmarkButtons.tsx +++ b/apps/client/src/widgets/launch_bar/BookmarkButtons.tsx @@ -10,11 +10,11 @@ import { useChildNotes, useNote, useNoteIcon, useNoteLabelBoolean } from "../rea import NoteLink from "../react/NoteLink"; import ResponsiveContainer from "../react/ResponsiveContainer"; import { CustomNoteLauncher, launchCustomNoteLauncher } from "./GenericButtons"; -import { LaunchBarContext, LaunchBarDropdownButton, useLauncherIconAndTitle } from "./launch_bar_widgets"; +import { LaunchBarContext, LaunchBarDropdownButton, launcherContextMenuHandler, LauncherNoteProps, useLauncherIconAndTitle } from "./launch_bar_widgets"; const PARENT_NOTE_ID = "_lbBookmarks"; -export default function BookmarkButtons() { +export default function BookmarkButtons({ launcherNote }: LauncherNoteProps) { const { isHorizontalLayout } = useContext(LaunchBarContext); const style = useMemo(() => ({ display: "flex", @@ -22,20 +22,27 @@ export default function BookmarkButtons() { contain: "none" }), [ isHorizontalLayout ]); const childNotes = useChildNotes(PARENT_NOTE_ID); + const bookmarks = childNotes?.map(childNote => ); + const showContextMenu = launcherContextMenuHandler(launcherNote); return ( - {childNotes?.map(childNote => )} +
e.target === e.currentTarget && showContextMenu?.(e)} + > + {bookmarks}
} mobile={ - {childNotes?.map(childNote => )} + {bookmarks} } /> @@ -90,6 +97,7 @@ function BookmarkFolder({ note }: { note: FNote }) { return ( diff --git a/apps/client/src/widgets/launch_bar/CalendarWidget.tsx b/apps/client/src/widgets/launch_bar/CalendarWidget.tsx index 1972672232..21e4689cff 100644 --- a/apps/client/src/widgets/launch_bar/CalendarWidget.tsx +++ b/apps/client/src/widgets/launch_bar/CalendarWidget.tsx @@ -58,6 +58,7 @@ export default function CalendarWidget({ launcherNote }: LauncherNoteProps) { return ( { const dateNote = appContext.tabManager.getActiveContextNote()?.getOwnedLabelValue("dateNote"); diff --git a/apps/client/src/widgets/launch_bar/GenericButtons.tsx b/apps/client/src/widgets/launch_bar/GenericButtons.tsx index 59c158dec1..ba29b303b5 100644 --- a/apps/client/src/widgets/launch_bar/GenericButtons.tsx +++ b/apps/client/src/widgets/launch_bar/GenericButtons.tsx @@ -1,7 +1,8 @@ import { useCallback } from "preact/hooks"; -import appContext from "../../components/app_context"; +import appContext, { CommandNames } from "../../components/app_context"; import FNote from "../../entities/fnote"; +import { showLauncherContextMenu } from "../../menus/launcher_button_context_menu"; import link_context_menu from "../../menus/link_context_menu"; import { isCtrlKey } from "../../services/utils"; import { useGlobalShortcut, useNoteLabel } from "../react/hooks"; @@ -13,7 +14,7 @@ export function CustomNoteLauncher(props: { getHoistedNoteId?: (launcherNote: FNote) => string | null; keyboardShortcut?: string; }) { - const { launcherNote, getTargetNoteId } = props; + const { launcherNote, getTargetNoteId, getHoistedNoteId } = props; const { icon, title } = useLauncherIconAndTitle(launcherNote); const launch = useCallback(async (evt: MouseEvent | KeyboardEvent) => { @@ -31,11 +32,17 @@ export function CustomNoteLauncher(props: { onClick={launch} onAuxClick={launch} onContextMenu={async evt => { - evt.preventDefault(); const targetNoteId = await getTargetNoteId(launcherNote); - if (targetNoteId) { - link_context_menu.openContextMenu(targetNoteId, evt); - } + const hoistedNoteId = getHoistedNoteId?.(launcherNote) ?? null; + const linkItems = targetNoteId ? link_context_menu.getItems(evt) : []; + await showLauncherContextMenu(launcherNote, evt, { + extraItems: linkItems, + onCommand: (command) => { + if (command && targetNoteId) { + link_context_menu.handleLinkContextMenuItem(command, evt, targetNoteId, {}, hoistedNoteId); + } + } + }); }} /> ); diff --git a/apps/client/src/widgets/launch_bar/HistoryNavigation.tsx b/apps/client/src/widgets/launch_bar/HistoryNavigation.tsx index 3e0ce6f967..11ad476312 100644 --- a/apps/client/src/widgets/launch_bar/HistoryNavigation.tsx +++ b/apps/client/src/widgets/launch_bar/HistoryNavigation.tsx @@ -3,6 +3,7 @@ import { useMemo } from "preact/hooks"; import FNote from "../../entities/fnote"; import contextMenu, { MenuCommandItem } from "../../menus/context_menu"; +import { showLauncherContextMenu } from "../../menus/launcher_button_context_menu"; import froca from "../../services/froca"; import link from "../../services/link"; import tree from "../../services/tree"; @@ -25,46 +26,61 @@ export default function HistoryNavigationButton({ launcherNote, command }: Histo icon={icon} text={title} triggerCommand={command} - onContextMenu={webContents ? handleHistoryContextMenu(webContents) : undefined} + onContextMenu={async (e) => { + const items = webContents ? await getHistoryItems(webContents) : []; + showLauncherContextMenu(launcherNote, e, { + extraItems: items, + onCommand: (cmd) => { + if (cmd && webContents) { + webContents.navigationHistory.goToIndex(parseInt(cmd, 10)); + } + } + }); + }} /> ); } +async function getHistoryItems(webContents: WebContents): Promise[]> { + if (webContents.navigationHistory.length() < 2) return []; + + let items: MenuCommandItem[] = []; + + const history = webContents.navigationHistory.getAllEntries(); + const activeIndex = webContents.navigationHistory.getActiveIndex(); + + for (const idx in history) { + const { noteId, notePath } = link.parseNavigationStateFromUrl(history[idx].url); + if (!noteId || !notePath) continue; + + const title = await tree.getNotePathTitle(notePath); + const index = parseInt(idx, 10); + const note = froca.getNoteFromCache(noteId); + + items.push({ + title, + command: idx, + checked: index === activeIndex, + enabled: index !== activeIndex, + uiIcon: note?.getIcon() + }); + } + + items.reverse(); + + if (items.length > HISTORY_LIMIT) { + items = items.slice(0, HISTORY_LIMIT); + } + + return items; +} + export function handleHistoryContextMenu(webContents: WebContents) { return async (e: MouseEvent) => { e.preventDefault(); - if (!webContents || webContents.navigationHistory.length() < 2) { - return; - } - - let items: MenuCommandItem[] = []; - - const history = webContents.navigationHistory.getAllEntries(); - const activeIndex = webContents.navigationHistory.getActiveIndex(); - - for (const idx in history) { - const { noteId, notePath } = link.parseNavigationStateFromUrl(history[idx].url); - if (!noteId || !notePath) continue; - - const title = await tree.getNotePathTitle(notePath); - const index = parseInt(idx, 10); - const note = froca.getNoteFromCache(noteId); - - items.push({ - title, - command: idx, - checked: index === activeIndex, - enabled: index !== activeIndex, - uiIcon: note?.getIcon() - }); - } - - items.reverse(); - - if (items.length > HISTORY_LIMIT) { - items = items.slice(0, HISTORY_LIMIT); - } + const items = await getHistoryItems(webContents); + if (items.length === 0) return; contextMenu.show({ x: e.pageX, diff --git a/apps/client/src/widgets/launch_bar/LauncherContainer.tsx b/apps/client/src/widgets/launch_bar/LauncherContainer.tsx index d5d443084b..dd3ae9d6e3 100644 --- a/apps/client/src/widgets/launch_bar/LauncherContainer.tsx +++ b/apps/client/src/widgets/launch_bar/LauncherContainer.tsx @@ -83,13 +83,13 @@ function initBuiltinWidget(note: FNote, isHorizontalLayout: boolean) { const baseSize = parseInt(note.getLabelValue("baseSize") || "40"); const growthFactor = parseInt(note.getLabelValue("growthFactor") || "100"); - return ; + return ; case "bookmarks": - return ; + return ; case "protectedSession": - return ; + return ; case "syncStatus": - return ; + return ; case "backInHistoryButton": return ; case "forwardInHistoryButton": @@ -97,11 +97,11 @@ function initBuiltinWidget(note: FNote, isHorizontalLayout: boolean) { case "todayInJournal": return ; case "quickSearch": - return ; + return ; case "mobileTabSwitcher": - return ; + return ; case "sidebarChat": - return isExperimentalFeatureEnabled("llm") ? : undefined; + return isExperimentalFeatureEnabled("llm") ? : undefined; default: console.warn(`Unrecognized builtin widget ${builtinWidget} for launcher ${note.noteId} "${note.title}"`); } diff --git a/apps/client/src/widgets/launch_bar/LauncherDefinitions.tsx b/apps/client/src/widgets/launch_bar/LauncherDefinitions.tsx index 408780224c..89bdb39194 100644 --- a/apps/client/src/widgets/launch_bar/LauncherDefinitions.tsx +++ b/apps/client/src/widgets/launch_bar/LauncherDefinitions.tsx @@ -14,7 +14,7 @@ import QuickSearchWidget from "../quick_search"; import { useGlobalShortcut, useLegacyWidget, useNoteLabel, useNoteRelationTarget } from "../react/hooks"; import { ParentComponent } from "../react/react_utils"; import { CustomNoteLauncher } from "./GenericButtons"; -import { LaunchBarActionButton, LaunchBarContext, LauncherNoteProps, useLauncherIconAndTitle } from "./launch_bar_widgets"; +import { LaunchBarActionButton, LaunchBarContext, launcherContextMenuHandler, LauncherNoteProps, useLauncherIconAndTitle } from "./launch_bar_widgets"; export function CommandButton({ launcherNote }: LauncherNoteProps) { const { icon, title } = useLauncherIconAndTitle(launcherNote); @@ -22,6 +22,7 @@ export function CommandButton({ launcherNote }: LauncherNoteProps) { return command && ( new QuickSearchWidget(), []); const parentComponent = useContext(ParentComponent) as BasicWidget | null; @@ -101,7 +103,7 @@ export function QuickSearchLauncherWidget() { parentComponent?.contentSized(); return ( -
+
{isEnabled && }
); @@ -136,7 +138,7 @@ export function CustomWidget({ launcherNote }: LauncherNoteProps) { }, [ widgetNote ]); return ( -
+
{widget && ( ("type" in widget && widget.type === "preact-launcher-widget") ? diff --git a/apps/client/src/widgets/launch_bar/ProtectedSessionStatusWidget.tsx b/apps/client/src/widgets/launch_bar/ProtectedSessionStatusWidget.tsx index 539643d4f9..8e9bcf3bf9 100644 --- a/apps/client/src/widgets/launch_bar/ProtectedSessionStatusWidget.tsx +++ b/apps/client/src/widgets/launch_bar/ProtectedSessionStatusWidget.tsx @@ -1,21 +1,23 @@ import { useState } from "preact/hooks"; import protected_session_holder from "../../services/protected_session_holder"; -import { LaunchBarActionButton } from "./launch_bar_widgets"; +import { LaunchBarActionButton, LauncherNoteProps } from "./launch_bar_widgets"; import { useTriliumEvent } from "../react/hooks"; import { t } from "../../services/i18n"; -export default function ProtectedSessionStatusWidget() { +export default function ProtectedSessionStatusWidget({ launcherNote }: LauncherNoteProps) { const protectedSessionAvailable = useProtectedSessionAvailable(); return ( protectedSessionAvailable ? ( ) : ( { // Open right pane if hidden, or toggle it if visible appContext.triggerEvent("toggleRightPane", {}); @@ -16,6 +16,7 @@ export default function SidebarChatButton() { return ( { - e.preventDefault(); - contextMenu.show({ - x: e.pageX, - y: e.pageY, - items: [{ title: t("spacer.configure_launchbar"), command: "showLaunchBarSubtree", uiIcon: "bx " + (isMobile() ? "bx-mobile" : "bx-sidebar") }], - selectMenuItemHandler: ({ command }) => { - if (command) { - appContext.triggerCommand(command); - } - } - }); - }} + onContextMenu={launcherNote ? (e) => showLauncherContextMenu(launcherNote, e, { + extraItems: [{ + title: t("spacer.configure_launchbar"), + command: "showLaunchBarSubtree", + uiIcon: "bx " + (isMobile() ? "bx-mobile" : "bx-sidebar") + }], + onCommand: (command) => { + if (command) appContext.triggerCommand(command); + } + }) : undefined} /> ) } diff --git a/apps/client/src/widgets/launch_bar/SyncStatus.tsx b/apps/client/src/widgets/launch_bar/SyncStatus.tsx index 651b89c075..27678df17b 100644 --- a/apps/client/src/widgets/launch_bar/SyncStatus.tsx +++ b/apps/client/src/widgets/launch_bar/SyncStatus.tsx @@ -9,6 +9,7 @@ import sync from "../../services/sync"; import { escapeQuotes } from "../../services/utils"; import ws, { subscribeToMessages, unsubscribeToMessage } from "../../services/ws"; import { useStaticTooltip, useTriliumOption } from "../react/hooks"; +import { launcherContextMenuHandler, LauncherNoteProps } from "./launch_bar_widgets"; type SyncState = "unknown" | "in-progress" | "connected-with-changes" | "connected-no-changes" @@ -49,7 +50,7 @@ const STATE_MAPPINGS: Record = { } }; -export default function SyncStatus() { +export default function SyncStatus({ launcherNote }: LauncherNoteProps) { const syncState = useSyncStatus(); const { title, icon, hasChanges } = STATE_MAPPINGS[syncState]; const spanRef = useRef(null); @@ -60,7 +61,10 @@ export default function SyncStatus() { }); return (syncServerHost && -
+
) { +/** Builds the default right-click handler that shows the launch-bar icon context menu (with the "Remove from launch bar" entry). Used by widgets that render a raw element rather than going through {@link LaunchBarActionButton} / {@link LaunchBarDropdownButton}. */ +export function launcherContextMenuHandler(launcherNote: FNote | null | undefined) { + if (!launcherNote) return undefined; + return (e: MouseEvent) => showLauncherContextMenu(launcherNote, e); +} + +export function LaunchBarActionButton({ className, launcherNote, onContextMenu, ...props }: Omit & { launcherNote?: FNote }) { const { isHorizontalLayout } = useContext(LaunchBarContext); return ( @@ -30,15 +37,20 @@ export function LaunchBarActionButton({ className, ...props }: Omit ); } -export function LaunchBarDropdownButton({ children, icon, dropdownOptions, ...props }: Pick & { icon: string }) { +export function LaunchBarDropdownButton({ children, icon, dropdownOptions, launcherNote, buttonProps, ...props }: Pick & { icon: string, launcherNote?: FNote }) { const { isHorizontalLayout } = useContext(LaunchBarContext); const titlePosition = getTitlePosition(isHorizontalLayout); + const resolvedButtonProps = launcherNote && !buttonProps?.onContextMenu + ? { ...buttonProps, onContextMenu: launcherContextMenuHandler(launcherNote) } + : buttonProps; + return ( {children} ); diff --git a/apps/client/src/widgets/mobile_widgets/TabSwitcher.tsx b/apps/client/src/widgets/mobile_widgets/TabSwitcher.tsx index 32f21b94ab..a1aa0f68e4 100644 --- a/apps/client/src/widgets/mobile_widgets/TabSwitcher.tsx +++ b/apps/client/src/widgets/mobile_widgets/TabSwitcher.tsx @@ -14,7 +14,7 @@ import froca from "../../services/froca"; import { t } from "../../services/i18n"; import type { ViewMode, ViewScope } from "../../services/link"; import { NoteContent } from "../collections/legacy/ListOrGridView"; -import { LaunchBarActionButton } from "../launch_bar/launch_bar_widgets"; +import { LaunchBarActionButton, LauncherNoteProps } from "../launch_bar/launch_bar_widgets"; import { ICON_MAPPINGS } from "../note_bars/CollectionProperties"; import ActionButton from "../react/ActionButton"; import { useActiveNoteContext, useNoteIcon, useTriliumEvents } from "../react/hooks"; @@ -30,13 +30,14 @@ const VIEW_MODE_ICON_MAPPINGS: Record, string> = { ocr: "bx bx-text" }; -export default function TabSwitcher() { +export default function TabSwitcher({ launcherNote }: LauncherNoteProps) { const [ shown, setShown ] = useState(false); const mainNoteContexts = useMainNoteContexts(); return ( <> Date: Thu, 16 Apr 2026 23:00:41 +0300 Subject: [PATCH 265/482] fix(launch_bar): some context menus intercepted by browser --- apps/client/src/widgets/launch_bar/GenericButtons.tsx | 3 +++ apps/client/src/widgets/launch_bar/HistoryNavigation.tsx | 2 ++ 2 files changed, 5 insertions(+) diff --git a/apps/client/src/widgets/launch_bar/GenericButtons.tsx b/apps/client/src/widgets/launch_bar/GenericButtons.tsx index ba29b303b5..6933233a66 100644 --- a/apps/client/src/widgets/launch_bar/GenericButtons.tsx +++ b/apps/client/src/widgets/launch_bar/GenericButtons.tsx @@ -32,6 +32,9 @@ export function CustomNoteLauncher(props: { onClick={launch} onAuxClick={launch} onContextMenu={async evt => { + // Must preventDefault synchronously — awaiting getTargetNoteId first would let the + // native browser context menu open before showLauncherContextMenu gets a chance to. + evt.preventDefault(); const targetNoteId = await getTargetNoteId(launcherNote); const hoistedNoteId = getHoistedNoteId?.(launcherNote) ?? null; const linkItems = targetNoteId ? link_context_menu.getItems(evt) : []; diff --git a/apps/client/src/widgets/launch_bar/HistoryNavigation.tsx b/apps/client/src/widgets/launch_bar/HistoryNavigation.tsx index 11ad476312..b35e38f337 100644 --- a/apps/client/src/widgets/launch_bar/HistoryNavigation.tsx +++ b/apps/client/src/widgets/launch_bar/HistoryNavigation.tsx @@ -27,6 +27,8 @@ export default function HistoryNavigationButton({ launcherNote, command }: Histo text={title} triggerCommand={command} onContextMenu={async (e) => { + // Prevent the native menu synchronously before awaiting history items. + e.preventDefault(); const items = webContents ? await getHistoryItems(webContents) : []; showLauncherContextMenu(launcherNote, e, { extraItems: items, From 3dc93fde379b23e9b3cd0da8659da9678a519cb4 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Thu, 16 Apr 2026 23:00:57 +0300 Subject: [PATCH 266/482] feat(desktop): disable cache in dev mode --- apps/server/src/services/window.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/apps/server/src/services/window.ts b/apps/server/src/services/window.ts index 5b98af008b..6415f85aa7 100644 --- a/apps/server/src/services/window.ts +++ b/apps/server/src/services/window.ts @@ -5,14 +5,21 @@ import url from "url"; import app_info from "./app_info.js"; import cls from "./cls.js"; import customDictionary from "./custom_dictionary.js"; -import { initPrintingHandlers } from "./printing.js"; import keyboardActionsService from "./keyboard_actions.js"; import log from "./log.js"; import optionService from "./options.js"; import port from "./port.js"; +import { initPrintingHandlers } from "./printing.js"; import { RESOURCE_DIR } from "./resource_dir.js"; import sqlInit from "./sql_init.js"; -import { isMac, isWindows } from "./utils.js"; +import { isDev, isMac, isWindows } from "./utils.js"; + +// In dev mode, disable Chromium's HTTP cache so stale assets cached from a +// previous production run (which served `max-age: 1y` headers) don't shadow +// freshly built dev output. Must be set before the app's `ready` event. +if (isDev) { + electron.app.commandLine.appendSwitch("disable-http-cache"); +} // Prevent the window being garbage collected let mainWindow: BrowserWindow | null; From bf9ee984069160fab207aa280823ae5c36100b32 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Thu, 16 Apr 2026 23:05:01 +0300 Subject: [PATCH 267/482] docs(user): add license --- .../doc_notes/en/User Guide/!!!meta.json | 2 +- .../en/User Guide/User Guide/AI.html | 2 + .../SQL Console.html | 1 - .../User Guide/Advanced Usage/Sharing.html | 6 +- .../Navigation/Jump to.html | 1 - .../Notes/Printing & Exporting as PDF.html | 1 - .../UI Elements/New Layout.html | 9 +- .../UI Elements/Recent Changes.html | 1 - .../UI Elements/Split View.html | 3 +- .../User Guide/Collections/Calendar.html | 2 - .../User Guide/Collections/Geo Map.html | 1 - .../Installation & Setup/Backup.html | 2 +- .../User Guide/Miscellaneous/License.html | 520 ++++++++++++++++++ .../Note Types/Mermaid Diagrams.html | 1 - .../User Guide/Note Types/Saved Search.html | 1 - .../User Guide/Note Types/Text.html | 1 - .../Note Types/Text/Insert buttons.html | 2 - .../User Guide/Note Types/Text/Tables.html | 3 +- .../Scripting/Backend scripts/Events.html | 1 - .../Custom Widgets/Word count widget.html | 4 +- .../Developer Guide/Documentation.md | 2 +- docs/User Guide/!!!meta.json | 41 +- .../User Guide/Miscellaneous/License.md | 237 ++++++++ 23 files changed, 805 insertions(+), 39 deletions(-) create mode 100644 apps/server/src/assets/doc_notes/en/User Guide/User Guide/Miscellaneous/License.html create mode 100644 docs/User Guide/User Guide/Miscellaneous/License.md diff --git a/apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json b/apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json index 65558c848b..1f707817a0 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json +++ b/apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json @@ -1 +1 @@ -[{"id":"_help_BOCnjTMBCoxW","title":"Feature Highlights","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Feature Highlights"},{"name":"iconClass","value":"bx bx-star","type":"label"}]},{"id":"_help_Otzi9La2YAUX","title":"Installation & Setup","type":"book","attributes":[{"name":"iconClass","value":"bx bx-cog","type":"label"}],"children":[{"id":"_help_poXkQfguuA0U","title":"Desktop Installation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation"},{"name":"iconClass","value":"bx bx-desktop","type":"label"}],"children":[{"id":"_help_nRqcgfTb97uV","title":"Using the desktop application as a server","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/Using the desktop application "},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_Rp0q8bSP6Ayl","title":"System Requirements","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/System Requirements"},{"name":"iconClass","value":"bx bx-chip","type":"label"}]},{"id":"_help_Un4wj2Mak2Ky","title":"Nix flake","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/Nix flake"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]}]},{"id":"_help_WOcw2SLH6tbX","title":"Server Installation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation"},{"name":"iconClass","value":"bx bx-server","type":"label"}],"children":[{"id":"_help_Dgg7bR3b6K9j","title":"1. Installing the server","type":"book","attributes":[{"name":"iconClass","value":"bx bx-folder","type":"label"}],"children":[{"id":"_help_3tW6mORuTHnB","title":"Packaged version for Linux","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Packaged version for Linux"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]},{"id":"_help_rWX5eY045zbE","title":"Using Docker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Docker"},{"name":"iconClass","value":"bx bxl-docker","type":"label"}]},{"id":"_help_moVgBcoxE3EK","title":"On NixOS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/On NixOS"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]},{"id":"_help_J1Bb6lVlwU5T","title":"Manually","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Manually"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}]},{"id":"_help_DCmT6e7clMoP","title":"Using Kubernetes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Kubernetes"},{"name":"iconClass","value":"bx bxl-kubernetes","type":"label"}]},{"id":"_help_klCWNks3ReaQ","title":"Multiple server instances","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Multiple server instances"},{"name":"iconClass","value":"bx bxs-user-account","type":"label"}]}]},{"id":"_help_vcjrb3VVYPZI","title":"2. Reverse proxy","type":"book","attributes":[{"name":"iconClass","value":"bx bx-folder","type":"label"}],"children":[{"id":"_help_ud6MShXL4WpO","title":"Nginx","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Nginx"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_fDLvzOx29Pfg","title":"Apache using Docker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Apache using Docker"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_LLzSMXACKhUs","title":"Trusted proxy","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Trusted proxy"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_5ERVJb9s4FRD","title":"Traefik","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Traefik"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_l2VkvOwUNfZj","title":"HTTPS (TLS)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/HTTPS (TLS)"},{"name":"iconClass","value":"bx bx-lock-alt","type":"label"}]},{"id":"_help_0hzsNCP31IAB","title":"Authentication","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Authentication"},{"name":"iconClass","value":"bx bx-user","type":"label"}]},{"id":"_help_7DAiwaf8Z7Rz","title":"Multi-Factor Authentication","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Multi-Factor Authentication"},{"name":"iconClass","value":"bx bx-stopwatch","type":"label"}]},{"id":"_help_Un4wj2Mak2Ky","title":"Nix flake","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Nix flake.clone"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_yeEaYqosGLSh","title":"Third-party cloud hosting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Third-party cloud hosting"},{"name":"iconClass","value":"bx bx-cloud","type":"label"}]},{"id":"_help_iGTnKjubbXkA","title":"System Requirements","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/System Requirements"},{"name":"iconClass","value":"bx bx-chip","type":"label"}]}]},{"id":"_help_cbkrhQjrkKrh","title":"Synchronization","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Synchronization"},{"name":"iconClass","value":"bx bx-sync","type":"label"}]},{"id":"_help_RDslemsQ6gCp","title":"Mobile Frontend","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Mobile Frontend"},{"name":"iconClass","value":"bx bx-mobile-alt","type":"label"}]},{"id":"_help_MtPxeAWVAzMg","title":"Web Clipper","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Web Clipper"},{"name":"iconClass","value":"bx bx-paperclip","type":"label"}]},{"id":"_help_n1lujUxCwipy","title":"Upgrading TriliumNext","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Upgrading TriliumNext"},{"name":"iconClass","value":"bx bx-up-arrow-alt","type":"label"}]},{"id":"_help_ODY7qQn5m2FT","title":"Backup","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Backup"},{"name":"iconClass","value":"bx bx-hdd","type":"label"}]},{"id":"_help_tAassRL4RSQL","title":"Data directory","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Data directory"},{"name":"iconClass","value":"bx bx-folder-open","type":"label"}]}]},{"id":"_help_gh7bpGYxajRS","title":"Basic Concepts and Features","type":"book","attributes":[{"name":"iconClass","value":"bx bx-help-circle","type":"label"}],"children":[{"id":"_help_Vc8PjrjAGuOp","title":"UI Elements","type":"book","attributes":[{"name":"iconClass","value":"bx bx-window-alt","type":"label"}],"children":[{"id":"_help_x0JgW8UqGXvq","title":"Vertical and horizontal layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Vertical and horizontal layout"},{"name":"iconClass","value":"bx bxs-layout","type":"label"}]},{"id":"_help_x3i7MxGccDuM","title":"Global menu","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Global menu"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_oPVyFC7WL2Lp","title":"Note Tree","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree"},{"name":"iconClass","value":"bx bxs-tree-alt","type":"label"}],"children":[{"id":"_help_YtSN43OrfzaA","title":"Note tree contextual menu","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Note tree contextual menu"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_yTjUdsOi4CIE","title":"Multiple selection","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Multiple selection"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_DvdZhoQZY9Yd","title":"Keyboard shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Keyboard shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_wyaGBBQrl4i3","title":"Hiding the subtree","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Hiding the subtree"},{"name":"iconClass","value":"bx bx-hide","type":"label"}]}]},{"id":"_help_BlN9DFI679QC","title":"Ribbon","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Ribbon"},{"name":"iconClass","value":"bx bx-dots-horizontal","type":"label"}]},{"id":"_help_3seOhtN8uLIY","title":"Tabs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Tabs"},{"name":"iconClass","value":"bx bx-dock-top","type":"label"}]},{"id":"_help_xYmIYSP6wE3F","title":"Launch Bar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Launch Bar"},{"name":"iconClass","value":"bx bx-sidebar","type":"label"}]},{"id":"_help_8YBEPzcpUgxw","title":"Note buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note buttons"},{"name":"iconClass","value":"bx bx-dots-vertical-rounded","type":"label"}]},{"id":"_help_4TIF1oA4VQRO","title":"Options","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Options"},{"name":"iconClass","value":"bx bx-cog","type":"label"}]},{"id":"_help_luNhaphA37EO","title":"Split View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View"},{"name":"iconClass","value":"bx bx-dock-right","type":"label"}]},{"id":"_help_XpOYSgsLkTJy","title":"Floating buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Floating buttons"},{"name":"iconClass","value":"bx bx-rectangle","type":"label"}]},{"id":"_help_RnaPdbciOfeq","title":"Right Sidebar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Right Sidebar"},{"name":"iconClass","value":"bx bxs-dock-right","type":"label"}]},{"id":"_help_r5JGHN99bVKn","title":"Recent Changes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Recent Changes"},{"name":"iconClass","value":"bx bx-history","type":"label"}]},{"id":"_help_ny318J39E5Z0","title":"Zoom","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Zoom"},{"name":"iconClass","value":"bx bx-zoom-in","type":"label"}]},{"id":"_help_lgKX7r3aL30x","title":"Note Tooltip","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tooltip"},{"name":"iconClass","value":"bx bx-message-detail","type":"label"}]},{"id":"_help_IjZS7iK5EXtb","title":"New Layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/New Layout"},{"name":"iconClass","value":"bx bx-layout","type":"label"}],"children":[{"id":"_help_I6p2a06hdnL6","title":"Breadcrumb","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/New Layout/Breadcrumb"},{"name":"iconClass","value":"bx bx-chevron-right","type":"label"}]},{"id":"_help_AlJ73vBCjWDw","title":"Status bar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/New Layout/Status bar"},{"name":"iconClass","value":"bx bx-dock-bottom","type":"label"}]}]}]},{"id":"_help_BFs8mudNFgCS","title":"Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes"},{"name":"iconClass","value":"bx bx-notepad","type":"label"}],"children":[{"id":"_help_p9kXRFAkwN4o","title":"Note Icons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_0vhv7lsOLy82","title":"Attachments","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Attachments"},{"name":"iconClass","value":"bx bx-paperclip","type":"label"}]},{"id":"_help_IakOLONlIfGI","title":"Cloning Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes"},{"name":"iconClass","value":"bx bx-duplicate","type":"label"}],"children":[{"id":"_help_TBwsyfadTA18","title":"Branch prefix","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes/Branch prefix"},{"name":"iconClass","value":"bx bx-rename","type":"label"}]}]},{"id":"_help_bwg0e8ewQMak","title":"Protected Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Protected Notes"},{"name":"iconClass","value":"bx bx-lock-alt","type":"label"}]},{"id":"_help_MKmLg5x6xkor","title":"Archived Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Archived Notes"},{"name":"iconClass","value":"bx bx-box","type":"label"}]},{"id":"_help_vZWERwf8U3nx","title":"Note Revisions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions"},{"name":"iconClass","value":"bx bx-history","type":"label"}]},{"id":"_help_aGlEvb9hyDhS","title":"Sorting Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Sorting Notes"},{"name":"iconClass","value":"bx bx-sort-up","type":"label"}]},{"id":"_help_NRnIZmSMc5sj","title":"Printing & Exporting as PDF","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF"},{"name":"iconClass","value":"bx bx-printer","type":"label"}]},{"id":"_help_CoFPLs3dRlXc","title":"Read-Only Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes"},{"name":"iconClass","value":"bx bx-edit-alt","type":"label"}]},{"id":"_help_0ESUbbAxVnoK","title":"Note List","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note List"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]}]},{"id":"_help_wArbEsdSae6g","title":"Navigation","type":"book","attributes":[{"name":"iconClass","value":"bx bx-navigation","type":"label"}],"children":[{"id":"_help_kBrnXNG3Hplm","title":"Tree Concepts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Tree Concepts"},{"name":"iconClass","value":"bx bx-pyramid","type":"label"}]},{"id":"_help_MMiBEQljMQh2","title":"Note Navigation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation"},{"name":"iconClass","value":"bx bxs-navigation","type":"label"}]},{"id":"_help_Ms1nauBra7gq","title":"Quick search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Quick search"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]},{"id":"_help_F1r9QtzQLZqm","title":"Jump to...","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to"},{"name":"iconClass","value":"bx bx-send","type":"label"}]},{"id":"_help_eIg8jdvaoNNd","title":"Search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Search"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]},{"id":"_help_u3YFHC9tQlpm","title":"Bookmarks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks"},{"name":"iconClass","value":"bx bx-bookmarks","type":"label"}]},{"id":"_help_OR8WJ7Iz9K4U","title":"Note Hoisting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Note Hoisting"},{"name":"iconClass","value":"bx bxs-chevrons-up","type":"label"}]},{"id":"_help_ZjLYv08Rp3qC","title":"Quick edit","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Quick edit"},{"name":"iconClass","value":"bx bx-edit","type":"label"}]},{"id":"_help_9sRHySam5fXb","title":"Workspaces","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Workspaces"},{"name":"iconClass","value":"bx bx-door-open","type":"label"}]},{"id":"_help_xWtq5NUHOwql","title":"Similar Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Similar Notes"},{"name":"iconClass","value":"bx bx-bar-chart","type":"label"}]},{"id":"_help_McngOG2jbUWX","title":"Search in note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Search in note"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]}]},{"id":"_help_A9Oc6YKKc65v","title":"Keyboard Shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Keyboard Shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_Wy267RK4M69c","title":"Themes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes"},{"name":"iconClass","value":"bx bx-palette","type":"label"}],"children":[{"id":"_help_VbjZvtUek0Ln","title":"Theme Gallery","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes/Theme Gallery"},{"name":"iconClass","value":"bx bx-book-reader","type":"label"}]},{"id":"_help_gOKqSJgXLcIj","title":"Icon Packs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes/Icon Packs"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_mHbBMPDPkVV5","title":"Import & Export","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export"},{"name":"iconClass","value":"bx bx-import","type":"label"}],"children":[{"id":"_help_Oau6X9rCuegd","title":"Markdown","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}],"children":[{"id":"_help_rJ9grSgoExl9","title":"Supported syntax","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown/Supported syntax"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}]}]},{"id":"_help_syuSEKf2rUGr","title":"Evernote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Evernote"},{"name":"iconClass","value":"bx bx-window-open","type":"label"}],"children":[{"id":"_help_dj3j8dG4th4l","title":"Process internal links by title","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_GnhlmrATVqcH","title":"OneNote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/OneNote"},{"name":"iconClass","value":"bx bx-window-open","type":"label"}]}]},{"id":"_help_rC3pL2aptaRE","title":"Zen mode","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Zen mode"},{"name":"iconClass","value":"bx bxs-yin-yang","type":"label"}]},{"id":"_help_YzMcWlCVeW09","title":"Active content","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Active content"},{"name":"iconClass","value":"bx bxs-widget","type":"label"}]}]},{"id":"_help_s3YCWHBfmYuM","title":"Quick Start","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Quick Start"},{"name":"iconClass","value":"bx bx-run","type":"label"}]},{"id":"_help_i6dbnitykE5D","title":"FAQ","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/FAQ"},{"name":"iconClass","value":"bx bx-question-mark","type":"label"}]},{"id":"_help_KSZ04uQ2D1St","title":"Note Types","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types"},{"name":"iconClass","value":"bx bx-edit","type":"label"}],"children":[{"id":"_help_iPIMuisry3hd","title":"Text","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text"},{"name":"iconClass","value":"bx bx-note","type":"label"}],"children":[{"id":"_help_NwBbFdNZ9h7O","title":"Block quotes & admonitions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Block quotes & admonitions"},{"name":"iconClass","value":"bx bx-info-circle","type":"label"}]},{"id":"_help_oSuaNgyyKnhu","title":"Bookmarks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Bookmarks"},{"name":"iconClass","value":"bx bx-bookmark","type":"label"}]},{"id":"_help_veGu4faJErEM","title":"Content language & Right-to-left support","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Content language & Right-to-le"},{"name":"iconClass","value":"bx bx-align-right","type":"label"}]},{"id":"_help_2x0ZAX9ePtzV","title":"Cut to subnote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Cut to subnote"},{"name":"iconClass","value":"bx bx-cut","type":"label"}]},{"id":"_help_UYuUB1ZekNQU","title":"Developer-specific formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Developer-specific formatting"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}],"children":[{"id":"_help_QxEyIjRBizuC","title":"Code blocks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Developer-specific formatting/Code blocks"},{"name":"iconClass","value":"bx bx-code","type":"label"}]}]},{"id":"_help_AgjCISero73a","title":"Footnotes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Footnotes"},{"name":"iconClass","value":"bx bx-bracket","type":"label"}]},{"id":"_help_nRhnJkTT8cPs","title":"Formatting toolbar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Formatting toolbar"},{"name":"iconClass","value":"bx bx-text","type":"label"}]},{"id":"_help_Gr6xFaF6ioJ5","title":"General formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/General formatting"},{"name":"iconClass","value":"bx bx-bold","type":"label"}]},{"id":"_help_AxshuNRegLAv","title":"Highlights list","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Highlights list"},{"name":"iconClass","value":"bx bx-highlight","type":"label"}]},{"id":"_help_mT0HEkOsz6i1","title":"Images","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Images"},{"name":"iconClass","value":"bx bx-image-alt","type":"label"}],"children":[{"id":"_help_0Ofbk1aSuVRu","title":"Image references","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Images/Image references"},{"name":"iconClass","value":"bx bxs-file-image","type":"label"}]}]},{"id":"_help_nBAXQFj20hS1","title":"Include Note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Include Note"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_CohkqWQC1iBv","title":"Insert buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Insert buttons"},{"name":"iconClass","value":"bx bx-plus","type":"label"}]},{"id":"_help_oiVPnW8QfnvS","title":"Keyboard shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Keyboard shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_QEAPj01N5f7w","title":"Links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links"},{"name":"iconClass","value":"bx bx-link-alt","type":"label"}],"children":[{"id":"_help_3IDVtesTQ8ds","title":"External links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links/External links"},{"name":"iconClass","value":"bx bx-link-external","type":"label"}]},{"id":"_help_hrZ1D00cLbal","title":"Internal (reference) links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links/Internal (reference) links"},{"name":"iconClass","value":"bx bx-link","type":"label"}]}]},{"id":"_help_S6Xx8QIWTV66","title":"Lists","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Lists"},{"name":"iconClass","value":"bx bx-list-ul","type":"label"}]},{"id":"_help_QrtTYPmdd1qq","title":"Markdown-like formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Markdown-like formatting"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}]},{"id":"_help_YfYAtQBcfo5V","title":"Math Equations","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Math Equations"},{"name":"iconClass","value":"bx bx-math","type":"label"}]},{"id":"_help_dEHYtoWWi8ct","title":"Other features","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Other features"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_gLt3vA97tMcp","title":"Premium features","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features"},{"name":"iconClass","value":"bx bx-star","type":"label"}],"children":[{"id":"_help_ZlN4nump6EbW","title":"Slash Commands","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Slash Commands"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_pwc194wlRzcH","title":"Text Snippets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Text Snippets"},{"name":"iconClass","value":"bx bx-align-left","type":"label"}]},{"id":"_help_5wZallV2Qo1t","title":"Format Painter","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Format Painter"},{"name":"iconClass","value":"bx bxs-paint-roll","type":"label"}]}]},{"id":"_help_oBo3iHIZnbG2","title":"Spell Check","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Spell Check"},{"name":"iconClass","value":"bx bx-check-double","type":"label"}]},{"id":"_help_BFvAtE74rbP6","title":"Table of contents","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Table of contents"},{"name":"iconClass","value":"bx bx-heading","type":"label"}]},{"id":"_help_NdowYOC1GFKS","title":"Tables","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Tables"},{"name":"iconClass","value":"bx bx-table","type":"label"}]}]},{"id":"_help_6f9hih2hXXZk","title":"Code","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Code"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_m523cpzocqaD","title":"Saved Search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Saved Search"},{"name":"iconClass","value":"bx bx-file-find","type":"label"}]},{"id":"_help_iRwzGnHPzonm","title":"Relation Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Relation Map"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_bdUJEHsAPYQR","title":"Note Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Note Map"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_HcABDtFCkbFN","title":"Render Note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Render Note"},{"name":"iconClass","value":"bx bx-extension","type":"label"}]},{"id":"_help_s1aBHPd79XYj","title":"Mermaid Diagrams","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mermaid Diagrams"},{"name":"iconClass","value":"bx bx-selection","type":"label"}],"children":[{"id":"_help_RH6yLjjWJHof","title":"ELK layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mermaid Diagrams/ELK layout"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_WWgeUaBb7UfC","title":"Syntax reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://mermaid.js.org/intro/syntax-reference.html"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_grjYqerjn243","title":"Canvas","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Canvas"},{"name":"iconClass","value":"bx bx-pen","type":"label"}]},{"id":"_help_1vHRoWCEjj0L","title":"Web View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Web View"},{"name":"iconClass","value":"bx bx-globe-alt","type":"label"}]},{"id":"_help_gBbsAeiuUxI5","title":"Mind Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mind Map"},{"name":"iconClass","value":"bx bx-sitemap","type":"label"}]},{"id":"_help_W8vYD3Q1zjCR","title":"File","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File"},{"name":"iconClass","value":"bx bx-file-blank","type":"label"}],"children":[{"id":"_help_XJGJrpu7F9sh","title":"PDFs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File/PDFs"},{"name":"iconClass","value":"bx bxs-file-pdf","type":"label"}]},{"id":"_help_AjqEeiDUOzj4","title":"Videos","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File/Videos"},{"name":"iconClass","value":"bx bx-video","type":"label"}]}]},{"id":"_help_GWHEkY4I4OE3","title":"Spreadsheets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Spreadsheets"},{"name":"iconClass","value":"bx bx-table","type":"label"}]}]},{"id":"_help_GTwFsgaA0lCt","title":"Collections","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections"},{"name":"iconClass","value":"bx bx-book","type":"label"}],"children":[{"id":"_help_xWbu3jpNWapp","title":"Calendar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Calendar"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]},{"id":"_help_2FvYrpmOXm29","title":"Table","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Table"},{"name":"iconClass","value":"bx bx-table","type":"label"}]},{"id":"_help_CtBQqbwXDx1w","title":"Kanban Board","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Kanban Board"},{"name":"iconClass","value":"bx bx-columns","type":"label"}]},{"id":"_help_81SGnPGMk7Xc","title":"Geo Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Geo Map"},{"name":"iconClass","value":"bx bx-map-alt","type":"label"}]},{"id":"_help_zP3PMqaG71Ct","title":"Presentation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Presentation"},{"name":"iconClass","value":"bx bx-slideshow","type":"label"}]},{"id":"_help_8QqnMzx393bx","title":"Grid View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Grid View"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_mULW0Q3VojwY","title":"List View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/List View"},{"name":"iconClass","value":"bx bx-list-ul","type":"label"}]},{"id":"_help_CssoWBu8I7jF","title":"Collection Properties","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Collection Properties"},{"name":"iconClass","value":"bx bx-cog","type":"label"}]}]},{"id":"_help_BgmBlOIl72jZ","title":"Troubleshooting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting"},{"name":"iconClass","value":"bx bx-bug","type":"label"}],"children":[{"id":"_help_wy8So3yZZlH9","title":"Reporting issues","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Reporting issues"},{"name":"iconClass","value":"bx bx-bug-alt","type":"label"}]},{"id":"_help_x59R8J8KV5Bp","title":"Anonymized Database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Anonymized Database"},{"name":"iconClass","value":"bx bx-low-vision","type":"label"}]},{"id":"_help_qzNzp9LYQyPT","title":"Error logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs"},{"name":"iconClass","value":"bx bx-comment-error","type":"label"}],"children":[{"id":"_help_bnyigUA2UK7s","title":"Backend (server) logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs/Backend (server) logs"},{"name":"iconClass","value":"bx bx-server","type":"label"}]},{"id":"_help_9yEHzMyFirZR","title":"Frontend logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs/Frontend logs"},{"name":"iconClass","value":"bx bx-window-alt","type":"label"}]}]},{"id":"_help_vdlYGAcpXAgc","title":"Synchronization fails with 504 Gateway Timeout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Synchronization fails with 504"},{"name":"iconClass","value":"bx bx-error","type":"label"}]},{"id":"_help_s8alTXmpFR61","title":"Refreshing the application","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Refreshing the application"},{"name":"iconClass","value":"bx bx-refresh","type":"label"}]}]},{"id":"_help_pKK96zzmvBGf","title":"Theme development","type":"book","attributes":[{"name":"iconClass","value":"bx bx-palette","type":"label"}],"children":[{"id":"_help_7NfNr5pZpVKV","title":"Creating a custom theme","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Creating a custom theme"},{"name":"iconClass","value":"bx bxs-color","type":"label"}]},{"id":"_help_WFGzWeUK6arS","title":"Customize the Next theme","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Customize the Next theme"},{"name":"iconClass","value":"bx bx-news","type":"label"}]},{"id":"_help_WN5z4M8ASACJ","title":"Reference","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Reference"},{"name":"iconClass","value":"bx bx-book-open","type":"label"}]},{"id":"_help_AlhDUqhENtH7","title":"Custom app-wide CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Custom app-wide CSS"},{"name":"iconClass","value":"bx bxs-file-css","type":"label"}]},{"id":"_help_g1mlRoU8CsqC","title":"Creating an icon pack","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Creating an icon pack"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_tC7s2alapj8V","title":"Advanced Usage","type":"book","attributes":[{"name":"iconClass","value":"bx bx-rocket","type":"label"}],"children":[{"id":"_help_zEY4DaJG4YT5","title":"Attributes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes"},{"name":"iconClass","value":"bx bx-list-check","type":"label"}],"children":[{"id":"_help_HI6GBBIduIgv","title":"Labels","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Labels"},{"name":"iconClass","value":"bx bx-hash","type":"label"}]},{"id":"_help_Cq5X6iKQop6R","title":"Relations","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Relations"},{"name":"iconClass","value":"bx bx-transfer","type":"label"}]},{"id":"_help_bwZpz2ajCEwO","title":"Attribute Inheritance","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Attribute Inheritance"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_OFXdgB2nNk1F","title":"Promoted Attributes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Promoted Attributes"},{"name":"iconClass","value":"bx bx-table","type":"label"}]}]},{"id":"_help_KC1HB96bqqHX","title":"Templates","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Templates"},{"name":"iconClass","value":"bx bx-copy","type":"label"}]},{"id":"_help_BCkXAVs63Ttv","title":"Note Map (Link map, Tree map)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note Map (Link map, Tree map)"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_R9pX4DGra2Vt","title":"Sharing","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing"},{"name":"iconClass","value":"bx bx-share-alt","type":"label"}],"children":[{"id":"_help_Qjt68inQ2bRj","title":"Serving directly the content of a note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Serving directly the content o"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_ycBFjKrrwE9p","title":"Exporting static HTML for web publishing","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Exporting static HTML for web "},{"name":"iconClass","value":"bx bxs-file-html","type":"label"}]},{"id":"_help_sLIJ6f1dkJYW","title":"Reverse proxy configuration","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Reverse proxy configuration"},{"name":"iconClass","value":"bx bx-world","type":"label"}]}]},{"id":"_help_5668rwcirq1t","title":"Advanced Showcases","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases"},{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_l0tKav7yLHGF","title":"Day Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Day Notes"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]},{"id":"_help_R7abl2fc6Mxi","title":"Weight Tracker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Weight Tracker"},{"name":"iconClass","value":"bx bx-line-chart","type":"label"}]},{"id":"_help_xYjQUYhpbUEW","title":"Task Manager","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Task Manager"},{"name":"iconClass","value":"bx bx-calendar-check","type":"label"}]}]},{"id":"_help_J5Ex1ZrMbyJ6","title":"Custom Request Handler","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Custom Request Handler"},{"name":"iconClass","value":"bx bx-globe","type":"label"}]},{"id":"_help_d3fAXQ2diepH","title":"Custom Resource Providers","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Custom Resource Providers"},{"name":"iconClass","value":"bx bxs-file-plus","type":"label"}]},{"id":"_help_pgxEVkzLl1OP","title":"ETAPI (REST API)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/ETAPI (REST API)"},{"name":"iconClass","value":"bx bx-extension","type":"label"}],"children":[{"id":"_help_9qPsTWBorUhQ","title":"API Reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/rest-api/etapi/"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_47ZrP6FNuoG8","title":"Default Note Title","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Default Note Title"},{"name":"iconClass","value":"bx bx-edit-alt","type":"label"}]},{"id":"_help_wX4HbRucYSDD","title":"Database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database"},{"name":"iconClass","value":"bx bx-data","type":"label"}],"children":[{"id":"_help_oyIAJ9PvvwHX","title":"Manually altering the database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Manually altering the database"},{"name":"iconClass","value":"bx bxs-edit","type":"label"}],"children":[{"id":"_help_YKWqdJhzi2VY","title":"SQL Console","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Manually altering the database/SQL Console"},{"name":"iconClass","value":"bx bx-data","type":"label"}]}]},{"id":"_help_6tZeKvSHEUiB","title":"Demo Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Demo Notes"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_Gzjqa934BdH4","title":"Configuration (config.ini or environment variables)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or e"},{"name":"iconClass","value":"bx bx-cog","type":"label"}],"children":[{"id":"_help_c5xB8m4g2IY6","title":"Trilium instance","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Trilium instance"},{"name":"iconClass","value":"bx bx-windows","type":"label"}]},{"id":"_help_LWtBjFej3wX3","title":"Cross-Origin Resource Sharing (CORS)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Cross-Origin Resource Sharing "},{"name":"iconClass","value":"bx bx-lock","type":"label"}]}]},{"id":"_help_ivYnonVFBxbQ","title":"Bulk Actions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Bulk Actions"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_4FahAwuGTAwC","title":"Note source","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note source"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_1YeN2MzFUluU","title":"Technologies used","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used"},{"name":"iconClass","value":"bx bx-pyramid","type":"label"}],"children":[{"id":"_help_MI26XDLSAlCD","title":"CKEditor","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/CKEditor"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_N4IDkixaDG9C","title":"MindElixir","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/MindElixir"},{"name":"iconClass","value":"bx bx-sitemap","type":"label"}]},{"id":"_help_H0mM1lTxF9JI","title":"Excalidraw","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/Excalidraw"},{"name":"iconClass","value":"bx bx-pen","type":"label"}]},{"id":"_help_MQHyy2dIFgxS","title":"Leaflet","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/Leaflet"},{"name":"iconClass","value":"bx bx-map-alt","type":"label"}]}]},{"id":"_help_m1lbrzyKDaRB","title":"Note ID","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note ID"},{"name":"iconClass","value":"bx bx-hash","type":"label"}]},{"id":"_help_0vTSyvhPTAOz","title":"Internal API","type":"book","attributes":[{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_z8O2VG4ZZJD7","title":"API Reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/rest-api/internal/"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_2mUhVmZK8RF3","title":"Hidden Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Hidden Notes"},{"name":"iconClass","value":"bx bx-hide","type":"label"}]},{"id":"_help_uYF7pmepw27K","title":"Metrics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Metrics"},{"name":"iconClass","value":"bx bxs-data","type":"label"}],"children":[{"id":"_help_bOP3TB56fL1V","title":"grafana-dashboard.json","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_64ZTlUPgEPtW","title":"Safe mode","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Safe mode"},{"name":"iconClass","value":"bx bxs-virus-block","type":"label"}]},{"id":"_help_HAIOFBoYIIdO","title":"Nightly release","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Nightly release"},{"name":"iconClass","value":"bx bx-moon","type":"label"}]},{"id":"_help_ZmT9ln8XJX2o","title":"Read-only database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Read-only database"},{"name":"iconClass","value":"bx bx-book-reader","type":"label"}]}]},{"id":"_help_GBBMSlVSOIGP","title":"AI","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/AI"},{"name":"iconClass","value":"bx bx-bot","type":"label"}]},{"id":"_help_CdNpE2pqjmI6","title":"Scripting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting"},{"name":"iconClass","value":"bx bxs-file-js","type":"label"}],"children":[{"id":"_help_yIhgI5H7A2Sm","title":"Frontend Basics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics"},{"name":"iconClass","value":"bx bx-window","type":"label"}],"children":[{"id":"_help_MgibgPcfeuGz","title":"Custom Widgets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets"},{"name":"iconClass","value":"bx bxs-widget","type":"label"}],"children":[{"id":"_help_SynTBQiBsdYJ","title":"Widget Basics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Widget Basics"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_GhurYZjh8e1V","title":"Note context aware widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Note context aware widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_M8IppdwVHSjG","title":"Right pane widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Right pane widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_YNxAqkI5Kg1M","title":"Word count widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Word count widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_VqGQnnPGnqAU","title":"CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/CSS"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_gMkgcLJ6jBkg","title":"Troubleshooting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Troubleshooting"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_es8OU2GuguFU","title":"Examples","type":"book","attributes":[{"name":"iconClass","value":"bx bx-code-alt","type":"label"}],"children":[{"id":"_help_TjLYAo3JMO8X","title":"\"New Task\" launcher button","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/New Task launcher button"},{"name":"iconClass","value":"bx bx-task","type":"label"}]},{"id":"_help_7kZPMD0uFwkH","title":"Downloading responses from Google Forms","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/Downloading responses from Goo"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_DL92EjAaXT26","title":"Using promoted attributes to configure scripts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/Using promoted attributes to c"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_4Gn3psZKsfSm","title":"Launch Bar Widgets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets"},{"name":"iconClass","value":"bx bx-dock-left","type":"label"}],"children":[{"id":"_help_IPArqVfDQ4We","title":"Note Title Widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets/Note Title Widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_gcI7RPbaNSh3","title":"Analog Watch","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets/Analog Watch"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_KLsqhjaqh1QW","title":"Preact","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact"},{"name":"iconClass","value":"bx bxl-react","type":"label"}],"children":[{"id":"_help_Bqde6BvPo05g","title":"Component libraries","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/Component libraries"},{"name":"iconClass","value":"bx bxs-component","type":"label"}]},{"id":"_help_ykYtbM9k3a7B","title":"Hooks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/Hooks"},{"name":"iconClass","value":"bx bx-question-mark","type":"label"}]},{"id":"_help_Sg9GrCtyftZf","title":"CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/CSS"},{"name":"iconClass","value":"bx bxs-file-css","type":"label"}]},{"id":"_help_RSssb9S3xgSr","title":"Built-in components","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/Built-in components"},{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_i9B4IW7b6V6z","title":"Widget showcase","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}]}]},{"id":"_help_SPirpZypehBG","title":"Backend scripts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts"},{"name":"iconClass","value":"bx bx-server","type":"label"}],"children":[{"id":"_help_fZ2IGYFXjkEy","title":"Server-side imports","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts/Server-side imports"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_GPERMystNGTB","title":"Events","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts/Events"},{"name":"iconClass","value":"bx bx-rss","type":"label"}]}]},{"id":"_help_wqXwKJl6VpNk","title":"Common concepts","type":"book","attributes":[{"name":"iconClass","value":"bx bxl-nodejs","type":"label"}],"children":[{"id":"_help_hA834UaHhSNn","title":"Script bundles","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Common concepts/Script bundles"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_GLks18SNjxmC","title":"Script API","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Script API"},{"name":"iconClass","value":"bx bx-code-curly","type":"label"}],"children":[{"id":"_help_Q2z6av6JZVWm","title":"Frontend API","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/frontend"},{"name":"iconClass","value":"bx bx-folder","type":"label"}],"enforceAttributes":true,"children":[{"id":"_help_habiZ3HU8Kw8","title":"FNote","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/frontend/interfaces/FNote.html"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_MEtfsqa5VwNi","title":"Backend API","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/backend"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true},{"id":"_help_ApVHZ8JY5ofC","title":"Day.js","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Script API/Day.js"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]}]},{"id":"_help_vElnKeDNPSVl","title":"Logging","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Logging"},{"name":"iconClass","value":"bx bx-terminal","type":"label"}]},{"id":"_help_cNpC0ITcfX0N","title":"Breaking changes","type":"book","attributes":[{"name":"iconClass","value":"bx bx-up-arrow-alt","type":"label"}],"children":[{"id":"_help_fqAK6opjUagR","title":"v0.103.0: Removal of axios","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Breaking changes/v0.103.0 Removal of axios"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_pAJ0jWz16xFm","title":"v0.103.0: `cheerio` is now deprecated","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Breaking changes/v0.103.0 `cheerio` is now depr"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_72dxvnbnkDFY","title":"v0.102.0: Upgrade to jQuery 4.0.0","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Breaking changes/v0.102.0 Upgrade to jQuery.0.0"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}]},{"id":"_help_Fm0j45KqyHpU","title":"Miscellaneous","type":"book","attributes":[{"name":"iconClass","value":"bx bx-info-circle","type":"label"}],"children":[{"id":"_help_WFbFXrgnDyyU","title":"Privacy Policy","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/Privacy Policy"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_NcsmUYZRWEW4","title":"Patterns of personal knowledge","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/Patterns of personal knowledge"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}] \ No newline at end of file +[{"id":"_help_BOCnjTMBCoxW","title":"Feature Highlights","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Feature Highlights"},{"name":"iconClass","value":"bx bx-star","type":"label"}]},{"id":"_help_Otzi9La2YAUX","title":"Installation & Setup","type":"book","attributes":[{"name":"iconClass","value":"bx bx-cog","type":"label"}],"children":[{"id":"_help_poXkQfguuA0U","title":"Desktop Installation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation"},{"name":"iconClass","value":"bx bx-desktop","type":"label"}],"children":[{"id":"_help_nRqcgfTb97uV","title":"Using the desktop application as a server","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/Using the desktop application "},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_Rp0q8bSP6Ayl","title":"System Requirements","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/System Requirements"},{"name":"iconClass","value":"bx bx-chip","type":"label"}]},{"id":"_help_Un4wj2Mak2Ky","title":"Nix flake","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/Nix flake"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]}]},{"id":"_help_WOcw2SLH6tbX","title":"Server Installation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation"},{"name":"iconClass","value":"bx bx-server","type":"label"}],"children":[{"id":"_help_Dgg7bR3b6K9j","title":"1. Installing the server","type":"book","attributes":[{"name":"iconClass","value":"bx bx-folder","type":"label"}],"children":[{"id":"_help_3tW6mORuTHnB","title":"Packaged version for Linux","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Packaged version for Linux"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]},{"id":"_help_rWX5eY045zbE","title":"Using Docker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Docker"},{"name":"iconClass","value":"bx bxl-docker","type":"label"}]},{"id":"_help_moVgBcoxE3EK","title":"On NixOS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/On NixOS"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]},{"id":"_help_J1Bb6lVlwU5T","title":"Manually","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Manually"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}]},{"id":"_help_DCmT6e7clMoP","title":"Using Kubernetes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Kubernetes"},{"name":"iconClass","value":"bx bxl-kubernetes","type":"label"}]},{"id":"_help_klCWNks3ReaQ","title":"Multiple server instances","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Multiple server instances"},{"name":"iconClass","value":"bx bxs-user-account","type":"label"}]}]},{"id":"_help_vcjrb3VVYPZI","title":"2. Reverse proxy","type":"book","attributes":[{"name":"iconClass","value":"bx bx-folder","type":"label"}],"children":[{"id":"_help_ud6MShXL4WpO","title":"Nginx","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Nginx"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_fDLvzOx29Pfg","title":"Apache using Docker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Apache using Docker"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_LLzSMXACKhUs","title":"Trusted proxy","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Trusted proxy"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_5ERVJb9s4FRD","title":"Traefik","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Traefik"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_l2VkvOwUNfZj","title":"HTTPS (TLS)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/HTTPS (TLS)"},{"name":"iconClass","value":"bx bx-lock-alt","type":"label"}]},{"id":"_help_0hzsNCP31IAB","title":"Authentication","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Authentication"},{"name":"iconClass","value":"bx bx-user","type":"label"}]},{"id":"_help_7DAiwaf8Z7Rz","title":"Multi-Factor Authentication","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Multi-Factor Authentication"},{"name":"iconClass","value":"bx bx-stopwatch","type":"label"}]},{"id":"_help_Un4wj2Mak2Ky","title":"Nix flake","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Nix flake.clone"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_yeEaYqosGLSh","title":"Third-party cloud hosting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Third-party cloud hosting"},{"name":"iconClass","value":"bx bx-cloud","type":"label"}]},{"id":"_help_iGTnKjubbXkA","title":"System Requirements","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/System Requirements"},{"name":"iconClass","value":"bx bx-chip","type":"label"}]}]},{"id":"_help_cbkrhQjrkKrh","title":"Synchronization","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Synchronization"},{"name":"iconClass","value":"bx bx-sync","type":"label"}]},{"id":"_help_RDslemsQ6gCp","title":"Mobile Frontend","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Mobile Frontend"},{"name":"iconClass","value":"bx bx-mobile-alt","type":"label"}]},{"id":"_help_MtPxeAWVAzMg","title":"Web Clipper","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Web Clipper"},{"name":"iconClass","value":"bx bx-paperclip","type":"label"}]},{"id":"_help_n1lujUxCwipy","title":"Upgrading TriliumNext","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Upgrading TriliumNext"},{"name":"iconClass","value":"bx bx-up-arrow-alt","type":"label"}]},{"id":"_help_ODY7qQn5m2FT","title":"Backup","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Backup"},{"name":"iconClass","value":"bx bx-hdd","type":"label"}]},{"id":"_help_tAassRL4RSQL","title":"Data directory","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Data directory"},{"name":"iconClass","value":"bx bx-folder-open","type":"label"}]}]},{"id":"_help_gh7bpGYxajRS","title":"Basic Concepts and Features","type":"book","attributes":[{"name":"iconClass","value":"bx bx-help-circle","type":"label"}],"children":[{"id":"_help_Vc8PjrjAGuOp","title":"UI Elements","type":"book","attributes":[{"name":"iconClass","value":"bx bx-window-alt","type":"label"}],"children":[{"id":"_help_x0JgW8UqGXvq","title":"Vertical and horizontal layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Vertical and horizontal layout"},{"name":"iconClass","value":"bx bxs-layout","type":"label"}]},{"id":"_help_x3i7MxGccDuM","title":"Global menu","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Global menu"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_oPVyFC7WL2Lp","title":"Note Tree","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree"},{"name":"iconClass","value":"bx bxs-tree-alt","type":"label"}],"children":[{"id":"_help_YtSN43OrfzaA","title":"Note tree contextual menu","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Note tree contextual menu"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_yTjUdsOi4CIE","title":"Multiple selection","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Multiple selection"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_DvdZhoQZY9Yd","title":"Keyboard shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Keyboard shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_wyaGBBQrl4i3","title":"Hiding the subtree","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Hiding the subtree"},{"name":"iconClass","value":"bx bx-hide","type":"label"}]}]},{"id":"_help_BlN9DFI679QC","title":"Ribbon","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Ribbon"},{"name":"iconClass","value":"bx bx-dots-horizontal","type":"label"}]},{"id":"_help_3seOhtN8uLIY","title":"Tabs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Tabs"},{"name":"iconClass","value":"bx bx-dock-top","type":"label"}]},{"id":"_help_xYmIYSP6wE3F","title":"Launch Bar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Launch Bar"},{"name":"iconClass","value":"bx bx-sidebar","type":"label"}]},{"id":"_help_8YBEPzcpUgxw","title":"Note buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note buttons"},{"name":"iconClass","value":"bx bx-dots-vertical-rounded","type":"label"}]},{"id":"_help_4TIF1oA4VQRO","title":"Options","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Options"},{"name":"iconClass","value":"bx bx-cog","type":"label"}]},{"id":"_help_luNhaphA37EO","title":"Split View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View"},{"name":"iconClass","value":"bx bx-dock-right","type":"label"}]},{"id":"_help_XpOYSgsLkTJy","title":"Floating buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Floating buttons"},{"name":"iconClass","value":"bx bx-rectangle","type":"label"}]},{"id":"_help_RnaPdbciOfeq","title":"Right Sidebar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Right Sidebar"},{"name":"iconClass","value":"bx bxs-dock-right","type":"label"}]},{"id":"_help_r5JGHN99bVKn","title":"Recent Changes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Recent Changes"},{"name":"iconClass","value":"bx bx-history","type":"label"}]},{"id":"_help_ny318J39E5Z0","title":"Zoom","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Zoom"},{"name":"iconClass","value":"bx bx-zoom-in","type":"label"}]},{"id":"_help_lgKX7r3aL30x","title":"Note Tooltip","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tooltip"},{"name":"iconClass","value":"bx bx-message-detail","type":"label"}]},{"id":"_help_IjZS7iK5EXtb","title":"New Layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/New Layout"},{"name":"iconClass","value":"bx bx-layout","type":"label"}],"children":[{"id":"_help_I6p2a06hdnL6","title":"Breadcrumb","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/New Layout/Breadcrumb"},{"name":"iconClass","value":"bx bx-chevron-right","type":"label"}]},{"id":"_help_AlJ73vBCjWDw","title":"Status bar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/New Layout/Status bar"},{"name":"iconClass","value":"bx bx-dock-bottom","type":"label"}]}]}]},{"id":"_help_BFs8mudNFgCS","title":"Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes"},{"name":"iconClass","value":"bx bx-notepad","type":"label"}],"children":[{"id":"_help_p9kXRFAkwN4o","title":"Note Icons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_0vhv7lsOLy82","title":"Attachments","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Attachments"},{"name":"iconClass","value":"bx bx-paperclip","type":"label"}]},{"id":"_help_IakOLONlIfGI","title":"Cloning Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes"},{"name":"iconClass","value":"bx bx-duplicate","type":"label"}],"children":[{"id":"_help_TBwsyfadTA18","title":"Branch prefix","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes/Branch prefix"},{"name":"iconClass","value":"bx bx-rename","type":"label"}]}]},{"id":"_help_bwg0e8ewQMak","title":"Protected Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Protected Notes"},{"name":"iconClass","value":"bx bx-lock-alt","type":"label"}]},{"id":"_help_MKmLg5x6xkor","title":"Archived Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Archived Notes"},{"name":"iconClass","value":"bx bx-box","type":"label"}]},{"id":"_help_vZWERwf8U3nx","title":"Note Revisions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions"},{"name":"iconClass","value":"bx bx-history","type":"label"}]},{"id":"_help_aGlEvb9hyDhS","title":"Sorting Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Sorting Notes"},{"name":"iconClass","value":"bx bx-sort-up","type":"label"}]},{"id":"_help_NRnIZmSMc5sj","title":"Printing & Exporting as PDF","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF"},{"name":"iconClass","value":"bx bx-printer","type":"label"}]},{"id":"_help_CoFPLs3dRlXc","title":"Read-Only Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes"},{"name":"iconClass","value":"bx bx-edit-alt","type":"label"}]},{"id":"_help_0ESUbbAxVnoK","title":"Note List","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note List"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]}]},{"id":"_help_wArbEsdSae6g","title":"Navigation","type":"book","attributes":[{"name":"iconClass","value":"bx bx-navigation","type":"label"}],"children":[{"id":"_help_kBrnXNG3Hplm","title":"Tree Concepts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Tree Concepts"},{"name":"iconClass","value":"bx bx-pyramid","type":"label"}]},{"id":"_help_MMiBEQljMQh2","title":"Note Navigation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation"},{"name":"iconClass","value":"bx bxs-navigation","type":"label"}]},{"id":"_help_Ms1nauBra7gq","title":"Quick search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Quick search"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]},{"id":"_help_F1r9QtzQLZqm","title":"Jump to...","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to"},{"name":"iconClass","value":"bx bx-send","type":"label"}]},{"id":"_help_eIg8jdvaoNNd","title":"Search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Search"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]},{"id":"_help_u3YFHC9tQlpm","title":"Bookmarks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks"},{"name":"iconClass","value":"bx bx-bookmarks","type":"label"}]},{"id":"_help_OR8WJ7Iz9K4U","title":"Note Hoisting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Note Hoisting"},{"name":"iconClass","value":"bx bxs-chevrons-up","type":"label"}]},{"id":"_help_ZjLYv08Rp3qC","title":"Quick edit","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Quick edit"},{"name":"iconClass","value":"bx bx-edit","type":"label"}]},{"id":"_help_9sRHySam5fXb","title":"Workspaces","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Workspaces"},{"name":"iconClass","value":"bx bx-door-open","type":"label"}]},{"id":"_help_xWtq5NUHOwql","title":"Similar Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Similar Notes"},{"name":"iconClass","value":"bx bx-bar-chart","type":"label"}]},{"id":"_help_McngOG2jbUWX","title":"Search in note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Search in note"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]}]},{"id":"_help_A9Oc6YKKc65v","title":"Keyboard Shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Keyboard Shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_Wy267RK4M69c","title":"Themes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes"},{"name":"iconClass","value":"bx bx-palette","type":"label"}],"children":[{"id":"_help_VbjZvtUek0Ln","title":"Theme Gallery","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes/Theme Gallery"},{"name":"iconClass","value":"bx bx-book-reader","type":"label"}]},{"id":"_help_gOKqSJgXLcIj","title":"Icon Packs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes/Icon Packs"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_mHbBMPDPkVV5","title":"Import & Export","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export"},{"name":"iconClass","value":"bx bx-import","type":"label"}],"children":[{"id":"_help_Oau6X9rCuegd","title":"Markdown","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}],"children":[{"id":"_help_rJ9grSgoExl9","title":"Supported syntax","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown/Supported syntax"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}]}]},{"id":"_help_syuSEKf2rUGr","title":"Evernote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Evernote"},{"name":"iconClass","value":"bx bx-window-open","type":"label"}],"children":[{"id":"_help_dj3j8dG4th4l","title":"Process internal links by title","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_GnhlmrATVqcH","title":"OneNote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/OneNote"},{"name":"iconClass","value":"bx bx-window-open","type":"label"}]}]},{"id":"_help_rC3pL2aptaRE","title":"Zen mode","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Zen mode"},{"name":"iconClass","value":"bx bxs-yin-yang","type":"label"}]},{"id":"_help_YzMcWlCVeW09","title":"Active content","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Active content"},{"name":"iconClass","value":"bx bxs-widget","type":"label"}]}]},{"id":"_help_s3YCWHBfmYuM","title":"Quick Start","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Quick Start"},{"name":"iconClass","value":"bx bx-run","type":"label"}]},{"id":"_help_i6dbnitykE5D","title":"FAQ","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/FAQ"},{"name":"iconClass","value":"bx bx-question-mark","type":"label"}]},{"id":"_help_KSZ04uQ2D1St","title":"Note Types","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types"},{"name":"iconClass","value":"bx bx-edit","type":"label"}],"children":[{"id":"_help_iPIMuisry3hd","title":"Text","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text"},{"name":"iconClass","value":"bx bx-note","type":"label"}],"children":[{"id":"_help_NwBbFdNZ9h7O","title":"Block quotes & admonitions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Block quotes & admonitions"},{"name":"iconClass","value":"bx bx-info-circle","type":"label"}]},{"id":"_help_oSuaNgyyKnhu","title":"Bookmarks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Bookmarks"},{"name":"iconClass","value":"bx bx-bookmark","type":"label"}]},{"id":"_help_veGu4faJErEM","title":"Content language & Right-to-left support","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Content language & Right-to-le"},{"name":"iconClass","value":"bx bx-align-right","type":"label"}]},{"id":"_help_2x0ZAX9ePtzV","title":"Cut to subnote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Cut to subnote"},{"name":"iconClass","value":"bx bx-cut","type":"label"}]},{"id":"_help_UYuUB1ZekNQU","title":"Developer-specific formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Developer-specific formatting"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}],"children":[{"id":"_help_QxEyIjRBizuC","title":"Code blocks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Developer-specific formatting/Code blocks"},{"name":"iconClass","value":"bx bx-code","type":"label"}]}]},{"id":"_help_AgjCISero73a","title":"Footnotes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Footnotes"},{"name":"iconClass","value":"bx bx-bracket","type":"label"}]},{"id":"_help_nRhnJkTT8cPs","title":"Formatting toolbar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Formatting toolbar"},{"name":"iconClass","value":"bx bx-text","type":"label"}]},{"id":"_help_Gr6xFaF6ioJ5","title":"General formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/General formatting"},{"name":"iconClass","value":"bx bx-bold","type":"label"}]},{"id":"_help_AxshuNRegLAv","title":"Highlights list","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Highlights list"},{"name":"iconClass","value":"bx bx-highlight","type":"label"}]},{"id":"_help_mT0HEkOsz6i1","title":"Images","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Images"},{"name":"iconClass","value":"bx bx-image-alt","type":"label"}],"children":[{"id":"_help_0Ofbk1aSuVRu","title":"Image references","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Images/Image references"},{"name":"iconClass","value":"bx bxs-file-image","type":"label"}]}]},{"id":"_help_nBAXQFj20hS1","title":"Include Note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Include Note"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_CohkqWQC1iBv","title":"Insert buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Insert buttons"},{"name":"iconClass","value":"bx bx-plus","type":"label"}]},{"id":"_help_oiVPnW8QfnvS","title":"Keyboard shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Keyboard shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_QEAPj01N5f7w","title":"Links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links"},{"name":"iconClass","value":"bx bx-link-alt","type":"label"}],"children":[{"id":"_help_3IDVtesTQ8ds","title":"External links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links/External links"},{"name":"iconClass","value":"bx bx-link-external","type":"label"}]},{"id":"_help_hrZ1D00cLbal","title":"Internal (reference) links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links/Internal (reference) links"},{"name":"iconClass","value":"bx bx-link","type":"label"}]}]},{"id":"_help_S6Xx8QIWTV66","title":"Lists","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Lists"},{"name":"iconClass","value":"bx bx-list-ul","type":"label"}]},{"id":"_help_QrtTYPmdd1qq","title":"Markdown-like formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Markdown-like formatting"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}]},{"id":"_help_YfYAtQBcfo5V","title":"Math Equations","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Math Equations"},{"name":"iconClass","value":"bx bx-math","type":"label"}]},{"id":"_help_dEHYtoWWi8ct","title":"Other features","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Other features"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_gLt3vA97tMcp","title":"Premium features","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features"},{"name":"iconClass","value":"bx bx-star","type":"label"}],"children":[{"id":"_help_ZlN4nump6EbW","title":"Slash Commands","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Slash Commands"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_pwc194wlRzcH","title":"Text Snippets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Text Snippets"},{"name":"iconClass","value":"bx bx-align-left","type":"label"}]},{"id":"_help_5wZallV2Qo1t","title":"Format Painter","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Format Painter"},{"name":"iconClass","value":"bx bxs-paint-roll","type":"label"}]}]},{"id":"_help_oBo3iHIZnbG2","title":"Spell Check","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Spell Check"},{"name":"iconClass","value":"bx bx-check-double","type":"label"}]},{"id":"_help_BFvAtE74rbP6","title":"Table of contents","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Table of contents"},{"name":"iconClass","value":"bx bx-heading","type":"label"}]},{"id":"_help_NdowYOC1GFKS","title":"Tables","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Tables"},{"name":"iconClass","value":"bx bx-table","type":"label"}]}]},{"id":"_help_6f9hih2hXXZk","title":"Code","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Code"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_m523cpzocqaD","title":"Saved Search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Saved Search"},{"name":"iconClass","value":"bx bx-file-find","type":"label"}]},{"id":"_help_iRwzGnHPzonm","title":"Relation Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Relation Map"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_bdUJEHsAPYQR","title":"Note Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Note Map"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_HcABDtFCkbFN","title":"Render Note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Render Note"},{"name":"iconClass","value":"bx bx-extension","type":"label"}]},{"id":"_help_s1aBHPd79XYj","title":"Mermaid Diagrams","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mermaid Diagrams"},{"name":"iconClass","value":"bx bx-selection","type":"label"}],"children":[{"id":"_help_RH6yLjjWJHof","title":"ELK layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mermaid Diagrams/ELK layout"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_WWgeUaBb7UfC","title":"Syntax reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://mermaid.js.org/intro/syntax-reference.html"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_grjYqerjn243","title":"Canvas","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Canvas"},{"name":"iconClass","value":"bx bx-pen","type":"label"}]},{"id":"_help_1vHRoWCEjj0L","title":"Web View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Web View"},{"name":"iconClass","value":"bx bx-globe-alt","type":"label"}]},{"id":"_help_gBbsAeiuUxI5","title":"Mind Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mind Map"},{"name":"iconClass","value":"bx bx-sitemap","type":"label"}]},{"id":"_help_W8vYD3Q1zjCR","title":"File","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File"},{"name":"iconClass","value":"bx bx-file-blank","type":"label"}],"children":[{"id":"_help_XJGJrpu7F9sh","title":"PDFs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File/PDFs"},{"name":"iconClass","value":"bx bxs-file-pdf","type":"label"}]},{"id":"_help_AjqEeiDUOzj4","title":"Videos","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File/Videos"},{"name":"iconClass","value":"bx bx-video","type":"label"}]}]},{"id":"_help_GWHEkY4I4OE3","title":"Spreadsheets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Spreadsheets"},{"name":"iconClass","value":"bx bx-table","type":"label"}]}]},{"id":"_help_GTwFsgaA0lCt","title":"Collections","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections"},{"name":"iconClass","value":"bx bx-book","type":"label"}],"children":[{"id":"_help_xWbu3jpNWapp","title":"Calendar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Calendar"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]},{"id":"_help_2FvYrpmOXm29","title":"Table","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Table"},{"name":"iconClass","value":"bx bx-table","type":"label"}]},{"id":"_help_CtBQqbwXDx1w","title":"Kanban Board","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Kanban Board"},{"name":"iconClass","value":"bx bx-columns","type":"label"}]},{"id":"_help_81SGnPGMk7Xc","title":"Geo Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Geo Map"},{"name":"iconClass","value":"bx bx-map-alt","type":"label"}]},{"id":"_help_zP3PMqaG71Ct","title":"Presentation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Presentation"},{"name":"iconClass","value":"bx bx-slideshow","type":"label"}]},{"id":"_help_8QqnMzx393bx","title":"Grid View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Grid View"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_mULW0Q3VojwY","title":"List View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/List View"},{"name":"iconClass","value":"bx bx-list-ul","type":"label"}]},{"id":"_help_CssoWBu8I7jF","title":"Collection Properties","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Collection Properties"},{"name":"iconClass","value":"bx bx-cog","type":"label"}]}]},{"id":"_help_BgmBlOIl72jZ","title":"Troubleshooting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting"},{"name":"iconClass","value":"bx bx-bug","type":"label"}],"children":[{"id":"_help_wy8So3yZZlH9","title":"Reporting issues","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Reporting issues"},{"name":"iconClass","value":"bx bx-bug-alt","type":"label"}]},{"id":"_help_x59R8J8KV5Bp","title":"Anonymized Database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Anonymized Database"},{"name":"iconClass","value":"bx bx-low-vision","type":"label"}]},{"id":"_help_qzNzp9LYQyPT","title":"Error logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs"},{"name":"iconClass","value":"bx bx-comment-error","type":"label"}],"children":[{"id":"_help_bnyigUA2UK7s","title":"Backend (server) logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs/Backend (server) logs"},{"name":"iconClass","value":"bx bx-server","type":"label"}]},{"id":"_help_9yEHzMyFirZR","title":"Frontend logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs/Frontend logs"},{"name":"iconClass","value":"bx bx-window-alt","type":"label"}]}]},{"id":"_help_vdlYGAcpXAgc","title":"Synchronization fails with 504 Gateway Timeout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Synchronization fails with 504"},{"name":"iconClass","value":"bx bx-error","type":"label"}]},{"id":"_help_s8alTXmpFR61","title":"Refreshing the application","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Refreshing the application"},{"name":"iconClass","value":"bx bx-refresh","type":"label"}]}]},{"id":"_help_pKK96zzmvBGf","title":"Theme development","type":"book","attributes":[{"name":"iconClass","value":"bx bx-palette","type":"label"}],"children":[{"id":"_help_7NfNr5pZpVKV","title":"Creating a custom theme","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Creating a custom theme"},{"name":"iconClass","value":"bx bxs-color","type":"label"}]},{"id":"_help_WFGzWeUK6arS","title":"Customize the Next theme","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Customize the Next theme"},{"name":"iconClass","value":"bx bx-news","type":"label"}]},{"id":"_help_WN5z4M8ASACJ","title":"Reference","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Reference"},{"name":"iconClass","value":"bx bx-book-open","type":"label"}]},{"id":"_help_AlhDUqhENtH7","title":"Custom app-wide CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Custom app-wide CSS"},{"name":"iconClass","value":"bx bxs-file-css","type":"label"}]},{"id":"_help_g1mlRoU8CsqC","title":"Creating an icon pack","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Creating an icon pack"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_tC7s2alapj8V","title":"Advanced Usage","type":"book","attributes":[{"name":"iconClass","value":"bx bx-rocket","type":"label"}],"children":[{"id":"_help_zEY4DaJG4YT5","title":"Attributes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes"},{"name":"iconClass","value":"bx bx-list-check","type":"label"}],"children":[{"id":"_help_HI6GBBIduIgv","title":"Labels","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Labels"},{"name":"iconClass","value":"bx bx-hash","type":"label"}]},{"id":"_help_Cq5X6iKQop6R","title":"Relations","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Relations"},{"name":"iconClass","value":"bx bx-transfer","type":"label"}]},{"id":"_help_bwZpz2ajCEwO","title":"Attribute Inheritance","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Attribute Inheritance"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_OFXdgB2nNk1F","title":"Promoted Attributes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Promoted Attributes"},{"name":"iconClass","value":"bx bx-table","type":"label"}]}]},{"id":"_help_KC1HB96bqqHX","title":"Templates","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Templates"},{"name":"iconClass","value":"bx bx-copy","type":"label"}]},{"id":"_help_BCkXAVs63Ttv","title":"Note Map (Link map, Tree map)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note Map (Link map, Tree map)"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_R9pX4DGra2Vt","title":"Sharing","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing"},{"name":"iconClass","value":"bx bx-share-alt","type":"label"}],"children":[{"id":"_help_Qjt68inQ2bRj","title":"Serving directly the content of a note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Serving directly the content o"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_ycBFjKrrwE9p","title":"Exporting static HTML for web publishing","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Exporting static HTML for web "},{"name":"iconClass","value":"bx bxs-file-html","type":"label"}]},{"id":"_help_sLIJ6f1dkJYW","title":"Reverse proxy configuration","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Reverse proxy configuration"},{"name":"iconClass","value":"bx bx-world","type":"label"}]}]},{"id":"_help_5668rwcirq1t","title":"Advanced Showcases","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases"},{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_l0tKav7yLHGF","title":"Day Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Day Notes"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]},{"id":"_help_R7abl2fc6Mxi","title":"Weight Tracker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Weight Tracker"},{"name":"iconClass","value":"bx bx-line-chart","type":"label"}]},{"id":"_help_xYjQUYhpbUEW","title":"Task Manager","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Task Manager"},{"name":"iconClass","value":"bx bx-calendar-check","type":"label"}]}]},{"id":"_help_J5Ex1ZrMbyJ6","title":"Custom Request Handler","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Custom Request Handler"},{"name":"iconClass","value":"bx bx-globe","type":"label"}]},{"id":"_help_d3fAXQ2diepH","title":"Custom Resource Providers","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Custom Resource Providers"},{"name":"iconClass","value":"bx bxs-file-plus","type":"label"}]},{"id":"_help_pgxEVkzLl1OP","title":"ETAPI (REST API)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/ETAPI (REST API)"},{"name":"iconClass","value":"bx bx-extension","type":"label"}],"children":[{"id":"_help_9qPsTWBorUhQ","title":"API Reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/rest-api/etapi/"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_47ZrP6FNuoG8","title":"Default Note Title","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Default Note Title"},{"name":"iconClass","value":"bx bx-edit-alt","type":"label"}]},{"id":"_help_wX4HbRucYSDD","title":"Database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database"},{"name":"iconClass","value":"bx bx-data","type":"label"}],"children":[{"id":"_help_oyIAJ9PvvwHX","title":"Manually altering the database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Manually altering the database"},{"name":"iconClass","value":"bx bxs-edit","type":"label"}],"children":[{"id":"_help_YKWqdJhzi2VY","title":"SQL Console","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Manually altering the database/SQL Console"},{"name":"iconClass","value":"bx bx-data","type":"label"}]}]},{"id":"_help_6tZeKvSHEUiB","title":"Demo Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Demo Notes"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_Gzjqa934BdH4","title":"Configuration (config.ini or environment variables)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or e"},{"name":"iconClass","value":"bx bx-cog","type":"label"}],"children":[{"id":"_help_c5xB8m4g2IY6","title":"Trilium instance","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Trilium instance"},{"name":"iconClass","value":"bx bx-windows","type":"label"}]},{"id":"_help_LWtBjFej3wX3","title":"Cross-Origin Resource Sharing (CORS)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Cross-Origin Resource Sharing "},{"name":"iconClass","value":"bx bx-lock","type":"label"}]}]},{"id":"_help_ivYnonVFBxbQ","title":"Bulk Actions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Bulk Actions"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_4FahAwuGTAwC","title":"Note source","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note source"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_1YeN2MzFUluU","title":"Technologies used","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used"},{"name":"iconClass","value":"bx bx-pyramid","type":"label"}],"children":[{"id":"_help_MI26XDLSAlCD","title":"CKEditor","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/CKEditor"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_N4IDkixaDG9C","title":"MindElixir","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/MindElixir"},{"name":"iconClass","value":"bx bx-sitemap","type":"label"}]},{"id":"_help_H0mM1lTxF9JI","title":"Excalidraw","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/Excalidraw"},{"name":"iconClass","value":"bx bx-pen","type":"label"}]},{"id":"_help_MQHyy2dIFgxS","title":"Leaflet","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/Leaflet"},{"name":"iconClass","value":"bx bx-map-alt","type":"label"}]}]},{"id":"_help_m1lbrzyKDaRB","title":"Note ID","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note ID"},{"name":"iconClass","value":"bx bx-hash","type":"label"}]},{"id":"_help_0vTSyvhPTAOz","title":"Internal API","type":"book","attributes":[{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_z8O2VG4ZZJD7","title":"API Reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/rest-api/internal/"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_2mUhVmZK8RF3","title":"Hidden Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Hidden Notes"},{"name":"iconClass","value":"bx bx-hide","type":"label"}]},{"id":"_help_uYF7pmepw27K","title":"Metrics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Metrics"},{"name":"iconClass","value":"bx bxs-data","type":"label"}],"children":[{"id":"_help_bOP3TB56fL1V","title":"grafana-dashboard.json","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_64ZTlUPgEPtW","title":"Safe mode","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Safe mode"},{"name":"iconClass","value":"bx bxs-virus-block","type":"label"}]},{"id":"_help_HAIOFBoYIIdO","title":"Nightly release","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Nightly release"},{"name":"iconClass","value":"bx bx-moon","type":"label"}]},{"id":"_help_ZmT9ln8XJX2o","title":"Read-only database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Read-only database"},{"name":"iconClass","value":"bx bx-book-reader","type":"label"}]}]},{"id":"_help_GBBMSlVSOIGP","title":"AI","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/AI"},{"name":"iconClass","value":"bx bx-bot","type":"label"}]},{"id":"_help_CdNpE2pqjmI6","title":"Scripting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting"},{"name":"iconClass","value":"bx bxs-file-js","type":"label"}],"children":[{"id":"_help_yIhgI5H7A2Sm","title":"Frontend Basics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics"},{"name":"iconClass","value":"bx bx-window","type":"label"}],"children":[{"id":"_help_MgibgPcfeuGz","title":"Custom Widgets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets"},{"name":"iconClass","value":"bx bxs-widget","type":"label"}],"children":[{"id":"_help_SynTBQiBsdYJ","title":"Widget Basics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Widget Basics"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_GhurYZjh8e1V","title":"Note context aware widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Note context aware widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_M8IppdwVHSjG","title":"Right pane widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Right pane widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_YNxAqkI5Kg1M","title":"Word count widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Word count widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_VqGQnnPGnqAU","title":"CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/CSS"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_gMkgcLJ6jBkg","title":"Troubleshooting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Troubleshooting"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_es8OU2GuguFU","title":"Examples","type":"book","attributes":[{"name":"iconClass","value":"bx bx-code-alt","type":"label"}],"children":[{"id":"_help_TjLYAo3JMO8X","title":"\"New Task\" launcher button","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/New Task launcher button"},{"name":"iconClass","value":"bx bx-task","type":"label"}]},{"id":"_help_7kZPMD0uFwkH","title":"Downloading responses from Google Forms","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/Downloading responses from Goo"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_DL92EjAaXT26","title":"Using promoted attributes to configure scripts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/Using promoted attributes to c"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_4Gn3psZKsfSm","title":"Launch Bar Widgets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets"},{"name":"iconClass","value":"bx bx-dock-left","type":"label"}],"children":[{"id":"_help_IPArqVfDQ4We","title":"Note Title Widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets/Note Title Widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_gcI7RPbaNSh3","title":"Analog Watch","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets/Analog Watch"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_KLsqhjaqh1QW","title":"Preact","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact"},{"name":"iconClass","value":"bx bxl-react","type":"label"}],"children":[{"id":"_help_Bqde6BvPo05g","title":"Component libraries","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/Component libraries"},{"name":"iconClass","value":"bx bxs-component","type":"label"}]},{"id":"_help_ykYtbM9k3a7B","title":"Hooks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/Hooks"},{"name":"iconClass","value":"bx bx-question-mark","type":"label"}]},{"id":"_help_Sg9GrCtyftZf","title":"CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/CSS"},{"name":"iconClass","value":"bx bxs-file-css","type":"label"}]},{"id":"_help_RSssb9S3xgSr","title":"Built-in components","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/Built-in components"},{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_i9B4IW7b6V6z","title":"Widget showcase","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}]}]},{"id":"_help_SPirpZypehBG","title":"Backend scripts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts"},{"name":"iconClass","value":"bx bx-server","type":"label"}],"children":[{"id":"_help_fZ2IGYFXjkEy","title":"Server-side imports","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts/Server-side imports"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_GPERMystNGTB","title":"Events","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts/Events"},{"name":"iconClass","value":"bx bx-rss","type":"label"}]}]},{"id":"_help_wqXwKJl6VpNk","title":"Common concepts","type":"book","attributes":[{"name":"iconClass","value":"bx bxl-nodejs","type":"label"}],"children":[{"id":"_help_hA834UaHhSNn","title":"Script bundles","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Common concepts/Script bundles"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_GLks18SNjxmC","title":"Script API","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Script API"},{"name":"iconClass","value":"bx bx-code-curly","type":"label"}],"children":[{"id":"_help_Q2z6av6JZVWm","title":"Frontend API","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/frontend"},{"name":"iconClass","value":"bx bx-folder","type":"label"}],"enforceAttributes":true,"children":[{"id":"_help_habiZ3HU8Kw8","title":"FNote","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/frontend/interfaces/FNote.html"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_MEtfsqa5VwNi","title":"Backend API","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/backend"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true},{"id":"_help_ApVHZ8JY5ofC","title":"Day.js","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Script API/Day.js"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]}]},{"id":"_help_vElnKeDNPSVl","title":"Logging","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Logging"},{"name":"iconClass","value":"bx bx-terminal","type":"label"}]},{"id":"_help_cNpC0ITcfX0N","title":"Breaking changes","type":"book","attributes":[{"name":"iconClass","value":"bx bx-up-arrow-alt","type":"label"}],"children":[{"id":"_help_fqAK6opjUagR","title":"v0.103.0: Removal of axios","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Breaking changes/v0.103.0 Removal of axios"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_pAJ0jWz16xFm","title":"v0.103.0: `cheerio` is now deprecated","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Breaking changes/v0.103.0 `cheerio` is now depr"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_72dxvnbnkDFY","title":"v0.102.0: Upgrade to jQuery 4.0.0","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Breaking changes/v0.102.0 Upgrade to jQuery.0.0"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}]},{"id":"_help_Fm0j45KqyHpU","title":"Miscellaneous","type":"book","attributes":[{"name":"iconClass","value":"bx bx-info-circle","type":"label"}],"children":[{"id":"_help_WFbFXrgnDyyU","title":"Privacy Policy","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/Privacy Policy"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_NcsmUYZRWEW4","title":"Patterns of personal knowledge","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/Patterns of personal knowledge"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_d1Ap6Pg6IjaJ","title":"License","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/License"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}] \ No newline at end of file diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/AI.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/AI.html index 00bbfb1eb0..e5000ac9fd 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/AI.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/AI.html @@ -16,6 +16,8 @@
  • perfectra1n/triliumnext-mcp
  • +
  • eliassoares/trilium-fastmcp +
  • } + /> + ); +} From 81c266f69bb0b7b9522d9080511bdac70a3986a5 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 06:25:47 +0300 Subject: [PATCH 284/482] fix(markdown): scroll padding affecting height --- apps/client/src/widgets/scroll_padding.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/client/src/widgets/scroll_padding.tsx b/apps/client/src/widgets/scroll_padding.tsx index e277ee86a1..57d7349d05 100644 --- a/apps/client/src/widgets/scroll_padding.tsx +++ b/apps/client/src/widgets/scroll_padding.tsx @@ -9,7 +9,8 @@ export default function ScrollPadding() { const isEnabled = ["text", "code"].includes(note?.type ?? "") && viewScope?.viewMode === "default" && note?.isContentAvailable() - && !note?.isTriliumSqlite(); + && !note?.isTriliumSqlite() + && !note?.isMarkdown(); const refreshHeight = () => { if (!ref.current) return; From b84e50065c9fe77e67c61aa31624d4f0fcfacb45 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 06:29:27 +0300 Subject: [PATCH 285/482] feat(markdown): compact title --- apps/client/src/widgets/layout/InlineTitle.tsx | 1 + apps/client/src/widgets/layout/NoteTypeSwitcher.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/client/src/widgets/layout/InlineTitle.tsx b/apps/client/src/widgets/layout/InlineTitle.tsx index f6e5a51556..d4e2602f9e 100644 --- a/apps/client/src/widgets/layout/InlineTitle.tsx +++ b/apps/client/src/widgets/layout/InlineTitle.tsx @@ -75,6 +75,7 @@ function shouldShow(note: FNote | null | undefined, type: NoteType | undefined, if (viewScope?.viewMode !== "default") return false; if (note?.noteId?.startsWith("_options")) return true; if (note?.isTriliumSqlite()) return false; + if (note?.isMarkdown()) return false; return type && supportedNoteTypes.has(type); } diff --git a/apps/client/src/widgets/layout/NoteTypeSwitcher.tsx b/apps/client/src/widgets/layout/NoteTypeSwitcher.tsx index cf685828aa..5babfbef7f 100644 --- a/apps/client/src/widgets/layout/NoteTypeSwitcher.tsx +++ b/apps/client/src/widgets/layout/NoteTypeSwitcher.tsx @@ -41,7 +41,7 @@ export default function NoteTypeSwitcher() { const currentNoteTypeData = useMemo(() => NOTE_TYPES.find(t => t.type === currentNoteType), [ currentNoteType ]); const { builtinTemplates, collectionTemplates } = useBuiltinTemplates(); - return (currentNoteType && supportedNoteTypes.has(currentNoteType) && !note?.isTriliumSqlite() && + return (currentNoteType && supportedNoteTypes.has(currentNoteType) && !note?.isTriliumSqlite() && !note?.isMarkdown() &&
    Date: Fri, 17 Apr 2026 06:32:49 +0300 Subject: [PATCH 286/482] feat(markdown): introduce some padding --- .../src/widgets/type_widgets/code/Markdown.css | 10 ++++++++++ .../src/widgets/type_widgets/code/Markdown.tsx | 14 +++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 apps/client/src/widgets/type_widgets/code/Markdown.css diff --git a/apps/client/src/widgets/type_widgets/code/Markdown.css b/apps/client/src/widgets/type_widgets/code/Markdown.css new file mode 100644 index 0000000000..19bd140e35 --- /dev/null +++ b/apps/client/src/widgets/type_widgets/code/Markdown.css @@ -0,0 +1,10 @@ +.note-detail-markdown { + .note-detail-code-editor .cm-editor { + padding-block: 0.25em; + } + + .markdown-preview { + padding: 0.5em; + } +} + diff --git a/apps/client/src/widgets/type_widgets/code/Markdown.tsx b/apps/client/src/widgets/type_widgets/code/Markdown.tsx index 3f7cf0df5f..beba918323 100644 --- a/apps/client/src/widgets/type_widgets/code/Markdown.tsx +++ b/apps/client/src/widgets/type_widgets/code/Markdown.tsx @@ -1,12 +1,24 @@ +import "./Markdown.css"; + +import { Marked } from "marked"; +import { useMemo, useState } from "preact/hooks"; + +import { SanitizedHtml } from "../../react/RawHtml"; import SplitEditor from "../helpers/SplitEditor"; import { TypeWidgetProps } from "../type_widget"; +const marked = new Marked({ breaks: true, gfm: true }); + export default function Markdown(props: TypeWidgetProps) { + const [ content, setContent ] = useState(""); + const html = useMemo(() => marked.parse(content) as string, [ content ]); + return ( Hello World
    } + onContentChanged={setContent} + previewContent={} /> ); } From 6d2496599fea7568b5c3a76171fa555116faa901 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 06:35:45 +0300 Subject: [PATCH 287/482] feat(markdown): make preview scrollable --- apps/client/src/widgets/type_widgets/code/Markdown.css | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/client/src/widgets/type_widgets/code/Markdown.css b/apps/client/src/widgets/type_widgets/code/Markdown.css index 19bd140e35..7392c3e5f8 100644 --- a/apps/client/src/widgets/type_widgets/code/Markdown.css +++ b/apps/client/src/widgets/type_widgets/code/Markdown.css @@ -3,8 +3,13 @@ padding-block: 0.25em; } - .markdown-preview { - padding: 0.5em; + .note-detail-split-preview { + overflow: auto; + + .markdown-preview { + padding: 0.5em; + } } + } From 1ec270dba2ff19c22f44aaca6c9891aaa42f4496 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 06:38:12 +0300 Subject: [PATCH 288/482] feat(markdown): basic percentage-based scroll --- .../widgets/type_widgets/code/Markdown.tsx | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/apps/client/src/widgets/type_widgets/code/Markdown.tsx b/apps/client/src/widgets/type_widgets/code/Markdown.tsx index beba918323..46d0d7f214 100644 --- a/apps/client/src/widgets/type_widgets/code/Markdown.tsx +++ b/apps/client/src/widgets/type_widgets/code/Markdown.tsx @@ -1,9 +1,9 @@ import "./Markdown.css"; +import DOMPurify from "dompurify"; import { Marked } from "marked"; -import { useMemo, useState } from "preact/hooks"; +import { useEffect, useMemo, useRef, useState } from "preact/hooks"; -import { SanitizedHtml } from "../../react/RawHtml"; import SplitEditor from "../helpers/SplitEditor"; import { TypeWidgetProps } from "../type_widget"; @@ -11,14 +11,40 @@ const marked = new Marked({ breaks: true, gfm: true }); export default function Markdown(props: TypeWidgetProps) { const [ content, setContent ] = useState(""); - const html = useMemo(() => marked.parse(content) as string, [ content ]); + const html = useMemo(() => DOMPurify.sanitize(marked.parse(content) as string), [ content ]); + const previewRef = useRef(null); + + useEffect(() => { + const split = previewRef.current?.closest(".note-detail-split"); + const preview = split?.querySelector(".note-detail-split-preview"); + const editor = split?.querySelector(".cm-scroller"); + if (!preview || !editor) return; + + function onScroll() { + if (!preview || !editor) return; + const editorMax = editor.scrollHeight - editor.clientHeight; + const previewMax = preview.scrollHeight - preview.clientHeight; + if (editorMax <= 0 || previewMax <= 0) return; + preview.scrollTop = (editor.scrollTop / editorMax) * previewMax; + } + + editor.addEventListener("scroll", onScroll, { passive: true }); + return () => editor.removeEventListener("scroll", onScroll); + }, [ html ]); return ( } + previewContent={( +
    + )} /> ); } From 3417f82e27f46c1103e63678bd13ff610290066c Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 06:43:50 +0300 Subject: [PATCH 289/482] feat(markdown): basic block-based sync --- .../widgets/type_widgets/code/Markdown.tsx | 88 ++++++++++++++++--- 1 file changed, 74 insertions(+), 14 deletions(-) diff --git a/apps/client/src/widgets/type_widgets/code/Markdown.tsx b/apps/client/src/widgets/type_widgets/code/Markdown.tsx index 46d0d7f214..257f7b39bb 100644 --- a/apps/client/src/widgets/type_widgets/code/Markdown.tsx +++ b/apps/client/src/widgets/type_widgets/code/Markdown.tsx @@ -1,7 +1,8 @@ import "./Markdown.css"; +import VanillaCodeMirror from "@triliumnext/codemirror"; import DOMPurify from "dompurify"; -import { Marked } from "marked"; +import { Marked, type TokensList } from "marked"; import { useEffect, useMemo, useRef, useState } from "preact/hooks"; import SplitEditor from "../helpers/SplitEditor"; @@ -9,28 +10,87 @@ import { TypeWidgetProps } from "../type_widget"; const marked = new Marked({ breaks: true, gfm: true }); +/** + * Render markdown and tag each top-level block with its 1-indexed source line, + * so the preview can be scrolled to match the editor. Marked does not emit + * source positions (markedjs/marked#1267) so we count newlines in `raw` ourselves. + */ +function renderWithSourceLines(src: string): string { + const tokens = marked.lexer(src); + let line = 1; + const parts: string[] = []; + for (const token of tokens) { + const startLine = line; + line += (token.raw.match(/\n/g) ?? []).length; + if (token.type === "space") continue; + const sub = [ token ] as unknown as TokensList; + (sub as TokensList).links = tokens.links; + parts.push(`
    ${marked.parser(sub)}
    `); + } + return parts.join(""); +} + export default function Markdown(props: TypeWidgetProps) { const [ content, setContent ] = useState(""); - const html = useMemo(() => DOMPurify.sanitize(marked.parse(content) as string), [ content ]); + const html = useMemo(() => DOMPurify.sanitize(renderWithSourceLines(content), { ADD_ATTR: [ "data-source-line" ] }), [ content ]); const previewRef = useRef(null); useEffect(() => { - const split = previewRef.current?.closest(".note-detail-split"); - const preview = split?.querySelector(".note-detail-split-preview"); - const editor = split?.querySelector(".cm-scroller"); - if (!preview || !editor) return; + let rafId = 0; + let scroller: HTMLElement | null = null; + let cmEditor: HTMLElement | null = null; + let preview: HTMLElement | null = null; function onScroll() { - if (!preview || !editor) return; - const editorMax = editor.scrollHeight - editor.clientHeight; - const previewMax = preview.scrollHeight - preview.clientHeight; - if (editorMax <= 0 || previewMax <= 0) return; - preview.scrollTop = (editor.scrollTop / editorMax) * previewMax; + if (!scroller || !cmEditor || !preview) return; + const view = VanillaCodeMirror.findFromDOM(cmEditor); + if (!view) return; + + const topLine = view.state.doc.lineAt(view.lineBlockAtHeight(scroller.scrollTop).from).number; + + const blocks = previewRef.current?.querySelectorAll("[data-source-line]"); + if (!blocks?.length) return; + + let before: HTMLElement | null = null; + let after: HTMLElement | null = null; + for (const el of blocks) { + const l = parseInt(el.dataset.sourceLine!, 10); + if (l <= topLine) before = el; + else { after = el; break; } + } + + if (!before) { preview.scrollTop = 0; return; } + + const previewTop = preview.getBoundingClientRect().top - preview.scrollTop; + const beforeOffset = before.getBoundingClientRect().top - previewTop; + const beforeLine = parseInt(before.dataset.sourceLine!, 10); + + if (!after) { preview.scrollTop = beforeOffset; return; } + + const afterOffset = after.getBoundingClientRect().top - previewTop; + const afterLine = parseInt(after.dataset.sourceLine!, 10); + const ratio = (topLine - beforeLine) / (afterLine - beforeLine); + preview.scrollTop = beforeOffset + (afterOffset - beforeOffset) * ratio; } - editor.addEventListener("scroll", onScroll, { passive: true }); - return () => editor.removeEventListener("scroll", onScroll); - }, [ html ]); + function tryAttach() { + const split = previewRef.current?.closest(".note-detail-split"); + scroller = split?.querySelector(".cm-scroller") ?? null; + cmEditor = split?.querySelector(".cm-editor") ?? null; + preview = split?.querySelector(".note-detail-split-preview") ?? null; + if (!scroller || !cmEditor || !preview) { + rafId = requestAnimationFrame(tryAttach); + return; + } + scroller.addEventListener("scroll", onScroll, { passive: true }); + } + tryAttach(); + + return () => { + cancelAnimationFrame(rafId); + scroller?.removeEventListener("scroll", onScroll); + }; + }, []); return ( Date: Fri, 17 Apr 2026 06:46:04 +0300 Subject: [PATCH 290/482] refactor(markdown): clean up a bit the sync rendering --- .../type_widgets/code/Markdown.spec.ts | 63 ++++++++++++++ .../widgets/type_widgets/code/Markdown.tsx | 87 +++++++++++-------- 2 files changed, 113 insertions(+), 37 deletions(-) create mode 100644 apps/client/src/widgets/type_widgets/code/Markdown.spec.ts diff --git a/apps/client/src/widgets/type_widgets/code/Markdown.spec.ts b/apps/client/src/widgets/type_widgets/code/Markdown.spec.ts new file mode 100644 index 0000000000..15369b8f43 --- /dev/null +++ b/apps/client/src/widgets/type_widgets/code/Markdown.spec.ts @@ -0,0 +1,63 @@ +import { describe, expect, it } from "vitest"; + +import { renderWithSourceLines } from "./Markdown.js"; + +describe("renderWithSourceLines", () => { + function extractLines(html: string): number[] { + return [ ...html.matchAll(/data-source-line="(\d+)"/g) ].map((m) => parseInt(m[1], 10)); + } + + it("returns empty string for empty input", () => { + expect(renderWithSourceLines("")).toBe(""); + }); + + it("tags a single block as line 1", () => { + const html = renderWithSourceLines("hello"); + expect(extractLines(html)).toEqual([ 1 ]); + expect(html).toContain("hello"); + }); + + it("assigns correct source lines to consecutive blocks separated by blank lines", () => { + const src = [ + "# Heading", // line 1 + "", // line 2 + "A paragraph.", // line 3 + "", // line 4 + "Another one." // line 5 + ].join("\n"); + + expect(extractLines(renderWithSourceLines(src))).toEqual([ 1, 3, 5 ]); + }); + + it("counts multi-line blocks so subsequent blocks get the right line", () => { + const src = [ + "```", // 1 + "code", // 2 + "more code", // 3 + "```", // 4 + "", // 5 + "after" // 6 + ].join("\n"); + + expect(extractLines(renderWithSourceLines(src))).toEqual([ 1, 6 ]); + }); + + it("renders standard markdown constructs inside the wrappers", () => { + const html = renderWithSourceLines("# Heading\n\n- item\n"); + expect(html).toContain(""); + expect(html).toContain("
  • item
  • "); + }); + + it("preserves reference-style links across per-block parsing", () => { + const src = [ + "[trilium][t]", // 1 + "", // 2 + "[t]: https://example.com" + ].join("\n"); + + const html = renderWithSourceLines(src); + expect(html).toContain('href="https://example.com"'); + }); +}); diff --git a/apps/client/src/widgets/type_widgets/code/Markdown.tsx b/apps/client/src/widgets/type_widgets/code/Markdown.tsx index 257f7b39bb..b42162a0b5 100644 --- a/apps/client/src/widgets/type_widgets/code/Markdown.tsx +++ b/apps/client/src/widgets/type_widgets/code/Markdown.tsx @@ -3,6 +3,7 @@ import "./Markdown.css"; import VanillaCodeMirror from "@triliumnext/codemirror"; import DOMPurify from "dompurify"; import { Marked, type TokensList } from "marked"; +import { RefObject } from "preact"; import { useEffect, useMemo, useRef, useState } from "preact/hooks"; import SplitEditor from "../helpers/SplitEditor"; @@ -10,31 +11,38 @@ import { TypeWidgetProps } from "../type_widget"; const marked = new Marked({ breaks: true, gfm: true }); -/** - * Render markdown and tag each top-level block with its 1-indexed source line, - * so the preview can be scrolled to match the editor. Marked does not emit - * source positions (markedjs/marked#1267) so we count newlines in `raw` ourselves. - */ -function renderWithSourceLines(src: string): string { - const tokens = marked.lexer(src); - let line = 1; - const parts: string[] = []; - for (const token of tokens) { - const startLine = line; - line += (token.raw.match(/\n/g) ?? []).length; - if (token.type === "space") continue; - const sub = [ token ] as unknown as TokensList; - (sub as TokensList).links = tokens.links; - parts.push(`
    ${marked.parser(sub)}
    `); - } - return parts.join(""); -} - export default function Markdown(props: TypeWidgetProps) { const [ content, setContent ] = useState(""); const html = useMemo(() => DOMPurify.sanitize(renderWithSourceLines(content), { ADD_ATTR: [ "data-source-line" ] }), [ content ]); const previewRef = useRef(null); + useSyncedScrolling(previewRef); + + return ( + + )} + /> + ); +} + +//#region Synced scrolling +/** + * One-directional (editor → preview) scroll sync. On editor scroll, finds the + * top visible source line via the CodeMirror `EditorView`, then scrolls the + * preview so the block tagged with that line is at the top — interpolating to + * the next block for smoothness. + */ +function useSyncedScrolling(previewRef: RefObject) { useEffect(() => { let rafId = 0; let scroller: HTMLElement | null = null; @@ -90,21 +98,26 @@ export default function Markdown(props: TypeWidgetProps) { cancelAnimationFrame(rafId); scroller?.removeEventListener("scroll", onScroll); }; - }, []); - - return ( - - )} - /> - ); + }, [ previewRef ]); } + +/** + * Render markdown and tag each top-level block with its 1-indexed source line, + * so the preview can be scrolled to match the editor. Marked does not emit + * source positions (markedjs/marked#1267) so we count newlines in `raw` ourselves. + */ +export function renderWithSourceLines(src: string): string { + const tokens = marked.lexer(src); + let line = 1; + const parts: string[] = []; + for (const token of tokens) { + const startLine = line; + line += (token.raw.match(/\n/g) ?? []).length; + if (token.type === "space") continue; + const sub = [ token ] as unknown as TokensList; + (sub as TokensList).links = tokens.links; + parts.push(`
    ${marked.parser(sub)}
    `); + } + return parts.join(""); +} +//#endregion From 0dfbfaa61ce84863c6241c5d4d2a8b16c826dcbe Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 06:51:31 +0300 Subject: [PATCH 291/482] refactor(markdown): get rid of DOM queries --- .../src/widgets/type_widgets/code/Code.tsx | 8 +++- .../widgets/type_widgets/code/Markdown.css | 9 ++-- .../widgets/type_widgets/code/Markdown.tsx | 45 +++++++------------ 3 files changed, 25 insertions(+), 37 deletions(-) diff --git a/apps/client/src/widgets/type_widgets/code/Code.tsx b/apps/client/src/widgets/type_widgets/code/Code.tsx index 4f34edd96b..0f99d37e07 100644 --- a/apps/client/src/widgets/type_widgets/code/Code.tsx +++ b/apps/client/src/widgets/type_widgets/code/Code.tsx @@ -2,6 +2,7 @@ import "./code.css"; import { default as VanillaCodeMirror, getThemeById } from "@triliumnext/codemirror"; import { NoteType } from "@triliumnext/commons"; +import { RefObject } from "preact"; import { useEffect, useRef, useState } from "preact/hooks"; import appContext, { CommandListenerData } from "../../../components/app_context"; @@ -31,6 +32,8 @@ export interface EditableCodeProps extends TypeWidgetProps, Omit void; placeholder?: string; + /** Optional external ref to the underlying CodeMirror `EditorView`. Populated once the editor has initialized. */ + editorRef?: RefObject; } export function ReadOnlyCode({ note, viewScope, ntxId, parentComponent }: TypeWidgetProps) { @@ -81,8 +84,9 @@ function formatViewSource(note: FNote, content: string) { return content; } -export function EditableCode({ note, ntxId, noteContext, debounceUpdate, parentComponent, updateInterval, noteType = "code", onContentChanged, dataSaved, placeholder, ...editorProps }: EditableCodeProps) { - const editorRef = useRef(null); +export function EditableCode({ note, ntxId, noteContext, debounceUpdate, parentComponent, updateInterval, noteType = "code", onContentChanged, dataSaved, placeholder, editorRef: externalEditorRef, ...editorProps }: EditableCodeProps) { + const internalEditorRef = useRef(null); + const editorRef = externalEditorRef ?? internalEditorRef; const containerRef = useRef(null); const [ vimKeymapEnabled ] = useTriliumOptionBool("vimKeymapEnabled"); const [ noteTabWidth ] = useNoteLabelInt(note, "tabWidth"); diff --git a/apps/client/src/widgets/type_widgets/code/Markdown.css b/apps/client/src/widgets/type_widgets/code/Markdown.css index 7392c3e5f8..fdfe0dcfff 100644 --- a/apps/client/src/widgets/type_widgets/code/Markdown.css +++ b/apps/client/src/widgets/type_widgets/code/Markdown.css @@ -3,12 +3,11 @@ padding-block: 0.25em; } - .note-detail-split-preview { + .markdown-preview { + box-sizing: border-box; + height: 100%; overflow: auto; - - .markdown-preview { - padding: 0.5em; - } + padding: 0.5em; } } diff --git a/apps/client/src/widgets/type_widgets/code/Markdown.tsx b/apps/client/src/widgets/type_widgets/code/Markdown.tsx index b42162a0b5..3d6e1ab2a5 100644 --- a/apps/client/src/widgets/type_widgets/code/Markdown.tsx +++ b/apps/client/src/widgets/type_widgets/code/Markdown.tsx @@ -15,13 +15,15 @@ export default function Markdown(props: TypeWidgetProps) { const [ content, setContent ] = useState(""); const html = useMemo(() => DOMPurify.sanitize(renderWithSourceLines(content), { ADD_ATTR: [ "data-source-line" ] }), [ content ]); const previewRef = useRef(null); + const editorRef = useRef(null); - useSyncedScrolling(previewRef); + useSyncedScrolling(editorRef, previewRef); return ( ) { +function useSyncedScrolling(editorRef: RefObject, previewRef: RefObject) { useEffect(() => { - let rafId = 0; - let scroller: HTMLElement | null = null; - let cmEditor: HTMLElement | null = null; - let preview: HTMLElement | null = null; + const view = editorRef.current; + const preview = previewRef.current; + if (!view || !preview) return; + + const scroller = view.scrollDOM; function onScroll() { - if (!scroller || !cmEditor || !preview) return; - const view = VanillaCodeMirror.findFromDOM(cmEditor); - if (!view) return; - + if (!view || !preview) return; const topLine = view.state.doc.lineAt(view.lineBlockAtHeight(scroller.scrollTop).from).number; - const blocks = previewRef.current?.querySelectorAll("[data-source-line]"); - if (!blocks?.length) return; + const blocks = preview.querySelectorAll("[data-source-line]"); + if (!blocks.length) return; let before: HTMLElement | null = null; let after: HTMLElement | null = null; @@ -81,24 +81,9 @@ function useSyncedScrolling(previewRef: RefObject) { preview.scrollTop = beforeOffset + (afterOffset - beforeOffset) * ratio; } - function tryAttach() { - const split = previewRef.current?.closest(".note-detail-split"); - scroller = split?.querySelector(".cm-scroller") ?? null; - cmEditor = split?.querySelector(".cm-editor") ?? null; - preview = split?.querySelector(".note-detail-split-preview") ?? null; - if (!scroller || !cmEditor || !preview) { - rafId = requestAnimationFrame(tryAttach); - return; - } - scroller.addEventListener("scroll", onScroll, { passive: true }); - } - tryAttach(); - - return () => { - cancelAnimationFrame(rafId); - scroller?.removeEventListener("scroll", onScroll); - }; - }, [ previewRef ]); + scroller.addEventListener("scroll", onScroll, { passive: true }); + return () => scroller.removeEventListener("scroll", onScroll); + }, [ editorRef, previewRef ]); } /** From dbe37730c36b804f62e8bd7fb7b202f7c1effd83 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 06:52:01 +0300 Subject: [PATCH 292/482] chore(markdown): make preview selectable --- apps/client/src/widgets/type_widgets/code/Markdown.css | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/client/src/widgets/type_widgets/code/Markdown.css b/apps/client/src/widgets/type_widgets/code/Markdown.css index fdfe0dcfff..02d4d0105f 100644 --- a/apps/client/src/widgets/type_widgets/code/Markdown.css +++ b/apps/client/src/widgets/type_widgets/code/Markdown.css @@ -8,6 +8,7 @@ height: 100%; overflow: auto; padding: 0.5em; + user-select: text; } } From 12e07dbfcdb1edc752d43bf286c04e8410244ae1 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 07:00:07 +0300 Subject: [PATCH 293/482] feat(markdown): basic block highlighting in preview --- .../widgets/type_widgets/code/Markdown.css | 12 +++++- .../widgets/type_widgets/code/Markdown.tsx | 39 +++++++++++++++++++ packages/codemirror/src/index.ts | 21 ++++++++-- 3 files changed, 67 insertions(+), 5 deletions(-) diff --git a/apps/client/src/widgets/type_widgets/code/Markdown.css b/apps/client/src/widgets/type_widgets/code/Markdown.css index 02d4d0105f..88f1aba621 100644 --- a/apps/client/src/widgets/type_widgets/code/Markdown.css +++ b/apps/client/src/widgets/type_widgets/code/Markdown.css @@ -7,9 +7,19 @@ box-sizing: border-box; height: 100%; overflow: auto; - padding: 0.5em; + padding: 0.5em 1em; user-select: text; } + .markdown-preview [data-source-line] { + border-left: 2px solid transparent; + padding-left: 0.5em; + margin-left: -0.5em; + } + + [data-source-line].markdown-preview-active { + border-left-color: var(--main-text-color); + } + } diff --git a/apps/client/src/widgets/type_widgets/code/Markdown.tsx b/apps/client/src/widgets/type_widgets/code/Markdown.tsx index 3d6e1ab2a5..158cd39ddb 100644 --- a/apps/client/src/widgets/type_widgets/code/Markdown.tsx +++ b/apps/client/src/widgets/type_widgets/code/Markdown.tsx @@ -18,6 +18,7 @@ export default function Markdown(props: TypeWidgetProps) { const editorRef = useRef(null); useSyncedScrolling(editorRef, previewRef); + useSyncedHighlight(editorRef, previewRef, html); return ( , previewRef: }, [ editorRef, previewRef ]); } +/** + * Highlights the preview block that corresponds to the editor's active line, + * matching the built-in `cm-activeLine` behavior. Re-runs when the rendered + * HTML changes so newly inserted blocks pick up the current cursor position. + */ +function useSyncedHighlight(editorRef: RefObject, previewRef: RefObject, html: string) { + useEffect(() => { + const view = editorRef.current; + const preview = previewRef.current; + if (!view || !preview) return; + + let current: HTMLElement | null = null; + + function update() { + if (!view || !preview) return; + const activeLine = view.state.doc.lineAt(view.state.selection.main.head).number; + + const blocks = preview.querySelectorAll("[data-source-line]"); + let match: HTMLElement | null = null; + for (const el of blocks) { + if (parseInt(el.dataset.sourceLine!, 10) <= activeLine) match = el; + else break; + } + + if (match === current) return; + current?.classList.remove("markdown-preview-active"); + match?.classList.add("markdown-preview-active"); + current = match; + } + + update(); + const unsubscribe = view.addUpdateListener((v) => { + if (v.selectionSet || v.docChanged) update(); + }); + return unsubscribe; + }, [ editorRef, previewRef, html ]); +} + /** * Render markdown and tag each top-level block with its 1-indexed source line, * so the preview can be scrolled to match the editor. Marked does not emit diff --git a/packages/codemirror/src/index.ts b/packages/codemirror/src/index.ts index 0fa8023ddb..de4f9f7a58 100644 --- a/packages/codemirror/src/index.ts +++ b/packages/codemirror/src/index.ts @@ -104,16 +104,14 @@ export default class CodeMirror extends EditorView { ]; } + extensions.push(EditorView.updateListener.of((v) => this.#onDocumentUpdated(v))); + if (!config.readOnly) { // Logic specific to editable notes if (config.placeholder) { extensions.push(placeholder(config.placeholder)); } - if (config.onContentChanged) { - extensions.push(EditorView.updateListener.of((v) => this.#onDocumentUpdated(v))); - } - extensions.push(historyCompartment.of(history())); } else { // Logic specific to read-only notes @@ -142,6 +140,21 @@ export default class CodeMirror extends EditorView { if (v.docChanged) { this.config.onContentChanged?.(); } + for (const listener of this.#updateListeners) listener(v); + } + + #updateListeners: Array<(v: ViewUpdate) => void> = []; + + /** + * Subscribe to view updates (doc changes, selection changes, viewport changes, etc.). + * Returns an unsubscribe function. The listener will not fire after the view is destroyed. + */ + addUpdateListener(listener: (v: ViewUpdate) => void): () => void { + this.#updateListeners.push(listener); + return () => { + const i = this.#updateListeners.indexOf(listener); + if (i >= 0) this.#updateListeners.splice(i, 1); + }; } getText() { From 438442345e3898a46abcf7c9588d47d9ec849b18 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 07:04:58 +0300 Subject: [PATCH 294/482] feat(codemirror): enable nested syntax highlighting for MD (closes #9150) --- packages/codemirror/package.json | 1 + .../codemirror/src/syntax_highlighting.ts | 10 +- pnpm-lock.yaml | 223 ++++++++++++++++++ 3 files changed, 232 insertions(+), 2 deletions(-) diff --git a/packages/codemirror/package.json b/packages/codemirror/package.json index 837ea1db6f..6d947aa4c3 100644 --- a/packages/codemirror/package.json +++ b/packages/codemirror/package.json @@ -12,6 +12,7 @@ "@codemirror/lang-javascript": "6.2.5", "@codemirror/lang-json": "6.0.2", "@codemirror/lang-markdown": "6.5.0", + "@codemirror/language-data": "6.5.1", "@codemirror/lang-php": "6.0.2", "@codemirror/lang-vue": "0.1.3", "@codemirror/lang-xml": "6.1.0", diff --git a/packages/codemirror/src/syntax_highlighting.ts b/packages/codemirror/src/syntax_highlighting.ts index 518c84732b..d5c862f254 100644 --- a/packages/codemirror/src/syntax_highlighting.ts +++ b/packages/codemirror/src/syntax_highlighting.ts @@ -101,8 +101,10 @@ const byMimeType: Record Promise (await import('./languages/gdscript.js')).gdscript, "text/x-gfm": async () => { const { markdown, markdownLanguage } = (await import('@codemirror/lang-markdown')); + const { languages } = (await import('@codemirror/language-data')); return markdown({ - base: markdownLanguage + base: markdownLanguage, + codeLanguages: languages }); }, "text/x-go": async () => (await import('@codemirror/legacy-modes/mode/go')).go, @@ -124,7 +126,11 @@ const byMimeType: Record Promise (await import('@codemirror/legacy-modes/mode/livescript')).liveScript, "text/x-lua": async () => (await import('@codemirror/legacy-modes/mode/lua')).lua, "text/x-mariadb": async () => (await import('@codemirror/legacy-modes/mode/sql')).sqlite, - "text/x-markdown": async () => ((await import('@codemirror/lang-markdown')).markdown()), + "text/x-markdown": async () => { + const { markdown } = (await import('@codemirror/lang-markdown')); + const { languages } = (await import('@codemirror/language-data')); + return markdown({ codeLanguages: languages }); + }, "text/x-mathematica": async () => (await import('@codemirror/legacy-modes/mode/mathematica')).mathematica, "text/x-modelica": async () => (await import('@codemirror/legacy-modes/mode/modelica')).modelica, "text/x-mscgen": async () => (await import('@codemirror/legacy-modes/mode/mscgen')).mscgen, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d7d06a0e18..cdb5c47c72 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1226,6 +1226,9 @@ importers: '@codemirror/lang-xml': specifier: 6.1.0 version: 6.1.0 + '@codemirror/language-data': + specifier: 6.5.1 + version: 6.5.1 '@codemirror/legacy-modes': specifier: 6.5.2 version: 6.5.2 @@ -2008,18 +2011,36 @@ packages: '@codemirror/commands@6.8.1': resolution: {integrity: sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw==} + '@codemirror/lang-angular@0.1.4': + resolution: {integrity: sha512-oap+gsltb/fzdlTQWD6BFF4bSLKcDnlxDsLdePiJpCVNKWXSTAbiiQeYI3UmES+BLAdkmIC1WjyztC1pi/bX4g==} + + '@codemirror/lang-cpp@6.0.3': + resolution: {integrity: sha512-URM26M3vunFFn9/sm6rzqrBzDgfWuDixp85uTY49wKudToc2jTHUrKIGGKs+QWND+YLofNNZpxcNGRynFJfvgA==} + '@codemirror/lang-css@6.3.1': resolution: {integrity: sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==} + '@codemirror/lang-go@6.0.1': + resolution: {integrity: sha512-7fNvbyNylvqCphW9HD6WFnRpcDjr+KXX/FgqXy5H5ZS0eC5edDljukm/yNgYkwTsgp2busdod50AOTIy6Jikfg==} + '@codemirror/lang-html@6.4.11': resolution: {integrity: sha512-9NsXp7Nwp891pQchI7gPdTwBuSuT3K65NGTHWHNJ55HjYcHLllr0rbIZNdOzas9ztc1EUVBlHou85FFZS4BNnw==} + '@codemirror/lang-java@6.0.2': + resolution: {integrity: sha512-m5Nt1mQ/cznJY7tMfQTJchmrjdjQ71IDs+55d1GAa8DGaB8JXWsVCkVT284C3RTASaY43YknrK2X3hPO/J3MOQ==} + '@codemirror/lang-javascript@6.2.5': resolution: {integrity: sha512-zD4e5mS+50htS7F+TYjBPsiIFGanfVqg4HyUz6WNFikgOPf2BgKlx+TQedI1w6n/IqRBVBbBWmGFdLB/7uxO4A==} '@codemirror/lang-json@6.0.2': resolution: {integrity: sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==} + '@codemirror/lang-less@6.0.2': + resolution: {integrity: sha512-EYdQTG22V+KUUk8Qq582g7FMnCZeEHsyuOJisHRft/mQ+ZSZ2w51NupvDUHiqtsOy7It5cHLPGfHQLpMh9bqpQ==} + + '@codemirror/lang-liquid@6.3.2': + resolution: {integrity: sha512-6PDVU3ZnfeYyz1at1E/ttorErZvZFXXt1OPhtfe1EZJ2V2iDFa0CwPqPgG5F7NXN0yONGoBogKmFAafKTqlwIw==} + '@codemirror/lang-markdown@6.3.2': resolution: {integrity: sha512-c/5MYinGbFxYl4itE9q/rgN/sMTjOr8XL5OWnC+EaRMLfCbVUmmubTJfdgpfcSS2SCaT7b+Q+xi3l6CgoE+BsA==} @@ -2029,12 +2050,33 @@ packages: '@codemirror/lang-php@6.0.2': resolution: {integrity: sha512-ZKy2v1n8Fc8oEXj0Th0PUMXzQJ0AIR6TaZU+PbDHExFwdu+guzOA4jmCHS1Nz4vbFezwD7LyBdDnddSJeScMCA==} + '@codemirror/lang-python@6.2.1': + resolution: {integrity: sha512-IRjC8RUBhn9mGR9ywecNhB51yePWCGgvHfY1lWN/Mrp3cKuHr0isDKia+9HnvhiWNnMpbGhWrkhuWOc09exRyw==} + + '@codemirror/lang-rust@6.0.2': + resolution: {integrity: sha512-EZaGjCUegtiU7kSMvOfEZpaCReowEf3yNidYu7+vfuGTm9ow4mthAparY5hisJqOHmJowVH3Upu+eJlUji6qqA==} + + '@codemirror/lang-sass@6.0.2': + resolution: {integrity: sha512-l/bdzIABvnTo1nzdY6U+kPAC51czYQcOErfzQ9zSm9D8GmNPD0WTW8st/CJwBTPLO8jlrbyvlSEcN20dc4iL0Q==} + + '@codemirror/lang-sql@6.10.0': + resolution: {integrity: sha512-6ayPkEd/yRw0XKBx5uAiToSgGECo/GY2NoJIHXIIQh1EVwLuKoU8BP/qK0qH5NLXAbtJRLuT73hx7P9X34iO4w==} + '@codemirror/lang-vue@0.1.3': resolution: {integrity: sha512-QSKdtYTDRhEHCfo5zOShzxCmqKJvgGrZwDQSdbvCRJ5pRLWBS7pD/8e/tH44aVQT6FKm0t6RVNoSUWHOI5vNug==} + '@codemirror/lang-wast@6.0.2': + resolution: {integrity: sha512-Imi2KTpVGm7TKuUkqyJ5NRmeFWF7aMpNiwHnLQe0x9kmrxElndyH0K6H/gXtWwY6UshMRAhpENsgfpSwsgmC6Q==} + '@codemirror/lang-xml@6.1.0': resolution: {integrity: sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==} + '@codemirror/lang-yaml@6.1.3': + resolution: {integrity: sha512-AZ8DJBuXGVHybpBQhmZtgew5//4hv3tdkXnr3vDmOUMJRuB6vn/uuwtmTOTlqEaQFg3hQSVeA90NmvIQyUV6FQ==} + + '@codemirror/language-data@6.5.1': + resolution: {integrity: sha512-0sWxeUSNlBr6OmkqybUTImADFUP0M3P0IiSde4nc24bz/6jIYzqYSgkOSLS+CBIoW1vU8Q9KUWXscBXeoMVC9w==} + '@codemirror/language@6.12.3': resolution: {integrity: sha512-QwCZW6Tt1siP37Jet9Tb02Zs81TQt6qQrZR2H+eGMcFsL1zMrk2/b9CLC7/9ieP1fjIUMgviLWMmgiHoJrj+ZA==} @@ -3627,15 +3669,24 @@ packages: '@lezer/common@1.5.2': resolution: {integrity: sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ==} + '@lezer/cpp@1.1.5': + resolution: {integrity: sha512-DIhSXmYtJKLehrjzDFN+2cPt547ySQ41nA8yqcDf/GxMc+YM736xqltFkvADL2M0VebU5I+3+4ks2Vv+Kyq3Aw==} + '@lezer/css@1.1.11': resolution: {integrity: sha512-FuAnusbLBl1SEAtfN8NdShxYJiESKw9LAFysfea1T96jD3ydBn12oYjaSG1a04BQRIUd93/0D8e5CV1cUMkmQg==} + '@lezer/go@1.0.1': + resolution: {integrity: sha512-xToRsYxwsgJNHTgNdStpcvmbVuKxTapV0dM0wey1geMMRc9aggoVyKgzYp41D2/vVOx+Ii4hmE206kvxIXBVXQ==} + '@lezer/highlight@1.2.3': resolution: {integrity: sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==} '@lezer/html@1.3.12': resolution: {integrity: sha512-RJ7eRWdaJe3bsiiLLHjCFT1JMk8m1YP9kaUbvu2rMLEoOnke9mcTVDyfOslsln0LtujdWespjJ39w6zo+RsQYw==} + '@lezer/java@1.1.3': + resolution: {integrity: sha512-yHquUfujwg6Yu4Fd1GNHCvidIvJwi/1Xu2DaKl/pfWIA2c1oXkVvawH3NyXhCaFx4OdlYBVX5wvz2f7Aoa/4Xw==} + '@lezer/javascript@1.5.1': resolution: {integrity: sha512-ATOImjeVJuvgm3JQ/bpo2Tmv55HSScE2MTPnKRMRIPx2cLhHGyX2VnqpHhtIV1tVzIjZDbcWQm+NCTF40ggZVw==} @@ -3651,9 +3702,21 @@ packages: '@lezer/php@1.0.2': resolution: {integrity: sha512-GN7BnqtGRpFyeoKSEqxvGvhJQiI4zkgmYnDk/JIyc7H7Ifc1tkPnUn/R2R8meH3h/aBf5rzjvU8ZQoyiNDtDrA==} + '@lezer/python@1.1.18': + resolution: {integrity: sha512-31FiUrU7z9+d/ElGQLJFXl+dKOdx0jALlP3KEOsGTex8mvj+SoE1FgItcHWK/axkxCHGUSpqIHt6JAWfWu9Rhg==} + + '@lezer/rust@1.0.2': + resolution: {integrity: sha512-Lz5sIPBdF2FUXcWeCu1//ojFAZqzTQNRga0aYv6dYXqJqPfMdCAI0NzajWUd4Xijj1IKJLtjoXRPMvTKWBcqKg==} + + '@lezer/sass@1.1.0': + resolution: {integrity: sha512-3mMGdCTUZ/84ArHOuXWQr37pnf7f+Nw9ycPUeKX+wu19b7pSMcZGLbaXwvD2APMBDOGxPmpK/O6S1v1EvLoqgQ==} + '@lezer/xml@1.0.6': resolution: {integrity: sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww==} + '@lezer/yaml@1.0.4': + resolution: {integrity: sha512-2lrrHqxalACEbxIbsjhqGpSW8kWpUKuY6RHgnSAFZa6qK62wvnPxA8hGOwOoDbwHcOFs5M4o27mjGu+P7TvBmw==} + '@listr2/prompt-adapter-inquirer@2.0.22': resolution: {integrity: sha512-hV36ZoY+xKL6pYOt1nPNnkciFkn89KZwqLhAFzJvYysAvL5uBQdiADZx/8bIDXIukzzwG0QlPYolgMzQUtKgpQ==} engines: {node: '>=18.0.0'} @@ -15453,6 +15516,20 @@ snapshots: '@codemirror/view': 6.41.0 '@lezer/common': 1.5.2 + '@codemirror/lang-angular@0.1.4': + dependencies: + '@codemirror/lang-html': 6.4.11 + '@codemirror/lang-javascript': 6.2.5 + '@codemirror/language': 6.12.3 + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.2 + + '@codemirror/lang-cpp@6.0.3': + dependencies: + '@codemirror/language': 6.12.3 + '@lezer/cpp': 1.1.5 + '@codemirror/lang-css@6.3.1': dependencies: '@codemirror/autocomplete': 6.18.6 @@ -15461,6 +15538,14 @@ snapshots: '@lezer/common': 1.5.2 '@lezer/css': 1.1.11 + '@codemirror/lang-go@6.0.1': + dependencies: + '@codemirror/autocomplete': 6.18.6 + '@codemirror/language': 6.12.3 + '@codemirror/state': 6.6.0 + '@lezer/common': 1.5.2 + '@lezer/go': 1.0.1 + '@codemirror/lang-html@6.4.11': dependencies: '@codemirror/autocomplete': 6.18.6 @@ -15473,6 +15558,11 @@ snapshots: '@lezer/css': 1.1.11 '@lezer/html': 1.3.12 + '@codemirror/lang-java@6.0.2': + dependencies: + '@codemirror/language': 6.12.3 + '@lezer/java': 1.1.3 + '@codemirror/lang-javascript@6.2.5': dependencies: '@codemirror/autocomplete': 6.18.6 @@ -15488,6 +15578,25 @@ snapshots: '@codemirror/language': 6.12.3 '@lezer/json': 1.0.3 + '@codemirror/lang-less@6.0.2': + dependencies: + '@codemirror/lang-css': 6.3.1 + '@codemirror/language': 6.12.3 + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.2 + + '@codemirror/lang-liquid@6.3.2': + dependencies: + '@codemirror/autocomplete': 6.18.6 + '@codemirror/lang-html': 6.4.11 + '@codemirror/language': 6.12.3 + '@codemirror/state': 6.6.0 + '@codemirror/view': 6.41.0 + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.2 + '@codemirror/lang-markdown@6.3.2': dependencies: '@codemirror/autocomplete': 6.18.6 @@ -15516,6 +15625,36 @@ snapshots: '@lezer/common': 1.5.2 '@lezer/php': 1.0.2 + '@codemirror/lang-python@6.2.1': + dependencies: + '@codemirror/autocomplete': 6.18.6 + '@codemirror/language': 6.12.3 + '@codemirror/state': 6.6.0 + '@lezer/common': 1.5.2 + '@lezer/python': 1.1.18 + + '@codemirror/lang-rust@6.0.2': + dependencies: + '@codemirror/language': 6.12.3 + '@lezer/rust': 1.0.2 + + '@codemirror/lang-sass@6.0.2': + dependencies: + '@codemirror/lang-css': 6.3.1 + '@codemirror/language': 6.12.3 + '@codemirror/state': 6.6.0 + '@lezer/common': 1.5.2 + '@lezer/sass': 1.1.0 + + '@codemirror/lang-sql@6.10.0': + dependencies: + '@codemirror/autocomplete': 6.18.6 + '@codemirror/language': 6.12.3 + '@codemirror/state': 6.6.0 + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.2 + '@codemirror/lang-vue@0.1.3': dependencies: '@codemirror/lang-html': 6.4.11 @@ -15525,6 +15664,13 @@ snapshots: '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.2 + '@codemirror/lang-wast@6.0.2': + dependencies: + '@codemirror/language': 6.12.3 + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.2 + '@codemirror/lang-xml@6.1.0': dependencies: '@codemirror/autocomplete': 6.18.6 @@ -15534,6 +15680,41 @@ snapshots: '@lezer/common': 1.5.2 '@lezer/xml': 1.0.6 + '@codemirror/lang-yaml@6.1.3': + dependencies: + '@codemirror/autocomplete': 6.18.6 + '@codemirror/language': 6.12.3 + '@codemirror/state': 6.6.0 + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.2 + '@lezer/yaml': 1.0.4 + + '@codemirror/language-data@6.5.1': + dependencies: + '@codemirror/lang-angular': 0.1.4 + '@codemirror/lang-cpp': 6.0.3 + '@codemirror/lang-css': 6.3.1 + '@codemirror/lang-go': 6.0.1 + '@codemirror/lang-html': 6.4.11 + '@codemirror/lang-java': 6.0.2 + '@codemirror/lang-javascript': 6.2.5 + '@codemirror/lang-json': 6.0.2 + '@codemirror/lang-less': 6.0.2 + '@codemirror/lang-liquid': 6.3.2 + '@codemirror/lang-markdown': 6.5.0 + '@codemirror/lang-php': 6.0.2 + '@codemirror/lang-python': 6.2.1 + '@codemirror/lang-rust': 6.0.2 + '@codemirror/lang-sass': 6.0.2 + '@codemirror/lang-sql': 6.10.0 + '@codemirror/lang-vue': 0.1.3 + '@codemirror/lang-wast': 6.0.2 + '@codemirror/lang-xml': 6.1.0 + '@codemirror/lang-yaml': 6.1.3 + '@codemirror/language': 6.12.3 + '@codemirror/legacy-modes': 6.5.2 + '@codemirror/language@6.12.3': dependencies: '@codemirror/state': 6.6.0 @@ -17280,12 +17461,24 @@ snapshots: '@lezer/common@1.5.2': {} + '@lezer/cpp@1.1.5': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.2 + '@lezer/css@1.1.11': dependencies: '@lezer/common': 1.5.2 '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.2 + '@lezer/go@1.0.1': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.2 + '@lezer/highlight@1.2.3': dependencies: '@lezer/common': 1.5.2 @@ -17296,6 +17489,12 @@ snapshots: '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.2 + '@lezer/java@1.1.3': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.2 + '@lezer/javascript@1.5.1': dependencies: '@lezer/common': 1.5.2 @@ -17323,12 +17522,36 @@ snapshots: '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.2 + '@lezer/python@1.1.18': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.2 + + '@lezer/rust@1.0.2': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.2 + + '@lezer/sass@1.1.0': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.2 + '@lezer/xml@1.0.6': dependencies: '@lezer/common': 1.5.2 '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.2 + '@lezer/yaml@1.0.4': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.2 + '@listr2/prompt-adapter-inquirer@2.0.22(@inquirer/prompts@6.0.1)': dependencies: '@inquirer/prompts': 6.0.1 From e943891e2f4597092d2c6d79eecb0bffeff85e50 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 07:09:36 +0300 Subject: [PATCH 295/482] chore(markdown): improve code margins when scrolling --- apps/client/src/widgets/type_widgets/code/Markdown.css | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/client/src/widgets/type_widgets/code/Markdown.css b/apps/client/src/widgets/type_widgets/code/Markdown.css index 88f1aba621..224fb0d62f 100644 --- a/apps/client/src/widgets/type_widgets/code/Markdown.css +++ b/apps/client/src/widgets/type_widgets/code/Markdown.css @@ -1,6 +1,10 @@ .note-detail-markdown { - .note-detail-code-editor .cm-editor { - padding-block: 0.25em; + .note-detail-code-editor { + margin-top: 0 !important; + + .cm-editor .cm-scroller { + padding-block: 0.25em; + } } .markdown-preview { From 0c051327cf430e360920f51520fd97f93f62c938 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 07:13:46 +0300 Subject: [PATCH 296/482] feat(markdown): render with ReadOnlyText --- .../widgets/type_widgets/code/Markdown.tsx | 9 +- .../type_widgets/text/ReadOnlyText.tsx | 116 +++++++++++------- 2 files changed, 79 insertions(+), 46 deletions(-) diff --git a/apps/client/src/widgets/type_widgets/code/Markdown.tsx b/apps/client/src/widgets/type_widgets/code/Markdown.tsx index 158cd39ddb..86bff72708 100644 --- a/apps/client/src/widgets/type_widgets/code/Markdown.tsx +++ b/apps/client/src/widgets/type_widgets/code/Markdown.tsx @@ -7,6 +7,7 @@ import { RefObject } from "preact"; import { useEffect, useMemo, useRef, useState } from "preact/hooks"; import SplitEditor from "../helpers/SplitEditor"; +import { ReadOnlyTextContent } from "../text/ReadOnlyText"; import { TypeWidgetProps } from "../type_widget"; const marked = new Marked({ breaks: true, gfm: true }); @@ -27,11 +28,11 @@ export default function Markdown(props: TypeWidgetProps) { editorRef={editorRef} onContentChanged={setContent} previewContent={( -
    )} /> diff --git a/apps/client/src/widgets/type_widgets/text/ReadOnlyText.tsx b/apps/client/src/widgets/type_widgets/text/ReadOnlyText.tsx index 172abb6990..e10a90cb80 100644 --- a/apps/client/src/widgets/type_widgets/text/ReadOnlyText.tsx +++ b/apps/client/src/widgets/type_widgets/text/ReadOnlyText.tsx @@ -5,7 +5,8 @@ import "./ReadOnlyText.css"; import "@triliumnext/ckeditor5"; import clsx from "clsx"; -import { useEffect, useMemo, useRef } from "preact/hooks"; +import { RefObject } from "preact"; +import { useEffect, useMemo } from "preact/hooks"; import appContext from "../../../components/app_context"; import FNote from "../../../entities/fnote"; @@ -13,7 +14,7 @@ import { applyInlineMermaid, rewriteMermaidDiagramsInContainer } from "../../../ import { getLocaleById } from "../../../services/i18n"; import { renderMathInElement } from "../../../services/math"; import { formatCodeBlocks } from "../../../services/syntax_highlight"; -import { useNoteBlob, useNoteLabel, useTriliumEvent, useTriliumOption, useTriliumOptionBool } from "../../react/hooks"; +import { useNoteBlob, useNoteLabel, useSyncedRef, useTriliumEvent, useTriliumOption, useTriliumOptionBool } from "../../react/hooks"; import { RawHtmlBlock } from "../../react/RawHtml"; import TouchBar, { TouchBarButton, TouchBarSpacer } from "../../react/TouchBar"; import { TypeWidgetProps } from "../type_widget"; @@ -22,51 +23,14 @@ import { loadIncludedNote, refreshIncludedNote, setupImageOpening } from "./util export default function ReadOnlyText({ note, noteContext, ntxId }: TypeWidgetProps) { const blob = useNoteBlob(note); - const contentRef = useRef(null); - const [ codeBlockWordWrap ] = useTriliumOptionBool("codeBlockWordWrap"); - const [ codeBlockTabWidth ] = useTriliumOption("codeBlockTabWidth"); const { isRtl } = useNoteLanguage(note); - useEffect(() => { - document.body.style.setProperty("--code-block-tab-width", codeBlockTabWidth || "4"); - }, [codeBlockTabWidth]); - - // Apply necessary transforms. - useEffect(() => { - const container = contentRef.current; - if (!container) return; - - appContext.triggerEvent("contentElRefreshed", { ntxId, contentEl: container }); - - rewriteMermaidDiagramsInContainer(container); - applyInlineMermaid(container); - applyIncludedNotes(container); - applyMath(container); - applyReferenceLinks(container); - formatCodeBlocks($(container)); - setupImageOpening(container, true); - }, [ blob ]); - - // React to included note changes. - useTriliumEvent("refreshIncludedNote", ({ noteId }) => { - if (!contentRef.current) return; - refreshIncludedNote(contentRef.current, noteId); - }); - - // Search integration. - useTriliumEvent("executeWithContentElement", ({ resolve, ntxId: eventNtxId }) => { - if (eventNtxId !== ntxId || !contentRef.current) return; - resolve($(contentRef.current)); - }); - return ( <> - @@ -85,6 +49,74 @@ export default function ReadOnlyText({ note, noteContext, ntxId }: TypeWidgetPro ); } +interface ReadOnlyTextContentProps { + /** CKEditor-compatible HTML to render. */ + html: string; + /** Note context id — enables `contentElRefreshed` / `executeWithContentElement` integrations when provided. */ + ntxId?: string | null; + dir?: "ltr" | "rtl"; + /** Extra classes appended to the content div. */ + className?: string; + /** Optional external ref to the rendered content div (e.g. to drive scroll sync). */ + contentRef?: RefObject; +} + +/** + * Renders arbitrary CKEditor-style HTML with the same pipeline as {@link ReadOnlyText}: + * mermaid rewriting, inline mermaid, included-note expansion, KaTeX math, reference-link + * titles, code-block syntax highlighting, and image click handling. Transforms re-run + * whenever `html` changes. + */ +export function ReadOnlyTextContent({ html, ntxId, dir, className, contentRef: externalContentRef }: ReadOnlyTextContentProps) { + const contentRef = useSyncedRef(externalContentRef); + const [ codeBlockWordWrap ] = useTriliumOptionBool("codeBlockWordWrap"); + const [ codeBlockTabWidth ] = useTriliumOption("codeBlockTabWidth"); + + useEffect(() => { + document.body.style.setProperty("--code-block-tab-width", codeBlockTabWidth || "4"); + }, [codeBlockTabWidth]); + + // Apply necessary transforms. + useEffect(() => { + const container = contentRef.current; + if (!container) return; + + if (ntxId) { + appContext.triggerEvent("contentElRefreshed", { ntxId, contentEl: container }); + } + + rewriteMermaidDiagramsInContainer(container); + applyInlineMermaid(container); + applyIncludedNotes(container); + applyMath(container); + applyReferenceLinks(container); + formatCodeBlocks($(container)); + setupImageOpening(container, true); + }, [ html, ntxId, contentRef ]); + + // React to included note changes. + useTriliumEvent("refreshIncludedNote", ({ noteId }) => { + if (!contentRef.current) return; + refreshIncludedNote(contentRef.current, noteId); + }); + + // Search integration. + useTriliumEvent("executeWithContentElement", ({ resolve, ntxId: eventNtxId }) => { + if (!ntxId || eventNtxId !== ntxId || !contentRef.current) return; + resolve($(contentRef.current)); + }); + + return ( + + ); +} + function useNoteLanguage(note: FNote) { const [ language ] = useNoteLabel(note, "language"); const isRtl = useMemo(() => { From 11b0bec47d829f002d6ce4a8e5f359d1d2081f72 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 07:15:39 +0300 Subject: [PATCH 297/482] chore(markdown): improve max width of Mermaid diagrams --- apps/client/src/widgets/type_widgets/code/Markdown.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/client/src/widgets/type_widgets/code/Markdown.css b/apps/client/src/widgets/type_widgets/code/Markdown.css index 224fb0d62f..30edf72ffe 100644 --- a/apps/client/src/widgets/type_widgets/code/Markdown.css +++ b/apps/client/src/widgets/type_widgets/code/Markdown.css @@ -13,6 +13,11 @@ overflow: auto; padding: 0.5em 1em; user-select: text; + + .mermaid-diagram, + .mermaid-diagram svg { + max-width: 100%; + } } .markdown-preview [data-source-line] { From 822e7ffbabd405db06f5f5ef3e6f00ac14324a25 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 07:32:08 +0300 Subject: [PATCH 298/482] feat(markdown): support full feature set (math, admonitions) --- .../type_widgets/code/Markdown.spec.ts | 20 +- .../widgets/type_widgets/code/Markdown.tsx | 36 ++- apps/server/src/services/export/markdown.ts | 10 +- apps/server/src/services/import/markdown.ts | 228 +-------------- packages/commons/src/index.ts | 1 + packages/commons/src/lib/markdown_renderer.ts | 275 ++++++++++++++++++ 6 files changed, 325 insertions(+), 245 deletions(-) create mode 100644 packages/commons/src/lib/markdown_renderer.ts diff --git a/apps/client/src/widgets/type_widgets/code/Markdown.spec.ts b/apps/client/src/widgets/type_widgets/code/Markdown.spec.ts index 15369b8f43..3153e8b7a0 100644 --- a/apps/client/src/widgets/type_widgets/code/Markdown.spec.ts +++ b/apps/client/src/widgets/type_widgets/code/Markdown.spec.ts @@ -43,9 +43,8 @@ describe("renderWithSourceLines", () => { }); it("renders standard markdown constructs inside the wrappers", () => { - const html = renderWithSourceLines("# Heading\n\n- item\n"); - expect(html).toContain("Heading"); expect(html).toContain("
      "); expect(html).toContain("
    • item
    • "); }); @@ -60,4 +59,19 @@ describe("renderWithSourceLines", () => { const html = renderWithSourceLines(src); expect(html).toContain('href="https://example.com"'); }); + + it("normalizes fenced code languages to CKEditor MIME identifiers for syntax highlighting", () => { + const html = renderWithSourceLines("```javascript\nconst x = 1;\n```"); + expect(html).toMatch(/class="language-application-javascript-env-(backend|frontend)"/); + }); + + it("produces CKEditor admonition markup for GFM callouts", () => { + const html = renderWithSourceLines("> [!NOTE]\n> heads up"); + expect(html).toContain('
  • The size of the source/preview panes can be adjusted by hovering over the border between them and dragging it with the mouse.
  • In the Floating buttons area:
    • The source/preview can be laid out left-right or bottom-top via the Move editing pane to the left / bottom option.
    • -
    • Press Lock editing to automatically mark the note as read-only. +
    • Press Lock editing to automatically mark the note as read-only. In this mode, the code pane is hidden and the diagram is displayed full-size. Similarly, press Unlock editing to mark a read-only note as editable.
    • -
    • Press the Copy image reference to the clipboard to be able to insert - the image representation of the diagram into a text note. See Image references for more information.
    • -
    • Press the Export diagram as SVG to download a scalable/vector rendering - of the diagram. Can be used to present the diagram without degrading when - zooming.
    • +
    • Press the Copy image reference to the clipboard to be able to insert + the image representation of the diagram into a text note. See [missing note] for more information.
    • +
    • Press the Export diagram as SVG to download a scalable/vector rendering + of the diagram. Can be used to present the diagram without degrading when + zooming.
    • Press the Export diagram as PNG to download a normal image (at 1x scale, raster) of the diagram. Can be used to send the diagram in more traditional channels such as e-mail.
    • -
    -
  • + +

    Errors in the diagram

    If there is an error in the source code, the error will be displayed in diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Render Note.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Render Note.html index 7e6b8cddbe..4a33c30bfe 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Render Note.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Render Note.html @@ -13,11 +13,13 @@

    1. HTML language for the legacy/vanilla method, with what needs to be displayed (for example <p>Hello world.</p>).
    2. -
    3. JSX for the Preact-based approach (see below).
    4. -
    +
  • JSX for the Preact-based approach (see below).
  • +
  • Create a Render Note.
  • -
  • Assign the renderNote relation to +
  • Assign the renderNote relation to point at the previously created code note.
  • Legacy scripting using jQuery

    @@ -46,10 +48,9 @@ $dateEl.text(new Date()); need to provide a HTML anymore.

    Here are the steps to creating a simple render note:

      -
    1. -

      Create a note of type Render Note.

      -
    2. -
    3. +
    4. Create a note of type Render Note.
    5. +
    6. Create a child Code note with JSX as the language.
      As an example, use the following content:

      export default function() {
      @@ -59,24 +60,21 @@ $dateEl.text(new Date());
      </> ); } -
    7. -
    8. -

      In the parent render note, define a ~renderNote relation - pointing to the newly created child.

      -
    9. -
    10. -

      Refresh the render note and it should display a “Hello world” message.

      -
    11. + +
    12. In the parent render note, define a ~renderNote relation + pointing to the newly created child.
    13. +
    14. Refresh the render note and it should display a “Hello world” message.

    Refreshing the note

    It's possible to refresh the note via:

    Examples

    \ No newline at end of file diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text.html index 42dbe0fa44..26a0791ace 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text.html @@ -20,168 +20,171 @@

    Fore more information see Formatting toolbar.

    Features and formatting

    Here's a list of various features supported by text notes:

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Dedicated articleFeature
    General formatting - -
      -
    • Headings (section titles, paragraph)
    • -
    • Font size
    • -
    • Bold, italic, underline, strike-through
    • -
    • Superscript, subscript
    • -
    • Font color & background color
    • -
    • Remove formatting
    • -
    -
    Lists - -
      -
    • Bulleted lists
    • -
    • Numbered lists
    • -
    • To-do lists
    • -
    -
    Block quotes & admonitions - -
      -
    • Block quotes
    • -
    • Admonitions
    • -
    -
    Tables - -
      -
    • Basic tables
    • -
    • Merging cells
    • -
    • Styling tables and cells.
    • -
    • Table captions
    • -
    -
    Developer-specific formatting - -
      -
    • Inline code
    • -
    • Code blocks
    • -
    • Keyboard shortcuts
    • -
    -
    Footnotes - -
      -
    • Footnotes
    • -
    -
    Images - -
      -
    • Images
    • -
    -
    Links - -
      -
    • External links
    • -
    • Internal Trilium links
    • -
    -
    Include Note - -
      -
    • Include note
    • -
    -
    Insert buttons - -
      -
    • Symbols
    • -
    • Math Equations -
    • -
    • Mermaid diagrams
    • -
    • Horizontal ruler
    • -
    • Page break
    • -
    -
    Other features - - -
    Premium features - - -
    -

    Read-Only vs. Editing Mode

    -

    Text notes are usually opened in edit mode. However, they may open in - read-only mode if the note is too big or the note is explicitly marked - as read-only. For more information, see Read-Only Notes.

    -

    Keyboard shortcuts

    -

    There are numerous keyboard shortcuts to format the text without having - to use the mouse. For a reference of all the key combinations, see  - Keyboard Shortcuts. In addition, see Markdown-like formatting as an alternative - to the keyboard shortcuts.

    -

    Technical details

    -

    For the text editing functionality, Trilium uses a commercial product - (with an open-source base) called CKEditor. - This brings the benefit of having a powerful WYSIWYG (What You See Is What - You Get) editor.

    \ No newline at end of file +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Dedicated articleFeature
    General formatting + +
      +
    • Headings (section titles, paragraph)
    • +
    • Font size
    • +
    • Bold, italic, underline, strike-through
    • +
    • Superscript, subscript
    • +
    • Font color & background color
    • +
    • Remove formatting
    • +
    +
    Lists + +
      +
    • Bulleted lists
    • +
    • Numbered lists
    • +
    • To-do lists
    • +
    +
    Block quotes & admonitions + +
      +
    • Block quotes
    • +
    • Admonitions
    • +
    +
    Tables + +
      +
    • Basic tables
    • +
    • Merging cells
    • +
    • Styling tables and cells.
    • +
    • Table captions
    • +
    +
    Developer-specific formatting + +
      +
    • Inline code
    • +
    • Code blocks
    • +
    • Keyboard shortcuts
    • +
    +
    Footnotes + +
      +
    • Footnotes
    • +
    +
    Images + +
      +
    • Images
    • +
    +
    Links + +
      +
    • External links
    • +
    • Internal Trilium links
    • +
    +
    Include Note + +
      +
    • Include note
    • +
    +
    Insert buttons + +
      +
    • Symbols
    • +
    • Math Equations +
    • +
    • Mermaid diagrams
    • +
    • Horizontal ruler
    • +
    • Page break
    • +
    +
    Other features + + +
    Premium features + + +
    +
    +

    Read-Only vs. Editing Mode

    +

    Text notes are usually opened in edit mode. However, they may open in + read-only mode if the note is too big or the note is explicitly marked + as read-only. For more information, see Read-Only Notes.

    +

    Keyboard shortcuts

    +

    There are numerous keyboard shortcuts to format the text without having + to use the mouse. For a reference of all the key combinations, see  + Keyboard Shortcuts. In addition, see Markdown-like formatting as an alternative + to the keyboard shortcuts.

    +

    Technical details

    +

    For the text editing functionality, Trilium uses a commercial product + (with an open-source base) called CKEditor. + This brings the benefit of having a powerful WYSIWYG (What You See Is What + You Get) editor.

    \ No newline at end of file diff --git a/docs/Developer Guide/Developer Guide/Documentation.md b/docs/Developer Guide/Developer Guide/Documentation.md index 2176a424b1..aae807a49d 100644 --- a/docs/Developer Guide/Developer Guide/Documentation.md +++ b/docs/Developer Guide/Developer Guide/Documentation.md @@ -1,5 +1,5 @@ # Documentation -There are multiple types of documentation for Trilium: +There are multiple types of documentation for Trilium: * The _User Guide_ represents the user-facing documentation. This documentation can be browsed by users directly from within Trilium, by pressing F1. * The _Developer's Guide_ represents a set of Markdown documents that present the internals of Trilium, for developers. diff --git a/docs/User Guide/!!!meta.json b/docs/User Guide/!!!meta.json index a70689b577..f7e41610bf 100644 --- a/docs/User Guide/!!!meta.json +++ b/docs/User Guide/!!!meta.json @@ -10739,6 +10739,117 @@ "dataFileName": "Spreadsheets_image.png" } ] + }, + { + "isClone": false, + "noteId": "6RM1Q7ppFVoj", + "notePath": [ + "pOsGYCXsbNQG", + "KSZ04uQ2D1St", + "6RM1Q7ppFVoj" + ], + "title": "Markdown", + "notePosition": 230, + "prefix": null, + "isExpanded": false, + "type": "text", + "mime": "text/html", + "attributes": [ + { + "type": "label", + "name": "iconClass", + "value": "bx bxl-markdown", + "isInheritable": false, + "position": 30 + }, + { + "type": "label", + "name": "shareAlias", + "value": "markdown", + "isInheritable": false, + "position": 40 + }, + { + "type": "relation", + "name": "internalLink", + "value": "Oau6X9rCuegd", + "isInheritable": false, + "position": 50 + }, + { + "type": "relation", + "name": "internalLink", + "value": "iPIMuisry3hd", + "isInheritable": false, + "position": 60 + }, + { + "type": "relation", + "name": "internalLink", + "value": "6f9hih2hXXZk", + "isInheritable": false, + "position": 70 + }, + { + "type": "relation", + "name": "internalLink", + "value": "oPVyFC7WL2Lp", + "isInheritable": false, + "position": 80 + }, + { + "type": "relation", + "name": "internalLink", + "value": "NwBbFdNZ9h7O", + "isInheritable": false, + "position": 90 + }, + { + "type": "relation", + "name": "internalLink", + "value": "YfYAtQBcfo5V", + "isInheritable": false, + "position": 100 + }, + { + "type": "relation", + "name": "internalLink", + "value": "s1aBHPd79XYj", + "isInheritable": false, + "position": 110 + }, + { + "type": "relation", + "name": "internalLink", + "value": "nBAXQFj20hS1", + "isInheritable": false, + "position": 120 + }, + { + "type": "relation", + "name": "internalLink", + "value": "hrZ1D00cLbal", + "isInheritable": false, + "position": 130 + }, + { + "type": "relation", + "name": "internalLink", + "value": "m1lbrzyKDaRB", + "isInheritable": false, + "position": 140 + }, + { + "type": "relation", + "name": "internalLink", + "value": "wy8So3yZZlH9", + "isInheritable": false, + "position": 150 + } + ], + "format": "markdown", + "dataFileName": "Markdown.md", + "attachments": [] } ] }, diff --git a/docs/User Guide/User Guide/Note Types.md b/docs/User Guide/User Guide/Note Types.md index 71ac53e644..8505e4fe8e 100644 --- a/docs/User Guide/User Guide/Note Types.md +++ b/docs/User Guide/User Guide/Note Types.md @@ -33,7 +33,7 @@ The following note types are supported by Trilium: | Relation Map | Allows easy creation of notes and relations between them. Can be used for mainly relational data such as a family tree. | | Note Map | Displays the relationships between the notes, whether via relations or their hierarchical structure. | | Render Note | Used in Scripting, it displays the HTML content of another note. This allows displaying any kind of content, provided there is a script behind it to generate it. | -| Collections | Displays the children of the note either as a grid, a list, or for a more specialized case: a calendar. 

    Generally useful for easy reading of short notes. | +| Collections | Displays the children of the note either as a grid, a list, or for a more specialized case: a calendar.  

    Generally useful for easy reading of short notes. | | Mermaid Diagrams | Displays diagrams such as bar charts, flow charts, state diagrams, etc. Requires a bit of technical knowledge since the diagrams are written in a specialized format. | | Canvas | Allows easy drawing of sketches, diagrams, handwritten content. Uses the same technology behind [excalidraw.com](https://excalidraw.com). | | Web View | Displays the content of an external web page, similar to a browser. | diff --git a/docs/User Guide/User Guide/Note Types/Markdown.md b/docs/User Guide/User Guide/Note Types/Markdown.md new file mode 100644 index 0000000000..685fc59b90 --- /dev/null +++ b/docs/User Guide/User Guide/Note Types/Markdown.md @@ -0,0 +1,51 @@ +# Markdown +Trilium has always supported Markdown through its [import feature](../Basic%20Concepts%20and%20Features/Import%20%26%20Export/Markdown.md), however the file was either transformed to a Text note (converted to Trilium's internal HTML format) or saved as a Code note with only syntax highlight. + +v0.103.0 introduces a new note type: Markdown which which displays Markdown source and a preview on the right. + +## Rationale + +The goal of this note type is to fill a gap: rendering Markdown but not altering its structure or its whitespace which would inevitably change otherwise through import/export. + +Even if Markdown is now specially treated by having a preview mechanism, Trilium remains at its core a WYSWYG editor so Markdown will not replace text notes. + +> [!NOTE] +> Feature requests regarding the Markdown implementation will be considered, but if they are outside the realm of Trilium they will not be implemented. One of the core aspects of the Markdown integration is that it reuses components that are already available through other features of the application. + +## Creating Markdown notes + +There are two ways to create a Markdown note: + +1. Create a new note (e.g. in the Note Tree) and select the type _Markdown_, just like all the other note types. +2. Create a note of type Code and select as the language either _Markdown_ or _GitHub-Flavored Markdown_. This maintains compatibility with your existing notes prior to the introduction of this feature. + +## Supported features in preview + +The following features are supported by Trilium's Markdown format and will show up in the preview pane: + +* All standard and GitHub-flavored syntax (basic formatting, tables, blockquotes) +* Code blocks with syntax highlight (e.g. ` ```js `) and automatic syntax highlight +* Block quotes & admonitions +* Math Equations +* Mermaid Diagrams using ` ```mermaid ` +* Include Note (no builtin Markdown syntax, but HTML syntax works just fine): + + ``` +
    +   +
    + ``` +* Internal (reference) links via its HTML syntax, or through a _Wikilinks_\-like format (only Note ID): + + ``` + [[Hg8TS5ZOxti6]] + ``` + +## Sync-scrolling + +When scrolling through the editing pane, the preview pane will attempt to synchronize its position to make it easier to see the preview. + +This feature cannot be disabled as of now; if the scrolling feels distracting, consider temporarily switching to the editor mode and then switching to preview mode when ready. + +> [!NOTE] +> This feature of synchronizing the scroll is based on blocks but it's provided on a best-effort basis since our underlying Markdown library doesn't support this feature natively, so we had to implement our own algorithm. Feel free to [report issues](../Troubleshooting/Reporting%20issues.md), but always provide a sample Markdown file to be able to reproduce it. \ No newline at end of file diff --git a/docs/User Guide/User Guide/Note Types/Mermaid Diagrams.md b/docs/User Guide/User Guide/Note Types/Mermaid Diagrams.md index 14b0729875..aea9436b24 100644 --- a/docs/User Guide/User Guide/Note Types/Mermaid Diagrams.md +++ b/docs/User Guide/User Guide/Note Types/Mermaid Diagrams.md @@ -35,7 +35,7 @@ It's possible to switch between the two layouts at any time by pressing the ![]( * In the Floating buttons area: * The source/preview can be laid out left-right or bottom-top via the _Move editing pane to the left / bottom_ option. * Press _Lock editing_ to automatically mark the note as read-only. In this mode, the code pane is hidden and the diagram is displayed full-size. Similarly, press _Unlock editing_ to mark a read-only note as editable. - * Press the _Copy image reference to the clipboard_ to be able to insert the image representation of the diagram into a text note. See Image references for more information. + * Press the _Copy image reference to the clipboard_ to be able to insert the image representation of the diagram into a text note. See [missing note] for more information. * Press the _Export diagram as SVG_ to download a scalable/vector rendering of the diagram. Can be used to present the diagram without degrading when zooming. * Press the _Export diagram as PNG_ to download a normal image (at 1x scale, raster) of the diagram. Can be used to send the diagram in more traditional channels such as e-mail. diff --git a/docs/User Guide/User Guide/Note Types/Render Note.md b/docs/User Guide/User Guide/Note Types/Render Note.md index 60387ce507..7bed5b4b79 100644 --- a/docs/User Guide/User Guide/Note Types/Render Note.md +++ b/docs/User Guide/User Guide/Note Types/Render Note.md @@ -69,4 +69,4 @@ It's possible to refresh the note via: ## Examples -* Weight Tracker which is present in the Demo Notes. \ No newline at end of file +* [missing note] which is present in the [missing note]. \ No newline at end of file From 5f32d83c790ae1d5275eec9a570da8a12f619893 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 21:24:43 +0300 Subject: [PATCH 333/482] fix(markdown): always maintain horizontal layout --- apps/client/src/widgets/type_widgets/code/Markdown.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/client/src/widgets/type_widgets/code/Markdown.tsx b/apps/client/src/widgets/type_widgets/code/Markdown.tsx index 586baa35b2..05a27ad511 100644 --- a/apps/client/src/widgets/type_widgets/code/Markdown.tsx +++ b/apps/client/src/widgets/type_widgets/code/Markdown.tsx @@ -49,6 +49,7 @@ export default function Markdown(props: TypeWidgetProps) { editorRef={setEditorView} onContentChanged={setContent} previewContent={} + forceOrientation="horizontal" /> ); From 9ff466c9f5bf89e58b5741c382cfdfea659dc8f8 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 21:33:31 +0300 Subject: [PATCH 334/482] docs: add more details to Markdown note type --- .../doc_notes/en/User Guide/!!!meta.json | 2 +- .../Note types with split view.html | 31 +++++ .../User Guide/Note Types/File.html | 37 +++--- .../User Guide/Note Types/Markdown.html | 98 ++++++++++++--- .../Note Types/Mermaid Diagrams.html | 8 +- .../User Guide/Note Types/Spreadsheets.html | 23 ++-- docs/User Guide/!!!meta.json | 117 ++++++++++++++++-- .../UI Elements/Note types with split view.md | 21 ++++ .../User Guide/Note Types/Markdown.md | 58 +++++++-- .../User Guide/Note Types/Mermaid Diagrams.md | 8 +- .../User Guide/Note Types/Spreadsheets.md | 1 - 11 files changed, 330 insertions(+), 74 deletions(-) create mode 100644 apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note types with split view.html create mode 100644 docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note types with split view.md diff --git a/apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json b/apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json index d4be06ab6b..9997e61c67 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json +++ b/apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json @@ -1 +1 @@ -[{"id":"_help_BOCnjTMBCoxW","title":"Feature Highlights","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Feature Highlights"},{"name":"iconClass","value":"bx bx-star","type":"label"}]},{"id":"_help_Otzi9La2YAUX","title":"Installation & Setup","type":"book","attributes":[{"name":"iconClass","value":"bx bx-cog","type":"label"}],"children":[{"id":"_help_poXkQfguuA0U","title":"Desktop Installation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation"},{"name":"iconClass","value":"bx bx-desktop","type":"label"}],"children":[{"id":"_help_nRqcgfTb97uV","title":"Using the desktop application as a server","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/Using the desktop application "},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_Rp0q8bSP6Ayl","title":"System Requirements","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/System Requirements"},{"name":"iconClass","value":"bx bx-chip","type":"label"}]},{"id":"_help_Un4wj2Mak2Ky","title":"Nix flake","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/Nix flake"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]}]},{"id":"_help_WOcw2SLH6tbX","title":"Server Installation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation"},{"name":"iconClass","value":"bx bx-server","type":"label"}],"children":[{"id":"_help_Dgg7bR3b6K9j","title":"1. Installing the server","type":"book","attributes":[{"name":"iconClass","value":"bx bx-folder","type":"label"}],"children":[{"id":"_help_3tW6mORuTHnB","title":"Packaged version for Linux","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Packaged version for Linux"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]},{"id":"_help_rWX5eY045zbE","title":"Using Docker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Docker"},{"name":"iconClass","value":"bx bxl-docker","type":"label"}]},{"id":"_help_moVgBcoxE3EK","title":"On NixOS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/On NixOS"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]},{"id":"_help_J1Bb6lVlwU5T","title":"Manually","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Manually"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}]},{"id":"_help_DCmT6e7clMoP","title":"Using Kubernetes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Kubernetes"},{"name":"iconClass","value":"bx bxl-kubernetes","type":"label"}]},{"id":"_help_klCWNks3ReaQ","title":"Multiple server instances","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Multiple server instances"},{"name":"iconClass","value":"bx bxs-user-account","type":"label"}]}]},{"id":"_help_vcjrb3VVYPZI","title":"2. Reverse proxy","type":"book","attributes":[{"name":"iconClass","value":"bx bx-folder","type":"label"}],"children":[{"id":"_help_ud6MShXL4WpO","title":"Nginx","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Nginx"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_fDLvzOx29Pfg","title":"Apache using Docker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Apache using Docker"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_LLzSMXACKhUs","title":"Trusted proxy","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Trusted proxy"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_5ERVJb9s4FRD","title":"Traefik","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Traefik"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_l2VkvOwUNfZj","title":"HTTPS (TLS)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/HTTPS (TLS)"},{"name":"iconClass","value":"bx bx-lock-alt","type":"label"}]},{"id":"_help_0hzsNCP31IAB","title":"Authentication","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Authentication"},{"name":"iconClass","value":"bx bx-user","type":"label"}]},{"id":"_help_7DAiwaf8Z7Rz","title":"Multi-Factor Authentication","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Multi-Factor Authentication"},{"name":"iconClass","value":"bx bx-stopwatch","type":"label"}]},{"id":"_help_Un4wj2Mak2Ky","title":"Nix flake","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Nix flake.clone"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_yeEaYqosGLSh","title":"Third-party cloud hosting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Third-party cloud hosting"},{"name":"iconClass","value":"bx bx-cloud","type":"label"}]},{"id":"_help_iGTnKjubbXkA","title":"System Requirements","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/System Requirements"},{"name":"iconClass","value":"bx bx-chip","type":"label"}]}]},{"id":"_help_cbkrhQjrkKrh","title":"Synchronization","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Synchronization"},{"name":"iconClass","value":"bx bx-sync","type":"label"}]},{"id":"_help_RDslemsQ6gCp","title":"Mobile Frontend","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Mobile Frontend"},{"name":"iconClass","value":"bx bx-mobile-alt","type":"label"}]},{"id":"_help_MtPxeAWVAzMg","title":"Web Clipper","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Web Clipper"},{"name":"iconClass","value":"bx bx-paperclip","type":"label"}]},{"id":"_help_n1lujUxCwipy","title":"Upgrading TriliumNext","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Upgrading TriliumNext"},{"name":"iconClass","value":"bx bx-up-arrow-alt","type":"label"}]},{"id":"_help_ODY7qQn5m2FT","title":"Backup","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Backup"},{"name":"iconClass","value":"bx bx-hdd","type":"label"}]},{"id":"_help_tAassRL4RSQL","title":"Data directory","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Data directory"},{"name":"iconClass","value":"bx bx-folder-open","type":"label"}]}]},{"id":"_help_gh7bpGYxajRS","title":"Basic Concepts and Features","type":"book","attributes":[{"name":"iconClass","value":"bx bx-help-circle","type":"label"}],"children":[{"id":"_help_Vc8PjrjAGuOp","title":"UI Elements","type":"book","attributes":[{"name":"iconClass","value":"bx bx-window-alt","type":"label"}],"children":[{"id":"_help_x0JgW8UqGXvq","title":"Vertical and horizontal layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Vertical and horizontal layout"},{"name":"iconClass","value":"bx bxs-layout","type":"label"}]},{"id":"_help_x3i7MxGccDuM","title":"Global menu","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Global menu"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_oPVyFC7WL2Lp","title":"Note Tree","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree"},{"name":"iconClass","value":"bx bxs-tree-alt","type":"label"}],"children":[{"id":"_help_YtSN43OrfzaA","title":"Note tree contextual menu","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Note tree contextual menu"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_yTjUdsOi4CIE","title":"Multiple selection","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Multiple selection"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_DvdZhoQZY9Yd","title":"Keyboard shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Keyboard shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_wyaGBBQrl4i3","title":"Hiding the subtree","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Hiding the subtree"},{"name":"iconClass","value":"bx bx-hide","type":"label"}]}]},{"id":"_help_BlN9DFI679QC","title":"Ribbon","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Ribbon"},{"name":"iconClass","value":"bx bx-dots-horizontal","type":"label"}]},{"id":"_help_3seOhtN8uLIY","title":"Tabs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Tabs"},{"name":"iconClass","value":"bx bx-dock-top","type":"label"}]},{"id":"_help_xYmIYSP6wE3F","title":"Launch Bar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Launch Bar"},{"name":"iconClass","value":"bx bx-sidebar","type":"label"}]},{"id":"_help_8YBEPzcpUgxw","title":"Note buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note buttons"},{"name":"iconClass","value":"bx bx-dots-vertical-rounded","type":"label"}]},{"id":"_help_4TIF1oA4VQRO","title":"Options","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Options"},{"name":"iconClass","value":"bx bx-cog","type":"label"}]},{"id":"_help_luNhaphA37EO","title":"Split View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View"},{"name":"iconClass","value":"bx bx-dock-right","type":"label"}]},{"id":"_help_XpOYSgsLkTJy","title":"Floating buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Floating buttons"},{"name":"iconClass","value":"bx bx-rectangle","type":"label"}]},{"id":"_help_RnaPdbciOfeq","title":"Right Sidebar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Right Sidebar"},{"name":"iconClass","value":"bx bxs-dock-right","type":"label"}]},{"id":"_help_r5JGHN99bVKn","title":"Recent Changes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Recent Changes"},{"name":"iconClass","value":"bx bx-history","type":"label"}]},{"id":"_help_ny318J39E5Z0","title":"Zoom","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Zoom"},{"name":"iconClass","value":"bx bx-zoom-in","type":"label"}]},{"id":"_help_lgKX7r3aL30x","title":"Note Tooltip","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tooltip"},{"name":"iconClass","value":"bx bx-message-detail","type":"label"}]},{"id":"_help_IjZS7iK5EXtb","title":"New Layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/New Layout"},{"name":"iconClass","value":"bx bx-layout","type":"label"}],"children":[{"id":"_help_I6p2a06hdnL6","title":"Breadcrumb","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/New Layout/Breadcrumb"},{"name":"iconClass","value":"bx bx-chevron-right","type":"label"}]},{"id":"_help_AlJ73vBCjWDw","title":"Status bar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/New Layout/Status bar"},{"name":"iconClass","value":"bx bx-dock-bottom","type":"label"}]}]}]},{"id":"_help_BFs8mudNFgCS","title":"Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes"},{"name":"iconClass","value":"bx bx-notepad","type":"label"}],"children":[{"id":"_help_p9kXRFAkwN4o","title":"Note Icons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_0vhv7lsOLy82","title":"Attachments","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Attachments"},{"name":"iconClass","value":"bx bx-paperclip","type":"label"}]},{"id":"_help_IakOLONlIfGI","title":"Cloning Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes"},{"name":"iconClass","value":"bx bx-duplicate","type":"label"}],"children":[{"id":"_help_TBwsyfadTA18","title":"Branch prefix","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes/Branch prefix"},{"name":"iconClass","value":"bx bx-rename","type":"label"}]}]},{"id":"_help_bwg0e8ewQMak","title":"Protected Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Protected Notes"},{"name":"iconClass","value":"bx bx-lock-alt","type":"label"}]},{"id":"_help_MKmLg5x6xkor","title":"Archived Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Archived Notes"},{"name":"iconClass","value":"bx bx-box","type":"label"}]},{"id":"_help_vZWERwf8U3nx","title":"Note Revisions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions"},{"name":"iconClass","value":"bx bx-history","type":"label"}]},{"id":"_help_aGlEvb9hyDhS","title":"Sorting Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Sorting Notes"},{"name":"iconClass","value":"bx bx-sort-up","type":"label"}]},{"id":"_help_NRnIZmSMc5sj","title":"Printing & Exporting as PDF","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF"},{"name":"iconClass","value":"bx bx-printer","type":"label"}]},{"id":"_help_CoFPLs3dRlXc","title":"Read-Only Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes"},{"name":"iconClass","value":"bx bx-edit-alt","type":"label"}]},{"id":"_help_0ESUbbAxVnoK","title":"Note List","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note List"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]}]},{"id":"_help_wArbEsdSae6g","title":"Navigation","type":"book","attributes":[{"name":"iconClass","value":"bx bx-navigation","type":"label"}],"children":[{"id":"_help_kBrnXNG3Hplm","title":"Tree Concepts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Tree Concepts"},{"name":"iconClass","value":"bx bx-pyramid","type":"label"}]},{"id":"_help_MMiBEQljMQh2","title":"Note Navigation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation"},{"name":"iconClass","value":"bx bxs-navigation","type":"label"}]},{"id":"_help_Ms1nauBra7gq","title":"Quick search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Quick search"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]},{"id":"_help_F1r9QtzQLZqm","title":"Jump to...","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to"},{"name":"iconClass","value":"bx bx-send","type":"label"}]},{"id":"_help_eIg8jdvaoNNd","title":"Search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Search"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]},{"id":"_help_u3YFHC9tQlpm","title":"Bookmarks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks"},{"name":"iconClass","value":"bx bx-bookmarks","type":"label"}]},{"id":"_help_OR8WJ7Iz9K4U","title":"Note Hoisting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Note Hoisting"},{"name":"iconClass","value":"bx bxs-chevrons-up","type":"label"}]},{"id":"_help_ZjLYv08Rp3qC","title":"Quick edit","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Quick edit"},{"name":"iconClass","value":"bx bx-edit","type":"label"}]},{"id":"_help_9sRHySam5fXb","title":"Workspaces","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Workspaces"},{"name":"iconClass","value":"bx bx-door-open","type":"label"}]},{"id":"_help_xWtq5NUHOwql","title":"Similar Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Similar Notes"},{"name":"iconClass","value":"bx bx-bar-chart","type":"label"}]},{"id":"_help_McngOG2jbUWX","title":"Search in note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Search in note"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]}]},{"id":"_help_A9Oc6YKKc65v","title":"Keyboard Shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Keyboard Shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_Wy267RK4M69c","title":"Themes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes"},{"name":"iconClass","value":"bx bx-palette","type":"label"}],"children":[{"id":"_help_VbjZvtUek0Ln","title":"Theme Gallery","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes/Theme Gallery"},{"name":"iconClass","value":"bx bx-book-reader","type":"label"}]},{"id":"_help_gOKqSJgXLcIj","title":"Icon Packs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes/Icon Packs"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_mHbBMPDPkVV5","title":"Import & Export","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export"},{"name":"iconClass","value":"bx bx-import","type":"label"}],"children":[{"id":"_help_Oau6X9rCuegd","title":"Markdown","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}],"children":[{"id":"_help_rJ9grSgoExl9","title":"Supported syntax","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown/Supported syntax"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}]}]},{"id":"_help_syuSEKf2rUGr","title":"Evernote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Evernote"},{"name":"iconClass","value":"bx bx-window-open","type":"label"}],"children":[{"id":"_help_dj3j8dG4th4l","title":"Process internal links by title","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_GnhlmrATVqcH","title":"OneNote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/OneNote"},{"name":"iconClass","value":"bx bx-window-open","type":"label"}]}]},{"id":"_help_rC3pL2aptaRE","title":"Zen mode","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Zen mode"},{"name":"iconClass","value":"bx bxs-yin-yang","type":"label"}]},{"id":"_help_YzMcWlCVeW09","title":"Active content","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Active content"},{"name":"iconClass","value":"bx bxs-widget","type":"label"}]}]},{"id":"_help_s3YCWHBfmYuM","title":"Quick Start","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Quick Start"},{"name":"iconClass","value":"bx bx-run","type":"label"}]},{"id":"_help_i6dbnitykE5D","title":"FAQ","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/FAQ"},{"name":"iconClass","value":"bx bx-question-mark","type":"label"}]},{"id":"_help_KSZ04uQ2D1St","title":"Note Types","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types"},{"name":"iconClass","value":"bx bx-edit","type":"label"}],"children":[{"id":"_help_iPIMuisry3hd","title":"Text","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text"},{"name":"iconClass","value":"bx bx-note","type":"label"}],"children":[{"id":"_help_NwBbFdNZ9h7O","title":"Block quotes & admonitions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Block quotes & admonitions"},{"name":"iconClass","value":"bx bx-info-circle","type":"label"}]},{"id":"_help_oSuaNgyyKnhu","title":"Bookmarks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Bookmarks"},{"name":"iconClass","value":"bx bx-bookmark","type":"label"}]},{"id":"_help_veGu4faJErEM","title":"Content language & Right-to-left support","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Content language & Right-to-le"},{"name":"iconClass","value":"bx bx-align-right","type":"label"}]},{"id":"_help_2x0ZAX9ePtzV","title":"Cut to subnote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Cut to subnote"},{"name":"iconClass","value":"bx bx-cut","type":"label"}]},{"id":"_help_UYuUB1ZekNQU","title":"Developer-specific formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Developer-specific formatting"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}],"children":[{"id":"_help_QxEyIjRBizuC","title":"Code blocks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Developer-specific formatting/Code blocks"},{"name":"iconClass","value":"bx bx-code","type":"label"}]}]},{"id":"_help_AgjCISero73a","title":"Footnotes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Footnotes"},{"name":"iconClass","value":"bx bx-bracket","type":"label"}]},{"id":"_help_nRhnJkTT8cPs","title":"Formatting toolbar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Formatting toolbar"},{"name":"iconClass","value":"bx bx-text","type":"label"}]},{"id":"_help_Gr6xFaF6ioJ5","title":"General formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/General formatting"},{"name":"iconClass","value":"bx bx-bold","type":"label"}]},{"id":"_help_AxshuNRegLAv","title":"Highlights list","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Highlights list"},{"name":"iconClass","value":"bx bx-highlight","type":"label"}]},{"id":"_help_mT0HEkOsz6i1","title":"Images","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Images"},{"name":"iconClass","value":"bx bx-image-alt","type":"label"}],"children":[{"id":"_help_0Ofbk1aSuVRu","title":"Image references","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Images/Image references"},{"name":"iconClass","value":"bx bxs-file-image","type":"label"}]}]},{"id":"_help_nBAXQFj20hS1","title":"Include Note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Include Note"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_CohkqWQC1iBv","title":"Insert buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Insert buttons"},{"name":"iconClass","value":"bx bx-plus","type":"label"}]},{"id":"_help_oiVPnW8QfnvS","title":"Keyboard shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Keyboard shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_QEAPj01N5f7w","title":"Links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links"},{"name":"iconClass","value":"bx bx-link-alt","type":"label"}],"children":[{"id":"_help_3IDVtesTQ8ds","title":"External links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links/External links"},{"name":"iconClass","value":"bx bx-link-external","type":"label"}]},{"id":"_help_hrZ1D00cLbal","title":"Internal (reference) links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links/Internal (reference) links"},{"name":"iconClass","value":"bx bx-link","type":"label"}]}]},{"id":"_help_S6Xx8QIWTV66","title":"Lists","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Lists"},{"name":"iconClass","value":"bx bx-list-ul","type":"label"}]},{"id":"_help_QrtTYPmdd1qq","title":"Markdown-like formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Markdown-like formatting"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}]},{"id":"_help_YfYAtQBcfo5V","title":"Math Equations","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Math Equations"},{"name":"iconClass","value":"bx bx-math","type":"label"}]},{"id":"_help_dEHYtoWWi8ct","title":"Other features","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Other features"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_gLt3vA97tMcp","title":"Premium features","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features"},{"name":"iconClass","value":"bx bx-star","type":"label"}],"children":[{"id":"_help_ZlN4nump6EbW","title":"Slash Commands","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Slash Commands"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_pwc194wlRzcH","title":"Text Snippets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Text Snippets"},{"name":"iconClass","value":"bx bx-align-left","type":"label"}]},{"id":"_help_5wZallV2Qo1t","title":"Format Painter","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Format Painter"},{"name":"iconClass","value":"bx bxs-paint-roll","type":"label"}]}]},{"id":"_help_oBo3iHIZnbG2","title":"Spell Check","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Spell Check"},{"name":"iconClass","value":"bx bx-check-double","type":"label"}]},{"id":"_help_BFvAtE74rbP6","title":"Table of contents","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Table of contents"},{"name":"iconClass","value":"bx bx-heading","type":"label"}]},{"id":"_help_NdowYOC1GFKS","title":"Tables","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Tables"},{"name":"iconClass","value":"bx bx-table","type":"label"}]}]},{"id":"_help_6f9hih2hXXZk","title":"Code","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Code"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_m523cpzocqaD","title":"Saved Search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Saved Search"},{"name":"iconClass","value":"bx bx-file-find","type":"label"}]},{"id":"_help_iRwzGnHPzonm","title":"Relation Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Relation Map"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_bdUJEHsAPYQR","title":"Note Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Note Map"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_HcABDtFCkbFN","title":"Render Note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Render Note"},{"name":"iconClass","value":"bx bx-extension","type":"label"}]},{"id":"_help_s1aBHPd79XYj","title":"Mermaid Diagrams","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mermaid Diagrams"},{"name":"iconClass","value":"bx bx-selection","type":"label"}],"children":[{"id":"_help_RH6yLjjWJHof","title":"ELK layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mermaid Diagrams/ELK layout"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_WWgeUaBb7UfC","title":"Syntax reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://mermaid.js.org/intro/syntax-reference.html"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_grjYqerjn243","title":"Canvas","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Canvas"},{"name":"iconClass","value":"bx bx-pen","type":"label"}]},{"id":"_help_1vHRoWCEjj0L","title":"Web View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Web View"},{"name":"iconClass","value":"bx bx-globe-alt","type":"label"}]},{"id":"_help_gBbsAeiuUxI5","title":"Mind Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mind Map"},{"name":"iconClass","value":"bx bx-sitemap","type":"label"}]},{"id":"_help_W8vYD3Q1zjCR","title":"File","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File"},{"name":"iconClass","value":"bx bx-file-blank","type":"label"}],"children":[{"id":"_help_XJGJrpu7F9sh","title":"PDFs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File/PDFs"},{"name":"iconClass","value":"bx bxs-file-pdf","type":"label"}]},{"id":"_help_AjqEeiDUOzj4","title":"Videos","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File/Videos"},{"name":"iconClass","value":"bx bx-video","type":"label"}]}]},{"id":"_help_GWHEkY4I4OE3","title":"Spreadsheets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Spreadsheets"},{"name":"iconClass","value":"bx bx-table","type":"label"}]},{"id":"_help_6RM1Q7ppFVoj","title":"Markdown","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Markdown"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}]}]},{"id":"_help_GTwFsgaA0lCt","title":"Collections","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections"},{"name":"iconClass","value":"bx bx-book","type":"label"}],"children":[{"id":"_help_xWbu3jpNWapp","title":"Calendar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Calendar"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]},{"id":"_help_2FvYrpmOXm29","title":"Table","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Table"},{"name":"iconClass","value":"bx bx-table","type":"label"}]},{"id":"_help_CtBQqbwXDx1w","title":"Kanban Board","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Kanban Board"},{"name":"iconClass","value":"bx bx-columns","type":"label"}]},{"id":"_help_81SGnPGMk7Xc","title":"Geo Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Geo Map"},{"name":"iconClass","value":"bx bx-map-alt","type":"label"}]},{"id":"_help_zP3PMqaG71Ct","title":"Presentation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Presentation"},{"name":"iconClass","value":"bx bx-slideshow","type":"label"}]},{"id":"_help_8QqnMzx393bx","title":"Grid View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Grid View"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_mULW0Q3VojwY","title":"List View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/List View"},{"name":"iconClass","value":"bx bx-list-ul","type":"label"}]},{"id":"_help_CssoWBu8I7jF","title":"Collection Properties","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Collection Properties"},{"name":"iconClass","value":"bx bx-cog","type":"label"}]}]},{"id":"_help_BgmBlOIl72jZ","title":"Troubleshooting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting"},{"name":"iconClass","value":"bx bx-bug","type":"label"}],"children":[{"id":"_help_wy8So3yZZlH9","title":"Reporting issues","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Reporting issues"},{"name":"iconClass","value":"bx bx-bug-alt","type":"label"}]},{"id":"_help_x59R8J8KV5Bp","title":"Anonymized Database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Anonymized Database"},{"name":"iconClass","value":"bx bx-low-vision","type":"label"}]},{"id":"_help_qzNzp9LYQyPT","title":"Error logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs"},{"name":"iconClass","value":"bx bx-comment-error","type":"label"}],"children":[{"id":"_help_bnyigUA2UK7s","title":"Backend (server) logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs/Backend (server) logs"},{"name":"iconClass","value":"bx bx-server","type":"label"}]},{"id":"_help_9yEHzMyFirZR","title":"Frontend logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs/Frontend logs"},{"name":"iconClass","value":"bx bx-window-alt","type":"label"}]}]},{"id":"_help_vdlYGAcpXAgc","title":"Synchronization fails with 504 Gateway Timeout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Synchronization fails with 504"},{"name":"iconClass","value":"bx bx-error","type":"label"}]},{"id":"_help_s8alTXmpFR61","title":"Refreshing the application","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Refreshing the application"},{"name":"iconClass","value":"bx bx-refresh","type":"label"}]}]},{"id":"_help_pKK96zzmvBGf","title":"Theme development","type":"book","attributes":[{"name":"iconClass","value":"bx bx-palette","type":"label"}],"children":[{"id":"_help_7NfNr5pZpVKV","title":"Creating a custom theme","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Creating a custom theme"},{"name":"iconClass","value":"bx bxs-color","type":"label"}]},{"id":"_help_WFGzWeUK6arS","title":"Customize the Next theme","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Customize the Next theme"},{"name":"iconClass","value":"bx bx-news","type":"label"}]},{"id":"_help_WN5z4M8ASACJ","title":"Reference","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Reference"},{"name":"iconClass","value":"bx bx-book-open","type":"label"}]},{"id":"_help_AlhDUqhENtH7","title":"Custom app-wide CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Custom app-wide CSS"},{"name":"iconClass","value":"bx bxs-file-css","type":"label"}]},{"id":"_help_g1mlRoU8CsqC","title":"Creating an icon pack","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Creating an icon pack"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_tC7s2alapj8V","title":"Advanced Usage","type":"book","attributes":[{"name":"iconClass","value":"bx bx-rocket","type":"label"}],"children":[{"id":"_help_zEY4DaJG4YT5","title":"Attributes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes"},{"name":"iconClass","value":"bx bx-list-check","type":"label"}],"children":[{"id":"_help_HI6GBBIduIgv","title":"Labels","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Labels"},{"name":"iconClass","value":"bx bx-hash","type":"label"}]},{"id":"_help_Cq5X6iKQop6R","title":"Relations","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Relations"},{"name":"iconClass","value":"bx bx-transfer","type":"label"}]},{"id":"_help_bwZpz2ajCEwO","title":"Attribute Inheritance","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Attribute Inheritance"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_OFXdgB2nNk1F","title":"Promoted Attributes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Promoted Attributes"},{"name":"iconClass","value":"bx bx-table","type":"label"}]}]},{"id":"_help_KC1HB96bqqHX","title":"Templates","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Templates"},{"name":"iconClass","value":"bx bx-copy","type":"label"}]},{"id":"_help_BCkXAVs63Ttv","title":"Note Map (Link map, Tree map)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note Map (Link map, Tree map)"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_R9pX4DGra2Vt","title":"Sharing","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing"},{"name":"iconClass","value":"bx bx-share-alt","type":"label"}],"children":[{"id":"_help_Qjt68inQ2bRj","title":"Serving directly the content of a note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Serving directly the content o"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_ycBFjKrrwE9p","title":"Exporting static HTML for web publishing","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Exporting static HTML for web "},{"name":"iconClass","value":"bx bxs-file-html","type":"label"}]},{"id":"_help_sLIJ6f1dkJYW","title":"Reverse proxy configuration","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Reverse proxy configuration"},{"name":"iconClass","value":"bx bx-world","type":"label"}]}]},{"id":"_help_5668rwcirq1t","title":"Advanced Showcases","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases"},{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_l0tKav7yLHGF","title":"Day Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Day Notes"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]},{"id":"_help_R7abl2fc6Mxi","title":"Weight Tracker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Weight Tracker"},{"name":"iconClass","value":"bx bx-line-chart","type":"label"}]},{"id":"_help_xYjQUYhpbUEW","title":"Task Manager","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Task Manager"},{"name":"iconClass","value":"bx bx-calendar-check","type":"label"}]}]},{"id":"_help_J5Ex1ZrMbyJ6","title":"Custom Request Handler","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Custom Request Handler"},{"name":"iconClass","value":"bx bx-globe","type":"label"}]},{"id":"_help_d3fAXQ2diepH","title":"Custom Resource Providers","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Custom Resource Providers"},{"name":"iconClass","value":"bx bxs-file-plus","type":"label"}]},{"id":"_help_pgxEVkzLl1OP","title":"ETAPI (REST API)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/ETAPI (REST API)"},{"name":"iconClass","value":"bx bx-extension","type":"label"}],"children":[{"id":"_help_9qPsTWBorUhQ","title":"API Reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/rest-api/etapi/"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_47ZrP6FNuoG8","title":"Default Note Title","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Default Note Title"},{"name":"iconClass","value":"bx bx-edit-alt","type":"label"}]},{"id":"_help_wX4HbRucYSDD","title":"Database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database"},{"name":"iconClass","value":"bx bx-data","type":"label"}],"children":[{"id":"_help_oyIAJ9PvvwHX","title":"Manually altering the database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Manually altering the database"},{"name":"iconClass","value":"bx bxs-edit","type":"label"}],"children":[{"id":"_help_YKWqdJhzi2VY","title":"SQL Console","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Manually altering the database/SQL Console"},{"name":"iconClass","value":"bx bx-data","type":"label"}]}]},{"id":"_help_6tZeKvSHEUiB","title":"Demo Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Demo Notes"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_Gzjqa934BdH4","title":"Configuration (config.ini or environment variables)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or e"},{"name":"iconClass","value":"bx bx-cog","type":"label"}],"children":[{"id":"_help_c5xB8m4g2IY6","title":"Trilium instance","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Trilium instance"},{"name":"iconClass","value":"bx bx-windows","type":"label"}]},{"id":"_help_LWtBjFej3wX3","title":"Cross-Origin Resource Sharing (CORS)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Cross-Origin Resource Sharing "},{"name":"iconClass","value":"bx bx-lock","type":"label"}]}]},{"id":"_help_ivYnonVFBxbQ","title":"Bulk Actions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Bulk Actions"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_4FahAwuGTAwC","title":"Note source","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note source"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_1YeN2MzFUluU","title":"Technologies used","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used"},{"name":"iconClass","value":"bx bx-pyramid","type":"label"}],"children":[{"id":"_help_MI26XDLSAlCD","title":"CKEditor","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/CKEditor"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_N4IDkixaDG9C","title":"MindElixir","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/MindElixir"},{"name":"iconClass","value":"bx bx-sitemap","type":"label"}]},{"id":"_help_H0mM1lTxF9JI","title":"Excalidraw","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/Excalidraw"},{"name":"iconClass","value":"bx bx-pen","type":"label"}]},{"id":"_help_MQHyy2dIFgxS","title":"Leaflet","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/Leaflet"},{"name":"iconClass","value":"bx bx-map-alt","type":"label"}]}]},{"id":"_help_m1lbrzyKDaRB","title":"Note ID","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note ID"},{"name":"iconClass","value":"bx bx-hash","type":"label"}]},{"id":"_help_0vTSyvhPTAOz","title":"Internal API","type":"book","attributes":[{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_z8O2VG4ZZJD7","title":"API Reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/rest-api/internal/"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_2mUhVmZK8RF3","title":"Hidden Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Hidden Notes"},{"name":"iconClass","value":"bx bx-hide","type":"label"}]},{"id":"_help_uYF7pmepw27K","title":"Metrics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Metrics"},{"name":"iconClass","value":"bx bxs-data","type":"label"}],"children":[{"id":"_help_bOP3TB56fL1V","title":"grafana-dashboard.json","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_64ZTlUPgEPtW","title":"Safe mode","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Safe mode"},{"name":"iconClass","value":"bx bxs-virus-block","type":"label"}]},{"id":"_help_HAIOFBoYIIdO","title":"Nightly release","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Nightly release"},{"name":"iconClass","value":"bx bx-moon","type":"label"}]},{"id":"_help_ZmT9ln8XJX2o","title":"Read-only database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Read-only database"},{"name":"iconClass","value":"bx bx-book-reader","type":"label"}]}]},{"id":"_help_GBBMSlVSOIGP","title":"AI","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/AI"},{"name":"iconClass","value":"bx bx-bot","type":"label"}]},{"id":"_help_CdNpE2pqjmI6","title":"Scripting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting"},{"name":"iconClass","value":"bx bxs-file-js","type":"label"}],"children":[{"id":"_help_yIhgI5H7A2Sm","title":"Frontend Basics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics"},{"name":"iconClass","value":"bx bx-window","type":"label"}],"children":[{"id":"_help_MgibgPcfeuGz","title":"Custom Widgets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets"},{"name":"iconClass","value":"bx bxs-widget","type":"label"}],"children":[{"id":"_help_SynTBQiBsdYJ","title":"Widget Basics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Widget Basics"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_GhurYZjh8e1V","title":"Note context aware widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Note context aware widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_M8IppdwVHSjG","title":"Right pane widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Right pane widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_YNxAqkI5Kg1M","title":"Word count widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Word count widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_VqGQnnPGnqAU","title":"CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/CSS"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_gMkgcLJ6jBkg","title":"Troubleshooting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Troubleshooting"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_es8OU2GuguFU","title":"Examples","type":"book","attributes":[{"name":"iconClass","value":"bx bx-code-alt","type":"label"}],"children":[{"id":"_help_TjLYAo3JMO8X","title":"\"New Task\" launcher button","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/New Task launcher button"},{"name":"iconClass","value":"bx bx-task","type":"label"}]},{"id":"_help_7kZPMD0uFwkH","title":"Downloading responses from Google Forms","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/Downloading responses from Goo"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_DL92EjAaXT26","title":"Using promoted attributes to configure scripts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/Using promoted attributes to c"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_4Gn3psZKsfSm","title":"Launch Bar Widgets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets"},{"name":"iconClass","value":"bx bx-dock-left","type":"label"}],"children":[{"id":"_help_IPArqVfDQ4We","title":"Note Title Widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets/Note Title Widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_gcI7RPbaNSh3","title":"Analog Watch","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets/Analog Watch"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_KLsqhjaqh1QW","title":"Preact","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact"},{"name":"iconClass","value":"bx bxl-react","type":"label"}],"children":[{"id":"_help_Bqde6BvPo05g","title":"Component libraries","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/Component libraries"},{"name":"iconClass","value":"bx bxs-component","type":"label"}]},{"id":"_help_ykYtbM9k3a7B","title":"Hooks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/Hooks"},{"name":"iconClass","value":"bx bx-question-mark","type":"label"}]},{"id":"_help_Sg9GrCtyftZf","title":"CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/CSS"},{"name":"iconClass","value":"bx bxs-file-css","type":"label"}]},{"id":"_help_RSssb9S3xgSr","title":"Built-in components","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/Built-in components"},{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_i9B4IW7b6V6z","title":"Widget showcase","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}]}]},{"id":"_help_SPirpZypehBG","title":"Backend scripts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts"},{"name":"iconClass","value":"bx bx-server","type":"label"}],"children":[{"id":"_help_fZ2IGYFXjkEy","title":"Server-side imports","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts/Server-side imports"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_GPERMystNGTB","title":"Events","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts/Events"},{"name":"iconClass","value":"bx bx-rss","type":"label"}]}]},{"id":"_help_wqXwKJl6VpNk","title":"Common concepts","type":"book","attributes":[{"name":"iconClass","value":"bx bxl-nodejs","type":"label"}],"children":[{"id":"_help_hA834UaHhSNn","title":"Script bundles","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Common concepts/Script bundles"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_GLks18SNjxmC","title":"Script API","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Script API"},{"name":"iconClass","value":"bx bx-code-curly","type":"label"}],"children":[{"id":"_help_Q2z6av6JZVWm","title":"Frontend API","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/frontend"},{"name":"iconClass","value":"bx bx-folder","type":"label"}],"enforceAttributes":true,"children":[{"id":"_help_habiZ3HU8Kw8","title":"FNote","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/frontend/interfaces/FNote.html"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_MEtfsqa5VwNi","title":"Backend API","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/backend"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true},{"id":"_help_ApVHZ8JY5ofC","title":"Day.js","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Script API/Day.js"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]}]},{"id":"_help_vElnKeDNPSVl","title":"Logging","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Logging"},{"name":"iconClass","value":"bx bx-terminal","type":"label"}]},{"id":"_help_cNpC0ITcfX0N","title":"Breaking changes","type":"book","attributes":[{"name":"iconClass","value":"bx bx-up-arrow-alt","type":"label"}],"children":[{"id":"_help_fqAK6opjUagR","title":"v0.103.0: Removal of axios","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Breaking changes/v0.103.0 Removal of axios"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_pAJ0jWz16xFm","title":"v0.103.0: `cheerio` is now deprecated","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Breaking changes/v0.103.0 `cheerio` is now depr"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_72dxvnbnkDFY","title":"v0.102.0: Upgrade to jQuery 4.0.0","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Breaking changes/v0.102.0 Upgrade to jQuery.0.0"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}]},{"id":"_help_Fm0j45KqyHpU","title":"Miscellaneous","type":"book","attributes":[{"name":"iconClass","value":"bx bx-info-circle","type":"label"}],"children":[{"id":"_help_WFbFXrgnDyyU","title":"Privacy Policy","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/Privacy Policy"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_NcsmUYZRWEW4","title":"Patterns of personal knowledge","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/Patterns of personal knowledge"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_d1Ap6Pg6IjaJ","title":"License","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/License"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}] \ No newline at end of file +[{"id":"_help_BOCnjTMBCoxW","title":"Feature Highlights","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Feature Highlights"},{"name":"iconClass","value":"bx bx-star","type":"label"}]},{"id":"_help_Otzi9La2YAUX","title":"Installation & Setup","type":"book","attributes":[{"name":"iconClass","value":"bx bx-cog","type":"label"}],"children":[{"id":"_help_poXkQfguuA0U","title":"Desktop Installation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation"},{"name":"iconClass","value":"bx bx-desktop","type":"label"}],"children":[{"id":"_help_nRqcgfTb97uV","title":"Using the desktop application as a server","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/Using the desktop application "},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_Rp0q8bSP6Ayl","title":"System Requirements","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/System Requirements"},{"name":"iconClass","value":"bx bx-chip","type":"label"}]},{"id":"_help_Un4wj2Mak2Ky","title":"Nix flake","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/Nix flake"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]}]},{"id":"_help_WOcw2SLH6tbX","title":"Server Installation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation"},{"name":"iconClass","value":"bx bx-server","type":"label"}],"children":[{"id":"_help_Dgg7bR3b6K9j","title":"1. Installing the server","type":"book","attributes":[{"name":"iconClass","value":"bx bx-folder","type":"label"}],"children":[{"id":"_help_3tW6mORuTHnB","title":"Packaged version for Linux","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Packaged version for Linux"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]},{"id":"_help_rWX5eY045zbE","title":"Using Docker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Docker"},{"name":"iconClass","value":"bx bxl-docker","type":"label"}]},{"id":"_help_moVgBcoxE3EK","title":"On NixOS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/On NixOS"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]},{"id":"_help_J1Bb6lVlwU5T","title":"Manually","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Manually"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}]},{"id":"_help_DCmT6e7clMoP","title":"Using Kubernetes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Kubernetes"},{"name":"iconClass","value":"bx bxl-kubernetes","type":"label"}]},{"id":"_help_klCWNks3ReaQ","title":"Multiple server instances","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Multiple server instances"},{"name":"iconClass","value":"bx bxs-user-account","type":"label"}]}]},{"id":"_help_vcjrb3VVYPZI","title":"2. Reverse proxy","type":"book","attributes":[{"name":"iconClass","value":"bx bx-folder","type":"label"}],"children":[{"id":"_help_ud6MShXL4WpO","title":"Nginx","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Nginx"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_fDLvzOx29Pfg","title":"Apache using Docker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Apache using Docker"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_LLzSMXACKhUs","title":"Trusted proxy","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Trusted proxy"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_5ERVJb9s4FRD","title":"Traefik","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Traefik"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_l2VkvOwUNfZj","title":"HTTPS (TLS)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/HTTPS (TLS)"},{"name":"iconClass","value":"bx bx-lock-alt","type":"label"}]},{"id":"_help_0hzsNCP31IAB","title":"Authentication","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Authentication"},{"name":"iconClass","value":"bx bx-user","type":"label"}]},{"id":"_help_7DAiwaf8Z7Rz","title":"Multi-Factor Authentication","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Multi-Factor Authentication"},{"name":"iconClass","value":"bx bx-stopwatch","type":"label"}]},{"id":"_help_Un4wj2Mak2Ky","title":"Nix flake","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Nix flake.clone"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_yeEaYqosGLSh","title":"Third-party cloud hosting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Third-party cloud hosting"},{"name":"iconClass","value":"bx bx-cloud","type":"label"}]},{"id":"_help_iGTnKjubbXkA","title":"System Requirements","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/System Requirements"},{"name":"iconClass","value":"bx bx-chip","type":"label"}]}]},{"id":"_help_cbkrhQjrkKrh","title":"Synchronization","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Synchronization"},{"name":"iconClass","value":"bx bx-sync","type":"label"}]},{"id":"_help_RDslemsQ6gCp","title":"Mobile Frontend","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Mobile Frontend"},{"name":"iconClass","value":"bx bx-mobile-alt","type":"label"}]},{"id":"_help_MtPxeAWVAzMg","title":"Web Clipper","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Web Clipper"},{"name":"iconClass","value":"bx bx-paperclip","type":"label"}]},{"id":"_help_n1lujUxCwipy","title":"Upgrading TriliumNext","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Upgrading TriliumNext"},{"name":"iconClass","value":"bx bx-up-arrow-alt","type":"label"}]},{"id":"_help_ODY7qQn5m2FT","title":"Backup","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Backup"},{"name":"iconClass","value":"bx bx-hdd","type":"label"}]},{"id":"_help_tAassRL4RSQL","title":"Data directory","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Data directory"},{"name":"iconClass","value":"bx bx-folder-open","type":"label"}]}]},{"id":"_help_gh7bpGYxajRS","title":"Basic Concepts and Features","type":"book","attributes":[{"name":"iconClass","value":"bx bx-help-circle","type":"label"}],"children":[{"id":"_help_Vc8PjrjAGuOp","title":"UI Elements","type":"book","attributes":[{"name":"iconClass","value":"bx bx-window-alt","type":"label"}],"children":[{"id":"_help_x0JgW8UqGXvq","title":"Vertical and horizontal layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Vertical and horizontal layout"},{"name":"iconClass","value":"bx bxs-layout","type":"label"}]},{"id":"_help_x3i7MxGccDuM","title":"Global menu","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Global menu"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_oPVyFC7WL2Lp","title":"Note Tree","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree"},{"name":"iconClass","value":"bx bxs-tree-alt","type":"label"}],"children":[{"id":"_help_YtSN43OrfzaA","title":"Note tree contextual menu","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Note tree contextual menu"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_yTjUdsOi4CIE","title":"Multiple selection","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Multiple selection"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_DvdZhoQZY9Yd","title":"Keyboard shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Keyboard shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_wyaGBBQrl4i3","title":"Hiding the subtree","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Hiding the subtree"},{"name":"iconClass","value":"bx bx-hide","type":"label"}]}]},{"id":"_help_BlN9DFI679QC","title":"Ribbon","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Ribbon"},{"name":"iconClass","value":"bx bx-dots-horizontal","type":"label"}]},{"id":"_help_3seOhtN8uLIY","title":"Tabs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Tabs"},{"name":"iconClass","value":"bx bx-dock-top","type":"label"}]},{"id":"_help_xYmIYSP6wE3F","title":"Launch Bar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Launch Bar"},{"name":"iconClass","value":"bx bx-sidebar","type":"label"}]},{"id":"_help_8YBEPzcpUgxw","title":"Note buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note buttons"},{"name":"iconClass","value":"bx bx-dots-vertical-rounded","type":"label"}]},{"id":"_help_4TIF1oA4VQRO","title":"Options","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Options"},{"name":"iconClass","value":"bx bx-cog","type":"label"}]},{"id":"_help_luNhaphA37EO","title":"Split View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View"},{"name":"iconClass","value":"bx bx-dock-right","type":"label"}]},{"id":"_help_XpOYSgsLkTJy","title":"Floating buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Floating buttons"},{"name":"iconClass","value":"bx bx-rectangle","type":"label"}]},{"id":"_help_RnaPdbciOfeq","title":"Right Sidebar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Right Sidebar"},{"name":"iconClass","value":"bx bxs-dock-right","type":"label"}]},{"id":"_help_r5JGHN99bVKn","title":"Recent Changes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Recent Changes"},{"name":"iconClass","value":"bx bx-history","type":"label"}]},{"id":"_help_ny318J39E5Z0","title":"Zoom","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Zoom"},{"name":"iconClass","value":"bx bx-zoom-in","type":"label"}]},{"id":"_help_lgKX7r3aL30x","title":"Note Tooltip","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tooltip"},{"name":"iconClass","value":"bx bx-message-detail","type":"label"}]},{"id":"_help_IjZS7iK5EXtb","title":"New Layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/New Layout"},{"name":"iconClass","value":"bx bx-layout","type":"label"}],"children":[{"id":"_help_I6p2a06hdnL6","title":"Breadcrumb","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/New Layout/Breadcrumb"},{"name":"iconClass","value":"bx bx-chevron-right","type":"label"}]},{"id":"_help_AlJ73vBCjWDw","title":"Status bar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/New Layout/Status bar"},{"name":"iconClass","value":"bx bx-dock-bottom","type":"label"}]}]},{"id":"_help_SL5f1Auq7sVN","title":"Note types with split view","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note types with split view"},{"name":"iconClass","value":"bx bx-card","type":"label"}]}]},{"id":"_help_BFs8mudNFgCS","title":"Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes"},{"name":"iconClass","value":"bx bx-notepad","type":"label"}],"children":[{"id":"_help_p9kXRFAkwN4o","title":"Note Icons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_0vhv7lsOLy82","title":"Attachments","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Attachments"},{"name":"iconClass","value":"bx bx-paperclip","type":"label"}]},{"id":"_help_IakOLONlIfGI","title":"Cloning Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes"},{"name":"iconClass","value":"bx bx-duplicate","type":"label"}],"children":[{"id":"_help_TBwsyfadTA18","title":"Branch prefix","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes/Branch prefix"},{"name":"iconClass","value":"bx bx-rename","type":"label"}]}]},{"id":"_help_bwg0e8ewQMak","title":"Protected Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Protected Notes"},{"name":"iconClass","value":"bx bx-lock-alt","type":"label"}]},{"id":"_help_MKmLg5x6xkor","title":"Archived Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Archived Notes"},{"name":"iconClass","value":"bx bx-box","type":"label"}]},{"id":"_help_vZWERwf8U3nx","title":"Note Revisions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions"},{"name":"iconClass","value":"bx bx-history","type":"label"}]},{"id":"_help_aGlEvb9hyDhS","title":"Sorting Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Sorting Notes"},{"name":"iconClass","value":"bx bx-sort-up","type":"label"}]},{"id":"_help_NRnIZmSMc5sj","title":"Printing & Exporting as PDF","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF"},{"name":"iconClass","value":"bx bx-printer","type":"label"}]},{"id":"_help_CoFPLs3dRlXc","title":"Read-Only Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes"},{"name":"iconClass","value":"bx bx-edit-alt","type":"label"}]},{"id":"_help_0ESUbbAxVnoK","title":"Note List","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note List"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]}]},{"id":"_help_wArbEsdSae6g","title":"Navigation","type":"book","attributes":[{"name":"iconClass","value":"bx bx-navigation","type":"label"}],"children":[{"id":"_help_kBrnXNG3Hplm","title":"Tree Concepts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Tree Concepts"},{"name":"iconClass","value":"bx bx-pyramid","type":"label"}]},{"id":"_help_MMiBEQljMQh2","title":"Note Navigation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation"},{"name":"iconClass","value":"bx bxs-navigation","type":"label"}]},{"id":"_help_Ms1nauBra7gq","title":"Quick search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Quick search"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]},{"id":"_help_F1r9QtzQLZqm","title":"Jump to...","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to"},{"name":"iconClass","value":"bx bx-send","type":"label"}]},{"id":"_help_eIg8jdvaoNNd","title":"Search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Search"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]},{"id":"_help_u3YFHC9tQlpm","title":"Bookmarks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks"},{"name":"iconClass","value":"bx bx-bookmarks","type":"label"}]},{"id":"_help_OR8WJ7Iz9K4U","title":"Note Hoisting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Note Hoisting"},{"name":"iconClass","value":"bx bxs-chevrons-up","type":"label"}]},{"id":"_help_ZjLYv08Rp3qC","title":"Quick edit","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Quick edit"},{"name":"iconClass","value":"bx bx-edit","type":"label"}]},{"id":"_help_9sRHySam5fXb","title":"Workspaces","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Workspaces"},{"name":"iconClass","value":"bx bx-door-open","type":"label"}]},{"id":"_help_xWtq5NUHOwql","title":"Similar Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Similar Notes"},{"name":"iconClass","value":"bx bx-bar-chart","type":"label"}]},{"id":"_help_McngOG2jbUWX","title":"Search in note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Search in note"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]}]},{"id":"_help_A9Oc6YKKc65v","title":"Keyboard Shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Keyboard Shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_Wy267RK4M69c","title":"Themes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes"},{"name":"iconClass","value":"bx bx-palette","type":"label"}],"children":[{"id":"_help_VbjZvtUek0Ln","title":"Theme Gallery","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes/Theme Gallery"},{"name":"iconClass","value":"bx bx-book-reader","type":"label"}]},{"id":"_help_gOKqSJgXLcIj","title":"Icon Packs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes/Icon Packs"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_mHbBMPDPkVV5","title":"Import & Export","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export"},{"name":"iconClass","value":"bx bx-import","type":"label"}],"children":[{"id":"_help_Oau6X9rCuegd","title":"Markdown","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}],"children":[{"id":"_help_rJ9grSgoExl9","title":"Supported syntax","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown/Supported syntax"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}]}]},{"id":"_help_syuSEKf2rUGr","title":"Evernote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Evernote"},{"name":"iconClass","value":"bx bx-window-open","type":"label"}],"children":[{"id":"_help_dj3j8dG4th4l","title":"Process internal links by title","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_GnhlmrATVqcH","title":"OneNote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/OneNote"},{"name":"iconClass","value":"bx bx-window-open","type":"label"}]}]},{"id":"_help_rC3pL2aptaRE","title":"Zen mode","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Zen mode"},{"name":"iconClass","value":"bx bxs-yin-yang","type":"label"}]},{"id":"_help_YzMcWlCVeW09","title":"Active content","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Active content"},{"name":"iconClass","value":"bx bxs-widget","type":"label"}]}]},{"id":"_help_s3YCWHBfmYuM","title":"Quick Start","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Quick Start"},{"name":"iconClass","value":"bx bx-run","type":"label"}]},{"id":"_help_i6dbnitykE5D","title":"FAQ","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/FAQ"},{"name":"iconClass","value":"bx bx-question-mark","type":"label"}]},{"id":"_help_KSZ04uQ2D1St","title":"Note Types","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types"},{"name":"iconClass","value":"bx bx-edit","type":"label"}],"children":[{"id":"_help_iPIMuisry3hd","title":"Text","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text"},{"name":"iconClass","value":"bx bx-note","type":"label"}],"children":[{"id":"_help_NwBbFdNZ9h7O","title":"Block quotes & admonitions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Block quotes & admonitions"},{"name":"iconClass","value":"bx bx-info-circle","type":"label"}]},{"id":"_help_oSuaNgyyKnhu","title":"Bookmarks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Bookmarks"},{"name":"iconClass","value":"bx bx-bookmark","type":"label"}]},{"id":"_help_veGu4faJErEM","title":"Content language & Right-to-left support","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Content language & Right-to-le"},{"name":"iconClass","value":"bx bx-align-right","type":"label"}]},{"id":"_help_2x0ZAX9ePtzV","title":"Cut to subnote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Cut to subnote"},{"name":"iconClass","value":"bx bx-cut","type":"label"}]},{"id":"_help_UYuUB1ZekNQU","title":"Developer-specific formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Developer-specific formatting"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}],"children":[{"id":"_help_QxEyIjRBizuC","title":"Code blocks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Developer-specific formatting/Code blocks"},{"name":"iconClass","value":"bx bx-code","type":"label"}]}]},{"id":"_help_AgjCISero73a","title":"Footnotes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Footnotes"},{"name":"iconClass","value":"bx bx-bracket","type":"label"}]},{"id":"_help_nRhnJkTT8cPs","title":"Formatting toolbar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Formatting toolbar"},{"name":"iconClass","value":"bx bx-text","type":"label"}]},{"id":"_help_Gr6xFaF6ioJ5","title":"General formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/General formatting"},{"name":"iconClass","value":"bx bx-bold","type":"label"}]},{"id":"_help_AxshuNRegLAv","title":"Highlights list","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Highlights list"},{"name":"iconClass","value":"bx bx-highlight","type":"label"}]},{"id":"_help_mT0HEkOsz6i1","title":"Images","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Images"},{"name":"iconClass","value":"bx bx-image-alt","type":"label"}],"children":[{"id":"_help_0Ofbk1aSuVRu","title":"Image references","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Images/Image references"},{"name":"iconClass","value":"bx bxs-file-image","type":"label"}]}]},{"id":"_help_nBAXQFj20hS1","title":"Include Note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Include Note"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_CohkqWQC1iBv","title":"Insert buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Insert buttons"},{"name":"iconClass","value":"bx bx-plus","type":"label"}]},{"id":"_help_oiVPnW8QfnvS","title":"Keyboard shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Keyboard shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_QEAPj01N5f7w","title":"Links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links"},{"name":"iconClass","value":"bx bx-link-alt","type":"label"}],"children":[{"id":"_help_3IDVtesTQ8ds","title":"External links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links/External links"},{"name":"iconClass","value":"bx bx-link-external","type":"label"}]},{"id":"_help_hrZ1D00cLbal","title":"Internal (reference) links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links/Internal (reference) links"},{"name":"iconClass","value":"bx bx-link","type":"label"}]}]},{"id":"_help_S6Xx8QIWTV66","title":"Lists","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Lists"},{"name":"iconClass","value":"bx bx-list-ul","type":"label"}]},{"id":"_help_QrtTYPmdd1qq","title":"Markdown-like formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Markdown-like formatting"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}]},{"id":"_help_YfYAtQBcfo5V","title":"Math Equations","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Math Equations"},{"name":"iconClass","value":"bx bx-math","type":"label"}]},{"id":"_help_dEHYtoWWi8ct","title":"Other features","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Other features"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_gLt3vA97tMcp","title":"Premium features","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features"},{"name":"iconClass","value":"bx bx-star","type":"label"}],"children":[{"id":"_help_ZlN4nump6EbW","title":"Slash Commands","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Slash Commands"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_pwc194wlRzcH","title":"Text Snippets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Text Snippets"},{"name":"iconClass","value":"bx bx-align-left","type":"label"}]},{"id":"_help_5wZallV2Qo1t","title":"Format Painter","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Format Painter"},{"name":"iconClass","value":"bx bxs-paint-roll","type":"label"}]}]},{"id":"_help_oBo3iHIZnbG2","title":"Spell Check","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Spell Check"},{"name":"iconClass","value":"bx bx-check-double","type":"label"}]},{"id":"_help_BFvAtE74rbP6","title":"Table of contents","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Table of contents"},{"name":"iconClass","value":"bx bx-heading","type":"label"}]},{"id":"_help_NdowYOC1GFKS","title":"Tables","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Tables"},{"name":"iconClass","value":"bx bx-table","type":"label"}]}]},{"id":"_help_6f9hih2hXXZk","title":"Code","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Code"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_m523cpzocqaD","title":"Saved Search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Saved Search"},{"name":"iconClass","value":"bx bx-file-find","type":"label"}]},{"id":"_help_iRwzGnHPzonm","title":"Relation Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Relation Map"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_bdUJEHsAPYQR","title":"Note Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Note Map"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_HcABDtFCkbFN","title":"Render Note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Render Note"},{"name":"iconClass","value":"bx bx-extension","type":"label"}]},{"id":"_help_s1aBHPd79XYj","title":"Mermaid Diagrams","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mermaid Diagrams"},{"name":"iconClass","value":"bx bx-selection","type":"label"}],"children":[{"id":"_help_RH6yLjjWJHof","title":"ELK layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mermaid Diagrams/ELK layout"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_WWgeUaBb7UfC","title":"Syntax reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://mermaid.js.org/intro/syntax-reference.html"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_grjYqerjn243","title":"Canvas","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Canvas"},{"name":"iconClass","value":"bx bx-pen","type":"label"}]},{"id":"_help_1vHRoWCEjj0L","title":"Web View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Web View"},{"name":"iconClass","value":"bx bx-globe-alt","type":"label"}]},{"id":"_help_gBbsAeiuUxI5","title":"Mind Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mind Map"},{"name":"iconClass","value":"bx bx-sitemap","type":"label"}]},{"id":"_help_W8vYD3Q1zjCR","title":"File","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File"},{"name":"iconClass","value":"bx bx-file-blank","type":"label"}],"children":[{"id":"_help_XJGJrpu7F9sh","title":"PDFs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File/PDFs"},{"name":"iconClass","value":"bx bxs-file-pdf","type":"label"}]},{"id":"_help_AjqEeiDUOzj4","title":"Videos","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File/Videos"},{"name":"iconClass","value":"bx bx-video","type":"label"}]}]},{"id":"_help_GWHEkY4I4OE3","title":"Spreadsheets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Spreadsheets"},{"name":"iconClass","value":"bx bx-table","type":"label"}]},{"id":"_help_6RM1Q7ppFVoj","title":"Markdown","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Markdown"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}]}]},{"id":"_help_GTwFsgaA0lCt","title":"Collections","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections"},{"name":"iconClass","value":"bx bx-book","type":"label"}],"children":[{"id":"_help_xWbu3jpNWapp","title":"Calendar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Calendar"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]},{"id":"_help_2FvYrpmOXm29","title":"Table","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Table"},{"name":"iconClass","value":"bx bx-table","type":"label"}]},{"id":"_help_CtBQqbwXDx1w","title":"Kanban Board","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Kanban Board"},{"name":"iconClass","value":"bx bx-columns","type":"label"}]},{"id":"_help_81SGnPGMk7Xc","title":"Geo Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Geo Map"},{"name":"iconClass","value":"bx bx-map-alt","type":"label"}]},{"id":"_help_zP3PMqaG71Ct","title":"Presentation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Presentation"},{"name":"iconClass","value":"bx bx-slideshow","type":"label"}]},{"id":"_help_8QqnMzx393bx","title":"Grid View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Grid View"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_mULW0Q3VojwY","title":"List View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/List View"},{"name":"iconClass","value":"bx bx-list-ul","type":"label"}]},{"id":"_help_CssoWBu8I7jF","title":"Collection Properties","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Collection Properties"},{"name":"iconClass","value":"bx bx-cog","type":"label"}]}]},{"id":"_help_BgmBlOIl72jZ","title":"Troubleshooting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting"},{"name":"iconClass","value":"bx bx-bug","type":"label"}],"children":[{"id":"_help_wy8So3yZZlH9","title":"Reporting issues","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Reporting issues"},{"name":"iconClass","value":"bx bx-bug-alt","type":"label"}]},{"id":"_help_x59R8J8KV5Bp","title":"Anonymized Database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Anonymized Database"},{"name":"iconClass","value":"bx bx-low-vision","type":"label"}]},{"id":"_help_qzNzp9LYQyPT","title":"Error logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs"},{"name":"iconClass","value":"bx bx-comment-error","type":"label"}],"children":[{"id":"_help_bnyigUA2UK7s","title":"Backend (server) logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs/Backend (server) logs"},{"name":"iconClass","value":"bx bx-server","type":"label"}]},{"id":"_help_9yEHzMyFirZR","title":"Frontend logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs/Frontend logs"},{"name":"iconClass","value":"bx bx-window-alt","type":"label"}]}]},{"id":"_help_vdlYGAcpXAgc","title":"Synchronization fails with 504 Gateway Timeout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Synchronization fails with 504"},{"name":"iconClass","value":"bx bx-error","type":"label"}]},{"id":"_help_s8alTXmpFR61","title":"Refreshing the application","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Refreshing the application"},{"name":"iconClass","value":"bx bx-refresh","type":"label"}]}]},{"id":"_help_pKK96zzmvBGf","title":"Theme development","type":"book","attributes":[{"name":"iconClass","value":"bx bx-palette","type":"label"}],"children":[{"id":"_help_7NfNr5pZpVKV","title":"Creating a custom theme","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Creating a custom theme"},{"name":"iconClass","value":"bx bxs-color","type":"label"}]},{"id":"_help_WFGzWeUK6arS","title":"Customize the Next theme","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Customize the Next theme"},{"name":"iconClass","value":"bx bx-news","type":"label"}]},{"id":"_help_WN5z4M8ASACJ","title":"Reference","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Reference"},{"name":"iconClass","value":"bx bx-book-open","type":"label"}]},{"id":"_help_AlhDUqhENtH7","title":"Custom app-wide CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Custom app-wide CSS"},{"name":"iconClass","value":"bx bxs-file-css","type":"label"}]},{"id":"_help_g1mlRoU8CsqC","title":"Creating an icon pack","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Creating an icon pack"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_tC7s2alapj8V","title":"Advanced Usage","type":"book","attributes":[{"name":"iconClass","value":"bx bx-rocket","type":"label"}],"children":[{"id":"_help_zEY4DaJG4YT5","title":"Attributes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes"},{"name":"iconClass","value":"bx bx-list-check","type":"label"}],"children":[{"id":"_help_HI6GBBIduIgv","title":"Labels","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Labels"},{"name":"iconClass","value":"bx bx-hash","type":"label"}]},{"id":"_help_Cq5X6iKQop6R","title":"Relations","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Relations"},{"name":"iconClass","value":"bx bx-transfer","type":"label"}]},{"id":"_help_bwZpz2ajCEwO","title":"Attribute Inheritance","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Attribute Inheritance"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_OFXdgB2nNk1F","title":"Promoted Attributes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Promoted Attributes"},{"name":"iconClass","value":"bx bx-table","type":"label"}]}]},{"id":"_help_KC1HB96bqqHX","title":"Templates","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Templates"},{"name":"iconClass","value":"bx bx-copy","type":"label"}]},{"id":"_help_BCkXAVs63Ttv","title":"Note Map (Link map, Tree map)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note Map (Link map, Tree map)"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_R9pX4DGra2Vt","title":"Sharing","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing"},{"name":"iconClass","value":"bx bx-share-alt","type":"label"}],"children":[{"id":"_help_Qjt68inQ2bRj","title":"Serving directly the content of a note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Serving directly the content o"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_ycBFjKrrwE9p","title":"Exporting static HTML for web publishing","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Exporting static HTML for web "},{"name":"iconClass","value":"bx bxs-file-html","type":"label"}]},{"id":"_help_sLIJ6f1dkJYW","title":"Reverse proxy configuration","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Reverse proxy configuration"},{"name":"iconClass","value":"bx bx-world","type":"label"}]}]},{"id":"_help_5668rwcirq1t","title":"Advanced Showcases","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases"},{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_l0tKav7yLHGF","title":"Day Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Day Notes"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]},{"id":"_help_R7abl2fc6Mxi","title":"Weight Tracker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Weight Tracker"},{"name":"iconClass","value":"bx bx-line-chart","type":"label"}]},{"id":"_help_xYjQUYhpbUEW","title":"Task Manager","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Task Manager"},{"name":"iconClass","value":"bx bx-calendar-check","type":"label"}]}]},{"id":"_help_J5Ex1ZrMbyJ6","title":"Custom Request Handler","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Custom Request Handler"},{"name":"iconClass","value":"bx bx-globe","type":"label"}]},{"id":"_help_d3fAXQ2diepH","title":"Custom Resource Providers","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Custom Resource Providers"},{"name":"iconClass","value":"bx bxs-file-plus","type":"label"}]},{"id":"_help_pgxEVkzLl1OP","title":"ETAPI (REST API)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/ETAPI (REST API)"},{"name":"iconClass","value":"bx bx-extension","type":"label"}],"children":[{"id":"_help_9qPsTWBorUhQ","title":"API Reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/rest-api/etapi/"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_47ZrP6FNuoG8","title":"Default Note Title","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Default Note Title"},{"name":"iconClass","value":"bx bx-edit-alt","type":"label"}]},{"id":"_help_wX4HbRucYSDD","title":"Database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database"},{"name":"iconClass","value":"bx bx-data","type":"label"}],"children":[{"id":"_help_oyIAJ9PvvwHX","title":"Manually altering the database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Manually altering the database"},{"name":"iconClass","value":"bx bxs-edit","type":"label"}],"children":[{"id":"_help_YKWqdJhzi2VY","title":"SQL Console","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Manually altering the database/SQL Console"},{"name":"iconClass","value":"bx bx-data","type":"label"}]}]},{"id":"_help_6tZeKvSHEUiB","title":"Demo Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Demo Notes"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_Gzjqa934BdH4","title":"Configuration (config.ini or environment variables)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or e"},{"name":"iconClass","value":"bx bx-cog","type":"label"}],"children":[{"id":"_help_c5xB8m4g2IY6","title":"Trilium instance","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Trilium instance"},{"name":"iconClass","value":"bx bx-windows","type":"label"}]},{"id":"_help_LWtBjFej3wX3","title":"Cross-Origin Resource Sharing (CORS)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Cross-Origin Resource Sharing "},{"name":"iconClass","value":"bx bx-lock","type":"label"}]}]},{"id":"_help_ivYnonVFBxbQ","title":"Bulk Actions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Bulk Actions"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_4FahAwuGTAwC","title":"Note source","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note source"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_1YeN2MzFUluU","title":"Technologies used","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used"},{"name":"iconClass","value":"bx bx-pyramid","type":"label"}],"children":[{"id":"_help_MI26XDLSAlCD","title":"CKEditor","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/CKEditor"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_N4IDkixaDG9C","title":"MindElixir","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/MindElixir"},{"name":"iconClass","value":"bx bx-sitemap","type":"label"}]},{"id":"_help_H0mM1lTxF9JI","title":"Excalidraw","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/Excalidraw"},{"name":"iconClass","value":"bx bx-pen","type":"label"}]},{"id":"_help_MQHyy2dIFgxS","title":"Leaflet","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/Leaflet"},{"name":"iconClass","value":"bx bx-map-alt","type":"label"}]}]},{"id":"_help_m1lbrzyKDaRB","title":"Note ID","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note ID"},{"name":"iconClass","value":"bx bx-hash","type":"label"}]},{"id":"_help_0vTSyvhPTAOz","title":"Internal API","type":"book","attributes":[{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_z8O2VG4ZZJD7","title":"API Reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/rest-api/internal/"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_2mUhVmZK8RF3","title":"Hidden Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Hidden Notes"},{"name":"iconClass","value":"bx bx-hide","type":"label"}]},{"id":"_help_uYF7pmepw27K","title":"Metrics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Metrics"},{"name":"iconClass","value":"bx bxs-data","type":"label"}],"children":[{"id":"_help_bOP3TB56fL1V","title":"grafana-dashboard.json","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_64ZTlUPgEPtW","title":"Safe mode","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Safe mode"},{"name":"iconClass","value":"bx bxs-virus-block","type":"label"}]},{"id":"_help_HAIOFBoYIIdO","title":"Nightly release","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Nightly release"},{"name":"iconClass","value":"bx bx-moon","type":"label"}]},{"id":"_help_ZmT9ln8XJX2o","title":"Read-only database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Read-only database"},{"name":"iconClass","value":"bx bx-book-reader","type":"label"}]}]},{"id":"_help_GBBMSlVSOIGP","title":"AI","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/AI"},{"name":"iconClass","value":"bx bx-bot","type":"label"}]},{"id":"_help_CdNpE2pqjmI6","title":"Scripting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting"},{"name":"iconClass","value":"bx bxs-file-js","type":"label"}],"children":[{"id":"_help_yIhgI5H7A2Sm","title":"Frontend Basics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics"},{"name":"iconClass","value":"bx bx-window","type":"label"}],"children":[{"id":"_help_MgibgPcfeuGz","title":"Custom Widgets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets"},{"name":"iconClass","value":"bx bxs-widget","type":"label"}],"children":[{"id":"_help_SynTBQiBsdYJ","title":"Widget Basics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Widget Basics"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_GhurYZjh8e1V","title":"Note context aware widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Note context aware widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_M8IppdwVHSjG","title":"Right pane widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Right pane widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_YNxAqkI5Kg1M","title":"Word count widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Word count widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_VqGQnnPGnqAU","title":"CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/CSS"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_gMkgcLJ6jBkg","title":"Troubleshooting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Troubleshooting"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_es8OU2GuguFU","title":"Examples","type":"book","attributes":[{"name":"iconClass","value":"bx bx-code-alt","type":"label"}],"children":[{"id":"_help_TjLYAo3JMO8X","title":"\"New Task\" launcher button","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/New Task launcher button"},{"name":"iconClass","value":"bx bx-task","type":"label"}]},{"id":"_help_7kZPMD0uFwkH","title":"Downloading responses from Google Forms","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/Downloading responses from Goo"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_DL92EjAaXT26","title":"Using promoted attributes to configure scripts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/Using promoted attributes to c"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_4Gn3psZKsfSm","title":"Launch Bar Widgets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets"},{"name":"iconClass","value":"bx bx-dock-left","type":"label"}],"children":[{"id":"_help_IPArqVfDQ4We","title":"Note Title Widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets/Note Title Widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_gcI7RPbaNSh3","title":"Analog Watch","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets/Analog Watch"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_KLsqhjaqh1QW","title":"Preact","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact"},{"name":"iconClass","value":"bx bxl-react","type":"label"}],"children":[{"id":"_help_Bqde6BvPo05g","title":"Component libraries","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/Component libraries"},{"name":"iconClass","value":"bx bxs-component","type":"label"}]},{"id":"_help_ykYtbM9k3a7B","title":"Hooks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/Hooks"},{"name":"iconClass","value":"bx bx-question-mark","type":"label"}]},{"id":"_help_Sg9GrCtyftZf","title":"CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/CSS"},{"name":"iconClass","value":"bx bxs-file-css","type":"label"}]},{"id":"_help_RSssb9S3xgSr","title":"Built-in components","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/Built-in components"},{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_i9B4IW7b6V6z","title":"Widget showcase","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}]}]},{"id":"_help_SPirpZypehBG","title":"Backend scripts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts"},{"name":"iconClass","value":"bx bx-server","type":"label"}],"children":[{"id":"_help_fZ2IGYFXjkEy","title":"Server-side imports","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts/Server-side imports"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_GPERMystNGTB","title":"Events","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts/Events"},{"name":"iconClass","value":"bx bx-rss","type":"label"}]}]},{"id":"_help_wqXwKJl6VpNk","title":"Common concepts","type":"book","attributes":[{"name":"iconClass","value":"bx bxl-nodejs","type":"label"}],"children":[{"id":"_help_hA834UaHhSNn","title":"Script bundles","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Common concepts/Script bundles"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_GLks18SNjxmC","title":"Script API","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Script API"},{"name":"iconClass","value":"bx bx-code-curly","type":"label"}],"children":[{"id":"_help_Q2z6av6JZVWm","title":"Frontend API","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/frontend"},{"name":"iconClass","value":"bx bx-folder","type":"label"}],"enforceAttributes":true,"children":[{"id":"_help_habiZ3HU8Kw8","title":"FNote","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/frontend/interfaces/FNote.html"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_MEtfsqa5VwNi","title":"Backend API","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/backend"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true},{"id":"_help_ApVHZ8JY5ofC","title":"Day.js","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Script API/Day.js"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]}]},{"id":"_help_vElnKeDNPSVl","title":"Logging","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Logging"},{"name":"iconClass","value":"bx bx-terminal","type":"label"}]},{"id":"_help_cNpC0ITcfX0N","title":"Breaking changes","type":"book","attributes":[{"name":"iconClass","value":"bx bx-up-arrow-alt","type":"label"}],"children":[{"id":"_help_fqAK6opjUagR","title":"v0.103.0: Removal of axios","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Breaking changes/v0.103.0 Removal of axios"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_pAJ0jWz16xFm","title":"v0.103.0: `cheerio` is now deprecated","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Breaking changes/v0.103.0 `cheerio` is now depr"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_72dxvnbnkDFY","title":"v0.102.0: Upgrade to jQuery 4.0.0","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Breaking changes/v0.102.0 Upgrade to jQuery.0.0"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}]},{"id":"_help_Fm0j45KqyHpU","title":"Miscellaneous","type":"book","attributes":[{"name":"iconClass","value":"bx bx-info-circle","type":"label"}],"children":[{"id":"_help_WFbFXrgnDyyU","title":"Privacy Policy","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/Privacy Policy"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_NcsmUYZRWEW4","title":"Patterns of personal knowledge","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/Patterns of personal knowledge"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_d1Ap6Pg6IjaJ","title":"License","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/License"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}] \ No newline at end of file diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note types with split view.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note types with split view.html new file mode 100644 index 0000000000..0f3b39ee11 --- /dev/null +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note types with split view.html @@ -0,0 +1,31 @@ +

    Split view is a feature of Mermaid Diagrams and  + Markdown notes which displays both the source code on one side + and the preview of the content on the other.

    +

    Mermaid Diagrams also + allow changing between a horizontal or a vertical split, to accommodate + for the various sizes of diagrams.

    +

    Display modes and interaction

    +

    The split comes with three different display modes:

    +
      +
    • Split view, in which both the source code is available on one + side and can be edited, and the preview is available on the other side. +
        +
      • In this mode, the size of either the source pane or the preview pane can + be adjusted by dragging the small border between them.
      • +
      +
    • +
    • Source view which shows the source code on the entire screen for + a more focused editing experience.
    • +
    • Preview which displays only the rendering of the diagram or text + in full screen, especially useful for read-only notes.
    • +
    +

    These buttons can be found near the Note buttons section + on the New Layout, + or in the Floating buttons on + the old layout.

    +

    The display node is stored at note level.

    +

    Relation to read-only notes

    +

    If a note is marked as read-only, + the source view will not be editable. While in preview mode, marking a + note as read-only has no effect since the preview itself is not editable.

    \ No newline at end of file diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/File.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/File.html index f64ba7eade..152140d5ed 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/File.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/File.html @@ -5,7 +5,8 @@ create a File note type directly:

    • Drag a file into the Note Tree.
    • -
    • Right click a note and select Import into note and point it to +
    • Right click a note and select Import into note and point it to one of the supported files.

    Supported file types

    @@ -82,28 +83,30 @@ href="#root/_help_BlN9DFI679QC">Ribbon.
    • Download, which will download the file for local use.
    • -
    • Open, will will open the file with the system-default application.
    • -
    • Upload new revision to replace the file with a new one.
    • +
    • Open, will will open the file with the system-default application.
    • +
    • Upload new revision to replace the file with a new one.
    - -
  • It is not possible to change the note type of a File note.
  • -
  • Convert into an attachment from the note menu.
  • + +
  • It is not possible to change the note type of a File note.
  • +
  • Convert into an attachment from the note menu.
  • Relation with other notes

    • Files are also displayed in the Note List based on their type:

      - -
    • -
    • -

      Non-image files can be embedded into text notes as read-only widgets via - the Include Note functionality.

      -
    • -
    • -

      Image files can be embedded into text notes like normal images via  - Image references.

      +

      + +

    • +
    • Non-image files can be embedded into text notes as read-only widgets via + the Include Note functionality.
    • +
    • Image files can be embedded into text notes like normal images via  + Image references.
    \ No newline at end of file diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Markdown.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Markdown.html index 38f262c704..74cf113776 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Markdown.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Markdown.html @@ -4,8 +4,10 @@ (converted to Trilium's internal HTML format) or saved as a Code note with only syntax highlight.

    -

    v0.103.0 introduces a new note type: Markdown which which displays Markdown - source and a preview on the right.

    +

    This note type is a split view, meaning that both the source code and + a preview of the document are displayed side-by-side. See Note types with split view for + more information.

    Rationale

    The goal of this note type is to fill a gap: rendering Markdown but not altering its structure or its whitespace which would inevitably change @@ -19,18 +21,15 @@ One of the core aspects of the Markdown integration is that it reuses components that are already available through other features of the application.

    -

    Creating Markdown notes

    -

    There are two ways to create a Markdown note:

    -
      -
    1. Create a new note (e.g. in the Note Tree) - and select the type Markdown, just like all the other note types.
    2. -
    3. Create a note of type Code and - select as the language either Markdown or GitHub-Flavored Markdown. - This maintains compatibility with your existing notes prior to the introduction - of this feature.
    4. -
    -

    Supported features in preview

    +

    Features

    +

    Source view pane

    +
      +
    • Syntax highlighting for the Markdown syntax.
    • +
    • Nested syntax highlighting for code inside code blocks.
    • +
    • When editing larger documents, the preview scrolls along with the source + editor.
    • +
    +

    Preview pane

    The following features are supported by Trilium's Markdown format and will show up in the preview pane:

      @@ -50,7 +49,7 @@

      Include Note (no builtin Markdown syntax, but HTML syntax works just fine):

      <section class="include-note" data-note-id="vJDjQm0VK8Na" data-box-size="expandable">
       	&nbsp;
      -</section>
      +</section>n
    • Internal (reference) links via @@ -59,9 +58,76 @@ class="reference-link" href="#root/pOsGYCXsbNQG/tC7s2alapj8V/_help_m1lbrzyKDaRB">Note ID):

      [[Hg8TS5ZOxti6]]
    -

    Sync-scrolling

    +

    Creating Markdown notes

    +

    There are two ways to create a Markdown note:

    +
      +
    1. Create a new note (e.g. in the Note Tree) + and select the type Markdown, just like all the other note types.
    2. +
    3. Create a note of type Code and + select as the language either Markdown or GitHub-Flavored Markdown. + This maintains compatibility with your existing notes prior to the introduction + of this feature.
    4. +
    + +

    Import/export

    +
      +
    • +

      By default, when importing a single Markdown file it automatically gets + converted to a Text note. + To avoid that and have it imported as a Markdown note instead:

      +
        +
      • +

        Right click the Note Tree and + select Import into note.

        +
      • +
      • +

        Select the file normally.

        +
      • +
      • +

        Uncheck Import HTML, Markdown and TXT as text notes if it's unclear from the metadata.

        +
      • +
      +
    • +
    • +

      When exporting Markdown files, the extension is preserved and the content + remains the same as in the source view.

      +
    • +
    • +

      Once exported as a Trilium ZIP, the ZIP will preserve the Markdown type + without converting to text notes thanks to the meta-information in it.

      +
    • +
    +

    Conversion between text notes and Markdown notes

    +

    Currently there is no built-in functionality to convert a Text note + into a Markdown note or vice-versa. We do have plans to address this in + the future.

    +

    This can be achieved manually, for a single note:

    +
      +
    1. Export the file as Markdown, with single format.
    2. +
    3. Import the file again, but unchecking Import HTML, Markdown and TXT as text notes if it's unclear from the metadata.
    4. +
    +

    For multiple notes, the process is slightly more involved:

    +
      +
    1. Export the file as Markdown, ZIP.
    2. +
    3. Extract the archive.
    4. +
    5. Remove the !!!meta.json file.
    6. +
    7. Compress the extracted files back into an archive.
    8. +
    9. Import the newly create archive, but unchecking Import HTML, Markdown and TXT as text notes if it's unclear from the metadata.
    10. +
    +

    Sync-scrolling & block highlight

    When scrolling through the editing pane, the preview pane will attempt to synchronize its position to make it easier to see the preview.

    +

    In addition, the block in the preview matching the position of the cursor + in the source view will appear slightly highlighted.

    +

    The sync is currently one-way only, scrolling the preview will not synchronize + the position of the editor.

    This feature cannot be disabled as of now; if the scrolling feels distracting, consider temporarily switching to the editor mode and then switching to preview mode when ready.

    diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams.html index eab35ba10f..d6ff44cd93 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams.html @@ -6,11 +6,15 @@ -

    Types of diagrams

    Trilium supports Mermaid, which adds support for various diagrams such as flowchart, sequence diagram, class diagram, state diagram, pie charts, etc., all using a text description of the chart instead of manually drawing the diagram.

    +

    This note type is a split view, meaning that both the source code and + a preview of the document are displayed side-by-side. See Note types with split view for + more information.

    +

    Sample diagrams

    Starting with v0.103.0, Mermaid diagrams no longer start with a sample flowchart, but instead a pane at the bottom will show all the supported diagrams with sample code for each:

    @@ -66,7 +70,7 @@
  • Press the Copy image reference to the clipboard to be able to insert the image representation of the diagram into a text note. See [missing note] for more information.
  • + href="#root/_help_0Ofbk1aSuVRu">Image references for more information.
  • Press the Export diagram as SVG to download a scalable/vector rendering of the diagram. Can be used to present the diagram without degrading when diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Spreadsheets.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Spreadsheets.html index 010b594aa6..06f944a848 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Spreadsheets.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Spreadsheets.html @@ -64,15 +64,15 @@ yet:

    • Trilium-specific formulas (e.g. to obtain the title of a note).
    • -
    • User-defined formulas
    • -
    • Cross-workbook calculation
    • +
    • User-defined formulas
    • +
    • Cross-workbook calculation

    If you would like us to work on these features, consider supporting us.

    Known limitations

      -
    • -

      It is possible to share a spreadsheet, case in which a best-effort HTML - rendering of the spreadsheet is done.

      +
    • It is possible to share a spreadsheet, case in which a best-effort HTML + rendering of the spreadsheet is done.
      • For more advanced use cases, this will most likely not work as intended. Feel free to report issues, but keep in @@ -80,12 +80,9 @@ the features of Univer.
    • -
    • -

      There is currently no export functionality, as stated previously.

      -
    • -
    • -

      There is no dedicated mobile support. Mobile support is currently experimental - in Univer and when it becomes stable, we could potentially integrate it - into Trilium as well.

      -
    • +
    • There is currently no export functionality, as stated previously.
    • +
    • There is no dedicated mobile support. Mobile support is currently experimental + in Univer and when it becomes stable, we could potentially integrate it + into Trilium as well.
    \ No newline at end of file diff --git a/docs/User Guide/!!!meta.json b/docs/User Guide/!!!meta.json index f7e41610bf..d1b8f5d265 100644 --- a/docs/User Guide/!!!meta.json +++ b/docs/User Guide/!!!meta.json @@ -3962,6 +3962,83 @@ "attachments": [] } ] + }, + { + "isClone": false, + "noteId": "SL5f1Auq7sVN", + "notePath": [ + "pOsGYCXsbNQG", + "gh7bpGYxajRS", + "Vc8PjrjAGuOp", + "SL5f1Auq7sVN" + ], + "title": "Note types with split view", + "notePosition": 230, + "prefix": null, + "isExpanded": false, + "type": "text", + "mime": "text/html", + "attributes": [ + { + "type": "relation", + "name": "internalLink", + "value": "s1aBHPd79XYj", + "isInheritable": false, + "position": 30 + }, + { + "type": "relation", + "name": "internalLink", + "value": "6RM1Q7ppFVoj", + "isInheritable": false, + "position": 40 + }, + { + "type": "relation", + "name": "internalLink", + "value": "CoFPLs3dRlXc", + "isInheritable": false, + "position": 50 + }, + { + "type": "relation", + "name": "internalLink", + "value": "8YBEPzcpUgxw", + "isInheritable": false, + "position": 60 + }, + { + "type": "relation", + "name": "internalLink", + "value": "IjZS7iK5EXtb", + "isInheritable": false, + "position": 70 + }, + { + "type": "relation", + "name": "internalLink", + "value": "XpOYSgsLkTJy", + "isInheritable": false, + "position": 80 + }, + { + "type": "label", + "name": "iconClass", + "value": "bx bx-card", + "isInheritable": false, + "position": 90 + }, + { + "type": "label", + "name": "shareAlias", + "value": "note-types-with-split-view", + "isInheritable": false, + "position": 100 + } + ], + "format": "markdown", + "dataFileName": "Note types with split view.md", + "attachments": [] } ] }, @@ -10094,6 +10171,13 @@ "value": "bx bx-selection", "isInheritable": false, "position": 20 + }, + { + "type": "relation", + "name": "internalLink", + "value": "SL5f1Auq7sVN", + "isInheritable": false, + "position": 40 } ], "format": "markdown", @@ -10797,54 +10881,61 @@ "isInheritable": false, "position": 80 }, + { + "type": "relation", + "name": "internalLink", + "value": "wy8So3yZZlH9", + "isInheritable": false, + "position": 150 + }, + { + "type": "relation", + "name": "internalLink", + "value": "SL5f1Auq7sVN", + "isInheritable": false, + "position": 160 + }, { "type": "relation", "name": "internalLink", "value": "NwBbFdNZ9h7O", "isInheritable": false, - "position": 90 + "position": 170 }, { "type": "relation", "name": "internalLink", "value": "YfYAtQBcfo5V", "isInheritable": false, - "position": 100 + "position": 180 }, { "type": "relation", "name": "internalLink", "value": "s1aBHPd79XYj", "isInheritable": false, - "position": 110 + "position": 190 }, { "type": "relation", "name": "internalLink", "value": "nBAXQFj20hS1", "isInheritable": false, - "position": 120 + "position": 200 }, { "type": "relation", "name": "internalLink", "value": "hrZ1D00cLbal", "isInheritable": false, - "position": 130 + "position": 210 }, { "type": "relation", "name": "internalLink", "value": "m1lbrzyKDaRB", "isInheritable": false, - "position": 140 - }, - { - "type": "relation", - "name": "internalLink", - "value": "wy8So3yZZlH9", - "isInheritable": false, - "position": 150 + "position": 220 } ], "format": "markdown", diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note types with split view.md b/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note types with split view.md new file mode 100644 index 0000000000..6595e897fd --- /dev/null +++ b/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note types with split view.md @@ -0,0 +1,21 @@ +# Note types with split view +Split view is a feature of Mermaid Diagrams and Markdown notes which displays both the source code on one side and the preview of the content on the other. + +Mermaid Diagrams also allow changing between a horizontal or a vertical split, to accommodate for the various sizes of diagrams. + +## Display modes and interaction + +The split comes with three different display modes: + +* _Split view_, in which both the source code is available on one side and can be edited, and the preview is available on the other side. + * In this mode, the size of either the source pane or the preview pane can be adjusted by dragging the small border between them. +* _Source view_ which shows the source code on the entire screen for a more focused editing experience. +* _Preview_ which displays only the rendering of the diagram or text in full screen, especially useful for read-only notes. + +These buttons can be found near the Note buttons section on the New Layout, or in the Floating buttons on the old layout. + +The display node is stored at note level. + +## Relation to read-only notes + +If a note is marked as [read-only](../Notes/Read-Only%20Notes.md), the source view will not be editable. While in preview mode, marking a note as read-only has no effect since the preview itself is not editable. \ No newline at end of file diff --git a/docs/User Guide/User Guide/Note Types/Markdown.md b/docs/User Guide/User Guide/Note Types/Markdown.md index 685fc59b90..b96b627329 100644 --- a/docs/User Guide/User Guide/Note Types/Markdown.md +++ b/docs/User Guide/User Guide/Note Types/Markdown.md @@ -1,7 +1,7 @@ # Markdown Trilium has always supported Markdown through its [import feature](../Basic%20Concepts%20and%20Features/Import%20%26%20Export/Markdown.md), however the file was either transformed to a Text note (converted to Trilium's internal HTML format) or saved as a Code note with only syntax highlight. -v0.103.0 introduces a new note type: Markdown which which displays Markdown source and a preview on the right. +This note type is a split view, meaning that both the source code and a preview of the document are displayed side-by-side. See Note types with split view for more information. ## Rationale @@ -12,14 +12,15 @@ Even if Markdown is now specially treated by having a preview mechanism, Trilium > [!NOTE] > Feature requests regarding the Markdown implementation will be considered, but if they are outside the realm of Trilium they will not be implemented. One of the core aspects of the Markdown integration is that it reuses components that are already available through other features of the application. -## Creating Markdown notes +## Features -There are two ways to create a Markdown note: +### Source view pane -1. Create a new note (e.g. in the Note Tree) and select the type _Markdown_, just like all the other note types. -2. Create a note of type Code and select as the language either _Markdown_ or _GitHub-Flavored Markdown_. This maintains compatibility with your existing notes prior to the introduction of this feature. +* Syntax highlighting for the Markdown syntax. +* Nested syntax highlighting for code inside code blocks. +* When editing larger documents, the preview scrolls along with the source editor. -## Supported features in preview +### Preview pane The following features are supported by Trilium's Markdown format and will show up in the preview pane: @@ -33,7 +34,7 @@ The following features are supported by Trilium's Markdown format and will show ```
      -
    + n ``` * Internal (reference) links via its HTML syntax, or through a _Wikilinks_\-like format (only Note ID): @@ -41,10 +42,51 @@ The following features are supported by Trilium's Markdown format and will show [[Hg8TS5ZOxti6]] ``` -## Sync-scrolling +## Creating Markdown notes + +There are two ways to create a Markdown note: + +1. Create a new note (e.g. in the Note Tree) and select the type _Markdown_, just like all the other note types. +2. Create a note of type Code and select as the language either _Markdown_ or _GitHub-Flavored Markdown_. This maintains compatibility with your existing notes prior to the introduction of this feature. + +> [!NOTE] +> There is no distinction between the new Markdown note type and code notes of type Markdown; internally both are represented as Code notes with the proper MIME type (e.g. `text/x-markdown`). + +## Import/export + +* By default, when importing a single Markdown file it automatically gets converted to a Text note. To avoid that and have it imported as a Markdown note instead: + + * Right click the Note Tree and select _Import into note_. + * Select the file normally. + * Uncheck _Import HTML, Markdown and TXT as text notes if it's unclear from the metadata_. +* When exporting Markdown files, the extension is preserved and the content remains the same as in the source view. +* Once exported as a Trilium ZIP, the ZIP will preserve the Markdown type without converting to text notes thanks to the meta-information in it. + +## Conversion between text notes and Markdown notes + +Currently there is no built-in functionality to convert a Text note into a Markdown note or vice-versa. We do have plans to address this in the future. + +This can be achieved manually, for a single note: + +1. Export the file as Markdown, with single format. +2. Import the file again, but unchecking _Import HTML, Markdown and TXT as text notes if it's unclear from the metadata_. + +For multiple notes, the process is slightly more involved: + +1. Export the file as Markdown, ZIP. +2. Extract the archive. +3. Remove the `!!!meta.json` file. +4. Compress the extracted files back into an archive. +5. Import the newly create archive, but unchecking _Import HTML, Markdown and TXT as text notes if it's unclear from the metadata_. + +## Sync-scrolling & block highlight When scrolling through the editing pane, the preview pane will attempt to synchronize its position to make it easier to see the preview. +In addition, the block in the preview matching the position of the cursor in the source view will appear slightly highlighted. + +The sync is currently one-way only, scrolling the preview will not synchronize the position of the editor. + This feature cannot be disabled as of now; if the scrolling feels distracting, consider temporarily switching to the editor mode and then switching to preview mode when ready. > [!NOTE] diff --git a/docs/User Guide/User Guide/Note Types/Mermaid Diagrams.md b/docs/User Guide/User Guide/Note Types/Mermaid Diagrams.md index aea9436b24..48c36e6f1e 100644 --- a/docs/User Guide/User Guide/Note Types/Mermaid Diagrams.md +++ b/docs/User Guide/User Guide/Note Types/Mermaid Diagrams.md @@ -4,10 +4,12 @@
    -## Types of diagrams - Trilium supports Mermaid, which adds support for various diagrams such as flowchart, sequence diagram, class diagram, state diagram, pie charts, etc., all using a text description of the chart instead of manually drawing the diagram. +This note type is a split view, meaning that both the source code and a preview of the document are displayed side-by-side. See Note types with split view for more information. + +## Sample diagrams + Starting with v0.103.0, Mermaid diagrams no longer start with a sample flowchart, but instead a pane at the bottom will show all the supported diagrams with sample code for each: * Simply click on any of the samples to apply it. @@ -35,7 +37,7 @@ It's possible to switch between the two layouts at any time by pressing the ![]( * In the Floating buttons area: * The source/preview can be laid out left-right or bottom-top via the _Move editing pane to the left / bottom_ option. * Press _Lock editing_ to automatically mark the note as read-only. In this mode, the code pane is hidden and the diagram is displayed full-size. Similarly, press _Unlock editing_ to mark a read-only note as editable. - * Press the _Copy image reference to the clipboard_ to be able to insert the image representation of the diagram into a text note. See [missing note] for more information. + * Press the _Copy image reference to the clipboard_ to be able to insert the image representation of the diagram into a text note. See Image references for more information. * Press the _Export diagram as SVG_ to download a scalable/vector rendering of the diagram. Can be used to present the diagram without degrading when zooming. * Press the _Export diagram as PNG_ to download a normal image (at 1x scale, raster) of the diagram. Can be used to send the diagram in more traditional channels such as e-mail. diff --git a/docs/User Guide/User Guide/Note Types/Spreadsheets.md b/docs/User Guide/User Guide/Note Types/Spreadsheets.md index 70fa55a757..7728206945 100644 --- a/docs/User Guide/User Guide/Note Types/Spreadsheets.md +++ b/docs/User Guide/User Guide/Note Types/Spreadsheets.md @@ -60,7 +60,6 @@ If you would like us to work on these features, consider [supporting us](https:/ ## Known limitations * It is possible to share a spreadsheet, case in which a best-effort HTML rendering of the spreadsheet is done. - * For more advanced use cases, this will most likely not work as intended. Feel free to [report issues](../Troubleshooting/Reporting%20issues.md), but keep in mind that we might not be able to have a complete feature parity with all the features of Univer. * There is currently no export functionality, as stated previously. * There is no dedicated mobile support. Mobile support is currently experimental in Univer and when it becomes stable, we could potentially integrate it into Trilium as well. \ No newline at end of file From 75b4877c874bd8d6920a65e3b3f7903b1978925e Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 21:35:14 +0300 Subject: [PATCH 335/482] fix(import/mime): importing a Markdown file with conversion to text disabled is treated as file instead of code --- apps/server/src/services/import/mime.spec.ts | 10 ++++++++++ apps/server/src/services/import/mime.ts | 2 +- apps/server/src/services/import/zip.ts | 8 ++++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/apps/server/src/services/import/mime.spec.ts b/apps/server/src/services/import/mime.spec.ts index 223517d320..9c9fe825b9 100644 --- a/apps/server/src/services/import/mime.spec.ts +++ b/apps/server/src/services/import/mime.spec.ts @@ -123,6 +123,16 @@ describe("#getType", () => { [{textImportedAsText: false}, "text/x-markdown"], "file" ], + [ + "w/ codeImportedAsCode: true and 'text/markdown' mime type (override) – it should return 'code'", + [{codeImportedAsCode: true}, "text/markdown"], "code" + ], + + [ + "w/ codeImportedAsCode: true and 'application/javascript' mime type (override) – it should return 'code'", + [{codeImportedAsCode: true}, "application/javascript"], "code" + ], + [ "w/ textImportedAsText: false and 'text/html' mime type – it should return 'file'", [{textImportedAsText: false}, "text/html"], "file" diff --git a/apps/server/src/services/import/mime.ts b/apps/server/src/services/import/mime.ts index b25e98926d..7a54a1f5a1 100644 --- a/apps/server/src/services/import/mime.ts +++ b/apps/server/src/services/import/mime.ts @@ -97,7 +97,7 @@ function getType(options: TaskData<"importNotes">, mime: string): NoteType { case options?.textImportedAsText && ["text/html", "text/markdown", "text/x-markdown", "text/mdx"].includes(mimeLc): return "text"; - case options?.codeImportedAsCode && CODE_MIME_TYPES.has(mimeLc): + case options?.codeImportedAsCode && (CODE_MIME_TYPES.has(mimeLc) || CODE_MIME_TYPES_OVERRIDE.has(mimeLc)): return "code"; case mime.startsWith("image/"): diff --git a/apps/server/src/services/import/zip.ts b/apps/server/src/services/import/zip.ts index 5d9e00d8ab..e4a0dfbd98 100644 --- a/apps/server/src/services/import/zip.ts +++ b/apps/server/src/services/import/zip.ts @@ -175,8 +175,12 @@ async function importZip(taskContext: TaskContext<"importNotes">, fileBuffer: Bu } function detectFileTypeAndMime(taskContext: TaskContext<"importNotes">, filePath: string) { - const mime = mimeService.getMime(filePath) || "application/octet-stream"; - const type = mimeService.getType(taskContext.data || {}, mime); + const rawMime = mimeService.getMime(filePath) || "application/octet-stream"; + const type = mimeService.getType(taskContext.data || {}, rawMime); + // Normalize aliased code MIMEs (e.g. `text/markdown` → `text/x-markdown`, + // `application/javascript` → `application/javascript;env=frontend`) so the + // stored MIME matches what the rest of the app expects. + const mime = (type === "code" && mimeService.normalizeMimeType(rawMime)) || rawMime; return { mime, type }; } From 69763c8b143739cb47694e899d6b701f08390f09 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 21:41:35 +0300 Subject: [PATCH 336/482] feat(markdown): render preview as Markdown --- apps/client/src/services/content_renderer.ts | 34 +++++++++- .../src/services/content_renderer_text.ts | 64 +++++++++++-------- 2 files changed, 69 insertions(+), 29 deletions(-) diff --git a/apps/client/src/services/content_renderer.ts b/apps/client/src/services/content_renderer.ts index e037383a73..cfe4383f09 100644 --- a/apps/client/src/services/content_renderer.ts +++ b/apps/client/src/services/content_renderer.ts @@ -1,6 +1,7 @@ import "./content_renderer.css"; -import { normalizeMimeTypeForCKEditor, type TextRepresentationResponse } from "@triliumnext/commons"; +import { normalizeMimeTypeForCKEditor, renderToHtml, type TextRepresentationResponse } from "@triliumnext/commons"; +import DOMPurify from "dompurify"; import { h, render } from "preact"; import WheelZoom from 'vanilla-js-wheel-zoom'; @@ -8,7 +9,7 @@ import FAttachment from "../entities/fattachment.js"; import FNote from "../entities/fnote.js"; import imageContextMenuService from "../menus/image_context_menu.js"; import { t } from "../services/i18n.js"; -import renderText from "./content_renderer_text.js"; +import renderText, { postProcessRichContent, renderChildrenList } from "./content_renderer_text.js"; import renderDoc from "./doc_renderer.js"; import { loadElkIfNeeded, postprocessMermaidSvg } from "./mermaid.js"; import openService from "./open.js"; @@ -54,6 +55,8 @@ export async function getRenderedContent(this: {} | { ctx: string }, entity: FNo if (type === "text" || type === "book") { await renderText(entity, $renderedContent, options); + } else if (type === "markdown") { + await renderMarkdown(entity, $renderedContent, options); } else if (type === "code") { await renderCode(entity, $renderedContent); } else if (["image", "canvas", "mindMap", "spreadsheet"].includes(type)) { @@ -119,6 +122,31 @@ export async function getRenderedContent(this: {} | { ctx: string }, entity: FNo }; } +/** + * Renders a markdown note by converting its source to CKEditor-compatible HTML, + * then running the same post-render pipeline as text notes (included notes, + * math, reference links, Mermaid, code highlight) so the preview matches what + * the user sees in the Markdown note type's preview pane. + */ +async function renderMarkdown(note: FNote | FAttachment, $renderedContent: JQuery, options: RenderOptions) { + const blob = await note.getBlob(); + const source = blob?.content ?? ""; + + if (!source.trim()) { + if (note instanceof FNote && !options.noChildrenList) { + await renderChildrenList($renderedContent, note, options.includeArchivedNotes ?? false); + } + return; + } + + const html = renderToHtml(source, note.title, { + sanitize: (dirty) => DOMPurify.sanitize(dirty), + wikiLink: { formatHref: (id) => `#root/${id}` } + }); + $renderedContent.append($('
    ').html(html)); + await postProcessRichContent(note, $renderedContent, options); +} + /** * Renders a code note, by displaying its content and applying syntax highlighting based on the selected MIME type. */ @@ -330,6 +358,8 @@ function getRenderingType(entity: FNote | FAttachment) { if (type === "file" && mime === "application/pdf") { type = "pdf"; + } else if (type === "code" && entity instanceof FNote && entity.isMarkdown()) { + type = "markdown"; } else if ((type === "file" || type === "viewConfig") && mime && CODE_MIME_TYPES.has(mime) && !isIconPack) { type = "code"; } else if (type === "file" && mime && mime.startsWith("audio/")) { diff --git a/apps/client/src/services/content_renderer_text.ts b/apps/client/src/services/content_renderer_text.ts index dd8178708d..1684ce766c 100644 --- a/apps/client/src/services/content_renderer_text.ts +++ b/apps/client/src/services/content_renderer_text.ts @@ -15,37 +15,47 @@ export default async function renderText(note: FNote | FAttachment, $renderedCon if (blob && !isHtmlEmpty(blob.content)) { $renderedContent.append($('
    ').html(blob.content)); - - const seenNoteIds = options.seenNoteIds ?? new Set(); - seenNoteIds.add("noteId" in note ? note.noteId : note.attachmentId); - if (!options.noIncludedNotes) { - await renderIncludedNotes($renderedContent[0], seenNoteIds); - } else { - $renderedContent.find("section.include-note").remove(); - } - - if ($renderedContent.find("span.math-tex").length > 0) { - renderMathInElement($renderedContent[0], { trust: true }); - } - - const getNoteIdFromLink = (el: HTMLElement) => tree.getNoteIdFromUrl($(el).attr("href") || ""); - const referenceLinks = $renderedContent.find("a.reference-link"); - const noteIdsToPrefetch = referenceLinks.map((i, el) => getNoteIdFromLink(el)); - await froca.getNotes(noteIdsToPrefetch); - - for (const el of referenceLinks) { - const innerSpan = document.createElement("span"); - await link.loadReferenceLinkTitle($(innerSpan), el.href); - el.replaceChildren(innerSpan); - } - - await rewriteMermaidDiagramsInContainer($renderedContent[0] as HTMLDivElement); - await formatCodeBlocks($renderedContent); + await postProcessRichContent(note, $renderedContent, options); } else if (note instanceof FNote && !options.noChildrenList) { await renderChildrenList($renderedContent, note, options.includeArchivedNotes ?? false); } } +/** + * Apply the post-render passes that make CKEditor-compatible HTML fully + * interactive: expand `
    `, render inline math and + * Mermaid diagrams, rewrite reference-link titles, and highlight code blocks. + * Assumes the caller has already appended the HTML inside a `.ck-content` child + * of `$renderedContent`. + */ +export async function postProcessRichContent(note: FNote | FAttachment, $renderedContent: JQuery, options: RenderOptions = {}) { + const seenNoteIds = options.seenNoteIds ?? new Set(); + seenNoteIds.add("noteId" in note ? note.noteId : note.attachmentId); + if (!options.noIncludedNotes) { + await renderIncludedNotes($renderedContent[0], seenNoteIds); + } else { + $renderedContent.find("section.include-note").remove(); + } + + if ($renderedContent.find("span.math-tex").length > 0) { + renderMathInElement($renderedContent[0], { trust: true }); + } + + const getNoteIdFromLink = (el: HTMLElement) => tree.getNoteIdFromUrl($(el).attr("href") || ""); + const referenceLinks = $renderedContent.find("a.reference-link"); + const noteIdsToPrefetch = referenceLinks.map((i, el) => getNoteIdFromLink(el)); + await froca.getNotes(noteIdsToPrefetch); + + for (const el of referenceLinks) { + const innerSpan = document.createElement("span"); + await link.loadReferenceLinkTitle($(innerSpan), el.href); + el.replaceChildren(innerSpan); + } + + await rewriteMermaidDiagramsInContainer($renderedContent[0] as HTMLDivElement); + await formatCodeBlocks($renderedContent); +} + async function renderIncludedNotes(contentEl: HTMLElement, seenNoteIds: Set) { // TODO: Consider duplicating with server's share/content_renderer.ts. const includeNoteEls = contentEl.querySelectorAll("section.include-note"); @@ -201,7 +211,7 @@ export async function applyInlineMermaid(container: HTMLDivElement) { mermaidLastRenderedByPosition.set(container, nodes.map((n) => n.innerHTML)); } -async function renderChildrenList($renderedContent: JQuery, note: FNote, includeArchivedNotes: boolean) { +export async function renderChildrenList($renderedContent: JQuery, note: FNote, includeArchivedNotes: boolean) { let childNoteIds = note.getChildNoteIds(); if (!childNoteIds.length) { From 2639c5a2259a7564f11c47f2595b0fb3d36a9e14 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 22:22:22 +0300 Subject: [PATCH 337/482] chore: fix typecheck error --- apps/client/src/widgets/find_in_text.ts | 2 +- apps/client/src/widgets/sidebar/TableOfContents.tsx | 4 ++-- packages/ckeditor5/tsconfig.lib.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/client/src/widgets/find_in_text.ts b/apps/client/src/widgets/find_in_text.ts index e97a7a8dff..049dd9f215 100644 --- a/apps/client/src/widgets/find_in_text.ts +++ b/apps/client/src/widgets/find_in_text.ts @@ -63,7 +63,7 @@ export default class FindInText { const findResultElement = editorEl?.querySelectorAll(".ck-find-result"); const scrollingContainer = editorEl?.closest('.scrolling-container'); const containerTop = scrollingContainer?.getBoundingClientRect().top ?? 0; - const closestIndex = Array.from(findResultElement ?? []).findIndex((el) => el.getBoundingClientRect().top >= containerTop); + const closestIndex = Array.from(findResultElement ?? []).findIndex((el: Element) => el.getBoundingClientRect().top >= containerTop); currentFound = closestIndex >= 0 ? closestIndex : 0; } } diff --git a/apps/client/src/widgets/sidebar/TableOfContents.tsx b/apps/client/src/widgets/sidebar/TableOfContents.tsx index 4442af884c..d84670128d 100644 --- a/apps/client/src/widgets/sidebar/TableOfContents.tsx +++ b/apps/client/src/widgets/sidebar/TableOfContents.tsx @@ -1,6 +1,6 @@ import "./TableOfContents.css"; -import { attributeChangeAffectsHeading, CKTextEditor, ModelElement } from "@triliumnext/ckeditor5"; +import { attributeChangeAffectsHeading, CKTextEditor, ModelElement, type ModelNode } from "@triliumnext/ckeditor5"; import clsx from "clsx"; import { useCallback, useEffect, useRef, useState } from "preact/hooks"; @@ -230,7 +230,7 @@ function extractTocFromTextEditor(editor: CKTextEditor) { // Fallback to plain text if DOM conversion fails if (!text) { text = Array.from( item.getChildren() ) - .map( c => c.is( '$text' ) ? c.data : '' ) + .map( (c: ModelNode) => c.is( '$text' ) ? c.data : '' ) .join( '' ); } diff --git a/packages/ckeditor5/tsconfig.lib.json b/packages/ckeditor5/tsconfig.lib.json index 748d57ae0b..613c7845e1 100644 --- a/packages/ckeditor5/tsconfig.lib.json +++ b/packages/ckeditor5/tsconfig.lib.json @@ -8,7 +8,7 @@ "tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo", "emitDeclarationOnly": true, "forceConsistentCasingInFileNames": true, - "lib": ["DOM", "ES2020"], + "lib": ["DOM", "ES2023"], "types": [ "vite/client", "jquery" From 64bc1271e178cde4fb98a4cd01d2e8d7b6934eda Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 23:03:28 +0300 Subject: [PATCH 338/482] fix(server): prevent NaN potentially corrupting the backup when migrating --- apps/server/src/assets/translations/en/server.json | 3 ++- apps/server/src/services/migration.ts | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/server/src/assets/translations/en/server.json b/apps/server/src/assets/translations/en/server.json index 8542592a8f..23c8347aee 100644 --- a/apps/server/src/assets/translations/en/server.json +++ b/apps/server/src/assets/translations/en/server.json @@ -397,7 +397,8 @@ "migration": { "old_version": "Direct migration from your current version is not supported. Please upgrade to the latest v0.60.4 first and only then to this version.", "error_message": "Error during migration to version {{version}}: {{stack}}", - "wrong_db_version": "The version of the database ({{version}}) is newer than what the application expects ({{targetVersion}}), which means that it was created by a newer and incompatible version of Trilium. Upgrade to the latest version of Trilium to resolve this issue." + "wrong_db_version": "The version of the database ({{version}}) is newer than what the application expects ({{targetVersion}}), which means that it was created by a newer and incompatible version of Trilium. Upgrade to the latest version of Trilium to resolve this issue.", + "invalid_db_version": "The database version is not a valid number. This usually indicates a corrupted 'dbVersion' option in the database. Please restore from a backup." }, "modals": { "error_title": "Error" diff --git a/apps/server/src/services/migration.ts b/apps/server/src/services/migration.ts index df43e42bd2..4edb9fb028 100644 --- a/apps/server/src/services/migration.ts +++ b/apps/server/src/services/migration.ts @@ -130,6 +130,11 @@ function isDbUpToDate() { async function migrateIfNecessary() { const currentDbVersion = getDbVersion(); + if (isNaN(currentDbVersion)) { + await crash(t("migration.invalid_db_version")); + return; + } + if (currentDbVersion > appInfo.dbVersion && process.env.TRILIUM_IGNORE_DB_VERSION !== "true") { await crash(t("migration.wrong_db_version", { version: currentDbVersion, targetVersion: appInfo.dbVersion })); } From 1acbf5ba45d1b1eef8a86f42a0503e597e33437e Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 23:26:24 +0300 Subject: [PATCH 339/482] feat(electron): generate appimage (closes #409) --- .github/actions/build-electron/action.yml | 18 +++- apps/desktop/scripts/build-appimage.sh | 101 ++++++++++++++++++++++ 2 files changed, 118 insertions(+), 1 deletion(-) create mode 100755 apps/desktop/scripts/build-appimage.sh diff --git a/.github/actions/build-electron/action.yml b/.github/actions/build-electron/action.yml index 58fa9743a5..d4dfc5b570 100644 --- a/.github/actions/build-electron/action.yml +++ b/.github/actions/build-electron/action.yml @@ -66,12 +66,20 @@ runs: if: ${{ inputs.os == 'linux' }} shell: ${{ inputs.shell }} run: | - sudo apt-get update && sudo apt-get install rpm flatpak-builder elfutils + sudo apt-get update && sudo apt-get install rpm flatpak-builder elfutils libfuse2 flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo FLATPAK_ARCH=$(if [[ ${{ inputs.arch }} = 'arm64' ]]; then echo 'aarch64'; else echo 'x86_64'; fi) FLATPAK_VERSION='24.08' flatpak install --user --no-deps --arch $FLATPAK_ARCH --assumeyes runtime/org.freedesktop.Platform/$FLATPAK_ARCH/$FLATPAK_VERSION runtime/org.freedesktop.Sdk/$FLATPAK_ARCH/$FLATPAK_VERSION org.electronjs.Electron2.BaseApp/$FLATPAK_ARCH/$FLATPAK_VERSION + - name: Install appimagetool + if: ${{ inputs.os == 'linux' }} + shell: ${{ inputs.shell }} + run: | + APPIMAGETOOL_ARCH=$(if [[ ${{ inputs.arch }} = 'arm64' ]]; then echo 'aarch64'; else echo 'x86_64'; fi) + wget -q "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${APPIMAGETOOL_ARCH}.AppImage" -O /usr/local/bin/appimagetool + chmod +x /usr/local/bin/appimagetool + - name: Update build info shell: ${{ inputs.shell }} run: pnpm run chore:update-build-info @@ -90,6 +98,14 @@ runs: TARGET_ARCH: ${{ inputs.arch }} run: pnpm run --filter desktop electron-forge:make --arch=${{ inputs.arch }} --platform=${{ inputs.forge_platform }} + - name: Build AppImage + if: ${{ inputs.os == 'linux' }} + shell: ${{ inputs.shell }} + env: + TRILIUM_ARTIFACT_NAME_HINT: TriliumNotes-${{ github.ref_name }}-${{ inputs.os }}-${{ inputs.arch }} + APPIMAGE_EXTRACT_AND_RUN: "1" + run: bash apps/desktop/scripts/build-appimage.sh ${{ inputs.arch }} + # Add DMG signing step - name: Sign DMG if: inputs.os == 'macos' diff --git a/apps/desktop/scripts/build-appimage.sh b/apps/desktop/scripts/build-appimage.sh new file mode 100755 index 0000000000..d4016ce134 --- /dev/null +++ b/apps/desktop/scripts/build-appimage.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env bash +# +# Build an AppImage from the packaged Electron app. +# +# Usage: ./build-appimage.sh [arch] +# arch: x64 or arm64 (default: x64) +# +# Prerequisites: +# - The Electron app must already be packaged via `electron-forge make` or `electron-forge package` +# - appimagetool must be available in PATH +# +# Environment variables: +# TRILIUM_ARTIFACT_NAME_HINT: If set, used as the base name for the output file + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +DESKTOP_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +FORGE_DIR="$DESKTOP_DIR/electron-forge" + +ARCH="${1:-x64}" +EXECUTABLE_NAME="trilium" +PRODUCT_NAME="Trilium Notes" + +# Map architecture names +case "$ARCH" in + x64) APPIMAGE_ARCH="x86_64" ;; + arm64) APPIMAGE_ARCH="aarch64" ;; + *) echo "Unsupported architecture: $ARCH"; exit 1 ;; +esac + +# Find the packaged app directory +PACKAGED_DIR="$DESKTOP_DIR/out/$PRODUCT_NAME-linux-$ARCH" +if [ ! -d "$PACKAGED_DIR" ]; then + echo "Error: Packaged app not found at $PACKAGED_DIR" + echo "Run 'electron-forge make' or 'electron-forge package' first." + exit 1 +fi + +echo "Building AppImage from: $PACKAGED_DIR" + +# Create AppDir structure +APPDIR="$DESKTOP_DIR/out/$PRODUCT_NAME.AppDir" +rm -rf "$APPDIR" +mkdir -p "$APPDIR" + +# Copy the packaged app contents into the AppDir +cp -a "$PACKAGED_DIR"/. "$APPDIR/" + +# Create the AppRun entry point +cat > "$APPDIR/AppRun" << 'APPRUN_EOF' +#!/bin/bash +HERE="$(dirname "$(readlink -f "$0")")" +exec "$HERE/trilium" "$@" +APPRUN_EOF +chmod +x "$APPDIR/AppRun" + +# Create the .desktop file +cat > "$APPDIR/$EXECUTABLE_NAME.desktop" << DESKTOP_EOF +[Desktop Entry] +Name=$PRODUCT_NAME +Comment=Build your personal knowledge base with Trilium Notes +GenericName=Note Taking Application +Exec=$EXECUTABLE_NAME %U +Icon=$EXECUTABLE_NAME +Type=Application +StartupNotify=true +StartupWMClass=$PRODUCT_NAME +Categories=Office;Utility; +DESKTOP_EOF + +# Copy the icon (AppImage expects it at the root of AppDir) +if [ -f "$FORGE_DIR/app-icon/png/256x256.png" ]; then + cp "$FORGE_DIR/app-icon/png/256x256.png" "$APPDIR/$EXECUTABLE_NAME.png" +elif [ -f "$APPDIR/icon.png" ]; then + cp "$APPDIR/icon.png" "$APPDIR/$EXECUTABLE_NAME.png" +else + echo "Warning: No icon found" +fi + +# Determine output filename +UPLOAD_DIR="$DESKTOP_DIR/upload" +mkdir -p "$UPLOAD_DIR" + +if [ -n "${TRILIUM_ARTIFACT_NAME_HINT:-}" ]; then + OUTPUT_NAME="${TRILIUM_ARTIFACT_NAME_HINT//\//-}.AppImage" +else + VERSION=$(node -e "console.log(require('$DESKTOP_DIR/package.json').version)") + OUTPUT_NAME="TriliumNotes-v${VERSION}-linux-${ARCH}.AppImage" +fi + +OUTPUT_PATH="$UPLOAD_DIR/$OUTPUT_NAME" + +# Build the AppImage +echo "Creating AppImage: $OUTPUT_PATH" +ARCH="$APPIMAGE_ARCH" appimagetool "$APPDIR" "$OUTPUT_PATH" + +# Clean up the AppDir +rm -rf "$APPDIR" + +echo "AppImage created successfully: $OUTPUT_PATH" From e99cf749883423c5c864580973cefc7e09605c54 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 23:29:27 +0300 Subject: [PATCH 340/482] feat(electron): customizable Electron directory (closes #4192) --- apps/desktop/src/main.ts | 13 +++++++++++++ .../Installation & Setup/Data directory.md | 11 ++++++++++- .../Installation & Setup/Desktop Installation.md | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/apps/desktop/src/main.ts b/apps/desktop/src/main.ts index 3617c4c9f4..6a3ca896ce 100644 --- a/apps/desktop/src/main.ts +++ b/apps/desktop/src/main.ts @@ -101,9 +101,22 @@ async function main() { /** * Returns a unique user data directory for Electron so that single instance locks between legitimately different instances such as different port or data directory can still act independently, but we are focusing the main window otherwise. + * + * When running in portable mode (TRILIUM_DATA_DIR is set), the user data is stored inside the data directory + * so that no files are written to the system's roaming profile (e.g. %APPDATA% on Windows). + * This can be overridden by setting TRILIUM_ELECTRON_DATA_DIR to a custom path. */ function getUserData() { + if (process.env.TRILIUM_ELECTRON_DATA_DIR) { + return process.env.TRILIUM_ELECTRON_DATA_DIR; + } + const name = `${app.getName()}-${port}`; + + if (process.env.TRILIUM_DATA_DIR) { + return join(process.env.TRILIUM_DATA_DIR, "electron-user-data", name); + } + return join(app.getPath("appData"), name); } diff --git a/docs/User Guide/User Guide/Installation & Setup/Data directory.md b/docs/User Guide/User Guide/Installation & Setup/Data directory.md index 3d66bafe90..3a447f82f2 100644 --- a/docs/User Guide/User Guide/Installation & Setup/Data directory.md +++ b/docs/User Guide/User Guide/Installation & Setup/Data directory.md @@ -77,6 +77,14 @@ TRILIUM_DATA_DIR=/home/myuser/data/my-trilium-data trilium You can then save the above command as a shell script on your path for convenience. +## Electron user data directory (desktop only) + +When running the desktop application, Electron stores internal data (caches, spell-check dictionaries, session storage, etc.) separately from the Trilium data directory. By default this goes to the system's application data folder (e.g. `%APPDATA%` on Windows), which may be undesirable in corporate environments with roaming profiles or when running in portable mode. + +When `TRILIUM_DATA_DIR` is set (e.g. via the `trilium-portable` script), the Electron user data is automatically redirected into `${TRILIUM_DATA_DIR}/electron-user-data/`, so no files are written to the system's roaming profile. + +If you need to store the Electron data in a different location than the Trilium data directory, you can set the `TRILIUM_ELECTRON_DATA_DIR` environment variable to an explicit path. + ## Fine-grained directory/path location Apart from the data directory, some of the subdirectories of it can be moved elsewhere by changing an environment variable: @@ -88,4 +96,5 @@ Apart from the data directory, some of the subdirectories of it can be moved els | `TRILIUM_LOG_DIR` | `${TRILIUM_DATA_DIR}/log` | Directory where daily Backend (server) logs are stored. | | `TRILIUM_TMP_DIR` | `${TRILIUM_DATA_DIR}/tmp` | Directory where temporary files are stored (for example when opening in an external app). | | `TRILIUM_ANONYMIZED_DB_DIR` | `${TRILIUM_DATA_DIR}/anonymized-db` | Directory where a Anonymized Database is stored. | -| `TRILIUM_CONFIG_INI_PATH` | `${TRILIUM_DATA_DIR}/config.ini` | Path to Configuration (config.ini or environment variables) file. | \ No newline at end of file +| `TRILIUM_CONFIG_INI_PATH` | `${TRILIUM_DATA_DIR}/config.ini` | Path to Configuration (config.ini or environment variables) file. | +| `TRILIUM_ELECTRON_DATA_DIR` | `${TRILIUM_DATA_DIR}/electron-user-data` (portable) or system appData (default) | Directory where Electron stores internal data such as caches and spell-check dictionaries (desktop only). | diff --git a/docs/User Guide/User Guide/Installation & Setup/Desktop Installation.md b/docs/User Guide/User Guide/Installation & Setup/Desktop Installation.md index c8eb58ee57..b39241c459 100644 --- a/docs/User Guide/User Guide/Installation & Setup/Desktop Installation.md +++ b/docs/User Guide/User Guide/Installation & Setup/Desktop Installation.md @@ -11,7 +11,7 @@ Trilium offers various startup scripts to customize your experience: * `trilium-no-cert-check`: Starts Trilium without validating [TLS certificates](Server%20Installation/HTTPS%20\(TLS\).md), useful if connecting to a server with a self-signed certificate. * Alternatively, set the `NODE_TLS_REJECT_UNAUTHORIZED=0` environment variable before starting Trilium. -* `trilium-portable`: Launches Trilium in portable mode, where the [data directory](Data%20directory.md) is created within the application's directory, making it easy to move the entire setup. +* `trilium-portable`: Launches Trilium in portable mode, where the [data directory](Data%20directory.md) is created within the application's directory, making it easy to move the entire setup. Electron's internal data (caches, dictionaries, etc.) is also stored within the data directory, so no files are written to the system's roaming profile. * `trilium-safe-mode`: Boots Trilium in "safe mode," disabling any startup scripts that might cause the application to crash. ## Synchronization From 1a07dff37359ecffe64d85e8904015dd2c596f67 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 23:29:38 +0300 Subject: [PATCH 341/482] feat(electron): disable terminal from portable mode --- apps/desktop/electron-forge/trilium-portable.bat | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/desktop/electron-forge/trilium-portable.bat b/apps/desktop/electron-forge/trilium-portable.bat index 5b71c9cf2a..6b4610215c 100644 --- a/apps/desktop/electron-forge/trilium-portable.bat +++ b/apps/desktop/electron-forge/trilium-portable.bat @@ -6,7 +6,7 @@ WHERE powershell.exe > NUL 2>&1 IF %ERRORLEVEL% NEQ 0 GOTO BATCH ELSE GOTO POWERSHELL :POWERSHELL -powershell -ExecutionPolicy Bypass -NonInteractive -NoLogo -Command "Set-Item -Path Env:TRILIUM_DATA_DIR -Value './trilium-data'; ./trilium.exe" +powershell -ExecutionPolicy Bypass -NonInteractive -NoLogo -Command "Set-Item -Path Env:TRILIUM_DATA_DIR -Value './trilium-data'; Set-Item -Path Env:ELECTRON_NO_ATTACH_CONSOLE -Value '1'; ./trilium.exe" GOTO END :BATCH @@ -17,6 +17,7 @@ chcp 65001 SET DIR=%~dp0 SET DIR=%DIR:~0,-1% SET TRILIUM_DATA_DIR=%DIR%\trilium-data +SET ELECTRON_NO_ATTACH_CONSOLE=1 cd "%DIR%" start trilium.exe GOTO END From 7d6fd54562b19603519464c832dd11d4f803478c Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 23:32:24 +0300 Subject: [PATCH 342/482] chore(client): fix TODO related to hidden node --- apps/client/src/types-fancytree.d.ts | 2 ++ apps/client/src/widgets/note_tree.ts | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/client/src/types-fancytree.d.ts b/apps/client/src/types-fancytree.d.ts index a8a151b55d..67130be1d2 100644 --- a/apps/client/src/types-fancytree.d.ts +++ b/apps/client/src/types-fancytree.d.ts @@ -269,6 +269,8 @@ declare namespace Fancytree { lazy: boolean; /** Alternative description used as hover banner */ tooltip: string; + /** `
  • ` element wrapping this node. `null` if the node has not been rendered yet. */ + li: HTMLLIElement | null; /** Outer element of single nodes */ span: HTMLElement; /** Outer element of single nodes for table extension */ diff --git a/apps/client/src/widgets/note_tree.ts b/apps/client/src/widgets/note_tree.ts index 5c2aadb1ea..5918fa800b 100644 --- a/apps/client/src/widgets/note_tree.ts +++ b/apps/client/src/widgets/note_tree.ts @@ -1568,8 +1568,9 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { toggleHiddenNode(show: boolean) { const hiddenNode = this.getNodesByNoteId("_hidden")[0]; - // TODO: Check how .li exists here. - $((hiddenNode as any).li).toggleClass("hidden-node-is-hidden", !show); + if (hiddenNode?.li) { + $(hiddenNode.li).toggleClass("hidden-node-is-hidden", !show); + } } async frocaReloadedEvent() { From 65d3224c1a6c16aab7a9446d92d194d308718c38 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 17 Apr 2026 23:47:59 +0300 Subject: [PATCH 343/482] fix(tree): hidden notes appearing on root import (closes #5520) --- apps/client/src/widgets/note_tree.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/client/src/widgets/note_tree.ts b/apps/client/src/widgets/note_tree.ts index 5918fa800b..27af4490ed 100644 --- a/apps/client/src/widgets/note_tree.ts +++ b/apps/client/src/widgets/note_tree.ts @@ -1534,8 +1534,11 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { const hoistedNotePath = await treeService.resolveNotePath(this.noteContext.hoistedNoteId); if (!forceUpdate && this.lastFilteredHoistedNotePath === hoistedNotePath) { - // no need to re-filter if the hoisting did not change - // (helps with flickering on simple note change with large subtrees) + // Hoisting did not change, so skip the expensive re-filter (avoids flickering on + // simple note changes with large subtrees). The hidden-node class must still be + // reapplied — the
  • may have been recreated by a lazy reload (e.g. via + // `getNodeFromPath` → `parentNode.load(true)` after an import into root). + this.toggleHiddenNode(this.noteContext.hoistedNoteId !== "root"); return; } From 77b89c5a01e237aa017fe5d51c877ee54a2a2294 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 02:32:03 +0000 Subject: [PATCH 344/482] chore(deps): update dependency wxt to v0.20.22 --- apps/web-clipper/package.json | 2 +- pnpm-lock.yaml | 38 +++++++++-------------------------- 2 files changed, 10 insertions(+), 30 deletions(-) diff --git a/apps/web-clipper/package.json b/apps/web-clipper/package.json index 82e8ffd6e7..f0d8f93f84 100644 --- a/apps/web-clipper/package.json +++ b/apps/web-clipper/package.json @@ -16,7 +16,7 @@ "packageManager": "pnpm@10.33.0", "devDependencies": { "@wxt-dev/auto-icons": "1.1.1", - "wxt": "0.20.21" + "wxt": "0.20.22" }, "dependencies": { "cash-dom": "8.1.5" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6c1c7168a7..693bc35b0d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -890,10 +890,10 @@ importers: devDependencies: '@wxt-dev/auto-icons': specifier: 1.1.1 - version: 1.1.1(wxt@0.20.21(@types/node@24.12.2)(eslint@10.2.0(jiti@2.6.1))(jiti@2.6.1)(less@4.1.3)(rollup@4.60.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 1.1.1(wxt@0.20.22(@types/node@24.12.2)(eslint@10.2.0(jiti@2.6.1))(jiti@2.6.1)(less@4.1.3)(rollup@4.60.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)) wxt: - specifier: 0.20.21 - version: 0.20.21(@types/node@24.12.2)(eslint@10.2.0(jiti@2.6.1))(jiti@2.6.1)(less@4.1.3)(rollup@4.60.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) + specifier: 0.20.22 + version: 0.20.22(@types/node@24.12.2)(eslint@10.2.0(jiti@2.6.1))(jiti@2.6.1)(less@4.1.3)(rollup@4.60.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) apps/website: dependencies: @@ -10852,9 +10852,6 @@ packages: engines: {node: '>=10'} hasBin: true - mlly@1.7.4: - resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} - mlly@1.8.0: resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} @@ -11656,10 +11653,6 @@ packages: resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} engines: {node: ^10 || ^12 || >=14} - postcss@8.5.8: - resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} - engines: {node: ^10 || ^12 || >=14} - postcss@8.5.9: resolution: {integrity: sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==} engines: {node: ^10 || ^12 || >=14} @@ -14091,8 +14084,8 @@ packages: resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==} engines: {node: '>=20'} - wxt@0.20.21: - resolution: {integrity: sha512-rDocJ9QEWKnGd7NTTTxKIJ5MsXwv9lXk4/ITFS9eeksTCYotshxzAiptkRPEHCgsJNiGMNY/UFNxVDyqWGe7Bw==} + wxt@0.20.22: + resolution: {integrity: sha512-njFI77H0dAbK/bQCN8u8QYiusg6GKDPMtsQDCqIfrh1oGHMHgrMEMgeGOlqAltG9OOGGB1DvFYDzTvxqfEKVKQ==} engines: {bun: '>=1.2.0', node: '>=20.12.0'} hasBin: true peerDependencies: @@ -21569,12 +21562,12 @@ snapshots: optionalDependencies: react: 19.2.4 - '@wxt-dev/auto-icons@1.1.1(wxt@0.20.21(@types/node@24.12.2)(eslint@10.2.0(jiti@2.6.1))(jiti@2.6.1)(less@4.1.3)(rollup@4.60.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))': + '@wxt-dev/auto-icons@1.1.1(wxt@0.20.22(@types/node@24.12.2)(eslint@10.2.0(jiti@2.6.1))(jiti@2.6.1)(less@4.1.3)(rollup@4.60.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))': dependencies: defu: 6.1.6 fs-extra: 11.3.4 sharp: 0.34.5 - wxt: 0.20.21(@types/node@24.12.2)(eslint@10.2.0(jiti@2.6.1))(jiti@2.6.1)(less@4.1.3)(rollup@4.60.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) + wxt: 0.20.22(@types/node@24.12.2)(eslint@10.2.0(jiti@2.6.1))(jiti@2.6.1)(less@4.1.3)(rollup@4.60.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3) '@wxt-dev/browser@0.1.40': dependencies: @@ -25905,7 +25898,7 @@ snapshots: local-pkg@1.1.1: dependencies: - mlly: 1.7.4 + mlly: 1.8.0 pkg-types: 2.3.0 quansync: 0.2.10 @@ -26688,13 +26681,6 @@ snapshots: mkdirp@1.0.4: {} - mlly@1.7.4: - dependencies: - acorn: 8.16.0 - pathe: 2.0.3 - pkg-types: 1.3.1 - ufo: 1.6.1 - mlly@1.8.0: dependencies: acorn: 8.16.0 @@ -27552,12 +27538,6 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - postcss@8.5.8: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - postcss@8.5.9: dependencies: nanoid: 3.3.11 @@ -30403,7 +30383,7 @@ snapshots: is-wsl: 3.1.1 powershell-utils: 0.1.0 - wxt@0.20.21(@types/node@24.12.2)(eslint@10.2.0(jiti@2.6.1))(jiti@2.6.1)(less@4.1.3)(rollup@4.60.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3): + wxt@0.20.22(@types/node@24.12.2)(eslint@10.2.0(jiti@2.6.1))(jiti@2.6.1)(less@4.1.3)(rollup@4.60.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3): dependencies: '@1natsu/wait-element': 4.1.2 '@aklinker1/rollup-plugin-visualizer': 5.12.0(rollup@4.60.1) From 6c2ce8f39cc222868937a1c9b8addbab66eceb00 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 02:32:56 +0000 Subject: [PATCH 345/482] fix(deps): update ai sdk --- apps/server/package.json | 4 ++-- pnpm-lock.yaml | 38 ++++++++++++++------------------------ 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/apps/server/package.json b/apps/server/package.json index 3f5871dfda..14852983f0 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -32,9 +32,9 @@ "dependencies": { "@ai-sdk/anthropic": "3.0.69", "@ai-sdk/google": "3.0.63", - "@ai-sdk/openai": "3.0.52", + "@ai-sdk/openai": "3.0.53", "@modelcontextprotocol/sdk": "^1.12.1", - "ai": "6.0.159", + "ai": "6.0.161", "better-sqlite3": "12.9.0", "html-to-text": "9.0.5", "js-yaml": "4.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6c1c7168a7..5929ba957e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -575,14 +575,14 @@ importers: specifier: 3.0.63 version: 3.0.63(zod@4.3.6) '@ai-sdk/openai': - specifier: 3.0.52 - version: 3.0.52(zod@4.3.6) + specifier: 3.0.53 + version: 3.0.53(zod@4.3.6) '@modelcontextprotocol/sdk': specifier: ^1.12.1 version: 1.29.0(zod@4.3.6) ai: - specifier: 6.0.159 - version: 6.0.159(zod@4.3.6) + specifier: 6.0.161 + version: 6.0.161(zod@4.3.6) better-sqlite3: specifier: 12.9.0 version: 12.9.0 @@ -1482,8 +1482,8 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/gateway@3.0.96': - resolution: {integrity: sha512-BDiVEMUVHGpngReeigzLyJobG0TvzYbNGzdHI8JYBZHrjOX4aL6qwIls7z3p7V4TuXVWUCbG8TSWEe7ksX4Vhw==} + '@ai-sdk/gateway@3.0.98': + resolution: {integrity: sha512-Ol+nP8PIlj8FjN8qKlxhE89N0woqAaGi9CUBGp1boe3RafpphJ7WMuq/RErSvxtwTqje03TP+zIdzP113krxRg==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 @@ -1494,8 +1494,8 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/openai@3.0.52': - resolution: {integrity: sha512-4Rr8NCGmfWTz6DCUvixn9UmyZcMatiHn0zWoMzI3JCUe9R1P/vsPOpCBALKoSzVYOjyJnhtnVIbfUKujcS39uw==} + '@ai-sdk/openai@3.0.53': + resolution: {integrity: sha512-Wld+Rbc05KaUn08uBt06eEuwcgalcIFtIl32Yp+GxuZXUQwOb6YeAuq+C6da4ch6BurFoqEaLemJVwjBb7x+PQ==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 @@ -6766,8 +6766,8 @@ packages: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} - ai@6.0.159: - resolution: {integrity: sha512-S18ozG7Dkm3Ud1tzOtAK5acczD4vygfml80RkpM9VWMFpvAFwAKSHaGYkATvPQHIE+VpD1tJY9zcTXLZ/zR5cw==} + ai@6.0.161: + resolution: {integrity: sha512-ufhmijmx2YyWTPAicGgtpLOB/xD7mG8zKs1pT1Trj+JL/3r1rS8fkMi/cHZoChSAQSGB4pgmcWVxDrVTUvK2IQ==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 @@ -11656,10 +11656,6 @@ packages: resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} engines: {node: ^10 || ^12 || >=14} - postcss@8.5.8: - resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} - engines: {node: ^10 || ^12 || >=14} - postcss@8.5.9: resolution: {integrity: sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==} engines: {node: ^10 || ^12 || >=14} @@ -14262,7 +14258,7 @@ snapshots: '@ai-sdk/provider-utils': 4.0.23(zod@4.3.6) zod: 4.3.6 - '@ai-sdk/gateway@3.0.96(zod@4.3.6)': + '@ai-sdk/gateway@3.0.98(zod@4.3.6)': dependencies: '@ai-sdk/provider': 3.0.8 '@ai-sdk/provider-utils': 4.0.23(zod@4.3.6) @@ -14275,7 +14271,7 @@ snapshots: '@ai-sdk/provider-utils': 4.0.23(zod@4.3.6) zod: 4.3.6 - '@ai-sdk/openai@3.0.52(zod@4.3.6)': + '@ai-sdk/openai@3.0.53(zod@4.3.6)': dependencies: '@ai-sdk/provider': 3.0.8 '@ai-sdk/provider-utils': 4.0.23(zod@4.3.6) @@ -21658,9 +21654,9 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 - ai@6.0.159(zod@4.3.6): + ai@6.0.161(zod@4.3.6): dependencies: - '@ai-sdk/gateway': 3.0.96(zod@4.3.6) + '@ai-sdk/gateway': 3.0.98(zod@4.3.6) '@ai-sdk/provider': 3.0.8 '@ai-sdk/provider-utils': 4.0.23(zod@4.3.6) '@opentelemetry/api': 1.9.0 @@ -27552,12 +27548,6 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - postcss@8.5.8: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - postcss@8.5.9: dependencies: nanoid: 3.3.11 From 036d09f99ee66661e74cb81f5336dd1653e39435 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 02:33:50 +0000 Subject: [PATCH 346/482] fix(deps): update dependency @codemirror/language-data to v6.5.2 --- packages/codemirror/package.json | 2 +- pnpm-lock.yaml | 35 ++++++++++++++++++-------------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/packages/codemirror/package.json b/packages/codemirror/package.json index 6d947aa4c3..c71c2d9255 100644 --- a/packages/codemirror/package.json +++ b/packages/codemirror/package.json @@ -12,7 +12,7 @@ "@codemirror/lang-javascript": "6.2.5", "@codemirror/lang-json": "6.0.2", "@codemirror/lang-markdown": "6.5.0", - "@codemirror/language-data": "6.5.1", + "@codemirror/language-data": "6.5.2", "@codemirror/lang-php": "6.0.2", "@codemirror/lang-vue": "0.1.3", "@codemirror/lang-xml": "6.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6c1c7168a7..290ccfbf85 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1227,8 +1227,8 @@ importers: specifier: 6.1.0 version: 6.1.0 '@codemirror/language-data': - specifier: 6.5.1 - version: 6.5.1 + specifier: 6.5.2 + version: 6.5.2 '@codemirror/legacy-modes': specifier: 6.5.2 version: 6.5.2 @@ -2032,6 +2032,9 @@ packages: '@codemirror/lang-javascript@6.2.5': resolution: {integrity: sha512-zD4e5mS+50htS7F+TYjBPsiIFGanfVqg4HyUz6WNFikgOPf2BgKlx+TQedI1w6n/IqRBVBbBWmGFdLB/7uxO4A==} + '@codemirror/lang-jinja@6.0.1': + resolution: {integrity: sha512-P5kyHLObzjtbGj16h+hyvZTxJhSjBEeSx4wMjbnAf3b0uwTy2+F0zGjMZL4PQOm/mh2eGZ5xUDVZXgwP783Nsw==} + '@codemirror/lang-json@6.0.2': resolution: {integrity: sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==} @@ -2074,8 +2077,8 @@ packages: '@codemirror/lang-yaml@6.1.3': resolution: {integrity: sha512-AZ8DJBuXGVHybpBQhmZtgew5//4hv3tdkXnr3vDmOUMJRuB6vn/uuwtmTOTlqEaQFg3hQSVeA90NmvIQyUV6FQ==} - '@codemirror/language-data@6.5.1': - resolution: {integrity: sha512-0sWxeUSNlBr6OmkqybUTImADFUP0M3P0IiSde4nc24bz/6jIYzqYSgkOSLS+CBIoW1vU8Q9KUWXscBXeoMVC9w==} + '@codemirror/language-data@6.5.2': + resolution: {integrity: sha512-CPkWBKrNS8stYbEU5kwBwTf3JB1kghlbh4FSAwzGW2TEscdeHHH4FGysREW86Mqnj3Qn09s0/6Ea/TutmoTobg==} '@codemirror/language@6.12.3': resolution: {integrity: sha512-QwCZW6Tt1siP37Jet9Tb02Zs81TQt6qQrZR2H+eGMcFsL1zMrk2/b9CLC7/9ieP1fjIUMgviLWMmgiHoJrj+ZA==} @@ -11656,10 +11659,6 @@ packages: resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} engines: {node: ^10 || ^12 || >=14} - postcss@8.5.8: - resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} - engines: {node: ^10 || ^12 || >=14} - postcss@8.5.9: resolution: {integrity: sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==} engines: {node: ^10 || ^12 || >=14} @@ -15573,6 +15572,17 @@ snapshots: '@lezer/common': 1.5.2 '@lezer/javascript': 1.5.1 + '@codemirror/lang-jinja@6.0.1': + dependencies: + '@codemirror/autocomplete': 6.18.6 + '@codemirror/lang-html': 6.4.11 + '@codemirror/language': 6.12.3 + '@codemirror/state': 6.6.0 + '@codemirror/view': 6.41.0 + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.2 + '@codemirror/lang-json@6.0.2': dependencies: '@codemirror/language': 6.12.3 @@ -15690,7 +15700,7 @@ snapshots: '@lezer/lr': 1.4.2 '@lezer/yaml': 1.0.4 - '@codemirror/language-data@6.5.1': + '@codemirror/language-data@6.5.2': dependencies: '@codemirror/lang-angular': 0.1.4 '@codemirror/lang-cpp': 6.0.3 @@ -15699,6 +15709,7 @@ snapshots: '@codemirror/lang-html': 6.4.11 '@codemirror/lang-java': 6.0.2 '@codemirror/lang-javascript': 6.2.5 + '@codemirror/lang-jinja': 6.0.1 '@codemirror/lang-json': 6.0.2 '@codemirror/lang-less': 6.0.2 '@codemirror/lang-liquid': 6.3.2 @@ -27552,12 +27563,6 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - postcss@8.5.8: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - postcss@8.5.9: dependencies: nanoid: 3.3.11 From 84d46c0a293e1afc90d14a3927911d103ec4e84f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 02:34:41 +0000 Subject: [PATCH 347/482] fix(deps): update dependency react-i18next to v17.0.3 --- apps/client/package.json | 2 +- apps/website/package.json | 2 +- pnpm-lock.yaml | 24 +++++++----------------- 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/apps/client/package.json b/apps/client/package.json index 0978d1b745..8f0026fbf9 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -66,7 +66,7 @@ "mind-elixir": "5.10.0", "panzoom": "9.4.4", "preact": "10.29.1", - "react-i18next": "17.0.2", + "react-i18next": "17.0.3", "react-window": "2.2.7", "reveal.js": "6.0.1", "rrule": "2.8.1", diff --git a/apps/website/package.json b/apps/website/package.json index e0f95b7596..8d6267f184 100644 --- a/apps/website/package.json +++ b/apps/website/package.json @@ -13,7 +13,7 @@ "preact": "10.29.1", "preact-iso": "2.11.1", "preact-render-to-string": "6.6.7", - "react-i18next": "17.0.2" + "react-i18next": "17.0.3" }, "devDependencies": { "@preact/preset-vite": "2.10.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6c1c7168a7..f6130f62e0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -358,8 +358,8 @@ importers: specifier: 10.29.1 version: 10.29.1 react-i18next: - specifier: 17.0.2 - version: 17.0.2(i18next@26.0.4(typescript@6.0.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@6.0.2) + specifier: 17.0.3 + version: 17.0.3(i18next@26.0.4(typescript@6.0.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@6.0.2) react-window: specifier: 2.2.7 version: 2.2.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -910,8 +910,8 @@ importers: specifier: 6.6.7 version: 6.6.7(preact@10.29.1) react-i18next: - specifier: 17.0.2 - version: 17.0.2(i18next@26.0.4(typescript@6.0.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@6.0.2) + specifier: 17.0.3 + version: 17.0.3(i18next@26.0.4(typescript@6.0.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@6.0.2) devDependencies: '@preact/preset-vite': specifier: 2.10.5 @@ -11656,10 +11656,6 @@ packages: resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} engines: {node: ^10 || ^12 || >=14} - postcss@8.5.8: - resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} - engines: {node: ^10 || ^12 || >=14} - postcss@8.5.9: resolution: {integrity: sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==} engines: {node: ^10 || ^12 || >=14} @@ -11887,8 +11883,8 @@ packages: peerDependencies: react: ^19.2.4 - react-i18next@17.0.2: - resolution: {integrity: sha512-shBftH2vaTWK2Bsp7FiL+cevx3xFJlvFxmsDFQSrJc+6twHkP0tv/bGa01VVWzpreUVVwU+3Hev5iFqRg65RwA==} + react-i18next@17.0.3: + resolution: {integrity: sha512-x4xjvUNZ56T+zfXWNedNnCET9Xq1IBYWX7IsWo5cCQ/RT+Rm7GWqt0h9PShFi4IhyMnsdiu1C6Jc4DE+/S3PFQ==} peerDependencies: i18next: '>= 26.0.1' react: '>= 16.8.0' @@ -27552,12 +27548,6 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - postcss@8.5.8: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - postcss@8.5.9: dependencies: nanoid: 3.3.11 @@ -27801,7 +27791,7 @@ snapshots: react: 19.2.4 scheduler: 0.27.0 - react-i18next@17.0.2(i18next@26.0.4(typescript@6.0.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@6.0.2): + react-i18next@17.0.3(i18next@26.0.4(typescript@6.0.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@6.0.2): dependencies: '@babel/runtime': 7.29.2 html-parse-stringify: 3.0.1 From a9e7cd7bfead66432f21171944179fd0c1d67582 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 02:36:22 +0000 Subject: [PATCH 348/482] chore(deps): update dependency officeparser to v6.1.0 --- apps/server/package.json | 2 +- pnpm-lock.yaml | 52 +++++++++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/apps/server/package.json b/apps/server/package.json index 3f5871dfda..6cefc7f673 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -114,7 +114,7 @@ "mime-types": "3.0.2", "multer": "2.1.1", "normalize-strings": "1.1.1", - "officeparser": "6.0.7", + "officeparser": "6.1.0", "rand-token": "1.0.1", "safe-compare": "1.1.4", "sanitize-filename": "1.6.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6c1c7168a7..f485d949ee 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -816,8 +816,8 @@ importers: specifier: 1.1.1 version: 1.1.1 officeparser: - specifier: 6.0.7 - version: 6.0.7(encoding@0.1.13) + specifier: 6.1.0 + version: 6.1.0(encoding@0.1.13) rand-token: specifier: 1.0.1 version: 1.0.1 @@ -6674,6 +6674,10 @@ packages: resolution: {integrity: sha512-9k/gHF6n/pAi/9tqr3m3aqkuiNosYTurLLUtc7xQ9sxB/wm7WPygCv8GYa6mS0fLJEHhqMC1ATYhz++U/lRHqg==} engines: {node: '>=10.0.0'} + '@xmldom/xmldom@0.9.9': + resolution: {integrity: sha512-qycIHAucxy/LXAYIjmLmtQ8q9GPnMbnjG1KXhWm9o5sCr6pOYDATkMPiTNa6/v8eELyqOQ2FsEqeoFYmgv/gJg==} + engines: {node: '>=14.6'} + '@xtuc/ieee754@1.2.0': resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} @@ -8821,6 +8825,10 @@ packages: resolution: {integrity: sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g==} engines: {node: '>=20'} + file-type@22.0.1: + resolution: {integrity: sha512-ww5Mhre0EE+jmBvOXTmXAbEMuZE7uX4a3+oRCQFNj8w++g3ev913N6tXQz0XTXbueQ5TWQfm6BdaViEHHn8bhA==} + engines: {node: '>=22'} + file-uri-to-path@1.0.0: resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} @@ -11193,8 +11201,8 @@ packages: ofetch@1.5.1: resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==} - officeparser@6.0.7: - resolution: {integrity: sha512-MkNHyWIfEZRDtB8c0fgJHdb4Ui0I/WztBjlUjlPiEbTO6dIYaJMt+llS5p5Foj13guUZgGxkkM9VwsVRthHNAA==} + officeparser@6.1.0: + resolution: {integrity: sha512-S/dMjUyhbeyDNUjnuGKsmuDx3IoOTcyy6uFzZ6321paaF5NVQVS+Ht8SkQEzEQ85DJ256LnTroMTP2PVKebX1Q==} engines: {node: '>=18.0.0'} hasBin: true @@ -11656,10 +11664,6 @@ packages: resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} engines: {node: ^10 || ^12 || >=14} - postcss@8.5.8: - resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} - engines: {node: ^10 || ^12 || >=14} - postcss@8.5.9: resolution: {integrity: sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==} engines: {node: ^10 || ^12 || >=14} @@ -13425,6 +13429,10 @@ packages: resolution: {integrity: sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ==} engines: {node: '>=18'} + uint8array-extras@1.5.0: + resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} + engines: {node: '>=18'} + ulid@2.4.0: resolution: {integrity: sha512-fIRiVTJNcSRmXKPZtGzFQv9WRrZ3M9eoptl/teFJvjOzmpU+/K/JH6HZ8deBfb5vMEpicJcLn7JmvdknlMq7Zg==} hasBin: true @@ -21589,6 +21597,8 @@ snapshots: '@xmldom/xmldom@0.8.12': {} + '@xmldom/xmldom@0.9.9': {} + '@xtuc/ieee754@1.2.0': {} '@xtuc/long@4.2.2': {} @@ -24283,6 +24293,15 @@ snapshots: transitivePeerDependencies: - supports-color + file-type@22.0.1: + dependencies: + '@tokenizer/inflate': 0.4.1 + strtok3: 10.3.5 + token-types: 6.1.2 + uint8array-extras: 1.5.0 + transitivePeerDependencies: + - supports-color + file-uri-to-path@1.0.0: {} file-uri-to-path@2.0.0: {} @@ -27069,14 +27088,13 @@ snapshots: node-fetch-native: 1.6.7 ufo: 1.6.1 - officeparser@6.0.7(encoding@0.1.13): + officeparser@6.1.0(encoding@0.1.13): dependencies: - '@xmldom/xmldom': 0.8.12 - concat-stream: 2.0.0 - file-type: 21.3.4 + '@xmldom/xmldom': 0.9.9 + fflate: 0.8.2 + file-type: 22.0.1 pdfjs-dist: 5.6.205 tesseract.js: 7.0.0(encoding@0.1.13) - yauzl: 3.3.0 transitivePeerDependencies: - encoding - supports-color @@ -27552,12 +27570,6 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - postcss@8.5.8: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - postcss@8.5.9: dependencies: nanoid: 3.3.11 @@ -29637,6 +29649,8 @@ snapshots: uint8array-extras@1.4.0: {} + uint8array-extras@1.5.0: {} + ulid@2.4.0: {} ulid@3.0.2: {} From e5daa75cb4586f60d51133da74fa3e3de85dbff5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 02:36:30 +0000 Subject: [PATCH 349/482] chore(deps): update node.js to v24.15.0 --- .nvmrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nvmrc b/.nvmrc index 045200741c..eefb690f4a 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -24.14.1 \ No newline at end of file +24.15.0 \ No newline at end of file From a617b597656a22f142299a8bbde88f901af3e84b Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 09:26:50 +0300 Subject: [PATCH 350/482] fix(print): text notes would override custom font --- apps/client/src/print.css | 11 +- .../Notes/Printing & Exporting as PDF.html | 27 +- .../Note types with split view.html | 18 +- .../Installation & Setup/Data directory.html | 23 ++ .../Desktop Installation.html | 4 +- .../en/User Guide/User Guide/Note Types.html | 190 +++++----- .../User Guide/Note Types/File.html | 37 +- .../User Guide/Note Types/Markdown.html | 88 ++--- .../Note Types/Mermaid Diagrams.html | 34 +- .../User Guide/Note Types/Render Note.html | 30 +- .../User Guide/Note Types/Spreadsheets.html | 8 +- .../User Guide/Note Types/Text.html | 333 +++++++++--------- .../Developer Guide/Documentation.md | 2 +- docs/User Guide/!!!meta.json | 141 ++++---- .../Notes/Printing & Exporting as PDF.md | 6 +- .../Installation & Setup/Data directory.md | 2 +- .../User Guide/Note Types/Markdown.md | 7 +- 17 files changed, 472 insertions(+), 489 deletions(-) diff --git a/apps/client/src/print.css b/apps/client/src/print.css index d0123c810e..b08ae29c36 100644 --- a/apps/client/src/print.css +++ b/apps/client/src/print.css @@ -1,8 +1,8 @@ @import "boxicons/css/boxicons.min.css"; :root { + --print-font-family: sans-serif; --print-font-size: 11pt; - --ck-content-color-image-caption-background: transparent !important; } @page { @@ -14,6 +14,7 @@ body { width: 100%; height: 100%; color: black; + font-family: var(--print-font-family); } .note-list-widget.full-height, @@ -26,6 +27,12 @@ body { } body[data-note-type="text"] .ck-content { + --ck-content-font-family: var(--print-font-family); + --ck-content-font-size: var(--print-font-size); + --ck-content-font-color: black; + --ck-content-line-height: 1.5; + --ck-content-color-image-caption-background: transparent; + font-size: var(--print-font-size); text-align: justify; } @@ -154,4 +161,4 @@ span[style] { .page-break::after { display: none !important; } -/* #endregion */ \ No newline at end of file +/* #endregion */ diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.html index 3083d72a84..cae0118ea7 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.html @@ -61,7 +61,8 @@ class="admonition note">
    • To print in landscape mode instead of portrait (useful for big diagrams or slides), add #printLandscape.
    • -
    • By default, the resulting PDF will be in Letter format. It is possible +
    • By default, the resulting PDF will be in Letter format. It is possible to adjust it to another page size via the #printPageSize attribute, with one of the following values: A0,
      1. First create a collection.
      2. Configure it to use List View.
      3. -
      4. Print the collection note normally.
      5. +
      6. Print the collection note normally.

      The resulting collection will contain all the children of the collection, while maintaining the hierarchy.

      @@ -100,9 +102,9 @@ class="admonition note"> href="#root/_help_4TIF1oA4VQRO">Options and assigning a key combination for:

        -
      • Print Active Note +
      • Print Active Note
      • -
      • Export Active Note as PDF +
      • Export Active Note as PDF

      Constraints & limitations

      @@ -165,19 +167,20 @@ class="admonition note"> class="reference-link" href="#root/_help_KC1HB96bqqHX">Templates.

    For example, to change the font of the document from the one defined by - the theme or the user to a serif one:

    body {
    -	--main-font-family: serif !important;
    -    --detail-font-family: var(--main-font-family) !important;
    +    the theme or the user to a serif one:

    :root {
    +	--print-font-family: serif;
    +    --print-font-size: 11pt;
     }

    To remark:

    • Multiple CSS notes can be add by using multiple ~printCss relations.
    • -
    • If the note pointing to the printCss doesn't +
    • If the note pointing to the printCss doesn't have the right note type or mime type, it will be ignored.
    • -
    • If migrating from a previous version where Custom app-wide CSS, there's no need for - @media print { since the style-sheet is used only for printing.
    • +
    • If migrating from a previous version where Custom app-wide CSS, there's no need for + @media print { since the style-sheet is used only for printing.

    Under the hood

    Both printing and exporting as PDF use the same mechanism: a note is rendered diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note types with split view.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note types with split view.html index 0f3b39ee11..605062dcaa 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note types with split view.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note types with split view.html @@ -1,8 +1,8 @@ -

    Split view is a feature of Mermaid Diagrams and  +

    Split view is a feature of Mermaid Diagrams and  Markdown notes which displays both the source code on one side + class="reference-link" href="#root/_help_6RM1Q7ppFVoj">Markdown notes which displays both the source code on one side and the preview of the content on the other.

    -

    Mermaid Diagrams also +

    Mermaid Diagrams also allow changing between a horizontal or a vertical split, to accommodate for the various sizes of diagrams.

    Display modes and interaction

    @@ -20,12 +20,12 @@
  • Preview which displays only the rendering of the diagram or text in full screen, especially useful for read-only notes.
  • -

    These buttons can be found near the Note buttons section - on the New Layout, - or in the Floating buttons on +

    These buttons can be found near the Note buttons section + on the New Layout, + or in the Floating buttons on the old layout.

    The display node is stored at note level.

    Relation to read-only notes

    -

    If a note is marked as read-only, - the source view will not be editable. While in preview mode, marking a - note as read-only has no effect since the preview itself is not editable.

    \ No newline at end of file +

    If a note is marked as read-only, the + source view will not be editable. While in preview mode, marking a note + as read-only has no effect since the preview itself is not editable.

    \ No newline at end of file diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Data directory.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Data directory.html index fbd042717a..ecd52a4302 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Data directory.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Data directory.html @@ -70,6 +70,21 @@ this:

    TRILIUM_DATA_DIR=/home/myuser/data/my-trilium-data trilium

    You can then save the above command as a shell script on your path for convenience.

    +

    Electron user data directory (desktop only)

    +

    When running the desktop application, Electron stores internal data (caches, + spell-check dictionaries, session storage, etc.) separately from the Trilium + data directory. By default this goes to the system's application data folder + (e.g. %APPDATA% on Windows), which may be + undesirable in corporate environments with roaming profiles or when running + in portable mode.

    +

    When TRILIUM_DATA_DIR is set (e.g. via the + trilium-portablescript), the Electron user data is automatically + redirected into ${TRILIUM_DATA_DIR}/electron-user-data/, + so no files are written to the system's roaming profile.

    +

    If you need to store the Electron data in a different location than the + Trilium data directory, you can set the TRILIUM_ELECTRON_DATA_DIR environment + variable to an explicit path.

    Fine-grained directory/path location

    Apart from the data directory, some of the subdirectories of it can be moved elsewhere by changing an environment variable:

    @@ -129,5 +144,13 @@ Path to Configuration (config.ini or environment variables) file. + + TRILIUM_ELECTRON_DATA_DIR + + ${TRILIUM_DATA_DIR}/electron-user-data (portable) + or system appData (default) + Directory where Electron stores internal data such as caches and spell-check + dictionaries (desktop only). + \ No newline at end of file diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Desktop Installation.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Desktop Installation.html index 40d7ddd89c..e1ea2fc9b7 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Desktop Installation.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Desktop Installation.html @@ -23,7 +23,9 @@
  • trilium-portable: Launches Trilium in portable mode, where the data directory is created within the application's directory, making it easy to move the - entire setup.
  • + entire setup. Electron's internal data (caches, dictionaries, etc.) is + also stored within the data directory, so no files are written to the system's + roaming profile.
  • trilium-safe-mode: Boots Trilium in "safe mode," disabling any startup scripts that might cause the application to crash.
  • diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types.html index 2607200081..d468c589c9 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types.html @@ -9,8 +9,7 @@ note where to place the new one and select:

    • Insert note after, to put the new note underneath the one selected.
    • -
    • Insert child note, to insert the note as a child of the selected +
    • Insert child note, to insert the note as a child of the selected note.

    @@ -21,8 +20,7 @@

  • When adding a link in a Text note, type the desired title of the new note and press Enter. Afterwards the type of the note will be asked.
  • -
  • Similarly, when creating a new tab, type the desired title and press Enter.
  • +
  • Similarly, when creating a new tab, type the desired title and press Enter.
  • Changing the type of a note

    It is possible to change the type of a note after it has been created @@ -32,96 +30,94 @@ edit the source of a note.

    Supported note types

    The following note types are supported by Trilium:

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Note TypeDescription
    Text - The default note type, which allows for rich text formatting, images, - admonitions and right-to-left support.
    Code - Uses a mono-space font and can be used to store larger chunks of code - or plain text than a text note, and has better syntax highlighting.
    Saved Search - Stores the information about a search (the search text, criteria, etc.) - for later use. Can be used for quick filtering of a large amount of notes, - for example. The search can easily be triggered.
    Relation Map - Allows easy creation of notes and relations between them. Can be used - for mainly relational data such as a family tree.
    Note Map - Displays the relationships between the notes, whether via relations or - their hierarchical structure.
    Render Note - Used in Scripting, - it displays the HTML content of another note. This allows displaying any - kind of content, provided there is a script behind it to generate it.
    Collections - Displays the children of the note either as a grid, a list, or for a more - specialized case: a calendar.   -
    -
    Generally useful for easy reading of short notes.
    Mermaid Diagrams - Displays diagrams such as bar charts, flow charts, state diagrams, etc. - Requires a bit of technical knowledge since the diagrams are written in - a specialized format.
    Canvas - Allows easy drawing of sketches, diagrams, handwritten content. Uses the - same technology behind excalidraw.com.
    Web View - Displays the content of an external web page, similar to a browser.
    Mind Map - Easy for brainstorming ideas, by placing them in a hierarchical layout.
    Geo Map - Displays the children of the note as a geographical map, one use-case - would be to plan vacations. It even has basic support for tracks. Notes - can also be created from it.
    File - Represents an uploaded file such as PDFs, images, video or audio files.
    -
    \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Note TypeDescription
    Text + The default note type, which allows for rich text formatting, images, + admonitions and right-to-left support.
    Code + Uses a mono-space font and can be used to store larger chunks of code + or plain text than a text note, and has better syntax highlighting.
    Saved Search + Stores the information about a search (the search text, criteria, etc.) + for later use. Can be used for quick filtering of a large amount of notes, + for example. The search can easily be triggered.
    Relation Map + Allows easy creation of notes and relations between them. Can be used + for mainly relational data such as a family tree.
    Note Map + Displays the relationships between the notes, whether via relations or + their hierarchical structure.
    Render Note + Used in Scripting, + it displays the HTML content of another note. This allows displaying any + kind of content, provided there is a script behind it to generate it.
    Collections + Displays the children of the note either as a grid, a list, or for a more + specialized case: a calendar.   +
    +
    Generally useful for easy reading of short notes.
    Mermaid Diagrams + Displays diagrams such as bar charts, flow charts, state diagrams, etc. + Requires a bit of technical knowledge since the diagrams are written in + a specialized format.
    Canvas + Allows easy drawing of sketches, diagrams, handwritten content. Uses the + same technology behind excalidraw.com.
    Web View + Displays the content of an external web page, similar to a browser.
    Mind Map + Easy for brainstorming ideas, by placing them in a hierarchical layout.
    Geo Map + Displays the children of the note as a geographical map, one use-case + would be to plan vacations. It even has basic support for tracks. Notes + can also be created from it.
    File + Represents an uploaded file such as PDFs, images, video or audio files.
    \ No newline at end of file diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/File.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/File.html index 152140d5ed..f64ba7eade 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/File.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/File.html @@ -5,8 +5,7 @@ create a File note type directly:

    • Drag a file into the Note Tree.
    • -
    • Right click a note and select Import into note and point it to +
    • Right click a note and select Import into note and point it to one of the supported files.

    Supported file types

    @@ -83,30 +82,28 @@ href="#root/_help_BlN9DFI679QC">Ribbon.
    • Download, which will download the file for local use.
    • -
    • Open, will will open the file with the system-default application.
    • -
    • Upload new revision to replace the file with a new one.
    • +
    • Open, will will open the file with the system-default application.
    • +
    • Upload new revision to replace the file with a new one.
    -
  • -
  • It is not possible to change the note type of a File note.
  • -
  • Convert into an attachment from the note menu.
  • + +
  • It is not possible to change the note type of a File note.
  • +
  • Convert into an attachment from the note menu.
  • Relation with other notes

    • Files are also displayed in the Note List based on their type:

      -

      - -

      + +
    • +
    • +

      Non-image files can be embedded into text notes as read-only widgets via + the Include Note functionality.

      +
    • +
    • +

      Image files can be embedded into text notes like normal images via  + Image references.

    • -
    • Non-image files can be embedded into text notes as read-only widgets via - the Include Note functionality.
    • -
    • Image files can be embedded into text notes like normal images via  - Image references.
    \ No newline at end of file diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Markdown.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Markdown.html index 74cf113776..2d3d41e7f9 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Markdown.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Markdown.html @@ -1,13 +1,12 @@ -

    Trilium has always supported Markdown through its import feature, +

    Trilium has always supported Markdown through its import feature, however the file was either transformed to a Text note - (converted to Trilium's internal HTML format) or saved as a Code note + href="#root/_help_iPIMuisry3hd">Text note (converted to Trilium's internal + HTML format) or saved as a Code note with only syntax highlight.

    This note type is a split view, meaning that both the source code and a preview of the document are displayed side-by-side. See Note types with split view for - more information.

    + href="#root/_help_SL5f1Auq7sVN">Note types with split view for more + information.

    Rationale

    The goal of this note type is to fill a gap: rendering Markdown but not altering its structure or its whitespace which would inevitably change @@ -33,65 +32,53 @@

    The following features are supported by Trilium's Markdown format and will show up in the preview pane:

      -
    • All standard and GitHub-flavored syntax (basic formatting, tables, blockquotes)
    • -
    • Code blocks with syntax highlight (e.g. ```js) - and automatic syntax highlight
    • -
    • Block quotes & admonitions -
    • -
    • Math Equations -
    • -
    • Mermaid Diagrams using - ```mermaid -
    • -
    • -

      Include Note (no - builtin Markdown syntax, but HTML syntax works just fine):

      <section class="include-note" data-note-id="vJDjQm0VK8Na" data-box-size="expandable">
      -	&nbsp;
      +  
    • +

      All standard and GitHub-flavored syntax (basic formatting, tables, blockquotes)

      +
    • +
    • +

      Code blocks with syntax highlight (e.g. <!--CODE_BLOCK_1776493385878_0-->mermaid +

      +
    • +
    • +

      Include Note (no + builtin Markdown syntax, but HTML syntax works just fine):

      <section class="include-note" data-note-id="vJDjQm0VK8Na" data-box-size="expandable">
      +    &nbsp;
       </section>n
      -
    • -
    • -

      Internal (reference) links via - its HTML syntax, or through a Wikilinks-like format (only  - Note ID):

      [[Hg8TS5ZOxti6]]
      -
    • +
    • +
    • +

      Internal (reference) links via + its HTML syntax, or through a Wikilinks-like format (only  + Note ID):

      [[Hg8TS5ZOxti6]]
      +

    Creating Markdown notes

    There are two ways to create a Markdown note:

      -
    1. Create a new note (e.g. in the Note Tree) +
    2. Create a new note (e.g. in the Note Tree) and select the type Markdown, just like all the other note types.
    3. -
    4. Create a note of type Code and - select as the language either Markdown or GitHub-Flavored Markdown. +
    5. Create a note of type Code and + select as the language either Markdown or GitHub-Flavored Markdown. This maintains compatibility with your existing notes prior to the introduction of this feature.

    Import/export

    • By default, when importing a single Markdown file it automatically gets - converted to a Text note. + converted to a Text note. To avoid that and have it imported as a Markdown note instead:

        -
      • -

        Right click the Note Tree and - select Import into note.

        -
      • -
      • -

        Select the file normally.

        -
      • -
      • -

        Uncheck Import HTML, Markdown and TXT as text notes if it's unclear from the metadata.

        -
      • +
      • Right click the Note Tree and + select Import into note.
      • +
      • Select the file normally.
      • +
      • Uncheck Import HTML, Markdown and TXT as text notes if it's unclear from the metadata.
    • @@ -105,9 +92,8 @@

    Conversion between text notes and Markdown notes

    Currently there is no built-in functionality to convert a Text note - into a Markdown note or vice-versa. We do have plans to address this in - the future.

    + href="#root/_help_iPIMuisry3hd">Text note into a Markdown note or vice-versa. + We do have plans to address this in the future.

    This can be achieved manually, for a single note:

    1. Export the file as Markdown, with single format.
    2. @@ -135,6 +121,6 @@

      This feature of synchronizing the scroll is based on blocks but it's provided on a best-effort basis since our underlying Markdown library doesn't support this feature natively, so we had to implement our own algorithm. Feel free - to report issues, - but always provide a sample Markdown file to be able to reproduce it.

      + to report issues, but always provide a + sample Markdown file to be able to reproduce it.

      \ No newline at end of file diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams.html index d6ff44cd93..a17a7ea0a8 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams.html @@ -12,8 +12,8 @@ the diagram.

      This note type is a split view, meaning that both the source code and a preview of the document are displayed side-by-side. See Note types with split view for - more information.

      + href="#root/_help_SL5f1Auq7sVN">Note types with split view for more + information.

      Sample diagrams

      Starting with v0.103.0, Mermaid diagrams no longer start with a sample flowchart, but instead a pane at the bottom will show all the supported @@ -52,34 +52,30 @@

    3. The preview can be moved around by holding the left mouse button and dragging.
    4. -
    5. Zooming can also be done by using the scroll wheel.
    6. -
    7. The zoom and position on the preview will remain fixed as the diagram - changes, to be able to work more easily with large diagrams.
    8. - +
    9. Zooming can also be done by using the scroll wheel.
    10. +
    11. The zoom and position on the preview will remain fixed as the diagram + changes, to be able to work more easily with large diagrams.
    12. +
    13. The size of the source/preview panes can be adjusted by hovering over the border between them and dragging it with the mouse.
    14. In the Floating buttons area:
      • The source/preview can be laid out left-right or bottom-top via the Move editing pane to the left / bottom option.
      • -
      • Press Lock editing to automatically mark the note as read-only. +
      • Press Lock editing to automatically mark the note as read-only. In this mode, the code pane is hidden and the diagram is displayed full-size. Similarly, press Unlock editing to mark a read-only note as editable.
      • -
      • Press the Copy image reference to the clipboard to be able to insert - the image representation of the diagram into a text note. See Image references for more information.
      • -
      • Press the Export diagram as SVG to download a scalable/vector rendering - of the diagram. Can be used to present the diagram without degrading when - zooming.
      • +
      • Press the Copy image reference to the clipboard to be able to insert + the image representation of the diagram into a text note. See Image references for more information.
      • +
      • Press the Export diagram as SVG to download a scalable/vector rendering + of the diagram. Can be used to present the diagram without degrading when + zooming.
      • Press the Export diagram as PNG to download a normal image (at 1x scale, raster) of the diagram. Can be used to send the diagram in more traditional channels such as e-mail.
      • -
      -
    15. + +

      Errors in the diagram

      If there is an error in the source code, the error will be displayed in diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Render Note.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Render Note.html index 4a33c30bfe..efff5c09b9 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Render Note.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Render Note.html @@ -13,13 +13,11 @@

      1. HTML language for the legacy/vanilla method, with what needs to be displayed (for example <p>Hello world.</p>).
      2. -
      3. JSX for the Preact-based approach (see below).
      4. -
      +
    16. JSX for the Preact-based approach (see below).
    17. +
  • Create a Render Note.
  • -
  • Assign the renderNote relation to +
  • Assign the renderNote relation to point at the previously created code note.
  • Legacy scripting using jQuery

    @@ -48,9 +46,10 @@ $dateEl.text(new Date());
    need to provide a HTML anymore.

    Here are the steps to creating a simple render note:

      -
    1. Create a note of type Render Note.
    2. -
    3. +
    4. +

      Create a note of type Render Note.

      +
    5. +
    6. Create a child Code note with JSX as the language.
      As an example, use the following content:

      export default function() {
      @@ -60,17 +59,20 @@ $dateEl.text(new Date());
      </> ); }
      -
    7. -
    8. In the parent render note, define a ~renderNote relation - pointing to the newly created child.
    9. -
    10. Refresh the render note and it should display a “Hello world” message.
    11. + +
    12. +

      In the parent render note, define a ~renderNote relation + pointing to the newly created child.

      +
    13. +
    14. +

      Refresh the render note and it should display a “Hello world” message.

      +

    Refreshing the note

    It's possible to refresh the note via:

    Examples

    diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Spreadsheets.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Spreadsheets.html index 06f944a848..b9ab252d4c 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Spreadsheets.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Spreadsheets.html @@ -64,9 +64,8 @@ yet:

    • Trilium-specific formulas (e.g. to obtain the title of a note).
    • -
    • User-defined formulas
    • -
    • Cross-workbook calculation
    • +
    • User-defined formulas
    • +
    • Cross-workbook calculation

    If you would like us to work on these features, consider supporting us.

    Known limitations

    @@ -81,8 +80,7 @@
  • There is currently no export functionality, as stated previously.
  • -
  • There is no dedicated mobile support. Mobile support is currently experimental +
  • There is no dedicated mobile support. Mobile support is currently experimental in Univer and when it becomes stable, we could potentially integrate it into Trilium as well.
  • \ No newline at end of file diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text.html index 26a0791ace..42dbe0fa44 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text.html @@ -20,171 +20,168 @@

    Fore more information see Formatting toolbar.

    Features and formatting

    Here's a list of various features supported by text notes:

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Dedicated articleFeature
    General formatting - -
      -
    • Headings (section titles, paragraph)
    • -
    • Font size
    • -
    • Bold, italic, underline, strike-through
    • -
    • Superscript, subscript
    • -
    • Font color & background color
    • -
    • Remove formatting
    • -
    -
    Lists - -
      -
    • Bulleted lists
    • -
    • Numbered lists
    • -
    • To-do lists
    • -
    -
    Block quotes & admonitions - -
      -
    • Block quotes
    • -
    • Admonitions
    • -
    -
    Tables - -
      -
    • Basic tables
    • -
    • Merging cells
    • -
    • Styling tables and cells.
    • -
    • Table captions
    • -
    -
    Developer-specific formatting - -
      -
    • Inline code
    • -
    • Code blocks
    • -
    • Keyboard shortcuts
    • -
    -
    Footnotes - -
      -
    • Footnotes
    • -
    -
    Images - -
      -
    • Images
    • -
    -
    Links - -
      -
    • External links
    • -
    • Internal Trilium links
    • -
    -
    Include Note - -
      -
    • Include note
    • -
    -
    Insert buttons - -
      -
    • Symbols
    • -
    • Math Equations -
    • -
    • Mermaid diagrams
    • -
    • Horizontal ruler
    • -
    • Page break
    • -
    -
    Other features - - -
    Premium features - - -
    -
    -

    Read-Only vs. Editing Mode

    -

    Text notes are usually opened in edit mode. However, they may open in - read-only mode if the note is too big or the note is explicitly marked - as read-only. For more information, see Read-Only Notes.

    -

    Keyboard shortcuts

    -

    There are numerous keyboard shortcuts to format the text without having - to use the mouse. For a reference of all the key combinations, see  - Keyboard Shortcuts. In addition, see Markdown-like formatting as an alternative - to the keyboard shortcuts.

    -

    Technical details

    -

    For the text editing functionality, Trilium uses a commercial product - (with an open-source base) called CKEditor. - This brings the benefit of having a powerful WYSIWYG (What You See Is What - You Get) editor.

    \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Dedicated articleFeature
    General formatting + +
      +
    • Headings (section titles, paragraph)
    • +
    • Font size
    • +
    • Bold, italic, underline, strike-through
    • +
    • Superscript, subscript
    • +
    • Font color & background color
    • +
    • Remove formatting
    • +
    +
    Lists + +
      +
    • Bulleted lists
    • +
    • Numbered lists
    • +
    • To-do lists
    • +
    +
    Block quotes & admonitions + +
      +
    • Block quotes
    • +
    • Admonitions
    • +
    +
    Tables + +
      +
    • Basic tables
    • +
    • Merging cells
    • +
    • Styling tables and cells.
    • +
    • Table captions
    • +
    +
    Developer-specific formatting + +
      +
    • Inline code
    • +
    • Code blocks
    • +
    • Keyboard shortcuts
    • +
    +
    Footnotes + +
      +
    • Footnotes
    • +
    +
    Images + +
      +
    • Images
    • +
    +
    Links + +
      +
    • External links
    • +
    • Internal Trilium links
    • +
    +
    Include Note + +
      +
    • Include note
    • +
    +
    Insert buttons + +
      +
    • Symbols
    • +
    • Math Equations +
    • +
    • Mermaid diagrams
    • +
    • Horizontal ruler
    • +
    • Page break
    • +
    +
    Other features + + +
    Premium features + + +
    +

    Read-Only vs. Editing Mode

    +

    Text notes are usually opened in edit mode. However, they may open in + read-only mode if the note is too big or the note is explicitly marked + as read-only. For more information, see Read-Only Notes.

    +

    Keyboard shortcuts

    +

    There are numerous keyboard shortcuts to format the text without having + to use the mouse. For a reference of all the key combinations, see  + Keyboard Shortcuts. In addition, see Markdown-like formatting as an alternative + to the keyboard shortcuts.

    +

    Technical details

    +

    For the text editing functionality, Trilium uses a commercial product + (with an open-source base) called CKEditor. + This brings the benefit of having a powerful WYSIWYG (What You See Is What + You Get) editor.

    \ No newline at end of file diff --git a/docs/Developer Guide/Developer Guide/Documentation.md b/docs/Developer Guide/Developer Guide/Documentation.md index aae807a49d..8b2fdc9998 100644 --- a/docs/Developer Guide/Developer Guide/Documentation.md +++ b/docs/Developer Guide/Developer Guide/Documentation.md @@ -1,5 +1,5 @@ # Documentation -There are multiple types of documentation for Trilium: +There are multiple types of documentation for Trilium: * The _User Guide_ represents the user-facing documentation. This documentation can be browsed by users directly from within Trilium, by pressing F1. * The _Developer's Guide_ represents a set of Markdown documents that present the internals of Trilium, for developers. diff --git a/docs/User Guide/!!!meta.json b/docs/User Guide/!!!meta.json index d1b8f5d265..92af202232 100644 --- a/docs/User Guide/!!!meta.json +++ b/docs/User Guide/!!!meta.json @@ -3984,42 +3984,42 @@ "name": "internalLink", "value": "s1aBHPd79XYj", "isInheritable": false, - "position": 30 + "position": 10 }, { "type": "relation", "name": "internalLink", "value": "6RM1Q7ppFVoj", "isInheritable": false, - "position": 40 - }, - { - "type": "relation", - "name": "internalLink", - "value": "CoFPLs3dRlXc", - "isInheritable": false, - "position": 50 + "position": 20 }, { "type": "relation", "name": "internalLink", "value": "8YBEPzcpUgxw", "isInheritable": false, - "position": 60 + "position": 30 }, { "type": "relation", "name": "internalLink", "value": "IjZS7iK5EXtb", "isInheritable": false, - "position": 70 + "position": 40 }, { "type": "relation", "name": "internalLink", "value": "XpOYSgsLkTJy", "isInheritable": false, - "position": 80 + "position": 50 + }, + { + "type": "relation", + "name": "internalLink", + "value": "CoFPLs3dRlXc", + "isInheritable": false, + "position": 60 }, { "type": "label", @@ -10147,17 +10147,24 @@ { "type": "relation", "name": "internalLink", - "value": "XpOYSgsLkTJy", + "value": "SL5f1Auq7sVN", "isInheritable": false, "position": 20 }, { "type": "relation", "name": "internalLink", - "value": "0Ofbk1aSuVRu", + "value": "XpOYSgsLkTJy", "isInheritable": false, "position": 30 }, + { + "type": "relation", + "name": "internalLink", + "value": "0Ofbk1aSuVRu", + "isInheritable": false, + "position": 40 + }, { "type": "label", "name": "shareAlias", @@ -10171,13 +10178,6 @@ "value": "bx bx-selection", "isInheritable": false, "position": 20 - }, - { - "type": "relation", - "name": "internalLink", - "value": "SL5f1Auq7sVN", - "isInheritable": false, - "position": 40 } ], "format": "markdown", @@ -10839,39 +10839,53 @@ "type": "text", "mime": "text/html", "attributes": [ - { - "type": "label", - "name": "iconClass", - "value": "bx bxl-markdown", - "isInheritable": false, - "position": 30 - }, - { - "type": "label", - "name": "shareAlias", - "value": "markdown", - "isInheritable": false, - "position": 40 - }, { "type": "relation", "name": "internalLink", "value": "Oau6X9rCuegd", "isInheritable": false, - "position": 50 + "position": 10 }, { "type": "relation", "name": "internalLink", "value": "iPIMuisry3hd", "isInheritable": false, - "position": 60 + "position": 20 }, { "type": "relation", "name": "internalLink", "value": "6f9hih2hXXZk", "isInheritable": false, + "position": 30 + }, + { + "type": "relation", + "name": "internalLink", + "value": "SL5f1Auq7sVN", + "isInheritable": false, + "position": 40 + }, + { + "type": "relation", + "name": "internalLink", + "value": "nBAXQFj20hS1", + "isInheritable": false, + "position": 50 + }, + { + "type": "relation", + "name": "internalLink", + "value": "hrZ1D00cLbal", + "isInheritable": false, + "position": 60 + }, + { + "type": "relation", + "name": "internalLink", + "value": "m1lbrzyKDaRB", + "isInheritable": false, "position": 70 }, { @@ -10886,56 +10900,21 @@ "name": "internalLink", "value": "wy8So3yZZlH9", "isInheritable": false, - "position": 150 + "position": 90 }, { - "type": "relation", - "name": "internalLink", - "value": "SL5f1Auq7sVN", + "type": "label", + "name": "iconClass", + "value": "bx bxl-markdown", "isInheritable": false, - "position": 160 + "position": 30 }, { - "type": "relation", - "name": "internalLink", - "value": "NwBbFdNZ9h7O", + "type": "label", + "name": "shareAlias", + "value": "markdown", "isInheritable": false, - "position": 170 - }, - { - "type": "relation", - "name": "internalLink", - "value": "YfYAtQBcfo5V", - "isInheritable": false, - "position": 180 - }, - { - "type": "relation", - "name": "internalLink", - "value": "s1aBHPd79XYj", - "isInheritable": false, - "position": 190 - }, - { - "type": "relation", - "name": "internalLink", - "value": "nBAXQFj20hS1", - "isInheritable": false, - "position": 200 - }, - { - "type": "relation", - "name": "internalLink", - "value": "hrZ1D00cLbal", - "isInheritable": false, - "position": 210 - }, - { - "type": "relation", - "name": "internalLink", - "value": "m1lbrzyKDaRB", - "isInheritable": false, - "position": 220 + "position": 40 } ], "format": "markdown", diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.md b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.md index b110d09b03..221ba93c9a 100644 --- a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.md +++ b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.md @@ -99,9 +99,9 @@ To do so: For example, to change the font of the document from the one defined by the theme or the user to a serif one: ``` -body { - --main-font-family: serif !important; - --detail-font-family: var(--main-font-family) !important; +:root { + --print-font-family: serif; + --print-font-size: 11pt; } ``` diff --git a/docs/User Guide/User Guide/Installation & Setup/Data directory.md b/docs/User Guide/User Guide/Installation & Setup/Data directory.md index 3a447f82f2..b9df162b9e 100644 --- a/docs/User Guide/User Guide/Installation & Setup/Data directory.md +++ b/docs/User Guide/User Guide/Installation & Setup/Data directory.md @@ -97,4 +97,4 @@ Apart from the data directory, some of the subdirectories of it can be moved els | `TRILIUM_TMP_DIR` | `${TRILIUM_DATA_DIR}/tmp` | Directory where temporary files are stored (for example when opening in an external app). | | `TRILIUM_ANONYMIZED_DB_DIR` | `${TRILIUM_DATA_DIR}/anonymized-db` | Directory where a Anonymized Database is stored. | | `TRILIUM_CONFIG_INI_PATH` | `${TRILIUM_DATA_DIR}/config.ini` | Path to Configuration (config.ini or environment variables) file. | -| `TRILIUM_ELECTRON_DATA_DIR` | `${TRILIUM_DATA_DIR}/electron-user-data` (portable) or system appData (default) | Directory where Electron stores internal data such as caches and spell-check dictionaries (desktop only). | +| `TRILIUM_ELECTRON_DATA_DIR` | `${TRILIUM_DATA_DIR}/electron-user-data` (portable) or system appData (default) | Directory where Electron stores internal data such as caches and spell-check dictionaries (desktop only). | \ No newline at end of file diff --git a/docs/User Guide/User Guide/Note Types/Markdown.md b/docs/User Guide/User Guide/Note Types/Markdown.md index b96b627329..4913eb5f83 100644 --- a/docs/User Guide/User Guide/Note Types/Markdown.md +++ b/docs/User Guide/User Guide/Note Types/Markdown.md @@ -25,15 +25,12 @@ Even if Markdown is now specially treated by having a preview mechanism, Trilium The following features are supported by Trilium's Markdown format and will show up in the preview pane: * All standard and GitHub-flavored syntax (basic formatting, tables, blockquotes) -* Code blocks with syntax highlight (e.g. ` ```js `) and automatic syntax highlight -* Block quotes & admonitions -* Math Equations -* Mermaid Diagrams using ` ```mermaid ` +* Code blocks with syntax highlight (e.g. `mermaid` * Include Note (no builtin Markdown syntax, but HTML syntax works just fine): ```
    -   +  
    n ``` * Internal (reference) links via its HTML syntax, or through a _Wikilinks_\-like format (only Note ID): From 1674bf0a87feb839865eb2cb4c093f2bd645d03d Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 09:28:54 +0300 Subject: [PATCH 351/482] fix(print): wait for custom fonts to be loaded (closes #8097) --- apps/client/src/print.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/client/src/print.tsx b/apps/client/src/print.tsx index c943413c49..11d1cad7b8 100644 --- a/apps/client/src/print.tsx +++ b/apps/client/src/print.tsx @@ -105,6 +105,9 @@ function SingleNoteRenderer({ note, onReady }: RendererProps) { // Check custom CSS. await loadCustomCss(note); + + // Wait for all fonts (including those from custom CSS) to finish loading. + await document.fonts.ready; } load().then(() => requestAnimationFrame(() => onReady({ @@ -130,6 +133,7 @@ function CollectionRenderer({ note, onReady, onProgressChanged }: RendererProps) media="print" onReady={async (data: PrintReport) => { await loadCustomCss(note); + await document.fonts.ready; onReady(data); }} onProgressChanged={onProgressChanged} From 374eeaeb08bc60c734412d95bf9b5b4314993e43 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 09:37:30 +0300 Subject: [PATCH 352/482] feat(print): respect user's detail font when printing --- apps/client/src/print.css | 3 ++- apps/client/src/print.tsx | 7 +++++++ .../Notes/Printing & Exporting as PDF.html | 8 +++++++- .../Notes/Printing & Exporting as PDF.md | 5 ++++- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/apps/client/src/print.css b/apps/client/src/print.css index b08ae29c36..25a61e5bf4 100644 --- a/apps/client/src/print.css +++ b/apps/client/src/print.css @@ -1,7 +1,6 @@ @import "boxicons/css/boxicons.min.css"; :root { - --print-font-family: sans-serif; --print-font-size: 11pt; } @@ -11,6 +10,8 @@ html, body { + --print-font-family: var(--detail-font-family, sans-serif); + width: 100%; height: 100%; color: black; diff --git a/apps/client/src/print.tsx b/apps/client/src/print.tsx index 11d1cad7b8..2a7f25161a 100644 --- a/apps/client/src/print.tsx +++ b/apps/client/src/print.tsx @@ -31,6 +31,13 @@ async function main() { if (!noteId) return; await import("./print.css"); + + // Load the user's font preferences so that --detail-font-family is available. + const fontLink = document.createElement("link"); + fontLink.rel = "stylesheet"; + fontLink.href = "api/fonts"; + document.head.appendChild(fontLink); + const note = await froca.getNote(noteId); const bodyWrapper = document.createElement("div"); diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.html index cae0118ea7..95992cf3d4 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.html @@ -167,10 +167,16 @@ class="admonition note"> class="reference-link" href="#root/_help_KC1HB96bqqHX">Templates.

    For example, to change the font of the document from the one defined by - the theme or the user to a serif one:

    :root {
    +    the theme or the user to a serif one:

    body {
     	--print-font-family: serif;
         --print-font-size: 11pt;
     }
    +

    To remark:

    • Multiple CSS notes can be add by using multiple ~printCss relations.
    • diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.md b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.md index 221ba93c9a..7055825a43 100644 --- a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.md +++ b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.md @@ -99,12 +99,15 @@ To do so: For example, to change the font of the document from the one defined by the theme or the user to a serif one: ``` -:root { +body { --print-font-family: serif; --print-font-size: 11pt; } ``` +> [!IMPORTANT] +> When altering `--print-font-family`, make sure the change is done at `body` level and not `:root`, since otherwise it won't be picked up due to specificity rules. + To remark: * Multiple CSS notes can be add by using multiple `~printCss` relations. From d240fb32bb691f73d91d26f05f7f455bd6a9df08 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sat, 18 Apr 2026 09:49:05 +0300 Subject: [PATCH 353/482] style/about dialog: refactor --- apps/client/src/widgets/dialogs/about.css | 21 +++++++------ apps/client/src/widgets/dialogs/about.tsx | 38 +++++++++++------------ 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/apps/client/src/widgets/dialogs/about.css b/apps/client/src/widgets/dialogs/about.css index 06e4d9f47c..54f0a8a4b9 100644 --- a/apps/client/src/widgets/dialogs/about.css +++ b/apps/client/src/widgets/dialogs/about.css @@ -173,10 +173,12 @@ /* TODO: move to global styles */ .property-sheet-table { + display: table; border-spacing: 0 2px; border-collapse: separate; - tr { + dl { + display: table-row; --_br: 8px; background: var(--card-background-color); @@ -190,17 +192,18 @@ } } - td { + dt, dd { + display: table-cell; padding: 10px 16px; vertical-align: top; + } - &:first-child { - white-space: nowrap; - color: var(--muted-text-color); - } + dt { + white-space: nowrap; + color: var(--muted-text-color); + } - &:last-child { - width: 100%; - } + dl { + width: 100%; } } \ No newline at end of file diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index 4cc3963864..e15dd31902 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -79,10 +79,10 @@ export default function AboutDialog() { triliumnotes.org - - - - - - - - - - - - - - - -
      {t("about.version_label")} +
      +
      +
      {t("about.version_label")}
      +
      {t("about.version", { appVersion: appInfo?.appVersion, dbVersion: appInfo?.dbVersion, @@ -99,27 +99,27 @@ export default function AboutDialog() { }} />
      -
      {t("about.contributors_label")} + + + +
      +
      {t("about.contributors_label")}
      +
      {t("about.contributor_full_list")} -
      {t("about.data_directory")} + + + +
      +
      {t("about.data_directory")}
      +
      {appInfo?.dataDirectory && ()} -
      + + +
    +
    + +
    From 131e10f4fe5810efa055173dd5f49bc85c057ec9 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 10:35:46 +0300 Subject: [PATCH 366/482] fix(text): clicking on a bookmark link won't scroll properly --- .../src/widgets/type_widgets/text/EditableText.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/apps/client/src/widgets/type_widgets/text/EditableText.tsx b/apps/client/src/widgets/type_widgets/text/EditableText.tsx index 760e00e489..26d021168b 100644 --- a/apps/client/src/widgets/type_widgets/text/EditableText.tsx +++ b/apps/client/src/widgets/type_widgets/text/EditableText.tsx @@ -61,6 +61,17 @@ export default function EditableText({ note, parentComponent, ntxId, noteContext onContentChange(newContent) { contentRef.current = newContent; watchdogRef.current?.editor?.setData(newContent); + + // Scroll to bookmark anchor if navigated with ?bookmark=... + const viewScope = noteContext?.viewScope; + if (viewScope?.bookmark) { + requestAnimationFrame(() => { + const el = watchdogRef.current?.editor?.editing.view.getDomRoot() + ?.querySelector(`[id="${CSS.escape(viewScope.bookmark!)}"]`); + el?.scrollIntoView({ behavior: "smooth", block: "center" }); + viewScope.bookmark = undefined; + }); + } }, dataSaved(savedData) { // Store back the saved data in order to retrieve it in case the CKEditor crashes. From 7219fc875d6622ea35cec202aa45dddaaff901d9 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 10:43:14 +0300 Subject: [PATCH 367/482] feat(text): improve display of reference links with bookmarks --- apps/client/src/services/link.ts | 15 +++++++++++++-- .../src/stylesheets/theme-next/notes/text.css | 9 +++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/apps/client/src/services/link.ts b/apps/client/src/services/link.ts index b6c5dbfdb6..1e375a994a 100644 --- a/apps/client/src/services/link.ts +++ b/apps/client/src/services/link.ts @@ -434,6 +434,13 @@ async function loadReferenceLinkTitle($el: JQuery, href: string | n const title = await getReferenceLinkTitle(href); $el.text(title); + if (viewScope?.bookmark) { + $el.append($("").append( + $("").addClass("bx bx-bookmark"), + document.createTextNode(viewScope.bookmark) + )); + } + if (note) { const icon = await getLinkIcon(noteId, viewScope.viewMode); @@ -459,8 +466,8 @@ async function getReferenceLinkTitle(href: string) { return attachment ? attachment.title : "[missing attachment]"; } - return note.title; + return note.title; } function getReferenceLinkTitleSync(href: string) { @@ -483,8 +490,12 @@ function getReferenceLinkTitleSync(href: string) { return attachment ? attachment.title : "[missing attachment]"; } - return note.title; + if (viewScope?.bookmark) { + return `${note.title} - ${viewScope.bookmark}`; + } + + return note.title; } if (glob.device !== "print") { diff --git a/apps/client/src/stylesheets/theme-next/notes/text.css b/apps/client/src/stylesheets/theme-next/notes/text.css index 5e58895ef5..8832d9a9cf 100644 --- a/apps/client/src/stylesheets/theme-next/notes/text.css +++ b/apps/client/src/stylesheets/theme-next/notes/text.css @@ -714,6 +714,15 @@ html .note-detail-editable-text :not(figure, .include-note, hr):first-child { text-decoration: underline; } +.ck-content a.reference-link small { + margin-left: 0.25em; + opacity: 0.5; + + >span { + font-size: 0.7em; + } +} + /* * Read-only text content */ From 3ce2af9abe8edf70dad5a58388e2a625e657e4d6 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sat, 18 Apr 2026 10:44:59 +0300 Subject: [PATCH 368/482] client/property sheet component: add support for CSS class names --- apps/client/src/widgets/react/PropertySheet.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/client/src/widgets/react/PropertySheet.tsx b/apps/client/src/widgets/react/PropertySheet.tsx index d359bd41bb..0053ea4ddd 100644 --- a/apps/client/src/widgets/react/PropertySheet.tsx +++ b/apps/client/src/widgets/react/PropertySheet.tsx @@ -1,15 +1,16 @@ import { ComponentChildren } from "preact"; +import clsx from "clsx"; import "./PropertySheet.css"; -export function PropertySheet({ children }: { children: ComponentChildren }) { - return
    +export function PropertySheet({ className, children }: { className?: string, children: ComponentChildren }) { + return
    {children}
    } -export function PropertySheetItem({label, children}: {label: string, children: ComponentChildren}) { +export function PropertySheetItem({className, label, children}: {className?: string, label: string, children: ComponentChildren}) { return
    {label}
    -
    {children}
    +
    {children}
    } \ No newline at end of file From b01feed4a291909c656fb4affa5487542e21e572 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 10:45:51 +0300 Subject: [PATCH 369/482] feat(text): add bookmark title for non-mirrored link --- apps/client/src/widgets/dialogs/add_link.tsx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/apps/client/src/widgets/dialogs/add_link.tsx b/apps/client/src/widgets/dialogs/add_link.tsx index 9d1f5522ff..e61e476190 100644 --- a/apps/client/src/widgets/dialogs/add_link.tsx +++ b/apps/client/src/widgets/dialogs/add_link.tsx @@ -27,6 +27,7 @@ export default function AddLinkDialog() { const [ suggestion, setSuggestion ] = useState(null); const [ bookmarks, setBookmarks ] = useState([]); const [ selectedBookmark, setSelectedBookmark ] = useState(""); + const [ noteTitle, setNoteTitle ] = useState(""); const [ shown, setShown ] = useState(false); const hasSubmittedRef = useRef(false); @@ -44,8 +45,9 @@ export default function AddLinkDialog() { }, [ opts ]); async function setDefaultLinkTitle(noteId: string) { - const noteTitle = await tree.getNoteTitle(noteId); - setLinkTitle(noteTitle); + const title = await tree.getNoteTitle(noteId); + setNoteTitle(title); + setLinkTitle(title); } function resetExternalLink() { @@ -79,6 +81,14 @@ export default function AddLinkDialog() { } }, [suggestion]); + useEffect(() => { + if (selectedBookmark) { + setLinkTitle(`${noteTitle} - ${selectedBookmark}`); + } else { + setLinkTitle(noteTitle); + } + }, [selectedBookmark, noteTitle]); + function onShown() { const $autocompleteEl = refToJQuerySelector(autocompleteRef); if (!opts?.text) { @@ -136,6 +146,7 @@ export default function AddLinkDialog() { setSuggestion(null); setBookmarks([]); setSelectedBookmark(""); + setNoteTitle(""); setShown(false); }} show={shown} From 683814c9d24ed5de2be898f38494bb192106f8f4 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sat, 18 Apr 2026 10:47:20 +0300 Subject: [PATCH 370/482] client/about dialog: refactor --- apps/client/src/widgets/dialogs/about.tsx | 46 +++++++++---------- .../src/widgets/react/PropertySheet.css | 4 ++ 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index 4f49153955..9abcb30950 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -82,38 +82,34 @@ export default function AboutDialog() { -
    - {t("about.version", { - appVersion: appInfo?.appVersion, - dbVersion: appInfo?.dbVersion, - syncVersion: appInfo?.syncVersion - })} -
    - -
    + {t("about.version", { + appVersion: appInfo?.appVersion, + dbVersion: appInfo?.dbVersion, + syncVersion: appInfo?.syncVersion + })} +
    +
    - - + + {t("about.contributor_full_list")} + -
    +
    {appInfo?.dataDirectory && ()}
    diff --git a/apps/client/src/widgets/react/PropertySheet.css b/apps/client/src/widgets/react/PropertySheet.css index 65289ad697..f41265511f 100644 --- a/apps/client/src/widgets/react/PropertySheet.css +++ b/apps/client/src/widgets/react/PropertySheet.css @@ -7,6 +7,10 @@ dt { color: var(--muted-text-color); } + + dd { + user-select: text; + } } } From 15c121f95025c963ed9270a3f359a03a62f5ea92 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 10:54:57 +0300 Subject: [PATCH 371/482] docs(user): document linking to bookmarks --- .../Navigation/Bookmarks.html | 5 ++ .../Notes/Printing & Exporting as PDF.html | 21 +++---- .../User Guide/Note Types/Text/Bookmarks.html | 60 ++++++++++++++++--- .../Developer Guide/Documentation.md | 2 +- docs/User Guide/!!!meta.json | 42 +++++++++++++ .../Navigation/Bookmarks.md | 3 + .../User Guide/Note Types/Text/Bookmarks.md | 25 +++++++- 7 files changed, 133 insertions(+), 25 deletions(-) diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks.html index 07943c9924..32231b4d69 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks.html @@ -1,3 +1,8 @@ +

    Frequently used notes can be bookmarked, which will make them appear in the Launch Bar for easy access.

    diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.html index 95992cf3d4..721b20ed26 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF.html @@ -61,8 +61,7 @@ class="admonition note">
    • To print in landscape mode instead of portrait (useful for big diagrams or slides), add #printLandscape.
    • -
    • By default, the resulting PDF will be in Letter format. It is possible +
    • By default, the resulting PDF will be in Letter format. It is possible to adjust it to another page size via the #printPageSize attribute, with one of the following values: A0,
      1. First create a collection.
      2. Configure it to use List View.
      3. -
      4. Print the collection note normally.
      5. +
      6. Print the collection note normally.

      The resulting collection will contain all the children of the collection, while maintaining the hierarchy.

      @@ -102,9 +100,9 @@ class="admonition note"> href="#root/_help_4TIF1oA4VQRO">Options and assigning a key combination for:

        -
      • Print Active Note +
      • Print Active Note
      • -
      • Export Active Note as PDF +
      • Export Active Note as PDF

      Constraints & limitations

      @@ -180,13 +178,12 @@ class="admonition note">

      To remark:

      • Multiple CSS notes can be add by using multiple ~printCss relations.
      • -
      • If the note pointing to the printCss doesn't +
      • If the note pointing to the printCss doesn't have the right note type or mime type, it will be ignored.
      • -
      • If migrating from a previous version where Custom app-wide CSS, there's no need for - @media print { since the style-sheet is used only for printing.
      • +
      • If migrating from a previous version where Custom app-wide CSS, there's no need for + @media print { since the style-sheet is used only for printing.

      Under the hood

      Both printing and exporting as PDF use the same mechanism: a note is rendered diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Bookmarks.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Bookmarks.html index bc7b346e33..25cb62942d 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Bookmarks.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Bookmarks.html @@ -1,5 +1,12 @@ +

      Bookmarks allows creating links to a certain - part of a note, such as referencing a particular heading.

      + part of a note, such as referencing a particular heading or section within + a note.

      Technically, bookmarks are HTML anchors.

      This feature was introduced in TriliumNext 0.94.0.

      Interaction

      @@ -7,13 +14,16 @@
    • To create a bookmark:
      • Place the cursor at the desired position where to place the bookmark.
      • -
      • Look for the +
      • Look for the button in the Formatting toolbar, and then press the button.
      • -
      +
    • Alternatively, use Slash Commands and + look for Bookmark.
    • +
  • To place a link to a bookmark:
      @@ -23,9 +33,41 @@
  • -

    Limitations

    -
      -
    • Currently it's not possible to create a link to a bookmark from a different - note. This functionality will be added after the internal links feature - is enhanced to support bookmarks.
    • -
    \ No newline at end of file +

    Linking across notes

    +

    Trilium v0.103.0 introduces cross-note bookmarks, which makes it possible + to create Internal (reference) links which + point to a specific bookmark in that document.

    +

    To do so:

    +
      +
    1. +

      First, create a bookmark in the target note using the same process as + described above.

      +
    2. +
    3. +

      In another note, press Ctrl+L to insert an internal + link. Select the target note containing bookmarks.

      +
    4. +
    5. +

      If the target note contains bookmarks, a section will appear underneath + the note selector with the list of bookmarks.

      +
    6. +
    7. +

      Add the link normally.

      +
    8. +
    +

    Clicking on a reference link pointing to a bookmark will automatically + scroll to the desired section.

    + \ No newline at end of file diff --git a/docs/Developer Guide/Developer Guide/Documentation.md b/docs/Developer Guide/Developer Guide/Documentation.md index 8b2fdc9998..18b7705caf 100644 --- a/docs/Developer Guide/Developer Guide/Documentation.md +++ b/docs/Developer Guide/Developer Guide/Documentation.md @@ -1,5 +1,5 @@ # Documentation -There are multiple types of documentation for Trilium: +There are multiple types of documentation for Trilium: * The _User Guide_ represents the user-facing documentation. This documentation can be browsed by users directly from within Trilium, by pressing F1. * The _Developer's Guide_ represents a set of Markdown documents that present the internals of Trilium, for developers. diff --git a/docs/User Guide/!!!meta.json b/docs/User Guide/!!!meta.json index 92af202232..61858de2ff 100644 --- a/docs/User Guide/!!!meta.json +++ b/docs/User Guide/!!!meta.json @@ -5413,6 +5413,20 @@ "value": "bx bx-bookmarks", "isInheritable": false, "position": 30 + }, + { + "type": "relation", + "name": "internalLink", + "value": "oSuaNgyyKnhu", + "isInheritable": false, + "position": 40 + }, + { + "type": "relation", + "name": "internalLink", + "value": "iPIMuisry3hd", + "isInheritable": false, + "position": 50 } ], "format": "markdown", @@ -7305,6 +7319,34 @@ "value": "bookmarks", "isInheritable": false, "position": 30 + }, + { + "type": "relation", + "name": "internalLink", + "value": "u3YFHC9tQlpm", + "isInheritable": false, + "position": 40 + }, + { + "type": "relation", + "name": "internalLink", + "value": "xYmIYSP6wE3F", + "isInheritable": false, + "position": 50 + }, + { + "type": "relation", + "name": "internalLink", + "value": "ZlN4nump6EbW", + "isInheritable": false, + "position": 60 + }, + { + "type": "relation", + "name": "internalLink", + "value": "hrZ1D00cLbal", + "isInheritable": false, + "position": 70 } ], "format": "markdown", diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks.md b/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks.md index 332ec24172..321cf83f21 100644 --- a/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks.md +++ b/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks.md @@ -1,4 +1,7 @@ # Bookmarks +> [!NOTE] +> Not to be confused with the Bookmarks concept for Text notes which acts like anchors, allowing navigation to a particular section. + Frequently used notes can be bookmarked, which will make them appear in the Launch Bar for easy access. ## Configuring the launch bar diff --git a/docs/User Guide/User Guide/Note Types/Text/Bookmarks.md b/docs/User Guide/User Guide/Note Types/Text/Bookmarks.md index e6321b5b89..6a699b139c 100644 --- a/docs/User Guide/User Guide/Note Types/Text/Bookmarks.md +++ b/docs/User Guide/User Guide/Note Types/Text/Bookmarks.md @@ -1,5 +1,8 @@ # Bookmarks -Bookmarks allows creating [links](Links.md) to a certain part of a note, such as referencing a particular heading. +> [!NOTE] +> Not to be confused with [bookmarked notes](../../Basic%20Concepts%20and%20Features/Navigation/Bookmarks.md), which simply pins a particular note to the Launch Bar for easy access. + +Bookmarks allows creating [links](Links.md) to a certain part of a note, such as referencing a particular heading or section within a note. Technically, bookmarks are HTML anchors. @@ -10,10 +13,26 @@ This feature was introduced in TriliumNext 0.94.0. * To create a bookmark: * Place the cursor at the desired position where to place the bookmark. * Look for the button in the Formatting toolbar, and then press the button. + * Alternatively, use Slash Commands and look for _Bookmark_. * To place a link to a bookmark: * Place the cursor at the desired position of the link. * From the [link](Links.md) pane, select the _Bookmarks_ section and select the desired bookmark. -## Limitations +## Linking across notes -* Currently it's not possible to create a link to a bookmark from a different note. This functionality will be added after the internal links feature is enhanced to support bookmarks. \ No newline at end of file +Trilium v0.103.0 introduces cross-note bookmarks, which makes it possible to create Internal (reference) links which point to a specific bookmark in that document. + +To do so: + +1. First, create a bookmark in the target note using the same process as described above. +2. In another note, press Ctrl+L to insert an internal link. Select the target note containing bookmarks. +3. If the target note contains bookmarks, a section will appear underneath the note selector with the list of bookmarks. +4. Add the link normally. + +Clicking on a reference link pointing to a bookmark will automatically scroll to the desired section. + +> [!NOTE] +> For notes created prior to Trilium v0.103.0, you might notice that the bookmarks might not be identified: +> +> * To fix this, simply go that note and make any change (e.g. inserting a space), this will trigger the recalculation of the links. +> * This limitation is intentional in order not to have to re-process all the notes, looking for anchors. \ No newline at end of file From 4244b66ceaccceb5515b5c6a645c43b0e85d23df Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 11:04:20 +0300 Subject: [PATCH 372/482] feat(text): rebrand bookmarks to anchors --- .../src/translations/en/translation.json | 4 +- apps/client/src/widgets/dialogs/add_link.tsx | 4 +- .../doc_notes/en/User Guide/!!!meta.json | 2 +- .../Navigation/Bookmarks.html | 5 - ..._Bookmarks_plus.png => 1_Anchors_plus.png} | Bin .../User Guide/Note Types/Text/Anchors.html | 62 ++++++ .../{Bookmarks_plus.png => Anchors_plus.png} | Bin .../User Guide/Note Types/Text/Bookmarks.html | 73 ------- .../Links/Internal (reference) links.html | 7 +- docs/User Guide/!!!meta.json | 197 ++++++++---------- .../Navigation/Bookmarks.md | 3 - ..._Bookmarks_plus.png => 1_Anchors_plus.png} | Bin .../User Guide/Note Types/Text/Anchors.md | 36 ++++ .../{Bookmarks_plus.png => Anchors_plus.png} | Bin .../User Guide/Note Types/Text/Bookmarks.md | 38 ---- .../Note Types/Text/Insert buttons.md | 2 +- .../ckeditor5/src/extra_slash_commands.ts | 8 +- .../ckeditor5/src/translation_overrides.ts | 11 +- 18 files changed, 210 insertions(+), 242 deletions(-) rename apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/{1_Bookmarks_plus.png => 1_Anchors_plus.png} (100%) create mode 100644 apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Anchors.html rename apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/{Bookmarks_plus.png => Anchors_plus.png} (100%) delete mode 100644 apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Bookmarks.html rename docs/User Guide/User Guide/Note Types/Text/{1_Bookmarks_plus.png => 1_Anchors_plus.png} (100%) create mode 100644 docs/User Guide/User Guide/Note Types/Text/Anchors.md rename docs/User Guide/User Guide/Note Types/Text/{Bookmarks_plus.png => Anchors_plus.png} (100%) delete mode 100644 docs/User Guide/User Guide/Note Types/Text/Bookmarks.md diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 3145ff7f03..79cf207780 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -41,8 +41,8 @@ "link_title_mirrors": "link title mirrors the note's current title", "link_title_arbitrary": "link title can be changed arbitrarily", "link_title": "Link title", - "bookmark": "Bookmark (optional)", - "bookmark_none": "None (link to note)", + "anchor": "Anchor (optional)", + "anchor_none": "None (link to note)", "button_add_link": "Add link" }, "branch_prefix": { diff --git a/apps/client/src/widgets/dialogs/add_link.tsx b/apps/client/src/widgets/dialogs/add_link.tsx index e61e476190..f68e38bfc4 100644 --- a/apps/client/src/widgets/dialogs/add_link.tsx +++ b/apps/client/src/widgets/dialogs/add_link.tsx @@ -163,13 +163,13 @@ export default function AddLinkDialog() { {bookmarks.length > 0 && ( - + setDescription((e.target as HTMLInputElement).value)} + style={{ width: "200px" }} + /> +
    + ); +} + function RevisionsList({ revisions, onSelect, currentRevision }: { revisions: RevisionItem[], onSelect: (val: string) => void, currentRevision?: RevisionItem }) { return ( @@ -150,20 +199,30 @@ function RevisionsList({ revisions, onSelect, currentRevision }: { revisions: Re value={item.revisionId} active={currentRevision && item.revisionId === currentRevision.revisionId} > - {item.dateCreated && item.dateCreated.substr(0, 16)} ({item.contentLength && utils.formatSize(item.contentLength)}) +
    + {item.dateCreated && item.dateCreated.substr(0, 16)} ({item.contentLength && utils.formatSize(item.contentLength)}) + {item.description && ( +
    + {item.description} +
    + )} +
    )}
    ); } -function RevisionPreview({noteContent, revisionItem, showDiff, setShown, onRevisionDeleted }: { +function RevisionPreview({noteContent, revisionItem, showDiff, setShown, onRevisionDeleted, onDescriptionUpdated }: { noteContent?: string, revisionItem?: RevisionItem, showDiff: boolean, setShown: Dispatch>, - onRevisionDeleted?: () => void + onRevisionDeleted?: () => void, + onDescriptionUpdated?: (revisionId: string, description: string) => void }) { const [ fullRevision, setFullRevision ] = useState(); + const [ editingDescription, setEditingDescription ] = useState(false); + const [ descriptionDraft, setDescriptionDraft ] = useState(""); useEffect(() => { if (revisionItem) { @@ -171,6 +230,7 @@ function RevisionPreview({noteContent, revisionItem, showDiff, setShown, onRevis } else { setFullRevision(undefined); } + setEditingDescription(false); }, [revisionItem]); return ( @@ -215,6 +275,25 @@ function RevisionPreview({noteContent, revisionItem, showDiff, setShown, onRevis }
    )}
    + {revisionItem && ( + { + setDescriptionDraft(revisionItem.description || ""); + setEditingDescription(true); + }} + onDraftChange={setDescriptionDraft} + onSave={async () => { + await server.patch(`revisions/${revisionItem.revisionId}`, { description: descriptionDraft }); + setEditingDescription(false); + toast.showMessage(t("revisions.description_updated")); + onDescriptionUpdated?.(revisionItem.revisionId!, descriptionDraft); + }} + onCancel={() => setEditingDescription(false)} + /> + )}
    void, + onDraftChange: (val: string) => void, + onSave: () => void, + onCancel: () => void +}) { + if (editing) { + return ( +
    + onDraftChange((e.target as HTMLInputElement).value)} + onKeyDown={(e) => { + if (e.key === "Enter") onSave(); + if (e.key === "Escape") onCancel(); + }} + // eslint-disable-next-line jsx-a11y/no-autofocus + autoFocus + style={{ flexGrow: 1 }} + /> + + +
    + ); + } + + return ( +
    + + {revisionItem.description || t("revisions.description_placeholder")} + + +
    + ); +} + const IMAGE_STYLE: CSSProperties = { maxWidth: "100%", maxHeight: "90%", diff --git a/apps/server/src/assets/db/schema.sql b/apps/server/src/assets/db/schema.sql index 27e38bf205..361a6ccdf4 100644 --- a/apps/server/src/assets/db/schema.sql +++ b/apps/server/src/assets/db/schema.sql @@ -48,6 +48,7 @@ CREATE TABLE IF NOT EXISTS "revisions" (`revisionId` TEXT NOT NULL PRIMARY KEY, type TEXT DEFAULT '' NOT NULL, mime TEXT DEFAULT '' NOT NULL, `title` TEXT NOT NULL, + `description` TEXT DEFAULT '' NOT NULL, `isProtected` INT NOT NULL DEFAULT 0, blobId TEXT DEFAULT NULL, `utcDateLastEdited` TEXT NOT NULL, diff --git a/apps/server/src/becca/entities/bnote.ts b/apps/server/src/becca/entities/bnote.ts index 06a9fd41dc..63b447c2b3 100644 --- a/apps/server/src/becca/entities/bnote.ts +++ b/apps/server/src/becca/entities/bnote.ts @@ -1543,7 +1543,7 @@ class BNote extends AbstractBeccaEntity { return !(this.noteId in this.becca.notes) || this.isBeingDeleted; } - saveRevision(): BRevision { + saveRevision(description?: string): BRevision { return sql.transactional(() => { let noteContent = this.getContent(); @@ -1552,6 +1552,7 @@ class BNote extends AbstractBeccaEntity { noteId: this.noteId, // title and text should be decrypted now title: this.title, + description: description || "", type: this.type, mime: this.mime, isProtected: this.isProtected, diff --git a/apps/server/src/becca/entities/brevision.ts b/apps/server/src/becca/entities/brevision.ts index 88f647db29..d9bf2e1c72 100644 --- a/apps/server/src/becca/entities/brevision.ts +++ b/apps/server/src/becca/entities/brevision.ts @@ -31,7 +31,7 @@ class BRevision extends AbstractBeccaEntity { return "revisionId"; } static get hashedProperties() { - return ["revisionId", "noteId", "title", "isProtected", "dateLastEdited", "dateCreated", "utcDateLastEdited", "utcDateCreated", "utcDateModified", "blobId"]; + return ["revisionId", "noteId", "title", "description", "isProtected", "dateLastEdited", "dateCreated", "utcDateLastEdited", "utcDateCreated", "utcDateModified", "blobId"]; } revisionId?: string; @@ -39,6 +39,7 @@ class BRevision extends AbstractBeccaEntity { type!: NoteType; mime!: string; title!: string; + description!: string; dateLastEdited?: string; utcDateLastEdited?: string; contentLength?: number; @@ -61,6 +62,7 @@ class BRevision extends AbstractBeccaEntity { this.mime = row.mime; this.isProtected = !!row.isProtected; this.title = row.title; + this.description = row.description || ""; this.blobId = row.blobId; this.dateLastEdited = row.dateLastEdited; this.dateCreated = row.dateCreated; @@ -193,6 +195,7 @@ class BRevision extends AbstractBeccaEntity { mime: this.mime, isProtected: this.isProtected, title: this.title, + description: this.description, blobId: this.blobId, dateLastEdited: this.dateLastEdited, dateCreated: this.dateCreated, diff --git a/apps/server/src/etapi/mappers.ts b/apps/server/src/etapi/mappers.ts index 4748122390..bff50af5c6 100644 --- a/apps/server/src/etapi/mappers.ts +++ b/apps/server/src/etapi/mappers.ts @@ -73,6 +73,7 @@ function mapRevisionToPojo(revision: BRevision) { mime: revision.mime, isProtected: revision.isProtected, title: revision.title, + description: revision.description, blobId: revision.blobId, dateLastEdited: revision.dateLastEdited, dateCreated: revision.dateCreated, diff --git a/apps/server/src/etapi/notes.ts b/apps/server/src/etapi/notes.ts index 935868ef78..96206f2dc6 100644 --- a/apps/server/src/etapi/notes.ts +++ b/apps/server/src/etapi/notes.ts @@ -192,9 +192,10 @@ function register(router: Router) { eu.route<{ noteId: string }>(router, "post", "/etapi/notes/:noteId/revision", (req, res, next) => { const note = eu.getAndCheckNote(req.params.noteId); - note.saveRevision(); + const description = req.body?.description || ""; + const revision = note.saveRevision(description); - return res.sendStatus(204); + res.status(201).json(mappers.mapRevisionToPojo(revision)); }); eu.route<{ noteId: string }>(router, "get", "/etapi/notes/:noteId/attachments", (req, res, next) => { diff --git a/apps/server/src/migrations/migrations.ts b/apps/server/src/migrations/migrations.ts index 5468312c55..93b25be8f1 100644 --- a/apps/server/src/migrations/migrations.ts +++ b/apps/server/src/migrations/migrations.ts @@ -6,6 +6,14 @@ // Migrations should be kept in descending order, so the latest migration is first. const MIGRATIONS: (SqlMigration | JsMigration)[] = [ + // Add description column to revisions table for manual revision comments + { + version: 238, + sql: /*sql*/` + ALTER TABLE revisions ADD COLUMN description TEXT DEFAULT '' NOT NULL; + `, + ignoreErrors: true + }, // Clean up obsolete keyboard shortcut options from renamed actions { version: 237, diff --git a/apps/server/src/routes/api/notes.ts b/apps/server/src/routes/api/notes.ts index e95ac75e96..9cca431f91 100644 --- a/apps/server/src/routes/api/notes.ts +++ b/apps/server/src/routes/api/notes.ts @@ -351,7 +351,12 @@ function forceSaveRevision(req: Request<{ noteId: string }>) { throw new ValidationError(`Note revision of a protected note cannot be created outside of a protected session.`); } - note.saveRevision(); + const description = req.body?.description || ""; + const revision = note.saveRevision(description); + + return { + revisionId: revision.revisionId + }; } function convertNoteToAttachment(req: Request<{ noteId: string }>) { diff --git a/apps/server/src/routes/api/revisions.ts b/apps/server/src/routes/api/revisions.ts index 34dbce728e..8598810791 100644 --- a/apps/server/src/routes/api/revisions.ts +++ b/apps/server/src/routes/api/revisions.ts @@ -111,6 +111,18 @@ function eraseRevision(req: Request<{ revisionId: string }>) { eraseService.eraseRevisions([req.params.revisionId]); } +function updateRevisionDescription(req: Request<{ revisionId: string }>) { + const revision = becca.getRevisionOrThrow(req.params.revisionId); + const { description } = req.body; + + if (typeof description !== "string") { + return [400, "Description must be a string."]; + } + + revision.description = description; + revision.save(); +} + function eraseAllExcessRevisions() { const allNoteIds = sql.getRows("SELECT noteId FROM notes WHERE SUBSTRING(noteId, 1, 1) != '_'") as { noteId: string }[]; allNoteIds.forEach((row) => { @@ -222,5 +234,6 @@ export default { eraseAllRevisions, eraseAllExcessRevisions, eraseRevision, - restoreRevision + restoreRevision, + updateRevisionDescription }; diff --git a/apps/server/src/routes/routes.ts b/apps/server/src/routes/routes.ts index 62872891ca..c689d46075 100644 --- a/apps/server/src/routes/routes.ts +++ b/apps/server/src/routes/routes.ts @@ -186,6 +186,7 @@ function register(app: express.Application) { apiRoute(GET, "/api/revisions/:revisionId", revisionsApiRoute.getRevision); apiRoute(GET, "/api/revisions/:revisionId/blob", revisionsApiRoute.getRevisionBlob); apiRoute(DEL, "/api/revisions/:revisionId", revisionsApiRoute.eraseRevision); + apiRoute(PATCH, "/api/revisions/:revisionId", revisionsApiRoute.updateRevisionDescription); apiRoute(PST, "/api/revisions/:revisionId/restore", revisionsApiRoute.restoreRevision); route(GET, "/api/revisions/:revisionId/image/:filename", [auth.checkApiAuthOrElectron], imageRoute.returnImageFromRevision); diff --git a/packages/commons/src/lib/rows.ts b/packages/commons/src/lib/rows.ts index 200b567023..977120c21f 100644 --- a/packages/commons/src/lib/rows.ts +++ b/packages/commons/src/lib/rows.ts @@ -28,6 +28,7 @@ export interface RevisionRow { mime: string; isProtected?: boolean; title: string; + description?: string; blobId?: string; dateLastEdited?: string; dateCreated?: string; diff --git a/packages/commons/src/lib/server_api.ts b/packages/commons/src/lib/server_api.ts index 84b16482bb..c43b155094 100644 --- a/packages/commons/src/lib/server_api.ts +++ b/packages/commons/src/lib/server_api.ts @@ -33,6 +33,7 @@ export interface RevisionItem { contentLength?: number; type: NoteType; title: string; + description?: string; isProtected?: boolean; mime: string; } @@ -44,6 +45,7 @@ export interface RevisionPojo { mime: string; isProtected?: boolean; title: string; + description?: string; blobId?: string; dateLastEdited?: string; dateCreated?: string; From 676a988433190f862673fb4524cf28906dbdad9c Mon Sep 17 00:00:00 2001 From: green Date: Sat, 18 Apr 2026 05:13:55 +0200 Subject: [PATCH 385/482] Translated using Weblate (Japanese) Currently translated at 99.9% (1961 of 1962 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/ --- apps/client/src/translations/ja/translation.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/client/src/translations/ja/translation.json b/apps/client/src/translations/ja/translation.json index cdbe639287..2c99b6e57c 100644 --- a/apps/client/src/translations/ja/translation.json +++ b/apps/client/src/translations/ja/translation.json @@ -615,7 +615,8 @@ "collections": "コレクション", "ai-chat": "AI チャット", "spreadsheet": "スプレッドシート", - "llm-chat": "AI チャット" + "llm-chat": "AI チャット", + "markdown": "Markdown" }, "edited_notes": { "no_edited_notes_found": "この日の編集されたノートはまだありません...", @@ -2479,5 +2480,10 @@ }, "launcher_button_context_menu": { "remove_from_launch_bar": "ランチャーバーから削除" + }, + "display_mode": { + "source": "ソースビュー", + "split": "分割ビュー", + "preview": "プレビュー" } } From a915c60c38af4fa4b4ee1f542ef68256762ddd96 Mon Sep 17 00:00:00 2001 From: "Francis C." Date: Sat, 18 Apr 2026 11:23:46 +0200 Subject: [PATCH 386/482] Translated using Weblate (Chinese (Traditional Han script)) Currently translated at 99.2% (401 of 404 strings) Translation: Trilium Notes/Server Translate-URL: https://hosted.weblate.org/projects/trilium/server/zh_Hant/ --- apps/server/src/assets/translations/tw/server.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/server/src/assets/translations/tw/server.json b/apps/server/src/assets/translations/tw/server.json index 8a549ec7a8..a6a411b9ab 100644 --- a/apps/server/src/assets/translations/tw/server.json +++ b/apps/server/src/assets/translations/tw/server.json @@ -45,7 +45,7 @@ "show-note-source": "顯示筆記來源對話方塊", "show-options": "打開選項頁面", "show-revisions": "顯示筆記歷史版本對話方塊", - "show-recent-changes": "顯示最近更改對話方塊", + "show-recent-changes": "顯示最近修改對話方塊", "show-sql-console": "打開 SQL 控制台頁面", "show-backend-log": "打開後端日誌頁面", "text-note-operations": "文字筆記操作", @@ -261,7 +261,7 @@ "show-note-source": "顯示筆記原始碼", "show-options": "顯示選項", "show-revisions": "顯示歷史版本", - "show-recent-changes": "顯示最近更改", + "show-recent-changes": "顯示最近修改", "show-sql-console": "顯示 SQL 控制台", "show-backend-log": "顯示後端日誌", "show-help": "顯示說明", From ec7b9e08e3971a1fb139726b3d827745f352644b Mon Sep 17 00:00:00 2001 From: passkal4 Date: Sat, 18 Apr 2026 11:40:50 +0200 Subject: [PATCH 387/482] Translated using Weblate (Uyghur) Currently translated at 23.0% (93 of 404 strings) Translation: Trilium Notes/Server Translate-URL: https://hosted.weblate.org/projects/trilium/server/ug/ --- apps/server/src/assets/translations/ug/server.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/server/src/assets/translations/ug/server.json b/apps/server/src/assets/translations/ug/server.json index 7f7380ddaa..66c2f76a28 100644 --- a/apps/server/src/assets/translations/ug/server.json +++ b/apps/server/src/assets/translations/ug/server.json @@ -85,6 +85,13 @@ "reload-frontend-app": "ئالدى تەرەپ ئەپىنى قايتا يۈكلەش", "open-dev-tools": "تەتقىقاتچى قوراللىرىنى ئېچىش", "find-in-text": "تېكىست ئىچىدىن ئىزدەش", - "toggle-left-note-tree-panel": "سول تەرەپ (خاتىرە دەرىخى) تاختىسىنى ئالماشتۇرۇش" + "toggle-left-note-tree-panel": "سول تەرەپ (خاتىرە دەرىخى) تاختىسىنى ئالماشتۇرۇش", + "toggle-full-screen": "پۈتۈن ئېكران شەكلىگە ئالماشتۇرۇش", + "zoom-out": "كىچىكلىتىش", + "zoom-in": "چوڭايتىش", + "note-navigation": "خاتىرە يولباشچىسى", + "reset-zoom-level": "چوڭ-كىچىكلىك دەرىجىسىنى ئەسلىگە كەلتۈرۈش", + "copy-without-formatting": "تاللانغان تېكىستنى فارماٹسىز كۆچۈرۈش", + "force-save-revision": "نۆۋەتتىكى خاتىرىنىڭ يېڭى نەشرىنى مەجبۇرىي قۇرۇش/ساقلاش" } } From 7dfdc7f31aa9c941eeccb987f4e7e6b65b5bc199 Mon Sep 17 00:00:00 2001 From: passkal4 Date: Sat, 18 Apr 2026 11:41:24 +0200 Subject: [PATCH 388/482] Translated using Weblate (Uyghur) Currently translated at 78.9% (94 of 119 strings) Translation: Trilium Notes/README Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ug/ --- docs/README-ug.md | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/docs/README-ug.md b/docs/README-ug.md index b20038be1e..9b081dba6c 100644 --- a/docs/README-ug.md +++ b/docs/README-ug.md @@ -285,23 +285,24 @@ pnpm run --filter desktop electron-forge:make --arch=x64 --platform=win32 ### تەتقىقاتچى ھۆججەتلىرى -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. +تەپسىلاتلار ئۈچۈن [ھۆججەت +يېتەكچىسى](https://github.com/TriliumNext/Trilium/blob/main/docs/Developer%20Guide/Developer%20Guide/Environment%20Setup.md)گە +قاراڭ. ئەگەر تېخىمۇ كۆپ سوئاللىرىڭىز بولسا، ئۈستىدىكى "بىز بىلەن ئالاقىلىشىڭ" +بۆلىكىدە تەمىنلەنگەن ئۇلىنىشلار ئارقىلىق بىز بىلەن ئالاقىلىشىڭنى قارشى ئالىمىز. -## 👏 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. +* ئەپنىڭ ئەسلى ئۇقۇم لاھىيەسى ۋە ئەمەلگە ئاشۇرۇلۇشىغا تۆھپە قوشقان + [zadam](https://github.com/zadam). +* ئەپ سىنبەلگىسىنى لاھىيەلىگەن [Sarah + Hussein](https://github.com/Sarah-Hussein). +* خەلقئارالاشتۇرۇش خىزمىتىگە تۆھپە قوشقان [nriver](https://github.com/nriver). +* Canvas جەھەتتىكى ئەسلى ئىجادىي خىزمەتلىرى ئۈچۈن [Thomas + Frei](https://github.com/thfrei). +* ئەسلى گرامماتىكا گەۋدىلەندۈرۈش كىچىك زاپچاسلارنى ئاپتورى + [antoniotejada](https://github.com/nriver). +* GitHub مەسىلىلىرى ۋە مۇنازىرىلىرىگە ئاپتوماتىك جاۋاب قايتۇرۇش بىلەن تەمىنلىگەن + [Dosu](https://dosu.dev/). * [Tabler Icons](https://tabler.io/icons) for the system tray icons. Trilium would not be possible without the technologies behind it: From 0bdebca2b694583e843788763099fd7807faa14f Mon Sep 17 00:00:00 2001 From: "Francis C." Date: Sat, 18 Apr 2026 11:29:07 +0200 Subject: [PATCH 389/482] Translated using Weblate (Chinese (Traditional Han script)) Currently translated at 89.7% (1760 of 1962 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/ --- .../src/translations/tw/translation.json | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/apps/client/src/translations/tw/translation.json b/apps/client/src/translations/tw/translation.json index cc0497127e..09b044c264 100644 --- a/apps/client/src/translations/tw/translation.json +++ b/apps/client/src/translations/tw/translation.json @@ -89,13 +89,21 @@ }, "delete_notes": { "delete_all_clones_description": "同時刪除所有克隆(可以在最近修改中撤消)", - "erase_notes_description": "通常(軟)刪除僅標記筆記為已刪除,可以在一段時間內透過最近修改對話方塊撤消。勾選此選項將立即擦除筆記,無法撤銷。", + "erase_notes_description": "立即刪除筆記,而非執行軟刪除。此操作無法撤銷,且會強制重新載入應用程式。", "erase_notes_warning": "永久擦除筆記(無法撤銷),包括所有克隆。這將強制應用程式重新載入。", - "notes_to_be_deleted": "將刪除以下筆記 ({{notesCount}})", + "notes_to_be_deleted": "待刪除筆記 ({{notesCount}})", "no_note_to_delete": "沒有筆記將被刪除(僅克隆)。", - "broken_relations_to_be_deleted": "將刪除以下關聯並斷開連接 ({{ relationCount}})", + "broken_relations_to_be_deleted": "斷開的關聯 ({{ relationCount}})", "cancel": "取消", - "close": "關閉" + "close": "關閉", + "title": "刪除筆記", + "clones_label": "克隆", + "delete_clones_description_one": "同時刪除 {{count}} 個其他克隆。此操作可在最近修改中撤銷。", + "erase_notes_label": "永久擦除", + "table_note_with_relation": "有關聯的筆記", + "table_relation": "關聯", + "table_points_to": "指向 (已刪除)", + "delete": "刪除" }, "export": { "export_note_title": "匯出筆記", @@ -206,7 +214,8 @@ "box_size_small": "小型(顯示大約 10 行)", "box_size_medium": "中型 (顯示大約30行)", "box_size_full": "完整顯示(完整文字框)", - "button_include": "內嵌筆記" + "button_include": "內嵌筆記", + "box_size_expandable": "可展開(預設為摺疊狀態)" }, "info": { "modalTitle": "資訊消息", @@ -1430,7 +1439,7 @@ "expand-subtree": "展開子階層", "collapse-subtree": "收摺子階層", "sort-by": "排序方式…", - "recent-changes-in-subtree": "子階層中的最近更改", + "recent-changes-in-subtree": "子階層中的最近修改", "convert-to-attachment": "轉換為附件", "copy-note-path-to-clipboard": "複製筆記路徑至剪貼簿", "protect-subtree": "保護子階層", @@ -2334,5 +2343,14 @@ "history": "對話歷史", "recent_chats": "最近的對話", "no_chats": "無先前的對話記錄" + }, + "revisions": { + "note_revisions": "筆記歷史版本", + "delete_all_revisions": "刪除此筆記的所有歷史版本", + "delete_all_button": "刪除所有歷史版本", + "help_title": "關於筆記歷史版本的說明", + "confirm_delete_all": "您要刪除此筆記的所有歷史版本嗎?", + "no_revisions": "尚無此筆記的歷史版本...", + "restore_button": "還原" } } From e5f97b6fdd35af201ade1cf4642e5cc954e78c18 Mon Sep 17 00:00:00 2001 From: green Date: Sat, 18 Apr 2026 05:14:25 +0200 Subject: [PATCH 390/482] Translated using Weblate (Japanese) Currently translated at 100.0% (116 of 116 strings) Translation: Trilium Notes/README Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ja/ --- docs/README-ja.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-ja.md b/docs/README-ja.md index 6804c08b7c..9f667bc589 100644 --- a/docs/README-ja.md +++ b/docs/README-ja.md @@ -63,7 +63,7 @@ Trilium Notes * ノートは任意の深さのツリーに配置できます。1つのノートをツリー内の複数の場所に配置できます([クローン](https://docs.triliumnotes.org/user-guide/concepts/notes/cloning)を参照) * 豊富な WYSIWYG ノートエディター 例: - 表、画像、[数式](https://docs.triliumnotes.org/user-guide/note-types/text) とマークダウン + 表、画像、[数式](https://docs.triliumnotes.org/user-guide/note-types/text) と markdown [自動フォーマット](https://docs.triliumnotes.org/user-guide/note-types/text/markdown-formatting) など * 構文ハイライト表示を含む From 1c508b830e4f20f3b2bf7375c8f01ea8e86a8719 Mon Sep 17 00:00:00 2001 From: green Date: Sat, 18 Apr 2026 05:12:40 +0200 Subject: [PATCH 391/482] Translated using Weblate (Japanese) Currently translated at 100.0% (404 of 404 strings) Translation: Trilium Notes/Server Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/ --- apps/server/src/assets/translations/ja/server.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/server/src/assets/translations/ja/server.json b/apps/server/src/assets/translations/ja/server.json index 2197272282..6e41b1934f 100644 --- a/apps/server/src/assets/translations/ja/server.json +++ b/apps/server/src/assets/translations/ja/server.json @@ -382,7 +382,8 @@ "migration": { "old_version": "現在のバージョンからの直接的な移行はサポートされていません。まず最新のv0.60.4にアップグレードしてから、このバージョンにアップグレードしてください。", "error_message": "バージョン {{version}} への移行中にエラーが発生しました: {{stack}}", - "wrong_db_version": "データベースのバージョン({{version}})は、アプリケーションが想定しているバージョン({{targetVersion}})よりも新しく、互換性のないバージョンによって作成された可能性があります。この問題を解決するには、Triliumを最新バージョンにアップグレードしてください。" + "wrong_db_version": "データベースのバージョン({{version}})は、アプリケーションが想定しているバージョン({{targetVersion}})よりも新しく、互換性のないバージョンによって作成された可能性があります。この問題を解決するには、Triliumを最新バージョンにアップグレードしてください。", + "invalid_db_version": "データベースのバージョン番号が無効です。これは通常、データベース内の 'dbVersion' オプションが破損していることを示しています。バックアップから復元してください。" }, "modals": { "error_title": "エラー" From 4b35881889a4e0209c470e3354b0a250a5d43769 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 12:46:13 +0300 Subject: [PATCH 392/482] feat(revisions): add a source field --- .../src/translations/en/translation.json | 7 ++++++- apps/client/src/widgets/dialogs/revisions.tsx | 18 +++++++++++++++++- apps/server/src/assets/db/schema.sql | 1 + apps/server/src/becca/entities/bnote.ts | 7 ++++--- apps/server/src/becca/entities/brevision.ts | 7 +++++-- apps/server/src/etapi/mappers.ts | 1 + apps/server/src/etapi/notes.ts | 2 +- apps/server/src/migrations/migrations.ts | 1 + apps/server/src/routes/api/notes.ts | 2 +- apps/server/src/routes/api/revisions.ts | 2 +- .../src/services/llm/tools/note_tools.ts | 4 ++-- packages/commons/src/lib/rows.ts | 4 ++++ packages/commons/src/lib/server_api.ts | 4 +++- 13 files changed, 47 insertions(+), 13 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 796e4c08fa..9fbf88bc26 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -310,7 +310,12 @@ "description_placeholder": "Add a description (optional)", "revision_saved": "Note revision has been saved.", "edit_description": "Edit description", - "description_updated": "Revision description has been updated." + "description_updated": "Revision description has been updated.", + "source_auto": "Auto", + "source_manual": "Manual", + "source_etapi": "ETAPI", + "source_llm": "LLM", + "source_restore": "Restore" }, "sort_child_notes": { "sort_children_by": "Sort children by...", diff --git a/apps/client/src/widgets/dialogs/revisions.tsx b/apps/client/src/widgets/dialogs/revisions.tsx index 06a44ed859..b3d3803960 100644 --- a/apps/client/src/widgets/dialogs/revisions.tsx +++ b/apps/client/src/widgets/dialogs/revisions.tsx @@ -200,7 +200,23 @@ function RevisionsList({ revisions, onSelect, currentRevision }: { revisions: Re active={currentRevision && item.revisionId === currentRevision.revisionId} >
    - {item.dateCreated && item.dateCreated.substr(0, 16)} ({item.contentLength && utils.formatSize(item.contentLength)}) +
    + {item.dateCreated && item.dateCreated.substr(0, 16)} + {item.source && item.source !== "auto" && ( + + {t(`revisions.source_${item.source}`)} + + )} +
    +
    + {item.contentLength && utils.formatSize(item.contentLength)} +
    {item.description && (
    {item.description} diff --git a/apps/server/src/assets/db/schema.sql b/apps/server/src/assets/db/schema.sql index 361a6ccdf4..60f0485471 100644 --- a/apps/server/src/assets/db/schema.sql +++ b/apps/server/src/assets/db/schema.sql @@ -49,6 +49,7 @@ CREATE TABLE IF NOT EXISTS "revisions" (`revisionId` TEXT NOT NULL PRIMARY KEY, mime TEXT DEFAULT '' NOT NULL, `title` TEXT NOT NULL, `description` TEXT DEFAULT '' NOT NULL, + `source` TEXT DEFAULT 'auto' NOT NULL, `isProtected` INT NOT NULL DEFAULT 0, blobId TEXT DEFAULT NULL, `utcDateLastEdited` TEXT NOT NULL, diff --git a/apps/server/src/becca/entities/bnote.ts b/apps/server/src/becca/entities/bnote.ts index 63b447c2b3..56251e76ea 100644 --- a/apps/server/src/becca/entities/bnote.ts +++ b/apps/server/src/becca/entities/bnote.ts @@ -1,4 +1,4 @@ -import type { AttachmentRow, AttributeType, CloneResponse, NoteRow, NoteType, RevisionRow } from "@triliumnext/commons"; +import type { AttachmentRow, AttributeType, CloneResponse, NoteRow, NoteType, RevisionRow, RevisionSource } from "@triliumnext/commons"; import { dayjs, getNoteIcon } from "@triliumnext/commons"; import cloningService from "../../services/cloning.js"; @@ -1543,7 +1543,7 @@ class BNote extends AbstractBeccaEntity { return !(this.noteId in this.becca.notes) || this.isBeingDeleted; } - saveRevision(description?: string): BRevision { + saveRevision(opts: { description?: string; source?: RevisionSource } = {}): BRevision { return sql.transactional(() => { let noteContent = this.getContent(); @@ -1552,7 +1552,8 @@ class BNote extends AbstractBeccaEntity { noteId: this.noteId, // title and text should be decrypted now title: this.title, - description: description || "", + description: opts.description || "", + source: opts.source || "auto", type: this.type, mime: this.mime, isProtected: this.isProtected, diff --git a/apps/server/src/becca/entities/brevision.ts b/apps/server/src/becca/entities/brevision.ts index d9bf2e1c72..4e90471cd2 100644 --- a/apps/server/src/becca/entities/brevision.ts +++ b/apps/server/src/becca/entities/brevision.ts @@ -7,7 +7,7 @@ import becca from "../becca.js"; import AbstractBeccaEntity from "./abstract_becca_entity.js"; import sql from "../../services/sql.js"; import BAttachment from "./battachment.js"; -import type { AttachmentRow, NoteType, RevisionPojo, RevisionRow } from "@triliumnext/commons"; +import type { AttachmentRow, NoteType, RevisionPojo, RevisionRow, RevisionSource } from "@triliumnext/commons"; import eraseService from "../../services/erase.js"; interface ContentOpts { @@ -31,7 +31,7 @@ class BRevision extends AbstractBeccaEntity { return "revisionId"; } static get hashedProperties() { - return ["revisionId", "noteId", "title", "description", "isProtected", "dateLastEdited", "dateCreated", "utcDateLastEdited", "utcDateCreated", "utcDateModified", "blobId"]; + return ["revisionId", "noteId", "title", "description", "source", "isProtected", "dateLastEdited", "dateCreated", "utcDateLastEdited", "utcDateCreated", "utcDateModified", "blobId"]; } revisionId?: string; @@ -40,6 +40,7 @@ class BRevision extends AbstractBeccaEntity { mime!: string; title!: string; description!: string; + source!: RevisionSource; dateLastEdited?: string; utcDateLastEdited?: string; contentLength?: number; @@ -63,6 +64,7 @@ class BRevision extends AbstractBeccaEntity { this.isProtected = !!row.isProtected; this.title = row.title; this.description = row.description || ""; + this.source = row.source || "auto"; this.blobId = row.blobId; this.dateLastEdited = row.dateLastEdited; this.dateCreated = row.dateCreated; @@ -196,6 +198,7 @@ class BRevision extends AbstractBeccaEntity { isProtected: this.isProtected, title: this.title, description: this.description, + source: this.source, blobId: this.blobId, dateLastEdited: this.dateLastEdited, dateCreated: this.dateCreated, diff --git a/apps/server/src/etapi/mappers.ts b/apps/server/src/etapi/mappers.ts index bff50af5c6..04e59b1000 100644 --- a/apps/server/src/etapi/mappers.ts +++ b/apps/server/src/etapi/mappers.ts @@ -74,6 +74,7 @@ function mapRevisionToPojo(revision: BRevision) { isProtected: revision.isProtected, title: revision.title, description: revision.description, + source: revision.source, blobId: revision.blobId, dateLastEdited: revision.dateLastEdited, dateCreated: revision.dateCreated, diff --git a/apps/server/src/etapi/notes.ts b/apps/server/src/etapi/notes.ts index 96206f2dc6..8edc583435 100644 --- a/apps/server/src/etapi/notes.ts +++ b/apps/server/src/etapi/notes.ts @@ -193,7 +193,7 @@ function register(router: Router) { const note = eu.getAndCheckNote(req.params.noteId); const description = req.body?.description || ""; - const revision = note.saveRevision(description); + const revision = note.saveRevision({ description, source: "etapi" }); res.status(201).json(mappers.mapRevisionToPojo(revision)); }); diff --git a/apps/server/src/migrations/migrations.ts b/apps/server/src/migrations/migrations.ts index 93b25be8f1..0c9dd4e8d1 100644 --- a/apps/server/src/migrations/migrations.ts +++ b/apps/server/src/migrations/migrations.ts @@ -11,6 +11,7 @@ const MIGRATIONS: (SqlMigration | JsMigration)[] = [ version: 238, sql: /*sql*/` ALTER TABLE revisions ADD COLUMN description TEXT DEFAULT '' NOT NULL; + ALTER TABLE revisions ADD COLUMN source TEXT DEFAULT 'auto' NOT NULL; `, ignoreErrors: true }, diff --git a/apps/server/src/routes/api/notes.ts b/apps/server/src/routes/api/notes.ts index 9cca431f91..8aec006a09 100644 --- a/apps/server/src/routes/api/notes.ts +++ b/apps/server/src/routes/api/notes.ts @@ -352,7 +352,7 @@ function forceSaveRevision(req: Request<{ noteId: string }>) { } const description = req.body?.description || ""; - const revision = note.saveRevision(description); + const revision = note.saveRevision({ description, source: "manual" }); return { revisionId: revision.revisionId diff --git a/apps/server/src/routes/api/revisions.ts b/apps/server/src/routes/api/revisions.ts index 8598810791..12e1c990ac 100644 --- a/apps/server/src/routes/api/revisions.ts +++ b/apps/server/src/routes/api/revisions.ts @@ -137,7 +137,7 @@ function restoreRevision(req: Request<{ revisionId: string }>) { const note = revision.getNote(); sql.transactional(() => { - note.saveRevision(); + note.saveRevision({ source: "restore" }); for (const oldNoteAttachment of note.getAttachments()) { oldNoteAttachment.markAsDeleted(); diff --git a/apps/server/src/services/llm/tools/note_tools.ts b/apps/server/src/services/llm/tools/note_tools.ts index 8a354175f3..d1ce83e3e0 100644 --- a/apps/server/src/services/llm/tools/note_tools.ts +++ b/apps/server/src/services/llm/tools/note_tools.ts @@ -116,7 +116,7 @@ export const noteTools = defineTools({ return { error: `Cannot update content for note type: ${note.type}` }; } - note.saveRevision(); + note.saveRevision({ source: "llm" }); setNoteContentFromLlm(note, content); return { success: true, @@ -158,7 +158,7 @@ export const noteTools = defineTools({ newContent = existingContent + (existingContent.endsWith("\n") ? "" : "\n") + content; } - note.saveRevision(); + note.saveRevision({ source: "llm" }); note.setContent(newContent); return { success: true, diff --git a/packages/commons/src/lib/rows.ts b/packages/commons/src/lib/rows.ts index 977120c21f..5f198aa02f 100644 --- a/packages/commons/src/lib/rows.ts +++ b/packages/commons/src/lib/rows.ts @@ -21,6 +21,9 @@ export interface AttachmentRow { encoding?: "base64"; } +export const REVISION_SOURCES = ["auto", "manual", "etapi", "llm", "restore"] as const; +export type RevisionSource = (typeof REVISION_SOURCES)[number]; + export interface RevisionRow { revisionId?: string; noteId: string; @@ -29,6 +32,7 @@ export interface RevisionRow { isProtected?: boolean; title: string; description?: string; + source?: RevisionSource; blobId?: string; dateLastEdited?: string; dateCreated?: string; diff --git a/packages/commons/src/lib/server_api.ts b/packages/commons/src/lib/server_api.ts index c43b155094..63e5c63680 100644 --- a/packages/commons/src/lib/server_api.ts +++ b/packages/commons/src/lib/server_api.ts @@ -1,4 +1,4 @@ -import { AttachmentRow, AttributeRow, BranchRow, NoteRow, NoteType } from "./rows.js"; +import { AttachmentRow, AttributeRow, BranchRow, NoteRow, NoteType, RevisionSource } from "./rows.js"; type Response = { success: true, @@ -34,6 +34,7 @@ export interface RevisionItem { type: NoteType; title: string; description?: string; + source?: RevisionSource; isProtected?: boolean; mime: string; } @@ -46,6 +47,7 @@ export interface RevisionPojo { isProtected?: boolean; title: string; description?: string; + source?: RevisionSource; blobId?: string; dateLastEdited?: string; dateCreated?: string; From 62189cfa0497900aef23ba18ef355cfdb10595a1 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 12:48:03 +0300 Subject: [PATCH 393/482] refactor(revisions): extract inline styles to CSS --- apps/client/src/widgets/dialogs/revisions.css | 67 +++++++++++++++++++ apps/client/src/widgets/dialogs/revisions.tsx | 27 +++----- 2 files changed, 76 insertions(+), 18 deletions(-) diff --git a/apps/client/src/widgets/dialogs/revisions.css b/apps/client/src/widgets/dialogs/revisions.css index 7d02c9cdbb..0f1ffe0314 100644 --- a/apps/client/src/widgets/dialogs/revisions.css +++ b/apps/client/src/widgets/dialogs/revisions.css @@ -71,6 +71,73 @@ body.mobile .revisions-dialog { flex-shrink: 0; } + .save-revision-controls { + display: flex; + gap: 5px; + align-items: center; + margin-inline-end: 10px; + + .save-revision-input { + width: 200px; + } + } + + .revision-item-header { + display: flex; + justify-content: space-between; + align-items: center; + gap: 4px; + } + + .revision-source-badge { + font-size: 0.75em; + padding: 0 4px; + border-radius: 3px; + background-color: var(--accented-background-color); + white-space: nowrap; + } + + .revision-item-size { + font-size: 0.85em; + opacity: 0.7; + } + + .revision-item-description { + font-size: 0.85em; + opacity: 0.7; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .revision-description-editor { + display: flex; + gap: 5px; + align-items: center; + margin: 3px 0; + + input { + flex-grow: 1; + } + } + + .revision-description-display { + display: flex; + align-items: center; + margin: 3px 0; + gap: 5px; + min-height: 24px; + } + + .revision-description-text { + font-size: 0.9em; + + &.empty { + opacity: 0.5; + font-style: italic; + } + } + .revision-content.type-file { display: flex; min-width: 0; diff --git a/apps/client/src/widgets/dialogs/revisions.tsx b/apps/client/src/widgets/dialogs/revisions.tsx index b3d3803960..9e6bde84d0 100644 --- a/apps/client/src/widgets/dialogs/revisions.tsx +++ b/apps/client/src/widgets/dialogs/revisions.tsx @@ -164,21 +164,19 @@ function SaveRevisionButton({ noteId, onSaved }: { noteId: string, onSaved: () = const [ description, setDescription ] = useState(""); return ( -
    +
    setDescription((e.target as HTMLInputElement).value)} - style={{ width: "200px" }} />
    +
    )} +
    +

    {revisionItem?.title ?? t("revisions.no_revisions")}

    + {revisionItem && ( +
    + {canShowDiff && ( + setShowDiff(newValue)} + switchOnName={t("revisions.highlight_changes")} + switchOffName={t("revisions.highlight_changes")} + /> + )} + {canInteract && canShowDiff &&
    } + {canInteract && ( + <> + { + if (await dialog.confirm(t("revisions.confirm_delete"))) { + await server.remove(`revisions/${revisionItem.revisionId}`); + toast.showMessage(t("revisions.revision_deleted")); + onRevisionDeleted?.(); + } + }} frame /> + { + if (revisionItem.revisionId) { + open.downloadRevision(revisionItem.noteId, revisionItem.revisionId); + } + }} + frame /> +
    + )}
    {revisionItem && ( Date: Sat, 18 Apr 2026 14:18:29 +0300 Subject: [PATCH 404/482] feat(revisions): group less used options into overflow menu --- .../src/translations/en/translation.json | 5 + apps/client/src/widgets/dialogs/revisions.css | 7 + apps/client/src/widgets/dialogs/revisions.tsx | 151 ++++++++++-------- 3 files changed, 92 insertions(+), 71 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index b20878120e..ab97764f30 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -301,7 +301,12 @@ "revision_deleted": "Note revision has been deleted.", "snapshot_interval": "Note Revision Snapshot Interval: {{seconds}}s.", "maximum_revisions": "Note Revision Snapshot Limit: {{number}}.", + "save_revision_now": "Save a revision now", + "snapshot_header": "Note revision snapshot", + "snapshot_interval_value": "Interval: {{seconds}}s", + "snapshot_limit_value": "Limit: {{number}}", "settings": "Note Revision Settings", + "menu_tooltip": "Revision options", "download_button": "Download", "mime": "MIME: ", "file_size": "File size:", diff --git a/apps/client/src/widgets/dialogs/revisions.css b/apps/client/src/widgets/dialogs/revisions.css index a9532ee0b4..6ed412ae01 100644 --- a/apps/client/src/widgets/dialogs/revisions.css +++ b/apps/client/src/widgets/dialogs/revisions.css @@ -87,6 +87,13 @@ body.mobile .revisions-dialog { flex-shrink: 0; } + .revision-menu-header { + font-weight: bold; + font-size: 0.85em; + text-transform: uppercase; + opacity: 0.6; + } + .revision-toolbar-separator { width: 1px; height: 1.2em; diff --git a/apps/client/src/widgets/dialogs/revisions.tsx b/apps/client/src/widgets/dialogs/revisions.tsx index 66b6d67cfb..3cf3c352e4 100644 --- a/apps/client/src/widgets/dialogs/revisions.tsx +++ b/apps/client/src/widgets/dialogs/revisions.tsx @@ -21,7 +21,8 @@ import toast from "../../services/toast"; import utils from "../../services/utils"; import ActionButton from "../react/ActionButton"; import Button from "../react/Button"; -import FormList, { FormListItem } from "../react/FormList"; +import Dropdown from "../react/Dropdown"; +import FormList, { FormDropdownDivider, FormListItem } from "../react/FormList"; import FormToggle from "../react/FormToggle"; import { useTriliumEvent } from "../react/hooks"; import Modal from "../react/Modal"; @@ -66,38 +67,20 @@ export default function RevisionsDialog() { title={t("revisions.note_revisions")} helpPageId="vZWERwf8U3nx" bodyStyle={{ display: "flex", height: "80vh" }} - header={ - <> - {note && ( - { - setRefreshCounter(c => c + 1); - setCurrentRevision(undefined); - }} - /> - )} - {!!revisions?.length && ( - + )} + + {titleBarButtons?.filter((b) => b !== null).map((titleBarButton) => ( +
    + + {onSubmit ? ( +
    { + e.preventDefault(); + onSubmit(); + }}> + {children} +
    ) : ( - title + + {children} + )} - {header} - {helpPageId && ( - - )} - - {titleBarButtons?.filter((b) => b !== null).map((titleBarButton) => ( -
    - - {onSubmit ? ( -
    { - e.preventDefault(); - onSubmit(); - }}> - {children} -
    - ) : ( - - {children} - - )}
    }
    From f9310c5cde12afb93b2e792a363d45464f794bea Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 17:00:19 +0300 Subject: [PATCH 419/482] feat(revisions): improve title display --- apps/client/src/stylesheets/style.css | 2 +- apps/client/src/widgets/dialogs/revisions.css | 29 +++++++++++++++---- apps/client/src/widgets/dialogs/revisions.tsx | 27 ++++++++++------- 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/apps/client/src/stylesheets/style.css b/apps/client/src/stylesheets/style.css index 1babd999fe..abc59d99c3 100644 --- a/apps/client/src/stylesheets/style.css +++ b/apps/client/src/stylesheets/style.css @@ -1166,8 +1166,8 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href display: flex; flex-direction: column; border-right: 1px solid var(--main-border-color); - overflow: auto; flex-shrink: 0; + min-height: 0; } .modal-content-with-sidebar > .modal-main { diff --git a/apps/client/src/widgets/dialogs/revisions.css b/apps/client/src/widgets/dialogs/revisions.css index 2a7eb8137a..a3ca80de8d 100644 --- a/apps/client/src/widgets/dialogs/revisions.css +++ b/apps/client/src/widgets/dialogs/revisions.css @@ -72,6 +72,27 @@ body.desktop .revisions-dialog { padding: 0; } + .modal-sidebar { + background-color: var(--card-background-color); + } + + .modal-sidebar .dropdown-menu.static { + background-color: transparent !important; + border-radius: 0 !important; + padding-top: 0 !important; + } + + .revision-sidebar-header { + padding: 0.75rem 1rem; + flex-shrink: 0; + text-align: center; + + h5 { + margin: 0; + font-size: 1em; + } + } + .revision-toolbar { display: flex; align-items: center; @@ -124,11 +145,9 @@ body.desktop .revisions-dialog { } .revision-list { - flex-shrink: 0; - - .dropdown-item + .dropdown-item { - border-top: 1px solid var(--main-border-color) !important; - } + flex: 1 1 0; + min-height: 0; + overflow: auto; .dropdown-item { min-height: 2.5em; diff --git a/apps/client/src/widgets/dialogs/revisions.tsx b/apps/client/src/widgets/dialogs/revisions.tsx index 9af385a589..c34b4618c2 100644 --- a/apps/client/src/widgets/dialogs/revisions.tsx +++ b/apps/client/src/widgets/dialogs/revisions.tsx @@ -65,7 +65,7 @@ export default function RevisionsDialog() { )} sidebar={ - { - const correspondingRevision = (revisions ?? []).find((r) => r.revisionId === revisionId); - if (correspondingRevision) { - setCurrentRevision(correspondingRevision); - } - }} - currentRevision={currentRevision} - /> + <> +
    +
    {t("revisions.note_revisions")}
    +
    + { + const correspondingRevision = (revisions ?? []).find((r) => r.revisionId === revisionId); + if (correspondingRevision) { + setCurrentRevision(correspondingRevision); + } + }} + currentRevision={currentRevision} + /> + } onHidden={() => { setShown(false); From bd30e9efc169b2a8c9ba08f5cc63c5eb7e012475 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 17:11:22 +0300 Subject: [PATCH 420/482] feat(revisions): declutter the header --- apps/client/src/widgets/dialogs/revisions.css | 38 ++--- apps/client/src/widgets/dialogs/revisions.tsx | 146 ++++++++++-------- 2 files changed, 95 insertions(+), 89 deletions(-) diff --git a/apps/client/src/widgets/dialogs/revisions.css b/apps/client/src/widgets/dialogs/revisions.css index a3ca80de8d..e3240635a6 100644 --- a/apps/client/src/widgets/dialogs/revisions.css +++ b/apps/client/src/widgets/dialogs/revisions.css @@ -70,6 +70,8 @@ body.desktop .revisions-dialog { .revisions-dialog { .modal-body { padding: 0; + display: flex; + flex-direction: column; } .modal-sidebar { @@ -94,27 +96,20 @@ body.desktop .revisions-dialog { } .revision-toolbar { - display: flex; - align-items: center; - gap: 4px; flex-shrink: 0; - - .revision-title { - font-size: 1.2em; - margin: 3px; - flex-grow: 1; - min-width: 0; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } + border-bottom: 1px solid var(--main-border-color); + padding: 8px 20px; } - .revision-title-buttons { + .revision-title { + font-size: 1.2em; + margin: 8px 0; + } + + .revision-toolbar-actions { display: flex; align-items: center; gap: 4px; - flex-shrink: 0; } .revision-menu-header { @@ -134,15 +129,16 @@ body.desktop .revisions-dialog { display: flex; flex-direction: column; min-width: 0; + min-height: 0; + } + + .revision-content { + flex-grow: 1; + min-height: 0; overflow: auto; } - .revision-toolbar-separator { - width: 1px; - height: 1.2em; - background-color: var(--main-border-color); - margin: 0 4px; - } + .revision-list { flex: 1 1 0; diff --git a/apps/client/src/widgets/dialogs/revisions.tsx b/apps/client/src/widgets/dialogs/revisions.tsx index c34b4618c2..2e073f349f 100644 --- a/apps/client/src/widgets/dialogs/revisions.tsx +++ b/apps/client/src/widgets/dialogs/revisions.tsx @@ -107,17 +107,21 @@ export default function RevisionsDialog() { }} show={shown} > + { + setRefreshCounter(c => c + 1); + setCurrentRevision(undefined); + }} + />
    { - setRefreshCounter(c => c + 1); - setCurrentRevision(undefined); - }} onDescriptionUpdated={(revisionId, description) => { setRevisions(prev => prev?.map(r => r.revisionId === revisionId ? { ...r, description } : r @@ -297,13 +301,72 @@ function RevisionsList({ revisions, onSelect, currentRevision }: { revisions: Re ); } -function RevisionPreview({noteContent, revisionItem, showDiff, setShowDiff, setShown, onRevisionDeleted, onDescriptionUpdated }: { - noteContent?: string, +function RevisionToolbar({ revisionItem, showDiff, setShowDiff, setShown, onRevisionDeleted }: { revisionItem?: RevisionItem, showDiff: boolean, setShowDiff: Dispatch>, setShown: Dispatch>, onRevisionDeleted?: () => void, +}) { + const canShowDiff = ["text", "code", "mermaid"].includes(revisionItem?.type ?? ""); + const canInteract = revisionItem && (!revisionItem.isProtected || protected_session_holder.isProtectedSessionAvailable()); + + return ( +
    + {revisionItem && ( +
    + {canShowDiff && ( + setShowDiff(newValue)} + switchOnName={t("revisions.highlight_changes")} + switchOffName={t("revisions.highlight_changes")} + /> + )} +
    + {canInteract && ( + <> + { + if (await dialog.confirm(t("revisions.confirm_delete"))) { + await server.remove(`revisions/${revisionItem.revisionId}`); + toast.showMessage(t("revisions.revision_deleted")); + onRevisionDeleted?.(); + } + }} frame /> + { + if (revisionItem.revisionId) { + open.downloadRevision(revisionItem.noteId, revisionItem.revisionId); + } + }} + frame /> +
    + )} +
    + ); +} + +function RevisionPreview({noteContent, revisionItem, showDiff, onDescriptionUpdated }: { + noteContent?: string, + revisionItem?: RevisionItem, + showDiff: boolean, onDescriptionUpdated?: (revisionId: string, description: string) => void }) { const [ fullRevision, setFullRevision ] = useState(); @@ -319,60 +382,12 @@ function RevisionPreview({noteContent, revisionItem, showDiff, setShowDiff, setS setEditingDescription(false); }, [revisionItem]); - const canShowDiff = ["text", "code", "mermaid"].includes(revisionItem?.type ?? ""); - const canInteract = revisionItem && (!revisionItem.isProtected || protected_session_holder.isProtectedSessionAvailable()); - return ( - <> -
    -

    {revisionItem?.title ?? t("revisions.no_revisions")}

    - {revisionItem && ( -
    - {canShowDiff && ( - setShowDiff(newValue)} - switchOnName={t("revisions.highlight_changes")} - switchOffName={t("revisions.highlight_changes")} - /> - )} - {canInteract && canShowDiff &&
    } - {canInteract && ( - <> - { - if (await dialog.confirm(t("revisions.confirm_delete"))) { - await server.remove(`revisions/${revisionItem.revisionId}`); - toast.showMessage(t("revisions.revision_deleted")); - onRevisionDeleted?.(); - } - }} frame /> - { - if (revisionItem.revisionId) { - open.downloadRevision(revisionItem.noteId, revisionItem.revisionId); - } - }} - frame /> -
    - )} -
    +
    +

    {revisionItem?.title ?? t("revisions.no_revisions")}

    {revisionItem && ( setEditingDescription(false)} /> )} -
    - -
    - + +
    ); } From fb5520a3c5f4f7abcc1fb8f0ac7c84448752fc4a Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 17:17:02 +0300 Subject: [PATCH 421/482] feat(revisions): relocate the description --- apps/client/src/widgets/dialogs/revisions.css | 5 ++ apps/client/src/widgets/dialogs/revisions.tsx | 82 ++++++++++--------- 2 files changed, 49 insertions(+), 38 deletions(-) diff --git a/apps/client/src/widgets/dialogs/revisions.css b/apps/client/src/widgets/dialogs/revisions.css index e3240635a6..b61cced865 100644 --- a/apps/client/src/widgets/dialogs/revisions.css +++ b/apps/client/src/widgets/dialogs/revisions.css @@ -177,6 +177,11 @@ body.desktop .revisions-dialog { } + .revision-description-icon { + opacity: 0.5; + flex-shrink: 0; + } + .revision-description-editor { display: flex; gap: 5px; diff --git a/apps/client/src/widgets/dialogs/revisions.tsx b/apps/client/src/widgets/dialogs/revisions.tsx index 2e073f349f..3578599151 100644 --- a/apps/client/src/widgets/dialogs/revisions.tsx +++ b/apps/client/src/widgets/dialogs/revisions.tsx @@ -116,20 +116,21 @@ export default function RevisionsDialog() { setRefreshCounter(c => c + 1); setCurrentRevision(undefined); }} + onDescriptionUpdated={(revisionId, description) => { + setRevisions(prev => prev?.map(r => + r.revisionId === revisionId ? { ...r, description } : r + )); + if (currentRevision?.revisionId === revisionId) { + setCurrentRevision({ ...currentRevision, description }); + } + }} />
    { - setRevisions(prev => prev?.map(r => - r.revisionId === revisionId ? { ...r, description } : r - )); - if (currentRevision?.revisionId === revisionId) { - setCurrentRevision({ ...currentRevision, description }); - } - }} /> + />
    ); @@ -301,15 +302,22 @@ function RevisionsList({ revisions, onSelect, currentRevision }: { revisions: Re ); } -function RevisionToolbar({ revisionItem, showDiff, setShowDiff, setShown, onRevisionDeleted }: { +function RevisionToolbar({ revisionItem, showDiff, setShowDiff, setShown, onRevisionDeleted, onDescriptionUpdated }: { revisionItem?: RevisionItem, showDiff: boolean, setShowDiff: Dispatch>, setShown: Dispatch>, onRevisionDeleted?: () => void, + onDescriptionUpdated?: (revisionId: string, description: string) => void, }) { const canShowDiff = ["text", "code", "mermaid"].includes(revisionItem?.type ?? ""); const canInteract = revisionItem && (!revisionItem.isProtected || protected_session_holder.isProtectedSessionAvailable()); + const [ editingDescription, setEditingDescription ] = useState(false); + const [ descriptionDraft, setDescriptionDraft ] = useState(""); + + useEffect(() => { + setEditingDescription(false); + }, [revisionItem]); return (
    @@ -359,35 +367,6 @@ function RevisionToolbar({ revisionItem, showDiff, setShowDiff, setShown, onRevi )}
    )} -
    - ); -} - -function RevisionPreview({noteContent, revisionItem, showDiff, onDescriptionUpdated }: { - noteContent?: string, - revisionItem?: RevisionItem, - showDiff: boolean, - onDescriptionUpdated?: (revisionId: string, description: string) => void -}) { - const [ fullRevision, setFullRevision ] = useState(); - const [ editingDescription, setEditingDescription ] = useState(false); - const [ descriptionDraft, setDescriptionDraft ] = useState(""); - - useEffect(() => { - if (revisionItem) { - server.get(`revisions/${revisionItem.revisionId}`).then(setFullRevision); - } else { - setFullRevision(undefined); - } - setEditingDescription(false); - }, [revisionItem]); - - return ( -
    -

    {revisionItem?.title ?? t("revisions.no_revisions")}

    {revisionItem && ( setEditingDescription(false)} /> )} +
    + ); +} + +function RevisionPreview({noteContent, revisionItem, showDiff }: { + noteContent?: string, + revisionItem?: RevisionItem, + showDiff: boolean, +}) { + const [ fullRevision, setFullRevision ] = useState(); + + useEffect(() => { + if (revisionItem) { + server.get(`revisions/${revisionItem.revisionId}`).then(setFullRevision); + } else { + setFullRevision(undefined); + } + }, [revisionItem]); + + return ( +
    +

    {revisionItem?.title ?? t("revisions.no_revisions")}

    ); @@ -424,6 +428,7 @@ function RevisionDescription({ revisionItem, editing, draft, onEdit, onDraftChan if (editing) { return (
    + + {revisionItem.description || t("revisions.description_placeholder")} From f4cf8829f7a10a829f744c51420876c43eed2783 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 17:23:07 +0300 Subject: [PATCH 422/482] feat(revisions): improve the layout even further & rebrand description to name --- apps/client/src/translations/en/translation.json | 6 +++--- apps/client/src/widgets/dialogs/revisions.css | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index e417e39386..0367588547 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -313,10 +313,10 @@ "preview_not_available": "Preview isn't available for this note type.", "save_revision": "Save revision", "save_revision_tooltip": "Manually save a snapshot of the current note", - "description_placeholder": "Add a description (optional)", + "description_placeholder": "Name this revision", "revision_saved": "Note revision has been saved.", - "edit_description": "Edit description", - "description_updated": "Revision description has been updated.", + "edit_description": "Edit name", + "description_updated": "Revision name has been updated.", "source_auto": "Auto-save", "source_manual": "Manual save", "source_etapi": "ETAPI", diff --git a/apps/client/src/widgets/dialogs/revisions.css b/apps/client/src/widgets/dialogs/revisions.css index b61cced865..378d24c391 100644 --- a/apps/client/src/widgets/dialogs/revisions.css +++ b/apps/client/src/widgets/dialogs/revisions.css @@ -81,13 +81,13 @@ body.desktop .revisions-dialog { .modal-sidebar .dropdown-menu.static { background-color: transparent !important; border-radius: 0 !important; - padding-top: 0 !important; } .revision-sidebar-header { padding: 0.75rem 1rem; flex-shrink: 0; text-align: center; + border-bottom: 1px solid var(--main-border-color); h5 { margin: 0; @@ -125,7 +125,6 @@ body.desktop .revisions-dialog { .revision-content-wrapper { flex-grow: 1; - padding-inline: 20px; display: flex; flex-direction: column; min-width: 0; @@ -136,6 +135,7 @@ body.desktop .revisions-dialog { flex-grow: 1; min-height: 0; overflow: auto; + padding: 20px; } From a2cd75c2c485985f9952c0e2089bfa569f147e64 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 17:36:31 +0300 Subject: [PATCH 423/482] feat(revisions): preserve monospace for code notes diff --- apps/client/src/widgets/dialogs/revisions.css | 9 +++++++++ apps/client/src/widgets/dialogs/revisions.tsx | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/client/src/widgets/dialogs/revisions.css b/apps/client/src/widgets/dialogs/revisions.css index 378d24c391..6ed398c149 100644 --- a/apps/client/src/widgets/dialogs/revisions.css +++ b/apps/client/src/widgets/dialogs/revisions.css @@ -210,6 +210,15 @@ body.desktop .revisions-dialog { } } + .revision-diff-code { + font-family: var(--font-family-monospace, monospace); + font-size: 0.9rem; + white-space: pre-wrap; + word-break: break-all; + max-width: 100%; + padding: 0; + } + /* HTML diff styles (htmldiff-js) */ .revision-diff-content { ins { diff --git a/apps/client/src/widgets/dialogs/revisions.tsx b/apps/client/src/widgets/dialogs/revisions.tsx index 3578599151..0b72b2e1e3 100644 --- a/apps/client/src/widgets/dialogs/revisions.tsx +++ b/apps/client/src/widgets/dialogs/revisions.tsx @@ -488,7 +488,7 @@ function RevisionContent({ noteContent, revisionItem, fullRevision, showDiff }: case "text": return ; case "code": - return
    {content}
    ; + return
    {content}
    ; case "image": switch (revisionItem.mime) { case "image/svg+xml": { @@ -571,7 +571,7 @@ function RevisionContentDiff({ noteContent, itemContent, itemType }: { } }, [noteContent, itemContent, itemType]); - return
    ; + return
    ; } From ffe60580dbba8badbc7afb8a962df3ce1c005631 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 17:55:03 +0300 Subject: [PATCH 424/482] fix(revisions): layout on mobile --- apps/client/src/stylesheets/style.css | 51 +++++++++++++++ apps/client/src/widgets/dialogs/revisions.css | 63 ++----------------- apps/client/src/widgets/dialogs/revisions.tsx | 27 ++++---- apps/client/src/widgets/react/Modal.tsx | 7 ++- 4 files changed, 73 insertions(+), 75 deletions(-) diff --git a/apps/client/src/stylesheets/style.css b/apps/client/src/stylesheets/style.css index abc59d99c3..1fdfe9aeea 100644 --- a/apps/client/src/stylesheets/style.css +++ b/apps/client/src/stylesheets/style.css @@ -1170,6 +1170,31 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href min-height: 0; } +.modal-content-with-sidebar .modal-sidebar-header { + padding: 0.75rem 1rem; + flex-shrink: 0; + text-align: center; + border-bottom: 1px solid var(--main-border-color); +} + +.modal-content-with-sidebar .modal-sidebar-header h5 { + margin: 0; + font-size: 1em; +} + +.modal-content-with-sidebar > .modal-main > .modal-header > .modal-title { + visibility: hidden; + flex-grow: 1; + width: 0; + padding: 0; + margin: 0; + overflow: hidden; +} + +.modal-content-with-sidebar > .modal-main > .modal-header { + flex-wrap: nowrap; +} + .modal-content-with-sidebar > .modal-main { display: flex; flex-direction: column; @@ -1185,6 +1210,32 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href min-height: 0; } +body.mobile .modal-content-with-sidebar { + flex-direction: column !important; +} + +body.mobile .modal-content-with-sidebar > .modal-sidebar { + border-right: none; + border-bottom: 1px solid var(--main-border-color); + height: 30vh; + flex-shrink: 0; + overflow: hidden; + order: 1; +} + +body.mobile .modal-content-with-sidebar > .modal-main { + order: 0; +} + +body.mobile .modal-content-with-sidebar .modal-sidebar-header { + display: none; +} + +body.mobile .modal-content-with-sidebar > .modal-main > .modal-header > .modal-title { + visibility: visible; + width: auto; +} + .ck-mentions .ck-button { font-size: var(--detail-font-size) !important; padding: 5px; diff --git a/apps/client/src/widgets/dialogs/revisions.css b/apps/client/src/widgets/dialogs/revisions.css index 6ed398c149..ca938047c2 100644 --- a/apps/client/src/widgets/dialogs/revisions.css +++ b/apps/client/src/widgets/dialogs/revisions.css @@ -3,61 +3,20 @@ body.mobile .revisions-dialog { height: 95vh; } - .modal-header { - display: flex; - flex-wrap: wrap; - gap: 0.25em; - font-size: 0.9em; - } - - .modal-title { - flex-grow: 1; - width: 100%; - } - - .modal-body { - height: fit-content !important; - flex-direction: column; - } - .modal-footer { font-size: 0.9em; } - .revision-list { - height: fit-content !important; - max-height: 20vh; - border-bottom: 1px solid var(--main-border-color) !important; - padding: 0 1em; - flex-shrink: 0; - } - - .modal-body > .revision-content-wrapper { - flex-grow: 1; - max-width: unset !important; - height: 100%; - margin: 0; - display: block !important; - } - - .modal-body > .revision-content-wrapper > div:first-of-type { - flex-direction: column; - } - .revision-title { font-size: 1rem; } - .revision-title-buttons { - text-align: center; - display: flex; - gap: 0.25em; + .revision-toolbar-actions { flex-wrap: wrap; } .revision-content { padding: 0.5em; - height: fit-content; } } @@ -65,6 +24,10 @@ body.desktop .revisions-dialog { .revision-list { width: 300px; } + + .modal-content { + height: 80vh; + } } .revisions-dialog { @@ -83,18 +46,6 @@ body.desktop .revisions-dialog { border-radius: 0 !important; } - .revision-sidebar-header { - padding: 0.75rem 1rem; - flex-shrink: 0; - text-align: center; - border-bottom: 1px solid var(--main-border-color); - - h5 { - margin: 0; - font-size: 1em; - } - } - .revision-toolbar { flex-shrink: 0; border-bottom: 1px solid var(--main-border-color); @@ -119,10 +70,6 @@ body.desktop .revisions-dialog { opacity: 0.6; } - .modal-content { - height: 80vh; - } - .revision-content-wrapper { flex-grow: 1; display: flex; diff --git a/apps/client/src/widgets/dialogs/revisions.tsx b/apps/client/src/widgets/dialogs/revisions.tsx index 0b72b2e1e3..3fdd9d0952 100644 --- a/apps/client/src/widgets/dialogs/revisions.tsx +++ b/apps/client/src/widgets/dialogs/revisions.tsx @@ -65,7 +65,7 @@ export default function RevisionsDialog() { )} sidebar={ - <> -
    -
    {t("revisions.note_revisions")}
    -
    - { - const correspondingRevision = (revisions ?? []).find((r) => r.revisionId === revisionId); - if (correspondingRevision) { - setCurrentRevision(correspondingRevision); - } - }} - currentRevision={currentRevision} - /> - + { + const correspondingRevision = (revisions ?? []).find((r) => r.revisionId === revisionId); + if (correspondingRevision) { + setCurrentRevision(correspondingRevision); + } + }} + currentRevision={currentRevision} + /> } onHidden={() => { setShown(false); diff --git a/apps/client/src/widgets/react/Modal.tsx b/apps/client/src/widgets/react/Modal.tsx index eaef4c2fa9..674729b7bc 100644 --- a/apps/client/src/widgets/react/Modal.tsx +++ b/apps/client/src/widgets/react/Modal.tsx @@ -151,7 +151,12 @@ export default function Modal({ children, className, size, title, customTitleBar
    {(show || keepInDom) &&
    - {sidebar &&
    {sidebar}
    } + {sidebar &&
    + {title &&
    +
    {typeof title === "string" ? title : title}
    +
    } + {sidebar} +
    }
    {!title || typeof title === "string" ? ( From dabbbbb874229863f91ed435b510762d8db31e54 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 18:01:34 +0300 Subject: [PATCH 425/482] fix(revisions): context menu on mobile + regression in tab switcher --- apps/client/src/widgets/dialogs/revisions.tsx | 2 ++ apps/client/src/widgets/react/Modal.tsx | 11 +++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/client/src/widgets/dialogs/revisions.tsx b/apps/client/src/widgets/dialogs/revisions.tsx index 3fdd9d0952..2fddb65ac3 100644 --- a/apps/client/src/widgets/dialogs/revisions.tsx +++ b/apps/client/src/widgets/dialogs/revisions.tsx @@ -152,6 +152,8 @@ function RevisionsMenu({ note, onRevisionSaved, onAllDeleted, hasRevisions }: { buttonClassName="custom-title-bar-button" noSelectButtonStyle buttonProps={{ title: t("revisions.menu_tooltip") }} + dropdownContainerClassName="mobile-bottom-menu" + dropdownOptions={{ popperConfig: { strategy: "fixed" } }} > } {sidebar}
    } -
    +
    {!title || typeof title === "string" ? (
    {title ?? <> }
    @@ -192,13 +192,20 @@ export default function Modal({ children, className, size, title, customTitleBar {children} )} -
    +
    }
    ); } +function ModalMain({ sidebar, children }: { sidebar: boolean; children: ComponentChildren }) { + if (sidebar) { + return
    {children}
    ; + } + return <>{children}; +} + function ModalInner({ children, footer, footerAlignment, bodyStyle, footerStyle: _footerStyle }: Pick) { // Memoize footer style const footerStyle = useMemo(() => { From da96d2bc88e3507cd151358c5bb64672aa2935bd Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 18:08:11 +0300 Subject: [PATCH 426/482] feat(revisions): dedicated no revisions modal --- apps/client/src/widgets/dialogs/revisions.css | 6 ++- apps/client/src/widgets/dialogs/revisions.tsx | 52 +++++++++++++++---- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/apps/client/src/widgets/dialogs/revisions.css b/apps/client/src/widgets/dialogs/revisions.css index ca938047c2..0985839c04 100644 --- a/apps/client/src/widgets/dialogs/revisions.css +++ b/apps/client/src/widgets/dialogs/revisions.css @@ -25,7 +25,7 @@ body.desktop .revisions-dialog { width: 300px; } - .modal-content { + .modal-content-with-sidebar { height: 80vh; } } @@ -85,7 +85,9 @@ body.desktop .revisions-dialog { padding: 20px; } - + .no-items { + padding-block: 3em; + } .revision-list { flex: 1 1 0; diff --git a/apps/client/src/widgets/dialogs/revisions.tsx b/apps/client/src/widgets/dialogs/revisions.tsx index 2fddb65ac3..e9f67d88f5 100644 --- a/apps/client/src/widgets/dialogs/revisions.tsx +++ b/apps/client/src/widgets/dialogs/revisions.tsx @@ -27,6 +27,7 @@ import FormList, { FormDropdownDivider, FormListItem } from "../react/FormList"; import FormToggle from "../react/FormToggle"; import { useTriliumEvent } from "../react/hooks"; import Modal from "../react/Modal"; +import NoItems from "../react/NoItems"; import { RawHtmlBlock } from "../react/RawHtml"; import PdfViewer from "../type_widgets/file/PdfViewer"; @@ -57,10 +58,49 @@ export default function RevisionsDialog() { } }, [ note, refreshCounter ]); + const hasRevisions = !!revisions?.length; + if (revisions?.length && !currentRevision) { setCurrentRevision(revisions[0]); } + const onHidden = () => { + setShown(false); + setShowDiff(true); + setNote(undefined); + setCurrentRevision(undefined); + setRevisions(undefined); + }; + + if (!hasRevisions) { + return ( + { + setRefreshCounter(c => c + 1); + setCurrentRevision(undefined); + }} + onAllDeleted={() => { + setRevisions([]); + setCurrentRevision(undefined); + }} + hasRevisions={false} + /> + )} + onHidden={onHidden} + show={shown} + > + + + ); + } + return ( )} sidebar={ @@ -93,13 +133,7 @@ export default function RevisionsDialog() { currentRevision={currentRevision} /> } - onHidden={() => { - setShown(false); - setShowDiff(false); - setNote(undefined); - setCurrentRevision(undefined); - setRevisions(undefined); - }} + onHidden={onHidden} show={shown} > -

    {revisionItem?.title ?? t("revisions.no_revisions")}

    +

    {revisionItem?.title}

    ); From 9d953ea7005e8d67be5e83295f7ec2c59e2c1404 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 18:47:21 +0300 Subject: [PATCH 427/482] docs(user): update note revisions to new layout --- .../Notes/1_Note Revisions_image.png | Bin 0 -> 927 bytes .../Notes/2_Note Revisions_image.png | Bin 0 -> 364139 bytes .../Notes/Note Revisions.html | 119 ++++++++++++++++-- .../Notes/Note Revisions_image.png | Bin 0 -> 548 bytes .../Notes/Note Revisions_note-revisi.png | Bin 143455 -> 0 bytes .../User Guide/Note Types/Markdown.html | 52 ++++---- .../Developer Guide/Documentation.md | 2 +- docs/User Guide/!!!meta.json | 57 ++++++++- .../Notes/1_Note Revisions_image.png | Bin 0 -> 927 bytes .../Notes/2_Note Revisions_image.png | Bin 0 -> 364139 bytes .../Notes/Note Revisions.md | 64 ++++++++-- .../Notes/Note Revisions_image.png | Bin 0 -> 548 bytes .../Notes/Note Revisions_note-revisi.png | Bin 143455 -> 0 bytes 13 files changed, 247 insertions(+), 47 deletions(-) create mode 100644 apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/1_Note Revisions_image.png create mode 100644 apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/2_Note Revisions_image.png create mode 100644 apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions_image.png delete mode 100644 apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions_note-revisi.png create mode 100644 docs/User Guide/User Guide/Basic Concepts and Features/Notes/1_Note Revisions_image.png create mode 100644 docs/User Guide/User Guide/Basic Concepts and Features/Notes/2_Note Revisions_image.png create mode 100644 docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions_image.png delete mode 100644 docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions_note-revisi.png diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/1_Note Revisions_image.png b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/1_Note Revisions_image.png new file mode 100644 index 0000000000000000000000000000000000000000..10b64a944c414798ef2d479bcd142bf63962da9a GIT binary patch literal 927 zcmV;Q17Q4#P)X1^@s6z#LUx00004b3#c}2nYxW zdm8m2fRu+` zurMT_-b`YLhll9(dgUVeMngkGwj%n;udgp`Yinb{q@*N#cz9rlNvx!#gu%VNy^e+S zz^0}q=IH3?P>ZdstT2c~txTjlQtRyOR6@kDK-v{WCnO{UFE1}8&akuk`g#d)xm>uv zzpo^ci@wvpxw+XAGdeoTxW2wVqZq|IDk@3>a&mGkNt}wky}cnN3Go#c7D_(17)ZOg zxB#(T*%w*$?fw6UpPwJ(<>g6&?d@&(WHE6NnK>~rk^6QXk*OfgBDe1DZUbE7xw^W7 z*Vk9@9T*sZjg1XBJ3C|G@bEA!EG$5Fb~e=2)miF^QU=sC)Az|I${5ex-`|6;$U10m zZwD%}nk_CaLS$qlbaizpg(@p6mHyP!RD=Ke`kKe#;o;)z37eXl;>;1VG8^aT=WUb3 z$z)nun&gd%iIH$l{g##%78E;m!exs&Jw0WCd~Q(xjCt5*r^MXIfJs z)@GicpD{l_A4^M1QDoK6_fU?-;lk}7PhvwWI58) zG&D3oe}6xCJRT#p@>Rc`^kM1p)Cx3x1G|=zl7cfcGnSN=Vbrg9e0;>Qu`v{t1LNc4 z`QL=9Ites3Hsaje+^@-G8AerT^**s{ps@bM{sFG7Z2CN{wvYe-002ovPDHLkV1o1W B#0vlb literal 0 HcmV?d00001 diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/2_Note Revisions_image.png b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/2_Note Revisions_image.png new file mode 100644 index 0000000000000000000000000000000000000000..cdaf1cef601e8fc6928c1701b1ffc2677fc7a4c1 GIT binary patch literal 364139 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%0D_Q24WmE)7X)Y2Tz~;8-1iOFm$V2 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 ^^J*dj*Vs#-t0Qf}k?)iehAZe8wyTU(YaSTs> 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.O&u$R?BWXzwgPvj>W3m zoX)h$JG#eV&`#29p^407AnCcY&u)e2^OEdzHey0I2Ke{!GkjGzzj_N*juJAEJ&HGd zWAd@DWfJF1RH4L$OG7#9vZ??d->a(i)oY|z7)hF)uvv zm}21;SzsjX0Dfme*B#M^>3%6K?~L4xDJMqxK>B?jz^=A;MB* zsT*>M%E#M1QcYCx*0YoW!AHxniHUr{nN05BrD#?x@KBM(Y4hG=Du4C&Ca3Cyhfmj8 z;a+li*n1B$kZ|D{*bhU~X7)o$kEu21v~%1riPr|rth z?1#LbpGZA9gAm9-vULEtDF703rmEF>Hp0Jl|7n_-P`r+;HY|{7Q%ydzW+SW zprE(zKOVdZ@*J}=Tl;fOm-|D^P*p~Qc4ydCrKPM>iPzfM(voIL+3sB%tlsTrIYC+N z`kkeqDxS3bqK~xrvP0)?l4KTxSiI~X!|e@^c0`=pwEWN@H$5F{Mlw#=dd-EhtEu>+<9AXBJ~E{&5;v+pD*6}e6e!=tIxqh zT37WiMNz6cQPDoqWjUP0K(RnGbK}!g_|+|x#sIcU60O?z&S#w?X;C)xD<=URXMO#$G=oHI!K_RJ*#bXLU1c{_hWWL*m{^ z`7E3`<8yk(qmDi*T{TFYmaC3Y+g5wCZ6vdE!^l!(j*fW7o96<;*Dvj*W!+2rLpQx~ zv5U9(z-j$ausV&h;cIju#FlP{9$FR=5}Yx!Q}5yQV%e+@hK9RgijPK4 zP1(<@@pcs2a|+NE_F{@Te#A&j2Tph|JVKg{Rn1_e_Ro*Qq4|SH?MAHktdF|pJnFk1 zI^^xTenVuJ+2*5-WfrV6+jmEstx5mrEn#q)I>pyHzrn%lG)YQgTd?dds@wC@3^jA8q+`@u%J_yQYPPEXmvM^h}6Gi^Z`_wbuNrxirgbH!m?)O0V!Uy=5+* zi`Ks4t$oE#dS8RSWsQ%m@6m#q{auzfOa+BZwrY`)vQ6nj(|yge1C7pmYiA$G*HTYAQn&=Cf8i9h&Mg`XY|=0`F*g&@#YII#lQ?4S8og~ z^_MwuYDq2VCv!)*|2<{NAN~8Jc51At3{5QwbtV}ckK~B6@~TtTDXYAI}*b^7VJf=8O1KroIRl$o({@^9rA8vG~BO4ESiT|>dg#l znqi(jB8t`WTKc=6?E&HeD?P>u5t)6B2Z`;vXfO8QNnx(0jIh}FlaPQz?YspOZo(yr zHlQY}4II(!gyjVq-f3)}jp~+w?uw)fgPM+fuq0rPNQ)Uz4Lpne;3#o_3??5S=#i7a z*!MjUqw(*dQ%((HS)n`^NHJ1zW|Q>&XPO1omFIOqr#99WGjxsaJHBM@uT6cbZ z$DCSH=xyKhR-wR-vM8Tl0cQn&W#lZ)vG4RE1(Q=T%bUbqtNPJlc9n^OO!@k?>pLc| ziWk(37&Y7}Db}L4X`uGXP-ZqbOZ9vBi@&1)Ba;bPqJj|l$Z=%XvpLy4kl6O|7sjRtXuTRKZ|U}{sH&3LouNpySypAAz0ni18XRVPeR63QKA90Ik>`zryHSQx`H&uKj|wdG zQx}<@-lLercTq7_|AnWsfhcMd3g`{JyKLV;iNzHh|Jn6rywHyJPX}37Z$9~6TMo9& z9#GiF4SmQ+#7ay;2!KVR!Gwob7zU?134JC^pwZi$Bx;e8UN_jIR71TX3OjOqZQOE7 zv?0!Hv(SFj!Xf(>+-v)hD&Bw%)|zE<2z3$!Ff@f1c2wHCVFAF_t$Ndu7XNb=haNvr ziy5q0k^c5pl4U~onOxvbic{OG3&tJ&de=m1mb3()B$1AeD~delBwv0Z`?hawYut`- zGETV)!5*5#842|b-g{T+KY(BvFMG?3Q;(rF=_>v6>^2IYP3k*)K3sWayh)Bv=&oYa zKJgT~wXVe?i$KL8X5u-iC%G^l1wsI61bOCX8a*Zyq05JdypGrg`s{36PYeE1cS`~~-Xf!g7GF^7l+iJ;SV zc!KrQ0(^k+r?TE_NCJpQ2)ZX3IHUnanf^kJIURgbQaf|YXEbhm5q1xRsW+UxSYZY7 z8YawC73TD1Unez&{x%+10$7#%_etfosfjkvP-c6IUe(9b{Q zcUKbv^S^F9U;KIBbN`FSPQ88c@NLihhKZ-n3U}Fu!*V-kZsnb<8oYkaE!t(^+KWJ{ z$JAaxbVT2{gm)k4U8eJF{PQ_iD&wqul9OoC>}8>8h0kH8*#S+~j!~5_JedPPkp%w= zc#Kl?`IFg3(8{|Q?tAKTN<~kDTSRy9&!w#tijcBE`bn@M7tKmk8OWhv*)1d_^r|%~ z*X1~;Nwj52PowSlaYj{KPr_LYo-O1M8`Q({n=5$FkB;1M3^E3BqI``qg^R%RbUN(; zhkZXJS8Ph4L9l!S*Xe66dp7;kM&QjIHyD4Ia93*C`IywG4~It4ZkwY?G@&YMVLBFa zd90R?clqwmPy``R`N7G>KWu=^S}8#s`s@X~=*;DqnN zo}p!vA4!I0o4&Lr=Bi25a71o#EIEGEdd;M2BxUBJq1zWmFE-WZo&spE7L}j0mcA1) zOVHANzKfC32X}`HtQyqyk=#*_Y;?t%=jt_L@5%7O^hXDhP`$jt(u=OMo4=1YUAndu z(~A11}5GZs7T*+cT8{jPWhped5)Ct z!*1q|?)hM2aO454z0Ij*x-So1&g9j;NP70JuOFOH!YPUL<(l7)D}6y$Ygd;G&a_Sk zH%B@5UMi}&R22O(Qpw)Aj6*!OX)y9zM>tR8LBJuu-73^pGZ>8Z;e+?@kK|VjpMw(a z2cs2KDn7SK`jLQ&$b&?h&|8W8%c{|FG5&F%4=8cyZQ?rpMyVt5sOw&(K8M}Eg*Vlp zXrw7#rw`j4ca9E>OLkGdiC@mBh%POO2_zD4Y~U&Pumoqwna%!e#fFL$GbNkq$vDP zxKdWWwf7Rk`Ul~+4?LuqGQCns&!iQzeQm@P#Z)&WkCvQ^Gj6kY`g}e83G42x9!Z-Y zY4>}~Pf1X8S5;EH=x3ZM5%QTEa^?#oBei;(Z`ghMc;MMa-$cQR-+7-e&btUjC90ML zY;2J!4z2g7Tp9G3kSwVloF9^UB2K&Y$hJF=bV&+;O2&HaEFzxlp<(x}CKYy>Stl#G zHf)aP<~tTi?pwWnF7HtgO4a}U!KCZM#W=mbuE(&tM61#HFHyk|5GnB*tbeU$VbZpt=ddlht<4jJp;D~(J2>h?D$ zUH6Z4=PEuk>sJq31fFPM3hLIS3OGg;Kt*Mq^{Ah^KJ{Md%p7^TRqXEa(L=iR+=iX? zozCQ>SFY21w)GOVcb(pbFY4TXn4+uqV$+5_-5oyz=AFtE6&4QRgb21HEow^V?~n(}Mwy!+!414Cuy6Tv>DI6K4+_km6Kmvt zbnerw7r$j&N!v5sl=rxcLh?#)llyn&hokQV7Z`Fvl=@P*f;MLiPMhs?z3{8H^?=5m z%65ey1H-9N&{|HmK+!7!7 zoZBWM{wAlZS1)l4@J^|Y#FiX=C&e~lv$D_TH^bar|IB^qzIpFU$RrQa56ndJCT6tJ ze3N~1l-Z=D=4!GiYe2iNg-tJgahtTIbUsDFVzAnYcZ)j`CEqiMykHqd6;j=wS zn!Z&EKUHSl^uGVu>1NGwpT)x&L|Dd)qdjr8i&wF-ZNjF?k4N#kJf_o_)qZPpAU(S{U}y+nVM!eIv_9!SErax=9jN? z>{6xze-1@E7;EqilwT)%)Sa!t9>d&l<;+v@M4f>%dh#{1>$x#ZyyEQZl=V66ze;uN zS@kxC?x$&4-FXivLDR*6ri=cki)*>Qnq>-8F(h@cBpL_4N)&&UNIh42&Ft9eFOOvy zk3>~6?&W^whS!O|vWx_A2hW)}M|qX59a2`&Gdn{{Z2O+rFLTR&g7TLkLMDf%UDzLmJ8!ZMZpCJ!IY#CP|* z6%GPu=WkW2(^IkTvEx=59Y|elwfD+r@H-Y2MQ|ug}eB)4Rsu~N%U!I zY^+saQn3+ZMM+~LX1LJj{e$T9i5~{3gmo9dT}l#g;%y)nA1J{z!z&ynK5QgnX)GF% z$}jWlOC43e7OK`cBDsluaDT?ntg}9N_4lT{-7D&KCM@pSzUuPjS;of8n?iP{?;cYk zU7=Dw%|~9unNBG;%^Jc)t!~}*H%1NFKxZWO(T#_&aAArB{V(2^pgV5rNpg={d)wq zeDYZ@nH5Xkj_0qGoS{NW-uF@pPsf;y%-E_T|KCh__}x)@SwA!ZgW$QA4u(lvh`Fu# z(f>Ue6skl05{b9fm7BX`ywBkM0`@wms?a(I#~UB;c}WD85uweHPJ`(*nitLWReRVlrb+f0gZXl7o^B5%#s zxqeK>O{|h_>ydlL9eL8L#uJhY_l!LReEEV}GD2Gn^Ok&1I4c-&AHxT>H(%brflshi z)tis0y?n=RrSka-5w0W=QAM8K2R+yGxtxB*q$DAO^+qfP1qoo5@V6d$W)ILd0z8We zk-tIh(({P@IttA9{2DbmDN^2}|S5F?IcrsN$*P+oDts8@%C5SJL9lj!2Xg z%41*I&~8Ce!9?mBD)w^*1I{ z`e05EcPq)mDPD34T<|~_vF}pWs42p_u5uFL>cItw4$~TWhMKJW4c<3EiNecj(3b`%4|%khW~S*Q;?^Wa{+R2@9X2 z28yZS-Zpm-j5Y{dboK0t+&DYcXes-0>youcVs=N`#}R>o!7r*4+Uu$Mqq`GL-V2ZE zuODd1*m$o~N!h?eM(6I|(alThuAk2Eh$Ewy{mlRsB5pGkt^pthqThuzLNz9I$QJch z^Wz=#HAOtf=y%CY9I1r6Bk%*!#Eiy`xL}@Q7Qlwdh-2#KJWKy+^_p}-&;H*^N2C534LM-|c|pzViS+6lnkLGtl&NHl2ec=&h6Sk&#_n ztS6g^8QCT!@dG|QU~%upHY1u+Y_bszWo*3h)3g1a?YrINPz9Y_IV`n-qfV3NS5I9_P6`gDY6_*WOa6^#jM&A>(<&clshV#$Gf-Y0tGsyX>YW6Gy45;csunWib;hd$ z?<8pGG-Ens{E3#M5w=xfHxF>yA3G+pb}bFr5Cm{}4LppO?dLn8j0)qW zaO}k18oUQfTKq;rw{XY4($mvlp;7z3yw}m<*>P54Qh)|O>2+aJ^G2eG1UWa5$^-H6 zk7AcwIKrCS-rn98nhIu+hzNBBxJ7mVApH@n-08In;tDEQ#bORDf60CY)R-_LfeLp0 zdc@g_WPPd`GncEpKVJ_jpB@Sc_zy{dF0!P+5+p$7n}b)GC4_Iq{Qdf68Wv1 zEjXlB8u%pn)vIfU&i4RMtHJ1`??T&2#Uy+l23FRcaA~D|I9Whz7ZEEh@ntXma)+7;H(f6QVfamG}g(^wJP(m zoNUf|;J5_xe+@Q>8cv^)zav%rI1I*gEP#1-U%FH@VuleEB%GNIxghY@ZPBh_$c0^P z2CP<=W2}#j?8Du^b7gu{pTrT3_4exmEOc-g6vQ2`ZEUQ8e47iDcd)IP#sX)+`4nj~DuRc-S|6~=UYAOJ5alri+NPsPn4QJ(I1j1`jF=}!<)aj5% z=H|blGO-!q0+UUwb+3S+Y5CfS?Ewg&MSo#mVhg4S93**Uc$j}&*d}~wQ1nOpOJ0oW z?X4QI+T6y;h4t4U!is=+&}Eak0eYvfBpZYjy~w6CV&f@4p#7iO{-L;F_wn#=I82&xd03(T+Gu|KvM=oAyFYI4cAm+FN?AyL;EPEjA>DNqQ+temR`pdjm>{B_mUS zNEZYX$`Lw3@LFH2m!SCVe^LqUX(A`R{pWk_tX_gIruOsdO@G|GNfgf?JGfvZ9^^}}pC5J;F3v~`!k|m5Q-SEFP3({+CMx}ySB%9Z zP$&?+tZ;4IaRu3epmG}BVe|lhWu`5B;8{^T^UX190eT|Dn{}|Ww6rz+XVOR!ip3mc zxPo;-yjJdspAXU*e+8p}jJg3N+JH0@t9&NzFwp3bq!8rI-swj5nho(@J%0?RSW@Jk{{5Gm0i{%HFwwonf`{%+{ zjt)=i&yVR)f^rxc_wnyDq}Al5Ha^LMOZEQs7XSSH(kTxGw76F@YaZ2b(=&MgW!!JV zY8A(&xlV6AgW6}-!4e@1pLUsOomYz5@1$|>+eMo`*~YH8K6;XqlxhD#FAT$7pyO8j zyXR`w0@!5&2z{A3@fMlY2&F;z?`OBuprkn`bJc^#8wkwvA;dGRY8>V75Z(CC+190P z7oe`N4iZ}?V&AbNoU3#2^)HN!a%{?}n-{Sl%Ctwyo4*NJ<5S*_(=Bq#JeGA=d#rr^ z*f;;W_x3nhh~%D0b%3S-*-^!!>8px-cD3Ik7*zIr^95;3wBcN;ldG$1yGe{Yes~fm z__l7W5_6XF~O840)N1Lm1O0z8UOR4iJB}mE`tSQ4Gd9La2*5o?ouNQ_9J>dhJjBOJYf# zu5$VOOq(-e8jl8_TKm4x$9lW_h{B7~Uxx-Qv)PA(lo)KDEA7^DUpv446rZruHvR|0 z?V)FdR;h;!elP#00!%xH#amWQj`_b9ue>}$T_8%qc<(J81p?Ich{yvj`*1fPxq2>B z7t=~&b!O7C34VnL`BUz3Jw(wRkN48&3*h`X&yh&xRM7t2uoGedFw114U`a0=5;`S1 zpd5m6N!RSNb3I?ytnbpSZ`LR>`-k*b#^t~RKA<>?Xk9|nr-cn$N*A_jq4_48*AD(0 zNpchousM#{Z`}T?FX})N-m|^9<}$+7e*Uv6-x;BR_wOP!S;B))hWJUzunnhNGN@V4 zEzbJcnNdFzh>v1`syx;3ghjBlP*AMMYB6S0yB8*5nuChE&^+5OSpDFYSra8bE;79BnduLEU z1?_t1U)fEez~iH$_f?VvF=R$9w4Txh-8_sdf(?QK$c1K;pC$BJ96g=+Rj~VURdtl z(iGfIAJS>tN}Ipxp6!mQRa{r9-1c)A`gsIk?QT(K1uBya)GMWDwh`i&=Q<(olfM>5Ur(;I=-y3@fPBEGID?o^C*<9Z=w%bw!a^)%v#d(OP?dC}wC;~Fn)s#q zPpLER;u)<+8&wws?ppkJSv6Dm5Qk2q;vhM+Wc4!@fHbWb{i#K)Vo6L)wAx@#2~JiF zyUC@u_l=6%Fc-GnStxR=!};Wog&dene)K2-%*2*wCn63kEaMSrvWB!r4qiMda6U-M zi3U&ub*@5-q4A#K!D_GvXr0;*ds%PRjIsSX&&<+(>DHxhF2m~tYa%o|vv$0$O*wZ( zp5M+^{&kXDW(D_%%zg#=>31UOB0{&{-g$BQm7mv~ac56Ph26Eh8yp=Rd6mNt_q%Hk z8vV7oq61dbzp6^9Cs3zC)oZFz)0S(0)zK509cmE|KMfJ91ETOv@k4!a``#mi^q4bw z+ppH^xoc-GPLFzn8)@qO>#w>xpQPS*hFd7_E*%k0lA7#4K}8Xds>^#2A8*|=4<#dP*}d=iY)-oI{;a!L;d4$PV?(~y(+)4?7bRjT3D@-l^7lKQbSMZ) zV4d{TZTN0&tKZJ(-8#derM>rl^XJs7^Vu=wGjnGQluxhFemR4`^nGXncPu>V=7+&= zdd!rrNFkt872FN9eP$a)n_~hk53^03{+hGLq%`|UF27P@$ot(7FPM3MX3M;y+RcjN zRnB%bBt`FEoqQ9+&I1`V#0z_Vwej4WSoLem;0|p!}{y>`5o}n{-E7FRT|h zm1j`ZeEHTLs)5v~+HG!}cDES+ZgEOwvg_3yT>+jh?BYi+?m zPueKc)M?WjCmJ+g?cgoUKW+Blczo6;0gGrh(Yta%!(s%f4%*1H^75c#t9Z)Jj)1jd zQp`(Qgb!#KPU2;Aes;P5m*nEH1=Jl2tJ8}Pa?!#)<26(;o}_II!s%RQmm@ z>?EhX^v^>vr8&Q}Gzyv#lgfhs)JI`k5?P-!I*A<4wN-z>H21YV^6l4hHtDVv+UuTA z$|j_?QxC_k)8L>{yK*!B%KVv9m(kV;!HqjGO@3^vt$T+*%X{k_(;M~7D}S2f6CEE= zS2`7F%l$1)3*42w6IFInxcyS85x%0y6Mmj6{5&V9GWIK+-Y-o_exqjJXc`;Ik;M8k zCYFOOy6o_29i3M_)&}HrrL7F>6xsBOrF0VuU7%y@>8$xD3Td2AK7~Sy+y)$U(!mxw zp+XCR22c_x!er`R!>n!Gro=YZ{MrP+{TI<9+a7D zG?CM}0YY~V=xDDqdQ4|A}{F$E-o0qIaF?Zzf1HpTicIDD5xoLS_9(aui_ zRcAH|?EPc#{kR*9{SbF|wB)~Cpn1~LVs;*77>wOO@S#N*ym9MR5SS^Z_pm=AAmkiv zI)Cw_!>{bPw9~;cNtoD|Mqpwr~UNXif<|)Odx&NcF)Islh3u^=Sddc4Ny%KPB=())9A0?e)^2of{OfE zWj@tTs`gAL8XVms$n&RwC9ve+=zuh!HQtet8L+QNzhCY z1}%=Y>2YC8W54INd0<(wqvp0xTi(eV8+?l$|M?c^ z#fjV@#gCAeAk=j8Kra{}(1xkY>x6QEMv!U$0($LVDZA|x`@C6cyt;5fcQuk!bf>s1E2t}b1x=Mt4*v4` z2wsr&B==`l0nxs9Y8-3DN`wPLLekhbw^034e=&e(6}amm6@~b9U?FDa)P0Cwh``p0 zf}}(P1sGME%_jB$UR<4Ke|-HkvIs9d_G2o_!4N)3M8ivAGQDf|%B%1|?~m33b_m2U z9y_^Q8W{yjUfA|#=&H%Mx0E`{Wm^PjT<~*p>GSb2&+z&cnAj(vNt6KzBF;rSMjScGhQ#gSXg{& z@*HoR`%v=jv*_0%TA2g7zQwGQ>>5qKiIYf(eiZT#_QlGTr!O+|$V~hl(ER6t@C@Af zl(S}gmy73N3yahmCAC{#FXBk#<+e`jx?*f_dP`}|T0D(FJdHl$EJlRcNofsqjSBlb zmr_S@4AlM(uDu3;2}FAh$SjcAYERSwwaFpIvRrbaxc8n?4!{NZu4?_^c6MG(DB6V^ z_wQc=Mo~0_n%#xSFmumD+4G}8uY|;iWew1yE7-}?3wMueIoNDlu|j2s*_WT;${l4dTzW+qs267n zN{x@l{`1XO)ygyZSoRv<&ec=<4Y%80u7cbB(w7$41)GIe;{Xhk1JFnONl+A1W2MNk zaFmcB>4n`Xgh~oFh|bfA19gCqCLt_t(^q>V%c6aea3!rg`lHXaqEHA)G8;3Ud?Jkx zW(Bi&s39_F*iMxrOoT(+^(ZVypu?P*S=n7i##d;WkK#sV^`e+~O;|K1+seN{{0NX* zYu*yz4jVM5Dn7-1AMfqVJ`APB32+THW9*5{nQ&uM(oW{)8IbPwKIr{Bvva8<9+W2d zfy}yRrFA7<5w1Xaa%2twiY8c!Pq7-+lI3ZE^$em01;;TWi~_aF>WDQF;9a#1<}BBx zgW^ZqOPHsc(ye~okpCz;5H0fu7sg;`%?c?+iQ@`WrB;^%l+vl#Zx)4yq&OU+-$oHj zTaBS}AndIul*=sq)K{wlKtzfDc7fo)aG53+wZy6eT4EGG{JBQ~&5$ArtB2h)&m}3O zL3Rf;NMsX>=cgLD#o39KBe(cAGV5DLF^a3~$|3s(K0i0Gq5QU|7ziKd*trsLMkN8T zAPdhzAq_j(c!1^-(HMj?WF%Vp=g$?*WOz)iH96!!PG9{}wGl@u6!L1z2-`YFyx1Bv ziiB?s)B_e~qJW(dXtXso{nI-EvYmz2q78sz;kODvEa7O@11qyI0%lDLZ8er?(q&fUnWO25_q`N0jyzTvushGVgg0J094^ zf+}JC^>hJ6zw>`?mL?W9x^=OueEPIfb5kmX#~pRVVOLh-S4oh%yFNzBX1UN@@It_@wfn1fdLzY zM!sEEGZ9Y@0@wQC`UVsVnk=x$dSF@SmicG}$vRc2xpLrK1aa#^POg38t4O#ZUO-lF zp*pqvy0NW6!Q#OrZk8=%Tz`WVKM9!h*5EYyvxkOH`*jW-Iz;p|y}(2jzWta%+>mP$ zcD%Nb_ewcjkhKi9;^9BVA44PzqZ2rUg|8zG+Tpi3t22`#Lrly%R(YXsnu*pv#_J^C zi<|6Kbze;*=RRD?8C@tjSiM0kslMjGvy^%uwKvz%Zo9U61T}FD;7W*lH=k=wPEMwx zKx@d_L1+vfp~UW&auyzT1+KUT^b|6`!q07Vy$<^dBC3=mVTUN^?Dn|iMtpn(no}-{ z9Hgmz{0`{otS8YH;CUr9-{l}3N=^%qcAPvMix>SdhnHt3ICsl~fSFN&ACZCYj>&g} zy@+uT{RAM#L`Vmvz=sKKF)jy5tZkH*FNy!=0wD3YBZ|7<172ILRR6?-j1!HI5XHG=xNWk=iQ(auSb& z?bB}*lCK*IW#1!ZRY<_@A}@YakY3~Qcc`{17rb`S*V^G*krwH(5Fzn<@o-sp%4d&| z5Qz!1G5@p`<}n1BM8Se@uATWk`+N8nU>p(O+Oe(kV*1@SP?;J|N5#jpQ$T%pu7QJI z1Tcz>wnsEO4JR;W5}>7}b%!&|2f)Q(BYSeS{(>v=wYD}(yqC|JmvL8&_1Esc{u+JT zncu~#57^*7Tn_w}ddqjLt#}PzL`w`eiui#Y7su{5lGVSfI4+mk)G+Ep0Foh0(}-`7 zQug$Af^N3^z=Mn1o!8({5kMY-KmGaBeQqeuyVfEaAL;ShnJz|n zo=~dWg=$p}PlgCxY)e zwKWFVnk__lDP7GDEToo*&O|aZE4icu;47FIJ;H;`DuVchk*1hJ3Evfn)K0IuZ}~G8 zG15A4(^4Yk<8$(n z&-w7VPB6qZ@hKh3FlL5GG~mpg5X72*SDOY`$=vi5WSP5g;|N}7`s?=IX}IQA9DkOG zRW0}r9<350k1=4Ks_JTp&r(w)!U7mqiMuy-cAxFKb0W@VlwD9IvR|0|P)P0CFG8&} z^4IUXa-VbFc$$7m;#aYh+Mmep=4nWb9oq)`KD^rd#oi{3+zp%cLj z8-xcdgFdr`X)W!0_;Tk~|#0H8qEk}dGZUu+L2YT(N-U!{e5ArXzO z*H6m%dYZgPln-rj6LWx~!Ro`kl><|ObD_^MuO91PWXeNDAwxnGCAUt_K`?-x?FtRv zVufr$ThI7!~jo z2XX@wP*%L~&-IDRNZmHSMkhuz`NRt$`7>q_AtN`rem;0vR_x=Qsx4t6aDU((jfIfW z<_{c|74s1zs|UU+)GnNpthmz7ZaKSTjI(Mvj2i7BRGiDN2i6j+HA>s_P$nQJewE#R zV5>`nMXpQLF=x)qmwWlixqwE(Oa9%^c~X9zRei8b(fZsB{yG`q!H+=)COGg>41t-# z?bZ{xnZ%6{R%>uDVS+IWB{+REB^Zt6^IRRn3awM4fNBDb)0sxXUAPGyC2c=^jVXX} zfJ1Xoa!||v9Bt)=e(uSyx$80P?mDYNpe^*7oxc_tF$6C|0W;{9%J9$QxP#&<-`jIR zcz4m+m0^`*7vA_xXoOxE4!Xqg^OA&#nW8;9~wL5q4 zOc*P!T&Fy@H1rQiNi*2J`ACAATXUpy>`R+|~r+tlV>BU65m z^k-ExseUUA_5Ek@rufhId;K$W-|wB7ASoKvCls|c?~LM!GMLAZsXj*GZC9nqw`JOh ziURGAv zrEgsyaqsO}VRgD+Zt0RKBh6QOYj1?n=eKsfsr5TM#Q8dwFQmKMr;3qly_C$(mYkIw zu_+olM(bDjmbfP!RC%ypQ1v_m*ywH<2&T$A0|K7>04l~EEQTTIZs>7~GEhTUFMy~C zKe@Sb5jEETzac|BR>k+l`hn$7tC)pl4m%VZXbZr~U>s~Afm*p910$d|m&tMw{ONRF zUKovxjKq!(NX}Q`LQMSeAP`%P!6ymd;v~?lTzSLvw5RX%8Oojj1?gvRKGBYRiB@^+ z=$&qQNP><2(KQy8#`~A;Bu~)NvF|azQ+qi7^EeWggq-vI+7=yd2|WV|3nvN%m>Vp6 z4%tfj-3!Ljk92nN!QsMI=a;Nt>A)idDPuzpnleICQkKalU(@(tH{N9byB%mW$Ocf> z0w9}23}&J^n?Yqjvqs2ASm4mR1NVa}8ukKzvlI5pR%rUTyOdq7*`j1 zDu0PEKA-`tccPX*2>G9sqNigWqo%%v36yir&V^1~u2h0G*NcQ!X=#b-?E1Yu`{r$W z;MtMSo>8d_A3ra+C(x~xCw^`fs))1eY18EEEi^?{RaHX_+xZ9!3K6s3X%!F8_k8QG z$(yj45e76NMn#Q~Aq14O4i3EPz&+XQKG7xLSaA9)C$x%`<(BXD^8X|aS9vT7KDx^5 zHI`k=+4qJe;@e#^mU<-aT=RU7zHMuN&A^LX79`}_!a|_!0STYx6tCHj@TBxOXhy~M zdCFi#pI2PcAll&5-tEwP8T|FCB=LWKzgSv`Q>Rtw-v-`Inl3R%zIQKueL0@<_}wP9 zuFjwwO^y|*Vp3r=PI=eUjEw}{q%ATnoT?nIS`0LP$#)Pkc5MHq8un6F!a32Xt>=+g z7?+_-&W)0b)g`6sC!JmQQ14;rQi&fJ`qcL4m2%;_&Ep=8-FeArecHD-HZdRk&3o8_ z>6GR6pkGcl@5^{N9O4y=<>V;8#J!nl>U;Jvh`MPFj?C>oGV9MlEDJ;F|4SN$LG+P$ z?JRh=_tKW4N=Gaq4)Hnh#>RpRUL#BavCY{+wN4wMRDIXdJj;mEt1p@s1<#lz8 zyLRo$Yg71Ne|omO%g>`4kIi{j7#};8YO&^!*AO+f)Os=%PPTC5@@_gmc7-#QEBDd5 zoG)MGa-MyXN~eyxceSF7Vs>rOz;^+P8%Zl~1Xdn)Yp2(;adHaBP1Y8>QGA1+E9~mk zr?4bDcH)F-QG9qfE4UJD3JT9GhWY7}?pSb?r zE_A=fg^h$@2b#^TVUDMI|D(OcAlmnKozIlcz|lKDPHTua{rP>fYp>inxBeK`)yn>5 zuena23Vk<_5hk-kXx}MG7C}J~4hBWl$AkMshV}ojyg%!U*VLqahwHz8Bff&wp`O?Q zRiT>tW0Cgu#@VBQd%y52o;J&LbqILdctu8yDnsWPh1uMMM^AextJ?}6`^G~N+W+;= zgCd)6=un^Xy1)NQ?$@uBN~3g-{O4TB-4{JZSTaVmIR%)_o!La9j7R39^N*M?o$?Zl z<$RmFp5!=9uf)dr`Ka}8WqXOk?6c)U*0#M&AEnskJk3sfB=WQ)ax=z z+_^u0O3g;S(!Ja_6t#MYMl>jLDP*{aCa5^{&D*zzmX<8)>go)^TD6P%r?`1}uK*7< z?B9Iwl*ecWA=u#}*(~Zmvv+p3+V(*FKOY94a7ypS>#CF9EDdrt=hEVLYTliqmZ_w$ z1llbfk`qw6+j_j^Isa=z_TQs1F)p2<>HC5uU5YiyPSWBI}Of5=ZJK zbA;+37x*5r`o|68U)Lz|Hb+zxYkrFETyL%`CI6B+*D-T*o4rfY-3EMJjjhgKoW-6+Kp07abQ>SGVh{`pQd=QHUn;^^Y`kh0eOU?Su$* zWOOvGNzEotYJW<8e!iT7!Y9}9|MkX;hu7`d^KH#*JdND+rj3U!=*&&T&pc33yIyd5 zvorO%i=)(LzsjjIjF`-KsUG`!M=s}Su%`DthhJB>oiSW_EOd|D$&Y;0iT?H8dd^l? zTwc!j`45lcd8h5Z6>VI?E}#|SjA5BXncsg2+-d2CM~bg^@MejMr#D*bO4X1X`KZ|7 z1HU9w#G2r$mWcY>wA2ilnM%wdk((p!k7>k2F&hTbaadSTN8fUMpAw(EzTcne`gM*J z1|6HLR}Fdisd}$JNNZxlvuq05zdwAWi2c9cIIfLO#5xxji_ykhnPXqKHaSGq)l$~k zMYo16GWE#{G(2Tyme-0?opd)R zYuo>KU$lN+k(8huwtUpCxpSwVPLk`r(|a}_D;y3Kd=$!9Y=1Se^1S1d43>|tSLjAX zmBmC4ooCx`&VP(C)GthfR(uoh%@-}h590CG^!|^lc*FjYqwl`_vHo)N%l_+>@}|5= z-uQE_LA+#6ON4W%P5hA2ialO}$4;G+3S?2N3TqJYo}`v(kaCiKdC_!W8WN9&5djE3 z6hCwYUA{|mYhbT{m-)JS}wtA=* zRNad9uWORg(71d5_2DgJ?==T5a6e_CIkjsw-ipn6mVBFYuEtiozXsAbjSAzUGX>@6 zZy~v8`J_6up+xB#9c6uLmhoY6lT~pUu#1(#!d8_#)&`x_ZY{O@>$uWvc;waNzcZ>wn90|*a>{+P@9o9od^vyq6ct3@O`3d_VH6h7Ipf+8)2sfa z@JRFk?`_Syv6NGKOlCrQ8nqukmhtdTe+gZ4Fp^p{Xz<=xl@Ehxb|$()QTRrnF2ZHf z25*y?khio*&?{9{Rf(#o@WB}n4S+Tv2FT;MUmw=GNlA$t&Bksh>U868V+}_P ze+TH8CMFUN(^L4S#l#;d6s?Y40*G?lJlbOdl zO0I(1dlansw!fm}+FacTjqP$`7RGUXUIs z%j`wWsPevSp%79GOxT4e3DA~jU}pX_{2L|^FJ8WMZGfdD`geb;IR*+iBJMv2R~EE^ zTEoZ3H(2uE?rC*J#ao^SF1omQ$i5ok=Hcn_uQ=Tah^X@Y`y4h;9fs7sxj$sWXHkQc z~()_w(wUy8Xx+3OV&vQ4SpZm|JgIqP@IojtiC@y;ES8a?Y` zzZ4HwhQ)=`woFVS-ZxkbA68!)U5l4eC!y=lQ8E4Ft3n%Ate7>hL`!?W(j-Q&Ro$b7b*Li%)}!t>E8$_0gks=)PyMhUWEPaH=4K z9c%a%klP19wpytIV}?NN0+hddm-XfEL~ap0lZjO!%(luueL8gNrIAz>nCMiLxVShn z&pG3Hq~x(uxAChOOq$LHPJ+Ys8c4fCayv|$x-o?zCMz@JOJ{Z^!}vs5WeLIugtw9R zaZOSo3?^97X46nwT3gr3%8o`msDl)b)q&m^oa#A?6_R9s67)bCirL}AYo+&2Q|W2d zjs({=(DJ9*t}$xsDpy=A*qC$e|{<=VQ?!|Q#1Mv_RT6S4e0h%W)rZxG^g@DILxxuUU=9T&3- z!=V?yz}OB-O_hW?>3i5vIWJ(HVghhLH;&5Srzh;=^SGgeYz^T$!)abp21OH};%H3@ zT)%z;6_7*g=zP}TMqXZCwG-JCK>=P{TU&;{Qc3kYFu|5W*9|Zj($jQ%bPyEC{^RWj zBemXs>_20^hO81$U>dIkV`*Cl2Mb51(jV9}3_)Z{1cA#Tkc)tE3G?F*?IN}Q{W2gK zOYzIhl*Jgav2_Nsfwdqu6Ej`9;9vgs=9Vunu=-7TJ}FiQCRv5S*OP)Rp^LCaagC5( ze7R(N(t6U}(b4hzj}}Ark~Gh-=Kk;B=@K6Yx}Zd4JCxvIE^lJ_*iC#z)`K_uG6O_k zY_XT;TD(BviPxv6#GW5FT&u}+4p&F6Y9~iY69YA?!ke7+>uu!aMdp>|%;yJ1-~46I zc&f&kB%!R#OYQG>_{;aFS#u7ar;Te&Ppt7i(|qgIyJ;zd=&dFBh9p$hG&M!@0-7Nz zIY>8wh-f%2;SG=FJf@Dxu{``4(SadW7slWRw?>s$RRvR%@^~U;&d@Awb?cWeJisop zO$5YlFkm!^3ygKm9*kd_9By+YSr^UAjs(toIsw~|)X;1k9#+a^%$~}FOx-HXe|2y- zqmM`7I0}FbAFFukrd8`T_%$E*Fl9OT!fk{{Sj{U0hG7TO{@#wX^J6raqq_9>@rLi*SUQyE(T;iIIg?Vccc4%t_|mEki4!@S%!H_g6{}Dk za`H0M(9`poefc!VXMSOejWb)~9sZVFdDOQyT@xnZzix1B{qtH-Kak^RNmfyWn|YRl zw{ffDSF31cN!@OH4NayXjyS}MR7*m?-|o98h@Fq(o9tT9V88%#&mPU=$Hk$OJlR*b zisGjuW~dtBRTjFOv?EP}i;r)mm56MPM%ag#SjKZTc-S>KB#cuX_#@(id)oadQjebk zN2`72*R1TqsKhl!*)NYgTxfQYBli|(x@~IY+z}*jx!}9>!nMyCP8zIxtJ^%JGWPq{ z=P4N$EzuP`JRD|b0dJc#e*{&V@#Nm(%2}Vx@wL_Qe8`U~W`?`U5NM^`e66!w^Y2)h zW%bZZk{xXEAAYf&_? z1%t*Z$9wJquslSrRcvf*91JU#6>$=fkx;$j;3>Oi$y;zsTLk-ga8-@mQ!vj;MN zK_jdHU;GMNc;UOGh8-D@H&|3uRLbh>nJ{|mucxE*$LGPJl2%Yi$kxt|8pa)P?6b7@ zVA0o2K1jwPXI)(b(cHq88`u@UC8v~cnK z@MlJ3Pcqt~_<1__Wq*ZcXrUXiBzdq2R1wTcs^ARB%FN7cW?_+pK@x_%tmAXh`BGNc z*CGtFH@P&CQkf0w{j= z!iCGa>nbpQjGmdEn4lO~-F%D>OR67$Nn}Lb;TZ@El@8w}Z!I1pKC`)c?4`<;fp)0K*DuD;wgAHok)+ zWnRhHi(Nuiwkk&UFj?9ozrCYF82>4r-Dj+)r$?Y^SgG-2VjGy3r-Vlw1d|y`8D0%J zPDqS;jSm@*s5w#+otD55t0TI(`WX` z+W3cI@z1dD!@$P23#!h^3)fM(VMmfU-;re;>`)n7XRw*YRG~B?D~6SyKXZ{>9UOx&;JPAq34}}NtYsp>?>O{s>t5zwV`nZB{YMisio|)$* zy8E`awpKPZaZ}FDjuF#ddWH+t_ zTEhlEb1{Wy#m9@(=%(YG;GC(tc0@CQ(R(rIiDS0$aZ98M)w!1rxwWlG&$Mt?rgSRqxC^*G`SbrGZb6huQ>nZ*nR%w24G%#@uD1M2br;2|zYC#961|c6J7^F)b^x zoer-o>wPV6(r@k?7{J94!V%(Aav)Yj>;eJ;I6N3iPtzSkOo{wPh${fzMI3~}xGqU0_R-#lUp5?S_Q*yDLL3~pWf4MNB4lWDe z_}=4d8({r~{S|5u`|vu>CVLy~Y|5kR54_WyZC!(aMLG(H`*p*pNcq&fRL0|0_<=0} zpt7>2hMp)zs$oMg`RKr#I}f=Y-9-6{W!7H6=Pj?ix1n0BYPBK}A%2z9V6PQ~v{^6` zs+3JHYBq~8F4}O^&MxP|sKs`VsTH6E)PT^_HM-Er{%YsWoj6oL)pS`6A;z=P%}y=QSJ5fjDGe}RY8o&QYcDn@{|h-$^X z*l_Ra?WM7{ww5_k#D&eNz<1t+X7Lm|M$qS@Zj6g=4nX=>8K35oV3(&NJ;~JHC_D+& zhZW7urbA~MD=MhBUHDOkg{1n!*|AxrJ(S6%#aZ>=b92OO2$px*2Yulp9Ee?GHfTPZ z{Jp0EU~; zkQTzSr6zQ!ahX$%eMyaoyfs0sfiIHd)VhTXebpC!M#Y$>?5HZAz&czP7H?xgki?JH zwr1n_Pt4Am*548(Q3>TdnV;)X#X@_q42QeBzu(w?j@$mkiKB3$R`L2RSI^~;(VT8d z`Ufox7z_5dmd_(l+d{HR%6B^F*|SO%$VAku<1e5uX;$j9!w2MqzP`S* zbLh})QIzS$-#&*e4njcKX#MKV;c*!M(rVO}>|Za#AX@Z6(NE)(&E>FTL-qDPZia$h z{3cckR1}^C`UIICAMV|Q?1wE`_IPb)5fTzj>FN9e5Gyu-8t{lzdjtW)2V12?gLXG% z2vJB2=r?ueCWQk4AJP$gB}oyTla~kOC#l7?_fQL^%EEn6YtJ4=pM_thM3)Q11jyl~ zj5w#}AveX|y^EL2i^xtmJqYyFPtC63)f1v6Ri)f-B+8W-mY0=jEYl1=rwo3}=m^Zy}z*D1=`)ep+Yt1i6seASWlM3~l7urA6=8H8s6R?_|~N z(LqVIrFqxnJ8@GYD=4Itz-)#@(z)4jxXjYXG}wV_**3dpt9NJAU!VQ>vTsV_z}usv zz&XKX1XNE0`_^x5j^Mk!2D68d3`FGRIni=Kitp)1A3V(E1zLEwk~=_t>_ohGbqNm= z*%f3baFK%vIP%YCrv`#wVRKH8YZ3N8Ax|QV!3Yijt`-?_V@^PJr%~H1ghE(U@~^hK%xIE6%`JSB<{wwf5An#XtWKvP^0HY`b~CSBXwL6Tm8ErZz+d; z#||GjV^?Cz`r@>(hQ~}ezRgkeFgAR2C~T{-D^9Lu?7e#rQ3_*{Sq1GDkAZ{xnzQ*H zA^o73$$D<(j7LQ{3@+GUP;~grfJtuk@5$Z|&rcnqlp%6Vg4QxTZ)rrVXUC>zuu9nD zK+_;={Yucs$49Tmn8g6VG$?9YH`NXxjSsdKWSe|tM=&DnIV-<_&``$v_wS2vhH~)p zr%rim$8*u_!+HFJ#3fBDK`8?pZ!^A1^tdO{>?8#&LUA;I65L!!Jq}8F_Qx6Njtxum z)9f7{145vxM50T)<@>nt{?;hv+Uy~lS9k;X$V3M@FADP8@^T;}C(DS0mD3z4I$sXx ziX112g$rUlR|y9bw_V~vD{ePB&A5Yp)CO@)gkh9zPwI{_vs9yJ3+HPum+|lfWKIaD zON+}2{hoC#JO79t(AcG|+12apbbETsZkasj){Ti{d;Dm{J}cJSk3@nZm4k*;_3#%H z$X%n4Ckv$KMnL!DShXq;T$Cg%RZ{95W2pO|9XE^Vr{+Q_%E85DG$*tHzKt2Ih>3?77?6X&IC*6)Eqq`v z*8r!J!}3k^Gg-H-arWkf7s686)qb(F|F~qsuc1%$0IRA2f^dKd3b}%m`T<-xMyGr7_DmU>nIH%IW4l@a6EwLkTe7D9WDI}9 z+@t&Z_se+IBEUeQY*3AGBE4e(RMl{NYLsSp=u^iZt8U$zh&zF%Vi!tJsHeY^))px( zAd(?CL9Qd2nVDqSm@t%3D3j{xTfS5J`TJ^Pb$8wOBZS!;JGLTWs@cqX*22n47}lr| z9QWXax(u{0azhkU9&IrmA(r_U(csJXgw*XK86^`NC;RvlRgP zbjK{DVTgC3h-0W%{ZPPRnUO4f%drGv z6$llsu4He3Dxp+2XL)(x-l9j;#G8SONnLbNnj{blN)DL4iq36(nCR_-a>E3G5UiTt zV15OD0_na&P@Ma1`wq6LrJOj0>}mmi)J8B}iF1u7=~`|?=zC)W%ei$;jk@xOhMWM-$|Jy_R_M~d;cz=H|jy^R-MppLe$q!Mk-8`X?DDGH}<57UN)+ywOGgoEZk>hdfApRq&fyj4(u8lVjL=^xsLxV z!;ZMexE};eASKBr%JPKf?h47AgQ@$=={~->mUi(YM?-BSnwpGP_h~2`-&!?@M;C$TuMrBBJZfTSjJEpC6-zD3zyTqU1oxbfbpmJ0NuTcA}NH zw(_H<;A(6PoZUTJ!g8^M+COl>#et~zLu7B>g}o2Y`qDs+;cBs8er z|M*6PYEXBb3*2Qq)LO6!xr87`(W%d5Wn~d==qP%DMbYht>FDTGAj>i}J-yj;=5%<( zr?CH~TWYXv_2kxuf@XV0%ONINmCDVM^_!^?ag4V;! z+uQh^L`-8!V|{%OE8CYCP`;Hv^1qD~q)1?dMiDwZN z6SSIMlk|XLh%NT($=yIzYMt7~#C8I+;T><-upuZY$Oiu6MB)Y6;40d$>&@&{ zxf{a#HKv?U+7pLz!m|U&-VLOEG58$zW+#6KIv1k zCG`Wi&c97c82I72zB!<<<}#D!+dTcdcbUxhUr3&-&3z^sYW&U}^8p=CGMnvoxp1Kx z>jp1;RZbi~o`eYm>3?P`nG6;KZ^7scXj5=fl33d-Zvhm!Na)tl&pr|);;z9b_4<)} z#X1^0r>KOCX|&3GlW$Kw-?v$k-JPff03(0+yafB277q>xkhWnP<&2$O#oH{Seeu@q zz5UO84?jQY4=5vL^q$vuH-sCITaCvKJ@8B?dpy@%H*MO4oFqN^&}sC%ezp?=i&^fm z&~KiZVwgoCjij{2+`U`>c6+A#c-^=x$}+*N=X4}9FQQ`fcs3+0{3OCN_i@}R@BAZ8 zC12o`&37`gBOheH;&St?Rdc$xXW4O)G4zqnJi$k&e5Ru>CeM5P!27wL^WGjPFg%Rbz)0M0zAp8cjoXbv1W5It9?@EOWeF%6ccn64;cY|EIi z-DcO}DJts|Cr(%y`1NdY3w%Ke>;PJ3(o9D;9>vY%{hah$+0=Xwy~n+<@`LC>fKJ$$ z^Td14@Pp^^Bv&25nGD;|)}Hy|kjd%wiAA0 z9(TAB=6#H}TRlKdv*MvOF4x1X0e2vK%CafZ>|ohDc(3ojZ@^T9zDi|N*Pf>t^cd5QFP9%vgUc9*7bB2WsbjTta1}I6U*;afiXGKgurix2E z{%x{TE&a$O{o=4NwAUyUy{{5d2L<`CwADvzUvE6nk&9*%@nAFJ7NP_lWFUy*1#oL3 zJ4s#_9gkw-P~MQ1n!EeR7g+$TJ&=*X+LMN!9@CjMJ7FX68U!DIj8CzRNrgwg6JvAY zh&`cSn@cpZkO9qiJJG`r``v^3H>Q7ttMG2d$dGW=QQ?(4Fh)>2d$n^RLs( zS9{{d-gTVLNAPDTkC++L(QU=t0={XSm>^xx|9s%IPl4s?+@Qc?hCK!$3rnU8`1|#p7tCbmU z=F>Eu(1P}smbSL7jZN7-+w8Ch4~|58H|?q_Kf3jXZV>F#uP}GrDBXSh#EFLq34W~y zj?^*YZh#4QHn15+fyOgCC%yR$mf{{}HU1^tAJ8;eUx>F!(bS_nMuYa^CM)1%=->Oy z$MWhD;4XUHl$&N7YO*J}-c@tEHwTiZN2Z+7%_6>yl=A{_Hp$577#VS4RDB~hHUxX` zu!{1(UGfn6er-pq-mn8z>dGCK(8C**ZLrq9v#+{AkG#$3@?)4*fsrV&crnM&c-K0u zS^?d_eN5M4?r_B>i9M*-HVUJZCo&$sdBa!aE}5`t{2|34*jlNofE@l?14` zT{`nJ?V!Qb*OV{?SW41Y0cX=yV3#{^s!nk3gSuf->I zS$g*aT#S6@_WFAzOoOvn0~pX*wdqsI<8&-c5?d`m0|Ruk{TMraNIkRx&B15G@#jy> zZfZ?>m?r0s-$CbfHloUIGaOl{amS+Pq~5*y64WE(sc#hXfshL<-v<_nkgks`cA#zA zi6Y<__wm#93V|qg!)F)8*F1N^T>tJCr~1qY3_7j0Rc*oPWl8YrGBx&yy=$~t+poxJ zsyWSW>#h2+O_&mospxmCl8VWRWN$P5vdQ}piyYPG6H)fgu~Hk~)LZp~%>2GngG8o4U~ z%E<_abTRL9Y_+*~cZjb$+NaQ!NABoj<4a6KA!_Dw} zld*ikfyX9II7AT2*G34ttvlyxACpfdFDsL%&AcPJ~k55+5dF@CfF9d*F@OEsLC4p%sxQqq_BomtpVm- ztp(4X_113;3J#u>$Gh+WMETu*|A%98>fjO(3<8pP7SkYsg}SHnOX}^&bH1DF&gl1-ltMo-tmNYW!FgbL*s=nu*L8)#-pO zv2XUtE%{vLzj$eDN6qILpGe*3K8uJc5)Y~E|Dgq*)ZD!OWs!OMw|737POveGm9wSx z`P0w4-Rn2Uh68ay=*c-bIVVQ4OV7=nI+v-@q`3l(UiSGpOmV0vfM&n6PELKz$HPzm zX;w9=bYo{y66W~j4Gqjhbq*?MlfRm+X(-qR2}eJ8@;sYaaAR$n~z524;| zE4hf&gb-wl_0qw%LIvfuhohPo?WevRKH~zKmQTh7^-!H8#iK7DXM(szAj79eYit}G z!Vs8{Ks6-;X(u|pIeB^MZ|EBJ`+j?zY0AQs5}TNiE6+jD16&NS!@25nZo$jf4)&*Xx#ZZFO@wka46b74^tH^+XDh?b4`k^(m3K5XeM(RGXK%Eji8HF{W=(Qisw&V^z$G&C7jC3gk(8F-CJKOD-#2-kMz$JgR= zcDKG?IlIGGCmS&fO01DEQeptFHBQYt41a!-PSxoo;9hnpb}7G`pN#BC-LJoW!`(~f zV@gNrtUd8dvFEYBUu{Yw!891RNcH?6g`#rdN9?x+04gbNp+Unp8->T;C(`7f>10dT z{{Ogo4{$F3wtxI1X`n5$H0@QCQe;%h$|hU(tgOn42vI^-$jTWTv0by7&Uw-hY*Xg+L!Fo%+t12udk%jy{vv~T$x^-TL>MwE?iPE)R%r5;yv zNESO>4yYkB?T_gECq@)4aoZ}IpP5T*aIMve5KP@2QPpYxxvEof!bKSX^;DOVP#~9) zcKlsWxXw*$i0!8uBSUvEZ%Zndq7CMk_Bl_$Tkp6YtW4Kh3>Nk61k}$5EB?*NgiZo^ zJ}B^7g}an2WV<&w=LoHDID`ZR!x|Ni@7+OwHL{Use8V$`!DhnccPCCdN6%0E;L_5P zSx;f65))8b@k zGNpCO9_%AbiU3ge0c+0}K~klBj4+wP#)*>Sj((ejfMQoZU^D=~DqRmjeF4r(QTY&I ztbqgqIu;fdpt7~V;TG??;9B{D-$Sax!J@MJ$~Fp$YDncsM2rJx*5$(pOeCe}$zho> zx~?t|tcGIZagjeb=BiIolZHoi56ivfIeL^t2nhh+&0r~Tws7281IxtuZWA!!gN=X1 zZL6^56_u125aUKG-74Geg&7xjRrqzPM>{Kp0<}G(8nvt`7bsfEA0cb}?GbQNL`*16 z&W8Tj6myiMbyN%Mrrr@4u0V`o04|%DFCr>>1lp4Hf{oOAF&~S-N0F%dkty{JWn-@PpLIXaNEC{_aTx~gk6sB=xB`Gw-A0IWZN%va zvEt;3X+sF(A9Rs33qPpZ^`3L-+R?pn1f)-BUQ^4$5ZMRa1|fc30r3A-H;~F02GjOnMxRI= zBJ{=R!imYl$ZjD7e0wRqUV?I%zWLV{tvxsmZ=7(p0{v@?<312mt4Ac4;BK3lpZ|c% zbRTLmydOfGjrhx7CPHpd8e1rfj@y=r9VH?{j?qxsKo~<%3(zD$*Hg7P-bui_#E>fL z4{-qJ%fz=q4wV{k_@XyjgpXJ=FQG(BeYl_aq=-w2+COzN)5%Ld-F{5wZ_LPFUXZAPZ!l zBcW8q>P9V^jhGJty8`P1knAb}i@$jBUdLId3u0Gdlov`geCj?D^zuB#V%fll2;1~| zyAf)1jW*EZa^K8$Z&dk(YB#D$?_dqtPe0F;xj9PrKUMqxTHc=@kxNWWygQCff-oi` zJO-fL<>BHE<2wq}x~VrM^^vzsa>wW6qPR@xMu-$`{M{FzDsOa3!+MtRu~$}Bh*9%x z&PDu?!d}HF6GU-uadvk83Sk5O<57x9oNT`8%=JHh9L8E24clBD=R1Gl!uzf+2E6S$ zgd`R9=YwQUqkf<=T6e^4h=Ncc5&!NQuC6agU_qPKU%uRzv2X|wo)0RF@MB`is8t|! zC*(#Dd=PeY6uE}|RgZ|jz2AZ&Tax3Z*ap%nLBsz>QwX`(BgpAK;A0>ldVt@9m<`_e zS|P_3P#Vrk+eWlVo?=J)!>}j)G2Kufkt#&~%D|sL4W;U2P21)V<{3kCp^qD%U~UKs z1`#nt7LJ9Ch)URBaYbW|y__cBi6HDtYZC$lVRgi1h72OOkB!^n&B1|wiV`<7c>T~Y z;$BkO%ie~@wXt1|$M5So?qq6@DYr%zpbSQI*h!x%ThAf8EC^#Pz5TOo?e zx9oiWt`8?S5NY(mMEpKMKv)Z$I^~{~#Yaelm_pu|!Jz=EnGYz`GvWZUUS3%Eh*YPn z*S=0%?;;&5O2ZvR6__^ zz&T?%M^SB4_==F0SC?EFB~_D*I_A0oI;PDQG$9rV$1ssQMF`@snq~`~ot!+3HHh>H z>AKsPRY`zGkZKU`5<*G#NdaVW_w~CtOi4K`tiLi#D4Z&Y)W?}lNY_Ik5!%ki73L82*C9&&@ylfU0p;D4G{+5KDVC@8YLiX?s<6vxIed|{X!p% zsFNymF~|vbzsdcrDDkp!5?jUJ5dw|eLMW>(^+_1P z^P{EI$7MnYbFuq?{Sa9nM}>u7MQQxwAL}mQB2@0+g&863B8WfqmI$S%A|m>6>-9I; zhaZ5p8v7Z2f;Y;#_n<;i=n`EYWG-p5RV_H-vf=tA(&|`QS+n20y9U6JKr4uBL9lIS zZU5m7JVB>JRGfsHB_e_W$TuMYKoJiKz)fRsk~K0183}#j_9HItIG3tEeR^{4)GY2z zfL`!V-f@pwswIWCi~0H@Kbo`6a+m7DfC-C#%XR*0C7# zCUf+PR)I}cM+l0z0Tc$rxl5e<5MvS24gv?-OG^u$??S4`HwY>q^&@bK{-L3*Kxkhb z+OR4G97JTs5WP1z;#;?GzwLa%^at<^#zImPGX@9&4619WK5jw3K^!yQdyeQ1y0%`y zza^e6sS5DNDX3U(N1;4H4{#SZB#@nbKu+B8TCJ?CT2thY;EUm2Vj_G|YSs@_G1@I+@!?p&PA3Pzxib0gC!wQ3s|ul%%_A)m<{Q+M zpR-^rBat9`s)4YeNW2e}JaPL2OA`ZKOf244kVS!4DH|LjFC}F3#ur*KS+$hVCgN=0 zU0YiVK&A>0!DjZ?)q>$@>Rr2tVPZr#hck)@8h{OK3m`$L_Nse&nEsm|lJsqzsQjjW zR_+09HTBS}x9GGAExGl@gufETpZzExtfx@7msxbwEmBW?9Ot4Fd(-15myYWX- zL*Dc!fdv)n&j9N`BuWL}Md^Wl;>B`Ayp);;9;yMTz_QM6xW-ZD69;&fQBbnyUmzhK zSy@?1UB_?*PdWP#Jl$Pwn0`tq+hFE{tI@XW+t4iQmNCs05V7wH{WT+uoBw*RnT zL$?X-mFTmQuv`?s`-V1x=6kQUtNk@Y*?WR77tU0D+Tj5mT7k7(wwD(S-H&+Gc!$BJ zT)F6ht&syALe}`hvcmkoK6h&vOS{{KRvMNR3*>?wLV3mqbCSpHMOXnUOgnJx1X~!+ z(3o3x`{)lId&-5)VpF+@f`Q(1pwX$v^wFhMzv2BSTPtg|` zu9Xm5I~%6w;{4{hlZ37Vp6T4~3Dsh`$dIjt*FDAWF_6#Br#MY%bbJ=2f42HG{P_I1 z7kjx~>9?NF#}Qh0zQ0+`d0Q&JFk$St2TJtQ%OY~KYX$#otlwlz8R~>(XzFzc$`z_7 zC2xvcUa?qaI{ROC0VU3L9+=E1;U-v(+g|i@Gaxv$0s9=l>!eQR4Z5B#a?{CZ~{g0_mQ@cJ^qthe?5sY+JlF?)zIfm-H_2`DD2xGc^*w2{(Lraf3~d7 z{YQ}3JHCJOraP14%99J!AKX1m{vQkTSS1`xE%MxF|NXTil3pOR`Ur(45@3janUFgX zy(~!|VZ*Q(YW%qO^7p}AwHcBvu-%qvT=8e*$~0uy#+{(iWhNQ?V(;0LEzWEtvF~x> z(Tnl?Z=MmRzQmF%NHQkAcGW3rkZ4 zlfgoIth^MFiA#49*v}R;ug33gB-&nl)7Gl0xVLL!I|wihtP6qfqtp$wSTX*u?FzJ% zqA?EE2P-qjkdfq$b^QUNaqwTnIVLPDOytFCm)P$__v`RO^|dKsR{~mwAsH&2I*w`3 zzEX+G!BP51qO$^oEn>BKACgc;m2X-NAdVXkM_>(uV>#ssOZ#TeD;b2S>GKCWhxP; zvkI&fb4odRd4wsc$haZ(|N8XJTC%;U+$b`{St-2c_B!|)YYa{HQZ()y953N&ct%)C z=Z=IKBdB3NrT+2#oNqG5V=ABhS9A#J0BzKWco@i95aB70uO zM+NUjIJHrigY0Hy^oy@JBoa15;4dj*rPBzThLp@Jo42cm7t)T z-|mRntki55IpiyAq_o#UN;3Y%&*LxZdDVV&y{6jriCgJ~M&d6EO=jzL?FS`6rUlF8 zo2%B%CykDmwwwCW{>r0z(!zW4_dRCM$iH!c3_hHPo=Fcru=1`h-0vUu&+6<>p{uWC zK8^geUZ1tiK7C=yLi17&AB)24FVdZns)@fISY7zS@b@2AYiaLky7aGB#erhlVYeh- zK9gW!*eU&ff8H3~Z@KMmbP0y?HKw`C-PZX|4mQ$f0zPSMpBiKLx6z7di&K)iEY)uHWYwj%9+2sDn!2g=n|7a` zRMT*O)0u?9W;PQWVZp;B27b-e^X;OoK9~HV|&Ss7M(@g>Lnuk^#6e7h7# z_b>oM{=Wgq{t}W7OL61zK`znFE<+)d@R9wIiX|j znh}3cn)k9go{;m~q}Nx~U&q_&sOy@I)y0`qe7&Ey{b-&-{he_CI%{bgU+?UTWR$zV z(Vm&Ny^{8}sJD4g66=6j8i2WWv8~syUk2t{Kn?*QxVk6o|L=18-~WAl&F6D7^V1Rs z4&Q*RQ`g1k1C5nP?7J(U)S1Qx7c4NP9zAfyTJgM!ypyXqdrMQk3x`;IMTSVrw!iwv z!jF~a8B_-OkZbX>lJ>^Dx*V5sxnMC`OIw2czO#41!e!p}MTXxy#rtkpou`vm^o?xQ z(#X#k^vKZBi11Xli6DJ4=9es(J;#3ai%?bQkq@``MMtzu{xkTMOS$uIPUzBfahTug z4Y|m$zGiBRsi)d}Le+ia?}QG9KPtX(!1O?FacHLV9?Ox*kMle(LF2~fid5ePE}9N1 znxB~{50f|`?`*!Al$cA=woYDduAai(E}#UK0**~SiEj7$$BMm_lW_)J~p{yz&2>rW!-CdD>Y z&gFn-{6+eT;U zS2mukmmd55#oZ;+j^5e+TEM~1ZR~FiEc!9Ik6&Kwnat#VAo$6rlsCM>U!*uF?3z=2 z+tAAv79%o!Q}gOLlS`6@%l8YD40Y6>*Chw5zB$gC=f3TJ?n#>T4yB9o&V#ZXEfjwh zQk4d8-7&V;b-llxJ%84&R)Y6{2F>Ta!_1F;{4_HKnd1KMo+BPX$4%hfw6txMR>9IL zagOKN+H%z%1{eodZ5N^TeXsLbeMiBETBYg(Z|{BAWRxFe9X%)${IlW3AJ<8zi<*N* zhUT_<%H_{?B|V}@GICGxJiEBSe=Iew=#OcSC{3T5Q@AKQ;y}{6d1_LlO!oba#JKrBpC; zWfLP4I6!*0H_lKYaAU=n5Kmwun+o&#sap+{PusQqpna%;UzCN?njH_qp%u;f=wp3@9o zi9-j2)Z$LQOMN`?YrjflWYp@tytAT}gC=*psDFHP*0u4i7mV=Ye48?AcTrx-N&K|X zRZiQd9cGIoD~s1+l~wLBA7L9L`6yL97i4{BN|%w?g9G<`>`UXNLrDvDea$Ui?Xwz2 zw4726JO-*}+`H9iw-$X@>a2NQ%e++76HzHIOTm7#FPc)~)Nv1*$37nHvom*zBv&+` zXrvN)?;$P*y?xNi$^#N)7>XGkkhtwU|gEgW(~E4buWozcnPe>BBC}m zsR`t${_|(Z=SV~m9o#T&)wZ^ z(C*N8gjUE>-Ed&?s+7bpPi9J5hd;u~p+ZXdn`Ifs!lJ*U%BPq6xSB0MsSvYhg z$ZU--=}1$)7MXqfYwEt3nBzK1);)k&(ccp$VmLPTK=c(n3E|t$J$ve!o1cR5?2+r1($Y~jcnJ9&Yr^?=O zyH0aWw>sH+4aZ&}S76sm`D=VTI))7l1WC3L&+sH>wFCE9yF{mrTKISt+}`CRr|NRO zndeL?AIH1vC6i`4g|r(cPM0FQO7v4Cr0I)3SG+;?QVCHD}&@~k51{LN4b zhTi6Lu^q$rD#r9VP0MX=aty7U*Hm9=si|!nDz@St%Ad3O)phg;t3z7L5F1nfWLy+q zBd3xLhfrOdtKlB!S61AOO>sxVAC*RjD$;t_MVI|P_EzAe@FkdNU_hi{pkaC0TrTy};`GlW?f_eVjgMOv27oUn!g;lMO#xIP zr$S{|=_IfdLXb$r)|S7|-HT`T{sZhe9#DOQET{)(U{Np);v5VN$9nsoKdym;j2ITn zA3^OUp*U9Gk5tz!5whO0tcJj8&I(J!7b5mwDqy@mm@UKQAAU8Ej_==Jz8yBZ0YDXh zgRv0p`p#f9BjE7_M$aZ9Qr<9lnuU)~zN8iiyIP~r5miF)3-FC#B?u5~bLAmLJSQ*9 z=uzisb))I^hL=sIM;7i93t=GMv@3g`t@Fj;wfuCSi@4?$+>JBT_Bhdh;^qldoy`k5 z+WWNEK*#)mDHGMd=x4EZUM!5ZewNAqq||Qhob5^`Klnblfpu)WxLf9(onK?$Wz7c{ zZ{0F@e@Q6olNpnkNON1Pt%o>&;HBgR2vHEktNv!k1IV4Iz|0DT#^KE3?3Y)kAw=>Gb5iA?HP{cO?m_ zsZU-XZ`V7&WBKjE1_e;K^uqbRA{$R!&Wse%U+pW;rX?m`DM>CRPu@(!%Q|JJcT!;a zs_mI%Cy&Sf*|aOBc~)P)58bntYLdODmg1pP8rXHIpL?5{3BTeFiL-eHUtN!cYP|{D zLMv^aueniS!{lG+t;9iclT22KJM+2rh~ve8r}sT*hWHtp$_^*FLhsQ8;On4}P=lsBlf zzw|_~#zDr*xw?{1^!V8F)+{)k-zL9!Wm#4v%2_T}GRd8LOofTc?tm9|MKW5OC>{#3 zyHNFmR71a?fS^>#HLeCfVk08zSq2**0&hbkK!A(uDFAM=Q}C0fy?TO^XlACdr3FXh zja5ewbKBMc>^H-%LQM>-gJnXhU@5E8q7){bP-b;GWS!`PWGtJlWrB0&8Hk-zP*3Jf z{&b!e0Uij9r5{ss(rSVz1EK)CnLaGmOuFA%f>w6Zc&{Sa>!&dV5|LE)l!jx4fks&{{>%79GYuP z@*8*Wx%nyLTl>P+m&8}-7uwBq`|7LPcCf)L|40ESkH}N1zjke^h!~3)^f!O6aCmgJJ~7 z-NG4 zsF*)vk382A<`=Bg3%`De=Gr%l0=PeJ zt`>uz$7--9B%*}Akno72@CY`}aNL)!R7EKiMfAe-Cd&T2_q=?XsWr*H_P5;?9VX80>f6WfRPEPwf5U zw(iv3)7sGKwSG>iI531~QG@eSW03AHY5}_*P0khdI67>!FR!^u?}~^7w0TCq;rZQH z<*5@?&${+z)ZkjB*pVe|8S#XU7caGBU+b!oAKA_nb9*JM21 zp|p2vye507H2MHZV7DMehB4+jt!>t#AQF}{`Xr@#Y$Ykc@KcW52u&fvqWUXxPZPDn zo@Ru88_eC8did}X!a{-`e%o_AbvMLBi7DZ(?!{~WMru{HhHQoKkcSaYeiCsnLUtpB z(bQ8=GcycCU0jF7?BZhRmK}J`TjMVrO#iAxsW~v)`ne~FHAXHm_8>n4W%0AJU;731 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 ZT7TVg-;N8lTbJvT)emUz&r~w;`9Cshy&3=j literal 0 HcmV?d00001 diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.html index 9b7d1ae1d2..7a3a2c743e 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.html @@ -1,13 +1,113 @@ +
    + +

    Trilium supports seamless versioning of notes by storing snapshots ("revisions") of notes at regular intervals.

    -

    Note Revisions Snapshot Interval

    +

    Displaying the revisions

    +
    +

    Interaction

    + +
      +
    • The full list of revisions are displayed on the left in reverse chronological + order. +
        +
      • The revisions are grouped by the date the revision was taken.
      • +
      • This list does not contain the current state of the note, so it + is possible to have notes with no revisions/snapshots saved.
      • +
      +
    • +
    • The icon of a revision indicates the source of that revision (e.g. + a + icon for a manually saved revision).
    • +
    • Pressing the […] on the top-right of the dialog displays multiple options, + including: +
        +
      • Saving a new revision now.
      • +
      • Checking the interval and limit for this note (see below).
      • +
      • Deleting all the revisions of this note.
      • +
      +
    • +
    • For supported notes (text, code), changes are highlighted. This behavior + can be toggled via the Highlight changes at the top of the dialog. +
        +
      • The highlighted changes are relative to the current state of the note, + not to the revision prior to this one.
      • +
      +
    • +
    • For any given revision, the buttons on the top-right allow operating on + it: +
        +
      • Deleting the revision.
      • +
      • Downloading the revision locally.
      • +
      • Restoring the revision, which replaces the current content of the note + with the one from the revision. Another revision is saved containing the + current content of the note.
      • +
      +
    • +
    +

    Named revisions

    +

    Named revisions are a new feature of Trilium v0.103.0 which allows adding + a short description of what the changes in the snapshot contain.

    +
      +
    • +

      The name of the revision is displayed underneath the time of the revision + in the sidebar, as well as at the top of the dialog where it is displayed + in full.

      +
    • +
    • +

      Clicking on the edit button near the name of the revision allows it to + be changed.

      +
    • +
    +

    When revisions are saved

    +

    Revisions are saved:

    +
      +
    • Automatically at a fixed interval. This behavior can be configured (see + below).
    • +
    • Manually, by: +
        +
      • Going to the press the note context menu and + select Save revision. +
      • +
      • Using the Force Save Revision keyboard shortcut.
      • +
      • In the Revisions dialog, pressing the […] button in the top-right + and selecting Save a revision now.
      • +
      +
    • +
    +

    Additionally, revisions can also come from somewhere else, and this is + indicated via the icon of the revision:

    +
      +
    • Generated externally, by ETAPI (REST API).
    • +
    • A modification created by AI.
    • +
    • A revision is restored, causing the existing note content to be saved + as a revision to prevent potential data loss.
    • +
    +

    Snapshot interval

    Time interval of taking note snapshot is configurable in the Options -> - Other dialog. This provides a tradeoff between more revisions and more + Other dialog. This provides a trade-off between more revisions and more data to store.

    -

    To turn off note versioning for a particular note (or subtree), add +

    To turn off note versioning for a particular note (or sub-tree), add disableVersioning labelto the note.

    -

    Note Revision Snapshots Limit

    + spellcheck="false">disableVersioning
    label to the note.

    +

    Maximum revisions

    The limit on the number of note snapshots can be configured in the Options -> Other dialog. The note revision snapshot number limit refers to the maximum number of revisions that can be saved for each note. Where -1 means @@ -15,10 +115,5 @@ for a single note through the versioningLimit=X label.

    The note limit will not take effect immediately; it will only apply when the note is modified.

    -

    You can click the Erase excess revision snapshots now button - to apply the changes immediately.

    -

    Note revisions can be accessed through the button on the right of ribbon - toolbar.

    -

    - -

    \ No newline at end of file +

    You can click the Erase excess revision snapshots now button to + apply the changes immediately.

    \ No newline at end of file diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions_image.png b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions_image.png new file mode 100644 index 0000000000000000000000000000000000000000..3839f0a1e8144d293ffe6cd5cb1742986cb82cf8 GIT binary patch literal 548 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

    u$? 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%0D3XE)(e3l{)Oe5>`)mU^aiH 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 xPLY2f(P_mQG5#m>9EGvzVe}(Yzpg=5jdQp@Vh) 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 following features are supported by Trilium's Markdown format and will show up in the preview pane:

    Creating Markdown notes

    There are two ways to create a Markdown note:

    1. Create a new note (e.g. in the Note Tree) and select the type Markdown, just like all the other note types.
    2. -
    3. Create a note of type Code and +
    4. Create a note of type Code and select as the language either Markdown or GitHub-Flavored Markdown. This maintains compatibility with your existing notes prior to the introduction of this feature.
    5. diff --git a/docs/Developer Guide/Developer Guide/Documentation.md b/docs/Developer Guide/Developer Guide/Documentation.md index 9818ff97ba..70b06f6dd7 100644 --- a/docs/Developer Guide/Developer Guide/Documentation.md +++ b/docs/Developer Guide/Developer Guide/Documentation.md @@ -1,5 +1,5 @@ # Documentation -There are multiple types of documentation for Trilium: +There are multiple types of documentation for Trilium: * The _User Guide_ represents the user-facing documentation. This documentation can be browsed by users directly from within Trilium, by pressing F1. * The _Developer's Guide_ represents a set of Markdown documents that present the internals of Trilium, for developers. diff --git a/docs/User Guide/!!!meta.json b/docs/User Guide/!!!meta.json index caa6550464..aeda15c94d 100644 --- a/docs/User Guide/!!!meta.json +++ b/docs/User Guide/!!!meta.json @@ -4539,18 +4539,69 @@ "value": "bx bx-history", "isInheritable": false, "position": 30 + }, + { + "type": "relation", + "name": "internalLink", + "value": "IjZS7iK5EXtb", + "isInheritable": false, + "position": 40 + }, + { + "type": "relation", + "name": "internalLink", + "value": "8YBEPzcpUgxw", + "isInheritable": false, + "position": 50 + }, + { + "type": "relation", + "name": "internalLink", + "value": "pgxEVkzLl1OP", + "isInheritable": false, + "position": 70 + }, + { + "type": "relation", + "name": "internalLink", + "value": "GBBMSlVSOIGP", + "isInheritable": false, + "position": 80 + }, + { + "type": "relation", + "name": "internalLink", + "value": "A9Oc6YKKc65v", + "isInheritable": false, + "position": 90 } ], "format": "markdown", "dataFileName": "Note Revisions.md", "attachments": [ { - "attachmentId": "1TA1nUFZzprY", - "title": "note-revisions.png", + "attachmentId": "BHquVQR30ess", + "title": "image.png", "role": "image", "mime": "image/png", "position": 10, - "dataFileName": "Note Revisions_note-revisi.png" + "dataFileName": "Note Revisions_image.png" + }, + { + "attachmentId": "eoYsKZfMMvlg", + "title": "image.png", + "role": "image", + "mime": "image/png", + "position": 10, + "dataFileName": "1_Note Revisions_image.png" + }, + { + "attachmentId": "w1kmtyCISdjQ", + "title": "image.png", + "role": "image", + "mime": "image/png", + "position": 10, + "dataFileName": "2_Note Revisions_image.png" } ] }, diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/1_Note Revisions_image.png b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/1_Note Revisions_image.png new file mode 100644 index 0000000000000000000000000000000000000000..10b64a944c414798ef2d479bcd142bf63962da9a GIT binary patch literal 927 zcmV;Q17Q4#P)X1^@s6z#LUx00004b3#c}2nYxW zdm8m2fRu+` zurMT_-b`YLhll9(dgUVeMngkGwj%n;udgp`Yinb{q@*N#cz9rlNvx!#gu%VNy^e+S zz^0}q=IH3?P>ZdstT2c~txTjlQtRyOR6@kDK-v{WCnO{UFE1}8&akuk`g#d)xm>uv zzpo^ci@wvpxw+XAGdeoTxW2wVqZq|IDk@3>a&mGkNt}wky}cnN3Go#c7D_(17)ZOg zxB#(T*%w*$?fw6UpPwJ(<>g6&?d@&(WHE6NnK>~rk^6QXk*OfgBDe1DZUbE7xw^W7 z*Vk9@9T*sZjg1XBJ3C|G@bEA!EG$5Fb~e=2)miF^QU=sC)Az|I${5ex-`|6;$U10m zZwD%}nk_CaLS$qlbaizpg(@p6mHyP!RD=Ke`kKe#;o;)z37eXl;>;1VG8^aT=WUb3 z$z)nun&gd%iIH$l{g##%78E;m!exs&Jw0WCd~Q(xjCt5*r^MXIfJs z)@GicpD{l_A4^M1QDoK6_fU?-;lk}7PhvwWI58) zG&D3oe}6xCJRT#p@>Rc`^kM1p)Cx3x1G|=zl7cfcGnSN=Vbrg9e0;>Qu`v{t1LNc4 z`QL=9Ites3Hsaje+^@-G8AerT^**s{ps@bM{sFG7Z2CN{wvYe-002ovPDHLkV1o1W B#0vlb literal 0 HcmV?d00001 diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/2_Note Revisions_image.png b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/2_Note Revisions_image.png new file mode 100644 index 0000000000000000000000000000000000000000..cdaf1cef601e8fc6928c1701b1ffc2677fc7a4c1 GIT binary patch literal 364139 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%0D_Q24WmE)7X)Y2Tz~;8-1iOFm$V2 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 ^^J*dj*Vs#-t0Qf}k?)iehAZe8wyTU(YaSTs> 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.O&u$R?BWXzwgPvj>W3m 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%0AJU;731 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 ZT7TVg-;N8lTbJvT)emUz&r~w;`9Cshy&3=j literal 0 HcmV?d00001 diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.md b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.md index f359e9e8aa..1d44e22ffd 100644 --- a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.md +++ b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.md @@ -1,20 +1,66 @@ # Note Revisions +
      + Trilium supports seamless versioning of notes by storing snapshots ("revisions") of notes at regular intervals. -## Note Revisions Snapshot Interval +## Displaying the revisions -Time interval of taking note snapshot is configurable in the Options -> Other dialog. This provides a tradeoff between more revisions and more data to store. +* On the 
      New Layout, press the [note context menu](../UI%20Elements/Note%20buttons.md) and select _Note revisions…_ +* On the old layout, press directly the button in the Note buttons area. -To turn off note versioning for a particular note (or subtree), add `disableVersioning` [label](../../Advanced%20Usage/Attributes.md)to the note. +## Interaction -## Note Revision Snapshots Limit +> [!NOTE] +> This documentation matches the redesign of the note revisions dialog on v0.103.0, older versions have a similar dialog but with some differences. + +* The full list of revisions are displayed on the left in reverse chronological order. + * The revisions are grouped by the date the revision was taken. + * This list does not contain the _current state_ of the note, so it is possible to have notes with no revisions/snapshots saved. +* The icon of a revision indicates the _source_ of that revision (e.g. a icon for a manually saved revision). +* Pressing the \[…\] on the top-right of the dialog displays multiple options, including: + * Saving a new revision now. + * Checking the interval and limit for this note (see below). + * Deleting all the revisions of this note. +* For supported notes (text, code), changes are highlighted. This behavior can be toggled via the _Highlight changes_ at the top of the dialog. + * The highlighted changes are relative to the **current state of the note**, not to the revision prior to this one. +* For any given revision, the buttons on the top-right allow operating on it: + * Deleting the revision. + * Downloading the revision locally. + * Restoring the revision, which replaces the current content of the note with the one from the revision. Another revision is saved containing the current content of the note. + +## Named revisions + +Named revisions are a new feature of Trilium v0.103.0 which allows adding a short description of what the changes in the snapshot contain. + +* The name of the revision is displayed underneath the time of the revision in the sidebar, as well as at the top of the dialog where it is displayed in full. +* Clicking on the edit button near the name of the revision allows it to be changed. + +## When revisions are saved + +Revisions are saved: + +* Automatically at a fixed interval. This behavior can be configured (see below). +* Manually, by: + * Going to the press the [note context menu](../UI%20Elements/Note%20buttons.md) and select _Save revision._ + * Using the _Force Save Revision_ [keyboard shortcut](../Keyboard%20Shortcuts.md). + * In the _Revisions_ dialog, pressing the \[…\] button in the top-right and selecting _Save a revision now_. + +Additionally, revisions can also come from somewhere else, and this is indicated via the icon of the revision: + +* Generated externally, by ETAPI (REST API). +* A modification created by AI. +* A revision is restored, causing the existing note content to be saved as a revision to prevent potential data loss. + +#### Snapshot interval + +Time interval of taking note snapshot is configurable in the Options -> Other dialog. This provides a trade-off between more revisions and more data to store. + +To turn off note versioning for a particular note (or sub-tree), add `disableVersioning` [label](../../Advanced%20Usage/Attributes.md) to the note. + +#### Maximum revisions The limit on the number of note snapshots can be configured in the Options -> Other dialog. The note revision snapshot number limit refers to the maximum number of revisions that can be saved for each note. Where -1 means no limit, 0 means delete all revisions. You can set the maximum revisions for a single note through the `versioningLimit=X` label. The note limit will not take effect immediately; it will only apply when the note is modified. -You can click the **Erase excess revision snapshots now** button to apply the changes immediately. - -Note revisions can be accessed through the button on the right of ribbon toolbar. - -![](Note%20Revisions_note-revisi.png) \ No newline at end of file +You can click the _Erase excess revision snapshots now_ button to apply the changes immediately. \ No newline at end of file diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions_image.png b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions_image.png new file mode 100644 index 0000000000000000000000000000000000000000..3839f0a1e8144d293ffe6cd5cb1742986cb82cf8 GIT binary patch literal 548 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

      u$? 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%0D3XE)(e3l{)Oe5>`)mU^aiH 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 xPLY2f(P_mQG5#m>9EGvzVe}(Yzpg=5jdQp@Vh) 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 Date: Sat, 18 Apr 2026 19:04:22 +0300 Subject: [PATCH 428/482] feat(revisions): add a shortcut to save named revisions --- apps/client/src/components/app_context.ts | 1 + apps/client/src/components/entrypoints.ts | 18 +++++++++++++ .../src/translations/en/translation.json | 4 +++ apps/client/src/widgets/dialogs/revisions.tsx | 16 ++++++++++++ .../client/src/widgets/ribbon/NoteActions.tsx | 1 + .../Notes/Note Revisions.html | 26 ++++++++++++------- .../src/assets/translations/en/server.json | 4 ++- apps/server/src/services/keyboard_actions.ts | 8 ++++++ docs/User Guide/!!!meta.json | 7 +++++ .../Notes/Note Revisions.md | 8 ++++++ .../src/lib/keyboard_actions_interface.ts | 3 ++- 11 files changed, 85 insertions(+), 11 deletions(-) diff --git a/apps/client/src/components/app_context.ts b/apps/client/src/components/app_context.ts index 27fc2e1396..ba213a4edf 100644 --- a/apps/client/src/components/app_context.ts +++ b/apps/client/src/components/app_context.ts @@ -281,6 +281,7 @@ export type CommandMappings = { backInNoteHistory: CommandData; forwardInNoteHistory: CommandData; forceSaveRevision: CommandData; + saveNamedRevision: CommandData; scrollToActiveNote: CommandData; quickSearch: CommandData; collapseTree: CommandData; diff --git a/apps/client/src/components/entrypoints.ts b/apps/client/src/components/entrypoints.ts index 8fc4e1b3d5..781790e156 100644 --- a/apps/client/src/components/entrypoints.ts +++ b/apps/client/src/components/entrypoints.ts @@ -1,6 +1,7 @@ import { CreateChildrenResponse, SqlExecuteResponse } from "@triliumnext/commons"; import bundleService from "../services/bundle.js"; +import dialog from "../services/dialog.js"; import dateNoteService from "../services/date_notes.js"; import froca from "../services/froca.js"; import { t } from "../services/i18n.js"; @@ -216,4 +217,21 @@ export default class Entrypoints extends Component { toastService.showMessage(t("entrypoints.note-revision-created")); } + + async saveNamedRevisionCommand() { + const noteId = appContext.tabManager.getActiveContextNoteId(); + if (!noteId) return; + + const name = await dialog.prompt({ + title: t("entrypoints.save-named-revision-title"), + message: t("entrypoints.save-named-revision-message"), + defaultValue: "" + }); + + // null means the user cancelled + if (name === null) return; + + await server.post(`notes/${noteId}/revision`, { description: name || undefined }); + toastService.showMessage(t("entrypoints.note-revision-created")); + } } diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 0367588547..7d4856a5b9 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -302,6 +302,7 @@ "snapshot_interval": "Note Revision Snapshot Interval: {{seconds}}s.", "maximum_revisions": "Note Revision Snapshot Limit: {{number}}.", "save_revision_now": "Save a revision now", + "save_named_revision": "Save named revision...", "snapshot_header": "Note revision snapshot", "snapshot_interval_value": "Interval: {{seconds}}s", "snapshot_limit_value": "Limit: {{number}}", @@ -746,6 +747,7 @@ "print_note": "Print note", "view_revisions": "Note revisions...", "save_revision": "Save revision", + "save_named_revision": "Save named revision...", "advanced": "Advanced", "convert_into_attachment_failed": "Converting note '{{title}}' failed.", "convert_into_attachment_successful": "Note '{{title}}' has been converted to attachment.", @@ -1925,6 +1927,8 @@ }, "entrypoints": { "note-revision-created": "Note revision has been created.", + "save-named-revision-title": "Save named revision", + "save-named-revision-message": "Enter a name for this revision (leave empty for no name):", "note-executed": "Note executed.", "sql-error": "Error occurred while executing SQL query: {{message}}" }, diff --git a/apps/client/src/widgets/dialogs/revisions.tsx b/apps/client/src/widgets/dialogs/revisions.tsx index e9f67d88f5..d36d509cc8 100644 --- a/apps/client/src/widgets/dialogs/revisions.tsx +++ b/apps/client/src/widgets/dialogs/revisions.tsx @@ -199,6 +199,22 @@ function RevisionsMenu({ note, onRevisionSaved, onAllDeleted, hasRevisions }: { > {t("revisions.save_revision_now")} + { + const name = await dialog.prompt({ + title: t("entrypoints.save-named-revision-title"), + message: t("entrypoints.save-named-revision-message"), + defaultValue: "" + }); + if (name === null) return; + await server.post(`notes/${note.noteId}/revision`, { description: name || undefined }); + toast.showMessage(t("revisions.revision_saved")); + onRevisionSaved(); + }} + > + {t("revisions.save_named_revision")} + {t("revisions.snapshot_header")} diff --git a/apps/client/src/widgets/ribbon/NoteActions.tsx b/apps/client/src/widgets/ribbon/NoteActions.tsx index 6490542d78..f9442f7185 100644 --- a/apps/client/src/widgets/ribbon/NoteActions.tsx +++ b/apps/client/src/widgets/ribbon/NoteActions.tsx @@ -153,6 +153,7 @@ export function NoteContextMenu({ note, noteContext, itemsAtStart, itemsNearNote + diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.html index 7a3a2c743e..fcbe2334a9 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.html @@ -62,16 +62,24 @@

      Named revisions

      Named revisions are a new feature of Trilium v0.103.0 which allows adding a short description of what the changes in the snapshot contain.

      +

      In the list of note revisions:

        -
      • -

        The name of the revision is displayed underneath the time of the revision - in the sidebar, as well as at the top of the dialog where it is displayed - in full.

        -
      • -
      • -

        Clicking on the edit button near the name of the revision allows it to - be changed.

        -
      • +
      • The name of the revision is displayed underneath the time of the revision + in the sidebar, as well as at the top of the dialog where it is displayed + in full.
      • +
      • Clicking on the edit button near the name of the revision allows it to + be changed.
      • +
      +

      To create a named revision, either:

      +
        +
      • Go to the Note buttons, + select Save named revision…, enter the name of revision and confirm.
      • +
      • Use the corresponding keyboard shortcut or + the Jump to... command + with the same name.
      • +
      • Save a revision normally, and adjust the name afterwards from the note + revision list.

      When revisions are saved

      Revisions are saved:

      diff --git a/apps/server/src/assets/translations/en/server.json b/apps/server/src/assets/translations/en/server.json index 23c8347aee..5ba0c138e9 100644 --- a/apps/server/src/assets/translations/en/server.json +++ b/apps/server/src/assets/translations/en/server.json @@ -100,6 +100,7 @@ "reset-zoom-level": "Reset zoom level", "copy-without-formatting": "Copy selected text without formatting", "force-save-revision": "Force creating / saving new note revision of the active note", + "save-named-revision": "Save a named revision of the active note", "toggle-book-properties": "Toggle Collection Properties", "toggle-classic-editor-toolbar": "Toggle the Formatting tab for the editor with fixed toolbar", "export-as-pdf": "Export the current note as a PDF", @@ -200,7 +201,8 @@ "zoom-in": "Zoom In", "reset-zoom-level": "Reset Zoom Level", "copy-without-formatting": "Copy Without Formatting", - "force-save-revision": "Force Save Revision" + "force-save-revision": "Force Save Revision", + "save-named-revision": "Save Named Revision" }, "login": { "title": "Login", diff --git a/apps/server/src/services/keyboard_actions.ts b/apps/server/src/services/keyboard_actions.ts index 326672eeb2..558d85ea5e 100644 --- a/apps/server/src/services/keyboard_actions.ts +++ b/apps/server/src/services/keyboard_actions.ts @@ -828,6 +828,14 @@ function getDefaultKeyboardActions() { defaultShortcuts: [], description: t("keyboard_actions.force-save-revision"), scope: "window" + }, + { + actionName: "saveNamedRevision", + friendlyName: t("keyboard_action_names.save-named-revision"), + iconClass: "bx bx-purchase-tag", + defaultShortcuts: [], + description: t("keyboard_actions.save-named-revision"), + scope: "window" } ]; diff --git a/docs/User Guide/!!!meta.json b/docs/User Guide/!!!meta.json index aeda15c94d..27057f940a 100644 --- a/docs/User Guide/!!!meta.json +++ b/docs/User Guide/!!!meta.json @@ -4574,6 +4574,13 @@ "value": "A9Oc6YKKc65v", "isInheritable": false, "position": 90 + }, + { + "type": "relation", + "name": "internalLink", + "value": "F1r9QtzQLZqm", + "isInheritable": false, + "position": 100 } ], "format": "markdown", diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.md b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.md index 1d44e22ffd..1a75dee966 100644 --- a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.md +++ b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.md @@ -32,9 +32,17 @@ Trilium supports seamless versioning of notes by storing snapshots ("revisions") Named revisions are a new feature of Trilium v0.103.0 which allows adding a short description of what the changes in the snapshot contain. +In the list of note revisions: + * The name of the revision is displayed underneath the time of the revision in the sidebar, as well as at the top of the dialog where it is displayed in full. * Clicking on the edit button near the name of the revision allows it to be changed. +To create a named revision, either: + +* Go to the Note buttons, select _Save named revision…_, enter the name of revision and confirm. +* Use the corresponding [keyboard shortcut](../Keyboard%20Shortcuts.md) or the Jump to... command with the same name. +* Save a revision normally, and adjust the name afterwards from the note revision list. + ## When revisions are saved Revisions are saved: diff --git a/packages/commons/src/lib/keyboard_actions_interface.ts b/packages/commons/src/lib/keyboard_actions_interface.ts index ce2defcd63..159785d4a8 100644 --- a/packages/commons/src/lib/keyboard_actions_interface.ts +++ b/packages/commons/src/lib/keyboard_actions_interface.ts @@ -94,7 +94,8 @@ const enum KeyboardActionNamesEnum { zoomIn, zoomReset, copyWithoutFormatting, - forceSaveRevision + forceSaveRevision, + saveNamedRevision } export type KeyboardActionNames = keyof typeof KeyboardActionNamesEnum; From fb3c487c0dcf42d7164a9ea5459958b5d77e80bd Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 19:22:03 +0300 Subject: [PATCH 429/482] test(server): fix ETAPI related test --- apps/server/spec/etapi/post-revision.spec.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/server/spec/etapi/post-revision.spec.ts b/apps/server/spec/etapi/post-revision.spec.ts index 20b4d15dd7..3714132fa2 100644 --- a/apps/server/spec/etapi/post-revision.spec.ts +++ b/apps/server/spec/etapi/post-revision.spec.ts @@ -20,10 +20,13 @@ describe("etapi/post-revision", () => { }); it("posts note revision", async () => { - await supertest(app) + const response = await supertest(app) .post(`/etapi/notes/${createdNoteId}/revision`) .auth(USER, token, { "type": "basic"}) .send("Changed content") - .expect(204); + .expect(201); + + expect(response.body.revisionId).toBeTruthy(); + expect(response.body.noteId).toBe(createdNoteId); }); }); From 1d25d79a3f67c3a7ba353a8f4da65f66f1aaf573 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 19:30:32 +0300 Subject: [PATCH 430/482] fix(ci): grant write permission to Claude code review workflow The pull-requests permission was set to read, preventing Claude from posting review comments on PRs. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/claude-code-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index b5e8cfd4dc..b739b56514 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read - pull-requests: read + pull-requests: write issues: read id-token: write From 2fa0a4b35cc08688f70e0f62eea867a8fe0ceb17 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 19:51:44 +0300 Subject: [PATCH 431/482] fix(ci): grant write permissions to interactive Claude workflow The contents, pull-requests, and issues permissions were set to read, preventing Claude from pushing commits and commenting on PRs/issues. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/claude.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 6b15fac7af..1051552ba1 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -19,9 +19,9 @@ jobs: (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) runs-on: ubuntu-latest permissions: - contents: read - pull-requests: read - issues: read + contents: write + pull-requests: write + issues: write id-token: write actions: read # Required for Claude to read CI results on PRs steps: From 10a2e21636e93d2cf2416ee1abe9cfc3b5e2dc60 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 19:29:54 +0300 Subject: [PATCH 432/482] chore(etapi): revert change to revision API --- apps/server/spec/etapi/post-revision.spec.ts | 9 +++------ apps/server/src/etapi/notes.ts | 4 ++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/apps/server/spec/etapi/post-revision.spec.ts b/apps/server/spec/etapi/post-revision.spec.ts index 3714132fa2..6c17c88384 100644 --- a/apps/server/spec/etapi/post-revision.spec.ts +++ b/apps/server/spec/etapi/post-revision.spec.ts @@ -1,5 +1,5 @@ import { Application } from "express"; -import { beforeAll, describe, expect, it } from "vitest"; +import { beforeAll, describe, it } from "vitest"; import supertest from "supertest"; import { createNote, login } from "./utils.js"; import config from "../../src/services/config.js"; @@ -20,13 +20,10 @@ describe("etapi/post-revision", () => { }); it("posts note revision", async () => { - const response = await supertest(app) + await supertest(app) .post(`/etapi/notes/${createdNoteId}/revision`) .auth(USER, token, { "type": "basic"}) .send("Changed content") - .expect(201); - - expect(response.body.revisionId).toBeTruthy(); - expect(response.body.noteId).toBe(createdNoteId); + .expect(204); }); }); diff --git a/apps/server/src/etapi/notes.ts b/apps/server/src/etapi/notes.ts index 8edc583435..9949b7abd2 100644 --- a/apps/server/src/etapi/notes.ts +++ b/apps/server/src/etapi/notes.ts @@ -193,9 +193,9 @@ function register(router: Router) { const note = eu.getAndCheckNote(req.params.noteId); const description = req.body?.description || ""; - const revision = note.saveRevision({ description, source: "etapi" }); + note.saveRevision({ description, source: "etapi" }); - res.status(201).json(mappers.mapRevisionToPojo(revision)); + return res.sendStatus(204); }); eu.route<{ noteId: string }>(router, "get", "/etapi/notes/:noteId/attachments", (req, res, next) => { From 23cb66bba90eb850097d10ec2fda9ffe131517db Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 19:55:26 +0300 Subject: [PATCH 433/482] chore(revisions): address requested changes --- .../src/translations/en/translation.json | 4 ++ apps/client/src/widgets/dialogs/revisions.tsx | 63 ++++++++----------- apps/client/src/widgets/react/Modal.tsx | 2 +- apps/server/src/etapi/notes.ts | 2 +- apps/server/src/routes/api/notes.ts | 2 +- .../src/services/llm/tools/note_tools.ts | 14 ++--- 6 files changed, 40 insertions(+), 47 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 7d4856a5b9..2baa838fb1 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -2539,5 +2539,9 @@ "move_note": "Move note", "clone_note": "Clone note" } + }, + "common": { + "save": "Save", + "cancel": "Cancel" } } diff --git a/apps/client/src/widgets/dialogs/revisions.tsx b/apps/client/src/widgets/dialogs/revisions.tsx index d36d509cc8..787264b1ac 100644 --- a/apps/client/src/widgets/dialogs/revisions.tsx +++ b/apps/client/src/widgets/dialogs/revisions.tsx @@ -28,7 +28,7 @@ import FormToggle from "../react/FormToggle"; import { useTriliumEvent } from "../react/hooks"; import Modal from "../react/Modal"; import NoItems from "../react/NoItems"; -import { RawHtmlBlock } from "../react/RawHtml"; +import { RawHtmlBlock, SanitizedHtml } from "../react/RawHtml"; import PdfViewer from "../type_widgets/file/PdfViewer"; export default function RevisionsDialog() { @@ -58,6 +58,7 @@ export default function RevisionsDialog() { } }, [ note, refreshCounter ]); + const revisionsLoaded = revisions !== undefined; const hasRevisions = !!revisions?.length; if (revisions?.length && !currentRevision) { @@ -72,7 +73,7 @@ export default function RevisionsDialog() { setRevisions(undefined); }; - if (!hasRevisions) { + if (revisionsLoaded && !hasRevisions) { return ( - - + +
    ); } @@ -584,41 +585,31 @@ function RevisionContentDiff({ noteContent, itemContent, itemType }: { itemContent: string | Buffer | undefined, itemType: string }) { - const contentRef = useRef(null); + if (!noteContent || typeof itemContent !== "string") { + return
    {t("revisions.diff_not_available")}
    ; + } - useEffect(() => { - if (!noteContent || typeof itemContent !== "string") { - if (contentRef.current) { - contentRef.current.textContent = t("revisions.diff_not_available"); + let diffHtml: string; + if (itemType === "text") { + // Use proper HTML-aware diff for rich text content + diffHtml = HtmlDiff.execute(noteContent, itemContent); + } else { + // Use word diff for code/mermaid (plain text) + const diff = diffWords(noteContent, itemContent); + diffHtml = diff.map(part => { + if (part.added) { + return `${utils.escapeHtml(part.value)}`; + } else if (part.removed) { + return `${utils.escapeHtml(part.value)}`; } - return; - } + return utils.escapeHtml(part.value); + }).join(""); + } - if (itemType === "text") { - // Use proper HTML-aware diff for rich text content - const diffHtml = HtmlDiff.execute(noteContent, itemContent); - if (contentRef.current) { - contentRef.current.innerHTML = diffHtml; - } - } else { - // Use word diff for code/mermaid (plain text) - const diff = diffWords(noteContent, itemContent); - const diffHtml = diff.map(part => { - if (part.added) { - return `${utils.escapeHtml(part.value)}`; - } else if (part.removed) { - return `${utils.escapeHtml(part.value)}`; - } - return utils.escapeHtml(part.value); - }).join(""); - - if (contentRef.current) { - contentRef.current.innerHTML = diffHtml; - } - } - }, [noteContent, itemContent, itemType]); - - return
    ; + return ; } diff --git a/apps/client/src/widgets/react/Modal.tsx b/apps/client/src/widgets/react/Modal.tsx index 9c0addce13..dcbb884961 100644 --- a/apps/client/src/widgets/react/Modal.tsx +++ b/apps/client/src/widgets/react/Modal.tsx @@ -153,7 +153,7 @@ export default function Modal({ children, className, size, title, customTitleBar
    {sidebar &&
    {title &&
    -
    {typeof title === "string" ? title : title}
    +
    {title}
    } {sidebar}
    } diff --git a/apps/server/src/etapi/notes.ts b/apps/server/src/etapi/notes.ts index 9949b7abd2..74faf7aabe 100644 --- a/apps/server/src/etapi/notes.ts +++ b/apps/server/src/etapi/notes.ts @@ -192,7 +192,7 @@ function register(router: Router) { eu.route<{ noteId: string }>(router, "post", "/etapi/notes/:noteId/revision", (req, res, next) => { const note = eu.getAndCheckNote(req.params.noteId); - const description = req.body?.description || ""; + const description = typeof req.body?.description === "string" ? req.body.description : ""; note.saveRevision({ description, source: "etapi" }); return res.sendStatus(204); diff --git a/apps/server/src/routes/api/notes.ts b/apps/server/src/routes/api/notes.ts index 8aec006a09..e8e7d92ff2 100644 --- a/apps/server/src/routes/api/notes.ts +++ b/apps/server/src/routes/api/notes.ts @@ -351,7 +351,7 @@ function forceSaveRevision(req: Request<{ noteId: string }>) { throw new ValidationError(`Note revision of a protected note cannot be created outside of a protected session.`); } - const description = req.body?.description || ""; + const description = typeof req.body?.description === "string" ? req.body.description : ""; const revision = note.saveRevision({ description, source: "manual" }); return { diff --git a/apps/server/src/services/llm/tools/note_tools.ts b/apps/server/src/services/llm/tools/note_tools.ts index 8a4ec1c97b..d1ce83e3e0 100644 --- a/apps/server/src/services/llm/tools/note_tools.ts +++ b/apps/server/src/services/llm/tools/note_tools.ts @@ -101,11 +101,10 @@ export const noteTools = defineTools({ description: "Replace the entire content of a note. Use this to completely rewrite a note's content. For text notes, provide Markdown content.", inputSchema: z.object({ noteId: z.string().describe("The ID of the note to update"), - content: z.string().describe("The new content for the note (Markdown for text notes, plain text for code notes)"), - changeDescription: z.string().describe("A concise description of what was changed and why (e.g. 'Fix typos in introduction', 'Add section on error handling'). Keep it short, under 100 characters.") + content: z.string().describe("The new content for the note (Markdown for text notes, plain text for code notes)") }), mutates: true, - execute: ({ noteId, content, changeDescription }) => { + execute: ({ noteId, content }) => { const note = becca.getNote(noteId); if (!note) { return { error: "Note not found" }; @@ -117,7 +116,7 @@ export const noteTools = defineTools({ return { error: `Cannot update content for note type: ${note.type}` }; } - note.saveRevision({ description: changeDescription, source: "llm" }); + note.saveRevision({ source: "llm" }); setNoteContentFromLlm(note, content); return { success: true, @@ -131,11 +130,10 @@ export const noteTools = defineTools({ description: "Append content to the end of an existing note. For text notes, provide Markdown content.", inputSchema: z.object({ noteId: z.string().describe("The ID of the note to append to"), - content: z.string().describe("The content to append (Markdown for text notes, plain text for code notes)"), - changeDescription: z.string().describe("A concise description of what was appended (e.g. 'Add meeting notes for May 15', 'Append troubleshooting section'). Keep it short, under 100 characters.") + content: z.string().describe("The content to append (Markdown for text notes, plain text for code notes)") }), mutates: true, - execute: ({ noteId, content, changeDescription }) => { + execute: ({ noteId, content }) => { const note = becca.getNote(noteId); if (!note) { return { error: "Note not found" }; @@ -160,7 +158,7 @@ export const noteTools = defineTools({ newContent = existingContent + (existingContent.endsWith("\n") ? "" : "\n") + content; } - note.saveRevision({ description: changeDescription, source: "llm" }); + note.saveRevision({ source: "llm" }); note.setContent(newContent); return { success: true, From b2bcccb4c7e47b1a8c07da66e59f13098aabbb4d Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 17:07:02 +0000 Subject: [PATCH 434/482] fix(ocr): adapt OfficeProcessor to officeparser v6.1.0 ESM changes v6.1.0 added native ESM with Node16 resolution and a strict exports field, breaking deep subpath imports like officeparser/dist/parsers/ExcelParser.js. Switch to the main package entry and use parseOfficeAsync(), which accepts a Buffer and auto-detects the format via magic bytes. Co-authored-by: Elian Doran --- .../ocr/processors/office_processor.ts | 38 ++++++++----------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/apps/server/src/services/ocr/processors/office_processor.ts b/apps/server/src/services/ocr/processors/office_processor.ts index f2ee7e8ebe..cb6b5f0a27 100644 --- a/apps/server/src/services/ocr/processors/office_processor.ts +++ b/apps/server/src/services/ocr/processors/office_processor.ts @@ -1,25 +1,20 @@ -import { parseExcel } from 'officeparser/dist/parsers/ExcelParser.js'; -import { parseOpenOffice } from 'officeparser/dist/parsers/OpenOfficeParser.js'; -import { parsePowerPoint } from 'officeparser/dist/parsers/PowerPointParser.js'; -import { parseWord } from 'officeparser/dist/parsers/WordParser.js'; -import type { OfficeParserConfig } from 'officeparser/dist/types.js'; +import officeparser from 'officeparser'; +import type { OfficeParserConfig } from 'officeparser'; import log from '../../log.js'; import { OCRProcessingOptions, OCRResult } from '../ocr_service.js'; import { FileProcessor } from './file_processor.js'; -type Parser = (buffer: Buffer, config: OfficeParserConfig) => Promise<{ toText(): string }>; - -const PARSER_BY_MIME: Record = { +const SUPPORTED_MIME_TYPES = new Set([ // Office Open XML - 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': parseWord, - 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': parseExcel, - 'application/vnd.openxmlformats-officedocument.presentationml.presentation': parsePowerPoint, + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', // OpenDocument - 'application/vnd.oasis.opendocument.text': parseOpenOffice, - 'application/vnd.oasis.opendocument.spreadsheet': parseOpenOffice, - 'application/vnd.oasis.opendocument.presentation': parseOpenOffice -}; + 'application/vnd.oasis.opendocument.text', + 'application/vnd.oasis.opendocument.spreadsheet', + 'application/vnd.oasis.opendocument.presentation' +]); const PARSER_CONFIG: OfficeParserConfig = { outputErrorToConsole: false, @@ -30,29 +25,28 @@ const PARSER_CONFIG: OfficeParserConfig = { /** * Office document processor for extracting text from DOCX/XLSX/PPTX and ODT/ODS/ODP files. - * Uses individual parsers from officeparser v6 to avoid pulling in pdfjs-dist. + * Uses officeparser's main API, which auto-detects the format from the buffer's magic bytes. */ export class OfficeProcessor extends FileProcessor { canProcess(mimeType: string): boolean { - return mimeType in PARSER_BY_MIME; + return SUPPORTED_MIME_TYPES.has(mimeType); } getSupportedMimeTypes(): string[] { - return Object.keys(PARSER_BY_MIME); + return [...SUPPORTED_MIME_TYPES]; } async extractText(buffer: Buffer, options: OCRProcessingOptions = {}): Promise { const mimeType = options.mimeType; - if (!mimeType || !(mimeType in PARSER_BY_MIME)) { + if (!mimeType || !SUPPORTED_MIME_TYPES.has(mimeType)) { throw new Error(`Unsupported MIME type for Office processor: ${mimeType}`); } log.info(`Starting Office document text extraction for ${mimeType}...`); - const parse = PARSER_BY_MIME[mimeType]; - const ast = await parse(buffer, PARSER_CONFIG); - const trimmed = ast.toText().trim(); + const text = await officeparser.parseOfficeAsync(buffer, PARSER_CONFIG); + const trimmed = text.trim(); return { text: trimmed, From dbea88fa56a9e7905844a23dafb664af5abf570f Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sat, 18 Apr 2026 20:20:06 +0300 Subject: [PATCH 435/482] client/modal dialog: add support for full page dialogs on mobile --- apps/client/src/stylesheets/style.css | 15 +++++++++++++++ apps/client/src/widgets/react/Modal.tsx | 8 ++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/apps/client/src/stylesheets/style.css b/apps/client/src/stylesheets/style.css index c1672f50c4..f9bc58362e 100644 --- a/apps/client/src/stylesheets/style.css +++ b/apps/client/src/stylesheets/style.css @@ -1666,6 +1666,21 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu { display: flex; } + body.mobile .modal-dialog.modal-dialog-full-page-on-mobile { + width: 100%; + height: 100%; + max-height: unset; + + .modal-content { + border-radius: 0; + border: 0; + + .modal-body { + overflow: scroll; + } + } + } + body.mobile .modal-content { overflow-y: auto; border-radius: var(--bs-modal-border-radius) var(--bs-modal-border-radius) 0 0; diff --git a/apps/client/src/widgets/react/Modal.tsx b/apps/client/src/widgets/react/Modal.tsx index fcaa287380..0a3d35fa79 100644 --- a/apps/client/src/widgets/react/Modal.tsx +++ b/apps/client/src/widgets/react/Modal.tsx @@ -77,9 +77,13 @@ export interface ModalProps { * If true, the modal will not focus itself after becoming visible. */ noFocus?: boolean; + /** + * Indicates if the dialog will be displayed as a full page on mobile devices. + */ + isFullPageOnMobile?: boolean; } -export default function Modal({ children, className, size, title, customTitleBarButtons: titleBarButtons, header, footer, footerStyle, footerAlignment, onShown, onSubmit, helpPageId, minWidth, maxWidth, zIndex, scrollable, onHidden, modalRef: externalModalRef, formRef, bodyStyle, show, stackable, keepInDom, noFocus }: ModalProps) { +export default function Modal({ children, className, size, title, customTitleBarButtons: titleBarButtons, header, footer, footerStyle, footerAlignment, onShown, onSubmit, helpPageId, minWidth, maxWidth, zIndex, scrollable, onHidden, modalRef: externalModalRef, formRef, bodyStyle, show, stackable, keepInDom, noFocus, isFullPageOnMobile }: ModalProps) { const modalRef = useSyncedRef(externalModalRef); const modalInstanceRef = useRef(); const elementToFocus = useRef(); @@ -143,7 +147,7 @@ export default function Modal({ children, className, size, title, customTitleBar return (
    - {(show || keepInDom) &&
    + {(show || keepInDom) &&
    {!title || typeof title === "string" ? ( From b349922addab22506f489b90dd5fd0b3d11954e6 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sat, 18 Apr 2026 20:20:39 +0300 Subject: [PATCH 436/482] client/about dialog: make full page on mobile --- apps/client/src/widgets/dialogs/about.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index 2e5de6907f..755c45a072 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -69,6 +69,7 @@ export default function AboutDialog() { setIsShown(false)} > From 36270397c23c51ad25c37b59d809c2b9b01b1655 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sat, 18 Apr 2026 20:21:52 +0300 Subject: [PATCH 437/482] git mailmap: update --- .mailmap | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 2 deletions(-) diff --git a/.mailmap b/.mailmap index 33287fa2ca..2aaad92883 100644 --- a/.mailmap +++ b/.mailmap @@ -1,2 +1,115 @@ -zadam -zadam \ No newline at end of file +# Format: Canonical Name +# Merges aliases so `git shortlog`, `git log --use-mailmap`, etc. group commits per person. + +# Core maintainers +zadam +zadam +zadam + +Elian Doran +Elian Doran + +Adorian Doran +Adorian Doran + +# Contributors with multiple emails / name variants +Panagiotis Papadopoulos <102623907+pano9000@users.noreply.github.com> + +Jon Fuller + +SiriusXT <11609255001@qq.com> +SiriusXT <11609255001@qq.com> <37627919+SiriusXT@users.noreply.github.com> + +JYC333 <22962980+JYC333@users.noreply.github.com> +JYC333 <22962980+JYC333@users.noreply.github.com> + +Nriver <6752679+Nriver@users.noreply.github.com> + +Francis C. +Francis C. + +Thomas Frei <7283497+thfrei@users.noreply.github.com> + +hasecilu + +meinzzzz + +FliegendeWurst +FliegendeWurst <2012gdwu@web.de> +FliegendeWurst <2012gdwu+github@posteo.de> + +MeIchthys +MeIchthys <10717998+meichthys@users.noreply.github.com> + +Marcel Wiechmann +Marcel Wiechmann + +Tomas Adamek +Tomas Adamek <50672285+Kureii@users.noreply.github.com> + +soulsands <407221377@qq.com> + +chesspro13 + +sigaloid <69441971+sigaloid@users.noreply.github.com> + +Marek Lewandowski +Marek Lewandowski +Marek Lewandowski + +lzinga +lzinga + +Sukant Gujar + +Matt Wilkie +Matt Wilkie + +Andreas Haan + +Potjoe-97 <42873357+Potjoe-97@users.noreply.github.com> +Potjoe-97 <42873357+Potjoe-97@users.noreply.github.com> + +Alex Pietsch <54153428+alexpietsch@users.noreply.github.com> + +Laurent Cozic +Laurent Cozic + +Zexin Yuan +Zexin Yuan + +hulmgulm +hulmgulm <12165268+hulmgulm@users.noreply.github.com> +hulmgulm + +Jules Bertholet + +Charles Dagenais + +Giulia Ye + +baddate <37013819+baddate@users.noreply.github.com> + +DerVogel101 <128903814+DerVogel101@users.noreply.github.com> +DerVogel101 <128903814+DerVogel101@users.noreply.github.com> + +Marcello Fuschi + +Jiahao Lee + +Dmitry Matveyev +Dmitry Matveyev + +Grant Zhu + +Sylvain Pasche +Sylvain Pasche + +mm21 <8033134+mm21@users.noreply.github.com> +mm21 <8033134+mm21@users.noreply.github.com> + +BeatLink +BeatLink + +Florian Meißner <161936+Mystler@users.noreply.github.com> +Florian Meißner <161936+Mystler@users.noreply.github.com> From 1d8a8107af8ca5edc8b51ff2f4f8f3c0e7615ceb Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sat, 18 Apr 2026 20:29:49 +0300 Subject: [PATCH 438/482] style/property sheet component: improve appearance --- apps/client/src/widgets/react/PropertySheet.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/client/src/widgets/react/PropertySheet.css b/apps/client/src/widgets/react/PropertySheet.css index e829526e77..4416e47cb5 100644 --- a/apps/client/src/widgets/react/PropertySheet.css +++ b/apps/client/src/widgets/react/PropertySheet.css @@ -7,7 +7,7 @@ background: var(--card-background-color); dt { - color: var(--muted-text-color); + opacity: .75; } dd { @@ -57,7 +57,7 @@ dl { margin: 0; - padding: 12px 20px; + padding: 16px 20px; &:first-child { border-radius: var(--border-radius) var(--border-radius) 0 0; @@ -70,9 +70,9 @@ dt { margin-bottom: 8px; font-size: .85em; - font-weight: 500; + font-weight: 550; text-transform: uppercase; - letter-spacing: .4pt; + letter-spacing: .75pt; } dd { From ac1bcefe80f442ac88ff8b5a3a052b1d08a71156 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sat, 18 Apr 2026 20:31:48 +0300 Subject: [PATCH 439/482] client/property sheet component: fix width limit on mobile --- apps/client/src/stylesheets/style.css | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/client/src/stylesheets/style.css b/apps/client/src/stylesheets/style.css index f9bc58362e..5d35dbfb14 100644 --- a/apps/client/src/stylesheets/style.css +++ b/apps/client/src/stylesheets/style.css @@ -1670,6 +1670,7 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu { width: 100%; height: 100%; max-height: unset; + max-width: unset; .modal-content { border-radius: 0; From 8d41ba85a84bca0da0864572397b88e7f779c4b1 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 21:35:29 +0300 Subject: [PATCH 440/482] docs(user): add documentation on code & print improvements --- .../doc_notes/en/User Guide/!!!meta.json | 2 +- ...e.png => 1_Jump to & command palette_.png} | Bin ...e.png => 2_Jump to & command palette_.png} | Bin ...to.html => Jump to & command palette.html} | 9 +- ...age.png => Jump to & command palette_.png} | Bin .../Notes/1_Printing & Exporting as PD.png | Bin 150 -> 248650 bytes .../Notes/Note Revisions.html | 43 +- .../Notes/Printing & Exporting as PD.png | Bin 89512 -> 150 bytes .../Notes/Printing & Exporting as PDF.html | 411 ++++++++++-------- .../Notes/Read-Only Notes.html | 3 +- .../User Guide/Note Types/Code.html | 57 ++- .../Code blocks.html | 4 +- .../Developer Guide/Documentation.md | 2 +- docs/User Guide/!!!meta.json | 149 ++++--- ...e.png => 1_Jump to & command palette_.png} | Bin ...e.png => 2_Jump to & command palette_.png} | Bin ...ump to.md => Jump to & command palette.md} | 8 +- ...age.png => Jump to & command palette_.png} | Bin .../Navigation/Note Navigation.md | 2 +- .../Navigation/Quick search.md | 2 +- .../Notes/1_Printing & Exporting as PD.png | Bin 150 -> 248650 bytes .../Notes/Note Revisions.md | 2 +- .../Notes/Printing & Exporting as PD.png | Bin 89512 -> 150 bytes .../Notes/Printing & Exporting as PDF.md | 71 ++- .../Notes/Read-Only Notes.md | 2 +- docs/User Guide/User Guide/Note Types/Code.md | 31 ++ .../Code blocks.md | 1 + 27 files changed, 491 insertions(+), 308 deletions(-) rename apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/{1_Jump to_image.png => 1_Jump to & command palette_.png} (100%) rename apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/{2_Jump to_image.png => 2_Jump to & command palette_.png} (100%) rename apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/{Jump to.html => Jump to & command palette.html} (92%) rename apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/{Jump to_image.png => Jump to & command palette_.png} (100%) rename docs/User Guide/User Guide/Basic Concepts and Features/Navigation/{1_Jump to_image.png => 1_Jump to & command palette_.png} (100%) rename docs/User Guide/User Guide/Basic Concepts and Features/Navigation/{2_Jump to_image.png => 2_Jump to & command palette_.png} (100%) rename docs/User Guide/User Guide/Basic Concepts and Features/Navigation/{Jump to.md => Jump to & command palette.md} (90%) rename docs/User Guide/User Guide/Basic Concepts and Features/Navigation/{Jump to_image.png => Jump to & command palette_.png} (100%) diff --git a/apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json b/apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json index 05880adefa..9b06730cd6 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json +++ b/apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json @@ -1 +1 @@ -[{"id":"_help_BOCnjTMBCoxW","title":"Feature Highlights","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Feature Highlights"},{"name":"iconClass","value":"bx bx-star","type":"label"}]},{"id":"_help_Otzi9La2YAUX","title":"Installation & Setup","type":"book","attributes":[{"name":"iconClass","value":"bx bx-cog","type":"label"}],"children":[{"id":"_help_poXkQfguuA0U","title":"Desktop Installation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation"},{"name":"iconClass","value":"bx bx-desktop","type":"label"}],"children":[{"id":"_help_nRqcgfTb97uV","title":"Using the desktop application as a server","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/Using the desktop application "},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_Rp0q8bSP6Ayl","title":"System Requirements","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/System Requirements"},{"name":"iconClass","value":"bx bx-chip","type":"label"}]},{"id":"_help_Un4wj2Mak2Ky","title":"Nix flake","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/Nix flake"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]}]},{"id":"_help_WOcw2SLH6tbX","title":"Server Installation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation"},{"name":"iconClass","value":"bx bx-server","type":"label"}],"children":[{"id":"_help_Dgg7bR3b6K9j","title":"1. Installing the server","type":"book","attributes":[{"name":"iconClass","value":"bx bx-folder","type":"label"}],"children":[{"id":"_help_3tW6mORuTHnB","title":"Packaged version for Linux","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Packaged version for Linux"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]},{"id":"_help_rWX5eY045zbE","title":"Using Docker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Docker"},{"name":"iconClass","value":"bx bxl-docker","type":"label"}]},{"id":"_help_moVgBcoxE3EK","title":"On NixOS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/On NixOS"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]},{"id":"_help_J1Bb6lVlwU5T","title":"Manually","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Manually"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}]},{"id":"_help_DCmT6e7clMoP","title":"Using Kubernetes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Kubernetes"},{"name":"iconClass","value":"bx bxl-kubernetes","type":"label"}]},{"id":"_help_klCWNks3ReaQ","title":"Multiple server instances","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Multiple server instances"},{"name":"iconClass","value":"bx bxs-user-account","type":"label"}]}]},{"id":"_help_vcjrb3VVYPZI","title":"2. Reverse proxy","type":"book","attributes":[{"name":"iconClass","value":"bx bx-folder","type":"label"}],"children":[{"id":"_help_ud6MShXL4WpO","title":"Nginx","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Nginx"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_fDLvzOx29Pfg","title":"Apache using Docker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Apache using Docker"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_LLzSMXACKhUs","title":"Trusted proxy","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Trusted proxy"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_5ERVJb9s4FRD","title":"Traefik","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Traefik"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_l2VkvOwUNfZj","title":"HTTPS (TLS)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/HTTPS (TLS)"},{"name":"iconClass","value":"bx bx-lock-alt","type":"label"}]},{"id":"_help_0hzsNCP31IAB","title":"Authentication","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Authentication"},{"name":"iconClass","value":"bx bx-user","type":"label"}]},{"id":"_help_7DAiwaf8Z7Rz","title":"Multi-Factor Authentication","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Multi-Factor Authentication"},{"name":"iconClass","value":"bx bx-stopwatch","type":"label"}]},{"id":"_help_Un4wj2Mak2Ky","title":"Nix flake","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Nix flake.clone"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_yeEaYqosGLSh","title":"Third-party cloud hosting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Third-party cloud hosting"},{"name":"iconClass","value":"bx bx-cloud","type":"label"}]},{"id":"_help_iGTnKjubbXkA","title":"System Requirements","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/System Requirements"},{"name":"iconClass","value":"bx bx-chip","type":"label"}]}]},{"id":"_help_cbkrhQjrkKrh","title":"Synchronization","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Synchronization"},{"name":"iconClass","value":"bx bx-sync","type":"label"}]},{"id":"_help_RDslemsQ6gCp","title":"Mobile Frontend","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Mobile Frontend"},{"name":"iconClass","value":"bx bx-mobile-alt","type":"label"}]},{"id":"_help_MtPxeAWVAzMg","title":"Web Clipper","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Web Clipper"},{"name":"iconClass","value":"bx bx-paperclip","type":"label"}]},{"id":"_help_n1lujUxCwipy","title":"Upgrading TriliumNext","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Upgrading TriliumNext"},{"name":"iconClass","value":"bx bx-up-arrow-alt","type":"label"}]},{"id":"_help_ODY7qQn5m2FT","title":"Backup","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Backup"},{"name":"iconClass","value":"bx bx-hdd","type":"label"}]},{"id":"_help_tAassRL4RSQL","title":"Data directory","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Data directory"},{"name":"iconClass","value":"bx bx-folder-open","type":"label"}]}]},{"id":"_help_gh7bpGYxajRS","title":"Basic Concepts and Features","type":"book","attributes":[{"name":"iconClass","value":"bx bx-help-circle","type":"label"}],"children":[{"id":"_help_Vc8PjrjAGuOp","title":"UI Elements","type":"book","attributes":[{"name":"iconClass","value":"bx bx-window-alt","type":"label"}],"children":[{"id":"_help_x0JgW8UqGXvq","title":"Vertical and horizontal layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Vertical and horizontal layout"},{"name":"iconClass","value":"bx bxs-layout","type":"label"}]},{"id":"_help_x3i7MxGccDuM","title":"Global menu","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Global menu"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_oPVyFC7WL2Lp","title":"Note Tree","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree"},{"name":"iconClass","value":"bx bxs-tree-alt","type":"label"}],"children":[{"id":"_help_YtSN43OrfzaA","title":"Note tree contextual menu","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Note tree contextual menu"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_yTjUdsOi4CIE","title":"Multiple selection","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Multiple selection"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_DvdZhoQZY9Yd","title":"Keyboard shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Keyboard shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_wyaGBBQrl4i3","title":"Hiding the subtree","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Hiding the subtree"},{"name":"iconClass","value":"bx bx-hide","type":"label"}]}]},{"id":"_help_BlN9DFI679QC","title":"Ribbon","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Ribbon"},{"name":"iconClass","value":"bx bx-dots-horizontal","type":"label"}]},{"id":"_help_3seOhtN8uLIY","title":"Tabs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Tabs"},{"name":"iconClass","value":"bx bx-dock-top","type":"label"}]},{"id":"_help_xYmIYSP6wE3F","title":"Launch Bar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Launch Bar"},{"name":"iconClass","value":"bx bx-sidebar","type":"label"}]},{"id":"_help_8YBEPzcpUgxw","title":"Note buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note buttons"},{"name":"iconClass","value":"bx bx-dots-vertical-rounded","type":"label"}]},{"id":"_help_4TIF1oA4VQRO","title":"Options","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Options"},{"name":"iconClass","value":"bx bx-cog","type":"label"}]},{"id":"_help_luNhaphA37EO","title":"Split View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View"},{"name":"iconClass","value":"bx bx-dock-right","type":"label"}]},{"id":"_help_XpOYSgsLkTJy","title":"Floating buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Floating buttons"},{"name":"iconClass","value":"bx bx-rectangle","type":"label"}]},{"id":"_help_RnaPdbciOfeq","title":"Right Sidebar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Right Sidebar"},{"name":"iconClass","value":"bx bxs-dock-right","type":"label"}]},{"id":"_help_r5JGHN99bVKn","title":"Recent Changes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Recent Changes"},{"name":"iconClass","value":"bx bx-history","type":"label"}]},{"id":"_help_ny318J39E5Z0","title":"Zoom","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Zoom"},{"name":"iconClass","value":"bx bx-zoom-in","type":"label"}]},{"id":"_help_lgKX7r3aL30x","title":"Note Tooltip","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tooltip"},{"name":"iconClass","value":"bx bx-message-detail","type":"label"}]},{"id":"_help_IjZS7iK5EXtb","title":"New Layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/New Layout"},{"name":"iconClass","value":"bx bx-layout","type":"label"}],"children":[{"id":"_help_I6p2a06hdnL6","title":"Breadcrumb","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/New Layout/Breadcrumb"},{"name":"iconClass","value":"bx bx-chevron-right","type":"label"}]},{"id":"_help_AlJ73vBCjWDw","title":"Status bar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/New Layout/Status bar"},{"name":"iconClass","value":"bx bx-dock-bottom","type":"label"}]}]},{"id":"_help_SL5f1Auq7sVN","title":"Note types with split view","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note types with split view"},{"name":"iconClass","value":"bx bx-card","type":"label"}]}]},{"id":"_help_BFs8mudNFgCS","title":"Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes"},{"name":"iconClass","value":"bx bx-notepad","type":"label"}],"children":[{"id":"_help_p9kXRFAkwN4o","title":"Note Icons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_0vhv7lsOLy82","title":"Attachments","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Attachments"},{"name":"iconClass","value":"bx bx-paperclip","type":"label"}]},{"id":"_help_IakOLONlIfGI","title":"Cloning Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes"},{"name":"iconClass","value":"bx bx-duplicate","type":"label"}],"children":[{"id":"_help_TBwsyfadTA18","title":"Branch prefix","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes/Branch prefix"},{"name":"iconClass","value":"bx bx-rename","type":"label"}]}]},{"id":"_help_bwg0e8ewQMak","title":"Protected Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Protected Notes"},{"name":"iconClass","value":"bx bx-lock-alt","type":"label"}]},{"id":"_help_MKmLg5x6xkor","title":"Archived Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Archived Notes"},{"name":"iconClass","value":"bx bx-box","type":"label"}]},{"id":"_help_vZWERwf8U3nx","title":"Note Revisions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions"},{"name":"iconClass","value":"bx bx-history","type":"label"}]},{"id":"_help_aGlEvb9hyDhS","title":"Sorting Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Sorting Notes"},{"name":"iconClass","value":"bx bx-sort-up","type":"label"}]},{"id":"_help_NRnIZmSMc5sj","title":"Printing & Exporting as PDF","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF"},{"name":"iconClass","value":"bx bx-printer","type":"label"}]},{"id":"_help_CoFPLs3dRlXc","title":"Read-Only Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes"},{"name":"iconClass","value":"bx bx-edit-alt","type":"label"}]},{"id":"_help_0ESUbbAxVnoK","title":"Note List","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note List"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]}]},{"id":"_help_wArbEsdSae6g","title":"Navigation","type":"book","attributes":[{"name":"iconClass","value":"bx bx-navigation","type":"label"}],"children":[{"id":"_help_kBrnXNG3Hplm","title":"Tree Concepts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Tree Concepts"},{"name":"iconClass","value":"bx bx-pyramid","type":"label"}]},{"id":"_help_MMiBEQljMQh2","title":"Note Navigation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation"},{"name":"iconClass","value":"bx bxs-navigation","type":"label"}]},{"id":"_help_Ms1nauBra7gq","title":"Quick search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Quick search"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]},{"id":"_help_F1r9QtzQLZqm","title":"Jump to...","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to"},{"name":"iconClass","value":"bx bx-send","type":"label"}]},{"id":"_help_eIg8jdvaoNNd","title":"Search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Search"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]},{"id":"_help_u3YFHC9tQlpm","title":"Bookmarks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks"},{"name":"iconClass","value":"bx bx-bookmarks","type":"label"}]},{"id":"_help_OR8WJ7Iz9K4U","title":"Note Hoisting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Note Hoisting"},{"name":"iconClass","value":"bx bxs-chevrons-up","type":"label"}]},{"id":"_help_ZjLYv08Rp3qC","title":"Quick edit","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Quick edit"},{"name":"iconClass","value":"bx bx-edit","type":"label"}]},{"id":"_help_9sRHySam5fXb","title":"Workspaces","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Workspaces"},{"name":"iconClass","value":"bx bx-door-open","type":"label"}]},{"id":"_help_xWtq5NUHOwql","title":"Similar Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Similar Notes"},{"name":"iconClass","value":"bx bx-bar-chart","type":"label"}]},{"id":"_help_McngOG2jbUWX","title":"Search in note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Search in note"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]}]},{"id":"_help_A9Oc6YKKc65v","title":"Keyboard Shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Keyboard Shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_Wy267RK4M69c","title":"Themes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes"},{"name":"iconClass","value":"bx bx-palette","type":"label"}],"children":[{"id":"_help_VbjZvtUek0Ln","title":"Theme Gallery","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes/Theme Gallery"},{"name":"iconClass","value":"bx bx-book-reader","type":"label"}]},{"id":"_help_gOKqSJgXLcIj","title":"Icon Packs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes/Icon Packs"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_mHbBMPDPkVV5","title":"Import & Export","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export"},{"name":"iconClass","value":"bx bx-import","type":"label"}],"children":[{"id":"_help_Oau6X9rCuegd","title":"Markdown","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}],"children":[{"id":"_help_rJ9grSgoExl9","title":"Supported syntax","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown/Supported syntax"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}]}]},{"id":"_help_syuSEKf2rUGr","title":"Evernote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Evernote"},{"name":"iconClass","value":"bx bx-window-open","type":"label"}],"children":[{"id":"_help_dj3j8dG4th4l","title":"Process internal links by title","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_GnhlmrATVqcH","title":"OneNote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/OneNote"},{"name":"iconClass","value":"bx bx-window-open","type":"label"}]}]},{"id":"_help_rC3pL2aptaRE","title":"Zen mode","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Zen mode"},{"name":"iconClass","value":"bx bxs-yin-yang","type":"label"}]},{"id":"_help_YzMcWlCVeW09","title":"Active content","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Active content"},{"name":"iconClass","value":"bx bxs-widget","type":"label"}]}]},{"id":"_help_s3YCWHBfmYuM","title":"Quick Start","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Quick Start"},{"name":"iconClass","value":"bx bx-run","type":"label"}]},{"id":"_help_i6dbnitykE5D","title":"FAQ","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/FAQ"},{"name":"iconClass","value":"bx bx-question-mark","type":"label"}]},{"id":"_help_KSZ04uQ2D1St","title":"Note Types","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types"},{"name":"iconClass","value":"bx bx-edit","type":"label"}],"children":[{"id":"_help_iPIMuisry3hd","title":"Text","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text"},{"name":"iconClass","value":"bx bx-note","type":"label"}],"children":[{"id":"_help_oSuaNgyyKnhu","title":"Anchors","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Anchors"},{"name":"iconClass","value":"bx bx-bookmark","type":"label"}]},{"id":"_help_NwBbFdNZ9h7O","title":"Block quotes & admonitions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Block quotes & admonitions"},{"name":"iconClass","value":"bx bx-info-circle","type":"label"}]},{"id":"_help_veGu4faJErEM","title":"Content language & Right-to-left support","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Content language & Right-to-le"},{"name":"iconClass","value":"bx bx-align-right","type":"label"}]},{"id":"_help_2x0ZAX9ePtzV","title":"Cut to subnote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Cut to subnote"},{"name":"iconClass","value":"bx bx-cut","type":"label"}]},{"id":"_help_UYuUB1ZekNQU","title":"Developer-specific formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Developer-specific formatting"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}],"children":[{"id":"_help_QxEyIjRBizuC","title":"Code blocks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Developer-specific formatting/Code blocks"},{"name":"iconClass","value":"bx bx-code","type":"label"}]}]},{"id":"_help_AgjCISero73a","title":"Footnotes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Footnotes"},{"name":"iconClass","value":"bx bx-bracket","type":"label"}]},{"id":"_help_nRhnJkTT8cPs","title":"Formatting toolbar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Formatting toolbar"},{"name":"iconClass","value":"bx bx-text","type":"label"}]},{"id":"_help_Gr6xFaF6ioJ5","title":"General formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/General formatting"},{"name":"iconClass","value":"bx bx-bold","type":"label"}]},{"id":"_help_AxshuNRegLAv","title":"Highlights list","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Highlights list"},{"name":"iconClass","value":"bx bx-highlight","type":"label"}]},{"id":"_help_mT0HEkOsz6i1","title":"Images","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Images"},{"name":"iconClass","value":"bx bx-image-alt","type":"label"}],"children":[{"id":"_help_0Ofbk1aSuVRu","title":"Image references","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Images/Image references"},{"name":"iconClass","value":"bx bxs-file-image","type":"label"}]}]},{"id":"_help_nBAXQFj20hS1","title":"Include Note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Include Note"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_CohkqWQC1iBv","title":"Insert buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Insert buttons"},{"name":"iconClass","value":"bx bx-plus","type":"label"}]},{"id":"_help_oiVPnW8QfnvS","title":"Keyboard shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Keyboard shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_QEAPj01N5f7w","title":"Links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links"},{"name":"iconClass","value":"bx bx-link-alt","type":"label"}],"children":[{"id":"_help_3IDVtesTQ8ds","title":"External links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links/External links"},{"name":"iconClass","value":"bx bx-link-external","type":"label"}]},{"id":"_help_hrZ1D00cLbal","title":"Internal (reference) links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links/Internal (reference) links"},{"name":"iconClass","value":"bx bx-link","type":"label"}]}]},{"id":"_help_S6Xx8QIWTV66","title":"Lists","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Lists"},{"name":"iconClass","value":"bx bx-list-ul","type":"label"}]},{"id":"_help_QrtTYPmdd1qq","title":"Markdown-like formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Markdown-like formatting"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}]},{"id":"_help_YfYAtQBcfo5V","title":"Math Equations","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Math Equations"},{"name":"iconClass","value":"bx bx-math","type":"label"}]},{"id":"_help_dEHYtoWWi8ct","title":"Other features","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Other features"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_gLt3vA97tMcp","title":"Premium features","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features"},{"name":"iconClass","value":"bx bx-star","type":"label"}],"children":[{"id":"_help_ZlN4nump6EbW","title":"Slash Commands","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Slash Commands"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_pwc194wlRzcH","title":"Text Snippets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Text Snippets"},{"name":"iconClass","value":"bx bx-align-left","type":"label"}]},{"id":"_help_5wZallV2Qo1t","title":"Format Painter","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Format Painter"},{"name":"iconClass","value":"bx bxs-paint-roll","type":"label"}]}]},{"id":"_help_oBo3iHIZnbG2","title":"Spell Check","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Spell Check"},{"name":"iconClass","value":"bx bx-check-double","type":"label"}]},{"id":"_help_BFvAtE74rbP6","title":"Table of contents","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Table of contents"},{"name":"iconClass","value":"bx bx-heading","type":"label"}]},{"id":"_help_NdowYOC1GFKS","title":"Tables","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Tables"},{"name":"iconClass","value":"bx bx-table","type":"label"}]}]},{"id":"_help_6f9hih2hXXZk","title":"Code","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Code"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_m523cpzocqaD","title":"Saved Search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Saved Search"},{"name":"iconClass","value":"bx bx-file-find","type":"label"}]},{"id":"_help_iRwzGnHPzonm","title":"Relation Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Relation Map"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_bdUJEHsAPYQR","title":"Note Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Note Map"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_HcABDtFCkbFN","title":"Render Note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Render Note"},{"name":"iconClass","value":"bx bx-extension","type":"label"}]},{"id":"_help_s1aBHPd79XYj","title":"Mermaid Diagrams","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mermaid Diagrams"},{"name":"iconClass","value":"bx bx-selection","type":"label"}],"children":[{"id":"_help_RH6yLjjWJHof","title":"ELK layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mermaid Diagrams/ELK layout"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_WWgeUaBb7UfC","title":"Syntax reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://mermaid.js.org/intro/syntax-reference.html"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_grjYqerjn243","title":"Canvas","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Canvas"},{"name":"iconClass","value":"bx bx-pen","type":"label"}]},{"id":"_help_1vHRoWCEjj0L","title":"Web View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Web View"},{"name":"iconClass","value":"bx bx-globe-alt","type":"label"}]},{"id":"_help_gBbsAeiuUxI5","title":"Mind Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mind Map"},{"name":"iconClass","value":"bx bx-sitemap","type":"label"}]},{"id":"_help_W8vYD3Q1zjCR","title":"File","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File"},{"name":"iconClass","value":"bx bx-file-blank","type":"label"}],"children":[{"id":"_help_XJGJrpu7F9sh","title":"PDFs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File/PDFs"},{"name":"iconClass","value":"bx bxs-file-pdf","type":"label"}]},{"id":"_help_AjqEeiDUOzj4","title":"Videos","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File/Videos"},{"name":"iconClass","value":"bx bx-video","type":"label"}]}]},{"id":"_help_GWHEkY4I4OE3","title":"Spreadsheets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Spreadsheets"},{"name":"iconClass","value":"bx bx-table","type":"label"}]},{"id":"_help_6RM1Q7ppFVoj","title":"Markdown","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Markdown"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}]}]},{"id":"_help_GTwFsgaA0lCt","title":"Collections","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections"},{"name":"iconClass","value":"bx bx-book","type":"label"}],"children":[{"id":"_help_xWbu3jpNWapp","title":"Calendar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Calendar"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]},{"id":"_help_2FvYrpmOXm29","title":"Table","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Table"},{"name":"iconClass","value":"bx bx-table","type":"label"}]},{"id":"_help_CtBQqbwXDx1w","title":"Kanban Board","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Kanban Board"},{"name":"iconClass","value":"bx bx-columns","type":"label"}]},{"id":"_help_81SGnPGMk7Xc","title":"Geo Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Geo Map"},{"name":"iconClass","value":"bx bx-map-alt","type":"label"}]},{"id":"_help_zP3PMqaG71Ct","title":"Presentation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Presentation"},{"name":"iconClass","value":"bx bx-slideshow","type":"label"}]},{"id":"_help_8QqnMzx393bx","title":"Grid View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Grid View"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_mULW0Q3VojwY","title":"List View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/List View"},{"name":"iconClass","value":"bx bx-list-ul","type":"label"}]},{"id":"_help_CssoWBu8I7jF","title":"Collection Properties","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Collection Properties"},{"name":"iconClass","value":"bx bx-cog","type":"label"}]}]},{"id":"_help_BgmBlOIl72jZ","title":"Troubleshooting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting"},{"name":"iconClass","value":"bx bx-bug","type":"label"}],"children":[{"id":"_help_wy8So3yZZlH9","title":"Reporting issues","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Reporting issues"},{"name":"iconClass","value":"bx bx-bug-alt","type":"label"}]},{"id":"_help_x59R8J8KV5Bp","title":"Anonymized Database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Anonymized Database"},{"name":"iconClass","value":"bx bx-low-vision","type":"label"}]},{"id":"_help_qzNzp9LYQyPT","title":"Error logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs"},{"name":"iconClass","value":"bx bx-comment-error","type":"label"}],"children":[{"id":"_help_bnyigUA2UK7s","title":"Backend (server) logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs/Backend (server) logs"},{"name":"iconClass","value":"bx bx-server","type":"label"}]},{"id":"_help_9yEHzMyFirZR","title":"Frontend logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs/Frontend logs"},{"name":"iconClass","value":"bx bx-window-alt","type":"label"}]}]},{"id":"_help_vdlYGAcpXAgc","title":"Synchronization fails with 504 Gateway Timeout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Synchronization fails with 504"},{"name":"iconClass","value":"bx bx-error","type":"label"}]},{"id":"_help_s8alTXmpFR61","title":"Refreshing the application","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Refreshing the application"},{"name":"iconClass","value":"bx bx-refresh","type":"label"}]}]},{"id":"_help_pKK96zzmvBGf","title":"Theme development","type":"book","attributes":[{"name":"iconClass","value":"bx bx-palette","type":"label"}],"children":[{"id":"_help_7NfNr5pZpVKV","title":"Creating a custom theme","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Creating a custom theme"},{"name":"iconClass","value":"bx bxs-color","type":"label"}]},{"id":"_help_WFGzWeUK6arS","title":"Customize the Next theme","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Customize the Next theme"},{"name":"iconClass","value":"bx bx-news","type":"label"}]},{"id":"_help_WN5z4M8ASACJ","title":"Reference","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Reference"},{"name":"iconClass","value":"bx bx-book-open","type":"label"}]},{"id":"_help_AlhDUqhENtH7","title":"Custom app-wide CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Custom app-wide CSS"},{"name":"iconClass","value":"bx bxs-file-css","type":"label"}]},{"id":"_help_g1mlRoU8CsqC","title":"Creating an icon pack","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Creating an icon pack"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_tC7s2alapj8V","title":"Advanced Usage","type":"book","attributes":[{"name":"iconClass","value":"bx bx-rocket","type":"label"}],"children":[{"id":"_help_zEY4DaJG4YT5","title":"Attributes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes"},{"name":"iconClass","value":"bx bx-list-check","type":"label"}],"children":[{"id":"_help_HI6GBBIduIgv","title":"Labels","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Labels"},{"name":"iconClass","value":"bx bx-hash","type":"label"}]},{"id":"_help_Cq5X6iKQop6R","title":"Relations","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Relations"},{"name":"iconClass","value":"bx bx-transfer","type":"label"}]},{"id":"_help_bwZpz2ajCEwO","title":"Attribute Inheritance","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Attribute Inheritance"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_OFXdgB2nNk1F","title":"Promoted Attributes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Promoted Attributes"},{"name":"iconClass","value":"bx bx-table","type":"label"}]}]},{"id":"_help_KC1HB96bqqHX","title":"Templates","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Templates"},{"name":"iconClass","value":"bx bx-copy","type":"label"}]},{"id":"_help_BCkXAVs63Ttv","title":"Note Map (Link map, Tree map)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note Map (Link map, Tree map)"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_R9pX4DGra2Vt","title":"Sharing","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing"},{"name":"iconClass","value":"bx bx-share-alt","type":"label"}],"children":[{"id":"_help_Qjt68inQ2bRj","title":"Serving directly the content of a note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Serving directly the content o"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_ycBFjKrrwE9p","title":"Exporting static HTML for web publishing","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Exporting static HTML for web "},{"name":"iconClass","value":"bx bxs-file-html","type":"label"}]},{"id":"_help_sLIJ6f1dkJYW","title":"Reverse proxy configuration","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Reverse proxy configuration"},{"name":"iconClass","value":"bx bx-world","type":"label"}]}]},{"id":"_help_5668rwcirq1t","title":"Advanced Showcases","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases"},{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_l0tKav7yLHGF","title":"Day Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Day Notes"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]},{"id":"_help_R7abl2fc6Mxi","title":"Weight Tracker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Weight Tracker"},{"name":"iconClass","value":"bx bx-line-chart","type":"label"}]},{"id":"_help_xYjQUYhpbUEW","title":"Task Manager","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Task Manager"},{"name":"iconClass","value":"bx bx-calendar-check","type":"label"}]}]},{"id":"_help_J5Ex1ZrMbyJ6","title":"Custom Request Handler","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Custom Request Handler"},{"name":"iconClass","value":"bx bx-globe","type":"label"}]},{"id":"_help_d3fAXQ2diepH","title":"Custom Resource Providers","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Custom Resource Providers"},{"name":"iconClass","value":"bx bxs-file-plus","type":"label"}]},{"id":"_help_pgxEVkzLl1OP","title":"ETAPI (REST API)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/ETAPI (REST API)"},{"name":"iconClass","value":"bx bx-extension","type":"label"}],"children":[{"id":"_help_9qPsTWBorUhQ","title":"API Reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/rest-api/etapi/"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_47ZrP6FNuoG8","title":"Default Note Title","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Default Note Title"},{"name":"iconClass","value":"bx bx-edit-alt","type":"label"}]},{"id":"_help_wX4HbRucYSDD","title":"Database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database"},{"name":"iconClass","value":"bx bx-data","type":"label"}],"children":[{"id":"_help_oyIAJ9PvvwHX","title":"Manually altering the database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Manually altering the database"},{"name":"iconClass","value":"bx bxs-edit","type":"label"}],"children":[{"id":"_help_YKWqdJhzi2VY","title":"SQL Console","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Manually altering the database/SQL Console"},{"name":"iconClass","value":"bx bx-data","type":"label"}]}]},{"id":"_help_6tZeKvSHEUiB","title":"Demo Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Demo Notes"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_Gzjqa934BdH4","title":"Configuration (config.ini or environment variables)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or e"},{"name":"iconClass","value":"bx bx-cog","type":"label"}],"children":[{"id":"_help_c5xB8m4g2IY6","title":"Trilium instance","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Trilium instance"},{"name":"iconClass","value":"bx bx-windows","type":"label"}]},{"id":"_help_LWtBjFej3wX3","title":"Cross-Origin Resource Sharing (CORS)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Cross-Origin Resource Sharing "},{"name":"iconClass","value":"bx bx-lock","type":"label"}]}]},{"id":"_help_ivYnonVFBxbQ","title":"Bulk Actions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Bulk Actions"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_4FahAwuGTAwC","title":"Note source","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note source"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_1YeN2MzFUluU","title":"Technologies used","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used"},{"name":"iconClass","value":"bx bx-pyramid","type":"label"}],"children":[{"id":"_help_MI26XDLSAlCD","title":"CKEditor","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/CKEditor"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_N4IDkixaDG9C","title":"MindElixir","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/MindElixir"},{"name":"iconClass","value":"bx bx-sitemap","type":"label"}]},{"id":"_help_H0mM1lTxF9JI","title":"Excalidraw","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/Excalidraw"},{"name":"iconClass","value":"bx bx-pen","type":"label"}]},{"id":"_help_MQHyy2dIFgxS","title":"Leaflet","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/Leaflet"},{"name":"iconClass","value":"bx bx-map-alt","type":"label"}]}]},{"id":"_help_m1lbrzyKDaRB","title":"Note ID","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note ID"},{"name":"iconClass","value":"bx bx-hash","type":"label"}]},{"id":"_help_0vTSyvhPTAOz","title":"Internal API","type":"book","attributes":[{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_z8O2VG4ZZJD7","title":"API Reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/rest-api/internal/"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_2mUhVmZK8RF3","title":"Hidden Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Hidden Notes"},{"name":"iconClass","value":"bx bx-hide","type":"label"}]},{"id":"_help_uYF7pmepw27K","title":"Metrics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Metrics"},{"name":"iconClass","value":"bx bxs-data","type":"label"}],"children":[{"id":"_help_bOP3TB56fL1V","title":"grafana-dashboard.json","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_64ZTlUPgEPtW","title":"Safe mode","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Safe mode"},{"name":"iconClass","value":"bx bxs-virus-block","type":"label"}]},{"id":"_help_HAIOFBoYIIdO","title":"Nightly release","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Nightly release"},{"name":"iconClass","value":"bx bx-moon","type":"label"}]},{"id":"_help_ZmT9ln8XJX2o","title":"Read-only database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Read-only database"},{"name":"iconClass","value":"bx bx-book-reader","type":"label"}]}]},{"id":"_help_GBBMSlVSOIGP","title":"AI","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/AI"},{"name":"iconClass","value":"bx bx-bot","type":"label"}]},{"id":"_help_CdNpE2pqjmI6","title":"Scripting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting"},{"name":"iconClass","value":"bx bxs-file-js","type":"label"}],"children":[{"id":"_help_yIhgI5H7A2Sm","title":"Frontend Basics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics"},{"name":"iconClass","value":"bx bx-window","type":"label"}],"children":[{"id":"_help_MgibgPcfeuGz","title":"Custom Widgets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets"},{"name":"iconClass","value":"bx bxs-widget","type":"label"}],"children":[{"id":"_help_SynTBQiBsdYJ","title":"Widget Basics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Widget Basics"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_GhurYZjh8e1V","title":"Note context aware widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Note context aware widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_M8IppdwVHSjG","title":"Right pane widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Right pane widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_YNxAqkI5Kg1M","title":"Word count widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Word count widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_VqGQnnPGnqAU","title":"CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/CSS"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_gMkgcLJ6jBkg","title":"Troubleshooting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Troubleshooting"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_es8OU2GuguFU","title":"Examples","type":"book","attributes":[{"name":"iconClass","value":"bx bx-code-alt","type":"label"}],"children":[{"id":"_help_TjLYAo3JMO8X","title":"\"New Task\" launcher button","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/New Task launcher button"},{"name":"iconClass","value":"bx bx-task","type":"label"}]},{"id":"_help_7kZPMD0uFwkH","title":"Downloading responses from Google Forms","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/Downloading responses from Goo"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_DL92EjAaXT26","title":"Using promoted attributes to configure scripts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/Using promoted attributes to c"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_4Gn3psZKsfSm","title":"Launch Bar Widgets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets"},{"name":"iconClass","value":"bx bx-dock-left","type":"label"}],"children":[{"id":"_help_IPArqVfDQ4We","title":"Note Title Widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets/Note Title Widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_gcI7RPbaNSh3","title":"Analog Watch","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets/Analog Watch"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_KLsqhjaqh1QW","title":"Preact","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact"},{"name":"iconClass","value":"bx bxl-react","type":"label"}],"children":[{"id":"_help_Bqde6BvPo05g","title":"Component libraries","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/Component libraries"},{"name":"iconClass","value":"bx bxs-component","type":"label"}]},{"id":"_help_ykYtbM9k3a7B","title":"Hooks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/Hooks"},{"name":"iconClass","value":"bx bx-question-mark","type":"label"}]},{"id":"_help_Sg9GrCtyftZf","title":"CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/CSS"},{"name":"iconClass","value":"bx bxs-file-css","type":"label"}]},{"id":"_help_RSssb9S3xgSr","title":"Built-in components","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/Built-in components"},{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_i9B4IW7b6V6z","title":"Widget showcase","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}]}]},{"id":"_help_SPirpZypehBG","title":"Backend scripts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts"},{"name":"iconClass","value":"bx bx-server","type":"label"}],"children":[{"id":"_help_fZ2IGYFXjkEy","title":"Server-side imports","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts/Server-side imports"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_GPERMystNGTB","title":"Events","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts/Events"},{"name":"iconClass","value":"bx bx-rss","type":"label"}]}]},{"id":"_help_wqXwKJl6VpNk","title":"Common concepts","type":"book","attributes":[{"name":"iconClass","value":"bx bxl-nodejs","type":"label"}],"children":[{"id":"_help_hA834UaHhSNn","title":"Script bundles","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Common concepts/Script bundles"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_GLks18SNjxmC","title":"Script API","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Script API"},{"name":"iconClass","value":"bx bx-code-curly","type":"label"}],"children":[{"id":"_help_Q2z6av6JZVWm","title":"Frontend API","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/frontend"},{"name":"iconClass","value":"bx bx-folder","type":"label"}],"enforceAttributes":true,"children":[{"id":"_help_habiZ3HU8Kw8","title":"FNote","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/frontend/interfaces/FNote.html"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_MEtfsqa5VwNi","title":"Backend API","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/backend"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true},{"id":"_help_ApVHZ8JY5ofC","title":"Day.js","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Script API/Day.js"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]}]},{"id":"_help_vElnKeDNPSVl","title":"Logging","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Logging"},{"name":"iconClass","value":"bx bx-terminal","type":"label"}]},{"id":"_help_cNpC0ITcfX0N","title":"Breaking changes","type":"book","attributes":[{"name":"iconClass","value":"bx bx-up-arrow-alt","type":"label"}],"children":[{"id":"_help_fqAK6opjUagR","title":"v0.103.0: Removal of axios","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Breaking changes/v0.103.0 Removal of axios"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_pAJ0jWz16xFm","title":"v0.103.0: `cheerio` is now deprecated","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Breaking changes/v0.103.0 `cheerio` is now depr"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_72dxvnbnkDFY","title":"v0.102.0: Upgrade to jQuery 4.0.0","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Breaking changes/v0.102.0 Upgrade to jQuery.0.0"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}]},{"id":"_help_Fm0j45KqyHpU","title":"Miscellaneous","type":"book","attributes":[{"name":"iconClass","value":"bx bx-info-circle","type":"label"}],"children":[{"id":"_help_WFbFXrgnDyyU","title":"Privacy Policy","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/Privacy Policy"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_NcsmUYZRWEW4","title":"Patterns of personal knowledge","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/Patterns of personal knowledge"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_d1Ap6Pg6IjaJ","title":"License","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/License"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}] \ No newline at end of file +[{"id":"_help_BOCnjTMBCoxW","title":"Feature Highlights","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Feature Highlights"},{"name":"iconClass","value":"bx bx-star","type":"label"}]},{"id":"_help_Otzi9La2YAUX","title":"Installation & Setup","type":"book","attributes":[{"name":"iconClass","value":"bx bx-cog","type":"label"}],"children":[{"id":"_help_poXkQfguuA0U","title":"Desktop Installation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation"},{"name":"iconClass","value":"bx bx-desktop","type":"label"}],"children":[{"id":"_help_nRqcgfTb97uV","title":"Using the desktop application as a server","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/Using the desktop application "},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_Rp0q8bSP6Ayl","title":"System Requirements","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/System Requirements"},{"name":"iconClass","value":"bx bx-chip","type":"label"}]},{"id":"_help_Un4wj2Mak2Ky","title":"Nix flake","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/Nix flake"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]}]},{"id":"_help_WOcw2SLH6tbX","title":"Server Installation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation"},{"name":"iconClass","value":"bx bx-server","type":"label"}],"children":[{"id":"_help_Dgg7bR3b6K9j","title":"1. Installing the server","type":"book","attributes":[{"name":"iconClass","value":"bx bx-folder","type":"label"}],"children":[{"id":"_help_3tW6mORuTHnB","title":"Packaged version for Linux","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Packaged version for Linux"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]},{"id":"_help_rWX5eY045zbE","title":"Using Docker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Docker"},{"name":"iconClass","value":"bx bxl-docker","type":"label"}]},{"id":"_help_moVgBcoxE3EK","title":"On NixOS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/On NixOS"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]},{"id":"_help_J1Bb6lVlwU5T","title":"Manually","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Manually"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}]},{"id":"_help_DCmT6e7clMoP","title":"Using Kubernetes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Kubernetes"},{"name":"iconClass","value":"bx bxl-kubernetes","type":"label"}]},{"id":"_help_klCWNks3ReaQ","title":"Multiple server instances","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Multiple server instances"},{"name":"iconClass","value":"bx bxs-user-account","type":"label"}]}]},{"id":"_help_vcjrb3VVYPZI","title":"2. Reverse proxy","type":"book","attributes":[{"name":"iconClass","value":"bx bx-folder","type":"label"}],"children":[{"id":"_help_ud6MShXL4WpO","title":"Nginx","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Nginx"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_fDLvzOx29Pfg","title":"Apache using Docker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Apache using Docker"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_LLzSMXACKhUs","title":"Trusted proxy","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Trusted proxy"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_5ERVJb9s4FRD","title":"Traefik","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Traefik"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_l2VkvOwUNfZj","title":"HTTPS (TLS)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/HTTPS (TLS)"},{"name":"iconClass","value":"bx bx-lock-alt","type":"label"}]},{"id":"_help_0hzsNCP31IAB","title":"Authentication","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Authentication"},{"name":"iconClass","value":"bx bx-user","type":"label"}]},{"id":"_help_7DAiwaf8Z7Rz","title":"Multi-Factor Authentication","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Multi-Factor Authentication"},{"name":"iconClass","value":"bx bx-stopwatch","type":"label"}]},{"id":"_help_Un4wj2Mak2Ky","title":"Nix flake","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Nix flake.clone"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_yeEaYqosGLSh","title":"Third-party cloud hosting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Third-party cloud hosting"},{"name":"iconClass","value":"bx bx-cloud","type":"label"}]},{"id":"_help_iGTnKjubbXkA","title":"System Requirements","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/System Requirements"},{"name":"iconClass","value":"bx bx-chip","type":"label"}]}]},{"id":"_help_cbkrhQjrkKrh","title":"Synchronization","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Synchronization"},{"name":"iconClass","value":"bx bx-sync","type":"label"}]},{"id":"_help_RDslemsQ6gCp","title":"Mobile Frontend","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Mobile Frontend"},{"name":"iconClass","value":"bx bx-mobile-alt","type":"label"}]},{"id":"_help_MtPxeAWVAzMg","title":"Web Clipper","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Web Clipper"},{"name":"iconClass","value":"bx bx-paperclip","type":"label"}]},{"id":"_help_n1lujUxCwipy","title":"Upgrading TriliumNext","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Upgrading TriliumNext"},{"name":"iconClass","value":"bx bx-up-arrow-alt","type":"label"}]},{"id":"_help_ODY7qQn5m2FT","title":"Backup","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Backup"},{"name":"iconClass","value":"bx bx-hdd","type":"label"}]},{"id":"_help_tAassRL4RSQL","title":"Data directory","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Data directory"},{"name":"iconClass","value":"bx bx-folder-open","type":"label"}]}]},{"id":"_help_gh7bpGYxajRS","title":"Basic Concepts and Features","type":"book","attributes":[{"name":"iconClass","value":"bx bx-help-circle","type":"label"}],"children":[{"id":"_help_Vc8PjrjAGuOp","title":"UI Elements","type":"book","attributes":[{"name":"iconClass","value":"bx bx-window-alt","type":"label"}],"children":[{"id":"_help_x0JgW8UqGXvq","title":"Vertical and horizontal layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Vertical and horizontal layout"},{"name":"iconClass","value":"bx bxs-layout","type":"label"}]},{"id":"_help_x3i7MxGccDuM","title":"Global menu","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Global menu"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_oPVyFC7WL2Lp","title":"Note Tree","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree"},{"name":"iconClass","value":"bx bxs-tree-alt","type":"label"}],"children":[{"id":"_help_YtSN43OrfzaA","title":"Note tree contextual menu","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Note tree contextual menu"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_yTjUdsOi4CIE","title":"Multiple selection","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Multiple selection"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_DvdZhoQZY9Yd","title":"Keyboard shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Keyboard shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_wyaGBBQrl4i3","title":"Hiding the subtree","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Hiding the subtree"},{"name":"iconClass","value":"bx bx-hide","type":"label"}]}]},{"id":"_help_BlN9DFI679QC","title":"Ribbon","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Ribbon"},{"name":"iconClass","value":"bx bx-dots-horizontal","type":"label"}]},{"id":"_help_3seOhtN8uLIY","title":"Tabs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Tabs"},{"name":"iconClass","value":"bx bx-dock-top","type":"label"}]},{"id":"_help_xYmIYSP6wE3F","title":"Launch Bar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Launch Bar"},{"name":"iconClass","value":"bx bx-sidebar","type":"label"}]},{"id":"_help_8YBEPzcpUgxw","title":"Note buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note buttons"},{"name":"iconClass","value":"bx bx-dots-vertical-rounded","type":"label"}]},{"id":"_help_4TIF1oA4VQRO","title":"Options","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Options"},{"name":"iconClass","value":"bx bx-cog","type":"label"}]},{"id":"_help_luNhaphA37EO","title":"Split View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View"},{"name":"iconClass","value":"bx bx-dock-right","type":"label"}]},{"id":"_help_XpOYSgsLkTJy","title":"Floating buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Floating buttons"},{"name":"iconClass","value":"bx bx-rectangle","type":"label"}]},{"id":"_help_RnaPdbciOfeq","title":"Right Sidebar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Right Sidebar"},{"name":"iconClass","value":"bx bxs-dock-right","type":"label"}]},{"id":"_help_r5JGHN99bVKn","title":"Recent Changes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Recent Changes"},{"name":"iconClass","value":"bx bx-history","type":"label"}]},{"id":"_help_ny318J39E5Z0","title":"Zoom","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Zoom"},{"name":"iconClass","value":"bx bx-zoom-in","type":"label"}]},{"id":"_help_lgKX7r3aL30x","title":"Note Tooltip","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tooltip"},{"name":"iconClass","value":"bx bx-message-detail","type":"label"}]},{"id":"_help_IjZS7iK5EXtb","title":"New Layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/New Layout"},{"name":"iconClass","value":"bx bx-layout","type":"label"}],"children":[{"id":"_help_I6p2a06hdnL6","title":"Breadcrumb","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/New Layout/Breadcrumb"},{"name":"iconClass","value":"bx bx-chevron-right","type":"label"}]},{"id":"_help_AlJ73vBCjWDw","title":"Status bar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/New Layout/Status bar"},{"name":"iconClass","value":"bx bx-dock-bottom","type":"label"}]}]},{"id":"_help_SL5f1Auq7sVN","title":"Note types with split view","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note types with split view"},{"name":"iconClass","value":"bx bx-card","type":"label"}]}]},{"id":"_help_BFs8mudNFgCS","title":"Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes"},{"name":"iconClass","value":"bx bx-notepad","type":"label"}],"children":[{"id":"_help_p9kXRFAkwN4o","title":"Note Icons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_0vhv7lsOLy82","title":"Attachments","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Attachments"},{"name":"iconClass","value":"bx bx-paperclip","type":"label"}]},{"id":"_help_IakOLONlIfGI","title":"Cloning Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes"},{"name":"iconClass","value":"bx bx-duplicate","type":"label"}],"children":[{"id":"_help_TBwsyfadTA18","title":"Branch prefix","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes/Branch prefix"},{"name":"iconClass","value":"bx bx-rename","type":"label"}]}]},{"id":"_help_bwg0e8ewQMak","title":"Protected Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Protected Notes"},{"name":"iconClass","value":"bx bx-lock-alt","type":"label"}]},{"id":"_help_MKmLg5x6xkor","title":"Archived Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Archived Notes"},{"name":"iconClass","value":"bx bx-box","type":"label"}]},{"id":"_help_vZWERwf8U3nx","title":"Note Revisions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions"},{"name":"iconClass","value":"bx bx-history","type":"label"}]},{"id":"_help_aGlEvb9hyDhS","title":"Sorting Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Sorting Notes"},{"name":"iconClass","value":"bx bx-sort-up","type":"label"}]},{"id":"_help_NRnIZmSMc5sj","title":"Printing & Exporting as PDF","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF"},{"name":"iconClass","value":"bx bx-printer","type":"label"}]},{"id":"_help_CoFPLs3dRlXc","title":"Read-Only Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes"},{"name":"iconClass","value":"bx bx-edit-alt","type":"label"}]},{"id":"_help_0ESUbbAxVnoK","title":"Note List","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note List"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]}]},{"id":"_help_wArbEsdSae6g","title":"Navigation","type":"book","attributes":[{"name":"iconClass","value":"bx bx-navigation","type":"label"}],"children":[{"id":"_help_kBrnXNG3Hplm","title":"Tree Concepts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Tree Concepts"},{"name":"iconClass","value":"bx bx-pyramid","type":"label"}]},{"id":"_help_MMiBEQljMQh2","title":"Note Navigation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation"},{"name":"iconClass","value":"bx bxs-navigation","type":"label"}]},{"id":"_help_Ms1nauBra7gq","title":"Quick search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Quick search"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]},{"id":"_help_F1r9QtzQLZqm","title":"Jump to & command palette","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to & command palette"},{"name":"iconClass","value":"bx bx-send","type":"label"}]},{"id":"_help_eIg8jdvaoNNd","title":"Search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Search"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]},{"id":"_help_u3YFHC9tQlpm","title":"Bookmarks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks"},{"name":"iconClass","value":"bx bx-bookmarks","type":"label"}]},{"id":"_help_OR8WJ7Iz9K4U","title":"Note Hoisting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Note Hoisting"},{"name":"iconClass","value":"bx bxs-chevrons-up","type":"label"}]},{"id":"_help_ZjLYv08Rp3qC","title":"Quick edit","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Quick edit"},{"name":"iconClass","value":"bx bx-edit","type":"label"}]},{"id":"_help_9sRHySam5fXb","title":"Workspaces","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Workspaces"},{"name":"iconClass","value":"bx bx-door-open","type":"label"}]},{"id":"_help_xWtq5NUHOwql","title":"Similar Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Similar Notes"},{"name":"iconClass","value":"bx bx-bar-chart","type":"label"}]},{"id":"_help_McngOG2jbUWX","title":"Search in note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Search in note"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]}]},{"id":"_help_A9Oc6YKKc65v","title":"Keyboard Shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Keyboard Shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_Wy267RK4M69c","title":"Themes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes"},{"name":"iconClass","value":"bx bx-palette","type":"label"}],"children":[{"id":"_help_VbjZvtUek0Ln","title":"Theme Gallery","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes/Theme Gallery"},{"name":"iconClass","value":"bx bx-book-reader","type":"label"}]},{"id":"_help_gOKqSJgXLcIj","title":"Icon Packs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes/Icon Packs"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_mHbBMPDPkVV5","title":"Import & Export","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export"},{"name":"iconClass","value":"bx bx-import","type":"label"}],"children":[{"id":"_help_Oau6X9rCuegd","title":"Markdown","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}],"children":[{"id":"_help_rJ9grSgoExl9","title":"Supported syntax","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown/Supported syntax"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}]}]},{"id":"_help_syuSEKf2rUGr","title":"Evernote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Evernote"},{"name":"iconClass","value":"bx bx-window-open","type":"label"}],"children":[{"id":"_help_dj3j8dG4th4l","title":"Process internal links by title","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_GnhlmrATVqcH","title":"OneNote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/OneNote"},{"name":"iconClass","value":"bx bx-window-open","type":"label"}]}]},{"id":"_help_rC3pL2aptaRE","title":"Zen mode","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Zen mode"},{"name":"iconClass","value":"bx bxs-yin-yang","type":"label"}]},{"id":"_help_YzMcWlCVeW09","title":"Active content","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Active content"},{"name":"iconClass","value":"bx bxs-widget","type":"label"}]}]},{"id":"_help_s3YCWHBfmYuM","title":"Quick Start","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Quick Start"},{"name":"iconClass","value":"bx bx-run","type":"label"}]},{"id":"_help_i6dbnitykE5D","title":"FAQ","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/FAQ"},{"name":"iconClass","value":"bx bx-question-mark","type":"label"}]},{"id":"_help_KSZ04uQ2D1St","title":"Note Types","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types"},{"name":"iconClass","value":"bx bx-edit","type":"label"}],"children":[{"id":"_help_iPIMuisry3hd","title":"Text","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text"},{"name":"iconClass","value":"bx bx-note","type":"label"}],"children":[{"id":"_help_oSuaNgyyKnhu","title":"Anchors","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Anchors"},{"name":"iconClass","value":"bx bx-bookmark","type":"label"}]},{"id":"_help_NwBbFdNZ9h7O","title":"Block quotes & admonitions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Block quotes & admonitions"},{"name":"iconClass","value":"bx bx-info-circle","type":"label"}]},{"id":"_help_veGu4faJErEM","title":"Content language & Right-to-left support","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Content language & Right-to-le"},{"name":"iconClass","value":"bx bx-align-right","type":"label"}]},{"id":"_help_2x0ZAX9ePtzV","title":"Cut to subnote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Cut to subnote"},{"name":"iconClass","value":"bx bx-cut","type":"label"}]},{"id":"_help_UYuUB1ZekNQU","title":"Developer-specific formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Developer-specific formatting"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}],"children":[{"id":"_help_QxEyIjRBizuC","title":"Code blocks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Developer-specific formatting/Code blocks"},{"name":"iconClass","value":"bx bx-code","type":"label"}]}]},{"id":"_help_AgjCISero73a","title":"Footnotes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Footnotes"},{"name":"iconClass","value":"bx bx-bracket","type":"label"}]},{"id":"_help_nRhnJkTT8cPs","title":"Formatting toolbar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Formatting toolbar"},{"name":"iconClass","value":"bx bx-text","type":"label"}]},{"id":"_help_Gr6xFaF6ioJ5","title":"General formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/General formatting"},{"name":"iconClass","value":"bx bx-bold","type":"label"}]},{"id":"_help_AxshuNRegLAv","title":"Highlights list","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Highlights list"},{"name":"iconClass","value":"bx bx-highlight","type":"label"}]},{"id":"_help_mT0HEkOsz6i1","title":"Images","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Images"},{"name":"iconClass","value":"bx bx-image-alt","type":"label"}],"children":[{"id":"_help_0Ofbk1aSuVRu","title":"Image references","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Images/Image references"},{"name":"iconClass","value":"bx bxs-file-image","type":"label"}]}]},{"id":"_help_nBAXQFj20hS1","title":"Include Note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Include Note"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_CohkqWQC1iBv","title":"Insert buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Insert buttons"},{"name":"iconClass","value":"bx bx-plus","type":"label"}]},{"id":"_help_oiVPnW8QfnvS","title":"Keyboard shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Keyboard shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_QEAPj01N5f7w","title":"Links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links"},{"name":"iconClass","value":"bx bx-link-alt","type":"label"}],"children":[{"id":"_help_3IDVtesTQ8ds","title":"External links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links/External links"},{"name":"iconClass","value":"bx bx-link-external","type":"label"}]},{"id":"_help_hrZ1D00cLbal","title":"Internal (reference) links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links/Internal (reference) links"},{"name":"iconClass","value":"bx bx-link","type":"label"}]}]},{"id":"_help_S6Xx8QIWTV66","title":"Lists","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Lists"},{"name":"iconClass","value":"bx bx-list-ul","type":"label"}]},{"id":"_help_QrtTYPmdd1qq","title":"Markdown-like formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Markdown-like formatting"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}]},{"id":"_help_YfYAtQBcfo5V","title":"Math Equations","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Math Equations"},{"name":"iconClass","value":"bx bx-math","type":"label"}]},{"id":"_help_dEHYtoWWi8ct","title":"Other features","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Other features"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_gLt3vA97tMcp","title":"Premium features","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features"},{"name":"iconClass","value":"bx bx-star","type":"label"}],"children":[{"id":"_help_ZlN4nump6EbW","title":"Slash Commands","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Slash Commands"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_pwc194wlRzcH","title":"Text Snippets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Text Snippets"},{"name":"iconClass","value":"bx bx-align-left","type":"label"}]},{"id":"_help_5wZallV2Qo1t","title":"Format Painter","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Format Painter"},{"name":"iconClass","value":"bx bxs-paint-roll","type":"label"}]}]},{"id":"_help_oBo3iHIZnbG2","title":"Spell Check","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Spell Check"},{"name":"iconClass","value":"bx bx-check-double","type":"label"}]},{"id":"_help_BFvAtE74rbP6","title":"Table of contents","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Table of contents"},{"name":"iconClass","value":"bx bx-heading","type":"label"}]},{"id":"_help_NdowYOC1GFKS","title":"Tables","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Tables"},{"name":"iconClass","value":"bx bx-table","type":"label"}]}]},{"id":"_help_6f9hih2hXXZk","title":"Code","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Code"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_m523cpzocqaD","title":"Saved Search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Saved Search"},{"name":"iconClass","value":"bx bx-file-find","type":"label"}]},{"id":"_help_iRwzGnHPzonm","title":"Relation Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Relation Map"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_bdUJEHsAPYQR","title":"Note Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Note Map"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_HcABDtFCkbFN","title":"Render Note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Render Note"},{"name":"iconClass","value":"bx bx-extension","type":"label"}]},{"id":"_help_s1aBHPd79XYj","title":"Mermaid Diagrams","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mermaid Diagrams"},{"name":"iconClass","value":"bx bx-selection","type":"label"}],"children":[{"id":"_help_RH6yLjjWJHof","title":"ELK layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mermaid Diagrams/ELK layout"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_WWgeUaBb7UfC","title":"Syntax reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://mermaid.js.org/intro/syntax-reference.html"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_grjYqerjn243","title":"Canvas","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Canvas"},{"name":"iconClass","value":"bx bx-pen","type":"label"}]},{"id":"_help_1vHRoWCEjj0L","title":"Web View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Web View"},{"name":"iconClass","value":"bx bx-globe-alt","type":"label"}]},{"id":"_help_gBbsAeiuUxI5","title":"Mind Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mind Map"},{"name":"iconClass","value":"bx bx-sitemap","type":"label"}]},{"id":"_help_W8vYD3Q1zjCR","title":"File","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File"},{"name":"iconClass","value":"bx bx-file-blank","type":"label"}],"children":[{"id":"_help_XJGJrpu7F9sh","title":"PDFs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File/PDFs"},{"name":"iconClass","value":"bx bxs-file-pdf","type":"label"}]},{"id":"_help_AjqEeiDUOzj4","title":"Videos","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File/Videos"},{"name":"iconClass","value":"bx bx-video","type":"label"}]}]},{"id":"_help_GWHEkY4I4OE3","title":"Spreadsheets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Spreadsheets"},{"name":"iconClass","value":"bx bx-table","type":"label"}]},{"id":"_help_6RM1Q7ppFVoj","title":"Markdown","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Markdown"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}]}]},{"id":"_help_GTwFsgaA0lCt","title":"Collections","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections"},{"name":"iconClass","value":"bx bx-book","type":"label"}],"children":[{"id":"_help_xWbu3jpNWapp","title":"Calendar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Calendar"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]},{"id":"_help_2FvYrpmOXm29","title":"Table","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Table"},{"name":"iconClass","value":"bx bx-table","type":"label"}]},{"id":"_help_CtBQqbwXDx1w","title":"Kanban Board","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Kanban Board"},{"name":"iconClass","value":"bx bx-columns","type":"label"}]},{"id":"_help_81SGnPGMk7Xc","title":"Geo Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Geo Map"},{"name":"iconClass","value":"bx bx-map-alt","type":"label"}]},{"id":"_help_zP3PMqaG71Ct","title":"Presentation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Presentation"},{"name":"iconClass","value":"bx bx-slideshow","type":"label"}]},{"id":"_help_8QqnMzx393bx","title":"Grid View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Grid View"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_mULW0Q3VojwY","title":"List View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/List View"},{"name":"iconClass","value":"bx bx-list-ul","type":"label"}]},{"id":"_help_CssoWBu8I7jF","title":"Collection Properties","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Collection Properties"},{"name":"iconClass","value":"bx bx-cog","type":"label"}]}]},{"id":"_help_BgmBlOIl72jZ","title":"Troubleshooting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting"},{"name":"iconClass","value":"bx bx-bug","type":"label"}],"children":[{"id":"_help_wy8So3yZZlH9","title":"Reporting issues","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Reporting issues"},{"name":"iconClass","value":"bx bx-bug-alt","type":"label"}]},{"id":"_help_x59R8J8KV5Bp","title":"Anonymized Database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Anonymized Database"},{"name":"iconClass","value":"bx bx-low-vision","type":"label"}]},{"id":"_help_qzNzp9LYQyPT","title":"Error logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs"},{"name":"iconClass","value":"bx bx-comment-error","type":"label"}],"children":[{"id":"_help_bnyigUA2UK7s","title":"Backend (server) logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs/Backend (server) logs"},{"name":"iconClass","value":"bx bx-server","type":"label"}]},{"id":"_help_9yEHzMyFirZR","title":"Frontend logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs/Frontend logs"},{"name":"iconClass","value":"bx bx-window-alt","type":"label"}]}]},{"id":"_help_vdlYGAcpXAgc","title":"Synchronization fails with 504 Gateway Timeout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Synchronization fails with 504"},{"name":"iconClass","value":"bx bx-error","type":"label"}]},{"id":"_help_s8alTXmpFR61","title":"Refreshing the application","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Refreshing the application"},{"name":"iconClass","value":"bx bx-refresh","type":"label"}]}]},{"id":"_help_pKK96zzmvBGf","title":"Theme development","type":"book","attributes":[{"name":"iconClass","value":"bx bx-palette","type":"label"}],"children":[{"id":"_help_7NfNr5pZpVKV","title":"Creating a custom theme","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Creating a custom theme"},{"name":"iconClass","value":"bx bxs-color","type":"label"}]},{"id":"_help_WFGzWeUK6arS","title":"Customize the Next theme","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Customize the Next theme"},{"name":"iconClass","value":"bx bx-news","type":"label"}]},{"id":"_help_WN5z4M8ASACJ","title":"Reference","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Reference"},{"name":"iconClass","value":"bx bx-book-open","type":"label"}]},{"id":"_help_AlhDUqhENtH7","title":"Custom app-wide CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Custom app-wide CSS"},{"name":"iconClass","value":"bx bxs-file-css","type":"label"}]},{"id":"_help_g1mlRoU8CsqC","title":"Creating an icon pack","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Creating an icon pack"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_tC7s2alapj8V","title":"Advanced Usage","type":"book","attributes":[{"name":"iconClass","value":"bx bx-rocket","type":"label"}],"children":[{"id":"_help_zEY4DaJG4YT5","title":"Attributes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes"},{"name":"iconClass","value":"bx bx-list-check","type":"label"}],"children":[{"id":"_help_HI6GBBIduIgv","title":"Labels","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Labels"},{"name":"iconClass","value":"bx bx-hash","type":"label"}]},{"id":"_help_Cq5X6iKQop6R","title":"Relations","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Relations"},{"name":"iconClass","value":"bx bx-transfer","type":"label"}]},{"id":"_help_bwZpz2ajCEwO","title":"Attribute Inheritance","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Attribute Inheritance"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_OFXdgB2nNk1F","title":"Promoted Attributes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Promoted Attributes"},{"name":"iconClass","value":"bx bx-table","type":"label"}]}]},{"id":"_help_KC1HB96bqqHX","title":"Templates","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Templates"},{"name":"iconClass","value":"bx bx-copy","type":"label"}]},{"id":"_help_BCkXAVs63Ttv","title":"Note Map (Link map, Tree map)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note Map (Link map, Tree map)"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_R9pX4DGra2Vt","title":"Sharing","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing"},{"name":"iconClass","value":"bx bx-share-alt","type":"label"}],"children":[{"id":"_help_Qjt68inQ2bRj","title":"Serving directly the content of a note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Serving directly the content o"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_ycBFjKrrwE9p","title":"Exporting static HTML for web publishing","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Exporting static HTML for web "},{"name":"iconClass","value":"bx bxs-file-html","type":"label"}]},{"id":"_help_sLIJ6f1dkJYW","title":"Reverse proxy configuration","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Reverse proxy configuration"},{"name":"iconClass","value":"bx bx-world","type":"label"}]}]},{"id":"_help_5668rwcirq1t","title":"Advanced Showcases","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases"},{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_l0tKav7yLHGF","title":"Day Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Day Notes"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]},{"id":"_help_R7abl2fc6Mxi","title":"Weight Tracker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Weight Tracker"},{"name":"iconClass","value":"bx bx-line-chart","type":"label"}]},{"id":"_help_xYjQUYhpbUEW","title":"Task Manager","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Task Manager"},{"name":"iconClass","value":"bx bx-calendar-check","type":"label"}]}]},{"id":"_help_J5Ex1ZrMbyJ6","title":"Custom Request Handler","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Custom Request Handler"},{"name":"iconClass","value":"bx bx-globe","type":"label"}]},{"id":"_help_d3fAXQ2diepH","title":"Custom Resource Providers","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Custom Resource Providers"},{"name":"iconClass","value":"bx bxs-file-plus","type":"label"}]},{"id":"_help_pgxEVkzLl1OP","title":"ETAPI (REST API)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/ETAPI (REST API)"},{"name":"iconClass","value":"bx bx-extension","type":"label"}],"children":[{"id":"_help_9qPsTWBorUhQ","title":"API Reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/rest-api/etapi/"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_47ZrP6FNuoG8","title":"Default Note Title","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Default Note Title"},{"name":"iconClass","value":"bx bx-edit-alt","type":"label"}]},{"id":"_help_wX4HbRucYSDD","title":"Database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database"},{"name":"iconClass","value":"bx bx-data","type":"label"}],"children":[{"id":"_help_oyIAJ9PvvwHX","title":"Manually altering the database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Manually altering the database"},{"name":"iconClass","value":"bx bxs-edit","type":"label"}],"children":[{"id":"_help_YKWqdJhzi2VY","title":"SQL Console","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Manually altering the database/SQL Console"},{"name":"iconClass","value":"bx bx-data","type":"label"}]}]},{"id":"_help_6tZeKvSHEUiB","title":"Demo Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Demo Notes"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_Gzjqa934BdH4","title":"Configuration (config.ini or environment variables)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or e"},{"name":"iconClass","value":"bx bx-cog","type":"label"}],"children":[{"id":"_help_c5xB8m4g2IY6","title":"Trilium instance","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Trilium instance"},{"name":"iconClass","value":"bx bx-windows","type":"label"}]},{"id":"_help_LWtBjFej3wX3","title":"Cross-Origin Resource Sharing (CORS)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Cross-Origin Resource Sharing "},{"name":"iconClass","value":"bx bx-lock","type":"label"}]}]},{"id":"_help_ivYnonVFBxbQ","title":"Bulk Actions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Bulk Actions"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_4FahAwuGTAwC","title":"Note source","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note source"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_1YeN2MzFUluU","title":"Technologies used","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used"},{"name":"iconClass","value":"bx bx-pyramid","type":"label"}],"children":[{"id":"_help_MI26XDLSAlCD","title":"CKEditor","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/CKEditor"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_N4IDkixaDG9C","title":"MindElixir","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/MindElixir"},{"name":"iconClass","value":"bx bx-sitemap","type":"label"}]},{"id":"_help_H0mM1lTxF9JI","title":"Excalidraw","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/Excalidraw"},{"name":"iconClass","value":"bx bx-pen","type":"label"}]},{"id":"_help_MQHyy2dIFgxS","title":"Leaflet","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/Leaflet"},{"name":"iconClass","value":"bx bx-map-alt","type":"label"}]}]},{"id":"_help_m1lbrzyKDaRB","title":"Note ID","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note ID"},{"name":"iconClass","value":"bx bx-hash","type":"label"}]},{"id":"_help_0vTSyvhPTAOz","title":"Internal API","type":"book","attributes":[{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_z8O2VG4ZZJD7","title":"API Reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/rest-api/internal/"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_2mUhVmZK8RF3","title":"Hidden Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Hidden Notes"},{"name":"iconClass","value":"bx bx-hide","type":"label"}]},{"id":"_help_uYF7pmepw27K","title":"Metrics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Metrics"},{"name":"iconClass","value":"bx bxs-data","type":"label"}],"children":[{"id":"_help_bOP3TB56fL1V","title":"grafana-dashboard.json","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_64ZTlUPgEPtW","title":"Safe mode","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Safe mode"},{"name":"iconClass","value":"bx bxs-virus-block","type":"label"}]},{"id":"_help_HAIOFBoYIIdO","title":"Nightly release","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Nightly release"},{"name":"iconClass","value":"bx bx-moon","type":"label"}]},{"id":"_help_ZmT9ln8XJX2o","title":"Read-only database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Read-only database"},{"name":"iconClass","value":"bx bx-book-reader","type":"label"}]}]},{"id":"_help_GBBMSlVSOIGP","title":"AI","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/AI"},{"name":"iconClass","value":"bx bx-bot","type":"label"}]},{"id":"_help_CdNpE2pqjmI6","title":"Scripting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting"},{"name":"iconClass","value":"bx bxs-file-js","type":"label"}],"children":[{"id":"_help_yIhgI5H7A2Sm","title":"Frontend Basics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics"},{"name":"iconClass","value":"bx bx-window","type":"label"}],"children":[{"id":"_help_MgibgPcfeuGz","title":"Custom Widgets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets"},{"name":"iconClass","value":"bx bxs-widget","type":"label"}],"children":[{"id":"_help_SynTBQiBsdYJ","title":"Widget Basics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Widget Basics"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_GhurYZjh8e1V","title":"Note context aware widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Note context aware widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_M8IppdwVHSjG","title":"Right pane widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Right pane widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_YNxAqkI5Kg1M","title":"Word count widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Word count widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_VqGQnnPGnqAU","title":"CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/CSS"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_gMkgcLJ6jBkg","title":"Troubleshooting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Troubleshooting"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_es8OU2GuguFU","title":"Examples","type":"book","attributes":[{"name":"iconClass","value":"bx bx-code-alt","type":"label"}],"children":[{"id":"_help_TjLYAo3JMO8X","title":"\"New Task\" launcher button","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/New Task launcher button"},{"name":"iconClass","value":"bx bx-task","type":"label"}]},{"id":"_help_7kZPMD0uFwkH","title":"Downloading responses from Google Forms","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/Downloading responses from Goo"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_DL92EjAaXT26","title":"Using promoted attributes to configure scripts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/Using promoted attributes to c"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_4Gn3psZKsfSm","title":"Launch Bar Widgets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets"},{"name":"iconClass","value":"bx bx-dock-left","type":"label"}],"children":[{"id":"_help_IPArqVfDQ4We","title":"Note Title Widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets/Note Title Widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_gcI7RPbaNSh3","title":"Analog Watch","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets/Analog Watch"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_KLsqhjaqh1QW","title":"Preact","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact"},{"name":"iconClass","value":"bx bxl-react","type":"label"}],"children":[{"id":"_help_Bqde6BvPo05g","title":"Component libraries","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/Component libraries"},{"name":"iconClass","value":"bx bxs-component","type":"label"}]},{"id":"_help_ykYtbM9k3a7B","title":"Hooks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/Hooks"},{"name":"iconClass","value":"bx bx-question-mark","type":"label"}]},{"id":"_help_Sg9GrCtyftZf","title":"CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/CSS"},{"name":"iconClass","value":"bx bxs-file-css","type":"label"}]},{"id":"_help_RSssb9S3xgSr","title":"Built-in components","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Preact/Built-in components"},{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_i9B4IW7b6V6z","title":"Widget showcase","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}]}]},{"id":"_help_SPirpZypehBG","title":"Backend scripts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts"},{"name":"iconClass","value":"bx bx-server","type":"label"}],"children":[{"id":"_help_fZ2IGYFXjkEy","title":"Server-side imports","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts/Server-side imports"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_GPERMystNGTB","title":"Events","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts/Events"},{"name":"iconClass","value":"bx bx-rss","type":"label"}]}]},{"id":"_help_wqXwKJl6VpNk","title":"Common concepts","type":"book","attributes":[{"name":"iconClass","value":"bx bxl-nodejs","type":"label"}],"children":[{"id":"_help_hA834UaHhSNn","title":"Script bundles","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Common concepts/Script bundles"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_GLks18SNjxmC","title":"Script API","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Script API"},{"name":"iconClass","value":"bx bx-code-curly","type":"label"}],"children":[{"id":"_help_Q2z6av6JZVWm","title":"Frontend API","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/frontend"},{"name":"iconClass","value":"bx bx-folder","type":"label"}],"enforceAttributes":true,"children":[{"id":"_help_habiZ3HU8Kw8","title":"FNote","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/frontend/interfaces/FNote.html"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_MEtfsqa5VwNi","title":"Backend API","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/backend"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true},{"id":"_help_ApVHZ8JY5ofC","title":"Day.js","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Script API/Day.js"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]}]},{"id":"_help_vElnKeDNPSVl","title":"Logging","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Logging"},{"name":"iconClass","value":"bx bx-terminal","type":"label"}]},{"id":"_help_cNpC0ITcfX0N","title":"Breaking changes","type":"book","attributes":[{"name":"iconClass","value":"bx bx-up-arrow-alt","type":"label"}],"children":[{"id":"_help_fqAK6opjUagR","title":"v0.103.0: Removal of axios","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Breaking changes/v0.103.0 Removal of axios"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_pAJ0jWz16xFm","title":"v0.103.0: `cheerio` is now deprecated","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Breaking changes/v0.103.0 `cheerio` is now depr"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_72dxvnbnkDFY","title":"v0.102.0: Upgrade to jQuery 4.0.0","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Breaking changes/v0.102.0 Upgrade to jQuery.0.0"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}]},{"id":"_help_Fm0j45KqyHpU","title":"Miscellaneous","type":"book","attributes":[{"name":"iconClass","value":"bx bx-info-circle","type":"label"}],"children":[{"id":"_help_WFbFXrgnDyyU","title":"Privacy Policy","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/Privacy Policy"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_NcsmUYZRWEW4","title":"Patterns of personal knowledge","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/Patterns of personal knowledge"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_d1Ap6Pg6IjaJ","title":"License","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/License"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}] \ No newline at end of file diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/1_Jump to_image.png b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/1_Jump to & command palette_.png similarity index 100% rename from apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/1_Jump to_image.png rename to apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/1_Jump to & command palette_.png diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/2_Jump to_image.png b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/2_Jump to & command palette_.png similarity index 100% rename from apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/2_Jump to_image.png rename to apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/2_Jump to & command palette_.png diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to & command palette.html similarity index 92% rename from apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to.html rename to apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to & command palette.html index 7d108b9304..c6ab832bdb 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to & command palette.html @@ -1,5 +1,5 @@
    -

    Jump to Note

    @@ -10,7 +10,7 @@
    • In the Launch Bar, press - button.
    • + button.
    • Using the keyboard, press Ctrl + J.

    In addition to searching for notes, it is also possible to search for @@ -33,7 +33,7 @@

    Alternatively you can click on the "time" icon on the right.

    Command Palette

    -

    The command palette is a feature which allows easy execution of various @@ -52,7 +52,8 @@

    • Type a few words to filter between commands.
    • Use the up and down arrows on the keyboard or the mouse to select a command.
    • -
    • Press Enter to execute the command.
    • +
    • Press Enter to execute the command.

    To exit the command palette:

      diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to_image.png b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to & command palette_.png similarity index 100% rename from apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to_image.png rename to apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to & command palette_.png diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/1_Printing & Exporting as PD.png b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/1_Printing & Exporting as PD.png index a5d522d26713818252d60bcc12c3680ab4107bd0..ee46c2c7b3fa2585e8e56f2d0e94ac5007d1559d 100644 GIT binary patch literal 248650 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 z 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

      SGzOxKIeN;>cFh$$} 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

      e;U!%CjV$O9@%rKwl}F2zhu2 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%0DP5zBfvMNLO6eac}gEn{}D$lfj{*MB4~v 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 tGo^dS#wY6|L^$?ZCj7qJ~ literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^vOp})0VEjg3})T{Qn8*cjv*T7lYjK{8}yudG;Qyd za?b5c5yw(36PN{u-?!iB{

      Displaying the revisions

      Interaction

  • The icon of a revision indicates the source of that revision (e.g. a @@ -72,14 +71,13 @@

    To create a named revision, either:

      -
    • Go to the Note buttons, +
    • Go to the Note buttons, select Save named revision…, enter the name of revision and confirm.
    • -
    • Use the corresponding keyboard shortcut or - the Jump to... command +
    • Use the corresponding keyboard shortcut or + the Jump to... command with the same name.
    • -
    • Save a revision normally, and adjust the name afterwards from the note - revision list.
    • +
    • Save a revision normally, and adjust the name afterwards from the note + revision list.

    When revisions are saved

    Revisions are saved:

    @@ -88,25 +86,22 @@ below).
  • Manually, by:
      -
    • Going to the press the note context menu and +
    • Going to the press the note context menu and select Save revision.
    • -
    • Using the Force Save Revision keyboard shortcut.
    • -
    • In the Revisions dialog, pressing the […] button in the top-right +
    • Using the Force Save Revision keyboard shortcut.
    • +
    • In the Revisions dialog, pressing the […] button in the top-right and selecting Save a revision now.
    • -
    +
  • Additionally, revisions can also come from somewhere else, and this is indicated via the icon of the revision:

      -
    • Generated externally, by ETAPI (REST API).
    • -
    • A modification created by AI.
    • -
    • A revision is restored, causing the existing note content to be saved - as a revision to prevent potential data loss.
    • +
    • Generated externally, by ETAPI (REST API).
    • +
    • A modification created by AI.
    • +
    • A revision is restored, causing the existing note content to be saved + as a revision to prevent potential data loss.

    Snapshot interval

    Time interval of taking note snapshot is configurable in the Options -> diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PD.png b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PD.png index b205c18bd878c8887aefd95c6d7beb4e1931c46c..a5d522d26713818252d60bcc12c3680ab4107bd0 100644 GIT binary patch literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^vOp})0VEjg3})T{Qn8*cjv*T7lYjK{8}yudG;Qyd za?b5c5yw(36PN{u-?!iB{Mn<%vxc~k%nzLTs-QAsshi8U```=#$zh{Q$K=}8;Vls%RsHm%J1$fE-o=WGa z|MKO1YREtDjqch|K+aJ9eV9^5;P0!u5dHuAKZE~%0Qvm)Y3BTu#KgpnjSc8~TU*;x zVgG-hEW!Q&=QC}ZtaY3Zf4I3A&S?7CTHUj?aAmU6lC|GvsWWnQb=854lZS_1+W&H) zJ>+v$)hN>cXiPtYCDb_M{`K|6uClW7#Q3<&FYDU{M|a^uAQPjbF|?vP%tVG?Y;|jc z4>BZu7z7I9S(Wwl^cvLfiHIaF+0WEzrEgVPeUnhcsgL2BE6~UsNEH742LuAi=VE@#eqj^HS#Q?rzrVl#-qd!w z<`rtVRzB><*`HrNCp)uX5uu?NE$091x+K#>kFCkCMA9>P?hlXNEbmYI;4IGzu0|;o_Vvn5CA|+{RzGub5#TWi z{vH#9PmXdCPriekp(%~0^6v=h-Rz<=n`!a$F)*MuYx^g38XgCdHUHuXm7LU=E2@4K zlSM=f&THO#ljjnHgHF&Ie^x0A#i2OsL{;Q%mbfU3l@sikUCS)k(hZM zEMTp^D82KbXpC0!r|2xhP(hJ=rfKHb6&Bz?R|&?Y5B z51lrP=MY(-^~CA*oNMyxB{`Dw(!5WeuaPOmQN-p)_vqyi69U)js|nTHj>?F~U8b%6 z&AKFcSqMi=EN;#c50cHC84M~~n$u4A%T z`n3A(gO2-Pnt0CO=HBAh$(xPha&0qGuYsfo@|NaG!73hm3+*DQvE{ITc18`kD2EI- z3weypQHm}4^hr~Bgx0&+R^tyM<|XW2&Ga_dp5LQ zPkwZdkqkWXl02TYd}kNIQD=D;K!Y%8>N?mkC3&V(y! zQ}LO0GUHKlJ8gce^uO}HY_OZ)T|SI07Ia!@o0&0=|G>{7HE@{l9FO!K_f}zGvlT7lh@KR zZ`%acF|#&}2BMH-K53!FR|HOx0F9iye&9r}DAa>vM0|>BnyP)hHVPWA_lq@Qf;QuTG{8IkEw+_S2u+)AYbHksddzom~h_$sO=a;N3j_spBq<#+ow0{#n})XNvW@vMv+(1?(v z8Li-~SJO3N#Hr7S3}5K5(zk3ZSJ%{_#Ve+Le)0Xy;?H0;CSaINnJ8Q!*?5hS1f01y!)kS(sn(cypD zhnS(4b4(SsOJraE$iB%+*d8?FEvaap55n8XjYTP&V+$YYDryY+%OiWDZ z9adu>KNLgr{+KN!g`b_b($plubPz)=_#{(m`}hzXgyYZZJKHrL+dn}q-CJ$5sPs;B zadBZ`Vd;Lyxa%Z#xIFzMPZiu(*Ts&oovf9Tl9J&ZrtBi=O9pweHT5-Po}025yAU9qotgR&Y@(Ve`)cfvX;2-zTwRiw^3{?B01yL_9H=9J zNK0$-yYTRR)4z;Hky;XAdl!@+UP@4?+-QTwW^qN|;aT?L)jxmKAI(lJRZB(qeQ)*G zuYi+T&w2j~9^zyf>Kuk=)C4}t!{ zs*IJ){s_ck3AZ4u=s4aso)^L-!)^ z>G}CsGtW#+0ABnJP79;~S*dy7KLbPA@*og~bOcC!L2Dq3T<(sQUsY#t2N1Ns5FHEu zZuSp-Ge3&z&yzz#6|eV~EPLJ#>+|PT_*!;%^pn%m&$?c4BUA0%6RbZ!F5* z3BojS=ROjX+Vk7I-w8eSy7c+)9RB?pTrMcUDs^F#)iyeIcE!o3R#sNKtv6CTqBOL$ zXAK}hKQBv6q;wjsc{PniNcXbxSts732sm;bWy@2aM8x`g#`c(nly#ga56>%rwt8_g zCkZ7XmNNkdNOr9(0K${#&M_goQ=i$N{?gV7oSdA@SW;BCE}(zYan*geJ`#x!2Z-H~ z(aNYw`k~iB?lfk{4DJIG>CimLfzcOR3WK*c>x{jZl7B+vkx!F8ed4I4`ZAXo^BkAp z+qa1dkdCsCkB@tMRSXB8AO0Q&>A5=d5{|S(ImFkyhrS6~q9*7({=wR>U#Yf> zmGs`wx6#o#lv7{qK75ZWs;3h7J>C1HmBZk(RVnVe7SYP~j{eb`LXa_=Nk~Y<;$qrC zi_|eVf4L?K%6^wZ6-YY(5iz5QbfP~~L0xD1viLQ8d9S-$X=bwtbP#^$ht&M$Z7axx z_@87N60)iuOjIsKPt?@NlQSN9zU}+7`oZku3c}vc@9GT!Z5$e0GT>UmpEPmZ;eCNH z@1b^rY@FY#fk)R%5>adf#YF zgroMztbmq@Oz-?L(v21E9wsUxG0_3U_3xqV!=!sGH|G;yF( z^9Ud^k3VYzVxUYG1>9WMnYC*XhA*!dWP(z}bDT5gs)ne$4$KAuaCfB!YZ&HE7FyHgCf}V2ZOgg8lhKSO_6<`Ud^Z zHzM%j+XucLD~ckPLT0fN4sl^&_w&Q`M$cW5$H=>7(%PMlApq)1Dz=sW`SqQadoUzZ z#C~#b((+wiUYAvK)4;+>%>pJ$ z%Jw&>y7F!27SUZ*eiz4z(UeC3^lgjpB*Moy?F1<56%-WEYJ&d%8;OQQCi)aaNyXCN`n0`w|~05@`x-`ABH;2QTrP#oDaUZcHy zs;QZk;rjsVcw-FDwV3Ee^th?u#KqMWWcP?4uN%|C+27&ymjjfnEv@*A9g-6YiWdW5 zD_(AaTAM2J3Ks_gK!aIxru~L&J}l+n>xlW*_&$|eaIqEW`VJElhz;W<&%kplcQ%m7 zRL&_f7C^>?fB(kUkqFN|Jw06?DF`@Q{jkB_IIHcVr8Nxpz}fNpuC+zwPXkHyfq{Ye z_;|2!m@H@?x_nZyLI0OqRyG(eM9&7Rodz}WQsd@O z$?y*b>B~LzmXrYeZ)A`hXqIkeKLd@`Y=ir4B)`FWhK!koK$cwr^m&g1u~%%LxFlK zr9%YW8UkMoizR1xRO9ZZuC8vFGtqGH89P>V*Ry`yl0e(raw+D_!f|%XQ&d^u?cDf1 z86d&I+$9(zT8A-^0lLM`ZZnF43$*TpI||XpExukuS+aNT-0?Qom9~5#gVfT}vh0q@ zKCxR_TU#QI!a7WTVA;JkkQ&b_01^YOi2dCs3@s_yu-_m|Ni=o`GNlgfIG z0gWK2KLAW|Y=8tMcU|R18GV*S!RCVTr2V!05l(tPUzl|TDIGL|I#}-mK#lX@Fl`8r zW8s^do4@*#c3QC-+Fd2wYqxydD_|* zIdQS;`)_F}<2=3tfUI80Gud|%Wk$8UY;0^02PdNHR!lH@K}zr~&5 zbBZ9{+H#Bub+pLfE_C6G@v*UCRTA`PatQT%ci|s$hc@N*kgQvNY~I%2nu2ezEEm}7 z2T%@{mY2^EXITIp;!*MTr;2Laq})YuGc`4>Gx%*#GSuNryBVYp@@@Qw4LJPUw{L|Z zfWISj)z#Cx?Vte-ht61AT}=nB4hu`i^!uA<+!~i|t9|e3*Fuv_n->K&U5&iG&#$j8 zsMjuAr@Hy+$;dtfDx&&@oSa-z)91J@TpmV2lB&a^(o&uSBN`|cg&@Q;nw#<)pqG%$ zKA`RGwtM*xbBK$>SX;%Q@};^u&(1NRC6Z_>rSrj@9m9?Pdl@(J zROy{59y+_ag7~fjrHnd*ci;Z|7MytDV@uQr;5LB@A?i4%28BXlm1xX|kVB3`u0vh| zULE$oZ6AeFL`fwhV0odT}PCNybIS@UdGeI6u&79r7MN zI24LCnIeZscODo?2!OIq8BH=p)>9|U9AaKnR0MjsJx+hn-a-kh$ zR&o#5KF8)E>BIZp^ydsg;K_ep=Oha=EGy2=W|o$|880=8>5b{V)~WK+R5Ih?<5QlO zCsL69Z-3CB$1p{#teIw?6Oc4E#;_U`VEN$R8(He<-$B29z@PBHJ0Gl!^p>xBHY~?< z09a747lx8t6_;)Sd(L+HxT14MrERmbF%fTC!Wkm`d;i9TN`$?+iXN+rpP!$F1q=9$ zCOhHmjIiEpG^@jBhmwafhw^_zQ1&BC_#QQr3#hd0(4Dt8OFkTs+VkANkP;%Coq)dC zi6RB$zu!~-J~j1QY}-ID!QfKji!(JORtsflZyRa;N`@kGO@~k=xiJ+!j6O`13^$PY zPS`l|zOLP1aq0jd+Vq!l5##jrA%4+OQMT$h5iz}W;|yx@0y|`( z%*nnyC>*s8vldVh4J1wHJ!wiu*(r&R^UN$qPV9t#*RsnIdr{M^+b9oC z?{t#&i}T?Ga8q)Uawbf5-@tCJ=5OdfTZ<-txRk|CQ%GAi_qbmxvqhQS=pNi-vwa}F z$=g`#9D=Ua7?RM`EXi7d#|Z7-X5qz_{1UBnrPQ zo=HbQYyk)Z?<5X-0V&`0gm|OOq!DyG!l5Ki@>O%Q!5jv!?NLv(imFf*4u0hc{j z7bl*gkj>0#G6eSwPf>C4FqDncKto*R1t3XXe+`$>klZzF=K-Z^*RGnrAx4{C2u{Qxxo&*no>{6dkIcT0brc}X zVo5anu;KlKs?@Cw6|;b06446}$dVyttt6sF1)DY{Ggt;`tGsd>Yv>iH#b#GgPc{K{ zRBbm=7H~BYfSJ0qDSh)tI#a^SW&7usfYYyxaw^D<*{O_}9QQjU&KOgl2i1+5;Lo49cU;qQSp|74IWHVJ|^-lWwG+RFW(<%ve&s#e21HkHV2x=WPxNlax00_~s<;>c^AepV_ zyYvm+3IAjpd!5Je)>JQA{5wYJvV0}`oL?wA`sJpvIKAWsAx*5%wAID>ZR3L<~cOAO$~E&+@^Y=GMBpq?oGT zqDf<;*C?kHDzTEb_qxixA5|x12(Q_~3hI3XlSwFa6CxtsppVtSqDuI%w9p7S`S^&! zUnD5z#MeKN;7pDf@6TK|jZgEwe_$4j|ArHn44Qw<_Qc95?x_Z{H~pGA%OW%i?zbt| zP4HxLwDd$#O49|0LWYW5&?Nokv*k5~ik;89I?uGKl5(RSM(4lV$zM4no85|J@KvW@W?+B&+&fSDK4ez$8*T7x^kV@)5s+0I?3PMroALZow=Kf(^MC~s(!0t^Q;2lD}r58R6# z7c;q=Hqz$t`r)$F3>D@!wLp18P=-3X%EmR~Uax3q-T0x@lNEtQ*AQYzz%JzI#Z1ik+oFIK1TTglV(Ys*M)yx3DHQ;kub1^**5g|h7BmZ%7q=WCJUI6JcpEQ6 z5PYa`M6&Qg1YCHBGU-qlQS!K_Er)8a;9a2Pf!`*Xx}SmESEy4k`j*VQ73RdBG#Lm7ih!!F z(r3WTVnRkW1w7C?ZHi1jTMq=GV>=mwrrJb^XN4jh!!XsHD#oALgdV|Hru1Vb@vS3I2%*Ve2 z#$M!lWDb28((wwtW2`Aaf&XZqjAf`p@}r8WmH=w;Pg14oMIy0aLxo@!v#T+Dh>y{| zat?#?wx6m(48{IXNdt?ai2&i#)YL80jr#Fz>0T+B)V0H8QTB_eDIr9OM>W#~o*;s5 zk5J>paQ0QxNe{-RuIOuG=nt!JI$B4FlH;KLSa@X2V>j`Un(0imxfpM#((V@zN)s9r zZ2?71Gvz~xH^@y6R#sLPmL>hx^ReB48=tH_#+y@RnP-65Yj0Fpysb6gZ!R^=+sBIa z+k=C)^}V4CpyFl@b}XJ=)()NzIQoaMcwLy&u^j>-BtzV_d%Jw{of$zIZz%sP`@MT8 zzJh{+?eQU41n1N9*CKNebD;%>dkq#{QSBkvfI~bEA(CnQ8SRRg2poax}o zW`CIW^SOLhLDKtm_E^!}?x4w6N*kvgq-ui{_cZuR^I=s=cu+lQ|3w~%U0r*CLcWMr zLEynlWBtZzh>tGV`sBonA#NoS8OHZ04~e z-`s&6$iGIKggB6#$DmPZ80MoEZf7{MAes9KKTMm`H{Xs9XnXQMvt+Ux%j94b0Md}>%mV2UPmT&AIN;O9!d<>IeHqj8-JPby^Z80bjXPG zX-fK>6g#m@D{MYxxRj?}m1c(&(R`&tIOGIa4dC$6K4bJhT~uc9f(?IEyxAkVVLA>h zZnD5jAh4*wPdk6_)3Gdf^_$^t7dDhFWFPo2>}+j?E-JAvB$Jb~fpQN-C3Hw(+T`6w z9^Br1%xr|YSK&mAShhKoSu5_FG$qP`A!li*gp$`6$8yc8P&Av( zs?KH5p?Vh(o%5G=vPhUscY(DcA^7nd_|>5*Cjyo8%Z%?#bjUa@37nb z{XXKKx&1rH1xk5yM!3m+P?cq)tJd7DAxxs}DgHhsROHJ@{n}3N<#v!`y1F_N{*BR4 z?}32DZiVp=A|oM+vd~0gjqlTvVc$+%Dqu#c@qa8(-+FiYAG9& zcDMO-oJ~E3DDm1Plf+SV4WH!q;xQ`Kb1Y|7(?zi|C)4DUlDY;&#VHVFw1%|Z+=Q$j zFt&B5g}hcoE)dHillC9{0pd4M9zJoS~t)6nMCrBW6qiy}TPdv%g3NvJ} z{E_?kE5!f^*g+~>K*l**5bekS4JE%8qFOelI8)|4TE;!Mrd0de7WRnuczu z3HUmEyS7oI!dpn>jH+twjNL>bIoM0&p3C0IrK*Xq#W06hydw*8ixLup-xGF%gDS*L zDnZ=iZUD#dmWc#4=E2%|InX6v5Z{+4;R)S}bR0z?VY4&FX^jpfe`Eg(wUAtreZ}T_ zuGW!Ja*35~VnHZp^sHV|-EnsZvWNkR{&jq~X&50IgYhC3FIGq3Dp}^q50jrsv9!jT z2&TYY$>LO7b_P}*pRd@hceQ^V!4;q5LzjMeBWIyVkq^I}C4W*ns**^%pU_Zk1ke{Y z;!frrweEfsed?o%+)zI8&4=OqIt2D0Lr}$lZzCQ@s#4N%t_hIMfbDmy7juqfk@OGZ z1gxAeMQ8FD-^UUg)B$hgbyN0FG6(NqeM3HKO#VHX%o*y=DUz%MD-DibW$NO20rA9x zNWc7Xk&I!0bzK--*87tA`U{Z&1W%gy$Vd@w$yqi)3TtCn65aC0uK!8nEy&uCL^UWH zzX$R0j-h{aWlYm00V%e5_IV?WpB?y`FpWOhsfRw#XMg?0R6xA2QTK%BsT#5{3|QR7LoqvJehBs?jKMcva+-`iazbP1E)PQ+ zE+M4&>X*<#rXA8tDLpIGhBW%M#alq8f}WB!<@EY{AzSM3v)P~R7^sbkFqb0|Y0P%~ zwc}X)&_V08_p!8e&y;Gqhu-oWzS)T5o96CE%F;d%>b9{(_1*CFRz*6zLQW1{j+P?S zGA#%KuA-CI z!!D^<5v*^le-b`zVT;XL2`|vf`aQ6nl5>p`)Q+L%TJ$FS>Q@qPs@BaKVQt#a+447o z0@)}nY~3U3@uqG+)T)WdHl0b2sAqsQ7yb{t5D_SMs-uHIzAs{X7`AB`$TlvgV zq{S?qw_o#Mw$U>jpZeh78=oBqwK|m(luc90bxjRONj~4>uVX_@d8iksRS)_vOisId zOx9l7D-xoC%Oe2!?ENF{Bukj}>W-$xC#K8yi^mS^fwde`R5Gp?;RH7m)^|!nZ4#7Y zP(*BE?zrou+9k$P>2sO>_?^vFCj1Xmv@#^?G`Ze)-Xg?c~X+Q-o2Gsz!pjLUzf zqGqh}0U4F?r;gfSW?|;w$ra>+rr0}n4J+FNG z%f7*BRWntHIjFDVfSbjYL6lWgEZQie3*jpr;v&<;bZJmNz^LhwiuRX3!;Xfpzh_ZH zT60X{b6^kQv1mqYQE>P~_x>fqlHkd3KWFp3STnz8g#%oexbc8y`k!}YHXOlisxg3= zQP0{U`ka!zA|l=SFB2BcX`qT+IvQ0&UN2N-h@nT9qRKi+|L1z;OkQQ>z{W88N*q6+ zS#^`u|KDS0{xuxodZ^q1{IrRG?KnCDAub#|Ezcu*TQpsG|3~|ACyMrIMViWRnA&9~ zCnp1eBqJjuCB+*kh(HLB?t&u_7!M=gy=w(l2>`>A;XW+E*!&}!x^%Tp|L}bFs{fd_ zj-w1x_lH83}c~srNAYog z=yS|{;O>J{9EZ_MV+J)SlU6V$S*ngKfex-yA9EGSR`T`BhR>2g|W8JZ|@j2|!jEC;Fz_jA$ z{xCgot-4x>WU-9pD(I7nx_WGzg8D=6-wH6vLRKqxmeYrxJ2OCpup>Nt`dY6|lJ~FC zX*Ls4QhRy}H6#59lqxAM)Xs=qr*gE4{KISiqBr4(S=ZL&kQfdwBLM zvv{PZQpE|-7hm5H$X}ANKOrWYn3yOxt``7ax%H;YgKq%pBZMKr1ik~`zxQYaoP9HU zgHIjYD;8?-f5%tl$$+M^2pq6L$$U^Drj-W>)v{-mEaKwS;-Kf^=m(lM4<%mEF6bgO z4c&!)0tb%ND9$AAB_=iiT>G18uHCFMpcvV(2=k0Wsn^W+)G(Ypw%J0?syOh8c`&96BgbYd zd)4l8@MUsjlA6VXf8){uy5j-W`%sjf9klckYGh(U;4<*-o8TN@i|sMvLpL1a7=pmv z+{X!kq!(U~z)2ATJ&g3}0=mn4P%v*TMsa9{SdT0%EGo!&{s03?cH3y6$_wD?I)`lR zEWc0sd*>fOu;0K5##NO}L1E_T20-w(Lj_l?71aD?l@;MbH@v3khXm3RydJAZ>@&wMJMYFK9o{8~J8q_niO2j6I430ZVT zbVXC8-gsJr3`JB=c0VuMG=>n^7IsGph?ulZHiLtM0pEs(KwlEjH82o&Sy9QA08-+{ zhV79-oBt)vq;>X2jy6zcP17~+g<-^Vlb)33gG3C>t$*sZZ>s|?Hq=9mPSjzh%{b62 zl=Dnh9;V$ZTi?h*eeZDZE73bz(X#w}C0|VD=JSnW#5FMKjhTH-gKJ^c2HJHeHUT>U z-K`|5Q3I>`0&>o#U2OT?M`+rZvdAHTc7HQtNpntR8FZ?5*p)XcAsi1v&jaSJN@rw3u)KSMix(Ca=4~ivkdTnTuAXuTT5-ztt(khAxa9La;Fg?k@=7=k06r>K zrI~tEdeE$k1M&kxxAdz zJrzbzn$5jVw;AoLFY(zJ<1BA>2kn3n=8U5vGkc~4&>g75!dJ7Prf_&Bx|67lu@G# zR**?M908peP^f{7Ls0^X|K^>gb2-wV#0;VNOW0kBL-!qro z7(EngN#NP5TOkH++E)r?lS&xz0v3b7I}tX@pZW6(ivBtrq8d7n#_!OF;0&%G&=F8U zq!^m%FmibPV~u<2?>pP%CD@k;haUjHla|m!j7aktR06W2qJ$$imd@DDKY*DBJnu-* zx%Kd9%0@&(h@Uf#SYtzj;ZrbQMS#irQ)vaHpPT__ITB@8PX!3M1Fe{!SY#cl{0M3a z$@T{`|91bGkDZ;J3n{Xt|4Z)0$~rFKVyy869uO!3l$GPl&rx-|Rj5{s#L1y=$?c&^ z4Kj=sOhH>f7ryhMGCU35{;-a}f^oXM>7ehvB1WN18gSsts=6_0ePN?|NSApiEGp^= z7^YA^v{9jFoO^^My+yHf@q8305EAA3JlI2wk~elq{SFtGV@f>!~2@KGD6eqOht*Bqv9r zN=Qmd3JV_rK$Dd1aG!JysI+!6)UK#H2k44O8ciV9=dfa?!T~3x6iah-IHFN*(nu*p zMn$FUaJO37oTc;)^FmBDhz5(A_X}A1srC?gdqu8+eif|p@UNOZneYgLo~LPw@FNb z!aR2poBgjEawT9`dPY^S$B!T1p?|_lc^bJj&cxpNKpu&)!(xSF!$N2P2}2oBNp#Yz zGfs#Ob84Fe^HL{T0#m)i4tmA9F5(PeiJeox`3kAa#mRUQx^htW8W`ikLaJH}@IiN| z(9(4e5qtfDi3(4F2^-%jz}fl1P$JzxAuhR2ni(u~E=Gff&Uw5d7R^##2&d)a*9zv_ z34~w`WQPAy-!hACeAWsWoERsATpZ(2fi{V+w%F8dxA6q0DbzJAkl`Q)BFAF9IaWLY zSht*)p+twi;h@*5 z0R|W%snft?CO)RBifgnwn@SSH0d;yZFCLQy#CRgscnb=2caQ1CwX1745C4DEbV zcT1VBahCUO2LUpBu!CWjV``nlg&Z>!zK!WYa+$p%2h+{H+_?WtOuI_IV->YzxbET0 zP%|59jCn#);w$xc(VvZo_RRovg*g#yN8%v(1z7kRiuZZgj?wppcTHuvk{>7B;z;1( z1+Zu(y~IE8J3eHSljqT+M*;#aJ}-ugP_Uq?sDIX3^%f$JD^6M9ju~0 z#`UBEt?dRl?;x~RkjBCN15w!hxLt!*)PYXQSL`@ouN@mGdmGcWyI_j+cg-Sr6zCTz z(g7`>>_2ShD8gQ7Wq&5lG}WqV9&+HSF0{EjU4xeTr45QYEu|^2P}io#B$u7DCzbu* z5Zs|22~(Amx`;d=laiI+(j|`=>~aC=u;~Hh9kt*Z&?HU0=(GB5X?gDW0QxvoT_2|! zJGe({K_AhhQw1P{x!Ki|UNT6C_c~XfpuuXIj1c^JY_g}CrlO@xZD)nOa=+0OXwFWt zM-ppQUB72B(LMmsNeJN!YRC3;Ep14Z5mbp1Op}0)n=R<)62RKPocapo_b4afgk~fx@HGgw`lCouCX$kbe zb!iT7kct4S8JT|Cd7MeEo+kD{P;ev=&dEovp@Agc5D2*TB}Y0!yXjGg>)RHWw4^zy zeeK_qh<`UV=W+TKxEKkylJdw}$NP^Ls73g0j`PG3H0y?POl>z7`enhkWMP(?Sdd%U zQ2OdnCq)%@Z?Lb=8|b)%KtefKL4p*Y0fw<~yYq5^E$SL*_$Zx~u^RU1he(f$iPme1 z3dNO&&pR+4j`OsVJ`b?~4L0pl)M=SNJVrIdKY0zSaaMZVska6=NF-_2?=Z%5OtGlKeW6czw||4oA%7-l_R2ZLnaIZ63(QGgNHQ`Y|Q7Mo+d zTjKH{&4x>3Rk8h`I5q*|!m^94?FPtZ9E2>bfZJd)tYuO~G`XxoNB6;GYTI$r151oP zTFnFb`(BRvye_>F_G-wsDYVc*f24@f^Oj~o$TZAzMWWFN%3IA9!HuTn5=4rN3Bglf z1C%1Kn;Ql?@P0cgzO-}v8%Pv82xDMs)zh>7VhHT7A2yFRI1P9-1tLbcT48}dLA!s{ zP3s7nh}tC8!{m&NGG~98YCvj(Y=^iV^bWZGlXLsgFrvGR|PYH-4P_LV0@{xMx&S&G^NZ}ptqTvQ^$zBV40(b z^|@$n``hKPW zWSZWi@vGrN1!a6`!>1uDt(s_a&!4!xM{>t?OzhSqZVXh~I;o?hJO2$xcBI3nXA8ek zZIRsC?4{Y**1!PV_?+iBI5@=u$_v2skYvAXE_YkBx2|uvbS)?KY}{Jv>f0m9Dip-8#Fi!&^=qu zAU=73`E;AVD3(|64kN50`<9tOT(8M&>C()E{@J8vwol3U`TUou^fM3Tmf+sAnvW8= zQ93RR%mRVWtd}~rE<5OOy%eYF6%D)uAm|@l5n@wkZ_^}{Ow5eu?9V1s zzi}`RmhOslHE>HmME-ltHm|c`oe%O?($dm;dwaJTz`)yfYR}$PZ>M5kWByonRxc-a zXF6THuIyGd1&UI8=ab^4GZgMYUAc@U!gxz}YlD5x=|I;%?O$*d#m^M$&lIP;6qCta z=#$0Y_S-A#C32b5`nZ^oAjAyBpJ4DiTW634_Ie#m;8Srd7xxdGxx9tu4;mK>e&6V? zeOO9v4>Q;E64ZaHS6zcFmvMaMh{+NCUq%Sm5`aWoCOe^L%URYgzwLTQAJ+Hic#9nO z5%s%QQI6+JRsH@z8j&E5_LhT_iaY2DJ>eJkE@$?W< zW}a`!QE|&^`ln*(wBiQ^P4U}m@@<1ngm9&|Q(l8J5-&1HQ3e$D&N{k%3)Ts>s%8X- zMNNYK<*M~GKEmAl#6p=TYN>)bjxEo=Fj=UJ(z7%sR{YL_*-uBO>ETB0Kl3*qoO`Y~ z_?Zg@7k}UbQfzt+H%eIn>v?hX%Mn+4Y8-KagJ4fb4-9NM+k8RcS zpqrsUI&yN*W3JyL-@38RATpt(^Rcb~8gD^;fBzKu!Kyau{2%hhs?zf(?m9j?sy=w} z&PGP6snP$D)?tqzw6IumK%kMtE>3XOT88Uf^`;*uOLWb4%uO}SEIO&R&n^_5njeq^N4U0j@%I@*p_`#mjL)P@WLEUKW>)Yx6`k<&RPW9RV|^ z{2ez0sWt+gXT2CT{#V!h$ zv<_TIx^3Yn!~124f9}`wydQm>SDP30u(0Y$5nOf5zc{=3xXkV1?Nd+vh7l%Vuwp%j zmo|uaJUcriiKPfRw<#w&wAxR|1TpTo;cb47@&Lahy3MxYf$u zVOnM@d@C2C_Wv+-R$)~}-P%SGknV1j?(Pz)MR#{2ozf`Xwdn2!=@bF!mXPj7x>1ll z-QWKH>t6@!U>&{ddgq*D%rTzl9_iht8AFz04iOMb;xJgWHzkkuu)IrGS9W1th@$>b2i0QOO_poJRW%F&PUeb2q>;CJ5$4Rv zRlAq|=Uj=&4V4Kb+=&gE3^galyA^1@sdD~*YEXWAVh|MzUJ8r(NVxhGjuwnLmi-s! z@M!#+3+1KeVw@nI4nHUJNuC5@RA$C097VkykEV5fmw3g8<1ZxZ4)L4XJOtR}jCA^% zm1%YtUUCeTDG-DFA_$uC&v!7+ZR%wNe#i`hRlOeF4(U*%3b8M*jZMR#Mzffgkwtc4 zP#q?Vlo84f^^v*$NoUC7eV<3VIdc-fURug--WQj}lUoP}11!`c%B90jrE5loJGdj} zBnF9&x3P))zb8CW0L0-2W62zuezb5Yna0*$3uOStbjz&2U}fougN$(*Boz`-c5DvH zSs3QnE``VO6df8XDolf(7T9)8$g!127Bn@j%o?*Jia5nBMO#GWuQpT0`uZccg9}xg z5AihUwDl>8{p^bqo8DV)`NCOQEIXw`k=vP52ze{D#ZAD0_6fR+v@k&zKaE^`O~r4H zBb$zcF}{c?TBtlik;syeG{T&qqr=0mHS&Vb@S_|LbLvXU$WhUyce$#CN=@Mu#X8my z-fqgR)T{r7h)t#8ak6(&?>;dp*{WrfwT)YdI;7NT(^zIj-rnwc5XNR^SRm|%S}y*| z`wp8g?p$N7d|Y)?-{P$B)h?jAEOo?zF}5G+L&{o;U%)6%nAtva`9aDt29p_hBkDAn zF`xQ1kt|e2-bFxvL0w2x@!zgv9X>?hJ za*nc?-`q4sr%io0)u|1_AcpvX+A90FN}q*k1T|8!&9IJ+@$XyDj3wgC|K71~U?2{T z&gAB=-bT5kZuW5Sx5%ADwm4UgZnjG9CNMP<>sj!X49*X=6~uzKA(%5zsX^A?;jUNF z&iwBY>w8)uJOudjBg+#r_c2%_z&k+4%`7O7QZ>l4(NEckJWSfJItHX)?% zmwWmkGA!{-9*3a{ka~#h!*on%&C4x{5(PB8OlY)mss!ZI*tkukO}fjZhHpkSone#w zm14hwP90s#db`h=NtZzXO+k+Q;eY%8y*Y`?x~pNgn)S&UudC5<=qeu>`$ljZ8$;}b z91>y%6~TyGtW3lqG4Em8s&D&{ZcyIu0X4_!xGq&Pe7i z8$3fI$wP2aAa5aL1Cgn0X?))oO@5B6ip&gcRW1aHH}XQ`i_kRb*_9$ElWX=rVq=IZ zLAvW6RIz?EXtbN8G9iUq3G5`UxazQ^ej*F;WEeGqGV-_(LW!3g89iUuBQ#%TnF{|` z-f&*JgNIMp;*M4wDY=M3-68~IX}O53qw}lU;4B0M;*ey(N~E{Ly-Gx!oV=>2NYS}?NbR_9@l~Osg#zy8EwfpFWg-YN;x?S6b@6zbehHF56PBh79~+j6n0qjdpF^|u9Ol)%Pd-8 zXT?0IeDCUltC%l<&s?f9s6EPBcBV1f&o^59A!T&lq0g{EKO*V-9Jn1i#}omMZGS~ zeKUl37#Wc@zL)wx18#t-sw!yORtx*wriroz9@V1|F{{n0!CPD#WYMp{zG9Yk7rl74 z^A_mKZ7_B^v@!jsF$R8gYvKRCQp;QsKej$=kE2>YPFrhhn65&P)g>Et*~~W8f`S6& zgzIa!*`YA~S-8KD1g)DJT0u=1gxr6Q=xjo>&%Z;4kLce7(k9UB)KT-w*vF{qHAv4# zu>>Uy>j=GEIAyseV5~3dWGp&a`|WV~#=9P|?Q0Xb4kfOmyJ)eKjVi)zWm802g&ce6 zze%2>L*J*L+{f*}b4bel&X|k@q3$pZA7@TM9nh)SKbeNo?yKUAI%gQP+a#+FsaNqS z>W?ODou|`gejJtoE#ihZeeJ!)@`vw2agu2Ii$*r}E8OrlOBjn}tdfdznWx)`rzdNi zCa9jWsGfY)Vjmi?CQ3)>^~d5_7htPEP%14a_UkPXjnFeE$HqJ`l~GY-OyYUEe-g%BGnWNO zF|TvP4Ow%Drix1vdA^Ron#@B z;!CD_GEeYtr_5FlQR6L|k)1Aoe`sFd#vm);CxLdUgmDj&R_S3>B)WA}N^0N{!tz{>15mR2 zi*07SsI@B7hQ$)a?0@QZkJ&O60Qk{bulj?Xe%wc}Ar=GbwAmaM5EB#1TP-auvw#9B zli)&$SwhN7;G$AK1`YeO)s9q@u^gvY+x~GjbGycn1g&zq@1T(V1JGPlKFU7)IRi+xGLex`tjH&a(LB70 za{#|UB^BTT`X+iNgLZZKGJ-G7c8i~L0UqTGs05;DZ_%l!XLSJww6Y2i<2M6N3h;xO ze8{i0UIvN|^km68=h$W-Ef8ro`5p?Gb$Nty`*K{Y440q>YDU1#XEAgdL7Q^`Iy|76 zU0nBbiqe`<;1x5)ZvxW-Vdqn2ql~XBnpZ%Wl_luu;OF<%8i^z%yCC=8gC_=E#cUju zWn6%Qm|+gIL?d42aZg!;Iy2t$&Q@aqo5QN;^=cv{Ha6H-I*u&Htp7pvd*wp;U+ECE zLD{0(@GBtcI$Lh31!zQYR7u86buM%x8Z=sCa#Iw00i*bJJdi@F-2gj@=;{=(4ZQi= z-XqTsG(1qkwtq4y8S?7<=ezF7y?2i9xk$p-!cFsn5UYNq#%EwAsHB08PliCwvWfVN z#!!`v5u%=rl941fjXZ{e!XSV;-WJRZoydfDIvH#qm5h?mqJ0nP;f~FSoQPAh3jmTg z9MLy#fJU5;Bx68)i%OxT+Jp__)27^>zs9)`g&jY$TLw zaZ`J5+n1hF>y|clG|B54QX@a0)zf!4z3X;pTH;2j2LBVeoP+Q=ks%wlpJvo@!_^$# zBRz6b+x#^R5j;t5D=z_FHI`O}7OU9Wck9DvH(B|h zpVo^tS=0s-Ni`UBg^hF#^4Aoqr+>SPL7Qe^ffm z{MJ@&`>SpZc7WUhE&SxvRHHT*3jobIdba0=$Eu|&d`qzUPabh8k_EN}fHkpWhd&U{ zGc3K_78G%=u88Yj3G~8*ld5CagW5i&aPw}UWDThx+eb`)pRJN z;e2%bA76@oV$Sisl>Ln8`*$Ar0r8D|H{ArpZ2%c#KujrQZ~!n&RE+hJfG(4u4=lIX z@4WU)!TRy3%N*9B%<->~;$VR*SXp65GP!@K$##xGo{Wyn|K*dhL&>5p4lZhJQaA$! zqcw^h9lxLC^1sq!8f`odQjl8Qt+au%dKR}lCtzrX$JJ6W+h&1&dx1dO1gavTs)+j$ z&IHbYMT|xqS`VV+t0H(bv5pseW$~?Wy?t?Q*a}DG8Jd;2VWq{zDxVj+wT{(YbI`43 zHZT-CPe5(a(t9=)#tmre(-fUDrhXlmewxS@1QI4br8Ue92U%)_x1>TJ*|@oJ4c=w3 zx)=8;K5epg-BbBVW&!Qw=5gMOAB#@#R^u5V4PyBHK)g987OfV+ptfDfdFj?}^PJ9U zHO2o!*eN&2H3kv43I4zs{Yb7w>4gnTBdh?dJB<3~Ny|EX&y@Q~bMUJXI(Vd@7cWqE zZM3IWu;O(Rx~AhlBmJD6Wl|63g0sNFw>|oGSfDmKBO^1 zY8#+kx&?}wVlQzwbocGNaZK_zh_*ZB+(OCYGsy*b?vx}UW(hAtU*b#~PjPZuW{fS_ zb2|$-ZS`$P%mn+l|HysM1*a<3C4+j$eDKjy2tGaW4A42UP0CVr&t$4SW8Q_)w=Wu4 zAHp2mYR(b4+6JK9$jSGPgdSVA@uuRo>FA8Ue5z9Ml6x&&rX|OywUXj62btqmonv17 zQ2@nggLsjX2`6bW_|TZQ8J;I7rfk1lbnKzhETEu`v|DVU-nNL^TluGi@rNg zQ~EOGzj@dBc~*AXd80`(QmUSwgYh|BQv@S2%=yCkb?i>O;h`uhw}hrJp#Ep1(6Q>ZA#NSsVy?=d!>!$B`37+_@x zEg9R=)}L$D>~C!b=2)O(+g{>%p1%c}6RU|Vdev@yZl?_~lJEr6;Y4Zz`4Dz9U^RyF zMZPVeLm@XF2QsK}BY%P@m5(a)>g1d~K+V^|gl>shM1l5x=7m^!{b%Gu+A$>7Z;u@H zB?SQNp@@TPfPhUl{vwC&;h$X=q={T7C6tKjgsl`4q(lg=JeN0aBPf5bi^>hI*^45e z<>JaR@;)zVDusPkTwFS^6H#0DzbrUy;mHv-=ta%v!C0NN_D#D}lsE zIxx>?p|Fi2^5b<9jl#PvHk;0*^p~?0;;Z_ zJS)pFuJopojDPaN&1WpMf$gs?!9&nv?|ioh=G_pAInuM( z<|xkqx{1L+P-Bfo2KRLCXzXfmBiz_#I;^Pw*;mYz{+`ub=3CM58XD;*A-crk89c&p z#MpqB2uU|u?C{bFJ@>!AIvuyW-M70Pv|qn@X?-8*M%Vo2@uQ@GljPDoKZ)`!d1Mkg zKa_%0HZhh;Aqpp%DO)B%5jn~w^!UaZw_l1G$wK0zZo=b0SEs61F`9Jp@h9eQvVT%g zM&{h7PXsAT&0CTXq_Ejrjde*m%!j~HoB)Lul^W*0@yYlz*FV*VIry$M5$LN!C;o$8 znq*e`h&9fh#xrY%WQj&1GsACNH$rV^hSuH3s;xGod1OLVijmO6xb|D&2pwlza1VEk zh2RSpJQhR6Ullepy?PiX1)mCqd+RJ9#+Gb^+3N(p#KH&^r}4l9o7iQx&2DGc@6f)`8$R%eR z{yCGU$dQndLl`qk#V5!9r51kN+**;e5Y0)2BgH5Q;I)lJDRDu z4`kGg=trwG@4J{aKF5JN1Ed0)Dx)>@#k$ZvHkmij9GeQC;p|?y+Qe4@(Rq=DcDoTR z^TO*>KYhLHxlMoFy?XtYNPeqSmJD>0?||F;`BnAI#o z6jV5aDq_lC6q(zSa6`q?l-c<_7^!_KXr4y@r7piBzli^3_}|r%@VQiC%#57sjdSIk zH)zprtC5I6K z*YAhHVz5HO0Gece=dJhGs>-VX^{FDb!eaV)%F~~lw#^>3#e$RIj%)aHIuJJ81Cf5A z7Vv>qc6F`&CnOH*8YuvNtdNq^bKvdaYR4T=tgS4$r6mfhxwNsUABnX|5ob8cjo)yv zw5+A*en@uG>#=Cbt3p1B;h4tiED zXQ_qgBzC3pp zuCxKW#>>eexas%WH`DPydCJQbY^@V==ROpqDy}CV{Sw5hFN25sIbw(h3N-Hw*Q@i? z4Y8TEyePvvtMooW4Jp16E8W&AubJWJzUjB1cfd90QA|yZi=QuqAuN?CRl{kxKs_vd zORtMaixYIA(qF)%zHygAO`D;CFr+yQhyeYNRP-llOmbz z)q^O?$Q*#|U6{!TI4b~47oCVJ98Jh|4+?Ur9$-TfSs5w45gCb~4@+t5 z-%MpSlB)kLO>k2noq8a)1Hk>lKv{lsAM2Hng1qo8;2Bf~4mSzB(?TOF9L^gX8^gn2 zzx{j(;~+-tusn!O{YIQbF(&A9z7$AXUj8Of=Ae<2Pfz3HM!v_U{^xGU%YzAdzc0l# zK4Wuqy5F3k{w6-=cdqvh{rRRH5lKN$7l34fHJX`)4~|lZ|JQ5AZe&yrpqskT*Y#8e z*3dT}?2HHAB?KckWwgtyay&UID%}z1Ison$i7qUtEudas=dc~yuXPgc>$?8gS8~nY z4;m_m%>$#0O-Fa-FV3YRyA`rxOwe7qxGXil76?LWR&2qb(8XRuj z7Xfv-D+%nar~r*TU-+MlEU9VPHd6W&B#*z}niAik({Z9n+lHZ$V#QVeW5w?bn0n^F zM^ormZBVoAmD1T)X5rR=D9nN5Q@!<_g;k|%HHm=Tm;mRMu&CvYi%Z4Lb`hS&>(J5q zfyk

  • 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

    h2f_xr$8Tpa78H;^z`AeBS3pQql=WWLVt&S^ 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 - -

    Screenshot of the note contextual menu indicating the “Export as PDF” - option.
    + +
    Screenshot of the Print preview functionality introduced in v0.103.0.
    -

    Printing

    -

    This feature allows printing of notes. It works on both the desktop client, - but also on the web.

    +

    Trilium allows printing notes to a real printer, or generating a structured + PDF for a single note or for multiple notes through Collections.

    Note that not all note types are printable as of now. We do plan to increase the coverage of supported note types in the future.

    +

    Printing and exporting as PDF are not perfect. Due to technical limitations, + and sometimes even browser or Electron glitches the text might appear cut + off in some circumstances. 

    +

    Printing a note or exporting as PDF on the desktop

    + +

    On the desktop application of Trilium it is possible to export a note + as PDF. To print a note:

    + +

    This will trigger the print preview screen next.

    +

    Print preview & print options

    +

    The print preview dialog allows the following printing options to be adjusted:

    +
      +
    • +

      The printer to use

      +
        +
      • +

        Save as PDF generates a PDF that is structured (maintains a table + of contents, keeps the text selectable). Prefer this over other virtual + PDF printers that ship with the operating system.

        +
      • +
      +
    • +
    • +

      Page orientation: Portrait (default) or Landscape.

      +
    • +
    • +

      Page size

      +
    • +
    • +

      Scale the entire content from 10% to 200% to improve the fit within the + page.

      +
    • +
    • +

      Margins, which can be removed completely or adjusted individually for + all the four edges.

      +
    • +
    • +

      Print only a subset of pages. Individual page numbers are separated by + colons and hyphen-based ranges are supported (e.g. 3-5 for pages 3 to 5).

      +
    • +
    +

    Additional interaction:

    +
      +
    • Print using system dialog allows setting more options that are + otherwise not available in Trilium.
    • +
    + +

    Printing on the browser

    +

    This feature allows printing of notes. It works on both the desktop client, + but also on the web.

    To print a note, select the - button to the right of the note and select Print note. Depending on the size and type of the note, this can take up to a few seconds. Afterwards you will be redirected to the system/browser printing dialog.

    - -

    Reporting issues with the rendering

    -

    Should you encounter any visual issues in the resulting PDF file (e.g. - a table does not fit properly, there is cut off text, etc.) feel free to +

    On the server or PWA (mobile), the option is not available due to technical + constraints and it will be hidden.

    +

    Reporting issues with the rendering

    +

    Should you encounter any visual issues in the resulting PDF file (e.g. + a table does not fit properly, there is cut off text, etc.) feel free to + report the issue. In this case, it's best to offer a sample note (click + on the + button, select Export note → This note and all of its descendants → HTML + in ZIP archive). Make sure not to accidentally leak any personal information.

    +

    Consider adjusting font sizes and using page breaks to + work around the layout.

    + +

    Automatic opening of the file

    +

    When the PDF is exported, it is automatically opened with the system default + application for easy preview.

    +

    Note that if you are using Linux with the GNOME desktop environment, sometimes + the default application might seem incorrect (such as opening in GIMP). + This is because it uses Gnome's “Recommended applications” list.

    +

    To solve this, you can change the recommended application for PDFs via + this command line. First, list the available applications via gio mime application/pdf and + then set the desired one. For example to use GNOME's Evince:

    gio mime application/pdf
    +

    Printing multiple notes

    +

    Since v0.100.0, it is possible to print more than one note at the time + by using Collections:

    +
      +
    1. First create a collection.
    2. +
    3. Configure it to use List View.
    4. +
    5. Print the collection note normally.
    6. +
    +

    The resulting collection will contain all the children of the collection, + while maintaining the hierarchy.

    + +

    Keyboard shortcut

    +

    It's possible to trigger both printing and export as PDF from the keyboard + by going to Keyboard shortcuts in Options and assigning a key combination + for:

    +
      +
    • Print Active Note +
    • +
    • Export Active Note as PDF +
    • +
    +

    Constraints & limitations

    +

    Not all Note Types are + supported when printing, in which case the Print and Export as PDF options + will be disabled.

    +
      +
    • For Code notes: +
        +
      • Line numbers are not printed.
      • +
      • Syntax highlighting is enabled, however a default theme (Visual Studio) + is enforced.
      • +
      +
    • +
    • For Collections, + the following are supported: +
        +
      • List View, allowing + to print multiple notes at once while preserving hierarchy (similar to + a book).
      • +
      • Presentation, + where each slide/sub-note is displayed. +
          +
        • Most note types are supported, especially the ones that have an image + representation such as Canvas and  + Mind Map.
        • +
        +
      • +
      • Table, where the + table is rendered in a print-friendly way. +
          +
        • Tables that are too complex (especially if they have multiple columns) + might not fit properly, however tables with a large number of rows are + supported thanks to pagination.
        • +
        • Consider printing in landscape mode, or using #printLandscape if + exporting to PDF.
        • +
        +
      • +
      • The rest of the collections are not supported, but we plan to add support + for all the collection types at some point.
      • +
      +
    • +
    • Using Custom app-wide CSS for + printing is no longer supported, instead a custom printCss relation + needs to be used (see below).
    • +
    +

    Customizing the print CSS

    +

    As an advanced use case, it's possible to customize the CSS used for printing + such as adjusting the fonts, sizes or margins. Note that Custom app-wide CSS will not work for + printing.

    +

    To do so:

    +
      +
    • Create a CSS code note.
    • +
    • On the note being printed, apply the ~printCss relation + to point to the newly created CSS code note.
    • +
    • To apply the CSS to multiple notes, consider using inheritable attributes or  report the issue. In this case, it's best to offer a sample note (click - on the - button, select Export note → This note and all of its descendants → HTML - in ZIP archive). Make sure not to accidentally leak any personal information.

      -

      Consider adjusting font sizes and using page breaks to - work around the layout.

      -

      Exporting as PDF

      -

      On the desktop application of Trilium it is possible to export a note - as PDF. On the server or PWA (mobile), the option is not available due - to technical constraints and it will be hidden.

      -

      To print a note, select the - button to the right of the note and select Export as PDF. Afterwards - you will be prompted to select where to save the PDF file.

      - -

      Automatic opening of the file

      -

      When the PDF is exported, it is automatically opened with the system default - application for easy preview.

      -

      Note that if you are using Linux with the GNOME desktop environment, sometimes - the default application might seem incorrect (such as opening in GIMP). - This is because it uses Gnome's “Recommended applications” list.

      -

      To solve this, you can change the recommended application for PDFs via - this command line. First, list the available applications via gio mime application/pdf and - then set the desired one. For example to use GNOME's Evince:

      gio mime application/pdf
      -

      Customizing exporting as PDF

      -

      When exporting to PDF, there are no customizable settings such as page - orientation, size. However, there are a few Attributes to adjust some of the settings:

      -
        -
      • To print in landscape mode instead of portrait (useful for big diagrams - or slides), add #printLandscape.
      • -
      • By default, the resulting PDF will be in Letter format. It is possible - to adjust it to another page size via the #printPageSize attribute, - with one of the following values: A0, - A1, A2, A3, - A4, A5, A6, - Legal, Letter, Tabloid, - Ledger.
      • -
      - -

      Printing multiple notes

      -

      Since v0.100.0, it is possible to print more than one note at the time - by using Collections:

      -
        -
      1. First create a collection.
      2. -
      3. Configure it to use List View.
      4. -
      5. Print the collection note normally.
      6. -
      -

      The resulting collection will contain all the children of the collection, - while maintaining the hierarchy.

      - -

      Keyboard shortcut

      -

      It's possible to trigger both printing and export as PDF from the keyboard - by going to Keyboard shortcuts in Options and assigning a key combination - for:

      -
        -
      • Print Active Note -
      • -
      • Export Active Note as PDF -
      • -
      -

      Constraints & limitations

      -

      Not all Note Types are - supported when printing, in which case the Print and Export as PDF options - will be disabled.

      -
        -
      • For Code notes: -
          -
        • Line numbers are not printed.
        • -
        • Syntax highlighting is enabled, however a default theme (Visual Studio) - is enforced.
        • -
        -
      • -
      • For Collections, - the following are supported: -
          -
        • List View, allowing - to print multiple notes at once while preserving hierarchy (similar to - a book).
        • -
        • Presentation, - where each slide/sub-note is displayed. -
            -
          • Most note types are supported, especially the ones that have an image - representation such as Canvas and  - Mind Map.
          • -
          -
        • -
        • Table, where the - table is rendered in a print-friendly way. -
            -
          • Tables that are too complex (especially if they have multiple columns) - might not fit properly, however tables with a large number of rows are - supported thanks to pagination.
          • -
          • Consider printing in landscape mode, or using #printLandscape if - exporting to PDF.
          • -
          -
        • -
        • The rest of the collections are not supported, but we plan to add support - for all the collection types at some point.
        • -
        -
      • -
      • Using Custom app-wide CSS for - printing is no longer supported, instead a custom printCss relation - needs to be used (see below).
      • -
      -

      Customizing the print CSS

      -

      As an advanced use case, it's possible to customize the CSS used for printing - such as adjusting the fonts, sizes or margins. Note that Custom app-wide CSS will not work for - printing.

      -

      To do so:

      -
        -
      • Create a CSS code note.
      • -
      • On the note being printed, apply the ~printCss relation - to point to the newly created CSS code note.
      • -
      • To apply the CSS to multiple notes, consider using inheritable attributes or  - Templates.
      • -
      -

      For example, to change the font of the document from the one defined by - the theme or the user to a serif one:

      body {
      +    class="reference-link" href="#root/_help_KC1HB96bqqHX">Templates.
    • +
    +

    For example, to change the font of the document from the one defined by + the theme or the user to a serif one:

    body {
     	--print-font-family: serif;
         --print-font-size: 11pt;
     }
    - -

    To remark:

    -
      -
    • Multiple CSS notes can be add by using multiple ~printCss relations.
    • -
    • If the note pointing to the printCss doesn't - have the right note type or mime type, it will be ignored.
    • + +

      To remark:

      +
        +
      • Multiple CSS notes can be add by using multiple ~printCss relations.
      • +
      • If the note pointing to the printCss doesn't + have the right note type or mime type, it will be ignored.
      • If migrating from a previous version where Custom app-wide CSS, there's no need for @media print { since the style-sheet is used only for printing.
      • -
      -

      Under the hood

      -

      Both printing and exporting as PDF use the same mechanism: a note is rendered - individually in a separate webpage that is then sent to the browser or - the Electron application either for printing or exporting as PDF.

      -

      The webpage that renders a single note can actually be accessed in a web - browser. For example http://localhost:8080/#root/WWRGzqHUfRln/RRZsE9Al8AIZ?ntxId=0o4fzk becomes - http://localhost:8080/?print#root/WWRGzqHUfRln/RRZsE9Al8AIZ.

      -

      Accessing the print note in a web browser allows for easy debugging to - understand why a particular note doesn't render well. The mechanism for - rendering is similar to the one used in Note List.

      \ No newline at end of file +
    +

    Under the hood

    +

    Both printing and exporting as PDF use the same mechanism: a note is rendered + individually in a separate webpage that is then sent to the browser or + the Electron application either for printing or exporting as PDF.

    +

    The webpage that renders a single note can actually be accessed in a web + browser. For example http://localhost:8080/#root/WWRGzqHUfRln/RRZsE9Al8AIZ?ntxId=0o4fzk becomes + http://localhost:8080/?print#root/WWRGzqHUfRln/RRZsE9Al8AIZ.

    +

    Accessing the print note in a web browser allows for easy debugging to + understand why a particular note doesn't render well. The mechanism for + rendering is similar to the one used in Note List.

    +
      +
    1. ^ +
      +

       

      +
      +
    2. +
    \ No newline at end of file diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes.html index c1e5399a62..8fff5ceb53 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes.html @@ -54,7 +54,8 @@ hide the Mermaid source code and display the diagram preview in full-size. In this case, the read-only mode can be easily toggled on or off via a dedicated button in the Floating buttons area.
  • -
  • Geo Map View will +
  • Geo Map will disallow all interaction that would otherwise change the map (dragging notes, adding new items).
  • \ No newline at end of file diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Code.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Code.html index 95e10fd245..a658cdc82a 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Code.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Code.html @@ -4,15 +4,16 @@

    This can be useful for a few things:

    • computer programmers can store code snippets as notes with syntax highlighting
    • -
    • JavaScript code notes can be executed inside Trilium for some extra functionality +
    • JavaScript code notes can be executed inside Trilium for some extra functionality
      • we call such JavaScript code notes "scripts" - see Scripting
      -
    • -
    • JSON, XML etc. can be used as storage for structured data (typically used - in conjunction with scripting)
    • + +
    • JSON, XML etc. can be used as storage for structured data (typically used + in conjunction with scripting)

    For shorter snippets of code that can be embedded in Text notes, see Code blocks.

    @@ -37,6 +38,54 @@ to manually refresh the application.

    The list of languages is also shared with the Code blocks feature of Text notes.

    +

    Word wrap

    +

    Long lines can be displayed on multiple lines:

    +
      +
    • Globally for all code notes, from Options → Code Notes. +
    • +
    • For a particular note, by going to the menu in Note buttons and + selecting Word wrap and selecting the appropriate option: +
        +
      • Auto, to respect the global word wrap for code notes.
      • +
      • On or Off, to change the state of the word wrap for this + note regardless of the global option.
      • +
      +
    • +
    +

    Adjusting options using the status bar

    + +

    The status bar at the bottom of the editor shows the current indentation + settings and language. Clicking on the indentation indicator opens a menu + with three sections:

    +
      +
    1. Indent Using — switch between Spaces and Tabs. If a per-note + override is active, a "Reset to default" option appears.
    2. +
    3. Display Width — choose from preset widths (1, 2, 3, 4, + 6, 8). Changes are saved as a per-note #tabWidth label.
    4. +
    5. Re-indent Content To — convert existing indentation to + a different style. For example, re-indent a file from 4 spaces to 2 spaces, + or from spaces to tabs. This rewrites the leading whitespace on every line + while preserving alignment remainders.
    6. +
    +

    Clicking the language indicator lets you change the note's MIME type.

    +

    Re-indentation

    +

    When you re-indent content, the editor:

    +
      +
    • Measures the visual column width of each line's leading whitespace using + the current style
    • +
    • Calculates indent levels and any alignment remainder
    • +
    • Rebuilds the leading whitespace in the target style
    • +
    • Preserves non-leading whitespace, blank lines, and content without indentation
    • +

    Color schemes

    Since Trilium 0.94.0 the colors of code notes can be customized by going 

  • It is possible to disable the syntax highlighting for all the notes by selecting “No syntax highlighting” in the “Color scheme” option.
  • -
  • Word wrapping is disabled by default, but can be configured from the same +
  • Word wrapping is disabled by default, but can be configured from the same section.
  • +
  • The tab width can also be adjusted from Options.