Compare commits

..

3 Commits

33 changed files with 317 additions and 883 deletions

View File

@@ -75,7 +75,7 @@
"@types/leaflet-gpx": "1.3.8",
"@types/mark.js": "8.11.12",
"@types/reveal.js": "5.2.2",
"@types/tabulator-tables": "6.3.1",
"@types/tabulator-tables": "6.3.0",
"copy-webpack-plugin": "13.0.1",
"happy-dom": "20.0.11",
"script-loader": "0.7.2",

View File

@@ -234,9 +234,6 @@
--right-pane-item-hover-background: #ffffff26;
--right-pane-item-hover-color: white;
--bottom-panel-background-color: #11111180;
--bottom-panel-title-bar-background-color: #3F3F3F80;
--scrollbar-thumb-color: #fdfdfd5c;
--scrollbar-thumb-hover-color: #ffffff7d;
--scrollbar-background-color: transparent;

View File

@@ -232,9 +232,6 @@
--right-pane-item-hover-background: #00000013;
--right-pane-item-hover-color: inherit;
--bottom-panel-background-color: #0000000a;
--bottom-panel-title-bar-background-color: #00000017;
--scrollbar-thumb-color: #0000005c;
--scrollbar-thumb-hover-color: #00000066;
--scrollbar-background-color: transparent;

View File

@@ -128,12 +128,6 @@ body.backdrop-effects-disabled {
font-size: 0.9rem !important;
}
.dropdown-menu.tn-dropdown-menu-scrollable {
/* Note: scrollable dropdowns does not support submenus */
max-height: 90vh;
overflow: scroll;
}
body.desktop .dropdown-menu::before,
:root .ck.ck-dropdown__panel::before,
:root .excalidraw .popover::before,

View File

@@ -653,8 +653,7 @@ body a.tn-link:focus-visible,
}
body a.tn-link:hover,
.use-tn-links a:hover,
.use-tn-links a.ck-widget_selected {
.use-tn-links a:hover {
box-shadow: 0 0 0 4px var(--link-hover-background);
--background: var(--link-hover-background);
color: var(--link-hover-color);

View File

@@ -670,33 +670,16 @@ html .note-detail-editable-text :not(figure, .include-note, hr):first-child {
color: var(--main-text-color);
}
/* Links */
.ck-content a.ck-widget {
outline: none;
}
.ck-content a.ck-widget.ck-widget_selected,
.ck-content a.ck-link_selected {
outline: 2px solid var(--input-focus-outline-color);
outline-offset: 2px;
background: var(--link-hover-background);
}
/* Reference link */
.ck-content a.reference-link,
.ck-content a.reference-link:hover {
/* Apply underline only to the span inside the link so it can follow the
* target note's user defined color */
text-decoration: none;
text-decoration: none;
}
.ck-content a.reference-link > span {
color: var(--custom-color, inherit);
}
.ck-content a.reference-link:hover > span {
text-decoration: underline;
}

View File

@@ -1230,7 +1230,7 @@ body.layout-vertical .tab-row-widget-is-sorting .note-tab.note-tab-is-dragging .
margin-bottom: 2px;
}
body.layout-vertical #rest-pane > .classic-toolbar-widget {
body.vertical-layout #rest-pane > .classic-toolbar-widget {
border-start-start-radius: var(--center-pane-border-radius);
}

View File

@@ -1 +0,0 @@
{}

View File

@@ -818,8 +818,7 @@
},
"inherited_attribute_list": {
"title": "Inherited Attributes",
"no_inherited_attributes": "No inherited attributes.",
"none": "none"
"no_inherited_attributes": "No inherited attributes."
},
"note_info_widget": {
"note_id": "Note ID",
@@ -2204,9 +2203,6 @@
"note_paths_title": "Note paths",
"code_note_switcher": "Change language mode"
},
"attributes_panel": {
"title": "Note Attributes"
},
"right_pane": {
"empty_message": "Nothing to show for this note",
"empty_button": "Hide the panel",

View File

@@ -1934,10 +1934,7 @@
},
"highlights_list_2": {
"title": "Lista wyróżnień",
"options": "Opcje",
"modal_title": "Konfiguracja listy wyróżnień",
"menu_configure": "Konfiguracja listy wyróżnień...",
"no_highlights": "Nie znaleziono wyróżnień."
"options": "Opcje"
},
"quick-search": {
"placeholder": "Szybkie wyszukiwanie",

View File

@@ -483,7 +483,7 @@
"workspace_template": "Эта заметка появится в списке доступных шаблонов при создании новой заметки, но только если будет установлен фокус на рабочую область с этим шаблоном",
"workspace_search_home": "новые заметки поиска будут созданы как дочерние записи этой заметки, когда установлен фокус на какую-либо родительскую заметку этого рабочего пространство",
"workspace_calendar_root": "Определяет корень календаря для каждого рабочего пространства",
"hide_highlight_widget": "Скрыть виджет «Акценты»",
"hide_highlight_widget": "Скрыть виджет «Выделенное»",
"is_owned_by_note": "принадлежит заметке",
"and_more": "... и ещё {{count}}.",
"app_theme": "отмечает заметки CSS, которые являются полноценными темами Trilium и, таким образом, доступны в опциях Trilium.",
@@ -750,8 +750,7 @@
},
"toc": {
"table_of_contents": "Оглавление",
"options": "Параметры",
"no_headings": "Заголовки не найдены."
"options": "Параметры"
},
"note_tree": {
"hide-archived-notes": "Скрыть архивные заметки",
@@ -1563,13 +1562,7 @@
},
"highlights_list_2": {
"options": "Параметры",
"title": "Акценты",
"modal_title": "Настроить акценты",
"menu_configure": "Настроить акценты...",
"no_highlights": "Акценты в тексте не найдены.",
"title_with_count_one": "{{count}} акцент",
"title_with_count_few": "{{count}} акцента",
"title_with_count_many": "{{count}} акцентов"
"title": "Список выделенного"
},
"include_note": {
"dialog_title": "Вставить заметку",
@@ -1762,15 +1755,15 @@
"enable_tray": "Включить отображение иконки в системном трее (чтобы изменения вступили в силу, необходимо перезапустить Trilium)"
},
"highlights_list": {
"title": "Акценты",
"title": "Список выделенного",
"bold": "Жирный текст",
"italic": "Наклонный текст",
"underline": "Подчеркнутый текст",
"color": "Цветной текст",
"description": "Вы можете настроить список акцентов, отображаемый на правой панели:",
"description": "Вы можете настроить список выделенного, отображаемый на правой панели:",
"bg_color": "Текст с заливкой фона",
"visibility_title": "Видимость списка акцентов",
"visibility_description": "Вы можете скрыть виджет списка акцентов, добавив атрибут #hideHighlightWidget к заметке.",
"visibility_title": "Видимость списка выделений",
"visibility_description": "Вы можете скрыть виджет списка выделенного, добавив атрибут #hideHighlightWidget к заметке.",
"shortcut_info": "Вы можете настроить сочетание клавиш для быстрого переключения правой панели (включая список выделенного) в меню Параметры -> Сочетания клавиш (название \"toggleRightPane\")."
},
"custom_date_time_format": {
@@ -1815,7 +1808,7 @@
"edit_this_note": "Редактировать заметку"
},
"show_highlights_list_widget_button": {
"show_highlights_list": "Показать список акцентов"
"show_highlights_list": "Показать список выделенного"
},
"zen_mode": {
"button_exit": "Покинуть режим \"дзен\""
@@ -2210,11 +2203,5 @@
},
"popup-editor": {
"maximize": "Переключить на полный редактор"
},
"right_pane": {
"custom_widget_go_to_source": "Исходный код",
"toggle": "Переключить панель справа",
"empty_button": "Скрыть панель",
"empty_message": "Нечего отобразить для текущей заметки"
}
}

