Compare commits

...

66 Commits

Author SHA1 Message Date
Elian Doran
17ba479182 chore(deps): update dependency @smithy/middleware-retry to v4.4.39 (#8906) 2026-03-06 19:01:41 +02:00
Elian Doran
a465014bbe fix(deps): update codemirror (#8885) 2026-03-06 19:01:13 +02:00
Elian Doran
5dfe253ef6 chore(deps): update imjasonh/setup-crane action to v0.5 (#8910) 2026-03-06 19:00:14 +02:00
Elian Doran
ae7ca6021f Translations update from Hosted Weblate (#8919) 2026-03-06 18:57:49 +02:00
noobhjy
c389697acd Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1676 of 1676 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2026-03-06 16:50:15 +00:00
Aleksandr Reid
c13c3e0f4a Translated using Weblate (Russian)
Currently translated at 100.0% (1676 of 1676 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2026-03-06 16:50:14 +00:00
Ulices
82c042d045 Translated using Weblate (Spanish)
Currently translated at 100.0% (1676 of 1676 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/es/
2026-03-06 16:50:14 +00:00
Aleksandr Reid
9145ba1690 Translated using Weblate (Russian)
Currently translated at 100.0% (387 of 387 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ru/
2026-03-06 16:50:13 +00:00
Marcel
d60653ee17 Translated using Weblate (German)
Currently translated at 100.0% (158 of 158 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/de/
2026-03-06 16:50:12 +00:00
Marcel
dae8613b4e Translated using Weblate (German)
Currently translated at 100.0% (1676 of 1676 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2026-03-06 16:50:12 +00:00
Aindriú Mac Giolla Eoin
2f8e2c40be Translated using Weblate (Irish)
Currently translated at 100.0% (1676 of 1676 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ga/
2026-03-06 16:50:11 +00:00
Francis C.
d85225a0dc Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1676 of 1676 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2026-03-06 16:50:11 +00:00
green
0cb66df2b2 Translated using Weblate (Japanese)
Currently translated at 100.0% (1676 of 1676 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2026-03-06 16:50:10 +00:00
Aleksandr Reid
92e0578cb6 Translated using Weblate (Russian)
Currently translated at 100.0% (158 of 158 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ru/
2026-03-06 16:50:09 +00:00
Elian Doran
2eee06786e chore(deps): update dependency lint-staged to v16.3.2 (#8908) 2026-03-06 18:50:00 +02:00
Elian Doran
19053dcb3b fix(deps): update dependency mind-elixir to v5.9.2 (#8909) 2026-03-06 18:49:24 +02:00
JYC333
e10c30c59f fix(deps): update dependency i18next to v25.8.14 (#8922) 2026-03-06 14:12:55 +00:00
Elian Doran
c356159664 fix(deps): update dependency marked to v17.0.4 (#8923) 2026-03-06 15:45:12 +02:00
Elian Doran
579be68ca1 chore(deps): update dependency electron to v40.8.0 (#8924) 2026-03-06 15:28:24 +02:00
Elian Doran
a6326a682e chore(deps): update dependency @types/node to v24.12.0 (#8934) 2026-03-06 15:27:19 +02:00
renovate[bot]
4595a3a5dd fix(deps): update dependency i18next to v25.8.14 2026-03-06 12:42:27 +00:00
renovate[bot]
ee21185e64 chore(deps): update dependency electron to v40.8.0 2026-03-06 12:39:17 +00:00
Elian Doran
6d0676c37d chore(deps): update docker/login-action action to v4 (#8925) 2026-03-06 14:38:39 +02:00
Elian Doran
1d4768a581 chore(deps): update docker/setup-qemu-action action to v4 (#8926) 2026-03-06 14:38:14 +02:00
Elian Doran
d086bb7fcb chore(deps): update dependency multer to v2.1.1 [security] (#8929) 2026-03-06 14:37:33 +02:00
Elian Doran
2607c4a32e fix(deps): update dependency react-i18next to v16.5.5 (#8936) 2026-03-06 14:37:12 +02:00
Elian Doran
624333a2ef chore(deps): update dependency express-rate-limit to v8.3.0 (#8937) 2026-03-06 14:36:43 +02:00
Elian Doran
d4acb37f21 chore(deps): update dependency ejs to v5 (#8938) 2026-03-06 14:36:24 +02:00
Elian Doran
6c1a1e9812 chore(deps): update docker/build-push-action action to v7 (#8939) 2026-03-06 13:19:16 +02:00
Elian Doran
9a13641f9b chore(deps): update docker/metadata-action action to v6 (#8940) 2026-03-06 13:18:33 +02:00
renovate[bot]
699e0624c9 chore(deps): update docker/setup-qemu-action action to v4 2026-03-06 06:58:29 +00:00
renovate[bot]
47ceb0d4d2 chore(deps): update docker/metadata-action action to v6 2026-03-06 06:58:27 +00:00
renovate[bot]
15c42f4a09 chore(deps): update docker/login-action action to v4 2026-03-06 06:58:24 +00:00
renovate[bot]
bf8401bb26 chore(deps): update docker/build-push-action action to v7 2026-03-06 06:58:21 +00:00
renovate[bot]
f234433c63 chore(deps): update dependency ejs to v5 2026-03-06 06:58:18 +00:00
renovate[bot]
1b70101123 chore(deps): update imjasonh/setup-crane action to v0.5 2026-03-06 06:57:50 +00:00
renovate[bot]
d610c63c28 chore(deps): update dependency express-rate-limit to v8.3.0 2026-03-06 06:57:17 +00:00
renovate[bot]
5e820a407f chore(deps): update dependency @types/node to v24.12.0 2026-03-06 06:56:18 +00:00
renovate[bot]
62610979b7 fix(deps): update dependency react-i18next to v16.5.5 2026-03-06 06:55:50 +00:00
renovate[bot]
700e99e854 fix(deps): update dependency mind-elixir to v5.9.2 2026-03-06 06:55:19 +00:00
renovate[bot]
7767116b3d fix(deps): update dependency marked to v17.0.4 2026-03-06 06:54:40 +00:00
renovate[bot]
0206e8247b fix(deps): update codemirror 2026-03-06 06:52:48 +00:00
renovate[bot]
5476fe3df9 chore(deps): update dependency lint-staged to v16.3.2 2026-03-06 06:50:46 +00:00
renovate[bot]
d9a4581d37 chore(deps): update dependency @smithy/middleware-retry to v4.4.39 2026-03-06 06:49:46 +00:00
renovate[bot]
8d9c888481 chore(deps): update dependency multer to v2.1.1 [security] 2026-03-06 06:46:38 +00:00
Elian Doran
11e4b672d1 Fix CI test issues (#8932) 2026-03-06 08:43:51 +02:00
Elian Doran
bace3daadc Update apps/server/src/routes/session_parser.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-06 08:43:31 +02:00
Elian Doran
dee5380e60 fix(ci): sequential tests ended up run in parallel 2026-03-06 08:20:17 +02:00
Elian Doran
bc6a6fd860 Revert "test(server): reset ws module"
This reverts commit 0212398815.
2026-03-05 23:44:24 +02:00
Elian Doran
e928337fe9 test(server): adjust timeout 2026-03-05 23:40:43 +02:00
Elian Doran
432f86ea4b Revert "test(server): switch to forks with 2 max workers"
This reverts commit 4ac22678df.
2026-03-05 23:37:28 +02:00
Elian Doran
5d2daecee0 test(server): switch to forks with 6 max workers 2026-03-05 23:35:15 +02:00
Elian Doran
7c8eb311af test(server): switch to forks with 3 max workers 2026-03-05 23:31:54 +02:00
Elian Doran
4ac22678df test(server): switch to forks with 2 max workers 2026-03-05 23:25:45 +02:00
Elian Doran
5057c02176 test(server): fix errors due to database already existing 2026-03-05 22:52:26 +02:00
Elian Doran
d301e56216 refactor(server): don't set up other timers on module init 2026-03-05 22:19:04 +02:00
Elian Doran
3c22ab8c9c refactor(server): don't set up session timer on module init 2026-03-05 22:17:19 +02:00
Elian Doran
0212398815 test(server): reset ws module 2026-03-05 22:14:34 +02:00
Elian Doran
db0c515bad test(server): fake timers not restored 2026-03-05 22:11:51 +02:00
Elian Doran
9b4f8c5003 feat(ci/client): HTML output 2026-03-05 22:07:11 +02:00
Elian Doran
85d8c4c8fa feat(ci/server): HTML output 2026-03-05 22:06:46 +02:00
Elian Doran
5afab6938a test(server): reduce max workers to 1 2026-03-05 21:54:30 +02:00
Elian Doran
a437169ad5 test(server): increase hook timeout 2026-03-05 21:20:12 +02:00
Elian Doran
f632d3aeb6 Merge remote-tracking branch 'origin/main' into fix/ci 2026-03-05 21:14:57 +02:00
Elian Doran
513fffcb1a ci(dev): escape test filter 2026-03-05 21:14:21 +02:00
Elian Doran
c80bb9657c fix(mindmap): crashing on auto-switch to dark theme 2026-03-05 19:25:07 +02:00
38 changed files with 962 additions and 801 deletions

View File

@@ -40,11 +40,32 @@ jobs:
- name: Run the client-side tests
run: pnpm run --filter=client test
- name: Upload client test report
uses: actions/upload-artifact@v4
if: always()
with:
name: client-test-report
path: apps/client/test-output/vitest/html/
retention-days: 30
- name: Run the server-side tests
run: pnpm run --filter=server test
- name: Upload server test report
uses: actions/upload-artifact@v4
if: always()
with:
name: server-test-report
path: apps/server/test-output/vitest/html/
retention-days: 30
- name: Run CKEditor e2e tests
run: |
pnpm run --filter=ckeditor5-mermaid test
pnpm run --filter=ckeditor5-math test
- name: Run the rest of the tests
run: pnpm run --filter=\!client --filter=\!server test"
run: pnpm run --filter=\!client --filter=\!server --filter=\!ckeditor5-mermaid --filter=\!ckeditor5-math test
build_docker:
name: Build Docker image
@@ -69,7 +90,7 @@ jobs:
- name: Trigger server build
run: pnpm run server:build
- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v6
- uses: docker/build-push-action@v7
with:
context: apps/server
cache-from: type=gha
@@ -106,7 +127,7 @@ jobs:
uses: docker/setup-buildx-action@v3
- name: Build and export to Docker
uses: docker/build-push-action@v6
uses: docker/build-push-action@v7
with:
context: apps/server
file: apps/server/${{ matrix.dockerfile }}

View File

@@ -59,7 +59,7 @@ jobs:
run: pnpm run server:build
- name: Build and export to Docker
uses: docker/build-push-action@v6
uses: docker/build-push-action@v7
with:
context: apps/server
file: apps/server/${{ matrix.dockerfile }}
@@ -164,7 +164,7 @@ jobs:
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@v6
with:
images: ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
@@ -175,13 +175,13 @@ jobs:
latest=false
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GHCR
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ${{ env.GHCR_REGISTRY }}
username: ${{ github.actor }}
@@ -189,7 +189,7 @@ jobs:
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
uses: docker/build-push-action@v7
with:
context: apps/server
file: apps/server/${{ matrix.dockerfile }}
@@ -229,17 +229,17 @@ jobs:
run: echo "TEST_TAG=${TEST_TAG,,}" >> $GITHUB_ENV
- name: Set up crane
uses: imjasonh/setup-crane@v0.4
uses: imjasonh/setup-crane@v0.5
- name: Login to GHCR
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ${{ env.GHCR_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to DockerHub
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ${{ env.DOCKERHUB_REGISTRY }}
username: ${{ secrets.DOCKERHUB_USERNAME }}
@@ -247,7 +247,7 @@ jobs:
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@v6
with:
images: ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |

View File

@@ -47,7 +47,7 @@
"draggabilly": "3.0.0",
"force-graph": "1.51.1",
"globals": "17.4.0",
"i18next": "25.8.13",
"i18next": "25.8.14",
"i18next-http-backend": "3.0.2",
"jquery": "4.0.0",
"jquery.fancytree": "2.38.5",
@@ -57,13 +57,13 @@
"leaflet": "1.9.4",
"leaflet-gpx": "2.2.0",
"mark.js": "8.11.1",
"marked": "17.0.3",
"marked": "17.0.4",
"mermaid": "11.12.3",
"mind-elixir": "5.9.1",
"mind-elixir": "5.9.2",
"normalize.css": "8.0.1",
"panzoom": "9.4.3",
"preact": "10.28.4",
"react-i18next": "16.5.4",
"react-i18next": "16.5.5",
"react-window": "2.2.7",
"reveal.js": "5.2.1",
"rrule": "2.8.1",

View File

@@ -1535,7 +1535,8 @@
"new-feature": "新建",
"collections": "集合",
"book": "集合",
"ai-chat": "AI聊天"
"ai-chat": "AI聊天",
"spreadsheet": "电子表格"
},
"protect_note": {
"toggle-on": "保护笔记",

View File

@@ -1488,20 +1488,21 @@
"mermaid-diagram": "Mermaid Diagramm",
"canvas": "Leinwand",
"web-view": "Webansicht",
"mind-map": "Mind Map",
"mind-map": "Mindmap",
"file": "Datei",
"image": "Bild",
"launcher": "Starter",
"doc": "Dokument",
"widget": "Widget",
"confirm-change": "Es is nicht empfehlenswert den Notiz-Typ zu ändern, wenn der Inhalt der Notiz nicht leer ist. Möchtest du dennoch fortfahren?",
"confirm-change": "Es ist nicht empfehlenswert den Notiz-Typ zu ändern, wenn der Inhalt der Notiz nicht leer ist. Möchtest du dennoch fortfahren?",
"geo-map": "Geo-Karte",
"beta-feature": "Beta",
"book": "Sammlung",
"ai-chat": "KI Chat",
"ai-chat": "KI-Chat",
"task-list": "Aufgabenliste",
"new-feature": "Neu",
"collections": "Sammlungen"
"collections": "Sammlungen",
"spreadsheet": "Tabelle"
},
"protect_note": {
"toggle-on": "Notiz schützen",

View File

@@ -1548,7 +1548,8 @@
"task-list": "Lista de tareas",
"book": "Colección",
"new-feature": "Nuevo",
"collections": "Colecciones"
"collections": "Colecciones",
"spreadsheet": "Hoja de cálculo"
},
"protect_note": {
"toggle-on": "Proteger la nota",
@@ -1650,7 +1651,8 @@
},
"search_result": {
"no_notes_found": "No se han encontrado notas para los parámetros de búsqueda dados.",
"search_not_executed": "La búsqueda aún no se ha ejecutado. Dé clic en el botón «Buscar» para ver los resultados."
"search_not_executed": "La búsqueda aún no se ha ejecutado.",
"search_now": "Buscar ahora"
},
"spacer": {
"configure_launchbar": "Configurar barra de lanzamiento"

View File

@@ -1571,7 +1571,8 @@
"ai-chat": "Comhrá AI",
"task-list": "Liosta Tascanna",
"new-feature": "Nua",
"collections": "Bailiúcháin"
"collections": "Bailiúcháin",
"spreadsheet": "Scarbhileog"
},
"protect_note": {
"toggle-on": "Cosain an nóta",

View File

@@ -600,7 +600,8 @@
"task-list": "タスクリスト",
"new-feature": "New",
"collections": "コレクション",
"ai-chat": "AI チャット"
"ai-chat": "AI チャット",
"spreadsheet": "スプレッドシート"
},
"edited_notes": {
"no_edited_notes_found": "この日の編集されたノートはまだありません...",

View File

@@ -257,7 +257,7 @@
"collapseExpand": "свернуть/развернуть узел",
"notSet": "не установлено",
"goBackForwards": "назад / вперед в истории",
"showJumpToNoteDialog": "показать <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">окно \"Перейти к\"</a>",
"showJumpToNoteDialog": "Перейти к <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">\"Перейти к\" окно</a>",
"scrollToActiveNote": "прокрутка к активной заметке",
"jumpToParentNote": "переход к родительской заметке",
"collapseWholeTree": "свернуть все дерево заметок",
@@ -471,7 +471,7 @@
"calendar_root": "отмечает заметку, которая должна использоваться в качестве корневой для заметок дня. Только одна должна быть отмечена как таковая.",
"archived": "заметки с этой меткой не будут отображаться в результатах поиска по умолчанию (а также в диалоговых окнах «Перейти к», «Добавить ссылку» и т. д.).",
"exclude_from_export": "заметки (с их поддеревьями) не будут включены ни в один экспорт заметок",
"run": "определяет, при каких событиях должен запускаться скрипт. Возможные значения:\n<ul>\n<li>frontendStartup — при запуске (или обновлении) фронтенда Trilium, но не на мобильном устройстве.</li>\n<li>mobileStartup — при запуске (или обновлении) фронтенда Trilium на мобильном устройстве.</li>\n<li>backendStartup — при запуске бэкенда Trilium.</li>\n<li>hourly — запускать каждый час. Для указания времени можно использовать дополнительную метку <code>runAtHour</code>.</li>\n<li>daily — запускать раз в день.</li>\n</ul>",
"run": "определяет, при каких событиях должен запускаться скрипт. Возможные значения:<ul>\n<li>frontendStartup — при запуске (или обновлении) фронтенда Trilium, но не на мобильном устройстве.</li>\n<li>mobileStartup — при запуске (или обновлении) фронтенда Trilium на мобильном устройстве.</li>\n<li>backendStartup — при запуске бэкенда Trilium.</li>\n<li>hourly — запускать каждый час. Для указания времени можно использовать дополнительную метку <code>runAtHour</code>.</li>\n<li>daily — запускать раз в день.</li></ul>",
"run_on_instance": "Определить, на каком экземпляре Trilium это должно выполняться. По умолчанию — для всех экземпляров.",
"run_at_hour": "В какой час это должно выполняться? Следует использовать вместе с <code>#run=hourly</code>. Можно задать несколько раз для большего количества запусков в течение дня.",
"disable_inclusion": "скрипты с этой меткой не будут включены в выполнение родительского скрипта.",
@@ -594,7 +594,8 @@
"display-week-numbers": "Отображать номера недель",
"hide-weekends": "Скрыть выходные",
"raster": "Растр",
"show-scale": "Показать масштаб"
"show-scale": "Показать масштаб",
"show-labels": "Показать названия маркеров"
},
"editorfeatures": {
"note_completion_enabled": "Включить автодополнение",
@@ -782,7 +783,13 @@
"shared-indicator-tooltip": "Эта заметка опубликована",
"shared-indicator-tooltip-with-url": "Эта заметка доступно публично по адресу: {{- url}}",
"subtree-hidden-moved-description-other": "В дереве, к которому относится эта заметка, скрыты дочерние заметки.",
"subtree-hidden-moved-description-collection": "Эта коллекция скрывает свои дочерние заметки в дереве."
"subtree-hidden-moved-description-collection": "Эта коллекция скрывает свои дочерние заметки в дереве.",
"clone-indicator-tooltip": "У этой заметки {{- count}} родителей: {{- parents}}",
"clone-indicator-tooltip-single": "Эта заметка клонирована (1 дополнительный родитель: {{- parent}})",
"subtree-hidden-moved-title": "Добавлено в {{title}}",
"subtree-hidden-tooltip_one": "{{count}} дочерняя заметка скрыта",
"subtree-hidden-tooltip_few": "Скрыто {{count}} дочерних заметок",
"subtree-hidden-tooltip_many": "Скрыто {{count}} дочерних заметок"
},
"quick-search": {
"no-results": "Результаты не найдены",
@@ -826,7 +833,9 @@
"mind-map": "Mind Map",
"geo-map": "Географическая карта",
"task-list": "Список задач",
"confirm-change": "Не рекомендуется менять тип заметки, если её содержимое не пустое. Вы всё равно хотите продолжить?"
"confirm-change": "Не рекомендуется менять тип заметки, если её содержимое не пустое. Вы всё равно хотите продолжить?",
"ai-chat": "Чат с ИИ",
"spreadsheet": "Электронная таблица"
},
"tree-context-menu": {
"open-in-popup": "Быстрое редактирование",
@@ -1153,7 +1162,8 @@
"search_note_saved": "Заметка с настройкой поиска сохранена в {{- notePathTitle}}",
"unknown_search_option": "Неизвестный параметр поиска {{searchOptionName}}",
"actions_executed": "Действия выполнены.",
"view_options": "Просмотреть опции:"
"view_options": "Просмотреть опции:",
"option": "опция"
},
"ancestor": {
"depth_label": "глубина",
@@ -1403,7 +1413,8 @@
"type_text_to_filter": "Введите текст для фильтрации сочетаний клавиш...",
"reload_app": "Перезагрузить приложение, чтобы применить изменения",
"confirm_reset": "Вы действительно хотите сбросить все сочетания клавиш до значений по умолчанию?",
"set_all_to_default": "Установить все сочетания клавиш по умолчанию"
"set_all_to_default": "Установить все сочетания клавиш по умолчанию",
"no_results": "Не найдено ярлыков, соответствующих '{{filter}}'"
},
"sync_2": {
"timeout_unit": "миллисекунд",
@@ -1713,7 +1724,8 @@
"delete_this_note": "Удалить эту заметку",
"insert_child_note": "Вставить дочернюю заметку",
"note_revisions": "История изменений",
"content_language_switcher": "Язык содержимого: {{language}}"
"content_language_switcher": "Язык содержимого: {{language}}",
"backlinks": "Ссылки"
},
"svg_export_button": {
"button_title": "Экспортировать диаграмму как SVG"
@@ -1790,7 +1802,8 @@
},
"search_result": {
"no_notes_found": "По заданным параметрам поиска заметки не найдены.",
"search_not_executed": "Поиск ещё не выполнен. Нажмите кнопку «Поиск» выше, чтобы увидеть результаты."
"search_not_executed": "Поиск ещё не выполнен.",
"search_now": "Искать сейчас"
},
"empty": {
"search_placeholder": "поиск заметки по ее названию",
@@ -1988,10 +2001,12 @@
"print_report_collection_content_few": "{{count}} заметки в коллекции не удалось распечатать, поскольку они не поддерживаются или защищены.",
"print_report_collection_content_many": "{{count}} заметок в коллекции не удалось распечатать, поскольку они не поддерживаются или защищены.",
"print_report_collection_details_button": "Подробнее",
"print_report_collection_details_ignored_notes": "Пропущенные заметки"
"print_report_collection_details_ignored_notes": "Пропущенные заметки",
"print_report_error_title": "Не удалось напечатать",
"print_report_stack_trace": "Трассировка стека"
},
"book": {
"no_children_help": "В этой коллекции нет дочерних заметок, поэтому отображать нечего. Подробности см. в <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a>.",
"no_children_help": "В этой коллекции нет дочерних заметок, поэтому отображать нечего.",
"drag_locked_title": "Защищено от изменения",
"drag_locked_message": "Перетаскивание не допускается, так как коллекция защищена от редактирования."
},
@@ -2007,7 +2022,9 @@
"rendering_error": "Невозможно отобразить содержимое из-за ошибки."
},
"pagination": {
"total_notes": "{{count}} заметок"
"total_notes": "{{count}} заметок",
"prev_page": "Предыдущая страница",
"next_page": "Следующая страница"
},
"status_bar": {
"attributes_one": "{{count}} атрибут",
@@ -2137,5 +2154,49 @@
},
"platform_indicator": {
"available_on": "Доступно для {{platform}}"
},
"render": {
"setup_title": "Отобразить настраиваемый HTML или Preact JSX в этой заметке",
"setup_create_sample_preact": "Создать образец заметки с помощью Preact",
"setup_create_sample_html": "Создать образец заметки с помощью HTML",
"setup_sample_created": "Образец заметки был создан в качестве дочерней записи.",
"disabled_description": "Эти заметки для рендера поступают из внешнего источника. Чтобы защитить вас от вредоносного содержимого, они не включены по умолчанию. Убедитесь, что вы доверяете источнику до его включения.",
"disabled_button_enable": "Включить заметки для рендера"
},
"web_view_setup": {
"title": "Создайте живой просмотр веб-страницы прямо в Trilium",
"url_placeholder": "Введите или вставьте адрес сайта, например https://triliumnotes.org",
"create_button": "Создать веб-просмотр",
"invalid_url_title": "Неверный адрес",
"invalid_url_message": "Введите корректный веб-адрес, например https://triliumnotes.org.",
"disabled_description": "Этот веб-просмотр был импортирован из внешнего источника. Чтобы защитить вас от фишинга или вредоносного контента, он не загружается автоматически. Вы можете включить его, если доверяете источнику.",
"disabled_button_enable": "Включить просмотр веб-страниц"
},
"active_content_badges": {
"type_icon_pack": "Набор иконок",
"type_backend_script": "Бэкенд скрипт",
"type_frontend_script": "Фронтенд скрипт",
"type_widget": "Виджет",
"type_app_css": "Пользовательский CSS",
"type_render_note": "Заметка для рендера",
"type_web_view": "Просмотр веб-страницы",
"type_app_theme": "Пользовательская тема",
"toggle_tooltip_enable_tooltip": "Нажмите, чтобы включить этот {{type}}.",
"toggle_tooltip_disable_tooltip": "Нажмите, чтобы выключить этот {{type}}.",
"menu_docs": "Открытая документация",
"menu_execute_now": "Выполнить скрипт сейчас",
"menu_run": "Выполнять автоматически",
"menu_run_disabled": "Вручную",
"menu_run_backend_startup": "При запуске бэкенда",
"menu_run_hourly": "Ежечасно",
"menu_run_daily": "Ежедневно",
"menu_run_frontend_startup": "Когда запускается интерфейс ПК",
"menu_run_mobile_startup": "При запуске мобильного интерфейса",
"menu_change_to_widget": "Изменить виджет",
"menu_change_to_frontend_script": "Перейти к фронтенд скрипту",
"menu_theme_base": "Базовая тема"
},
"setup_form": {
"more_info": "Узнать больше"
}
}

View File

@@ -1496,7 +1496,8 @@
"task-list": "任務列表",
"new-feature": "新增",
"collections": "集合",
"ai-chat": "AI 聊天"
"ai-chat": "AI 聊天",
"spreadsheet": "試算表"
},
"protect_note": {
"toggle-on": "保護筆記",

View File

@@ -6,7 +6,7 @@ import "./MindMap.css";
import nodeMenu from "@mind-elixir/node-menu";
import { DISPLAYABLE_LOCALE_IDS } from "@triliumnext/commons";
import { snapdom } from "@zumer/snapdom";
import { default as VanillaMindElixir,MindElixirData, MindElixirInstance, Operation, Options, THEME as LIGHT_THEME, DARK_THEME } from "mind-elixir";
import { DARK_THEME, default as VanillaMindElixir, MindElixirData, MindElixirInstance, Operation, Options, THEME as LIGHT_THEME } from "mind-elixir";
import { HTMLAttributes, RefObject } from "preact";
import { useCallback, useEffect, useRef } from "preact/hooks";
@@ -154,6 +154,7 @@ function MindElixir({ containerRef: externalContainerRef, containerProps, apiRef
const apiRef = useRef<MindElixirInstance>(null);
const [ locale ] = useTriliumOption("locale");
const colorScheme = useColorScheme();
const defaultColorScheme = useRef(colorScheme);
function reinitialize() {
if (!containerRef.current) return;
@@ -162,7 +163,7 @@ function MindElixir({ containerRef: externalContainerRef, containerProps, apiRef
el: containerRef.current,
locale: LOCALE_MAPPINGS[locale as DISPLAYABLE_LOCALE_IDS] ?? undefined,
editable,
theme: LIGHT_THEME
theme: defaultColorScheme.current === "dark" ? DARK_THEME : LIGHT_THEME
});
if (editable) {
@@ -188,7 +189,11 @@ function MindElixir({ containerRef: externalContainerRef, containerProps, apiRef
if (!apiRef.current) return;
const newTheme = colorScheme === "dark" ? DARK_THEME : LIGHT_THEME;
if (apiRef.current.theme === newTheme) return; // Avoid unnecessary theme changes, which can be expensive to render.
apiRef.current.changeTheme(newTheme);
try {
apiRef.current.changeTheme(newTheme);
} catch (e) {
console.warn("Failed to change mind map theme:", e);
}
}, [ colorScheme ]);
useEffect(() => {

View File

@@ -120,7 +120,11 @@ export default defineConfig(() => ({
environment: "happy-dom",
setupFiles: [
"./src/test/setup.ts"
]
],
reporters: [
"verbose",
["html", { outputFile: "./test-output/vitest/html/index.html" }]
],
},
commonjsOptions: {
transformMixedEsModules: true,

View File

@@ -35,7 +35,7 @@
"@triliumnext/commons": "workspace:*",
"@triliumnext/server": "workspace:*",
"copy-webpack-plugin": "14.0.0",
"electron": "40.6.1",
"electron": "40.8.0",
"@electron-forge/cli": "7.11.1",
"@electron-forge/maker-deb": "7.11.1",
"@electron-forge/maker-dmg": "7.11.1",

View File

@@ -12,7 +12,7 @@
"@triliumnext/desktop": "workspace:*",
"@types/fs-extra": "11.0.4",
"copy-webpack-plugin": "14.0.0",
"electron": "40.6.1",
"electron": "40.8.0",
"fs-extra": "11.3.4"
},
"scripts": {

View File

@@ -81,15 +81,15 @@
"csrf-csrf": "3.2.2",
"debounce": "3.0.0",
"debug": "4.4.3",
"ejs": "4.0.1",
"electron": "40.6.1",
"ejs": "5.0.1",
"electron": "40.8.0",
"electron-debug": "4.1.0",
"electron-window-state": "5.0.3",
"escape-html": "1.0.3",
"express": "5.2.1",
"express-http-proxy": "2.1.2",
"express-openid-connect": "2.19.4",
"express-rate-limit": "8.2.1",
"express-rate-limit": "8.3.0",
"express-session": "1.19.0",
"file-uri-to-path": "2.0.0",
"fs-extra": "11.3.4",
@@ -98,7 +98,7 @@
"html2plaintext": "2.1.4",
"http-proxy-agent": "7.0.2",
"https-proxy-agent": "7.0.6",
"i18next": "25.8.13",
"i18next": "25.8.14",
"i18next-fs-backend": "2.6.1",
"image-type": "6.0.0",
"ini": "6.0.0",
@@ -106,9 +106,9 @@
"is-svg": "6.1.0",
"jimp": "1.6.0",
"lorem-ipsum": "2.0.8",
"marked": "17.0.3",
"marked": "17.0.4",
"mime-types": "3.0.2",
"multer": "2.1.0",
"multer": "2.1.1",
"normalize-strings": "1.1.1",
"rand-token": "1.0.1",
"safe-compare": "1.1.4",

View File

@@ -86,8 +86,9 @@ export default async function buildApp() {
app.use(`/robots.txt`, express.static(path.join(publicAssetsDir, "robots.txt")));
app.use(`/icon.png`, express.static(path.join(publicAssetsDir, "icon.png")));
const sessionParser = (await import("./routes/session_parser.js")).default;
const { default: sessionParser, startSessionCleanup } = await import("./routes/session_parser.js");
app.use(sessionParser);
startSessionCleanup();
app.use(favicon(path.join(assetsDir, isDev ? "icon-dev.ico" : "icon.ico")));
if (openID.isOpenIDEnabled())
@@ -98,16 +99,16 @@ export default async function buildApp() {
custom.register(app);
error_handlers.register(app);
// triggers sync timer
await import("./services/sync.js");
const { startSyncTimer } = await import("./services/sync.js");
startSyncTimer();
// triggers backup timer
await import("./services/backup.js");
// trigger consistency checks timer
await import("./services/consistency_checks.js");
const { startConsistencyChecks } = await import("./services/consistency_checks.js");
startConsistencyChecks();
await import("./services/scheduler.js");
const { startScheduler } = await import("./services/scheduler.js");
startScheduler();
startScheduledCleanup();

View File

@@ -156,7 +156,8 @@
"go-to-next-note-title": "К следующей заметке",
"open-today-journal-note-title": "Открыть сегодняшнюю заметку в журнале",
"zen-mode": "Режим \"Дзен\"",
"command-palette": "Открыть панель команд"
"command-palette": "Открыть панель команд",
"tab-switcher-title": "Переключатель вкладок"
},
"tray": {
"bookmarks": "Закладки",
@@ -313,7 +314,7 @@
"title": "Настройка",
"heading": "Настройка Trilium",
"new-document": "Я новый пользователь и хочу создать новый документ Trilium для своих заметок",
"sync-from-desktop": "У меня уже есть приложение ПК, и я хочу настроить синхронизацию с ним",
"sync-from-desktop": "У меня уже есть настольное приложение, и я хочу настроить синхронизацию с ним",
"sync-from-server": "У меня уже есть сервер, и я хочу настроить синхронизацию с ним",
"init-in-progress": "Идет инициализация документа",
"redirecting": "Вскоре вы будете перенаправлены на страницу приложения."
@@ -397,8 +398,8 @@
"clipped-from": "Эта заметка изначально была вырезана из {{- url}}"
},
"setup_sync-from-desktop": {
"heading": "Синхронизация с приложения ПК",
"description": "Эту настройку необходимо инициировать из приложения для ПК:",
"heading": "Синхронизация с настольной версией",
"description": "Это настройку нужно выполнить с помощью настольной версии:",
"step1": "Откройте приложение Trilium Notes на ПК.",
"step2": "В меню Trilium выберите «Параметры».",
"step3": "Нажмите на категорию «Синхронизация».",

View File

@@ -2,7 +2,7 @@ import { dayjs } from "@triliumnext/commons";
import type { Application } from "express";
import { SessionData } from "express-session";
import supertest, { type Response } from "supertest";
import { beforeAll, describe, expect, it, vi } from "vitest";
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
import cls from "../services/cls.js";
import { type SQLiteSessionStore } from "./session_parser.js";
@@ -20,6 +20,10 @@ describe("Login Route test", () => {
({ sessionStore, CLEAN_UP_INTERVAL } = (await import("./session_parser.js")));
});
afterAll(() => {
vi.useRealTimers();
});
it("should return the login page, when using a GET request", async () => {
// RegExp for login page specific string in HTML

View File

@@ -113,11 +113,13 @@ const sessionParser: express.RequestHandler = session({
store: sessionStore
});
setInterval(() => {
// Clean up expired sesions.
const now = Date.now();
const result = sql.execute(/*sql*/`DELETE FROM sessions WHERE expires < ?`, now);
console.log("Cleaning up expired sessions: ", result.changes);
}, CLEAN_UP_INTERVAL);
export function startSessionCleanup() {
setInterval(() => {
// Clean up expired sessions.
const now = Date.now();
const result = sql.execute(/*sql*/`DELETE FROM sessions WHERE expires < ?`, now);
console.log("Cleaning up expired sessions: ", result.changes);
}, CLEAN_UP_INTERVAL);
}
export default sessionParser;

View File

@@ -953,12 +953,14 @@ function runEntityChangesChecks() {
consistencyChecks.findEntityChangeIssues();
}
sqlInit.dbReady.then(() => {
setInterval(cls.wrap(runPeriodicChecks), 60 * 60 * 1000);
export function startConsistencyChecks() {
sqlInit.dbReady.then(() => {
setInterval(cls.wrap(runPeriodicChecks), 60 * 60 * 1000);
// kickoff checks soon after startup (to not block the initial load)
setTimeout(cls.wrap(runPeriodicChecks), 4 * 1000);
});
// kickoff checks soon after startup (to not block the initial load)
setTimeout(cls.wrap(runPeriodicChecks), 4 * 1000);
});
}
export default {
runOnDemandChecks,

View File

@@ -24,6 +24,7 @@ async function testImport(fileName: string, mimetype: string) {
const rootNote = becca.getNote("root");
if (!rootNote) {
reject("Missing root note.");
return;
}
const importedNote = single.importSingleFile(

View File

@@ -35,39 +35,41 @@ function runNotesWithLabel(runAttrValue: string) {
}
}
// If the database is already initialized, we need to check the hidden subtree. Otherwise, hidden subtree
// is also checked before importing the demo.zip, so no need to do it again.
if (sqlInit.isDbInitialized()) {
console.log("Checking hidden subtree.");
sqlInit.dbReady.then(() => cls.init(() => hiddenSubtreeService.checkHiddenSubtree()));
}
// Periodic checks.
sqlInit.dbReady.then(() => {
if (!process.env.TRILIUM_SAFE_MODE) {
setTimeout(
cls.wrap(() => runNotesWithLabel("backendStartup")),
10 * 1000
);
setInterval(
cls.wrap(() => runNotesWithLabel("hourly")),
3600 * 1000
);
setInterval(
cls.wrap(() => runNotesWithLabel("daily")),
24 * 3600 * 1000
);
setInterval(
cls.wrap(() => hiddenSubtreeService.checkHiddenSubtree()),
7 * 3600 * 1000
);
export function startScheduler() {
// If the database is already initialized, we need to check the hidden subtree. Otherwise, hidden subtree
// is also checked before importing the demo.zip, so no need to do it again.
if (sqlInit.isDbInitialized()) {
console.log("Checking hidden subtree.");
sqlInit.dbReady.then(() => cls.init(() => hiddenSubtreeService.checkHiddenSubtree()));
}
setInterval(() => checkProtectedSessionExpiration(), 30000);
});
// Periodic checks.
sqlInit.dbReady.then(() => {
if (!process.env.TRILIUM_SAFE_MODE) {
setTimeout(
cls.wrap(() => runNotesWithLabel("backendStartup")),
10 * 1000
);
setInterval(
cls.wrap(() => runNotesWithLabel("hourly")),
3600 * 1000
);
setInterval(
cls.wrap(() => runNotesWithLabel("daily")),
24 * 3600 * 1000
);
setInterval(
cls.wrap(() => hiddenSubtreeService.checkHiddenSubtree()),
7 * 3600 * 1000
);
}
setInterval(() => checkProtectedSessionExpiration(), 30000);
});
}
function checkProtectedSessionExpiration() {
const protectedSessionTimeout = options.getOptionInt("protectedSessionTimeout");

View File

@@ -50,7 +50,7 @@ async function initDbConnection() {
await migrationService.migrateIfNecessary();
sql.execute('CREATE TEMP TABLE "param_list" (`paramId` TEXT NOT NULL PRIMARY KEY)');
sql.execute('CREATE TEMP TABLE IF NOT EXISTS "param_list" (`paramId` TEXT NOT NULL PRIMARY KEY)');
sql.execute(`
CREATE TABLE IF NOT EXISTS "user_data"

View File

@@ -446,15 +446,17 @@ function getOutstandingPullCount() {
return outstandingPullCount;
}
becca_loader.beccaLoaded.then(() => {
setInterval(cls.wrap(sync), 60000);
export function startSyncTimer() {
becca_loader.beccaLoaded.then(() => {
setInterval(cls.wrap(sync), 60000);
// kickoff initial sync immediately, but should happen after initial consistency checks
setTimeout(cls.wrap(sync), 5000);
// kickoff initial sync immediately, but should happen after initial consistency checks
setTimeout(cls.wrap(sync), 5000);
// called just so ws.setLastSyncedPush() is called
getLastSyncedPush();
});
// called just so ws.setLastSyncedPush() is called
getLastSyncedPush();
});
}
export default {
sync,

View File

@@ -1,6 +1,6 @@
import type { Application, NextFunction,Request, Response } from "express";
import supertest from "supertest";
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { safeExtractMessageAndStackFromError } from "../services/utils.js";
@@ -23,6 +23,10 @@ describe("Share API test", () => {
});
});
afterAll(() => {
vi.useRealTimers();
});
beforeEach(() => {
cannotSetHeadersCount = 0;
});

View File

@@ -19,16 +19,18 @@ export default defineConfig(() => ({
exclude: [
"spec/build-checks/**",
],
hookTimeout: 20000,
hookTimeout: 20_000,
testTimeout: 40_000,
reporters: [
"verbose"
"verbose",
["html", { outputFile: "./test-output/vitest/html/index.html" }]
],
coverage: {
reportsDirectory: './test-output/vitest/coverage',
provider: 'v8' as const,
reporter: [ "text", "html" ]
},
pool: "vmForks",
maxWorkers: 3
pool: "forks",
maxWorkers: 6
},
}));

View File

@@ -9,12 +9,12 @@
"preview": "pnpm build && vite preview"
},
"dependencies": {
"i18next": "25.8.13",
"i18next": "25.8.14",
"i18next-http-backend": "3.0.2",
"preact": "10.28.4",
"preact-iso": "2.11.1",
"preact-render-to-string": "6.6.6",
"react-i18next": "16.5.4"
"react-i18next": "16.5.5"
},
"devDependencies": {
"@preact/preset-vite": "2.10.3",

View File

@@ -43,7 +43,7 @@
"code_title": "Code Notizen",
"canvas_title": "Leinwand",
"mermaid_title": "Mermaid Diagramm",
"mindmap_title": "Mind Map",
"mindmap_title": "Mindmap",
"text_description": "Die Notizen werden mit einem visuellen Editor (WYSIWYG) bearbeitet, der Tabellen, Bilder, mathematische Ausdrücke und Code-Blöcke mit Syntaxhervorhebung unterstützt. Formatieren Sie den Text schnell mit einer Markdown-ähnlichen Syntax oder mit Slash-Befehlen.",
"code_description": "Große Quellcode- oder Skriptdateien werden mit einem speziellen Editor bearbeitet, der Syntaxhervorhebung für viele Programmiersprachen und diverse Farbschemata bietet.",
"title": "Verschiedene Darstellungsformen für Ihre Informationen",

View File

@@ -12,7 +12,7 @@
"get_started": "Начало работы",
"github": "GitHub",
"dockerhub": "Docker Hub",
"screenshot_alt": "Скриншот приложения Trilium Notes для ПК"
"screenshot_alt": "Скриншот приложения Trilium Notes для настольного приложения"
},
"organization_benefits": {
"title": "Структура",
@@ -202,6 +202,7 @@
"title": "Ресурсы",
"icon_packs": "Наборы иконок",
"download": "Скачать",
"website": "Сайт"
"website": "Сайт",
"icon_packs_intro": "Расширьте выбор значков для заметок, используя набор иконок. Подробнее о наборах иконок смотрите в <DocumentationLink>официальной документации</DocumentationLink>."
}
}

View File

@@ -50,7 +50,7 @@
"@triliumnext/server": "workspace:*",
"@types/express": "5.0.6",
"@types/js-yaml": "4.0.9",
"@types/node": "24.11.0",
"@types/node": "24.12.0",
"@vitest/browser-webdriverio": "4.0.18",
"@vitest/coverage-v8": "4.0.18",
"@vitest/ui": "4.0.18",

View File

@@ -32,7 +32,7 @@
"eslint": "10.0.2",
"eslint-config-ckeditor5": ">=9.1.0",
"http-server": "14.1.1",
"lint-staged": "16.3.1",
"lint-staged": "16.3.2",
"stylelint": "17.4.0",
"stylelint-config-ckeditor5": ">=9.1.0",
"ts-node": "10.9.2",

View File

@@ -33,7 +33,7 @@
"eslint": "10.0.2",
"eslint-config-ckeditor5": ">=9.1.0",
"http-server": "14.1.1",
"lint-staged": "16.3.1",
"lint-staged": "16.3.2",
"stylelint": "17.4.0",
"stylelint-config-ckeditor5": ">=9.1.0",
"ts-node": "10.9.2",

View File

@@ -35,7 +35,7 @@
"eslint": "10.0.2",
"eslint-config-ckeditor5": ">=9.1.0",
"http-server": "14.1.1",
"lint-staged": "16.3.1",
"lint-staged": "16.3.2",
"stylelint": "17.4.0",
"stylelint-config-ckeditor5": ">=9.1.0",
"ts-node": "10.9.2",

View File

@@ -35,7 +35,7 @@
"eslint": "10.0.2",
"eslint-config-ckeditor5": ">=9.1.0",
"http-server": "14.1.1",
"lint-staged": "16.3.1",
"lint-staged": "16.3.2",
"stylelint": "17.4.0",
"stylelint-config-ckeditor5": ">=9.1.0",
"ts-node": "10.9.2",

View File

@@ -35,7 +35,7 @@
"eslint": "10.0.2",
"eslint-config-ckeditor5": ">=9.1.0",
"http-server": "14.1.1",
"lint-staged": "16.3.1",
"lint-staged": "16.3.2",
"stylelint": "17.4.0",
"stylelint-config-ckeditor5": ">=9.1.0",
"ts-node": "10.9.2",

View File

@@ -16,7 +16,7 @@
"ckeditor5-premium-features": "47.4.0"
},
"devDependencies": {
"@smithy/middleware-retry": "4.4.37",
"@smithy/middleware-retry": "4.4.39",
"@types/jquery": "4.0.0"
}
}

View File

@@ -8,7 +8,7 @@
"@codemirror/commands": "6.10.2",
"@codemirror/lang-css": "6.3.1",
"@codemirror/lang-html": "6.4.11",
"@codemirror/lang-javascript": "6.2.4",
"@codemirror/lang-javascript": "6.2.5",
"@codemirror/lang-json": "6.0.2",
"@codemirror/lang-markdown": "6.5.0",
"@codemirror/lang-php": "6.0.2",
@@ -16,7 +16,7 @@
"@codemirror/lang-xml": "6.1.0",
"@codemirror/legacy-modes": "6.5.2",
"@codemirror/search": "6.6.0",
"@codemirror/view": "6.39.15",
"@codemirror/view": "6.39.16",
"@fsegurai/codemirror-theme-abcdef": "6.2.3",
"@fsegurai/codemirror-theme-abyss": "6.2.3",
"@fsegurai/codemirror-theme-android-studio": "6.2.3",

1381
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff