Compare commits

..

3367 Commits

Author SHA1 Message Date
Elian Doran
056c07591e chore: remove extra sample and generated files 2025-11-03 10:48:45 +02:00
Elian Doran
0df15a02ba Merge remote-tracking branch 'origin/main' into copilot/integrate-technical-documentation 2025-11-03 10:46:37 +02:00
Elian Doran
02404a5f5b fix(build-docs): error due to becca not loading 2025-11-03 10:07:05 +02:00
Elian Doran
ed146f71c5 chore(dev): fix untracked type definitions after typecheck 2025-11-03 09:52:28 +02:00
Elian Doran
4492876293 chore(deps): update dependency rollup-plugin-webpack-stats to v2.1.7 (#7602) 2025-11-03 08:39:04 +02:00
renovate[bot]
51779cf218 chore(deps): update dependency rollup-plugin-webpack-stats to v2.1.7 2025-11-03 06:17:52 +00:00
Elian Doran
5536284826 fix(deps): update dependency debounce to v3 (#7604) 2025-11-03 08:15:40 +02:00
Elian Doran
e4d74108c6 chore(deps): update pnpm to v10.20.0 (#7603) 2025-11-03 08:15:05 +02:00
Elian Doran
faf67f5da2 chore(deps): update dependency @types/node to v24.10.0 (#7605) 2025-11-03 08:13:58 +02:00
renovate[bot]
021d1ba0fb chore(deps): update dependency @types/node to v24.10.0 2025-11-03 01:51:50 +00:00
renovate[bot]
ffead56a1d fix(deps): update dependency debounce to v3 2025-11-03 01:12:20 +00:00
renovate[bot]
b644701983 chore(deps): update pnpm to v10.20.0 2025-11-03 01:11:39 +00:00
copilot-swe-agent[bot]
18810bb86f Address code review feedback - improve outputSubDir handling
Improved the importAndExportDocs function to better handle the empty outputSubDir case:
- Use meaningful name for temporary zip file ('user-guide' instead of '')
- Explicitly handle empty outputSubDir for root directory output
- Added comments to clarify the behavior

Co-authored-by: eliandoran <21236836+eliandoran@users.noreply.github.com>
2025-11-02 22:31:25 +00:00
copilot-swe-agent[bot]
4f442551a9 Integrate Developer Guide into documentation build process
Added Developer Guide to the documentation build process alongside the User Guide.
- Modified build-docs.ts to import and export both User Guide and Developer Guide
- Created importAndExportDocs helper function to handle multiple documentation sources
- Developer Guide is exported to /site/developer-guide/ subdirectory
- Updated GitHub workflow to validate Developer Guide is built
- Added build-docs app to workflow triggers

The documentation build now produces:
- User Guide at /site/ (root) and /site/user-guide/
- Developer Guide at /site/developer-guide/
- Script API at /site/script-api/{backend,frontend}/
- REST API at /site/rest-api/{internal,etapi}/

Co-authored-by: eliandoran <21236836+eliandoran@users.noreply.github.com>
2025-11-02 22:28:24 +00:00
copilot-swe-agent[bot]
a8f565d912 Remove build artifacts from git and update .gitignore 2025-11-02 22:23:43 +00:00
copilot-swe-agent[bot]
0c6a57d3bb Fix documentation build system - resolve becca module instance issue
Fixed the issue where multiple becca instances were being created due to inconsistent module import paths. The solution was to export becca from becca_loader and access it from there, ensuring a single instance is used throughout the build process.

Co-authored-by: eliandoran <21236836+eliandoran@users.noreply.github.com>
2025-11-02 22:18:49 +00:00
copilot-swe-agent[bot]
01deab9c79 Initial plan 2025-11-02 21:57:43 +00:00
Elian Doran
a5a90b582a Translations update from Hosted Weblate (#7597) 2025-11-02 23:05:06 +02:00
Hosted Weblate
510601037d Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/
2025-11-02 20:35:51 +00:00
Eugene
b312b6f3bc Translated using Weblate (Russian)
Currently translated at 15.1% (23 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ru/
2025-11-02 20:35:47 +00:00
Eugene
0c1efd3402 Translated using Weblate (Russian)
Currently translated at 64.4% (76 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ru/
2025-11-02 20:35:46 +00:00
Elian Doran
69182a1a42 feat(mermaid): add link to docs (closes #5378) 2025-11-02 22:32:36 +02:00
Elian Doran
8a63f2028c docs(user): update link to ETAPI 2025-11-02 22:20:41 +02:00
Elian Doran
947330ed73 chore(options/etapi): update help 2025-11-02 22:08:42 +02:00
Elian Doran
4526455486 fix(help): webview source not updating 2025-11-02 21:40:21 +02:00
Elian Doran
1d259aab9d Improve documentation building & static Swagger (#7570) 2025-11-02 20:24:58 +02:00
Elian Doran
5171675dee chore(build-docs): fix URL 2025-11-02 20:13:10 +02:00
Elian Doran
6bc54892a3 Update apps/build-docs/src/swagger.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-02 20:12:50 +02:00
Elian Doran
0a6670ce5e Update apps/build-docs/src/backend_script_entrypoint.ts
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-11-02 20:05:44 +02:00
Elian Doran
beb7c66ff5 feat(build-docs): rewrite URLs for in-app help 2025-11-02 19:45:16 +02:00
Elian Doran
966e5a2ef3 chore(build-docs): update meta 2025-11-02 18:33:13 +02:00
Elian Doran
4f5be54030 chore(build-docs): generate types for doc 2025-11-02 18:28:31 +02:00
Elian Doran
68c6260e45 chore(build-docs): relocate OpenAPI location 2025-11-02 18:14:03 +02:00
Elian Doran
85bfd49d1c Merge remote-tracking branch 'origin/main' into feature/api_docs
; Conflicts:
;	_regroup/package.json
;	pnpm-lock.yaml
2025-11-02 18:05:02 +02:00
Elian Doran
23f2e1eb45 chore(deps): update dependency eslint-plugin-playwright to v2.3.0 (#7585) 2025-11-02 12:15:15 +02:00
Elian Doran
9bbd6d146b fix(deps): update dependency globals to v16.5.0 (#7591) 2025-11-02 12:14:40 +02:00
Elian Doran
37aa8ec176 chore(deps): update node.js to v24 (#7593) 2025-11-02 12:14:22 +02:00
renovate[bot]
05f3f9627d chore(deps): update node.js to v24 2025-11-02 09:31:25 +00:00
Elian Doran
a9fa99cadf chore(deps): update dependency @smithy/middleware-retry to v4.4.6 (#7574) 2025-11-02 11:30:19 +02:00
Elian Doran
d5c1604a58 chore(deps): update dependency axios to v1.13.1 (#7575) 2025-11-02 11:29:30 +02:00
Elian Doran
e99f821e88 chore(deps): update dependency chardet to v2.1.1 (#7576) 2025-11-02 11:29:19 +02:00
renovate[bot]
6571ff9d84 fix(deps): update dependency globals to v16.5.0 2025-11-02 09:29:14 +00:00
Elian Doran
9d63ef20fb chore(deps): update dependency esbuild to v0.25.12 (#7577) 2025-11-02 11:29:06 +02:00
renovate[bot]
71a3cf0cfe chore(deps): update dependency eslint-plugin-playwright to v2.3.0 2025-11-02 09:28:29 +00:00
Elian Doran
e5e55e1cf1 chore(deps): update dependency happy-dom to v20.0.10 (#7578) 2025-11-02 11:28:12 +02:00
Elian Doran
83b13cae92 chore(deps): update dependency ollama to v0.6.2 (#7579) 2025-11-02 11:27:57 +02:00
Elian Doran
6663c3abc1 fix(deps): update dependency dayjs to v1.11.19 (#7581) 2025-11-02 11:27:37 +02:00
renovate[bot]
738b28c2b3 chore(deps): update dependency esbuild to v0.25.12 2025-11-02 09:27:32 +00:00
Elian Doran
4eec6021c3 fix(deps): update dependency react-i18next to v16.2.3 (#7582) 2025-11-02 11:27:12 +02:00
Elian Doran
39bda30853 chore(deps): update dependency @anthropic-ai/sdk to v0.68.0 (#7583) 2025-11-02 11:26:57 +02:00
Elian Doran
6adcaca5e0 chore(deps): update dependency electron to v38.5.0 (#7584) 2025-11-02 11:26:49 +02:00
Elian Doran
5a5f71fc71 chore(deps): update dependency express-rate-limit to v8.2.1 (#7586) 2025-11-02 11:26:01 +02:00
Elian Doran
f3765f95b5 chore(deps): update dependency node-abi to v4.17.0 (#7587) 2025-11-02 11:25:45 +02:00
Elian Doran
6ebb0eb03e chore(deps): update dependency rimraf to v6.1.0 (#7588) 2025-11-02 11:25:30 +02:00
Elian Doran
b42aa32b72 chore(deps): update pnpm to v10.20.0 (#7589) 2025-11-02 11:25:13 +02:00
Elian Doran
11e1ea7ea5 fix(deps): update dependency eslint-linter-browserify to v9.39.0 (#7590) 2025-11-02 11:24:51 +02:00
Elian Doran
5f6fac994f fix(deps): update eslint monorepo to v9.39.0 (#7592) 2025-11-02 11:24:15 +02:00
Elian Doran
d7460e9fe5 chore(renovate): ignore legacy Dockerfile from Renovate updates 2025-11-02 11:22:29 +02:00
renovate[bot]
89585e38ce fix(deps): update eslint monorepo to v9.39.0 2025-11-02 02:03:29 +00:00
renovate[bot]
938c6e356b fix(deps): update dependency eslint-linter-browserify to v9.39.0 2025-11-02 02:01:50 +00:00
renovate[bot]
b7dd806d07 chore(deps): update pnpm to v10.20.0 2025-11-02 02:01:05 +00:00
renovate[bot]
a1d86cef58 chore(deps): update dependency rimraf to v6.1.0 2025-11-02 02:00:54 +00:00
renovate[bot]
1fec5bb564 chore(deps): update dependency node-abi to v4.17.0 2025-11-02 02:00:49 +00:00
renovate[bot]
35e98addc8 chore(deps): update dependency express-rate-limit to v8.2.1 2025-11-02 01:59:58 +00:00
renovate[bot]
79290633b1 chore(deps): update dependency electron to v38.5.0 2025-11-02 01:58:25 +00:00
renovate[bot]
ffc9e715ef chore(deps): update dependency @anthropic-ai/sdk to v0.68.0 2025-11-02 01:57:40 +00:00
renovate[bot]
8f8302c4a3 fix(deps): update dependency react-i18next to v16.2.3 2025-11-02 01:56:54 +00:00
renovate[bot]
136b449f60 fix(deps): update dependency dayjs to v1.11.19 2025-11-02 01:56:07 +00:00
renovate[bot]
61319c3a14 chore(deps): update dependency ollama to v0.6.2 2025-11-02 01:55:13 +00:00
renovate[bot]
104a1f0c3a chore(deps): update dependency happy-dom to v20.0.10 2025-11-02 01:54:26 +00:00
renovate[bot]
16200312ce chore(deps): update dependency chardet to v2.1.1 2025-11-02 01:52:16 +00:00
renovate[bot]
664de68d53 chore(deps): update dependency axios to v1.13.1 2025-11-02 01:51:29 +00:00
renovate[bot]
6190949dcc chore(deps): update dependency @smithy/middleware-retry to v4.4.6 2025-11-02 01:50:40 +00:00
Elian Doran
3ac248169f chore(build-docs): fix typecheck issues 2025-11-01 23:40:27 +02:00
Elian Doran
15e240ac33 refactor(build-docs): remove old Swagger integration 2025-11-01 23:37:17 +02:00
Elian Doran
d30fc09e73 chore(build-docs): fix link to FNote 2025-11-01 23:13:35 +02:00
Elian Doran
6a2b9b748f chore(build-docs): add project names to typedoc 2025-11-01 23:03:14 +02:00
Elian Doran
b5e2187c0d chore(build-docs): update meta 2025-11-01 23:00:14 +02:00
Elian Doran
d9a349a531 refactor(build-docs): define output for typedoc at script level 2025-11-01 22:54:42 +02:00
Elian Doran
2c1cebfbc3 feat(build-docs): split documentation in two 2025-11-01 22:51:33 +02:00
Elian Doran
c6738ac52f feat(build-docs): generate script API 2025-11-01 22:42:27 +02:00
Elian Doran
604f2abf5a chore(build-docs): fix wrong mkdir 2025-11-01 21:47:07 +02:00
Elian Doran
617703899f chore(build-docs): relocate to /rest-api 2025-11-01 21:35:18 +02:00
Elian Doran
6322ca11c9 feat(share): improve webview layout 2025-11-01 21:28:31 +02:00
Elian Doran
d62aecc551 fix(build-docs): crash in clean environment 2025-11-01 21:15:34 +02:00
Elian Doran
953b376ce3 refactor(build-docs): trigger build of share theme internally 2025-11-01 20:58:32 +02:00
Elian Doran
80f1707d8b chore(build-docs): integrate with docs:build 2025-11-01 20:52:28 +02:00
Elian Doran
4f9f8652e2 fix(build-docs): links to API reference 2025-11-01 20:47:00 +02:00
Elian Doran
6e06d7169f refactor(build-docs): integrate with original build-docs script 2025-11-01 20:37:03 +02:00
Elian Doran
ecf12a4063 feat(build-docs): build both docs 2025-11-01 20:22:17 +02:00
Elian Doran
64428ae761 feat(build-docs): clean before building 2025-11-01 20:16:59 +02:00
Elian Doran
3524c34ff9 feat(build-docs): switch to redocly 2025-11-01 20:15:38 +02:00
Elian Doran
3f99c8b337 feat(build-docs): copy swagger UI 2025-11-01 20:03:53 +02:00
Elian Doran
27d9ae885f Merge branch 'main' of github.com:TriliumNext/Trilium 2025-11-01 19:36:11 +02:00
Elian Doran
35efd2a680 test(server): broken test due to CLS 2025-11-01 16:48:49 +02:00
Elian Doran
19c6ae6fe5 Keyboard shortcut for today note button (#7549) 2025-11-01 16:17:24 +02:00
SngAbc
bf0761a303 Fix: activate the nearest path when opening a cloned note (#7552) 2025-11-01 16:06:26 +02:00
Weblate (bot)
8391fd7534 Translations update from Hosted Weblate (#7566)
* Update translation files

Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/

* Translated using Weblate (Portuguese)

Currently translated at 9.2% (14 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/pt/

---------

Co-authored-by: Francisco Machado <kikomachado089@gmail.com>
2025-11-01 16:04:10 +02:00
SngAbc
6d4b87888a fix(electron): allow extra window to reload (#7567) 2025-11-01 16:02:17 +02:00
Weblate (bot)
3f0b0f9b62 Translations update from Hosted Weblate (#7565) 2025-11-01 14:09:26 +02:00
Elian Doran
859d9dcd04 docs(user): document system requirements 2025-10-31 11:52:40 +02:00
Elian Doran
76dd9baea8 docs(user): document adjusting borders 2025-10-31 11:21:17 +02:00
Elian Doran
82ff5f6660 docs(user): sync 2025-10-31 11:07:22 +02:00
Elian Doran
b52d30c55a chore(dialog/export): strange order with OPML 2025-10-31 11:05:40 +02:00
Elian Doran
99fd088ff5 chore(share): use same sandbox features for iframe 2025-10-31 10:12:56 +02:00
Elian Doran
945f29c759 feat(share): render webviews using iframe 2025-10-31 10:12:15 +02:00
Elian Doran
98f42887d8 Translations update from Hosted Weblate (#7562) 2025-10-31 09:09:29 +02:00
Eduard Frigola
a1b589148b Translated using Weblate (Catalan)
Currently translated at 17.8% (69 of 387 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ca/
2025-10-31 08:04:01 +01:00
Elian Doran
66bb639a15 docs(user): port patterns of personal knowledge 2025-10-30 22:50:14 +02:00
Elian Doran
1784b50990 docs(user): port privacy policy 2025-10-30 22:37:59 +02:00
Elian Doran
5e9c271bfd docs(release): port v0.48 changelog 2025-10-30 22:36:41 +02:00
Elian Doran
70837fdc69 Translations update from Hosted Weblate (#7559) 2025-10-30 16:07:11 +02:00
Hosted Weblate
67d80512f6 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-30 13:46:35 +00:00
Elian Doran
dd8a1e8aca docs(user): document all share theme attributes 2025-10-30 15:46:13 +02:00
Elian Doran
99f43e2280 docs(user): improve fine-grained directory path documentation 2025-10-30 12:02:32 +02:00
Elian Doran
bcffa77c90 docs(user): index page for import/export 2025-10-30 11:54:44 +02:00
Elian Doran
8ab2069411 docs(user): fix empty section in kanban board 2025-10-30 11:43:48 +02:00
Elian Doran
21fc61d132 docs(user): restructure LLM section 2025-10-30 11:42:46 +02:00
Elian Doran
552df50fe4 docs(user): add icons to most notes 2025-10-30 11:40:07 +02:00
Elian Doran
c058b663ee Translations update from Hosted Weblate (#7556) 2025-10-30 09:05:27 +02:00
Francis C
6c19370235 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/zh_Hant/
2025-10-30 07:50:44 +01:00
Francis C
d332bb57ba Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/zh_Hans/
2025-10-30 07:50:44 +01:00
Antonio Sanchez Castellón
3ef38e7f4e Translated using Weblate (Spanish)
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/es/
2025-10-30 07:50:43 +01:00
Francis C
1abc3b5534 Translated using Weblate (Japanese)
Currently translated at 100.0% (1621 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-10-30 07:50:42 +01:00
Francis C
ddcd27ddf6 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (387 of 387 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/zh_Hant/
2025-10-30 07:50:41 +01:00
Francis C
ff385c8c88 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1621 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-10-30 07:50:40 +01:00
Antonio Sanchez Castellón
a641e452ce Translated using Weblate (Spanish)
Currently translated at 100.0% (387 of 387 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/es/
2025-10-30 07:50:39 +01:00
Francis C
5f4fa25da5 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (387 of 387 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/zh_Hans/
2025-10-30 07:50:38 +01:00
Antonio Sanchez Castellón
ea177e972e Translated using Weblate (Spanish)
Currently translated at 100.0% (1621 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/es/
2025-10-30 07:50:38 +01:00
Manfred Manni
7e3013bfdc Translated using Weblate (German)
Currently translated at 100.0% (1621 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-10-30 07:50:37 +01:00
Francis C
5115baeb21 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1621 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-10-30 07:50:36 +01:00
Hosted Weblate
35a924a05a Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-30 07:50:36 +01:00
Elian Doran
78f067965f fix(share): TOC indicator no longer working due to layout changes 2025-10-30 08:49:48 +02:00
Elian Doran
413b16b51c chore(collections): rename Board to Kanban Board 2025-10-30 08:42:00 +02:00
Elian Doran
59586c53b2 chore(website): rename Board to Kanban Board 2025-10-30 08:34:28 +02:00
Elian Doran
70ed1d7abb chore(website): fix URLs pointing to documentation 2025-10-30 08:33:54 +02:00
Elian Doran
67de6c614c docs(user): change alias for server documentation 2025-10-30 08:31:26 +02:00
Elian Doran
faf030ab3a docs(user): minor improvements to the collection main page 2025-10-30 08:18:13 +02:00
Elian Doran
6e20d4b5dd docs(user): rename Board to Kanban Board 2025-10-30 08:15:57 +02:00
Elian Doran
10e809af75 docs(user): rename and reorder collection pages 2025-10-30 08:14:22 +02:00
Elian Doran
f1478f8149 docs(user): change presentation method for collections 2025-10-30 08:13:34 +02:00
Elian Doran
9087adf254 docs(user): move collections one level up 2025-10-30 08:07:09 +02:00
Elian Doran
f944c6d8e2 docs(user): add slug + tips on how to identify pages without one easily 2025-10-30 08:03:09 +02:00
Elian Doran
444e103047 docs(dev): document exporting functionality 2025-10-29 22:36:45 +02:00
Elian Doran
1d6ab64ae5 docs(guide): document exporting for web publishing 2025-10-29 22:21:15 +02:00
Elian Doran
0bc86d7c75 docs(guide): deduplicate home page with quick start 2025-10-29 22:00:31 +02:00
Elian Doran
cfd55147df Deploy share-based static documentation (#7548) 2025-10-29 21:27:49 +02:00
Elian Doran
754bb61a52 feat(export/share): render 404 page 2025-10-29 21:05:50 +02:00
Elian Doran
4f103375b5 fix(share): 404 not rendering in dev mode 2025-10-29 20:20:35 +02:00
Elian Doran
496091677b style(share): overflow on wrong element 2025-10-29 20:14:32 +02:00
Elian Doran
618b67f551 fix(share): redesign layout to avoid jumping on tablets 2025-10-29 20:02:02 +02:00
contributor
9c791df0ed open today note in current tab #7472
https://github.com/TriliumNext/Trilium/pull/7549#issuecomment-3458822614
2025-10-29 19:22:13 +02:00
Elian Doran
ce4f46c226 chore(share): fix relative imports 2025-10-29 19:13:11 +02:00
Elian Doran
44cfbcf7f4 refactor(share): move icon loading in CSS rather than in JS 2025-10-29 19:11:43 +02:00
Elian Doran
a317331551 fix(share): theme toggle flashing while switching between notes 2025-10-29 19:05:23 +02:00
Elian Doran
eeec3e440d fix(share): flash while theme is loading 2025-10-29 19:00:09 +02:00
Elian Doran
b06aa29ea3 chore(share): remove leftover color management logic 2025-10-29 18:46:55 +02:00
Elian Doran
9c3f9a524e fix(share): flash of dark color on light theme 2025-10-29 18:46:24 +02:00
Elian Doran
1c832182d6 refactor(share): reduce duplication in theme management 2025-10-29 18:40:31 +02:00
Elian Doran
b58e1f146c fix(share): light theme not properly restored 2025-10-29 18:35:27 +02:00
Elian Doran
bc86fb95b5 feat(share): add dev mode 2025-10-29 18:27:43 +02:00
Elian Doran
6c43db692e fix(client): boxicons missing in prod 2025-10-29 18:16:25 +02:00
Elian Doran
6ffce824d1 fix(docker): incorrect version for arm v7 2025-10-29 17:43:10 +02:00
Elian Doran
f1f8f34ef8 fix(export/share): load search index once per page 2025-10-29 15:33:38 +02:00
Elian Doran
a0b19ce526 fix(export/share): search not working on root 2025-10-29 15:26:48 +02:00
Elian Doran
4cc9ba824d chore(export/share): tweak search results 2025-10-29 15:24:25 +02:00
Elian Doran
08e66c18e7 fix(export/share): navigation in search not working 2025-10-29 14:57:53 +02:00
Elian Doran
cf8089b07f feat(export/share): functional full-text search 2025-10-29 13:58:37 +02:00
Elian Doran
f8c61ecde9 feat(export/share): use better content parsing for search 2025-10-29 08:45:47 +02:00
Elian Doran
6d51da9b88 feat(export/share): generate search index 2025-10-29 08:41:07 +02:00
Elian Doran
0ad95d00dc chore(ci): try to fix arm v6/v7 build 2025-10-29 08:08:16 +02:00
Elian Doran
9819a92b48 docs(guide): remove a missing note link 2025-10-28 23:01:56 +02:00
Elian Doran
55a7017e92 docs(guide): document the zoom function 2025-10-28 22:55:52 +02:00
Elian Doran
1581568741 docs(guide): add promoted attribute for alias 2025-10-28 22:31:59 +02:00
Elian Doran
d7982c65dd docs(guide): add alias for most pages 2025-10-28 22:30:46 +02:00
Elian Doran
39608a2815 docs(guide): home page & third party hosting + sync 2025-10-28 22:07:05 +02:00
Elian Doran
f656c2caaa fix(export/zip): links breaking down in markdown export 2025-10-28 21:32:05 +02:00
Elian Doran
bd3e92f091 fix(export/zip): export options not considered 2025-10-28 20:40:53 +02:00
Elian Doran
7ce7c66463 chore(build-docs): address requested changes 2025-10-28 19:31:57 +02:00
Elian Doran
61d26fec60 refactor(build-docs): use proper await when building documentation 2025-10-28 19:30:55 +02:00
Elian Doran
1822eea77c chore: remove remaining references to mkdocs 2025-10-28 19:19:39 +02:00
Elian Doran
28c0e4e802 chore(client): remove no longer relevant input 2025-10-28 19:15:01 +02:00
Elian Doran
5b7e9d4c12 Revision history: two fixes (#7544) 2025-10-28 18:30:50 +02:00
contributor
bee2fdb22f chore: remove dead translation 2025-10-28 18:26:35 +02:00
contributor
5c46a0dfa8 chore: remove dead code
https://github.com/TriliumNext/Trilium/pull/7544#issuecomment-3456187575
2025-10-28 18:26:35 +02:00
Elian Doran
88d90fdedd fix(export/share): favicon working only on top-level 2025-10-28 18:23:11 +02:00
Elian Doran
2a1ecdbdca feat(share): display admonition icons (closes #6733) 2025-10-28 18:18:03 +02:00
Elian Doran
5772046674 chore(share): remove redundant file 2025-10-28 18:17:06 +02:00
Elian Doran
1e2c8b2ac4 fix(export/share): ckcontent CSS missing 2025-10-28 18:16:37 +02:00
Elian Doran
955b202b8a chore(export/share): hide last updated 2025-10-28 17:59:12 +02:00
Elian Doran
be98a27439 feat(export/share): prefer #shareAlias 2025-10-28 17:57:48 +02:00
Elian Doran
54200fa0cb chore(export/share): disable non-functional search 2025-10-28 17:33:36 +02:00
Elian Doran
5d82a26c87 fix(build-docs): missing favicon 2025-10-28 17:23:31 +02:00
Elian Doran
e51070e389 chore(share): handle BAttachments too 2025-10-28 17:16:34 +02:00
Elian Doran
e0dc4fee20 fix(share): reference links not working 2025-10-28 17:14:33 +02:00
contributor
e683dc1d66 add openTodayNote to CommandMappings #7472 2025-10-28 16:59:46 +02:00
contributor
14a3438a20 move shortcut definition to "Note navigation" section #7472 2025-10-28 16:59:41 +02:00
contributor
dd483fccbc use common translation for openTodayNote #7472 2025-10-28 16:59:36 +02:00
contributor
5620e7f4a7 feat: add command openTodayNote with empty keyboard shortcut #7472 2025-10-28 16:59:28 +02:00
Elian Doran
187e9b57de fix(share): note tree not visible on mobile 2025-10-28 16:57:04 +02:00
Elian Doran
d6d67e7957 fix(docs/share): share theme not built 2025-10-28 16:45:27 +02:00
Elian Doran
bde03e8378 feat(docs/share): integrate in the CI 2025-10-28 16:42:52 +02:00
Elian Doran
4c3fcdba4a fix(share): images appearing stretched 2025-10-28 16:34:38 +02:00
Elian Doran
7a5c1277f1 feat(docs/share): set up script to build documentation 2025-10-28 16:24:55 +02:00
Elian Doran
69b262040a Translations update from Hosted Weblate (#7547) 2025-10-28 16:22:15 +02:00
Manfred Manni
8731fa6c31 Translated using Weblate (German)
Currently translated at 59.3% (70 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/de/
2025-10-28 13:50:36 +00:00
Elian Doran
f4e8fc4d83 Export with share theme (#5830) 2025-10-28 15:50:21 +02:00
Elian Doran
dd5b3a3c1c chore(server): address requested changes 2025-10-28 15:44:00 +02:00
Elian Doran
17319d25e8 chore(server): fix a few type issues 2025-10-28 14:51:03 +02:00
Elian Doran
2f189b6961 chore(share): remove now redundant project 2025-10-28 14:47:51 +02:00
Elian Doran
b1f8d44576 Merge remote-tracking branch 'origin/main' into feature/export_with_share_theme 2025-10-28 14:29:37 +02:00
Elian Doran
7f22532a0a fix: import markdown to text note (#7538) 2025-10-28 14:15:29 +02:00
Elian Doran
c7beb87980 Update dependency node to v24 (#7537) 2025-10-28 14:14:00 +02:00
Elian Doran
5cd1fd53d4 Translations update from Hosted Weblate (#7546) 2025-10-28 14:11:20 +02:00
Elian Doran
2eadbe3f01 Translated using Weblate (German)
Currently translated at 44.9% (53 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/de/
2025-10-28 13:10:51 +01:00
Hosted Weblate
4e7493f648 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-28 13:06:25 +01:00
Elian Doran
b9d54a44f6 Translations update from Hosted Weblate (#7545) 2025-10-28 14:06:08 +02:00
Elian Doran
a1ad8be02b Apply suggestion from @gemini-code-assist[bot]
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-10-28 14:05:06 +02:00
Elian Doran
b02514f395 Apply suggestion from @gemini-code-assist[bot]
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-10-28 14:04:47 +02:00
Elian Doran
dcef3f2be5 Apply suggestion from @gemini-code-assist[bot]
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-10-28 14:04:39 +02:00
Rugved Inamdar
585fdabd27 Translated using Weblate (Hindi)
Currently translated at 0.6% (1 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/hi/
2025-10-28 12:02:42 +00:00
Rugved Inamdar
71fcb77a22 Translated using Weblate (Hindi)
Currently translated at 0.8% (1 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/hi/
2025-10-28 12:02:41 +00:00
Rugved Inamdar
33ecf6aa6d Translated using Weblate (Hindi)
Currently translated at 0.1% (1 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/hi/
2025-10-28 12:02:40 +00:00
Rugved Inamdar
1f75de83c6 Added translation using Weblate (Marathi) 2025-10-28 12:02:39 +00:00
Rugved Inamdar
31b52f72d2 Added translation using Weblate (Marathi) 2025-10-28 12:02:39 +00:00
Rugved Inamdar
01aaf81196 Added translation using Weblate (Marathi) 2025-10-28 12:02:38 +00:00
Rugved Inamdar
3ecfdd62e8 Added translation using Weblate (Marathi) 2025-10-28 12:02:38 +00:00
Rugved Inamdar
3c74d0714a Added translation using Weblate (Hindi) 2025-10-28 12:02:37 +00:00
Rugved Inamdar
f58d9adff2 Added translation using Weblate (Hindi) 2025-10-28 12:02:36 +00:00
Rugved Inamdar
0eecf5b132 Added translation using Weblate (Hindi) 2025-10-28 12:02:36 +00:00
Rugved Inamdar
9e3cca333a Added translation using Weblate (Hindi) 2025-10-28 12:02:35 +00:00
Manfred Manni
81c233463e Translated using Weblate (German)
Currently translated at 44.9% (53 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/de/
2025-10-28 12:02:34 +00:00
DerVogel101
87946e7e85 Translated using Weblate (German)
Currently translated at 100.0% (1621 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-10-28 12:02:33 +00:00
Elian Doran
c3768a051d Fix some CSS issues (#7543) 2025-10-28 14:02:24 +02:00
contributor
c579cd3ce7 fix: no note on edited notes view if a revision made between note created/modified date 2025-10-28 12:55:34 +02:00
contributor
945e2625d3 fix: wrong dates in “Note Revisions” view 2025-10-28 12:55:13 +02:00
Elian Doran
ff36414a55 chore(deps): update dependency @types/serve-static to v2 (#7535) 2025-10-28 08:24:02 +02:00
renovate[bot]
8f184c5b10 chore(deps): update dependency node to v24 2025-10-28 06:23:07 +00:00
Elian Doran
c027a2bbfa chore(deps): update dependency @types/archiver to v7 (#7534) 2025-10-28 08:22:36 +02:00
Elian Doran
91adc2258d fix(deps): update dependency react-i18next to v16.2.1 (#7532) 2025-10-28 08:22:12 +02:00
Elian Doran
6701e83927 chore(deps): update dependency axios to v1.13.0 (#7533) 2025-10-28 08:21:44 +02:00
Elian Doran
3f54e589d8 fix(deps): update dependency mermaid to v11.12.1 (#7531) 2025-10-28 08:21:09 +02:00
Elian Doran
f65be73f71 chore(deps): update dependency @types/express to v5.0.5 (#7530) 2025-10-28 08:20:33 +02:00
Elian Doran
346e9282bd Translations update from Hosted Weblate (#7528) 2025-10-28 08:19:57 +02:00
SiriusXT
8f8ea7adc3 fix(types): correct CommandMappings key for pasteMarkdownIntoText 2025-10-28 14:10:11 +08:00
SiriusXT
4affd3a955 fix: note map button overlapping menu 2025-10-28 11:28:36 +08:00
SiriusXT
bcce05cc4d fix(zen): Show fixed toolbar in Zen mode 2025-10-28 11:20:36 +08:00
SiriusXT
ac16c42e23 Merge branch 'main' into patch_import_markdown 2025-10-28 11:03:41 +08:00
SiriusXT
5025329e92 fix: restore editor focus after inserting markdown 2025-10-28 11:00:53 +08:00
SiriusXT
507910b0ce fix: import markdown to text note 2025-10-28 10:17:37 +08:00
renovate[bot]
b59fab9dba chore(deps): update dependency @types/serve-static to v2 2025-10-28 01:53:53 +00:00
renovate[bot]
ac7e4580f6 chore(deps): update dependency @types/archiver to v7 2025-10-28 01:53:07 +00:00
renovate[bot]
27d1044ba8 chore(deps): update dependency axios to v1.13.0 2025-10-28 01:52:22 +00:00
renovate[bot]
96c949b2fc fix(deps): update dependency react-i18next to v16.2.1 2025-10-28 01:51:32 +00:00
renovate[bot]
927cd0255e fix(deps): update dependency mermaid to v11.12.1 2025-10-28 01:50:45 +00:00
renovate[bot]
c2c8417c42 chore(deps): update dependency @types/express to v5.0.5 2025-10-28 01:49:55 +00:00
migraine-user
3bb224e682 Translated using Weblate (Korean)
Currently translated at 1.3% (2 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ko/
2025-10-27 20:43:03 +00:00
Elian Doran
6f126ea17b Fix typo in German translation for 'copy-link' (#7527) 2025-10-27 22:42:52 +02:00
DerVogel101
61a5cf1452 Fix typo in German translation for 'copy-link'
Fixed a missing character in the German translation of the context menu action copy-link.
2025-10-27 21:25:08 +01:00
Elian Doran
14b8d0a47e chore(share): bring back syntax highlight 2025-10-27 22:18:08 +02:00
Elian Doran
12df6a0d6e chore(uikit): create empty project 2025-10-27 20:53:13 +02:00
Elian Doran
21d243eec1 fix(desktop): share not working 2025-10-27 20:29:56 +02:00
Elian Doran
161238ca11 fix(windows script): add -command flag (#7513) 2025-10-27 18:47:03 +02:00
Elian Doran
4d5267e18b fix (empty tab): recent notes not showing when creating a empty tab (#7523) 2025-10-27 18:43:31 +02:00
Elian Doran
0fa52907b3 Website static fixes (#7525) 2025-10-27 18:39:20 +02:00
Elian Doran
c4f57f3d15 refactor(website): simplify loop 2025-10-27 18:34:26 +02:00
Elian Doran
6bde264156 fix(website): lang/dir not updating after switching language 2025-10-27 18:31:03 +02:00
Elian Doran
4f72f81a95 chore(website): fix typecheck issues 2025-10-27 18:19:35 +02:00
Elian Doran
c212c5d6ff Merge remote-tracking branch 'origin/main' into fix/website_static 2025-10-27 18:11:39 +02:00
Elian Doran
f24880d42c fix(website): incorrect default language 2025-10-27 18:10:21 +02:00
Elian Doran
ee9bf1d47b fix(website): incorrect lang tag 2025-10-27 18:04:49 +02:00
Elian Doran
b069fab82f chore(website): use static loading of translations 2025-10-27 17:17:37 +02:00
Elian Doran
d5ce01a65b Revert "fix(website): missing suspense"
This reverts commit dbfa94a9ee.
2025-10-27 16:45:52 +02:00
Elian Doran
dbfa94a9ee fix(website): missing suspense 2025-10-27 16:35:26 +02:00
Elian Doran
86aaa97809 fix(website): language-specific pages not properly determined 2025-10-27 16:30:03 +02:00
Elian Doran
c4c8fe23a9 fix(website): pages not prerendered 2025-10-27 16:29:44 +02:00
Elian Doran
715fe77db3 Translations update from Hosted Weblate (#7519) 2025-10-27 16:20:42 +02:00
Francis C
40f5abd6e3 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/zh_Hant/
2025-10-27 14:18:09 +00:00
Giovi
f3f7e5900b Translated using Weblate (Italian)
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/it/
2025-10-27 14:18:08 +00:00
green
f4402a6d81 Translated using Weblate (Japanese)
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ja/
2025-10-27 14:18:08 +00:00
green
6966efd374 Translated using Weblate (Japanese)
Currently translated at 98.0% (149 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ja/
2025-10-27 14:18:07 +00:00
Hosted Weblate
cd3e025fdc Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/
2025-10-27 14:18:06 +00:00
marc hooijschuur
a224b774d3 Translated using Weblate (Dutch)
Currently translated at 2.9% (48 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/nl/
2025-10-27 14:18:05 +00:00
Elian Doran
f20078f3b0 fix(print): some images not loading 2025-10-27 16:17:51 +02:00
SiriusXT
56019e5449 fix (empty tab): recent notes not showing when creating a empty tab 2025-10-27 16:59:28 +08:00
SiriusXT
7dd517d8f7 fix (empty tab): recent notes not showing when creating a empty tab 2025-10-27 14:42:22 +08:00
Elian Doran
b2f1b3c910 chore(deps): update dependency @types/turndown to v5.0.6 (#7521) 2025-10-27 08:13:12 +02:00
renovate[bot]
2197fae700 chore(deps): update dependency @types/turndown to v5.0.6 2025-10-27 01:55:23 +00:00
Elian Doran
3661733f07 chore(server): remove duplicate math handling 2025-10-26 22:00:11 +02:00
Elian Doran
52a6f2597e fix(share): template directory in production 2025-10-26 21:38:16 +02:00
Elian Doran
d8e9cad23d feat(website): describe presentation collection 2025-10-26 19:24:43 +02:00
Elian Doran
6ed333d222 style(website): redesign list with screenshot 2025-10-26 19:11:11 +02:00
Elian Doran
ba26c478d6 fix(export/share): assets incorrectly rewritten 2025-10-26 12:15:35 +02:00
Elian Doran
055fcb7b2a fix(export/share): handling of fonts 2025-10-26 11:34:09 +02:00
Elian Doran
f4468706ef fix(export/share): asset path for styles and scripts 2025-10-26 11:07:08 +02:00
Elian Doran
212956201a chore(export/share): export full share script & styles 2025-10-26 11:02:19 +02:00
Elian Doran
1182592fc5 chore(share): fix another typecheck issue 2025-10-26 10:07:42 +02:00
Elian Doran
d534db29c9 feat(note_icon): add an empty option (closes #7370) 2025-10-26 10:03:51 +02:00
Elian Doran
40edd42740 Translations update from Hosted Weblate (#7516) 2025-10-25 23:57:24 +03:00
Newcomer1989
d2c7011735 Translated using Weblate (German)
Currently translated at 20.5% (30 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/de/
2025-10-25 20:54:49 +00:00
Manfred Manni
a050d1741b Translated using Weblate (German)
Currently translated at 22.8% (27 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/de/
2025-10-25 20:54:48 +00:00
greenfork
18982865da Translated using Weblate (Russian)
Currently translated at 99.1% (1607 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-10-25 20:54:48 +00:00
Newcomer1989
3aa810fed7 Translated using Weblate (German)
Currently translated at 100.0% (1621 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-10-25 20:54:47 +00:00
Elian Doran
c5ecc22c67 chore(website): update macOS requirement 2025-10-25 23:54:37 +03:00
Elian Doran
252f8ccb1f Internationalization improvements for the website (#7515) 2025-10-25 23:46:43 +03:00
Elian Doran
e1bb704383 fix(website/i18n): language list fit on mobile 2025-10-25 23:33:54 +03:00
Elian Doran
dce0d9400b chore(website/i18n): bring back root-level pages 2025-10-25 23:11:02 +03:00
Elian Doran
615c783fe3 chore(website/i18n): add t to list of deps 2025-10-25 22:52:38 +03:00
Elian Doran
f29411baf7 fix(website/i18n): header link not indicating active 2025-10-25 22:49:22 +03:00
Elian Doran
be5e70130c feat(website/i18n): highlight current language 2025-10-25 22:39:04 +03:00
Elian Doran
9ba1e9d732 feat(website/i18n): swap locale when footer 2025-10-25 22:36:27 +03:00
Elian Doran
e1dc4d1433 chore(website/i18n): another missing translation 2025-10-25 22:18:07 +03:00
Elian Doran
d0d268496c Update apps/website/src/components/Header.tsx
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-10-25 22:16:50 +03:00
Elian Doran
8a6950c945 Merge branch 'main' into feature/website_i18n 2025-10-25 22:03:18 +03:00
Elian Doran
477592d176 fix(website/i18n): language detection not always working 2025-10-25 21:55:53 +03:00
Elian Doran
7e5c2ed79d chore(website): set up testing 2025-10-25 21:54:30 +03:00
Elian Doran
bc580f2a88 feat(website/i18n): language auto-detection 2025-10-25 21:39:02 +03:00
Elian Doran
71cd92e0b5 fix(website/i18n): header sometimes not correctly translated 2025-10-25 21:13:48 +03:00
Elian Doran
a4d92e12be chore(website/i18n): add more CJK fonts 2025-10-25 21:05:54 +03:00
Elian Doran
c40279b480 chore(website): missing a translation 2025-10-25 20:40:05 +03:00
Elian Doran
4c7e7c157c chore(website): solve a warning about sectioned h1 size 2025-10-25 20:31:08 +03:00
Elian Doran
c08386450a chore(website/i18n): different load mechanism for translations 2025-10-25 20:27:42 +03:00
Elian Doran
eb93762ecc chore(website/i18n): missing translations in header 2025-10-25 20:27:23 +03:00
Elian Doran
2697f9a25d fix(website/i18n): get started in download button not working 2025-10-25 20:00:09 +03:00
Elian Doran
9515e2099b feat(website/i18n): set right dir and lang tags 2025-10-25 19:58:31 +03:00
Elian Doran
966c08da87 fix(website/i18n): home page link not working 2025-10-25 19:53:36 +03:00
Elian Doran
ea04446e81 chore(website/i18n): handle Chinese 2025-10-25 19:17:26 +03:00
Elian Doran
e4f806ed14 feat(website/i18n): get translation to actually render 2025-10-25 19:13:28 +03:00
Elian Doran
49cf7ae1a3 feat(website/i18n): render pages by locale 2025-10-25 18:54:24 +03:00
Elian Doran
1a6f5a027f chore(website/i18n): add English too 2025-10-25 18:21:52 +03:00
Elian Doran
f4796f0f9e feat(website/i18n): footer navigation 2025-10-25 18:18:47 +03:00
Elian Doran
30480b2c23 chore(website/i18n): start generating routes 2025-10-25 17:25:58 +03:00
Elian Doran
b7b1d17817 chore(website): add list of locales 2025-10-25 16:41:10 +03:00
Elian Doran
c4e5494c14 chore(deps): update dependency @types/express to v5.0.4 (#7487) 2025-10-25 16:37:47 +03:00
Elian Doran
b0f63c02c9 chore(deps): update dependency vite to v7.1.12 (#7495) 2025-10-25 16:37:20 +03:00
Elian Doran
2480509811 chore(deps): update dependency electron to v38.4.0 (#7500) 2025-10-25 16:28:45 +03:00
Elian Doran
7872193ed0 chore(deps): update dependency node-abi to v4.15.0 (#7501) 2025-10-25 16:28:37 +03:00
Ryan Keane
1a68bdfe02 fix(windows script): add -command flag
I don't know why if I replace old, system builtin powershell executable
with powershell 7, scripts fail with this error:

The argument 'Set-Item -Path ...' is not recognized as the name of a
script file. Check the spelling of the name, or if a path was included,
verify that the path is correct and try again.

Adding -Command at the end of flags just fixed it.

Signed-off-by: Ryan Keane <the.ra2.ifv@gmail.com>
2025-10-25 01:07:28 -07:00
Elian Doran
14e06c4555 chore(dev): add entry point for starting web site in dev mode 2025-10-25 09:34:53 +03:00
Elian Doran
b8e17959ae Translations update from Hosted Weblate (#7512) 2025-10-25 09:19:43 +03:00
Sarah Hussein
c16a135efc Translated using Weblate (Arabic)
Currently translated at 55.4% (81 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ar/
2025-10-25 06:18:55 +00:00
Sarah Hussein
cbc756ba06 Translated using Weblate (Arabic)
Currently translated at 85.7% (332 of 387 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ar/
2025-10-25 06:18:54 +00:00
Sarah Hussein
64daeb0826 Translated using Weblate (Arabic)
Currently translated at 65.0% (1055 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-25 06:18:53 +00:00
Hosted Weblate
e15839db47 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-25 06:18:53 +00:00
Elian Doran
dcdffed003 chore(deps): remove unused types for session-file-store 2025-10-25 09:18:41 +03:00
renovate[bot]
48e85fad43 chore(deps): update dependency node-abi to v4.15.0 2025-10-25 06:17:51 +00:00
renovate[bot]
189071deb8 chore(deps): update dependency electron to v38.4.0 2025-10-25 06:17:20 +00:00
Elian Doran
354f1d65c1 chore(deps): update dependency eslint-plugin-react-hooks to v7.0.1 (#7491) 2025-10-25 09:14:40 +03:00
renovate[bot]
b78893b106 chore(deps): update dependency vite to v7.1.12 2025-10-25 06:14:32 +00:00
Elian Doran
9310315c6a chore(deps): update dependency @types/tabulator-tables to v6.3.0 (#7499) 2025-10-25 09:13:38 +03:00
renovate[bot]
1794f8546d chore(deps): update dependency @types/express to v5.0.4 2025-10-25 06:12:41 +00:00
Elian Doran
b3bc0572e5 chore(deps): update ckeditor5 config packages to v12.2.0 (#7498) 2025-10-25 09:12:04 +03:00
Elian Doran
253ce1f223 fix(deps): update dependency preact-render-to-string to v6.6.3 (#7497) 2025-10-25 09:11:45 +03:00
Elian Doran
2f3bf94b47 fix(deps): update dependency mind-elixir to v5.3.4 (#7496) 2025-10-25 09:11:26 +03:00
Elian Doran
d802caa03b chore(deps): update dependency turndown to v7.2.2 (#7494) 2025-10-25 09:10:35 +03:00
renovate[bot]
e69751a8b3 fix(deps): update dependency preact-render-to-string to v6.6.3 2025-10-25 06:10:07 +00:00
Elian Doran
0760ea22fb chore(deps): update dependency lint-staged to v16.2.6 (#7493) 2025-10-25 09:09:27 +03:00
Elian Doran
8a8f407e99 chore(deps): update dependency happy-dom to v20.0.8 (#7492) 2025-10-25 09:09:09 +03:00
renovate[bot]
e030dd96da chore(deps): update dependency eslint-plugin-react-hooks to v7.0.1 2025-10-25 06:08:45 +00:00
Elian Doran
01abfc2528 chore(deps): update dependency @types/yargs to v17.0.34 (#7490) 2025-10-25 09:08:36 +03:00
Elian Doran
042b929dc5 chore(deps): update dependency @types/serve-static to v1.15.10 (#7488) 2025-10-25 09:08:03 +03:00
Elian Doran
ab1d5e31fb chore(deps): update dependency @types/cookie-parser to v1.4.10 (#7486) 2025-10-25 09:07:41 +03:00
Elian Doran
d073e4c37f chore(deps): update dependency @types/archiver to v6.0.4 (#7485) 2025-10-25 09:07:29 +03:00
Elian Doran
d60d965a42 chore(deps): update dependency @smithy/middleware-retry to v4.4.5 (#7484) 2025-10-25 09:07:13 +03:00
Elian Doran
1c87cfbbd9 chore(deps): update dependency ini to v6 (#7507) 2025-10-25 09:06:21 +03:00
Elian Doran
fee333512a chore(deps): update dependency openai to v6.7.0 (#7502) 2025-10-25 09:05:53 +03:00
Elian Doran
38a3f46506 chore(deps): update node.js to v22.21.0 (#7503) 2025-10-25 09:05:35 +03:00
Elian Doran
bf7506fcd8 chore(deps): update pnpm to v10.19.0 (#7504) 2025-10-25 09:05:05 +03:00
Elian Doran
6fbba426de fix(deps): update codemirror (#7505) 2025-10-25 09:04:29 +03:00
Elian Doran
d5bdec13b5 fix(deps): update dependency react-i18next to v16.2.0 (#7506) 2025-10-25 09:04:02 +03:00
Elian Doran
cc1b6eb42d chore(deps): update github artifact actions (major) (#7508) 2025-10-25 09:03:36 +03:00
renovate[bot]
8baf496f96 chore(deps): update github artifact actions 2025-10-25 01:23:17 +00:00
renovate[bot]
23a20c4490 chore(deps): update dependency ini to v6 2025-10-25 01:23:11 +00:00
renovate[bot]
c8b98f2db6 fix(deps): update dependency react-i18next to v16.2.0 2025-10-25 01:22:39 +00:00
renovate[bot]
3f36f515db fix(deps): update codemirror 2025-10-25 01:22:07 +00:00
renovate[bot]
892eb5b95d chore(deps): update pnpm to v10.19.0 2025-10-25 01:21:37 +00:00
renovate[bot]
62a69a0da0 chore(deps): update node.js to v22.21.0 2025-10-25 01:21:29 +00:00
renovate[bot]
3588e38543 chore(deps): update dependency openai to v6.7.0 2025-10-25 01:21:24 +00:00
renovate[bot]
41450ab85a chore(deps): update dependency @types/tabulator-tables to v6.3.0 2025-10-25 01:19:49 +00:00
renovate[bot]
0526d99560 chore(deps): update ckeditor5 config packages to v12.2.0 2025-10-25 01:19:14 +00:00
renovate[bot]
557d576b85 fix(deps): update dependency mind-elixir to v5.3.4 2025-10-25 01:18:06 +00:00
renovate[bot]
041c961cfa chore(deps): update dependency turndown to v7.2.2 2025-10-25 01:16:54 +00:00
renovate[bot]
dcc35bd507 chore(deps): update dependency lint-staged to v16.2.6 2025-10-25 01:16:19 +00:00
renovate[bot]
09c3e5b56e chore(deps): update dependency happy-dom to v20.0.8 2025-10-25 01:15:41 +00:00
renovate[bot]
950793377d chore(deps): update dependency @types/yargs to v17.0.34 2025-10-25 01:13:27 +00:00
renovate[bot]
7dac61dc26 chore(deps): update dependency @types/serve-static to v1.15.10 2025-10-25 01:11:50 +00:00
renovate[bot]
42dcb8f141 chore(deps): update dependency @types/cookie-parser to v1.4.10 2025-10-25 01:10:08 +00:00
renovate[bot]
43dc8a4b87 chore(deps): update dependency @types/archiver to v6.0.4 2025-10-25 01:09:20 +00:00
renovate[bot]
35316a4c45 chore(deps): update dependency @smithy/middleware-retry to v4.4.5 2025-10-25 01:08:32 +00:00
Elian Doran
1366489f99 Translations update from Hosted Weblate (#7479) 2025-10-24 23:31:57 +03:00
Elian Doran
0c399a676a chore(share): fix typecheck issue 2025-10-24 23:28:42 +03:00
brtkcs
31ee78b1aa Translated using Weblate (Hungarian)
Currently translated at 21.2% (31 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/hu/
2025-10-24 20:14:05 +00:00
brtkcs
808ba75ee0 Translated using Weblate (Hungarian)
Currently translated at 27.1% (32 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/hu/
2025-10-24 20:14:04 +00:00
brtkcs
ac1399a139 Translated using Weblate (Hungarian)
Currently translated at 8.2% (32 of 387 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/hu/
2025-10-24 20:14:04 +00:00
brtkcs
1e4793351a Translated using Weblate (Hungarian)
Currently translated at 1.9% (32 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/hu/
2025-10-24 20:14:03 +00:00
Sarah Hussein
f502fe41c7 Translated using Weblate (Arabic)
Currently translated at 52.7% (77 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ar/
2025-10-24 20:14:02 +00:00
brtkcs
0ec0091357 Translated using Weblate (Hungarian)
Currently translated at 19.1% (28 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/hu/
2025-10-24 20:14:02 +00:00
brtkcs
0e2196f872 Translated using Weblate (Hungarian)
Currently translated at 24.5% (29 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/hu/
2025-10-24 20:14:01 +00:00
Sarah Hussein
32dee254cd Translated using Weblate (Arabic)
Currently translated at 82.4% (319 of 387 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ar/
2025-10-24 20:14:01 +00:00
Sarah Hussein
d4a6a297f4 Translated using Weblate (Arabic)
Currently translated at 64.3% (1043 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-24 20:14:00 +00:00
brtkcs
a64d8cd8e2 Translated using Weblate (Hungarian)
Currently translated at 7.4% (29 of 387 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/hu/
2025-10-24 20:14:00 +00:00
brtkcs
bf4cfb9c02 Translated using Weblate (Hungarian)
Currently translated at 1.7% (29 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/hu/
2025-10-24 20:13:59 +00:00
Manfred Manni
a99dfecf43 Translated using Weblate (German)
Currently translated at 100.0% (387 of 387 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/de/
2025-10-24 20:13:59 +00:00
Manfred Manni
1530d96eca Translated using Weblate (German)
Currently translated at 99.8% (1619 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-10-24 20:13:58 +00:00
Elian Doran
5dc066f4c6 chore(dev): add work-around to run on Ubuntu
See https://github.com/electron/electron/issues/42510.
2025-10-24 23:03:20 +03:00
Elian Doran
395f33cd5b chore(share): bring back boxicons 2025-10-24 22:32:42 +03:00
Elian Doran
21b20cf575 chore(share): bring back most of the logic 2025-10-24 21:18:06 +03:00
Elian Doran
e3dd25b591 chore(share): set up math 2025-10-24 21:13:40 +03:00
Elian Doran
b9a4e7ab11 chore(share): enable code splitting 2025-10-24 20:52:54 +03:00
Elian Doran
6ae67c410c chore(share): load Mermaid only when necessary 2025-10-24 20:52:47 +03:00
Elian Doran
4ef7667484 chore(share): bring back inline mermaid rendering 2025-10-24 19:09:19 +03:00
Elian Doran
3660e2f127 refactor(share): store assets at /share/asset level 2025-10-24 19:00:26 +03:00
Elian Doran
357d294f2d chore(export/share): address review 2025-10-24 18:25:16 +03:00
Elian Doran
bb636128b0 fix(export/share): missing files and wrong meta handling 2025-10-24 16:02:20 +03:00
Elian Doran
aa102ab393 fix(export/share): missing templates after merge 2025-10-24 14:54:20 +03:00
Elian Doran
ea53665e64 Merge remote-tracking branch 'origin/main' into feature/export_with_share_theme 2025-10-24 14:43:20 +03:00
Elian Doran
1e8f179f81 Translations update from Hosted Weblate (#7469) 2025-10-23 20:37:39 +03:00
Elian Doran
54c906de8d Apply suggestion from @gemini-code-assist[bot]
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-10-23 20:35:34 +03:00
Elian Doran
114b3ef4d1 Apply suggestion from @gemini-code-assist[bot]
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-10-23 20:33:43 +03:00
Elian Doran
f6fa1e69b3 Apply suggestion from @gemini-code-assist[bot]
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-10-23 20:33:03 +03:00
Elian Doran
fcc8086f9c Apply suggestion from @gemini-code-assist[bot]
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-10-23 20:32:21 +03:00
Bond
7eefff0a74 Translated using Weblate (Vietnamese)
Currently translated at 10.9% (16 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/vi/
2025-10-23 19:28:31 +02:00
Микола Копитін
1b842e35ff Translated using Weblate (Ukrainian)
Currently translated at 26.0% (38 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/uk/
2025-10-23 19:28:30 +02:00
Bond
c9021ca742 Translated using Weblate (Vietnamese)
Currently translated at 55.9% (66 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/vi/
2025-10-23 19:28:29 +02:00
Микола Копитін
b229ab3c02 Translated using Weblate (Ukrainian)
Currently translated at 32.2% (38 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/uk/
2025-10-23 19:28:29 +02:00
Bond
6825f28ba0 Translated using Weblate (Vietnamese)
Currently translated at 3.0% (50 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/vi/
2025-10-23 19:28:28 +02:00
Микола Копитін
5e72f271ea Translated using Weblate (Ukrainian)
Currently translated at 21.9% (32 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/uk/
2025-10-23 19:28:27 +02:00
Микола Копитін
9ad6dfd5e9 Translated using Weblate (Ukrainian)
Currently translated at 27.9% (33 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/uk/
2025-10-23 19:28:27 +02:00
Marc
81031673c3 Translated using Weblate (French)
Currently translated at 100.0% (146 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/fr/
2025-10-23 19:28:26 +02:00
Микола Копитін
1a6423fd36 Translated using Weblate (Ukrainian)
Currently translated at 20.5% (30 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/uk/
2025-10-23 19:28:26 +02:00
onlyfranz
9b872617e6 Translated using Weblate (German)
Currently translated at 2.7% (4 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/de/
2025-10-23 19:28:25 +02:00
Sarah Hussein
57be2e2474 Translated using Weblate (Arabic)
Currently translated at 25.4% (30 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ar/
2025-10-23 19:28:25 +02:00
Микола Копитін
1d65afef53 Translated using Weblate (Ukrainian)
Currently translated at 26.2% (31 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/uk/
2025-10-23 19:28:24 +02:00
Sarah Hussein
b6385618d1 Translated using Weblate (Arabic)
Currently translated at 63.5% (1030 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-23 19:28:23 +02:00
Giovi
e3d7c7419f Translated using Weblate (Italian)
Currently translated at 100.0% (387 of 387 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/it/
2025-10-23 19:28:22 +02:00
Giovi
2a6c295967 Translated using Weblate (Italian)
Currently translated at 100.0% (1621 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-10-23 19:28:22 +02:00
green
f5f32df847 Translated using Weblate (Japanese)
Currently translated at 100.0% (1621 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-10-23 19:28:21 +02:00
Francis C
1f350b2730 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1621 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-10-23 19:28:20 +02:00
Marc
386992255e Translated using Weblate (French)
Currently translated at 100.0% (387 of 387 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/fr/
2025-10-23 19:28:20 +02:00
Bilal Janati
eb505c4615 Translated using Weblate (French)
Currently translated at 100.0% (1621 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/fr/
2025-10-23 19:28:19 +02:00
Marc
003d2b5354 Translated using Weblate (French)
Currently translated at 100.0% (1621 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/fr/
2025-10-23 19:28:19 +02:00
Elian Doran
b452f78242 feat(mobile/search): search definitions always shown 2025-10-23 20:24:16 +03:00
Elian Doran
7d1abee8e4 feat(mobile/search): show results (closes #5655) 2025-10-23 20:16:17 +03:00
Elian Doran
d503993a74 chore(mobile/search): further improve the layout 2025-10-23 20:03:44 +03:00
Elian Doran
fe98ba8c8c chore(mobile/search): improve actions fit 2025-10-23 19:15:38 +03:00
Elian Doran
18608ecb34 feat(mobile): render search definition 2025-10-23 19:07:40 +03:00
Elian Doran
ab6da26a25 refactor(client): standalone rendering mechanism for ribbon 2025-10-23 18:09:32 +03:00
Elian Doran
f95082ccdb fix(server): calendar tooltip positioning (closes #5675) 2025-10-23 16:57:48 +03:00
Elian Doran
e94b5ac07a fix(server): edited notes listing automatically generated hidden notes (closes #5683) 2025-10-23 16:42:27 +03:00
Elian Doran
5d0669b464 fix(canvas): images appearing muted in dark mode (closes #5708) 2025-10-23 16:11:05 +03:00
Elian Doran
af95d85b73 chore(client): disable import/export for help notes 2025-10-23 14:43:04 +03:00
Elian Doran
aae90ede19 chore(share): keep diacritics in slug instead of stripping them in 2025-10-23 14:29:47 +03:00
Elian Doran
0fa1c0f5c4 chore(share): improve slugification to strip diacritics cleanly 2025-10-23 14:26:15 +03:00
Elian Doran
d2b6014b49 fix(share): HTML tags displayed escaped in headings 2025-10-23 14:19:54 +03:00
Elian Doran
94d62f810a fix(share): heading and navigation not supporting CJK (closes #6430) 2025-10-23 14:06:13 +03:00
Elian Doran
e953f0cc1a Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-10-23 13:22:26 +03:00
Elian Doran
347da8abde fix(collections/list): excessive spacing in empty note content (closes #7319) 2025-10-23 08:16:26 +03:00
Elian Doran
5ff07820d3 chore(release): prepare for 0.99.3 2025-10-22 22:37:46 +03:00
Adorian Doran
6eccaac4bb style: fix broken colored links inside read-only notes (hover color) 2025-10-22 22:12:58 +03:00
Adorian Doran
f5038a08e5 style/board/board items: make the note custom color be applied again as the text color 2025-10-22 22:05:16 +03:00
Adorian Doran
d1e6bd9c3a Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-10-22 21:52:21 +03:00
Adorian Doran
7911973a83 style: fix broken colored links inside read-only notes 2025-10-22 21:52:08 +03:00
Jon Fuller
968b595aec fix(scheduler): change session expiration check interval to 30 seconds from 1ms
Increase interval for checking protected session expiration from 1ms to 30s.
2025-10-22 11:20:14 -07:00
Elian Doran
704f2c2238 Translations update from Hosted Weblate (#7461) 2025-10-22 18:30:09 +03:00
Hosted Weblate
f6b86d725c Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-22 17:27:54 +02:00
Elian Doran
a7e0866e0d Flatpak improvements (#7460) 2025-10-22 18:27:33 +03:00
Elian Doran
2cb3b877d1 chore(forge): fixup electron-forge:make scripts 2025-10-22 18:24:34 +03:00
Elian Doran
0b808b8db3 fix(forge): missing icon in flatpak build 2025-10-22 18:05:38 +03:00
Elian Doran
f02af893bb fix(forge): wrong exec in flatpak desktop template (closes #5516) 2025-10-22 18:03:52 +03:00
Elian Doran
cb3f941760 chore(forge): add script to make flatpak 2025-10-22 17:45:31 +03:00
Elian Doran
93f145a20f fix(forge): missing flatpak permissions (closes #7454) 2025-10-22 17:44:19 +03:00
Elian Doran
d34e2a0246 Translations update from Hosted Weblate (#7453) 2025-10-22 08:00:27 +03:00
Hosted Weblate
9a0b4f67ed Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-22 07:59:55 +03:00
Marc
651e158e3a Translated using Weblate (French)
Currently translated at 88.8% (1440 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/fr/
2025-10-22 07:59:55 +03:00
Elian Doran
d11784a894 Translations update from Hosted Weblate (#7449) 2025-10-22 07:54:29 +03:00
Elian Doran
14db789b7f Apply suggestion from @gemini-code-assist[bot]
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-10-22 07:53:45 +03:00
Marc
c4a4995da0 Translated using Weblate (French)
Currently translated at 71.9% (105 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/fr/
2025-10-22 07:53:12 +03:00
Marc
45de9da893 Translated using Weblate (French)
Currently translated at 90.9% (352 of 387 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/fr/
2025-10-22 07:53:12 +03:00
Marc
a6fce1b4c8 Translated using Weblate (French)
Currently translated at 86.9% (1409 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/fr/
2025-10-22 07:53:12 +03:00
Hosted Weblate
1d28a5e5b8 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-22 07:53:12 +03:00
Adorian Doran
d4b05fa0a0 style/dialogs/delete confirmation: fix the spacing of the note list 2025-10-22 01:29:54 +03:00
Adorian Doran
4bcf209072 style/reference links: enable colors in table collections as well 2025-10-22 00:57:55 +03:00
Adorian Doran
4b34ae3fd4 style/text editor/reference links: make the underline use the same color as the link caption 2025-10-22 00:51:58 +03:00
Adorian Doran
8590ff1f46 style/text editor/reference links color: fix regression 2025-10-22 00:45:51 +03:00
Elian Doran
c4e2c003de feat(i18n): enable Italian language 2025-10-21 21:35:05 +03:00
Elian Doran
eee3aa2bb4 feat(i18n): update Italian translations 2025-10-21 20:59:28 +03:00
Elian Doran
ce9f703e0c feat(scripts): import weblate CSVs into translations 2025-10-21 20:59:12 +03:00
Elian Doran
279ccec3ab Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-10-21 19:14:33 +03:00
Elian Doran
ab3852678e chore(splitjs): get rid of minified version
Not useful for the app.
2025-10-21 19:14:31 +03:00
Elian Doran
65f7aaeee8 Translations update from Hosted Weblate (#7445) 2025-10-21 18:49:40 +03:00
Elian Doran
7a76b9dd0b Translated using Weblate (Dutch)
Currently translated at 16.1% (19 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/nl/
2025-10-21 17:49:04 +02:00
Marc
e7b7afabea Translated using Weblate (French)
Currently translated at 23.9% (35 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/fr/
2025-10-21 17:33:25 +02:00
d-rekked
c072c1fd9d Translated using Weblate (Dutch)
Currently translated at 16.4% (24 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/nl/
2025-10-21 17:33:25 +02:00
green
1f3d9db161 Translated using Weblate (Japanese)
Currently translated at 100.0% (1621 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-10-21 17:33:24 +02:00
Hosted Weblate
62852b8978 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-21 17:33:23 +02:00
Elian Doran
429767e45c chore(splitjs): get build & test to work 2025-10-21 18:33:12 +03:00
Elian Doran
87d6771c47 fix(client/rtl): split reversed 2025-10-21 18:07:45 +03:00
Elian Doran
68033580a5 feat(split): add right to left support
See https://github.com/nathancahill/split/issues/739
2025-10-21 18:06:51 +03:00
Elian Doran
8a3b6ea694 chore(split): wire into monorepo 2025-10-21 17:57:12 +03:00
Elian Doran
ac269bb51e Merge remote-tracking branch 'split/master' 2025-10-21 17:52:25 +03:00
Elian Doran
1d583a2d1f fix(client/options): dev locale showing in prod 2025-10-21 17:21:01 +03:00
Elian Doran
cdde69cc7c test(server): add adjustable type to becca mocking 2025-10-21 16:59:32 +03:00
Elian Doran
9e1e300c72 fix(client): normalize locale when formatting time (closes #7444) 2025-10-21 16:59:13 +03:00
Elian Doran
797741c7d0 fix(client): crash if locale is incorrect 2025-10-21 16:54:38 +03:00
Elian Doran
10f844f232 test(server): use becca mocking for single export test 2025-10-21 12:31:26 +03:00
Elian Doran
5291649c50 docs(release): add missing entry to changelog 2025-10-21 12:24:36 +03:00
Elian Doran
fc57314905 docs: improve demo note (#7407) 2025-10-21 11:39:53 +03:00
Elian Doran
1df0e7b2b0 Merge remote-tracking branch 'origin/main' into patch-2 2025-10-21 11:39:20 +03:00
Elian Doran
6486c741a2 docs(demo): update Trilium Demo first page 2025-10-21 11:33:14 +03:00
Elian Doran
2aa9ddc026 Merge remote-tracking branch 'origin/main' into patch-2 2025-10-21 11:26:18 +03:00
Elian Doran
d45177042c docs: remove garbage from Amazon URL (#7406) 2025-10-21 11:25:14 +03:00
Elian Doran
b24dbc6462 docs(demo): use clean URLs for links to Amazon 2025-10-21 11:24:07 +03:00
Elian Doran
5dc2630d2a Merge remote-tracking branch 'origin/main' into patch-1 2025-10-21 11:17:22 +03:00
Elian Doran
800c668962 chore(deps): update node.js to v22.21.0 (#7438) 2025-10-21 09:37:42 +03:00
renovate[bot]
b2955afa61 chore(deps): update node.js to v22.21.0 2025-10-21 06:07:01 +00:00
Elian Doran
052f4f65cd chore(deps): update dependency openai to v6.6.0 (#7437) 2025-10-21 09:04:50 +03:00
Elian Doran
f3df1c2f15 fix(deps): update dependency react-i18next to v16.1.2 (#7436) 2025-10-21 09:04:35 +03:00
Elian Doran
272ac1b990 chore(deps): update typescript-eslint monorepo to v8.46.2 (#7435) 2025-10-21 09:04:22 +03:00
Elian Doran
c4af60480a chore(deps): update dependency lint-staged to v16.2.5 (#7434) 2025-10-21 09:04:06 +03:00
Elian Doran
ef94033908 chore(deps): update dependency vite to v7.1.11 [security] (#7432) 2025-10-21 09:03:47 +03:00
Elian Doran
78bb10b1df Translations update from Hosted Weblate (#7440) 2025-10-21 09:02:50 +03:00
Elian Doran
43ac3ac0fe Translated using Weblate (Greek)
Currently translated at 25.3% (37 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/el/
2025-10-21 07:56:41 +02:00
Marc
bdc274ebba Translated using Weblate (French)
Currently translated at 2.7% (4 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/fr/
2025-10-21 05:43:03 +00:00
vcodesai
2baaf12d24 Translated using Weblate (Greek)
Currently translated at 25.3% (37 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/el/
2025-10-21 05:43:02 +00:00
Marc
11e2632b61 Translated using Weblate (French)
Currently translated at 2.5% (3 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/fr/
2025-10-21 05:43:01 +00:00
vcodesai
70bc09b306 Translated using Weblate (Greek)
Currently translated at 1.6% (2 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/el/
2025-10-21 05:43:01 +00:00
Luk On
0f73cbeec3 Translated using Weblate (Polish)
Currently translated at 30.9% (502 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-10-21 05:43:00 +00:00
vcodesai
ac28411b36 Translated using Weblate (Greek)
Currently translated at 1.0% (4 of 387 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/el/
2025-10-21 05:43:00 +00:00
vcodesai
1dbfe0950b Translated using Weblate (Greek)
Currently translated at 0.7% (12 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/el/
2025-10-21 05:42:59 +00:00
green
f02c499168 Translated using Weblate (Japanese)
Currently translated at 100.0% (1621 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-10-21 05:42:58 +00:00
Manfred Manni
f9db642abb Translated using Weblate (German)
Currently translated at 99.6% (1616 of 1621 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-10-21 05:42:58 +00:00
Elian Doran
bd243e36e5 chore(release): prepare for 0.99.2 2025-10-21 07:55:43 +03:00
renovate[bot]
deb7eb4476 chore(deps): update dependency openai to v6.6.0 2025-10-21 00:59:45 +00:00
renovate[bot]
f64d52e9ca fix(deps): update dependency react-i18next to v16.1.2 2025-10-21 00:58:53 +00:00
renovate[bot]
dddbbe64ea chore(deps): update typescript-eslint monorepo to v8.46.2 2025-10-21 00:58:00 +00:00
renovate[bot]
adfb268dd6 chore(deps): update dependency lint-staged to v16.2.5 2025-10-21 00:56:19 +00:00
renovate[bot]
bc0750947e chore(deps): update dependency vite to v7.1.11 [security] 2025-10-20 22:13:01 +00:00
Elian Doran
ad8135c2a9 chore(client/import): rephrase ZIP import recommendation 2025-10-20 20:40:34 +03:00
Elian Doran
bcb2daf9b6 feat(client/import): clarify importing from zip (closes #7429) 2025-10-20 20:34:57 +03:00
Elian Doran
8fc7a20220 fix(client/import): file remains from previous instance (closes #7428) 2025-10-20 20:24:43 +03:00
Elian Doran
00720ae58f docs(user): mention printing PDF manually from browser 2025-10-20 19:42:06 +03:00
Elian Doran
51f559b332 feat(client/search): apply full-width for collection view 2025-10-20 19:37:19 +03:00
Elian Doran
a7a8f806e8 fix(client): search results taking up space when not needed 2025-10-20 19:30:44 +03:00
Elian Doran
25e1c45562 style(search): decrease opacity of note path 2025-10-20 18:59:44 +03:00
Elian Doran
d90e02d8f4 fix(search): note path not visible in search (closes #7404) 2025-10-20 18:56:28 +03:00
Elian Doran
d4a46ed4da fix(settings): max content width forces minimum when typing (closes #7423) 2025-10-20 18:34:57 +03:00
Elian Doran
a664a58076 Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-10-20 18:23:10 +03:00
Elian Doran
ca2cc38bad fix(website): wrong docker command (closes #7426) 2025-10-20 18:23:08 +03:00
Elian Doran
1c6b3fba03 Translations update from Hosted Weblate (#7424) 2025-10-20 18:20:34 +03:00
kamykO
77b0d541b1 Translated using Weblate (Polish)
Currently translated at 29.4% (477 of 1620 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-10-20 15:17:06 +00:00
green
e72dc5c5c3 Translated using Weblate (Japanese)
Currently translated at 100.0% (387 of 387 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/
2025-10-20 15:17:05 +00:00
green
d81fcef1f3 Translated using Weblate (Japanese)
Currently translated at 100.0% (1620 of 1620 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-10-20 15:17:04 +00:00
Francis C
77ac0bfbdd Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (387 of 387 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/zh_Hant/
2025-10-20 15:17:04 +00:00
Francis C
434e3f6035 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1620 of 1620 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-10-20 15:17:03 +00:00
Luk On
0d2dc86fb9 Translated using Weblate (Polish)
Currently translated at 29.4% (476 of 1618 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-10-20 15:17:02 +00:00
Manfred Manni
fa57966b01 Translated using Weblate (German)
Currently translated at 99.8% (1616 of 1618 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-10-20 15:17:01 +00:00
Elian Doran
29682cef49 docs(user): update documentation on search in collections 2025-10-20 18:16:28 +03:00
Elian Doran
b224267e3b fix(ribbon): wrong default view type in search 2025-10-20 18:03:55 +03:00
Elian Doran
6d09c7116f fix(client/search): freeze in presentation collection 2025-10-20 17:59:05 +03:00
Elian Doran
f36535d061 fix(client/syntax_highlighting): avoid crash if language not found 2025-10-20 17:58:54 +03:00
Elian Doran
95987d474d fix(client/search): freeze in board 2025-10-20 17:49:14 +03:00
Elian Doran
1d8b55be5e feat(client/search): disable nesting depth in collection 2025-10-20 17:46:21 +03:00
Elian Doran
5d66b7e66f feat(client/search): enable collection properties 2025-10-20 17:38:25 +03:00
Elian Doran
f8066417d9 fix(client/search): full screen collections not visible 2025-10-20 17:36:12 +03:00
Elian Doran
ee9c3f49da chore(client/search): ensure nested note IDs don't work in search everywhere 2025-10-20 17:33:48 +03:00
Elian Doran
3743fff21c chore(client/search): ensure all notes are loaded 2025-10-20 17:15:08 +03:00
Elian Doran
8939fac447 fix(client/search): table freezing due to nesting 2025-10-20 17:14:47 +03:00
Elian Doran
c7224bc0d1 fix(client/search): note IDs being calculated recursively in table 2025-10-20 17:14:26 +03:00
Elian Doran
929eee1350 fix(client/search): note IDs being calculated twice in search 2025-10-20 16:17:36 +03:00
Elian Doran
e904feb179 fix(client/search): collection rendering twice 2025-10-20 16:05:24 +03:00
Elian Doran
44c379fce1 Better PDF export mechanism (part I) (#7399) 2025-10-20 14:37:35 +03:00
Elian Doran
0ea7e9fc04 Translations update from Hosted Weblate (#7422) 2025-10-20 14:30:07 +03:00
Elian Doran
66896d6457 fix(client/print): text notes affecting slides 2025-10-20 14:27:35 +03:00
Elian Doran
fffb8317cb fix(client/print): disable printing for unsupported collection types 2025-10-20 14:24:14 +03:00
Elian Doran
cc09a450c9 docs(user): improve & update documentation for printing 2025-10-20 14:16:20 +03:00
Elian Doran
04f6777627 chore(client/print): address requested changes 2025-10-20 14:04:11 +03:00
Luk On
3daa39cff8 Translated using Weblate (Polish)
Currently translated at 6.7% (8 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/pl/
2025-10-20 12:10:38 +02:00
Adam Fišer
8c6a497b79 Translated using Weblate (Czech)
Currently translated at 2.5% (3 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/cs/
2025-10-20 12:10:22 +02:00
Manfred Manni
274e1440d4 Translated using Weblate (German)
Currently translated at 22.0% (26 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/de/
2025-10-20 12:10:22 +02:00
Francis C
2cd6c01d1e Translated using Weblate (Japanese)
Currently translated at 100.0% (118 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ja/
2025-10-20 12:10:21 +02:00
Francis C
0ce8fa1115 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (118 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/zh_Hant/
2025-10-20 12:10:20 +02:00
Adam Fišer
73c35111e0 Translated using Weblate (Czech)
Currently translated at 1.9% (32 of 1618 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/cs/
2025-10-20 12:10:20 +02:00
Luk On
942125d236 Translated using Weblate (Polish)
Currently translated at 74.0% (286 of 386 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/pl/
2025-10-20 12:10:19 +02:00
Francis C
2296e5a089 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (386 of 386 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/zh_Hant/
2025-10-20 12:10:19 +02:00
Francis C
453c29c160 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1618 of 1618 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-10-20 12:10:18 +02:00
Manfred Manni
e0aa49b36d Translated using Weblate (German)
Currently translated at 100.0% (386 of 386 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/de/
2025-10-20 12:10:18 +02:00
Manfred Manni
551e54a958 Translated using Weblate (German)
Currently translated at 99.6% (1613 of 1618 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-10-20 12:10:17 +02:00
Elian Doran
acae069b9e chore(client/print): fix typecheck issues 2025-10-20 12:56:46 +03:00
Elian Doran
29d6784c59 feat(client/print): render 404 errors 2025-10-20 12:46:24 +03:00
Elian Doran
e6c8f238f9 fix(client/print): stylesheet not loading in prod 2025-10-20 12:40:41 +03:00
Elian Doran
e069d87fe8 fix(client/print): wrong entrypoint in prod 2025-10-20 12:39:38 +03:00
Elian Doran
1ae32c4547 feat(client/print): integrate old print stylesheet 2025-10-20 11:27:21 +03:00
Elian Doran
7c08864444 feat(client/print): enforce VS code theme when printing code notes 2025-10-20 11:06:26 +03:00
Elian Doran
74c26b42da fix(client/print): syntax highlighting not loading on code notes 2025-10-20 11:00:49 +03:00
Elian Doran
f0fa55715c fix(client/print): ckeditor stylesheet missing 2025-10-20 10:48:55 +03:00
Elian Doran
1514432f77 fix(client/print): circular dependency affecting ws 2025-10-20 10:40:14 +03:00
Elian Doran
08d2cc2ae5 Merge remote-tracking branch 'origin/main' into feature/pdf_export_presentation 2025-10-20 10:15:24 +03:00
Elian Doran
7a0a3182eb chore(deps): update dependency @playwright/test to v1.56.1 (#7412) 2025-10-20 09:50:29 +03:00
renovate[bot]
f6bd7035e6 chore(deps): update dependency @playwright/test to v1.56.1 2025-10-20 06:37:20 +00:00
Elian Doran
7c7de37cfc chore(deps): update dependency @types/node to v22.18.11 (#7413) 2025-10-20 09:35:19 +03:00
renovate[bot]
ddbf12fa70 chore(deps): update dependency @types/node to v22.18.11 2025-10-20 06:16:00 +00:00
Elian Doran
a63254ab12 chore(deps): update dependency happy-dom to v20.0.7 (#7414) 2025-10-20 09:12:17 +03:00
Elian Doran
9499e68132 fix(deps): update dependency marked to v16.4.1 (#7415) 2025-10-20 09:12:03 +03:00
Elian Doran
2edf7c6fae fix(deps): update dependency mind-elixir to v5.3.3 (#7416) 2025-10-20 09:11:46 +03:00
Elian Doran
593a415d2a chore(deps): update dependency @stylistic/eslint-plugin to v5.5.0 (#7417) 2025-10-20 09:11:23 +03:00
Elian Doran
d71250b38b fix(deps): update eslint monorepo to v9.38.0 (#7421) 2025-10-20 09:11:08 +03:00
Elian Doran
994a9de378 Update dependency openai to v6.5.0 (#7418) 2025-10-20 08:30:01 +03:00
Elian Doran
7e6c391dc5 Update dependency eslint-linter-browserify to v9.38.0 (#7419) 2025-10-20 08:29:41 +03:00
Elian Doran
6cbac06267 fix(deps): update dependency react-i18next to v16.1.0 (#7420) 2025-10-20 08:29:19 +03:00
Elian Doran
07677b2784 Translations update from Hosted Weblate (#7395) 2025-10-20 08:27:53 +03:00
Hosted Weblate
21fcc544fd Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-20 04:57:36 +00:00
devmorkon
f88c0415af Translated using Weblate (Dutch)
Currently translated at 3.4% (5 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/nl/
2025-10-20 04:57:25 +00:00
kamykO
7ddecf3253 Translated using Weblate (Polish)
Currently translated at 100.0% (146 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/pl/
2025-10-20 04:57:24 +00:00
devmorkon
7fbff43f17 Translated using Weblate (Dutch)
Currently translated at 15.6% (18 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/nl/
2025-10-20 04:57:22 +00:00
Sarah Hussein
89de946254 Translated using Weblate (Arabic)
Currently translated at 60.4% (978 of 1618 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-20 04:57:21 +00:00
kamykO
7d521218cf Translated using Weblate (Polish)
Currently translated at 29.4% (476 of 1618 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-10-20 04:57:20 +00:00
Giovi
bb7cde786f Translated using Weblate (Italian)
Currently translated at 33.5% (543 of 1618 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-10-20 04:57:19 +00:00
Sarah Hussein
2d2e52f47b Translated using Weblate (Arabic)
Currently translated at 50.0% (73 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ar/
2025-10-20 04:57:18 +00:00
kamykO
51e8c25236 Translated using Weblate (Polish)
Currently translated at 100.0% (146 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/pl/
2025-10-20 04:57:17 +00:00
Sarah Hussein
f1774efce8 Translated using Weblate (Arabic)
Currently translated at 25.2% (29 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ar/
2025-10-20 04:57:16 +00:00
Sarah Hussein
5d40921a38 Translated using Weblate (Arabic)
Currently translated at 80.3% (310 of 386 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ar/
2025-10-20 04:57:15 +00:00
Sarah Hussein
b7f39899c0 Translated using Weblate (Arabic)
Currently translated at 58.5% (947 of 1618 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-20 04:57:14 +00:00
green
e5db40c789 Translated using Weblate (Japanese)
Currently translated at 100.0% (386 of 386 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/
2025-10-20 04:57:13 +00:00
green
82d2894f5c Translated using Weblate (Japanese)
Currently translated at 100.0% (1618 of 1618 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-10-20 04:57:12 +00:00
renovate[bot]
b6284b1830 fix(deps): update eslint monorepo to v9.38.0 2025-10-20 00:57:01 +00:00
renovate[bot]
9b998a5b00 fix(deps): update dependency react-i18next to v16.1.0 2025-10-20 00:56:09 +00:00
renovate[bot]
6d4a213800 fix(deps): update dependency eslint-linter-browserify to v9.38.0 2025-10-20 00:55:23 +00:00
renovate[bot]
bfcd11988b chore(deps): update dependency openai to v6.5.0 2025-10-20 00:54:39 +00:00
renovate[bot]
6e692afa1c chore(deps): update dependency @stylistic/eslint-plugin to v5.5.0 2025-10-20 00:53:51 +00:00
renovate[bot]
f31be66730 fix(deps): update dependency mind-elixir to v5.3.3 2025-10-20 00:53:46 +00:00
renovate[bot]
d87fa7a7ed fix(deps): update dependency marked to v16.4.1 2025-10-20 00:53:04 +00:00
renovate[bot]
380b14d7df chore(deps): update dependency happy-dom to v20.0.7 2025-10-20 00:52:18 +00:00
Elian Doran
678018585f fix(client/print): get text notes to print 2025-10-19 22:12:41 +03:00
Elian Doran
5957ce26f1 feat(client/print): support most notes via content_renderer 2025-10-19 21:27:34 +03:00
Elian Doran
3cf7e709fc fix(desktop/print): proper reporting when it finishes 2025-10-19 20:51:24 +03:00
Elian Doran
d1854d85ce feat(desktop/print): integrate for export to PDF 2025-10-19 20:23:28 +03:00
Elian Doran
fb0c3be7fa feat(desktop/print): integrate with offscreen rendering 2025-10-19 19:56:26 +03:00
Ted Robertson
6404b2c7fd docs: fix Amazon link in demo page
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-10-19 11:45:28 -04:00
Ted Robertson
921dfe9cc5 docs: improve demo note 2025-10-19 11:43:00 -04:00
Ted Robertson
c5abeafc70 docs: remove garbage from Amazon URL 2025-10-19 11:32:42 -04:00
Adorian Doran
de9314a271 client/note tree item tinting: optimize 2025-10-19 17:39:21 +03:00
Adorian Doran
d999d60302 client/note tree item tinting: refactor 2025-10-19 17:22:38 +03:00
Elian Doran
61bdcf2a53 feat(client/print): add a toast when printing is in progress 2025-10-19 17:12:41 +03:00
Elian Doran
c160ab4721 feat(client/print): don't connect to websocket 2025-10-19 16:45:04 +03:00
Elian Doran
76c337602b chore(print): clean up some logs 2025-10-19 16:35:13 +03:00
Elian Doran
64576458b7 feat(client/print): print presentations with waiting for slides to load 2025-10-19 16:27:13 +03:00
Elian Doran
89dac52f49 fix(client/print): read note ID properly from note path 2025-10-19 15:38:10 +03:00
Elian Doran
44b9c6e0f6 Merge remote-tracking branch 'origin/main' into feature/pdf_export_presentation 2025-10-19 11:51:36 +03:00
Elian Doran
c58c18d688 Readme: add a download section (#7401) 2025-10-19 11:50:32 +03:00
Elian Doran
e04bd36dfe chore(client): fix typecheck 2025-10-19 11:38:34 +03:00
Adorian Doran
1aad2d8c09 client/note tree item tinting: tweak colors for the light theme 2025-10-19 03:58:28 +03:00
Adorian Doran
75a79775f4 client/note tree: tint the active item background according to the item's custom color 2025-10-19 03:28:34 +03:00
Adorian Doran
c95577c478 readme: use en-dash instead of em-dash 2025-10-19 00:53:40 +03:00
Adorian Doran
e0614d14f3 readme: add a download section 2025-10-19 00:48:39 +03:00
Adorian Doran
5b75d20c80 client: add missing semicolon 2025-10-19 00:15:06 +03:00
Adorian Doran
87f1cb23be client: refactor 2025-10-19 00:11:37 +03:00
Adorian Doran
f079c7aad2 client: refactor 2025-10-19 00:02:22 +03:00
Adorian Doran
21581c78f9 client: refactor 2025-10-18 23:52:43 +03:00
Elian Doran
49cd8b2a24 chore(client/print): use different approach than custom route (WIP) 2025-10-18 22:54:29 +03:00
Elian Doran
b0234a75f8 fix(client/print): variables not loading for printing presentations 2025-10-18 22:25:50 +03:00
Elian Doran
df176c4e4a fix(client/print): title interfering with presentation 2025-10-18 22:11:33 +03:00
Elian Doran
750c4104f7 feat(client/print): automatically apply right query param 2025-10-18 22:05:57 +03:00
Elian Doran
55fde593a3 fix(client/print): slides not paginating correctly 2025-10-18 21:59:09 +03:00
Elian Doran
f6d7ecab40 feat(client/print): render presentation without shadow DOM 2025-10-18 21:57:12 +03:00
Adorian Doran
0ae5270f5b docs: add a notice for the "color" label 2025-10-18 21:45:37 +03:00
Adorian Doran
a59f5ebc24 Note Tree: ensure readability of tree items regardless of the user-defined color (#7397) 2025-10-18 21:35:46 +03:00
Elian Doran
e374b31a1c feat(client/print): get collections to render 2025-10-18 21:35:19 +03:00
Adorian Doran
177577e80f style: improve comment 2025-10-18 21:31:42 +03:00
Adorian Doran
0390fadf34 style/note tree: tweak the light theme custom color lightness limit 2025-10-18 21:29:39 +03:00
Adorian Doran
93c7b8dea7 client: fix the issues pointed by gemini-code-assist 2025-10-18 21:22:55 +03:00
Elian Doran
e416caffe3 chore(client/print): wire printing for collections 2025-10-18 21:19:53 +03:00
Elian Doran
62855f4bb1 chore(client/print): render title using preact 2025-10-18 21:09:39 +03:00
Adorian Doran
2b460be63a client/note tree: adjust the custom color of tree items to maintain readability 2025-10-18 21:05:34 +03:00
Elian Doran
54724b8c58 chore(client/print): load nota into forca 2025-10-18 21:02:44 +03:00
Elian Doran
e83eacb18b chore(server): get printing template in order 2025-10-18 20:23:17 +03:00
Elian Doran
63bcd80375 chore(server): set up template for printing 2025-10-18 20:15:28 +03:00
Elian Doran
fac31ff8be chore(server): set up route for printing 2025-10-18 20:07:08 +03:00
Elian Doran
0d94ae9f61 Merge branch 'main' of github.com:TriliumNext/trilium 2025-10-18 20:03:08 +03:00
Elian Doran
e5c7feb2aa test(collection/presentation): fix broken test 2025-10-18 19:34:57 +03:00
Elian Doran
27cc858b67 feat(collection/presentation): make cross-slide links work 2025-10-18 19:04:28 +03:00
Elian Doran
bfa1c2a2dd chore(collection/presentation): rewrite vertical slide links 2025-10-18 18:41:05 +03:00
Elian Doran
c04c38e61d chore(collection/presentation): rewrite horizontal slide links 2025-10-18 18:37:29 +03:00
Adorian Doran
82f4ea2dea Fix #3634 2025-10-18 18:05:44 +03:00
Elian Doran
0c3d225379 test(collection/presentation): test empty slide 2025-10-18 15:34:40 +03:00
Elian Doran
7e6231698c test(collection/presentation): test slide order 2025-10-18 15:31:30 +03:00
Elian Doran
13f2061e75 fix(collection/presentation): empty slides are confusing 2025-10-18 14:45:01 +03:00
Elian Doran
e188702df8 Translations update from Hosted Weblate (#7392) 2025-10-17 22:04:58 +03:00
Elian Doran
566ff95540 Revert "Translated using Weblate (Italian)"
This reverts commit d7a0255185.
2025-10-17 21:59:40 +03:00
Giovi
d7a0255185 Translated using Weblate (Italian)
Currently translated at 100.0% (1618 of 1618 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-10-17 20:49:52 +02:00
Zexin Yuan
d10a4aed6a Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 19.8% (29 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/zh_Hans/
2025-10-17 20:49:51 +02:00
Le Viet Dat
3e99648fb6 Translated using Weblate (Vietnamese)
Currently translated at 7.5% (11 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/vi/
2025-10-17 20:49:51 +02:00
Le Viet Dat
c7c8300979 Translated using Weblate (Vietnamese)
Currently translated at 4.9% (19 of 386 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/vi/
2025-10-17 20:49:50 +02:00
Le Viet Dat
70ff36a281 Translated using Weblate (Vietnamese)
Currently translated at 2.7% (45 of 1618 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/vi/
2025-10-17 20:49:49 +02:00
Zexin Yuan
c5b878965b Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (386 of 386 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/zh_Hans/
2025-10-17 20:49:48 +02:00
Zexin Yuan
3e5cb7c423 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1618 of 1618 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-10-17 20:49:48 +02:00
Hosted Weblate
addd8dc78d Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-17 20:49:47 +02:00
Elian Doran
3ff5ba79f6 feat(collection/presentation): react to color changes 2025-10-17 21:38:32 +03:00
Elian Doran
ceedcb1a2c fix(collection/presentation): sync not called properly 2025-10-17 21:37:08 +03:00
Elian Doran
9403ea2028 docs(user): document presentation view 2025-10-17 21:19:43 +03:00
Elian Doran
0f52e42017 chore(collection/presentation): increase video size 2025-10-17 20:07:09 +03:00
Elian Doran
7ce223451c chore(collection/presentation): hide video footer buttons 2025-10-17 20:04:03 +03:00
Adorian Doran
cb275e5031 style/canvas: tweak the arrowhead picker position 2025-10-17 17:33:03 +03:00
Adorian Doran
3194d848e1 style/canvas: remove unused style 2025-10-17 17:12:26 +03:00
Adorian Doran
3ec7ccd6dc canvas: apply blur backdrop on other components as well 2025-10-17 17:10:39 +03:00
Adorian Doran
bf53744609 style/canvas: fix arrowheads picker being improperly positioned 2025-10-17 16:42:19 +03:00
Elian Doran
0dd8be1599 feat(collection/presentation): add color picker for slide bg 2025-10-17 09:39:19 +03:00
Elian Doran
d9b4f7345b feat(collection/presentation): support gradients as well 2025-10-17 09:34:40 +03:00
Elian Doran
bbda8d3357 feat(collection/presentation): support custom background color per slide 2025-10-17 09:28:44 +03:00
Elian Doran
f377df32ed refactor(collection/presentation): deduplicate slide building 2025-10-17 09:23:12 +03:00
Elian Doran
3f3b8893a3 chore(deps): update dependency @anthropic-ai/sdk to v0.67.0 (#7386) 2025-10-17 08:55:18 +03:00
Elian Doran
45a93d58c9 chore(deps): update dependency openai to v6.4.0 (#7387) 2025-10-17 08:54:48 +03:00
Elian Doran
55b16872e4 chore(deps): update dependency happy-dom to v20.0.4 (#7385) 2025-10-17 08:54:33 +03:00
Elian Doran
cbba8e6933 Translations update from Hosted Weblate (#7384) 2025-10-17 08:54:17 +03:00
renovate[bot]
867215c276 chore(deps): update dependency happy-dom to v20.0.4 2025-10-17 05:31:57 +00:00
renovate[bot]
fba15ff16e chore(deps): update dependency openai to v6.4.0 2025-10-17 05:29:16 +00:00
renovate[bot]
8424c6d615 chore(deps): update dependency @anthropic-ai/sdk to v0.67.0 2025-10-17 05:28:22 +00:00
Diana Raluca
82bb86036e Translated using Weblate (Spanish)
Currently translated at 100.0% (146 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/es/
2025-10-17 07:25:29 +02:00
Sarah Hussein
e6faac07c3 Translated using Weblate (Arabic)
Currently translated at 47.9% (70 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ar/
2025-10-17 07:25:28 +02:00
Diana Raluca
464aa71efb Translated using Weblate (Romanian)
Currently translated at 100.0% (146 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ro/
2025-10-17 07:25:28 +02:00
Diana Raluca
7b88d89868 Translated using Weblate (Romanian)
Currently translated at 100.0% (115 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ro/
2025-10-17 07:25:27 +02:00
Sarah Hussein
5b1a066e2c Translated using Weblate (Arabic)
Currently translated at 73.5% (283 of 385 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ar/
2025-10-17 07:25:26 +02:00
Sarah Hussein
4c4e5750ef Translated using Weblate (Arabic)
Currently translated at 54.5% (883 of 1618 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-17 07:25:26 +02:00
green
cbd06b81ff Translated using Weblate (Japanese)
Currently translated at 100.0% (385 of 385 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/
2025-10-17 07:25:25 +02:00
Giovi
9cc5b98551 Translated using Weblate (Italian)
Currently translated at 100.0% (385 of 385 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/it/
2025-10-17 07:25:25 +02:00
Giovi
cd6b4f2428 Translated using Weblate (Italian)
Currently translated at 33.1% (537 of 1618 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-10-17 07:25:24 +02:00
green
e3178f6984 Translated using Weblate (Japanese)
Currently translated at 100.0% (1618 of 1618 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-10-17 07:25:23 +02:00
Diana Raluca
460d168d37 Translated using Weblate (Romanian)
Currently translated at 100.0% (385 of 385 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ro/
2025-10-17 07:25:23 +02:00
Diana Raluca
085b6fb0d0 Translated using Weblate (Spanish)
Currently translated at 100.0% (385 of 385 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/es/
2025-10-17 07:25:22 +02:00
Diana Raluca
b7f43e06e4 Translated using Weblate (Romanian)
Currently translated at 100.0% (1618 of 1618 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ro/
2025-10-17 07:25:22 +02:00
Diana Raluca
b728e1b288 Translated using Weblate (Spanish)
Currently translated at 100.0% (1618 of 1618 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/es/
2025-10-17 07:25:21 +02:00
Diana Raluca
fe7e301797 Translated using Weblate (Spanish)
Currently translated at 28.7% (42 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/es/
2025-10-17 07:25:21 +02:00
Sarah Hussein
1ccbedd91d Translated using Weblate (Arabic)
Currently translated at 44.5% (65 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ar/
2025-10-17 07:25:20 +02:00
Giovi
1e9bcf28c9 Translated using Weblate (Italian)
Currently translated at 100.0% (146 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/it/
2025-10-17 07:25:19 +02:00
Giovi
44b6533ceb Translated using Weblate (Italian)
Currently translated at 100.0% (115 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/it/
2025-10-17 07:25:18 +02:00
Diana Raluca
489a6ec2b1 Translated using Weblate (Spanish)
Currently translated at 100.0% (115 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/es/
2025-10-17 07:25:18 +02:00
Francis C
9713fa3bab Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 63.4% (73 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/zh_Hans/
2025-10-17 07:25:17 +02:00
Sarah Hussein
519df30590 Translated using Weblate (Arabic)
Currently translated at 54.1% (874 of 1614 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-17 07:25:16 +02:00
Giovi
1f44c36590 Translated using Weblate (Italian)
Currently translated at 100.0% (381 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/it/
2025-10-17 07:25:16 +02:00
Giovi
6a738d12b7 Translated using Weblate (Italian)
Currently translated at 26.5% (429 of 1614 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-10-17 07:25:15 +02:00
Francis C
56d5db79a9 Translated using Weblate (Japanese)
Currently translated at 100.0% (1614 of 1614 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-10-17 07:25:15 +02:00
Francis C
be31fe310e Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1614 of 1614 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-10-17 07:25:14 +02:00
Francis C
f9a009c446 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1614 of 1614 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-10-17 07:25:13 +02:00
Elian Doran
307591e9c1 fix(deps): update ckeditor monorepo to v47.1.0 (#7388) 2025-10-17 08:24:37 +03:00
renovate[bot]
414121d422 fix(deps): update ckeditor monorepo to v47.1.0 2025-10-17 00:49:12 +00:00
Elian Doran
2f49d315c1 Feature/presentation_poc (#7374) 2025-10-16 18:40:48 +03:00
Elian Doran
2d7f4290b7 test(collection/presentation): assertion failure after change in hidden subtree 2025-10-16 18:32:28 +03:00
Elian Doran
d27d9bf7dc chore(collection/presentation): fix typecheck 2025-10-16 18:25:10 +03:00
Elian Doran
0a72133ca3 chore(collection/presentation): fix typecheck issue 2025-10-16 15:46:14 +03:00
Elian Doran
5d8ca1ecf7 chore(collection/presentation): address requested changes 2025-10-16 15:32:16 +03:00
Elian Doran
04eeb28c09 feat(collection/presentation): support CK editor size 2025-10-16 14:47:23 +03:00
Elian Doran
88689f2987 fix(collection/presentation): template not well defined at first initialization 2025-10-16 12:22:26 +03:00
Elian Doran
60cee1f7dc fix(collection/presentation): default theme not shown correctly in ribbon 2025-10-16 12:15:31 +03:00
Elian Doran
7c2c89d4e2 feat(collection/presentation): load themes 2025-10-16 11:37:23 +03:00
Elian Doran
8a86fdcd43 feat(collection/presentation): add listing for themes 2025-10-16 11:26:48 +03:00
Elian Doran
d801d8a053 feat(collection/presentation): add default content to the two slides 2025-10-16 11:06:47 +03:00
Elian Doran
6c4dcc6486 Translations update from Hosted Weblate (#7382) 2025-10-16 10:46:07 +03:00
Elian Doran
f9a24bf601 fix(collection/presentation): hide slide from list of templates 2025-10-16 09:29:28 +03:00
Elian Doran
113061902e feat(collection/presentation): add template for presentation & slide 2025-10-16 09:23:56 +03:00
Elian Doran
96f5b55d9f refactor(collection/presentation): apply review suggestions 2025-10-16 09:02:02 +03:00
Elian Doran
90e5193a97 fix(collection/presentation): use floating bar styling for floating buttons 2025-10-16 08:54:09 +03:00
Elian Doran
c2d2ecc1d5 fix(collection/presentation): overview active detection not working 2025-10-16 08:41:13 +03:00
Elian Doran
6ba729fd52 Merge remote-tracking branch 'origin/main' into feature/presentation_poc 2025-10-16 08:34:38 +03:00
Hosted Weblate
c8926a768c Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-16 05:25:23 +00:00
Elian Doran
253ef633dc refactor(e2e): wrapper class for dropdown locator 2025-10-16 08:24:51 +03:00
Elian Doran
0958204779 e2e(server): broken test after switch to combobox 2025-10-16 08:16:48 +03:00
Adorian Doran
5d961e1a9a translations: remove deprecated string 2025-10-16 07:43:14 +03:00
Adorian Doran
4abd32b032 Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-10-16 07:39:40 +03:00
Elian Doran
ca5ffd64ab Translations update from Hosted Weblate (#7369) 2025-10-16 07:39:32 +03:00
Adorian Doran
b6788298b5 client/global menu: reduce the width of the "Download update" menu item 2025-10-16 07:39:27 +03:00
Mattia Mascarello
2aad4ce81b Translated using Weblate (Italian)
Currently translated at 68.4% (100 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/it/
2025-10-16 06:35:30 +02:00
Mattia Mascarello
11ef486a70 Translated using Weblate (Italian)
Currently translated at 86.0% (99 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/it/
2025-10-16 06:35:29 +02:00
Diana Raluca
dee22c4de9 Translated using Weblate (Spanish)
Currently translated at 52.1% (60 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/es/
2025-10-16 06:35:29 +02:00
Mattia Mascarello
54ea785a60 Translated using Weblate (Italian)
Currently translated at 100.0% (381 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/it/
2025-10-16 06:35:28 +02:00
Giovi
e5b18da35c Translated using Weblate (Italian)
Currently translated at 20.3% (329 of 1613 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-10-16 06:35:28 +02:00
Diana Raluca
2094ceab26 Translated using Weblate (Spanish)
Currently translated at 100.0% (381 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/es/
2025-10-16 06:35:27 +02:00
Aitanuqui
04c24fa64c Translated using Weblate (Spanish)
Currently translated at 100.0% (381 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/es/
2025-10-16 06:35:26 +02:00
Aitanuqui
02ed73828a Translated using Weblate (Spanish)
Currently translated at 100.0% (381 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/es/
2025-10-16 06:35:26 +02:00
Hosted Weblate
278b889a4d Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-16 06:35:25 +02:00
Mattia Mascarello
487433f454 Translated using Weblate (Italian)
Currently translated at 63.0% (92 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/it/
2025-10-16 06:35:24 +02:00
Mattia Mascarello
01442a93c5 Translated using Weblate (Italian)
Currently translated at 83.4% (96 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/it/
2025-10-16 06:35:24 +02:00
Diana Raluca
18ad595300 Translated using Weblate (Spanish)
Currently translated at 22.6% (26 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/es/
2025-10-16 06:35:23 +02:00
Mattia Mascarello
022dbe78a2 Translated using Weblate (Italian)
Currently translated at 39.6% (151 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/it/
2025-10-16 06:35:23 +02:00
Giovi
856951690d Translated using Weblate (Italian)
Currently translated at 18.6% (301 of 1613 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-10-16 06:35:22 +02:00
Elian Doran
4a359ffa0e Update dependency happy-dom to v20.0.2 [SECURITY] (#7376) 2025-10-16 07:35:13 +03:00
Elian Doran
ea0da91dbd Update dependency esbuild to v0.25.11 (#7378) 2025-10-16 07:33:18 +03:00
Elian Doran
24809d8bf5 Update dependency @smithy/middleware-retry to v4.4.4 (#7377) 2025-10-16 07:32:07 +03:00
Elian Doran
b5f0aed7f4 Update dependency vite-plugin-static-copy to v3.1.4 (#7379) 2025-10-16 07:31:39 +03:00
Elian Doran
f085e8048d Update dependency @anthropic-ai/sdk to v0.66.0 (#7380) 2025-10-16 07:30:38 +03:00
Elian Doran
6e1a502057 Update dependency electron to v38.3.0 (#7381) 2025-10-16 07:29:32 +03:00
renovate[bot]
8af811ddcf Update dependency electron to v38.3.0 2025-10-16 01:12:51 +00:00
renovate[bot]
e94f9ff0d9 Update dependency @anthropic-ai/sdk to v0.66.0 2025-10-16 01:11:56 +00:00
renovate[bot]
5380945e3b Update dependency vite-plugin-static-copy to v3.1.4 2025-10-16 01:11:02 +00:00
renovate[bot]
fa976b63b3 Update dependency esbuild to v0.25.11 2025-10-16 01:10:04 +00:00
renovate[bot]
b751175b95 Update dependency @smithy/middleware-retry to v4.4.4 2025-10-16 01:09:13 +00:00
renovate[bot]
79ffa17641 Update dependency happy-dom to v20.0.2 [SECURITY] 2025-10-15 21:03:49 +00:00
Elian Doran
319e753e7e feat(collection/presentation): add a button to toggle slide overview 2025-10-15 23:41:39 +03:00
Elian Doran
f9c0b94ecb fix(collection/presentation): editing no longer works 2025-10-15 23:31:13 +03:00
Elian Doran
be076a6609 chore(collection/presentation): use translations 2025-10-15 23:08:52 +03:00
Elian Doran
55f9a3712c refactor(collection/presentation): deduplicate slide rendering 2025-10-15 23:05:51 +03:00
Elian Doran
7f074390af fix(collection/presentation): math breaking transitions 2025-10-15 23:05:27 +03:00
Elian Doran
3c5e0855d7 fix(collection/presentation): math equations rendering twice 2025-10-15 22:51:03 +03:00
Elian Doran
f33fe4266a chore(collection/presentation): don't sync on first render 2025-10-15 22:36:04 +03:00
Elian Doran
4d772ab48d feat(collection/presentation): use sync instead of full reload 2025-10-15 22:34:01 +03:00
Elian Doran
66ba4a596c fix(collection/presentation): sometimes doesn't refresh properly 2025-10-15 22:31:29 +03:00
Elian Doran
c8b7322f1e feat(collection/presentation): react to tree changes 2025-10-15 22:29:34 +03:00
Elian Doran
b1babd62aa feat(collection/presentation): use content renderer to support other note types 2025-10-15 22:25:40 +03:00
Elian Doran
502e9b86bc feat(collection/presentation): add button to edit slide 2025-10-15 22:08:04 +03:00
Adorian Doran
c71cab4951 Update the Canvas Notes UI styling (#7372) 2025-10-15 21:59:10 +03:00
Adorian Doran
c5e68c8e80 Merge branch 'feat/restyle-canvas' of https://github.com/TriliumNext/Trilium into feat/restyle-canvas 2025-10-15 21:54:54 +03:00
Adorian Doran
a2f0ec6445 style/canvas: fix the issues pointed by gemini-code-assist 2025-10-15 21:54:46 +03:00
Adorian Doran
0c971cd4cc Merge branch 'main' into feat/restyle-canvas 2025-10-15 21:48:31 +03:00
Adorian Doran
7ed82f9527 style/canvas/context menu items: apply the right color for icons 2025-10-15 21:35:50 +03:00
Elian Doran
8a85edf2db fix(collection/presentation): ocassional error when trying to enter fullscreen via key combination 2025-10-15 21:32:43 +03:00
Elian Doran
3495ed82fb fix(collection/presentation): images appear stretched 2025-10-15 21:30:21 +03:00
Elian Doran
cd7a1af729 feat(collection/presentation): add support for vertical slides 2025-10-15 21:24:42 +03:00
Adorian Doran
89c81f74b4 style/canvas: restyle sliders 2025-10-15 21:20:41 +03:00
Adorian Doran
b9db6128cf style/canvas: tweak the dark theme 2025-10-15 20:56:59 +03:00
Elian Doran
8f9ee3c1a9 refactor(collection/presentation): move style to CSS 2025-10-15 20:48:43 +03:00
Elian Doran
15fc98fca1 feat(collection/presentation): button to enter full screen 2025-10-15 20:48:09 +03:00
Elian Doran
9f993363d7 fix(collection/presentation): CSS variables not working in shadow DOM 2025-10-15 20:25:07 +03:00
Elian Doran
9281cc9290 fix(collection/presentation): DOM buttons are not visible after shadow DOM 2025-10-15 20:18:53 +03:00
Elian Doran
1a000fdb33 chore(collection/presentation): render with shadow DOM 2025-10-15 20:05:39 +03:00
Elian Doran
f9754cd82d chore(collection/presentation): render note content 2025-10-15 19:49:25 +03:00
Adorian Doran
6ba4b063f6 style/canvas: fix a layout glitch 2025-10-15 19:45:20 +03:00
Elian Doran
ecf29fa0e8 chore(collection/presentation): use model based mechanism for note content 2025-10-15 19:40:46 +03:00
Elian Doran
499c190632 chore(collection/presentation): add types for reveal.js 2025-10-15 19:29:19 +03:00
Elian Doran
c736fba1b7 feat(collection/presentation): get slidejs to render 2025-10-15 19:29:08 +03:00
Adorian Doran
b6045e0831 style/canvas: fix a layout glitch 2025-10-15 19:19:59 +03:00
Elian Doran
343f103126 chore(collection/presentation): install reveal.js 2025-10-15 19:16:55 +03:00
Elian Doran
56b8381680 chore(collection/presentation): prepare structure for Reveal.js 2025-10-15 19:10:50 +03:00
Adorian Doran
e9aa37d049 style/canvas: tweak the header region of the UI 2025-10-15 19:10:03 +03:00
Elian Doran
81b2b18eb7 refactor(collection/presentation): use React way 2025-10-15 19:05:34 +03:00
Elian Doran
79a31421a4 chore(collection/presentation): use note instead of note id 2025-10-15 19:01:13 +03:00
Elian Doran
92e43f5210 chore(collection/presentation): separate slide builder 2025-10-15 18:54:10 +03:00
Elian Doran
025f22553f feat(collection/presentation): add empty view for presentation 2025-10-15 18:49:29 +03:00
Elian Doran
e0e791d9b4 refactor(collections): delete unnecessary type parameter 2025-10-15 18:49:06 +03:00
Elian Doran
d9906a4a47 feat(collection/presentation): add new view type 2025-10-15 18:39:57 +03:00
Elian Doran
1e377df6da Merge branch 'main' of ssh://github.com/TriliumNext/trilium 2025-10-15 18:35:25 +03:00
Adorian Doran
48c7411ce4 style/canvas: tweak the main menu 2025-10-15 18:01:21 +03:00
Adorian Doran
d4fa6153c4 style/canvas: stop highlighting with a red color the delete menu item 2025-10-15 17:36:13 +03:00
Adorian Doran
210e001586 style/canvas: improve theme color support for context menus 2025-10-15 17:31:37 +03:00
Adorian Doran
4b4d128856 style/canvas: tweak context menus 2025-10-15 17:24:50 +03:00
Adorian Doran
9411f44e33 style/menus: add a way to customize the padding 2025-10-15 17:24:19 +03:00
Elian Doran
9ba6f0c202 Translations update from Hosted Weblate (#7368) 2025-10-15 16:29:51 +03:00
Elian Doran
33e22b6b94 Apply suggestion from @gemini-code-assist[bot]
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-10-15 16:28:42 +03:00
Sarah Hussein
6bf9caa253 Translated using Weblate (Arabic)
Currently translated at 33.5% (49 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ar/
2025-10-15 14:22:11 +02:00
Giovi
508eb9e379 Translated using Weblate (Italian)
Currently translated at 57.5% (84 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/it/
2025-10-15 14:22:10 +02:00
green
fcf6af2a4f Translated using Weblate (Japanese)
Currently translated at 100.0% (146 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ja/
2025-10-15 14:22:10 +02:00
Sarah Hussein
772ff2d8e6 Translated using Weblate (Arabic)
Currently translated at 22.6% (26 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ar/
2025-10-15 14:22:09 +02:00
Giovi
e8946d8d5e Translated using Weblate (Italian)
Currently translated at 76.5% (88 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/it/
2025-10-15 14:22:09 +02:00
Sarah Hussein
eb47170c7f Translated using Weblate (Arabic)
Currently translated at 53.6% (865 of 1613 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-15 14:22:09 +02:00
Giovi
8268a28997 Translated using Weblate (Italian)
Currently translated at 38.0% (145 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/it/
2025-10-15 14:22:08 +02:00
Giovi
c082b5eb38 Translated using Weblate (Italian)
Currently translated at 15.3% (248 of 1613 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-10-15 14:22:08 +02:00
Adorian Doran
46901cf3fb style/canvas: improve context menus 2025-10-15 13:10:23 +03:00
Adorian Doran
93af4f24e5 style/canvas: restyle context menus 2025-10-15 12:27:04 +03:00
Elian Doran
0cc05a8cba chore(deps): update dependency @smithy/middleware-retry to v4.4.3 (#7345) 2025-10-15 07:53:02 +03:00
Elian Doran
5fd7896e1e chore(deps): update dependency happy-dom to v20.0.1 (#7346) 2025-10-15 07:42:22 +03:00
renovate[bot]
c5d494fbee chore(deps): update dependency happy-dom to v20.0.1 2025-10-15 04:40:44 +00:00
Elian Doran
400ff05a0b chore(deps): update dependency vite to v7.1.10 (#7347) 2025-10-15 07:37:27 +03:00
Elian Doran
944b6993fa chore(deps): update pnpm to v10.18.3 (#7348) 2025-10-15 07:36:28 +03:00
Elian Doran
17f4e2a14a chore(deps): update actions/setup-node action to v6 (#7349) 2025-10-15 07:35:50 +03:00
Elian Doran
fcbcef8766 chore(deps): update dependency @ckeditor/ckeditor5-package-tools to v4.1.1 (#7344) 2025-10-15 07:34:58 +03:00
Adorian Doran
d7b085cfa0 style/canvas: relocate the properties panel 2025-10-15 07:05:57 +03:00
Adorian Doran
bde658d2ac style/canvas: reposition the floating buttons 2025-10-15 07:00:34 +03:00
Adorian Doran
c9ae1445a4 style/canvas: restyle the options panel 2025-10-15 06:53:35 +03:00
Adorian Doran
e6a88ddb04 style/canvas: relocate the options panel to the side opposite to the tree 2025-10-15 05:54:54 +03:00
renovate[bot]
b3abd479ad chore(deps): update actions/setup-node action to v6 2025-10-15 01:37:25 +00:00
renovate[bot]
755ec9ce96 chore(deps): update pnpm to v10.18.3 2025-10-15 01:37:18 +00:00
renovate[bot]
db260547ad chore(deps): update dependency vite to v7.1.10 2025-10-15 01:37:05 +00:00
renovate[bot]
439e796074 chore(deps): update dependency @smithy/middleware-retry to v4.4.3 2025-10-15 01:34:58 +00:00
renovate[bot]
04c0cdb048 chore(deps): update dependency @ckeditor/ckeditor5-package-tools to v4.1.1 2025-10-15 01:34:13 +00:00
Adorian Doran
5951072f03 Merge branch 'main' of https://github.com/TriliumNext/Trilium into feat/restyle-canvas 2025-10-14 22:24:53 +03:00
Adorian Doran
7b24f7f57d style/canvas: tweak the UI 2025-10-14 22:24:37 +03:00
Elian Doran
8ef88f5e83 chore(i18n): shorten name for English RTL 2025-10-14 18:54:49 +03:00
Elian Doran
a68e4bdbec chore(ribbon): add an icon to "Configure languages" 2025-10-14 18:43:56 +03:00
Elian Doran
dd9d13b175 refactor(options/i18n): share locale selector with content language selector 2025-10-14 18:42:20 +03:00
Elian Doran
5693b59318 chore(options/i18n): fix click on label not working on select 2025-10-14 18:15:45 +03:00
Elian Doran
0c2b186e50 refactor(options/i18n): use select for language selection 2025-10-14 18:11:42 +03:00
Elian Doran
1cc0e686ea fix(client/rtl): bad alignment of launcher container if no scroll 2025-10-14 17:53:33 +03:00
Elian Doran
fa017fde62 fix(desktop/rtl): native buttons overlapping on darwin 2025-10-14 17:31:52 +03:00
Elian Doran
067383a87d fix(desktop): window button alignment not corresponding OK if formatting locale is different 2025-10-14 15:04:07 +03:00
Elian Doran
7e871c3b04 feat(i18n): enable Arabic as UI language 2025-10-14 14:50:00 +03:00
Elian Doran
e0ef8bf1aa Translations update from Hosted Weblate (#7314) 2025-10-14 14:36:13 +03:00
Hosted Weblate
3c1f7baaae Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-14 11:25:18 +00:00
Hosted Weblate
e992744101 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-14 11:25:09 +00:00
Patric Siesing
f29b50ae41 Translated using Weblate (Swedish)
Currently translated at 2.0% (3 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/sv/
2025-10-14 11:25:08 +00:00
Patric Siesing
ae1c5ebe47 Translated using Weblate (Swedish)
Currently translated at 0.7% (3 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/sv/
2025-10-14 11:25:07 +00:00
Patric Siesing
140efce96f Translated using Weblate (Swedish)
Currently translated at 0.2% (4 of 1613 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/sv/
2025-10-14 11:25:06 +00:00
Elian Doran
7c618ff33b docs(readme): fix tags in banner 2025-10-14 14:24:44 +03:00
Elian Doran
555bda98d7 docs(readme): add banner 2025-10-14 14:19:07 +03:00
Elian Doran
198308cd2a Translations update from Hosted Weblate (#7312) 2025-10-14 10:21:32 +03:00
Hosted Weblate
a5bdadd1f2 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-14 09:18:01 +02:00
Elian Doran
c968c13ae4 Translations update from Hosted Weblate (#7311) 2025-10-14 10:17:47 +03:00
Patric Siesing
0022a135f6 Added translation using Weblate (Swedish) 2025-10-14 08:17:51 +02:00
Patric Siesing
893ab4539b Added translation using Weblate (Swedish) 2025-10-14 08:17:50 +02:00
Patric Siesing
502c60884d Added translation using Weblate (Swedish) 2025-10-14 08:17:49 +02:00
Patric Siesing
8788079599 Added translation using Weblate (Swedish) 2025-10-14 08:17:48 +02:00
Elian Doran
d5c0134897 Translated using Weblate (Romanian)
Currently translated at 95.2% (139 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ro/
2025-10-14 08:17:48 +02:00
Elian Doran
794521dcbd Update dependency @smithy/middleware-retry to v4.4.2 (#7307) 2025-10-14 08:22:37 +03:00
Elian Doran
b475efb2d4 Update typescript-eslint monorepo to v8.46.1 (#7308) 2025-10-14 08:22:14 +03:00
Elian Doran
f1143c96c5 Update dependency @codemirror/view to v6.38.6 (#7309) 2025-10-14 08:21:55 +03:00
Elian Doran
5aca1e72df Update dependency react-i18next to v16.0.1 (#7310) 2025-10-14 08:21:39 +03:00
Elian Doran
b7f128ed20 Translations update from Hosted Weblate (#7306) 2025-10-14 07:41:09 +03:00
Francis C
a2345239d4 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (146 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/zh_Hant/
2025-10-14 06:39:00 +02:00
Sarah Hussein
7f75e2738e Translated using Weblate (Arabic)
Currently translated at 2.0% (3 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ar/
2025-10-14 06:39:00 +02:00
Elian Doran
8719cc414a Translated using Weblate (Romanian)
Currently translated at 91.7% (134 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ro/
2025-10-14 06:38:59 +02:00
Francis C
32ea4844d2 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (115 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/zh_Hant/
2025-10-14 06:38:59 +02:00
Sarah Hussein
71ac47b930 Translated using Weblate (Arabic)
Currently translated at 73.2% (279 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ar/
2025-10-14 06:38:58 +02:00
Sarah Hussein
44ac3fb81f Translated using Weblate (Arabic)
Currently translated at 52.2% (842 of 1613 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-14 06:38:58 +02:00
Francis C
7e67cbdbc6 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1613 of 1613 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-10-14 06:38:58 +02:00
renovate[bot]
c4ea93f663 fix(deps): update dependency react-i18next to v16.0.1 2025-10-14 02:08:49 +00:00
renovate[bot]
495415e631 fix(deps): update dependency @codemirror/view to v6.38.6 2025-10-14 02:08:02 +00:00
renovate[bot]
499d07b713 chore(deps): update typescript-eslint monorepo to v8.46.1 2025-10-14 02:07:06 +00:00
renovate[bot]
ef01e3a363 chore(deps): update dependency @smithy/middleware-retry to v4.4.2 2025-10-14 02:05:22 +00:00
Languages add-on
9cebae5fd9 Added translation using Weblate (md (generated) (md)) 2025-10-14 02:46:35 +02:00
Languages add-on
620748c7fc Added translation using Weblate (Norwegian Bokmål) 2025-10-14 02:46:34 +02:00
Languages add-on
5cf3975686 Added translation using Weblate (Chinese (Simplified Han script)) 2025-10-14 02:46:34 +02:00
Languages add-on
4b054db235 Added translation using Weblate (Chinese (Traditional Han script)) 2025-10-14 02:46:33 +02:00
Languages add-on
fa66baa20b Added translation using Weblate (Slovenian) 2025-10-14 02:46:32 +02:00
Languages add-on
fb78807a02 Added translation using Weblate (Korean) 2025-10-14 02:46:32 +02:00
Languages add-on
0ac4b87ffb Added translation using Weblate (Serbian) 2025-10-14 02:46:31 +02:00
Languages add-on
3a406a0de0 Added translation using Weblate (Finnish) 2025-10-14 02:46:31 +02:00
Languages add-on
82f5fb3195 Added translation using Weblate (Persian) 2025-10-14 02:46:30 +02:00
Languages add-on
7ccf0428d6 Added translation using Weblate (French) 2025-10-14 02:46:29 +02:00
Languages add-on
fb2de3d149 Added translation using Weblate (Spanish) 2025-10-14 02:46:29 +02:00
Languages add-on
754c2980f8 Added translation using Weblate (Dutch) 2025-10-14 02:46:28 +02:00
Languages add-on
f89b1bd2e4 Added translation using Weblate (Indonesian) 2025-10-14 02:46:27 +02:00
Languages add-on
9bc91b31d3 Added translation using Weblate (Arabic) 2025-10-14 02:46:27 +02:00
Languages add-on
08efa10f95 Added translation using Weblate (Italian) 2025-10-14 02:46:26 +02:00
Languages add-on
6aa21397e0 Added translation using Weblate (Polish) 2025-10-14 02:46:25 +02:00
Languages add-on
b98bde5eed Added translation using Weblate (Hungarian) 2025-10-14 02:46:25 +02:00
Languages add-on
a9def845df Added translation using Weblate (Croatian) 2025-10-14 02:46:24 +02:00
Languages add-on
bf6d0e128f Added translation using Weblate (Vietnamese) 2025-10-14 02:46:24 +02:00
Languages add-on
ccd4bf553b Added translation using Weblate (Portuguese) 2025-10-14 02:46:23 +02:00
Languages add-on
f83ce81cc8 Added translation using Weblate (Czech) 2025-10-14 02:46:22 +02:00
Languages add-on
b1715b60fb Added translation using Weblate (Catalan) 2025-10-14 02:46:21 +02:00
Languages add-on
0b7e8e8efc Added translation using Weblate (Japanese) 2025-10-14 02:46:21 +02:00
Languages add-on
6b7c71ba18 Added translation using Weblate (Ukrainian) 2025-10-14 02:46:20 +02:00
Languages add-on
a072920f80 Added translation using Weblate (Russian) 2025-10-14 02:46:20 +02:00
Languages add-on
2ffda9e8ef Added translation using Weblate (Greek) 2025-10-14 02:46:19 +02:00
Languages add-on
04c4257dee Added translation using Weblate (German) 2025-10-14 02:46:18 +02:00
Languages add-on
e892b79f10 Added translation using Weblate (Portuguese (Brazil)) 2025-10-14 02:46:18 +02:00
Languages add-on
ab98e86fde Added translation using Weblate (Turkish) 2025-10-14 02:46:17 +02:00
renato rinaldi
cce927b6ec Translated using Weblate (Italian)
Currently translated at 13.7% (221 of 1613 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-10-14 02:46:17 +02:00
Elian Doran
c7a9e585f8 Translated using Weblate (Romanian)
Currently translated at 91.7% (134 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ro/
2025-10-14 02:46:16 +02:00
Elian Doran
7a44bdbe87 Translated using Weblate (Romanian)
Currently translated at 48.6% (71 of 146 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ro/
2025-10-14 02:46:15 +02:00
Elian Doran
5c51891959 Translated using Weblate (Romanian)
Currently translated at 28.1% (43 of 153 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ro/
2025-10-14 02:46:15 +02:00
Elian Doran
b003033f87 Added translation using Weblate (Romanian) 2025-10-14 02:46:14 +02:00
Adorian Doran
d87f626975 style/tree: improve icon alignment 2025-10-14 01:09:34 +03:00
Adorian Doran
8d3c64dc54 style/launcher/left pane toggle button arrow: fix the transform property being overidden 2025-10-14 00:41:21 +03:00
Adorian Doran
86bc4a6046 Fix #7230 2025-10-14 00:31:02 +03:00
Adorian Doran
fcc2e00f03 style/admonitions: add background color 2025-10-14 00:15:52 +03:00
Adorian Doran
a68f351797 style/launcher: fix arrow rotation on the legacy theme 2025-10-13 22:17:46 +03:00
Adorian Doran
a95a2ea7dc style/launcher: tweak (again) the left pane toggle button 2025-10-13 22:09:56 +03:00
Adorian Doran
fba51f2cd0 style/launcher: tweak the left pane toggle button 2025-10-13 22:07:05 +03:00
Adorian Doran
6fd37c4c8d style/global menu: tweak the update available indicators 2025-10-13 20:18:04 +03:00
Elian Doran
2ef4aeb884 chore(website/i18n): remove unnecessary translations 2025-10-13 20:08:34 +03:00
Elian Doran
016ba1e617 Add translation support for the website (#7277) 2025-10-13 19:49:27 +03:00
Elian Doran
51b00a5407 chore(website/i18n): address requested changes 2025-10-13 19:42:22 +03:00
Elian Doran
c28cf4da16 chore(website/i18n): fix typecheck issue 2025-10-13 19:33:50 +03:00
Elian Doran
2b915a1217 feat(website/i18n): translate download options 2025-10-13 19:22:14 +03:00
Elian Doran
d978c38b80 feat(website/i18n): translate 404 2025-10-13 19:05:05 +03:00
Elian Doran
b129349236 feat(website/i18n): translate support us 2025-10-13 19:03:56 +03:00
Elian Doran
d20ebd6b2d chore(vscode): support <Trans> syntax for i18n-ally 2025-10-13 19:01:12 +03:00
Elian Doran
b9e1b46884 chore(website/i18n): few translations in support us 2025-10-13 18:42:15 +03:00
Elian Doran
828ad79de2 fix(website/i18n): missing msgid 2025-10-13 18:36:10 +03:00
Elian Doran
d45e3a7a43 Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-10-13 18:33:02 +03:00
Elian Doran
296b63d855 docs(user): mention reverse proxy config (closes #4910) 2025-10-13 18:32:02 +03:00
Elian Doran
1fb95c5128 Translations update from Hosted Weblate (#7305) 2025-10-13 17:54:34 +03:00
Adhe Kurniawan
3b5c253672 Translated using Weblate (Indonesian)
Currently translated at 21.5% (82 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/id/
2025-10-13 16:52:02 +02:00
Adhe Kurniawan
3dcd176f35 Translated using Weblate (Indonesian)
Currently translated at 1.1% (18 of 1613 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/id/
2025-10-13 16:52:01 +02:00
Sarah Hussein
e4d673e14e Translated using Weblate (Arabic)
Currently translated at 51.2% (826 of 1613 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-13 16:52:01 +02:00
minkipark
38c9b64bec Translated using Weblate (Korean)
Currently translated at 2.3% (38 of 1613 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ko/
2025-10-13 16:52:00 +02:00
Harun Çevik
fd11b34fe1 Translated using Weblate (Turkish)
Currently translated at 0.5% (2 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/tr/
2025-10-13 16:51:59 +02:00
Hosted Weblate
4f568d2870 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-13 16:51:59 +02:00
Elian Doran
36f5060855 chore(ci): revert changes breaking the workflows 2025-10-13 17:51:50 +03:00
Elian Doran
5071f61174 docs(user): using desktop application as server (closes #6431) 2025-10-13 17:50:37 +03:00
Elian Doran
985a54edd1 docs(user): exporting a ZIP using curl & ETAPI (closes #4958) 2025-10-13 17:27:43 +03:00
Elian Doran
8c1914359a docs(user): minor tweaks to TLS installation 2025-10-13 17:23:48 +03:00
Elian Doran
ef225704c3 docs(user): sync & update a reference to Docker image 2025-10-13 16:57:40 +03:00
Elian Doran
1d95205503 fix(collections/list): children are displayed twice for empty notes (closes #7301) 2025-10-13 13:12:00 +03:00
Elian Doran
6d5ff42225 Translations update from Hosted Weblate (#7296) 2025-10-13 08:22:49 +03:00
Hosted Weblate
41e395f1d7 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-13 07:17:52 +02:00
Elian Doran
901bbfeeaf fix(deps): update dependency katex to v0.16.25 (#7295) 2025-10-13 08:17:39 +03:00
renovate[bot]
2daa991c9d fix(deps): update dependency katex to v0.16.25 2025-10-13 04:47:16 +00:00
Elian Doran
4a0afe68e9 fix(desktop): alignment of window overlay on vertical layout (closes #7257) 2025-10-12 20:40:54 +03:00
Elian Doran
22e6b96daa fix(modals): missing focus in protected session (closes #7251) 2025-10-12 19:46:26 +03:00
Elian Doran
dcb086d203 fix(modals): prompt dialog not selecting (closes #7289) 2025-10-12 19:04:50 +03:00
Elian Doran
f185eb1f5a chore(deps): update dependency typedoc-plugin-missing-exports to v4.1.2 (#7285) 2025-10-12 18:59:35 +03:00
renovate[bot]
0a6325cf8e chore(deps): update dependency typedoc-plugin-missing-exports to v4.1.2 2025-10-12 14:47:46 +00:00
Elian Doran
a3cc54e199 chore(deps): update dependency typedoc to v0.28.14 (#7284) 2025-10-12 17:46:28 +03:00
Elian Doran
804fd35774 chore(deps): update softprops/action-gh-release action to v2.4.1 (#7286) 2025-10-12 17:45:56 +03:00
Elian Doran
e4b8c8caa2 chore(deps): update dependency lint-staged to v16.2.4 (#7283) 2025-10-12 17:45:33 +03:00
Elian Doran
5c2f5e92eb chore(deps): update dependency @types/node to v22.18.10 (#7282) 2025-10-12 17:45:14 +03:00
Elian Doran
76ad386c70 chore(deps): update dependency @types/leaflet to v1.9.21 (#7281) 2025-10-12 08:18:47 +03:00
Elian Doran
c6b2044492 Translations update from Hosted Weblate (#7280) 2025-10-12 08:18:19 +03:00
renovate[bot]
4a953fad72 chore(deps): update softprops/action-gh-release action to v2.4.1 2025-10-12 01:45:40 +00:00
renovate[bot]
f06d8f27a1 chore(deps): update dependency typedoc to v0.28.14 2025-10-12 01:45:30 +00:00
renovate[bot]
ffd4201a73 chore(deps): update dependency lint-staged to v16.2.4 2025-10-12 01:45:24 +00:00
renovate[bot]
bc529e7089 chore(deps): update dependency @types/node to v22.18.10 2025-10-12 01:44:28 +00:00
renovate[bot]
f143cac61e chore(deps): update dependency @types/leaflet to v1.9.21 2025-10-12 01:43:32 +00:00
AndreR
e7657d4eb1 Translated using Weblate (German)
Currently translated at 9.5% (11 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/de/
2025-10-12 00:08:09 +02:00
Sarah Hussein
b6ad98e9ff Translated using Weblate (Arabic)
Currently translated at 69.5% (265 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ar/
2025-10-12 00:08:08 +02:00
Sarah Hussein
128120ad12 Translated using Weblate (Arabic)
Currently translated at 50.0% (807 of 1613 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-12 00:08:08 +02:00
green
efa8fef4cf Translated using Weblate (Japanese)
Currently translated at 100.0% (1613 of 1613 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-10-12 00:08:07 +02:00
CactusTrebleFraming
f5db38950a Translated using Weblate (French)
Currently translated at 85.5% (1380 of 1613 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/fr/
2025-10-12 00:08:07 +02:00
Newcomer1989
d187da46a0 Translated using Weblate (German)
Currently translated at 100.0% (1613 of 1613 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-10-12 00:08:07 +02:00
Elian Doran
fb2afb5794 feat(website/i18n): translate footer 2025-10-11 22:45:37 +03:00
Elian Doran
6fe261836e feat(website/i18n): translate download button 2025-10-11 22:35:31 +03:00
Elian Doran
fc9f2bceb0 feat(website/i18n): translate final call-to-action 2025-10-11 22:27:15 +03:00
Elian Doran
ce88afee1b feat(website/i18n): translate FAQ section 2025-10-11 22:26:10 +03:00
Elian Doran
07eb3f64e3 feat(website/i18n): translate collections 2025-10-11 22:19:08 +03:00
Elian Doran
e32ba61a3c feat(website/i18n): translate extensibility benefits 2025-10-11 22:16:01 +03:00
Elian Doran
43e66fa4a6 Translations update from Hosted Weblate (#7276) 2025-10-11 22:10:07 +03:00
Elian Doran
ee9de82203 feat(website/i18n): translate note types 2025-10-11 22:08:53 +03:00
Hosted Weblate
df3baf1a67 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-11 19:01:58 +00:00
Elian Doran
6968d213bd Translations update from Hosted Weblate (#7275) 2025-10-11 22:01:42 +03:00
Elian Doran
ffaa011c3e feat(website/i18n): translate first three sections in the home page 2025-10-11 21:00:03 +03:00
Elian Doran
d56debaa9f feat(website/i18n): use translations in get-started 2025-10-11 20:46:41 +03:00
Elian Doran
2c71e995f2 feat(website/i18n): set up 2025-10-11 20:46:29 +03:00
Hosted Weblate
4da47979d1 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-11 19:02:49 +02:00
Elian Doran
2751aecab9 fix(deps): update dependency i18next to v25.6.0 (#7273) 2025-10-11 20:02:32 +03:00
renovate[bot]
1dccb6da31 fix(deps): update dependency i18next to v25.6.0 2025-10-11 01:31:47 +00:00
Elian Doran
8557bad242 chore(docs): bring back relation map updates 2025-10-10 22:58:38 +03:00
Elian Doran
f43dfc23c0 Translations update from Hosted Weblate (#7269) 2025-10-10 22:22:13 +03:00
D Walterfang
e2984ec2ab Translated using Weblate (Dutch)
Currently translated at 13.0% (15 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/nl/
2025-10-10 21:14:10 +02:00
Sarah Hussein
2e14d73c5b Translated using Weblate (Arabic)
Currently translated at 17.3% (20 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ar/
2025-10-10 21:14:10 +02:00
Sarah Hussein
1afd00f7e8 Translated using Weblate (Arabic)
Currently translated at 51.1% (195 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ar/
2025-10-10 21:14:10 +02:00
Sarah Hussein
23f5f57c92 Translated using Weblate (Arabic)
Currently translated at 39.5% (636 of 1608 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-10 21:14:10 +02:00
Elian Doran
d80d637cc2 Allow any date for first day of the week (#7244) 2025-10-10 22:14:04 +03:00
Jakob Schlanstedt
b25ab3a988 fix(calendar): sunday ISO dayjs mismatch 2025-10-10 15:42:16 +02:00
Jakob Schlanstedt
62e978068a feat(calendar.ts): optimize getWeekNumber by using isoWeek 2025-10-10 15:42:16 +02:00
Jakob Schlanstedt
89879a6851 feat(First-day-of-the-week and date-notes)!: make any day configurable to become first day of the week and make date-notes ISO 8601-compliant
Section 4.1.4.1 ISO 8601-1
https://www.loc.gov/standards/datetime/iso-tc154-wg5_n0038_iso_wd_8601-1_2016-02-16.pdf
2025-10-10 15:42:16 +02:00
Elian Doran
e1a0452448 chore(deps): update electron-forge monorepo to v7.10.2 (#7253) 2025-10-10 14:55:59 +03:00
Elian Doran
c9f7d2a457 Translations update from Hosted Weblate (#7259) 2025-10-10 14:55:44 +03:00
Le Viet Dat
fd71a90a8e Translated using Weblate (Vietnamese)
Currently translated at 53.9% (62 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/vi/
2025-10-10 13:01:16 +02:00
Sarah Hussein
f06d6a4e92 Translated using Weblate (Arabic)
Currently translated at 50.9% (194 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ar/
2025-10-10 13:01:16 +02:00
Sarah Hussein
6bb98c3eae Translated using Weblate (Arabic)
Currently translated at 29.9% (481 of 1608 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-10 13:01:15 +02:00
renovate[bot]
cf21706f26 chore(deps): update electron-forge monorepo to v7.10.2 2025-10-10 07:28:10 +00:00
Hosted Weblate
d0fbda50fc Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-10 09:26:07 +02:00
Elian Doran
9abef88177 Translations update from Hosted Weblate (#7249) 2025-10-10 10:25:56 +03:00
Elian Doran
1a94e9637d Translated using Weblate (Arabic)
Currently translated at 13.0% (15 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ar/
2025-10-10 09:23:13 +02:00
Le Viet Dat
e15ff806e5 Translated using Weblate (Vietnamese)
Currently translated at 46.0% (53 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/vi/
2025-10-10 09:23:11 +02:00
Sarah Hussein
7b01165970 Translated using Weblate (Arabic)
Currently translated at 45.4% (173 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ar/
2025-10-10 09:23:11 +02:00
Sarah Hussein
fc3cc6ffec Translated using Weblate (Arabic)
Currently translated at 19.9% (320 of 1608 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-10 09:23:10 +02:00
Le Viet Dat
6d99ccefdb Translated using Weblate (Vietnamese)
Currently translated at 7.8% (9 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/vi/
2025-10-10 07:34:38 +02:00
Hosted Weblate
b055c7e2ef Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-10 07:34:37 +02:00
Le Viet Dat
e488845d29 Translated using Weblate (Vietnamese)
Currently translated at 3.4% (4 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/vi/
2025-10-10 07:34:36 +02:00
Sarah Hussein
fcd71052c5 Translated using Weblate (Arabic)
Currently translated at 13.0% (15 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ar/
2025-10-10 07:34:36 +02:00
Le Viet Dat
b465336d0a Translated using Weblate (Vietnamese)
Currently translated at 2.6% (3 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/vi/
2025-10-10 07:34:35 +02:00
Sarah Hussein
23e4fef078 Translated using Weblate (Arabic)
Currently translated at 35.9% (137 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ar/
2025-10-10 07:34:35 +02:00
Sarah Hussein
32f360979c Translated using Weblate (Arabic)
Currently translated at 19.0% (306 of 1608 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-10 07:34:34 +02:00
Le Viet Dat
c1cc187a88 Translated using Weblate (Vietnamese)
Currently translated at 0.7% (3 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/vi/
2025-10-10 07:34:34 +02:00
green
f7dbcfb77a Translated using Weblate (Japanese)
Currently translated at 100.0% (1608 of 1608 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-10-10 07:34:33 +02:00
Sarah Hussein
52916a8bbb Translated using Weblate (Arabic)
Currently translated at 17.6% (284 of 1606 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-10 07:34:32 +02:00
Sarah Hussein
c8e311744a Translated using Weblate (Arabic)
Currently translated at 17.5% (282 of 1606 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-10 07:34:32 +02:00
Sarah Hussein
b87f0c1a57 Translated using Weblate (Arabic)
Currently translated at 16.9% (272 of 1606 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-10 07:34:31 +02:00
Elian Doran
3ebb4c3c9c chore(deps): update dependency @types/node to v22.18.9 (#7252) 2025-10-10 08:34:23 +03:00
renovate[bot]
10350b1a42 chore(deps): update dependency @types/node to v22.18.9 2025-10-10 05:30:25 +00:00
Elian Doran
a5beb2ae41 chore(deps): update pnpm to v10.18.2 (#7254) 2025-10-10 08:29:36 +03:00
Elian Doran
b081d3fb2d chore(deps): update dependency openai to v6.3.0 (#7255) 2025-10-10 08:28:59 +03:00
Elian Doran
7bc4c530e8 chore(deps): update dependency happy-dom to v20 (#7256) 2025-10-10 08:28:25 +03:00
renovate[bot]
1002f01e57 chore(deps): update dependency happy-dom to v20 2025-10-10 01:34:28 +00:00
renovate[bot]
f9bcc99bf9 chore(deps): update dependency openai to v6.3.0 2025-10-10 01:33:47 +00:00
renovate[bot]
2956c97983 chore(deps): update pnpm to v10.18.2 2025-10-10 01:33:05 +00:00
Elian Doran
8bf9544bea Improved right-to-left support (#7227) 2025-10-09 21:22:33 +03:00
Elian Doran
4ea2fdf471 chore(server): hide body in set_password and setup too 2025-10-09 21:02:18 +03:00
Elian Doran
492f481999 chore(rtl): address 2nd set of requested changes 2025-10-09 20:48:30 +03:00
Elian Doran
00b215c093 chore(rtl): address requested changes 2025-10-09 20:46:10 +03:00
Elian Doran
b84010318d fix(server): RTL not reported correctly to JS 2025-10-09 19:44:22 +03:00
Elian Doran
63a08c4bd3 fix(login): failure to load if password was failed 2025-10-09 19:33:21 +03:00
Elian Doran
b34fbff6d1 test(server): failing i18n test due to dev language 2025-10-09 19:30:55 +03:00
Elian Doran
e08a9e1915 chore(client): add Arabic to full calendar 2025-10-09 19:28:05 +03:00
Elian Doran
519ada3a48 refactor(server): loading runtime JS as early as possible 2025-10-09 19:18:28 +03:00
Elian Doran
90524d99dc refactor(server): remove template-level loading of bootstrap 2025-10-09 19:16:12 +03:00
Elian Doran
2936a537cf feat(rtl): apply same mechanism for login/desktop/mobile 2025-10-09 19:12:46 +03:00
Elian Doran
6f51d82f82 fix(login): layout shift due to bootstrap loading later 2025-10-09 18:59:38 +03:00
Elian Doran
ea4fe3f290 feat(i18n): add an option to automatically match formatting locale to set locale 2025-10-09 18:54:55 +03:00
Elian Doran
6d9bdd5c6f feat(client/rtl): support formatting locale for Arabic 2025-10-09 18:47:10 +03:00
Elian Doran
3c2642e822 feat(client/i18n): enable formatting locale on browser as well & use for date formatting 2025-10-09 18:44:35 +03:00
Elian Doran
f4df7c1eec feat(client/rtl): improve alignment of the attribute editor 2025-10-09 18:34:32 +03:00
Elian Doran
74d7191222 chore(client/rtl): fix alignment of global menu in horizontal layout 2025-10-09 17:57:58 +03:00
Elian Doran
2c71a56324 chore(client/rtl): revert dropdown arrow 2025-10-09 17:55:17 +03:00
Elian Doran
3ab8627db8 feat(client/rtl): enable Arabic as dev-only language for now 2025-10-09 17:55:05 +03:00
Elian Doran
9d7c513fb7 Merge remote-tracking branch 'origin/main' into feature/rtl_ui 2025-10-09 17:46:26 +03:00
Elian Doran
f880aa769c fix(client/rtl): wrong order of tabs 2025-10-09 17:45:48 +03:00
Elian Doran
c64e695036 chore(deps): update dependency python to 3.14 (#7237) 2025-10-09 16:18:32 +03:00
Elian Doran
a500dc9067 fix(deps): update dependency @codemirror/view to v6.38.5 (#7236) 2025-10-09 16:18:17 +03:00
Elian Doran
08d6a49cb6 chore(deps): update dependency rollup-plugin-webpack-stats to v2.1.6 (#7235) 2025-10-09 16:17:58 +03:00
Elian Doran
315f8b4503 chore(deps): update dependency jsdoc to v4.0.5 (#7234) 2025-10-09 16:17:44 +03:00
Elian Doran
9dc4de1366 chore(deps): update electron-forge monorepo to v7.10.0 (#7238) 2025-10-09 16:13:31 +03:00
Elian Doran
a22796397a chore(deps): update softprops/action-gh-release action to v2.4.0 (#7239) 2025-10-09 16:10:56 +03:00
Elian Doran
372297f829 fix(deps): update dependency marked to v16.4.0 (#7240) 2025-10-09 16:10:27 +03:00
Elian Doran
f0908045f1 fix(deps): update dependency mind-elixir to v5.3.2 (#7241) 2025-10-09 16:10:00 +03:00
Elian Doran
b431a70792 chore(deps): update dependency eslint-plugin-react-hooks to v7 (#7242) 2025-10-09 16:09:33 +03:00
Elian Doran
c14cdb618b chore(deps): update github/codeql-action action to v4 (#7243) 2025-10-09 16:08:55 +03:00
renovate[bot]
f596080d06 chore(deps): update electron-forge monorepo to v7.10.0 2025-10-09 11:42:00 +00:00
Elian Doran
c88f03f4fd chore(deps): update dependency electron to v38.2.2 (#7233) 2025-10-09 14:39:47 +03:00
Elian Doran
8ca65edc70 chore(deps): update dependency @smithy/middleware-retry to v4.4.1 (#7232) 2025-10-09 14:38:36 +03:00
Elian Doran
5131c1d72c Translations update from Hosted Weblate (#7245) 2025-10-09 13:49:30 +03:00
Elian Doran
8fab4dd94d chore(ci): use different check 2025-10-09 13:34:06 +03:00
renovate[bot]
583c488b96 chore(deps): update github/codeql-action action to v4 2025-10-09 10:18:30 +00:00
renovate[bot]
d16598c03d chore(deps): update dependency eslint-plugin-react-hooks to v7 2025-10-09 10:18:26 +00:00
renovate[bot]
e6e8cdcec1 fix(deps): update dependency mind-elixir to v5.3.2 2025-10-09 10:17:44 +00:00
renovate[bot]
7561bd471b fix(deps): update dependency marked to v16.4.0 2025-10-09 10:17:03 +00:00
renovate[bot]
b9cc8015fe chore(deps): update softprops/action-gh-release action to v2.4.0 2025-10-09 10:16:24 +00:00
renovate[bot]
853be9000b chore(deps): update dependency python to 3.14 2025-10-09 10:15:32 +00:00
renovate[bot]
9a7638cc73 fix(deps): update dependency @codemirror/view to v6.38.5 2025-10-09 10:15:28 +00:00
renovate[bot]
10448a9f36 chore(deps): update dependency rollup-plugin-webpack-stats to v2.1.6 2025-10-09 10:14:36 +00:00
renovate[bot]
360a7f530d chore(deps): update dependency jsdoc to v4.0.5 2025-10-09 10:13:44 +00:00
renovate[bot]
f457dbf7d4 chore(deps): update dependency electron to v38.2.2 2025-10-09 10:13:39 +00:00
renovate[bot]
3f6d93230e chore(deps): update dependency @smithy/middleware-retry to v4.4.1 2025-10-09 10:12:43 +00:00
Sarah Hussein
1b2be2c345 Translated using Weblate (Arabic)
Currently translated at 12.1% (14 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ar/
2025-10-09 11:51:32 +02:00
Sarah Hussein
6d1faac772 Translated using Weblate (Arabic)
Currently translated at 14.2% (229 of 1606 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-09 11:51:31 +02:00
Adhe Kurniawan
a9fe48aa0a Translated using Weblate (Indonesian)
Currently translated at 1.0% (4 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/id/
2025-10-09 11:51:31 +02:00
Adhe Kurniawan
e2e58fee56 Translated using Weblate (Indonesian)
Currently translated at 11.3% (13 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/id/
2025-10-09 11:51:30 +02:00
Adhe Kurniawan
95ac70518b Translated using Weblate (Indonesian)
Currently translated at 0.2% (4 of 1606 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/id/
2025-10-09 11:51:29 +02:00
green
e95949e4d6 Translated using Weblate (Japanese)
Currently translated at 100.0% (1606 of 1606 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-10-09 11:51:29 +02:00
Adhe Kurniawan
ae87b9e027 Added translation using Weblate (Indonesian) 2025-10-09 11:51:28 +02:00
Adhe Kurniawan
fe4e5286f7 Added translation using Weblate (Indonesian) 2025-10-09 11:51:27 +02:00
Adhe Kurniawan
b43a5252b1 Added translation using Weblate (Indonesian) 2025-10-09 11:51:27 +02:00
green
a732487e7f Translated using Weblate (Japanese)
Currently translated at 100.0% (115 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ja/
2025-10-09 11:51:26 +02:00
Sarah Hussein
112b847869 Translated using Weblate (Arabic)
Currently translated at 29.9% (114 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ar/
2025-10-09 11:51:26 +02:00
Sarah Hussein
2fdcbc4726 Translated using Weblate (Arabic)
Currently translated at 12.8% (207 of 1606 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-09 11:51:25 +02:00
green
e9aa215b95 Translated using Weblate (Japanese)
Currently translated at 100.0% (1606 of 1606 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-10-09 11:51:24 +02:00
Elian Doran
6b6322798e test(server): protected session timeout crashing on LLM tests 2025-10-09 12:51:11 +03:00
Elian Doran
a8011e4755 refactor(server): fix a few cyclic dependencies regarding protected_session 2025-10-09 12:43:38 +03:00
Elian Doran
b2fcf5fa6c test(server): tests failing due to CLS and lack of content 2025-10-09 12:18:39 +03:00
Elian Doran
8ac0425ca5 chore(llm): try to fix flaky test 2025-10-09 10:40:35 +03:00
Elian Doran
f9a841245c fix(client/rtl): mobile detail menu appearing on the wrong side 2025-10-08 22:26:43 +03:00
Elian Doran
a377a0ef15 chore(i18n): translate a missing string 2025-10-08 22:24:45 +03:00
Elian Doran
ea3cf8078e fix(client/rtl): initial drag of mobile tree not working 2025-10-08 22:13:52 +03:00
Elian Doran
13d2721696 chore(client/rtl): normalize values between RTL and LTR 2025-10-08 22:03:56 +03:00
Elian Doran
b8f0fc722c chore(client/rtl): use different mechanism for calculating drag state 2025-10-08 21:54:39 +03:00
Elian Doran
3e54e0fc42 fix(client/rtl): sidebar not draggable 2025-10-08 21:46:26 +03:00
Elian Doran
06d87dc94b fix(client/rtl): sidebar always displayed on mobile 2025-10-08 21:41:48 +03:00
Elian Doran
d35f97d99a feat(client/rtl): hide English RTL from production 2025-10-08 21:35:57 +03:00
Elian Doran
c4358d52d5 fix(server): crash in prod due to RTL 2025-10-08 21:28:41 +03:00
Elian Doran
b8ffb004ce fix(client/rtl): minor padding issue 2025-10-08 21:09:49 +03:00
Elian Doran
3a3cb0c68d Translations update from Hosted Weblate (#7223) 2025-10-08 21:03:38 +03:00
Elian Doran
d98e6fe88a Translated using Weblate (Arabic)
Currently translated at 8.6% (10 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ar/
2025-10-08 20:02:22 +02:00
Elian Doran
b5f73874cb fix(client/rtl): tooltips not inverted 2025-10-08 19:06:19 +03:00
Elian Doran
9d1e89268f fix(client/rtl): bootstrap not in RTL mode 2025-10-08 18:50:27 +03:00
Elian Doran
d9bfa08672 fix(client/rtl): right positioning not adjusted 2025-10-08 18:36:10 +03:00
Elian Doran
8a8727e6df fix(client/rtl): toggling not working 2025-10-08 18:24:01 +03:00
Elian Doran
d19d05ec7b fix(client/rtl): select arrow in wrong position 2025-10-08 18:20:45 +03:00
Elian Doran
b0bb93975a fix(client/rtl): toggle buttons out of bounds 2025-10-08 18:14:35 +03:00
Elian Doran
09c5686cb7 fix(client/rtl): floating buttons on the wrong side 2025-10-08 18:12:06 +03:00
Elian Doran
42b1dcebcd feat(client/rtl): set lang to body as well 2025-10-08 18:04:57 +03:00
Elian Doran
1e78dd8296 fix(client/rtl): tree chevron in the wrong direction 2025-10-08 18:03:48 +03:00
Elian Doran
3d9861f904 feat(client/rtl): handle transform 2025-10-08 17:58:38 +03:00
Elian Doran
668e1dff4b feat(client/rtl): handle transform-origin 2025-10-08 17:56:39 +03:00
Elian Doran
c91a03834d feat(client/rtl): handle text-align 2025-10-08 17:54:40 +03:00
Elian Doran
20e293f5df feat(client/rtl): handle float 2025-10-08 17:52:41 +03:00
Elian Doran
87fb3c1e82 feat(client/rtl): handle right 2025-10-08 17:51:58 +03:00
Elian Doran
db1bcfda45 feat(client/rtl): handle left 2025-10-08 17:50:54 +03:00
Elian Doran
a8e44afd6d feat(client/rtl): handle border-right 2025-10-08 17:47:27 +03:00
Elian Doran
1b1bceebfe feat(client/rtl): handle border-left 2025-10-08 17:46:59 +03:00
Elian Doran
6faccd3b14 feat(client/rtl): handle padding-right 2025-10-08 17:46:10 +03:00
Elian Doran
34117fa9ad feat(client/rtl): handle padding-left 2025-10-08 17:45:58 +03:00
Elian Doran
6b93013674 feat(client/rtl): handle margin-right 2025-10-08 17:45:31 +03:00
Elian Doran
247ab1aec3 feat(client/rtl): handle margin-left 2025-10-08 17:44:17 +03:00
Elian Doran
adff36cf22 feat(i18n/rtl): apply right to left direction at root level 2025-10-08 12:08:39 +03:00
Elian Doran
034ac59c9a feat(i18n/rtl): add an English with RTL enabled for testing 2025-10-08 11:51:14 +03:00
Hosted Weblate
80d805a807 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-08 10:44:04 +02:00
Kuzma Simonov
39ca136c5d Translated using Weblate (Russian)
Currently translated at 22.6% (26 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ru/
2025-10-08 10:44:02 +02:00
Hosted Weblate
29dbfa6fc4 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-08 10:44:01 +02:00
Elian Doran
3e30870c87 feat(i18n): add Portuguese (Portugal) 2025-10-08 11:39:06 +03:00
Elian Doran
ee1a11975c fix(board): keyboard overlay appears cut 2025-10-08 11:12:25 +03:00
Elian Doran
f0fc3e96ce docs(readme): use formal GitHub account 2025-10-08 11:01:53 +03:00
Elian Doran
cd75ff9a8a chore(ci): deploy website on release 2025-10-08 11:00:36 +03:00
Elian Doran
f196140210 chore(i18n): update available not translated 2025-10-08 10:46:19 +03:00
Elian Doran
a77c4e6dfa Translations update from Hosted Weblate (#7221) 2025-10-08 07:46:28 +03:00
Sarah Hussein
1d4d193552 Translated using Weblate (Arabic)
Currently translated at 6.0% (7 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ar/
2025-10-08 00:01:23 +02:00
ssantos
3225f4c8f5 Translated using Weblate (Portuguese)
Currently translated at 97.3% (1563 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pt/
2025-10-08 00:01:20 +02:00
Sarah Hussein
800c4dc012 Translated using Weblate (Arabic)
Currently translated at 4.9% (19 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ar/
2025-10-08 00:01:19 +02:00
Sarah Hussein
d662882c03 Translated using Weblate (Arabic)
Currently translated at 1.0% (17 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-10-08 00:01:19 +02:00
Elian Doran
31c8e96d70 chore(forge): set wayland socket for flatpak build 2025-10-07 18:38:13 +03:00
Elian Doran
1191421388 fix(flake): bettersqlite3 dependency not build properly 2025-10-07 18:27:13 +03:00
Elian Doran
831a184c2a test(server): try to use fake timers to avoid flaky test in the CI 2025-10-07 15:34:58 +03:00
Elian Doran
c671f91bca test(server): fix test failures 2025-10-07 14:27:05 +03:00
Elian Doran
fa436c7ce6 test(server): switch to vmForks due to better error reporting 2025-10-07 14:25:58 +03:00
Elian Doran
d1367286c9 test(server): fix unrejected failure in test 2025-10-07 14:20:06 +03:00
Elian Doran
d10b0fa823 fix(hidden_subtree): builtin templates have #excludeFromNoteMap (closes #7187) 2025-10-07 12:20:29 +03:00
Elian Doran
545c8648b7 feat(demo): add a template with #excludeFromNoteMap (closes #3547) 2025-10-07 11:49:36 +03:00
Elian Doran
d6e9acc149 fix(ckeditor5-math): equation not maintaining styles (closes #7211) 2025-10-07 11:14:56 +03:00
Elian Doran
26e14aff7b Translations update from Hosted Weblate (#7219) 2025-10-07 10:17:34 +03:00
Elian Doran
280ec5b406 Translated using Weblate (Portuguese)
Currently translated at 0.8% (1 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/pt/
2025-10-07 09:17:03 +02:00
Miguel Dias
26081ffd36 Translated using Weblate (Portuguese)
Currently translated at 0.1% (2 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pt/
2025-10-07 09:17:02 +02:00
Miguel Dias
f106cbf6c0 Translated using Weblate (Portuguese)
Currently translated at 99.7% (380 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/pt/
2025-10-07 09:17:02 +02:00
green
f3877a52ab Translated using Weblate (Japanese)
Currently translated at 100.0% (1605 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-10-07 09:17:01 +02:00
Hosted Weblate
5becf60a63 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-07 09:17:00 +02:00
Elian Doran
2ea96dc8f8 Revert "fix(deps): update dependency mind-elixir to v5.3.1" (#7220) 2025-10-07 10:16:54 +03:00
Elian Doran
e48724662e Revert "fix(deps): update dependency mind-elixir to v5.3.1" 2025-10-07 10:16:42 +03:00
Elian Doran
745ce7de76 fix(deps): update dependency mind-elixir to v5.3.1 (#7202) 2025-10-07 10:16:16 +03:00
Elian Doran
997217861c chore(deps): update pnpm to v10.18.1 (#7212) 2025-10-07 10:15:49 +03:00
Elian Doran
44f8e8b833 chore(deps): update dependency @playwright/test to v1.56.0 (#7213) 2025-10-07 10:15:25 +03:00
Elian Doran
99e2b63ff0 chore(deps): update dependency @types/express-serve-static-core to v5.1.0 (#7214) 2025-10-07 10:15:08 +03:00
Elian Doran
0139d90ac7 chore(deps): update dependency openai to v6.2.0 (#7215) 2025-10-07 10:14:55 +03:00
Elian Doran
5b7484c27c chore(deps): update typescript-eslint monorepo to v8.46.0 (#7216) 2025-10-07 10:14:46 +03:00
renovate[bot]
71e64be44c fix(deps): update dependency mind-elixir to v5.3.1 2025-10-07 07:05:43 +00:00
renovate[bot]
639651329a chore(deps): update typescript-eslint monorepo to v8.46.0 2025-10-07 07:04:54 +00:00
renovate[bot]
a7a0d3584a chore(deps): update dependency openai to v6.2.0 2025-10-07 07:04:10 +00:00
renovate[bot]
f765441f1e chore(deps): update dependency @types/express-serve-static-core to v5.1.0 2025-10-07 07:03:35 +00:00
renovate[bot]
10cd5bf130 chore(deps): update dependency @playwright/test to v1.56.0 2025-10-07 07:02:53 +00:00
renovate[bot]
d93c5dfeea chore(deps): update pnpm to v10.18.1 2025-10-07 07:02:08 +00:00
Elian Doran
b58aac1298 fix(client): invalid import after moving protocol config 2025-10-07 09:59:33 +03:00
Elian Doran
d662718a4a feat(client): allow opening obsidian: links (closes #7207) 2025-10-06 20:05:42 +03:00
Elian Doran
bebd3d430b refactor(commons): deduplicate allowed protocols 2025-10-06 20:04:07 +03:00
Elian Doran
2fca995725 docs(guide): update html docs with sharing 2025-10-06 19:58:33 +03:00
Elian Doran
caa1ea12f1 feat: Add shareHtml relation for custom HTML snippets in shared pages (#7157) 2025-10-06 19:32:17 +03:00
Elian Doran
f25e4ea391 Translations update from Hosted Weblate (#7210) 2025-10-06 19:22:42 +03:00
Elian Doran
6c106300d4 chore(client): launch bar background affecting custom icons (closes #7147) 2025-10-06 19:18:47 +03:00
Hosted Weblate
05b433edb5 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-06 15:55:10 +00:00
Elian Doran
69a59f0935 fix(collections/list): not reacting to expand/collapse button (closes #7209) 2025-10-06 18:55:02 +03:00
Elian Doran
fa7575ed00 fix(collections/table): react to tree state changes (closes #7204) 2025-10-06 18:49:11 +03:00
Elian Doran
b2174549c7 chore(collections/table): avoid rendering if rows didn't load yet 2025-10-06 18:48:13 +03:00
Elian Doran
19f16274ab Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-10-06 18:29:20 +03:00
Elian Doran
7f88ae5494 fix(mobile): formatting toolbar appears cut off (closes #7206) 2025-10-06 18:29:17 +03:00
Elian Doran
c820b5caa4 feat(collections/board): keep title of the column always visible 2025-10-06 18:10:54 +03:00
Elian Doran
b1638e1ffc docs(collections/board): keyboard shortcuts 2025-10-06 18:02:45 +03:00
Elian Doran
f2e60f52d2 feat(collections/board): restore focus 2025-10-06 17:54:52 +03:00
Elian Doran
d845343e97 feat(collections/board): basic keyboard interaction 2025-10-06 17:48:08 +03:00
Elian Doran
ee2edc92e7 Translations update from Hosted Weblate (#7205) 2025-10-06 12:28:17 +03:00
green
332216f5f5 Translated using Weblate (Japanese)
Currently translated at 100.0% (115 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ja/
2025-10-06 11:27:05 +02:00
Elian Doran
4d4cd7d130 Translations update from Hosted Weblate (#7200) 2025-10-05 21:51:04 +03:00
AndreR
b3cc51ce63 Translated using Weblate (German)
Currently translated at 5.2% (6 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/de/
2025-10-05 20:32:49 +02:00
Elian Doran
05645d93ef Translated using Weblate (Russian)
Currently translated at 21.7% (25 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ru/
2025-10-05 20:32:49 +02:00
green
a2d09efca4 Translated using Weblate (Japanese)
Currently translated at 60.0% (69 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ja/
2025-10-05 20:32:48 +02:00
Elian Doran
1212f9a9e9 Translated using Weblate (Italian)
Currently translated at 7.8% (9 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/it/
2025-10-05 20:32:48 +02:00
Elian Doran
75f7986e36 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 63.4% (73 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/zh_Hans/
2025-10-05 20:32:48 +02:00
Francis C
2447a6fc8d Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 77.3% (89 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/zh_Hant/
2025-10-05 17:43:01 +02:00
green
38a4a3e7b6 Translated using Weblate (Japanese)
Currently translated at 100.0% (381 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/
2025-10-05 17:43:00 +02:00
green
28240d549d Translated using Weblate (Japanese)
Currently translated at 100.0% (1605 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-10-05 17:42:59 +02:00
Languages add-on
5da46a1678 Added translation using Weblate (md (generated) (md)) 2025-10-05 17:42:59 +02:00
Languages add-on
e592a37799 Added translation using Weblate (Norwegian Bokmål) 2025-10-05 17:42:58 +02:00
Languages add-on
15d00b61dd Added translation using Weblate (Slovenian) 2025-10-05 17:42:57 +02:00
Languages add-on
5d0b6f9fad Added translation using Weblate (Korean) 2025-10-05 17:42:57 +02:00
Languages add-on
2a40ffd164 Added translation using Weblate (Serbian) 2025-10-05 17:42:56 +02:00
Languages add-on
8c687de3c6 Added translation using Weblate (Finnish) 2025-10-05 17:42:56 +02:00
Languages add-on
27415b4e16 Added translation using Weblate (Persian) 2025-10-05 17:42:55 +02:00
Languages add-on
ce0b39765e Added translation using Weblate (French) 2025-10-05 17:42:55 +02:00
Languages add-on
fafc4af237 Added translation using Weblate (Dutch) 2025-10-05 17:42:54 +02:00
Languages add-on
76a283ed77 Added translation using Weblate (Arabic) 2025-10-05 17:42:54 +02:00
Languages add-on
99500bca8f Added translation using Weblate (Polish) 2025-10-05 17:42:53 +02:00
Languages add-on
a982fc326f Added translation using Weblate (Hungarian) 2025-10-05 17:42:53 +02:00
Languages add-on
b16309d01a Added translation using Weblate (Croatian) 2025-10-05 17:42:52 +02:00
Languages add-on
1bfc3d450f Added translation using Weblate (Vietnamese) 2025-10-05 17:42:52 +02:00
Languages add-on
37b63d4ea9 Added translation using Weblate (Portuguese) 2025-10-05 17:42:51 +02:00
Languages add-on
e7315e7d35 Added translation using Weblate (Czech) 2025-10-05 17:42:50 +02:00
Languages add-on
718dffa672 Added translation using Weblate (Catalan) 2025-10-05 17:42:50 +02:00
Languages add-on
c3dd9865e7 Added translation using Weblate (Ukrainian) 2025-10-05 17:42:49 +02:00
Languages add-on
1702ec5644 Added translation using Weblate (Greek) 2025-10-05 17:42:49 +02:00
Languages add-on
dfddf044cf Added translation using Weblate (German) 2025-10-05 17:42:48 +02:00
Languages add-on
24a632056a Added translation using Weblate (Portuguese (Brazil)) 2025-10-05 17:42:47 +02:00
Languages add-on
dc7f4a6cf3 Added translation using Weblate (Turkish) 2025-10-05 17:42:47 +02:00
Languages add-on
cd100f37fe Added translation using Weblate (md (generated) (md)) 2025-10-05 17:42:46 +02:00
Languages add-on
984e8bbba0 Added translation using Weblate (md (generated) (md)) 2025-10-05 17:42:46 +02:00
Elian Doran
fcc22cc212 Translated using Weblate (Romanian)
Currently translated at 96.5% (111 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ro/
2025-10-05 17:42:45 +02:00
Hosted Weblate
4101acc2e3 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-05 17:42:44 +02:00
Elian Doran
f30bdd54b1 fix(relation_map): floating buttons stuck when showing source 2025-10-05 18:38:40 +03:00
Elian Doran
62bb8ac89a chore(release): prepare for 0.99.1 2025-10-05 11:52:06 +03:00
Elian Doran
33dfcb1c6e docs(release): 0.99.1 2025-10-05 11:50:52 +03:00
Elian Doran
5969815ed1 fix(deps): downgrade mind-elixir (closes #7170) 2025-10-05 11:27:25 +03:00
Elian Doran
2b2125c702 fix(ai_chat): conversation not visible on Firefox 2025-10-05 11:03:18 +03:00
Adorian Doran
85a4557bb0 website: tweak the hero section 2025-10-04 19:11:44 +03:00
Adorian Doran
0d9e4a1aa2 website/header: add some style to the GitHub button 2025-10-04 17:07:32 +03:00
Elian Doran
4a01181110 docs(readme): change file naming format 2025-10-04 15:53:33 +03:00
Elian Doran
89dfc480f3 docs(readme): bring back original documents 2025-10-04 15:47:27 +03:00
Elian Doran
c178fc2957 Translations update from Hosted Weblate (#7186) 2025-10-04 15:41:40 +03:00
Hosted Weblate
9d8c62caaf Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-04 06:44:06 +00:00
minkipark
279f014c42 Translated using Weblate (Korean)
Currently translated at 10.2% (39 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ko/
2025-10-04 06:44:06 +00:00
minkipark
826e9c7114 Translated using Weblate (Korean)
Currently translated at 2.1% (34 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ko/
2025-10-04 06:44:05 +00:00
Languages add-on
384c8649b4 Added translation using Weblate (Norwegian Bokmål) 2025-10-04 06:44:05 +00:00
Languages add-on
ecc8bc3866 Added translation using Weblate (Slovenian) 2025-10-04 06:44:04 +00:00
Languages add-on
bb4d723f18 Added translation using Weblate (Korean) 2025-10-04 06:44:04 +00:00
Languages add-on
e250510ab1 Added translation using Weblate (Serbian) 2025-10-04 06:44:03 +00:00
Languages add-on
dc630f927f Added translation using Weblate (Finnish) 2025-10-04 06:44:02 +00:00
Languages add-on
e47cb13b89 Added translation using Weblate (Persian) 2025-10-04 06:44:02 +00:00
Languages add-on
838ae315e3 Added translation using Weblate (French) 2025-10-04 06:44:01 +00:00
Languages add-on
58afa86a2b Added translation using Weblate (Dutch) 2025-10-04 06:44:01 +00:00
Languages add-on
5b90ece12f Added translation using Weblate (Arabic) 2025-10-04 06:44:00 +00:00
Languages add-on
afb2072b97 Added translation using Weblate (Polish) 2025-10-04 06:44:00 +00:00
Languages add-on
8e0ca56b85 Added translation using Weblate (Hungarian) 2025-10-04 06:43:59 +00:00
Languages add-on
8e4cf38840 Added translation using Weblate (Croatian) 2025-10-04 06:43:58 +00:00
Languages add-on
cb872d3638 Added translation using Weblate (Vietnamese) 2025-10-04 06:43:58 +00:00
Languages add-on
781be26833 Added translation using Weblate (Portuguese) 2025-10-04 06:43:57 +00:00
Languages add-on
0ad5f3493d Added translation using Weblate (Czech) 2025-10-04 06:43:57 +00:00
Languages add-on
15bb3acb31 Added translation using Weblate (Catalan) 2025-10-04 06:43:56 +00:00
Languages add-on
a43ddf3f9f Added translation using Weblate (Ukrainian) 2025-10-04 06:43:56 +00:00
Languages add-on
8417bfebb0 Added translation using Weblate (Greek) 2025-10-04 06:43:55 +00:00
Languages add-on
28e8ea2da9 Added translation using Weblate (Portuguese (Brazil)) 2025-10-04 06:43:54 +00:00
Languages add-on
393264b4a1 Added translation using Weblate (Turkish) 2025-10-04 06:43:54 +00:00
Jiho Min
9306a28c87 Translated using Weblate (Korean)
Currently translated at 1.8% (29 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ko/
2025-10-04 06:43:53 +00:00
Newcomer1989
77fef38009 Added translation using Weblate (German) 2025-10-04 06:43:53 +00:00
Elian Doran
c14ea42978 Translated using Weblate (Romanian)
Currently translated at 21.7% (25 of 115 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ro/
2025-10-04 06:43:52 +00:00
Elian Doran
341cd62b13 Added translation using Weblate (Romanian) 2025-10-04 06:43:52 +00:00
Hosted Weblate
9e6cfe7c1e Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-10-04 06:43:51 +00:00
Tore Aursand
9695dd404b Translated using Weblate (Norwegian Bokmål)
Currently translated at 1.8% (7 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/nb_NO/
2025-10-04 06:43:50 +00:00
green
5e6be01251 Translated using Weblate (Japanese)
Currently translated at 100.0% (381 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/
2025-10-04 06:43:50 +00:00
Elian Doran
f367a1c776 fix(deps): update eslint monorepo to v9.37.0 (#7197) 2025-10-04 09:43:42 +03:00
renovate[bot]
bce987c67a fix(deps): update eslint monorepo to v9.37.0 2025-10-04 05:55:42 +00:00
Elian Doran
e7a9f9c566 chore(deps): update dependency @types/serve-static to v1.15.9 (#7190) 2025-10-04 08:50:10 +03:00
Elian Doran
33150e3a98 chore(deps): update dependency electron to v38.2.1 (#7191) 2025-10-04 08:49:56 +03:00
renovate[bot]
e1aead098e chore(deps): update dependency @types/serve-static to v1.15.9 2025-10-04 05:49:51 +00:00
Elian Doran
9f9a276a51 chore(deps): update dependency eslint-plugin-react-hooks to v6.1.1 (#7192) 2025-10-04 08:49:41 +03:00
Elian Doran
873df6da6c chore(deps): update softprops/action-gh-release action to v2.3.4 (#7193) 2025-10-04 08:49:23 +03:00
Elian Doran
2e353afb98 fix(deps): update dependency katex to v0.16.23 (#7194) 2025-10-04 08:48:52 +03:00
Elian Doran
d497688d9a chore(deps): update dependency stylelint to v16.25.0 (#7195) 2025-10-04 08:48:32 +03:00
Elian Doran
2cf3a04482 fix(deps): update dependency eslint-linter-browserify to v9.37.0 (#7196) 2025-10-04 08:47:55 +03:00
renovate[bot]
e50fd6f540 fix(deps): update dependency eslint-linter-browserify to v9.37.0 2025-10-04 01:11:23 +00:00
renovate[bot]
5096163ae3 chore(deps): update dependency stylelint to v16.25.0 2025-10-04 01:10:24 +00:00
renovate[bot]
0d6640ae14 fix(deps): update dependency katex to v0.16.23 2025-10-04 01:09:28 +00:00
renovate[bot]
52ac93e99c chore(deps): update softprops/action-gh-release action to v2.3.4 2025-10-04 01:08:33 +00:00
renovate[bot]
674b0a8215 chore(deps): update dependency eslint-plugin-react-hooks to v6.1.1 2025-10-04 01:08:27 +00:00
renovate[bot]
ec56b297dc chore(deps): update dependency electron to v38.2.1 2025-10-04 01:07:35 +00:00
Elian Doran
a477cc22e6 docs(readme): normalize file name format 2025-10-03 20:25:49 +03:00
Elian Doran
119278b5f5 docs(readme): redesign support section 2025-10-03 20:12:32 +03:00
Elian Doran
5414fbeacb docs(readme): improve shoutsout section 2025-10-03 20:00:32 +03:00
Adorian Doran
a4b01bba9b website/GitHub utils: improve 2025-10-03 19:36:36 +03:00
Adorian Doran
bab536751a website: use a pre-defined GitHub stargazers count outside of SSR 2025-10-03 19:22:58 +03:00
Adorian Doran
7657e17373 website: add a GitHub social button to the site's header 2025-10-03 19:09:23 +03:00
Adorian Doran
30f530abdb website: use "Inter" as the main font 2025-10-03 17:09:17 +03:00
Adorian Doran
1d373bc7d5 Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-10-03 16:49:20 +03:00
Adorian Doran
9d3c5d04b9 website: add meta description 2025-10-03 16:49:10 +03:00
Elian Doran
ba91fbbe6b fix(ribbon): formatting tab not activating automatically (closes #7185) 2025-10-03 16:46:26 +03:00
Elian Doran
f6898779bb fix(code): unable to search in read-only code notes 2025-10-03 16:09:32 +03:00
Elian Doran
dbb90bdd2b fix(client/print): split button visible 2025-10-03 16:05:32 +03:00
Elian Doran
f442c56ed6 fix(client/options): missing ribbon widgets section in Appearance 2025-10-03 16:01:31 +03:00
Elian Doran
e971a9cb03 fix(client): enter shortcut key not working 2025-10-03 15:46:53 +03:00
Elian Doran
b450a4faa0 fix(client): delete shortcut key not working 2025-10-03 15:39:27 +03:00
Elian Doran
9a2440942b chore(deps): update dependency vite to v7.1.9 (#7177) 2025-10-03 09:13:39 +03:00
Elian Doran
c3151f9afa chore(deps): update dependency openai to v6.1.0 (#7178) 2025-10-03 09:13:09 +03:00
renovate[bot]
f277612444 chore(deps): update dependency openai to v6.1.0 2025-10-03 06:12:29 +00:00
renovate[bot]
1b92ad2f53 chore(deps): update dependency vite to v7.1.9 2025-10-03 06:11:33 +00:00
Elian Doran
f96abe0e45 chore(deps): update pnpm to v10.18.0 (#7179) 2025-10-03 09:09:27 +03:00
Elian Doran
142a276cc4 fix(deps): update codemirror (#7180) 2025-10-03 09:09:05 +03:00
renovate[bot]
a52b0a45fe fix(deps): update codemirror 2025-10-03 00:28:25 +00:00
renovate[bot]
6df40ec80a chore(deps): update pnpm to v10.18.0 2025-10-03 00:27:33 +00:00
Elian Doran
713340a9ba docs(guide): advanced CSS customisation 2025-10-02 22:25:47 +03:00
Elian Doran
ee8b41c81b Equation improvements (#7174) 2025-10-02 21:43:58 +03:00
Elian Doran
dd477258a9 docs(guide): document formatting equations 2025-10-02 21:35:54 +03:00
Elian Doran
7c30e2b4f6 feat(math): inherit attributes from selection 2025-10-02 20:52:05 +03:00
Elian Doran
37a3c00214 Translations update from Hosted Weblate (#7175) 2025-10-02 19:13:50 +03:00
Tore Aursand
d30cdadb2d Added translation using Weblate (Norwegian Bokmål) 2025-10-02 18:09:59 +02:00
Tore Aursand
58f0d01944 Added translation using Weblate (Norwegian Bokmål) 2025-10-02 18:09:58 +02:00
Elian Doran
d4791944b0 Translated using Weblate (Romanian)
Currently translated at 100.0% (381 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ro/
2025-10-02 18:09:57 +02:00
Elian Doran
92a052674f Translated using Weblate (Romanian)
Currently translated at 100.0% (1605 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ro/
2025-10-02 18:09:57 +02:00
Elian Doran
d49ce7c289 feat(math): support more attributes 2025-10-02 18:32:46 +03:00
Elian Doran
5f38d52f20 feat(math): support font size adjustment (closes #7172) 2025-10-02 18:31:08 +03:00
Elian Doran
6286745684 Translations update from Hosted Weblate (#7171) 2025-10-02 12:07:03 +03:00
Bilal Janati
4f574f8aa4 Translated using Weblate (French)
Currently translated at 88.4% (337 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/fr/
2025-10-02 11:02:04 +02:00
Bilal Janati
a3e27248ad Translated using Weblate (French)
Currently translated at 85.0% (1365 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/fr/
2025-10-02 11:02:01 +02:00
Elian Doran
e48569245d chore(deps): update dependency jiti to v2.6.1 (#7161) 2025-10-02 11:19:28 +03:00
Elian Doran
473f7a83e6 chore(deps): update dependency openai to v6.0.1 (#7162) 2025-10-02 11:19:18 +03:00
Elian Doran
1c622fa848 fix(deps): update dependency mind-elixir to v5.3.1 (#7166) 2025-10-02 11:19:09 +03:00
renovate[bot]
409e650506 fix(deps): update dependency mind-elixir to v5.3.1 2025-10-02 07:47:06 +00:00
renovate[bot]
d461f5474e chore(deps): update dependency openai to v6.0.1 2025-10-02 07:46:28 +00:00
renovate[bot]
36e731cc2c chore(deps): update dependency jiti to v2.6.1 2025-10-02 07:45:40 +00:00
Elian Doran
b77fbcb7ad chore(deps): update dependency vite-plugin-static-copy to v3.1.3 (#7163) 2025-10-02 10:38:46 +03:00
Elian Doran
7b7dc346ca fix(deps): update dependency i18next to v25.5.3 (#7164) 2025-10-02 10:38:26 +03:00
Elian Doran
b4f8a02ba6 chore(deps): update dependency react-refresh to v0.18.0 (#7165) 2025-10-02 10:38:10 +03:00
Elian Doran
9d6a5d1bb5 chore(deps): update dependency eslint-plugin-react-hooks to v6 (#7167) 2025-10-02 10:37:46 +03:00
renovate[bot]
fa747c5c4b chore(deps): update dependency eslint-plugin-react-hooks to v6 2025-10-02 04:56:39 +00:00
renovate[bot]
bc93f40cdb chore(deps): update dependency react-refresh to v0.18.0 2025-10-02 04:54:53 +00:00
renovate[bot]
a9975798d7 fix(deps): update dependency i18next to v25.5.3 2025-10-02 04:54:01 +00:00
renovate[bot]
4ea4404aba chore(deps): update dependency vite-plugin-static-copy to v3.1.3 2025-10-02 04:53:11 +00:00
Elian Doran
361848b518 fix(deps): update ckeditor monorepo to v47 (major) (#7168) 2025-10-02 07:49:34 +03:00
renovate[bot]
8c46103f63 fix(deps): update ckeditor monorepo to v47 2025-10-02 01:54:42 +00:00
Elian Doran
edcdecb720 Merge branch 'main' of https://github.com/TriliumNext/trilium 2025-10-01 22:27:42 +03:00
Elian Doran
e1ef02058d fix(client): function keys (e.g. help) not working due to change in modifiers 2025-10-01 22:27:39 +03:00
Elian Doran
d9746df16b chore(deps): pin all deps to latest (#7159) 2025-10-01 21:13:48 +03:00
Elian Doran
b4c20d9683 fix(client): shortcut keys without modifiers affecting normal usage 2025-10-01 21:08:51 +03:00
Elian Doran
59955b7414 chore(deps): pin all deps to latest 2025-10-01 20:52:25 +03:00
Elian Doran
95b1c82ccb docs(guide): document script logging 2025-10-01 20:22:50 +03:00
Elian Doran
7cfebbabeb feat(script): api.log now supports objects 2025-10-01 20:22:02 +03:00
Elian Doran
f412874c73 fix(export): missing toast icon 2025-10-01 19:51:36 +03:00
Elian Doran
873c4c6636 refactor(client): remove string from viewtype 2025-10-01 19:44:55 +03:00
Elian Doran
efcd54be50 fix(ribbon): not visible when coming from view source on same note 2025-10-01 19:41:20 +03:00
Elian Doran
ae0bb78b1c docs(guide): document included notes in share 2025-10-01 19:41:20 +03:00
Elian Doran
29fa335a27 chore(deps): update dependency typescript to v5.9.3 (#7151) 2025-10-01 19:32:42 +03:00
Elian Doran
3a84a78cd1 chore(deps): update dependency openai to v6 (#7155) 2025-10-01 19:31:40 +03:00
Elian Doran
df6bb7e6bf fix(deps): broken types after major update 2025-10-01 19:21:51 +03:00
renovate[bot]
dfcaebc613 chore(deps): update dependency openai to v6 2025-10-01 14:03:26 +00:00
renovate[bot]
1ece35536b chore(deps): update dependency typescript to v5.9.3 2025-10-01 14:02:28 +00:00
Elian Doran
1a90548622 chore(deps): update dependency @types/node to v22.18.8 (#7149) 2025-10-01 16:53:06 +03:00
renovate[bot]
cc7e5bdb80 chore(deps): update dependency @types/node to v22.18.8 2025-10-01 08:18:20 +00:00
Elian Doran
5c73b21ff7 chore(deps): update dependency dotenv to v17.2.3 (#7142) 2025-10-01 11:15:17 +03:00
Elian Doran
e9078107ae chore(deps): update dependency preact-render-to-string to v6.6.2 (#7150) 2025-10-01 11:14:59 +03:00
Elian Doran
6c24b18bc1 chore(deps): update dependency typescript to v5.9.3 (#7152) 2025-10-01 11:14:44 +03:00
renovate[bot]
be7ff73142 chore(deps): update dependency preact-render-to-string to v6.6.2 2025-10-01 08:14:24 +00:00
renovate[bot]
63ac45d369 chore(deps): update dependency dotenv to v17.2.3 2025-10-01 08:13:59 +00:00
Elian Doran
f164a4b786 fix(deps): update dependency @codemirror/legacy-modes to v6.5.2 (#7153) 2025-10-01 11:13:49 +03:00
Elian Doran
806d601115 chore(deps): update dependency @smithy/middleware-retry to v4.4.0 (#7154) 2025-10-01 11:13:05 +03:00
Elian Doran
6b3cf49398 Translations update from Hosted Weblate (#7158) 2025-10-01 11:11:37 +03:00
Kevin Leutzinger
b8851565eb docs: clarify shareHtmlLocation goes on snippet note 2025-10-01 03:53:40 -04:00
Kevin Leutzinger
888d0d1084 add docs about shareHtml and shareHtmlLocation 2025-10-01 03:47:49 -04:00
Kevin Leutzinger
0a25d4db0d shareHTML to shareHtml 2025-10-01 03:30:16 -04:00
A
4a72f2c6a7 Translated using Weblate (Finnish)
Currently translated at 3.4% (13 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/fi/
2025-10-01 08:02:13 +02:00
A
446bdd6a5e Translated using Weblate (Finnish)
Currently translated at 6.1% (98 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/fi/
2025-10-01 08:02:12 +02:00
Lorenzo Strambi
cb26fac2ea Translated using Weblate (Italian)
Currently translated at 35.6% (136 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/it/
2025-10-01 08:02:11 +02:00
Lorenzo Strambi
3a45440c74 Translated using Weblate (Italian)
Currently translated at 12.9% (208 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-10-01 08:02:09 +02:00
Kuzma Simonov
e115d6e275 Translated using Weblate (Russian)
Currently translated at 100.0% (1605 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-10-01 08:02:07 +02:00
Aitanuqui
fc614ccf83 Translated using Weblate (Spanish)
Currently translated at 100.0% (381 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/es/
2025-10-01 08:02:06 +02:00
Aitanuqui
17c9db7698 Translated using Weblate (Spanish)
Currently translated at 99.8% (1603 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/es/
2025-10-01 08:02:04 +02:00
Kevin Leutzinger
d483b6e840 add shareHTML relation 2025-09-30 23:06:20 -04:00
renovate[bot]
032819e812 chore(deps): update dependency @smithy/middleware-retry to v4.4.0 2025-10-01 02:24:12 +00:00
renovate[bot]
9d7d415756 fix(deps): update dependency @codemirror/legacy-modes to v6.5.2 2025-10-01 02:23:26 +00:00
renovate[bot]
e9d432b4bf chore(deps): update dependency typescript to v5.9.3 2025-10-01 02:22:42 +00:00
Elian Doran
be35584f9a chore(website): cross-platform preview 2025-09-30 22:22:10 +03:00
Elian Doran
80be4cc6b8 feat(website): improve ARM detection 2025-09-30 22:20:10 +03:00
Elian Doran
c74ba44b91 chore(website): apply download card effect only on desktop 2025-09-30 21:58:44 +03:00
Elian Doran
28a79baa01 fix(website): hamburger menu alignment on mobile 2025-09-30 21:56:32 +03:00
Elian Doran
5279601105 fix(website): screenshot would not fit properly on some screen sizes 2025-09-30 21:53:15 +03:00
Elian Doran
c2639951a5 style(website): improve alignment of download button 2025-09-30 21:38:46 +03:00
Elian Doran
6bfab1387d chore(website): remove redundant winget link 2025-09-30 21:32:30 +03:00
Elian Doran
4212d208fc chore(website): build on preview 2025-09-30 21:22:32 +03:00
Elian Doran
9e5bded4cf chore(website): maintain platform coloring despite reordering 2025-09-30 21:21:26 +03:00
Elian Doran
ce0763f03d feat(website): reorder platforms to always get the recommended one in center 2025-09-30 21:18:52 +03:00
Elian Doran
e860b7aa32 chore(website): arch & platform not properly rendered statically 2025-09-30 21:08:19 +03:00
Elian Doran
0be9310450 feat(website): highlight which platform to download 2025-09-30 21:06:19 +03:00
Elian Doran
d870a260e1 feat(website): improve download instructions 2025-09-30 20:53:29 +03:00
Elian Doran
2de545be1c chore(website): fix page title 2025-09-30 19:46:47 +03:00
Elian Doran
bf04e5a15b feat(website): different download behaviour for Linux 2025-09-30 19:45:56 +03:00
Elian Doran
46d2d7e160 feat(website): linux light/dark screenshot 2025-09-30 19:35:42 +03:00
Elian Doran
1775b22c7a chore(deps): update dependency @types/node to v22.18.7 (#7140) 2025-09-30 13:37:13 +03:00
Elian Doran
ae022b6389 chore(deps): update dependency dotenv to v17.2.3 (#7141) 2025-09-30 13:37:02 +03:00
renovate[bot]
d4155102c5 chore(deps): update dependency dotenv to v17.2.3 2025-09-30 09:52:06 +00:00
renovate[bot]
3b1a25230f chore(deps): update dependency @types/node to v22.18.7 2025-09-30 09:51:14 +00:00
Elian Doran
d8639793e0 chore(deps): update dependency happy-dom to v19.0.2 (#7143) 2025-09-30 12:43:46 +03:00
Elian Doran
06fec88214 chore(deps): update dependency @anthropic-ai/sdk to v0.65.0 (#7144) 2025-09-30 12:43:33 +03:00
Elian Doran
da93928976 chore(deps): update dependency cross-env to v10.1.0 (#7145) 2025-09-30 12:43:19 +03:00
Elian Doran
2314443d19 chore(deps): update typescript-eslint monorepo to v8.45.0 (#7146) 2025-09-30 12:42:59 +03:00
renovate[bot]
4b34047324 chore(deps): update typescript-eslint monorepo to v8.45.0 2025-09-30 00:39:57 +00:00
renovate[bot]
bc1d4de13d chore(deps): update dependency cross-env to v10.1.0 2025-09-30 00:38:12 +00:00
renovate[bot]
6bae4c8075 chore(deps): update dependency @anthropic-ai/sdk to v0.65.0 2025-09-30 00:37:22 +00:00
renovate[bot]
84a89fd0ba chore(deps): update dependency happy-dom to v19.0.2 2025-09-30 00:36:28 +00:00
Elian Doran
1447fa6f14 Translations update from Hosted Weblate (#7137) 2025-09-29 23:37:41 +03:00
Микола Копитін
bc4937f9d2 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (1605 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/uk/
2025-09-29 22:34:06 +02:00
Josue Estrada
43a7b828d9 Translated using Weblate (Spanish)
Currently translated at 99.1% (1591 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/es/
2025-09-29 22:34:06 +02:00
Elian Doran
d611591e1a docs(user): document a few gaps 2025-09-29 23:33:53 +03:00
Elian Doran
f7a565ec73 refactor(collections/table): rework persistence 2025-09-29 17:51:53 +03:00
Elian Doran
6b35e909ab fix(collections): note list sometimes not restored (fixes #7129) 2025-09-29 17:51:53 +03:00
Elian Doran
53b9ce0f3d Automatically resize webview (#7125) 2025-09-29 10:48:47 +03:00
Elian Doran
5e1cd7d6ac Replace jsdom with node-html-parser (#7128) 2025-09-29 10:47:33 +03:00
Elian Doran
acb98061ce chore(deps): remove jsdom as dev dependency 2025-09-29 09:59:39 +03:00
Elian Doran
979ef6287f chore(server): different handling of buffer vs string 2025-09-29 09:55:34 +03:00
Elian Doran
58a883797d fix(server): infinite loop in note map 2025-09-29 09:45:16 +03:00
Elian Doran
f718e87673 chore(server): fix share content renderer 2025-09-29 09:25:46 +03:00
Elian Doran
4c6a742af7 chore(server): fix clipper 2025-09-29 09:25:31 +03:00
Elian Doran
848dc51a7a Merge remote-tracking branch 'origin/main' into refactor/replace_jsdom 2025-09-29 09:22:36 +03:00
Elian Doran
44541b66c4 chore(deps): update dependency lint-staged to v16.2.3 (#7130) 2025-09-29 09:20:13 +03:00
Elian Doran
3694018441 chore(deps): update dependency rollup-plugin-webpack-stats to v2.1.5 (#7131) 2025-09-29 09:20:00 +03:00
Elian Doran
3874e54d76 fix(deps): update dependency @codemirror/view to v6.38.4 (#7132) 2025-09-29 09:19:48 +03:00
Elian Doran
10de141c00 chore(deps): update dependency electron to v38.2.0 (#7133) 2025-09-29 09:19:32 +03:00
Elian Doran
806ba320a8 chore(deps): update dependency preact-iso to v2.11.0 (#7134) 2025-09-29 09:19:11 +03:00
Elian Doran
09ef24d27d chore(deps): update dependency happy-dom to v19 (#7135) 2025-09-29 09:18:58 +03:00
renovate[bot]
236f3cada7 chore(deps): update dependency happy-dom to v19 2025-09-29 05:59:00 +00:00
renovate[bot]
c2afef4832 chore(deps): update dependency preact-iso to v2.11.0 2025-09-29 05:58:11 +00:00
renovate[bot]
b9fa7d70bb chore(deps): update dependency electron to v38.2.0 2025-09-29 05:56:26 +00:00
renovate[bot]
9ac31f2667 fix(deps): update dependency @codemirror/view to v6.38.4 2025-09-29 05:55:32 +00:00
renovate[bot]
639d1befef chore(deps): update dependency rollup-plugin-webpack-stats to v2.1.5 2025-09-29 05:54:31 +00:00
renovate[bot]
b99c8d5cc1 chore(deps): update dependency lint-staged to v16.2.3 2025-09-29 05:53:37 +00:00
Elian Doran
0770398010 Translations update from Hosted Weblate (#7136) 2025-09-29 08:51:13 +03:00
green
c3d24451b7 Translated using Weblate (Japanese)
Currently translated at 100.0% (1605 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-09-29 03:02:01 +00:00
Francis C
4db1a3bdec Translated using Weblate (Japanese)
Currently translated at 100.0% (1605 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-09-29 03:02:00 +00:00
Elian Doran
2a0410f597 chore(types): fill in gap from jsdom 2025-09-28 20:55:20 +03:00
Elian Doran
7e79d907be feat(server): replace jsdom 2025-09-28 19:43:04 +03:00
Elian Doran
c0ea441c59 chore(server): fix tests 2025-09-28 19:19:39 +03:00
Elian Doran
290d134d88 test(server/similarity): reward map 2025-09-28 19:10:49 +03:00
Elian Doran
517bfd2c9a test(server/note_map): clipper processing notes & images 2025-09-28 19:02:38 +03:00
Papierkorb2292
31990a9992 Let browser display webview with max size instead of manually adjusting the size, so the webview size is sure to be updated when a parent element changes size 2025-09-28 17:41:25 +02:00
Elian Doran
151a2c284d test(server/note_map): backlinks with excerpts 2025-09-28 17:12:01 +03:00
Elian Doran
614a8f177c test(server/share): attachment links 2025-09-28 15:43:39 +03:00
Elian Doran
8b5e53e579 test(server/share): included text notes 2025-09-28 15:07:10 +03:00
Elian Doran
1ad8b1bf85 test(server/share): protected notes 2025-09-28 14:48:14 +03:00
Elian Doran
a393584a2a test(server/share): implement basic shaca mocking with content 2025-09-28 14:40:30 +03:00
Elian Doran
804fc72ed8 test(server/share): basic text rendering check 2025-09-28 14:07:55 +03:00
Elian Doran
3f8f05368c fix(modal): event leak for onHidden 2025-09-28 11:10:39 +03:00
Elian Doran
5a56ba2fd5 chore: fix various references to the old repo 2025-09-28 11:02:24 +03:00
Elian Doran
de7c1329f8 fix(add_link): focus resets to start of note (closes #7115) 2025-09-28 10:55:48 +03:00
Elian Doran
6fc5aa0090 fix(bulk_actions): deleting a bulk action would execute all bulk actions 2025-09-28 10:42:15 +03:00
Elian Doran
2eaeccda05 fix(next): toasts unreadable with background effects on 2025-09-28 10:38:24 +03:00
Elian Doran
56f970ab08 chore(deps): update dependency webdriverio to v9.20.0 (#7119) 2025-09-28 10:37:49 +03:00
renovate[bot]
d1cb9e4a3f chore(deps): update dependency webdriverio to v9.20.0 2025-09-28 00:59:17 +00:00
Elian Doran
992adcab65 Correct 'febuary' key and fix Russian typos (#7103) 2025-09-28 02:14:11 +03:00
Elian Doran
d3b3a83477 Translations update from Hosted Weblate (#7118) 2025-09-28 02:12:34 +03:00
Miljenko Šuflaj
98ad371d01 Translated using Weblate (Croatian)
Currently translated at 25.7% (98 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/hr/
2025-09-28 01:02:04 +02:00
green
3cdae245e1 Translated using Weblate (Japanese)
Currently translated at 100.0% (381 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/
2025-09-28 01:02:03 +02:00
Kuzma Simonov
887c78d893 Translated using Weblate (Russian)
Currently translated at 99.6% (1600 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-09-28 01:02:02 +02:00
green
e208497d71 Translated using Weblate (Japanese)
Currently translated at 100.0% (1605 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-09-28 01:02:01 +02:00
Elian Doran
dd744b4e0d Landing page (#7108) 2025-09-28 01:34:06 +03:00
Elian Doran
647cbc7e7a chore(ci): set up pnpm cache for website deployment 2025-09-28 01:08:27 +03:00
Elian Doran
cc93102859 fix(website): null error in download-helper 2025-09-28 01:03:31 +03:00
Elian Doran
5b673e753b fix(website): hydration issues due to rendering on the server of client-side logic 2025-09-28 00:58:15 +03:00
Elian Doran
bd2eb6fdbb fix(website): screenshot not loading due to SSR 2025-09-28 00:36:21 +03:00
Elian Doran
c25f783980 fix(website): typecheck failing due to asset import 2025-09-28 00:29:40 +03:00
Elian Doran
9b37708f0c fix(ci): missing deployment secrets in reusable action 2025-09-28 00:21:05 +03:00
Elian Doran
7386bb35e5 fix(website): yet another case of server-side rendering failing 2025-09-28 00:16:51 +03:00
Elian Doran
9274522877 chore(ci): don't run playwright on website changes 2025-09-28 00:15:15 +03:00
Elian Doran
1b444686af fix(website): another case of server-side rendering failing 2025-09-28 00:15:04 +03:00
Elian Doran
b3dfdacdc3 fix(ci): failing due to electron-rebuild 2025-09-28 00:10:54 +03:00
Elian Doran
159fab41ce fix(website): SSR not working due to download helper 2025-09-28 00:02:41 +03:00
Elian Doran
093f48f76a feat(ci): filter dependencies to make installation faster 2025-09-28 00:00:29 +03:00
Elian Doran
6998a3593e feat(ci): set up deployment workflow for website 2025-09-27 23:57:56 +03:00
Elian Doran
c3250cfd72 style(website): minor missing margin on mobile 2025-09-27 22:59:28 +03:00
Elian Doran
e52eb9bcb0 feat(website): switch assets to webp 2025-09-27 22:42:08 +03:00
Elian Doran
5ac2892e34 chore(website): fix typecheck issues 2025-09-27 22:36:26 +03:00
Elian Doran
a15aab395a feat(website): add alt + lazy loading 2025-09-27 22:26:41 +03:00
Elian Doran
f991276152 feat(website): add link to older versions 2025-09-27 22:23:10 +03:00
Elian Doran
1f71ceb611 fix(website): favicon no longer working 2025-09-27 22:16:38 +03:00
Elian Doran
92e14159b9 feat(website): display version to be downloaded 2025-09-27 22:16:19 +03:00
Elian Doran
b8419604e5 fix(website): discrepancies in production build 2025-09-27 21:29:39 +03:00
Elian Doran
096fd82e64 style(website): minor tweaks on light/dark mode 2025-09-27 21:20:28 +03:00
Elian Doran
cbaae52a7e style(website): minor improvements to get started 2025-09-27 21:14:20 +03:00
Elian Doran
5905299331 fix(website): mobile regression and layout tweaks 2025-09-27 21:11:34 +03:00
Elian Doran
2df0763141 refactor(website): use nested CSS 2025-09-27 21:02:23 +03:00
Elian Doran
fb7453f7b0 feat(website): improve icon fit 2025-09-27 19:59:12 +03:00
Elian Doran
974d20b0ba feat(website): add icons to collections 2025-09-27 19:56:11 +03:00
Elian Doran
c2f6d9aa07 feat(website): add icons to note types 2025-09-27 19:53:47 +03:00
Elian Doran
6194386464 feat(website): reorder sections around 2025-09-27 19:39:39 +03:00
Elian Doran
329ecd6894 feat(website): improve FAQ section 2025-09-27 19:29:40 +03:00
Elian Doran
150f470aee chore(website): improve scoop link 2025-09-27 19:26:29 +03:00
Elian Doran
83b843f047 style(website): disable link underline globally 2025-09-27 19:23:16 +03:00
Elian Doran
24043611c3 feat(website): split REST API into separate entry 2025-09-27 19:20:03 +03:00
Elian Doran
2c99ba64bc feat(website): add links to all feature descriptions 2025-09-27 19:08:39 +03:00
Elian Doran
ffe30bed75 chore(website): use same more info mechanism for list with screenshot 2025-09-27 19:02:13 +03:00
Elian Doran
b6088f488f feat(website): use list with screenshot for note types 2025-09-27 18:59:51 +03:00
Elian Doran
e04165a184 feat(website): use list with screenshot for note types 2025-09-27 18:47:45 +03:00
Elian Doran
d7aa95ce8e feat(website): add icons for each benefit 2025-09-27 18:40:00 +03:00
Elian Doran
28214ec9fb feat(website): split benefits into three different sections 2025-09-27 18:27:15 +03:00
Elian Doran
28952a5253 feat(website): list with screenshot for collections 2025-09-27 18:17:20 +03:00
Elian Doran
d66505e5bc fix(website): hover effect for buttons 2025-09-27 17:57:24 +03:00
Elian Doran
c4354032b5 feat(website): add a final call-to-action 2025-09-27 17:56:59 +03:00
Elian Doran
d23550d3ef fix(website): mobile menu causing issues with scroll anchoring 2025-09-27 17:39:40 +03:00
Elian Doran
894ec1e3c1 feat(website): social buttons in mobile menu 2025-09-27 17:37:01 +03:00
Elian Doran
bdb03f8d51 style(website): use color in header instead of bold for active 2025-09-27 17:28:14 +03:00
Elian Doran
61ea27c8f4 style(website): misalignment of icon in button 2025-09-27 17:27:02 +03:00
Elian Doran
ac45617d8f feat(website): mobile toggle menu 2025-09-27 17:23:44 +03:00
Elian Doran
35853ff988 fix(website): logo not working in subfolder 2025-09-27 17:04:31 +03:00
Elian Doran
80009f99e8 chore(website): rebrand donate to support us 2025-09-27 17:03:39 +03:00
Elian Doran
0b1d001c20 chore(website): rebrand download to get started 2025-09-27 17:01:54 +03:00
Elian Doran
cb63e88cdc style(website): colored download links 2025-09-27 16:52:43 +03:00
Elian Doran
a5c7f4221b feat(website): full-width Docker card 2025-09-27 16:49:32 +03:00
Elian Doran
f61010a65e feat(website): further improve alignment in download cards 2025-09-27 16:42:06 +03:00
Elian Doran
b99f5b2cbe feat(website): multiple recommended downloads for better fit 2025-09-27 16:39:10 +03:00
Elian Doran
9919d0cbfa style(website): align download buttons slightly 2025-09-27 16:35:09 +03:00
Elian Doran
fe8099d8d1 feat(website): change URL for NixOS server module 2025-09-27 16:30:25 +03:00
Elian Doran
0da336c8e1 feat(website): homebrew cask for macOS 2025-09-27 16:25:10 +03:00
Elian Doran
37f5d19739 feat(website): quick start for downloads 2025-09-27 16:23:12 +03:00
Elian Doran
2ac0d84cee feat(website): help button for Linux and Docker 2025-09-27 16:09:16 +03:00
Elian Doran
e639961b68 feat(website): open external links in new tab in downloads 2025-09-27 15:58:37 +03:00
Elian Doran
adf29b4e6e refactor(website): use button component in downloads 2025-09-27 15:57:23 +03:00
Elian Doran
b00cd032a3 feat(website): add dedicated card for docker in downloads 2025-09-27 15:51:42 +03:00
Elian Doran
60e8f46777 feat(website): add help pages to all note types / collections 2025-09-27 15:38:01 +03:00
Elian Doran
ef2860770f chore(website): minor adjustment to footer 2025-09-27 15:22:06 +03:00
Elian Doran
aa562e9c26 style(website): full-height for desktop download section 2025-09-27 15:01:59 +03:00
Elian Doran
866ccc1696 feat(website): windows light/dark screenshot 2025-09-27 15:01:03 +03:00
Elian Doran
dbe241dee7 feat(website): macos light/dark screenshot 2025-09-27 14:47:46 +03:00
Elian Doran
bd32a08e11 style(website): slight adjustments to hero section on desktop 2025-09-27 14:29:17 +03:00
Elian Doran
8416dab870 feat(website): improve hero download buttons on mobile 2025-09-27 14:27:31 +03:00
Elian Doran
6fda669307 feat(website): add github & docker links on hero section 2025-09-27 14:15:08 +03:00
Elian Doran
c21a9223f5 refactor(website): use link component with rel 2025-09-27 14:02:49 +03:00
Elian Doran
4e4e65b462 feat(website): adjust page title 2025-09-27 13:55:04 +03:00
Elian Doran
5e07231d78 feat(website): add footer social buttons 2025-09-27 13:37:31 +03:00
Elian Doran
d71d1ce8b4 feat(website): improve the donation page 2025-09-27 13:18:48 +03:00
Elian Doran
892e84deaa feat(website): outline for donation buttons 2025-09-27 12:46:16 +03:00
Elian Doran
7a73af0299 feat(website): improve download button with icon and platform title 2025-09-27 12:41:33 +03:00
Elian Doran
65dae511e5 feat(website): add icons for donate buttons 2025-09-27 12:14:16 +03:00
Elian Doran
55c70b404c chore(website): improve header layout on mobile 2025-09-27 11:55:49 +03:00
Elian Doran
8117586548 chore(website): further improve layout on mobile 2025-09-27 11:54:00 +03:00
Elian Doran
3ce9c7ba3d chore(website): improve screenshot fit on mobile 2025-09-27 11:46:36 +03:00
Elian Doran
ab162efab8 chore(website): improve hero section layout on mobile 2025-09-27 11:43:19 +03:00
Elian Doran
babfc3cfb9 chore(website): hide download buttons on mobile 2025-09-27 11:34:09 +03:00
Elian Doran
3d780d7d02 chore(website): improve main layout on mobile 2025-09-27 11:32:30 +03:00
Elian Doran
5b81aff8be chore(website): set up name and favicon 2025-09-27 11:26:08 +03:00
Elian Doran
86b14a5763 chore(website): improve contrast on buttons on light theme 2025-09-27 11:22:56 +03:00
Elian Doran
14a2794d15 chore(website): minor changes according to review 2025-09-27 11:19:29 +03:00
Elian Doran
eef68aca0f chore(deps): update dependency @smithy/middleware-retry to v4.3.1 (#7109) 2025-09-27 10:39:03 +03:00
Elian Doran
f6f7445528 chore(deps): update dependency @anthropic-ai/sdk to v0.64.0 (#7111) 2025-09-27 10:37:47 +03:00
Elian Doran
f7c0184a6b fix(deps): update dependency react-i18next to v16 (#7112) 2025-09-27 10:37:27 +03:00
renovate[bot]
65bc599a16 fix(deps): update dependency react-i18next to v16 2025-09-27 01:29:01 +00:00
renovate[bot]
b445bef74c chore(deps): update dependency @anthropic-ai/sdk to v0.64.0 2025-09-27 01:28:15 +00:00
renovate[bot]
93d7ba032d chore(deps): update dependency @smithy/middleware-retry to v4.3.1 2025-09-27 01:26:19 +00:00
Elian Doran
334e2c3949 chore(website): get rid of package lock 2025-09-27 01:43:28 +03:00
Elian Doran
a11797fe6e chore(website): remove old website 2025-09-27 01:42:15 +03:00
Elian Doran
3cf0ec5740 feat(website): draft a donation page 2025-09-27 01:40:47 +03:00
Elian Doran
40f578f43f Translations update from Hosted Weblate (#7106) 2025-09-27 01:39:46 +03:00
Elian Doran
428abb4591 feat(website): improve 404 page 2025-09-27 01:20:59 +03:00
Elian Doran
4954fa89b5 feat(website): add link to documentation 2025-09-27 01:16:39 +03:00
Elian Doran
10f7837a7f style(website): full-height layout 2025-09-27 01:11:12 +03:00
Miljenko Šuflaj
fca310cc31 Added translation using Weblate (Croatian) 2025-09-27 00:06:19 +02:00
Miljenko Šuflaj
cf58b511df Added translation using Weblate (Croatian) 2025-09-27 00:06:19 +02:00
green
9da1f52a71 Translated using Weblate (Japanese)
Currently translated at 99.7% (380 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/
2025-09-27 00:06:17 +02:00
green
5c8e674ddb Translated using Weblate (Japanese)
Currently translated at 99.7% (1601 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-09-27 00:06:16 +02:00
Newcomer1989
f027b25bc2 Translated using Weblate (German)
Currently translated at 100.0% (1605 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-09-27 00:06:16 +02:00
Elian Doran
cfe71a3426 style(website): improve footer layout 2025-09-27 01:04:28 +03:00
Elian Doran
70afb636ca feat(website): architecture switcher for download 2025-09-27 01:01:06 +03:00
Elian Doran
818efe7fb0 feat(website): port download page 2025-09-27 00:46:51 +03:00
Elian Doran
3c2263db86 chore(website): apply content width to 404 page 2025-09-27 00:09:17 +03:00
Elian Doran
7c30bc9c72 feat(website): more options link in the hero section 2025-09-27 00:08:35 +03:00
Elian Doran
ec8d719d41 style(website): improve card title / content contrast 2025-09-26 23:54:39 +03:00
Elian Doran
5f884c4440 style(website): improve card on dark mode 2025-09-26 23:49:22 +03:00
Elian Doran
e6c806d462 style(website): improve hero section 2025-09-26 23:46:29 +03:00
Elian Doran
4afceeca79 style(website): general dark theme 2025-09-26 23:44:07 +03:00
Elian Doran
7990c60ce7 feat(website): clickable header banner 2025-09-26 23:40:34 +03:00
Elian Doran
74c248bce2 style(website): improve header nav layout 2025-09-26 23:37:36 +03:00
Elian Doran
2df646f80c refactor(website): move back into website2 2025-09-26 23:35:28 +03:00
Elian Doran
768260782a refactor(website): split each section into a component 2025-09-26 23:34:14 +03:00
Elian Doran
4eff105af5 refactor(website): split CSS 2025-09-26 23:32:09 +03:00
Elian Doran
68ef6ea142 chore(website): reimplement download button 2025-09-26 23:28:58 +03:00
Elian Doran
772d4ac5a1 chore(website): port the rest of the layout 2025-09-26 23:24:28 +03:00
Elian Doran
b3e1a79d40 chore(website): port FAQ 2025-09-26 23:21:41 +03:00
Elian Doran
d7afa8526d chore(website): port collections 2025-09-26 23:18:38 +03:00
Elian Doran
b4a2a6c12b chore(website): port note types 2025-09-26 23:16:06 +03:00
Elian Doran
32c15f5e03 chore(website): port benefits section 2025-09-26 23:06:57 +03:00
Elian Doran
b5a491820c chore(website): start with fresh template for preact 2025-09-26 22:54:56 +03:00
Elian Doran
8a477c87e0 chore(website): small adjustments to layout 2025-09-26 22:48:37 +03:00
Elian Doran
8bcae8cdb8 feat(website): smart download now button in header 2025-09-26 22:44:27 +03:00
Elian Doran
ea87161a91 feat(website): smart download now button 2025-09-26 22:40:27 +03:00
Elian Doran
f2bb6cb848 chore(website): remove unnecessary spacing in links 2025-09-26 22:21:12 +03:00
Elian Doran
fecb677552 chore(website): remove unnecessary nbsp 2025-09-26 22:19:21 +03:00
Elian Doran
3ba9b56833 chore(website): fix charset 2025-09-26 22:18:50 +03:00
Elian Doran
a329e7d72a chore(website): fix image references 2025-09-26 22:18:24 +03:00
Elian Doran
2568f6bb53 chore(website): improve formatting slightly 2025-09-26 22:11:15 +03:00
Elian Doran
23936596fa chore(website): extract stylesheet 2025-09-26 22:05:23 +03:00
Elian Doran
398db56fe7 chore(website): add existing structure 2025-09-26 22:04:17 +03:00
Elian Doran
423ef14ca6 chore(website): create empty template 2025-09-26 22:01:07 +03:00
Elian Doran
9921d3e0a7 feat(share): render included notes 2025-09-26 18:42:59 +03:00
e.lednev
ac22fd8d60 - Renamed localization key febuary to february.
- Corrected various spelling and grammatical errors in the `ru.json` translation file.
2025-09-26 13:17:19 +03:00
Elian Doran
ff065964e9 chore(deps): update dependency @sveltejs/kit to v2.43.5 (#7095) 2025-09-26 09:45:21 +03:00
Elian Doran
951dda50ac chore(deps): update dependency tsx to v4.20.6 (#7097) 2025-09-26 09:45:08 +03:00
renovate[bot]
01bd2f1815 chore(deps): update dependency tsx to v4.20.6 2025-09-26 05:42:18 +00:00
renovate[bot]
570f8fd155 chore(deps): update dependency @sveltejs/kit to v2.43.5 2025-09-26 05:41:31 +00:00
Elian Doran
5d348e3ad6 chore(deps): update dependency lint-staged to v16.2.1 (#7096) 2025-09-26 08:33:19 +03:00
Elian Doran
9573346d55 chore(deps): update dependency tsx to v4.20.6 (#7098) 2025-09-26 08:32:55 +03:00
Elian Doran
e4570a1bb0 chore(deps): update dependency @inlang/paraglide-js to v2.4.0 (#7099) 2025-09-26 08:32:18 +03:00
Elian Doran
b884aba244 Translations update from Hosted Weblate (#7100) 2025-09-26 08:31:57 +03:00
Jiri Novacek
9c73908560 Translated using Weblate (Czech)
Currently translated at 5.2% (20 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/cs/
2025-09-26 03:02:11 +00:00
Jiri Novacek
b399d292a9 Translated using Weblate (Czech)
Currently translated at 1.3% (21 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/cs/
2025-09-26 03:02:10 +00:00
green
a557d9770f Translated using Weblate (Japanese)
Currently translated at 98.9% (377 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/
2025-09-26 03:02:08 +00:00
greenfork
a11ebfeb42 Translated using Weblate (Russian)
Currently translated at 99.6% (1599 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-09-26 03:02:07 +00:00
green
4695c3726d Translated using Weblate (Japanese)
Currently translated at 93.0% (1494 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-09-26 03:02:05 +00:00
Francis C
324f79ceb9 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1605 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-09-26 03:02:04 +00:00
Antonio Martín Villaseñor
fc5e459895 Translated using Weblate (Spanish)
Currently translated at 99.0% (1589 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/es/
2025-09-26 03:02:03 +00:00
Francis C
bdaba67859 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1605 of 1605 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-09-26 03:02:01 +00:00
renovate[bot]
2b01e2fdaf chore(deps): update dependency @inlang/paraglide-js to v2.4.0 2025-09-26 02:12:30 +00:00
renovate[bot]
9967da6ea1 chore(deps): update dependency tsx to v4.20.6 2025-09-26 02:11:43 +00:00
renovate[bot]
a56a00ba2f chore(deps): update dependency lint-staged to v16.2.1 2025-09-26 02:10:11 +00:00
Elian Doran
82df26031f fix(client): Use number sorting for number columns in Table view (#7094) 2025-09-25 21:28:04 +03:00
Florian Meißner
b4af8e7339 fix(client): Use number sorting for number columns in Table view 2025-09-25 19:28:02 +02:00
Elian Doran
e6180f427b fix(client): note buttons visible in zen mode 2025-09-25 19:49:06 +03:00
Elian Doran
9a95ec170d fix(client): resize gutter not available in zen mode (fixes #7093) 2025-09-25 19:40:40 +03:00
Elian Doran
7be0507db5 chore(deps): update dependency electron to v38 (#6879) 2025-09-25 09:55:01 +03:00
Elian Doran
1d324ab3b0 chore(deps): override node-abi 2025-09-25 09:45:52 +03:00
Elian Doran
9e00ed7e14 chore(deps): update better-sqlite3 to 12.4.1 2025-09-25 09:38:13 +03:00
renovate[bot]
02a6652b44 chore(deps): update dependency electron to v38 2025-09-25 06:10:38 +00:00
Elian Doran
e19f7b286a chore(deps): update node.js to v22.20.0 (#7089) 2025-09-25 09:06:19 +03:00
Elian Doran
50301a97f3 chore(deps): update dependency @tailwindcss/typography to v0.5.19 (#7087) 2025-09-25 09:06:03 +03:00
Elian Doran
408e31079c chore(deps): update dependency ollama to v0.6.0 (#7088) 2025-09-25 09:05:49 +03:00
renovate[bot]
bf81e159ca chore(deps): update node.js to v22.20.0 2025-09-25 02:02:48 +00:00
renovate[bot]
b1f89296ff chore(deps): update dependency ollama to v0.6.0 2025-09-25 02:02:42 +00:00
renovate[bot]
1948302a64 chore(deps): update dependency @tailwindcss/typography to v0.5.19 2025-09-25 02:01:53 +00:00
Elian Doran
187585b32f style(next): fix alignment of multiplicity in promoted attrs 2025-09-24 23:37:00 +03:00
Elian Doran
d351fd506a chore(toast): get rid of redundant titles 2025-09-24 23:10:14 +03:00
Elian Doran
1cf29c985e Translations update from Hosted Weblate (#7086) 2025-09-24 22:57:32 +03:00
Jiri Novacek
04374540ad Translated using Weblate (Czech)
Currently translated at 2.8% (11 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/cs/
2025-09-24 21:40:24 +02:00
Jiri Novacek
ce8f3a4f8f Translated using Weblate (Czech)
Currently translated at 0.6% (11 of 1603 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/cs/
2025-09-24 21:40:24 +02:00
Krzysztof Kaplon
acb21b992d Translated using Weblate (Polish)
Currently translated at 75.0% (286 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/pl/
2025-09-24 21:40:23 +02:00
Elian Doran
15f344fe4a feat(toast): improve layout for toasts without title 2025-09-24 22:40:03 +03:00
Elian Doran
120324c3f0 style(next): show toast titles again 2025-09-24 22:03:35 +03:00
Elian Doran
59ce8b912d feat(ws): add a warning toast if websocket gets disconnected 2025-09-24 21:56:15 +03:00
Elian Doran
619888847b chore(options/mfa): alert contained escaped characters 2025-09-24 21:56:15 +03:00
Elian Doran
06b782e91d chore(deps): update dependency jiti to v2.6.0 (#7066) 2025-09-24 21:22:43 +03:00
renovate[bot]
1d7e0a193a chore(deps): update dependency jiti to v2.6.0 2025-09-24 18:09:03 +00:00
Elian Doran
2d815852e4 chore(deps): update typescript-eslint monorepo to v8.44.1 (#7062) 2025-09-24 21:06:45 +03:00
Elian Doran
735a7104f1 chore(deps): update dependency @eslint/compat to v1.4.0 (#7065) 2025-09-24 21:06:17 +03:00
Elian Doran
e3e4772aab chore(deps): update dependency lint-staged to v16.2.0 (#7067) 2025-09-24 21:05:54 +03:00
Elian Doran
8bb65b94d0 chore(deps): update svelte monorepo (#7068) 2025-09-24 21:04:20 +03:00
renovate[bot]
b9edae4fc9 chore(deps): update svelte monorepo 2025-09-24 17:20:37 +00:00
renovate[bot]
27aae18345 chore(deps): update dependency @eslint/compat to v1.4.0 2025-09-24 17:19:28 +00:00
renovate[bot]
47db63d909 chore(deps): update typescript-eslint monorepo to v8.44.1 2025-09-24 17:18:48 +00:00
renovate[bot]
8ebeead32c chore(deps): update dependency lint-staged to v16.2.0 2025-09-24 17:15:03 +00:00
Elian Doran
09d43e710f chore(deps): update dependency @smithy/middleware-retry to v4.3.0 (#7081) 2025-09-24 20:12:54 +03:00
Elian Doran
7240f64a49 chore(deps): update dependency @playwright/test to v1.55.1 (#7080) 2025-09-24 20:12:42 +03:00
Elian Doran
ab868d76db chore(deps): update dependency @anthropic-ai/sdk to v0.63.1 (#7079) 2025-09-24 20:12:24 +03:00
renovate[bot]
acdaf6a636 chore(deps): update dependency @playwright/test to v1.55.1 2025-09-24 17:11:12 +00:00
Elian Doran
6dccef1689 fix(deps): update dependency mind-elixir to v5.2.1 (#7064) 2025-09-24 20:10:13 +03:00
Elian Doran
f7ec726b15 fix(deps): update dependency @codemirror/view to v6.38.3 (#7063) 2025-09-24 20:09:47 +03:00
Elian Doran
781570f950 chore(deps): update pnpm to v10.17.1 (#7061) 2025-09-24 20:08:51 +03:00
Elian Doran
7774d41457 chore(deps): update dependency vite to v7.1.7 (#7060) 2025-09-24 20:08:38 +03:00
Elian Doran
27e6d1b00b chore(release): prepare for v0.99.0 2025-09-24 19:20:20 +03:00
Elian Doran
73ea0cce32 docs(release): document v0.99.0 2025-09-24 19:19:59 +03:00
Elian Doran
a1741b8634 chore(ci/docker): version number set to late 2025-09-24 19:12:28 +03:00
Elian Doran
a0f1a63fb6 Revert "fix: re-enable rootless images" (#7082) 2025-09-24 19:07:06 +03:00
Elian Doran
7c13373f16 Revert "fix: re-enable rootless images" 2025-09-24 19:06:27 +03:00
Elian Doran
239b7b810d Translations update from Hosted Weblate (#7077) 2025-09-24 07:52:45 +03:00
renovate[bot]
29c8bcaf6e chore(deps): update dependency @smithy/middleware-retry to v4.3.0 2025-09-24 01:16:44 +00:00
renovate[bot]
2b3ae94f8d chore(deps): update dependency @anthropic-ai/sdk to v0.63.1 2025-09-24 01:15:20 +00:00
green
e753924c4b Translated using Weblate (Japanese)
Currently translated at 83.8% (1341 of 1599 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-09-23 19:20:39 +00:00
Elian Doran
8080d3b8a7 fix(client/search): unable to search for empty string 2025-09-23 22:20:25 +03:00
Elian Doran
1f4dd04ef0 fix(client/search): highlight remaining stuck 2025-09-23 22:08:17 +03:00
Elian Doran
348432bd5b fix(client/search): not reacting to change 2025-09-23 21:55:39 +03:00
Elian Doran
d2962b060e fix(client/search): results not being displayed 2025-09-23 21:44:39 +03:00
Elian Doran
fae66e555e chore(client/search): fix improper nesting 2025-09-23 20:33:43 +03:00
Elian Doran
aeb9bfc1fd feat(client/options): add a description for the editor features 2025-09-23 20:31:15 +03:00
Elian Doran
5a15024e59 refactor(client): use type safety for option names 2025-09-23 20:24:55 +03:00
Elian Doran
23c2acaab7 fix(client): note title shown for read-only notes for the first time 2025-09-23 20:24:55 +03:00
Elian Doran
4cc55b02ab feat(client/text): provide a way to disable slash commands 2025-09-23 20:24:55 +03:00
Elian Doran
71ce9c459e refactor(client/options): deduplicate editor feature checkbox 2025-09-23 20:24:55 +03:00
Elian Doran
97b5ea0798 fix(share): text not visible under dark theme in prod 2025-09-23 20:24:54 +03:00
Elian Doran
5fd0f79d44 Translations update from Hosted Weblate (#7074) 2025-09-23 17:30:17 +03:00
Krzysztof Kaplon
2a090c7014 Translated using Weblate (Polish)
Currently translated at 72.9% (278 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/pl/
2025-09-23 15:02:09 +02:00
Krzysztof Kaplon
126030f17e Translated using Weblate (Polish)
Currently translated at 29.7% (476 of 1599 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-09-23 15:02:07 +02:00
Микола Копитін
f22fd1d454 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (381 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/uk/
2025-09-23 15:02:06 +02:00
green
8d4c656a6f Translated using Weblate (Japanese)
Currently translated at 98.1% (374 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/
2025-09-23 15:02:05 +02:00
greenfork
3c5a053a2c Translated using Weblate (Russian)
Currently translated at 100.0% (1599 of 1599 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-09-23 15:02:04 +02:00
green
664b7e45e7 Translated using Weblate (Japanese)
Currently translated at 74.5% (1192 of 1599 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-09-23 15:02:00 +02:00
renovate[bot]
5c618abc79 fix(deps): update dependency mind-elixir to v5.2.1 2025-09-23 00:29:35 +00:00
renovate[bot]
220cf8aedd fix(deps): update dependency @codemirror/view to v6.38.3 2025-09-23 00:28:46 +00:00
renovate[bot]
78f16ddc12 chore(deps): update pnpm to v10.17.1 2025-09-23 00:27:00 +00:00
renovate[bot]
0048e95e0c chore(deps): update dependency vite to v7.1.7 2025-09-23 00:26:49 +00:00
Elian Doran
13e9fcbfba chore(global_menu): indicate external changes to zoom 2025-09-22 20:19:00 +03:00
Elian Doran
5249911ddb chore(client): remove redundant log 2025-09-22 20:08:37 +03:00
Elian Doran
59fe1299b2 chore(global_menu): make zoom item unclickable to avoid misclicks 2025-09-22 20:07:10 +03:00
Elian Doran
1c9f1ba82c chore(global_menu): dismiss menu when entering fullscreen 2025-09-22 20:06:01 +03:00
Elian Doran
311f4aded8 fix(global_menu): zoom controls tooltip overlapping 2025-09-22 20:03:06 +03:00
Elian Doran
ed8df51216 fix(desktop): wrong separator in spellcheck context menu 2025-09-22 19:59:45 +03:00
Elian Doran
5e4d403556 fix(ci/docker): upload digest failing due to x64 name 2025-09-22 19:51:58 +03:00
Elian Doran
f3a9c718ad fix(ci/docker): upload digest failing 2025-09-22 19:32:55 +03:00
Elian Doran
f3733eb341 fix: re-enable rootless images (#7050) 2025-09-22 19:14:21 +03:00
Elian Doran
3b06845a71 fix(board): unable to create by clicking outside 2025-09-22 18:52:41 +03:00
Elian Doran
94e20c44e5 fix(desktop): background effects always on 2025-09-22 18:45:45 +03:00
Elian Doran
1638fd8590 fix(ribbon): unable to set content language to "none" 2025-09-22 18:37:03 +03:00
Elian Doran
effe0a4f51 chore(options_init): disable bold & italic as default highlight options 2025-09-22 18:33:15 +03:00
Elian Doran
bb3ac277f4 feat(ribbon): hide file details when opening PDF (closes #6873) 2025-09-22 18:27:13 +03:00
Adorian Doran
68aacfea6f Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-09-22 13:57:09 +03:00
Adorian Doran
e0056a457e style(legacy)/jump to note: fix broken selection colors 2025-09-22 13:56:58 +03:00
Elian Doran
4d6c2fd8cb Update typo in ru translation (#7053) 2025-09-22 13:53:02 +03:00
Elian Doran
f63b8cef2d Translations update from Hosted Weblate (#7055) 2025-09-22 13:51:55 +03:00
renato rinaldi
f19da292c1 Translated using Weblate (Italian)
Currently translated at 35.6% (136 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/it/
2025-09-22 12:51:18 +02:00
Elian Doran
36003b76e9 Translations update from Hosted Weblate (#7054) 2025-09-22 13:50:17 +03:00
Jukka Tainio
1c627dec05 Translated using Weblate (Finnish)
Currently translated at 2.6% (10 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/fi/
2025-09-22 10:02:00 +00:00
Dmitry Matveyev
2dcb67b099 Update typo in ru translation 2025-09-22 10:59:08 +03:00
Elian Doran
de8a090410 Update dependency jsonc-eslint-parser to v2.4.1 (#7051) 2025-09-22 08:09:56 +03:00
Elian Doran
fc09a41ba0 Update svelte monorepo (#7052) 2025-09-22 08:09:37 +03:00
renovate[bot]
12f461d0ea Update svelte monorepo 2025-09-22 01:26:01 +00:00
renovate[bot]
1256338ab5 Update dependency jsonc-eslint-parser to v2.4.1 2025-09-22 01:25:21 +00:00
Quik2007
43c761328d fix: re-enable rootless images 2025-09-21 23:09:20 +02:00
Adorian Doran
6f565afd44 style/global menu: improve the full screen / zoom buttons, refactor 2025-09-21 15:13:08 +03:00
Adorian Doran
5c27e96960 style(next)/tab bar: tweak appearance 2025-09-21 12:00:23 +03:00
Adorian Doran
c0337befa7 style/tab bar: tweak the alignment of icons 2025-09-21 11:41:05 +03:00
Adorian Doran
3bda10caf0 style/title row/note icon: tweak alignment 2025-09-21 11:37:32 +03:00
Adorian Doran
a25e376f85 style/ribbon/similar notes: reduce the font size of the items 2025-09-21 11:04:22 +03:00
Adorian Doran
1b238a98de style(next)/ribbon/note map: fix the padding of the "fix nodes" button 2025-09-21 10:59:00 +03:00
Adorian Doran
38659e501e style(next)/ribbon: tweak the editability dropdown 2025-09-21 10:57:41 +03:00
Adorian Doran
113af940c1 client/dialogs/note type chooser: fix broken headings regression 2025-09-21 10:31:36 +03:00
Elian Doran
089ca7fd29 Update dependency mind-elixir to v5.2.0 (#7047) 2025-09-21 08:45:03 +03:00
renovate[bot]
529523dd4e Update dependency mind-elixir to v5.2.0 2025-09-21 00:33:07 +00:00
Adorian Doran
89417f15dc UI improvements (#7046) 2025-09-21 03:30:49 +03:00
Adorian Doran
51692aabd5 style(next)/dropdowns: fix scrollbar broken corners 2025-09-21 03:09:39 +03:00
Adorian Doran
9cde4c26d9 style(next)/horizontal layout launcher: increase the contrast of icons for the dark theme 2025-09-21 02:28:27 +03:00
Adorian Doran
c7bce91b67 Merge branch 'main' of https://github.com/TriliumNext/Trilium into feat/ui-improvements 2025-09-21 02:26:02 +03:00
Adorian Doran
91b6910a9c style(next)/horizontal layout launcher: increase the contrast of icons for the dark theme 2025-09-21 02:25:49 +03:00
Adorian Doran
9fb37968f8 style(next)/quick search/results dropdown: temporary workaround - improve appearance 2025-09-21 02:18:33 +03:00
Adorian Doran
6cfc6509f6 style(next)/quick search/results dropdown: add a temporary workaround for the broken backdrop effect when the background effects are active 2025-09-21 02:09:55 +03:00
Adorian Doran
fd054693d9 style(next)/note map: fix the broken padding of the "Fix nodes" button 2025-09-21 01:54:44 +03:00
Adorian Doran
8b65de2442 style/editor forms/text inputs: fix the hover state background color overriding the focused state background color 2025-09-21 01:44:08 +03:00
Adorian Doran
25905ebff7 style/dropdowns: tweak the appearance of keyboard selected items 2025-09-21 01:34:11 +03:00
Elian Doran
e88b59009a Translations update from Hosted Weblate (#7043) 2025-09-20 23:11:57 +03:00
Kuzma Simonov
3aee1c8546 Translated using Weblate (Russian)
Currently translated at 100.0% (381 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ru/
2025-09-20 20:02:08 +00:00
Kuzma Simonov
2dd554a8be Translated using Weblate (Russian)
Currently translated at 100.0% (1599 of 1599 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-09-20 20:02:06 +00:00
fr0st
f4fae04327 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (381 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/pt_BR/
2025-09-20 20:02:04 +00:00
fr0st
21032d1bb8 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (1599 of 1599 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pt_BR/
2025-09-20 20:02:02 +00:00
Adorian Doran
6745b887fb style/global menu button: fix the focus indicator 2025-09-20 22:46:56 +03:00
Adorian Doran
d0d166e426 style/global menu button: tweak appearance 2025-09-20 22:07:59 +03:00
Adorian Doran
754b95876e style/global menu button: tweak appearance 2025-09-20 22:04:37 +03:00
Adorian Doran
0bb10cf3ee style/global menu button: tweak appearance 2025-09-20 21:50:27 +03:00
Adorian Doran
d276cdf519 style/floating buttons: fix the offset of the "Show buttons" button on canvas notes 2025-09-20 17:05:06 +03:00
Adorian Doran
2768b76278 style(next)/horizontal layout: tweak the show/hide tree button 2025-09-20 16:36:43 +03:00
Elian Doran
d244803501 chore(deps): update dependency svelte to v5.39.3 (#7038) 2025-09-20 14:18:21 +03:00
renovate[bot]
158ca2acf2 chore(deps): update dependency svelte to v5.39.3 2025-09-20 05:17:09 +00:00
Elian Doran
3ef44febd8 chore(deps): update dependency @tailwindcss/typography to v0.5.18 (#7037) 2025-09-20 08:14:52 +03:00
Elian Doran
5be41ee669 chore(deps): update dependency @stylistic/eslint-plugin to v5.4.0 (#7039) 2025-09-20 08:14:05 +03:00
Elian Doran
b887d4a7d2 fix(deps): update dependency eslint-linter-browserify to v9.36.0 (#7040) 2025-09-20 08:13:46 +03:00
Elian Doran
be1de86a42 fix(deps): update eslint monorepo to v9.36.0 (#7041) 2025-09-20 08:13:06 +03:00
renovate[bot]
345d098e5f fix(deps): update eslint monorepo to v9.36.0 2025-09-20 01:17:03 +00:00
renovate[bot]
fae5421516 fix(deps): update dependency eslint-linter-browserify to v9.36.0 2025-09-20 01:15:47 +00:00
renovate[bot]
934f144bf9 chore(deps): update dependency @stylistic/eslint-plugin to v5.4.0 2025-09-20 01:14:52 +00:00
renovate[bot]
5affb837a6 chore(deps): update dependency @tailwindcss/typography to v0.5.18 2025-09-20 01:14:03 +00:00
Adorian Doran
188319d2d9 UI / theme improvements (#7036) 2025-09-20 04:11:40 +03:00
Adorian Doran
fe762577b1 Merge branch 'main' into feat/theme/improvements 2025-09-20 04:04:51 +03:00
Adorian Doran
f30da3d13b client/menus: improve the multicolumn breaking strategy 2025-09-20 04:02:46 +03:00
Adorian Doran
053a84483c client/menus: improve the multicolumn breaking strategy 2025-09-20 03:25:16 +03:00
Adorian Doran
34338a795f style/menus: document a style 2025-09-20 03:17:12 +03:00
Adorian Doran
012aceb7f2 style/menus: remove no longer used styles 2025-09-20 03:11:54 +03:00
Adorian Doran
a92604e92f client/menus: avoid unnecessary menu item no-column-break grouping 2025-09-20 03:09:56 +03:00
Adorian Doran
9a9edf16c4 client/menus: manage proper column breaking on Firefox 2025-09-20 02:59:41 +03:00
Adorian Doran
daba190e74 client/menus: rearrange "Insert note" submenu items 2025-09-20 01:57:58 +03:00
Adorian Doran
8877eded9b style/menus: tweak header layout and add multi-column menu divider line 2025-09-20 01:11:24 +03:00
Adorian Doran
0b05f597dc client/menus: refactor 2025-09-20 01:08:36 +03:00
Adorian Doran
b26803b627 client/menus: refactor 2025-09-20 00:34:25 +03:00
Adorian Doran
17e87278eb client/menus: add support for menu headers 2025-09-20 00:18:56 +03:00
Adorian Doran
79718c7e6e style(next)/bulk actions dialog: fix the alignment of the help and close buttons for actions 2025-09-19 23:46:14 +03:00
Elian Doran
0917c25bce Translations update from Hosted Weblate (#7034) 2025-09-19 22:49:56 +03:00
ssantos
45c3f6d44a Translated using Weblate (Portuguese)
Currently translated at 99.7% (380 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/pt/
2025-09-19 21:02:01 +02:00
Adorian Doran
90337016e7 style(next)/launcher/calendar: fix the rounded corners of the arrow buttons 2025-09-19 21:49:01 +03:00
Adorian Doran
c0c1c8a9c2 style(next)/launcher/calendar: restyle the week number column 2025-09-19 21:41:44 +03:00
Adorian Doran
42a082f11b style: fix the spacing of the keyboard shortcuts in menu items 2025-09-19 21:10:26 +03:00
Elian Doran
891e6b9751 fix(canvas): canvas overwriting other notes (closes #6788) 2025-09-19 16:35:27 +03:00
Elian Doran
2be9d71659 fix(canvas): error when trying to save due to uninitialized API 2025-09-19 16:26:06 +03:00
Elian Doran
3f562332c7 chore(deps): update dependency @sveltejs/kit to v2.42.2 (#7028) 2025-09-19 09:31:17 +03:00
renovate[bot]
edd7e43b41 chore(deps): update dependency @sveltejs/kit to v2.42.2 2025-09-19 05:43:38 +00:00
Elian Doran
6ea1e31350 chore(deps): update dependency vite to v7.1.6 (#7029) 2025-09-19 08:41:19 +03:00
Elian Doran
770648619e fix(deps): update dependency mermaid to v11.12.0 (#7030) 2025-09-19 08:40:39 +03:00
renovate[bot]
08c3e97a46 fix(deps): update dependency mermaid to v11.12.0 2025-09-19 02:26:36 +00:00
renovate[bot]
9a08b864ee chore(deps): update dependency vite to v7.1.6 2025-09-19 02:25:50 +00:00
Elian Doran
039d6e6a4e chore(ckeditor): update license 2025-09-18 23:09:16 +03:00
Elian Doran
36692a5ad7 Translations update from Hosted Weblate (#7027) 2025-09-18 22:41:55 +03:00
ssantos
67c7d7575d Translated using Weblate (Portuguese)
Currently translated at 99.2% (378 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/pt/
2025-09-18 20:17:21 +02:00
Languages add-on
bb51eed0bc Added translation using Weblate (Portuguese) 2025-09-18 18:13:46 +00:00
ssantos
adce041b02 Added translation using Weblate (Portuguese) 2025-09-18 20:13:44 +02:00
Elian Doran
183d11ff72 fix(client): global menu has outline 2025-09-18 16:19:23 +03:00
Elian Doran
a9f5b44fac fix(client): dangling tooltips after closing split 2025-09-18 15:30:11 +03:00
Elian Doran
c4560c2bc8 fix(ribbon): classic toolbar becoming empty sometimes 2025-09-18 13:39:30 +03:00
Elian Doran
ba740eff9b fix(client): global menu blur-behind not working 2025-09-18 12:36:39 +03:00
Elian Doran
9dcf46cbb3 chore(deps): update dependency @types/node to v22.18.6 (#7016) 2025-09-18 08:59:00 +03:00
renovate[bot]
7782b11186 chore(deps): update dependency @types/node to v22.18.6 2025-09-18 05:12:52 +00:00
Elian Doran
e1b8f973d5 chore(deps): update dependency @smithy/middleware-retry to v4.2.4 (#7015) 2025-09-18 08:08:35 +03:00
Elian Doran
a51e475095 chore(deps): update dependency electron to v37.5.1 (#7017) 2025-09-18 08:08:08 +03:00
Elian Doran
13685d2688 chore(deps): update dependency esbuild to v0.25.10 (#7018) 2025-09-18 08:07:10 +03:00
Elian Doran
8bef36c6c7 chore(deps): update dependency @anthropic-ai/sdk to v0.63.0 (#7019) 2025-09-18 08:05:41 +03:00
Elian Doran
207807e0c2 chore(deps): update dependency svelte to v5.39.2 (#7020) 2025-09-18 08:05:21 +03:00
renovate[bot]
b5c82af464 chore(deps): update dependency svelte to v5.39.2 2025-09-18 04:51:39 +00:00
Elian Doran
3fa95d4fee Translations update from Hosted Weblate (#7022) 2025-09-18 07:50:31 +03:00
Newcomer1989
ee43b21b0c Translated using Weblate (German)
Currently translated at 100.0% (381 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/de/
2025-09-18 04:49:38 +00:00
Newcomer1989
29e091461f Translated using Weblate (German)
Currently translated at 100.0% (1599 of 1599 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-09-18 04:49:38 +00:00
Elian Doran
5b6a2b1f5d chore(deps): update pnpm to v10.17.0 (#7021) 2025-09-18 07:49:32 +03:00
Elian Doran
d657303f2f fix(client): keyboard shortcuts offset in tree menu 2025-09-18 07:47:10 +03:00
renovate[bot]
a4d541ae1c chore(deps): update pnpm to v10.17.0 2025-09-18 00:54:54 +00:00
renovate[bot]
b38631b04b chore(deps): update dependency @anthropic-ai/sdk to v0.63.0 2025-09-18 00:53:04 +00:00
renovate[bot]
fe0f8ad83d chore(deps): update dependency esbuild to v0.25.10 2025-09-18 00:52:13 +00:00
renovate[bot]
46950cbceb chore(deps): update dependency electron to v37.5.1 2025-09-18 00:51:23 +00:00
renovate[bot]
9893de4642 chore(deps): update dependency @smithy/middleware-retry to v4.2.4 2025-09-18 00:49:37 +00:00
Elian Doran
b9055c6810 fix(client): close button not working on first render 2025-09-17 22:57:09 +03:00
Elian Doran
f068b335f5 Translations update from Hosted Weblate (#7014) 2025-09-17 20:53:57 +03:00
Dong-ha, Lee
7c750811cc Translated using Weblate (Korean)
Currently translated at 1.3% (21 of 1599 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ko/
2025-09-17 19:02:05 +02:00
Francis C
2edce23a29 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (381 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/zh_Hant/
2025-09-17 19:02:03 +02:00
Francis C
3efe628eb7 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (381 of 381 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/zh_Hans/
2025-09-17 19:02:01 +02:00
Elian Doran
fdbb88ccd1 Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-09-17 18:14:04 +03:00
Elian Doran
c44395887b refactor(react): remove deprecated import 2025-09-17 12:05:06 +03:00
Elian Doran
1ae81abf0a fix(collections/board): double entry on Enter + dismiss not working 2025-09-17 10:55:03 +03:00
Elian Doran
74b89098c5 fix(deps): update ckeditor monorepo (#7011) 2025-09-17 08:56:34 +03:00
Elian Doran
ae46798d1d fix(client/dialogs): branch prefix initial value incorrect 2025-09-17 08:52:47 +03:00
Elian Doran
b502e999de style(client): improve read-only note title 2025-09-17 08:50:37 +03:00
Elian Doran
57004ab848 fix(client): note title not working for in-app help 2025-09-17 08:50:23 +03:00
Elian Doran
fbd47025d6 chore(react): monkey patch boostrap tooltip handling 2025-09-17 08:47:13 +03:00
Elian Doran
f87d270caa refactor(react): get rid of jQuery in static tooltip 2025-09-17 08:26:05 +03:00
renovate[bot]
2ccaf5f97c fix(deps): update ckeditor monorepo 2025-09-17 05:01:16 +00:00
Elian Doran
641c6f4595 chore(dx/nix): fix flake fully (#7004) 2025-09-17 08:00:23 +03:00
Elian Doran
eb1039d9f7 chore(deps): update dependency @smithy/middleware-retry to v4.2.2 (#7007) 2025-09-17 07:59:32 +03:00
Elian Doran
349d946e6f chore(deps): update dependency @types/node to v22.18.5 (#7008) 2025-09-17 07:59:10 +03:00
Elian Doran
170e271bb4 chore(deps): update dependency fs-extra to v11.3.2 (#7009) 2025-09-17 07:58:41 +03:00
Elian Doran
adca755598 chore(deps): update dependency ollama to v0.5.18 (#7010) 2025-09-17 07:58:19 +03:00
Elian Doran
f58cbc64bb chore(deps): update dependency @sveltejs/kit to v2.42.1 (#7012) 2025-09-17 07:57:02 +03:00
Elian Doran
8d5e8c7ea8 chore(deps): update typescript-eslint monorepo to v8.44.0 (#7013) 2025-09-17 07:55:12 +03:00
renovate[bot]
411d61d251 chore(deps): update typescript-eslint monorepo to v8.44.0 2025-09-17 01:54:31 +00:00
renovate[bot]
e7556f7dfa chore(deps): update dependency @sveltejs/kit to v2.42.1 2025-09-17 01:53:05 +00:00
renovate[bot]
3e0f07aa48 chore(deps): update dependency ollama to v0.5.18 2025-09-17 01:51:03 +00:00
renovate[bot]
e5a90662eb chore(deps): update dependency fs-extra to v11.3.2 2025-09-17 01:50:24 +00:00
renovate[bot]
9886376738 chore(deps): update dependency @types/node to v22.18.5 2025-09-17 01:49:49 +00:00
renovate[bot]
73603f6593 chore(deps): update dependency @smithy/middleware-retry to v4.2.2 2025-09-17 01:49:04 +00:00
Elian Doran
88bc6739ca chore(react): port create_pane_button 2025-09-16 23:05:43 +03:00
Elian Doran
a4e8e62452 chore(react): port close_pane_button 2025-09-16 23:01:33 +03:00
Elian Doran
78e45d095b chore(react): port move_pane_button 2025-09-16 22:45:54 +03:00
FliegendeWurst
834c67aeff chore(dx/nix): fix flake fully 2025-09-16 18:05:56 +02:00
Elian Doran
23b798e392 Fix(build): Fix the issue that on ARM64 Linux failed to launch due to missing better_sqlite3.node (#7002) 2025-09-16 19:01:55 +03:00
Elian Doran
bd374bf617 Translations update from Hosted Weblate (#7003) 2025-09-16 18:59:38 +03:00
hllverel
87d8bcdde5 Translated using Weblate (Turkish)
Currently translated at 3.6% (59 of 1599 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/tr/
2025-09-16 15:53:46 +00:00
Elian Doran
a840d91379 feat(desktop): use unique appdata if port is different 2025-09-16 18:43:01 +03:00
Elian Doran
0fcff6639f refactor(desktop): use shorter imports 2025-09-16 18:27:52 +03:00
Elian Doran
f607c9793d chore(desktop): use translation 2025-09-16 18:24:44 +03:00
Elian Doran
06254442c9 chore(desktop): use different mechanism for second instance 2025-09-16 18:22:32 +03:00
Linull/李林
c5725a5850 Merge branch 'main' into fix-arm64-sqlite 2025-09-16 22:22:00 +08:00
linull
dbad13c4e2 Add comments explaining exclude/include matrix configuration 2025-09-16 22:13:26 +08:00
linull
a274da80b7 Remove test workflow, prepare for PR
Core changes for ARM64 Linux better-sqlite3 fix:
- .github/workflows/release.yml: Use ubuntu-24.04-arm for ARM64 Linux
- .github/actions/build-electron/action.yml: Add TARGET_ARCH env var
- scripts/electron-rebuild.mts: Add arch parameter to rebuild
2025-09-16 22:02:51 +08:00
linull
66c05619df Fix path checking in test workflow 2025-09-16 21:51:27 +08:00
linull
67c99dea2d Fix flatpak dependencies for ARM64 build 2025-09-16 21:40:34 +08:00
linull
c77b7f8c74 Add detailed better_sqlite3.node checking
- Check exact path: app.asar.unpacked/node_modules/better-sqlite3/build/Release/
- Verify file existence and architecture
- Upload artifacts for manual inspection
2025-09-16 21:35:50 +08:00
linull
cc51fbe77e Update test workflow to build and check packages 2025-09-16 21:35:00 +08:00
linull
2e510f9dbb Fix better-sqlite3 for ARM64 Linux
- Use ubuntu-24.04-arm for ARM64 Linux builds
- Add TARGET_ARCH support to electron-rebuild
- Add test workflow for ARM64 fix
2025-09-16 21:29:16 +08:00
Elian Doran
e12df98d12 fix(desktop): export failing due to missing ckeditor5-content 2025-09-16 16:13:17 +03:00
Elian Doran
d8402755ee chore(client): add fallback font 2025-09-16 16:03:27 +03:00
Elian Doran
614b704702 Translations update from Hosted Weblate (#6995) 2025-09-16 14:33:29 +03:00
dev loupiz
fb6e87b0a5 Translated using Weblate (Arabic)
Currently translated at 0.1% (1 of 1599 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-09-16 11:55:33 +02:00
dev loupiz
80baa31221 Added translation using Weblate (Arabic) 2025-09-16 11:44:45 +02:00
dev loupiz
e2f1f56e06 Added translation using Weblate (Arabic) 2025-09-16 11:44:44 +02:00
Микола Копитін
8ed6aeb278 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (380 of 380 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/uk/
2025-09-16 11:44:43 +02:00
Микола Копитін
7123dc305f Translated using Weblate (Ukrainian)
Currently translated at 100.0% (1599 of 1599 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/uk/
2025-09-16 11:44:43 +02:00
Francis C
43cb632528 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1599 of 1599 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-09-16 11:44:42 +02:00
Francis C
74c5b12a33 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1599 of 1599 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-09-16 11:44:41 +02:00
Guido
acebed10b0 Translated using Weblate (Dutch)
Currently translated at 2.7% (44 of 1599 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/nl/
2025-09-15 16:43:59 +00:00
Kuzma Simonov
21f5c36c05 Translated using Weblate (Russian)
Currently translated at 100.0% (380 of 380 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ru/
2025-09-15 16:43:58 +00:00
Kuzma Simonov
35c297e0d1 Translated using Weblate (Russian)
Currently translated at 100.0% (1599 of 1599 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-09-15 16:43:57 +00:00
Elian Doran
e672890bd4 Translated using Weblate (Romanian)
Currently translated at 100.0% (380 of 380 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ro/
2025-09-15 16:43:56 +00:00
Elian Doran
a3f2dc5e76 Translated using Weblate (Romanian)
Currently translated at 100.0% (1599 of 1599 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ro/
2025-09-15 16:43:56 +00:00
openapphub
a19db4fd2d Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1599 of 1599 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-09-15 16:43:55 +00:00
Elian Doran
982d136151 fix(client): menu stays active while printing 2025-09-15 19:42:31 +03:00
Elian Doran
377de59df9 fix(client): printing triggers twice 2025-09-15 19:40:32 +03:00
Elian Doran
b394fb1e86 fix(demo): geomap incorrect 2025-09-15 19:29:00 +03:00
Elian Doran
a5171ce093 fix(client): pressing "Download" on PDF preview also opens note 2025-09-15 18:58:58 +03:00
Elian Doran
c5dbaccea8 fix(client): pressing "Open" on PDF preview also opens note 2025-09-15 18:58:22 +03:00
Elian Doran
0c9d1e91bb fix(client): opening a new tab doesn't preserve view scope 2025-09-15 18:46:08 +03:00
Elian Doran
a1ee0cb5d0 feat(client): disable background effects setting if native title bar is on 2025-09-15 18:41:03 +03:00
Elian Doran
a2d41247fe fix(desktop): background effects breaking if native title bar is enabled 2025-09-15 18:35:04 +03:00
Elian Doran
97bb38e4f3 chore(deps): update dependency @types/node to v22.18.3 (#6976) 2025-09-15 09:03:48 +03:00
Elian Doran
8e8ae26828 chore(deps): update dependency debug to v4.4.3 (#6979) 2025-09-15 09:02:05 +03:00
Elian Doran
e241e91a84 fix(deps): update dependency @inlang/paraglide-js to v2.3.2 (#6983) 2025-09-15 08:41:00 +03:00
renovate[bot]
ea277cf972 chore(deps): update dependency debug to v4.4.3 2025-09-15 05:39:00 +00:00
Elian Doran
046e7ac4c3 fix(deps): update dependency @codemirror/lang-html to v6.4.10 (#6981) 2025-09-15 08:37:43 +03:00
Elian Doran
beea8d9edf chore(deps): update dependency typedoc to v0.28.13 (#6980) 2025-09-15 08:37:08 +03:00
Elian Doran
1c928bb139 chore(deps): update dependency axios to v1.12.2 (#6978) 2025-09-15 08:36:43 +03:00
Elian Doran
987e6ad4c6 fix(deps): update dependency preact to v10.27.2 (#6984) 2025-09-15 08:36:12 +03:00
Elian Doran
b7732e53c6 chore(deps): update pnpm to v10.16.1 (#6985) 2025-09-15 08:34:37 +03:00
renovate[bot]
bfb34cf236 chore(deps): update dependency @types/node to v22.18.3 2025-09-15 05:34:26 +00:00
Elian Doran
50b9bebf98 chore(deps): update svelte monorepo (#6986) 2025-09-15 08:32:58 +03:00
Elian Doran
e21624ed52 fix(deps): update dependency marked to v16.3.0 (#6987) 2025-09-15 08:27:24 +03:00
Elian Doran
86a8085239 feat(readme): update readme with new docs site (#6990) 2025-09-15 08:20:06 +03:00
perf3ct
19c756a971 feat(readme): update readme with new docs site 2025-09-15 04:16:57 +00:00
renovate[bot]
b76c6ed444 fix(deps): update dependency marked to v16.3.0 2025-09-15 01:16:38 +00:00
renovate[bot]
bd07342689 chore(deps): update svelte monorepo 2025-09-15 01:16:02 +00:00
renovate[bot]
be1d7309fd chore(deps): update pnpm to v10.16.1 2025-09-15 01:15:25 +00:00
renovate[bot]
9471fad7bb fix(deps): update dependency preact to v10.27.2 2025-09-15 01:15:15 +00:00
renovate[bot]
642bf60f45 fix(deps): update dependency @inlang/paraglide-js to v2.3.2 2025-09-15 01:14:26 +00:00
renovate[bot]
7245e32876 fix(deps): update dependency @codemirror/lang-html to v6.4.10 2025-09-15 01:13:40 +00:00
renovate[bot]
dcc1a2dc51 chore(deps): update dependency typedoc to v0.28.13 2025-09-15 01:13:01 +00:00
renovate[bot]
2b3874d8e9 chore(deps): update dependency axios to v1.12.2 2025-09-15 01:12:15 +00:00
Elian Doran
29f9c311d2 chore(client): missing class selector 2025-09-14 20:57:36 +03:00
Elian Doran
adae78e747 fix(client): typecheck 2025-09-14 20:16:38 +03:00
Elian Doran
5b5f3233d8 feat: create a more seamless PWA top bar (#6960) 2025-09-14 19:10:03 +03:00
Elian Doran
e6889798ff Translations update from Hosted Weblate (#6973) 2025-09-14 19:05:20 +03:00
Newcomer1989
a5ae6f7013 Translated using Weblate (German)
Currently translated at 100.0% (380 of 380 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/de/
2025-09-14 18:01:48 +02:00
Elian Doran
0ac2df8102 Port collections to React (#6837) 2025-09-14 19:01:30 +03:00
Elian Doran
ec5e7607f0 Merge branch 'main' into react/collections 2025-09-14 19:01:18 +03:00
Elian Doran
7588026640 fix(collapse-subtree): improve performance of collapsing subtrees from O(n) to O(v) (#6971) 2025-09-14 18:27:29 +03:00
Elian Doran
ad366ee928 docs(help): document new features for collections 2025-09-14 18:25:14 +03:00
Jakob Schlanstedt
1fc38e941e fix(collapse-subtree): improve performance of collapsing subtrees from O(n) to O(v)
Only collapse currently expanded descendants instead of the entire subtree.
Assuming n is the number of subnotes and v is the number of opened notes
2025-09-14 10:56:18 +02:00
Elian Doran
b80c4ed921 chore(client): remove unnecessary file 2025-09-14 11:43:26 +03:00
Elian Doran
1de9634c44 chore(client): remove unnecessary logs 2025-09-14 11:29:19 +03:00
Elian Doran
d8386bfbe8 (fix)redirectBareDomain not working when MFA is on (#6961) 2025-09-14 11:18:20 +03:00
Elian Doran
3a02ad7836 chore(deps): update dependency axios to v1.12.0 [security] (#6968) 2025-09-14 11:15:46 +03:00
Elian Doran
d36716bdb6 chore(client): tests not being able to access .tsx 2025-09-14 10:59:15 +03:00
Elian Doran
970f4b028d chore(server): fix a few more type errors 2025-09-14 10:58:11 +03:00
Elian Doran
6077da0df8 chore(react/collections): fix the rest of client type errors 2025-09-14 10:53:54 +03:00
Elian Doran
e77e0c54f0 chore(react/collections): clean up old files 2025-09-14 10:40:14 +03:00
Elian Doran
4040f8ba89 chore(react): solve most type errors 2025-09-14 10:38:05 +03:00
Elian Doran
3ac0dfb2ad refactor(react): add type safety for note relations 2025-09-14 10:22:20 +03:00
Elian Doran
b8e4947adb refactor(react): add type safety for note labels 2025-09-14 10:17:06 +03:00
perf3ct
d1f2dfca05 fix(docs): handle quoted and unquoted paths in mkdocs fixer 2025-09-13 19:42:32 +00:00
renovate[bot]
c6a9b48aa0 chore(deps): update dependency axios to v1.12.0 [security] 2025-09-13 19:18:14 +00:00
perf3ct
fd690592ba feat(docs): cleanse .md from hyperlinks in compiled mkdocs 2025-09-13 19:14:45 +00:00
Elian Doran
8a66ee7565 feat(tree): allow multiple selection for archive/unarchive 2025-09-13 17:26:27 +03:00
Elian Doran
f42d375cc7 feat(tree): archive/unarchive notes 2025-09-13 17:16:02 +03:00
Elian Doran
68beb0d419 feat(collections/table): disable "Insert row above/below" if sorting 2025-09-13 16:52:26 +03:00
Elian Doran
50d2814044 Translations update from Hosted Weblate (#6963) 2025-09-13 16:33:24 +03:00
Guido
8ddd27c258 Translated using Weblate (Dutch)
Currently translated at 12.8% (49 of 380 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/nl/
2025-09-13 15:02:01 +02:00
Francis C
ac78eada0a Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (380 of 380 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/zh_Hant/
2025-09-13 15:02:00 +02:00
Francis C
6b0395dec8 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (380 of 380 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/zh_Hans/
2025-09-13 15:01:59 +02:00
Elian Doran
5bb1432450 fix(react/collections/geomap): "note not found" when deleting GPX 2025-09-13 15:46:09 +03:00
Elian Doran
dc854cbd10 fix(react/collections/geomap): react to icon & color changes 2025-09-13 15:16:58 +03:00
Elian Doran
3128f2dace fix(react/collections/geomap): corrupted map after closing split 2025-09-13 15:12:26 +03:00
Elian Doran
6ba494999c chore(collections): support child notes on import as well 2025-09-13 14:47:40 +03:00
Elian Doran
050ff5d8cd fix(collections): not updating on import 2025-09-13 14:42:02 +03:00
Elian Doran
9c8b0611ea refactor: add typesafety to TaskContext 2025-09-13 13:44:23 +03:00
Elian Doran
777d5ab3b7 refactor: extract WS API into separate file 2025-09-13 13:07:31 +03:00
Elian Doran
39fecb3ffe refactor: further improve task context types 2025-09-13 13:06:28 +03:00
Elian Doran
4cd0702cbb refactor: proper websocket message types 2025-09-13 12:59:00 +03:00
Elian Doran
998688573d refactor(server): integrate entity types changes into commons 2025-09-13 12:00:20 +03:00
Elian Doran
a6833f5a6f fix(react/notelist): normal list/grid not showing if text 2025-09-13 11:46:17 +03:00
Elian Doran
a162d697da fix(react/collections/geomap): note shifting on its own randomly 2025-09-13 11:14:46 +03:00
Elian Doran
f281e9691d fix(react/ribbon/collection): default property not working 2025-09-13 11:05:37 +03:00
Elian Doran
cbc2ee3cd1 chore(react/collections/board): simply column dragging slightly 2025-09-13 11:02:56 +03:00
Elian Doran
4f469d0d3c chore(react/collections/board): fix column dragging offset 2025-09-13 11:01:39 +03:00
Elian Doran
e77a49ace6 chore(react/collections/board): improve column dragging experience slightly 2025-09-13 10:43:48 +03:00
Elian Doran
8bde2092c6 chore(react/collections/board): improve note dragging experience 2025-09-13 10:13:37 +03:00
Elian Doran
7edfaad04e chore(react/collections/board): note not properly marked as dragged 2025-09-13 09:59:01 +03:00
Elian Doran
ae5576f2a3 chore(react/collections/board): fix dragging from tree 2025-09-13 09:46:09 +03:00
Elian Doran
b934b2b6ca chore(react/collections/board): use custom type for dragging cards 2025-09-13 09:41:54 +03:00
Elian Doran
87648f340b chore(react/collections/board): prevent crash if dragging wrong JSON 2025-09-13 09:31:37 +03:00
Elian Doran
679abc6e3e chore(react/collections/board): drag interfering with column title editing 2025-09-13 09:29:29 +03:00
Elian Doran
dd930261bf feat(react/collections/board): improve multiline in "New item" 2025-09-13 09:21:33 +03:00
Elian Doran
92a0faf475 feat(react/collections/board): title editor not dismissing on blur 2025-09-13 09:20:18 +03:00
Elian Doran
3ce6b43018 feat(react/collections/board): disable autofill when entering note title 2025-09-13 09:18:52 +03:00
Elian Doran
220858926f feat(react/collections/board): flickerless add new item 2025-09-13 09:15:31 +03:00
Elian Doran
d908a1b0d2 chore(react/collections/board): ignore empty titles 2025-09-12 23:41:56 +03:00
Elian Doran
b361cc0630 chore(react/collections/board): start with no name for new notes 2025-09-12 23:40:40 +03:00
Elian Doran
cd3663e041 chore(react/collections/board): fix add on blur if value not changed 2025-09-12 23:29:13 +03:00
Elian Doran
c53e927a55 fix(react/collections/board): column and card drag mixing 2025-09-12 23:14:15 +03:00
Elian Doran
7bbb15a535 fix(react/collections/board): no columns if dragging column onto itself 2025-09-12 22:49:58 +03:00
Elian Doran
0dddcbcfa1 feat(collections/board): remove note from board 2025-09-12 22:25:33 +03:00
Elian Doran
3175b75192 feat(collections/board): unarchive note 2025-09-12 22:08:32 +03:00
Elian Doran
6703b78457 refactor(collections/board): move within board to API 2025-09-12 21:50:56 +03:00
Elian Doran
7a61bbc297 feat(collections/board): allow dragging from note tree 2025-09-12 21:42:25 +03:00
Elian Doran
dd6003172d feat(collections/geomap): show toast if drag not enabled 2025-09-12 21:06:54 +03:00
Elian Doran
338f3d536f chore(ribbon): use "show" instead of "include" for archived notes 2025-09-12 19:51:53 +03:00
Elian Doran
27804384db feat(ribbon): improve display of note ID 2025-09-12 19:48:35 +03:00
Elian Doran
7e5069c7d1 feat(collections/board): support archived notes 2025-09-12 19:34:54 +03:00
Elian Doran
0a813f9b53 feat(collections/table): support archived notes 2025-09-12 19:02:10 +03:00
Judging28
c79c21e965 (fix)check redirectBareDomain option first 2025-09-12 23:49:32 +08:00
Elian Doran
0c0bcb87f9 feat(collections/calendar): support archived notes 2025-09-12 18:35:15 +03:00
Elian Doran
f537852469 fix(ribbon): book properties overlapping 2025-09-12 18:20:17 +03:00
Elian Doran
ff422d112b feat(collections/geomap): react to archived notes 2025-09-12 18:08:55 +03:00
Elian Doran
bf92280ed9 feat(collections): add book property to include archived notes 2025-09-12 18:03:07 +03:00
Elian Doran
d1e57e85b6 feat(collections): add label to show archived notes 2025-09-12 17:57:58 +03:00
Elian Doran
f300b6c8a2 refactor(collections/board): use API to reorder column 2025-09-12 17:39:52 +03:00
qwreey
4c0addd929 feat: Create a more seamless PWA top bar 2025-09-12 14:29:19 +00:00
Elian Doran
a08bc79ae4 feat(collections/board): add option to archive note 2025-09-12 17:21:59 +03:00
Elian Doran
8ad00084e1 style(collections/board): slightly bigger card padding 2025-09-12 17:08:36 +03:00
Elian Doran
0d275b3259 refactor(collections/board): use same title editor for new columns 2025-09-12 17:05:17 +03:00
Elian Doran
ede4b99bcd style(collections/board): better new item that creates only after enter 2025-09-12 16:57:23 +03:00
Elian Doran
e99748e45f style(collections/board): minor improvements to Add item 2025-09-12 16:28:26 +03:00
Elian Doran
114fdd6f91 style(collections/board): smoother shadows, no shift 2025-09-12 16:26:45 +03:00
Elian Doran
245675d409 chore(collections/board): reintroduce note click on the board 2025-09-12 16:24:35 +03:00
Elian Doran
e156f0a2e8 chore(collections/board): improve font size 2025-09-12 16:16:12 +03:00
Elian Doran
519d76d809 chore(collections/board): normalize line height when editing 2025-09-12 16:07:44 +03:00
Elian Doran
b4fa70d1d5 chore(collections/board): improve fit in multiline 2025-09-12 16:06:19 +03:00
Elian Doran
3825fb24f4 chore(collections/board): basic multiline editing 2025-09-12 16:02:44 +03:00
Elian Doran
79e51b543a chore(collections/board): icon as part of the text for better fit on multiline 2025-09-12 15:49:45 +03:00
Elian Doran
54fe9dde70 chore(collections/board): floating edit button for note titles 2025-09-12 15:46:39 +03:00
Elian Doran
d224ffd6d3 chore(collections/board): remove more of the old files 2025-09-12 15:39:44 +03:00
Elian Doran
1e1a458add chore(collections/board): bring back scrolling inside columns 2025-09-12 15:39:30 +03:00
Elian Doran
0844f60343 chore(collections/board): fix unnecessary repaint 2025-09-12 15:29:20 +03:00
Elian Doran
c8f9d6e6df chore(collections/board): fix dragging notes across columns 2025-09-12 15:10:20 +03:00
Elian Doran
95a392ccfa chore(collections/board): fix dragging notes not working 2025-09-12 15:08:00 +03:00
Elian Doran
2972a23f19 chore(collections/board): use context for column dragging 2025-09-12 14:48:05 +03:00
Elian Doran
f55a39eab6 chore(collections/board): clean up old code 2025-09-12 14:31:59 +03:00
Elian Doran
8611328a03 chore(collections/board): reordering notes not refreshing properly 2025-09-12 14:21:10 +03:00
Elian Doran
08dc05c504 chore(collections/board): extract dragging to separate hook 2025-09-12 14:13:00 +03:00
Elian Doran
174f796b56 chore(collections/board): context menu wrongly positioned 2025-09-12 13:58:52 +03:00
Elian Doran
85949a0464 Merge remote-tracking branch 'origin/main' into react/collections
; Conflicts:
;	pnpm-lock.yaml
2025-09-12 13:58:00 +03:00
Elian Doran
1b711e2c08 fix(client/dialogs): shrink images checked when it shouldn't (closes #6930) 2025-09-12 13:50:06 +03:00
Elian Doran
60ea415361 Merge branch 'main' of ssh://github.com/TriliumNext/trilium 2025-09-12 13:00:32 +03:00
Elian Doran
01613da38f Translations update from Hosted Weblate (#6952) 2025-09-12 12:53:28 +03:00
Elian Doran
d6e6e78acc chore(server): improve & translate DB not initialized message 2025-09-12 12:49:25 +03:00
Elian Doran
0e5e439f69 docs(help): remove clone causing small issues in hidden subtree 2025-09-12 12:43:54 +03:00
Elian Doran
fc78f68fa7 chore(server): display startup info right at the beginning 2025-09-12 12:36:59 +03:00
Elian Doran
2f6d81ce2c chore(server): remove LLM features ready log 2025-09-12 12:34:02 +03:00
Elian Doran
08a600167a chore(server): integrate DB size into startup info 2025-09-12 12:27:41 +03:00
Elian Doran
9779e706c5 chore(server): improve the display of the start-up information 2025-09-12 12:17:22 +03:00
Tino Elfering
b8e9d853e5 Translated using Weblate (Dutch)
Currently translated at 2.6% (41 of 1573 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/nl/
2025-09-12 10:56:34 +02:00
Elian Doran
4041746240 chore(server): add a logo at startup 2025-09-12 09:34:00 +03:00
Elian Doran
c96a65b21d chore(react/collections/board): minor flicker when renaming note 2025-09-11 22:44:17 +03:00
Elian Doran
d67018b6d7 chore(react/collections/board): use translations 2025-09-11 22:35:31 +03:00
Elian Doran
f7e47b5120 feat(react/collections/table): make note title editable 2025-09-11 22:22:50 +03:00
Elian Doran
5bc28b63a6 fix(deps): update ckeditor monorepo to v46.1.0 (#6943) 2025-09-11 22:15:35 +03:00
Elian Doran
62452b61b1 refactor(react/collections/table): deduplicate editing 2025-09-11 21:51:02 +03:00
Elian Doran
cb84e4c7b6 refactor(react/collections/table): split card/column 2025-09-11 21:42:59 +03:00
Elian Doran
60ef816f0c chore(react/collections/table): bring back renaming columns 2025-09-11 21:37:33 +03:00
Elian Doran
d367cf9972 chore(react/collections/table): bring back wheel scroll 2025-09-11 21:20:25 +03:00
Elian Doran
05973672e4 chore(react/collections/table): add back insert above/below 2025-09-11 21:11:44 +03:00
Elian Doran
c4398e92e1 Translations update from Hosted Weblate (#6950) 2025-09-11 20:53:05 +03:00
Elian Doran
68b8ba691f chore(react/collections/table): fix one extra rendering of wrong type 2025-09-11 20:45:54 +03:00
Elian Doran
d52cf455a9 chore(react/collections/table): not loading config correctly 2025-09-11 20:37:09 +03:00
Elian Doran
fee822c689 chore(react/collections/table): slightly improve editing experience 2025-09-11 20:32:21 +03:00
Elian Doran
228a1ad0da chore(react/collections/table): reintroduce icon while editing 2025-09-11 20:07:01 +03:00
Elian Doran
1ce42d1301 chore(react/collections/table): reintroduce editing of newly added item 2025-09-11 20:02:58 +03:00
Elian Doran
3d2a4d8c38 chore(react/collections/table): reintroduce item context menu partially 2025-09-11 19:35:55 +03:00
Elian Doran
803164791f chore(react/collections/table): reintroduce column context menu 2025-09-11 19:25:17 +03:00
Elian Doran
2b452a18df refactor(react/collections/table): use class-based API 2025-09-11 19:14:54 +03:00
Elian Doran
efcdac75e4 chore(react/collections/table): fix adding new columns 2025-09-11 19:03:25 +03:00
Elian Doran
c30c9a7360 chore(react/collections/table): set up column dragging 2025-09-11 18:57:01 +03:00
Elian Doran
ce0da3fb80 chore(react/collections/table): use a placeholder for items 2025-09-11 18:32:06 +03:00
Elian Doran
728c20c184 chore(react/collections/table): bring back repositioning 2025-09-11 18:27:42 +03:00
Elian Doran
e10475679b chore(react/collections/table): bring back refresh 2025-09-11 18:17:24 +03:00
Elian Doran
d9af0461ef chore(react/collections/table): add drop indicator 2025-09-11 18:11:12 +03:00
Elian Doran
2e4791d377 chore(react/collections/table): basic drag support to change columns 2025-09-11 18:05:09 +03:00
Jan Mareš
d1244e02db Translated using Weblate (Czech)
Currently translated at 0.2% (1 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/cs/
2025-09-11 17:01:59 +02:00
renovate[bot]
867d1841e9 fix(deps): update ckeditor monorepo to v46.1.0 2025-09-11 14:50:50 +00:00
Elian Doran
3232900bdc chore(deps): update dependency electron to v37.5.0 (#6939) 2025-09-11 16:57:06 +03:00
Elian Doran
077de9f539 chore(deps): update dependency @anthropic-ai/sdk to v0.62.0 (#6938) 2025-09-11 16:56:12 +03:00
Elian Doran
b37f4bf0df chore(deps): update dependency globals to v16.4.0 (#6940) 2025-09-11 16:55:38 +03:00
renovate[bot]
64dd83e8fb chore(deps): update dependency globals to v16.4.0 2025-09-11 07:37:53 +00:00
renovate[bot]
5a615970c2 chore(deps): update dependency electron to v37.5.0 2025-09-11 07:37:25 +00:00
Elian Doran
2a5cb85199 fix(client/dialogs): include note not respecting size (closes #6947) 2025-09-11 10:06:07 +03:00
Elian Doran
5f1f27a4f9 chore(deps): update dependency @smithy/middleware-retry to v4.2.1 (#6937) 2025-09-11 08:16:43 +03:00
Elian Doran
0d9f398de2 chore(deps): update electron-forge monorepo to v7.9.0 (#6941) 2025-09-11 08:16:11 +03:00
Elian Doran
b0e84952c8 fix(deps): update dependency @inlang/paraglide-js to v2.3.0 (#6944) 2025-09-11 08:13:50 +03:00
Elian Doran
3df8cf3c13 fix(deps): update dependency globals to v16.4.0 (#6945) 2025-09-11 08:13:30 +03:00
Elian Doran
975e5a89af chore(deps): update svelte monorepo (#6942) 2025-09-11 08:11:08 +03:00
renovate[bot]
7102615eaa chore(deps): update svelte monorepo 2025-09-11 04:42:47 +00:00
renovate[bot]
68fa273c75 fix(deps): update dependency globals to v16.4.0 2025-09-11 01:33:09 +00:00
renovate[bot]
f8ecf0ec0b fix(deps): update dependency @inlang/paraglide-js to v2.3.0 2025-09-11 01:32:37 +00:00
renovate[bot]
888aba0b04 chore(deps): update electron-forge monorepo to v7.9.0 2025-09-11 01:31:03 +00:00
renovate[bot]
2216136de3 chore(deps): update dependency @anthropic-ai/sdk to v0.62.0 2025-09-11 01:29:29 +00:00
renovate[bot]
4163c5534a chore(deps): update dependency @smithy/middleware-retry to v4.2.1 2025-09-11 01:28:57 +00:00
Elian Doran
3ddcaddd79 Merge branch 'react/collections' of https://github.com/TriliumNext/trilium into react/collections 2025-09-10 22:53:22 +03:00
Elian Doran
b029e0d790 chore(react/collections/board): add columns without refresh yet 2025-09-10 22:20:17 +03:00
Elian Doran
6f2d51f3ff chore(react/collections/board): attempt to reload events 2025-09-10 21:41:15 +03:00
Elian Doran
ecf8c4ffbe chore(react/collections/board): get new items to be created 2025-09-10 21:10:31 +03:00
Elian Doran
4b769da90b chore(react/collections/board): render items 2025-09-10 20:38:47 +03:00
Elian Doran
4247c8fdc6 chore(react/collections/board): render empty columns 2025-09-10 20:18:17 +03:00
Elian Doran
7777cd5238 chore(react/collections/table): integrate relation editor 2025-09-10 19:05:01 +03:00
Elian Doran
cb959e93f2 chore(react/collections/table): fix type error 2025-09-10 18:48:42 +03:00
Elian Doran
30979b460b Translations update from Hosted Weblate (#6936) 2025-09-10 18:44:46 +03:00
Jan Mareš
901d1ecf4a Added translation using Weblate (Czech) 2025-09-10 16:41:48 +02:00
Jan Mareš
c84a38f2b2 Added translation using Weblate (Czech) 2025-09-10 16:41:48 +02:00
Elian Doran
ed461bc22f Translations update from Hosted Weblate (#6935) 2025-09-10 10:06:39 +03:00
Alberto Rossi
28368e6e12 Translated using Weblate (Italian)
Currently translated at 13.1% (207 of 1573 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-09-10 09:02:03 +02:00
Kuzma Simonov
8247855330 Translated using Weblate (Russian)
Currently translated at 100.0% (1573 of 1573 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-09-10 09:02:02 +02:00
Elian Doran
7cd6237f16 chore(deps): update dependency express-http-proxy to v2.1.2 (#6933) 2025-09-10 09:28:13 +03:00
Elian Doran
ca9bdc337a chore(deps): update dependency @types/tabulator-tables to v6.2.11 (#6932) 2025-09-10 09:27:33 +03:00
Elian Doran
e6d2394d54 chore(deps): update svelte monorepo (#6934) 2025-09-10 09:27:04 +03:00
renovate[bot]
3d43665603 chore(deps): update svelte monorepo 2025-09-09 21:27:22 +00:00
renovate[bot]
f135ffbe49 chore(deps): update dependency express-http-proxy to v2.1.2 2025-09-09 21:26:51 +00:00
renovate[bot]
3d99bc7166 chore(deps): update dependency @types/tabulator-tables to v6.2.11 2025-09-09 21:26:20 +00:00
Elian Doran
3789edf53a chore(react/collections/table): port note relation formatter 2025-09-09 21:20:52 +03:00
Elian Doran
4d57134aa2 chore(react/collections/table): port note title formatter 2025-09-09 21:11:06 +03:00
Elian Doran
e3d9a120cb chore(react/collections/table): port row number formatter 2025-09-09 21:03:55 +03:00
Elian Doran
043791fc91 chore(react/collections/table): port note ID formatter 2025-09-09 20:35:57 +03:00
Elian Doran
33a37be378 chore(react/collections/table): fix occasional error when initializing 2025-09-09 19:49:57 +03:00
Elian Doran
32ce6e7a08 chore(react/collections/table): integrate cleanup 2025-09-09 19:41:38 +03:00
Elian Doran
3046cfd6ee chore(react/collections/table): react to external data changes 2025-09-09 19:34:22 +03:00
Elian Doran
9758632bf0 chore(react/collections/table): react to sorted change 2025-09-09 19:18:27 +03:00
Elian Doran
0c7f926421 chore(react/collections/table): react to nesting depth change 2025-09-09 19:00:08 +03:00
Elian Doran
ab6fc9303b chore(react/collections/table) reintroduce delete/rename 2025-09-09 18:56:53 +03:00
Elian Doran
4e37a5f08e chore(react/collections/table): fix some issues with col editing 2025-09-09 18:48:09 +03:00
Elian Doran
426b4dde54 chore(deps): update dependency vite to v7.1.5 (#6924) 2025-09-09 09:33:52 +03:00
renovate[bot]
d3cc79a28c chore(deps): update dependency vite to v7.1.5 2025-09-09 06:24:53 +00:00
Elian Doran
b0a826aaca chore(deps): update typescript-eslint monorepo to v8.43.0 (#6925) 2025-09-09 07:40:54 +03:00
Elian Doran
9c0e678e50 chore(deps): update dependency chalk to v5.6.2 (#6923) 2025-09-09 07:40:23 +03:00
renovate[bot]
bbb2571215 chore(deps): update typescript-eslint monorepo to v8.43.0 2025-09-09 00:51:37 +00:00
renovate[bot]
d2a0d75906 chore(deps): update dependency chalk to v5.6.2 2025-09-09 00:49:23 +00:00
Elian Doran
e16dc941d2 chore(deps): update dependency eslint-plugin-svelte to v3.12.2 (#6920) 2025-09-08 18:00:21 +03:00
Elian Doran
fa61e7bacb chore(deps): update dependency stylelint to v16.24.0 (#6921) 2025-09-08 17:59:54 +03:00
Elian Doran
439a182103 Translations update from Hosted Weblate (#6922) 2025-09-08 13:24:51 +03:00
Микола Копитін
7eb478cc6a Translated using Weblate (Ukrainian)
Currently translated at 100.0% (1573 of 1573 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/uk/
2025-09-08 11:03:19 +02:00
Francis C
4341c1fbc8 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1573 of 1573 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-09-08 11:03:18 +02:00
Elian Doran
e8039715e7 Translated using Weblate (Romanian)
Currently translated at 100.0% (1573 of 1573 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ro/
2025-09-08 11:03:18 +02:00
Newcomer1989
3cacfdfd6f Translated using Weblate (German)
Currently translated at 100.0% (1573 of 1573 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-09-08 11:03:18 +02:00
Francis C
7b2cd20cff Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1573 of 1573 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-09-08 11:03:18 +02:00
renovate[bot]
79a5fab39e chore(deps): update dependency stylelint to v16.24.0 2025-09-08 02:12:38 +00:00
renovate[bot]
b03d687f75 chore(deps): update dependency eslint-plugin-svelte to v3.12.2 2025-09-08 02:12:02 +00:00
Elian Doran
61ec341c27 Revert "fix: close context menu when clicking items with submenus"
This reverts commit 2f93af4d6f.
2025-09-07 22:57:27 +03:00
Elian Doran
22835108be fix: add left-click check for tree button handlers (#6903) 2025-09-07 22:53:42 +03:00
Elian Doran
1e654fbcd6 chore(react/collections/table): refresh columns 2025-09-07 22:29:01 +03:00
Elian Doran
49c4776dbd chore(react/collections/table): reintroduce column creation 2025-09-07 22:16:21 +03:00
Elian Doran
41c4bc69cc chore(react/collections/table): get attribute detail to show 2025-09-07 22:08:26 +03:00
Elian Doran
6eea921820 chore(react/collections/table): bring back dragging rows 2025-09-07 21:23:04 +03:00
Elian Doran
3d97b317f2 chore(react/collections/table): fix when empty 2025-09-07 21:13:29 +03:00
Elian Doran
7ba24968d8 chore(react/collections/table): bring editing cells 2025-09-07 21:07:55 +03:00
Elian Doran
57046d714b chore(react/collections/table): bring back adding new rows 2025-09-07 20:44:39 +03:00
Elian Doran
0526445d3c chore(react/collections/table): add datatree props 2025-09-07 19:49:01 +03:00
Elian Doran
b62d1a303c chore(react/collections/table): add more properties 2025-09-07 19:41:25 +03:00
Elian Doran
e25c5cc6c7 refactor(react/collections/table): move events to dedicated prop 2025-09-07 19:19:09 +03:00
Elian Doran
e761cd7c27 chore(react/collections/table): set up writing to attachment 2025-09-07 19:03:16 +03:00
SiriusXT
617548f6b6 Merge branch 'main' into sirius_tree_patch 2025-09-07 19:18:23 +08:00
SiriusXT
2f93af4d6f fix: close context menu when clicking items with submenus 2025-09-07 17:15:09 +08:00
Elian Doran
c2504bb6db Merge remote-tracking branch 'origin/main' into react/collections 2025-09-07 11:54:34 +03:00
Elian Doran
145f89eded fix(shortcuts): try to fix ime composition checks (#6851) 2025-09-07 11:17:35 +03:00
Elian Doran
6c0e4b6a48 Merge branch 'main' into fix/ime-shortcut-input-fix 2025-09-07 11:13:18 +03:00
Elian Doran
87d1eefc86 chore(deps): update softprops/action-gh-release action to v2.3.3 (#6915) 2025-09-07 11:07:52 +03:00
Elian Doran
a87ec6f2e7 Translations update from Hosted Weblate (#6916) 2025-09-07 11:01:48 +03:00
donut
a9d5478bcd Translated using Weblate (Polish)
Currently translated at 37.8% (143 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/pl/
2025-09-07 09:59:34 +02:00
Elian Doran
5eae51a1b4 Apply note wrapper on mobile (#6847) 2025-09-07 10:59:28 +03:00
Elian Doran
ac94ab6914 feat: Make splits resizable (#6866) 2025-09-07 10:48:37 +03:00
Elian Doran
38673a85c9 feat: show source diff between note and revision (#6887) 2025-09-07 10:42:21 +03:00
renovate[bot]
d75951c869 chore(deps): update softprops/action-gh-release action to v2.3.3 2025-09-07 07:24:01 +00:00
Elian Doran
67d36a9e28 fix(deps): update dependency mind-elixir to v5.1.1 (#6914) 2025-09-07 10:02:35 +03:00
renovate[bot]
de8e8915ff fix(deps): update dependency mind-elixir to v5.1.1 2025-09-07 01:22:19 +00:00
Elian Doran
2161816ef4 fix(deps): update ckeditor monorepo to v46.0.3 (#6895) 2025-09-06 23:15:09 +03:00
renovate[bot]
d046bdec65 fix(deps): update ckeditor monorepo to v46.0.3 2025-09-06 20:05:18 +00:00
Elian Doran
cddd7d1562 fix(deps): update dependency ckeditor5 to v46.0.3 [security] (#6885) 2025-09-06 23:01:30 +03:00
renovate[bot]
15a3104904 fix(deps): update dependency ckeditor5 to v46.0.3 [security] 2025-09-06 19:53:33 +00:00
Elian Doran
e1ca6eca0f chore(deps): update dependency vite to v7.1.4 (#6893) 2025-09-06 22:52:01 +03:00
Elian Doran
cc0137bdc9 fix(deps): update dependency @mermaid-js/layout-elk to v0.2.0 (#6899) 2025-09-06 22:42:06 +03:00
Elian Doran
86a620bc08 Add an option to disable smooth scrolling for the Electron app (#6912) 2025-09-06 22:41:26 +03:00
Elian Doran
3ba9c3b4a8 Merge branch 'main' into history_diff 2025-09-06 22:37:55 +03:00
Elian Doran
8dc5ada553 Style: improve window background effects (#6913) 2025-09-06 22:36:59 +03:00
Elian Doran
9fe744c545 chore(deps): update actions/setup-node action to v5 (#6902) 2025-09-06 22:36:15 +03:00
Elian Doran
cc29eb0f9b chore(deps): update svelte monorepo (#6892) 2025-09-06 22:27:17 +03:00
renovate[bot]
901edde634 chore(deps): update dependency vite to v7.1.4 2025-09-06 19:24:39 +00:00
Elian Doran
44dd6d499d fix(deps): update dependency eslint-linter-browserify to v9.35.0 (#6905) 2025-09-06 22:24:05 +03:00
renovate[bot]
375f09cbaf fix(deps): update dependency @mermaid-js/layout-elk to v0.2.0 2025-09-06 19:23:04 +00:00
Elian Doran
d4e5a31de4 chore(deps): update tailwindcss monorepo to v4.1.13 (#6894) 2025-09-06 22:22:25 +03:00
Elian Doran
f3fa3864b2 chore(deps): update dependency node to v22 (#6891) 2025-09-06 22:21:44 +03:00
Elian Doran
1c978c2497 chore(deps): update dependency @types/leaflet-gpx to v1.3.8 (#6890) 2025-09-06 22:21:05 +03:00
Elian Doran
0f4ec2b3e2 chore(deps): update dependency @anthropic-ai/sdk to v0.61.0 (#6896) 2025-09-06 22:20:02 +03:00
Elian Doran
e30b1abaa4 chore(deps): update dependency @smithy/middleware-retry to v4.2.0 (#6897) 2025-09-06 22:19:26 +03:00
renovate[bot]
16cbee1fb2 chore(deps): update svelte monorepo 2025-09-06 19:18:48 +00:00
Elian Doran
56932f2b56 chore(deps): update dependency express-rate-limit to v8.1.0 (#6898) 2025-09-06 22:18:40 +03:00
Elian Doran
6a8f6b8370 fix(deps): update dependency i18next to v25.5.2 (#6900) 2025-09-06 22:17:19 +03:00
Elian Doran
7fa8e65015 fix(deps): update dependency mermaid to v11.11.0 (#6901) 2025-09-06 22:16:53 +03:00
Elian Doran
4f50b8c7d5 fix(deps): update eslint monorepo to v9.35.0 (#6907) 2025-09-06 22:15:36 +03:00
Elian Doran
eca85d9978 chore(deps): update actions/setup-python action to v6 (#6909) 2025-09-06 22:15:10 +03:00
Elian Doran
f0ea2eb39b fix(deps): update dependency force-graph to v1.51.0 (#6906) 2025-09-06 22:14:42 +03:00
Elian Doran
4c5b229680 chore(deps): update actions/github-script action to v8 (#6908) 2025-09-06 22:13:07 +03:00
Elian Doran
83251cbc43 Merge branch 'main' into feat/performance/disable-smooth-scroll 2025-09-06 22:12:19 +03:00
Adorian Doran
c2f20cce32 Merge branch 'main' into feat/electron-app/background-effects-improvements 2025-09-06 22:02:47 +03:00
Adorian Doran
ec5ab44519 style/background effects: tweak launcher pane colors 2025-09-06 22:00:16 +03:00
renovate[bot]
ed6d21a05a chore(deps): update dependency node to v22 2025-09-06 18:58:17 +00:00
renovate[bot]
a2f3913fe5 chore(deps): update actions/setup-python action to v6 2025-09-06 18:57:17 +00:00
renovate[bot]
d66c0ef308 chore(deps): update actions/setup-node action to v5 2025-09-06 18:57:14 +00:00
renovate[bot]
0f9f6746ed chore(deps): update actions/github-script action to v8 2025-09-06 18:57:10 +00:00
renovate[bot]
9b534a0dc1 fix(deps): update eslint monorepo to v9.35.0 2025-09-06 18:57:07 +00:00
renovate[bot]
1ce73c1238 fix(deps): update dependency mermaid to v11.11.0 2025-09-06 18:56:11 +00:00
renovate[bot]
3b5b7ca01d fix(deps): update dependency i18next to v25.5.2 2025-09-06 18:55:40 +00:00
renovate[bot]
ce64a7816d fix(deps): update dependency force-graph to v1.51.0 2025-09-06 18:55:09 +00:00
renovate[bot]
37e095a93c fix(deps): update dependency eslint-linter-browserify to v9.35.0 2025-09-06 18:54:39 +00:00
Adorian Doran
300f6a103f style/background effects: tweak launcher pane colors 2025-09-06 21:53:47 +03:00
renovate[bot]
e7cb5a6b92 chore(deps): update dependency express-rate-limit to v8.1.0 2025-09-06 18:53:07 +00:00
renovate[bot]
67296fabf7 chore(deps): update dependency @smithy/middleware-retry to v4.2.0 2025-09-06 18:52:37 +00:00
renovate[bot]
d868f7fb26 chore(deps): update dependency @anthropic-ai/sdk to v0.61.0 2025-09-06 18:52:08 +00:00
renovate[bot]
1555d98f7d chore(deps): update tailwindcss monorepo to v4.1.13 2025-09-06 18:51:05 +00:00
renovate[bot]
3a02941b38 chore(deps): update dependency @types/leaflet-gpx to v1.3.8 2025-09-06 18:49:37 +00:00
Elian Doran
f25de1ffbe chore(ci): bring back typecheck 2025-09-06 21:43:48 +03:00
Adorian Doran
008e90324f style/background effects: tweak launcher pane colors 2025-09-06 21:43:09 +03:00
Adorian Doran
73dcc2eb26 style/background effects: convert the tree action button background color to a transparent color 2025-09-06 21:32:31 +03:00
Adorian Doran
eae2540a31 style/background effects: convert the tree item hover color to a transparent color 2025-09-06 21:21:43 +03:00
Adorian Doran
2a7fc8edb6 style/background effects: extract color overrides as theme variables 2025-09-06 21:13:09 +03:00
Elian Doran
cd67299b1d chore(react/collections/table): bring back footer 2025-09-06 21:08:32 +03:00
Elian Doran
ff38008207 chore(react/collections/table): react to note changes 2025-09-06 20:31:44 +03:00
Elian Doran
76e903a782 chore(react/collections/table): set up context menu partially 2025-09-06 20:25:50 +03:00
Adorian Doran
25698f5d9b electron app: display the smooth scrolling setting only on the Electron app 2025-09-06 19:31:45 +03:00
Adorian Doran
c729731c7e electron app: mention that a restart is required for the smooth scrolling setting to take effect 2025-09-06 19:24:32 +03:00
Elian Doran
9d877ec97a chore(react/collections/table): enable modules 2025-09-06 19:19:52 +03:00
Elian Doran
b4cead757d chore(react/collections/table): get rid of react-tables 2025-09-06 19:12:24 +03:00
Adorian Doran
dcc2f28079 electron app: add Romanian translation 2025-09-06 19:05:20 +03:00
Adorian Doran
97aa00e18b electron app: add an option to disable smooth scrolling 2025-09-06 19:00:45 +03:00
Elian Doran
f076581bed chore(react/collections/table): get table to render 2025-09-06 18:48:58 +03:00
Elian Doran
5d8f789791 fix(desktop): background effects causing issues on Win10 2025-09-06 17:47:13 +03:00
Elian Doran
4faabb7770 Translations update from Hosted Weblate (#6911) 2025-09-06 17:34:54 +03:00
Elian Doran
1cffff77bf fix(client): touch bar triggering on server 2025-09-06 17:26:48 +03:00
donut
8f9b3df681 Translated using Weblate (Polish)
Currently translated at 37.3% (141 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/pl/
2025-09-06 14:08:09 +00:00
Mik Piet
449575e0f7 Translated using Weblate (Polish)
Currently translated at 7.3% (115 of 1566 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-09-06 14:08:08 +00:00
donut
b7d47779d6 Translated using Weblate (Polish)
Currently translated at 7.3% (115 of 1566 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-09-06 14:08:08 +00:00
Elian Doran
fe443c8a89 fix(next): window border cut-off on macOS 2025-09-06 17:07:56 +03:00
Elian Doran
f01a772d8d chore(react/collections/geomap): remove some logs 2025-09-06 16:23:42 +03:00
Elian Doran
76d068aa23 chore(react/collections/calendar): optimize button building 2025-09-06 16:13:33 +03:00
Elian Doran
b151db0843 chore(react/collections/calendar): header & touchbar sometimes not updating 2025-09-06 16:09:02 +03:00
Elian Doran
5a3f432d89 feat(react/collections/calendar): improve performance on option change 2025-09-06 16:02:25 +03:00
Elian Doran
8dcef5ea9f chore(react/collections): add spacer for calendar touch bar 2025-09-06 15:40:47 +03:00
Elian Doran
05299952a9 chore(react/collections): use normal buttons for calendar prev/next 2025-09-06 15:36:37 +03:00
Elian Doran
5966b9ff23 chore(react/collections): add date navigation buttons to calendar touchbar 2025-09-06 15:20:22 +03:00
Elian Doran
1917c04baf chore(react/collections): reintroduce calendar title & type touch bar 2025-09-06 14:59:57 +03:00
Elian Doran
4c20ac0b1c chore(react/collections): reintroduce geomap touch bar buttons 2025-09-06 14:31:41 +03:00
Elian Doran
6bd548cc22 refactor(react/touchbar): use more performant mechanism 2025-09-06 14:23:43 +03:00
Elian Doran
3e7f0ad0a8 chore(react/touchbar): add slider 2025-09-06 14:18:32 +03:00
Elian Doran
785f72ecd6 chore(react/touchbar): react to updates 2025-09-06 14:08:00 +03:00
Elian Doran
62cdb1a797 chore(react): basic React-like touch bar support 2025-09-06 14:00:23 +03:00
Elian Doran
24e17c4e4f style(collections/calendar): improve button style 2025-09-06 13:28:16 +03:00
Elian Doran
d664c0166d style(collections/calendar): bring back some header styles + layout 2025-09-06 13:19:25 +03:00
Elian Doran
05ebe821f2 Revert "chore(collections/calendar): experiment with avoiding floating buttons"
This reverts commit 6c4ac347db.
2025-09-06 13:17:21 +03:00
Elian Doran
6c4ac347db chore(collections/calendar): experiment with avoiding floating buttons 2025-09-06 13:09:24 +03:00
Elian Doran
e8024ce341 fix(collections/calendar): header not initializing properly on first render 2025-09-06 12:34:18 +03:00
Elian Doran
afc17f41f6 feat(collections/calendar): use own UI for header 2025-09-06 12:26:42 +03:00
Elian Doran
49c80f0e0b fix(client): sql result taking unnecessary space when inactive 2025-09-06 11:28:19 +03:00
Elian Doran
10a6a3056a chore(react/collections/calendar): reintroduce tests 2025-09-06 11:20:39 +03:00
Elian Doran
69af62cde0 refactor(react/collections/calendar): split editing 2025-09-06 11:06:24 +03:00
Elian Doran
0cc8b5def0 chore(react/collections/calendar): add back event customization 2025-09-06 10:58:24 +03:00
Elian Doran
fc52e73153 refactor(react/collections/calendar): change event handling 2025-09-06 10:54:18 +03:00
Elian Doran
ce67e460c6 refactor(react/collections/calendar): add a few more options 2025-09-06 10:53:15 +03:00
Elian Doran
85e5f4d2c0 refactor(react/collections/calendar): add back clicking on date notes 2025-09-06 10:52:14 +03:00
Elian Doran
6237afe3cd refactor(react/collections/calendar): change event in api 2025-09-06 10:43:43 +03:00
Elian Doran
cfddb6f04e chore(react/collections/calendar): port dragging items 2025-09-06 10:36:32 +03:00
perf3ct
3bf1a77381 feat(docs): also deploy docs upon README change 2025-09-05 19:52:03 +00:00
perf3ct
c4d430c62d feat(docs): use readme as index.md in mkdocs deployment 2025-09-05 19:40:59 +00:00
perf3ct
d583ee2de3 feat(docs): just remove the other language READMEs from the hide list 2025-09-05 19:34:54 +00:00
perf3ct
406a381ef4 feat(docs): try to continue fixing the links in the mkdocs 2025-09-05 19:18:14 +00:00
Elian Doran
1d82308c43 feat(docs): create docs.triliumnotes.org as additional place to serve user-facing docs (#6889) 2025-09-05 21:49:36 +03:00
perf3ct
5c1595b1fd feat(docs): remove unused python 2025-09-05 15:15:12 +00:00
perf3ct
667cfb999b feat(docs): oops forgot to add it to the package.json 2025-09-05 15:11:48 +00:00
Elian Doran
f0b5954c54 refactor(react/collections/calendar): refactor into API 2025-09-05 18:10:34 +03:00
perf3ct
9b0e817635 feat(docs): transition from python to ts 2025-09-05 15:09:27 +00:00
Elian Doran
b93d9a6b6e chore(react/collections/calendar): render calendar events 2025-09-05 18:00:27 +03:00
Elian Doran
5bb9117fde chore(react/collections/calendar): render non-calendar events 2025-09-05 17:56:35 +03:00
Elian Doran
84d35c1a37 chore(react/collections/calendar): create event from selection 2025-09-05 17:44:24 +03:00
Elian Doran
ba42e90502 chore(react/collections/calendar): handle resize 2025-09-05 17:33:46 +03:00
Elian Doran
10d1ec1bb2 chore(react/collections/calendar): bring back saving of view 2025-09-05 17:18:02 +03:00
Elian Doran
d6ccd106e6 chore(react/collections/calendar): bring back locale 2025-09-05 16:51:36 +03:00
Elian Doran
7f7eaea2b1 chore(react/collections/calendar): hide weekends & week numbers 2025-09-05 16:28:34 +03:00
Elian Doran
d33b1eb394 chore(react/collections/calendar): add views & first day of week 2025-09-05 16:26:52 +03:00
Elian Doran
feb984649f chore(react/collections/calendar): set up CSS 2025-09-05 16:22:48 +03:00
Elian Doran
aada49e548 chore(react/collections/calendar): get calendar to render 2025-09-05 16:03:12 +03:00
SiriusXT
7f3c34178b fix: add left-click check for tree button handlers 2025-09-05 19:32:42 +08:00
Elian Doran
c79dd43105 chore(react/collections): bring back touch bar 2025-09-05 11:54:58 +03:00
Elian Doran
cb53ff880d chore(react/collections/geomap): clean up 2025-09-05 11:04:36 +03:00
Elian Doran
3d88b3c74b fix(react/collections/geomap): drag not always working 2025-09-05 10:32:26 +03:00
Elian Doran
d3c66714c2 fix(react/collections/geomap): crash for notes without location 2025-09-05 08:48:24 +03:00
perf3ct
e8ca443697 feat(docs): try to fix local doc links 2025-09-04 22:16:43 -07:00
perf3ct
94089113ef feat(docs): try to handle moved files too in script 2025-09-04 21:55:28 -07:00
perf3ct
1847fc2060 feat(docs): fix nav and scripts 2025-09-04 23:50:22 +00:00
perf3ct
7ca21b52a0 feat(docs): fix references to zadam 2025-09-04 23:46:50 +00:00
perf3ct
444beb4908 feat(docs): get images to work now 2025-09-04 23:39:40 +00:00
perf3ct
791869ca9e feat(docs): try to capture all pages 2025-09-04 23:30:20 +00:00
perf3ct
33c8406b8a feat(docs): try to make pnpm happy for mkdocs
asfd

asdf
2025-09-04 21:57:26 +00:00
perf3ct
b6212c4e98 feat(docs): try to get wrangler to work...
feat(docs)asdf

asdf
2025-09-04 21:32:32 +00:00
perf3ct
fcd2409ee3 feat(docs): try to get mkdocs to work again 2025-09-04 21:20:01 +00:00
perf3ct
dad060d0c9 feat(docs): let's try to deploy our stuff to mkdocs 2025-09-04 21:13:12 +00:00
Elian Doran
9444195de7 chore(react/collections): set up dragging (partially) 2025-09-04 23:35:18 +03:00
Elian Doran
b25f3094b7 refactor(react/collections): reintroduce gpx tracks 2025-09-04 22:53:39 +03:00
Elian Doran
ec378a8fc5 refactor(react/collections): reintroduce scale 2025-09-04 22:05:44 +03:00
Elian Doran
9adf9a841c chore(react/collections/geomap): bring back remove from map 2025-09-04 21:52:41 +03:00
Elian Doran
8bb8e011f3 chore(react/collections/geomap): properly dispose 2025-09-04 21:50:45 +03:00
Elian Doran
3b66522a5e chore(react/collections/geomap): bring back map context menu 2025-09-04 21:46:05 +03:00
Elian Doran
dd2b718974 chore(react/collections/geomap): bring back dark theme labels 2025-09-04 21:40:12 +03:00
Elian Doran
50121153dd chore(react/collections/geomap): bring back adding new items 2025-09-04 21:37:08 +03:00
Elian Doran
189b7e20db chore(react/collections/geomap): bring back context menu 2025-09-04 21:26:09 +03:00
SiriusXT
5e572a8c6a fix: remove unnecessary line breaks 2025-09-04 22:07:04 +08:00
Elian Doran
dd654fcd8d chore(react/collections/geomap): bring back open on click 2025-09-04 16:51:03 +03:00
Elian Doran
0f9a529647 chore(react/collections/geomap): fix editability 2025-09-04 16:47:38 +03:00
Elian Doran
5854adb806 chore(react/collections/geomap): bring back dragging 2025-09-04 16:44:35 +03:00
SiriusXT
c60c738c7e feat: show source diff between note and revision 2025-09-04 21:34:13 +08:00
Elian Doran
ec40d20e6a chore(react/collections/geomap): middle click 2025-09-04 16:24:01 +03:00
Elian Doran
3e2b777c30 chore(react/collections/geomap): fix color class 2025-09-04 16:19:56 +03:00
Elian Doran
4a02981c09 refactor(react/collections/geomap): display reactive icon, text 2025-09-04 16:17:27 +03:00
Elian Doran
3382ccc7bf refactor(react/collections/geomap): use different mechanism for markers 2025-09-04 15:58:50 +03:00
Elian Doran
581303c923 chore(react/collections/geomap): get markers to show up 2025-09-04 15:47:56 +03:00
Elian Doran
63dd79e23c chore(react/collections/geomap): restore state 2025-09-04 15:16:49 +03:00
Elian Doran
2346230d36 chore(react/collections/geomap): save state 2025-09-04 14:26:29 +03:00
SiriusXT
1c451fb98a fix: adapt diff highlight for dark theme 2025-09-04 18:47:14 +08:00
SiriusXT
7eeb43a83b Merge branch 'main' into history_diff 2025-09-04 17:37:00 +08:00
SiriusXT
fa2188f087 fix: improve <pre> tag regex handling when formatting HTML strings 2025-09-04 17:36:19 +08:00
Elian Doran
df1b87e3ac chore(dx/nix): fix flake partially 2025-09-04 12:12:23 +03:00
Elian Doran
62a0a44049 chore(dx): have electron-rebuild read from path on NixOS too 2025-09-04 09:26:16 +03:00
SiriusXT
0ae25d2212 feat: show source diff between note and revision 2025-09-04 10:53:46 +08:00
Elian Doran
620e6012da refactor(react/collections): reintroduce view mode 2025-09-03 23:57:38 +03:00
Elian Doran
330b17bff8 refactor(react/collections): move layer name to view 2025-09-03 23:35:29 +03:00
Elian Doran
1969ce562a chore(react/collections): start porting geomap 2025-09-03 23:23:42 +03:00
Elian Doran
5ea15cc7eb Merge remote-tracking branch 'origin/main' into react/collections 2025-09-03 22:41:44 +03:00
Elian Doran
88aa76bcab Improve development experience (#6842) 2025-09-03 22:13:17 +03:00
Elian Doran
401120fa28 Merge remote-tracking branch 'origin/main' into feature/dx_improvement 2025-09-03 21:24:51 +03:00
Elian Doran
534113b303 fix(dx/share): ckcontent for share theme not preserved 2025-09-03 21:09:56 +03:00
Elian Doran
53df7835d3 Revert "chore(dx/server): remove dependency on CKEditor for now"
This reverts commit 4739e2e3b2.
2025-09-03 20:24:23 +03:00
Elian Doran
ee9afb7fa0 fix(next): 1px border on tab when background effects are on 2025-09-03 20:09:19 +03:00
Elian Doran
6163ab8c42 refactor(dx): remove unused .env files 2025-09-03 20:08:29 +03:00
Elian Doran
e73724a576 chore(dx/desktop): integrate e2e tests in same project 2025-09-03 20:08:17 +03:00
Elian Doran
e71284d887 chore(dx): get rid of references to NX 2025-09-03 18:23:47 +03:00
Elian Doran
11d95b89e1 chore(dx/edit-docs): de-nxify 2025-09-03 18:16:03 +03:00
Elian Doran
ee7052ebc2 chore(deps): update dependency dotenv to v17.2.2 (#6876) 2025-09-03 18:02:23 +03:00
renovate[bot]
9059642738 chore(deps): update dependency dotenv to v17.2.2 2025-09-03 14:14:24 +00:00
Elian Doran
fe8e3b4489 chore(deps): update svelte monorepo (#6874) 2025-09-03 17:11:58 +03:00
Elian Doran
4e00e5b995 chore(deps): update dependency dotenv to v17.2.2 (#6875) 2025-09-03 17:11:45 +03:00
Elian Doran
05ae0ca9d7 chore(deps): update dependency @anthropic-ai/sdk to v0.61.0 (#6877) 2025-09-03 17:11:38 +03:00
Elian Doran
ac0116109b chore(deps): update typescript-eslint monorepo to v8.42.0 (#6878) 2025-09-03 17:11:28 +03:00
renovate[bot]
710ed9dd0e chore(deps): update svelte monorepo 2025-09-03 12:45:44 +00:00
Elian Doran
c75d2435fa fix(dx/share): ckcontent missing 2025-09-03 15:23:32 +03:00
Elian Doran
050aa40e20 fix(dx/share): templates and script not accessible 2025-09-03 12:12:01 +03:00
Elian Doran
cb6d87302d fix(dx/client): doc notes not working 2025-09-03 12:00:06 +03:00
Elian Doran
f9e725bcf8 chore(dx): add aliases to desktop 2025-09-03 11:56:44 +03:00
Elian Doran
a56d622df7 chore(dx): address self-review 2025-09-03 10:55:40 +03:00
Adorian Doran
267f5105b2 Theme tweaks (#6832) 2025-09-03 10:53:57 +03:00
SiriusXT
4e2ffad70d Merge branch 'main' into siriusxt_split 2025-09-03 14:05:08 +08:00
Elian Doran
7db3bde933 chore(e2e): merge .env in playwright config + add retry 2025-09-03 09:02:10 +03:00
Adorian Doran
a9564f8f38 style/launchbar buttons: fix broken hover state when background effects are enabled 2025-09-03 05:25:26 +03:00
Adorian Doran
9c5a130ab4 style/text editor/forms: restyle text areas 2025-09-03 04:38:37 +03:00
Adorian Doran
c40398df5d style/text editor/forms: tweak text boxes 2025-09-03 04:29:02 +03:00
Adorian Doran
27fdd9e715 style/text editor/find and replace: add style for the "replace" buttons 2025-09-03 04:13:29 +03:00
renovate[bot]
59697095b1 chore(deps): update typescript-eslint monorepo to v8.42.0 2025-09-03 00:40:09 +00:00
renovate[bot]
a16f5f5505 chore(deps): update dependency @anthropic-ai/sdk to v0.61.0 2025-09-03 00:38:49 +00:00
renovate[bot]
922d484a33 chore(deps): update dependency dotenv to v17.2.2 2025-09-03 00:37:18 +00:00
Elian Doran
f63f24ac9d feat(server/e2e): upload test report if it fails 2025-09-02 22:51:57 +03:00
Elian Doran
e7521fe30c chore(server/e2e): increase timeout of a flaky test 2025-09-02 22:30:09 +03:00
Elian Doran
f6579ac434 fix(e2e/server): data dir not working 2025-09-02 21:45:59 +03:00
Elian Doran
e1b4a0b720 fix(deps): update dependency @codemirror/view to v6.38.2 (#6860) 2025-09-02 21:33:12 +03:00
Elian Doran
9c43d661be fix(desktop): forge building for the wrong arch 2025-09-02 21:13:32 +03:00
Elian Doran
d2d8bff9f7 fix(e2e/server): wrong database dir 2025-09-02 21:06:41 +03:00
Elian Doran
a1beb13094 chore(ci): add logs for electron-forge flatpak build 2025-09-02 20:46:44 +03:00
Elian Doran
37d66848d6 Merge remote-tracking branch 'origin/main' into feature/dx_improvement
; Conflicts:
;	pnpm-lock.yaml
2025-09-02 20:43:43 +03:00
Elian Doran
991399fe4f Merge branch 'main' into renovate/codemirror 2025-09-02 20:41:41 +03:00
Elian Doran
27855456a0 chore(deps): update dependency lint-staged to v16.1.6 (#6856) 2025-09-02 20:40:55 +03:00
Elian Doran
0687ed9ec4 chore(deps): update dependency typedoc to v0.28.12 (#6857) 2025-09-02 20:40:42 +03:00
Elian Doran
632976e71f chore(deps): update pnpm to v10.15.1 (#6859) 2025-09-02 20:40:25 +03:00
Elian Doran
98addef614 fix(deps): update dependency dayjs to v1.11.18 (#6861) 2025-09-02 20:40:10 +03:00
Elian Doran
c72c9934b5 fix(deps): update dependency react-i18next to v15.7.3 (#6862) 2025-09-02 20:39:54 +03:00
Elian Doran
6362f24ae9 chore(deps): update dependency @stylistic/eslint-plugin to v5.3.1 (#6863) 2025-09-02 20:39:41 +03:00
Elian Doran
dc2d2fe25b chore(deps): update dependency vite to v7.1.4 (#6858) 2025-09-02 20:39:20 +03:00
renovate[bot]
bbc007e6cf chore(deps): update dependency vite to v7.1.4 2025-09-02 17:36:12 +00:00
Elian Doran
3dfd195630 chore(deps): update dependency @sveltejs/kit to v2.37.0 (#6864) 2025-09-02 20:34:24 +03:00
Elian Doran
e3f72baab3 chore(deps): update node.js to v22.19.0 (#6865) 2025-09-02 20:33:23 +03:00
Elian Doran
1bb19d0d9e Translations update from Hosted Weblate (#6871) 2025-09-02 20:31:45 +03:00
Микола Копитін
bc1b69a836 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (1566 of 1566 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/uk/
2025-09-02 17:03:22 +00:00
Elian Doran
26c7f0b017 feat(dx/desktop): improve rebuilding experience on NixOS 2025-09-02 19:56:27 +03:00
Elian Doran
d058dbe9af chore(dx/desktop): clean up env 2025-09-02 19:56:18 +03:00
Elian Doran
c1c237402a chore(dx/desktop): clean up package.json 2025-09-02 19:49:36 +03:00
Elian Doran
bb20de6c24 chore(dx/env): remove unnecessary nx config 2025-09-02 19:44:38 +03:00
Elian Doran
8d7af7b01d chore(dx/server): de-nxify 2025-09-02 19:44:28 +03:00
Elian Doran
fd1c122cd4 chore(dx/apps): build db-compare & dump-db 2025-09-02 19:29:38 +03:00
Elian Doran
3925ba3eef chore(dx/ci): fix sequential/parallel tests 2025-09-02 19:16:49 +03:00
Elian Doran
4306072ca7 chore(dx/ci): sequential/parallel tests 2025-09-02 19:09:45 +03:00
Elian Doran
15fba23ad7 chore(dx/ci): denx-ify playwright 2025-09-02 19:00:49 +03:00
Elian Doran
04753226e5 chore(dx/ci): fix package command 2025-09-02 18:42:30 +03:00
Elian Doran
3fda97a9bd chore(dx/client): allocate more memory for the build 2025-09-02 18:38:50 +03:00
Elian Doran
26afdd105f chore(dx/server): get tests to run 2025-09-02 18:33:22 +03:00
Elian Doran
7c50251c37 chore(dx): clean up global package.json 2025-09-02 18:32:03 +03:00
Elian Doran
3de9d07769 chore: update lock 2025-09-02 17:54:05 +03:00
Elian Doran
d60899e362 chore(dx): remove unnecessary nx configs 2025-09-02 17:43:32 +03:00
Elian Doran
7c8019ac5b chore(dx/ci): get rid of nx-specific workflows 2025-09-02 17:38:24 +03:00
Elian Doran
1258d0cf7d chore(dx/desktop): read electron version from package.json 2025-09-02 17:37:57 +03:00
SiriusXT
2264369e9e feat: Make splits resizable 2025-09-02 22:05:26 +08:00
Elian Doran
e18a8556c1 chore(dx/ci): remove most references to NX, apart from unit test 2025-09-02 16:40:52 +03:00
SiriusXT
5436011f8e feat: Make splits resizable 2025-09-02 20:17:01 +08:00
Elian Doran
ce0fd3cec2 chore(dx/desktop): get forge to run 2025-09-02 13:59:09 +03:00
Elian Doran
bd349f5abc feat(dx/desktop): support raw NixOS via LD_LIBRARY_PATH injection 2025-09-02 12:18:22 +03:00
Elian Doran
7fdea613ff feat(dx/desktop): perfect way to override bettersqlite native 2025-09-02 11:50:58 +03:00
Elian Doran
16beeb2e88 fix(dx): broken imports after changing hoisting 2025-09-02 11:03:24 +03:00
Elian Doran
ae74f8ea83 feat(dx/desktop): isolate node_modules dependency 2025-09-02 10:45:42 +03:00
SiriusXT
88b748e67b Merge branch 'main' into siriusxt_split 2025-09-02 09:36:06 +08:00
SiriusXT
3254069999 feat: Make splits resizable 2025-09-02 09:28:53 +08:00
renovate[bot]
0bfa9f0c58 chore(deps): update node.js to v22.19.0 2025-09-02 01:18:18 +00:00
renovate[bot]
498ffa806d chore(deps): update dependency @sveltejs/kit to v2.37.0 2025-09-02 01:18:13 +00:00
renovate[bot]
9bfed2a80d chore(deps): update dependency @stylistic/eslint-plugin to v5.3.1 2025-09-02 01:17:37 +00:00
renovate[bot]
ec902c5762 fix(deps): update dependency react-i18next to v15.7.3 2025-09-02 01:17:32 +00:00
renovate[bot]
bb1d31f877 fix(deps): update dependency dayjs to v1.11.18 2025-09-02 01:16:58 +00:00
renovate[bot]
09f938fb72 fix(deps): update dependency @codemirror/view to v6.38.2 2025-09-02 01:16:21 +00:00
renovate[bot]
a3e9192998 chore(deps): update pnpm to v10.15.1 2025-09-02 01:15:40 +00:00
renovate[bot]
80b7c0b4c9 chore(deps): update dependency typedoc to v0.28.12 2025-09-02 01:14:46 +00:00
renovate[bot]
f01d6938f3 chore(deps): update dependency lint-staged to v16.1.6 2025-09-02 01:14:40 +00:00
Adorian Doran
ab95d707a3 style/text editor/forms: refactor 2025-09-02 02:43:11 +03:00
Adorian Doran
6475b4029a style/text editor/forms: restyle number inputs 2025-09-02 02:42:05 +03:00
Adorian Doran
f646b3dc5c style/text editor/color selector dropdown: fix layout 2025-09-02 02:14:43 +03:00
Adorian Doran
bcef0802e4 style/text editor/insert emoji flyout: fix the spacing of the skin tone dropdown items 2025-09-02 02:08:04 +03:00
Adorian Doran
47099cc77b style/text editor/insert math flyout: fix layout 2025-09-02 02:03:49 +03:00
Elian Doran
793102f3ad chore(dx/electron): fix tray icons 2025-09-01 22:55:53 +03:00
Elian Doran
6f29bdf355 chore(dx/electron): different window icon 2025-09-01 22:25:06 +03:00
Elian Doran
edf53c8a0f chore(dx/desktop): configure dev & start-prod 2025-09-01 21:16:10 +03:00
Elian Doran
24859e33c1 chore(dx/desktop): generate prod package.json 2025-09-01 21:15:44 +03:00
Elian Doran
ebcf4315f7 chore(dx/desktop): remote main not working in dist build 2025-09-01 21:15:17 +03:00
Elian Doran
135e2bb10e chore(dx/desktop): get prod build 2025-09-01 20:50:22 +03:00
Elian Doran
72a256eccf refactor(dx/server): simplify build script even further 2025-09-01 20:29:34 +03:00
Elian Doran
1e991c0526 refactor(dx/server): extract basic build commands to separate file 2025-09-01 19:36:14 +03:00
Elian Doran
978e6b9dde chore(dx/server): unnecessary import 2025-09-01 19:22:46 +03:00
perf3ct
a2acb3cbb7 fix(shortcuts): try to fix ime composition checks 2025-09-01 16:21:58 +00:00
Papierkorb2292
623fcce3d1 Also update note context in other note context events in note wrapper so it works with tabs 2025-09-01 11:33:15 +02:00
Papierkorb2292
c99ef4a549 Make note wrapper widget aware of note context on mobile 2025-09-01 11:01:29 +02:00
Papierkorb2292
c629ce6ef8 Add note wrapper widget in mobile_layout.tsx 2025-09-01 11:01:08 +02:00
Elian Doran
35743de0df fix(dx/client): client not starting due to duplicate config 2025-09-01 11:53:17 +03:00
Elian Doran
5cf182cf98 fix(dx/client): not serving Vite due to NODE_ENV 2025-09-01 11:50:41 +03:00
Elian Doran
01022546e8 fix(dx/client): insert math not working due to icon import 2025-09-01 11:33:18 +03:00
Elian Doran
83be42f4ea Translations update from Hosted Weblate (#6843) 2025-09-01 09:10:52 +03:00
Mik Piet
ab9fec0186 Translated using Weblate (Polish)
Currently translated at 7.0% (111 of 1566 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-09-01 06:02:00 +02:00
Flowerlywind
c6dd32ea7b Translated using Weblate (Vietnamese)
Currently translated at 2.5% (40 of 1566 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/vi/
2025-09-01 06:01:58 +02:00
Kuzma Simonov
1d4cd538ac Translated using Weblate (Russian)
Currently translated at 100.0% (1566 of 1566 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-09-01 06:01:57 +02:00
rodrigomescua
dc99f725f9 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (1566 of 1566 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pt_BR/
2025-09-01 06:01:55 +02:00
Newcomer1989
2f804f3eac Translated using Weblate (German)
Currently translated at 100.0% (1566 of 1566 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-09-01 06:01:54 +02:00
Elian Doran
4b9688af04 chore(dx/server): minify output 2025-08-31 23:19:07 +03:00
Elian Doran
897b896c11 chore(dx/server): fix vite interfering in production 2025-08-31 23:12:52 +03:00
Elian Doran
3600b46824 chore(dx/server): fix missing path to client 2025-08-31 23:04:18 +03:00
Elian Doran
9266fe63b9 chore(dx/client): disable share CSS for now 2025-08-31 23:03:38 +03:00
Elian Doran
a3ea52968f chore(dx/client): fix codemirror dep 2025-08-31 23:03:30 +03:00
Elian Doran
a06f2aeb8b chore(dx/server): trigger build of client & copy artifacts 2025-08-31 23:03:21 +03:00
Elian Doran
f4a56d4e19 chore(dx/client): get vite build to work 2025-08-31 23:02:41 +03:00
Elian Doran
f3f7ff5622 chore(dx/server): copy share templates when building 2025-08-31 22:48:50 +03:00
Elian Doran
dbf016adaf chore(dx/server): build all entrypoints with right ext 2025-08-31 22:43:21 +03:00
Elian Doran
0e5108bd08 chore(dx/server): start building & copying assets 2025-08-31 22:30:07 +03:00
Elian Doran
cf1180faa9 chore(dx/server): remove babel compacting for tiny gain in perf 2025-08-31 21:05:23 +03:00
Elian Doran
1b25275b2e fix(dx/electron): web contents not working 2025-08-31 20:43:48 +03:00
Elian Doran
886c694db7 chore(dx/server): update server:start command 2025-08-31 20:43:33 +03:00
Elian Doran
3d38a2aa14 chore(dx/desktop): get dev mode for Electron 2025-08-31 20:43:20 +03:00
Elian Doran
51d879ba6f style(client): toast sometimes going out of bounds 2025-08-31 20:42:46 +03:00
Elian Doran
91ae9d75f7 Revert "chore(dx/server): improve asset management for DB init"
This reverts commit 42559364e4.
2025-08-31 20:31:51 +03:00
Elian Doran
42559364e4 chore(dx/server): improve asset management for DB init 2025-08-31 20:28:21 +03:00
Elian Doran
9d6bb306e7 fix(electron): history navigation context menu not working 2025-08-31 19:39:54 +03:00
Elian Doran
c92860ae49 chore(dx/client): fix error when optimizing premium plugins 2025-08-31 19:27:05 +03:00
Elian Doran
b012624b67 chore(dx/client): fix emoji import error 2025-08-31 19:26:56 +03:00
Elian Doran
5f1d2f02ee chore(dx/client): fix SVG icons causing errors in CKEditor 2025-08-31 19:26:47 +03:00
Elian Doran
46cb869237 chore(dx/server): client paths not correct 2025-08-31 19:21:36 +03:00
Elian Doran
054c497678 chore(dx/client): improve startup speed by properly configuring middleware 2025-08-31 18:57:31 +03:00
Elian Doran
8362424976 chore(dx/client): fix highlightjs not working 2025-08-31 18:52:52 +03:00
Elian Doran
f7a0dc00e8 chore(dx/client): fix bootstrap CSS imports 2025-08-31 18:52:22 +03:00
Elian Doran
e49c4655a6 chore(dx/client): ckeditor5 CSS imports 2025-08-31 18:51:18 +03:00
Elian Doran
1dcb3b1529 chore(dx/server): set up cache for Vite 2025-08-31 18:28:20 +03:00
Elian Doran
cc474f39d8 chore(dx/server): basic middleware integration for vite 2025-08-31 18:24:02 +03:00
Elian Doran
113d36f5dd chore(dx/client): set paths for client dependencies 2025-08-31 18:19:03 +03:00
Elian Doran
63c0841c32 chore(dx/server): get server to run up to missing public server 2025-08-31 16:58:57 +03:00
Elian Doran
4739e2e3b2 chore(dx/server): remove dependency on CKEditor for now 2025-08-31 16:52:32 +03:00
Elian Doran
aa316091e6 chore(dx): fix cannot read properties of undefined if DB dir is missing 2025-08-31 16:41:03 +03:00
Elian Doran
2297721228 chore(dx): get rid of nx 2025-08-31 16:36:55 +03:00
Adorian Doran
03ab912495 style/text editor/forms: tweak buttons 2025-08-31 03:33:30 +03:00
Adorian Doran
d12dfabd0b style/text editor/forms: various layout fixes 2025-08-31 03:19:33 +03:00
Adorian Doran
ed748bbebd style/text editor/forms: restyle dropdowns 2025-08-31 02:58:53 +03:00
Adorian Doran
e85858d22d style/text editor/forms: fix visible focus for buttons 2025-08-31 02:30:13 +03:00
Adorian Doran
0afa9717e5 style/text editor/forms: restyle buttons 2025-08-31 02:28:24 +03:00
Adorian Doran
1e2e3498c6 style/text editor/forms: restyle text boxes 2025-08-31 01:45:12 +03:00
Elian Doran
59a01b816c Translations update from Hosted Weblate (#6838) 2025-08-30 20:33:31 +03:00
Francis C
508f46af42 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (378 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/zh_Hant/
2025-08-30 19:24:31 +02:00
Francis C
1af865a577 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1566 of 1566 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-08-30 19:24:31 +02:00
Francis C
74834af222 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1566 of 1566 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-08-30 19:24:31 +02:00
Elian Doran
f55e33f303 refactor(note_tree): improve type safety 2025-08-30 20:02:32 +03:00
Elian Doran
5b8394d685 chore(react/collections): display books even if collections only 2025-08-30 19:50:20 +03:00
Elian Doran
34fc30b8db chore(react/collections): avoid intersection observer when not needed 2025-08-30 19:48:05 +03:00
Elian Doran
6e575df40b chore(react/collections): add intersection observer 2025-08-30 19:42:16 +03:00
Elian Doran
2689b22674 chore(react): not reacting to deleted note labels 2025-08-30 19:33:32 +03:00
Elian Doran
5570f3bdcf chore(react/collections): title stretched thin 2025-08-30 19:27:41 +03:00
Elian Doran
cc7edbe3a7 chore(react/collections): full-height rendering for non-legacy 2025-08-30 19:24:32 +03:00
Adorian Doran
fcb77360e1 style/text editor/text alignment dropdown: use a horizontal toolbar instead of a vertical one 2025-08-30 19:22:27 +03:00
Elian Doran
c49e84efc6 refactor(react/collections): rename 2025-08-30 19:21:26 +03:00
Elian Doran
98a4a8d8c6 chore(react/collections): fix list body 2025-08-30 19:13:08 +03:00
Elian Doran
5f73532d62 chore(react/collections): fix expand state when switching notes 2025-08-30 19:11:12 +03:00
Elian Doran
d52f9f2a92 chore(react/collections): highlighting in grid title 2025-08-30 19:07:06 +03:00
Elian Doran
1cee01a22a chore(react/collections): content highlighting in list 2025-08-30 19:03:18 +03:00
Elian Doran
68dff71512 chore(react/collections): title highlighting in list title 2025-08-30 18:49:32 +03:00
Adorian Doran
3d285e105e style/text editor/insert text snippet dropdown: tweak appearance 2025-08-30 18:25:44 +03:00
Elian Doran
f92948d65c chore(react/collections): bring back attribute rendering 2025-08-30 17:39:09 +03:00
Elian Doran
c4d771f2c6 chore(react/collections): use translation 2025-08-30 17:30:35 +03:00
Elian Doran
566ffbdde2 fix(react/collections): pagination displayed when not needed 2025-08-30 17:26:43 +03:00
Elian Doran
5cf18ae17c chore(react/collections/view): first implementation 2025-08-30 17:26:00 +03:00
Elian Doran
4891721cc0 chore(react): fix editorconfig 2025-08-30 17:07:10 +03:00
Elian Doran
49b189e7a9 chore(react/collections/list): add note count to pagination 2025-08-30 17:05:33 +03:00
Elian Doran
a9c5a3105f chore(react/collections/list): add class to title 2025-08-30 17:00:24 +03:00
Elian Doran
c13f5a9b04 refactor(react/collections/list): split pagination into separate file 2025-08-30 16:58:23 +03:00
Elian Doran
12f805c020 chore(react/collections/list): display pagination 2025-08-30 16:40:25 +03:00
Elian Doran
c2a5f437fd chore(react/collections/list): display children recursively 2025-08-30 16:19:21 +03:00
Elian Doran
1c986e2bf6 chore(react/collections/list): display note content 2025-08-30 16:01:02 +03:00
Elian Doran
09fd1c7628 chore(react/collections): get list view to show something 2025-08-30 15:44:49 +03:00
Elian Doran
ecf44deecf chore(react/collections): calculate note Ids 2025-08-30 15:11:49 +03:00
Elian Doran
5fb843268f chore(react/collections): fix imports of ViewTypeOptions 2025-08-30 14:32:06 +03:00
Elian Doran
ffb90c2b4b chore(react/collections): move files around for ease of development 2025-08-30 14:29:54 +03:00
Elian Doran
bb55544f25 Translations update from Hosted Weblate (#6834) 2025-08-30 14:08:47 +03:00
Hosted Weblate
2e9e9a60bf Update translation files
Updated by "Remove blank strings" add-on in Weblate.

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/
2025-08-30 13:08:15 +02:00
Elian Doran
f7e77cd6cb fix(auth): add missing TOTP verification for /login/token (#6823) 2025-08-30 14:08:10 +03:00
Elian Doran
a7a94789e6 chore(server/tree): improve type safety 2025-08-30 14:06:35 +03:00
Elian Doran
864ac1a270 fix(tree): defend against stray null values that may occur when multi… (#6821) 2025-08-30 14:04:02 +03:00
Elian Doran
fbec6d8873 feat(react/widgets): port shared_info 2025-08-30 13:59:53 +03:00
Elian Doran
5f647a932d Port small widgets to React (#6830) 2025-08-30 12:51:31 +03:00
Elian Doran
6e5046c0d4 chore(react/widgets): fix import error 2025-08-30 12:16:29 +03:00
Elian Doran
3c9a8e38d3 feat(react/widgets): port close zen button 2025-08-30 12:04:31 +03:00
Elian Doran
b3a3196136 style(react/widgets): improve api log slightly 2025-08-30 11:36:47 +03:00
Elian Doran
3229b7d106 feat(react/widgets): port api_log 2025-08-30 11:31:49 +03:00
Elian Doran
4213c377f8 fix(react/widgets): alignment of shortcuts in context menu 2025-08-30 11:15:06 +03:00
Elian Doran
86365ebd44 feat(react/widgets): port left pane toggle 2025-08-30 10:29:03 +03:00
Elian Doran
20cf685174 Translations update from Hosted Weblate (#6833) 2025-08-30 09:32:32 +03:00
nvcutrb
aeb5a7b251 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1565 of 1565 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-08-30 04:01:58 +02:00
Aitanuqui
47a50bb449 Translated using Weblate (Spanish)
Currently translated at 100.0% (1565 of 1565 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/es/
2025-08-30 04:01:57 +02:00
nvcutrb
a2a5b67496 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1565 of 1565 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-08-30 04:01:55 +02:00
Adorian Doran
a94cc5bdab style/text editor/insert text snippet dropdown: tweak appearance 2025-08-30 02:55:23 +03:00
Adorian Doran
526c5a6dd8 Merge branch 'main' of https://github.com/TriliumNext/Trilium into feat/theme/improvements 2025-08-30 01:06:02 +03:00
Elian Doran
3f5239706f feat(text_snippets): support color class as well 2025-08-29 23:41:46 +03:00
Elian Doran
d2761abd04 feat(text_snippets): display actual note icon 2025-08-29 23:39:40 +03:00
Elian Doran
57983b54d2 fix(react/widgets): electron imports breaking browser 2025-08-29 23:24:12 +03:00
Elian Doran
703cf8434a fix(react/widgets): unnecessary padding due to SQL schemas 2025-08-29 22:45:20 +03:00
Elian Doran
aa4375e25f feat(react/widgets): port mobile editor toolbar 2025-08-29 22:40:03 +03:00
Adorian Doran
7d3a672b55 style/toasts: prevent long text from overflowing 2025-08-29 21:36:09 +03:00
Adorian Doran
c08b30a060 style/text editor: hide icons from the text snippets dropdown 2025-08-29 21:30:04 +03:00
Elian Doran
d579e39b40 feat(react/widgets): port mobile detail menu 2025-08-29 21:18:34 +03:00
Adorian Doran
b147d4bdeb style: brighten the border of dropdowns 2025-08-29 21:17:43 +03:00
Adorian Doran
48faa8a813 client/quick search results: tweak the busy indicator 2025-08-29 21:06:48 +03:00
Elian Doran
ec646809dd feat(react/widgets): port toggle sidebar 2025-08-29 19:39:46 +03:00
Elian Doran
ab48a28635 refactor(react/widgets): typings for dynamic require + solve type errors 2025-08-29 19:29:15 +03:00
Elian Doran
3fd7afbb57 feat(react/widgets): port title bar buttons 2025-08-29 19:09:40 +03:00
Elian Doran
4074929c6b chore(react/global_menu): disable auto-show 2025-08-29 18:50:21 +03:00
Adorian Doran
d73e84ea6c client/quick search results: tweak icon alignment 2025-08-29 18:37:02 +03:00
Elian Doran
753f1dc7b6 feat(react/widgets): sql table schemas 2025-08-29 17:14:27 +03:00
Adorian Doran
9464667323 client/quick search results: remove deprecated styles 2025-08-29 17:12:52 +03:00
Adorian Doran
4d82f2f22d client/quick search results: tweak footer divider margins 2025-08-29 17:11:10 +03:00
Adorian Doran
e3d28e703f client/quick search results: tweak snippet background color 2025-08-29 17:01:08 +03:00
Adorian Doran
5f39a314b5 client/quick search results: fix overflowing snippets 2025-08-29 16:58:13 +03:00
Adorian Doran
43caadc472 client/quick search results: refactor the item delimiter line 2025-08-29 16:57:02 +03:00
Elian Doran
f2ce8b9f3c feat(react/widgets): search results interfering with SQL results + bad note path style 2025-08-29 16:28:49 +03:00
Elian Doran
735e91e636 feat(react/widgets): port sql_result 2025-08-29 16:10:37 +03:00
Elian Doran
4df94d1f20 chore(react/global_menu): add missing command names 2025-08-29 15:02:56 +03:00
Elian Doran
70440520e1 fix(react/global_menu): misalignment of the "advanced" submenu 2025-08-29 15:01:29 +03:00
Elian Doran
e49e2d5093 fix(react/global_menu): styling and layout of keyboard shortcuts 2025-08-29 13:01:54 +03:00
Elian Doran
f0ac301417 refactor(react/global_menu): get rid of outsideChildren 2025-08-29 12:50:45 +03:00
Elian Doran
168ff90e38 fix(react/global_menu): menu layout on mobile 2025-08-29 12:48:10 +03:00
Elian Doran
5e4f529b26 chore(react/global_menu): advanced submenu toggle on mobile 2025-08-29 12:40:16 +03:00
Elian Doran
0d1bd3e298 feat(react/global_menu): add show/hide conditions 2025-08-29 12:36:12 +03:00
Elian Doran
70f826b737 feat(react/global_menu): add update indicator 2025-08-29 12:30:22 +03:00
Elian Doran
8bd5af3fd2 feat(react/global_menu): add a few more items 2025-08-29 12:00:45 +03:00
Elian Doran
dbbae87cd3 feat(react/global_menu): port advanced options 2025-08-29 11:55:05 +03:00
Elian Doran
83fd42aff2 feat(react): add bootstrap tooltip to menu items 2025-08-29 11:54:16 +03:00
Nriver
93c9383a92 fix(auth): add missing TOTP verification for /login/token to align with /login 2025-08-29 11:13:50 +08:00
Romain DEP.
7c490d8b72 fix(tree): defend against stray null values that may occur when multiple sorting overrides are defined
fixes #6820
2025-08-29 01:57:18 +02:00
Elian Doran
b4b5e86a14 Translations update from Hosted Weblate (#6819) 2025-08-29 01:31:37 +03:00
Elian Doran
e166b97b8f feat(react/widgets): port a few more global menu items 2025-08-29 01:07:11 +03:00
Elian Doran
829f382726 feat(react/widgets): global menu with zoom controls 2025-08-29 00:47:47 +03:00
Elian Doran
4ef103063d feat(react/widgets): port search result 2025-08-28 23:16:04 +03:00
Elian Doran
fa66e50193 feat(react/widgets): port scroll padding 2025-08-28 22:12:39 +03:00
Antonio Liccardo (TuxmAL)
255ad96c8b Translated using Weblate (Italian)
Currently translated at 12.9% (202 of 1565 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-08-28 20:52:03 +02:00
Kuzma Simonov
a12fa1177b Translated using Weblate (Russian)
Currently translated at 100.0% (1565 of 1565 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-08-28 20:52:02 +02:00
rodrigomescua
6fa7cc8201 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (378 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/pt_BR/
2025-08-28 20:52:02 +02:00
Newcomer1989
2fff5418a9 Translated using Weblate (German)
Currently translated at 100.0% (378 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/de/
2025-08-28 20:52:01 +02:00
rodrigomescua
2e805cd5a3 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (1565 of 1565 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pt_BR/
2025-08-28 20:52:00 +02:00
Newcomer1989
61eaa89de6 Translated using Weblate (German)
Currently translated at 100.0% (1565 of 1565 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-08-28 20:51:59 +02:00
Elian Doran
aa0c021f8b Theme tweaks (#6783) 2025-08-28 21:51:52 +03:00
Elian Doran
4fd02db079 chore(react): remove irrelevant TODO 2025-08-28 21:03:33 +03:00
Elian Doran
88bbc7e8c1 Port floating buttons to React (#6811) 2025-08-28 21:01:43 +03:00
Elian Doran
af0ba32dd9 chore(react/floating_buttons): fix wrong import of fnote 2025-08-28 20:28:55 +03:00
Elian Doran
938d295bf3 chore(react/floating_buttons): fix type error 2025-08-28 20:13:55 +03:00
Elian Doran
f82667066f feat(react/floating_buttons): add mobile support 2025-08-28 20:10:21 +03:00
Elian Doran
03a7fe1282 fix(react/floating_buttons): react to note type/mime changes 2025-08-28 20:04:47 +03:00
Elian Doran
0c0504ffd1 refactor(react/floating_buttons): use enabled at component level 2025-08-28 19:56:53 +03:00
Elian Doran
e4900ce87b fix(react/floating_buttons): style differences from original 2025-08-28 19:12:26 +03:00
Elian Doran
04de87722b fix(react/floating_buttons): backlinks affecting show/hide button 2025-08-28 19:05:30 +03:00
Elian Doran
a95e28c085 feat(react/floating_buttons): port backlinks 2025-08-28 18:35:37 +03:00
Elian Doran
9fbcfb0f0f fix(deps): update dependency marked to v16.2.1 (#6815) 2025-08-28 08:52:41 +03:00
renovate[bot]
f24a3442fb fix(deps): update dependency marked to v16.2.1 2025-08-28 05:05:28 +00:00
Elian Doran
918a945e3b chore(deps): update dependency svelte to v5.38.6 (#6813) 2025-08-28 08:03:31 +03:00
Elian Doran
3b96b5779b fix(deps): update dependency dayjs to v1.11.14 (#6814) 2025-08-28 08:02:48 +03:00
Elian Doran
a93b20428e chore(deps): update dependency electron to v37.4.0 (#6816) 2025-08-28 08:02:23 +03:00
renovate[bot]
0522024f6d chore(deps): update dependency electron to v37.4.0 2025-08-28 02:54:57 +00:00
renovate[bot]
f27f135a61 fix(deps): update dependency dayjs to v1.11.14 2025-08-28 02:53:40 +00:00
renovate[bot]
6a76136878 chore(deps): update dependency svelte to v5.38.6 2025-08-28 02:53:04 +00:00
Elian Doran
1766d28fc2 feat(react/floating_buttons): port show/hide 2025-08-28 00:44:18 +03:00
Elian Doran
f51d944bb3 feat(react/floating_buttons): port in-app help button 2025-08-28 00:23:00 +03:00
Elian Doran
cabe240e7e refactor(react/floating_buttons): split into two buttons 2025-08-28 00:06:40 +03:00
Elian Doran
e72fb39c4d feat(react/floating_buttons): port PNG/SVG export buttons 2025-08-28 00:02:02 +03:00
Elian Doran
0ca30e0e87 feat(react/floating_buttons): port copy image reference 2025-08-27 23:57:33 +03:00
Elian Doran
cc362393be chore(react/floating_buttons): port geo map buttons 2025-08-27 23:45:51 +03:00
Elian Doran
40bfd827d2 chore(react/floating_buttons): improve sizing 2025-08-27 23:36:50 +03:00
Elian Doran
a4046fbf6e feat(react/floating_buttons): port relation map buttons 2025-08-27 23:33:07 +03:00
Elian Doran
28605f2687 feat(react/floating_buttons): fancy title + keyboard shortcut 2025-08-27 23:20:19 +03:00
Elian Doran
2085d1bbba feat(react/floating_buttons): port save to note button 2025-08-27 23:14:25 +03:00
Elian Doran
08db03800e feat(react/floating_buttons): port open Trilium API docs 2025-08-27 22:59:07 +03:00
Elian Doran
04b7e0cde9 feat(react/floating_buttons): port execute note button 2025-08-27 22:54:05 +03:00
Elian Doran
401260d3ca feat(react/floating_buttons): port highlights list 2025-08-27 22:47:20 +03:00
Elian Doran
53e0c05290 feat(react/floating_buttons): port toc 2025-08-27 22:44:11 +03:00
Elian Doran
cdbb89482e feat(react/floating_buttons): port edit button 2025-08-27 22:33:36 +03:00
Elian Doran
e290635ba5 feat(react/floating_buttons): port toggle read only button 2025-08-27 22:09:00 +03:00
Elian Doran
e340e6f5e3 feat(react/floating_buttons): port switch split orientation 2025-08-27 21:56:02 +03:00
Elian Doran
2d950e8f3a refactor(react/floating_buttons): use component-driven approach 2025-08-27 21:37:48 +03:00
Elian Doran
4c70d72ba2 feat(react/floating_buttons): port refresh button 2025-08-27 21:29:49 +03:00
Elian Doran
80edc4c4e0 feat(react): base structure for floating buttons 2025-08-27 21:15:54 +03:00
Adorian Doran
4d07a1aab6 client/quick search results: add a whitespace between attributes 2025-08-27 20:51:12 +03:00
Adorian Doran
e2cd357319 style/quick search results: customize the highlight color 2025-08-27 20:51:12 +03:00
Adorian Doran
620b57bfa6 style/quick search results: refactor 2025-08-27 20:51:12 +03:00
Adorian Doran
934c9d3df8 style/quick search results: improve appearance 2025-08-27 20:51:12 +03:00
Adorian Doran
f034e8bb37 style/quick search results: tweak layout 2025-08-27 20:51:12 +03:00
Adorian Doran
93f80c6837 client/quick search: extract inline styles 2025-08-27 20:51:12 +03:00
Adorian Doran
a54177fee0 style(legacy)/checkboxes and radios: add a gap between the tickbox and the label 2025-08-27 20:51:12 +03:00
Adorian Doran
0e6ad42923 style: fix button class 2025-08-27 20:51:12 +03:00
Adorian Doran
b0beb74011 style/dropdown buttons: tweak 2025-08-27 20:51:12 +03:00
Adorian Doran
4857fecc41 style/launcher/calendar: fix the width for the horizontal layout 2025-08-27 20:49:01 +03:00
Adorian Doran
8405d960be style/ribbon/attribute editor: improve layout 2025-08-27 20:45:17 +03:00
Adorian Doran
b9101c9fb2 style/delete note dialog: tweak layout 2025-08-27 20:41:14 +03:00
Adorian Doran
e457e6a2f2 style/note icon buttons: fade the color and use the default cursor when disabled 2025-08-27 20:41:14 +03:00
Elian Doran
f3416fa03e Translations update from Hosted Weblate (#6807) 2025-08-27 20:31:34 +03:00
rodrigomescua
3e5ab2b1e1 Translated using Weblate (Portuguese (Brazil))
Currently translated at 82.0% (1284 of 1564 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pt_BR/
2025-08-27 17:15:24 +00:00
Newcomer1989
5c0bc9a7c2 Translated using Weblate (German)
Currently translated at 91.8% (1437 of 1564 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-08-27 17:15:23 +00:00
Elian Doran
2adfa55acd React context-aware widgets (ribbon, note actions, note title) (#6731) 2025-08-27 20:15:04 +03:00
Elian Doran
8125e8afcd fix(react/options): plain text not disabled 2025-08-27 20:14:33 +03:00
Elian Doran
e328f18558 feat(react/ribbon): edit content languages in modal 2025-08-27 19:56:14 +03:00
Elian Doran
cbdfa9079c fix(react/ribbon): bad right margin of note type 2025-08-27 19:51:24 +03:00
Elian Doran
e08c4515a7 fix(react/ribbon): note type not always updating 2025-08-27 19:49:22 +03:00
Elian Doran
650aa16b89 feat(react/ribbon): improve style of note type modal 2025-08-27 19:46:26 +03:00
Elian Doran
11d908218b feat(react/ribbon): allow editing code types directly 2025-08-27 19:42:20 +03:00
Elian Doran
3627a7dc93 refactor(react/dialogs): allow modals in sub-components 2025-08-27 19:35:47 +03:00
Elian Doran
1e1c8cc4ff fix(ribbon): code note types not refreshing 2025-08-27 19:13:30 +03:00
Elian Doran
d616bc09c9 chore(e2e): remove test that is no longer relevant 2025-08-27 18:55:52 +03:00
Elian Doran
f1cef44d5d Merge remote-tracking branch 'origin/main' into react/note_context_aware
; Conflicts:
;	pnpm-lock.yaml
2025-08-27 18:30:19 +03:00
Elian Doran
3795be4750 Translations update from Hosted Weblate (#6802) 2025-08-27 18:29:13 +03:00
Elian Doran
2bb66a7526 chore(react): fix some more type errors 2025-08-27 18:27:47 +03:00
Elian Doran
28a472782f chore(react): remove debug log 2025-08-27 18:26:27 +03:00
Elian Doran
a4da002352 fix(react/ribbon): saving from attribute dialog not working 2025-08-27 18:25:54 +03:00
Elian Doran
94fdc2beee fix(react/dialogs): formatting toolbar shown in code notes in quick edit 2025-08-27 18:12:39 +03:00
Elian Doran
dd4a01d9f8 fix(react/dialogs): jump to note sometimes showing empty list 2025-08-27 17:59:37 +03:00
Elian Doran
a2a6c67350 fix(react): alignment and size of search/bulk action buttons 2025-08-27 17:53:27 +03:00
Elian Doran
2152ca7ba6 fix(react): search crashing due to bad rendering mechanism 2025-08-27 17:46:20 +03:00
Elian Doran
40e4d236f4 fix(react): owned attributes not showing up the first time 2025-08-27 17:42:38 +03:00
Elian Doran
0450cd080d fix(react): note context sometimes not working on mobile 2025-08-27 17:37:28 +03:00
Elian Doran
1eaac79d63 fix(react/ribbon): note context menu button looking off 2025-08-27 16:58:01 +03:00
Elian Doran
19c0305ed9 fix(react/revisions): revision list overflowing when too many 2025-08-27 16:41:42 +03:00
Elian Doran
f0d14a966a fix(react/revisions): wrong selection when navigating between notes 2025-08-27 16:39:48 +03:00
Elian Doran
37e6ccdc1a fix(react/revisions): selection not possible due to new hierarchy 2025-08-27 16:37:07 +03:00
Elian Doran
06cea99b40 fix(react): note title not selecting text 2025-08-27 16:28:07 +03:00
Elian Doran
1851336862 fix(react/ribbon): solve some type errors 2025-08-27 16:17:19 +03:00
Elian Doran
461eb273d9 fix(react/ribbon): attribute editor sometimes not clearing between notes 2025-08-27 15:53:27 +03:00
Elian Doran
470edc4d70 fix(react/ribbon): attribute editor saving unnecessarily 2025-08-27 15:35:44 +03:00
Elian Doran
26132a2a56 fix(react/ribbon): crash due to misuse of component rendering 2025-08-27 15:19:31 +03:00
Elian Doran
d92bd16042 chore(react/ribbon): react to note type changes 2025-08-27 14:56:18 +03:00
Elian Doran
1c7dfa6c91 chore(react/ribbon): fix activation of add new label to all tabs 2025-08-27 13:19:52 +03:00
Elian Doran
3a3fed4314 chore(react/ribbon): fix 3px height of the ribbon when collapsed 2025-08-27 13:13:02 +03:00
Elian Doran
82bdb76d75 chore(react/ribbon): simplify useNoteContext & handle setNoteContext 2025-08-27 13:06:57 +03:00
Elian Doran
066f3ea078 chore(react/ribbon): react to add new label/relation even when not shown 2025-08-27 13:05:51 +03:00
Elian Doran
9d760a21d5 chore(react/ribbon): disable when view mode is not good 2025-08-27 12:20:11 +03:00
Elian Doran
976c795ac6 chore(react/ribbon): add tooltip with keyboard shortcut 2025-08-27 12:16:40 +03:00
Elian Doran
ed320e4e24 chore(client): fix type error due to React integration 2025-08-27 11:59:07 +03:00
Newcomer1989
3111738700 Translated using Weblate (German)
Currently translated at 100.0% (378 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/de/
2025-08-27 10:28:44 +02:00
rodrigomescua
1fa0bada23 Translated using Weblate (Portuguese (Brazil))
Currently translated at 62.5% (978 of 1564 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pt_BR/
2025-08-27 10:28:44 +02:00
Newcomer1989
11eca7e58b Translated using Weblate (German)
Currently translated at 90.3% (1413 of 1564 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-08-27 10:28:44 +02:00
toaik
4b50e2f14d Translated using Weblate (German)
Currently translated at 90.3% (1413 of 1564 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-08-27 10:28:43 +02:00
Newcomer1989
63faba9603 Translated using Weblate (German)
Currently translated at 90.3% (1413 of 1564 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-08-27 10:28:43 +02:00
Elian Doran
3e213699e0 chore(client): fix type error due to React integration 2025-08-27 11:27:49 +03:00
Elian Doran
c88ff07691 chore(deps): update dependency typedoc to v0.28.11 (#6792) 2025-08-27 11:25:52 +03:00
Elian Doran
b53aa5cf6e chore(deps): update svelte monorepo (#6793) 2025-08-27 11:25:44 +03:00
Elian Doran
2641b9b3fe fix(deps): update dependency bootstrap to v5.3.8 (#6794) 2025-08-27 11:25:35 +03:00
Elian Doran
3a2a73992c chore(deps): update dependency @types/node to v22.18.0 (#6795) 2025-08-27 11:24:39 +03:00
Elian Doran
b82b17a701 chore(deps): update typescript-eslint monorepo to v8.41.0 (#6796) 2025-08-27 11:24:27 +03:00
renovate[bot]
a6202edcd1 chore(deps): update typescript-eslint monorepo to v8.41.0 2025-08-27 02:40:21 +00:00
renovate[bot]
6eac0cb75d chore(deps): update dependency @types/node to v22.18.0 2025-08-27 02:38:43 +00:00
renovate[bot]
83672d6138 fix(deps): update dependency bootstrap to v5.3.8 2025-08-27 02:38:15 +00:00
renovate[bot]
51dadf72d0 chore(deps): update svelte monorepo 2025-08-27 02:37:45 +00:00
renovate[bot]
0cbf61acb3 chore(deps): update dependency typedoc to v0.28.11 2025-08-27 02:37:12 +00:00
Elian Doran
399c7435ac Merge remote-tracking branch 'origin/main' into react/note_context_aware 2025-08-26 23:49:00 +03:00
Elian Doran
d51fae7878 fix(mobile): file properties not displayed 2025-08-26 23:23:45 +03:00
Elian Doran
9750e25ad5 fix(mobile): note title not working 2025-08-26 22:21:42 +03:00
Elian Doran
2f9b2f0e8f refactor(react): rename formatting toolbar for clarity 2025-08-26 21:57:28 +03:00
Elian Doran
8deaf22544 fix(quick_edit): classic toolbar not shown 2025-08-26 21:45:22 +03:00
Elian Doran
b192f43187 chore(release): prepare for 0.98.1 2025-08-26 20:35:41 +03:00
Elian Doran
8cb8d1303c docs(release): v0.98.1 2025-08-26 20:34:36 +03:00
Elian Doran
5237348975 chore(docs): fix quick search documentation not in meta 2025-08-26 19:44:01 +03:00
Elian Doran
72e2f6757e fix(client): autocomplete looking off in new tab 2025-08-26 19:15:36 +03:00
Elian Doran
cf059e7f86 Translations update from Hosted Weblate (#6787) 2025-08-26 15:36:21 +03:00
Elian Doran
44d69216b6 Translated using Weblate (Romanian)
Currently translated at 100.0% (1564 of 1564 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ro/
2025-08-26 14:35:50 +02:00
Elian Doran
c38bf09af0 chore(client): fix a table nesting issue 2025-08-26 11:53:58 +03:00
Elian Doran
9373d47e86 fix: log same error message on api 401 as on login error to allow fail2ban blocking (#6782) 2025-08-26 08:53:55 +03:00
hulmgulm
29350628c3 Merge branch 'main' into main 2025-08-26 06:26:41 +02:00
Elian Doran
83d1a68879 fix(i18n): pt_BR still not working 2025-08-25 23:32:20 +03:00
hulmgulm
f188408099 Merge branch 'main' into main 2025-08-25 21:22:07 +02:00
Elian Doran
449ab3a798 fix(client/about): directory not displayed on desktop 2025-08-25 22:19:17 +03:00
hulmgulm
21504d1417 Logout same error message on api 401 as on login error 2025-08-25 21:18:01 +02:00
Elian Doran
3060b496e3 chore(client): remove redundant log 2025-08-25 22:09:29 +03:00
Elian Doran
bd35539fa1 fix(i18n): electron locale for pt_BR 2025-08-25 21:34:59 +03:00
Elian Doran
df6447e3ad feat(quick_search): also allow for the equals operator in note title's quick search (#6769) 2025-08-25 20:49:45 +03:00
Elian Doran
24fd898f0d fix(add_link): inserting link to selection not working properly (closes #6776) 2025-08-25 20:48:15 +03:00
Elian Doran
1aa6238288 chore(deps): update dependency @types/jquery to v3.5.33 (#6748) 2025-08-25 20:22:33 +03:00
Elian Doran
c16c4788da fix(client): type error 2025-08-25 20:18:51 +03:00
Elian Doran
0c35daab85 Merge remote-tracking branch 'origin/main' into renovate/jquery-3.x 2025-08-25 20:01:59 +03:00
Elian Doran
4a19639e92 fix(deps): update dependency tsx to v4.20.5 (#6775) 2025-08-25 20:00:55 +03:00
renovate[bot]
36cceea677 fix(deps): update dependency tsx to v4.20.5 2025-08-25 16:33:16 +00:00
Elian Doran
4dbc76790a Merge remote-tracking branch 'origin/main' into react/note_context_aware 2025-08-25 19:33:14 +03:00
Elian Doran
b32a344a21 chore(deps): update dependency tsx to v4.20.5 (#6772) 2025-08-25 19:31:04 +03:00
Elian Doran
3896ab822f Translations update from Hosted Weblate (#6778) 2025-08-25 19:30:49 +03:00
OKiU Network
cfa4ba57d4 Translated using Weblate (Dutch)
Currently translated at 1.8% (7 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/nl/
2025-08-25 18:29:51 +02:00
OKiU Network
da051e0269 Translated using Weblate (Dutch)
Currently translated at 0.3% (5 of 1564 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/nl/
2025-08-25 18:29:50 +02:00
Cédric MARCOUX
3eda77a91f Translated using Weblate (French)
Currently translated at 88.3% (334 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/fr/
2025-08-25 18:29:49 +02:00
OKiU Network
5c2f4be5dd Added translation using Weblate (Dutch) 2025-08-25 18:29:49 +02:00
OKiU Network
435b501db9 Added translation using Weblate (Dutch) 2025-08-25 18:29:48 +02:00
Newcomer1989
5a27ffef5f Translated using Weblate (German)
Currently translated at 100.0% (378 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/de/
2025-08-25 18:29:47 +02:00
Luis Rebhan
02256d9a45 Translated using Weblate (German)
Currently translated at 82.9% (1297 of 1564 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-08-25 18:29:47 +02:00
Newcomer1989
7e069009d6 Translated using Weblate (German)
Currently translated at 82.9% (1297 of 1564 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-08-25 18:29:46 +02:00
Elian Doran
3c25cda4c0 feat(docs): also improve how environment variables are shown in docs (#6727) 2025-08-25 19:29:40 +03:00
Elian Doran
70d7ad0b1a fix(jump_to): fix issue where attributes/tags don't show in results (#6752) 2025-08-25 19:26:48 +03:00
Elian Doran
e793b2f661 feat(config): fix previously documented env var formula not working (#6726) 2025-08-25 19:23:35 +03:00
Elian Doran
917ea3e401 feat(react): set up ESLint 2025-08-25 18:42:07 +03:00
Elian Doran
5a54dd666f refactor(react): fix a few more rules of hooks violations 2025-08-25 18:41:48 +03:00
Elian Doran
733ec2c145 refactor(react): fix a few rules of hooks violations 2025-08-25 18:00:10 +03:00
Elian Doran
e386b03b90 refactor(react): fix all eslint issues in .tsx files 2025-08-25 17:20:47 +03:00
Elian Doran
25d5d51085 chore(react): fix note path when empty 2025-08-25 16:15:13 +03:00
Elian Doran
50c4301a34 chore(react): fix height of title bar 2025-08-25 16:05:09 +03:00
Elian Doran
0f60c0696b chore(react): fix leak in content widget 2025-08-25 15:53:21 +03:00
Elian Doran
3ec2947c4f chore(react): fix configure languages open in background 2025-08-25 14:48:13 +03:00
Elian Doran
e89162838e chore(react): fix events not updating properly 2025-08-25 14:48:00 +03:00
Elian Doran
72181090a5 refactor(react): get rid of ReactBasicWidget 2025-08-25 14:36:17 +03:00
Elian Doran
72b2a5cc0d chore(react): use effects for event handlers to prevent leaks 2025-08-25 14:27:32 +03:00
Elian Doran
1eaeec8100 Revert "chore(react): prototype for note context"
This reverts commit 660db3b3ab.
2025-08-25 13:51:43 +03:00
Elian Doran
660db3b3ab chore(react): prototype for note context 2025-08-25 11:48:56 +03:00
Elian Doran
89d2fcb81e refactor(react): add debug information for devtools 2025-08-25 11:01:12 +03:00
Elian Doran
ccda623840 refactor(react/ribbon): remove unnecessary hook 2025-08-25 10:32:11 +03:00
renovate[bot]
a6e7dff61e chore(deps): update dependency tsx to v4.20.5 2025-08-25 06:59:19 +00:00
Elian Doran
86d1bbe8ff chore(deps): update dependency webdriverio to v9.19.2 (#6773) 2025-08-25 09:54:52 +03:00
Elian Doran
a10cb06f14 fix(deps): update dependency i18next to v25.4.2 (#6774) 2025-08-25 09:54:41 +03:00
renovate[bot]
dd9a62818b fix(deps): update dependency i18next to v25.4.2 2025-08-25 00:34:50 +00:00
renovate[bot]
c0e936675c chore(deps): update dependency webdriverio to v9.19.2 2025-08-25 00:34:18 +00:00
Jon Fuller
b0b788b7dc Merge branch 'main' into fix/quick-search-equals-operator 2025-08-24 14:47:31 -07:00
Jon Fuller
18f0f3ecac Fix for casing and formatting in i18n.ts which was causing compile errors (#6770) 2025-08-24 14:47:18 -07:00
Sky Swimmer
e7d745ac94 Update calendar_view.ts
Same as the previous, another casing error
2025-08-24 23:22:54 +02:00
Sky Swimmer
24abf7f0ed Update i18n.ts
Another casing error throwing off tests
2025-08-24 23:22:24 +02:00
Elian Doran
36fb097d1d chore(react/ribbon): add CSS for context menu 2025-08-25 00:21:44 +03:00
Elian Doran
35ef5fd0d3 chore(react/ribbon): add disable rules for context menu 2025-08-25 00:19:12 +03:00
Sky Swimmer
9a08f6534b Fix casing and formatting in i18n.ts which was causing compile errors 2025-08-24 23:14:45 +02:00
Elian Doran
885dd2053b chore(react/ribbon): add rest of the note action items 2025-08-25 00:08:40 +03:00
Elian Doran
6f6f280bdd chore(react/ribbon): add part of the note actions menu 2025-08-24 23:56:05 +03:00
Elian Doran
a3e8fd374f chore(react/ribbon): port convert to attachment 2025-08-24 23:21:28 +03:00
Elian Doran
f91c1f4180 chore(react/ribbon): port revisions button 2025-08-24 22:56:47 +03:00
Elian Doran
d85746c1b9 Revert "refactor(react/ribbon): use effects for event handling"
This reverts commit 5a17075eef.
2025-08-24 22:43:20 +03:00
Elian Doran
5a17075eef refactor(react/ribbon): use effects for event handling 2025-08-24 22:21:11 +03:00
Elian Doran
6cab47fb55 feat(react/ribbon): bring back toggling tabs via keyboard shortcut 2025-08-24 22:14:42 +03:00
perf3ct
93c5413790 feat(quick_search): also allow for the equals operator in note title's quick search 2025-08-24 18:53:05 +00:00
Elian Doran
f2db7baeba refactor(react): use beta approach for handling events everywhere 2025-08-24 21:18:48 +03:00
Elian Doran
a507991808 refactor(react/modals): use classless components 2025-08-24 20:57:23 +03:00
Elian Doran
7c86f90ac6 chore(react/ribbon): fix some more crashes when rapidly switching tabs 2025-08-24 20:31:39 +03:00
Elian Doran
1e9b772692 chore(react/ribbon): fix cannot set style when switching attributes 2025-08-24 20:25:11 +03:00
Elian Doran
096ab52216 refactor(react/ribbon): solve type errors 2025-08-24 20:23:00 +03:00
Elian Doran
88c3cd5cdd refactor(react/ribbon): move files around & remove imports 2025-08-24 20:16:58 +03:00
Elian Doran
99a911a220 chore(react/ribbon): port bulk actions for search 2025-08-24 20:12:22 +03:00
Elian Doran
3218ab971b chore(react/ribbon): fix alignment of help/close buttons 2025-08-24 19:03:19 +03:00
Elian Doran
274e3c1f7f refactor(react/ribbon): split into two files 2025-08-24 18:40:05 +03:00
Elian Doran
f8916a6e35 chore(react/ribbon): port limit 2025-08-24 18:34:29 +03:00
Elian Doran
73f20d01e4 chore(react/ribbon): port order by 2025-08-24 18:29:47 +03:00
Elian Doran
2fd3a875b6 chore(react/ribbon): port include archived notes 2025-08-24 18:11:29 +03:00
Elian Doran
68cba8d3b2 chore(react/ribbon): port debug 2025-08-24 18:09:33 +03:00
Elian Doran
6b28fd405e chore(react/ribbon): port fast search 2025-08-24 18:07:16 +03:00
Elian Doran
3bccbabe53 chore(react/ribbon): port ancestor depth 2025-08-24 18:02:18 +03:00
Elian Doran
c97c66ed8a Translations update from Hosted Weblate (#6767) 2025-08-24 17:30:55 +03:00
Elian Doran
4b212232c8 chore(react/ribbon): port ancestor (without depth) 2025-08-24 17:29:48 +03:00
Elian Doran
ac3a8edf2b chore(react/ribbon): add search script 2025-08-24 17:20:40 +03:00
Sleepy0Duck5
b581025bbe Translated using Weblate (Korean)
Currently translated at 10.0% (38 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ko/
2025-08-24 16:02:09 +02:00
Sleepy0Duck5
7bc5331747 Translated using Weblate (Korean)
Currently translated at 0.9% (15 of 1564 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ko/
2025-08-24 16:02:07 +02:00
Kuzma Simonov
2415976475 Translated using Weblate (Russian)
Currently translated at 100.0% (1564 of 1564 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-08-24 16:02:06 +02:00
Francis C
8d0d0f0449 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (378 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/zh_Hant/
2025-08-24 16:02:02 +02:00
Francis C
16b00ed160 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1564 of 1564 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-08-24 16:02:01 +02:00
chdagenais
df73a420f9 Translated using Weblate (French)
Currently translated at 83.5% (316 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/fr/
2025-08-24 16:01:59 +02:00
Newcomer1989
1e4d57f275 Translated using Weblate (German)
Currently translated at 92.8% (351 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/de/
2025-08-24 16:01:56 +02:00
chdagenais
19a238c8d3 Translated using Weblate (French)
Currently translated at 82.2% (1287 of 1564 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/fr/
2025-08-24 16:01:54 +02:00
Francis C
5ffd8a79eb Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1564 of 1564 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-08-24 16:01:53 +02:00
Elian Doran
04fbc82d7c chore(react/ribbon): save search to note 2025-08-24 16:58:10 +03:00
Elian Doran
3f105f7b8b chore(react/ribbon): focus on search textbox 2025-08-24 16:45:17 +03:00
Elian Doran
b9193a5562 chore(react/ribbon): handle search error 2025-08-24 16:41:44 +03:00
Elian Doran
e1fa188244 chore(react/ribbon): refresh options 2025-08-24 16:17:10 +03:00
Elian Doran
80ad87671a chore(react/ribbon): search & execute button 2025-08-24 16:02:15 +03:00
Elian Doran
b6d5a6ec2e chore(react/ribbon): dynamic rendering of search options 2025-08-24 15:59:22 +03:00
Elian Doran
759398d804 chore(react/ribbon): working execute search button 2025-08-24 15:48:53 +03:00
Elian Doran
c1b30db3d1 chore(react/ribbon): port search string 2025-08-24 15:29:07 +03:00
Elian Doran
0c8bfc39ef refactor(react/ribbon): bring back tab activation 2025-08-24 12:23:25 +03:00
Elian Doran
3815fddb27 Merge branch 'react/note_context_aware' of https://github.com/TriliumNext/trilium into react/note_context_aware 2025-08-24 12:22:16 +03:00
Elian Doran
b585a64a38 Merge remote-tracking branch 'origin/main' into react/note_context_aware 2025-08-24 12:05:05 +03:00
Elian Doran
58e58c192f Merge branch 'main' of https://github.com/TriliumNext/trilium 2025-08-24 11:58:56 +03:00
Elian Doran
5939344378 fix(deps): update dependency i18next to v25.4.1 (#6754) 2025-08-24 11:49:48 +03:00
Elian Doran
ad85ee3531 feat(react/ribbon): start porting search definitions (buttons) 2025-08-24 11:42:25 +03:00
renovate[bot]
349f19fef7 fix(deps): update dependency i18next to v25.4.1 2025-08-24 08:18:50 +00:00
Elian Doran
d5777a024e chore(deps): update svelte monorepo (#6753) 2025-08-24 11:17:52 +03:00
Elian Doran
b7f4ee6171 fix(deps): update dependency react-i18next to v15.7.2 (#6755) 2025-08-24 11:17:05 +03:00
Elian Doran
a83c4e3970 fix(deps): update dependency eslint-linter-browserify to v9.34.0 (#6756) 2025-08-24 11:16:53 +03:00
Elian Doran
5a767dae34 feat(i18n): add support for Brazilian Portuguese 2025-08-24 11:05:52 +03:00
Elian Doran
9f93d30b99 feat(i18n): add support for Ukrainian 2025-08-24 10:53:21 +03:00
Elian Doran
dff525edc6 Translations update from Hosted Weblate (#6743) 2025-08-24 10:52:42 +03:00
renovate[bot]
26da431320 fix(deps): update dependency react-i18next to v15.7.2 2025-08-24 07:32:43 +00:00
renovate[bot]
cde4622693 fix(deps): update dependency eslint-linter-browserify to v9.34.0 2025-08-24 07:30:44 +00:00
renovate[bot]
5ede7ecc69 chore(deps): update svelte monorepo 2025-08-24 01:36:13 +00:00
Elian Doran
b607d1e628 refactor(react/ribbon): shared component for labelled entry 2025-08-23 23:59:41 +03:00
Elian Doran
d7e36bdf93 feat(react/ribbon): reintroduce combobox collection properties 2025-08-23 23:54:14 +03:00
Elian Doran
2b8b185b5b feat(react/ribbon): reintroduce number collection properties 2025-08-23 23:39:47 +03:00
Elian Doran
927ebcbec9 feat(react/ribbon): reintroduce checkbox collection properties 2025-08-23 23:32:12 +03:00
Elian Doran
ea1397de63 feat(react/ribbon): reintroduce button collection properties 2025-08-23 23:25:25 +03:00
Elian Doran
ce1f5c6204 feat(react/ribbon): port view type 2025-08-23 22:49:32 +03:00
Elian Doran
652114c7b5 feat(react/ribbon): finalize port of inherited attributes tab 2025-08-23 22:18:04 +03:00
Elian Doran
17cd2128fd chore(react): add editorconfig for .tsx 2025-08-23 22:02:41 +03:00
Elian Doran
bc4378cb3e chore(react/ribbon): port inherited attributes partially 2025-08-23 22:02:33 +03:00
perf3ct
513878dfef feat(jump_to): got the styling to look exactly how we were hoping for 2025-08-23 18:58:18 +00:00
perf3ct
753d5529b2 feat(jump_to): get the styling very close to what we want it to look like... 2025-08-23 18:40:11 +00:00
Elian Doran
9f217b88e4 refactor(react/ribbon): set up keyboard shortcuts 2025-08-23 20:59:21 +03:00
Elian Doran
d53faa8c01 refactor(react/ribbon): imperative api for saving, reloading, updating attributes 2025-08-23 20:49:54 +03:00
Elian Doran
a934760960 refactor(react/ribbon): use custom method for injecting handlers 2025-08-23 20:44:03 +03:00
Elian Doran
82914fc2aa chore(react/ribbon): unable to create notes in attribute editor 2025-08-23 20:35:19 +03:00
Elian Doran
db687197de chore(react/ribbon): add focus to attribute editor 2025-08-23 20:31:00 +03:00
Elian Doran
efd713dc61 chore(react/ribbon): add blur & keydown events 2025-08-23 19:54:02 +03:00
Elian Doran
3f3c7cfe88 chore(react/ribbon): add menu 2025-08-23 19:48:01 +03:00
Elian Doran
73ca285b7a chore(react/ribbon): support reference links in attributes 2025-08-23 19:26:23 +03:00
Elian Doran
168d25c020 chore(react/ribbon): fix save icon displayed when it shouldn't 2025-08-23 19:13:48 +03:00
Elian Doran
e8ae5486c8 chore(react/ribbon): display attribute errors 2025-08-23 18:28:42 +03:00
Elian Doran
f049b8b915 chore(react/ribbon): save attribute changes 2025-08-23 18:23:38 +03:00
Микола Копитін
4e755dc537 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (1560 of 1560 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/uk/
2025-08-23 14:16:31 +02:00
Francis C
5351310a38 Translated using Weblate (Japanese)
Currently translated at 67.9% (1060 of 1560 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-08-23 14:16:31 +02:00
Микола Копитін
211ca43a82 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (378 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/uk/
2025-08-23 14:16:31 +02:00
Микола Копитін
e5235e7f22 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (1560 of 1560 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/uk/
2025-08-23 14:16:31 +02:00
Astryd Park
e72298f0b4 Translated using Weblate (Korean)
Currently translated at 0.2% (1 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ko/
2025-08-23 14:16:31 +02:00
Микола Копитін
3abf5c65c6 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (378 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/uk/
2025-08-23 14:16:31 +02:00
Микола Копитін
268acb0b88 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (1560 of 1560 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/uk/
2025-08-23 14:16:30 +02:00
Kuzma Simonov
196b3b873f Translated using Weblate (Russian)
Currently translated at 100.0% (378 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ru/
2025-08-23 14:16:30 +02:00
Микола Копитін
4d9801a372 Translated using Weblate (Russian)
Currently translated at 100.0% (1560 of 1560 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-08-23 14:16:30 +02:00
Kuzma Simonov
bd710ba665 Translated using Weblate (Russian)
Currently translated at 100.0% (1560 of 1560 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-08-23 14:16:30 +02:00
Francis C
afe369c876 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1560 of 1560 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-08-23 14:16:30 +02:00
Newcomer1989
206007bbce Translated using Weblate (German)
Currently translated at 81.7% (309 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/de/
2025-08-23 14:16:30 +02:00
rodrigomescua
8ad05b92c0 Translated using Weblate (Portuguese (Brazil))
Currently translated at 60.8% (950 of 1560 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pt_BR/
2025-08-23 14:16:30 +02:00
Francis C
735da2a855 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1560 of 1560 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-08-23 14:16:30 +02:00
Elian Doran
980077f559 Add UI performance-related settings (#6747) 2025-08-23 15:16:22 +03:00
Elian Doran
12053e75bb chore(react/ribbon): fix size of attribute widget 2025-08-23 13:13:01 +03:00
Elian Doran
62372ed4c5 chore(react/ribbon): add logic for displaying attribute detail 2025-08-23 12:55:48 +03:00
Elian Doran
e5caf37697 chore(react/ribbon): load current attributes in editor 2025-08-23 12:39:49 +03:00
Elian Doran
befc5a9530 feat(react/ribbon): display help tooltip in attribute editor 2025-08-23 12:31:54 +03:00
Elian Doran
1e00407864 chore(react/ribbon): use separate component for editor 2025-08-23 12:05:03 +03:00
Elian Doran
73038efccf chore(react/ribbon): add some CKEditor events 2025-08-23 11:52:40 +03:00
Elian Doran
6d37e19b40 chore(react/ribbon): start implementing attribute editor 2025-08-23 11:44:51 +03:00
Elian Doran
2c33ef2b0d chore(react/ribbon): similar notes style 2025-08-23 11:28:10 +03:00
Elian Doran
6c30e0836f chore(react/ribbon): also react to width, not just height 2025-08-23 11:21:05 +03:00
Elian Doran
5f77ca31bd chore(react/ribbon): react note map to height changes 2025-08-23 11:12:14 +03:00
Elian Doran
f7c82d6b09 chore(react/ribbon): watch note map size 2025-08-23 11:00:25 +03:00
Elian Doran
86dd9aa42a chore(react/ribbon): integrate expand/collapse button 2025-08-23 10:47:46 +03:00
Elian Doran
5daca270e4 fix(deps): update dependency mermaid to v11.10.1 (#6749) 2025-08-23 08:47:35 +03:00
Elian Doran
e18813a4bf fix(deps): update eslint monorepo to v9.34.0 (#6750) 2025-08-23 08:47:16 +03:00
renovate[bot]
4aa7e211f3 fix(deps): update eslint monorepo to v9.34.0 2025-08-23 00:25:46 +00:00
renovate[bot]
419dc7edfb fix(deps): update dependency mermaid to v11.10.1 2025-08-23 00:24:33 +00:00
renovate[bot]
eaa84a6b39 chore(deps): update dependency @types/jquery to v3.5.33 2025-08-23 00:23:57 +00:00
Adorian Doran
1d0503d0e4 client/settings/ui-performance-settings: remove form groups 2025-08-23 03:22:59 +03:00
Adorian Doran
f7f98aa9a3 client/settings/ui-performance-settings: improve code formatting 2025-08-23 03:10:51 +03:00
Adorian Doran
575d14261a Merge branch 'main' of https://github.com/TriliumNext/Trilium into client/settings/ui-performance-settings 2025-08-23 02:20:37 +03:00
Adorian Doran
9aab606deb style: improve the support of disabled backdrop effects 2025-08-23 02:15:06 +03:00
Adorian Doran
2e11681b52 client/settings/disable backdrop effects: add the CSS implementation 2025-08-23 01:26:21 +03:00
Adorian Doran
8cca6637f7 client/settings/disable backdrop effects: react to the option change 2025-08-23 01:23:20 +03:00
Adorian Doran
82e076378c client/settings/disable backdrop effects: add the corresponding checkbox in the Appearance settings page 2025-08-23 01:20:54 +03:00
Adorian Doran
94ddad3c49 client/settings/disable backdrop effects: add an option to enable or disable backdrop effects 2025-08-23 01:15:00 +03:00
Adorian Doran
d35dbca18b client/settings/disable shadows: add the CSS implementation 2025-08-23 00:58:50 +03:00
Adorian Doran
7468d6147a client/settings/disable shadows: react to the option change 2025-08-23 00:55:46 +03:00
Adorian Doran
7c78d749de client/settings/disable shadows: add the corresponding checkbox in the Appearance settings page 2025-08-23 00:49:35 +03:00
Adorian Doran
85dd99a3c4 client/settings/disable shadows: add an option to enable or disable shadows 2025-08-23 00:43:49 +03:00
Adorian Doran
0a9c0234e2 client/settings/disable motion: update translation 2025-08-23 00:38:06 +03:00
JYC333
fad77ba5a0 chore(deps): update dependency vite-plugin-static-copy to v3.1.2 [security] (#6735) 2025-08-22 23:30:13 +02:00
JYC333
12723f3216 fix(deps): update dependency react-i18next to v15.7.1 (#6739) 2025-08-22 23:29:38 +02:00
JYC333
a43140515f chore(deps): update ckeditor5 config packages to v12.1.1 (#6738) 2025-08-22 23:29:26 +02:00
Adorian Doran
3e3cc8c541 client/settings/disable motion: refactor 2025-08-23 00:19:26 +03:00
Elian Doran
a85141ace2 feat(react/ribbon): port note map partially 2025-08-22 23:47:02 +03:00
Elian Doran
c33280bbb2 chore(react): fix leak & adjustable class name 2025-08-22 23:45:31 +03:00
Elian Doran
df3aa04787 chore(react): proper legacy widget injection & event handling 2025-08-22 23:33:02 +03:00
Elian Doran
4bd25a0d4a chore(react): use different injection mechanism 2025-08-22 23:24:00 +03:00
Elian Doran
7fadf4c6e1 chore(react): prototype hook to render legacy widgets 2025-08-22 23:12:14 +03:00
Adorian Doran
d1538508e8 client/settings/disable motion: turn off jQuery animations if motion is disabled 2025-08-22 22:20:57 +03:00
Elian Doran
b24d786933 chore(react/ribbon): fix a few type errors 2025-08-22 21:58:35 +03:00
Elian Doran
8f69b87dd1 feat(react/ribbon): port note paths tab 2025-08-22 21:45:03 +03:00
Adorian Doran
9b1da8c311 Settings/Appearance: improve CSS selector specificity 2025-08-22 21:37:56 +03:00
Elian Doran
8287063aab feat(react/ribbon): port image properties 2025-08-22 21:09:51 +03:00
Adorian Doran
e4a8258acf client/settings/disable motion: fix submenus not opening 2025-08-22 20:52:31 +03:00
Adorian Doran
5e88043c7b client/settings/disable motion: add the CSS implementation 2025-08-22 20:48:26 +03:00
Adorian Doran
bedf9112fb client/settings/disable motion: add localization support 2025-08-22 20:42:17 +03:00
Adorian Doran
03681d23c5 client/settings/disable motion: add an option to allow transitions and animations to be disabled 2025-08-22 20:32:08 +03:00
Elian Doran
21683db0b8 refactor(react/ribbon): dedicated component for file upload 2025-08-22 20:25:15 +03:00
Elian Doran
978d829150 feat(react/ribbon): port file notes 2025-08-22 20:17:00 +03:00
Elian Doran
cc05572a35 feat(react/ribbon): port similar notes 2025-08-22 19:27:58 +03:00
Elian Doran
c5bb310613 chore(react/ribbon): bring back note info auto-refresh 2025-08-22 19:07:04 +03:00
Elian Doran
77551b1fed feat(react/ribbon): port note info tab 2025-08-22 18:23:54 +03:00
Elian Doran
70728c274e feat(react/ribbon): port note properties 2025-08-22 17:41:45 +03:00
Elian Doran
cee4714665 feat(react/ribbon): port edited notes 2025-08-22 17:31:15 +03:00
Elian Doran
c3eca3b626 feat(react/ribbon): port script tab 2025-08-22 16:58:44 +03:00
Elian Doran
01e4cd2e78 chore(react/ribbon): set up formatting toolbar 2025-08-22 16:34:16 +03:00
Elian Doran
b99d01ad7b chore(react/ribbon): bring back tab filtering 2025-08-22 16:07:30 +03:00
Elian Doran
bf0213907e chore(react/ribbon): finalize language switcher 2025-08-22 15:40:36 +03:00
Elian Doran
eff5b6459d chore(react/ribbon): fix event 2025-08-22 15:11:12 +03:00
Elian Doran
8e29b5eed6 feat(react/ribbon): port note language 2025-08-22 12:34:21 +03:00
Elian Doran
c91748da15 feat(react/ribbon): port template switch 2025-08-22 12:15:03 +03:00
Elian Doran
f04f9dc262 feat(react/ribbon): port shared switch 2025-08-22 11:57:45 +03:00
Elian Doran
e873cdab7e chore(react/ribbon): fix width of editability select 2025-08-22 11:42:07 +03:00
Elian Doran
f9b6fd6ac5 feat(react): port bookmark switch 2025-08-22 11:40:27 +03:00
renovate[bot]
aa191e110c fix(deps): update dependency react-i18next to v15.7.1 2025-08-22 02:44:08 +00:00
renovate[bot]
dd09907925 chore(deps): update ckeditor5 config packages to v12.1.1 2025-08-22 02:43:31 +00:00
Elian Doran
da4810672d feat(react/ribbon): improve editability select 2025-08-21 22:24:35 +03:00
Elian Doran
f772f59d7c feat(react/ribbon): port editability select 2025-08-21 22:19:26 +03:00
Elian Doran
1964fb90d5 feat(react/ribbon): port toggle protected note 2025-08-21 21:26:45 +03:00
Elian Doran
5945f2860a chore(react/ribbon): finalize note type selection 2025-08-21 21:01:57 +03:00
Elian Doran
f45da049b9 chore(react/ribbon): change note type 2025-08-21 20:56:37 +03:00
Elian Doran
c0beab8a5d chore(react/ribbon): display current note type 2025-08-21 20:38:19 +03:00
Elian Doran
cabeb13adb chore(react/ribbon): add note types 2025-08-21 20:30:12 +03:00
Elian Doran
e2e9721d5f chore(react/ribbon): add basic note types & badges 2025-08-21 20:16:06 +03:00
Elian Doran
4e9deab605 chore(react/ribbon): make content work 2025-08-21 19:59:56 +03:00
Elian Doran
9bb048fb01 chore(react/ribbon): toggleable tabs 2025-08-21 19:48:07 +03:00
Elian Doran
6849f80506 chore(react/ribbon): make tabs activable 2025-08-21 19:35:21 +03:00
Elian Doran
5597f4e2e0 chore(react/ribbon): add all ribbon tab titles & icon 2025-08-21 19:27:18 +03:00
renovate[bot]
35e9508bde chore(deps): update dependency vite-plugin-static-copy to v3.1.2 [security] 2025-08-21 15:41:25 +00:00
Elian Doran
45fbcec805 feat(react/ribbon): port base structure 2025-08-21 18:29:13 +03:00
Elian Doran
4c8da70ef3 chore(deps): update dependency rollup-plugin-webpack-stats to v2.1.4 (#6721) 2025-08-21 17:49:28 +03:00
Elian Doran
ed5da5cd4a Translations update from Hosted Weblate (#6732) 2025-08-21 17:49:10 +03:00
Astryd Park
dc5fccdbcd Added translation using Weblate (Korean) 2025-08-21 16:32:31 +02:00
Astryd Park
91aea333c7 Added translation using Weblate (Korean) 2025-08-21 16:32:31 +02:00
Микола Копитін
a0de01cff1 Translated using Weblate (Ukrainian)
Currently translated at 99.4% (376 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/uk/
2025-08-21 16:32:30 +02:00
Микола Копитін
a41ed34193 Translated using Weblate (Ukrainian)
Currently translated at 37.0% (578 of 1560 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/uk/
2025-08-21 16:32:30 +02:00
Newcomer1989
49e8811c18 Translated using Weblate (German)
Currently translated at 77.7% (294 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/de/
2025-08-21 16:32:29 +02:00
Lucas Fernandes de Camargo
488563a82e Translated using Weblate (Portuguese (Brazil))
Currently translated at 22.5% (351 of 1560 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pt_BR/
2025-08-21 16:32:29 +02:00
Elian Doran
d76d50f30e chore(react): fix a type error 2025-08-21 17:16:03 +03:00
Elian Doran
4685aef88d chore(react/note_icon): reset to default icon 2025-08-21 16:19:18 +03:00
Elian Doran
a106510924 chore(react/note_icon): react to icon changes 2025-08-21 15:50:14 +03:00
Elian Doran
9d54503ef7 chore(react/note_icon): reintroduce setting the icon 2025-08-21 15:21:32 +03:00
Elian Doran
b1449eebf3 chore(react/note_icon): reintroduce read-only 2025-08-21 15:14:19 +03:00
Elian Doran
b213453062 refactor(react/note_icon): introduce autofocus at text box level 2025-08-21 15:11:08 +03:00
Elian Doran
076c0321cf chore(react/note_icon): focus search by default 2025-08-21 15:09:25 +03:00
Elian Doran
4d71b73f38 chore(react/note_icon): case insensitive search 2025-08-21 15:07:41 +03:00
Elian Doran
b20ffdf7db chore(react/note_icon): sort by count 2025-08-21 15:05:55 +03:00
Elian Doran
ef018e22d6 feat(react/note_icon): render dropdown only when needed 2025-08-21 15:03:54 +03:00
Elian Doran
3fa290a257 chore(react/note_icon): add back filter by category 2025-08-21 14:57:54 +03:00
Elian Doran
cdde530b60 chore(react/note_icon): add back filter by text 2025-08-21 14:45:19 +03:00
Elian Doran
aa608510d0 feat(react): port note icon 2025-08-21 14:41:59 +03:00
Elian Doran
009fd63ce9 chore(react): finalize note title porting 2025-08-21 13:18:39 +03:00
Elian Doran
bea352855a refactor(react): allow binding multiple events at once 2025-08-21 13:17:28 +03:00
Elian Doran
51e8a80ca3 chore(react/note_title): delete new notes on escape 2025-08-21 13:13:48 +03:00
Elian Doran
8a543d4513 chore(react/note_title): focus content on enter 2025-08-21 13:00:08 +03:00
Elian Doran
945e180a6f chore(react/note_title): add before unload listener 2025-08-21 12:55:33 +03:00
Elian Doran
b93fa332d3 fix(client): please wait for save showing up multiple times 2025-08-21 12:49:03 +03:00
Elian Doran
9e947f742d fix(react/note_title): title shown on empty widget pane 2025-08-21 12:15:12 +03:00
Elian Doran
033e90f8b7 fix(react/note_title): not refreshing on protected session 2025-08-21 12:13:30 +03:00
Elian Doran
be576176c5 feat(react/note_title): bring back navigation title 2025-08-21 11:08:33 +03:00
Elian Doran
4da3e8a4d8 refactor(react/note_title): use note property for title as well 2025-08-21 10:54:38 +03:00
Elian Doran
db2bf537ea refactor(react/note_title): use hook for listening to note property 2025-08-21 10:44:58 +03:00
Elian Doran
9a4fdcaef2 chore(react/note_title): bring back styles 2025-08-21 10:34:30 +03:00
Elian Doran
ca40360f7d feat(react): basic implementation of note title 2025-08-21 10:08:49 +03:00
Elian Doran
799e705ff8 fix(react): note context not always updated 2025-08-21 09:18:52 +03:00
Elian Doran
a1b18c7f97 chore(deps): update dependency @sveltejs/kit to v2.36.1 (#6723) 2025-08-21 08:22:09 +03:00
Elian Doran
9958a6e1bf fix(deps): update dependency i18next to v25.4.0 (#6724) 2025-08-21 08:21:24 +03:00
renovate[bot]
1fc6d8aca7 fix(deps): update dependency i18next to v25.4.0 2025-08-21 05:21:13 +00:00
Elian Doran
3e9ec2d943 chore(deps): update dependency @playwright/test to v1.55.0 (#6722) 2025-08-21 08:20:47 +03:00
Elian Doran
1420def1c3 fix(deps): update dependency react-i18next to v15.7.0 (#6725) 2025-08-21 08:19:38 +03:00
renovate[bot]
3b4184e765 chore(deps): update dependency @sveltejs/kit to v2.36.1 2025-08-21 02:22:23 +00:00
perf3ct
4ce9102f93 feat(docs): try to also improve how environment variables are shown in docs 2025-08-21 02:21:00 +00:00
perf3ct
eb27ec2234 feat(config): fix previously documented env var formula not working
asdf
2025-08-21 02:18:08 +00:00
renovate[bot]
b70e25d348 fix(deps): update dependency react-i18next to v15.7.0 2025-08-21 00:05:32 +00:00
renovate[bot]
772c0bbe1a chore(deps): update dependency @playwright/test to v1.55.0 2025-08-21 00:04:01 +00:00
renovate[bot]
144021c053 chore(deps): update dependency rollup-plugin-webpack-stats to v2.1.4 2025-08-21 00:03:29 +00:00
Elian Doran
59486cd55d feat(react): basic handling of note context aware 2025-08-20 23:53:13 +03:00
Elian Doran
afe3904ea3 feat(react): render raw react components 2025-08-20 22:13:52 +03:00
Elian Doran
8abd3ed3f1 feat(docs): implement swagger ui endpoint for internal api (#6719) 2025-08-20 21:36:21 +03:00
perf3ct
53ed510c92 feat(docs): remove old json api docs 2025-08-20 17:36:22 +00:00
Elian Doran
4ec46a2ebd chore(client): add some documentation 2025-08-20 20:34:00 +03:00
Elian Doran
db6f948499 Translations update from Hosted Weblate (#6720) 2025-08-20 20:33:26 +03:00
perf3ct
05c73011f5 feat(docs): add additional api routes 2025-08-20 17:30:26 +00:00
Микола Копитін
3b733d01f1 Translated using Weblate (Ukrainian)
Currently translated at 44.1% (167 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/uk/
2025-08-20 17:29:08 +00:00
Микола Копитін
ebf21296d4 Translated using Weblate (Ukrainian)
Currently translated at 11.8% (184 of 1551 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/uk/
2025-08-20 17:29:07 +00:00
Elian Doran
6f83ac4822 Port settings to React (#6660) 2025-08-20 20:28:54 +03:00
perf3ct
d358924324 feat(docs): implement swagger ui endpoint for internal api 2025-08-20 17:14:44 +00:00
perf3ct
f9a3606ca2 feat(docs): implement swagger ui endpoint for internal api 2025-08-20 17:11:54 +00:00
Elian Doran
33299ad51e chore(deps): update package lock 2025-08-20 19:45:49 +03:00
Elian Doran
8752182e7e Bump mermaid from 11.9.0 to 11.10.0 in /apps/client (#6717) 2025-08-20 19:22:44 +03:00
Elian Doran
0551ac8ead feat(ci): don't run checks outside main repo 2025-08-20 19:22:21 +03:00
Elian Doran
6d5a11bd4d Translations update from Hosted Weblate (#6718) 2025-08-20 19:14:25 +03:00
Elian Doran
ce19d84247 test(e2e): i18n test broken due to button 2025-08-20 19:10:41 +03:00
Микола Копитін
f24aa45a3b Translated using Weblate (Ukrainian)
Currently translated at 39.6% (150 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/uk/
2025-08-20 18:02:18 +02:00
Микола Копитін
64a28a7e75 Translated using Weblate (Ukrainian)
Currently translated at 10.8% (168 of 1551 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/uk/
2025-08-20 18:02:16 +02:00
Flowerlywind
249a755312 Translated using Weblate (Vietnamese)
Currently translated at 2.1% (34 of 1551 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/vi/
2025-08-20 18:02:13 +02:00
Kuzma Simonov
a3d51a013c Translated using Weblate (Russian)
Currently translated at 88.6% (335 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ru/
2025-08-20 18:02:12 +02:00
repilac
839def9959 Translated using Weblate (Japanese)
Currently translated at 97.6% (369 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/
2025-08-20 18:02:10 +02:00
Kuzma Simonov
fd432a7100 Translated using Weblate (Russian)
Currently translated at 81.9% (1271 of 1551 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-08-20 18:02:08 +02:00
repilac
60a07ce1e7 Translated using Weblate (Japanese)
Currently translated at 68.2% (1059 of 1551 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-08-20 18:02:07 +02:00
diego diaz
88c5700d87 Translated using Weblate (Spanish)
Currently translated at 100.0% (1551 of 1551 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/es/
2025-08-20 18:02:05 +02:00
Elian Doran
d59993abf6 fix(server): potential race condition when rotating logs 2025-08-20 19:00:41 +03:00
Elian Doran
0754011909 chore(react): fix type errors 2025-08-20 18:52:14 +03:00
Elian Doran
376bb66cab Merge remote-tracking branch 'origin/main' into react/settings
; Conflicts:
;	pnpm-lock.yaml
2025-08-20 18:32:57 +03:00
Elian Doran
588e15c633 fix(settings): not fitting properly on mobile 2025-08-20 18:17:52 +03:00
Elian Doran
93b8ad20d7 fix(react/settings): settings displayed inline 2025-08-20 18:17:42 +03:00
dependabot[bot]
e51b3d760d Bump mermaid from 11.9.0 to 11.10.0 in /apps/client
Bumps [mermaid](https://github.com/mermaid-js/mermaid) from 11.9.0 to 11.10.0.
- [Release notes](https://github.com/mermaid-js/mermaid/releases)
- [Commits](https://github.com/mermaid-js/mermaid/compare/mermaid@11.9.0...mermaid@11.10.0)

---
updated-dependencies:
- dependency-name: mermaid
  dependency-version: 11.10.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-20 14:44:27 +00:00
Elian Doran
91f3bc4488 chore(deps): update svelte monorepo (#6707) 2025-08-20 08:41:54 +03:00
Elian Doran
3e80a99bbf fix(deps): update dependency mermaid to v11.10.0 [security] (#6700) 2025-08-20 08:41:11 +03:00
renovate[bot]
37cdb55e79 chore(deps): update svelte monorepo 2025-08-20 05:37:42 +00:00
renovate[bot]
58b66c0c95 fix(deps): update dependency mermaid to v11.10.0 [security] 2025-08-20 05:36:02 +00:00
Elian Doran
e5f9db86a1 fix(deps): update ckeditor monorepo to v46.0.2 (#6704) 2025-08-20 08:32:25 +03:00
Elian Doran
f138f99356 chore(deps): update pnpm to v10.15.0 (#6706) 2025-08-20 08:31:17 +03:00
renovate[bot]
c42f4b9814 fix(deps): update ckeditor monorepo to v46.0.2 2025-08-20 05:31:11 +00:00
Elian Doran
0a9fb886e3 fix(deps): update dependency @mermaid-js/layout-elk to v0.1.9 (#6705) 2025-08-20 08:31:04 +03:00
Elian Doran
3c4577201f chore(deps): update dependency vite to v7.1.3 (#6703) 2025-08-20 08:30:16 +03:00
Elian Doran
816421188f chore(deps): update dependency electron to v37.3.1 (#6702) 2025-08-20 08:29:36 +03:00
renovate[bot]
5b15d2c4c6 chore(deps): update pnpm to v10.15.0 2025-08-20 01:18:37 +00:00
renovate[bot]
4bc7165452 fix(deps): update dependency @mermaid-js/layout-elk to v0.1.9 2025-08-20 01:18:28 +00:00
renovate[bot]
82d6531e8c chore(deps): update dependency vite to v7.1.3 2025-08-20 01:17:10 +00:00
renovate[bot]
d6209035c3 chore(deps): update dependency electron to v37.3.1 2025-08-20 01:16:36 +00:00
Elian Doran
1d7799f981 refactor(react/settings): add names to all form groups 2025-08-19 23:34:25 +03:00
Elian Doran
51291a61e6 refactor(react/settings): associate IDs for labels 2025-08-19 22:54:23 +03:00
Elian Doran
0841603be0 refactor(react/settings): use FormGroup for time selector 2025-08-19 22:36:47 +03:00
Elian Doran
59ba6a0b1e chore(react/settings): use FormGroup for labels 2025-08-19 22:32:20 +03:00
Elian Doran
53eda46043 chore(react/settings): use translation for all units 2025-08-19 21:50:29 +03:00
Elian Doran
cbc9fb7d08 chore(react/settings): solve type errors 2025-08-19 21:41:05 +03:00
Elian Doran
1f479b20be chore(react/settings): use onBlur instead of onChange 2025-08-19 20:09:56 +03:00
Elian Doran
f00b8e9522 chore(react/settings): set 100% width for textarea 2025-08-19 17:39:41 +03:00
Elian Doran
c7dd271516 Translations update from Hosted Weblate (#6697) 2025-08-19 17:07:49 +03:00
Hosted Weblate
a947a61d65 Update translation files
Updated by "Remove blank strings" add-on in Weblate.

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/
2025-08-19 16:02:30 +02:00
Székely Miklós
0122f1cc5e Translated using Weblate (Hungarian)
Currently translated at 6.3% (24 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/hu/
2025-08-19 16:02:27 +02:00
Wojciech O
acb905a3e6 Translated using Weblate (Polish)
Currently translated at 37.0% (140 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/pl/
2025-08-19 16:02:26 +02:00
Wojciech O
7422eb5598 Translated using Weblate (Polish)
Currently translated at 1.3% (21 of 1551 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-08-19 16:02:22 +02:00
Kuzma Simonov
e721166f95 Translated using Weblate (Russian)
Currently translated at 50.2% (190 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ru/
2025-08-19 16:02:18 +02:00
acwr47
5a48130fa4 Translated using Weblate (Japanese)
Currently translated at 96.8% (366 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/
2025-08-19 16:02:16 +02:00
Kuzma Simonov
b60fe1ad10 Translated using Weblate (Russian)
Currently translated at 81.8% (1269 of 1551 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-08-19 16:02:15 +02:00
gri-gri
1405b0147c Translated using Weblate (Russian)
Currently translated at 81.8% (1269 of 1551 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-08-19 16:02:13 +02:00
acwr47
222a7a57bc Translated using Weblate (Japanese)
Currently translated at 67.8% (1052 of 1551 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-08-19 16:02:12 +02:00
Elian Doran
cddf9f0242 Merge remote-tracking branch 'origin/main' into react/settings
; Conflicts:
;	apps/client/package.json
;	apps/client/src/translations/en/translation.json
;	apps/client/src/translations/tw/translation.json
;	pnpm-lock.yaml
2025-08-19 13:50:27 +03:00
Elian Doran
3e17ff5e7b chore(react/settings): clean up options widget 2025-08-19 13:47:15 +03:00
Elian Doran
04973094f2 feat(react/settings): port LLM settings 2025-08-19 13:46:13 +03:00
Elian Doran
018a6cb84a chore(react/settings): add back some checks for MFA 2025-08-19 10:54:02 +03:00
Elian Doran
44825af0c0 feat(react/settings): port OAuth settings 2025-08-19 10:51:05 +03:00
Elian Doran
cfb3607052 feat(react/settings): port totp settings 2025-08-19 10:37:14 +03:00
Elian Doran
c5ec928aac fix(deps): update dependency preact to v10.27.1 (#6690) 2025-08-19 08:40:36 +03:00
Elian Doran
8d0183a9fb chore(deps): update svelte monorepo (#6691) 2025-08-19 08:38:55 +03:00
Elian Doran
ecd4079871 chore(deps): update typescript-eslint monorepo to v8.40.0 (#6692) 2025-08-19 08:38:24 +03:00
Elian Doran
3ed975f2e6 fix(deps): update dependency marked to v16.2.0 (#6693) 2025-08-19 08:35:28 +03:00
renovate[bot]
c6deb537d5 fix(deps): update dependency marked to v16.2.0 2025-08-19 01:29:40 +00:00
renovate[bot]
e7b3d806a7 chore(deps): update typescript-eslint monorepo to v8.40.0 2025-08-19 01:28:54 +00:00
renovate[bot]
d1a0778b48 chore(deps): update svelte monorepo 2025-08-19 01:27:47 +00:00
renovate[bot]
378634567f fix(deps): update dependency preact to v10.27.1 2025-08-19 01:27:13 +00:00
Elian Doran
ed56ed2be0 feat(quick_search): format multi-line results better (#6672) 2025-08-18 23:14:15 +03:00
Elian Doran
648aa7e3b0 fix(hotkeys): interpret shortcut in the user's locale (#6681) 2025-08-18 23:10:59 +03:00
Elian Doran
73ff41f2b2 fix(react/settings): hook leak after closing tabs 2025-08-18 22:15:47 +03:00
Elian Doran
3837466cb3 feat(react/settings): react to external changes 2025-08-18 20:41:33 +03:00
Elian Doran
b97a5ef888 chore(react/settings): reimplement reset shortcuts 2025-08-18 19:47:40 +03:00
Elian Doran
2ff1276ebb Translations update from Hosted Weblate (#6686) 2025-08-18 19:06:42 +03:00
Elian Doran
227cf5de85 feat(react/settings): port protected session timeout 2025-08-18 19:00:42 +03:00
Elian Doran
ccf52be431 feat(react/settings): port tray options 2025-08-18 18:47:18 +03:00
Elian Doran
07713e988c feat(react/settings): port search engine settings 2025-08-18 18:43:27 +03:00
Elian Doran
f934318625 feat(react/settings): port revision snapshot list 2025-08-18 18:27:12 +03:00
Elian Doran
6fb90abd75 feat(react/settings): port network connections 2025-08-18 18:22:07 +03:00
Elian Doran
27cc33888a feat(react/settings): port share settings 2025-08-18 18:19:48 +03:00
Elian Doran
95af901808 feat(react/settings): port HTML import tags 2025-08-18 18:07:58 +03:00
Elian Doran
c5a7f84250 feat(react/settings): port note revision snapshot interval 2025-08-18 17:51:45 +03:00
Elian Doran
a71d28500d feat(react/settings): port attachment erasure timeout 2025-08-18 17:42:39 +03:00
Elian Doran
436fd16f3a feat(react/settings): port note erasure timeout 2025-08-18 17:37:20 +03:00
Székely Miklós
ca34bf42f6 Added translation using Weblate (Hungarian) 2025-08-18 15:38:27 +02:00
Székely Miklós
fbf2315f57 Added translation using Weblate (Hungarian) 2025-08-18 15:38:26 +02:00
tomek7667
72f50dcb6b Translated using Weblate (Polish)
Currently translated at 16.4% (62 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/pl/
2025-08-18 15:38:25 +02:00
tomek7667
fd4c2f79a7 Translated using Weblate (Polish)
Currently translated at 0.6% (10 of 1551 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-08-18 15:38:25 +02:00
acwr47
72f9335213 Translated using Weblate (Japanese)
Currently translated at 66.9% (1038 of 1551 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-08-18 15:38:25 +02:00
Elian Doran
53d97047a3 feat(react/settings): port code read-only size 2025-08-18 16:10:05 +03:00
Elian Doran
2ba3666e23 feat(react/settings): port code mime types 2025-08-18 15:55:18 +03:00
Elian Doran
4a1d379ab4 feat(react/settings): port code editor appearance 2025-08-18 15:02:58 +03:00
Elian Doran
73167e1e30 feat(react/settings): port code editor settings 2025-08-18 14:27:45 +03:00
Elian Doran
ffc13f5de3 feat(react/settings): port date time format 2025-08-18 14:19:38 +03:00
tomek7667
9ba23d49d8 Added translation using Weblate (Polish) 2025-08-18 12:32:13 +02:00
tomek7667
222a6c48a7 Added translation using Weblate (Polish) 2025-08-18 12:32:13 +02:00
VortexP
e33208e6ec Translated using Weblate (Finnish)
Currently translated at 6.1% (95 of 1551 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/fi/
2025-08-18 12:32:12 +02:00
acwr47
af8781eaa7 Translated using Weblate (Japanese)
Currently translated at 65.5% (1016 of 1551 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-08-18 12:32:12 +02:00
Francis C
167b1a8d2e Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (378 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/zh_Hant/
2025-08-18 12:32:12 +02:00
Francis C
0a7aff507c Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1551 of 1551 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-08-18 12:32:12 +02:00
Francis C
103532aad9 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1551 of 1551 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-08-18 12:32:11 +02:00
Elian Doran
16939e9fd5 feat(react/settings): port auto read-only size 2025-08-18 12:14:38 +03:00
Elian Doran
4ef6169041 feat(react/settings): port highlight list settings 2025-08-18 12:11:29 +03:00
Elian Doran
9ebee42118 feat(react/settings): port TOC settings 2025-08-18 11:26:58 +03:00
Elian Doran
234d3997b1 feat(react/settings): port code block settings 2025-08-18 11:21:09 +03:00
Elian Doran
3ba0bcea4e feat(react/settings): port heading style 2025-08-18 09:47:18 +03:00
Elian Doran
701855344e feat(react/settings): port text features 2025-08-18 09:40:36 +03:00
Elian Doran
71b627fbc7 feat(react/settings): port text formatting toolbar 2025-08-18 09:34:16 +03:00
Elian Doran
5a4fc2c690 fix(deps): update dependency mind-elixir to v5.0.6 (#6682) 2025-08-18 09:07:10 +03:00
Elian Doran
0d67db52a2 chore(deps): update dependency chalk to v5.6.0 (#6683) 2025-08-18 09:06:25 +03:00
perf3ct
d971554201 feat(quick_search): also show the tags/attributes in quick search results 2025-08-18 03:20:04 +00:00
perf3ct
8fd7d7176e Merge branch 'main' into feat/quick-search-multiline-results 2025-08-18 00:30:58 +00:00
renovate[bot]
675575eed9 chore(deps): update dependency chalk to v5.6.0 2025-08-18 00:29:14 +00:00
renovate[bot]
2122cde293 fix(deps): update dependency mind-elixir to v5.0.6 2025-08-18 00:28:33 +00:00
Romain DEP.
b68a554bba fix(hotkeys): interpret shortcut in the user's locale
fixes #6547
2025-08-17 23:48:48 +02:00
Elian Doran
33043c7133 chore(call_to_action): add missing translation 2025-08-17 23:37:33 +03:00
Elian Doran
2e0f606a7a chore(release): prepare for v0.98.0 2025-08-17 22:46:16 +03:00
Elian Doran
87878dd6a7 Translations update from Hosted Weblate (#6679) 2025-08-17 22:20:39 +03:00
morteza rahvard
5296e073cc Translated using Weblate (Persian)
Currently translated at 0.7% (12 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/fa/
2025-08-17 19:17:36 +00:00
acwr47
7bfb7d6f6e Translated using Weblate (Japanese)
Currently translated at 65.4% (1014 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-08-17 19:17:35 +00:00
Elian Doran
b5069cc7c2 chore(call_to_action): rephrase 2025-08-17 22:17:21 +03:00
Elian Doran
3b6791f51a chore(call_to_action): disable background effects for now 2025-08-17 21:23:22 +03:00
Elian Doran
0b0be77e02 chore(deps): update dependency @sveltejs/kit to v2.31.1 (#6676) 2025-08-17 08:23:45 +03:00
renovate[bot]
60db10559e chore(deps): update dependency @sveltejs/kit to v2.31.1 2025-08-17 02:31:17 +00:00
Elian Doran
76b066ba4a Translations update from Hosted Weblate (#6673) 2025-08-16 23:27:47 +03:00
ali mohammadi
a28db32369 Translated using Weblate (Persian)
Currently translated at 1.5% (6 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/fa/
2025-08-16 20:02:07 +00:00
ali mohammadi
2523632391 Translated using Weblate (Persian)
Currently translated at 0.1% (3 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/fa/
2025-08-16 20:02:05 +00:00
neketos851
53548c356a Translated using Weblate (Ukrainian)
Currently translated at 2.1% (8 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/uk/
2025-08-16 20:02:03 +00:00
neketos851
565904ff5d Translated using Weblate (Ukrainian)
Currently translated at 3.1% (49 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/uk/
2025-08-16 20:02:01 +00:00
acwr47
e0c5545f8c Translated using Weblate (Japanese)
Currently translated at 65.2% (1012 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-08-16 20:01:59 +00:00
Aristide Bauchart
bc21285289 Translated using Weblate (French)
Currently translated at 81.7% (309 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/fr/
2025-08-16 20:01:57 +00:00
perf3ct
bbf8d757cd feat(quick_search): format multi-line results better 2025-08-16 19:16:27 +00:00
Elian Doran
318d504fad chore(deps): update dependency @types/node to v22.17.2 (#6665) 2025-08-16 08:55:02 +03:00
Elian Doran
fd5038148c Merge branch 'main' into renovate/node-22.x 2025-08-16 08:55:00 +03:00
renovate[bot]
693ca9291e chore(deps): update dependency @types/node to v22.17.2 2025-08-16 05:45:48 +00:00
Elian Doran
cfd8afc226 chore(deps): update dependency @sveltejs/kit to v2.31.0 (#6666) 2025-08-16 08:44:44 +03:00
Elian Doran
3e52ca7600 chore(deps): update dependency electron to v37.3.0 (#6667) 2025-08-16 08:44:09 +03:00
renovate[bot]
482522e802 chore(deps): update dependency electron to v37.3.0 2025-08-16 02:10:14 +00:00
renovate[bot]
8b5b6a01c6 chore(deps): update dependency @sveltejs/kit to v2.31.0 2025-08-16 02:09:37 +00:00
Elian Doran
5614891d92 fix(react/settings): unnecessary top margin 2025-08-16 00:22:18 +03:00
Elian Doran
b9b4961f3c fix(react/settings): shortcuts saved upon render 2025-08-16 00:13:18 +03:00
Elian Doran
7b83b20339 feat(react/settings): port shortcuts 2025-08-16 00:08:51 +03:00
Elian Doran
e4403dd316 Translations update from Hosted Weblate (#6664) 2025-08-15 23:04:33 +03:00
ali mohammadi
3f267fe6c9 Added translation using Weblate (Persian) 2025-08-15 21:31:45 +02:00
ali mohammadi
3229471485 Added translation using Weblate (Persian) 2025-08-15 21:31:44 +02:00
neketos851
62bac1adf9 Translated using Weblate (Ukrainian)
Currently translated at 0.7% (3 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/uk/
2025-08-15 21:31:43 +02:00
neketos851
82becfd52a Translated using Weblate (Ukrainian)
Currently translated at 0.5% (9 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/uk/
2025-08-15 21:31:43 +02:00
Elian Doran
92f035545b Translations update from Hosted Weblate (#6663) 2025-08-15 21:49:49 +03:00
neketos851
74d8ea7dcb Added translation using Weblate (Ukrainian) 2025-08-15 20:45:02 +02:00
neketos851
ac3f087279 Added translation using Weblate (Ukrainian) 2025-08-15 20:45:02 +02:00
VortexP
1cc4eb98c1 Translated using Weblate (Finnish)
Currently translated at 1.5% (6 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/fi/
2025-08-15 20:45:01 +02:00
VortexP
e99bdf8f24 Translated using Weblate (Finnish)
Currently translated at 6.0% (94 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/fi/
2025-08-15 20:45:01 +02:00
acwr47
b4f521a141 Translated using Weblate (Japanese)
Currently translated at 60.8% (943 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-08-15 20:45:01 +02:00
VortexP
1e23bc09f1 Translated using Weblate (Finnish)
Currently translated at 1.3% (5 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/fi/
2025-08-15 16:07:51 +00:00
VortexP
e3ec90405d Translated using Weblate (Finnish)
Currently translated at 1.6% (25 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/fi/
2025-08-15 16:07:51 +00:00
acwr47
41c87794a4 Translated using Weblate (Japanese)
Currently translated at 60.7% (942 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-08-15 16:07:50 +00:00
VortexP
e62d2d4fda Added translation using Weblate (Finnish) 2025-08-15 16:07:50 +00:00
VortexP
93adaa0f52 Added translation using Weblate (Finnish) 2025-08-15 16:07:49 +00:00
Excal
263a5d2067 Translated using Weblate (Russian)
Currently translated at 7.9% (30 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ru/
2025-08-15 16:07:48 +00:00
acwr47
f0a5005794 Translated using Weblate (Japanese)
Currently translated at 60.3% (936 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-08-15 16:07:48 +00:00
Elian Doran
577457c8ab fix(docs): Update links to Trilium repo files in advanced config docs (#6662) 2025-08-15 19:07:39 +03:00
Jon Fuller
c0c450c444 fix(docs): Update links to Trilium repo files in advanced config docs 2025-08-15 08:39:40 -07:00
Elian Doran
1e1e0b0f51 Fix (Update): No update notification in the global menu (#6657) 2025-08-15 16:56:12 +03:00
Elian Doran
a19204a1d5 Translations update from Hosted Weblate (#6661) 2025-08-15 16:55:35 +03:00
Flowerlywind
1d139bfdfe Translated using Weblate (Vietnamese)
Currently translated at 2.1% (33 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/vi/
2025-08-15 14:02:12 +02:00
Excal
75072decec Translated using Weblate (Russian)
Currently translated at 1.8% (7 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ru/
2025-08-15 14:02:09 +02:00
Francis C
0cf2ad6901 Translated using Weblate (Japanese)
Currently translated at 96.8% (366 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/
2025-08-15 14:02:08 +02:00
acwr47
ccbd57a0c0 Translated using Weblate (Japanese)
Currently translated at 54.5% (845 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-08-15 14:02:07 +02:00
Francis C
92e6c8c445 Translated using Weblate (Japanese)
Currently translated at 54.5% (845 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-08-15 14:02:06 +02:00
Francis C
1e966f1d59 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (378 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/zh_Hant/
2025-08-15 14:02:05 +02:00
Francis C
6872c2194e Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1550 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-08-15 14:02:03 +02:00
Bruno MARGUERIN
5b6a0216db Translated using Weblate (French)
Currently translated at 71.1% (269 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/fr/
2025-08-15 14:02:01 +02:00
Elian Doran
e9a7194cd6 Translated using Weblate (Romanian)
Currently translated at 100.0% (1550 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ro/
2025-08-15 14:01:59 +02:00
Bruno MARGUERIN
26898b9122 Translated using Weblate (French)
Currently translated at 82.3% (1277 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/fr/
2025-08-15 14:01:58 +02:00
Elian Doran
3e00e490cf chore(react/settings): start porting protected session timeout 2025-08-15 14:23:54 +03:00
Elian Doran
c02ed17ebc feat(react/settings): port change password 2025-08-15 14:19:49 +03:00
Elian Doran
fb559d66fe feat(react/settings): port spellcheck 2025-08-15 13:52:52 +03:00
Elian Doran
25dce64c3b feat(react/settings): port backup DB list 2025-08-15 13:16:57 +03:00
Elian Doran
6f19fde76e feat(react/settings): port backup DB now 2025-08-15 12:52:59 +03:00
Elian Doran
33ae91f49c feat(backup): display full path to the database 2025-08-15 12:52:50 +03:00
Elian Doran
99c179e29a feat(react/settings): port automatic backup 2025-08-15 12:47:35 +03:00
Elian Doran
1dbcb5a027 fix(react/dialogs): unable to chain prompts 2025-08-15 12:33:23 +03:00
Elian Doran
54d613e00e fix(react/dialogs): prompt not setting default value properly 2025-08-15 12:15:29 +03:00
Elian Doran
1f8aa90482 fix(react/settings): etapi list not always reacting to changes 2025-08-15 12:11:40 +03:00
Elian Doran
c9dcbef014 feat(react/settings): port etapi tokens 2025-08-15 12:00:11 +03:00
Elian Doran
68086ec3f1 feat(react/settings): port sync test 2025-08-15 11:30:48 +03:00
Elian Doran
f62078d02b feat(react/settings): port sync options 2025-08-15 11:21:19 +03:00
SiriusXT
ab1d8594ea Fix (Update): No update notification in the global menu 2025-08-15 16:04:59 +08:00
Elian Doran
c368ec3c38 feat(react/settings): port content languages 2025-08-15 10:26:25 +03:00
Elian Doran
1a15782686 fix(deps): update dependency i18next to v25.3.6 (#6652) 2025-08-15 09:05:12 +03:00
Elian Doran
3bd0aeef77 chore(deps): update svelte monorepo (#6654) 2025-08-15 09:04:48 +03:00
Elian Doran
b463baedd2 chore(deps): update dependency tsx to v4.20.4 (#6632) 2025-08-15 09:04:22 +03:00
Elian Doran
ae77c41dab chore(deps): update tailwindcss monorepo to v4.1.12 (#6651) 2025-08-15 09:03:58 +03:00
Elian Doran
807d909acd chore(deps): update dependency @anthropic-ai/sdk to v0.60.0 (#6653) 2025-08-15 09:03:36 +03:00
Elian Doran
fa4f5f526e chore(deps): update dependency turndown to v7.2.1 (#6650) 2025-08-15 09:03:13 +03:00
renovate[bot]
edff43cdb3 chore(deps): update dependency tsx to v4.20.4 2025-08-15 05:51:01 +00:00
renovate[bot]
46fe45528c chore(deps): update svelte monorepo 2025-08-15 02:17:16 +00:00
renovate[bot]
b4b53da6a4 chore(deps): update dependency @anthropic-ai/sdk to v0.60.0 2025-08-15 02:16:43 +00:00
renovate[bot]
41fd270080 fix(deps): update dependency i18next to v25.3.6 2025-08-15 02:16:06 +00:00
renovate[bot]
410bb3cdca chore(deps): update tailwindcss monorepo to v4.1.12 2025-08-15 02:15:22 +00:00
renovate[bot]
bc6fc24fbd chore(deps): update dependency turndown to v7.2.1 2025-08-15 02:14:46 +00:00
Elian Doran
c039f06c2b chore(react/settings): fix a margin between radios 2025-08-15 00:19:37 +03:00
Elian Doran
520effbbb7 chore(react/settings): bring back style 2025-08-15 00:08:43 +03:00
Elian Doran
a42d780724 refactor(react/settings): fix type errors 2025-08-14 23:58:58 +03:00
Elian Doran
da92255dd6 refactor(react/settings): use better option mechanism 2025-08-14 23:54:32 +03:00
Elian Doran
cce3d3bce8 chore(react/settings): port date settings 2025-08-14 23:51:27 +03:00
Elian Doran
f524e99290 chore(react/settings): port first day of the week 2025-08-14 23:37:25 +03:00
Elian Doran
ba19fc7cf3 chore(react/settings): port formatting locale 2025-08-14 23:32:44 +03:00
Elian Doran
22c3de582f chore(react/settings): port language selection 2025-08-14 23:25:44 +03:00
Elian Doran
48896e67cb chore(react/settings): remove unnecessary ribbon settings 2025-08-14 23:11:13 +03:00
Elian Doran
16cd91eb02 feat(react/settings): port database anonymization 2025-08-14 23:10:53 +03:00
Elian Doran
7e03774b8e feat(react/settings): port vacuum database 2025-08-14 22:42:49 +03:00
Elian Doran
a04f6e3858 feat(react/settings): port integrity check 2025-08-14 22:40:54 +03:00
Elian Doran
96eb1be556 feat(react/settings): port advanced sync options 2025-08-14 22:35:58 +03:00
Jon Fuller
f8e20a1405 Update README.md (#6648) 2025-08-14 12:31:35 -07:00
Elian Doran
c67c3a6861 feat(react/settings): port images 2025-08-14 22:27:07 +03:00
Elian Doran
d04897e011 feat(react/settings): port related settings 2025-08-14 22:05:45 +03:00
MeIchthys
558ae1a2ea Update README.md
- Update links to point to new TriliumNext/Trilium repo
- Update a couple broken links
2025-08-14 14:59:08 -04:00
Elian Doran
64bffb82b1 feat(react/settings): port max content width 2025-08-14 21:55:16 +03:00
Elian Doran
81ac390eab feat(react/settings): port electron integration 2025-08-14 21:44:30 +03:00
Elian Doran
0db556fac2 feat(react/settings): port font size 2025-08-14 21:31:09 +03:00
Elian Doran
2793df06c4 fix(react/settings): useTriliumEvent not cleaning up properly 2025-08-14 21:05:24 +03:00
Elian Doran
e7b448e2bc fix(react/settings): event leak in useOption 2025-08-14 19:55:45 +03:00
Elian Doran
d2bc72d54f chore(react/settings): port font family settings 2025-08-14 19:25:22 +03:00
Elian Doran
83b22b4861 chore(react/settings): allow combo to have any possible object structure 2025-08-14 18:51:32 +03:00
Elian Doran
d42a949602 refactor(react/settings): use separate components inside same file 2025-08-14 18:29:08 +03:00
Elian Doran
83e1512b59 feat(react/settings): port override theme fonts 2025-08-14 18:26:40 +03:00
Elian Doran
ba6a1ec584 feat(react/settings): port theme switch 2025-08-14 18:18:45 +03:00
Elian Doran
6685e583f2 chore(react/settings): make layout switch functional 2025-08-14 17:59:17 +03:00
Elian Doran
d6032c912e chore(react/settings): improve layout 2025-08-14 17:54:52 +03:00
Elian Doran
25527ecc21 fix(react/settings): not working properly when side-by-side in split 2025-08-14 17:53:24 +03:00
Elian Doran
e0e7bd42cc feat(react/settings): react to property change 2025-08-14 17:47:45 +03:00
Elian Doran
fbc1af56ed feat(react/settings): basic hook to read Trilium option 2025-08-14 17:36:11 +03:00
Elian Doran
8ff108db9e feat(react/settings): basic rendering of React content widgets 2025-08-14 17:19:38 +03:00
Elian Doran
1dfcf960d3 fix(client): missing calendar view language support 2025-08-14 15:20:08 +03:00
Elian Doran
9bdc51a3fb feat(i18n): add Japanese language 2025-08-14 14:51:57 +03:00
Elian Doran
dbf3bcfacf Merge remote-tracking branch 'weblate/main' 2025-08-14 14:34:30 +03:00
Elian Doran
3d5b269315 chore(docs): fix file 2025-08-14 14:23:37 +03:00
Elian Doran
48f97da9cc chore(forge/rpm): rename key properly 2025-08-14 14:10:33 +03:00
Elian Doran
9c954fbd81 Create CNAME 2025-08-14 13:53:25 +03:00
Elian Doran
c6bd41654f chore(forge/rpm): add public key 2025-08-14 13:40:23 +03:00
Francis C
d65a74bb23 Translated using Weblate (Japanese)
Currently translated at 96.8% (366 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/
2025-08-14 12:30:37 +02:00
acwr47
ff08bca042 Translated using Weblate (Japanese)
Currently translated at 41.6% (646 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-08-14 12:30:36 +02:00
Francis C
a5d3d2e3b4 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1550 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-08-14 12:30:35 +02:00
Bruno MARGUERIN
496a0667ee Translated using Weblate (French)
Currently translated at 71.1% (269 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/fr/
2025-08-14 12:30:34 +02:00
Bruno MARGUERIN
9be688b667 Translated using Weblate (French)
Currently translated at 80.7% (1252 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/fr/
2025-08-14 12:30:33 +02:00
Elian Doran
f3d9008c61 feat(forge): rpm signing (#6646) 2025-08-14 13:30:26 +03:00
Elian Doran
649a43c978 fix(forge): RPM signing not done on the right file 2025-08-14 12:45:18 +03:00
Elian Doran
50568704ca feat(forge): minor improvements to RPM signing 2025-08-14 12:40:19 +03:00
Elian Doran
b66b4dec83 feat(forge): proper rpm signing 2025-08-14 12:04:12 +03:00
Francis C
8d0e807435 Translated using Weblate (Japanese)
Currently translated at 96.8% (366 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/
2025-08-14 09:02:31 +00:00
acwr47
bf05ed7caf Translated using Weblate (Japanese)
Currently translated at 96.8% (366 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/
2025-08-14 09:02:29 +00:00
Elian Doran
b5080eff00 Translated using Weblate (Russian)
Currently translated at 55.6% (863 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-08-14 09:02:28 +00:00
Francis C
c474769dd6 Translated using Weblate (Japanese)
Currently translated at 35.4% (550 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-08-14 09:02:27 +00:00
acwr47
a6ae01da0b Translated using Weblate (Japanese)
Currently translated at 35.4% (550 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-08-14 09:02:25 +00:00
Francis C
2bf4c44dbf Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (378 of 378 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/zh_Hant/
2025-08-14 09:02:24 +00:00
Francis C
5ca0fbba13 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1550 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-08-14 09:02:22 +00:00
Elian Doran
4cd84b2019 Translated using Weblate (Romanian)
Currently translated at 99.0% (1536 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ro/
2025-08-14 09:02:19 +00:00
Marcelo Popper Costa
c502a45cf5 Translated using Weblate (Portuguese (Brazil))
Currently translated at 22.3% (346 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pt_BR/
2025-08-14 09:02:17 +00:00
Francis C
9e66914306 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1550 of 1550 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-08-14 09:02:15 +00:00
Elian Doran
d33d27ee82 feat(forge): validate rpm signing 2025-08-14 11:45:59 +03:00
Elian Doran
e2b13573ae feat(forge): rpm signing 2025-08-14 10:43:38 +03:00
Elian Doran
ec74f5f1de feat(logs): provide an option to keep all logs (#6644) 2025-08-14 08:51:46 +03:00
Elian Doran
5dee56debc Add Traditional Chinese translation for README file & fix Docker Hub URL (#6645) 2025-08-14 08:43:08 +03:00
Francis C.
5623fc992d Update README-ZH_TW.md (tiny fix) 2025-08-14 12:04:45 +08:00
Francis C.
1d28bfc570 Update README-ZH_TW.md (tiny fix) 2025-08-14 11:25:53 +08:00
Francis C.
084327e973 Revise some words for Simplified Chinese translation 2025-08-14 11:20:32 +08:00
Francis C.
b2885efdc1 Update README-ZH_CN.md 2025-08-14 10:56:54 +08:00
Francis C.
b65a75f138 fix relative path for URLs 2025-08-14 10:27:41 +08:00
Francis C.
0ee7f50bb4 Move readme to docs folder 2025-08-14 10:15:03 +08:00
Francis C.
02ce21bc18 Add readme file translation for Traditional Chinese & fix Docker Hub URL 2025-08-14 10:12:14 +08:00
Romain DEP.
3ba487bb00 feat(logs): provide an option to keep all logs 2025-08-13 23:35:31 +02:00
Elian Doran
9cf7fa1997 fix(export/share): use right extension for clones 2025-06-24 22:14:15 +03:00
Elian Doran
fded714f18 fix(export/share): use right extension for images 2025-06-24 19:53:21 +03:00
Elian Doran
06de06b501 refactor(export/share): share type for format 2025-06-24 19:21:09 +03:00
Elian Doran
9abdbbbc5b refactor(export/share): fix type 2025-06-24 19:06:18 +03:00
Elian Doran
3ebfee8bd2 fix(export/share): tree error in prod 2025-06-24 18:49:19 +03:00
Elian Doran
6d446c5b27 fix(export/share): asset path in prod 2025-06-24 18:49:11 +03:00
Elian Doran
3a55490bbf refactor(share): use a string cache for templates 2025-06-24 18:08:29 +03:00
Elian Doran
bc4643fed2 refactor(share): use internal rendering method for subtemplates 2025-06-24 17:48:52 +03:00
Elian Doran
a2110ca631 fix(export/share): tree not expanding properly 2025-06-24 17:45:06 +03:00
Elian Doran
413137ac64 chore(nx): sync tsconfig 2025-06-23 21:23:44 +03:00
Elian Doran
9bc966491d fix(edit-docs): import error 2025-06-23 21:22:45 +03:00
Elian Doran
61dbc15fc6 feat(export/share): use translation 2025-06-23 20:14:13 +03:00
Elian Doran
b475037127 feat(export/share): render non-text note types 2025-06-23 20:00:40 +03:00
Elian Doran
35622a2122 feat(export/share): always render empty files 2025-06-23 19:38:47 +03:00
Elian Doran
77e4c3d0ec refactor(export/share): use different URL rewriting mechanism 2025-06-23 19:28:45 +03:00
Elian Doran
8523050ab2 fix(export/share): note children preview links not working 2025-06-23 19:00:20 +03:00
Elian Doran
0efdf65202 refactor(export/share): build index file 2025-06-23 18:46:21 +03:00
Elian Doran
acb0991d05 refactor(export/zip): separate building provider into own method 2025-06-23 18:24:59 +03:00
Elian Doran
a9f68f5487 feat(export/zip): add option to export with share theme 2025-06-23 18:13:47 +03:00
Elian Doran
55bb2fdb9b refactor(export/zip): extract prepare content into providers 2025-06-23 16:22:42 +03:00
Elian Doran
e529633b8b chore(export/zip): bring back markdown exporter 2025-06-23 16:17:29 +03:00
Elian Doran
dfd575b6eb refactor(export/zip): extract into separate provider 2025-06-23 16:08:31 +03:00
Elian Doran
c5196721d4 chore(nx): sync tsconfig 2025-06-23 15:36:10 +03:00
Elian Doran
968c75b618 Merge remote-tracking branch 'origin/main' into feature/export_with_share_theme 2025-06-23 15:35:30 +03:00
Elian Doran
01beebf660 feat(export/zip): load script as well 2025-06-14 01:23:02 +03:00
Elian Doran
d3115e834a feat(export/zip): get logo to work 2025-06-14 01:01:12 +03:00
Elian Doran
01a552ceb5 feat(export/zip): get boxicons to work 2025-06-14 00:52:56 +03:00
Elian Doran
d8958adea5 feat(export/zip): basic tree navigation 2025-06-14 00:07:55 +03:00
Elian Doran
4d5e866db6 feat(export/zip): get CSS to load 2025-06-13 23:47:04 +03:00
Elian Doran
f189deb415 feat(export/zip): get tree to render 2025-06-13 23:22:44 +03:00
Elian Doran
9c460dbc87 feat(export/zip): get same rendering engine as share 2025-06-13 23:10:14 +03:00
Elian Doran
2c6ba9ba2c refactor(share): extract note rendering logic 2025-06-13 17:48:19 +03:00
Nathan Cahill
a1ef80f5ae split.js v1.6.5 react-split v2.0.14 react-split-grid v1.0.4 2022-01-06 18:05:56 -06:00
Johan Sundström
d9a350a003 accept arrays for snapOffset in splitjs 2021-05-11 16:33:35 +02:00
Nathan Cahill
3b9bb98d8d v1.6.4 2021-04-05 08:58:28 -04:00
Nathan Cahill
87e7449da2 update types 2021-04-05 08:57:28 -04:00
Nathan Cahill
a2c8695a6d splitjs v1.6.3, split-grid v1.0.10 2021-04-02 09:27:16 -04:00
Nathan Cahill
2f74e84777 add maxSize option 2021-04-02 09:27:16 -04:00
Nathan Cahill
db9591a011 split.js v1.6.2, react-split-grid v1.0.3 2020-07-07 11:01:34 +02:00
Nathan Cahill
e56e29fd64 add sizes to onDrag 2020-07-07 10:56:14 +02:00
Nathan Cahill
06e4a8bc50 Merge pull request #214 from pgherveou/patch-1
Update splitjs type definitions
2020-07-07 10:52:39 +02:00
Nathan Cahill
d4a1905e73 react-split v2.0.9 2020-06-24 13:39:50 +02:00
Nathan Cahill
bc583b0ceb split.js v1.6.1 2020-06-24 13:39:36 +02:00
Nathan Cahill
d5b8666dee revert from mjs esm build for webpack 2020-06-24 13:39:07 +02:00
PG Herveou
905e311e42 Update index.d.ts 2020-06-15 14:49:22 -04:00
PG Herveou
d3d4c88b47 Merge branch 'master' into patch-1 2020-06-15 14:48:48 -04:00
Nathan Cahill
7cdad71a8e david-dm down 2020-06-15 10:16:04 +02:00
Nathan Cahill
4e2b331ba0 readmes 2020-06-12 15:18:11 +02:00
Nathan Cahill
f0c0c6ec67 split.js - v1.6.0 2020-06-10 18:52:40 +02:00
Nathan Cahill
57656efacc add types 2020-06-10 18:47:40 +02:00
Nathan Cahill
a8b26cbe27 update defs 2020-06-10 18:39:30 +02:00
Nathan Cahill
1c9ffe5378 bump license year 2020-06-10 18:17:04 +02:00
Nathan Cahill
47d3bb7575 allow ssr with global
Co-authored-by: Austin Buckler <buckleraustin@gmail.com>
2020-06-10 18:05:27 +02:00
Nathan Cahill
03d6cb58db drop support for ie 8 2020-06-10 17:31:11 +02:00
Nathan Cahill
5d0f64db46 upgrade jasmine, dependabot, rollup 2020-06-10 16:42:41 +02:00
Nathan Cahill
76a973ac8a remove old browsers 2020-06-10 16:14:40 +02:00
Nathan Cahill
0491f27d55 remove old browsers not working 2020-06-10 16:08:50 +02:00
Nathan Cahill
3caa7fcfa5 run saucelabs 2020-06-10 15:16:17 +02:00
Nathan Cahill
bfdb3caa50 fix saucelabs versions 2020-06-10 14:45:59 +02:00
Nathan Cahill
f815c2ff8d version bump and format 2020-06-10 14:04:08 +02:00
Nathan Cahill
7c654903f6 Merge pull request #221 from inetsoft-anton/patch-1
Unrestrict cursor option typing
2019-11-22 08:54:07 -07:00
inetsoft-anton
27bfaba5ec Unrestrict cursor option typing
There doesn't appear to be a restriction in the code that limits the cursor style to one of col-resize or row-resize.
Change it to string to be more lenient, like gutterAlign.
2019-11-22 10:26:38 -05:00
PG Herveou
c2548cb4fa Update package.json 2019-11-06 11:30:29 -05:00
PG Herveou
086fe79dd9 Update package.json 2019-11-06 11:29:55 -05:00
PG Herveou
e8dfce7421 Update splitjs type definitions
This PR update the drag method definitions
see: https://github.com/nathancahill/split/tree/master/packages/splitjs#ondrag-ondragstart-ondragend
2019-11-06 11:25:32 -05:00
Nathan Cahill
c55da9de12 Merge pull request #198 from donaldpipowitch/patch-1
added missing react section
2019-07-07 15:44:17 -04:00
Nathan Cahill
ed5763d89a update karma conf 2019-07-07 12:46:25 -04:00
Nathan Cahill
e49912e83c docs 2019-07-07 12:08:32 -04:00
Donald Pipowitch
0b90bf460a added missing react section 2019-06-07 09:48:00 +02:00
Nathan Cahill
cf5f5476df splitjs - v1.5.11 2019-06-01 13:18:06 -04:00
Nathan Cahill
a12ba57de7 fix logo 2019-06-01 13:13:54 -04:00
Nathan Cahill
4574a233e6 splitjs - v1.5.10 2019-06-01 13:13:06 -04:00
Nathan Cahill
6e9ebf75ad fix link to flex layout 2019-06-01 10:54:13 -04:00
Nathan Cahill
1e720d4810 remove semi-colons from readme 2019-06-01 10:47:18 -04:00
Nathan Cahill
2e2c20f8a3 bump license year 2019-04-05 16:44:39 -04:00
Nathan Cahill
f1b976d4e4 fix typo in docs 2019-04-05 16:42:24 -04:00
Nathan Cahill
071e8a0cc1 Merge pull request #189 from stoplightio/master
Fix lack of item index in elementStyle
2019-03-11 15:41:31 -04:00
Jakub Rożek
c0006e961b consistently pass index to elementStyle 2019-03-11 15:40:54 +01:00
Nathan Cahill
7754829e1a handle case in hidden iframes - fixes #171 2018-11-22 11:27:53 -08:00
Nathan Cahill
a752e75409 add cdnjs 2018-11-11 17:19:16 -06:00
Nathan Cahill
61a9706b6a add cdnjs 2018-11-11 16:49:17 -06:00
Nathan Cahill
12a510c9c8 add saucelabs 2018-11-08 13:09:44 -07:00
Nathan Cahill
936d274f5a add saucelabs 2018-11-08 12:39:05 -07:00
Nathan Cahill
42fac91aed add saucelabs 2018-11-08 12:38:15 -07:00
Nathan Cahill
b934045cbd add saucelabs 2018-11-08 12:35:59 -07:00
Nathan Cahill
b77ebedf78 add saucelabs 2018-11-08 12:34:37 -07:00
Nathan Cahill
3c09f27676 es builds 2018-11-07 10:08:41 -07:00
Nathan Cahill
c545a4c685 fix paths 2018-11-06 14:35:25 -07:00
Nathan Cahill
9f0c5bf123 ignore minSize if parent is too small 2018-11-06 09:48:52 -07:00
Nathan Cahill
22a1c4cc65 v1.5.9 2018-11-05 15:05:29 -07:00
Nathan Cahill
dcd51d64fb handle views without clientSize 2018-11-05 14:58:27 -07:00
Nathan Cahill
92f95e7288 clarify css layouts 2018-11-05 12:41:25 -07:00
Nathan Cahill
31cbe99224 standardize package json 2018-11-05 07:20:37 -07:00
Nathan Cahill
45aad74b01 switch to saucelabs 2018-11-04 18:04:44 -07:00
Nathan Cahill
f1b8a1b7f2 disable browserstack until ie testing is fixed 2018-11-04 16:40:31 -07:00
Nathan Cahill
4356adcdfe fix browserstack paths 2018-11-04 15:50:10 -07:00
Nathan Cahill
8c1d9c27c2 browserstack config 2018-11-04 15:46:18 -07:00
Nathan Cahill
52c593c54e browserstack 2018-11-04 15:28:54 -07:00
Nathan Cahill
977615aa2b remove old react link 2018-11-04 15:14:11 -07:00
Nathan Cahill
58cc1280ce deprecate bower 2018-11-04 14:37:33 -07:00
Nathan Cahill
eaeb2f1bb2 move off rawgit 2018-11-04 14:36:43 -07:00
Nathan Cahill
f1d912e4bd remove submodules 2018-11-04 14:32:14 -07:00
Nathan Cahill
7c3619675a monorepo 2018-11-04 14:30:29 -07:00
1573 changed files with 106058 additions and 63380 deletions

View File

@@ -1,6 +1,6 @@
root = true
[*.{js,ts}]
[*.{js,ts,tsx}]
charset = utf-8
end_of_line = lf
indent_size = 4

1
.env
View File

@@ -1 +0,0 @@
NODE_OPTIONS=--max_old_space_size=4096

View File

@@ -74,7 +74,7 @@ runs:
- name: Update build info
shell: ${{ inputs.shell }}
run: npm run chore:update-build-info
run: pnpm run chore:update-build-info
# Critical debugging configuration
- name: Run electron-forge build with enhanced logging
@@ -86,7 +86,8 @@ runs:
APPLE_ID_PASSWORD: ${{ env.APPLE_ID_PASSWORD }}
WINDOWS_SIGN_EXECUTABLE: ${{ env.WINDOWS_SIGN_EXECUTABLE }}
TRILIUM_ARTIFACT_NAME_HINT: TriliumNotes-${{ github.ref_name }}-${{ inputs.os }}-${{ inputs.arch }}
run: pnpm nx --project=desktop electron-forge:make -- --arch=${{ inputs.arch }} --platform=${{ inputs.forge_platform }}
TARGET_ARCH: ${{ inputs.arch }}
run: pnpm run --filter desktop electron-forge:make --arch=${{ inputs.arch }} --platform=${{ inputs.forge_platform }}
# Add DMG signing step
- name: Sign DMG
@@ -162,3 +163,25 @@ runs:
echo "Found ZIP: $zip_file"
echo "Note: ZIP files are not code signed, but their contents should be"
fi
- name: Sign the RPM
if: inputs.os == 'linux'
shell: ${{ inputs.shell }}
run: |
echo -n "$GPG_SIGNING_KEY" | base64 --decode | gpg --import
# Import the key into RPM for verification
gpg --export -a > pubkey
rpm --import pubkey
rm pubkey
# Sign the RPM
rpm_file=$(find ./apps/desktop/upload -name "*.rpm" -print -quit)
rpmsign --define "_gpg_name Trilium Notes Signing Key <triliumnotes@outlook.com>" --addsign "$rpm_file"
rpm -Kv "$rpm_file"
# Validate code signing
if ! rpm -K "$rpm_file" | grep -q "digests signatures OK"; then
echo .rpm file not signed
exit 1
fi

View File

@@ -10,9 +10,9 @@ runs:
steps:
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
cache: "pnpm"
- name: Install dependencies
shell: bash
@@ -23,7 +23,7 @@ runs:
shell: bash
run: |
pnpm run chore:update-build-info
pnpm nx --project=server package
pnpm run --filter server package
- name: Prepare artifacts
shell: bash
run: |

View File

@@ -0,0 +1,103 @@
name: "Deploy to Cloudflare Pages"
description: "Deploys to Cloudflare Pages on either a temporary branch with preview comment, or on the production version if on the main branch."
inputs:
project_name:
description: "CloudFlare Pages project name"
comment_body:
description: "The message to display when deployment is ready"
default: "Deployment is ready."
required: false
production_url:
description: "The URL to mention as the production URL."
required: true
deploy_dir:
description: "The directory from which to deploy."
required: true
cloudflare_api_token:
description: "The Cloudflare API token to use for deployment."
required: true
cloudflare_account_id:
description: "The Cloudflare account ID to use for deployment."
required: true
github_token:
description: "The GitHub token to use for posting PR comments."
required: true
runs:
using: composite
steps:
# Install wrangler globally to avoid workspace issues
- name: Install Wrangler
shell: bash
run: npm install -g wrangler
# Deploy using Wrangler (use pre-installed wrangler)
- name: Deploy to Cloudflare Pages
id: deploy
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ inputs.cloudflare_api_token }}
accountId: ${{ inputs.cloudflare_account_id }}
command: pages deploy ${{ inputs.deploy_dir }} --project-name=${{ inputs.project_name}} --branch=${{ github.ref_name }}
wranglerVersion: '' # Use pre-installed version
# Deploy preview for PRs
- name: Deploy Preview to Cloudflare Pages
id: preview-deployment
if: github.event_name == 'pull_request'
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ inputs.cloudflare_api_token }}
accountId: ${{ inputs.cloudflare_account_id }}
command: pages deploy ${{ inputs.deploy_dir }} --project-name=${{ inputs.project_name}} --branch=pr-${{ github.event.pull_request.number }}
wranglerVersion: '' # Use pre-installed version
# Post deployment URL as PR comment
- name: Comment PR with Preview URL
if: github.event_name == 'pull_request'
uses: actions/github-script@v8
env:
COMMENT_BODY: ${{ inputs.comment_body }}
PRODUCTION_URL: ${{ inputs.production_url }}
PROJECT_NAME: ${{ inputs.project_name }}
with:
github-token: ${{ inputs.github_token }}
script: |
const prNumber = context.issue.number;
// Construct preview URL based on Cloudflare Pages pattern
const projectName = process.env.PROJECT_NAME;
const previewUrl = `https://pr-${prNumber}.${projectName}.pages.dev`;
// Check if we already commented
const comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber
});
const customMessage = process.env.COMMENT_BODY;
const botComment = comments.data.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes(customMessage)
);
const mainUrl = process.env.PRODUCTION_URL;
const commentBody = `${customMessage}!\n\n🔗 Preview URL: ${previewUrl}\n📖 Production URL: ${mainUrl}\n\n✅ All checks passed\n\n_This preview will be updated automatically with new commits._`;
if (botComment) {
// Update existing comment
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: commentBody
});
} else {
// Create new comment
await github.rest.issues.createComment({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
body: commentBody
});
}

View File

@@ -1,40 +0,0 @@
---
applyTo: '**'
---
// This file is automatically generated by Nx Console
You are in an nx workspace using Nx 21.3.9 and pnpm as the package manager.
You have access to the Nx MCP server and the tools it provides. Use them. Follow these guidelines in order to best help the user:
# General Guidelines
- When answering questions, use the nx_workspace tool first to gain an understanding of the workspace architecture
- For questions around nx configuration, best practices or if you're unsure, use the nx_docs tool to get relevant, up-to-date docs!! Always use this instead of assuming things about nx configuration
- If the user needs help with an Nx configuration or project graph error, use the 'nx_workspace' tool to get any errors
- To help answer questions about the workspace structure or simply help with demonstrating how tasks depend on each other, use the 'nx_visualize_graph' tool
# Generation Guidelines
If the user wants to generate something, use the following flow:
- learn about the nx workspace and any specifics the user needs by using the 'nx_workspace' tool and the 'nx_project_details' tool if applicable
- get the available generators using the 'nx_generators' tool
- decide which generator to use. If no generators seem relevant, check the 'nx_available_plugins' tool to see if the user could install a plugin to help them
- get generator details using the 'nx_generator_schema' tool
- you may use the 'nx_docs' tool to learn more about a specific generator or technology if you're unsure
- decide which options to provide in order to best complete the user's request. Don't make any assumptions and keep the options minimalistic
- open the generator UI using the 'nx_open_generate_ui' tool
- wait for the user to finish the generator
- read the generator log file using the 'nx_read_generator_log' tool
- use the information provided in the log file to answer the user's question or continue with what they were doing
# Running Tasks Guidelines
If the user wants help with tasks or commands (which include keywords like "test", "build", "lint", or other similar actions), use the following flow:
- Use the 'nx_current_running_tasks_details' tool to get the list of tasks (this can include tasks that were completed, stopped or failed).
- If there are any tasks, ask the user if they would like help with a specific task then use the 'nx_current_running_task_output' tool to get the terminal output for that task/command
- Use the terminal output from 'nx_current_running_task_output' to see what's wrong and help the user fix their problem. Use the appropriate tools if necessary
- If the user would like to rerun the task or command, always use `nx run <taskId>` to rerun in the terminal. This will ensure that the task will run in the nx context and will be run the same way it originally executed
- If the task was marked as "continuous" do not offer to rerun the task. This task is already running and the user can see the output in the terminal. You can use 'nx_current_running_task_output' to get the output of the task to verify the output.

View File

@@ -12,6 +12,7 @@ jobs:
steps:
- name: Check if PRs have conflicts
uses: eps1lon/actions-label-merge-conflict@v3
if: github.repository == ${{ vars.REPO_MAIN }}
with:
dirtyLabel: "merge-conflicts"
repoToken: "${{ secrets.MERGE_CONFLICT_LABEL_PAT }}"

View File

@@ -67,7 +67,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
@@ -95,6 +95,6 @@ jobs:
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v4
with:
category: "/language:${{matrix.language}}"

78
.github/workflows/deploy-docs.yml vendored Normal file
View File

@@ -0,0 +1,78 @@
name: Deploy Documentation
on:
# Trigger on push to main branch
push:
branches:
- main
- master # Also support master branch
# Only run when docs files change
paths:
- 'docs/**'
- 'apps/edit-docs/**'
- 'apps/build-docs/**'
- 'packages/share-theme/**'
# Allow manual triggering from Actions tab
workflow_dispatch:
# Run on pull requests for preview deployments
pull_request:
branches:
- main
- master
paths:
- 'docs/**'
- 'apps/edit-docs/**'
- 'apps/build-docs/**'
- 'packages/share-theme/**'
jobs:
build-and-deploy:
name: Build and Deploy Documentation
runs-on: ubuntu-latest
timeout-minutes: 10
# Required permissions for deployment
permissions:
contents: read
deployments: write
pull-requests: write # For PR preview comments
id-token: write # For OIDC authentication (if needed)
steps:
- name: Checkout Repository
uses: actions/checkout@v5
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: '24'
cache: 'pnpm'
- name: Install Dependencies
run: pnpm install --frozen-lockfile
- name: Trigger build of documentation
run: pnpm docs:build
- name: Validate Built Site
run: |
test -f site/index.html || (echo "ERROR: site/index.html not found" && exit 1)
test -f site/developer-guide/index.html || (echo "ERROR: site/developer-guide/index.html not found" && exit 1)
echo "✓ User Guide and Developer Guide built successfully"
- name: Deploy
uses: ./.github/actions/deploy-to-cloudflare-pages
if: github.repository == ${{ vars.REPO_MAIN }}
with:
project_name: "trilium-docs"
comment_body: "📚 Documentation preview is ready"
production_url: "https://docs.triliumnotes.org"
deploy_dir: "site"
cloudflare_api_token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
cloudflare_account_id: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
github_token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -19,45 +19,24 @@ permissions:
pull-requests: write # for PR comments
jobs:
check-affected:
name: Check affected jobs (NX)
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@v5
with:
fetch-depth: 0 # needed for https://github.com/marketplace/actions/nx-set-shas
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- uses: nrwl/nx-set-shas@v4
- name: Check affected
run: pnpm nx affected --verbose -t typecheck build rebuild-deps test-build
test_dev:
name: Test development
runs-on: ubuntu-latest
needs:
- check-affected
steps:
- name: Checkout the repository
uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
cache: "pnpm"
- run: pnpm install --frozen-lockfile
- name: Typecheck
run: pnpm typecheck
- name: Run the unit tests
run: pnpm run test:all
@@ -66,7 +45,6 @@ jobs:
runs-on: ubuntu-latest
needs:
- test_dev
- check-affected
steps:
- uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
@@ -75,7 +53,7 @@ jobs:
- name: Update build info
run: pnpm run chore:update-build-info
- name: Trigger client build
run: pnpm nx run client:build
run: pnpm client:build
- name: Send client bundle stats to RelativeCI
if: false
uses: relative-ci/agent-action@v3
@@ -83,7 +61,7 @@ jobs:
webpackStatsFile: ./apps/client/dist/webpack-stats.json
key: ${{ secrets.RELATIVE_CI_CLIENT_KEY }}
- name: Trigger server build
run: pnpm nx run server:build
run: pnpm run server:build
- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v6
with:
@@ -95,7 +73,6 @@ jobs:
runs-on: ubuntu-latest
needs:
- build_docker
- check-affected
strategy:
matrix:
include:
@@ -112,7 +89,7 @@ jobs:
- name: Update build info
run: pnpm run chore:update-build-info
- name: Trigger build
run: pnpm nx run server:build
run: pnpm server:build
- name: Set IMAGE_NAME to lowercase
run: echo "IMAGE_NAME=${IMAGE_NAME,,}" >> $GITHUB_ENV

View File

@@ -44,9 +44,9 @@ jobs:
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
cache: "pnpm"
- name: Install npm dependencies
@@ -82,16 +82,16 @@ jobs:
require-healthy: true
- name: Run Playwright tests
run: TRILIUM_DOCKER=1 TRILIUM_PORT=8082 pnpm exec nx run server-e2e:e2e
run: TRILIUM_DOCKER=1 TRILIUM_PORT=8082 pnpm --filter=server-e2e e2e
- name: Upload Playwright trace
if: failure()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: Playwright trace (${{ matrix.dockerfile }})
path: test-output/playwright/output
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v5
if: ${{ !cancelled() }}
with:
name: Playwright report (${{ matrix.dockerfile }})
@@ -116,10 +116,10 @@ jobs:
- dockerfile: Dockerfile
platform: linux/arm64
image: ubuntu-24.04-arm
- dockerfile: Dockerfile
- dockerfile: Dockerfile.legacy
platform: linux/arm/v7
image: ubuntu-24.04-arm
- dockerfile: Dockerfile
- dockerfile: Dockerfile.legacy
platform: linux/arm/v8
image: ubuntu-24.04-arm
runs-on: ${{ matrix.image }}
@@ -144,20 +144,20 @@ jobs:
uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Run the TypeScript build
run: pnpm run server:build
- name: Update build info
run: pnpm run chore:update-build-info
- name: Run the TypeScript build
run: pnpm run server:build
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
@@ -209,9 +209,9 @@ jobs:
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: digests-${{ env.PLATFORM_PAIR }}
name: digests-${{ env.PLATFORM_PAIR }}-${{ matrix.dockerfile }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
@@ -223,7 +223,7 @@ jobs:
- build
steps:
- name: Download digests
uses: actions/download-artifact@v5
uses: actions/download-artifact@v6
with:
path: /tmp/digests
pattern: digests-*

View File

@@ -19,7 +19,6 @@ concurrency:
cancel-in-progress: true
env:
GITHUB_UPLOAD_URL: https://uploads.github.com/repos/TriliumNext/Notes/releases/179589950/assets{?name,label}
GITHUB_RELEASE_ID: 179589950
permissions:
@@ -27,7 +26,7 @@ permissions:
jobs:
nightly-electron:
if: github.repository == 'TriliumNext/Trilium'
if: github.repository == ${{ vars.REPO_MAIN }}
name: Deploy nightly
strategy:
fail-fast: false
@@ -51,13 +50,12 @@ jobs:
- uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- uses: nrwl/nx-set-shas@v4
- name: Update nightly version
run: npm run chore:ci-update-nightly-version
- name: Run the build
@@ -76,9 +74,10 @@ jobs:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
WINDOWS_SIGN_EXECUTABLE: ${{ vars.WINDOWS_SIGN_EXECUTABLE }}
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGN_KEY }}
- name: Publish release
uses: softprops/action-gh-release@v2.3.2
uses: softprops/action-gh-release@v2.4.1
if: ${{ github.event_name != 'pull_request' }}
with:
make_latest: false
@@ -90,14 +89,14 @@ jobs:
name: Nightly Build
- name: Publish artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
if: ${{ github.event_name == 'pull_request' }}
with:
name: TriliumNotes ${{ matrix.os.name }} ${{ matrix.arch }}
path: apps/desktop/upload
nightly-server:
if: github.repository == 'TriliumNext/Trilium'
if: github.repository == ${{ vars.REPO_MAIN }}
name: Deploy server nightly
strategy:
fail-fast: false
@@ -119,7 +118,7 @@ jobs:
arch: ${{ matrix.arch }}
- name: Publish release
uses: softprops/action-gh-release@v2.3.2
uses: softprops/action-gh-release@v2.4.1
if: ${{ github.event_name != 'pull_request' }}
with:
make_latest: false

View File

@@ -4,6 +4,8 @@ on:
push:
branches:
- main
paths-ignore:
- "apps/website/**"
pull_request:
permissions:
@@ -19,25 +21,21 @@ jobs:
filter: tree:0
fetch-depth: 0
# This enables task distribution via Nx Cloud
# Run this command as early as possible, before dependencies are installed
# Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun
# Connect your workspace by running "nx connect" and uncomment this line to enable task distribution
# - run: npx nx-cloud start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="e2e-ci"
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
- uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- run: pnpm exec playwright install --with-deps
- uses: nrwl/nx-set-shas@v4
# Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud
# - run: npx nx-cloud record -- echo Hello World
# Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected
# When you enable task distribution, run the e2e-ci task instead of e2e
- run: pnpm exec nx affected -t e2e --exclude desktop-e2e
- run: pnpm --filter server-e2e e2e
- name: Upload test report
if: failure()
uses: actions/upload-artifact@v5
with:
name: e2e report
path: apps/server-e2e/test-output

View File

@@ -30,18 +30,30 @@ jobs:
image: win-signing
shell: cmd
forge_platform: win32
# Exclude ARM64 Linux from default matrix to use native runner
exclude:
- arch: arm64
os:
name: linux
# Add ARM64 Linux with native ubuntu-24.04-arm runner for better-sqlite3 compatibility
include:
- arch: arm64
os:
name: linux
image: ubuntu-24.04-arm
shell: bash
forge_platform: linux
runs-on: ${{ matrix.os.image }}
steps:
- uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- uses: nrwl/nx-set-shas@v4
- name: Run the build
uses: ./.github/actions/build-electron
with:
@@ -58,9 +70,10 @@ jobs:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
WINDOWS_SIGN_EXECUTABLE: ${{ vars.WINDOWS_SIGN_EXECUTABLE }}
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGN_KEY }}
- name: Upload the artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: release-desktop-${{ matrix.os.name }}-${{ matrix.arch }}
path: apps/desktop/upload/*.*
@@ -87,7 +100,7 @@ jobs:
arch: ${{ matrix.arch }}
- name: Upload the artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: release-server-linux-${{ matrix.arch }}
path: upload/*.*
@@ -107,14 +120,14 @@ jobs:
docs/Release Notes
- name: Download all artifacts
uses: actions/download-artifact@v5
uses: actions/download-artifact@v6
with:
merge-multiple: true
pattern: release-*
path: upload
- name: Publish stable release
uses: softprops/action-gh-release@v2.3.2
uses: softprops/action-gh-release@v2.4.1
with:
draft: false
body_path: docs/Release Notes/Release Notes/${{ github.ref_name }}.md

51
.github/workflows/website.yml vendored Normal file
View File

@@ -0,0 +1,51 @@
name: Deploy website
on:
push:
branches:
- main
paths:
- "apps/website/**"
pull_request:
paths:
- "apps/website/**"
release:
types: [ released ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
name: Build & deploy website
permissions:
contents: read
deployments: write
pull-requests: write # For PR preview comments
steps:
- uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v6
with:
node-version: 24
cache: "pnpm"
- name: Install dependencies
run: pnpm install --filter website --frozen-lockfile
- name: Build the website
run: pnpm website:build
- name: Deploy
uses: ./.github/actions/deploy-to-cloudflare-pages
with:
project_name: "trilium-homepage"
comment_body: "📚 Website preview is ready"
production_url: "https://triliumnotes.org"
deploy_dir: "apps/website/dist"
cloudflare_api_token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
cloudflare_account_id: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
github_token: ${{ secrets.GITHUB_TOKEN }}

11
.gitignore vendored
View File

@@ -1,4 +1,5 @@
# See https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
/.cache
# compiled output
dist
@@ -32,14 +33,11 @@ testem.log
.DS_Store
Thumbs.db
.nx/cache
.nx/workspace-data
vite.config.*.timestamp*
vitest.config.*.timestamp*
test-output
apps/*/data
apps/*/data*
apps/*/out
upload
@@ -47,4 +45,7 @@ upload
*.tsbuildinfo
/result
.svelte-kit
.svelte-kit
# docs
site/

2
.nvmrc
View File

@@ -1 +1 @@
22.18.0
24.11.0

View File

@@ -5,7 +5,6 @@
"lokalise.i18n-ally",
"ms-azuretools.vscode-docker",
"ms-playwright.playwright",
"nrwl.angular-console",
"redhat.vscode-yaml",
"tobermory.es6-string-html",
"vitest.explorer",

View File

@@ -14,6 +14,7 @@ usageMatchRegex:
# the `{key}` will be placed by a proper keypath matching regex,
# you can ignore it and use your own matching rules as well
- "[^\\w\\d]t\\(['\"`]({key})['\"`]"
- <Trans\s*i18nKey="({key})"[^>]*>
# A RegEx to set a custom scope range. This scope will be used as a prefix when detecting keys
# and works like how the i18next framework identifies the namespace scope from the

8
.vscode/mcp.json vendored
View File

@@ -1,8 +0,0 @@
{
"servers": {
"nx-mcp": {
"type": "http",
"url": "http://localhost:9461/mcp"
}
}
}

View File

@@ -5,7 +5,8 @@
"i18n-ally.keystyle": "nested",
"i18n-ally.localesPaths": [
"apps/server/src/assets/translations",
"apps/client/src/translations"
"apps/client/src/translations",
"apps/website/public/translations"
],
"npm.exclude": [
"**/dist",
@@ -35,6 +36,5 @@
"docs/**/*.png": true,
"apps/server/src/assets/doc_notes/**": true,
"apps/edit-docs/demo/**": true
},
"nxConsole.generateAiAgentRules": true
}
}

View File

@@ -20,5 +20,10 @@
"scope": "typescript",
"prefix": "jqf",
"body": ["private $${1:name}!: JQuery<HTMLElement>;"]
},
"region": {
"scope": "css",
"prefix": "region",
"body": ["/* #region ${1:name} */\n$0\n/* #endregion */"]
}
}

View File

@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Overview
Trilium Notes is a hierarchical note-taking application with advanced features like synchronization, scripting, and rich text editing. It's built as a TypeScript monorepo using NX, with multiple applications and shared packages.
Trilium Notes is a hierarchical note-taking application with advanced features like synchronization, scripting, and rich text editing. It's built as a TypeScript monorepo using pnpm, with multiple applications and shared packages.
## Development Commands
@@ -14,12 +14,9 @@ Trilium Notes is a hierarchical note-taking application with advanced features l
### Running Applications
- `pnpm run server:start` - Start development server (http://localhost:8080)
- `pnpm nx run server:serve` - Alternative server start command
- `pnpm nx run desktop:serve` - Run desktop Electron app
- `pnpm run server:start-prod` - Run server in production mode
### Building
- `pnpm nx build <project>` - Build specific project (server, client, desktop, etc.)
- `pnpm run client:build` - Build client application
- `pnpm run server:build` - Build server application
- `pnpm run electron:build` - Build desktop application
@@ -28,13 +25,8 @@ Trilium Notes is a hierarchical note-taking application with advanced features l
- `pnpm test:all` - Run all tests (parallel + sequential)
- `pnpm test:parallel` - Run tests that can run in parallel
- `pnpm test:sequential` - Run tests that must run sequentially (server, ckeditor5-mermaid, ckeditor5-math)
- `pnpm nx test <project>` - Run tests for specific project
- `pnpm coverage` - Generate coverage reports
### Linting & Type Checking
- `pnpm nx run <project>:lint` - Lint specific project
- `pnpm nx run <project>:typecheck` - Type check specific project
## Architecture Overview
### Monorepo Structure
@@ -94,7 +86,6 @@ Frontend uses a widget system (`apps/client/src/widgets/`):
- `apps/server/src/assets/db/schema.sql` - Core database structure
4. **Configuration**:
- `nx.json` - NX workspace configuration
- `package.json` - Project dependencies and scripts
## Note Types and Features
@@ -154,7 +145,7 @@ Trilium provides powerful user scripting capabilities:
- Update schema in `apps/server/src/assets/db/schema.sql`
## Build System Notes
- Uses NX for monorepo management with build caching
- Uses pnpm for monorepo management
- Vite for fast development builds
- ESBuild for production optimization
- pnpm workspaces for dependency management

113
README.md
View File

@@ -1,11 +1,22 @@
<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/notes)
![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/triliumnext/notes/total)
![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/)
[English](./README.md) | [Chinese](./docs/README-ZH_CN.md) | [Russian](./docs/README.ru.md) | [Japanese](./docs/README.ja.md) | [Italian](./docs/README.it.md) | [Spanish](./docs/README.es.md)
[English](./README.md) | [Chinese (Simplified)](./docs/README-ZH_CN.md) | [Chinese (Traditional)](./docs/README-ZH_TW.md) | [Russian](./docs/README-ru.md) | [Japanese](./docs/README-ja.md) | [Italian](./docs/README-it.md) | [Spanish](./docs/README-es.md)
Trilium Notes is a free and open-source, cross-platform hierarchical note taking application with focus on building large personal knowledge bases.
@@ -13,6 +24,27 @@ See [screenshots](https://triliumnext.github.io/Docs/Wiki/screenshot-tour) for q
<a href="https://triliumnext.github.io/Docs/Wiki/screenshot-tour"><img src="./docs/app.png" alt="Trilium Screenshot" width="1000"></a>
## ⏬ Download
- [Latest release](https://github.com/TriliumNext/Trilium/releases/latest) stable version, recommended for most users.
- [Nightly build](https://github.com/TriliumNext/Trilium/releases/tag/nightly) unstable development version, updated daily with the latest features and fixes.
## 📚 Documentation
**Visit our comprehensive documentation at [docs.triliumnotes.org](https://docs.triliumnotes.org/)**
Our documentation is available in multiple formats:
- **Online Documentation**: Browse the full documentation at [docs.triliumnotes.org](https://docs.triliumnotes.org/)
- **In-App Help**: Press `F1` within Trilium to access the same documentation directly in the application
- **GitHub**: Navigate through the [User Guide](./docs/User%20Guide/User%20Guide/) in this repository
### Quick Links
- [Getting Started Guide](https://docs.triliumnotes.org/)
- [Installation Instructions](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation.md)
- [Docker Setup](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation/1.%20Installing%20the%20server/Using%20Docker.md)
- [Upgrading TriliumNext](./docs/User%20Guide/User%20Guide/Installation%20%26%20Setup/Upgrading%20TriliumNext.md)
- [Basic Concepts and Features](./docs/User%20Guide/User%20Guide/Basic%20Concepts%20and%20Features/Notes.md)
- [Patterns of Personal Knowledge Base](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge)
## 🎁 Features
* Notes can be arranged into arbitrarily deep tree. Single note can be placed into multiple places in the tree (see [cloning](https://triliumnext.github.io/Docs/Wiki/cloning-notes))
@@ -46,28 +78,15 @@ See [screenshots](https://triliumnext.github.io/Docs/Wiki/screenshot-tour) for q
- [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?
## Why TriliumNext?
[The original Trilium project is in maintenance mode](https://github.com/zadam/trilium/issues/4620).
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 Trilium?
### ⬆️Migrating from Zadam/Trilium?
There are no special migration steps to migrate from a zadam/Trilium instance to a TriliumNext/Notes instance. Simply [install TriliumNext/Notes](#-installation) as usual and it will use your existing database.
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/Notes/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 have their sync versions incremented.
## 📖 Documentation
We're currently in the progress of moving the documentation to in-app (hit the `F1` key within Trilium). As a result, there may be some missing parts until we've completed the migration. If you'd prefer to navigate through the documentation within GitHub, you can navigate the [User Guide](./docs/User%20Guide/User%20Guide/) documentation.
Below are some quick links for your convenience to navigate the documentation:
- [Server installation](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation.md)
- [Docker installation](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation/1.%20Installing%20the%20server/Using%20Docker.md)
- [Upgrading TriliumNext](./docs/User%20Guide/User%20Guide/Installation%20%26%20Setup/Upgrading%20TriliumNext.md)
- [Concepts and Features - Note](./docs/User%20Guide/User%20Guide/Basic%20Concepts%20and%20Features/Notes.md)
- [Patterns of personal knowledge base](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge)
Until we finish reorganizing the documentation, you may also want to [browse the old documentation](https://triliumnext.github.io/Docs).
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
@@ -75,8 +94,8 @@ Feel free to join our official conversations. We would love to hear what feature
- [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/Notes/discussions) (For asynchronous discussions.)
- [Github Issues](https://github.com/TriliumNext/Notes/issues) (For bug reports and feature requests.)
- [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
@@ -104,13 +123,15 @@ Currently only the latest versions of Chrome & Firefox are supported (and tested
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).
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).
See issue https://github.com/TriliumNext/Trilium/issues/4962 for more information on mobile app support.
See issue https://github.com/TriliumNext/Notes/issues/72 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/notes)) follow [the server installation docs](https://triliumnext.github.io/Docs/Wiki/server-installation).
To install TriliumNext on your own server (including via Docker from [Dockerhub](https://hub.docker.com/r/triliumnext/trilium)) follow [the server installation docs](https://triliumnext.github.io/Docs/Wiki/server-installation).
## 💻 Contribute
@@ -140,7 +161,7 @@ Download the repository, install dependencies using `pnpm` and then run the envi
git clone https://github.com/TriliumNext/Trilium.git
cd Trilium
pnpm install
pnpm nx run edit-docs:edit-docs
pnpm edit-docs:edit-docs
```
### Building the Executable
@@ -149,27 +170,45 @@ Download the repository, install dependencies using `pnpm` and then build the de
git clone https://github.com/TriliumNext/Trilium.git
cd Trilium
pnpm install
pnpm nx --project=desktop electron-forge:make -- --arch=x64 --platform=win32
pnpm run --filter desktop electron-forge:make --arch=x64 --platform=win32
```
For more details, see the [development docs](https://github.com/TriliumNext/Notes/blob/develop/docs/Developer%20Guide/Developer%20Guide/Building%20and%20deployment/Running%20a%20development%20build.md).
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](./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.
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
* [CKEditor 5](https://github.com/ckeditor/ckeditor5) - best WYSIWYG editor on the market, very interactive and listening team
* [FancyTree](https://github.com/mar10/fancytree) - very feature rich tree library without real competition. Trilium Notes would not be the same without it.
* [CodeMirror](https://github.com/codemirror/CodeMirror) - code editor with support for huge amount of languages
* [jsPlumb](https://github.com/jsplumb/jsplumb) - visual connectivity library without competition. Used in [relation maps](https://triliumnext.github.io/Docs/Wiki/relation-map.html) and [link maps](https://triliumnext.github.io/Docs/Wiki/note-map.html#link-map)
* [zadam](https://github.com/zadam) for the original concept and implementation of the application.
* [Sarah Hussein](https://github.com/Sarah-Hussein) for designing the application icon.
* [nriver](https://github.com/nriver) for his work on internationalization.
* [Thomas Frei](https://github.com/thfrei) for his original work on the Canvas.
* [antoniotejada](https://github.com/nriver) for the original syntax highlight widget.
* [Dosu](https://dosu.dev/) for providing us with the automated responses to GitHub issues and discussions.
* [Tabler Icons](https://tabler.io/icons) for the system tray icons.
Trilium would not be possible without the technologies behind it:
* [CKEditor 5](https://github.com/ckeditor/ckeditor5) - the visual editor behind text notes. We are grateful for being offered a set of the premium features.
* [CodeMirror](https://github.com/codemirror/CodeMirror) - code editor with support for huge amount of languages.
* [Excalidraw](https://github.com/excalidraw/excalidraw) - the infinite whiteboard used in Canvas notes.
* [Mind Elixir](https://github.com/SSShooter/mind-elixir-core) - providing the mind map functionality.
* [Leaflet](https://github.com/Leaflet/Leaflet) - for rendering geographical maps.
* [Tabulator](https://github.com/olifolkerd/tabulator) - for the interactive table used in collections.
* [FancyTree](https://github.com/mar10/fancytree) - feature-rich tree library without real competition.
* [jsPlumb](https://github.com/jsplumb/jsplumb) - visual connectivity library. Used in [relation maps](https://triliumnext.github.io/Docs/Wiki/relation-map.html) and [link maps](https://triliumnext.github.io/Docs/Wiki/note-map.html#link-map)
## 🤝 Support
Support for the TriliumNext organization will be possible in the near future. For now, you can:
- Support continued development on TriliumNext by supporting our developers: [eliandoran](https://github.com/sponsors/eliandoran) (See the [repository insights]([developers]([url](https://github.com/TriliumNext/Notes/graphs/contributors))) for a full list)
- Show a token of gratitude to the original Trilium developer ([zadam](https://github.com/sponsors/zadam)) via [PayPal](https://paypal.me/za4am) or Bitcoin (bitcoin:bc1qv3svjn40v89mnkre5vyvs2xw6y8phaltl385d2).
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

View File

@@ -35,22 +35,20 @@
"chore:generate-openapi": "tsx bin/generate-openapi.js"
},
"devDependencies": {
"@playwright/test": "1.54.2",
"@stylistic/eslint-plugin": "5.2.3",
"@types/express": "5.0.3",
"@types/node": "22.17.1",
"@types/yargs": "17.0.33",
"@playwright/test": "1.56.1",
"@stylistic/eslint-plugin": "5.5.0",
"@types/express": "5.0.5",
"@types/node": "24.10.0",
"@types/yargs": "17.0.34",
"@vitest/coverage-v8": "3.2.4",
"eslint": "9.33.0",
"eslint": "9.39.0",
"eslint-plugin-simple-import-sort": "12.1.1",
"esm": "3.2.25",
"jsdoc": "4.0.4",
"jsdoc": "4.0.5",
"lorem-ipsum": "2.0.8",
"rcedit": "4.0.1",
"rimraf": "6.0.1",
"tslib": "2.8.1",
"typedoc": "0.28.10",
"typedoc-plugin-missing-exports": "4.1.0"
"rimraf": "6.1.0",
"tslib": "2.8.1"
},
"optionalDependencies": {
"appdmg": "0.6.6"

View File

@@ -1,4 +1,3 @@
import type child_process from "child_process";
import { describe, beforeAll, afterAll } from "vitest";
let etapiAuthToken: string | undefined;
@@ -12,8 +11,6 @@ type SpecDefinitionsFunc = () => void;
function describeEtapi(description: string, specDefinitions: SpecDefinitionsFunc): void {
describe(description, () => {
let appProcess: ReturnType<typeof child_process.spawn>;
beforeAll(async () => {});
afterAll(() => {});

View File

@@ -1,15 +0,0 @@
{
"entryPoints": [
"src/services/backend_script_entrypoint.ts",
"src/public/app/services/frontend_script_entrypoint.ts"
],
"plugin": [
"typedoc-plugin-missing-exports"
],
"outputs": [
{
"name": "html",
"path": "./docs/Script API"
}
]
}

View File

@@ -0,0 +1,22 @@
{
"name": "build-docs",
"version": "1.0.0",
"description": "",
"main": "src/main.ts",
"scripts": {
"start": "tsx ."
},
"keywords": [],
"author": "Elian Doran <contact@eliandoran.me>",
"license": "AGPL-3.0-only",
"packageManager": "pnpm@10.20.0",
"devDependencies": {
"@redocly/cli": "2.10.0",
"archiver": "7.0.1",
"fs-extra": "11.3.2",
"react": "19.2.0",
"react-dom": "19.2.0",
"typedoc": "0.28.14",
"typedoc-plugin-missing-exports": "4.1.2"
}
}

View File

@@ -0,0 +1,36 @@
/**
* The backend script API is accessible to code notes with the "JS (backend)" language.
*
* The entire API is exposed as a single global: {@link api}
*
* @module Backend Script API
*/
/**
* This file creates the entrypoint for TypeDoc that simulates the context from within a
* script note on the server side.
*
* Make sure to keep in line with backend's `script_context.ts`.
*/
export type { default as AbstractBeccaEntity } from "../../server/src/becca/entities/abstract_becca_entity.js";
export type { default as BAttachment } from "../../server/src/becca/entities/battachment.js";
export type { default as BAttribute } from "../../server/src/becca/entities/battribute.js";
export type { default as BBranch } from "../../server/src/becca/entities/bbranch.js";
export type { default as BEtapiToken } from "../../server/src/becca/entities/betapi_token.js";
export type { BNote };
export type { default as BOption } from "../../server/src/becca/entities/boption.js";
export type { default as BRecentNote } from "../../server/src/becca/entities/brecent_note.js";
export type { default as BRevision } from "../../server/src/becca/entities/brevision.js";
import BNote from "../../server/src/becca/entities/bnote.js";
import BackendScriptApi, { type Api } from "../../server/src/services/backend_script_api.js";
export type { Api };
const fakeNote = new BNote();
/**
* The `api` global variable allows access to the backend script API, which is documented in {@link Api}.
*/
export const api: Api = new BackendScriptApi(fakeNote, {});

View File

@@ -0,0 +1,145 @@
process.env.TRILIUM_INTEGRATION_TEST = "memory-no-store";
process.env.TRILIUM_RESOURCE_DIR = "../server/src";
process.env.NODE_ENV = "development";
import cls from "@triliumnext/server/src/services/cls.js";
import { dirname, join, resolve } from "path";
import * as fs from "fs/promises";
import * as fsExtra from "fs-extra";
import archiver from "archiver";
import { WriteStream } from "fs";
import { execSync } from "child_process";
import BuildContext from "./context.js";
const DOCS_ROOT = "../../../docs";
const OUTPUT_DIR = "../../site";
async function importAndExportDocs(sourcePath: string, outputSubDir: string) {
const note = await importData(sourcePath);
// Use a meaningful name for the temporary zip file
const zipName = outputSubDir || "user-guide";
const zipFilePath = `output-${zipName}.zip`;
try {
const { exportToZip } = (await import("@triliumnext/server/src/services/export/zip.js")).default;
const branch = note.getParentBranches()[0];
const taskContext = new (await import("@triliumnext/server/src/services/task_context.js")).default(
"no-progress-reporting",
"export",
null
);
const fileOutputStream = fsExtra.createWriteStream(zipFilePath);
await exportToZip(taskContext, branch, "share", fileOutputStream);
await waitForStreamToFinish(fileOutputStream);
// Output to root directory if outputSubDir is empty, otherwise to subdirectory
const outputPath = outputSubDir ? join(OUTPUT_DIR, outputSubDir) : OUTPUT_DIR;
await extractZip(zipFilePath, outputPath);
} finally {
if (await fsExtra.exists(zipFilePath)) {
await fsExtra.rm(zipFilePath);
}
}
}
async function buildDocsInner() {
const i18n = await import("@triliumnext/server/src/services/i18n.js");
await i18n.initializeTranslations();
const sqlInit = (await import("../../server/src/services/sql_init.js")).default;
await sqlInit.createInitialDatabase(true);
// Wait for becca to be loaded before importing data
const beccaLoader = await import("../../server/src/becca/becca_loader.js");
await beccaLoader.beccaLoaded;
// Build User Guide
console.log("Building User Guide...");
await importAndExportDocs(join(__dirname, DOCS_ROOT, "User Guide"), "");
// Build Developer Guide
console.log("Building Developer Guide...");
await importAndExportDocs(join(__dirname, DOCS_ROOT, "Developer Guide"), "developer-guide");
// Copy favicon.
await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "favicon.ico"));
console.log("Documentation built successfully!");
}
export async function importData(path: string) {
const buffer = await createImportZip(path);
const importService = (await import("../../server/src/services/import/zip.js")).default;
const TaskContext = (await import("../../server/src/services/task_context.js")).default;
const context = new TaskContext("no-progress-reporting", "importNotes", null);
const becca = (await import("../../server/src/becca/becca.js")).default;
const rootNote = becca.getRoot();
if (!rootNote) {
throw new Error("Missing root note for import.");
}
return await importService.importZip(context, buffer, rootNote, {
preserveIds: true
});
}
async function createImportZip(path: string) {
const inputFile = "input.zip";
const archive = archiver("zip", {
zlib: { level: 0 }
});
console.log("Archive path is ", resolve(path))
archive.directory(path, "/");
const outputStream = fsExtra.createWriteStream(inputFile);
archive.pipe(outputStream);
archive.finalize();
await waitForStreamToFinish(outputStream);
try {
return await fsExtra.readFile(inputFile);
} finally {
await fsExtra.rm(inputFile);
}
}
function waitForStreamToFinish(stream: WriteStream) {
return new Promise<void>((res, rej) => {
stream.on("finish", () => res());
stream.on("error", (err) => rej(err));
});
}
export async function extractZip(zipFilePath: string, outputPath: string, ignoredFiles?: Set<string>) {
const { readZipFile, readContent } = (await import("@triliumnext/server/src/services/import/zip.js"));
await readZipFile(await fs.readFile(zipFilePath), async (zip, entry) => {
// We ignore directories since they can appear out of order anyway.
if (!entry.fileName.endsWith("/") && !ignoredFiles?.has(entry.fileName)) {
const destPath = join(outputPath, entry.fileName);
const fileContent = await readContent(zip, entry);
await fsExtra.mkdirs(dirname(destPath));
await fs.writeFile(destPath, fileContent);
}
zip.readEntry();
});
}
export default async function buildDocs({ gitRootDir }: BuildContext) {
// Build the share theme.
execSync(`pnpm run --filter share-theme build`, {
stdio: "inherit",
cwd: gitRootDir
});
// Trigger the actual build.
await new Promise((res, rej) => {
cls.init(() => {
buildDocsInner()
.catch(rej)
.then(res);
});
});
}

View File

@@ -0,0 +1,4 @@
export default interface BuildContext {
gitRootDir: string;
baseDir: string;
}

View File

@@ -0,0 +1,28 @@
/**
* The front script API is accessible to code notes with the "JS (frontend)" language.
*
* The entire API is exposed as a single global: {@link api}
*
* @module Frontend Script API
*/
/**
* This file creates the entrypoint for TypeDoc that simulates the context from within a
* script note.
*
* Make sure to keep in line with frontend's `script_context.ts`.
*/
export type { default as BasicWidget } from "../../client/src/widgets/basic_widget.js";
export type { default as FAttachment } from "../../client/src/entities/fattachment.js";
export type { default as FAttribute } from "../../client/src/entities/fattribute.js";
export type { default as FBranch } from "../../client/src/entities/fbranch.js";
export type { default as FNote } from "../../client/src/entities/fnote.js";
export type { Api } from "../../client/src/services/frontend_script_api.js";
export type { default as NoteContextAwareWidget } from "../../client/src/widgets/note_context_aware_widget.js";
export type { default as RightPanelWidget } from "../../client/src/widgets/right_panel_widget.js";
import FrontendScriptApi, { type Api } from "../../client/src/services/frontend_script_api.js";
//@ts-expect-error
export const api: Api = new FrontendScriptApi();

View File

@@ -0,0 +1,26 @@
import { join } from "path";
import BuildContext from "./context";
import buildSwagger from "./swagger";
import { existsSync, mkdirSync, rmSync } from "fs";
import buildDocs from "./build-docs";
import buildScriptApi from "./script-api";
const context: BuildContext = {
gitRootDir: join(__dirname, "../../../"),
baseDir: join(__dirname, "../../../site")
};
async function main() {
// Clean input dir.
if (existsSync(context.baseDir)) {
rmSync(context.baseDir, { recursive: true });
}
mkdirSync(context.baseDir);
// Start building.
await buildDocs(context);
buildSwagger(context);
buildScriptApi(context);
}
main();

View File

@@ -0,0 +1,15 @@
import { execSync } from "child_process";
import BuildContext from "./context";
import { join } from "path";
export default function buildScriptApi({ baseDir, gitRootDir }: BuildContext) {
// Generate types
execSync(`pnpm typecheck`, { stdio: "inherit", cwd: gitRootDir });
for (const config of [ "backend", "frontend" ]) {
const outDir = join(baseDir, "script-api", config);
execSync(`pnpm typedoc --options typedoc.${config}.json --html "${outDir}"`, {
stdio: "inherit"
});
}
}

View File

@@ -0,0 +1,32 @@
import BuildContext from "./context";
import { join } from "path";
import { execSync } from "child_process";
import { mkdirSync } from "fs";
interface BuildInfo {
specPath: string;
outDir: string;
}
const DIR_PREFIX = "rest-api";
const buildInfos: BuildInfo[] = [
{
// Paths are relative to Git root.
specPath: "apps/server/internal.openapi.yaml",
outDir: `${DIR_PREFIX}/internal`
},
{
specPath: "apps/server/etapi.openapi.yaml",
outDir: `${DIR_PREFIX}/etapi`
}
];
export default function buildSwagger({ baseDir, gitRootDir }: BuildContext) {
for (const { specPath, outDir } of buildInfos) {
const absSpecPath = join(gitRootDir, specPath);
const targetDir = join(baseDir, outDir);
mkdirSync(targetDir, { recursive: true });
execSync(`pnpm redocly build-docs ${absSpecPath} -o ${targetDir}/index.html`, { stdio: "inherit" });
}
}

View File

@@ -0,0 +1,36 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "bundler",
"target": "ES2020",
"outDir": "dist",
"strict": false,
"types": [
"node",
"express"
],
"rootDir": "src",
"tsBuildInfoFile": "dist/tsconfig.app.tsbuildinfo"
},
"include": [
"src/**/*.ts",
"../server/src/*.d.ts"
],
"exclude": [
"eslint.config.js",
"eslint.config.cjs",
"eslint.config.mjs"
],
"references": [
{
"path": "../server/tsconfig.app.json"
},
{
"path": "../desktop/tsconfig.app.json"
},
{
"path": "../client/tsconfig.app.json"
}
]
}

View File

@@ -0,0 +1,15 @@
{
"extends": "../../tsconfig.base.json",
"include": [],
"references": [
{
"path": "../server"
},
{
"path": "../client"
},
{
"path": "./tsconfig.app.json"
}
]
}

View File

@@ -0,0 +1,10 @@
{
"$schema": "https://typedoc.org/schema.json",
"name": "Trilium Backend API",
"entryPoints": [
"src/backend_script_entrypoint.ts"
],
"plugin": [
"typedoc-plugin-missing-exports"
]
}

View File

@@ -0,0 +1,10 @@
{
"$schema": "https://typedoc.org/schema.json",
"name": "Trilium Frontend API",
"entryPoints": [
"src/frontend_script_entrypoint.ts"
],
"plugin": [
"typedoc-plugin-missing-exports"
]
}

View File

@@ -1,5 +1,4 @@
# The development license key for premium CKEditor features.
# Note: This key must only be used for the Trilium Notes project.
# Expires on: 2025-09-13
VITE_CKEDITOR_KEY=eyJhbGciOiJFUzI1NiJ9.eyJleHAiOjE3NTc3MjE1OTksImp0aSI6ImFiN2E0NjZmLWJlZGMtNDNiYy1iMzU4LTk0NGQ0YWJhY2I3ZiIsImRpc3RyaWJ1dGlvbkNoYW5uZWwiOlsic2giLCJkcnVwYWwiXSwid2hpdGVMYWJlbCI6dHJ1ZSwiZmVhdHVyZXMiOlsiRFJVUCIsIkNNVCIsIkRPIiwiRlAiLCJTQyIsIlRPQyIsIlRQTCIsIlBPRSIsIkNDIiwiTUYiLCJTRUUiLCJFQ0giLCJFSVMiXSwidmMiOiI1MzlkOWY5YyJ9.2rvKPql4hmukyXhEtWPZ8MLxKvzPIwzCdykO653g7IxRRZy2QJpeRszElZx9DakKYZKXekVRAwQKgHxwkgbE_w
VITE_CKEDITOR_KEY=eyJhbGciOiJFUzI1NiJ9.eyJleHAiOjE3ODcyNzA0MDAsImp0aSI6IjkyMWE1MWNlLTliNDMtNGRlMC1iOTQwLTc5ZjM2MDBkYjg1NyIsImRpc3RyaWJ1dGlvbkNoYW5uZWwiOiJ0cmlsaXVtIiwiZmVhdHVyZXMiOlsiVFJJTElVTSJdLCJ2YyI6ImU4YzRhMjBkIn0.hny77p-U4-jTkoqbwPytrEar5ylGCWBN7Ez3SlB8i6_mJCBIeCSTOlVQk_JMiOEq3AGykUMHzWXzjdMFwgniOw
VITE_CKEDITOR_ENABLE_INSPECTOR=false

View File

@@ -1,16 +1,21 @@
{
"name": "@triliumnext/client",
"version": "0.97.2",
"version": "0.99.3",
"description": "JQuery-based client for TriliumNext, used for both web and desktop (via Electron)",
"private": true,
"license": "AGPL-3.0-only",
"author": {
"name": "Trilium Notes Team",
"email": "contact@eliandoran.me",
"url": "https://github.com/TriliumNext/Notes"
"url": "https://github.com/TriliumNext/Trilium"
},
"scripts": {
"build": "cross-env NODE_OPTIONS=--max-old-space-size=4096 vite build",
"test": "vitest",
"circular-deps": "dpdm -T src/**/*.ts --tree=false --warning=false --skip-dynamic-imports=circular"
},
"dependencies": {
"@eslint/js": "9.33.0",
"@eslint/js": "9.39.0",
"@excalidraw/excalidraw": "0.18.0",
"@fullcalendar/core": "6.1.19",
"@fullcalendar/daygrid": "6.1.19",
@@ -19,7 +24,7 @@
"@fullcalendar/multimonth": "6.1.19",
"@fullcalendar/timegrid": "6.1.19",
"@maplibre/maplibre-gl-leaflet": "0.1.3",
"@mermaid-js/layout-elk": "0.1.8",
"@mermaid-js/layout-elk": "0.2.0",
"@mind-elixir/node-menu": "5.0.0",
"@popperjs/core": "2.11.8",
"@triliumnext/ckeditor5": "workspace:*",
@@ -27,62 +32,52 @@
"@triliumnext/commons": "workspace:*",
"@triliumnext/highlightjs": "workspace:*",
"@triliumnext/share-theme": "workspace:*",
"@triliumnext/split.js": "workspace:*",
"autocomplete.js": "0.38.1",
"bootstrap": "5.3.7",
"bootstrap": "5.3.8",
"boxicons": "2.1.4",
"dayjs": "1.11.13",
"color": "5.0.2",
"dayjs": "1.11.19",
"dayjs-plugin-utc": "0.1.2",
"debounce": "2.2.0",
"debounce": "3.0.0",
"draggabilly": "3.0.0",
"force-graph": "1.50.1",
"globals": "16.3.0",
"i18next": "25.3.4",
"force-graph": "1.51.0",
"globals": "16.5.0",
"i18next": "25.6.0",
"i18next-http-backend": "3.0.2",
"jquery": "3.7.1",
"jquery.fancytree": "2.38.5",
"jsplumb": "2.15.6",
"katex": "0.16.22",
"katex": "0.16.25",
"knockout": "3.5.1",
"leaflet": "1.9.4",
"leaflet-gpx": "2.2.0",
"mark.js": "8.11.1",
"marked": "16.1.2",
"mermaid": "11.9.0",
"mind-elixir": "5.0.5",
"marked": "16.4.1",
"mermaid": "11.12.1",
"mind-elixir": "5.3.4",
"normalize.css": "8.0.1",
"panzoom": "9.4.3",
"preact": "10.27.0",
"split.js": "1.6.5",
"preact": "10.27.2",
"react-i18next": "16.2.3",
"reveal.js": "5.2.1",
"svg-pan-zoom": "3.6.2",
"tabulator-tables": "6.3.1",
"vanilla-js-wheel-zoom": "9.0.4",
"photoswipe": "^5.4.4"
"vanilla-js-wheel-zoom": "9.0.4"
},
"devDependencies": {
"@ckeditor/ckeditor5-inspector": "5.0.0",
"@preact/preset-vite": "2.10.2",
"@types/bootstrap": "5.2.10",
"@types/jquery": "3.5.32",
"@types/leaflet": "1.9.20",
"@types/leaflet-gpx": "1.3.7",
"@types/jquery": "3.5.33",
"@types/leaflet": "1.9.21",
"@types/leaflet-gpx": "1.3.8",
"@types/mark.js": "8.11.12",
"@types/tabulator-tables": "6.2.10",
"@types/reveal.js": "5.2.1",
"@types/tabulator-tables": "6.3.0",
"copy-webpack-plugin": "13.0.1",
"happy-dom": "18.0.1",
"happy-dom": "20.0.10",
"script-loader": "0.7.2",
"vite-plugin-static-copy": "3.1.1"
},
"nx": {
"name": "client",
"targets": {
"serve": {
"dependsOn": [
"^build"
]
},
"circular-deps": {
"command": "pnpx dpdm -T {projectRoot}/src/**/*.ts --tree=false --warning=false --skip-dynamic-imports=circular"
}
}
"vite-plugin-static-copy": "3.1.4"
}
}

View File

@@ -7,6 +7,9 @@
"display": "standalone",
"scope": "/",
"start_url": "/",
"display_override": [
"window-controls-overlay"
],
"icons": [
{
"src": "icon.png",

View File

@@ -1,6 +1,6 @@
import froca from "../services/froca.js";
import RootCommandExecutor from "./root_command_executor.js";
import Entrypoints, { type SqlExecuteResults } from "./entrypoints.js";
import Entrypoints from "./entrypoints.js";
import options from "../services/options.js";
import utils, { hasTouchBar } from "../services/utils.js";
import zoomComponent from "./zoom.js";
@@ -31,16 +31,14 @@ import { StartupChecks } from "./startup_checks.js";
import type { CreateNoteOpts } from "../services/note_create.js";
import { ColumnComponent } from "tabulator-tables";
import { ChooseNoteTypeCallback } from "../widgets/dialogs/note_type_chooser.jsx";
import type RootContainer from "../widgets/containers/root_container.js";
import { SqlExecuteResults } from "@triliumnext/commons";
interface Layout {
getRootWidget: (appContext: AppContext) => RootWidget;
getRootWidget: (appContext: AppContext) => RootContainer;
}
interface RootWidget extends Component {
render: () => JQuery<HTMLElement>;
}
interface BeforeUploadListener extends Component {
export interface BeforeUploadListener extends Component {
beforeUnloadEvent(): boolean;
}
@@ -85,7 +83,6 @@ export type CommandMappings = {
focusTree: CommandData;
focusOnTitle: CommandData;
focusOnDetail: CommandData;
focusOnSearchDefinition: Required<CommandData>;
searchNotes: CommandData & {
searchString?: string;
ancestorNoteId?: string | null;
@@ -93,6 +90,11 @@ export type CommandMappings = {
closeTocCommand: CommandData;
closeHlt: CommandData;
showLaunchBarSubtree: CommandData;
showHiddenSubtree: CommandData;
showSQLConsoleHistory: CommandData;
logout: CommandData;
switchToMobileVersion: CommandData;
switchToDesktopVersion: CommandData;
showRevisions: CommandData & {
noteId?: string | null;
};
@@ -114,7 +116,7 @@ export type CommandMappings = {
openedFileUpdated: CommandData & {
entityType: string;
entityId: string;
lastModifiedMs: number;
lastModifiedMs?: number;
filePath: string;
};
focusAndSelectTitle: CommandData & {
@@ -138,6 +140,7 @@ export type CommandMappings = {
showLeftPane: CommandData;
showAttachments: CommandData;
showSearchHistory: CommandData;
showShareSubtree: CommandData;
hoistNote: CommandData & { noteId: string };
leaveProtectedSession: CommandData;
enterProtectedSession: CommandData;
@@ -215,12 +218,12 @@ export type CommandMappings = {
/** Works only in the electron context menu. */
replaceMisspelling: CommandData;
importMarkdownInline: CommandData;
showPasswordNotSet: CommandData;
showProtectedSessionPasswordDialog: CommandData;
showUploadAttachmentsDialog: CommandData & { noteId: string };
showIncludeNoteDialog: CommandData & { textTypeWidget: EditableTextTypeWidget };
showAddLinkDialog: CommandData & { textTypeWidget: EditableTextTypeWidget, text: string };
showPasteMarkdownDialog: CommandData & { textTypeWidget: EditableTextTypeWidget };
closeProtectedSessionPasswordDialog: CommandData;
copyImageReferenceToClipboard: CommandData;
copyImageToClipboard: CommandData;
@@ -267,6 +270,7 @@ export type CommandMappings = {
closeThisNoteSplit: CommandData;
moveThisNoteSplit: CommandData & { isMovingLeft: boolean };
jumpToNote: CommandData;
openTodayNote: CommandData;
commandPalette: CommandData;
// Keyboard shortcuts
@@ -323,6 +327,7 @@ export type CommandMappings = {
printActiveNote: CommandData;
exportAsPdf: CommandData;
openNoteExternally: CommandData;
openNoteCustom: CommandData;
renderActiveNote: CommandData;
unhoist: CommandData;
reloadFrontendApp: CommandData;
@@ -526,7 +531,7 @@ export type FilteredCommandNames<T extends CommandData> = keyof Pick<CommandMapp
export class AppContext extends Component {
isMainWindow: boolean;
components: Component[];
beforeUnloadListeners: WeakRef<BeforeUploadListener>[];
beforeUnloadListeners: (WeakRef<BeforeUploadListener> | (() => boolean))[];
tabManager!: TabManager;
layout?: Layout;
noteTreeWidget?: NoteTreeWidget;
@@ -619,7 +624,7 @@ export class AppContext extends Component {
component.triggerCommand(commandName, { $el: $(this) });
});
this.child(rootWidget);
this.child(rootWidget as Component);
this.triggerEvent("initialRenderComplete", {});
}
@@ -646,16 +651,20 @@ export class AppContext extends Component {
}
getComponentByEl(el: HTMLElement) {
return $(el).closest(".component").prop("component");
return $(el).closest("[data-component-id]").prop("component");
}
addBeforeUnloadListener(obj: BeforeUploadListener) {
addBeforeUnloadListener(obj: BeforeUploadListener | (() => boolean)) {
if (typeof WeakRef !== "function") {
// older browsers don't support WeakRef
return;
}
this.beforeUnloadListeners.push(new WeakRef<BeforeUploadListener>(obj));
if (typeof obj === "object") {
this.beforeUnloadListeners.push(new WeakRef<BeforeUploadListener>(obj));
} else {
this.beforeUnloadListeners.push(obj);
}
}
}
@@ -665,25 +674,29 @@ const appContext = new AppContext(window.glob.isMainWindow);
$(window).on("beforeunload", () => {
let allSaved = true;
appContext.beforeUnloadListeners = appContext.beforeUnloadListeners.filter((wr) => !!wr.deref());
appContext.beforeUnloadListeners = appContext.beforeUnloadListeners.filter((wr) => typeof wr === "function" || !!wr.deref());
for (const weakRef of appContext.beforeUnloadListeners) {
const component = weakRef.deref();
for (const listener of appContext.beforeUnloadListeners) {
if (typeof listener === "object") {
const component = listener.deref();
if (!component) {
continue;
}
if (!component) {
continue;
}
if (!component.beforeUnloadEvent()) {
console.log(`Component ${component.componentId} is not finished saving its state.`);
toast.showMessage(t("app_context.please_wait_for_save"), 10000);
allSaved = false;
if (!component.beforeUnloadEvent()) {
console.log(`Component ${component.componentId} is not finished saving its state.`);
allSaved = false;
}
} else {
if (!listener()) {
allSaved = false;
}
}
}
if (!allSaved) {
toast.showMessage(t("app_context.please_wait_for_save"), 10000);
return "some string";
}
});

View File

@@ -1,6 +1,8 @@
import utils from "../services/utils.js";
import type { CommandMappings, CommandNames, EventData, EventNames } from "./app_context.js";
type EventHandler = ((data: any) => void);
/**
* Abstract class for all components in the Trilium's frontend.
*
@@ -19,6 +21,7 @@ export class TypedComponent<ChildT extends TypedComponent<ChildT>> {
initialized: Promise<void> | null;
parent?: TypedComponent<any>;
_position!: number;
private listeners: Record<string, EventHandler[]> | null = {};
constructor() {
this.componentId = `${this.sanitizedClassName}-${utils.randomString(8)}`;
@@ -76,6 +79,14 @@ export class TypedComponent<ChildT extends TypedComponent<ChildT>> {
handleEventInChildren<T extends EventNames>(name: T, data: EventData<T>): Promise<unknown[] | unknown> | null {
const promises: Promise<unknown>[] = [];
// Handle React children.
if (this.listeners?.[name]) {
for (const listener of this.listeners[name]) {
listener(data);
}
}
// Handle legacy children.
for (const child of this.children) {
const ret = child.handleEvent(name, data) as Promise<void>;
@@ -120,6 +131,35 @@ export class TypedComponent<ChildT extends TypedComponent<ChildT>> {
return promise;
}
registerHandler<T extends EventNames>(name: T, handler: EventHandler) {
if (!this.listeners) {
this.listeners = {};
}
if (!this.listeners[name]) {
this.listeners[name] = [];
}
if (this.listeners[name].includes(handler)) {
return;
}
this.listeners[name].push(handler);
}
removeHandler<T extends EventNames>(name: T, handler: EventHandler) {
if (!this.listeners?.[name]?.includes(handler)) {
return;
}
this.listeners[name] = this.listeners[name]
.filter(listener => listener !== handler);
if (!this.listeners[name].length) {
delete this.listeners[name];
}
}
}
export default class Component extends TypedComponent<Component> {}

View File

@@ -10,22 +10,7 @@ import bundleService from "../services/bundle.js";
import froca from "../services/froca.js";
import linkService from "../services/link.js";
import { t } from "../services/i18n.js";
import type FNote from "../entities/fnote.js";
// TODO: Move somewhere else nicer.
export type SqlExecuteResults = string[][][];
// TODO: Deduplicate with server.
interface SqlExecuteResponse {
success: boolean;
error?: string;
results: SqlExecuteResults;
}
// TODO: Deduplicate with server.
interface CreateChildrenResponse {
note: FNote;
}
import { CreateChildrenResponse, SqlExecuteResponse } from "@triliumnext/commons";
export default class Entrypoints extends Component {
constructor() {
@@ -34,7 +19,7 @@ export default class Entrypoints extends Component {
openDevToolsCommand() {
if (utils.isElectron()) {
utils.dynamicRequire("@electron/remote").getCurrentWindow().toggleDevTools();
utils.dynamicRequire("@electron/remote").getCurrentWindow().webContents.toggleDevTools();
}
}
@@ -124,7 +109,7 @@ export default class Entrypoints extends Component {
if (utils.isElectron()) {
// standard JS version does not work completely correctly in electron
const webContents = utils.dynamicRequire("@electron/remote").getCurrentWebContents();
const activeIndex = parseInt(webContents.navigationHistory.getActiveIndex());
const activeIndex = webContents.navigationHistory.getActiveIndex();
webContents.goToIndex(activeIndex - 1);
} else {
@@ -136,7 +121,7 @@ export default class Entrypoints extends Component {
if (utils.isElectron()) {
// standard JS version does not work completely correctly in electron
const webContents = utils.dynamicRequire("@electron/remote").getCurrentWebContents();
const activeIndex = parseInt(webContents.navigationHistory.getActiveIndex());
const activeIndex = webContents.navigationHistory.getActiveIndex();
webContents.goToIndex(activeIndex + 1);
} else {
@@ -174,6 +159,16 @@ export default class Entrypoints extends Component {
this.openInWindowCommand({ notePath: "", hoistedNoteId: "root" });
}
async openTodayNoteCommand() {
const todayNote = await dateNoteService.getTodayNote();
if (!todayNote) {
console.warn("Missing today note.");
return;
}
await appContext.tabManager.openInSameTab(todayNote.noteId);
}
async runActiveNoteCommand() {
const noteContext = appContext.tabManager.getActiveContext();
if (!noteContext) {

View File

@@ -326,9 +326,11 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
}
// Collections must always display a note list, even if no children.
const viewType = note.getLabelValue("viewType") ?? "grid";
if (!["list", "grid"].includes(viewType)) {
return true;
if (note.type === "book") {
const viewType = note.getLabelValue("viewType") ?? "grid";
if (!["list", "grid"].includes(viewType)) {
return true;
}
}
if (!note.hasChildren()) {
@@ -438,4 +440,22 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
}
}
export function openInCurrentNoteContext(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent | React.PointerEvent<HTMLCanvasElement> | null, notePath: string, viewScope?: ViewScope) {
const ntxId = $(evt?.target as Element)
.closest("[data-ntx-id]")
.attr("data-ntx-id");
const noteContext = ntxId ? appContext.tabManager.getNoteContextById(ntxId) : appContext.tabManager.getActiveContext();
if (noteContext) {
noteContext.setNote(notePath, { viewScope }).then(() => {
if (noteContext !== appContext.tabManager.getActiveContext()) {
appContext.tabManager.activateNoteContext(noteContext.ntxId);
}
});
} else {
appContext.tabManager.openContextWithNote(notePath, { viewScope, activate: true });
}
}
export default NoteContext;

View File

@@ -43,8 +43,6 @@ export default class RootCommandExecutor extends Component {
const noteContext = await appContext.tabManager.openTabWithNoteWithHoisting(searchNote.noteId, {
activate: true
});
appContext.triggerCommand("focusOnSearchDefinition", { ntxId: noteContext.ntxId });
}
async searchInSubtreeCommand({ notePath }: CommandListenerData<"searchInSubtree">) {

View File

@@ -433,6 +433,9 @@ export default class TabManager extends Component {
$autocompleteEl.autocomplete("close");
}
// close dangling tooltips
$("body > div.tooltip").remove();
const noteContextsToRemove = noteContextToRemove.getSubContexts();
const ntxIdsToRemove = noteContextsToRemove.map((nc) => nc.ntxId);
@@ -600,18 +603,18 @@ export default class TabManager extends Component {
}
async moveTabToNewWindowCommand({ ntxId }: { ntxId: string }) {
const { notePath, hoistedNoteId } = this.getNoteContextById(ntxId);
const { notePath, hoistedNoteId, viewScope } = this.getNoteContextById(ntxId);
const removed = await this.removeNoteContext(ntxId);
if (removed) {
this.triggerCommand("openInWindow", { notePath, hoistedNoteId });
this.triggerCommand("openInWindow", { notePath, hoistedNoteId, viewScope });
}
}
async copyTabToNewWindowCommand({ ntxId }: { ntxId: string }) {
const { notePath, hoistedNoteId } = this.getNoteContextById(ntxId);
this.triggerCommand("openInWindow", { notePath, hoistedNoteId });
const { notePath, hoistedNoteId, viewScope } = this.getNoteContextById(ntxId);
this.triggerCommand("openInWindow", { notePath, hoistedNoteId, viewScope });
}
async reopenLastTabCommand() {

View File

@@ -23,11 +23,11 @@ export default class TouchBarComponent extends Component {
this.$widget = $("<div>");
$(window).on("focusin", async (e) => {
const $target = $(e.target);
const focusedEl = e.target as unknown as HTMLElement;
const $target = $(focusedEl);
this.$activeModal = $target.closest(".modal-dialog");
const parentComponentEl = $target.closest(".component");
this.lastFocusedComponent = appContext.getComponentByEl(parentComponentEl[0]);
this.lastFocusedComponent = appContext.getComponentByEl(focusedEl);
this.#refreshTouchBar();
});
}

View File

@@ -8,13 +8,9 @@ import electronContextMenu from "./menus/electron_context_menu.js";
import glob from "./services/glob.js";
import { t } from "./services/i18n.js";
import options from "./services/options.js";
import server from "./services/server.js";
import type ElectronRemote from "@electron/remote";
import type Electron from "electron";
import "./stylesheets/bootstrap.scss";
import "boxicons/css/boxicons.min.css";
import "./stylesheets/media-viewer.css";
import "./styles/gallery.css";
import "autocomplete.js/index_jquery.js";
await appContext.earlyInit();
@@ -48,6 +44,10 @@ if (utils.isElectron()) {
electronContextMenu.setupContextMenu();
}
if (utils.isPWA()) {
initPWATopbarColor();
}
function initOnElectron() {
const electron: typeof Electron = utils.dynamicRequire("electron");
electron.ipcRenderer.on("globalShortcut", async (event, actionName) => appContext.triggerCommand(actionName));
@@ -116,3 +116,20 @@ function initDarkOrLightMode(style: CSSStyleDeclaration) {
const { nativeTheme } = utils.dynamicRequire("@electron/remote") as typeof ElectronRemote;
nativeTheme.themeSource = themeSource;
}
function initPWATopbarColor() {
const tracker = $("#background-color-tracker");
if (tracker.length) {
const applyThemeColor = () => {
let meta = $("meta[name='theme-color']");
if (!meta.length) {
meta = $(`<meta name="theme-color">`).appendTo($("head"));
}
meta.attr("content", tracker.css("color"));
};
tracker.on("transitionend", applyThemeColor);
applyThemeColor();
}
}

View File

@@ -1,6 +1,5 @@
import server from "../services/server.js";
import noteAttributeCache from "../services/note_attribute_cache.js";
import ws from "../services/ws.js";
import protectedSessionHolder from "../services/protected_session_holder.js";
import cssClassManager from "../services/css_class_manager.js";
import type { Froca } from "../services/froca-interface.js";
@@ -64,7 +63,7 @@ export interface NoteMetaData {
/**
* Note is the main node and concept in Trilium.
*/
class FNote {
export default class FNote {
private froca: Froca;
noteId!: string;
@@ -256,18 +255,20 @@ class FNote {
return this.children;
}
async getSubtreeNoteIds() {
async getSubtreeNoteIds(includeArchived = false) {
let noteIds: (string | string[])[] = [];
for (const child of await this.getChildNotes()) {
if (child.isArchived && !includeArchived) continue;
noteIds.push(child.noteId);
noteIds.push(await child.getSubtreeNoteIds());
noteIds.push(await child.getSubtreeNoteIds(includeArchived));
}
return noteIds.flat();
}
async getSubtreeNotes() {
const noteIds = await this.getSubtreeNoteIds();
return this.froca.getNotes(noteIds);
return (await this.froca.getNotes(noteIds));
}
async getChildNotes() {
@@ -416,7 +417,7 @@ class FNote {
return notePaths;
}
getSortedNotePathRecords(hoistedNoteId = "root"): NotePathRecord[] {
getSortedNotePathRecords(hoistedNoteId = "root", activeNotePath: string | null = null): NotePathRecord[] {
const isHoistedRoot = hoistedNoteId === "root";
const notePaths: NotePathRecord[] = this.getAllNotePaths().map((path) => ({
@@ -427,7 +428,23 @@ class FNote {
isHidden: path.includes("_hidden")
}));
// Calculate the length of the prefix match between two arrays
const prefixMatchLength = (path: string[], target: string[]) => {
const diffIndex = path.findIndex((seg, i) => seg !== target[i]);
return diffIndex === -1 ? Math.min(path.length, target.length) : diffIndex;
};
notePaths.sort((a, b) => {
if (activeNotePath) {
const activeSegments = activeNotePath.split('/');
const aOverlap = prefixMatchLength(a.notePath, activeSegments);
const bOverlap = prefixMatchLength(b.notePath, activeSegments);
// Paths with more matching prefix segments are prioritized
// when the match count is equal, other criteria are used for sorting
if (bOverlap !== aOverlap) {
return bOverlap - aOverlap;
}
}
if (a.isInHoistedSubTree !== b.isInHoistedSubTree) {
return a.isInHoistedSubTree ? -1 : 1;
} else if (a.isArchived !== b.isArchived) {
@@ -448,10 +465,11 @@ class FNote {
* Returns the note path considered to be the "best"
*
* @param {string} [hoistedNoteId='root']
* @param {string|null} [activeNotePath=null]
* @return {string[]} array of noteIds constituting the particular note path
*/
getBestNotePath(hoistedNoteId = "root") {
return this.getSortedNotePathRecords(hoistedNoteId)[0]?.notePath;
getBestNotePath(hoistedNoteId = "root", activeNotePath: string | null = null) {
return this.getSortedNotePathRecords(hoistedNoteId, activeNotePath)[0]?.notePath;
}
/**
@@ -584,7 +602,7 @@ class FNote {
let childBranches = this.getChildBranches();
if (!childBranches) {
ws.logError(`No children for '${this.noteId}'. This shouldn't happen.`);
console.error(`No children for '${this.noteId}'. This shouldn't happen.`);
return [];
}
@@ -905,8 +923,8 @@ class FNote {
return this.getBlob();
}
async getBlob() {
return await this.froca.getBlob("notes", this.noteId);
getBlob() {
return this.froca.getBlob("notes", this.noteId);
}
toString() {
@@ -1020,6 +1038,14 @@ class FNote {
return this.noteId.startsWith("_options");
}
isTriliumSqlite() {
return this.mime === "text/x-sqlite;schema=trilium";
}
isTriliumScript() {
return this.mime.startsWith("application/javascript");
}
/**
* Provides note's date metadata.
*/
@@ -1027,5 +1053,3 @@ class FNote {
return await server.get<NoteMetaData>(`notes/${this.noteId}/metadata`);
}
}
export default FNote;

View File

@@ -1,78 +1,47 @@
import FlexContainer from "../widgets/containers/flex_container.js";
import GlobalMenuWidget from "../widgets/buttons/global_menu.js";
import TabRowWidget from "../widgets/tab_row.js";
import TitleBarButtonsWidget from "../widgets/title_bar_buttons.js";
import LeftPaneContainer from "../widgets/containers/left_pane_container.js";
import NoteTreeWidget from "../widgets/note_tree.js";
import NoteTitleWidget from "../widgets/note_title.js";
import OwnedAttributeListWidget from "../widgets/ribbon_widgets/owned_attribute_list.js";
import NoteActionsWidget from "../widgets/buttons/note_actions.js";
import NoteTitleWidget from "../widgets/note_title.jsx";
import NoteDetailWidget from "../widgets/note_detail.js";
import RibbonContainer from "../widgets/containers/ribbon_container.js";
import PromotedAttributesWidget from "../widgets/ribbon_widgets/promoted_attributes.js";
import InheritedAttributesWidget from "../widgets/ribbon_widgets/inherited_attribute_list.js";
import NoteListWidget from "../widgets/note_list.js";
import SearchDefinitionWidget from "../widgets/ribbon_widgets/search_definition.js";
import SqlResultWidget from "../widgets/sql_result.js";
import SqlTableSchemasWidget from "../widgets/sql_table_schemas.js";
import FilePropertiesWidget from "../widgets/ribbon_widgets/file_properties.js";
import ImagePropertiesWidget from "../widgets/ribbon_widgets/image_properties.js";
import NotePropertiesWidget from "../widgets/ribbon_widgets/note_properties.js";
import NoteIconWidget from "../widgets/note_icon.js";
import SearchResultWidget from "../widgets/search_result.js";
import PromotedAttributesWidget from "../widgets/promoted_attributes.js";
import NoteIconWidget from "../widgets/note_icon.jsx";
import ScrollingContainer from "../widgets/containers/scrolling_container.js";
import RootContainer from "../widgets/containers/root_container.js";
import WatchedFileUpdateStatusWidget from "../widgets/watched_file_update_status.js";
import SpacerWidget from "../widgets/spacer.js";
import QuickSearchWidget from "../widgets/quick_search.js";
import SplitNoteContainer from "../widgets/containers/split_note_container.js";
import LeftPaneToggleWidget from "../widgets/buttons/left_pane_toggle.js";
import CreatePaneButton from "../widgets/buttons/create_pane_button.js";
import ClosePaneButton from "../widgets/buttons/close_pane_button.js";
import BasicPropertiesWidget from "../widgets/ribbon_widgets/basic_properties.js";
import NoteInfoWidget from "../widgets/ribbon_widgets/note_info_widget.js";
import BookPropertiesWidget from "../widgets/ribbon_widgets/book_properties.js";
import NoteMapRibbonWidget from "../widgets/ribbon_widgets/note_map.js";
import NotePathsWidget from "../widgets/ribbon_widgets/note_paths.js";
import SimilarNotesWidget from "../widgets/ribbon_widgets/similar_notes.js";
import RightPaneContainer from "../widgets/containers/right_pane_container.js";
import EditButton from "../widgets/floating_buttons/edit_button.js";
import EditedNotesWidget from "../widgets/ribbon_widgets/edited_notes.js";
import ShowTocWidgetButton from "../widgets/buttons/show_toc_widget_button.js";
import ShowHighlightsListWidgetButton from "../widgets/buttons/show_highlights_list_widget_button.js";
import NoteWrapperWidget from "../widgets/note_wrapper.js";
import BacklinksWidget from "../widgets/floating_buttons/zpetne_odkazy.js";
import SharedInfoWidget from "../widgets/shared_info.js";
import FindWidget from "../widgets/find.js";
import TocWidget from "../widgets/toc.js";
import HighlightsListWidget from "../widgets/highlights_list.js";
import PasswordNoteSetDialog from "../widgets/dialogs/password_not_set.js";
import FloatingButtons from "../widgets/floating_buttons/floating_buttons.js";
import RelationMapButtons from "../widgets/floating_buttons/relation_map_buttons.js";
import SvgExportButton from "../widgets/floating_buttons/svg_export_button.js";
import LauncherContainer from "../widgets/containers/launcher_container.js";
import RevisionsButton from "../widgets/buttons/revisions_button.js";
import CodeButtonsWidget from "../widgets/floating_buttons/code_buttons.js";
import ApiLogWidget from "../widgets/api_log.js";
import HideFloatingButtonsButton from "../widgets/floating_buttons/hide_floating_buttons_button.js";
import ScriptExecutorWidget from "../widgets/ribbon_widgets/script_executor.js";
import MovePaneButton from "../widgets/buttons/move_pane_button.js";
import UploadAttachmentsDialog from "../widgets/dialogs/upload_attachments.js";
import CopyImageReferenceButton from "../widgets/floating_buttons/copy_image_reference_button.js";
import ScrollPaddingWidget from "../widgets/scroll_padding.js";
import ClassicEditorToolbar from "../widgets/ribbon_widgets/classic_editor_toolbar.js";
import ScrollPadding from "../widgets/scroll_padding.js";
import options from "../services/options.js";
import utils from "../services/utils.js";
import GeoMapButtons from "../widgets/floating_buttons/geo_map_button.js";
import ContextualHelpButton from "../widgets/floating_buttons/help_button.js";
import CloseZenButton from "../widgets/close_zen_button.js";
import type { AppContext } from "../components/app_context.js";
import type { WidgetsByParent } from "../services/bundle.js";
import SwitchSplitOrientationButton from "../widgets/floating_buttons/switch_layout_button.js";
import ToggleReadOnlyButton from "../widgets/floating_buttons/toggle_read_only_button.js";
import PngExportButton from "../widgets/floating_buttons/png_export_button.js";
import RefreshButton from "../widgets/floating_buttons/refresh_button.js";
import { applyModals } from "./layout_commons.js";
import Ribbon from "../widgets/ribbon/Ribbon.jsx";
import FloatingButtons from "../widgets/FloatingButtons.jsx";
import { DESKTOP_FLOATING_BUTTONS } from "../widgets/FloatingButtonsDefinitions.jsx";
import SearchResult from "../widgets/search_result.jsx";
import GlobalMenu from "../widgets/buttons/global_menu.jsx";
import SqlResults from "../widgets/sql_result.js";
import SqlTableSchemas from "../widgets/sql_table_schemas.js";
import TitleBarButtons from "../widgets/title_bar_buttons.jsx";
import LeftPaneToggle from "../widgets/buttons/left_pane_toggle.js";
import ApiLog from "../widgets/api_log.jsx";
import CloseZenModeButton from "../widgets/close_zen_button.jsx";
import SharedInfo from "../widgets/shared_info.jsx";
import NoteList from "../widgets/collections/NoteList.jsx";
export default class DesktopLayout {
@@ -107,9 +76,9 @@ export default class DesktopLayout {
new FlexContainer("row")
.class("tab-row-container")
.child(new FlexContainer("row").id("tab-row-left-spacer"))
.optChild(launcherPaneIsHorizontal, new LeftPaneToggleWidget(true))
.optChild(launcherPaneIsHorizontal, <LeftPaneToggle isHorizontalLayout={true} />)
.child(new TabRowWidget().class("full-width"))
.optChild(customTitleBarButtons, new TitleBarButtonsWidget())
.optChild(customTitleBarButtons, <TitleBarButtons />)
.css("height", "40px")
.css("background-color", "var(--launcher-pane-background-color)")
.setParent(appContext)
@@ -130,7 +99,7 @@ export default class DesktopLayout {
new FlexContainer("column")
.id("rest-pane")
.css("flex-grow", "1")
.optChild(!fullWidthTabBar, new FlexContainer("row").child(new TabRowWidget()).optChild(customTitleBarButtons, new TitleBarButtonsWidget()).css("height", "40px"))
.optChild(!fullWidthTabBar, new FlexContainer("row").child(new TabRowWidget()).optChild(customTitleBarButtons, <TitleBarButtons />).css("height", "40px"))
.child(
new FlexContainer("row")
.filling()
@@ -151,69 +120,30 @@ export default class DesktopLayout {
.css("min-height", "50px")
.css("align-items", "center")
.cssBlock(".title-row > * { margin: 5px; }")
.child(new NoteIconWidget())
.child(new NoteTitleWidget())
.child(<NoteIconWidget />)
.child(<NoteTitleWidget />)
.child(new SpacerWidget(0, 1))
.child(new MovePaneButton(true))
.child(new MovePaneButton(false))
.child(new ClosePaneButton())
.child(new CreatePaneButton())
.child(<MovePaneButton direction="left" />)
.child(<MovePaneButton direction="right" />)
.child(<ClosePaneButton />)
.child(<CreatePaneButton />)
)
.child(
new RibbonContainer()
// the order of the widgets matter. Some of these want to "activate" themselves
// when visible. When this happens to multiple of them, the first one "wins".
// promoted attributes should always win.
.ribbon(new ClassicEditorToolbar())
.ribbon(new ScriptExecutorWidget())
.ribbon(new SearchDefinitionWidget())
.ribbon(new EditedNotesWidget())
.ribbon(new BookPropertiesWidget())
.ribbon(new NotePropertiesWidget())
.ribbon(new FilePropertiesWidget())
.ribbon(new ImagePropertiesWidget())
.ribbon(new BasicPropertiesWidget())
.ribbon(new OwnedAttributeListWidget())
.ribbon(new InheritedAttributesWidget())
.ribbon(new NotePathsWidget())
.ribbon(new NoteMapRibbonWidget())
.ribbon(new SimilarNotesWidget())
.ribbon(new NoteInfoWidget())
.button(new RevisionsButton())
.button(new NoteActionsWidget())
)
.child(new SharedInfoWidget())
.child(<Ribbon />)
.child(<SharedInfo />)
.child(new WatchedFileUpdateStatusWidget())
.child(
new FloatingButtons()
.child(new RefreshButton())
.child(new SwitchSplitOrientationButton())
.child(new ToggleReadOnlyButton())
.child(new EditButton())
.child(new ShowTocWidgetButton())
.child(new ShowHighlightsListWidgetButton())
.child(new CodeButtonsWidget())
.child(new RelationMapButtons())
.child(new GeoMapButtons())
.child(new CopyImageReferenceButton())
.child(new SvgExportButton())
.child(new PngExportButton())
.child(new BacklinksWidget())
.child(new ContextualHelpButton())
.child(new HideFloatingButtonsButton())
)
.child(<FloatingButtons items={DESKTOP_FLOATING_BUTTONS} />)
.child(
new ScrollingContainer()
.filling()
.child(new PromotedAttributesWidget())
.child(new SqlTableSchemasWidget())
.child(<SqlTableSchemas />)
.child(new NoteDetailWidget())
.child(new NoteListWidget(false))
.child(new SearchResultWidget())
.child(new SqlResultWidget())
.child(new ScrollPaddingWidget())
.child(<NoteList media="screen" />)
.child(<SearchResult />)
.child(<SqlResults />)
.child(<ScrollPadding />)
)
.child(new ApiLogWidget())
.child(<ApiLog />)
.child(new FindWidget())
.child(
...this.customWidgets.get("node-detail-pane"), // typo, let's keep it for a while as BC
@@ -232,11 +162,11 @@ export default class DesktopLayout {
)
)
)
.child(new CloseZenButton())
.child(<CloseZenModeButton />)
// Desktop-specific dialogs.
.child(new PasswordNoteSetDialog())
.child(new UploadAttachmentsDialog());
.child(<PasswordNoteSetDialog />)
.child(<UploadAttachmentsDialog />);
applyModals(rootContainer);
return rootContainer;
@@ -246,14 +176,18 @@ export default class DesktopLayout {
let launcherPane;
if (isHorizontal) {
launcherPane = new FlexContainer("row").css("height", "53px").class("horizontal").child(new LauncherContainer(true)).child(new GlobalMenuWidget(true));
launcherPane = new FlexContainer("row")
.css("height", "53px")
.class("horizontal")
.child(new LauncherContainer(true))
.child(<GlobalMenu isHorizontalLayout={true} />);
} else {
launcherPane = new FlexContainer("column")
.css("width", "53px")
.class("vertical")
.child(new GlobalMenuWidget(false))
.child(<GlobalMenu isHorizontalLayout={false} />)
.child(new LauncherContainer(false))
.child(new LeftPaneToggleWidget(false));
.child(<LeftPaneToggle isHorizontalLayout={false} />);
}
launcherPane.id("launcher-pane");

View File

@@ -24,48 +24,49 @@ import InfoDialog from "../widgets/dialogs/info.js";
import IncorrectCpuArchDialog from "../widgets/dialogs/incorrect_cpu_arch.js";
import PopupEditorDialog from "../widgets/dialogs/popup_editor.js";
import FlexContainer from "../widgets/containers/flex_container.js";
import NoteIconWidget from "../widgets/note_icon.js";
import NoteTitleWidget from "../widgets/note_title.js";
import ClassicEditorToolbar from "../widgets/ribbon_widgets/classic_editor_toolbar.js";
import PromotedAttributesWidget from "../widgets/ribbon_widgets/promoted_attributes.js";
import NoteIconWidget from "../widgets/note_icon";
import PromotedAttributesWidget from "../widgets/promoted_attributes.js";
import NoteDetailWidget from "../widgets/note_detail.js";
import NoteListWidget from "../widgets/note_list.js";
import { CallToActionDialog } from "../widgets/dialogs/call_to_action.jsx";
import CallToActionDialog from "../widgets/dialogs/call_to_action.jsx";
import NoteTitleWidget from "../widgets/note_title.jsx";
import FormattingToolbar from "../widgets/ribbon/FormattingToolbar.js";
import NoteList from "../widgets/collections/NoteList.jsx";
import StandaloneRibbonAdapter from "../widgets/ribbon/components/StandaloneRibbonAdapter.jsx";
export function applyModals(rootContainer: RootContainer) {
rootContainer
.child(new BulkActionsDialog())
.child(new AboutDialog())
.child(new HelpDialog())
.child(new RecentChangesDialog())
.child(new BranchPrefixDialog())
.child(new SortChildNotesDialog())
.child(new IncludeNoteDialog())
.child(new NoteTypeChooserDialog())
.child(new JumpToNoteDialog())
.child(new AddLinkDialog())
.child(new CloneToDialog())
.child(new MoveToDialog())
.child(new ImportDialog())
.child(new ExportDialog())
.child(new MarkdownImportDialog())
.child(new ProtectedSessionPasswordDialog())
.child(new RevisionsDialog())
.child(new DeleteNotesDialog())
.child(new InfoDialog())
.child(new ConfirmDialog())
.child(new PromptDialog())
.child(new IncorrectCpuArchDialog())
.child(<BulkActionsDialog />)
.child(<AboutDialog />)
.child(<HelpDialog />)
.child(<RecentChangesDialog />)
.child(<BranchPrefixDialog />)
.child(<SortChildNotesDialog />)
.child(<IncludeNoteDialog />)
.child(<NoteTypeChooserDialog />)
.child(<JumpToNoteDialog />)
.child(<AddLinkDialog />)
.child(<CloneToDialog />)
.child(<MoveToDialog />)
.child(<ImportDialog />)
.child(<ExportDialog />)
.child(<MarkdownImportDialog />)
.child(<ProtectedSessionPasswordDialog />)
.child(<RevisionsDialog />)
.child(<DeleteNotesDialog />)
.child(<InfoDialog />)
.child(<ConfirmDialog />)
.child(<PromptDialog />)
.child(<IncorrectCpuArchDialog />)
.child(new PopupEditorDialog()
.child(new FlexContainer("row")
.class("title-row")
.css("align-items", "center")
.cssBlock(".title-row > * { margin: 5px; }")
.child(new NoteIconWidget())
.child(new NoteTitleWidget()))
.child(new ClassicEditorToolbar())
.child(<NoteIconWidget />)
.child(<NoteTitleWidget />))
.child(<StandaloneRibbonAdapter component={FormattingToolbar} />)
.child(new PromotedAttributesWidget())
.child(new NoteDetailWidget())
.child(new NoteListWidget(true)))
.child(new CallToActionDialog());
.child(<NoteList media="screen" displayOnlyCollections />))
.child(<CallToActionDialog />);
}

View File

@@ -3,30 +3,30 @@ import NoteTitleWidget from "../widgets/note_title.js";
import NoteDetailWidget from "../widgets/note_detail.js";
import QuickSearchWidget from "../widgets/quick_search.js";
import NoteTreeWidget from "../widgets/note_tree.js";
import ToggleSidebarButtonWidget from "../widgets/mobile_widgets/toggle_sidebar_button.js";
import MobileDetailMenuWidget from "../widgets/mobile_widgets/mobile_detail_menu.js";
import ScreenContainer from "../widgets/mobile_widgets/screen_container.js";
import ScrollingContainer from "../widgets/containers/scrolling_container.js";
import FilePropertiesWidget from "../widgets/ribbon_widgets/file_properties.js";
import FloatingButtons from "../widgets/floating_buttons/floating_buttons.js";
import EditButton from "../widgets/floating_buttons/edit_button.js";
import RelationMapButtons from "../widgets/floating_buttons/relation_map_buttons.js";
import SvgExportButton from "../widgets/floating_buttons/svg_export_button.js";
import BacklinksWidget from "../widgets/floating_buttons/zpetne_odkazy.js";
import HideFloatingButtonsButton from "../widgets/floating_buttons/hide_floating_buttons_button.js";
import NoteListWidget from "../widgets/note_list.js";
import GlobalMenuWidget from "../widgets/buttons/global_menu.js";
import LauncherContainer from "../widgets/containers/launcher_container.js";
import RootContainer from "../widgets/containers/root_container.js";
import SharedInfoWidget from "../widgets/shared_info.js";
import PromotedAttributesWidget from "../widgets/ribbon_widgets/promoted_attributes.js";
import PromotedAttributesWidget from "../widgets/promoted_attributes.js";
import SidebarContainer from "../widgets/mobile_widgets/sidebar_container.js";
import type AppContext from "../components/app_context.js";
import TabRowWidget from "../widgets/tab_row.js";
import RefreshButton from "../widgets/floating_buttons/refresh_button.js";
import MobileEditorToolbar from "../widgets/ribbon_widgets/mobile_editor_toolbar.js";
import MobileEditorToolbar from "../widgets/type_widgets/ckeditor/mobile_editor_toolbar.js";
import { applyModals } from "./layout_commons.js";
import CloseZenButton from "../widgets/close_zen_button.js";
import FilePropertiesTab from "../widgets/ribbon/FilePropertiesTab.jsx";
import { useNoteContext } from "../widgets/react/hooks.jsx";
import FloatingButtons from "../widgets/FloatingButtons.jsx";
import { MOBILE_FLOATING_BUTTONS } from "../widgets/FloatingButtonsDefinitions.jsx";
import ToggleSidebarButton from "../widgets/mobile_widgets/toggle_sidebar_button.jsx";
import CloseZenModeButton from "../widgets/close_zen_button.js";
import NoteWrapperWidget from "../widgets/note_wrapper.js";
import MobileDetailMenu from "../widgets/mobile_widgets/mobile_detail_menu.js";
import NoteList from "../widgets/collections/NoteList.jsx";
import StandaloneRibbonAdapter from "../widgets/ribbon/components/StandaloneRibbonAdapter.jsx";
import SearchDefinitionTab from "../widgets/ribbon/SearchDefinitionTab.jsx";
import SearchResult from "../widgets/search_result.jsx";
const MOBILE_CSS = `
<style>
@@ -43,8 +43,8 @@ kbd {
border: none;
cursor: pointer;
font-size: 1.25em;
padding-left: 0.5em;
padding-right: 0.5em;
padding-inline-start: 0.5em;
padding-inline-end: 0.5em;
color: var(--main-text-color);
}
.quick-search {
@@ -62,7 +62,7 @@ const FANCYTREE_CSS = `
margin-top: 0px;
overflow-y: auto;
contain: content;
padding-left: 10px;
padding-inline-start: 10px;
}
.fancytree-custom-icon {
@@ -71,7 +71,7 @@ const FANCYTREE_CSS = `
.fancytree-title {
font-size: 1.5em;
margin-left: 0.6em !important;
margin-inline-start: 0.6em !important;
}
.fancytree-node {
@@ -84,7 +84,7 @@ const FANCYTREE_CSS = `
span.fancytree-expander {
width: 24px !important;
margin-right: 5px;
margin-inline-end: 5px;
}
.fancytree-loading span.fancytree-expander {
@@ -104,7 +104,7 @@ span.fancytree-expander {
.tree-wrapper .scroll-to-active-note-button,
.tree-wrapper .tree-settings-button {
position: fixed;
margin-right: 16px;
margin-inline-end: 16px;
display: none;
}
@@ -129,44 +129,41 @@ export default class MobileLayout {
.class("d-md-flex d-lg-flex d-xl-flex col-12 col-sm-5 col-md-4 col-lg-3 col-xl-3")
.id("mobile-sidebar-wrapper")
.css("max-height", "100%")
.css("padding-left", "0")
.css("padding-right", "0")
.css("padding-inline-start", "0")
.css("padding-inline-end", "0")
.css("contain", "content")
.child(new FlexContainer("column").filling().id("mobile-sidebar-wrapper").child(new QuickSearchWidget()).child(new NoteTreeWidget().cssBlock(FANCYTREE_CSS)))
)
.child(
new ScreenContainer("detail", "column")
new ScreenContainer("detail", "row")
.id("detail-container")
.class("d-sm-flex d-md-flex d-lg-flex d-xl-flex col-12 col-sm-7 col-md-8 col-lg-9")
.child(
new FlexContainer("row")
.contentSized()
.css("font-size", "larger")
.css("align-items", "center")
.child(new ToggleSidebarButtonWidget().contentSized())
.child(new NoteTitleWidget().contentSized().css("position", "relative").css("padding-left", "0.5em"))
.child(new MobileDetailMenuWidget(true).contentSized())
new NoteWrapperWidget()
.child(
new FlexContainer("row")
.contentSized()
.css("font-size", "larger")
.css("align-items", "center")
.child(<ToggleSidebarButton />)
.child(<NoteTitleWidget />)
.child(<MobileDetailMenu />)
)
.child(<SharedInfoWidget />)
.child(<FloatingButtons items={MOBILE_FLOATING_BUTTONS} />)
.child(new PromotedAttributesWidget())
.child(
new ScrollingContainer()
.filling()
.contentSized()
.child(new NoteDetailWidget())
.child(<NoteList media="screen" />)
.child(<StandaloneRibbonAdapter component={SearchDefinitionTab} />)
.child(<SearchResult />)
.child(<FilePropertiesWrapper />)
)
.child(<MobileEditorToolbar />)
)
.child(new SharedInfoWidget())
.child(
new FloatingButtons()
.child(new RefreshButton())
.child(new EditButton())
.child(new RelationMapButtons())
.child(new SvgExportButton())
.child(new BacklinksWidget())
.child(new HideFloatingButtonsButton())
)
.child(new PromotedAttributesWidget())
.child(
new ScrollingContainer()
.filling()
.contentSized()
.child(new NoteDetailWidget())
.child(new NoteListWidget(false))
.child(new FilePropertiesWidget().css("font-size", "smaller"))
)
.child(new MobileEditorToolbar())
)
)
.child(
@@ -174,10 +171,25 @@ export default class MobileLayout {
.contentSized()
.id("mobile-bottom-bar")
.child(new TabRowWidget().css("height", "40px"))
.child(new FlexContainer("row").class("horizontal").css("height", "53px").child(new LauncherContainer(true)).child(new GlobalMenuWidget(true)).id("launcher-pane"))
.child(new FlexContainer("row")
.class("horizontal")
.css("height", "53px")
.child(new LauncherContainer(true))
.child(<GlobalMenuWidget isHorizontalLayout />)
.id("launcher-pane"))
)
.child(new CloseZenButton());
.child(<CloseZenModeButton />);
applyModals(rootContainer);
return rootContainer;
}
}
function FilePropertiesWrapper() {
const { note } = useNoteContext();
return (
<div>
{note?.type === "file" && <FilePropertiesTab note={note} />}
</div>
);
}

View File

@@ -1,5 +1,3 @@
import "./stylesheets/bootstrap.scss";
// @ts-ignore - module = undefined
// Required for correct loading of scripts in Electron
if (typeof module === 'object') {window.module = module; module = undefined;}

View File

@@ -1,6 +1,8 @@
import keyboardActionService from "../services/keyboard_actions.js";
import { KeyboardActionNames } from "@triliumnext/commons";
import keyboardActionService, { getActionSync } from "../services/keyboard_actions.js";
import note_tooltip from "../services/note_tooltip.js";
import utils from "../services/utils.js";
import { should } from "vitest";
export interface ContextMenuOptions<T> {
x: number;
@@ -13,8 +15,13 @@ export interface ContextMenuOptions<T> {
onHide?: () => void;
}
interface MenuSeparatorItem {
title: "----";
export interface MenuSeparatorItem {
kind: "separator";
}
export interface MenuHeader {
title: string;
kind: "header";
}
export interface MenuItemBadge {
@@ -38,12 +45,13 @@ export interface MenuCommandItem<T> {
handler?: MenuHandler<T>;
items?: MenuItem<T>[] | null;
shortcut?: string;
keyboardShortcut?: KeyboardActionNames;
spellingSuggestion?: string;
checked?: boolean;
columns?: number;
}
export type MenuItem<T> = MenuCommandItem<T> | MenuSeparatorItem;
export type MenuItem<T> = MenuCommandItem<T> | MenuSeparatorItem | MenuHeader;
export type MenuHandler<T> = (item: MenuCommandItem<T>, e: JQuery.MouseDownEvent<HTMLElement, undefined, HTMLElement, HTMLElement>) => void;
export type ContextMenuEvent = PointerEvent | MouseEvent | JQuery.ContextMenuEvent;
@@ -142,20 +150,57 @@ class ContextMenu {
this.$widget
.css({
display: "block",
top: top,
left: left
top,
left
})
.addClass("show");
}
addItems($parent: JQuery<HTMLElement>, items: MenuItem<any>[]) {
for (const item of items) {
addItems($parent: JQuery<HTMLElement>, items: MenuItem<any>[], multicolumn = false) {
let $group = $parent; // The current group or parent element to which items are being appended
let shouldStartNewGroup = false; // If true, the next item will start a new group
let shouldResetGroup = false; // If true, the next item will be the last one from the group
for (let index = 0; index < items.length; index++) {
const item = items[index];
if (!item) {
continue;
}
if (item.title === "----") {
$parent.append($("<div>").addClass("dropdown-divider"));
// If the current item is a header, start a new group. This group will contain the
// header and the next item that follows the header.
if ("kind" in item && item.kind === "header") {
if (multicolumn && !shouldResetGroup) {
shouldStartNewGroup = true;
}
}
// If the next item is a separator, start a new group. This group will contain the
// current item, the separator, and the next item after the separator.
const nextItem = (index < items.length - 1) ? items[index + 1] : null;
if (multicolumn && nextItem && "kind" in nextItem && nextItem.kind === "separator") {
if (!shouldResetGroup) {
shouldStartNewGroup = true;
} else {
shouldResetGroup = true; // Continue the current group
}
}
// Create a new group to avoid column breaks before and after the seaparator / header.
// This is a workaround for Firefox not supporting break-before / break-after: avoid
// for columns.
if (shouldStartNewGroup) {
$group = $("<div class='dropdown-no-break'>");
$parent.append($group);
shouldStartNewGroup = false;
}
if ("kind" in item && item.kind === "separator") {
$group.append($("<div>").addClass("dropdown-divider"));
shouldResetGroup = true; // End the group after the next item
} else if ("kind" in item && item.kind === "header") {
$group.append($("<h6>").addClass("dropdown-header").text(item.title));
shouldResetGroup = true;
} else {
const $icon = $("<span>");
@@ -185,7 +230,23 @@ class ContextMenu {
}
}
if ("shortcut" in item && item.shortcut) {
if ("keyboardShortcut" in item && item.keyboardShortcut) {
const shortcuts = getActionSync(item.keyboardShortcut).effectiveShortcuts;
if (shortcuts) {
const allShortcuts: string[] = [];
for (const effectiveShortcut of shortcuts) {
allShortcuts.push(effectiveShortcut.split("+")
.map(key => `<kbd>${key}</kbd>`)
.join("+"));
}
if (allShortcuts.length) {
const container = $("<span>").addClass("keyboard-shortcut");
container.append($(allShortcuts.join(",")));
$link.append(container);
}
}
} else if ("shortcut" in item && item.shortcut) {
$link.append($("<kbd>").text(item.shortcut));
}
@@ -241,16 +302,24 @@ class ContextMenu {
$link.addClass("dropdown-toggle");
const $subMenu = $("<ul>").addClass("dropdown-menu");
if (!this.isMobile && item.columns) {
$subMenu.css("column-count", item.columns);
const hasColumns = !!item.columns && item.columns > 1;
if (!this.isMobile && hasColumns) {
$subMenu.css("column-count", item.columns!);
}
this.addItems($subMenu, item.items);
this.addItems($subMenu, item.items, hasColumns);
$item.append($subMenu);
}
$parent.append($item);
$group.append($item);
// After adding a menu item, if the previous item was a separator or header,
// reset the group so that the next item will be appended directly to the parent.
if (shouldResetGroup) {
$group = $parent;
shouldResetGroup = false;
};
}
}
}

View File

@@ -37,7 +37,7 @@ function setupContextMenu() {
handler: () => webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord)
});
items.push({ title: `----` });
items.push({ kind: "separator" });
}
if (params.isEditable) {
@@ -112,7 +112,7 @@ function setupContextMenu() {
// Replace the placeholder with the real search keyword.
let searchUrl = searchEngineUrl.replace("{keyword}", encodeURIComponent(params.selectionText));
items.push({ title: "----" });
items.push({ kind: "separator" });
items.push({
title: t("electron_context_menu.search_online", { term: shortenedSelection, searchEngine: searchEngineName }),

View File

@@ -2,8 +2,6 @@ import { t } from "../services/i18n.js";
import utils from "../services/utils.js";
import contextMenu from "./context_menu.js";
import imageService from "../services/image.js";
import mediaViewer from "../services/media_viewer.js";
import type { MediaItem } from "../services/media_viewer.js";
const PROP_NAME = "imageContextMenuInstalled";
@@ -20,12 +18,6 @@ function setupContextMenu($image: JQuery<HTMLElement>) {
x: e.pageX,
y: e.pageY,
items: [
{
title: "View in Lightbox",
command: "viewInLightbox",
uiIcon: "bx bx-expand",
enabled: true
},
{
title: t("image_context_menu.copy_reference_to_clipboard"),
command: "copyImageReferenceToClipboard",
@@ -38,48 +30,7 @@ function setupContextMenu($image: JQuery<HTMLElement>) {
}
],
selectMenuItemHandler: async ({ command }) => {
if (command === "viewInLightbox") {
const src = $image.attr("src");
const alt = $image.attr("alt");
const title = $image.attr("title");
if (!src) {
console.error("Missing image source");
return;
}
const item: MediaItem = {
src: src,
alt: alt || "Image",
title: title || alt,
element: $image[0] as HTMLElement
};
// Try to get actual dimensions
const imgElement = $image[0] as HTMLImageElement;
if (imgElement.naturalWidth && imgElement.naturalHeight) {
item.width = imgElement.naturalWidth;
item.height = imgElement.naturalHeight;
}
mediaViewer.openSingle(item, {
bgOpacity: 0.95,
showHideOpacity: true,
pinchToClose: true,
closeOnScroll: false,
closeOnVerticalDrag: true,
wheelToZoom: true,
getThumbBoundsFn: () => {
// Get position for zoom animation
const rect = imgElement.getBoundingClientRect();
return {
x: rect.left,
y: rect.top,
w: rect.width
};
}
});
} else if (command === "copyImageReferenceToClipboard") {
if (command === "copyImageReferenceToClipboard") {
imageService.copyImageReferenceToClipboard($image);
} else if (command === "copyImageToClipboard") {
try {

View File

@@ -45,16 +45,16 @@ export default class LauncherContextMenu implements SelectMenuItemEventListener<
isVisibleRoot || isAvailableRoot ? { title: t("launcher_context_menu.add-script-launcher"), command: "addScriptLauncher", uiIcon: "bx bx-code-curly" } : null,
isVisibleRoot || isAvailableRoot ? { title: t("launcher_context_menu.add-custom-widget"), command: "addWidgetLauncher", uiIcon: "bx bx-customize" } : null,
isVisibleRoot || isAvailableRoot ? { title: t("launcher_context_menu.add-spacer"), command: "addSpacerLauncher", uiIcon: "bx bx-dots-horizontal" } : null,
isVisibleRoot || isAvailableRoot ? { title: "----" } : null,
isVisibleRoot || isAvailableRoot ? { kind: "separator" } : null,
isAvailableItem ? { title: t("launcher_context_menu.move-to-visible-launchers"), command: "moveLauncherToVisible", uiIcon: "bx bx-show", enabled: true } : null,
isVisibleItem ? { title: t("launcher_context_menu.move-to-available-launchers"), command: "moveLauncherToAvailable", uiIcon: "bx bx-hide", enabled: true } : null,
isVisibleItem || isAvailableItem ? { title: "----" } : null,
isVisibleItem || isAvailableItem ? { kind: "separator" } : null,
{ title: `${t("launcher_context_menu.duplicate-launcher")}`, command: "duplicateSubtree", uiIcon: "bx bx-outline", enabled: isItem },
{ title: `${t("launcher_context_menu.delete")}`, command: "deleteNotes", uiIcon: "bx bx-trash destructive-action-icon", enabled: canBeDeleted },
{ title: "----" },
{ kind: "separator" },
{ title: t("launcher_context_menu.reset"), command: "resetLauncher", uiIcon: "bx bx-reset destructive-action-icon", enabled: canBeReset }
];

View File

@@ -13,6 +13,8 @@ import type NoteTreeWidget from "../widgets/note_tree.js";
import type FAttachment from "../entities/fattachment.js";
import type { SelectMenuItemEventListener } from "../components/events.js";
import utils from "../services/utils.js";
import attributes from "../services/attributes.js";
import { executeBulkActions } from "../services/bulk_action.js";
// TODO: Deduplicate once client/server is well split.
interface ConvertToAttachmentResponse {
@@ -61,6 +63,11 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
// the only exception is when the only selected note is the one that was right-clicked, then
// it's clear what the user meant to do.
const selNodes = this.treeWidget.getSelectedNodes();
const selectedNotes = await froca.getNotes(selNodes.map(node => node.data.noteId));
if (note && !selectedNotes.includes(note)) selectedNotes.push(note);
const isArchived = selectedNotes.every(note => note.isArchived);
const canToggleArchived = !selectedNotes.some(note => note.isArchived !== isArchived);
const noSelectedNotes = selNodes.length === 0 || (selNodes.length === 1 && selNodes[0] === this.node);
const notSearch = note?.type !== "search";
@@ -69,27 +76,29 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
const insertNoteAfterEnabled = isNotRoot && !isHoisted && parentNotSearch;
const items: (MenuItem<TreeCommandNames> | null)[] = [
{ title: `${t("tree-context-menu.open-in-a-new-tab")}`, command: "openInTab", uiIcon: "bx bx-link-external", enabled: noSelectedNotes },
{ title: t("tree-context-menu.open-in-a-new-tab"), command: "openInTab", shortcut: "Ctrl+Click", uiIcon: "bx bx-link-external", enabled: noSelectedNotes },
{ title: t("tree-context-menu.open-in-a-new-split"), command: "openNoteInSplit", uiIcon: "bx bx-dock-right", enabled: noSelectedNotes },
{ title: t("tree-context-menu.open-in-popup"), command: "openNoteInPopup", uiIcon: "bx bx-edit", enabled: noSelectedNotes },
isHoisted
? null
: {
title: `${t("tree-context-menu.hoist-note")} <kbd data-command="toggleNoteHoisting"></kbd>`,
title: `${t("tree-context-menu.hoist-note")}`,
command: "toggleNoteHoisting",
keyboardShortcut: "toggleNoteHoisting",
uiIcon: "bx bxs-chevrons-up",
enabled: noSelectedNotes && notSearch
},
!isHoisted || !isNotRoot
? null
: { title: `${t("tree-context-menu.unhoist-note")} <kbd data-command="toggleNoteHoisting"></kbd>`, command: "toggleNoteHoisting", uiIcon: "bx bx-door-open" },
: { title: t("tree-context-menu.unhoist-note"), command: "toggleNoteHoisting", keyboardShortcut: "toggleNoteHoisting", uiIcon: "bx bx-door-open" },
{ title: "----" },
{ kind: "separator" },
{
title: `${t("tree-context-menu.insert-note-after")}<kbd data-command="createNoteAfter"></kbd>`,
title: t("tree-context-menu.insert-note-after"),
command: "insertNoteAfter",
keyboardShortcut: "createNoteAfter",
uiIcon: "bx bx-plus",
items: insertNoteAfterEnabled ? await noteTypesService.getNoteTypeItems("insertNoteAfter") : null,
enabled: insertNoteAfterEnabled && noSelectedNotes && notOptionsOrHelp,
@@ -97,21 +106,22 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
},
{
title: `${t("tree-context-menu.insert-child-note")}<kbd data-command="createNoteInto"></kbd>`,
title: t("tree-context-menu.insert-child-note"),
command: "insertChildNote",
keyboardShortcut: "createNoteInto",
uiIcon: "bx bx-plus",
items: notSearch ? await noteTypesService.getNoteTypeItems("insertChildNote") : null,
enabled: notSearch && noSelectedNotes && notOptionsOrHelp,
columns: 2
},
{ title: "----" },
{ kind: "separator" },
{ title: t("tree-context-menu.protect-subtree"), command: "protectSubtree", uiIcon: "bx bx-check-shield", enabled: noSelectedNotes },
{ title: t("tree-context-menu.unprotect-subtree"), command: "unprotectSubtree", uiIcon: "bx bx-shield", enabled: noSelectedNotes },
{ title: "----" },
{ kind: "separator" },
{
title: t("tree-context-menu.advanced"),
@@ -120,48 +130,52 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
items: [
{ title: t("tree-context-menu.apply-bulk-actions"), command: "openBulkActionsDialog", uiIcon: "bx bx-list-plus", enabled: true },
{ title: "----" },
{ kind: "separator" },
{
title: `${t("tree-context-menu.edit-branch-prefix")} <kbd data-command="editBranchPrefix"></kbd>`,
title: t("tree-context-menu.edit-branch-prefix"),
command: "editBranchPrefix",
keyboardShortcut: "editBranchPrefix",
uiIcon: "bx bx-rename",
enabled: isNotRoot && parentNotSearch && noSelectedNotes && notOptionsOrHelp
},
{ title: t("tree-context-menu.convert-to-attachment"), command: "convertNoteToAttachment", uiIcon: "bx bx-paperclip", enabled: isNotRoot && !isHoisted && notOptionsOrHelp },
{ title: "----" },
{ kind: "separator" },
{ title: `${t("tree-context-menu.expand-subtree")} <kbd data-command="expandSubtree"></kbd>`, command: "expandSubtree", uiIcon: "bx bx-expand", enabled: noSelectedNotes },
{ title: `${t("tree-context-menu.collapse-subtree")} <kbd data-command="collapseSubtree"></kbd>`, command: "collapseSubtree", uiIcon: "bx bx-collapse", enabled: noSelectedNotes },
{ title: t("tree-context-menu.expand-subtree"), command: "expandSubtree", keyboardShortcut: "expandSubtree", uiIcon: "bx bx-expand", enabled: noSelectedNotes },
{ title: t("tree-context-menu.collapse-subtree"), command: "collapseSubtree", keyboardShortcut: "collapseSubtree", uiIcon: "bx bx-collapse", enabled: noSelectedNotes },
{
title: `${t("tree-context-menu.sort-by")} <kbd data-command="sortChildNotes"></kbd>`,
title: t("tree-context-menu.sort-by"),
command: "sortChildNotes",
keyboardShortcut: "sortChildNotes",
uiIcon: "bx bx-sort-down",
enabled: noSelectedNotes && notSearch
},
{ title: "----" },
{ kind: "separator" },
{ title: t("tree-context-menu.copy-note-path-to-clipboard"), command: "copyNotePathToClipboard", uiIcon: "bx bx-directions", enabled: true },
{ title: t("tree-context-menu.recent-changes-in-subtree"), command: "recentChangesInSubtree", uiIcon: "bx bx-history", enabled: noSelectedNotes && notOptionsOrHelp }
]
},
{ title: "----" },
{ kind: "separator" },
{
title: `${t("tree-context-menu.cut")} <kbd data-command="cutNotesToClipboard"></kbd>`,
title: t("tree-context-menu.cut"),
command: "cutNotesToClipboard",
keyboardShortcut: "cutNotesToClipboard",
uiIcon: "bx bx-cut",
enabled: isNotRoot && !isHoisted && parentNotSearch
},
{ title: `${t("tree-context-menu.copy-clone")} <kbd data-command="copyNotesToClipboard"></kbd>`, command: "copyNotesToClipboard", uiIcon: "bx bx-copy", enabled: isNotRoot && !isHoisted },
{ title: t("tree-context-menu.copy-clone"), command: "copyNotesToClipboard", keyboardShortcut: "copyNotesToClipboard", uiIcon: "bx bx-copy", enabled: isNotRoot && !isHoisted },
{
title: `${t("tree-context-menu.paste-into")} <kbd data-command="pasteNotesFromClipboard"></kbd>`,
title: t("tree-context-menu.paste-into"),
command: "pasteNotesFromClipboard",
keyboardShortcut: "pasteNotesFromClipboard",
uiIcon: "bx bx-paste",
enabled: !clipboard.isClipboardEmpty() && notSearch && noSelectedNotes
},
@@ -174,39 +188,71 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
},
{
title: `${t("tree-context-menu.move-to")} <kbd data-command="moveNotesTo"></kbd>`,
title: t("tree-context-menu.move-to"),
command: "moveNotesTo",
keyboardShortcut: "moveNotesTo",
uiIcon: "bx bx-transfer",
enabled: isNotRoot && !isHoisted && parentNotSearch
},
{ title: `${t("tree-context-menu.clone-to")} <kbd data-command="cloneNotesTo"></kbd>`, command: "cloneNotesTo", uiIcon: "bx bx-duplicate", enabled: isNotRoot && !isHoisted },
{ title: t("tree-context-menu.clone-to"), command: "cloneNotesTo", keyboardShortcut: "cloneNotesTo", uiIcon: "bx bx-duplicate", enabled: isNotRoot && !isHoisted },
{
title: `${t("tree-context-menu.duplicate")} <kbd data-command="duplicateSubtree">`,
title: t("tree-context-menu.duplicate"),
command: "duplicateSubtree",
keyboardShortcut: "duplicateSubtree",
uiIcon: "bx bx-outline",
enabled: parentNotSearch && isNotRoot && !isHoisted && notOptionsOrHelp
},
{
title: `${t("tree-context-menu.delete")} <kbd data-command="deleteNotes"></kbd>`,
title: !isArchived ? t("tree-context-menu.archive") : t("tree-context-menu.unarchive"),
uiIcon: !isArchived ? "bx bx-archive" : "bx bx-archive-out",
enabled: canToggleArchived,
handler: () => {
if (!selectedNotes.length) return;
if (selectedNotes.length == 1) {
const note = selectedNotes[0];
if (!isArchived) {
attributes.addLabel(note.noteId, "archived");
} else {
attributes.removeOwnedLabelByName(note, "archived");
}
} else {
const noteIds = selectedNotes.map(note => note.noteId);
if (!isArchived) {
executeBulkActions(noteIds, [{
name: "addLabel", labelName: "archived"
}]);
} else {
executeBulkActions(noteIds, [{
name: "deleteLabel", labelName: "archived"
}]);
}
}
}
},
{
title: t("tree-context-menu.delete"),
command: "deleteNotes",
keyboardShortcut: "deleteNotes",
uiIcon: "bx bx-trash destructive-action-icon",
enabled: isNotRoot && !isHoisted && parentNotSearch && notOptionsOrHelp
},
{ title: "----" },
{ kind: "separator" },
{ title: t("tree-context-menu.import-into-note"), command: "importIntoNote", uiIcon: "bx bx-import", enabled: notSearch && noSelectedNotes && notOptionsOrHelp },
{ title: t("tree-context-menu.export"), command: "exportNote", uiIcon: "bx bx-export", enabled: notSearch && noSelectedNotes && notOptionsOrHelp },
{ title: "----" },
{ kind: "separator" },
{
title: `${t("tree-context-menu.search-in-subtree")} <kbd data-command="searchInSubtree"></kbd>`,
title: t("tree-context-menu.search-in-subtree"),
command: "searchInSubtree",
keyboardShortcut: "searchInSubtree",
uiIcon: "bx bx-search",
enabled: notSearch && noSelectedNotes
}

View File

@@ -1,9 +1,7 @@
import appContext from "./components/app_context.js";
import noteAutocompleteService from "./services/note_autocomplete.js";
import glob from "./services/glob.js";
import "./stylesheets/bootstrap.scss";
import "boxicons/css/boxicons.min.css";
import "./stylesheets/media-viewer.css";
import "autocomplete.js/index_jquery.js";
glob.setupGlobs();

155
apps/client/src/print.css Normal file
View File

@@ -0,0 +1,155 @@
:root {
--print-font-size: 11pt;
--ck-content-color-image-caption-background: transparent !important;
}
html,
body {
width: 100%;
height: 100%;
color: black;
}
@page {
margin: 2cm;
}
.note-list-widget.full-height,
.note-list-widget.full-height .note-list-widget-content {
height: unset !important;
}
.component {
contain: none !important;
}
body[data-note-type="text"] .ck-content {
font-size: var(--print-font-size);
text-align: justify;
}
.ck-content figcaption {
font-style: italic;
}
.ck-content a {
text-decoration: none;
}
.ck-content a:not([href^="#root/"]) {
text-decoration: underline;
color: #374a75;
}
.ck-content .todo-list__label * {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
@supports selector(.todo-list__label__description:has(*)) and (height: 1lh) {
.ck-content .todo-list__label__description {
/* The percentage of the line height that the check box occupies */
--box-ratio: 0.75;
/* The size of the gap between the check box and the caption */
--box-text-gap: 0.25em;
--box-size: calc(1lh * var(--box-ratio));
--box-vert-offset: calc((1lh - var(--box-size)) / 2);
display: inline-block;
padding-inline-start: calc(var(--box-size) + var(--box-text-gap));
/* Source: https://pictogrammers.com/library/mdi/icon/checkbox-blank-outline/ */
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3e%3cpath d='M19%2c3H5C3.89%2c3 3%2c3.89 3%2c5V19A2%2c2 0 0%2c0 5%2c21H19A2%2c2 0 0%2c0 21%2c19V5C21%2c3.89 20.1%2c3 19%2c3M19%2c5V19H5V5H19Z' /%3e%3c/svg%3e");
background-position: 0 var(--box-vert-offset);
background-size: var(--box-size);
background-repeat: no-repeat;
}
.ck-content .todo-list__label:has(input[type="checkbox"]:checked) .todo-list__label__description {
/* Source: https://pictogrammers.com/library/mdi/icon/checkbox-outline/ */
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3e%3cpath d='M19%2c3H5A2%2c2 0 0%2c0 3%2c5V19A2%2c2 0 0%2c0 5%2c21H19A2%2c2 0 0%2c0 21%2c19V5A2%2c2 0 0%2c0 19%2c3M19%2c5V19H5V5H19M10%2c17L6%2c13L7.41%2c11.58L10%2c14.17L16.59%2c7.58L18%2c9' /%3e%3c/svg%3e");
}
.ck-content .todo-list__label input[type="checkbox"] {
display: none !important;
}
}
/* #region Footnotes */
.footnote-reference a,
.footnote-back-link a {
text-decoration: none !important;
}
li.footnote-item {
position: relative;
width: fit-content;
}
.ck-content .footnote-back-link {
margin-right: 0.25em;
}
.ck-content .footnote-content {
display: inline-block;
width: unset;
}
/* #endregion */
/* #region Widows and orphans */
p,
blockquote {
widows: 4;
orphans: 4;
}
pre > code {
widows: 6;
orphans: 6;
overflow: auto;
white-space: pre-wrap !important;
}
h1,
h2,
h3,
h4,
h5,
h6 {
page-break-after: avoid;
break-after: avoid;
}
/* #endregion */
/* #region Tables */
.table thead th,
.table td,
.table th {
/* Fix center vertical alignment of table cells */
vertical-align: middle;
}
pre {
box-shadow: unset !important;
border: 0.75pt solid gray !important;
border-radius: 2pt !important;
}
th,
span[style] {
print-color-adjust: exact;
-webkit-print-color-adjust: exact;
}
/* #endregion */
/* #region Page breaks */
.page-break {
page-break-after: always;
break-after: always;
}
.page-break > *,
.page-break::after {
display: none !important;
}
/* #endregion */

105
apps/client/src/print.tsx Normal file
View File

@@ -0,0 +1,105 @@
import FNote from "./entities/fnote";
import { render } from "preact";
import { CustomNoteList } from "./widgets/collections/NoteList";
import { useCallback, useLayoutEffect, useRef } from "preact/hooks";
import content_renderer from "./services/content_renderer";
interface RendererProps {
note: FNote;
onReady: () => void;
}
async function main() {
const notePath = window.location.hash.substring(1);
const noteId = notePath.split("/").at(-1);
if (!noteId) return;
await import("./print.css");
const froca = (await import("./services/froca")).default;
const note = await froca.getNote(noteId);
render(<App note={note} noteId={noteId} />, document.body);
}
function App({ note, noteId }: { note: FNote | null | undefined, noteId: string }) {
const sentReadyEvent = useRef(false);
const onReady = useCallback(() => {
if (sentReadyEvent.current) return;
window.dispatchEvent(new Event("note-ready"));
window._noteReady = true;
sentReadyEvent.current = true;
}, []);
const props: RendererProps | undefined | null = note && { note, onReady };
if (!note || !props) return <Error404 noteId={noteId} />
useLayoutEffect(() => {
document.body.dataset.noteType = note.type;
}, [ note ]);
return (
<>
{note.type === "book"
? <CollectionRenderer {...props} />
: <SingleNoteRenderer {...props} />
}
</>
);
}
function SingleNoteRenderer({ note, onReady }: RendererProps) {
const containerRef = useRef<HTMLDivElement>(null);
useLayoutEffect(() => {
async function load() {
if (note.type === "text") {
await import("@triliumnext/ckeditor5/src/theme/ck-content.css");
}
const { $renderedContent } = await content_renderer.getRenderedContent(note, { noChildrenList: true });
const container = containerRef.current!;
container.replaceChildren(...$renderedContent);
// Wait for all images to load.
const images = Array.from(container.querySelectorAll("img"));
await Promise.all(
images.map(img => {
if (img.complete) return Promise.resolve();
return new Promise<void>(resolve => {
img.addEventListener("load", () => resolve(), { once: true });
img.addEventListener("error", () => resolve(), { once: true });
});
})
);
}
load().then(() => requestAnimationFrame(onReady))
}, [ note ]);
return <>
<h1>{note.title}</h1>
<main ref={containerRef} />
</>;
}
function CollectionRenderer({ note, onReady }: RendererProps) {
return <CustomNoteList
isEnabled
note={note}
notePath={note.getBestNotePath().join("/")}
ntxId="print"
highlightedTokens={null}
media="print"
onReady={onReady}
/>;
}
function Error404({ noteId }: { noteId: string }) {
return (
<main>
<p>The note you are trying to print could not be found.</p>
<small>{noteId}</small>
</main>
)
}
main();

View File

@@ -1,5 +1,15 @@
import $ from "jquery";
async function loadBootstrap() {
if (document.body.dir === "rtl") {
await import("bootstrap/dist/css/bootstrap.rtl.min.css");
} else {
await import("bootstrap/dist/css/bootstrap.min.css");
}
}
(window as any).$ = $;
(window as any).jQuery = $;
await loadBootstrap();
$("body").show();

View File

@@ -2,6 +2,7 @@ import server from "./server.js";
import froca from "./froca.js";
import type FNote from "../entities/fnote.js";
import type { AttributeRow } from "./load_results.js";
import { AttributeType } from "@triliumnext/commons";
async function addLabel(noteId: string, name: string, value: string = "", isInheritable = false) {
await server.put(`notes/${noteId}/attribute`, {
@@ -25,6 +26,14 @@ async function removeAttributeById(noteId: string, attributeId: string) {
await server.remove(`notes/${noteId}/attributes/${attributeId}`);
}
export async function removeOwnedAttributesByNameOrType(note: FNote, type: AttributeType, name: string) {
for (const attr of note.getOwnedAttributes()) {
if (attr.type === type && attr.name === name) {
await server.remove(`notes/${note.noteId}/attributes/${attr.attributeId}`);
}
}
}
/**
* Removes a label identified by its name from the given note, if it exists. Note that the label must be owned, i.e.
* it will not remove inherited attributes.
@@ -52,7 +61,7 @@ function removeOwnedLabelByName(note: FNote, labelName: string) {
* @param value the value of the attribute to set.
*/
export async function setAttribute(note: FNote, type: "label" | "relation", name: string, value: string | null | undefined) {
if (value) {
if (value !== null && value !== undefined) {
// Create or update the attribute.
await server.put(`notes/${note.noteId}/set-attribute`, { type, name, value });
} else {

View File

@@ -210,7 +210,7 @@ function makeToast(id: string, message: string): ToastOptions {
}
ws.subscribeToMessages(async (message) => {
if (message.taskType !== "deleteNotes") {
if (!("taskType" in message) || message.taskType !== "deleteNotes") {
return;
}
@@ -228,7 +228,7 @@ ws.subscribeToMessages(async (message) => {
});
ws.subscribeToMessages(async (message) => {
if (message.taskType !== "undeleteNotes") {
if (!("taskType" in message) || message.taskType !== "undeleteNotes") {
return;
}

View File

@@ -18,7 +18,7 @@ import type FNote from "../entities/fnote.js";
import toast from "./toast.js";
import { BulkAction } from "@triliumnext/commons";
const ACTION_GROUPS = [
export const ACTION_GROUPS = [
{
title: t("bulk_actions.labels"),
actions: [AddLabelBulkAction, UpdateLabelValueBulkAction, RenameLabelBulkAction, DeleteLabelBulkAction]

View File

@@ -1,521 +0,0 @@
/**
* CKEditor PhotoSwipe Integration
* Handles click-to-lightbox functionality for images in CKEditor content
*/
import mediaViewer from './media_viewer.js';
import galleryManager from './gallery_manager.js';
import appContext from '../components/app_context.js';
import type { MediaItem } from './media_viewer.js';
import type { GalleryItem } from './gallery_manager.js';
/**
* Configuration for CKEditor PhotoSwipe integration
*/
interface CKEditorPhotoSwipeConfig {
enableGalleryMode?: boolean;
showHints?: boolean;
hintDelay?: number;
excludeSelector?: string;
}
/**
* Integration manager for CKEditor and PhotoSwipe
*/
class CKEditorPhotoSwipeIntegration {
private static instance: CKEditorPhotoSwipeIntegration;
private config: Required<CKEditorPhotoSwipeConfig>;
private observers: Map<HTMLElement, MutationObserver> = new Map();
private processedImages: WeakSet<HTMLImageElement> = new WeakSet();
private containerGalleries: Map<HTMLElement, GalleryItem[]> = new Map();
private hintPool: HTMLElement[] = [];
private activeHints: Map<string, HTMLElement> = new Map();
private hintTimeouts: Map<string, number> = new Map();
private constructor() {
this.config = {
enableGalleryMode: true,
showHints: true,
hintDelay: 2000,
excludeSelector: '.no-lightbox, .cke_widget_element'
};
}
/**
* Get singleton instance
*/
static getInstance(): CKEditorPhotoSwipeIntegration {
if (!CKEditorPhotoSwipeIntegration.instance) {
CKEditorPhotoSwipeIntegration.instance = new CKEditorPhotoSwipeIntegration();
}
return CKEditorPhotoSwipeIntegration.instance;
}
/**
* Setup integration for a CKEditor content container
*/
setupContainer(container: HTMLElement | JQuery<HTMLElement>, config?: Partial<CKEditorPhotoSwipeConfig>): void {
const element = container instanceof $ ? container[0] : container;
if (!element) return;
// Merge configuration
if (config) {
this.config = { ...this.config, ...config };
}
// Process existing images
this.processImages(element);
// Setup mutation observer for dynamically added images
this.observeContainer(element);
// Setup gallery if enabled
if (this.config.enableGalleryMode) {
this.setupGalleryMode(element);
}
}
/**
* Process all images in a container
*/
private processImages(container: HTMLElement): void {
const images = container.querySelectorAll<HTMLImageElement>(`img:not(${this.config.excludeSelector})`);
images.forEach(img => {
if (!this.processedImages.has(img)) {
this.setupImageLightbox(img);
this.processedImages.add(img);
}
});
}
/**
* Setup lightbox for a single image
*/
private setupImageLightbox(img: HTMLImageElement): void {
// Skip if already processed or is a CKEditor widget element
if (img.closest('.cke_widget_element') || img.closest('.ck-widget')) {
return;
}
// Make image clickable and mark it as PhotoSwipe-enabled
img.style.cursor = 'zoom-in';
img.style.transition = 'opacity 0.2s';
img.classList.add('photoswipe-enabled');
img.setAttribute('data-photoswipe', 'true');
// Store event handlers for cleanup
const mouseEnterHandler = () => {
img.style.opacity = '0.9';
if (this.config.showHints) {
this.showHint(img);
}
};
const mouseLeaveHandler = () => {
img.style.opacity = '1';
this.hideHint(img);
};
// Add hover effect with cleanup tracking
img.addEventListener('mouseenter', mouseEnterHandler);
img.addEventListener('mouseleave', mouseLeaveHandler);
// Store handlers for cleanup
(img as any)._photoswipeHandlers = { mouseEnterHandler, mouseLeaveHandler };
// Add double-click handler to prevent default navigation behavior
const dblClickHandler = (e: MouseEvent) => {
// Only prevent double-click in specific contexts to avoid breaking other features
if (img.closest('.attachment-detail-wrapper') ||
img.closest('.note-detail-editable-text') ||
img.closest('.note-detail-readonly-text')) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
// Trigger the same behavior as single click (open lightbox)
img.click();
}
};
img.addEventListener('dblclick', dblClickHandler, true); // Use capture phase to ensure we get it first
(img as any)._photoswipeHandlers.dblClickHandler = dblClickHandler;
// Add click handler
img.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
// Check if we should open as gallery
const container = img.closest('.note-detail-editable-text, .note-detail-readonly-text');
if (container && this.config.enableGalleryMode) {
const gallery = this.containerGalleries.get(container as HTMLElement);
if (gallery && gallery.length > 1) {
// Find index of clicked image
const index = gallery.findIndex(item => {
const itemElement = document.querySelector(`img[src="${item.src}"]`);
return itemElement === img;
});
galleryManager.openGallery(gallery, index >= 0 ? index : 0, {
showThumbnails: true,
showCounter: true,
enableKeyboardNav: true,
loop: true
});
return;
}
}
// Open single image
this.openSingleImage(img);
});
// Add keyboard support
img.setAttribute('tabindex', '0');
img.setAttribute('role', 'button');
img.setAttribute('aria-label', 'Click to view in lightbox');
img.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
img.click();
}
});
}
/**
* Open a single image in lightbox
*/
private openSingleImage(img: HTMLImageElement): void {
const item: MediaItem = {
src: img.src,
alt: img.alt || 'Image',
title: img.title || img.alt,
element: img,
width: img.naturalWidth || undefined,
height: img.naturalHeight || undefined
};
mediaViewer.openSingle(item, {
bgOpacity: 0.95,
showHideOpacity: true,
pinchToClose: true,
closeOnScroll: false,
closeOnVerticalDrag: true,
wheelToZoom: true,
getThumbBoundsFn: () => {
const rect = img.getBoundingClientRect();
return {
x: rect.left,
y: rect.top,
w: rect.width
};
}
}, {
onClose: () => {
// Check if we're in attachment detail view and need to reset viewScope
const activeContext = appContext.tabManager.getActiveContext();
if (activeContext?.viewScope?.viewMode === 'attachments') {
// Get the note ID from the image source
const attachmentMatch = img.src.match(/\/api\/attachments\/([A-Za-z0-9_]+)\/image\//);
if (attachmentMatch) {
const currentAttachmentId = activeContext.viewScope.attachmentId;
if (currentAttachmentId === attachmentMatch[1]) {
// Actually reset the viewScope instead of just logging
try {
if (activeContext.note) {
activeContext.setNote(activeContext.note.noteId, {
viewScope: { viewMode: 'default' }
});
}
} catch (error) {
console.error('Failed to reset viewScope after PhotoSwipe close:', error);
}
}
}
}
// Restore focus to the image
img.focus();
}
});
}
/**
* Setup gallery mode for a container
*/
private setupGalleryMode(container: HTMLElement): void {
const images = container.querySelectorAll<HTMLImageElement>(`img:not(${this.config.excludeSelector})`);
if (images.length <= 1) return;
const galleryItems: GalleryItem[] = [];
images.forEach((img, index) => {
// Skip CKEditor widget elements
if (img.closest('.cke_widget_element') || img.closest('.ck-widget')) {
return;
}
const item: GalleryItem = {
src: img.src,
alt: img.alt || `Image ${index + 1}`,
title: img.title || img.alt,
element: img,
index: index,
width: img.naturalWidth || undefined,
height: img.naturalHeight || undefined
};
// Check for caption
const figure = img.closest('figure');
if (figure) {
const caption = figure.querySelector('figcaption');
if (caption) {
item.caption = caption.textContent || undefined;
}
}
galleryItems.push(item);
});
if (galleryItems.length > 0) {
this.containerGalleries.set(container, galleryItems);
}
}
/**
* Observe container for dynamic changes
*/
private observeContainer(container: HTMLElement): void {
// Disconnect existing observer if any
const existingObserver = this.observers.get(container);
if (existingObserver) {
existingObserver.disconnect();
}
const observer = new MutationObserver((mutations) => {
let hasNewImages = false;
mutations.forEach(mutation => {
if (mutation.type === 'childList') {
mutation.addedNodes.forEach(node => {
if (node.nodeType === Node.ELEMENT_NODE) {
const element = node as HTMLElement;
if (element.tagName === 'IMG') {
hasNewImages = true;
} else if (element.querySelector('img')) {
hasNewImages = true;
}
}
});
}
});
if (hasNewImages) {
// Process new images
this.processImages(container);
// Update gallery if enabled
if (this.config.enableGalleryMode) {
this.setupGalleryMode(container);
}
}
});
observer.observe(container, {
childList: true,
subtree: true
});
this.observers.set(container, observer);
}
/**
* Get or create a hint element from the pool
*/
private getHintFromPool(): HTMLElement {
let hint = this.hintPool.pop();
if (!hint) {
hint = document.createElement('div');
hint.className = 'ckeditor-image-hint';
hint.textContent = 'Click to view in lightbox';
hint.style.cssText = `
position: absolute;
background: rgba(0, 0, 0, 0.8);
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
z-index: 1000;
pointer-events: none;
opacity: 0;
transition: opacity 0.3s;
display: none;
`;
}
return hint;
}
/**
* Return hint to pool
*/
private returnHintToPool(hint: HTMLElement): void {
hint.style.opacity = '0';
hint.style.display = 'none';
if (this.hintPool.length < 10) { // Keep max 10 hints in pool
this.hintPool.push(hint);
} else {
hint.remove();
}
}
/**
* Show hint for an image
*/
private showHint(img: HTMLImageElement): void {
// Check if hint already exists
const imgId = img.dataset.imgId || `img-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
if (!img.dataset.imgId) {
img.dataset.imgId = imgId;
}
// Clear any existing timeout
const existingTimeout = this.hintTimeouts.get(imgId);
if (existingTimeout) {
clearTimeout(existingTimeout);
this.hintTimeouts.delete(imgId);
}
let hint = this.activeHints.get(imgId);
if (hint) {
hint.style.opacity = '1';
return;
}
// Get hint from pool
hint = this.getHintFromPool();
this.activeHints.set(imgId, hint);
// Position and show hint
if (!hint.parentElement) {
document.body.appendChild(hint);
}
const imgRect = img.getBoundingClientRect();
hint.style.display = 'block';
hint.style.left = `${imgRect.left + (imgRect.width - hint.offsetWidth) / 2}px`;
hint.style.top = `${imgRect.top - hint.offsetHeight - 5}px`;
// Show hint
requestAnimationFrame(() => {
hint.style.opacity = '1';
});
// Auto-hide after delay
const timeout = window.setTimeout(() => {
this.hideHint(img);
}, this.config.hintDelay);
this.hintTimeouts.set(imgId, timeout);
}
/**
* Hide hint for an image
*/
private hideHint(img: HTMLImageElement): void {
const imgId = img.dataset.imgId;
if (!imgId) return;
// Clear timeout
const timeout = this.hintTimeouts.get(imgId);
if (timeout) {
clearTimeout(timeout);
this.hintTimeouts.delete(imgId);
}
const hint = this.activeHints.get(imgId);
if (hint) {
hint.style.opacity = '0';
this.activeHints.delete(imgId);
setTimeout(() => {
this.returnHintToPool(hint);
}, 300);
}
}
/**
* Cleanup integration for a container
*/
cleanupContainer(container: HTMLElement | JQuery<HTMLElement>): void {
const element = container instanceof $ ? container[0] : container;
if (!element) return;
// Disconnect observer
const observer = this.observers.get(element);
if (observer) {
observer.disconnect();
this.observers.delete(element);
}
// Clear gallery
this.containerGalleries.delete(element);
// Remove event handlers and hints
const images = element.querySelectorAll<HTMLImageElement>('img');
images.forEach(img => {
this.hideHint(img);
// Remove event handlers
const handlers = (img as any)._photoswipeHandlers;
if (handlers) {
img.removeEventListener('mouseenter', handlers.mouseEnterHandler);
img.removeEventListener('mouseleave', handlers.mouseLeaveHandler);
if (handlers.dblClickHandler) {
img.removeEventListener('dblclick', handlers.dblClickHandler, true);
}
delete (img as any)._photoswipeHandlers;
}
// Mark as unprocessed
this.processedImages.delete(img);
});
}
/**
* Update configuration
*/
updateConfig(config: Partial<CKEditorPhotoSwipeConfig>): void {
this.config = { ...this.config, ...config };
}
/**
* Cleanup all integrations
*/
cleanup(): void {
// Disconnect all observers
this.observers.forEach(observer => observer.disconnect());
this.observers.clear();
// Clear all galleries
this.containerGalleries.clear();
// Clear all hints
this.activeHints.forEach(hint => hint.remove());
this.activeHints.clear();
// Clear all timeouts
this.hintTimeouts.forEach(timeout => clearTimeout(timeout));
this.hintTimeouts.clear();
// Clear hint pool
this.hintPool.forEach(hint => hint.remove());
this.hintPool = [];
// Clear processed images
this.processedImages = new WeakSet();
}
}
// Export singleton instance
export default CKEditorPhotoSwipeIntegration.getInstance();

View File

@@ -23,11 +23,13 @@ interface Options {
tooltip?: boolean;
trim?: boolean;
imageHasZoom?: boolean;
/** If enabled, it will prevent the default behavior in which an empty note would display a list of children. */
noChildrenList?: boolean;
}
const CODE_MIME_TYPES = new Set(["application/json"]);
async function getRenderedContent(this: {} | { ctx: string }, entity: FNote | FAttachment, options: Options = {}) {
export async function getRenderedContent(this: {} | { ctx: string }, entity: FNote | FAttachment, options: Options = {}) {
options = Object.assign(
{
@@ -42,7 +44,7 @@ async function getRenderedContent(this: {} | { ctx: string }, entity: FNote | FA
const $renderedContent = $('<div class="rendered-content">');
if (type === "text" || type === "book") {
await renderText(entity, $renderedContent);
await renderText(entity, $renderedContent, options);
} else if (type === "code") {
await renderCode(entity, $renderedContent);
} else if (["image", "canvas", "mindMap"].includes(type)) {
@@ -114,7 +116,7 @@ async function getRenderedContent(this: {} | { ctx: string }, entity: FNote | FA
};
}
async function renderText(note: FNote | FAttachment, $renderedContent: JQuery<HTMLElement>) {
async function renderText(note: FNote | FAttachment, $renderedContent: JQuery<HTMLElement>, options: Options = {}) {
// entity must be FNote
const blob = await note.getBlob();
@@ -135,7 +137,7 @@ async function renderText(note: FNote | FAttachment, $renderedContent: JQuery<HT
}
await formatCodeBlocks($renderedContent);
} else if (note instanceof FNote) {
} else if (note instanceof FNote && !options.noChildrenList) {
await renderChildrenList($renderedContent, note);
}
}
@@ -256,8 +258,19 @@ function renderFile(entity: FNote | FAttachment, type: string, $renderedContent:
</button>
`);
$downloadButton.on("click", () => openService.downloadFileNote(entity.noteId));
$openButton.on("click", () => openService.openNoteExternally(entity.noteId, entity.mime));
$downloadButton.on("click", (e) => {
e.stopPropagation();
openService.downloadFileNote(entity.noteId)
});
$openButton.on("click", async (e) => {
const iconEl = $openButton.find("> .bx");
iconEl.removeClass("bx bx-link-external");
iconEl.addClass("bx bx-loader spin");
e.stopPropagation();
await openService.openNoteExternally(entity.noteId, entity.mime)
iconEl.removeClass("bx bx-loader spin");
iconEl.addClass("bx bx-link-external");
});
// open doesn't work for protected notes since it works through a browser which isn't in protected session
$openButton.toggle(!entity.isProtected);

View File

@@ -1,21 +1,39 @@
import {readCssVar} from "../utils/css-var";
import Color, { ColorInstance } from "color";
const registeredClasses = new Set<string>();
function createClassForColor(color: string | null) {
if (!color?.trim()) {
return "";
}
// Read the color lightness limits defined in the theme as CSS variables
const normalizedColorName = color.replace(/[^a-z0-9]/gi, "");
const lightThemeColorMaxLightness = readCssVar(
document.documentElement,
"tree-item-light-theme-max-color-lightness"
).asNumber(70);
if (!normalizedColorName.trim()) {
return "";
}
const darkThemeColorMinLightness = readCssVar(
document.documentElement,
"tree-item-dark-theme-min-color-lightness"
).asNumber(50);
const className = `color-${normalizedColorName}`;
function createClassForColor(colorString: string | null) {
if (!colorString?.trim()) return "";
const color = parseColor(colorString);
if (!color) return "";
const className = `color-${color.hex().substring(1)}`;
if (!registeredClasses.has(className)) {
// make the active fancytree selector more specific than the normal color setting
$("head").append(`<style>.${className}, span.fancytree-active.${className} { color: ${color} !important; }</style>`);
const adjustedColor = adjustColorLightness(color, lightThemeColorMaxLightness!,
darkThemeColorMinLightness!);
$("head").append(`<style>
.${className}, span.fancytree-active.${className} {
--light-theme-custom-color: ${adjustedColor.lightThemeColor};
--dark-theme-custom-color: ${adjustedColor.darkThemeColor};
--custom-color-hue: ${getHue(color) ?? 'unset'};
}
</style>`);
registeredClasses.add(className);
}
@@ -23,6 +41,41 @@ function createClassForColor(color: string | null) {
return className;
}
function parseColor(color: string) {
try {
return Color(color);
} catch (ex) {
console.error(ex);
}
}
/**
* Returns a pair of colors — one optimized for light themes and the other for dark themes, derived
* from the specified color to maintain sufficient contrast with each theme.
* The adjustment is performed by limiting the colors lightness in the CIELAB color space,
* according to the lightThemeMaxLightness and darkThemeMinLightness parameters.
*/
function adjustColorLightness(color: ColorInstance, lightThemeMaxLightness: number, darkThemeMinLightness: number) {
const labColor = color.lab();
const lightness = labColor.l();
// For the light theme, limit the maximum lightness
const lightThemeColor = labColor.l(Math.min(lightness, lightThemeMaxLightness)).hex();
// For the dark theme, limit the minimum lightness
const darkThemeColor = labColor.l(Math.max(lightness, darkThemeMinLightness)).hex();
return {lightThemeColor, darkThemeColor};
}
/** Returns the hue of the specified color, or undefined if the color is grayscale. */
function getHue(color: ColorInstance) {
const hslColor = color.hsl();
if (hslColor.saturationl() > 0) {
return hslColor.hue();
}
}
export default {
createClassForColor
};

View File

@@ -60,7 +60,7 @@ async function confirmDeleteNoteBoxWithNote(title: string) {
return new Promise<ConfirmDialogResult | undefined>((res) => appContext.triggerCommand("showConfirmDeleteNoteBoxWithNoteDialog", { title, callback: res }));
}
async function prompt(props: PromptDialogOptions) {
export async function prompt(props: PromptDialogOptions) {
return new Promise<string | null>((res) => appContext.triggerCommand("showPromptDialog", { ...props, callback: res }));
}

View File

@@ -48,6 +48,6 @@ function getUrl(docNameValue: string, language: string) {
// Cannot have spaces in the URL due to how JQuery.load works.
docNameValue = docNameValue.replaceAll(" ", "%20");
const basePath = window.glob.isDev ? new URL(window.glob.assetPath).pathname : window.glob.assetPath;
const basePath = window.glob.isDev ? window.glob.assetPath + "/.." : window.glob.assetPath;
return `${basePath}/doc_notes/${language}/${docNameValue}.html`;
}

View File

@@ -1,16 +1,8 @@
import ws from "./ws.js";
import appContext from "../components/app_context.js";
import { OpenedFileUpdateStatus } from "@triliumnext/commons";
// TODO: Deduplicate
interface Message {
type: string;
entityType: string;
entityId: string;
lastModifiedMs: number;
filePath: string;
}
const fileModificationStatus: Record<string, Record<string, Message>> = {
const fileModificationStatus: Record<string, Record<string, OpenedFileUpdateStatus>> = {
notes: {},
attachments: {}
};
@@ -39,7 +31,7 @@ function ignoreModification(entityType: string, entityId: string) {
delete fileModificationStatus[entityType][entityId];
}
ws.subscribeToMessages(async (message: Message) => {
ws.subscribeToMessages(async message => {
if (message.type !== "openedFileUpdated") {
return;
}

View File

@@ -40,20 +40,23 @@ class FrocaImpl implements Froca {
constructor() {
this.initializedPromise = this.loadInitialTree();
this.#clear();
}
async loadInitialTree() {
const resp = await server.get<SubtreeResponse>("tree");
// clear the cache only directly before adding new content which is important for e.g., switching to protected session
this.#clear();
this.addResp(resp);
}
#clear() {
this.notes = {};
this.branches = {};
this.attributes = {};
this.attachments = {};
this.blobPromises = {};
this.addResp(resp);
}
async loadSubTree(subTreeNoteId: string) {

View File

@@ -8,6 +8,7 @@ import FAttribute, { type FAttributeRow } from "../entities/fattribute.js";
import FAttachment, { type FAttachmentRow } from "../entities/fattachment.js";
import type { default as FNote, FNoteRow } from "../entities/fnote.js";
import type { EntityChange } from "../server_types.js";
import type { OptionNames } from "@triliumnext/commons";
async function processEntityChanges(entityChanges: EntityChange[]) {
const loadResults = new LoadResults(entityChanges);
@@ -30,13 +31,14 @@ async function processEntityChanges(entityChanges: EntityChange[]) {
continue; // only noise
}
options.set(attributeEntity.name, attributeEntity.value);
loadResults.addOption(attributeEntity.name);
options.set(attributeEntity.name as OptionNames, attributeEntity.value);
loadResults.addOption(attributeEntity.name as OptionNames);
} else if (ec.entityName === "attachments") {
processAttachment(loadResults, ec);
} else if (ec.entityName === "blobs" || ec.entityName === "etapi_tokens") {
} else if (ec.entityName === "blobs") {
// NOOP - these entities are handled at the backend level and don't require frontend processing
} else if (ec.entityName === "etapi_tokens") {
loadResults.hasEtapiTokenChanges = true;
} else {
throw new Error(`Unknown entityName '${ec.entityName}'`);
}
@@ -77,9 +79,7 @@ async function processEntityChanges(entityChanges: EntityChange[]) {
noteAttributeCache.invalidate();
}
// TODO: Remove after porting the file
// @ts-ignore
const appContext = (await import("../components/app_context.js")).default as any;
const appContext = (await import("../components/app_context.js")).default;
await appContext.triggerEvent("entitiesReloaded", { loadResults });
}
}

View File

@@ -21,6 +21,7 @@ import dayjs from "dayjs";
import type NoteContext from "../components/note_context.js";
import type NoteDetailWidget from "../widgets/note_detail.js";
import type Component from "../components/component.js";
import { formatLogMessage } from "@triliumnext/commons";
/**
* A whole number
@@ -455,7 +456,7 @@ export interface Api {
/**
* Log given message to the log pane in UI
*/
log(message: string): void;
log(message: string | object): void;
}
/**
@@ -696,7 +697,7 @@ function FrontendScriptApi(this: Api, startNote: FNote, currentNote: FNote, orig
this.log = (message) => {
const { noteId } = this.startNote;
message = `${utils.now()}: ${message}`;
message = `${utils.now()}: ${formatLogMessage(message)}`;
console.log(`Script ${noteId}: ${message}`);

View File

@@ -1,28 +0,0 @@
/**
* The front script API is accessible to code notes with the "JS (frontend)" language.
*
* The entire API is exposed as a single global: {@link api}
*
* @module Frontend Script API
*/
/**
* This file creates the entrypoint for TypeDoc that simulates the context from within a
* script note.
*
* Make sure to keep in line with frontend's `script_context.ts`.
*/
export type { default as BasicWidget } from "../widgets/basic_widget.js";
export type { default as FAttachment } from "../entities/fattachment.js";
export type { default as FAttribute } from "../entities/fattribute.js";
export type { default as FBranch } from "../entities/fbranch.js";
export type { default as FNote } from "../entities/fnote.js";
export type { Api } from "./frontend_script_api.js";
export type { default as NoteContextAwareWidget } from "../widgets/note_context_aware_widget.js";
export type { default as RightPanelWidget } from "../widgets/right_panel_widget.js";
import FrontendScriptApi, { type Api } from "./frontend_script_api.js";
//@ts-expect-error
export const api: Api = new FrontendScriptApi();

View File

@@ -1,387 +0,0 @@
/**
* Tests for Gallery Manager
*/
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import galleryManager from './gallery_manager';
import mediaViewer from './media_viewer';
import type { GalleryItem, GalleryConfig } from './gallery_manager';
import type { MediaViewerCallbacks } from './media_viewer';
// Mock media viewer
vi.mock('./media_viewer', () => ({
default: {
open: vi.fn(),
openSingle: vi.fn(),
close: vi.fn(),
next: vi.fn(),
prev: vi.fn(),
goTo: vi.fn(),
getCurrentIndex: vi.fn(() => 0),
isOpen: vi.fn(() => false),
getImageDimensions: vi.fn(() => Promise.resolve({ width: 800, height: 600 }))
}
}));
// Mock froca
vi.mock('./froca', () => ({
default: {
getNoteComplement: vi.fn()
}
}));
// Mock utils
vi.mock('./utils', () => ({
default: {
createImageSrcUrl: vi.fn((note: any) => `/api/images/${note.noteId}`),
randomString: vi.fn(() => 'test123')
}
}));
describe('GalleryManager', () => {
let mockItems: GalleryItem[];
beforeEach(() => {
// Reset mocks
vi.clearAllMocks();
// Create mock gallery items
mockItems = [
{
src: '/api/images/note1/image1.jpg',
alt: 'Image 1',
title: 'First Image',
noteId: 'note1',
index: 0,
width: 800,
height: 600
},
{
src: '/api/images/note1/image2.jpg',
alt: 'Image 2',
title: 'Second Image',
noteId: 'note1',
index: 1,
width: 1024,
height: 768
},
{
src: '/api/images/note1/image3.jpg',
alt: 'Image 3',
title: 'Third Image',
noteId: 'note1',
index: 2,
width: 1920,
height: 1080
}
];
// Setup DOM
document.body.innerHTML = '';
});
afterEach(() => {
// Cleanup
galleryManager.cleanup();
document.body.innerHTML = '';
});
describe('Gallery Creation', () => {
it('should create gallery from container with images', async () => {
// Create container with images
const container = document.createElement('div');
container.innerHTML = `
<img src="/api/images/note1/image1.jpg" alt="Image 1" />
<img src="/api/images/note1/image2.jpg" alt="Image 2" />
<img src="/api/images/note1/image3.jpg" alt="Image 3" />
`;
document.body.appendChild(container);
// Create gallery from container
const items = await galleryManager.createGalleryFromContainer(container);
expect(items).toHaveLength(3);
expect(items[0].src).toBe('/api/images/note1/image1.jpg');
expect(items[0].alt).toBe('Image 1');
expect(items[0].index).toBe(0);
});
it('should extract captions from figure elements', async () => {
const container = document.createElement('div');
container.innerHTML = `
<figure>
<img src="/api/images/note1/image1.jpg" alt="Image 1" />
<figcaption>This is a caption</figcaption>
</figure>
`;
document.body.appendChild(container);
const items = await galleryManager.createGalleryFromContainer(container);
expect(items).toHaveLength(1);
expect(items[0].caption).toBe('This is a caption');
});
it('should handle images without dimensions', async () => {
const container = document.createElement('div');
container.innerHTML = `<img src="/api/images/note1/image1.jpg" alt="Image 1" />`;
document.body.appendChild(container);
const items = await galleryManager.createGalleryFromContainer(container);
expect(items).toHaveLength(1);
expect(items[0].width).toBe(800); // From mocked getImageDimensions
expect(items[0].height).toBe(600);
expect(mediaViewer.getImageDimensions).toHaveBeenCalledWith('/api/images/note1/image1.jpg');
});
});
describe('Gallery Opening', () => {
it('should open gallery with multiple items', () => {
const callbacks: MediaViewerCallbacks = {
onOpen: vi.fn(),
onClose: vi.fn(),
onChange: vi.fn()
};
galleryManager.openGallery(mockItems, 0, {}, callbacks);
expect(mediaViewer.open).toHaveBeenCalledWith(
mockItems,
0,
expect.objectContaining({
loop: true,
allowPanToNext: true,
preload: [2, 2]
}),
expect.objectContaining({
onOpen: expect.any(Function),
onClose: expect.any(Function),
onChange: expect.any(Function)
})
);
});
it('should handle empty items array', () => {
galleryManager.openGallery([], 0);
expect(mediaViewer.open).not.toHaveBeenCalled();
});
it('should apply custom configuration', () => {
const config: GalleryConfig = {
showThumbnails: false,
autoPlay: true,
slideInterval: 5000,
loop: false
};
galleryManager.openGallery(mockItems, 0, config);
expect(mediaViewer.open).toHaveBeenCalledWith(
mockItems,
0,
expect.objectContaining({
loop: false
}),
expect.any(Object)
);
});
});
describe('Gallery Navigation', () => {
beforeEach(() => {
// Open a gallery first
galleryManager.openGallery(mockItems, 0);
});
it('should navigate to next slide', () => {
galleryManager.nextSlide();
expect(mediaViewer.next).toHaveBeenCalled();
});
it('should navigate to previous slide', () => {
galleryManager.previousSlide();
expect(mediaViewer.prev).toHaveBeenCalled();
});
it('should go to specific slide', () => {
galleryManager.goToSlide(2);
expect(mediaViewer.goTo).toHaveBeenCalledWith(2);
});
it('should not navigate to invalid slide index', () => {
const state = galleryManager.getGalleryState();
if (state) {
// Try to go to invalid index
galleryManager.goToSlide(-1);
expect(mediaViewer.goTo).not.toHaveBeenCalled();
galleryManager.goToSlide(10);
expect(mediaViewer.goTo).not.toHaveBeenCalled();
}
});
});
describe('Slideshow Functionality', () => {
beforeEach(() => {
vi.useFakeTimers();
galleryManager.openGallery(mockItems, 0, { autoPlay: false });
});
afterEach(() => {
vi.useRealTimers();
});
it('should start slideshow', () => {
const state = galleryManager.getGalleryState();
expect(state?.isPlaying).toBe(false);
galleryManager.startSlideshow();
const updatedState = galleryManager.getGalleryState();
expect(updatedState?.isPlaying).toBe(true);
});
it('should stop slideshow', () => {
galleryManager.startSlideshow();
galleryManager.stopSlideshow();
const state = galleryManager.getGalleryState();
expect(state?.isPlaying).toBe(false);
});
it('should toggle slideshow', () => {
const initialState = galleryManager.getGalleryState();
expect(initialState?.isPlaying).toBe(false);
galleryManager.toggleSlideshow();
expect(galleryManager.getGalleryState()?.isPlaying).toBe(true);
galleryManager.toggleSlideshow();
expect(galleryManager.getGalleryState()?.isPlaying).toBe(false);
});
it('should advance slides automatically in slideshow', () => {
galleryManager.startSlideshow();
// Fast-forward time
vi.advanceTimersByTime(4000); // Default interval
expect(mediaViewer.goTo).toHaveBeenCalledWith(1);
});
it('should update slideshow interval', () => {
galleryManager.startSlideshow();
galleryManager.updateSlideshowInterval(5000);
const state = galleryManager.getGalleryState();
expect(state?.config.slideInterval).toBe(5000);
});
});
describe('Gallery State', () => {
it('should track gallery state', () => {
expect(galleryManager.getGalleryState()).toBeNull();
galleryManager.openGallery(mockItems, 1);
const state = galleryManager.getGalleryState();
expect(state).not.toBeNull();
expect(state?.items).toEqual(mockItems);
expect(state?.currentIndex).toBe(1);
});
it('should check if gallery is open', () => {
expect(galleryManager.isGalleryOpen()).toBe(false);
vi.mocked(mediaViewer.isOpen).mockReturnValue(true);
galleryManager.openGallery(mockItems, 0);
expect(galleryManager.isGalleryOpen()).toBe(true);
});
});
describe('Gallery Cleanup', () => {
it('should close gallery on cleanup', () => {
galleryManager.openGallery(mockItems, 0);
galleryManager.cleanup();
expect(mediaViewer.close).toHaveBeenCalled();
expect(galleryManager.getGalleryState()).toBeNull();
});
it('should stop slideshow on close', () => {
galleryManager.openGallery(mockItems, 0, { autoPlay: true });
const state = galleryManager.getGalleryState();
expect(state?.isPlaying).toBe(true);
galleryManager.closeGallery();
expect(mediaViewer.close).toHaveBeenCalled();
});
});
describe('UI Enhancements', () => {
beforeEach(() => {
// Create PhotoSwipe container mock
const pswpElement = document.createElement('div');
pswpElement.className = 'pswp';
document.body.appendChild(pswpElement);
});
it('should add thumbnail strip when enabled', (done) => {
galleryManager.openGallery(mockItems, 0, { showThumbnails: true });
// Wait for UI setup
setTimeout(() => {
const thumbnailStrip = document.querySelector('.gallery-thumbnail-strip');
expect(thumbnailStrip).toBeTruthy();
const thumbnails = document.querySelectorAll('.gallery-thumbnail');
expect(thumbnails).toHaveLength(3);
done();
}, 150);
});
it('should add slideshow controls', (done) => {
galleryManager.openGallery(mockItems, 0);
setTimeout(() => {
const controls = document.querySelector('.gallery-slideshow-controls');
expect(controls).toBeTruthy();
const playPauseBtn = document.querySelector('.slideshow-play-pause');
expect(playPauseBtn).toBeTruthy();
done();
}, 150);
});
it('should add image counter when enabled', (done) => {
galleryManager.openGallery(mockItems, 0, { showCounter: true });
setTimeout(() => {
const counter = document.querySelector('.gallery-counter');
expect(counter).toBeTruthy();
expect(counter?.textContent).toContain('1');
expect(counter?.textContent).toContain('3');
done();
}, 150);
});
it('should add keyboard hints', (done) => {
galleryManager.openGallery(mockItems, 0);
setTimeout(() => {
const hints = document.querySelector('.gallery-keyboard-hints');
expect(hints).toBeTruthy();
expect(hints?.textContent).toContain('Navigate');
expect(hints?.textContent).toContain('ESC');
done();
}, 150);
});
});
});

View File

@@ -1,987 +0,0 @@
/**
* Gallery Manager for PhotoSwipe integration in Trilium Notes
* Handles multi-image galleries, slideshow mode, and navigation features
*/
import mediaViewer, { MediaItem, MediaViewerCallbacks, MediaViewerConfig } from './media_viewer.js';
import utils from './utils.js';
import froca from './froca.js';
import type FNote from '../entities/fnote.js';
/**
* Gallery configuration options
*/
export interface GalleryConfig {
showThumbnails?: boolean;
thumbnailHeight?: number;
autoPlay?: boolean;
slideInterval?: number; // in milliseconds
showCounter?: boolean;
enableKeyboardNav?: boolean;
enableSwipeGestures?: boolean;
preloadCount?: number;
loop?: boolean;
}
/**
* Gallery item with additional metadata
*/
export interface GalleryItem extends MediaItem {
noteId?: string;
attachmentId?: string;
caption?: string;
description?: string;
index?: number;
}
/**
* Gallery state management
*/
interface GalleryState {
items: GalleryItem[];
currentIndex: number;
isPlaying: boolean;
slideshowTimer?: number;
config: Required<GalleryConfig>;
}
/**
* GalleryManager handles multi-image galleries with slideshow and navigation features
*/
class GalleryManager {
private static instance: GalleryManager;
private currentGallery: GalleryState | null = null;
private defaultConfig: Required<GalleryConfig> = {
showThumbnails: true,
thumbnailHeight: 80,
autoPlay: false,
slideInterval: 4000,
showCounter: true,
enableKeyboardNav: true,
enableSwipeGestures: true,
preloadCount: 2,
loop: true
};
private slideshowCallbacks: Set<() => void> = new Set();
private $thumbnailStrip?: JQuery<HTMLElement>;
private $slideshowControls?: JQuery<HTMLElement>;
// Track all dynamically created elements for proper cleanup
private createdElements: Map<string, HTMLElement | JQuery<HTMLElement>> = new Map();
private setupTimeout?: number;
private constructor() {
// Cleanup on window unload
window.addEventListener('beforeunload', () => this.cleanup());
}
/**
* Get singleton instance
*/
static getInstance(): GalleryManager {
if (!GalleryManager.instance) {
GalleryManager.instance = new GalleryManager();
}
return GalleryManager.instance;
}
/**
* Create gallery from images in a note's content
*/
async createGalleryFromNote(note: FNote, config?: GalleryConfig): Promise<GalleryItem[]> {
const items: GalleryItem[] = [];
try {
// Parse note content to find images
const parser = new DOMParser();
const content = await note.getContent();
const doc = parser.parseFromString(content || '', 'text/html');
const images = doc.querySelectorAll('img');
for (let i = 0; i < images.length; i++) {
const img = images[i];
const src = img.getAttribute('src');
if (!src) continue;
// Convert relative URLs to absolute
const absoluteSrc = this.resolveImageSrc(src, note.noteId);
const item: GalleryItem = {
src: absoluteSrc,
alt: img.getAttribute('alt') || `Image ${i + 1} from ${note.title}`,
title: img.getAttribute('title') || img.getAttribute('alt') || undefined,
caption: img.getAttribute('data-caption') || undefined,
noteId: note.noteId,
index: i,
width: parseInt(img.getAttribute('width') || '0') || undefined,
height: parseInt(img.getAttribute('height') || '0') || undefined
};
// Try to get thumbnail from data attribute or create one
const thumbnailSrc = img.getAttribute('data-thumbnail');
if (thumbnailSrc) {
item.msrc = this.resolveImageSrc(thumbnailSrc, note.noteId);
}
items.push(item);
}
// Also check for image attachments
const attachmentItems = await this.getAttachmentImages(note);
items.push(...attachmentItems);
} catch (error) {
console.error('Failed to create gallery from note:', error);
}
return items;
}
/**
* Get image attachments from a note
*/
private async getAttachmentImages(note: FNote): Promise<GalleryItem[]> {
const items: GalleryItem[] = [];
try {
// Get child notes that are images
const childNotes = await note.getChildNotes();
for (const childNote of childNotes) {
if (childNote.type === 'image') {
const item: GalleryItem = {
src: utils.createImageSrcUrl(childNote),
alt: childNote.title,
title: childNote.title,
noteId: childNote.noteId,
index: items.length
};
items.push(item);
}
}
} catch (error) {
console.error('Failed to get attachment images:', error);
}
return items;
}
/**
* Create gallery from a container element with images
*/
async createGalleryFromContainer(
container: HTMLElement | JQuery<HTMLElement>,
selector: string = 'img',
config?: GalleryConfig
): Promise<GalleryItem[]> {
const $container = $(container);
const images = $container.find(selector);
const items: GalleryItem[] = [];
for (let i = 0; i < images.length; i++) {
const img = images[i] as HTMLImageElement;
const item: GalleryItem = {
src: img.src,
alt: img.alt || `Image ${i + 1}`,
title: img.title || img.alt || undefined,
element: img,
index: i,
width: img.naturalWidth || undefined,
height: img.naturalHeight || undefined
};
// Try to extract caption from nearby elements
const $img = $(img);
const $figure = $img.closest('figure');
if ($figure.length) {
const $caption = $figure.find('figcaption');
if ($caption.length) {
item.caption = $caption.text();
}
}
// Check for data attributes
item.noteId = $img.data('note-id');
item.attachmentId = $img.data('attachment-id');
items.push(item);
}
return items;
}
/**
* Open gallery with specified items
*/
openGallery(
items: GalleryItem[],
startIndex: number = 0,
config?: GalleryConfig,
callbacks?: MediaViewerCallbacks
): void {
if (!items || items.length === 0) {
console.warn('No items provided to gallery');
return;
}
// Close any existing gallery
this.closeGallery();
// Merge configuration
const finalConfig = { ...this.defaultConfig, ...config };
// Initialize gallery state
this.currentGallery = {
items,
currentIndex: startIndex,
isPlaying: finalConfig.autoPlay,
config: finalConfig
};
// Enhanced PhotoSwipe configuration for gallery
const photoSwipeConfig: Partial<MediaViewerConfig> = {
bgOpacity: 0.95,
showHideOpacity: true,
allowPanToNext: true,
spacing: 0.12,
loop: finalConfig.loop,
arrowKeys: finalConfig.enableKeyboardNav,
pinchToClose: finalConfig.enableSwipeGestures,
closeOnVerticalDrag: finalConfig.enableSwipeGestures,
preload: [finalConfig.preloadCount, finalConfig.preloadCount],
wheelToZoom: true,
// Enable mobile and accessibility enhancements
mobileA11y: {
touch: {
hapticFeedback: true,
multiTouchEnabled: true
},
a11y: {
enableKeyboardNav: finalConfig.enableKeyboardNav,
enableScreenReaderAnnouncements: true,
keyboardShortcutsEnabled: true
},
mobileUI: {
bottomSheetEnabled: true,
adaptiveToolbar: true,
swipeIndicators: true,
gestureHints: true
},
performance: {
adaptiveQuality: true,
batteryOptimization: true
}
}
};
// Enhanced callbacks
const enhancedCallbacks: MediaViewerCallbacks = {
onOpen: () => {
this.onGalleryOpen();
callbacks?.onOpen?.();
},
onClose: () => {
this.onGalleryClose();
callbacks?.onClose?.();
},
onChange: (index) => {
this.onSlideChange(index);
callbacks?.onChange?.(index);
},
onImageLoad: callbacks?.onImageLoad,
onImageError: callbacks?.onImageError
};
// Open with media viewer
mediaViewer.open(items, startIndex, photoSwipeConfig, enhancedCallbacks);
// Setup gallery UI enhancements
this.setupGalleryUI();
// Start slideshow if configured
if (finalConfig.autoPlay) {
this.startSlideshow();
}
}
/**
* Setup gallery UI enhancements
*/
private setupGalleryUI(): void {
if (!this.currentGallery) return;
// Clear any existing timeout
if (this.setupTimeout) {
clearTimeout(this.setupTimeout);
}
// Add gallery-specific UI elements to PhotoSwipe
this.setupTimeout = window.setTimeout(() => {
// Validate gallery is still open before manipulating DOM
if (!this.currentGallery || !this.isGalleryOpen()) {
return;
}
// PhotoSwipe needs a moment to initialize
const pswpElement = document.querySelector('.pswp');
if (!pswpElement) return;
// Add thumbnail strip if enabled
if (this.currentGallery.config.showThumbnails) {
this.addThumbnailStrip(pswpElement);
}
// Add slideshow controls
this.addSlideshowControls(pswpElement);
// Add image counter if enabled
if (this.currentGallery.config.showCounter) {
this.addImageCounter(pswpElement);
}
// Add keyboard hints
this.addKeyboardHints(pswpElement);
}, 100);
}
/**
* Add thumbnail strip navigation
*/
private addThumbnailStrip(container: Element): void {
if (!this.currentGallery) return;
// Create thumbnail strip container safely using DOM APIs
const stripDiv = document.createElement('div');
stripDiv.className = 'gallery-thumbnail-strip';
stripDiv.setAttribute('style', `
position: absolute;
bottom: 60px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 8px;
padding: 10px;
background: rgba(0, 0, 0, 0.7);
border-radius: 8px;
max-width: 90%;
overflow-x: auto;
z-index: 100;
`);
// Create thumbnails safely
this.currentGallery.items.forEach((item, index) => {
const thumbDiv = document.createElement('div');
thumbDiv.className = 'gallery-thumbnail';
thumbDiv.dataset.index = index.toString();
thumbDiv.setAttribute('style', `
width: ${this.currentGallery!.config.thumbnailHeight}px;
height: ${this.currentGallery!.config.thumbnailHeight}px;
cursor: pointer;
border: 2px solid ${index === this.currentGallery!.currentIndex ? '#fff' : 'transparent'};
border-radius: 4px;
overflow: hidden;
flex-shrink: 0;
opacity: ${index === this.currentGallery!.currentIndex ? '1' : '0.6'};
transition: all 0.2s;
`);
const img = document.createElement('img');
// Sanitize src URLs
const src = this.sanitizeUrl(item.msrc || item.src);
img.src = src;
// Use textContent for safe text insertion
img.alt = this.sanitizeText(item.alt || '');
img.setAttribute('style', `
width: 100%;
height: 100%;
object-fit: cover;
`);
thumbDiv.appendChild(img);
stripDiv.appendChild(thumbDiv);
});
this.$thumbnailStrip = $(stripDiv);
$(container).append(this.$thumbnailStrip);
this.createdElements.set('thumbnailStrip', this.$thumbnailStrip);
// Handle thumbnail clicks
this.$thumbnailStrip.on('click', '.gallery-thumbnail', (e) => {
const index = parseInt($(e.currentTarget).data('index'));
this.goToSlide(index);
});
// Handle hover effect
this.$thumbnailStrip.on('mouseenter', '.gallery-thumbnail', (e) => {
if (!$(e.currentTarget).hasClass('active')) {
$(e.currentTarget).css('opacity', '0.8');
}
});
this.$thumbnailStrip.on('mouseleave', '.gallery-thumbnail', (e) => {
if (!$(e.currentTarget).hasClass('active')) {
$(e.currentTarget).css('opacity', '0.6');
}
});
}
/**
* Sanitize text content to prevent XSS
*/
private sanitizeText(text: string): string {
// Remove any HTML tags and entities
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
/**
* Sanitize URL to prevent XSS
*/
private sanitizeUrl(url: string): string {
// Only allow safe protocols
const allowedProtocols = ['http:', 'https:', 'data:'];
try {
const urlObj = new URL(url, window.location.href);
// Special validation for data URLs
if (urlObj.protocol === 'data:') {
// Only allow image MIME types for data URLs
const allowedImageTypes = [
'data:image/jpeg',
'data:image/jpg',
'data:image/png',
'data:image/gif',
'data:image/webp',
'data:image/svg+xml',
'data:image/bmp'
];
// Check if data URL starts with an allowed image type
const isAllowedImage = allowedImageTypes.some(type =>
url.toLowerCase().startsWith(type)
);
if (!isAllowedImage) {
console.warn('Rejected non-image data URL:', url.substring(0, 50));
return '';
}
// Additional check for base64 encoding
if (!url.includes(';base64,') && !url.includes(';charset=')) {
console.warn('Rejected data URL with invalid encoding');
return '';
}
} else if (!allowedProtocols.includes(urlObj.protocol)) {
return '';
}
return urlObj.href;
} catch {
// If URL parsing fails, check if it's a relative path
if (url.startsWith('/') || url.startsWith('api/')) {
return url;
}
return '';
}
}
/**
* Add slideshow controls
*/
private addSlideshowControls(container: Element): void {
if (!this.currentGallery) return;
const controlsHtml = `
<div class="gallery-slideshow-controls" style="
position: absolute;
top: 20px;
right: 20px;
display: flex;
gap: 10px;
z-index: 100;
">
<button class="slideshow-play-pause" style="
background: rgba(255, 255, 255, 0.9);
border: none;
border-radius: 4px;
width: 44px;
height: 44px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
" aria-label="${this.currentGallery.isPlaying ? 'Pause slideshow' : 'Play slideshow'}">
<i class="bx ${this.currentGallery.isPlaying ? 'bx-pause' : 'bx-play'}"></i>
</button>
<button class="slideshow-settings" style="
background: rgba(255, 255, 255, 0.9);
border: none;
border-radius: 4px;
width: 44px;
height: 44px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
" aria-label="Slideshow settings">
<i class="bx bx-cog"></i>
</button>
</div>
<div class="slideshow-interval-selector" style="
position: absolute;
top: 80px;
right: 20px;
background: rgba(0, 0, 0, 0.8);
color: white;
padding: 10px;
border-radius: 4px;
display: none;
z-index: 101;
">
<label style="display: block; margin-bottom: 5px;">Slide interval:</label>
<select class="interval-select" style="
background: rgba(255, 255, 255, 0.1);
color: white;
border: 1px solid rgba(255, 255, 255, 0.3);
padding: 4px;
border-radius: 3px;
">
<option value="3000">3 seconds</option>
<option value="4000" selected>4 seconds</option>
<option value="5000">5 seconds</option>
<option value="7000">7 seconds</option>
<option value="10000">10 seconds</option>
</select>
</div>
`;
this.$slideshowControls = $(controlsHtml);
$(container).append(this.$slideshowControls);
this.createdElements.set('slideshowControls', this.$slideshowControls);
// Handle play/pause button
this.$slideshowControls.find('.slideshow-play-pause').on('click', () => {
this.toggleSlideshow();
});
// Handle settings button
this.$slideshowControls.find('.slideshow-settings').on('click', () => {
const $selector = this.$slideshowControls?.find('.slideshow-interval-selector');
$selector?.toggle();
});
// Handle interval change
this.$slideshowControls.find('.interval-select').on('change', (e) => {
const interval = parseInt($(e.target).val() as string);
this.updateSlideshowInterval(interval);
});
}
/**
* Add image counter
*/
private addImageCounter(container: Element): void {
if (!this.currentGallery) return;
// Create counter element safely
const counterDiv = document.createElement('div');
counterDiv.className = 'gallery-counter';
counterDiv.setAttribute('style', `
position: absolute;
top: 20px;
left: 20px;
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 8px 12px;
border-radius: 4px;
font-size: 14px;
z-index: 100;
`);
const currentSpan = document.createElement('span');
currentSpan.className = 'current-index';
currentSpan.textContent = String(this.currentGallery.currentIndex + 1);
const separatorSpan = document.createElement('span');
separatorSpan.textContent = ' / ';
const totalSpan = document.createElement('span');
totalSpan.className = 'total-count';
totalSpan.textContent = String(this.currentGallery.items.length);
counterDiv.appendChild(currentSpan);
counterDiv.appendChild(separatorSpan);
counterDiv.appendChild(totalSpan);
container.appendChild(counterDiv);
this.createdElements.set('counter', counterDiv);
}
/**
* Add keyboard hints overlay
*/
private addKeyboardHints(container: Element): void {
// Create hints element safely
const hintsDiv = document.createElement('div');
hintsDiv.className = 'gallery-keyboard-hints';
hintsDiv.setAttribute('style', `
position: absolute;
bottom: 20px;
left: 20px;
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 8px 12px;
border-radius: 4px;
font-size: 12px;
opacity: 0;
transition: opacity 0.3s;
z-index: 100;
`);
// Create hint items
const hints = [
{ key: '←/→', action: 'Navigate' },
{ key: 'Space', action: 'Play/Pause' },
{ key: 'ESC', action: 'Close' }
];
hints.forEach(hint => {
const hintItem = document.createElement('div');
const kbd = document.createElement('kbd');
kbd.style.cssText = 'background: rgba(255,255,255,0.2); padding: 2px 4px; border-radius: 2px;';
kbd.textContent = hint.key;
hintItem.appendChild(kbd);
hintItem.appendChild(document.createTextNode(' ' + hint.action));
hintsDiv.appendChild(hintItem);
});
container.appendChild(hintsDiv);
this.createdElements.set('keyboardHints', hintsDiv);
const $hints = $(hintsDiv);
// Show hints on hover with scoped selector
const handleMouseEnter = () => {
if (this.currentGallery) {
$hints.css('opacity', '0.6');
}
};
const handleMouseLeave = () => {
$hints.css('opacity', '0');
};
$(container).on('mouseenter.galleryHints', handleMouseEnter);
$(container).on('mouseleave.galleryHints', handleMouseLeave);
// Track cleanup callback
this.slideshowCallbacks.add(() => {
$(container).off('.galleryHints');
});
}
/**
* Handle gallery open event
*/
private onGalleryOpen(): void {
// Add keyboard listener for slideshow control
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === ' ') {
e.preventDefault();
this.toggleSlideshow();
}
};
document.addEventListener('keydown', handleKeyDown);
this.slideshowCallbacks.add(() => {
document.removeEventListener('keydown', handleKeyDown);
});
}
/**
* Handle gallery close event
*/
private onGalleryClose(): void {
this.stopSlideshow();
// Clear setup timeout if exists
if (this.setupTimeout) {
clearTimeout(this.setupTimeout);
this.setupTimeout = undefined;
}
// Cleanup event listeners
this.slideshowCallbacks.forEach(callback => callback());
this.slideshowCallbacks.clear();
// Remove all tracked UI elements
this.createdElements.forEach((element, key) => {
if (element instanceof HTMLElement) {
element.remove();
} else if (element instanceof $) {
element.remove();
}
});
this.createdElements.clear();
// Clear jQuery references
this.$thumbnailStrip = undefined;
this.$slideshowControls = undefined;
// Clear state
this.currentGallery = null;
}
/**
* Handle slide change event
*/
private onSlideChange(index: number): void {
if (!this.currentGallery) return;
this.currentGallery.currentIndex = index;
// Update thumbnail highlighting
if (this.$thumbnailStrip) {
this.$thumbnailStrip.find('.gallery-thumbnail').each((i, el) => {
const $thumb = $(el);
if (i === index) {
$thumb.css({
'border-color': '#fff',
'opacity': '1'
});
// Scroll thumbnail into view
const thumbLeft = $thumb.position().left;
const thumbWidth = $thumb.outerWidth() || 0;
const stripWidth = this.$thumbnailStrip!.width() || 0;
const scrollLeft = this.$thumbnailStrip!.scrollLeft() || 0;
if (thumbLeft < 0) {
this.$thumbnailStrip!.scrollLeft(scrollLeft + thumbLeft - 10);
} else if (thumbLeft + thumbWidth > stripWidth) {
this.$thumbnailStrip!.scrollLeft(scrollLeft + (thumbLeft + thumbWidth - stripWidth) + 10);
}
} else {
$thumb.css({
'border-color': 'transparent',
'opacity': '0.6'
});
}
});
}
// Update counter using tracked element
const counterElement = this.createdElements.get('counter');
if (counterElement instanceof HTMLElement) {
const currentIndexElement = counterElement.querySelector('.current-index');
if (currentIndexElement) {
currentIndexElement.textContent = String(index + 1);
}
}
}
/**
* Start slideshow
*/
startSlideshow(): void {
if (!this.currentGallery || this.currentGallery.isPlaying) return;
// Validate gallery state before starting slideshow
if (!this.isGalleryOpen() || this.currentGallery.items.length === 0) {
console.warn('Cannot start slideshow: gallery not ready');
return;
}
// Ensure PhotoSwipe is ready
if (!mediaViewer.isOpen()) {
console.warn('Cannot start slideshow: PhotoSwipe not ready');
return;
}
this.currentGallery.isPlaying = true;
// Update button icon
this.$slideshowControls?.find('.slideshow-play-pause i')
.removeClass('bx-play')
.addClass('bx-pause');
// Start timer
this.scheduleNextSlide();
}
/**
* Stop slideshow
*/
stopSlideshow(): void {
if (!this.currentGallery) return;
this.currentGallery.isPlaying = false;
// Clear timer
if (this.currentGallery.slideshowTimer) {
clearTimeout(this.currentGallery.slideshowTimer);
this.currentGallery.slideshowTimer = undefined;
}
// Update button icon
this.$slideshowControls?.find('.slideshow-play-pause i')
.removeClass('bx-pause')
.addClass('bx-play');
}
/**
* Toggle slideshow play/pause
*/
toggleSlideshow(): void {
if (!this.currentGallery) return;
if (this.currentGallery.isPlaying) {
this.stopSlideshow();
} else {
this.startSlideshow();
}
}
/**
* Schedule next slide in slideshow
*/
private scheduleNextSlide(): void {
if (!this.currentGallery || !this.currentGallery.isPlaying) return;
// Clear any existing timer
if (this.currentGallery.slideshowTimer) {
clearTimeout(this.currentGallery.slideshowTimer);
}
this.currentGallery.slideshowTimer = window.setTimeout(() => {
if (!this.currentGallery || !this.currentGallery.isPlaying) return;
// Go to next slide
const nextIndex = (this.currentGallery.currentIndex + 1) % this.currentGallery.items.length;
this.goToSlide(nextIndex);
// Schedule next transition
this.scheduleNextSlide();
}, this.currentGallery.config.slideInterval);
}
/**
* Update slideshow interval
*/
updateSlideshowInterval(interval: number): void {
if (!this.currentGallery) return;
this.currentGallery.config.slideInterval = interval;
// Restart slideshow with new interval if playing
if (this.currentGallery.isPlaying) {
this.stopSlideshow();
this.startSlideshow();
}
}
/**
* Go to specific slide
*/
goToSlide(index: number): void {
if (!this.currentGallery) return;
if (index >= 0 && index < this.currentGallery.items.length) {
mediaViewer.goTo(index);
}
}
/**
* Navigate to next slide
*/
nextSlide(): void {
mediaViewer.next();
}
/**
* Navigate to previous slide
*/
previousSlide(): void {
mediaViewer.prev();
}
/**
* Close gallery
*/
closeGallery(): void {
mediaViewer.close();
}
/**
* Check if gallery is open
*/
isGalleryOpen(): boolean {
return this.currentGallery !== null && mediaViewer.isOpen();
}
/**
* Get current gallery state
*/
getGalleryState(): GalleryState | null {
return this.currentGallery;
}
/**
* Resolve image source URL
*/
private resolveImageSrc(src: string, noteId: string): string {
// Handle different image source formats
if (src.startsWith('http://') || src.startsWith('https://')) {
return src;
}
if (src.startsWith('api/images/')) {
return `/${src}`;
}
if (src.startsWith('/')) {
return src;
}
// Assume it's a note ID or attachment reference
return `/api/images/${noteId}/${src}`;
}
/**
* Cleanup resources
*/
cleanup(): void {
// Clear any pending timeouts
if (this.setupTimeout) {
clearTimeout(this.setupTimeout);
this.setupTimeout = undefined;
}
this.closeGallery();
// Ensure all elements are removed
this.createdElements.forEach((element) => {
if (element instanceof HTMLElement) {
element.remove();
} else if (element instanceof $) {
element.remove();
}
});
this.createdElements.clear();
this.slideshowCallbacks.clear();
this.currentGallery = null;
}
}
// Export singleton instance
export default GalleryManager.getInstance();

View File

@@ -20,9 +20,6 @@ function setupGlobs() {
window.glob.froca = froca;
window.glob.treeCache = froca; // compatibility for CKEditor builds for a while
// for CKEditor integration (button on block toolbar)
window.glob.importMarkdownInline = async () => appContext.triggerCommand("importMarkdownInline");
window.onerror = function (msg, url, lineNo, columnNo, error) {
const string = String(msg).toLowerCase();

View File

@@ -6,7 +6,7 @@ import { describe, expect, it } from "vitest";
describe("i18n", () => {
it("translations are valid JSON", () => {
for (const locale of LOCALES) {
if (locale.contentOnly) {
if (locale.contentOnly || locale.id === "en_rtl") {
continue;
}

View File

@@ -3,6 +3,7 @@ import i18next from "i18next";
import i18nextHttpBackend from "i18next-http-backend";
import server from "./server.js";
import type { Locale } from "@triliumnext/commons";
import { initReactI18next } from "react-i18next";
let locales: Locale[] | null;
@@ -16,6 +17,7 @@ export async function initLocale() {
locales = await server.get<Locale[]>("options/locales");
i18next.use(initReactI18next);
await i18next.use(i18nextHttpBackend).init({
lng: locale,
fallbackLng: "en",

View File

@@ -1,7 +1,7 @@
import { t } from "./i18n.js";
import toastService, { showError } from "./toast.js";
function copyImageReferenceToClipboard($imageWrapper: JQuery<HTMLElement>) {
export function copyImageReferenceToClipboard($imageWrapper: JQuery<HTMLElement>) {
try {
$imageWrapper.attr("contenteditable", "true");
selectImage($imageWrapper.get(0));

View File

@@ -1,597 +0,0 @@
/**
* Image Annotations Module for PhotoSwipe
* Provides ability to add, display, and manage annotations on images
*/
import froca from './froca.js';
import server from './server.js';
import type FNote from '../entities/fnote.js';
import type FAttribute from '../entities/fattribute.js';
import { ImageValidator, withErrorBoundary, ImageError, ImageErrorType } from './image_error_handler.js';
/**
* Annotation position and data
*/
export interface ImageAnnotation {
id: string;
noteId: string;
x: number; // Percentage from left (0-100)
y: number; // Percentage from top (0-100)
text: string;
author?: string;
created: Date;
modified?: Date;
color?: string;
icon?: string;
type?: 'comment' | 'marker' | 'region';
width?: number; // For region type
height?: number; // For region type
}
/**
* Annotation configuration
*/
export interface AnnotationConfig {
enableAnnotations: boolean;
showByDefault: boolean;
allowEditing: boolean;
defaultColor: string;
defaultIcon: string;
}
/**
* ImageAnnotationsService manages image annotations using Trilium's attribute system
*/
class ImageAnnotationsService {
private static instance: ImageAnnotationsService;
private activeAnnotations: Map<string, ImageAnnotation[]> = new Map();
private annotationElements: Map<string, HTMLElement> = new Map();
private isEditMode: boolean = false;
private selectedAnnotation: ImageAnnotation | null = null;
private config: AnnotationConfig = {
enableAnnotations: true,
showByDefault: true,
allowEditing: true,
defaultColor: '#ffeb3b',
defaultIcon: 'bx-comment'
};
// Annotation attribute prefix in Trilium
private readonly ANNOTATION_PREFIX = 'imageAnnotation';
private constructor() {}
static getInstance(): ImageAnnotationsService {
if (!ImageAnnotationsService.instance) {
ImageAnnotationsService.instance = new ImageAnnotationsService();
}
return ImageAnnotationsService.instance;
}
/**
* Load annotations for an image note
*/
async loadAnnotations(noteId: string): Promise<ImageAnnotation[]> {
return await withErrorBoundary(async () => {
// Validate note ID
if (!noteId || typeof noteId !== 'string') {
throw new ImageError(
ImageErrorType.INVALID_INPUT,
'Invalid note ID provided'
);
}
const note = await froca.getNote(noteId);
if (!note) return [];
const attributes = note.getAttributes();
const annotations: ImageAnnotation[] = [];
// Parse annotation attributes
for (const attr of attributes) {
if (attr.name.startsWith(this.ANNOTATION_PREFIX)) {
try {
const annotationData = JSON.parse(attr.value);
annotations.push({
...annotationData,
id: attr.attributeId,
noteId: noteId,
created: new Date(annotationData.created),
modified: annotationData.modified ? new Date(annotationData.modified) : undefined
});
} catch (error) {
console.error('Failed to parse annotation:', error);
}
}
}
// Sort by creation date
annotations.sort((a, b) => a.created.getTime() - b.created.getTime());
this.activeAnnotations.set(noteId, annotations);
return annotations;
}) || [];
}
/**
* Save a new annotation
*/
async saveAnnotation(annotation: Omit<ImageAnnotation, 'id' | 'created'>): Promise<ImageAnnotation> {
return await withErrorBoundary(async () => {
// Validate annotation data
if (!annotation.text || !annotation.noteId) {
throw new ImageError(
ImageErrorType.INVALID_INPUT,
'Invalid annotation data'
);
}
// Sanitize text
annotation.text = this.sanitizeText(annotation.text);
const note = await froca.getNote(annotation.noteId);
if (!note) {
throw new Error('Note not found');
}
const newAnnotation: ImageAnnotation = {
...annotation,
id: this.generateId(),
created: new Date()
};
// Save as note attribute
const attributeName = `${this.ANNOTATION_PREFIX}_${newAnnotation.id}`;
const attributeValue = JSON.stringify({
x: newAnnotation.x,
y: newAnnotation.y,
text: newAnnotation.text,
author: newAnnotation.author,
created: newAnnotation.created.toISOString(),
color: newAnnotation.color,
icon: newAnnotation.icon,
type: newAnnotation.type,
width: newAnnotation.width,
height: newAnnotation.height
});
await server.put(`notes/${annotation.noteId}/attributes`, {
attributes: [{
type: 'label',
name: attributeName,
value: attributeValue
}]
});
// Update cache
const annotations = this.activeAnnotations.get(annotation.noteId) || [];
annotations.push(newAnnotation);
this.activeAnnotations.set(annotation.noteId, annotations);
return newAnnotation;
}) as Promise<ImageAnnotation>;
}
/**
* Update an existing annotation
*/
async updateAnnotation(annotation: ImageAnnotation): Promise<void> {
try {
const note = await froca.getNote(annotation.noteId);
if (!note) {
throw new Error('Note not found');
}
annotation.modified = new Date();
// Update attribute
const attributeName = `${this.ANNOTATION_PREFIX}_${annotation.id}`;
const attributeValue = JSON.stringify({
x: annotation.x,
y: annotation.y,
text: annotation.text,
author: annotation.author,
created: annotation.created.toISOString(),
modified: annotation.modified.toISOString(),
color: annotation.color,
icon: annotation.icon,
type: annotation.type,
width: annotation.width,
height: annotation.height
});
// Find and update the attribute
const attributes = note.getAttributes();
const attr = attributes.find(a => a.name === attributeName);
if (attr) {
await server.put(`notes/${annotation.noteId}/attributes/${attr.attributeId}`, {
value: attributeValue
});
}
// Update cache
const annotations = this.activeAnnotations.get(annotation.noteId) || [];
const index = annotations.findIndex(a => a.id === annotation.id);
if (index !== -1) {
annotations[index] = annotation;
this.activeAnnotations.set(annotation.noteId, annotations);
}
} catch (error) {
console.error('Failed to update annotation:', error);
throw error;
}
}
/**
* Delete an annotation
*/
async deleteAnnotation(noteId: string, annotationId: string): Promise<void> {
try {
const note = await froca.getNote(noteId);
if (!note) return;
const attributeName = `${this.ANNOTATION_PREFIX}_${annotationId}`;
const attributes = note.getAttributes();
const attr = attributes.find(a => a.name === attributeName);
if (attr) {
await server.remove(`notes/${noteId}/attributes/${attr.attributeId}`);
}
// Update cache
const annotations = this.activeAnnotations.get(noteId) || [];
const filtered = annotations.filter(a => a.id !== annotationId);
this.activeAnnotations.set(noteId, filtered);
// Remove element if exists
const element = this.annotationElements.get(annotationId);
if (element) {
element.remove();
this.annotationElements.delete(annotationId);
}
} catch (error) {
console.error('Failed to delete annotation:', error);
throw error;
}
}
/**
* Render annotations on an image container
*/
renderAnnotations(container: HTMLElement, noteId: string, imageElement: HTMLImageElement): void {
const annotations = this.activeAnnotations.get(noteId) || [];
// Clear existing annotation elements
this.clearAnnotationElements();
// Create annotation overlay container
const overlay = this.createOverlayContainer(container, imageElement);
// Render each annotation
annotations.forEach(annotation => {
const element = this.createAnnotationElement(annotation, overlay);
this.annotationElements.set(annotation.id, element);
});
// Add click handler for creating new annotations
if (this.config.allowEditing && this.isEditMode) {
this.setupAnnotationCreation(overlay, noteId);
}
// Add ARIA attributes for accessibility
overlay.setAttribute('role', 'img');
overlay.setAttribute('aria-label', 'Image with annotations');
}
/**
* Create overlay container for annotations
*/
private createOverlayContainer(container: HTMLElement, imageElement: HTMLImageElement): HTMLElement {
let overlay = container.querySelector('.annotation-overlay') as HTMLElement;
if (!overlay) {
overlay = document.createElement('div');
overlay.className = 'annotation-overlay';
overlay.style.cssText = `
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: ${this.isEditMode ? 'auto' : 'none'};
z-index: 10;
`;
// Position overlay over the image
const rect = imageElement.getBoundingClientRect();
const containerRect = container.getBoundingClientRect();
overlay.style.top = `${rect.top - containerRect.top}px`;
overlay.style.left = `${rect.left - containerRect.left}px`;
overlay.style.width = `${rect.width}px`;
overlay.style.height = `${rect.height}px`;
container.appendChild(overlay);
}
return overlay;
}
/**
* Create annotation element
*/
private createAnnotationElement(annotation: ImageAnnotation, container: HTMLElement): HTMLElement {
const element = document.createElement('div');
element.className = `annotation-marker annotation-${annotation.type || 'comment'}`;
element.dataset.annotationId = annotation.id;
// Position based on percentage
element.style.cssText = `
position: absolute;
left: ${annotation.x}%;
top: ${annotation.y}%;
transform: translate(-50%, -50%);
cursor: pointer;
z-index: 20;
pointer-events: auto;
`;
// Create marker based on type
if (annotation.type === 'region') {
// Region annotation
element.style.cssText += `
width: ${annotation.width || 20}%;
height: ${annotation.height || 20}%;
border: 2px solid ${annotation.color || this.config.defaultColor};
background: ${annotation.color || this.config.defaultColor}33;
border-radius: 4px;
`;
} else {
// Point annotation
const marker = document.createElement('div');
marker.style.cssText = `
width: 24px;
height: 24px;
background: ${annotation.color || this.config.defaultColor};
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
`;
const icon = document.createElement('i');
icon.className = `bx ${annotation.icon || this.config.defaultIcon}`;
icon.style.cssText = `
color: #333;
font-size: 14px;
`;
marker.appendChild(icon);
element.appendChild(marker);
// Add ARIA attributes for accessibility
element.setAttribute('role', 'button');
element.setAttribute('aria-label', `Annotation: ${this.sanitizeText(annotation.text)}`);
element.setAttribute('tabindex', '0');
}
// Add tooltip
const tooltip = document.createElement('div');
tooltip.className = 'annotation-tooltip';
tooltip.style.cssText = `
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
background: rgba(0,0,0,0.9);
color: white;
padding: 8px 12px;
border-radius: 4px;
font-size: 12px;
white-space: nowrap;
max-width: 200px;
pointer-events: none;
opacity: 0;
transition: opacity 0.2s;
margin-bottom: 8px;
`;
// Use textContent to prevent XSS
tooltip.textContent = this.sanitizeText(annotation.text);
element.appendChild(tooltip);
// Show tooltip on hover
element.addEventListener('mouseenter', () => {
tooltip.style.opacity = '1';
});
element.addEventListener('mouseleave', () => {
tooltip.style.opacity = '0';
});
// Handle click for editing
element.addEventListener('click', (e) => {
e.stopPropagation();
this.selectAnnotation(annotation);
});
container.appendChild(element);
return element;
}
/**
* Setup annotation creation on click
*/
private setupAnnotationCreation(overlay: HTMLElement, noteId: string): void {
overlay.addEventListener('click', async (e) => {
if (!this.isEditMode) return;
const rect = overlay.getBoundingClientRect();
const x = ((e.clientX - rect.left) / rect.width) * 100;
const y = ((e.clientY - rect.top) / rect.height) * 100;
// Show annotation creation dialog
const text = prompt('Enter annotation text:');
if (text) {
await this.saveAnnotation({
noteId,
x,
y,
text,
author: 'current_user', // TODO: Get from session
type: 'comment'
});
// Reload annotations
await this.loadAnnotations(noteId);
// Re-render
const imageElement = overlay.parentElement?.querySelector('img') as HTMLImageElement;
if (imageElement && overlay.parentElement) {
this.renderAnnotations(overlay.parentElement, noteId, imageElement);
}
}
});
}
/**
* Select an annotation for editing
*/
private selectAnnotation(annotation: ImageAnnotation): void {
this.selectedAnnotation = annotation;
// Highlight selected annotation
this.annotationElements.forEach((element, id) => {
if (id === annotation.id) {
element.classList.add('selected');
element.style.outline = '2px solid #2196F3';
} else {
element.classList.remove('selected');
element.style.outline = 'none';
}
});
// Show edit options
if (this.isEditMode) {
this.showEditDialog(annotation);
}
}
/**
* Show edit dialog for annotation
*/
private showEditDialog(annotation: ImageAnnotation): void {
// Simple implementation - could be replaced with a proper modal
const newText = prompt('Edit annotation:', annotation.text);
if (newText !== null) {
annotation.text = newText;
this.updateAnnotation(annotation);
// Update tooltip with sanitized text
const element = this.annotationElements.get(annotation.id);
if (element) {
const tooltip = element.querySelector('.annotation-tooltip');
if (tooltip) {
// Use textContent to prevent XSS
tooltip.textContent = this.sanitizeText(newText);
}
}
}
}
/**
* Toggle edit mode
*/
toggleEditMode(): void {
this.isEditMode = !this.isEditMode;
// Update overlay pointer events
document.querySelectorAll('.annotation-overlay').forEach(overlay => {
(overlay as HTMLElement).style.pointerEvents = this.isEditMode ? 'auto' : 'none';
});
}
/**
* Clear all annotation elements
*/
private clearAnnotationElements(): void {
this.annotationElements.forEach(element => element.remove());
this.annotationElements.clear();
}
/**
* Generate unique ID
*/
private generateId(): string {
return `ann_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
/**
* Export annotations as JSON
*/
exportAnnotations(noteId: string): string {
const annotations = this.activeAnnotations.get(noteId) || [];
return JSON.stringify(annotations, null, 2);
}
/**
* Import annotations from JSON
*/
async importAnnotations(noteId: string, json: string): Promise<void> {
try {
const annotations = JSON.parse(json) as ImageAnnotation[];
for (const annotation of annotations) {
await this.saveAnnotation({
noteId,
x: annotation.x,
y: annotation.y,
text: annotation.text,
author: annotation.author,
color: annotation.color,
icon: annotation.icon,
type: annotation.type,
width: annotation.width,
height: annotation.height
});
}
await this.loadAnnotations(noteId);
} catch (error) {
console.error('Failed to import annotations:', error);
throw error;
}
}
/**
* Sanitize text to prevent XSS
*/
private sanitizeText(text: string): string {
if (!text) return '';
// Remove any HTML tags and dangerous characters
const div = document.createElement('div');
div.textContent = text;
// Additional validation
const sanitized = div.textContent || '';
// Remove any remaining special characters that could be dangerous
return sanitized
.replace(/<script[^>]*>.*?<\/script>/gi, '')
.replace(/<iframe[^>]*>.*?<\/iframe>/gi, '')
.replace(/javascript:/gi, '')
.replace(/on\w+\s*=/gi, '');
}
/**
* Cleanup resources
*/
cleanup(): void {
this.clearAnnotationElements();
this.activeAnnotations.clear();
this.selectedAnnotation = null;
this.isEditMode = false;
}
}
export default ImageAnnotationsService.getInstance();

View File

@@ -1,877 +0,0 @@
/**
* Image Comparison Module for Trilium Notes
* Provides side-by-side and overlay comparison modes for images
*/
import mediaViewer from './media_viewer.js';
import utils from './utils.js';
/**
* Comparison mode types
*/
export type ComparisonMode = 'side-by-side' | 'overlay' | 'swipe' | 'difference';
/**
* Image comparison configuration
*/
export interface ComparisonConfig {
mode: ComparisonMode;
syncZoom: boolean;
syncPan: boolean;
showLabels: boolean;
swipePosition?: number; // For swipe mode (0-100)
opacity?: number; // For overlay mode (0-1)
highlightDifferences?: boolean; // For difference mode
}
/**
* Comparison state
*/
interface ComparisonState {
leftImage: ComparisonImage;
rightImage: ComparisonImage;
config: ComparisonConfig;
container?: HTMLElement;
isActive: boolean;
}
/**
* Image data for comparison
*/
export interface ComparisonImage {
src: string;
title?: string;
noteId?: string;
width?: number;
height?: number;
}
/**
* ImageComparisonService provides various comparison modes for images
*/
class ImageComparisonService {
private static instance: ImageComparisonService;
private currentComparison: ComparisonState | null = null;
private comparisonContainer?: HTMLElement;
private leftCanvas?: HTMLCanvasElement;
private rightCanvas?: HTMLCanvasElement;
private leftContext?: CanvasRenderingContext2D;
private rightContext?: CanvasRenderingContext2D;
private swipeHandle?: HTMLElement;
private isDraggingSwipe: boolean = false;
private currentZoom: number = 1;
private panX: number = 0;
private panY: number = 0;
private defaultConfig: ComparisonConfig = {
mode: 'side-by-side',
syncZoom: true,
syncPan: true,
showLabels: true,
swipePosition: 50,
opacity: 0.5,
highlightDifferences: false
};
private constructor() {}
static getInstance(): ImageComparisonService {
if (!ImageComparisonService.instance) {
ImageComparisonService.instance = new ImageComparisonService();
}
return ImageComparisonService.instance;
}
/**
* Start image comparison
*/
async startComparison(
leftImage: ComparisonImage,
rightImage: ComparisonImage,
container: HTMLElement,
config?: Partial<ComparisonConfig>
): Promise<void> {
try {
// Close any existing comparison
this.closeComparison();
// Merge configuration
const finalConfig = { ...this.defaultConfig, ...config };
// Initialize state
this.currentComparison = {
leftImage,
rightImage,
config: finalConfig,
container,
isActive: true
};
// Load images
await this.loadImages(leftImage, rightImage);
// Create comparison UI based on mode
switch (finalConfig.mode) {
case 'side-by-side':
await this.createSideBySideComparison(container);
break;
case 'overlay':
await this.createOverlayComparison(container);
break;
case 'swipe':
await this.createSwipeComparison(container);
break;
case 'difference':
await this.createDifferenceComparison(container);
break;
}
// Add controls
this.addComparisonControls(container);
} catch (error) {
console.error('Failed to start image comparison:', error);
this.closeComparison();
throw error;
}
}
/**
* Load images and get dimensions
*/
private async loadImages(leftImage: ComparisonImage, rightImage: ComparisonImage): Promise<void> {
const loadImage = (src: string): Promise<HTMLImageElement> => {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = () => reject(new Error(`Failed to load image: ${src}`));
img.src = src;
});
};
const [leftImg, rightImg] = await Promise.all([
loadImage(leftImage.src),
loadImage(rightImage.src)
]);
// Update dimensions
leftImage.width = leftImg.naturalWidth;
leftImage.height = leftImg.naturalHeight;
rightImage.width = rightImg.naturalWidth;
rightImage.height = rightImg.naturalHeight;
}
/**
* Create side-by-side comparison
*/
private async createSideBySideComparison(container: HTMLElement): Promise<void> {
if (!this.currentComparison) return;
// Clear container
container.innerHTML = '';
container.style.cssText = `
display: flex;
width: 100%;
height: 100%;
position: relative;
background: #1a1a1a;
`;
// Create left panel
const leftPanel = document.createElement('div');
leftPanel.className = 'comparison-panel comparison-left';
leftPanel.style.cssText = `
flex: 1;
position: relative;
overflow: hidden;
border-right: 2px solid #333;
`;
// Create right panel
const rightPanel = document.createElement('div');
rightPanel.className = 'comparison-panel comparison-right';
rightPanel.style.cssText = `
flex: 1;
position: relative;
overflow: hidden;
`;
// Add images
const leftImg = await this.createImageElement(this.currentComparison.leftImage);
const rightImg = await this.createImageElement(this.currentComparison.rightImage);
leftPanel.appendChild(leftImg);
rightPanel.appendChild(rightImg);
// Add labels if enabled
if (this.currentComparison.config.showLabels) {
this.addImageLabel(leftPanel, this.currentComparison.leftImage.title || 'Image 1');
this.addImageLabel(rightPanel, this.currentComparison.rightImage.title || 'Image 2');
}
container.appendChild(leftPanel);
container.appendChild(rightPanel);
// Setup synchronized zoom and pan if enabled
if (this.currentComparison.config.syncZoom || this.currentComparison.config.syncPan) {
this.setupSynchronizedControls(leftPanel, rightPanel);
}
}
/**
* Create overlay comparison
*/
private async createOverlayComparison(container: HTMLElement): Promise<void> {
if (!this.currentComparison) return;
container.innerHTML = '';
container.style.cssText = `
position: relative;
width: 100%;
height: 100%;
background: #1a1a1a;
overflow: hidden;
`;
// Create base image
const baseImg = await this.createImageElement(this.currentComparison.leftImage);
baseImg.style.position = 'absolute';
baseImg.style.zIndex = '1';
// Create overlay image
const overlayImg = await this.createImageElement(this.currentComparison.rightImage);
overlayImg.style.position = 'absolute';
overlayImg.style.zIndex = '2';
overlayImg.style.opacity = String(this.currentComparison.config.opacity || 0.5);
container.appendChild(baseImg);
container.appendChild(overlayImg);
// Add opacity slider
this.addOpacityControl(container, overlayImg);
// Add labels
if (this.currentComparison.config.showLabels) {
const labelContainer = document.createElement('div');
labelContainer.style.cssText = `
position: absolute;
top: 10px;
left: 10px;
z-index: 10;
display: flex;
gap: 10px;
`;
const baseLabel = this.createLabel(this.currentComparison.leftImage.title || 'Base', '#4CAF50');
const overlayLabel = this.createLabel(this.currentComparison.rightImage.title || 'Overlay', '#2196F3');
labelContainer.appendChild(baseLabel);
labelContainer.appendChild(overlayLabel);
container.appendChild(labelContainer);
}
}
/**
* Create swipe comparison
*/
private async createSwipeComparison(container: HTMLElement): Promise<void> {
if (!this.currentComparison) return;
container.innerHTML = '';
container.style.cssText = `
position: relative;
width: 100%;
height: 100%;
background: #1a1a1a;
overflow: hidden;
cursor: ew-resize;
`;
// Create images
const leftImg = await this.createImageElement(this.currentComparison.leftImage);
const rightImg = await this.createImageElement(this.currentComparison.rightImage);
leftImg.style.position = 'absolute';
leftImg.style.zIndex = '1';
// Create clipping container for right image
const clipContainer = document.createElement('div');
clipContainer.className = 'swipe-clip-container';
clipContainer.style.cssText = `
position: absolute;
top: 0;
left: 0;
width: ${this.currentComparison.config.swipePosition}%;
height: 100%;
overflow: hidden;
z-index: 2;
`;
rightImg.style.position = 'absolute';
clipContainer.appendChild(rightImg);
// Create swipe handle
this.swipeHandle = document.createElement('div');
this.swipeHandle.className = 'swipe-handle';
this.swipeHandle.style.cssText = `
position: absolute;
top: 0;
left: ${this.currentComparison.config.swipePosition}%;
width: 4px;
height: 100%;
background: white;
cursor: ew-resize;
z-index: 3;
transform: translateX(-50%);
box-shadow: 0 0 10px rgba(0,0,0,0.5);
`;
// Add handle icon
const handleIcon = document.createElement('div');
handleIcon.style.cssText = `
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 40px;
height: 40px;
background: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2px 10px rgba(0,0,0,0.3);
`;
handleIcon.innerHTML = '<i class="bx bx-move-horizontal" style="font-size: 24px; color: #333;"></i>';
this.swipeHandle.appendChild(handleIcon);
container.appendChild(leftImg);
container.appendChild(clipContainer);
container.appendChild(this.swipeHandle);
// Setup swipe interaction
this.setupSwipeInteraction(container, clipContainer);
// Add labels
if (this.currentComparison.config.showLabels) {
this.addSwipeLabels(container);
}
}
/**
* Create difference comparison using canvas
*/
private async createDifferenceComparison(container: HTMLElement): Promise<void> {
if (!this.currentComparison) return;
container.innerHTML = '';
container.style.cssText = `
position: relative;
width: 100%;
height: 100%;
background: #1a1a1a;
overflow: hidden;
`;
// Create canvas for difference visualization
const canvas = document.createElement('canvas');
canvas.className = 'difference-canvas';
const ctx = canvas.getContext('2d');
if (!ctx) {
throw new Error('Failed to get canvas context');
}
// Load images
const leftImg = new Image();
const rightImg = new Image();
await Promise.all([
new Promise((resolve) => {
leftImg.onload = resolve;
leftImg.src = this.currentComparison!.leftImage.src;
}),
new Promise((resolve) => {
rightImg.onload = resolve;
rightImg.src = this.currentComparison!.rightImage.src;
})
]);
// Set canvas size
const maxWidth = Math.max(leftImg.width, rightImg.width);
const maxHeight = Math.max(leftImg.height, rightImg.height);
canvas.width = maxWidth;
canvas.height = maxHeight;
// Calculate difference
this.calculateImageDifference(ctx, leftImg, rightImg, maxWidth, maxHeight);
// Style canvas
canvas.style.cssText = `
max-width: 100%;
max-height: 100%;
object-fit: contain;
`;
container.appendChild(canvas);
// Add difference statistics
this.addDifferenceStatistics(container, ctx, maxWidth, maxHeight);
}
/**
* Calculate and visualize image difference
*/
private calculateImageDifference(
ctx: CanvasRenderingContext2D,
leftImg: HTMLImageElement,
rightImg: HTMLImageElement,
width: number,
height: number
): void {
// Draw left image
ctx.drawImage(leftImg, 0, 0, width, height);
const leftData = ctx.getImageData(0, 0, width, height);
// Draw right image
ctx.clearRect(0, 0, width, height);
ctx.drawImage(rightImg, 0, 0, width, height);
const rightData = ctx.getImageData(0, 0, width, height);
// Calculate difference
const diffData = ctx.createImageData(width, height);
let totalDiff = 0;
for (let i = 0; i < leftData.data.length; i += 4) {
const rDiff = Math.abs(leftData.data[i] - rightData.data[i]);
const gDiff = Math.abs(leftData.data[i + 1] - rightData.data[i + 1]);
const bDiff = Math.abs(leftData.data[i + 2] - rightData.data[i + 2]);
const avgDiff = (rDiff + gDiff + bDiff) / 3;
totalDiff += avgDiff;
if (this.currentComparison?.config.highlightDifferences && avgDiff > 30) {
// Highlight differences in red
diffData.data[i] = 255; // Red
diffData.data[i + 1] = 0; // Green
diffData.data[i + 2] = 0; // Blue
diffData.data[i + 3] = Math.min(255, avgDiff * 2); // Alpha based on difference
} else {
// Show original image with reduced opacity for non-different areas
diffData.data[i] = leftData.data[i];
diffData.data[i + 1] = leftData.data[i + 1];
diffData.data[i + 2] = leftData.data[i + 2];
diffData.data[i + 3] = avgDiff > 10 ? 255 : 128;
}
}
ctx.putImageData(diffData, 0, 0);
}
/**
* Add difference statistics overlay
*/
private addDifferenceStatistics(
container: HTMLElement,
ctx: CanvasRenderingContext2D,
width: number,
height: number
): void {
const imageData = ctx.getImageData(0, 0, width, height);
let changedPixels = 0;
const threshold = 30;
for (let i = 0; i < imageData.data.length; i += 4) {
const r = imageData.data[i];
const g = imageData.data[i + 1];
const b = imageData.data[i + 2];
if (r > threshold || g > threshold || b > threshold) {
changedPixels++;
}
}
const totalPixels = width * height;
const changePercentage = ((changedPixels / totalPixels) * 100).toFixed(2);
const statsDiv = document.createElement('div');
statsDiv.className = 'difference-stats';
statsDiv.style.cssText = `
position: absolute;
top: 10px;
right: 10px;
background: rgba(0, 0, 0, 0.8);
color: white;
padding: 10px;
border-radius: 4px;
font-size: 12px;
z-index: 10;
`;
statsDiv.innerHTML = `
<div><strong>Difference Analysis</strong></div>
<div>Changed pixels: ${changedPixels.toLocaleString()}</div>
<div>Total pixels: ${totalPixels.toLocaleString()}</div>
<div>Difference: ${changePercentage}%</div>
`;
container.appendChild(statsDiv);
}
/**
* Create image element
*/
private async createImageElement(image: ComparisonImage): Promise<HTMLImageElement> {
const img = document.createElement('img');
img.src = image.src;
img.alt = image.title || 'Comparison image';
img.style.cssText = `
width: 100%;
height: 100%;
object-fit: contain;
`;
await new Promise((resolve, reject) => {
img.onload = resolve;
img.onerror = reject;
});
return img;
}
/**
* Add image label
*/
private addImageLabel(container: HTMLElement, text: string): void {
const label = document.createElement('div');
label.className = 'image-label';
label.style.cssText = `
position: absolute;
top: 10px;
left: 10px;
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 6px 10px;
border-radius: 4px;
font-size: 12px;
z-index: 10;
`;
label.textContent = text;
container.appendChild(label);
}
/**
* Create label element
*/
private createLabel(text: string, color: string): HTMLElement {
const label = document.createElement('div');
label.style.cssText = `
background: ${color};
color: white;
padding: 4px 8px;
border-radius: 3px;
font-size: 12px;
`;
label.textContent = text;
return label;
}
/**
* Add swipe labels
*/
private addSwipeLabels(container: HTMLElement): void {
if (!this.currentComparison) return;
const leftLabel = document.createElement('div');
leftLabel.style.cssText = `
position: absolute;
top: 10px;
left: 10px;
background: rgba(76, 175, 80, 0.9);
color: white;
padding: 6px 10px;
border-radius: 4px;
font-size: 12px;
z-index: 10;
`;
leftLabel.textContent = this.currentComparison.leftImage.title || 'Left';
const rightLabel = document.createElement('div');
rightLabel.style.cssText = `
position: absolute;
top: 10px;
right: 10px;
background: rgba(33, 150, 243, 0.9);
color: white;
padding: 6px 10px;
border-radius: 4px;
font-size: 12px;
z-index: 10;
`;
rightLabel.textContent = this.currentComparison.rightImage.title || 'Right';
container.appendChild(leftLabel);
container.appendChild(rightLabel);
}
/**
* Setup swipe interaction
*/
private setupSwipeInteraction(container: HTMLElement, clipContainer: HTMLElement): void {
if (!this.swipeHandle) return;
let startX = 0;
let startPosition = this.currentComparison?.config.swipePosition || 50;
const handleMouseMove = (e: MouseEvent) => {
if (!this.isDraggingSwipe) return;
const rect = container.getBoundingClientRect();
const x = e.clientX - rect.left;
const percentage = Math.max(0, Math.min(100, (x / rect.width) * 100));
clipContainer.style.width = `${percentage}%`;
if (this.swipeHandle) {
this.swipeHandle.style.left = `${percentage}%`;
}
if (this.currentComparison) {
this.currentComparison.config.swipePosition = percentage;
}
};
const handleMouseUp = () => {
this.isDraggingSwipe = false;
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
container.style.cursor = 'default';
};
this.swipeHandle.addEventListener('mousedown', (e) => {
this.isDraggingSwipe = true;
startX = e.clientX;
startPosition = this.currentComparison?.config.swipePosition || 50;
container.style.cursor = 'ew-resize';
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
});
// Also allow dragging anywhere in the container
container.addEventListener('mousedown', (e) => {
if (e.target === this.swipeHandle || (e.target as HTMLElement).parentElement === this.swipeHandle) {
return;
}
const rect = container.getBoundingClientRect();
const x = e.clientX - rect.left;
const percentage = (x / rect.width) * 100;
clipContainer.style.width = `${percentage}%`;
if (this.swipeHandle) {
this.swipeHandle.style.left = `${percentage}%`;
}
if (this.currentComparison) {
this.currentComparison.config.swipePosition = percentage;
}
});
}
/**
* Add opacity control for overlay mode
*/
private addOpacityControl(container: HTMLElement, overlayImg: HTMLImageElement): void {
const control = document.createElement('div');
control.className = 'opacity-control';
control.style.cssText = `
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.8);
padding: 10px 20px;
border-radius: 4px;
z-index: 10;
display: flex;
align-items: center;
gap: 10px;
`;
const label = document.createElement('label');
label.textContent = 'Opacity:';
label.style.color = 'white';
label.style.fontSize = '12px';
const slider = document.createElement('input');
slider.type = 'range';
slider.min = '0';
slider.max = '100';
slider.value = String((this.currentComparison?.config.opacity || 0.5) * 100);
slider.style.width = '150px';
const value = document.createElement('span');
value.textContent = `${slider.value}%`;
value.style.color = 'white';
value.style.fontSize = '12px';
value.style.minWidth = '35px';
slider.addEventListener('input', () => {
const opacity = parseInt(slider.value) / 100;
overlayImg.style.opacity = String(opacity);
value.textContent = `${slider.value}%`;
if (this.currentComparison) {
this.currentComparison.config.opacity = opacity;
}
});
control.appendChild(label);
control.appendChild(slider);
control.appendChild(value);
container.appendChild(control);
}
/**
* Setup synchronized controls for side-by-side mode
*/
private setupSynchronizedControls(leftPanel: HTMLElement, rightPanel: HTMLElement): void {
const leftImg = leftPanel.querySelector('img') as HTMLImageElement;
const rightImg = rightPanel.querySelector('img') as HTMLImageElement;
if (!leftImg || !rightImg) return;
// Synchronize scroll
if (this.currentComparison?.config.syncPan) {
leftPanel.addEventListener('scroll', () => {
rightPanel.scrollLeft = leftPanel.scrollLeft;
rightPanel.scrollTop = leftPanel.scrollTop;
});
rightPanel.addEventListener('scroll', () => {
leftPanel.scrollLeft = rightPanel.scrollLeft;
leftPanel.scrollTop = rightPanel.scrollTop;
});
}
// Synchronize zoom with wheel events
if (this.currentComparison?.config.syncZoom) {
const handleWheel = (e: WheelEvent) => {
e.preventDefault();
const delta = e.deltaY < 0 ? 1.1 : 0.9;
this.currentZoom = Math.max(0.5, Math.min(5, this.currentZoom * delta));
leftImg.style.transform = `scale(${this.currentZoom})`;
rightImg.style.transform = `scale(${this.currentZoom})`;
};
leftPanel.addEventListener('wheel', handleWheel);
rightPanel.addEventListener('wheel', handleWheel);
}
}
/**
* Add comparison controls toolbar
*/
private addComparisonControls(container: HTMLElement): void {
const toolbar = document.createElement('div');
toolbar.className = 'comparison-toolbar';
toolbar.style.cssText = `
position: absolute;
top: 10px;
right: 10px;
background: rgba(0, 0, 0, 0.8);
border-radius: 4px;
padding: 8px;
display: flex;
gap: 8px;
z-index: 100;
`;
// Mode switcher
const modes: ComparisonMode[] = ['side-by-side', 'overlay', 'swipe', 'difference'];
modes.forEach(mode => {
const btn = document.createElement('button');
btn.className = `mode-btn mode-${mode}`;
btn.style.cssText = `
background: ${this.currentComparison?.config.mode === mode ? '#2196F3' : 'rgba(255,255,255,0.1)'};
color: white;
border: none;
padding: 6px 10px;
border-radius: 3px;
cursor: pointer;
font-size: 12px;
`;
btn.textContent = mode.replace('-', ' ').replace(/\b\w/g, l => l.toUpperCase());
btn.addEventListener('click', async () => {
if (this.currentComparison && this.currentComparison.container) {
this.currentComparison.config.mode = mode;
await this.startComparison(
this.currentComparison.leftImage,
this.currentComparison.rightImage,
this.currentComparison.container,
this.currentComparison.config
);
}
});
toolbar.appendChild(btn);
});
// Close button
const closeBtn = document.createElement('button');
closeBtn.style.cssText = `
background: rgba(255,0,0,0.5);
color: white;
border: none;
padding: 6px 10px;
border-radius: 3px;
cursor: pointer;
font-size: 12px;
margin-left: 10px;
`;
closeBtn.textContent = 'Close';
closeBtn.addEventListener('click', () => this.closeComparison());
toolbar.appendChild(closeBtn);
container.appendChild(toolbar);
}
/**
* Close comparison
*/
closeComparison(): void {
if (this.currentComparison?.container) {
this.currentComparison.container.innerHTML = '';
}
this.currentComparison = null;
this.comparisonContainer = undefined;
this.leftCanvas = undefined;
this.rightCanvas = undefined;
this.leftContext = undefined;
this.rightContext = undefined;
this.swipeHandle = undefined;
this.isDraggingSwipe = false;
this.currentZoom = 1;
this.panX = 0;
this.panY = 0;
}
/**
* Check if comparison is active
*/
isComparisonActive(): boolean {
return this.currentComparison?.isActive || false;
}
/**
* Get current comparison state
*/
getComparisonState(): ComparisonState | null {
return this.currentComparison;
}
}
export default ImageComparisonService.getInstance();

View File

@@ -1,874 +0,0 @@
/**
* Basic Image Editor Module for Trilium Notes
* Provides non-destructive image editing capabilities
*/
import server from './server.js';
import toastService from './toast.js';
import { ImageValidator, withErrorBoundary, MemoryMonitor, ImageError, ImageErrorType } from './image_error_handler.js';
/**
* Edit operation types
*/
export type EditOperation =
| 'rotate'
| 'crop'
| 'brightness'
| 'contrast'
| 'saturation'
| 'blur'
| 'sharpen';
/**
* Edit history entry
*/
export interface EditHistoryEntry {
operation: EditOperation;
params: any;
timestamp: Date;
}
/**
* Crop area definition
*/
export interface CropArea {
x: number;
y: number;
width: number;
height: number;
}
/**
* Editor state
*/
interface EditorState {
originalImage: HTMLImageElement | null;
currentImage: HTMLImageElement | null;
canvas: HTMLCanvasElement;
context: CanvasRenderingContext2D;
history: EditHistoryEntry[];
historyIndex: number;
isEditing: boolean;
}
/**
* Filter parameters
*/
export interface FilterParams {
brightness?: number; // -100 to 100
contrast?: number; // -100 to 100
saturation?: number; // -100 to 100
blur?: number; // 0 to 20
sharpen?: number; // 0 to 100
}
/**
* ImageEditorService provides basic image editing capabilities
*/
class ImageEditorService {
private static instance: ImageEditorService;
private editorState: EditorState;
private tempCanvas: HTMLCanvasElement;
private tempContext: CanvasRenderingContext2D;
private cropOverlay?: HTMLElement;
private cropHandles?: HTMLElement[];
private cropArea: CropArea | null = null;
private isDraggingCrop: boolean = false;
private dragStartX: number = 0;
private dragStartY: number = 0;
private currentFilters: FilterParams = {};
// Canvas size limits for security and memory management
private readonly MAX_CANVAS_SIZE = 8192; // Maximum width/height
private readonly MAX_CANVAS_AREA = 50000000; // 50 megapixels
private constructor() {
// Initialize canvases
this.editorState = {
originalImage: null,
currentImage: null,
canvas: document.createElement('canvas'),
context: null as any,
history: [],
historyIndex: -1,
isEditing: false
};
const ctx = this.editorState.canvas.getContext('2d');
if (!ctx) {
throw new Error('Failed to get canvas context');
}
this.editorState.context = ctx;
this.tempCanvas = document.createElement('canvas');
const tempCtx = this.tempCanvas.getContext('2d');
if (!tempCtx) {
throw new Error('Failed to get temp canvas context');
}
this.tempContext = tempCtx;
}
static getInstance(): ImageEditorService {
if (!ImageEditorService.instance) {
ImageEditorService.instance = new ImageEditorService();
}
return ImageEditorService.instance;
}
/**
* Start editing an image
*/
async startEditing(src: string | HTMLImageElement): Promise<HTMLCanvasElement> {
return await withErrorBoundary(async () => {
// Validate input
if (typeof src === 'string') {
ImageValidator.validateUrl(src);
}
// Load image
let img: HTMLImageElement;
if (typeof src === 'string') {
img = await this.loadImage(src);
} else {
img = src;
}
// Validate image dimensions
ImageValidator.validateDimensions(img.naturalWidth, img.naturalHeight);
// Check memory availability
const estimatedMemory = MemoryMonitor.estimateImageMemory(img.naturalWidth, img.naturalHeight);
if (!MemoryMonitor.checkMemoryAvailable(estimatedMemory)) {
throw new ImageError(
ImageErrorType.MEMORY_ERROR,
'Insufficient memory to process image',
{ estimatedMemory }
);
}
if (img.naturalWidth > this.MAX_CANVAS_SIZE ||
img.naturalHeight > this.MAX_CANVAS_SIZE ||
img.naturalWidth * img.naturalHeight > this.MAX_CANVAS_AREA) {
// Scale down if too large
const scale = Math.min(
this.MAX_CANVAS_SIZE / Math.max(img.naturalWidth, img.naturalHeight),
Math.sqrt(this.MAX_CANVAS_AREA / (img.naturalWidth * img.naturalHeight))
);
const scaledWidth = Math.floor(img.naturalWidth * scale);
const scaledHeight = Math.floor(img.naturalHeight * scale);
console.warn(`Image too large (${img.naturalWidth}x${img.naturalHeight}), scaling to ${scaledWidth}x${scaledHeight}`);
// Create scaled image
const scaledCanvas = document.createElement('canvas');
scaledCanvas.width = scaledWidth;
scaledCanvas.height = scaledHeight;
const scaledCtx = scaledCanvas.getContext('2d');
if (!scaledCtx) throw new Error('Failed to get scaled canvas context');
scaledCtx.drawImage(img, 0, 0, scaledWidth, scaledHeight);
// Create new image from scaled canvas
const scaledImg = new Image();
scaledImg.src = scaledCanvas.toDataURL();
await new Promise(resolve => scaledImg.onload = resolve);
img = scaledImg;
// Clean up scaled canvas
scaledCanvas.width = 0;
scaledCanvas.height = 0;
}
// Store original
this.editorState.originalImage = img;
this.editorState.currentImage = img;
this.editorState.isEditing = true;
this.editorState.history = [];
this.editorState.historyIndex = -1;
this.currentFilters = {};
// Setup canvas with validated dimensions
this.editorState.canvas.width = img.naturalWidth;
this.editorState.canvas.height = img.naturalHeight;
this.editorState.context.drawImage(img, 0, 0);
return this.editorState.canvas;
}, (error) => {
this.stopEditing();
throw error;
}) || this.editorState.canvas;
}
/**
* Rotate image by degrees (90, 180, 270)
*/
rotate(degrees: 90 | 180 | 270 | -90): void {
if (!this.editorState.isEditing) return;
const { canvas, context } = this.editorState;
const { width, height } = canvas;
// Setup temp canvas
if (degrees === 90 || degrees === -90 || degrees === 270) {
this.tempCanvas.width = height;
this.tempCanvas.height = width;
} else {
this.tempCanvas.width = width;
this.tempCanvas.height = height;
}
// Clear temp canvas
this.tempContext.clearRect(0, 0, this.tempCanvas.width, this.tempCanvas.height);
// Rotate
this.tempContext.save();
if (degrees === 90) {
this.tempContext.translate(height, 0);
this.tempContext.rotate(Math.PI / 2);
} else if (degrees === 180) {
this.tempContext.translate(width, height);
this.tempContext.rotate(Math.PI);
} else if (degrees === 270 || degrees === -90) {
this.tempContext.translate(0, width);
this.tempContext.rotate(-Math.PI / 2);
}
this.tempContext.drawImage(canvas, 0, 0);
this.tempContext.restore();
// Copy back to main canvas
canvas.width = this.tempCanvas.width;
canvas.height = this.tempCanvas.height;
context.drawImage(this.tempCanvas, 0, 0);
// Add to history
this.addToHistory('rotate', { degrees });
}
/**
* Start crop selection
*/
startCrop(container: HTMLElement): void {
if (!this.editorState.isEditing) return;
// Create crop overlay
this.cropOverlay = document.createElement('div');
this.cropOverlay.className = 'crop-overlay';
this.cropOverlay.style.cssText = `
position: absolute;
border: 2px dashed #fff;
background: rgba(0, 0, 0, 0.3);
cursor: move;
z-index: 1000;
`;
// Create resize handles
this.cropHandles = [];
const handlePositions = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w'];
handlePositions.forEach(pos => {
const handle = document.createElement('div');
handle.className = `crop-handle crop-handle-${pos}`;
handle.dataset.position = pos;
handle.style.cssText = `
position: absolute;
width: 10px;
height: 10px;
background: white;
border: 1px solid #333;
z-index: 1001;
`;
// Position handles
switch (pos) {
case 'nw':
handle.style.top = '-5px';
handle.style.left = '-5px';
handle.style.cursor = 'nw-resize';
break;
case 'n':
handle.style.top = '-5px';
handle.style.left = '50%';
handle.style.transform = 'translateX(-50%)';
handle.style.cursor = 'n-resize';
break;
case 'ne':
handle.style.top = '-5px';
handle.style.right = '-5px';
handle.style.cursor = 'ne-resize';
break;
case 'e':
handle.style.top = '50%';
handle.style.right = '-5px';
handle.style.transform = 'translateY(-50%)';
handle.style.cursor = 'e-resize';
break;
case 'se':
handle.style.bottom = '-5px';
handle.style.right = '-5px';
handle.style.cursor = 'se-resize';
break;
case 's':
handle.style.bottom = '-5px';
handle.style.left = '50%';
handle.style.transform = 'translateX(-50%)';
handle.style.cursor = 's-resize';
break;
case 'sw':
handle.style.bottom = '-5px';
handle.style.left = '-5px';
handle.style.cursor = 'sw-resize';
break;
case 'w':
handle.style.top = '50%';
handle.style.left = '-5px';
handle.style.transform = 'translateY(-50%)';
handle.style.cursor = 'w-resize';
break;
}
this.cropOverlay.appendChild(handle);
this.cropHandles!.push(handle);
});
// Set initial crop area (80% of image)
const canvasRect = this.editorState.canvas.getBoundingClientRect();
const initialSize = Math.min(canvasRect.width, canvasRect.height) * 0.8;
const initialX = (canvasRect.width - initialSize) / 2;
const initialY = (canvasRect.height - initialSize) / 2;
this.cropArea = {
x: initialX,
y: initialY,
width: initialSize,
height: initialSize
};
this.updateCropOverlay();
container.appendChild(this.cropOverlay);
// Setup drag handlers
this.setupCropHandlers();
}
/**
* Setup crop interaction handlers
*/
private setupCropHandlers(): void {
if (!this.cropOverlay) return;
// Drag to move
this.cropOverlay.addEventListener('mousedown', (e) => {
if ((e.target as HTMLElement).classList.contains('crop-handle')) return;
this.isDraggingCrop = true;
this.dragStartX = e.clientX;
this.dragStartY = e.clientY;
const handleMove = (e: MouseEvent) => {
if (!this.isDraggingCrop || !this.cropArea) return;
const deltaX = e.clientX - this.dragStartX;
const deltaY = e.clientY - this.dragStartY;
this.cropArea.x += deltaX;
this.cropArea.y += deltaY;
this.dragStartX = e.clientX;
this.dragStartY = e.clientY;
this.updateCropOverlay();
};
const handleUp = () => {
this.isDraggingCrop = false;
document.removeEventListener('mousemove', handleMove);
document.removeEventListener('mouseup', handleUp);
};
document.addEventListener('mousemove', handleMove);
document.addEventListener('mouseup', handleUp);
});
// Resize handles
this.cropHandles?.forEach(handle => {
handle.addEventListener('mousedown', (e) => {
e.stopPropagation();
const position = handle.dataset.position!;
const startX = e.clientX;
const startY = e.clientY;
const startCrop = { ...this.cropArea! };
const handleResize = (e: MouseEvent) => {
if (!this.cropArea) return;
const deltaX = e.clientX - startX;
const deltaY = e.clientY - startY;
switch (position) {
case 'nw':
this.cropArea.x = startCrop.x + deltaX;
this.cropArea.y = startCrop.y + deltaY;
this.cropArea.width = startCrop.width - deltaX;
this.cropArea.height = startCrop.height - deltaY;
break;
case 'n':
this.cropArea.y = startCrop.y + deltaY;
this.cropArea.height = startCrop.height - deltaY;
break;
case 'ne':
this.cropArea.y = startCrop.y + deltaY;
this.cropArea.width = startCrop.width + deltaX;
this.cropArea.height = startCrop.height - deltaY;
break;
case 'e':
this.cropArea.width = startCrop.width + deltaX;
break;
case 'se':
this.cropArea.width = startCrop.width + deltaX;
this.cropArea.height = startCrop.height + deltaY;
break;
case 's':
this.cropArea.height = startCrop.height + deltaY;
break;
case 'sw':
this.cropArea.x = startCrop.x + deltaX;
this.cropArea.width = startCrop.width - deltaX;
this.cropArea.height = startCrop.height + deltaY;
break;
case 'w':
this.cropArea.x = startCrop.x + deltaX;
this.cropArea.width = startCrop.width - deltaX;
break;
}
// Ensure minimum size
this.cropArea.width = Math.max(50, this.cropArea.width);
this.cropArea.height = Math.max(50, this.cropArea.height);
this.updateCropOverlay();
};
const handleUp = () => {
document.removeEventListener('mousemove', handleResize);
document.removeEventListener('mouseup', handleUp);
};
document.addEventListener('mousemove', handleResize);
document.addEventListener('mouseup', handleUp);
});
});
}
/**
* Update crop overlay position
*/
private updateCropOverlay(): void {
if (!this.cropOverlay || !this.cropArea) return;
this.cropOverlay.style.left = `${this.cropArea.x}px`;
this.cropOverlay.style.top = `${this.cropArea.y}px`;
this.cropOverlay.style.width = `${this.cropArea.width}px`;
this.cropOverlay.style.height = `${this.cropArea.height}px`;
}
/**
* Apply crop
*/
applyCrop(): void {
if (!this.editorState.isEditing || !this.cropArea) return;
const { canvas, context } = this.editorState;
const canvasRect = canvas.getBoundingClientRect();
// Convert crop area from screen to canvas coordinates
const scaleX = canvas.width / canvasRect.width;
const scaleY = canvas.height / canvasRect.height;
const cropX = this.cropArea.x * scaleX;
const cropY = this.cropArea.y * scaleY;
const cropWidth = this.cropArea.width * scaleX;
const cropHeight = this.cropArea.height * scaleY;
// Get cropped image data
const imageData = context.getImageData(cropX, cropY, cropWidth, cropHeight);
// Resize canvas and put cropped image
canvas.width = cropWidth;
canvas.height = cropHeight;
context.putImageData(imageData, 0, 0);
// Clean up crop overlay
this.cancelCrop();
// Add to history
this.addToHistory('crop', {
x: cropX,
y: cropY,
width: cropWidth,
height: cropHeight
});
}
/**
* Cancel crop
*/
cancelCrop(): void {
if (this.cropOverlay) {
this.cropOverlay.remove();
this.cropOverlay = undefined;
}
this.cropHandles = undefined;
this.cropArea = null;
}
/**
* Apply brightness adjustment
*/
applyBrightness(value: number): void {
if (!this.editorState.isEditing) return;
this.currentFilters.brightness = value;
this.applyFilters();
}
/**
* Apply contrast adjustment
*/
applyContrast(value: number): void {
if (!this.editorState.isEditing) return;
this.currentFilters.contrast = value;
this.applyFilters();
}
/**
* Apply saturation adjustment
*/
applySaturation(value: number): void {
if (!this.editorState.isEditing) return;
this.currentFilters.saturation = value;
this.applyFilters();
}
/**
* Apply all filters
*/
private applyFilters(): void {
const { canvas, context, originalImage } = this.editorState;
if (!originalImage) return;
// Clear canvas and redraw original
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(originalImage, 0, 0, canvas.width, canvas.height);
// Get image data
const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
// Apply brightness
if (this.currentFilters.brightness) {
const brightness = this.currentFilters.brightness * 2.55; // Convert to 0-255 range
for (let i = 0; i < data.length; i += 4) {
data[i] = Math.min(255, Math.max(0, data[i] + brightness));
data[i + 1] = Math.min(255, Math.max(0, data[i + 1] + brightness));
data[i + 2] = Math.min(255, Math.max(0, data[i + 2] + brightness));
}
}
// Apply contrast
if (this.currentFilters.contrast) {
const factor = (259 * (this.currentFilters.contrast + 255)) / (255 * (259 - this.currentFilters.contrast));
for (let i = 0; i < data.length; i += 4) {
data[i] = Math.min(255, Math.max(0, factor * (data[i] - 128) + 128));
data[i + 1] = Math.min(255, Math.max(0, factor * (data[i + 1] - 128) + 128));
data[i + 2] = Math.min(255, Math.max(0, factor * (data[i + 2] - 128) + 128));
}
}
// Apply saturation
if (this.currentFilters.saturation) {
const saturation = this.currentFilters.saturation / 100;
for (let i = 0; i < data.length; i += 4) {
const gray = 0.2989 * data[i] + 0.5870 * data[i + 1] + 0.1140 * data[i + 2];
data[i] = Math.min(255, Math.max(0, gray + saturation * (data[i] - gray)));
data[i + 1] = Math.min(255, Math.max(0, gray + saturation * (data[i + 1] - gray)));
data[i + 2] = Math.min(255, Math.max(0, gray + saturation * (data[i + 2] - gray)));
}
}
// Put modified image data back
context.putImageData(imageData, 0, 0);
}
/**
* Apply blur effect
*/
applyBlur(radius: number): void {
if (!this.editorState.isEditing) return;
const { canvas, context } = this.editorState;
// Use CSS filter for performance
context.filter = `blur(${radius}px)`;
context.drawImage(canvas, 0, 0);
context.filter = 'none';
this.addToHistory('blur', { radius });
}
/**
* Apply sharpen effect
*/
applySharpen(amount: number): void {
if (!this.editorState.isEditing) return;
const { canvas, context } = this.editorState;
const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
const width = canvas.width;
const height = canvas.height;
// Create copy of original data
const original = new Uint8ClampedArray(data);
// Sharpen kernel
const kernel = [
0, -1, 0,
-1, 5 + amount / 25, -1,
0, -1, 0
];
// Apply convolution
for (let y = 1; y < height - 1; y++) {
for (let x = 1; x < width - 1; x++) {
const idx = (y * width + x) * 4;
for (let c = 0; c < 3; c++) {
let sum = 0;
for (let ky = -1; ky <= 1; ky++) {
for (let kx = -1; kx <= 1; kx++) {
const kidx = ((y + ky) * width + (x + kx)) * 4;
sum += original[kidx + c] * kernel[(ky + 1) * 3 + (kx + 1)];
}
}
data[idx + c] = Math.min(255, Math.max(0, sum));
}
}
}
context.putImageData(imageData, 0, 0);
this.addToHistory('sharpen', { amount });
}
/**
* Undo last operation
*/
undo(): void {
if (!this.editorState.isEditing || this.editorState.historyIndex <= 0) return;
this.editorState.historyIndex--;
this.replayHistory();
}
/**
* Redo operation
*/
redo(): void {
if (!this.editorState.isEditing ||
this.editorState.historyIndex >= this.editorState.history.length - 1) return;
this.editorState.historyIndex++;
this.replayHistory();
}
/**
* Replay history up to current index
*/
private replayHistory(): void {
const { canvas, context, originalImage, history, historyIndex } = this.editorState;
if (!originalImage) return;
// Reset to original
canvas.width = originalImage.naturalWidth;
canvas.height = originalImage.naturalHeight;
context.drawImage(originalImage, 0, 0);
// Replay operations
for (let i = 0; i <= historyIndex; i++) {
const entry = history[i];
// Apply operation based on entry
// Note: This is simplified - actual implementation would need to store and replay exact operations
}
}
/**
* Add operation to history
*/
private addToHistory(operation: EditOperation, params: any): void {
// Remove any operations after current index
this.editorState.history = this.editorState.history.slice(0, this.editorState.historyIndex + 1);
// Add new operation
this.editorState.history.push({
operation,
params,
timestamp: new Date()
});
this.editorState.historyIndex++;
// Limit history size
if (this.editorState.history.length > 50) {
this.editorState.history.shift();
this.editorState.historyIndex--;
}
}
/**
* Save edited image
*/
async saveImage(noteId?: string): Promise<Blob> {
if (!this.editorState.isEditing) {
throw new ImageError(
ImageErrorType.INVALID_INPUT,
'No image being edited'
);
}
return new Promise((resolve, reject) => {
this.editorState.canvas.toBlob((blob) => {
if (blob) {
resolve(blob);
if (noteId) {
// Optionally save to server
this.saveToServer(noteId, blob);
}
} else {
reject(new Error('Failed to create blob'));
}
}, 'image/png');
});
}
/**
* Save edited image to server
*/
private async saveToServer(noteId: string, blob: Blob): Promise<void> {
try {
const formData = new FormData();
formData.append('image', blob, 'edited.png');
await server.upload(`notes/${noteId}/image`, formData);
toastService.showMessage('Image saved successfully');
} catch (error) {
console.error('Failed to save image:', error);
toastService.showError('Failed to save image');
}
}
/**
* Reset to original image
*/
reset(): void {
if (!this.editorState.isEditing || !this.editorState.originalImage) return;
const { canvas, context, originalImage } = this.editorState;
canvas.width = originalImage.naturalWidth;
canvas.height = originalImage.naturalHeight;
context.drawImage(originalImage, 0, 0);
this.currentFilters = {};
this.editorState.history = [];
this.editorState.historyIndex = -1;
}
/**
* Stop editing and clean up resources
*/
stopEditing(): void {
this.cancelCrop();
// Request garbage collection after cleanup
MemoryMonitor.requestGarbageCollection();
// Clean up canvas memory
if (this.editorState.canvas) {
this.editorState.context.clearRect(0, 0, this.editorState.canvas.width, this.editorState.canvas.height);
this.editorState.canvas.width = 0;
this.editorState.canvas.height = 0;
}
if (this.tempCanvas) {
this.tempContext.clearRect(0, 0, this.tempCanvas.width, this.tempCanvas.height);
this.tempCanvas.width = 0;
this.tempCanvas.height = 0;
}
// Release image references
if (this.editorState.originalImage) {
this.editorState.originalImage.src = '';
}
if (this.editorState.currentImage) {
this.editorState.currentImage.src = '';
}
this.editorState.isEditing = false;
this.editorState.originalImage = null;
this.editorState.currentImage = null;
this.editorState.history = [];
this.editorState.historyIndex = -1;
this.currentFilters = {};
}
/**
* Load image from URL
*/
private loadImage(src: string): Promise<HTMLImageElement> {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = 'anonymous';
img.onload = () => resolve(img);
img.onerror = () => reject(new Error(`Failed to load image: ${src}`));
img.src = src;
});
}
/**
* Check if can undo
*/
canUndo(): boolean {
return this.editorState.historyIndex > 0;
}
/**
* Check if can redo
*/
canRedo(): boolean {
return this.editorState.historyIndex < this.editorState.history.length - 1;
}
/**
* Get current canvas
*/
getCanvas(): HTMLCanvasElement {
return this.editorState.canvas;
}
/**
* Check if editing
*/
isEditing(): boolean {
return this.editorState.isEditing;
}
}
export default ImageEditorService.getInstance();

View File

@@ -1,369 +0,0 @@
/**
* Error Handler for Image Processing Operations
* Provides error boundaries and validation for image-related operations
*/
import toastService from './toast.js';
/**
* Error types for image operations
*/
export enum ImageErrorType {
INVALID_INPUT = 'INVALID_INPUT',
SIZE_LIMIT_EXCEEDED = 'SIZE_LIMIT_EXCEEDED',
MEMORY_ERROR = 'MEMORY_ERROR',
PROCESSING_ERROR = 'PROCESSING_ERROR',
NETWORK_ERROR = 'NETWORK_ERROR',
SECURITY_ERROR = 'SECURITY_ERROR'
}
/**
* Custom error class for image operations
*/
export class ImageError extends Error {
constructor(
public type: ImageErrorType,
message: string,
public details?: any
) {
super(message);
this.name = 'ImageError';
}
}
/**
* Input validation utilities
*/
export class ImageValidator {
private static readonly MAX_FILE_SIZE = 100 * 1024 * 1024; // 100MB
private static readonly ALLOWED_MIME_TYPES = [
'image/jpeg',
'image/jpg',
'image/png',
'image/gif',
'image/webp',
'image/svg+xml',
'image/bmp'
];
private static readonly MAX_DIMENSION = 16384;
private static readonly MAX_AREA = 100000000; // 100 megapixels
/**
* Validate file input
*/
static validateFile(file: File): void {
// Check file size
if (file.size > this.MAX_FILE_SIZE) {
throw new ImageError(
ImageErrorType.SIZE_LIMIT_EXCEEDED,
`File size exceeds maximum allowed size of ${this.MAX_FILE_SIZE / 1024 / 1024}MB`,
{ fileSize: file.size, maxSize: this.MAX_FILE_SIZE }
);
}
// Check MIME type
if (!this.ALLOWED_MIME_TYPES.includes(file.type)) {
throw new ImageError(
ImageErrorType.INVALID_INPUT,
`File type ${file.type} is not supported`,
{ fileType: file.type, allowedTypes: this.ALLOWED_MIME_TYPES }
);
}
}
/**
* Validate image dimensions
*/
static validateDimensions(width: number, height: number): void {
if (width <= 0 || height <= 0) {
throw new ImageError(
ImageErrorType.INVALID_INPUT,
'Invalid image dimensions',
{ width, height }
);
}
if (width > this.MAX_DIMENSION || height > this.MAX_DIMENSION) {
throw new ImageError(
ImageErrorType.SIZE_LIMIT_EXCEEDED,
`Image dimensions exceed maximum allowed size of ${this.MAX_DIMENSION}px`,
{ width, height, maxDimension: this.MAX_DIMENSION }
);
}
if (width * height > this.MAX_AREA) {
throw new ImageError(
ImageErrorType.SIZE_LIMIT_EXCEEDED,
`Image area exceeds maximum allowed area of ${this.MAX_AREA / 1000000} megapixels`,
{ area: width * height, maxArea: this.MAX_AREA }
);
}
}
/**
* Validate URL
*/
static validateUrl(url: string): void {
try {
const parsedUrl = new URL(url);
// Check protocol
if (!['http:', 'https:', 'data:', 'blob:'].includes(parsedUrl.protocol)) {
throw new ImageError(
ImageErrorType.SECURITY_ERROR,
`Unsupported protocol: ${parsedUrl.protocol}`,
{ url, protocol: parsedUrl.protocol }
);
}
// Additional security checks for data URLs
if (parsedUrl.protocol === 'data:') {
const [header] = url.split(',');
if (!header.includes('image/')) {
throw new ImageError(
ImageErrorType.INVALID_INPUT,
'Data URL does not contain image data',
{ url: url.substring(0, 100) }
);
}
}
} catch (error) {
if (error instanceof ImageError) {
throw error;
}
throw new ImageError(
ImageErrorType.INVALID_INPUT,
'Invalid URL format',
{ url, originalError: error }
);
}
}
/**
* Sanitize filename
*/
static sanitizeFilename(filename: string): string {
// Remove path traversal attempts
filename = filename.replace(/\.\./g, '');
filename = filename.replace(/[\/\\]/g, '_');
// Remove special characters except dots and dashes
filename = filename.replace(/[^a-zA-Z0-9._-]/g, '_');
// Limit length
if (filename.length > 255) {
const ext = filename.split('.').pop();
filename = filename.substring(0, 250) + '.' + ext;
}
return filename;
}
}
/**
* Error boundary wrapper for async operations
*/
export async function withErrorBoundary<T>(
operation: () => Promise<T>,
errorHandler?: (error: Error) => void
): Promise<T | null> {
try {
return await operation();
} catch (error) {
const imageError = error instanceof ImageError
? error
: new ImageError(
ImageErrorType.PROCESSING_ERROR,
error instanceof Error ? error.message : 'Unknown error occurred',
{ originalError: error }
);
// Log error
console.error('[Image Error]', imageError.type, imageError.message, imageError.details);
// Show user-friendly message
switch (imageError.type) {
case ImageErrorType.SIZE_LIMIT_EXCEEDED:
toastService.showError('Image is too large to process');
break;
case ImageErrorType.INVALID_INPUT:
toastService.showError('Invalid image or input provided');
break;
case ImageErrorType.MEMORY_ERROR:
toastService.showError('Not enough memory to process image');
break;
case ImageErrorType.SECURITY_ERROR:
toastService.showError('Security violation detected');
break;
case ImageErrorType.NETWORK_ERROR:
toastService.showError('Network error occurred');
break;
default:
toastService.showError('Failed to process image');
}
// Call custom error handler if provided
if (errorHandler) {
errorHandler(imageError);
}
return null;
}
}
/**
* Memory monitoring utilities
*/
export class MemoryMonitor {
private static readonly WARNING_THRESHOLD = 0.8; // 80% of available memory
/**
* Check if memory is available for operation
*/
static checkMemoryAvailable(estimatedBytes: number): boolean {
if ('memory' in performance && (performance as any).memory) {
const memory = (performance as any).memory;
const used = memory.usedJSHeapSize;
const limit = memory.jsHeapSizeLimit;
const available = limit - used;
if (estimatedBytes > available * this.WARNING_THRESHOLD) {
console.warn(`Memory warning: Estimated ${estimatedBytes} bytes needed, ${available} bytes available`);
return false;
}
}
return true;
}
/**
* Estimate memory needed for image
*/
static estimateImageMemory(width: number, height: number, channels: number = 4): number {
// Each pixel uses 4 bytes (RGBA) or specified channels
return width * height * channels;
}
/**
* Force garbage collection if available
*/
static requestGarbageCollection(): void {
if (typeof (globalThis as any).gc === 'function') {
(globalThis as any).gc();
}
}
}
/**
* Web Worker support for heavy operations
*/
export class ImageWorkerPool {
private workers: Worker[] = [];
private taskQueue: Array<{
data: any;
resolve: (value: any) => void;
reject: (error: any) => void;
}> = [];
private busyWorkers = new Set<Worker>();
constructor(
private workerScript: string,
private poolSize: number = navigator.hardwareConcurrency || 4
) {
this.initializeWorkers();
}
private initializeWorkers(): void {
for (let i = 0; i < this.poolSize; i++) {
try {
const worker = new Worker(this.workerScript);
worker.addEventListener('message', (e) => this.handleWorkerMessage(worker, e));
worker.addEventListener('error', (e) => this.handleWorkerError(worker, e));
this.workers.push(worker);
} catch (error) {
console.error('Failed to create worker:', error);
}
}
}
private handleWorkerMessage(worker: Worker, event: MessageEvent): void {
this.busyWorkers.delete(worker);
// Process next task if available
if (this.taskQueue.length > 0) {
const task = this.taskQueue.shift()!;
this.executeTask(worker, task);
}
}
private handleWorkerError(worker: Worker, event: ErrorEvent): void {
this.busyWorkers.delete(worker);
console.error('Worker error:', event);
}
private executeTask(
worker: Worker,
task: { data: any; resolve: (value: any) => void; reject: (error: any) => void }
): void {
this.busyWorkers.add(worker);
const messageHandler = (e: MessageEvent) => {
worker.removeEventListener('message', messageHandler);
worker.removeEventListener('error', errorHandler);
this.busyWorkers.delete(worker);
task.resolve(e.data);
// Process next task
if (this.taskQueue.length > 0) {
const nextTask = this.taskQueue.shift()!;
this.executeTask(worker, nextTask);
}
};
const errorHandler = (e: ErrorEvent) => {
worker.removeEventListener('message', messageHandler);
worker.removeEventListener('error', errorHandler);
this.busyWorkers.delete(worker);
task.reject(e);
// Process next task
if (this.taskQueue.length > 0) {
const nextTask = this.taskQueue.shift()!;
this.executeTask(worker, nextTask);
}
};
worker.addEventListener('message', messageHandler);
worker.addEventListener('error', errorHandler);
worker.postMessage(task.data);
}
async process(data: any): Promise<any> {
return new Promise((resolve, reject) => {
// Find available worker
const availableWorker = this.workers.find(w => !this.busyWorkers.has(w));
if (availableWorker) {
this.executeTask(availableWorker, { data, resolve, reject });
} else {
// Queue task
this.taskQueue.push({ data, resolve, reject });
}
});
}
terminate(): void {
this.workers.forEach(worker => worker.terminate());
this.workers = [];
this.taskQueue = [];
this.busyWorkers.clear();
}
}
export default {
ImageError,
ImageErrorType,
ImageValidator,
MemoryMonitor,
ImageWorkerPool,
withErrorBoundary
};

View File

@@ -1,839 +0,0 @@
/**
* EXIF Data Viewer Module for Trilium Notes
* Extracts and displays EXIF metadata from images
*/
/**
* EXIF data structure
*/
export interface ExifData {
// Image information
make?: string;
model?: string;
software?: string;
dateTime?: Date;
dateTimeOriginal?: Date;
dateTimeDigitized?: Date;
// Camera settings
exposureTime?: string;
fNumber?: number;
exposureProgram?: string;
iso?: number;
shutterSpeedValue?: string;
apertureValue?: number;
brightnessValue?: number;
exposureBiasValue?: number;
maxApertureValue?: number;
meteringMode?: string;
flash?: string;
focalLength?: number;
focalLengthIn35mm?: number;
// Image properties
imageWidth?: number;
imageHeight?: number;
orientation?: number;
xResolution?: number;
yResolution?: number;
resolutionUnit?: string;
colorSpace?: string;
whiteBalance?: string;
// GPS information
gpsLatitude?: number;
gpsLongitude?: number;
gpsAltitude?: number;
gpsTimestamp?: Date;
gpsSpeed?: number;
gpsDirection?: number;
// Other metadata
artist?: string;
copyright?: string;
userComment?: string;
imageDescription?: string;
lensModel?: string;
lensMake?: string;
// Raw data
raw?: Record<string, any>;
}
/**
* EXIF tag definitions
*/
const EXIF_TAGS: Record<number, string> = {
0x010F: 'make',
0x0110: 'model',
0x0131: 'software',
0x0132: 'dateTime',
0x829A: 'exposureTime',
0x829D: 'fNumber',
0x8822: 'exposureProgram',
0x8827: 'iso',
0x9003: 'dateTimeOriginal',
0x9004: 'dateTimeDigitized',
0x9201: 'shutterSpeedValue',
0x9202: 'apertureValue',
0x9203: 'brightnessValue',
0x9204: 'exposureBiasValue',
0x9205: 'maxApertureValue',
0x9207: 'meteringMode',
0x9209: 'flash',
0x920A: 'focalLength',
0xA002: 'imageWidth',
0xA003: 'imageHeight',
0x0112: 'orientation',
0x011A: 'xResolution',
0x011B: 'yResolution',
0x0128: 'resolutionUnit',
0xA001: 'colorSpace',
0xA403: 'whiteBalance',
0x8298: 'copyright',
0x013B: 'artist',
0x9286: 'userComment',
0x010E: 'imageDescription',
0xA434: 'lensModel',
0xA433: 'lensMake',
0xA432: 'focalLengthIn35mm'
};
/**
* GPS tag definitions
*/
const GPS_TAGS: Record<number, string> = {
0x0001: 'gpsLatitudeRef',
0x0002: 'gpsLatitude',
0x0003: 'gpsLongitudeRef',
0x0004: 'gpsLongitude',
0x0005: 'gpsAltitudeRef',
0x0006: 'gpsAltitude',
0x0007: 'gpsTimestamp',
0x000D: 'gpsSpeed',
0x0010: 'gpsDirection'
};
/**
* ImageExifService extracts and manages EXIF metadata from images
*/
class ImageExifService {
private static instance: ImageExifService;
private exifCache: Map<string, ExifData> = new Map();
private cacheOrder: string[] = []; // Track cache insertion order for LRU
private readonly MAX_CACHE_SIZE = 50; // Maximum number of cached entries
private readonly MAX_BUFFER_SIZE = 100 * 1024 * 1024; // 100MB max buffer size
private constructor() {}
static getInstance(): ImageExifService {
if (!ImageExifService.instance) {
ImageExifService.instance = new ImageExifService();
}
return ImageExifService.instance;
}
/**
* Extract EXIF data from image URL or file
*/
async extractExifData(source: string | File | Blob): Promise<ExifData | null> {
try {
// Check cache if URL
if (typeof source === 'string' && this.exifCache.has(source)) {
// Move to end for LRU
this.updateCacheOrder(source);
return this.exifCache.get(source)!;
}
// Get array buffer with size validation
const buffer = await this.getArrayBuffer(source);
// Validate buffer size
if (buffer.byteLength > this.MAX_BUFFER_SIZE) {
console.error('Buffer size exceeds maximum allowed size');
return null;
}
// Parse EXIF data
const exifData = this.parseExifData(buffer);
// Cache if URL with LRU eviction
if (typeof source === 'string' && exifData) {
this.addToCache(source, exifData);
}
return exifData;
} catch (error) {
console.error('Failed to extract EXIF data:', error);
return null;
}
}
/**
* Get array buffer from various sources
*/
private async getArrayBuffer(source: string | File | Blob): Promise<ArrayBuffer> {
if (source instanceof File || source instanceof Blob) {
return source.arrayBuffer();
} else {
const response = await fetch(source);
return response.arrayBuffer();
}
}
/**
* Parse EXIF data from array buffer
*/
private parseExifData(buffer: ArrayBuffer): ExifData | null {
const dataView = new DataView(buffer);
// Check for JPEG SOI marker
if (dataView.getUint16(0) !== 0xFFD8) {
return null; // Not a JPEG
}
// Find APP1 marker (EXIF)
let offset = 2;
let marker;
while (offset < dataView.byteLength) {
marker = dataView.getUint16(offset);
if (marker === 0xFFE1) {
// Found EXIF marker
return this.parseExifSegment(dataView, offset + 2);
}
if ((marker & 0xFF00) !== 0xFF00) {
break; // Invalid marker
}
offset += 2 + dataView.getUint16(offset + 2);
}
return null;
}
/**
* Parse EXIF segment with bounds checking
*/
private parseExifSegment(dataView: DataView, offset: number): ExifData | null {
// Bounds check
if (offset + 2 > dataView.byteLength) {
console.error('Invalid offset for EXIF segment');
return null;
}
const length = dataView.getUint16(offset);
// Validate segment length
if (offset + length > dataView.byteLength) {
console.error('EXIF segment length exceeds buffer size');
return null;
}
// Check for "Exif\0\0" identifier with bounds check
if (offset + 6 > dataView.byteLength) {
console.error('Invalid EXIF header offset');
return null;
}
const exifHeader = String.fromCharCode(
dataView.getUint8(offset + 2),
dataView.getUint8(offset + 3),
dataView.getUint8(offset + 4),
dataView.getUint8(offset + 5)
);
if (exifHeader !== 'Exif') {
return null;
}
// TIFF header offset
const tiffOffset = offset + 8;
// Check byte order
const byteOrder = dataView.getUint16(tiffOffset);
const littleEndian = byteOrder === 0x4949; // 'II' for Intel
if (byteOrder !== 0x4949 && byteOrder !== 0x4D4D) {
return null; // Invalid byte order
}
// Parse IFD
const ifdOffset = this.getUint32(dataView, tiffOffset + 4, littleEndian);
const exifData = this.parseIFD(dataView, tiffOffset, tiffOffset + ifdOffset, littleEndian);
// Parse GPS data if available
if (exifData.raw?.gpsIFDPointer) {
const gpsData = this.parseGPSIFD(
dataView,
tiffOffset,
tiffOffset + exifData.raw.gpsIFDPointer,
littleEndian
);
Object.assign(exifData, gpsData);
}
return this.formatExifData(exifData);
}
/**
* Parse IFD (Image File Directory) with bounds checking
*/
private parseIFD(
dataView: DataView,
tiffOffset: number,
ifdOffset: number,
littleEndian: boolean
): ExifData {
// Bounds check for IFD offset
if (ifdOffset + 2 > dataView.byteLength) {
console.error('Invalid IFD offset');
return { raw: {} };
}
const numEntries = this.getUint16(dataView, ifdOffset, littleEndian);
// Validate number of entries
if (numEntries > 1000) { // Reasonable limit
console.error('Too many IFD entries');
return { raw: {} };
}
const data: ExifData = { raw: {} };
for (let i = 0; i < numEntries; i++) {
const entryOffset = ifdOffset + 2 + (i * 12);
// Bounds check for entry
if (entryOffset + 12 > dataView.byteLength) {
console.warn('IFD entry exceeds buffer bounds');
break;
}
const tag = this.getUint16(dataView, entryOffset, littleEndian);
const type = this.getUint16(dataView, entryOffset + 2, littleEndian);
const count = this.getUint32(dataView, entryOffset + 4, littleEndian);
const valueOffset = entryOffset + 8;
const value = this.getTagValue(
dataView,
tiffOffset,
type,
count,
valueOffset,
littleEndian
);
const tagName = EXIF_TAGS[tag];
if (tagName) {
(data as any)[tagName] = value;
}
// Store raw value
data.raw![tag] = value;
// Check for EXIF IFD pointer
if (tag === 0x8769) {
const exifIFDOffset = tiffOffset + value;
const exifData = this.parseIFD(dataView, tiffOffset, exifIFDOffset, littleEndian);
Object.assign(data, exifData);
}
// Store GPS IFD pointer
if (tag === 0x8825) {
data.raw!.gpsIFDPointer = value;
}
}
return data;
}
/**
* Parse GPS IFD
*/
private parseGPSIFD(
dataView: DataView,
tiffOffset: number,
ifdOffset: number,
littleEndian: boolean
): Partial<ExifData> {
const numEntries = this.getUint16(dataView, ifdOffset, littleEndian);
const gpsData: any = {};
for (let i = 0; i < numEntries; i++) {
const entryOffset = ifdOffset + 2 + (i * 12);
// Bounds check for entry
if (entryOffset + 12 > dataView.byteLength) {
console.warn('IFD entry exceeds buffer bounds');
break;
}
const tag = this.getUint16(dataView, entryOffset, littleEndian);
const type = this.getUint16(dataView, entryOffset + 2, littleEndian);
const count = this.getUint32(dataView, entryOffset + 4, littleEndian);
const valueOffset = entryOffset + 8;
const value = this.getTagValue(
dataView,
tiffOffset,
type,
count,
valueOffset,
littleEndian
);
const tagName = GPS_TAGS[tag];
if (tagName) {
gpsData[tagName] = value;
}
}
// Convert GPS coordinates
const result: Partial<ExifData> = {};
if (gpsData.gpsLatitude && gpsData.gpsLatitudeRef) {
result.gpsLatitude = this.convertGPSCoordinate(
gpsData.gpsLatitude,
gpsData.gpsLatitudeRef
);
}
if (gpsData.gpsLongitude && gpsData.gpsLongitudeRef) {
result.gpsLongitude = this.convertGPSCoordinate(
gpsData.gpsLongitude,
gpsData.gpsLongitudeRef
);
}
if (gpsData.gpsAltitude) {
result.gpsAltitude = gpsData.gpsAltitude;
}
return result;
}
/**
* Get tag value based on type
*/
private getTagValue(
dataView: DataView,
tiffOffset: number,
type: number,
count: number,
offset: number,
littleEndian: boolean
): any {
switch (type) {
case 1: // BYTE
case 7: // UNDEFINED
if (count === 1) {
return dataView.getUint8(offset);
}
const bytes = [];
for (let i = 0; i < count; i++) {
bytes.push(dataView.getUint8(offset + i));
}
return bytes;
case 2: // ASCII
const stringOffset = count > 4
? tiffOffset + this.getUint32(dataView, offset, littleEndian)
: offset;
let str = '';
for (let i = 0; i < count - 1; i++) {
const char = dataView.getUint8(stringOffset + i);
if (char === 0) break;
str += String.fromCharCode(char);
}
return str;
case 3: // SHORT
if (count === 1) {
return this.getUint16(dataView, offset, littleEndian);
}
const shorts = [];
const shortOffset = count > 2
? tiffOffset + this.getUint32(dataView, offset, littleEndian)
: offset;
for (let i = 0; i < count; i++) {
shorts.push(this.getUint16(dataView, shortOffset + i * 2, littleEndian));
}
return shorts;
case 4: // LONG
if (count === 1) {
return this.getUint32(dataView, offset, littleEndian);
}
const longs = [];
const longOffset = tiffOffset + this.getUint32(dataView, offset, littleEndian);
for (let i = 0; i < count; i++) {
longs.push(this.getUint32(dataView, longOffset + i * 4, littleEndian));
}
return longs;
case 5: // RATIONAL
const ratOffset = tiffOffset + this.getUint32(dataView, offset, littleEndian);
if (count === 1) {
const num = this.getUint32(dataView, ratOffset, littleEndian);
const den = this.getUint32(dataView, ratOffset + 4, littleEndian);
return den === 0 ? 0 : num / den;
}
const rationals = [];
for (let i = 0; i < count; i++) {
const num = this.getUint32(dataView, ratOffset + i * 8, littleEndian);
const den = this.getUint32(dataView, ratOffset + i * 8 + 4, littleEndian);
rationals.push(den === 0 ? 0 : num / den);
}
return rationals;
default:
return null;
}
}
/**
* Convert GPS coordinate to decimal degrees
*/
private convertGPSCoordinate(coord: number[], ref: string): number {
if (!coord || coord.length !== 3) return 0;
const degrees = coord[0];
const minutes = coord[1];
const seconds = coord[2];
let decimal = degrees + minutes / 60 + seconds / 3600;
if (ref === 'S' || ref === 'W') {
decimal = -decimal;
}
return decimal;
}
/**
* Format EXIF data for display
*/
private formatExifData(data: ExifData): ExifData {
const formatted: ExifData = { ...data };
// Format dates
if (formatted.dateTime) {
formatted.dateTime = this.parseExifDate(formatted.dateTime as any);
}
if (formatted.dateTimeOriginal) {
formatted.dateTimeOriginal = this.parseExifDate(formatted.dateTimeOriginal as any);
}
if (formatted.dateTimeDigitized) {
formatted.dateTimeDigitized = this.parseExifDate(formatted.dateTimeDigitized as any);
}
// Format exposure time
if (formatted.exposureTime) {
const time = formatted.exposureTime as any;
if (typeof time === 'number') {
if (time < 1) {
formatted.exposureTime = `1/${Math.round(1 / time)}`;
} else {
formatted.exposureTime = `${time}s`;
}
}
}
// Format exposure program
if (formatted.exposureProgram) {
const programs = [
'Not defined',
'Manual',
'Normal program',
'Aperture priority',
'Shutter priority',
'Creative program',
'Action program',
'Portrait mode',
'Landscape mode'
];
const index = formatted.exposureProgram as any;
formatted.exposureProgram = programs[index] || 'Unknown';
}
// Format metering mode
if (formatted.meteringMode) {
const modes = [
'Unknown',
'Average',
'Center-weighted average',
'Spot',
'Multi-spot',
'Pattern',
'Partial'
];
const index = formatted.meteringMode as any;
formatted.meteringMode = modes[index] || 'Unknown';
}
// Format flash
if (formatted.flash !== undefined) {
const flash = formatted.flash as any;
formatted.flash = (flash & 1) ? 'Flash fired' : 'Flash did not fire';
}
return formatted;
}
/**
* Parse EXIF date string
*/
private parseExifDate(dateStr: string): Date {
// EXIF date format: "YYYY:MM:DD HH:MM:SS"
const parts = dateStr.split(' ');
if (parts.length !== 2) return new Date(dateStr);
const dateParts = parts[0].split(':');
const timeParts = parts[1].split(':');
if (dateParts.length !== 3 || timeParts.length !== 3) {
return new Date(dateStr);
}
return new Date(
parseInt(dateParts[0]),
parseInt(dateParts[1]) - 1,
parseInt(dateParts[2]),
parseInt(timeParts[0]),
parseInt(timeParts[1]),
parseInt(timeParts[2])
);
}
/**
* Get uint16 with endianness and bounds checking
*/
private getUint16(dataView: DataView, offset: number, littleEndian: boolean): number {
if (offset + 2 > dataView.byteLength) {
console.error('Uint16 read exceeds buffer bounds');
return 0;
}
return dataView.getUint16(offset, littleEndian);
}
/**
* Get uint32 with endianness and bounds checking
*/
private getUint32(dataView: DataView, offset: number, littleEndian: boolean): number {
if (offset + 4 > dataView.byteLength) {
console.error('Uint32 read exceeds buffer bounds');
return 0;
}
return dataView.getUint32(offset, littleEndian);
}
/**
* Create EXIF display panel
*/
createExifPanel(exifData: ExifData): HTMLElement {
const panel = document.createElement('div');
panel.className = 'exif-panel';
panel.style.cssText = `
background: rgba(0, 0, 0, 0.9);
color: white;
padding: 15px;
border-radius: 8px;
max-width: 400px;
max-height: 500px;
overflow-y: auto;
font-size: 12px;
`;
const sections = [
{
title: 'Camera',
fields: ['make', 'model', 'lensModel']
},
{
title: 'Settings',
fields: ['exposureTime', 'fNumber', 'iso', 'focalLength', 'exposureProgram', 'meteringMode', 'flash']
},
{
title: 'Image',
fields: ['imageWidth', 'imageHeight', 'orientation', 'colorSpace', 'whiteBalance']
},
{
title: 'Date/Time',
fields: ['dateTimeOriginal', 'dateTime']
},
{
title: 'Location',
fields: ['gpsLatitude', 'gpsLongitude', 'gpsAltitude']
},
{
title: 'Other',
fields: ['software', 'artist', 'copyright', 'imageDescription']
}
];
sections.forEach(section => {
const hasData = section.fields.some(field => (exifData as any)[field]);
if (!hasData) return;
const sectionDiv = document.createElement('div');
sectionDiv.style.marginBottom = '15px';
const title = document.createElement('h4');
// Use textContent for safe title insertion
title.textContent = section.title;
title.style.cssText = 'margin: 0 0 8px 0; color: #4CAF50;';
title.setAttribute('aria-label', `Section: ${section.title}`);
sectionDiv.appendChild(title);
section.fields.forEach(field => {
const value = (exifData as any)[field];
if (!value) return;
const row = document.createElement('div');
row.style.cssText = 'display: flex; justify-content: space-between; margin: 4px 0;';
const label = document.createElement('span');
// Use textContent for safe text insertion
label.textContent = this.formatFieldName(field) + ':';
label.style.color = '#aaa';
const val = document.createElement('span');
// Use textContent for safe value insertion
val.textContent = this.formatFieldValue(field, value);
val.style.textAlign = 'right';
row.appendChild(label);
row.appendChild(val);
sectionDiv.appendChild(row);
});
panel.appendChild(sectionDiv);
});
// Add GPS map link if coordinates available
if (exifData.gpsLatitude && exifData.gpsLongitude) {
const mapLink = document.createElement('a');
mapLink.href = `https://www.google.com/maps?q=${exifData.gpsLatitude},${exifData.gpsLongitude}`;
mapLink.target = '_blank';
mapLink.textContent = 'View on Map';
mapLink.style.cssText = `
display: inline-block;
margin-top: 10px;
padding: 8px 12px;
background: #4CAF50;
color: white;
text-decoration: none;
border-radius: 4px;
`;
panel.appendChild(mapLink);
}
return panel;
}
/**
* Format field name for display
*/
private formatFieldName(field: string): string {
const names: Record<string, string> = {
make: 'Camera Make',
model: 'Camera Model',
lensModel: 'Lens',
exposureTime: 'Shutter Speed',
fNumber: 'Aperture',
iso: 'ISO',
focalLength: 'Focal Length',
exposureProgram: 'Mode',
meteringMode: 'Metering',
flash: 'Flash',
imageWidth: 'Width',
imageHeight: 'Height',
orientation: 'Orientation',
colorSpace: 'Color Space',
whiteBalance: 'White Balance',
dateTimeOriginal: 'Date Taken',
dateTime: 'Date Modified',
gpsLatitude: 'Latitude',
gpsLongitude: 'Longitude',
gpsAltitude: 'Altitude',
software: 'Software',
artist: 'Artist',
copyright: 'Copyright',
imageDescription: 'Description'
};
return names[field] || field;
}
/**
* Format field value for display
*/
private formatFieldValue(field: string, value: any): string {
if (value instanceof Date) {
return value.toLocaleString();
}
switch (field) {
case 'fNumber':
return `f/${value}`;
case 'focalLength':
return `${value}mm`;
case 'gpsLatitude':
case 'gpsLongitude':
return value.toFixed(6) + '°';
case 'gpsAltitude':
return `${value.toFixed(1)}m`;
case 'imageWidth':
case 'imageHeight':
return `${value}px`;
default:
return String(value);
}
}
/**
* Add to cache with LRU eviction
*/
private addToCache(key: string, data: ExifData): void {
// Remove from order if exists
const existingIndex = this.cacheOrder.indexOf(key);
if (existingIndex !== -1) {
this.cacheOrder.splice(existingIndex, 1);
}
// Add to end
this.cacheOrder.push(key);
this.exifCache.set(key, data);
// Evict oldest if over limit
while (this.cacheOrder.length > this.MAX_CACHE_SIZE) {
const oldestKey = this.cacheOrder.shift();
if (oldestKey) {
this.exifCache.delete(oldestKey);
}
}
}
/**
* Update cache order for LRU
*/
private updateCacheOrder(key: string): void {
const index = this.cacheOrder.indexOf(key);
if (index !== -1) {
this.cacheOrder.splice(index, 1);
this.cacheOrder.push(key);
}
}
/**
* Clear EXIF cache
*/
clearCache(): void {
this.exifCache.clear();
this.cacheOrder = [];
}
}
export default ImageExifService.getInstance();

View File

@@ -1,681 +0,0 @@
/**
* Image Sharing and Export Module for Trilium Notes
* Provides functionality for sharing, downloading, and exporting images
*/
import server from './server.js';
import utils from './utils.js';
import toastService from './toast.js';
import type FNote from '../entities/fnote.js';
import { ImageValidator, withErrorBoundary, MemoryMonitor, ImageError, ImageErrorType } from './image_error_handler.js';
/**
* Export format options
*/
export type ExportFormat = 'original' | 'jpeg' | 'png' | 'webp';
/**
* Export size presets
*/
export type SizePreset = 'original' | 'thumbnail' | 'small' | 'medium' | 'large' | 'custom';
/**
* Export configuration
*/
export interface ExportConfig {
format: ExportFormat;
quality: number; // 0-100 for JPEG/WebP
size: SizePreset;
customWidth?: number;
customHeight?: number;
maintainAspectRatio: boolean;
addWatermark: boolean;
watermarkText?: string;
watermarkPosition?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center';
watermarkOpacity?: number;
}
/**
* Share options
*/
export interface ShareOptions {
method: 'link' | 'email' | 'social';
expiresIn?: number; // Hours
password?: string;
allowDownload: boolean;
trackViews: boolean;
}
/**
* Share link data
*/
export interface ShareLink {
url: string;
shortUrl?: string;
expiresAt?: Date;
password?: string;
views: number;
maxViews?: number;
created: Date;
}
/**
* Size presets in pixels
*/
const SIZE_PRESETS = {
thumbnail: { width: 150, height: 150 },
small: { width: 400, height: 400 },
medium: { width: 800, height: 800 },
large: { width: 1600, height: 1600 }
};
/**
* ImageSharingService handles image sharing, downloading, and exporting
*/
class ImageSharingService {
private static instance: ImageSharingService;
private activeShares: Map<string, ShareLink> = new Map();
private downloadCanvas?: HTMLCanvasElement;
private downloadContext?: CanvasRenderingContext2D;
// Canvas size limits for security and memory management
private readonly MAX_CANVAS_SIZE = 8192; // Maximum width/height
private readonly MAX_CANVAS_AREA = 50000000; // 50 megapixels
private defaultExportConfig: ExportConfig = {
format: 'original',
quality: 90,
size: 'original',
maintainAspectRatio: true,
addWatermark: false,
watermarkPosition: 'bottom-right',
watermarkOpacity: 0.5
};
private constructor() {
// Initialize download canvas
this.downloadCanvas = document.createElement('canvas');
this.downloadContext = this.downloadCanvas.getContext('2d') || undefined;
}
static getInstance(): ImageSharingService {
if (!ImageSharingService.instance) {
ImageSharingService.instance = new ImageSharingService();
}
return ImageSharingService.instance;
}
/**
* Download image with options
*/
async downloadImage(
src: string,
filename: string,
config?: Partial<ExportConfig>
): Promise<void> {
await withErrorBoundary(async () => {
// Validate inputs
ImageValidator.validateUrl(src);
const sanitizedFilename = ImageValidator.sanitizeFilename(filename);
const finalConfig = { ...this.defaultExportConfig, ...config };
// Load image
const img = await this.loadImage(src);
// Process image based on config
const processedBlob = await this.processImage(img, finalConfig);
// Create download link
const url = URL.createObjectURL(processedBlob);
const link = document.createElement('a');
link.href = url;
// Determine filename with extension
const extension = finalConfig.format === 'original'
? this.getOriginalExtension(sanitizedFilename)
: finalConfig.format;
const finalFilename = this.ensureExtension(sanitizedFilename, extension);
link.download = finalFilename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
// Cleanup
URL.revokeObjectURL(url);
toastService.showMessage(`Downloaded ${finalFilename}`);
});
}
/**
* Process image according to export configuration
*/
private async processImage(img: HTMLImageElement, config: ExportConfig): Promise<Blob> {
if (!this.downloadCanvas || !this.downloadContext) {
throw new Error('Canvas not initialized');
}
// Calculate dimensions
const { width, height } = this.calculateDimensions(
img.naturalWidth,
img.naturalHeight,
config
);
// Validate canvas dimensions
ImageValidator.validateDimensions(width, height);
// Check memory availability
const estimatedMemory = MemoryMonitor.estimateImageMemory(width, height);
if (!MemoryMonitor.checkMemoryAvailable(estimatedMemory)) {
throw new ImageError(
ImageErrorType.MEMORY_ERROR,
'Insufficient memory to process image',
{ width, height, estimatedMemory }
);
}
// Set canvas size
this.downloadCanvas.width = width;
this.downloadCanvas.height = height;
// Clear canvas
this.downloadContext.fillStyle = 'white';
this.downloadContext.fillRect(0, 0, width, height);
// Draw image
this.downloadContext.drawImage(img, 0, 0, width, height);
// Add watermark if enabled
if (config.addWatermark && config.watermarkText) {
this.addWatermark(this.downloadContext, width, height, config);
}
// Convert to blob
return new Promise((resolve, reject) => {
const mimeType = this.getMimeType(config.format);
const quality = config.quality / 100;
this.downloadCanvas!.toBlob(
(blob) => {
if (blob) {
resolve(blob);
} else {
reject(new Error('Failed to create blob'));
}
},
mimeType,
quality
);
});
}
/**
* Calculate dimensions based on size preset
*/
private calculateDimensions(
originalWidth: number,
originalHeight: number,
config: ExportConfig
): { width: number; height: number } {
if (config.size === 'original') {
return { width: originalWidth, height: originalHeight };
}
if (config.size === 'custom' && config.customWidth && config.customHeight) {
if (config.maintainAspectRatio) {
const aspectRatio = originalWidth / originalHeight;
const targetRatio = config.customWidth / config.customHeight;
if (aspectRatio > targetRatio) {
return {
width: config.customWidth,
height: Math.round(config.customWidth / aspectRatio)
};
} else {
return {
width: Math.round(config.customHeight * aspectRatio),
height: config.customHeight
};
}
}
return { width: config.customWidth, height: config.customHeight };
}
// Use preset
const preset = SIZE_PRESETS[config.size as keyof typeof SIZE_PRESETS];
if (!preset) {
return { width: originalWidth, height: originalHeight };
}
if (config.maintainAspectRatio) {
const aspectRatio = originalWidth / originalHeight;
const maxWidth = preset.width;
const maxHeight = preset.height;
let width = originalWidth;
let height = originalHeight;
if (width > maxWidth) {
width = maxWidth;
height = Math.round(width / aspectRatio);
}
if (height > maxHeight) {
height = maxHeight;
width = Math.round(height * aspectRatio);
}
return { width, height };
}
return preset;
}
/**
* Add watermark to canvas
*/
private addWatermark(
ctx: CanvasRenderingContext2D,
width: number,
height: number,
config: ExportConfig
): void {
if (!config.watermarkText) return;
ctx.save();
// Set watermark style
ctx.globalAlpha = config.watermarkOpacity || 0.5;
ctx.fillStyle = 'white';
ctx.strokeStyle = 'black';
ctx.lineWidth = 2;
ctx.font = `${Math.min(width, height) * 0.05}px Arial`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
// Calculate position
let x = width / 2;
let y = height / 2;
switch (config.watermarkPosition) {
case 'top-left':
x = width * 0.1;
y = height * 0.1;
ctx.textAlign = 'left';
break;
case 'top-right':
x = width * 0.9;
y = height * 0.1;
ctx.textAlign = 'right';
break;
case 'bottom-left':
x = width * 0.1;
y = height * 0.9;
ctx.textAlign = 'left';
break;
case 'bottom-right':
x = width * 0.9;
y = height * 0.9;
ctx.textAlign = 'right';
break;
}
// Draw watermark with outline
ctx.strokeText(config.watermarkText, x, y);
ctx.fillText(config.watermarkText, x, y);
ctx.restore();
}
/**
* Generate shareable link for image
*/
async generateShareLink(
noteId: string,
options?: Partial<ShareOptions>
): Promise<ShareLink> {
try {
const finalOptions = {
method: 'link' as const,
allowDownload: true,
trackViews: false,
...options
};
// Create share token on server
const response = await server.post(`notes/${noteId}/share`, {
type: 'image',
expiresIn: finalOptions.expiresIn,
password: finalOptions.password,
allowDownload: finalOptions.allowDownload,
trackViews: finalOptions.trackViews
});
const shareLink: ShareLink = {
url: `${window.location.origin}/share/${response.token}`,
shortUrl: response.shortUrl,
expiresAt: response.expiresAt ? new Date(response.expiresAt) : undefined,
password: finalOptions.password,
views: 0,
maxViews: response.maxViews,
created: new Date()
};
// Store in active shares
this.activeShares.set(response.token, shareLink);
return shareLink;
} catch (error) {
console.error('Failed to generate share link:', error);
throw error;
}
}
/**
* Copy image or link to clipboard
*/
async copyToClipboard(
src: string,
type: 'image' | 'link' = 'link'
): Promise<void> {
await withErrorBoundary(async () => {
// Validate URL
ImageValidator.validateUrl(src);
if (type === 'link') {
// Copy URL to clipboard
await navigator.clipboard.writeText(src);
toastService.showMessage('Link copied to clipboard');
} else {
// Copy image data to clipboard
const img = await this.loadImage(src);
if (!this.downloadCanvas || !this.downloadContext) {
throw new Error('Canvas not initialized');
}
// Validate dimensions before setting
ImageValidator.validateDimensions(img.naturalWidth, img.naturalHeight);
this.downloadCanvas.width = img.naturalWidth;
this.downloadCanvas.height = img.naturalHeight;
this.downloadContext.drawImage(img, 0, 0);
this.downloadCanvas.toBlob(async (blob) => {
if (blob) {
try {
const item = new ClipboardItem({ 'image/png': blob });
await navigator.clipboard.write([item]);
toastService.showMessage('Image copied to clipboard');
} catch (error) {
console.error('Failed to copy image to clipboard:', error);
// Fallback to copying link
await navigator.clipboard.writeText(src);
toastService.showMessage('Image link copied to clipboard');
}
}
});
}
});
}
/**
* Share via native share API (mobile)
*/
async shareNative(
src: string,
title: string,
text?: string
): Promise<void> {
if (!navigator.share) {
throw new Error('Native share not supported');
}
try {
// Try to share with file
const img = await this.loadImage(src);
const blob = await this.processImage(img, this.defaultExportConfig);
const file = new File([blob], `${title}.${this.defaultExportConfig.format}`, {
type: this.getMimeType(this.defaultExportConfig.format)
});
await navigator.share({
title,
text: text || `Check out this image: ${title}`,
files: [file]
});
} catch (error) {
// Fallback to sharing URL
try {
await navigator.share({
title,
text: text || `Check out this image: ${title}`,
url: src
});
} catch (shareError) {
console.error('Failed to share:', shareError);
throw shareError;
}
}
}
/**
* Export multiple images as ZIP
*/
async exportBatch(
images: Array<{ src: string; filename: string }>,
config?: Partial<ExportConfig>
): Promise<void> {
try {
// Dynamic import of JSZip
const JSZip = (await import('jszip')).default;
const zip = new JSZip();
const finalConfig = { ...this.defaultExportConfig, ...config };
// Process each image
for (const { src, filename } of images) {
try {
const img = await this.loadImage(src);
const blob = await this.processImage(img, finalConfig);
const extension = finalConfig.format === 'original'
? this.getOriginalExtension(filename)
: finalConfig.format;
const finalFilename = this.ensureExtension(filename, extension);
zip.file(finalFilename, blob);
} catch (error) {
console.error(`Failed to process image ${filename}:`, error);
}
}
// Generate and download ZIP
const zipBlob = await zip.generateAsync({ type: 'blob' });
const url = URL.createObjectURL(zipBlob);
const link = document.createElement('a');
link.href = url;
link.download = `images_${Date.now()}.zip`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
toastService.showMessage(`Exported ${images.length} images`);
} catch (error) {
console.error('Failed to export images:', error);
toastService.showError('Failed to export images');
throw error;
}
}
/**
* Open share dialog
*/
openShareDialog(
src: string,
title: string,
noteId?: string
): void {
// Create modal dialog
const dialog = document.createElement('div');
dialog.className = 'share-dialog-overlay';
dialog.style.cssText = `
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 10000;
`;
const content = document.createElement('div');
content.className = 'share-dialog';
content.style.cssText = `
background: white;
border-radius: 8px;
padding: 20px;
width: 400px;
max-width: 90%;
`;
content.innerHTML = `
<h3 style="margin: 0 0 15px 0;">Share Image</h3>
<div class="share-options" style="display: flex; flex-direction: column; gap: 10px;">
<button class="share-copy-link" style="padding: 10px; border: 1px solid #ddd; border-radius: 4px; cursor: pointer;">
<i class="bx bx-link"></i> Copy Link
</button>
<button class="share-copy-image" style="padding: 10px; border: 1px solid #ddd; border-radius: 4px; cursor: pointer;">
<i class="bx bx-copy"></i> Copy Image
</button>
<button class="share-download" style="padding: 10px; border: 1px solid #ddd; border-radius: 4px; cursor: pointer;">
<i class="bx bx-download"></i> Download
</button>
${navigator.share ? `
<button class="share-native" style="padding: 10px; border: 1px solid #ddd; border-radius: 4px; cursor: pointer;">
<i class="bx bx-share"></i> Share...
</button>
` : ''}
${noteId ? `
<button class="share-generate-link" style="padding: 10px; border: 1px solid #ddd; border-radius: 4px; cursor: pointer;">
<i class="bx bx-link-external"></i> Generate Share Link
</button>
` : ''}
</div>
<button class="close-dialog" style="margin-top: 15px; padding: 8px 16px; background: #f0f0f0; border: none; border-radius: 4px; cursor: pointer;">
Close
</button>
`;
// Add event handlers
content.querySelector('.share-copy-link')?.addEventListener('click', () => {
this.copyToClipboard(src, 'link');
dialog.remove();
});
content.querySelector('.share-copy-image')?.addEventListener('click', () => {
this.copyToClipboard(src, 'image');
dialog.remove();
});
content.querySelector('.share-download')?.addEventListener('click', () => {
this.downloadImage(src, title);
dialog.remove();
});
content.querySelector('.share-native')?.addEventListener('click', () => {
this.shareNative(src, title);
dialog.remove();
});
content.querySelector('.share-generate-link')?.addEventListener('click', async () => {
if (noteId) {
const link = await this.generateShareLink(noteId);
await this.copyToClipboard(link.url, 'link');
dialog.remove();
}
});
content.querySelector('.close-dialog')?.addEventListener('click', () => {
dialog.remove();
});
dialog.appendChild(content);
document.body.appendChild(dialog);
}
/**
* Load image from URL
*/
private loadImage(src: string): Promise<HTMLImageElement> {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = 'anonymous';
img.onload = () => resolve(img);
img.onerror = () => reject(new Error(`Failed to load image: ${src}`));
img.src = src;
});
}
/**
* Get MIME type for format
*/
private getMimeType(format: ExportFormat): string {
switch (format) {
case 'jpeg':
return 'image/jpeg';
case 'png':
return 'image/png';
case 'webp':
return 'image/webp';
default:
return 'image/png';
}
}
/**
* Get original extension from filename
*/
private getOriginalExtension(filename: string): string {
const parts = filename.split('.');
if (parts.length > 1) {
return parts[parts.length - 1].toLowerCase();
}
return 'png';
}
/**
* Ensure filename has correct extension
*/
private ensureExtension(filename: string, extension: string): string {
const parts = filename.split('.');
if (parts.length > 1) {
parts[parts.length - 1] = extension;
return parts.join('.');
}
return `${filename}.${extension}`;
}
/**
* Cleanup resources
*/
cleanup(): void {
this.activeShares.clear();
// Clean up canvas memory
if (this.downloadCanvas && this.downloadContext) {
this.downloadContext.clearRect(0, 0, this.downloadCanvas.width, this.downloadCanvas.height);
this.downloadCanvas.width = 0;
this.downloadCanvas.height = 0;
}
this.downloadCanvas = undefined;
this.downloadContext = undefined;
}
}
export default ImageSharingService.getInstance();

View File

@@ -4,6 +4,7 @@ import ws from "./ws.js";
import utils from "./utils.js";
import appContext from "../components/app_context.js";
import { t } from "./i18n.js";
import { WebSocketMessage } from "@triliumnext/commons";
type BooleanLike = boolean | "true" | "false";
@@ -66,7 +67,7 @@ function makeToast(id: string, message: string): ToastOptions {
}
ws.subscribeToMessages(async (message) => {
if (message.taskType !== "importNotes") {
if (!("taskType" in message) || message.taskType !== "importNotes") {
return;
}
@@ -87,8 +88,8 @@ ws.subscribeToMessages(async (message) => {
}
});
ws.subscribeToMessages(async (message) => {
if (message.taskType !== "importAttachments") {
ws.subscribeToMessages(async (message: WebSocketMessage) => {
if (!("taskType" in message) || message.taskType !== "importAttachments") {
return;
}

View File

@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { byBookType, byNoteType } from "./help_button.js";
import { byBookType, byNoteType } from "./in_app_help.js";
import fs from "fs";
import type { HiddenSubtreeItem } from "@triliumnext/commons";
import path from "path";
@@ -25,7 +25,7 @@ describe("Help button", () => {
...Object.values(byBookType)
].filter((noteId) => noteId) as string[];
const metaPath = path.resolve(path.join(__dirname, "../../../../server/src/assets/doc_notes/en/User Guide/!!!meta.json"));
const metaPath = path.resolve(path.join(__dirname, "../../../server/src/assets/doc_notes/en/User Guide/!!!meta.json"));
const meta: HiddenSubtreeItem[] = JSON.parse(fs.readFileSync(metaPath, "utf-8"));
const allNoteIds = new Set(getNoteIds(meta));

View File

@@ -0,0 +1,44 @@
import { NoteType } from "@triliumnext/commons";
import FNote from "../entities/fnote";
import { ViewTypeOptions } from "../widgets/collections/interface";
export const byNoteType: Record<Exclude<NoteType, "book">, string | null> = {
canvas: null,
code: null,
contentWidget: null,
doc: null,
file: null,
image: null,
launcher: null,
mermaid: "s1aBHPd79XYj",
mindMap: null,
noteMap: null,
relationMap: null,
render: null,
search: null,
text: null,
webView: null,
aiChat: null
};
export const byBookType: Record<ViewTypeOptions, string | null> = {
list: "mULW0Q3VojwY",
grid: "8QqnMzx393bx",
calendar: "xWbu3jpNWapp",
table: "2FvYrpmOXm29",
geoMap: "81SGnPGMk7Xc",
board: "CtBQqbwXDx1w",
presentation: null
};
export function getHelpUrlForNote(note: FNote | null | undefined) {
if (note && note.type !== "book" && byNoteType[note.type]) {
return byNoteType[note.type];
} else if (note?.hasLabel("calendarRoot")) {
return "l0tKav7yLHGF";
} else if (note?.hasLabel("textSnippet")) {
return "pwc194wlRzcH";
} else if (note && note.type === "book") {
return byBookType[note.getAttributeValue("label", "viewType") as ViewTypeOptions ?? ""]
}
}

View File

@@ -62,6 +62,10 @@ async function getAction(actionName: string, silent = false) {
return action;
}
export function getActionSync(actionName: string) {
return keyboardActionRepo[actionName];
}
function updateDisplayedShortcuts($container: JQuery<HTMLElement>) {
//@ts-ignore
//TODO: each() does not support async callbacks.

View File

@@ -3,16 +3,8 @@ import linkContextMenuService from "../menus/link_context_menu.js";
import appContext, { type NoteCommandData } from "../components/app_context.js";
import froca from "./froca.js";
import utils from "./utils.js";
// Be consistent with `allowedSchemes` in `src\services\html_sanitizer.ts`
// TODO: Deduplicate with server once we can.
export const ALLOWED_PROTOCOLS = [
'http', 'https', 'ftp', 'ftps', 'mailto', 'data', 'evernote', 'file', 'facetime', 'gemini', 'git',
'gopher', 'imap', 'irc', 'irc6', 'jabber', 'jar', 'lastfm', 'ldap', 'ldaps', 'magnet', 'message',
'mumble', 'nfs', 'onenote', 'pop', 'rmi', 's3', 'sftp', 'skype', 'sms', 'spotify', 'steam', 'svn', 'udp',
'view-source', 'vlc', 'vnc', 'ws', 'wss', 'xmpp', 'jdbc', 'slack', 'tel', 'smb', 'zotero', 'geo',
'mid'
];
import { ALLOWED_PROTOCOLS } from "@triliumnext/commons";
import { openInCurrentNoteContext } from "../components/note_context.js";
function getNotePathFromUrl(url: string) {
const notePathMatch = /#(root[A-Za-z0-9_/]*)$/.exec(url);
@@ -35,8 +27,7 @@ async function getLinkIcon(noteId: string, viewMode: ViewMode | undefined) {
return icon;
}
// TODO: Remove `string` once all the view modes have been mapped.
type ViewMode = "default" | "source" | "attachments" | "contextual-help" | string;
export type ViewMode = "default" | "source" | "attachments" | "contextual-help";
export interface ViewScope {
/**
@@ -326,21 +317,7 @@ function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent
viewScope
});
} else if (isLeftClick) {
const ntxId = $(evt?.target as any)
.closest("[data-ntx-id]")
.attr("data-ntx-id");
const noteContext = ntxId ? appContext.tabManager.getNoteContextById(ntxId) : appContext.tabManager.getActiveContext();
if (noteContext) {
noteContext.setNote(notePath, { viewScope }).then(() => {
if (noteContext !== appContext.tabManager.getActiveContext()) {
appContext.tabManager.activateNoteContext(noteContext.ntxId);
}
});
} else {
appContext.tabManager.openContextWithNote(notePath, { viewScope, activate: true });
}
openInCurrentNoteContext(evt, notePath, viewScope);
}
} else if (hrefLink) {
const withinEditLink = $link?.hasClass("ck-link-actions__preview");

View File

@@ -1,4 +1,4 @@
import type { AttachmentRow } from "@triliumnext/commons";
import type { AttachmentRow, EtapiTokenRow, OptionNames } from "@triliumnext/commons";
import type { AttributeType } from "../entities/fattribute.js";
import type { EntityChange } from "../server_types.js";
@@ -53,6 +53,7 @@ type EntityRowMappings = {
options: OptionRow;
revisions: RevisionRow;
note_reordering: NoteReorderingRow;
etapi_tokens: EtapiTokenRow;
};
export type EntityRowNames = keyof EntityRowMappings;
@@ -66,8 +67,9 @@ export default class LoadResults {
private revisionRows: RevisionRow[];
private noteReorderings: string[];
private contentNoteIdToComponentId: ContentNoteIdToComponentIdRow[];
private optionNames: string[];
private optionNames: OptionNames[];
private attachmentRows: AttachmentRow[];
public hasEtapiTokenChanges: boolean = false;
constructor(entityChanges: EntityChange[]) {
const entities: Record<string, Record<string, any>> = {};
@@ -178,11 +180,11 @@ export default class LoadResults {
return this.contentNoteIdToComponentId.find((l) => l.noteId === noteId && l.componentId !== componentId);
}
addOption(name: string) {
addOption(name: OptionNames) {
this.optionNames.push(name);
}
isOptionReloaded(name: string) {
isOptionReloaded(name: OptionNames) {
return this.optionNames.includes(name);
}
@@ -215,7 +217,8 @@ export default class LoadResults {
this.revisionRows.length === 0 &&
this.contentNoteIdToComponentId.length === 0 &&
this.optionNames.length === 0 &&
this.attachmentRows.length === 0
this.attachmentRows.length === 0 &&
!this.hasEtapiTokenChanges
);
}

View File

@@ -1,552 +0,0 @@
import PhotoSwipe from 'photoswipe';
import type PhotoSwipeOptions from 'photoswipe';
import type { DataSource, SlideData } from 'photoswipe';
import 'photoswipe/style.css';
import '../styles/photoswipe-mobile-a11y.css';
import mobileA11yService, { type MobileA11yConfig } from './photoswipe_mobile_a11y.js';
// Define Content type locally since it's not exported by PhotoSwipe
interface Content {
width?: number;
height?: number;
[key: string]: any;
}
// Define AugmentedEvent type locally
interface AugmentedEvent<T extends string> {
content: Content;
slide?: any;
preventDefault?: () => void;
[key: string]: any;
}
/**
* Media item interface for PhotoSwipe gallery
*/
export interface MediaItem {
src: string;
width?: number;
height?: number;
alt?: string;
title?: string;
noteId?: string;
element?: HTMLElement;
msrc?: string; // Thumbnail source
}
/**
* Configuration options for the media viewer
*/
export interface MediaViewerConfig {
bgOpacity?: number;
showHideOpacity?: boolean;
showAnimationDuration?: number;
hideAnimationDuration?: number;
allowPanToNext?: boolean;
spacing?: number;
maxSpreadZoom?: number;
getThumbBoundsFn?: (index: number) => { x: number; y: number; w: number } | undefined;
pinchToClose?: boolean;
closeOnScroll?: boolean;
closeOnVerticalDrag?: boolean;
mouseMovePan?: boolean;
arrowKeys?: boolean;
returnFocus?: boolean;
escKey?: boolean;
errorMsg?: string;
preloadFirstSlide?: boolean;
preload?: [number, number];
loop?: boolean;
wheelToZoom?: boolean;
mobileA11y?: MobileA11yConfig; // Mobile and accessibility configuration
}
/**
* Event callbacks for media viewer
*/
export interface MediaViewerCallbacks {
onOpen?: () => void;
onClose?: () => void;
onChange?: (index: number) => void;
onImageLoad?: (index: number, item: MediaItem) => void;
onImageError?: (index: number, item: MediaItem, error?: Error) => void;
}
/**
* PhotoSwipe data item with original item reference
*/
interface PhotoSwipeDataItem extends SlideData {
_originalItem?: MediaItem;
}
/**
* Error handler for media viewer operations
*/
class MediaViewerError extends Error {
constructor(message: string, public readonly cause?: unknown) {
super(message);
this.name = 'MediaViewerError';
}
}
/**
* MediaViewerService manages the PhotoSwipe lightbox for viewing images and media
* in Trilium Notes. Implements singleton pattern for global access.
*/
class MediaViewerService {
private static instance: MediaViewerService;
private photoSwipe: PhotoSwipe | null = null;
private defaultConfig: MediaViewerConfig;
private currentItems: MediaItem[] = [];
private callbacks: MediaViewerCallbacks = {};
private cleanupHandlers: Array<() => void> = [];
private constructor() {
// Default configuration optimized for Trilium
this.defaultConfig = {
bgOpacity: 0.95,
showHideOpacity: true,
showAnimationDuration: 250,
hideAnimationDuration: 250,
allowPanToNext: true,
spacing: 0.12,
maxSpreadZoom: 4,
pinchToClose: true,
closeOnScroll: false,
closeOnVerticalDrag: true,
mouseMovePan: true,
arrowKeys: true,
returnFocus: true,
escKey: true,
errorMsg: 'The image could not be loaded',
preloadFirstSlide: true,
preload: [1, 2],
loop: true,
wheelToZoom: true
};
// Setup global cleanup on window unload
window.addEventListener('beforeunload', () => this.destroy());
}
/**
* Get singleton instance of MediaViewerService
*/
static getInstance(): MediaViewerService {
if (!MediaViewerService.instance) {
MediaViewerService.instance = new MediaViewerService();
}
return MediaViewerService.instance;
}
/**
* Open the media viewer with specified items
*/
open(items: MediaItem[], startIndex: number = 0, config?: Partial<MediaViewerConfig>, callbacks?: MediaViewerCallbacks): void {
try {
// Validate inputs
if (!items || items.length === 0) {
throw new MediaViewerError('No items provided to media viewer');
}
if (startIndex < 0 || startIndex >= items.length) {
console.warn(`Invalid start index ${startIndex}, using 0`);
startIndex = 0;
}
// Close any existing viewer
this.close();
this.currentItems = items;
this.callbacks = callbacks || {};
// Prepare data source for PhotoSwipe with error handling
const dataSource: DataSource = items.map((item, index) => {
try {
return this.prepareItem(item);
} catch (error) {
console.error(`Failed to prepare item at index ${index}:`, error);
// Return a minimal valid item as fallback
return {
src: item.src,
width: 800,
height: 600,
alt: item.alt || 'Error loading image'
} as PhotoSwipeDataItem;
}
});
// Merge configurations
const finalConfig = {
...this.defaultConfig,
...config,
dataSource,
index: startIndex,
errorMsg: config?.errorMsg || 'The image could not be loaded. Please try again.'
};
// Create and initialize PhotoSwipe
this.photoSwipe = new PhotoSwipe(finalConfig);
// Setup event handlers
this.setupEventHandlers();
// Apply mobile and accessibility enhancements
if (config?.mobileA11y || this.shouldAutoEnhance()) {
mobileA11yService.enhancePhotoSwipe(this.photoSwipe, config?.mobileA11y);
}
// Initialize the viewer
this.photoSwipe.init();
} catch (error) {
console.error('Failed to open media viewer:', error);
// Cleanup on error
this.close();
// Re-throw as MediaViewerError
throw error instanceof MediaViewerError ? error : new MediaViewerError('Failed to open media viewer', error);
}
}
/**
* Open a single image in the viewer
*/
openSingle(item: MediaItem, config?: Partial<MediaViewerConfig>, callbacks?: MediaViewerCallbacks): void {
this.open([item], 0, config, callbacks);
}
/**
* Close the media viewer
*/
close(): void {
if (this.photoSwipe) {
this.photoSwipe.destroy();
this.photoSwipe = null;
this.cleanupEventHandlers();
}
}
/**
* Navigate to next item
*/
next(): void {
if (this.photoSwipe) {
this.photoSwipe.next();
}
}
/**
* Navigate to previous item
*/
prev(): void {
if (this.photoSwipe) {
this.photoSwipe.prev();
}
}
/**
* Go to specific slide by index
*/
goTo(index: number): void {
if (this.photoSwipe && index >= 0 && index < this.currentItems.length) {
this.photoSwipe.goTo(index);
}
}
/**
* Get current slide index
*/
getCurrentIndex(): number {
return this.photoSwipe ? this.photoSwipe.currIndex : -1;
}
/**
* Check if viewer is open
*/
isOpen(): boolean {
return this.photoSwipe !== null;
}
/**
* Update configuration dynamically
*/
updateConfig(config: Partial<MediaViewerConfig>): void {
this.defaultConfig = {
...this.defaultConfig,
...config
};
}
/**
* Prepare item for PhotoSwipe
*/
private prepareItem(item: MediaItem): PhotoSwipeDataItem {
const prepared: PhotoSwipeDataItem = {
src: item.src,
alt: item.alt || '',
title: item.title
};
// If dimensions are provided, use them
if (item.width && item.height) {
prepared.width = item.width;
prepared.height = item.height;
} else {
// Default dimensions - will be updated when image loads
prepared.width = 0;
prepared.height = 0;
}
// Add thumbnail if provided
if (item.msrc) {
prepared.msrc = item.msrc;
}
// Store original item reference
prepared._originalItem = item;
return prepared;
}
/**
* Setup event handlers for PhotoSwipe
*/
private setupEventHandlers(): void {
if (!this.photoSwipe) return;
// Opening event
const openHandler = () => {
if (this.callbacks.onOpen) {
this.callbacks.onOpen();
}
};
this.photoSwipe.on('openingAnimationEnd', openHandler);
this.cleanupHandlers.push(() => this.photoSwipe?.off('openingAnimationEnd', openHandler));
// Closing event
const closeHandler = () => {
if (this.callbacks.onClose) {
this.callbacks.onClose();
}
};
this.photoSwipe.on('close', closeHandler);
this.cleanupHandlers.push(() => this.photoSwipe?.off('close', closeHandler));
// Change event
const changeHandler = () => {
if (this.callbacks.onChange && this.photoSwipe) {
this.callbacks.onChange(this.photoSwipe.currIndex);
}
};
this.photoSwipe.on('change', changeHandler);
this.cleanupHandlers.push(() => this.photoSwipe?.off('change', changeHandler));
// Image load event - also update dimensions if needed
const loadCompleteHandler = (e: any) => {
try {
const { content } = e;
const extContent = content as Content & { type?: string; data?: HTMLImageElement; index?: number; _originalItem?: MediaItem };
if (extContent.type === 'image' && extContent.data) {
// Update dimensions if they were not provided
if (content.width === 0 || content.height === 0) {
const img = extContent.data;
content.width = img.naturalWidth;
content.height = img.naturalHeight;
if (typeof extContent.index === 'number') {
this.photoSwipe?.refreshSlideContent(extContent.index);
}
}
if (this.callbacks.onImageLoad && typeof extContent.index === 'number' && extContent._originalItem) {
this.callbacks.onImageLoad(extContent.index, extContent._originalItem);
}
}
} catch (error) {
console.error('Error in loadComplete handler:', error);
}
};
this.photoSwipe.on('loadComplete', loadCompleteHandler);
this.cleanupHandlers.push(() => this.photoSwipe?.off('loadComplete', loadCompleteHandler));
// Image error event
const errorHandler = (e: any) => {
try {
const { content } = e;
const extContent = content as Content & { index?: number; _originalItem?: MediaItem };
if (this.callbacks.onImageError && typeof extContent.index === 'number' && extContent._originalItem) {
const error = new MediaViewerError(`Failed to load image at index ${extContent.index}`);
this.callbacks.onImageError(extContent.index, extContent._originalItem, error);
}
} catch (error) {
console.error('Error in errorHandler:', error);
}
};
this.photoSwipe.on('loadError', errorHandler);
this.cleanupHandlers.push(() => this.photoSwipe?.off('loadError', errorHandler));
}
/**
* Cleanup event handlers
*/
private cleanupEventHandlers(): void {
this.cleanupHandlers.forEach(handler => handler());
this.cleanupHandlers = [];
}
/**
* Destroy the service and cleanup resources
*/
destroy(): void {
this.close();
this.currentItems = [];
this.callbacks = {};
// Cleanup mobile and accessibility enhancements
mobileA11yService.cleanup();
}
/**
* Get dimensions from image element or URL with proper resource cleanup
*/
async getImageDimensions(src: string): Promise<{ width: number; height: number }> {
return new Promise((resolve, reject) => {
const img = new Image();
let resolved = false;
const cleanup = () => {
img.onload = null;
img.onerror = null;
// Clear the src to help with garbage collection
if (!resolved) {
img.src = '';
}
};
img.onload = () => {
resolved = true;
const dimensions = {
width: img.naturalWidth,
height: img.naturalHeight
};
cleanup();
resolve(dimensions);
};
img.onerror = () => {
const error = new MediaViewerError(`Failed to load image: ${src}`);
cleanup();
reject(error);
};
// Set a timeout for image loading
const timeoutId = setTimeout(() => {
if (!resolved) {
cleanup();
reject(new MediaViewerError(`Image loading timeout: ${src}`));
}
}, 30000); // 30 second timeout
img.src = src;
// Clear timeout on success or error
// Store the original handlers with timeout cleanup
const originalOnload = img.onload;
const originalOnerror = img.onerror;
img.onload = function(ev: Event) {
clearTimeout(timeoutId);
if (originalOnload) {
originalOnload.call(img, ev);
}
};
img.onerror = function(ev: Event | string) {
clearTimeout(timeoutId);
if (originalOnerror) {
originalOnerror.call(img, ev);
}
};
});
}
/**
* Create items from image elements in a container with error isolation
*/
async createItemsFromContainer(container: HTMLElement, selector: string = 'img'): Promise<MediaItem[]> {
const images = container.querySelectorAll<HTMLImageElement>(selector);
const items: MediaItem[] = [];
// Process each image with isolated error handling
const promises = Array.from(images).map(async (img) => {
try {
const item: MediaItem = {
src: img.src,
alt: img.alt || `Image ${items.length + 1}`,
title: img.title || img.alt || `Image ${items.length + 1}`,
element: img,
width: img.naturalWidth || undefined,
height: img.naturalHeight || undefined
};
// Try to get dimensions if not available
if (!item.width || !item.height) {
try {
const dimensions = await this.getImageDimensions(img.src);
item.width = dimensions.width;
item.height = dimensions.height;
} catch (error) {
// Log but don't fail - image will still be viewable
console.warn(`Failed to get dimensions for image: ${img.src}`, error);
// Set default dimensions as fallback
item.width = 800;
item.height = 600;
}
}
return item;
} catch (error) {
// Log error but continue processing other images
console.error(`Failed to process image: ${img.src}`, error);
return null;
}
});
// Wait for all promises and filter out nulls
const results = await Promise.allSettled(promises);
for (const result of results) {
if (result.status === 'fulfilled' && result.value !== null) {
items.push(result.value);
}
}
return items;
}
/**
* Apply theme-specific styles
*/
applyTheme(isDarkTheme: boolean): void {
// This will be expanded to modify PhotoSwipe's appearance based on Trilium's theme
const opacity = isDarkTheme ? 0.95 : 0.9;
this.updateConfig({ bgOpacity: opacity });
}
/**
* Check if mobile/accessibility enhancements should be auto-enabled
*/
private shouldAutoEnhance(): boolean {
// Auto-enable for touch devices
const isTouchDevice = 'ontouchstart' in window ||
navigator.maxTouchPoints > 0;
// Auto-enable if user has accessibility preferences
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const prefersHighContrast = window.matchMedia('(prefers-contrast: high)').matches;
return isTouchDevice || prefersReducedMotion || prefersHighContrast;
}
}
// Export singleton instance
export default MediaViewerService.getInstance();

View File

@@ -36,6 +36,8 @@ export interface Suggestion {
commandId?: string;
commandDescription?: string;
commandShortcut?: string;
attributeSnippet?: string;
highlightedAttributeSnippet?: string;
}
export interface Options {
@@ -323,7 +325,33 @@ function initNoteAutocomplete($el: JQuery<HTMLElement>, options?: Options) {
html += '</div>';
return html;
}
return `<span class="${suggestion.icon ?? "bx bx-note"}"></span> ${suggestion.highlightedNotePathTitle}`;
// Add special class for search-notes action
const actionClass = suggestion.action === "search-notes" ? "search-notes-action" : "";
// Choose appropriate icon based on action
let iconClass = suggestion.icon ?? "bx bx-note";
if (suggestion.action === "search-notes") {
iconClass = "bx bx-search";
} else if (suggestion.action === "create-note") {
iconClass = "bx bx-plus";
} else if (suggestion.action === "external-link") {
iconClass = "bx bx-link-external";
}
// Simplified HTML structure without nested divs
let html = `<div class="note-suggestion ${actionClass}">`;
html += `<span class="icon ${iconClass}"></span>`;
html += `<span class="text">`;
html += `<span class="search-result-title">${suggestion.highlightedNotePathTitle}</span>`;
// Add attribute snippet inline if available
if (suggestion.highlightedAttributeSnippet) {
html += `<span class="search-result-attributes">${suggestion.highlightedAttributeSnippet}</span>`;
}
html += `</span>`;
html += `</div>`;
return html;
}
},
// we can't cache identical searches because notes can be created / renamed, new recent notes can be added

View File

@@ -1,71 +0,0 @@
import type FNote from "../entities/fnote.js";
import BoardView from "../widgets/view_widgets/board_view/index.js";
import CalendarView from "../widgets/view_widgets/calendar_view.js";
import GeoView from "../widgets/view_widgets/geo_view/index.js";
import ListOrGridView from "../widgets/view_widgets/list_or_grid_view.js";
import TableView from "../widgets/view_widgets/table_view/index.js";
import type { ViewModeArgs } from "../widgets/view_widgets/view_mode.js";
import type ViewMode from "../widgets/view_widgets/view_mode.js";
const allViewTypes = ["list", "grid", "calendar", "table", "geoMap", "board"] as const;
export type ArgsWithoutNoteId = Omit<ViewModeArgs, "noteIds">;
export type ViewTypeOptions = typeof allViewTypes[number];
export default class NoteListRenderer {
private viewType: ViewTypeOptions;
private args: ArgsWithoutNoteId;
public viewMode?: ViewMode<any>;
constructor(args: ArgsWithoutNoteId) {
this.args = args;
this.viewType = this.#getViewType(args.parentNote);
}
#getViewType(parentNote: FNote): ViewTypeOptions {
const viewType = parentNote.getLabelValue("viewType");
if (!(allViewTypes as readonly string[]).includes(viewType || "")) {
// when not explicitly set, decide based on the note type
return parentNote.type === "search" ? "list" : "grid";
} else {
return viewType as ViewTypeOptions;
}
}
get isFullHeight() {
switch (this.viewType) {
case "list":
case "grid":
return false;
default:
return true;
}
}
async renderList() {
const args = this.args;
const viewMode = this.#buildViewMode(args);
this.viewMode = viewMode;
await viewMode.beforeRender();
return await viewMode.renderList();
}
#buildViewMode(args: ViewModeArgs) {
switch (this.viewType) {
case "calendar":
return new CalendarView(args);
case "table":
return new TableView(args);
case "geoMap":
return new GeoView(args);
case "board":
return new BoardView(args);
case "list":
case "grid":
default:
return new ListOrGridView(this.viewType, args);
}
}
}

View File

@@ -1,7 +1,7 @@
import { t } from "./i18n.js";
import froca from "./froca.js";
import server from "./server.js";
import type { MenuCommandItem, MenuItem, MenuItemBadge } from "../menus/context_menu.js";
import type { MenuCommandItem, MenuItem, MenuItemBadge, MenuSeparatorItem } from "../menus/context_menu.js";
import type { NoteType } from "../entities/fnote.js";
import type { TreeCommandNames } from "../menus/tree_context_menu.js";
@@ -73,7 +73,7 @@ const BETA_BADGE = {
title: t("note_types.beta-feature")
};
const SEPARATOR = { title: "----" };
const SEPARATOR: MenuSeparatorItem = { kind: "separator" };
const creationDateCache = new Map<string, Date>();
let rootCreationDate: Date | undefined;
@@ -81,8 +81,8 @@ let rootCreationDate: Date | undefined;
async function getNoteTypeItems(command?: TreeCommandNames) {
const items: MenuItem<TreeCommandNames>[] = [
...getBlankNoteTypes(command),
...await getBuiltInTemplates(t("note_types.collections"), command, true),
...await getBuiltInTemplates(null, command, false),
...await getBuiltInTemplates(t("note_types.collections"), command, true),
...await getUserTemplates(command)
];
@@ -121,7 +121,10 @@ async function getUserTemplates(command?: TreeCommandNames) {
}
const items: MenuItem<TreeCommandNames>[] = [
SEPARATOR
{
title: t("note_type_chooser.templates"),
kind: "header"
}
];
for (const templateNote of templateNotes) {
@@ -158,15 +161,15 @@ async function getBuiltInTemplates(title: string | null, command: TreeCommandNam
if (title) {
items.push({
title: title,
enabled: false,
uiIcon: "bx bx-empty"
kind: "header"
});
} else {
items.push(SEPARATOR);
}
for (const templateNote of childNotes) {
if (templateNote.hasLabel("collection") !== filterCollections) {
if (templateNote.hasLabel("collection") !== filterCollections ||
!templateNote.hasLabel("template")) {
continue;
}

View File

@@ -35,7 +35,7 @@ function download(url: string) {
}
}
function downloadFileNote(noteId: string) {
export function downloadFileNote(noteId: string) {
const url = `${getFileUrl("notes", noteId)}?${Date.now()}`; // don't use cache
download(url);
@@ -163,7 +163,7 @@ async function openExternally(type: string, entityId: string, mime: string) {
}
}
const openNoteExternally = async (noteId: string, mime: string) => await openExternally("notes", noteId, mime);
export const openNoteExternally = async (noteId: string, mime: string) => await openExternally("notes", noteId, mime);
const openAttachmentExternally = async (attachmentId: string, mime: string) => await openExternally("attachments", attachmentId, mime);
function getHost() {

Some files were not shown because too many files have changed in this diff Show More