View File

@@ -691,12 +691,7 @@
"convert_into_attachment_prompt": "確定要將筆記 '{{title}}' 轉換為父級筆記的附件嗎?",
"print_pdf": "匯出為 PDF…",
"open_note_on_server": "在伺服器上開啟筆記",
"view_revisions": "筆記歷史版本...",
"advanced": "進階",
"export_as_image": "匯出為圖片",
"export_as_image_png": "PNG (點陣)",
"export_as_image_svg": "SVG (向量)",
"note_map": "筆記地圖"
"view_revisions": "筆記歷史版本..."
},
"onclick_button": {
"no_click_handler": "按鈕元件'{{componentId}}'沒有定義點擊時的處理方式"
@@ -795,7 +790,7 @@
"file_type": "檔案類型",
"file_size": "檔案大小",
"download": "下載",
"open": "以外部程式打開",
"open": "打開",
"upload_new_revision": "上傳新版本",
"upload_success": "已上傳新檔案版本。",
"upload_failed": "新檔案版本上傳失敗。",
@@ -826,9 +821,7 @@
"note_size_info": "筆記大小提供了該筆記儲存需求的粗略估計。它考慮了筆記及其歷史的內容。",
"calculate": "計算",
"subtree_size": "(子階層大小: {{size}}, 共計 {{count}} 個筆記)",
"title": "筆記資訊",
"mime": "MIME 類型",
"show_similar_notes": "顯示相似筆記"
"title": "筆記資訊"
},
"note_map": {
"open_full": "展開顯示",
@@ -891,8 +884,7 @@
"search_parameters": "搜尋參數",
"unknown_search_option": "未知的搜尋選項 {{searchOptionName}}",
"search_note_saved": "搜尋筆記已儲存至 {{- notePathTitle}}",
"actions_executed": "已執行操作。",
"view_options": "查看選項:"
"actions_executed": "已執行操作。"
},
"similar_notes": {
"title": "相似筆記",
@@ -1511,11 +1503,7 @@
},
"highlights_list_2": {
"title": "高亮列表",
"options": "選項",
"title_with_count_one": "{{count}} 處高亮",
"modal_title": "設定高亮列表",
"menu_configure": "設定高亮列表…",
"no_highlights": "未找到高亮內容。"
"options": "選項"
},
"quick-search": {
"placeholder": "快速搜尋",
@@ -1551,13 +1539,8 @@
},
"note_title": {
"placeholder": "請輸入筆記標題...",
"created_on": "建立於 <Value />",
"last_modified": "修改於 <Value />",
"note_type_switcher_label": "從 {{type}} 切換至:",
"note_type_switcher_others": "其他筆記類型",
"note_type_switcher_templates": "模板",
"note_type_switcher_collection": "集合",
"edited_notes": "編輯過的筆記"
"created_on": "建立於 {{date}}",
"last_modified": "最後修改於 {{date}}"
},
"search_result": {
"no_notes_found": "沒有找到符合搜尋條件的筆記。",
@@ -1586,8 +1569,7 @@
},
"toc": {
"table_of_contents": "目錄",
"options": "選項",
"no_headings": "無標題。"
"options": "選項"
},
"watched_file_update_status": {
"file_last_modified": "檔案 <code class=\"file-path\"></code> 最後修改時間為 <span class=\"file-last-modified\"></span>。",
@@ -1961,9 +1943,8 @@
"unknown_widget": "未知元件:\"{{id}}\"。"
},
"note_language": {
"not_set": "設定語言",
"configure-languages": "設定語言…",
"help-on-languages": "設定內容語言說明…"
"not_set": "設定",
"configure-languages": "設定語言…"
},
"content_language": {
"title": "內文語言",
@@ -2030,7 +2011,7 @@
"book_properties_config": {
"hide-weekends": "隱藏週末",
"display-week-numbers": "顯示週數",
"map-style": "地圖樣式",
"map-style": "地圖樣式",
"max-nesting-depth": "最大嵌套深度:",
"raster": "柵格",
"vector_light": "向量(淺色)",
@@ -2087,19 +2068,14 @@
"next_theme_title": "試用新 Trilium 主題",
"next_theme_message": "您正在使用舊版主題,要試用新主題嗎?",
"next_theme_button": "試用新主題",
"dismiss": "關閉",
"new_layout_title": "新版面配置",
"new_layout_button": "更多資訊"
"dismiss": "關閉"
},
"settings": {
"related_settings": "相關設定"
},
"settings_appearance": {
"related_code_blocks": "文字筆記中程式碼區塊的配色方案",
"related_code_notes": "程式碼筆記的配色方案",
"ui": "使用者介面",
"ui_old_layout": "舊版面配置",
"ui_new_layout": "新版面配置"
"related_code_notes": "程式碼筆記的配色方案"
},
"units": {
"percentage": "%"
@@ -2159,40 +2135,6 @@
"read_only_explicit": "唯讀",
"read_only_auto": "自動唯讀",
"shared_publicly": "公開分享",
"shared_locally": "本地分享",
"read_only_explicit_description": "此筆記已被手動設定為唯讀。\n點擊以臨時編輯。",
"read_only_temporarily_disabled": "臨時編輯",
"shared_copy_to_clipboard": "複製連結至剪貼簿",
"shared_open_in_browser": "在瀏覽器中打開連結",
"shared_unshare": "取消分享",
"clipped_note": "網頁擷取",
"execute_script": "運行腳本",
"execute_sql": "運行 SQL"
},
"breadcrumb": {
"hoisted_badge": "聚焦",
"hoisted_badge_title": "取消聚焦",
"workspace_badge": "工作空間",
"scroll_to_top_title": "跳轉至筆記開頭",
"create_new_note": "新增子筆記",
"empty_hide_archived_notes": "隱藏已歸檔的筆記"
},
"status_bar": {
"language_title": "更改內容語言",
"note_info_title": "查看筆記資訊(如日期、筆記大小)",
"backlinks_one": "{{count}} 個反連結",
"backlinks_title_one": "查看反連結",
"attachments_one": "{{count}} 個附件",
"attachments_title_one": "在新分頁中查看附件",
"attributes_one": "{{count}} 個屬性",
"attributes_title": "自有屬性及繼承屬性",
"note_paths_one": "{{count}} 條路徑",
"note_paths_title": "筆記路徑",
"code_note_switcher": "更改語言模式"
},
"right_pane": {
"empty_button": "隱藏面板",
"toggle": "切換右側面板",
"custom_widget_go_to_source": "跳轉至原始碼"
"shared_locally": "本地分享"
}
}

View File

