From c8888261925195101387099094b1e7ca9b196823 Mon Sep 17 00:00:00 2001 From: Zaki Ur Rehman Date: Thu, 16 Apr 2026 18:06:14 +0500 Subject: [PATCH 01/79] 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 02/79] 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 b2f02962fc977f2316890ac54bd7e9fa8cfabb04 Mon Sep 17 00:00:00 2001 From: Zaki Ur Rehman Date: Thu, 16 Apr 2026 22:54:48 +0500 Subject: [PATCH 03/79] 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 f64b0290092edcc65af9edec06a35392f0246d04 Mon Sep 17 00:00:00 2001 From: Zaki Ur Rehman Date: Thu, 16 Apr 2026 23:04:29 +0500 Subject: [PATCH 04/79] 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 889e44363ac55b4e0f184145a40ed864b111b3b6 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Thu, 16 Apr 2026 22:26:56 +0300 Subject: [PATCH 05/79] 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 06/79] 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 07/79] 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 08/79] 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 09/79] 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 26/79] 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 27/79] 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 28/79] 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 29/79] 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 30/79] 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 31/79] 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 32/79] 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 33/79] 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 34/79] 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 35/79] 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 36/79] 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 37/79] 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 38/79] 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 39/79] 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 40/79] 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 74/79] 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 75/79] 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 76/79] 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 77/79] 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 78/79] 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 79/79] 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 })); }