@@ -46,19 +46,6 @@
overflow: hidden;
display: block;
flex-shrink: 2;
font-weight: normal;
}
}
.icon-action {
font-size: .9rem !important;
.bxs-chevron-right {
transform: translateY(8%);
&::before {
opacity: .75;
}
}
}
@@ -85,15 +72,6 @@
color: var(--custom-color, inherit) !important;
}
.dropdown .breadcrumb-child-list {
/* Icon */
li > span:first-child {
opacity: .75;
padding-inline-end: 4px;
translate: none;
};
}
a.breadcrumb-last-item,
a.breadcrumb-last-item:visited {
text-decoration: none;

View File

@@ -189,11 +189,10 @@ interface BreadcrumbSeparatorProps {
function BreadcrumbSeparator(props: BreadcrumbSeparatorProps) {
return (
<Dropdown
text={<Icon icon="bx bxs-chevron-right" />}
text={<Icon icon="bx bx-chevron-right" />}
noSelectButtonStyle
buttonClassName="icon-action"
hideToggleArrow
dropdownContainerClassName="tn-dropdown-menu-scrollable"
dropdownOptions={{ popperConfig: { strategy: "fixed", placement: "top" } }}
>
<BreadcrumbSeparatorDropdownContent {...props} />

View File

@@ -1,15 +1,15 @@
.component.status-bar {
contain: none;
border-top: 1px solid var(--main-border-color);
background-color: var(--left-pane-background-color);
> .status-bar-main-row {
min-height: 28px;
display: flex;
align-items: center;
background-color: var(--left-pane-background-color);
padding-inline: 0.25em;
font-size: 0.85em;
> .breadcrumb {
flex-grow: 1;
--icon-button-size: 23px;
@@ -155,6 +155,11 @@
}
}
.dropdown-code-note-switcher {
max-height: 90vh;
overflow: scroll;
}
.backlinks-widget > .dropdown-menu {
--menu-padding-size: .9em;
@@ -243,82 +248,16 @@
> .attribute-list {
font-size: 0.9em;
padding: 0.5em 0.75em;
.attributes-panel-label {
opacity: .5;
margin-inline-end: 4px;
font-weight: 600;
.inherited-attributes-widget > div {
padding: 0;
font-size: 0.9em;
}
.inherited-attributes-widget {
display: inline;
> div {
display: inline;
padding: 0;
}
}
.attribute-list-editor-wrapper {
display: flex;
flex-direction: column-reverse;
padding-bottom: 0 !important;
.attribute-list-editor {
padding-block: 0 !important;
padding-inline: 0 100px !important ;
}
.attribute-errors {
padding: 4px 0;
color: var(--dropdown-item-icon-destructive-color);
font-style: italic;
}
.ck.ck-editor__editable::after {
/* Remove a hidden spinner that causes overflow */
display: none;
}
}
}
div.similar-notes-widget div.similar-notes-wrapper {
max-height: unset;
}
button.select-button:not(:focus-visible) {
outline: none;
}
}
.bottom-panel {
margin: 0 !important;
padding: 0;
.bottom-panel-title-bar {
display: flex;
padding: 6px 12px;
background: var(--bottom-panel-title-bar-background-color);
justify-content: space-between;
align-items: center;
.bottom-panel-title-bar-caption {
text-transform: uppercase;
letter-spacing: .3pt;
font-weight: 600;
font-size: .85em;
.attribute-list-editor {
padding: 0 !important;
}
}
.bottom-panel-content {
border-bottom: 1px solid var(--main-border-color);
background: var(--bottom-panel-background-color);
padding: 8px 12px;
max-height: 40vh;
overflow-y: auto;
}
}

View File

@@ -266,15 +266,11 @@ function NoteInfoValue({ text, title, value }: { text: string; title?: string, v
);
}
function SimilarNotesPane({ note, similarNotesShown, setSimilarNotesShown }: NoteInfoContext) {
function SimilarNotesPane({ note, similarNotesShown }: NoteInfoContext) {
return (similarNotesShown &&
<BottomPanel title={t("similar_notes.title")}
className="similar-notes-pane"
visible={similarNotesShown}
setVisible={setSimilarNotesShown}
scrollable>
<div className="similar-notes-pane">
<SimilarNotesTab note={note} />
</BottomPanel>
</div>
);
}
//#endregion
@@ -371,20 +367,15 @@ function AttributesPane({ note, noteContext, attributesShown, setAttributesShown
}), [ api ]));
return (context &&
<BottomPanel title={t("attributes_panel.title")}
className="attribute-list"
visible={attributesShown}
setVisible={setAttributesShown}>
<span class="attributes-panel-label">{t("inherited_attribute_list.title")}</span>
<InheritedAttributesTab {...context} emptyListString="inherited_attribute_list.none" />
<div className={clsx("attribute-list", !attributesShown && "hidden-ext")}>
<InheritedAttributesTab {...context} />
<AttributeEditor
{...context}
api={api}
ntxId={noteContext.ntxId}
/>
</BottomPanel>
</div>
);
}
//#endregion
@@ -431,7 +422,7 @@ function CodeNoteSwitcher({ note }: StatusBarContext) {
icon="bx bx-code-curly"
text={correspondingMimeType?.title}
title={t("status_bar.code_note_switcher")}
dropdownContainerClassName="dropdown-code-note-switcher tn-dropdown-menu-scrollable"
dropdownContainerClassName="dropdown-code-note-switcher"
>
<NoteTypeCodeNoteList
currentMimeType={currentNoteMime}
@@ -448,26 +439,3 @@ function CodeNoteSwitcher({ note }: StatusBarContext) {
);
}
//#endregion
//#region Bottom panel
interface BottomPanelParams {
children: ComponentChildren;
title: string;
visible: boolean;
setVisible?: (visible: boolean) => void;
className?: string;
}
function BottomPanel({ children, title, visible, setVisible, className }: BottomPanelParams) {
return <div className={clsx("bottom-panel", className, {"hidden-ext": !visible})}>
<div className="bottom-panel-title-bar">
<span className="bottom-panel-title-bar-caption">{title}</span>
<button class="icon-action bx bx-x" onClick={() => setVisible?.(false)}></button>
</div>
<div class={clsx("bottom-panel-content")}>
{children}
</div>
</div>
}
//#endregion

View File

@@ -9,11 +9,7 @@ import RawHtml from "../react/RawHtml";
import { joinElements } from "../react/react_utils";
import AttributeDetailWidget from "../attribute_widgets/attribute_detail";
type InheritedAttributesTabArgs = Pick<TabContext, "note" | "componentId"> & {
emptyListString?: string;
}
export default function InheritedAttributesTab({ note, componentId, emptyListString }: InheritedAttributesTabArgs) {
export default function InheritedAttributesTab({ note, componentId }: Pick<TabContext, "note" | "componentId">) {
const [ inheritedAttributes, setInheritedAttributes ] = useState<FAttribute[]>();
const [ attributeDetailWidgetEl, attributeDetailWidget ] = useLegacyWidget(() => new AttributeDetailWidget());
@@ -67,7 +63,7 @@ export default function InheritedAttributesTab({ note, componentId, emptyListStr
/>
)), " ")
) : (
<>{t(emptyListString ?? "inherited_attribute_list.no_inherited_attributes")}</>
<>{t("inherited_attribute_list.no_inherited_attributes")}</>
)}
</div>

View File

@@ -283,7 +283,6 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI
return (
<>
{!hidden && <div
className="attribute-list-editor-wrapper"
ref={wrapperRef}
style="position: relative; padding-top: 10px; padding-bottom: 10px"
onKeyDown={(e) => {
@@ -297,107 +296,106 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI
setTimeout(() => save(), 100);
}
}}
> <div style="position: relative;">
<CKEditor
apiRef={editorRef}
className="attribute-list-editor"
tabIndex={200}
editor={CKEditorAttributeEditor}
currentValue={currentValue}
config={{
toolbar: { items: [] },
placeholder: t("attribute_editor.placeholder"),
mention: { feeds: mentionSetup },
licenseKey: "GPL",
language: "en"
}}
onChange={(currentValue) => {
currentValueRef.current = currentValue ?? "";
>
<CKEditor
apiRef={editorRef}
className="attribute-list-editor"
tabIndex={200}
editor={CKEditorAttributeEditor}
currentValue={currentValue}
config={{
toolbar: { items: [] },
placeholder: t("attribute_editor.placeholder"),
mention: { feeds: mentionSetup },
licenseKey: "GPL",
language: "en"
}}
onChange={(currentValue) => {
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 && clickIndex > attr.startIndex && attr.endIndex && 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");
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 && clickIndex > attr.startIndex && attr.endIndex && 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
/>
<div className="attribute-editor-buttons">
{ needsSaving && <ActionButton
icon="bx bx-save"
className="save-attributes-button tn-tool-button"
text={escapeQuotes(t("attribute_editor.save_attributes"))}
onClick={save}
/> }
<ActionButton
icon="bx bx-plus"
className="add-new-attribute-button tn-tool-button"
text={escapeQuotes(t("attribute_editor.add_a_new_attribute"))}
onClick={(e) => {
// Prevent automatic hiding of the context menu due to the button being clicked.
e.stopPropagation();
contextMenu.show<AttributeCommandNames>({
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)
});
}}
onKeyDown={() => attributeDetailWidget.hide()}
onBlur={() => save()}
onInitialized={() => editorRef.current?.focus()}
disableNewlines disableSpellcheck
/>
<div className="attribute-editor-buttons">
{ needsSaving && <ActionButton
icon="bx bx-save"
className="save-attributes-button tn-tool-button"
text={escapeQuotes(t("attribute_editor.save_attributes"))}
onClick={save}
/> }
<ActionButton
icon="bx bx-plus"
className="add-new-attribute-button tn-tool-button"
text={escapeQuotes(t("attribute_editor.add_a_new_attribute"))}
onClick={(e) => {
// Prevent automatic hiding of the context menu due to the button being clicked.
e.stopPropagation();
contextMenu.show<AttributeCommandNames>({
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)
});
}}
/>
</div>
</div>
{ error && (

View File

@@ -82,7 +82,7 @@
"toggle-note-paths": "Перейти к путям заметки",
"toggle-similar-notes": "Перейти к похожим заметкам",
"other": "Прочее",
"toggle-right-pane": "Включить/выключить отображение правой панели, которая включает оглавление и акценты",
"toggle-right-pane": "Включить/выключить отображение правой панели, которая включает оглавление и выделенные фрагменты",
"print-active-note": "Распечатать активную заметку",
"open-note-externally": "Открыть заметку как файл с помощью приложения по умолчанию",
"render-active-note": "Отрендерить (повторно отрендерить) активную заметку",

View File

@@ -108,7 +108,7 @@ function loginSync(req: Request) {
const givenHash = req.body.hash;
if (expectedHash !== givenHash) {
if (!utils.constantTimeCompare(expectedHash, givenHash)) {
return [400, { message: "Sync login credentials are incorrect. It looks like you're trying to sync two different initialized documents which is not possible." }];
}

View File

@@ -1,3 +1,4 @@
import crypto from "crypto";
import utils from "../services/utils.js";
import optionService from "../services/options.js";
import myScryptService from "../services/encryption/my_scrypt.js";
@@ -160,7 +161,11 @@ function verifyPassword(submittedPassword: string) {
const guess_hashed = myScryptService.getVerificationHash(submittedPassword);
return guess_hashed.equals(hashed_password);
// Use constant-time comparison to prevent timing attacks
if (hashed_password.length !== guess_hashed.length) {
return false;
}
return crypto.timingSafeEqual(guess_hashed, hashed_password);
}
function sendLoginError(req: Request, res: Response, errorType: 'password' | 'totp' = 'password') {

View File

@@ -1,5 +1,5 @@
import myScryptService from "./my_scrypt.js";
import utils from "../utils.js";
import utils, { constantTimeCompare } from "../utils.js";
import dataEncryptionService from "./data_encryption.js";
import sql from "../sql.js";
import sqlInit from "../sql_init.js";
@@ -87,8 +87,7 @@ function verifyOpenIDSubjectIdentifier(subjectIdentifier: string) {
return undefined;
}
console.log("Matches: " + givenHash === savedHash);
return givenHash === savedHash;
return constantTimeCompare(givenHash, savedHash as string);
}
function setDataKey(

View File

@@ -1,6 +1,6 @@
import optionService from "../options.js";
import myScryptService from "./my_scrypt.js";
import { toBase64 } from "../utils.js";
import { toBase64, constantTimeCompare } from "../utils.js";
import dataEncryptionService from "./data_encryption.js";
function verifyPassword(password: string) {
@@ -12,7 +12,7 @@ function verifyPassword(password: string) {
return false;
}
return givenPasswordHash === dbPasswordHash;
return constantTimeCompare(givenPasswordHash, dbPasswordHash);
}
function setDataKey(password: string, plainTextDataKey: string | Buffer) {

View File

@@ -1,6 +1,7 @@
import crypto from 'crypto';
import optionService from '../options.js';
import sql from '../sql.js';
import { constantTimeCompare } from '../utils.js';
function isRecoveryCodeSet() {
return optionService.getOptionBool('encryptedRecoveryCodes');
@@ -55,13 +56,22 @@ function verifyRecoveryCode(recoveryCodeGuess: string) {
const recoveryCodes = getRecoveryCodes();
let loginSuccess = false;
recoveryCodes.forEach((recoveryCode) => {
if (recoveryCodeGuess === recoveryCode) {
removeRecoveryCode(recoveryCode);
let matchedCode: string | null = null;
// Check ALL codes to prevent timing attacks - do not short-circuit
for (const recoveryCode of recoveryCodes) {
if (constantTimeCompare(recoveryCodeGuess, recoveryCode)) {
matchedCode = recoveryCode;
loginSuccess = true;
return;
// Continue checking all codes to maintain constant time
}
});
}
// Remove the matched code only after checking all codes
if (matchedCode) {
removeRecoveryCode(matchedCode);
}
return loginSuccess;
}

View File

@@ -1,6 +1,6 @@
import optionService from "../options.js";
import myScryptService from "./my_scrypt.js";
import { randomSecureToken, toBase64 } from "../utils.js";
import { randomSecureToken, toBase64, constantTimeCompare } from "../utils.js";
import dataEncryptionService from "./data_encryption.js";
import type { OptionNames } from "@triliumnext/commons";
@@ -18,7 +18,7 @@ function verifyTotpSecret(secret: string): boolean {
return false;
}
return givenSecretHash === dbSecretHash;
return constantTimeCompare(givenSecretHash, dbSecretHash);
}
function setTotpSecret(secret: string) {

View File

@@ -1,5 +1,5 @@
import becca from "../becca/becca.js";
import { fromBase64, randomSecureToken } from "./utils.js";
import { fromBase64, randomSecureToken, constantTimeCompare } from "./utils.js";
import BEtapiToken from "../becca/entities/betapi_token.js";
import crypto from "crypto";
@@ -83,15 +83,16 @@ function isValidAuthHeader(auth: string | undefined) {
return false;
}
return etapiToken.tokenHash === authTokenHash;
return constantTimeCompare(etapiToken.tokenHash, authTokenHash);
} else {
// Check ALL tokens to prevent timing attacks - do not short-circuit
let isValid = false;
for (const etapiToken of becca.getEtapiTokens()) {
if (etapiToken.tokenHash === authTokenHash) {
return true;
if (constantTimeCompare(etapiToken.tokenHash, authTokenHash)) {
isValid = true;
}
}
return false;
return isValid;
}
}

View File

@@ -74,6 +74,36 @@ export function hmac(secret: any, value: any) {
return hmac.digest("base64");
}
/**
* Constant-time string comparison to prevent timing attacks.
* Uses crypto.timingSafeEqual to ensure comparison time is independent
* of how many characters match.
*
* @param a First string to compare
* @param b Second string to compare
* @returns true if strings are equal, false otherwise
* @note Returns false for null/undefined/non-string inputs. Empty strings are considered equal.
*/
export function constantTimeCompare(a: string | null | undefined, b: string | null | undefined): boolean {
// Handle null/undefined/non-string cases safely
if (typeof a !== "string" || typeof b !== "string") {
return false;
}
const bufA = Buffer.from(a, "utf-8");
const bufB = Buffer.from(b, "utf-8");
// If lengths differ, we still do a constant-time comparison
// to avoid leaking length information through timing
if (bufA.length !== bufB.length) {
// Compare bufA against itself to maintain constant time behavior
crypto.timingSafeEqual(bufA, bufA);
return false;
}
return crypto.timingSafeEqual(bufA, bufB);
}
export function hash(text: string) {
text = text.normalize();
@@ -486,6 +516,7 @@ function slugify(text: string) {
export default {
compareVersions,
constantTimeCompare,
crash,
envToBoolean,
escapeHtml,

View File

@@ -1,35 +0,0 @@
{
"get-started": {
"title": "Започнете тук",
"desktop_title": "Свалете десктоп апликацията (v{{version}})",
"architecture": "Архитектура:",
"older_releases": "Вижте по-стари версии",
"server_title": "Конфигурирайте сървър за достъп от различни устройства"
},
"hero_section": {
"title": "Организирайте Вашите идеи. Създайте Вашата лична база от знания.",
"subtitle": "Trilium е решение с отворен код за създаване на бележки и организация на лична база от знания. Изполвайте приложението на Вашия десктоп, или го синхоранизирайте чрез сървар хостнат от Вас за да имате дотъп до бележките си навсякъде.",
"get_started": "Започнете тук",
"github": "GitHub",
"screenshot_alt": "Скриншот от Trilium Notes десктоп програмата"
},
"organization_benefits": {
"title": "Организация",
"note_structure_title": "Структура на бележката",
"note_structure_description": "Бележките може да бъдат подредени йерархично. Няма нужа от папки, понеже всяка бележка може да съдържа под-бележка. Една бележка може да бъде добавена на няколко места в йерархията.",
"attributes_title": "Етикети и връзки на бележката",
"attributes_description": "Използвайте връзки между бележките или добавете етикети за по-лесна кетегоризация. Изплозвайте избрани атрибуте за да въведете стуктурирана информация, която може да бъде използвана в таблици, табла.",
"hoisting_title": "Работни плотове",
"hoisting_description": "Лесно разделяйте лични от работни бележки като ги групирате в работен плот, който ще накара дървото от бележки да показва само специфичен сет от бележки."
},
"productivity_benefits": {
"title": "Продуктивност и безопасност",
"revisions_title": "Ревизии на бележката",
"revisions_content": "Бележките периодично се запазват и ревизиите може да се ползват за ревю или за да се отмени нежелана промяна. Ревизиите също могат да бъдат създавани ръчно.",
"sync_title": "Синхронизация",
"sync_content": "Използвайте лично хостната или качена в клауда инстанция за да синхронизирате Вашите бележки на няколко устройства, и за да ги достъпите от мобилно устройство използвайки ПУА(Прогресивен Уеб Апп).",
"protected_notes_title": "Защитени бележки",
"protected_notes_content": "Защитете чуствителна лична информация като криптирате съобщенията и ги заключите с парола.",
"jump_to_title": "Бързо търсене и команди"
}
}

View File

@@ -125,11 +125,5 @@
"geomap_description": "커스터마이징이 가능한 마커로 휴가를 계획하거나 관심 지점을 지도에 직접 표시하세요. 기록된 GPX 트랙을 표시하여 여정을 추적할 수도 있습니다.",
"presentation_title": "프레젠테이션",
"presentation_description": "슬라이드에 정보를 정리하고, 매끄러운 전환 효과와 함께 전체 화면으로 발표하세요. 슬라이드를 PDF로 내보내 간편하게 공유할 수도 있습니다."
},
"faq": {
"mobile_question": "모바일 앱이 있나요?",
"mobile_answer": "현재 공식적인 모바일 앱은 없습니다. 하지만, 서버 인스턴스를 가지고 있다면 웹 브라우저를 이용해 접근하거나 PWA로 설치할 수 있습니다. 안드로이드에는 (데스크탑 클라이언트처럼)오프라인에서도 작동하는 TriliumDroid라는 비공식 앱이 있습니다.",
"database_question": "어디에 데이터가 저장되나요?",
"server_question": "Trilium을 사용하기 위해 서버가 필요한가요?"
}
}

337
docs/README-bg.md vendored
View File

@@ -1,337 +0,0 @@
<div align="center">
<sup>Special thanks to:</sup><br />
<a href="https://go.warp.dev/Trilium" target="_blank">
<img alt="Warp sponsorship" width="400" src="https://github.com/warpdotdev/brand-assets/blob/main/Github/Sponsor/Warp-Github-LG-03.png"><br />
Warp, built for coding with multiple AI agents<br />
</a>
<sup>Available for macOS, Linux and Windows</sup>
</div>
<hr />
# Trilium Notes
![GitHub Sponsors](https://img.shields.io/github/sponsors/eliandoran)
![LiberaPay patrons](https://img.shields.io/liberapay/patrons/ElianDoran)\
![Docker Pulls](https://img.shields.io/docker/pulls/triliumnext/trilium)
![GitHub Downloads (all assets, all
releases)](https://img.shields.io/github/downloads/triliumnext/trilium/total)\
[![RelativeCI](https://badges.relative-ci.com/badges/Di5q7dz9daNDZ9UXi0Bp?branch=develop)](https://app.relative-ci.com/projects/Di5q7dz9daNDZ9UXi0Bp)
[![Translation
status](https://hosted.weblate.org/widget/trilium/svg-badge.svg)](https://hosted.weblate.org/engage/trilium/)
<!-- translate:off -->
<!-- LANGUAGE SWITCHER -->
[Chinese (Simplified Han script)](./README-ZH_CN.md) | [Chinese (Traditional Han
script)](./README-ZH_TW.md) | [English](../README.md) | [French](./README-fr.md)
| [German](./README-de.md) | [Greek](./README-el.md) | [Italian](./README-it.md)
| [Japanese](./README-ja.md) | [Romanian](./README-ro.md) |
[Spanish](./README-es.md)
<!-- translate:on -->
Trilium Notes is a free and open-source, cross-platform hierarchical note taking
application with focus on building large personal knowledge bases.
<img src="./app.png" alt="Trilium Screenshot" width="1000">
## ⏬ Download
- [Latest release](https://github.com/TriliumNext/Trilium/releases/latest)
stable version, recommended for most users.
- [Nightly build](https://github.com/TriliumNext/Trilium/releases/tag/nightly)
unstable development version, updated daily with the latest features and
fixes.
## 📚 Documentation
**Visit our comprehensive documentation at
[docs.triliumnotes.org](https://docs.triliumnotes.org/)**
Our documentation is available in multiple formats:
- **Online Documentation**: Browse the full documentation at
[docs.triliumnotes.org](https://docs.triliumnotes.org/)
- **In-App Help**: Press `F1` within Trilium to access the same documentation
directly in the application
- **GitHub**: Navigate through the [User Guide](./User%20Guide/User%20Guide/) in
this repository
### Quick Links
- [Getting Started Guide](https://docs.triliumnotes.org/)
- [Installation Instructions](https://docs.triliumnotes.org/user-guide/setup)
- [Docker
Setup](https://docs.triliumnotes.org/user-guide/setup/server/installation/docker)
- [Upgrading
TriliumNext](https://docs.triliumnotes.org/user-guide/setup/upgrading)
- [Basic Concepts and
Features](https://docs.triliumnotes.org/user-guide/concepts/notes)
- [Patterns of Personal Knowledge
Base](https://docs.triliumnotes.org/user-guide/misc/patterns-of-personal-knowledge)
## 🎁 Features
* Notes can be arranged into arbitrarily deep tree. Single note can be placed
into multiple places in the tree (see
[cloning](https://docs.triliumnotes.org/user-guide/concepts/notes/cloning))
* Rich WYSIWYG note editor including e.g. tables, images and
[math](https://docs.triliumnotes.org/user-guide/note-types/text) with markdown
[autoformat](https://docs.triliumnotes.org/user-guide/note-types/text/markdown-formatting)
* Support for editing [notes with source
code](https://docs.triliumnotes.org/user-guide/note-types/code), including
syntax highlighting
* Fast and easy [navigation between
notes](https://docs.triliumnotes.org/user-guide/concepts/navigation/note-navigation),
full text search and [note
hoisting](https://docs.triliumnotes.org/user-guide/concepts/navigation/note-hoisting)
* Seamless [note
versioning](https://docs.triliumnotes.org/user-guide/concepts/notes/note-revisions)
* Note
[attributes](https://docs.triliumnotes.org/user-guide/advanced-usage/attributes)
can be used for note organization, querying and advanced
[scripting](https://docs.triliumnotes.org/user-guide/scripts)
* UI available in English, German, Spanish, French, Romanian, and Chinese
(simplified and traditional)
* Direct [OpenID and TOTP
integration](https://docs.triliumnotes.org/user-guide/setup/server/mfa) for
more secure login
* [Synchronization](https://docs.triliumnotes.org/user-guide/setup/synchronization)
with self-hosted sync server
* there are [3rd party services for hosting synchronisation
server](https://docs.triliumnotes.org/user-guide/setup/server/cloud-hosting)
* [Sharing](https://docs.triliumnotes.org/user-guide/advanced-usage/sharing)
(publishing) notes to public internet
* Strong [note
encryption](https://docs.triliumnotes.org/user-guide/concepts/notes/protected-notes)
with per-note granularity
* Sketching diagrams, based on [Excalidraw](https://excalidraw.com/) (note type
"canvas")
* [Relation
maps](https://docs.triliumnotes.org/user-guide/note-types/relation-map) and
[note/link maps](https://docs.triliumnotes.org/user-guide/note-types/note-map)
for visualizing notes and their relations
* Mind maps, based on [Mind Elixir](https://docs.mind-elixir.com/)
* [Geo maps](https://docs.triliumnotes.org/user-guide/collections/geomap) with
location pins and GPX tracks
* [Scripting](https://docs.triliumnotes.org/user-guide/scripts) - see [Advanced
showcases](https://docs.triliumnotes.org/user-guide/advanced-usage/advanced-showcases)
* [REST API](https://docs.triliumnotes.org/user-guide/advanced-usage/etapi) for
automation
* Scales well in both usability and performance upwards of 100 000 notes
* Touch optimized [mobile
frontend](https://docs.triliumnotes.org/user-guide/setup/mobile-frontend) for
smartphones and tablets
* Built-in [dark
theme](https://docs.triliumnotes.org/user-guide/concepts/themes), support for
user themes
* [Evernote](https://docs.triliumnotes.org/user-guide/concepts/import-export/evernote)
and [Markdown import &
export](https://docs.triliumnotes.org/user-guide/concepts/import-export/markdown)
* [Web Clipper](https://docs.triliumnotes.org/user-guide/setup/web-clipper) for
easy saving of web content
* Customizable UI (sidebar buttons, user-defined widgets, ...)
* [Metrics](https://docs.triliumnotes.org/user-guide/advanced-usage/metrics),
along with a Grafana Dashboard.
✨ Check out the following third-party resources/communities for more TriliumNext
related goodies:
- [awesome-trilium](https://github.com/Nriver/awesome-trilium) for 3rd party
themes, scripts, plugins and more.
- [TriliumRocks!](https://trilium.rocks/) for tutorials, guides, and much more.
## ❓Why TriliumNext?
The original Trilium developer ([Zadam](https://github.com/zadam)) has
graciously given the Trilium repository to the community project which resides
at https://github.com/TriliumNext
### ⬆Migrating from Zadam/Trilium?
There are no special migration steps to migrate from a zadam/Trilium instance to
a TriliumNext/Trilium instance. Simply [install
TriliumNext/Trilium](#-installation) as usual and it will use your existing
database.
Versions up to and including
[v0.90.4](https://github.com/TriliumNext/Trilium/releases/tag/v0.90.4) are
compatible with the latest zadam/trilium version of
[v0.63.7](https://github.com/zadam/trilium/releases/tag/v0.63.7). Any later
versions of TriliumNext/Trilium have their sync versions incremented which
prevents direct migration.
## 💬 Discuss with us
Feel free to join our official conversations. We would love to hear what
features, suggestions, or issues you may have!
- [Matrix](https://matrix.to/#/#triliumnext:matrix.org) (For synchronous
discussions.)
- The `General` Matrix room is also bridged to
[XMPP](xmpp:discuss@trilium.thisgreat.party?join)
- [Github Discussions](https://github.com/TriliumNext/Trilium/discussions) (For
asynchronous discussions.)
- [Github Issues](https://github.com/TriliumNext/Trilium/issues) (For bug
reports and feature requests.)
## 🏗 Installation
### Windows / MacOS
Download the binary release for your platform from the [latest release
page](https://github.com/TriliumNext/Trilium/releases/latest), unzip the package
and run the `trilium` executable.
### Linux
If your distribution is listed in the table below, use your distribution's
package.
[![Packaging
status](https://repology.org/badge/vertical-allrepos/triliumnext.svg)](https://repology.org/project/triliumnext/versions)
You may also download the binary release for your platform from the [latest
release page](https://github.com/TriliumNext/Trilium/releases/latest), unzip the
package and run the `trilium` executable.
TriliumNext is also provided as a Flatpak, but not yet published on FlatHub.
### Browser (any OS)
If you use a server installation (see below), you can directly access the web
interface (which is almost identical to the desktop app).
Currently only the latest versions of Chrome & Firefox are supported (and
tested).
### Mobile
To use TriliumNext on a mobile device, you can use a mobile web browser to
access the mobile interface of a server installation (see below).
See issue https://github.com/TriliumNext/Trilium/issues/4962 for more
information on mobile app support.
If you prefer a native Android app, you can use
[TriliumDroid](https://apt.izzysoft.de/fdroid/index/apk/eu.fliegendewurst.triliumdroid).
Report bugs and missing features at [their
repository](https://github.com/FliegendeWurst/TriliumDroid). Note: It is best to
disable automatic updates on your server installation (see below) when using
TriliumDroid since the sync version must match between Trilium and TriliumDroid.
### Server
To install TriliumNext on your own server (including via Docker from
[Dockerhub](https://hub.docker.com/r/triliumnext/trilium)) follow [the server
installation docs](https://docs.triliumnotes.org/user-guide/setup/server).
## 💻 Contribute
### Translations
If you are a native speaker, help us translate Trilium by heading over to our
[Weblate page](https://hosted.weblate.org/engage/trilium/).
Here's the language coverage we have so far:
[![Translation
status](https://hosted.weblate.org/widget/trilium/multi-auto.svg)](https://hosted.weblate.org/engage/trilium/)
### Code
Download the repository, install dependencies using `pnpm` and then run the
server (available at http://localhost:8080):
```shell
git clone https://github.com/TriliumNext/Trilium.git
cd Trilium
pnpm install
pnpm run server:start
```
### Documentation
Download the repository, install dependencies using `pnpm` and then run the
environment required to edit the documentation:
```shell
git clone https://github.com/TriliumNext/Trilium.git
cd Trilium
pnpm install
pnpm edit-docs:edit-docs
```
### Building the Executable
Download the repository, install dependencies using `pnpm` and then build the
desktop app for Windows:
```shell
git clone https://github.com/TriliumNext/Trilium.git
cd Trilium
pnpm install
pnpm run --filter desktop electron-forge:make --arch=x64 --platform=win32
```
For more details, see the [development
docs](https://github.com/TriliumNext/Trilium/tree/main/docs/Developer%20Guide/Developer%20Guide).
### Developer Documentation
Please view the [documentation
guide](https://github.com/TriliumNext/Trilium/blob/main/docs/Developer%20Guide/Developer%20Guide/Environment%20Setup.md)
for details. If you have more questions, feel free to reach out via the links
described in the "Discuss with us" section above.
## 👏 Shoutouts
* [zadam](https://github.com/zadam) for the original concept and implementation
of the application.
* [Sarah Hussein](https://github.com/Sarah-Hussein) for designing the
application icon.
* [nriver](https://github.com/nriver) for his work on internationalization.
* [Thomas Frei](https://github.com/thfrei) for his original work on the Canvas.
* [antoniotejada](https://github.com/nriver) for the original syntax highlight
widget.
* [Dosu](https://dosu.dev/) for providing us with the automated responses to
GitHub issues and discussions.
* [Tabler Icons](https://tabler.io/icons) for the system tray icons.
Trilium would not be possible without the technologies behind it:
* [CKEditor 5](https://github.com/ckeditor/ckeditor5) - the visual editor behind
text notes. We are grateful for being offered a set of the premium features.
* [CodeMirror](https://github.com/codemirror/CodeMirror) - code editor with
support for huge amount of languages.
* [Excalidraw](https://github.com/excalidraw/excalidraw) - the infinite
whiteboard used in Canvas notes.
* [Mind Elixir](https://github.com/SSShooter/mind-elixir-core) - providing the
mind map functionality.
* [Leaflet](https://github.com/Leaflet/Leaflet) - for rendering geographical
maps.
* [Tabulator](https://github.com/olifolkerd/tabulator) - for the interactive
table used in collections.
* [FancyTree](https://github.com/mar10/fancytree) - feature-rich tree library
without real competition.
* [jsPlumb](https://github.com/jsplumb/jsplumb) - visual connectivity library.
Used in [relation
maps](https://docs.triliumnotes.org/user-guide/note-types/relation-map) and
[link
maps](https://docs.triliumnotes.org/user-guide/advanced-usage/note-map#link-map)
## 🤝 Support
Trilium is built and maintained with [hundreds of hours of
work](https://github.com/TriliumNext/Trilium/graphs/commit-activity). Your
support keeps it open-source, improves features, and covers costs such as
hosting.
Consider supporting the main developer
([eliandoran](https://github.com/eliandoran)) of the application via:
- [GitHub Sponsors](https://github.com/sponsors/eliandoran)
- [PayPal](https://paypal.me/eliandoran)
- [Buy Me a Coffee](https://buymeacoffee.com/eliandoran)
## 🔑 License
Copyright 2017-2025 zadam, Elian Doran, and other contributors
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option) any
later version.

View File

@@ -16,7 +16,7 @@
"@codemirror/lang-xml": "6.1.0",
"@codemirror/legacy-modes": "6.5.2",
"@codemirror/search": "6.5.11",
"@codemirror/view": "6.39.5",
"@codemirror/view": "6.39.4",
"@fsegurai/codemirror-theme-abcdef": "6.2.3",
"@fsegurai/codemirror-theme-abyss": "6.2.3",
"@fsegurai/codemirror-theme-android-studio": "6.2.3",

210
pnpm-lock.yaml generated
View File

@@ -330,8 +330,8 @@ importers:
specifier: 5.2.2
version: 5.2.2
'@types/tabulator-tables':
specifier: 6.3.1
version: 6.3.1
specifier: 6.3.0
version: 6.3.0
copy-webpack-plugin:
specifier: 13.0.1
version: 13.0.1(webpack@5.101.3(esbuild@0.27.2))
@@ -1220,89 +1220,89 @@ importers:
specifier: 6.5.11
version: 6.5.11
'@codemirror/view':
specifier: 6.39.5
version: 6.39.5
specifier: 6.39.4
version: 6.39.4
'@fsegurai/codemirror-theme-abcdef':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-abyss':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-android-studio':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-andromeda':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-basic-dark':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-basic-light':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-cobalt2':
specifier: 6.0.3
version: 6.0.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.0.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-forest':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-github-dark':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-github-light':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-gruvbox-dark':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-gruvbox-light':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-material-dark':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-material-light':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-monokai':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-nord':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-palenight':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-solarized-dark':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-solarized-light':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-tokyo-night-day':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-tokyo-night-storm':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-volcano':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-vscode-dark':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@fsegurai/codemirror-theme-vscode-light':
specifier: 6.2.3
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)
version: 6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)
'@replit/codemirror-indentation-markers':
specifier: 6.5.3
version: 6.5.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)
version: 6.5.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)
'@replit/codemirror-lang-nix':
specifier: 6.0.1
version: 6.0.1(@codemirror/autocomplete@6.18.6)(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/common@1.2.3)(@lezer/highlight@1.2.1)(@lezer/lr@1.4.2)
version: 6.0.1(@codemirror/autocomplete@6.18.6)(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/common@1.2.3)(@lezer/highlight@1.2.1)(@lezer/lr@1.4.2)
'@replit/codemirror-vim':
specifier: 6.3.0
version: 6.3.0(@codemirror/commands@6.10.1)(@codemirror/language@6.11.0)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)
version: 6.3.0(@codemirror/commands@6.10.1)(@codemirror/language@6.11.0)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)
'@ssddanbrown/codemirror-lang-smarty':
specifier: 1.0.0
version: 1.0.0
@@ -2100,8 +2100,8 @@ packages:
'@codemirror/theme-one-dark@6.1.2':
resolution: {integrity: sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==}
'@codemirror/view@6.39.5':
resolution: {integrity: sha512-A2MwwJB5vC0UeOKHTsB0ZX19DH3/0KMaPgz45r0wd+SRwjk8x3KvYVQ/lYHRdZXxE59H0eUea1ANPqIPxX7QTw==}
'@codemirror/view@6.39.4':
resolution: {integrity: sha512-xMF6OfEAUVY5Waega4juo1QGACfNkNF+aJLqpd8oUJz96ms2zbfQ9Gh35/tI3y8akEV31FruKfj7hBnIU/nkqA==}
'@colors/colors@1.5.0':
resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
@@ -5653,8 +5653,8 @@ packages:
'@types/supertest@6.0.3':
resolution: {integrity: sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w==}
'@types/tabulator-tables@6.3.1':
resolution: {integrity: sha512-qL05wGXVy0yfWcF8LCE9+9uSeUIpeKdgpm8YmOAPTjLd3FaoZziPOhVxIiLzEhLTFfOvbuwnaWDm4v4i87diRQ==}
'@types/tabulator-tables@6.3.0':
resolution: {integrity: sha512-/mQzrThCdSQXc2lz2SUZglIG+vWQ1sb1CEiVxw9SFGKPulaj1543zrL2qABeJIKjKPxcSgmWUyDA9e8CMaI2cQ==}
'@types/through2@2.0.41':
resolution: {integrity: sha512-ryQ0tidWkb1O1JuYvWKyMLYEtOWDqF5mHerJzKz/gQpoAaJq2l/dsMPBF0B5BNVT34rbARYJ5/tsZwLfUi2kwQ==}
@@ -15444,8 +15444,6 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-editor-multi-root@47.3.0':
dependencies:
@@ -16030,7 +16028,7 @@ snapshots:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/theme-one-dark': 6.1.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
ckeditor5: 47.3.0
'@ckeditor/ckeditor5-source-editing@47.3.0':
@@ -16216,21 +16214,21 @@ snapshots:
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/common': 1.2.3
'@codemirror/commands@6.10.1':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/common': 1.2.3
'@codemirror/commands@6.8.1':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/common': 1.2.3
'@codemirror/lang-css@6.3.1':
@@ -16248,7 +16246,7 @@ snapshots:
'@codemirror/lang-javascript': 6.2.4
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/common': 1.2.3
'@lezer/css': 1.1.11
'@lezer/html': 1.3.12
@@ -16259,7 +16257,7 @@ snapshots:
'@codemirror/language': 6.11.0
'@codemirror/lint': 6.8.5
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/common': 1.2.3
'@lezer/javascript': 1.5.1
@@ -16274,7 +16272,7 @@ snapshots:
'@codemirror/lang-html': 6.4.11
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/common': 1.2.3
'@lezer/markdown': 1.4.3
@@ -16284,7 +16282,7 @@ snapshots:
'@codemirror/lang-html': 6.4.11
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/common': 1.2.3
'@lezer/markdown': 1.4.3
@@ -16310,14 +16308,14 @@ snapshots:
'@codemirror/autocomplete': 6.18.6
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/common': 1.2.3
'@lezer/xml': 1.0.6
'@codemirror/language@6.11.0':
dependencies:
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/common': 1.2.3
'@lezer/highlight': 1.2.1
'@lezer/lr': 1.4.2
@@ -16330,13 +16328,13 @@ snapshots:
'@codemirror/lint@6.8.5':
dependencies:
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
crelt: 1.0.6
'@codemirror/search@6.5.11':
dependencies:
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
crelt: 1.0.6
'@codemirror/state@6.5.2':
@@ -16347,10 +16345,10 @@ snapshots:
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@codemirror/view@6.39.5':
'@codemirror/view@6.39.4':
dependencies:
'@codemirror/state': 6.5.2
crelt: 1.0.6
@@ -17334,172 +17332,172 @@ snapshots:
'@floating-ui/utils@0.2.9': {}
'@fsegurai/codemirror-theme-abcdef@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-abcdef@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-abyss@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-abyss@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-android-studio@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-android-studio@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-andromeda@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-andromeda@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-basic-dark@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-basic-dark@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-basic-light@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-basic-light@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-cobalt2@6.0.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-cobalt2@6.0.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-forest@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-forest@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-github-dark@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-github-dark@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-github-light@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-github-light@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-gruvbox-dark@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-gruvbox-dark@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-gruvbox-light@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-gruvbox-light@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-material-dark@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-material-dark@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-material-light@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-material-light@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-monokai@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-monokai@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-nord@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-nord@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-palenight@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-palenight@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-solarized-dark@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-solarized-dark@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-solarized-light@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-solarized-light@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-tokyo-night-day@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-tokyo-night-day@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-tokyo-night-storm@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-tokyo-night-storm@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-volcano@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-volcano@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-vscode-dark@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-vscode-dark@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fsegurai/codemirror-theme-vscode-light@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/highlight@1.2.1)':
'@fsegurai/codemirror-theme-vscode-light@6.2.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/highlight@1.2.1)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/highlight': 1.2.1
'@fullcalendar/core@6.1.19':
@@ -18935,29 +18933,29 @@ snapshots:
transitivePeerDependencies:
- ajv
'@replit/codemirror-indentation-markers@6.5.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)':
'@replit/codemirror-indentation-markers@6.5.3(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)':
dependencies:
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@replit/codemirror-lang-nix@6.0.1(@codemirror/autocomplete@6.18.6)(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)(@lezer/common@1.2.3)(@lezer/highlight@1.2.1)(@lezer/lr@1.4.2)':
'@replit/codemirror-lang-nix@6.0.1(@codemirror/autocomplete@6.18.6)(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)(@lezer/common@1.2.3)(@lezer/highlight@1.2.1)(@lezer/lr@1.4.2)':
dependencies:
'@codemirror/autocomplete': 6.18.6
'@codemirror/language': 6.11.0
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@lezer/common': 1.2.3
'@lezer/highlight': 1.2.1
'@lezer/lr': 1.4.2
'@replit/codemirror-vim@6.3.0(@codemirror/commands@6.10.1)(@codemirror/language@6.11.0)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/view@6.39.5)':
'@replit/codemirror-vim@6.3.0(@codemirror/commands@6.10.1)(@codemirror/language@6.11.0)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/view@6.39.4)':
dependencies:
'@codemirror/commands': 6.10.1
'@codemirror/language': 6.11.0
'@codemirror/search': 6.5.11
'@codemirror/state': 6.5.2
'@codemirror/view': 6.39.5
'@codemirror/view': 6.39.4
'@rolldown/binding-android-arm64@1.0.0-beta.29':
optional: true
@@ -20364,7 +20362,7 @@ snapshots:
'@types/methods': 1.1.4
'@types/superagent': 8.1.9
'@types/tabulator-tables@6.3.1': {}
'@types/tabulator-tables@6.3.0': {}
'@types/through2@2.0.41':
dependencies: