Compare commits

...

184 Commits

Author SHA1 Message Date
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
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
441 changed files with 8963 additions and 4421 deletions

View File

@@ -1,6 +1,4 @@
# GitHub Actions workflow for deploying MkDocs documentation to Cloudflare Pages name: Deploy Documentation
# This workflow builds and deploys your MkDocs site when changes are pushed to main
name: Deploy MkDocs Documentation
on: on:
# Trigger on push to main branch # Trigger on push to main branch
@@ -11,11 +9,8 @@ on:
# Only run when docs files change # Only run when docs files change
paths: paths:
- 'docs/**' - 'docs/**'
- 'README.md' # README is synced to docs/index.md - 'apps/edit-docs/**'
- 'mkdocs.yml' - 'packages/share-theme/**'
- 'requirements-docs.txt'
- '.github/workflows/deploy-docs.yml'
- 'scripts/fix-mkdocs-structure.ts'
# Allow manual triggering from Actions tab # Allow manual triggering from Actions tab
workflow_dispatch: workflow_dispatch:
@@ -27,15 +22,12 @@ on:
- master - master
paths: paths:
- 'docs/**' - 'docs/**'
- 'README.md' # README is synced to docs/index.md - 'apps/edit-docs/**'
- 'mkdocs.yml' - 'packages/share-theme/**'
- 'requirements-docs.txt'
- '.github/workflows/deploy-docs.yml'
- 'scripts/fix-mkdocs-structure.ts'
jobs: jobs:
build-and-deploy: build-and-deploy:
name: Build and Deploy MkDocs name: Build and Deploy Documentation
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 10 timeout-minutes: 10
@@ -49,72 +41,25 @@ jobs:
steps: steps:
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v5 uses: actions/checkout@v5
with:
fetch-depth: 0 # Fetch all history for git info and mkdocs-git-revision-date plugin
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: '3.14'
cache: 'pip'
cache-dependency-path: 'requirements-docs.txt'
- name: Install MkDocs and Dependencies
run: |
pip install --upgrade pip
pip install -r requirements-docs.txt
env:
PIP_DISABLE_PIP_VERSION_CHECK: 1
# Setup pnpm before fixing docs structure
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4
# Setup Node.js with pnpm
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v6 uses: actions/setup-node@v6
with: with:
node-version: '24' node-version: '24'
cache: 'pnpm' cache: 'pnpm'
# Install Node.js dependencies for the TypeScript script
- name: Install Dependencies - name: Install Dependencies
run: | run: pnpm install --frozen-lockfile
pnpm install --frozen-lockfile
- name: Fix Documentation Structure - name: Trigger build of documentation
run: | run: pnpm docs:build
# Fix duplicate navigation entries by moving overview pages to index.md
pnpm run chore:fix-mkdocs-structure
- name: Build MkDocs Site
run: |
# Build with strict mode but allow expected warnings
mkdocs build --verbose || {
EXIT_CODE=$?
# Check if the only issue is expected warnings
if mkdocs build 2>&1 | grep -E "WARNING.*(README|not found)" && \
[ $(mkdocs build 2>&1 | grep -c "ERROR") -eq 0 ]; then
echo "✅ Build succeeded with expected warnings"
mkdocs build --verbose
else
echo "❌ Build failed with unexpected errors"
exit $EXIT_CODE
fi
}
- name: Fix HTML Links
run: |
# Remove .md extensions from links in generated HTML
pnpm tsx ./scripts/fix-html-links.ts site
- name: Validate Built Site - name: Validate Built Site
run: | run: |
# Basic validation that important files exist
test -f site/index.html || (echo "ERROR: site/index.html not found" && exit 1) test -f site/index.html || (echo "ERROR: site/index.html not found" && exit 1)
test -f site/sitemap.xml || (echo "ERROR: site/sitemap.xml not found" && exit 1)
test -d site/assets || (echo "ERROR: site/assets directory not found" && exit 1)
echo "✅ Site validation passed"
- name: Deploy - name: Deploy
uses: ./.github/actions/deploy-to-cloudflare-pages uses: ./.github/actions/deploy-to-cloudflare-pages

View File

@@ -116,10 +116,10 @@ jobs:
- dockerfile: Dockerfile - dockerfile: Dockerfile
platform: linux/arm64 platform: linux/arm64
image: ubuntu-24.04-arm image: ubuntu-24.04-arm
- dockerfile: Dockerfile - dockerfile: Dockerfile.legacy
platform: linux/arm/v7 platform: linux/arm/v7
image: ubuntu-24.04-arm image: ubuntu-24.04-arm
- dockerfile: Dockerfile - dockerfile: Dockerfile.legacy
platform: linux/arm/v8 platform: linux/arm/v8
image: ubuntu-24.04-arm image: ubuntu-24.04-arm
runs-on: ${{ matrix.image }} runs-on: ${{ matrix.image }}

2
.nvmrc
View File

@@ -1 +1 @@
22.21.0 24.11.0

View File

@@ -38,19 +38,17 @@
"@playwright/test": "1.56.1", "@playwright/test": "1.56.1",
"@stylistic/eslint-plugin": "5.5.0", "@stylistic/eslint-plugin": "5.5.0",
"@types/express": "5.0.5", "@types/express": "5.0.5",
"@types/node": "24.9.1", "@types/node": "24.9.2",
"@types/yargs": "17.0.34", "@types/yargs": "17.0.34",
"@vitest/coverage-v8": "3.2.4", "@vitest/coverage-v8": "3.2.4",
"eslint": "9.38.0", "eslint": "9.39.0",
"eslint-plugin-simple-import-sort": "12.1.1", "eslint-plugin-simple-import-sort": "12.1.1",
"esm": "3.2.25", "esm": "3.2.25",
"jsdoc": "4.0.5", "jsdoc": "4.0.5",
"lorem-ipsum": "2.0.8", "lorem-ipsum": "2.0.8",
"rcedit": "4.0.1", "rcedit": "4.0.1",
"rimraf": "6.0.1", "rimraf": "6.1.0",
"tslib": "2.8.1", "tslib": "2.8.1"
"typedoc": "0.28.14",
"typedoc-plugin-missing-exports": "4.1.2"
}, },
"optionalDependencies": { "optionalDependencies": {
"appdmg": "0.6.6" "appdmg": "0.6.6"

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.19.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,127 @@
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 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);
const note = await importData(join(__dirname, DOCS_ROOT, "User Guide"));
// Export
const zipFilePath = "output.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);
await extractZip(zipFilePath, OUTPUT_DIR);
} finally {
if (await fsExtra.exists(zipFilePath)) {
await fsExtra.rm(zipFilePath);
}
}
// 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("@triliumnext/server/src/services/import/zip.js")).default;
const TaskContext = (await import("@triliumnext/server/src/services/task_context.js")).default;
const context = new TaskContext("no-progress-reporting", "importNotes", null);
const becca = (await import("@triliumnext/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

@@ -15,7 +15,7 @@
"circular-deps": "dpdm -T src/**/*.ts --tree=false --warning=false --skip-dynamic-imports=circular" "circular-deps": "dpdm -T src/**/*.ts --tree=false --warning=false --skip-dynamic-imports=circular"
}, },
"dependencies": { "dependencies": {
"@eslint/js": "9.38.0", "@eslint/js": "9.39.0",
"@excalidraw/excalidraw": "0.18.0", "@excalidraw/excalidraw": "0.18.0",
"@fullcalendar/core": "6.1.19", "@fullcalendar/core": "6.1.19",
"@fullcalendar/daygrid": "6.1.19", "@fullcalendar/daygrid": "6.1.19",
@@ -37,12 +37,12 @@
"bootstrap": "5.3.8", "bootstrap": "5.3.8",
"boxicons": "2.1.4", "boxicons": "2.1.4",
"color": "5.0.2", "color": "5.0.2",
"dayjs": "1.11.18", "dayjs": "1.11.19",
"dayjs-plugin-utc": "0.1.2", "dayjs-plugin-utc": "0.1.2",
"debounce": "2.2.0", "debounce": "2.2.0",
"draggabilly": "3.0.0", "draggabilly": "3.0.0",
"force-graph": "1.51.0", "force-graph": "1.51.0",
"globals": "16.4.0", "globals": "16.5.0",
"i18next": "25.6.0", "i18next": "25.6.0",
"i18next-http-backend": "3.0.2", "i18next-http-backend": "3.0.2",
"jquery": "3.7.1", "jquery": "3.7.1",
@@ -59,7 +59,7 @@
"normalize.css": "8.0.1", "normalize.css": "8.0.1",
"panzoom": "9.4.3", "panzoom": "9.4.3",
"preact": "10.27.2", "preact": "10.27.2",
"react-i18next": "16.2.1", "react-i18next": "16.2.3",
"reveal.js": "5.2.1", "reveal.js": "5.2.1",
"svg-pan-zoom": "3.6.2", "svg-pan-zoom": "3.6.2",
"tabulator-tables": "6.3.1", "tabulator-tables": "6.3.1",
@@ -76,7 +76,7 @@
"@types/reveal.js": "5.2.1", "@types/reveal.js": "5.2.1",
"@types/tabulator-tables": "6.3.0", "@types/tabulator-tables": "6.3.0",
"copy-webpack-plugin": "13.0.1", "copy-webpack-plugin": "13.0.1",
"happy-dom": "20.0.8", "happy-dom": "20.0.10",
"script-loader": "0.7.2", "script-loader": "0.7.2",
"vite-plugin-static-copy": "3.1.4" "vite-plugin-static-copy": "3.1.4"
} }

View File

@@ -270,6 +270,7 @@ export type CommandMappings = {
closeThisNoteSplit: CommandData; closeThisNoteSplit: CommandData;
moveThisNoteSplit: CommandData & { isMovingLeft: boolean }; moveThisNoteSplit: CommandData & { isMovingLeft: boolean };
jumpToNote: CommandData; jumpToNote: CommandData;
openTodayNote: CommandData;
commandPalette: CommandData; commandPalette: CommandData;
// Keyboard shortcuts // Keyboard shortcuts

View File

@@ -159,6 +159,16 @@ export default class Entrypoints extends Component {
this.openInWindowCommand({ notePath: "", hoistedNoteId: "root" }); 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() { async runActiveNoteCommand() {
const noteContext = appContext.tabManager.getActiveContext(); const noteContext = appContext.tabManager.getActiveContext();
if (!noteContext) { if (!noteContext) {

View File

@@ -417,7 +417,7 @@ export default class FNote {
return notePaths; return notePaths;
} }
getSortedNotePathRecords(hoistedNoteId = "root"): NotePathRecord[] { getSortedNotePathRecords(hoistedNoteId = "root", activeNotePath: string | null = null): NotePathRecord[] {
const isHoistedRoot = hoistedNoteId === "root"; const isHoistedRoot = hoistedNoteId === "root";
const notePaths: NotePathRecord[] = this.getAllNotePaths().map((path) => ({ const notePaths: NotePathRecord[] = this.getAllNotePaths().map((path) => ({
@@ -428,7 +428,23 @@ export default class FNote {
isHidden: path.includes("_hidden") 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) => { 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) { if (a.isInHoistedSubTree !== b.isInHoistedSubTree) {
return a.isInHoistedSubTree ? -1 : 1; return a.isInHoistedSubTree ? -1 : 1;
} else if (a.isArchived !== b.isArchived) { } else if (a.isArchived !== b.isArchived) {
@@ -449,10 +465,11 @@ export default class FNote {
* Returns the note path considered to be the "best" * Returns the note path considered to be the "best"
* *
* @param {string} [hoistedNoteId='root'] * @param {string} [hoistedNoteId='root']
* @param {string|null} [activeNotePath=null]
* @return {string[]} array of noteIds constituting the particular note path * @return {string[]} array of noteIds constituting the particular note path
*/ */
getBestNotePath(hoistedNoteId = "root") { getBestNotePath(hoistedNoteId = "root", activeNotePath: string | null = null) {
return this.getSortedNotePathRecords(hoistedNoteId)[0]?.notePath; return this.getSortedNotePathRecords(hoistedNoteId, activeNotePath)[0]?.notePath;
} }
/** /**

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

@@ -10,7 +10,7 @@ export const byNoteType: Record<Exclude<NoteType, "book">, string | null> = {
file: null, file: null,
image: null, image: null,
launcher: null, launcher: null,
mermaid: null, mermaid: "s1aBHPd79XYj",
mindMap: null, mindMap: null,
noteMap: null, noteMap: null,
relationMap: null, relationMap: null,

View File

@@ -26,21 +26,12 @@ async function resolveNotePathToSegments(notePath: string, hoistedNoteId = "root
} }
const path = notePath.split("/").reverse(); const path = notePath.split("/").reverse();
if (!path.includes("root")) {
path.push("root");
}
const effectivePathSegments: string[] = []; const effectivePathSegments: string[] = [];
let childNoteId: string | null = null; let childNoteId: string | null = null;
let i = 0; let i = 0;
while (true) { for (let i = 0; i < path.length; i++) {
if (i >= path.length) { const parentNoteId = path[i];
break;
}
const parentNoteId = path[i++];
if (childNoteId !== null) { if (childNoteId !== null) {
const child = await froca.getNote(childNoteId, !logErrors); const child = await froca.getNote(childNoteId, !logErrors);
@@ -65,7 +56,7 @@ async function resolveNotePathToSegments(notePath: string, hoistedNoteId = "root
return null; return null;
} }
if (!parents.some((p) => p.noteId === parentNoteId)) { if (!parents.some(p => p.noteId === parentNoteId) || (i === path.length - 1 && parentNoteId !== 'root')) {
if (logErrors) { if (logErrors) {
const parent = froca.getNoteFromCache(parentNoteId); const parent = froca.getNoteFromCache(parentNoteId);
@@ -77,7 +68,8 @@ async function resolveNotePathToSegments(notePath: string, hoistedNoteId = "root
); );
} }
const bestNotePath = child.getBestNotePath(hoistedNoteId); const activeNotePath = appContext.tabManager.getActiveContextNotePath();
const bestNotePath = child.getBestNotePath(hoistedNoteId, activeNotePath);
if (bestNotePath) { if (bestNotePath) {
const pathToRoot = bestNotePath.reverse().slice(1); const pathToRoot = bestNotePath.reverse().slice(1);
@@ -108,7 +100,9 @@ async function resolveNotePathToSegments(notePath: string, hoistedNoteId = "root
if (!note) { if (!note) {
throw new Error(`Unable to find note: ${notePath}.`); throw new Error(`Unable to find note: ${notePath}.`);
} }
const bestNotePath = note.getBestNotePath(hoistedNoteId);
const activeNotePath = appContext.tabManager.getActiveContextNotePath();
const bestNotePath = note.getBestNotePath(hoistedNoteId, activeNotePath);
if (!bestNotePath) { if (!bestNotePath) {
throw new Error(`Did not find any path segments for '${note.toString()}', hoisted note '${hoistedNoteId}'`); throw new Error(`Did not find any path segments for '${note.toString()}', hoisted note '${hoistedNoteId}'`);

View File

@@ -11,7 +11,11 @@ export function reloadFrontendApp(reason?: string) {
logInfo(`Frontend app reload: ${reason}`); logInfo(`Frontend app reload: ${reason}`);
} }
window.location.reload(); if (isElectron()) {
dynamicRequire("@electron/remote").BrowserWindow.getFocusedWindow()?.reload();
} else {
window.location.reload();
}
} }
export function restartDesktopApp() { export function restartDesktopApp() {

View File

@@ -1,24 +0,0 @@
import "normalize.css";
import "boxicons/css/boxicons.min.css";
import "@triliumnext/ckeditor5/src/theme/ck-content.css";
import "@triliumnext/share-theme/styles/index.css";
import "@triliumnext/share-theme/scripts/index.js";
async function ensureJQuery() {
const $ = (await import("jquery")).default;
(window as any).$ = $;
}
async function formatCodeBlocks() {
const anyCodeBlock = document.querySelector("#content pre");
if (!anyCodeBlock) {
return;
}
await ensureJQuery();
const { formatCodeBlocks } = await import("./services/syntax_highlight.js");
await formatCodeBlocks($("#content"));
}
async function setupTextNote() {
formatCodeBlocks();
}

View File

@@ -716,7 +716,6 @@
"backup_database_now": "نسخ اختياطي لقاعدة البيانات الان" "backup_database_now": "نسخ اختياطي لقاعدة البيانات الان"
}, },
"etapi": { "etapi": {
"wiki": "ويكي",
"created": "تم الأنشاء", "created": "تم الأنشاء",
"actions": "أجراءات", "actions": "أجراءات",
"title": "ETAPI", "title": "ETAPI",

View File

@@ -51,7 +51,7 @@
"bulk_actions_executed": "批量操作已成功执行。", "bulk_actions_executed": "批量操作已成功执行。",
"none_yet": "暂无操作 ... 通过点击上方的可用操作添加一个操作。", "none_yet": "暂无操作 ... 通过点击上方的可用操作添加一个操作。",
"labels": "标签", "labels": "标签",
"relations": "关联关系", "relations": "关系",
"notes": "笔记", "notes": "笔记",
"other": "其它" "other": "其它"
}, },
@@ -104,7 +104,8 @@
"export_status": "导出状态", "export_status": "导出状态",
"export_in_progress": "导出进行中:{{progressCount}}", "export_in_progress": "导出进行中:{{progressCount}}",
"export_finished_successfully": "导出成功完成。", "export_finished_successfully": "导出成功完成。",
"format_pdf": "PDF - 用于打印或共享目的。" "format_pdf": "PDF - 用于打印或共享目的。",
"share-format": "HTML 网页发布——采用与共享笔记相同的主题,但可发布为静态网站。"
}, },
"help": { "help": {
"noteNavigation": "笔记导航", "noteNavigation": "笔记导航",
@@ -184,7 +185,8 @@
}, },
"import-status": "导入状态", "import-status": "导入状态",
"in-progress": "导入进行中:{{progress}}", "in-progress": "导入进行中:{{progress}}",
"successful": "导入成功完成。" "successful": "导入成功完成。",
"importZipRecommendation": "导入 ZIP 文件时,笔记层级将反映压缩文件内的子目录结构。"
}, },
"include_note": { "include_note": {
"dialog_title": "包含笔记", "dialog_title": "包含笔记",
@@ -1287,10 +1289,6 @@
"etapi": { "etapi": {
"title": "ETAPI", "title": "ETAPI",
"description": "ETAPI 是一个 REST API用于以编程方式访问 Trilium 实例,而无需 UI。", "description": "ETAPI 是一个 REST API用于以编程方式访问 Trilium 实例,而无需 UI。",
"see_more": "有关更多详细信息,请参见 {{- link_to_wiki}} 和 {{- link_to_openapi_spec}} 或 {{- link_to_swagger_ui}}。",
"wiki": "维基",
"openapi_spec": "ETAPI OpenAPI 规范",
"swagger_ui": "ETAPI Swagger UI",
"create_token": "创建新的 ETAPI 令牌", "create_token": "创建新的 ETAPI 令牌",
"existing_tokens": "现有令牌", "existing_tokens": "现有令牌",
"no_tokens_yet": "目前还没有令牌。点击上面的按钮创建一个。", "no_tokens_yet": "目前还没有令牌。点击上面的按钮创建一个。",
@@ -1557,7 +1555,9 @@
"window-on-top": "保持此窗口置顶" "window-on-top": "保持此窗口置顶"
}, },
"note_detail": { "note_detail": {
"could_not_find_typewidget": "找不到类型为 '{{type}}' 的 typeWidget" "could_not_find_typewidget": "找不到类型为 '{{type}}' 的 typeWidget",
"printing": "正在打印…",
"printing_pdf": "正在导出为PDF…"
}, },
"note_title": { "note_title": {
"placeholder": "请输入笔记标题..." "placeholder": "请输入笔记标题..."

View File

@@ -104,7 +104,8 @@
"export_status": "Exportstatus", "export_status": "Exportstatus",
"export_in_progress": "Export läuft: {{progressCount}}", "export_in_progress": "Export läuft: {{progressCount}}",
"export_finished_successfully": "Der Export wurde erfolgreich abgeschlossen.", "export_finished_successfully": "Der Export wurde erfolgreich abgeschlossen.",
"format_pdf": "PDF - für Ausdrucke oder Teilen." "format_pdf": "PDF - für Ausdrucke oder Teilen.",
"share-format": "HTML für die Web-Veröffentlichung verwendet dasselbe Theme wie bei freigegebenen Notizen, kann jedoch als statische Website veröffentlicht werden."
}, },
"help": { "help": {
"noteNavigation": "Notiz Navigation", "noteNavigation": "Notiz Navigation",
@@ -1285,10 +1286,6 @@
"etapi": { "etapi": {
"title": "ETAPI", "title": "ETAPI",
"description": "ETAPI ist eine REST-API, die für den programmgesteuerten Zugriff auf die Trilium-Instanz ohne Benutzeroberfläche verwendet wird.", "description": "ETAPI ist eine REST-API, die für den programmgesteuerten Zugriff auf die Trilium-Instanz ohne Benutzeroberfläche verwendet wird.",
"see_more": "Weitere Details können im {{- link_to_wiki}} und in der {{- link_to_openapi_spec}} oder der {{- link_to_swagger_ui }} gefunden werden.",
"wiki": "Wiki",
"openapi_spec": "ETAPI OpenAPI-Spezifikation",
"swagger_ui": "ETAPI Swagger UI",
"create_token": "Erstelle ein neues ETAPI-Token", "create_token": "Erstelle ein neues ETAPI-Token",
"existing_tokens": "Vorhandene Token", "existing_tokens": "Vorhandene Token",
"no_tokens_yet": "Es sind noch keine Token vorhanden. Klicke auf die Schaltfläche oben, um eine zu erstellen.", "no_tokens_yet": "Es sind noch keine Token vorhanden. Klicke auf die Schaltfläche oben, um eine zu erstellen.",

View File

@@ -1453,10 +1453,6 @@
"etapi": { "etapi": {
"title": "ETAPI", "title": "ETAPI",
"description": "ETAPI is a REST API used to access Trilium instance programmatically, without UI.", "description": "ETAPI is a REST API used to access Trilium instance programmatically, without UI.",
"see_more": "See more details in the {{- link_to_wiki}} and the {{- link_to_openapi_spec}} or the {{- link_to_swagger_ui }}.",
"wiki": "wiki",
"openapi_spec": "ETAPI OpenAPI spec",
"swagger_ui": "ETAPI Swagger UI",
"create_token": "Create new ETAPI token", "create_token": "Create new ETAPI token",
"existing_tokens": "Existing tokens", "existing_tokens": "Existing tokens",
"no_tokens_yet": "There are no tokens yet. Click on the button above to create one.", "no_tokens_yet": "There are no tokens yet. Click on the button above to create one.",

View File

@@ -104,7 +104,8 @@
"export_status": "Estado de exportación", "export_status": "Estado de exportación",
"export_in_progress": "Exportación en curso: {{progressCount}}", "export_in_progress": "Exportación en curso: {{progressCount}}",
"export_finished_successfully": "La exportación finalizó exitosamente.", "export_finished_successfully": "La exportación finalizó exitosamente.",
"format_pdf": "PDF - para propósitos de impresión o compartición." "format_pdf": "PDF - para propósitos de impresión o compartición.",
"share-format": "HTML para publicación web: utiliza el mismo tema que se utiliza en las notas compartidas, pero se puede publicar como un sitio web estático."
}, },
"help": { "help": {
"noteNavigation": "Navegación de notas", "noteNavigation": "Navegación de notas",
@@ -184,7 +185,8 @@
}, },
"import-status": "Estado de importación", "import-status": "Estado de importación",
"in-progress": "Importación en progreso: {{progress}}", "in-progress": "Importación en progreso: {{progress}}",
"successful": "Importación finalizada exitosamente." "successful": "Importación finalizada exitosamente.",
"importZipRecommendation": "Al importar un archivo ZIP, la jerarquía de notas reflejará la estructura de subdirectorios dentro del archivo comprimido."
}, },
"include_note": { "include_note": {
"dialog_title": "Incluir nota", "dialog_title": "Incluir nota",
@@ -1444,10 +1446,6 @@
"etapi": { "etapi": {
"title": "ETAPI", "title": "ETAPI",
"description": "ETAPI es una REST API que se utiliza para acceder a la instancia de Trilium mediante programación, sin interfaz de usuario.", "description": "ETAPI es una REST API que se utiliza para acceder a la instancia de Trilium mediante programación, sin interfaz de usuario.",
"see_more": "Véa más detalles en el {{- link_to_wiki}} y el {{- link_to_openapi_spec}} o el {{- link_to_swagger_ui }}.",
"wiki": "wiki",
"openapi_spec": "Especificación ETAPI OpenAPI",
"swagger_ui": "ETAPI Swagger UI",
"create_token": "Crear nuevo token ETAPI", "create_token": "Crear nuevo token ETAPI",
"existing_tokens": "Tokens existentes", "existing_tokens": "Tokens existentes",
"no_tokens_yet": "Aún no hay tokens. Dé clic en el botón de arriba para crear uno.", "no_tokens_yet": "Aún no hay tokens. Dé clic en el botón de arriba para crear uno.",
@@ -1714,7 +1712,9 @@
"window-on-top": "Mantener esta ventana en la parte superior" "window-on-top": "Mantener esta ventana en la parte superior"
}, },
"note_detail": { "note_detail": {
"could_not_find_typewidget": "No se pudo encontrar typeWidget para el tipo '{{type}}'" "could_not_find_typewidget": "No se pudo encontrar typeWidget para el tipo '{{type}}'",
"printing": "Impresión en curso...",
"printing_pdf": "Exportando a PDF en curso.."
}, },
"note_title": { "note_title": {
"placeholder": "escriba el título de la nota aquí..." "placeholder": "escriba el título de la nota aquí..."

View File

@@ -1288,8 +1288,6 @@
"etapi": { "etapi": {
"title": "ETAPI", "title": "ETAPI",
"description": "ETAPI est une API REST utilisée pour accéder à l'instance Trilium par programme, sans interface utilisateur.", "description": "ETAPI est une API REST utilisée pour accéder à l'instance Trilium par programme, sans interface utilisateur.",
"wiki": "wiki",
"openapi_spec": "Spec ETAPI OpenAPI",
"create_token": "Créer un nouveau jeton ETAPI", "create_token": "Créer un nouveau jeton ETAPI",
"existing_tokens": "Jetons existants", "existing_tokens": "Jetons existants",
"no_tokens_yet": "Il n'y a pas encore de jetons. Cliquez sur le bouton ci-dessus pour en créer un.", "no_tokens_yet": "Il n'y a pas encore de jetons. Cliquez sur le bouton ci-dessus pour en créer un.",
@@ -1306,9 +1304,7 @@
"delete_token": "Supprimer/désactiver ce token", "delete_token": "Supprimer/désactiver ce token",
"rename_token_title": "Renommer le jeton", "rename_token_title": "Renommer le jeton",
"rename_token_message": "Veuillez saisir le nom du nouveau jeton", "rename_token_message": "Veuillez saisir le nom du nouveau jeton",
"delete_token_confirmation": "Êtes-vous sûr de vouloir supprimer le jeton ETAPI « {{name}} » ?", "delete_token_confirmation": "Êtes-vous sûr de vouloir supprimer le jeton ETAPI « {{name}} » ?"
"see_more": "Voir plus de détails dans le {{- link_to_wiki}} et le {{- link_to_openapi_spec}} ou le {{- link_to_swagger_ui }}.",
"swagger_ui": "Interface utilisateur ETAPI Swagger"
}, },
"options_widget": { "options_widget": {
"options_status": "Statut des options", "options_status": "Statut des options",

View File

@@ -132,10 +132,6 @@
"new_token_message": "Inserisci il nome del nuovo token", "new_token_message": "Inserisci il nome del nuovo token",
"title": "ETAPI", "title": "ETAPI",
"description": "ETAPI è un'API REST utilizzata per accedere alle istanze di Trilium in modo programmatico, senza interfaccia utente.", "description": "ETAPI è un'API REST utilizzata per accedere alle istanze di Trilium in modo programmatico, senza interfaccia utente.",
"see_more": "Per maggiori dettagli consulta {{- link_to_wiki}} e {{- link_to_openapi_spec}} o {{- link_to_swagger_ui}}.",
"wiki": "wiki",
"openapi_spec": "Specifiche ETAPI OpenAPI",
"swagger_ui": "Interfaccia utente ETAPI Swagger",
"create_token": "Crea un nuovo token ETAPI", "create_token": "Crea un nuovo token ETAPI",
"existing_tokens": "Token esistenti", "existing_tokens": "Token esistenti",
"no_tokens_yet": "Non ci sono ancora token. Clicca sul pulsante qui sopra per crearne uno.", "no_tokens_yet": "Non ci sono ancora token. Clicca sul pulsante qui sopra per crearne uno.",

View File

@@ -254,7 +254,8 @@
"export_status": "エクスポート状況", "export_status": "エクスポート状況",
"export_in_progress": "エクスポート処理中: {{progressCount}}", "export_in_progress": "エクスポート処理中: {{progressCount}}",
"export_finished_successfully": "エクスポートが正常に完了しました。", "export_finished_successfully": "エクスポートが正常に完了しました。",
"format_pdf": "PDF - 印刷または共有目的に。" "format_pdf": "PDF - 印刷または共有目的に。",
"share-format": "Web 公開用の HTML - 共有ノートで使用されるのと同じテーマを使用しますが、静的 Web サイトとして公開できます。"
}, },
"help": { "help": {
"title": "チートシート", "title": "チートシート",
@@ -656,10 +657,6 @@
"created": "作成日時", "created": "作成日時",
"title": "ETAPI", "title": "ETAPI",
"description": "ETAPI は、Trilium インスタンスに UI なしでプログラム的にアクセスするための REST API です。", "description": "ETAPI は、Trilium インスタンスに UI なしでプログラム的にアクセスするための REST API です。",
"see_more": "詳細は{{- link_to_wiki}}と{{- link_to_openapi_spec}}または{{- link_to_swagger_ui }}を参照してください。",
"wiki": "wiki",
"openapi_spec": "ETAPI OpenAPIの仕様",
"swagger_ui": "ETAPI Swagger UI",
"create_token": "新しくETAPIトークンを作成", "create_token": "新しくETAPIトークンを作成",
"existing_tokens": "既存のトークン", "existing_tokens": "既存のトークン",
"no_tokens_yet": "トークンはまだありません。上のボタンをクリックして作成してください。", "no_tokens_yet": "トークンはまだありません。上のボタンをクリックして作成してください。",

View File

@@ -1663,10 +1663,6 @@
"etapi": { "etapi": {
"title": "ETAPI", "title": "ETAPI",
"description": "ETAPI to interfejs API REST używany do programowego dostępu do instancji Trilium, bez interfejsu użytkownika.", "description": "ETAPI to interfejs API REST używany do programowego dostępu do instancji Trilium, bez interfejsu użytkownika.",
"see_more": "Zobacz więcej szczegółów w {{- link_to_wiki}} oraz w {{- link_to_openapi_spec}} lub {{- link_to_swagger_ui }}.",
"wiki": "wiki",
"openapi_spec": "specyfikacja ETAPI OpenAPI",
"swagger_ui": "ETAPI Swagger UI",
"create_token": "Utwórz nowy token ETAPI", "create_token": "Utwórz nowy token ETAPI",
"existing_tokens": "Istniejące tokeny", "existing_tokens": "Istniejące tokeny",
"no_tokens_yet": "Nie ma jeszcze żadnych tokenów. Kliknij przycisk powyżej, aby utworzyć jeden.", "no_tokens_yet": "Nie ma jeszcze żadnych tokenów. Kliknij przycisk powyżej, aby utworzyć jeden.",

View File

@@ -1422,10 +1422,6 @@
"etapi": { "etapi": {
"title": "ETAPI", "title": "ETAPI",
"description": "ETAPI é uma API REST usada para aceder a instância do Trilium programaticamente, sem interface gráfica.", "description": "ETAPI é uma API REST usada para aceder a instância do Trilium programaticamente, sem interface gráfica.",
"see_more": "Veja mais pormenores no {{- link_to_wiki}}, na {{- link_to_openapi_spec}} ou na {{- link_to_swagger_ui}}.",
"wiki": "wiki",
"openapi_spec": "Especificação OpenAPI do ETAPI",
"swagger_ui": "ETAPI Swagger UI",
"create_token": "Criar token ETAPI", "create_token": "Criar token ETAPI",
"existing_tokens": "Tokens existentes", "existing_tokens": "Tokens existentes",
"no_tokens_yet": "Ainda não existem tokens. Clique no botão acima para criar um.", "no_tokens_yet": "Ainda não existem tokens. Clique no botão acima para criar um.",

View File

@@ -1932,10 +1932,6 @@
"etapi": { "etapi": {
"title": "ETAPI", "title": "ETAPI",
"description": "ETAPI é uma API REST usada para acessar a instância do Trilium programaticamente, sem interface gráfica.", "description": "ETAPI é uma API REST usada para acessar a instância do Trilium programaticamente, sem interface gráfica.",
"see_more": "Veja mais detalhes no {{- link_to_wiki}}, na {{- link_to_openapi_spec}} ou na {{- link_to_swagger_ui}}.",
"wiki": "wiki",
"openapi_spec": "Especificação OpenAPI do ETAPI",
"swagger_ui": "ETAPI Swagger UI",
"create_token": "Criar novo token ETAPI", "create_token": "Criar novo token ETAPI",
"existing_tokens": "Tokens existentes", "existing_tokens": "Tokens existentes",
"no_tokens_yet": "Ainda não existem tokens. Clique no botão acima para criar um.", "no_tokens_yet": "Ainda não existem tokens. Clique no botão acima para criar um.",

View File

@@ -507,17 +507,13 @@
"new_token_message": "Introduceți denumirea noului token", "new_token_message": "Introduceți denumirea noului token",
"new_token_title": "Token ETAPI nou", "new_token_title": "Token ETAPI nou",
"no_tokens_yet": "Nu există încă token-uri. Clic pe butonul de deasupra pentru a crea una.", "no_tokens_yet": "Nu există încă token-uri. Clic pe butonul de deasupra pentru a crea una.",
"openapi_spec": "Specificația OpenAPI pentru ETAPI",
"swagger_ui": "UI-ul Swagger pentru ETAPI",
"rename_token": "Redenumește token-ul", "rename_token": "Redenumește token-ul",
"rename_token_message": "Introduceți denumirea noului token", "rename_token_message": "Introduceți denumirea noului token",
"rename_token_title": "Redenumire token", "rename_token_title": "Redenumire token",
"see_more": "Vedeți mai multe detalii în {{- link_to_wiki}} și în {{- link_to_openapi_spec}} sau în {{- link_to_swagger_ui }}.",
"title": "ETAPI", "title": "ETAPI",
"token_created_message": "Copiați token-ul creat în clipboard. Trilium stochează token-ul ca hash așadar această valoare poate fi văzută doar acum.", "token_created_message": "Copiați token-ul creat în clipboard. Trilium stochează token-ul ca hash așadar această valoare poate fi văzută doar acum.",
"token_created_title": "Token ETAPI creat", "token_created_title": "Token ETAPI creat",
"token_name": "Denumire token", "token_name": "Denumire token"
"wiki": "wiki"
}, },
"execute_script": { "execute_script": {
"example_1": "De exemplu, pentru a adăuga un șir de caractere la titlul unei notițe, se poate folosi acest mic script:", "example_1": "De exemplu, pentru a adăuga un șir de caractere la titlul unei notițe, se poate folosi acest mic script:",

View File

@@ -1440,7 +1440,6 @@
}, },
"etapi": { "etapi": {
"title": "ETAPI", "title": "ETAPI",
"wiki": "вики",
"created": "Создано", "created": "Создано",
"actions": "Действия", "actions": "Действия",
"existing_tokens": "Существующие токены", "existing_tokens": "Существующие токены",
@@ -1448,10 +1447,7 @@
"default_token_name": "новый токен", "default_token_name": "новый токен",
"rename_token_title": "Переименовать токен", "rename_token_title": "Переименовать токен",
"description": "ETAPI — это REST API, используемый для программного доступа к экземпляру Trilium без пользовательского интерфейса.", "description": "ETAPI — это REST API, используемый для программного доступа к экземпляру Trilium без пользовательского интерфейса.",
"see_more": "Более подробную информацию смотрите в {{- link_to_wiki}} и {{- link_to_openapi_spec}} или {{- link_to_swagger_ui }}.",
"create_token": "Создать новый токен ETAPI", "create_token": "Создать новый токен ETAPI",
"openapi_spec": "Спецификация ETAPI OpenAPI",
"swagger_ui": "Пользовательский интерфейс ETAPI Swagger",
"new_token_title": "Новый токен ETAPI", "new_token_title": "Новый токен ETAPI",
"token_created_title": "Создан токен ETAPI", "token_created_title": "Создан токен ETAPI",
"rename_token": "Переименовать этот токен", "rename_token": "Переименовать этот токен",

View File

@@ -104,7 +104,8 @@
"export_in_progress": "正在匯出:{{progressCount}}", "export_in_progress": "正在匯出:{{progressCount}}",
"export_finished_successfully": "成功匯出。", "export_finished_successfully": "成功匯出。",
"format_html": "HTML - 推薦,因為它保留了所有格式", "format_html": "HTML - 推薦,因為它保留了所有格式",
"format_pdf": "PDF - 用於列印或與他人分享。" "format_pdf": "PDF - 用於列印或與他人分享。",
"share-format": "HTML 網頁發佈——使用與共享筆記相同的佈景主題,但可發佈為靜態網站。"
}, },
"help": { "help": {
"noteNavigation": "筆記導航", "noteNavigation": "筆記導航",
@@ -1280,8 +1281,6 @@
"etapi": { "etapi": {
"title": "ETAPI", "title": "ETAPI",
"description": "ETAPI 是一個 REST API用於以編程方式訪問 Trilium 實例,而無需 UI。", "description": "ETAPI 是一個 REST API用於以編程方式訪問 Trilium 實例,而無需 UI。",
"wiki": "維基",
"openapi_spec": "ETAPI OpenAPI 規範",
"create_token": "新增 ETAPI 令牌", "create_token": "新增 ETAPI 令牌",
"existing_tokens": "現有令牌", "existing_tokens": "現有令牌",
"no_tokens_yet": "目前還沒有令牌。點擊上面的按鈕新增一個。", "no_tokens_yet": "目前還沒有令牌。點擊上面的按鈕新增一個。",
@@ -1298,9 +1297,7 @@
"delete_token": "刪除 / 停用此令牌", "delete_token": "刪除 / 停用此令牌",
"rename_token_title": "重新命名令牌", "rename_token_title": "重新命名令牌",
"rename_token_message": "請輸入新的令牌名稱", "rename_token_message": "請輸入新的令牌名稱",
"delete_token_confirmation": "您確定要刪除 ETAPI 令牌 \"{{name}}\" 嗎?", "delete_token_confirmation": "您確定要刪除 ETAPI 令牌 \"{{name}}\" 嗎?"
"see_more": "有關更多詳細資訊,請參閱 {{- link_to_wiki}} 和 {{- link_to_openapi_spec}} 或 {{- link_to_swagger_ui}}。",
"swagger_ui": "ETAPI Swagger UI"
}, },
"options_widget": { "options_widget": {
"options_status": "選項狀態", "options_status": "選項狀態",

View File

@@ -1402,10 +1402,6 @@
"etapi": { "etapi": {
"title": "ETAPI", "title": "ETAPI",
"description": "ETAPI — це REST API, який використовується для програмного доступу до екземпляра Trilium без інтерфейсу користувача.", "description": "ETAPI — це REST API, який використовується для програмного доступу до екземпляра Trilium без інтерфейсу користувача.",
"see_more": "Див. докладнішу інформацію у {{- link_to_wiki}} та {{- link_to_openapi_spec}} або {{- link_to_swagger_ui }}.",
"wiki": "вікі",
"openapi_spec": "ETAPI OpenAPI spec",
"swagger_ui": "ETAPI Swagger UI",
"create_token": "Створити новий токен ETAPI", "create_token": "Створити новий токен ETAPI",
"existing_tokens": "Існуючі токени", "existing_tokens": "Існуючі токени",
"no_tokens_yet": "Токенів поки що немає. Натисніть кнопку вище, щоб створити його.", "no_tokens_yet": "Токенів поки що немає. Натисніть кнопку вище, щоб створити його.",

View File

@@ -79,8 +79,8 @@ export default function ExportDialog() {
values={[ values={[
{ value: "html", label: t("export.format_html_zip") }, { value: "html", label: t("export.format_html_zip") },
{ value: "markdown", label: t("export.format_markdown") }, { value: "markdown", label: t("export.format_markdown") },
{ value: "opml", label: t("export.format_opml") }, { value: "share", label: t("export.share-format") },
{ value: "share", label: t("export.share-format") } { value: "opml", label: t("export.format_opml") }
]} ]}
/> />

View File

@@ -2,7 +2,7 @@ import type { ComponentChildren } from "preact";
import { CSSProperties } from "preact/compat"; import { CSSProperties } from "preact/compat";
interface OptionsSectionProps { interface OptionsSectionProps {
title?: string; title?: ComponentChildren;
children: ComponentChildren; children: ComponentChildren;
noCard?: boolean; noCard?: boolean;
style?: CSSProperties; style?: CSSProperties;

View File

@@ -11,6 +11,7 @@ import dialog from "../../../services/dialog";
import { formatDateTime } from "../../../utils/formatters"; import { formatDateTime } from "../../../utils/formatters";
import ActionButton from "../../react/ActionButton"; import ActionButton from "../../react/ActionButton";
import { useTriliumEvent } from "../../react/hooks"; import { useTriliumEvent } from "../../react/hooks";
import HelpButton from "../../react/HelpButton";
type RenameTokenCallback = (tokenId: string, oldName: string) => Promise<void>; type RenameTokenCallback = (tokenId: string, oldName: string) => Promise<void>;
type DeleteTokenCallback = (tokenId: string, name: string ) => Promise<void>; type DeleteTokenCallback = (tokenId: string, name: string ) => Promise<void>;
@@ -53,14 +54,8 @@ export default function EtapiSettings() {
return ( return (
<OptionsSection title={t("etapi.title")}> <OptionsSection title={t("etapi.title")}>
<FormText> <FormText>
{t("etapi.description")}<br /> {t("etapi.description")}
<RawHtml <HelpButton helpPage="pgxEVkzLl1OP" />
html={t("etapi.see_more", {
link_to_wiki: `<a class="tn-link" href="https://triliumnext.github.io/Docs/Wiki/etapi.html">${t("etapi.wiki")}</a>`,
// TODO: We use window.open src/public/app/services/link.ts -> prevents regular click behavior on "a" element here because it's a relative path
link_to_openapi_spec: `<a class="tn-link" onclick="window.open('etapi/etapi.openapi.yaml')" href="etapi/etapi.openapi.yaml">${t("etapi.openapi_spec")}</a>`,
link_to_swagger_ui: `<a class="tn-link" href="#_help_f3xpgx6H01PW">${t("etapi.swagger_ui")}</a>`
})} />
</FormText> </FormText>
<Button <Button
@@ -68,6 +63,7 @@ export default function EtapiSettings() {
text={t("etapi.create_token")} text={t("etapi.create_token")}
onClick={createTokenCallback} onClick={createTokenCallback}
/> />
<hr /> <hr />
<h5>{t("etapi.existing_tokens")}</h5> <h5>{t("etapi.existing_tokens")}</h5>

View File

@@ -74,7 +74,6 @@ export default defineConfig(() => ({
mobile: join(__dirname, "src", "mobile.ts"), mobile: join(__dirname, "src", "mobile.ts"),
login: join(__dirname, "src", "login.ts"), login: join(__dirname, "src", "login.ts"),
setup: join(__dirname, "src", "setup.ts"), setup: join(__dirname, "src", "setup.ts"),
share: join(__dirname, "src", "share.ts"),
set_password: join(__dirname, "src", "set_password.ts"), set_password: join(__dirname, "src", "set_password.ts"),
runtime: join(__dirname, "src", "runtime.ts"), runtime: join(__dirname, "src", "runtime.ts"),
print: join(__dirname, "src", "print.tsx") print: join(__dirname, "src", "print.tsx")
@@ -84,7 +83,8 @@ export default defineConfig(() => ({
chunkFileNames: "src/[name].js", chunkFileNames: "src/[name].js",
assetFileNames: "src/[name].[ext]", assetFileNames: "src/[name].[ext]",
manualChunks: { manualChunks: {
"ckeditor5": [ "@triliumnext/ckeditor5" ] "ckeditor5": [ "@triliumnext/ckeditor5" ],
"boxicons": [ "../../node_modules/boxicons/css/boxicons.min.css" ]
}, },
}, },
onwarn(warning, rollupWarn) { onwarn(warning, rollupWarn) {

View File

@@ -35,7 +35,7 @@
"@triliumnext/commons": "workspace:*", "@triliumnext/commons": "workspace:*",
"@triliumnext/server": "workspace:*", "@triliumnext/server": "workspace:*",
"copy-webpack-plugin": "13.0.1", "copy-webpack-plugin": "13.0.1",
"electron": "38.4.0", "electron": "38.5.0",
"@electron-forge/cli": "7.10.2", "@electron-forge/cli": "7.10.2",
"@electron-forge/maker-deb": "7.10.2", "@electron-forge/maker-deb": "7.10.2",
"@electron-forge/maker-dmg": "7.10.2", "@electron-forge/maker-dmg": "7.10.2",

View File

@@ -12,7 +12,7 @@
"@triliumnext/desktop": "workspace:*", "@triliumnext/desktop": "workspace:*",
"@types/fs-extra": "11.0.4", "@types/fs-extra": "11.0.4",
"copy-webpack-plugin": "13.0.1", "copy-webpack-plugin": "13.0.1",
"electron": "38.4.0", "electron": "38.5.0",
"fs-extra": "11.3.2" "fs-extra": "11.3.2"
}, },
"scripts": { "scripts": {

View File

@@ -23,6 +23,8 @@ if (!DOCS_ROOT || !USER_GUIDE_ROOT) {
throw new Error("Missing DOCS_ROOT or USER_GUIDE_ROOT environment variable."); throw new Error("Missing DOCS_ROOT or USER_GUIDE_ROOT environment variable.");
} }
const BASE_URL = "https://docs.triliumnotes.org";
const NOTE_MAPPINGS: NoteMapping[] = [ const NOTE_MAPPINGS: NoteMapping[] = [
{ {
rootNoteId: "pOsGYCXsbNQG", rootNoteId: "pOsGYCXsbNQG",
@@ -158,6 +160,14 @@ async function cleanUpMeta(outputPath: string, minify: boolean) {
} }
el.isExpanded = false; el.isExpanded = false;
// Rewrite web view URLs that point to root.
if (el.type === "webView" && minify) {
const srcAttr = el.attributes.find(attr => attr.name === "webViewSrc");
if (srcAttr.value.startsWith("/")) {
srcAttr.value = BASE_URL + srcAttr.value;
}
}
} }
if (minify) { if (minify) {

View File

@@ -1,4 +1,4 @@
FROM node:24.10.0-bullseye-slim AS builder FROM node:24.11.0-bullseye-slim AS builder
RUN corepack enable RUN corepack enable
# Install native dependencies since we might be building cross-platform. # Install native dependencies since we might be building cross-platform.
@@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
# We have to use --no-frozen-lockfile due to CKEditor patches # We have to use --no-frozen-lockfile due to CKEditor patches
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
FROM node:24.10.0-bullseye-slim FROM node:24.11.0-bullseye-slim
# Install only runtime dependencies # Install only runtime dependencies
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y --no-install-recommends \ apt-get install -y --no-install-recommends \

View File

@@ -1,4 +1,4 @@
FROM node:24.10.0-alpine AS builder FROM node:24.11.0-alpine AS builder
RUN corepack enable RUN corepack enable
# Install native dependencies since we might be building cross-platform. # Install native dependencies since we might be building cross-platform.
@@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
# We have to use --no-frozen-lockfile due to CKEditor patches # We have to use --no-frozen-lockfile due to CKEditor patches
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
FROM node:24.10.0-alpine FROM node:24.11.0-alpine
# Install runtime dependencies # Install runtime dependencies
RUN apk add --no-cache su-exec shadow RUN apk add --no-cache su-exec shadow

View File

@@ -1,4 +1,4 @@
FROM node:24.10.0-alpine AS builder FROM node:24.11.0-alpine AS builder
RUN corepack enable RUN corepack enable
# Install native dependencies since we might be building cross-platform. # Install native dependencies since we might be building cross-platform.
@@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
# We have to use --no-frozen-lockfile due to CKEditor patches # We have to use --no-frozen-lockfile due to CKEditor patches
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
FROM node:24.10.0-alpine FROM node:24.11.0-alpine
# Create a non-root user with configurable UID/GID # Create a non-root user with configurable UID/GID
ARG USER=trilium ARG USER=trilium
ARG UID=1001 ARG UID=1001

View File

@@ -0,0 +1,28 @@
FROM node:22.21.0-bullseye-slim AS builder
RUN corepack enable
# Install native dependencies since we might be building cross-platform.
WORKDIR /usr/src/app/build
COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
# We have to use --no-frozen-lockfile due to CKEditor patches
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
FROM node:22.21.0-bullseye-slim
# Install only runtime dependencies
RUN apt-get update && \
apt-get install -y --no-install-recommends \
gosu && \
rm -rf \
/var/lib/apt/lists/* \
/var/cache/apt/*
WORKDIR /usr/src/app
COPY ./dist /usr/src/app
RUN rm -rf /usr/src/app/node_modules/better-sqlite3
COPY --from=builder /usr/src/app/node_modules/better-sqlite3 /usr/src/app/node_modules/better-sqlite3
COPY ./start-docker.sh /usr/src/app
# Configure container
EXPOSE 8080
CMD [ "sh", "./start-docker.sh" ]
HEALTHCHECK --start-period=10s CMD exec gosu node node /usr/src/app/docker_healthcheck.cjs

View File

@@ -1,4 +1,4 @@
FROM node:24.10.0-bullseye-slim AS builder FROM node:24.11.0-bullseye-slim AS builder
RUN corepack enable RUN corepack enable
# Install native dependencies since we might be building cross-platform. # Install native dependencies since we might be building cross-platform.
@@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
# We have to use --no-frozen-lockfile due to CKEditor patches # We have to use --no-frozen-lockfile due to CKEditor patches
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
FROM node:24.10.0-bullseye-slim FROM node:24.11.0-bullseye-slim
# Create a non-root user with configurable UID/GID # Create a non-root user with configurable UID/GID
ARG USER=trilium ARG USER=trilium
ARG UID=1001 ARG UID=1001

View File

@@ -4,12 +4,12 @@ info:
title: ETAPI title: ETAPI
description: External Trilium API description: External Trilium API
contact: contact:
name: zadam name: Trilium Notes Team
email: zadam.apps@gmail.com email: contact@eliandoran.me
url: https://github.com/zadam/trilium url: https://triliumnotes.org
license: license:
name: Apache 2.0 name: GNU Affero General Public License v3.0 only
url: https://www.apache.org/licenses/LICENSE-2.0.html url: https://www.gnu.org/licenses/agpl-3.0.en.html
servers: servers:
- url: http://localhost:37740/etapi - url: http://localhost:37740/etapi
- url: http://localhost:8080/etapi - url: http://localhost:8080/etapi

View File

@@ -1,7 +1,7 @@
openapi: 3.1.0 openapi: 3.1.0
info: info:
title: Trilium Notes Internal API title: Internal Trilium API
version: 0.98.0 version: 0.99.3
description: | description: |
This is the internal API used by the Trilium Notes client application. This is the internal API used by the Trilium Notes client application.
@@ -24,11 +24,12 @@ info:
State-changing operations require CSRF tokens when using session authentication. State-changing operations require CSRF tokens when using session authentication.
contact: contact:
name: TriliumNext Issue Tracker name: Trilium Notes Team
url: https://github.com/TriliumNext/Trilium/issues email: contact@eliandoran.me
url: https://triliumnotes.org
license: license:
name: GNU Affero General Public License v3.0 name: GNU Affero General Public License v3.0 only
url: https://www.gnu.org/licenses/agpl-3.0.html url: https://www.gnu.org/licenses/agpl-3.0.en.html
servers: servers:
- url: http://localhost:8080 - url: http://localhost:8080

View File

@@ -26,17 +26,18 @@
}, },
"dependencies": { "dependencies": {
"better-sqlite3": "12.4.1", "better-sqlite3": "12.4.1",
"html-to-text": "9.0.5",
"node-html-parser": "7.0.1" "node-html-parser": "7.0.1"
}, },
"devDependencies": { "devDependencies": {
"@anthropic-ai/sdk": "0.67.0", "@anthropic-ai/sdk": "0.68.0",
"@braintree/sanitize-url": "7.1.1", "@braintree/sanitize-url": "7.1.1",
"@electron/remote": "2.1.3", "@electron/remote": "2.1.3",
"@preact/preset-vite": "2.10.2", "@preact/preset-vite": "2.10.2",
"@triliumnext/commons": "workspace:*", "@triliumnext/commons": "workspace:*",
"@triliumnext/express-partial-content": "workspace:*", "@triliumnext/express-partial-content": "workspace:*",
"@triliumnext/turndown-plugin-gfm": "workspace:*",
"@triliumnext/highlightjs": "workspace:*", "@triliumnext/highlightjs": "workspace:*",
"@triliumnext/turndown-plugin-gfm": "workspace:*",
"@types/archiver": "7.0.0", "@types/archiver": "7.0.0",
"@types/better-sqlite3": "7.6.13", "@types/better-sqlite3": "7.6.13",
"@types/cls-hooked": "4.3.9", "@types/cls-hooked": "4.3.9",
@@ -60,35 +61,34 @@
"@types/serve-static": "2.2.0", "@types/serve-static": "2.2.0",
"@types/stream-throttle": "0.1.4", "@types/stream-throttle": "0.1.4",
"@types/supertest": "6.0.3", "@types/supertest": "6.0.3",
"@types/swagger-ui-express": "4.1.8",
"@types/tmp": "0.2.6", "@types/tmp": "0.2.6",
"@types/turndown": "5.0.6", "@types/turndown": "5.0.6",
"@types/ws": "8.18.1", "@types/ws": "8.18.1",
"@types/xml2js": "0.4.14", "@types/xml2js": "0.4.14",
"archiver": "7.0.1", "archiver": "7.0.1",
"async-mutex": "0.5.0", "async-mutex": "0.5.0",
"axios": "1.13.0", "axios": "1.13.1",
"bindings": "1.5.0", "bindings": "1.5.0",
"bootstrap": "5.3.8", "bootstrap": "5.3.8",
"chardet": "2.1.0", "chardet": "2.1.1",
"cheerio": "1.1.2", "cheerio": "1.1.2",
"chokidar": "4.0.3", "chokidar": "4.0.3",
"cls-hooked": "4.2.2", "cls-hooked": "4.2.2",
"compression": "1.8.1", "compression": "1.8.1",
"cookie-parser": "1.4.7", "cookie-parser": "1.4.7",
"csrf-csrf": "3.2.2", "csrf-csrf": "3.2.2",
"dayjs": "1.11.18", "dayjs": "1.11.19",
"debounce": "2.2.0", "debounce": "2.2.0",
"debug": "4.4.3", "debug": "4.4.3",
"ejs": "3.1.10", "ejs": "3.1.10",
"electron": "38.4.0", "electron": "38.5.0",
"electron-debug": "4.1.0", "electron-debug": "4.1.0",
"electron-window-state": "5.0.3", "electron-window-state": "5.0.3",
"escape-html": "1.0.3", "escape-html": "1.0.3",
"express": "5.1.0", "express": "5.1.0",
"express-http-proxy": "2.1.2", "express-http-proxy": "2.1.2",
"express-openid-connect": "2.19.2", "express-openid-connect": "2.19.2",
"express-rate-limit": "8.1.0", "express-rate-limit": "8.2.1",
"express-session": "1.18.2", "express-session": "1.18.2",
"file-uri-to-path": "2.0.0", "file-uri-to-path": "2.0.0",
"fs-extra": "11.3.2", "fs-extra": "11.3.2",
@@ -109,7 +109,7 @@
"mime-types": "3.0.1", "mime-types": "3.0.1",
"multer": "2.0.2", "multer": "2.0.2",
"normalize-strings": "1.1.1", "normalize-strings": "1.1.1",
"ollama": "0.6.0", "ollama": "0.6.2",
"openai": "6.7.0", "openai": "6.7.0",
"rand-token": "1.0.1", "rand-token": "1.0.1",
"safe-compare": "1.1.4", "safe-compare": "1.1.4",
@@ -122,7 +122,6 @@
"striptags": "3.2.0", "striptags": "3.2.0",
"supertest": "7.1.4", "supertest": "7.1.4",
"swagger-jsdoc": "6.2.8", "swagger-jsdoc": "6.2.8",
"swagger-ui-express": "5.0.1",
"time2fa": "1.4.2", "time2fa": "1.4.2",
"tmp": "0.2.5", "tmp": "0.2.5",
"turndown": "7.2.2", "turndown": "7.2.2",

File diff suppressed because one or more lines are too long

View File

Before

Width:  |  Height:  |  Size: 168 KiB

After

Width:  |  Height:  |  Size: 168 KiB

View File

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

Before

Width:  |  Height:  |  Size: 172 KiB

After

Width:  |  Height:  |  Size: 172 KiB

View File

Before

Width:  |  Height:  |  Size: 167 KiB

After

Width:  |  Height:  |  Size: 167 KiB

View File

Before

Width:  |  Height:  |  Size: 237 KiB

After

Width:  |  Height:  |  Size: 237 KiB

View File

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 202 KiB

View File

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

View File

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

View File

Before

Width:  |  Height:  |  Size: 191 KiB

After

Width:  |  Height:  |  Size: 191 KiB

View File

@@ -1,6 +1,6 @@
<figure class="image image_resized" style="width:63.68%;"> <figure class="image image_resized" style="width:63.68%;">
<img style="aspect-ratio:1363/1364;" src="Introduction_image.png" width="1363" <img style="aspect-ratio:1363/1364;" src="AI_image.png"
height="1364"> width="1363" height="1364">
<figcaption>An example chat with an LLM</figcaption> <figcaption>An example chat with an LLM</figcaption>
</figure> </figure>
<p>The AI / LLM features within Trilium Notes are designed to allow you to <p>The AI / LLM features within Trilium Notes are designed to allow you to
@@ -11,13 +11,13 @@
<p>The quickest way to get started is to navigate to the “AI/LLM” settings:</p> <p>The quickest way to get started is to navigate to the “AI/LLM” settings:</p>
<figure <figure
class="image image_resized" style="width:74.04%;"> class="image image_resized" style="width:74.04%;">
<img style="aspect-ratio:1916/1906;" src="5_Introduction_image.png" width="1916" <img style="aspect-ratio:1916/1906;" src="5_AI_image.png"
height="1906"> width="1916" height="1906">
</figure> </figure>
<p>Enable the feature:</p> <p>Enable the feature:</p>
<figure class="image image_resized" style="width:82.82%;"> <figure class="image image_resized" style="width:82.82%;">
<img style="aspect-ratio:1911/997;" src="1_Introduction_image.png" width="1911" <img style="aspect-ratio:1911/997;" src="1_AI_image.png"
height="997"> width="1911" height="997">
</figure> </figure>
<h2>Embeddings</h2> <h2>Embeddings</h2>
@@ -43,30 +43,30 @@ class="image image_resized" style="width:74.04%;">
We will then hit the “refresh” button to have it fetch our models:</p> We will then hit the “refresh” button to have it fetch our models:</p>
<figure <figure
class="image image_resized" style="width:82.28%;"> class="image image_resized" style="width:82.28%;">
<img style="aspect-ratio:1912/1075;" src="4_Introduction_image.png" width="1912" <img style="aspect-ratio:1912/1075;" src="4_AI_image.png"
height="1075"> width="1912" height="1075">
</figure> </figure>
<p>When selecting the dropdown for the “Embedding Model”, embedding models <p>When selecting the dropdown for the “Embedding Model”, embedding models
should be at the top of the list, separated by regular chat models with should be at the top of the list, separated by regular chat models with
a horizontal line, as seen below:</p> a horizontal line, as seen below:</p>
<figure class="image image_resized" <figure class="image image_resized"
style="width:61.73%;"> style="width:61.73%;">
<img style="aspect-ratio:1232/959;" src="8_Introduction_image.png" width="1232" <img style="aspect-ratio:1232/959;" src="8_AI_image.png"
height="959"> width="1232" height="959">
</figure> </figure>
<p>After selecting an embedding model, embeddings should automatically begin <p>After selecting an embedding model, embeddings should automatically begin
to be generated by checking the embedding statistics at the top of the to be generated by checking the embedding statistics at the top of the
“AI/LLM” settings panel:</p> “AI/LLM” settings panel:</p>
<figure class="image image_resized" style="width:67.06%;"> <figure class="image image_resized" style="width:67.06%;">
<img style="aspect-ratio:1333/499;" src="7_Introduction_image.png" width="1333" <img style="aspect-ratio:1333/499;" src="7_AI_image.png"
height="499"> width="1333" height="499">
</figure> </figure>
<p>If you don't see any embeddings being created, you will want to scroll <p>If you don't see any embeddings being created, you will want to scroll
to the bottom of the settings, and hit “Recreate All Embeddings”:</p> to the bottom of the settings, and hit “Recreate All Embeddings”:</p>
<figure <figure
class="image image_resized" style="width:65.69%;"> class="image image_resized" style="width:65.69%;">
<img style="aspect-ratio:1337/1490;" src="3_Introduction_image.png" width="1337" <img style="aspect-ratio:1337/1490;" src="3_AI_image.png"
height="1490"> width="1337" height="1490">
</figure> </figure>
<p>Creating the embeddings will take some time, and will be regenerated when <p>Creating the embeddings will take some time, and will be regenerated when
a Note is created, updated, or deleted (removed).</p> a Note is created, updated, or deleted (removed).</p>
@@ -139,8 +139,8 @@ class="image image_resized" style="width:74.04%;">
<p>When Tools are executed within your Chat, you'll see output like the following:</p> <p>When Tools are executed within your Chat, you'll see output like the following:</p>
<figure <figure
class="image image_resized" style="width:66.88%;"> class="image image_resized" style="width:66.88%;">
<img style="aspect-ratio:1372/1591;" src="6_Introduction_image.png" width="1372" <img style="aspect-ratio:1372/1591;" src="6_AI_image.png"
height="1591"> width="1372" height="1591">
</figure> </figure>
<p>You don't need to tell the LLM to execute a certain tool, it should “smartly” <p>You don't need to tell the LLM to execute a certain tool, it should “smartly”
call tools and automatically execute them as needed.</p> call tools and automatically execute them as needed.</p>
@@ -149,13 +149,13 @@ class="image image_resized" style="width:74.04%;">
use the “Chat with Notes” button, where you can go ahead and start chatting!:</p> use the “Chat with Notes” button, where you can go ahead and start chatting!:</p>
<figure <figure
class="image image_resized" style="width:60.77%;"> class="image image_resized" style="width:60.77%;">
<img style="aspect-ratio:1378/539;" src="2_Introduction_image.png" width="1378" <img style="aspect-ratio:1378/539;" src="2_AI_image.png"
height="539"> width="1378" height="539">
</figure> </figure>
<p>If you don't see the “Chat with Notes” button on your side launchbar, <p>If you don't see the “Chat with Notes” button on your side launchbar,
you might need to move it from the “Available Launchers” section to the you might need to move it from the “Available Launchers” section to the
“Visible Launchers” section:</p> “Visible Launchers” section:</p>
<figure class="image image_resized" style="width:69.81%;"> <figure class="image image_resized" style="width:69.81%;">
<img style="aspect-ratio:1765/1287;" src="9_Introduction_image.png" width="1765" <img style="aspect-ratio:1765/1287;" src="9_AI_image.png"
height="1287"> width="1765" height="1287">
</figure> </figure>

View File

@@ -11,12 +11,12 @@
<p>To set your preferred chat model, you'll want to enter the provider's <p>To set your preferred chat model, you'll want to enter the provider's
name here:</p> name here:</p>
<figure class="image image_resized" style="width:88.38%;"> <figure class="image image_resized" style="width:88.38%;">
<img style="aspect-ratio:1884/1267;" src="AI Provider Information_im.png" <img style="aspect-ratio:1884/1267;" src="Providers_image.png"
width="1884" height="1267"> width="1884" height="1267">
</figure> </figure>
<p>And to set your preferred embedding provider:</p> <p>And to set your preferred embedding provider:</p>
<figure class="image image_resized" <figure class="image image_resized"
style="width:93.47%;"> style="width:93.47%;">
<img style="aspect-ratio:1907/1002;" src="1_AI Provider Information_im.png" <img style="aspect-ratio:1907/1002;" src="1_Providers_image.png"
width="1907" height="1002"> width="1907" height="1002">
</figure> </figure>

View File

@@ -9,8 +9,8 @@ class="image image_resized" style="width:50.49%;">
width="785" height="498"> width="785" height="498">
</figure> </figure>
<figure class="image image_resized" style="width:40.54%;"> <figure class="image image_resized" style="width:40.54%;">
<img style="aspect-ratio:467/100;" src="Installing Ollama_image.png" width="467" <img style="aspect-ratio:467/100;" src="Installing Ollama_image.png"
height="100"> width="467" height="100">
</figure> </figure>
<figure class="image image_resized" style="width:55.73%;"> <figure class="image image_resized" style="width:55.73%;">
<img style="aspect-ratio:1296/1011;" src="1_Installing Ollama_image.png" <img style="aspect-ratio:1296/1011;" src="1_Installing Ollama_image.png"

View File

Before

Width:  |  Height:  |  Size: 175 KiB

After

Width:  |  Height:  |  Size: 175 KiB

View File

@@ -10,9 +10,9 @@
and arbitrary tags - whenever you change tag attribute in the task note, and arbitrary tags - whenever you change tag attribute in the task note,
this task is then automatically moved to appropriate location.</p> this task is then automatically moved to appropriate location.</p>
<p>Task Manager also integrates with <a href="#root/_help_l0tKav7yLHGF">day notes</a> - <p>Task Manager also integrates with <a href="#root/_help_l0tKav7yLHGF">day notes</a> -
notes are <a href="#root/_help_IakOLONlIfGI">cloned</a> into day note to notes are <a href="#root/_help_IakOLONlIfGI">cloned</a> into day note to both todoDate
both todoDate note and doneDate note (with <a href="#root/_help_kBrnXNG3Hplm">prefix</a> of note and doneDate note (with <a href="#root/_help_kBrnXNG3Hplm">prefix</a> of either
either "TODO" or "DONE").</p> "TODO" or "DONE").</p>
<h2>Implementation</h2> <h2>Implementation</h2>
<p>New tasks are created in the TODO note which has <code>~child:template</code> <p>New tasks are created in the TODO note which has <code>~child:template</code>
<a <a
@@ -22,9 +22,9 @@
<p>Task template defines several <a href="#root/_help_OFXdgB2nNk1F">promoted attributes</a> - <p>Task template defines several <a href="#root/_help_OFXdgB2nNk1F">promoted attributes</a> -
todoDate, doneDate, tags, location. Importantly it also defines <code>~runOnAttributeChange</code> relation todoDate, doneDate, tags, location. Importantly it also defines <code>~runOnAttributeChange</code> relation
- <a href="#root/_help_GPERMystNGTB">event</a> handler which is run on attribute - <a href="#root/_help_GPERMystNGTB">event</a> handler which is run on attribute
change. This <a href="#root/_help_CdNpE2pqjmI6">script</a> handles when e.g. change. This <a href="#root/_help_CdNpE2pqjmI6">script</a> handles when e.g. we
we fill out the doneDate attribute - meaning the task is done and should fill out the doneDate attribute - meaning the task is done and should be
be moved to "Done" note and removed from TODO, locations and tags.</p> moved to "Done" note and removed from TODO, locations and tags.</p>
<h3>New task button</h3> <h3>New task button</h3>
<p>There's also "button" note which contains simple script which adds a button <p>There's also "button" note which contains simple script which adds a button
to create new note (task) in the TODO note.</p><pre><code class="language-text-x-trilium-auto">api.addButtonToToolbar({ to create new note (task) in the TODO note.</p><pre><code class="language-text-x-trilium-auto">api.addButtonToToolbar({

View File

@@ -1,6 +1,6 @@
<figure class="image"> <figure class="image">
<img style="aspect-ratio:1071/146;" src="Attributes_image.png" width="1071" <img style="aspect-ratio:1071/146;" src="Attributes_image.png"
height="146"> width="1071" height="146">
</figure> </figure>
<p>In Trilium, attributes are key-value pairs assigned to notes, providing <p>In Trilium, attributes are key-value pairs assigned to notes, providing
additional metadata or functionality. There are two primary types of attributes:</p> additional metadata or functionality. There are two primary types of attributes:</p>

View File

@@ -1,6 +1,6 @@
<p>Inheritance refers to the process of having a <a href="#root/_help_HI6GBBIduIgv">label</a> or <p>Inheritance refers to the process of having a <a href="#root/_help_HI6GBBIduIgv">label</a> or
a <a href="#root/_help_Cq5X6iKQop6R">relation</a> shared across multiple a <a href="#root/_help_Cq5X6iKQop6R">relation</a> shared across multiple notes,
notes, generally in parent-child relations (or anywhere if using templates).</p> generally in parent-child relations (or anywhere if using templates).</p>
<h2>Standard Inheritance</h2> <h2>Standard Inheritance</h2>
<p>In Trilium, attributes can be automatically inherited by child notes if <p>In Trilium, attributes can be automatically inherited by child notes if
they have the <code>isInheritable</code> flag set to <code>true</code>. This they have the <code>isInheritable</code> flag set to <code>true</code>. This

View File

@@ -1,5 +1,5 @@
<p>A label is an <a href="#root/_help_zEY4DaJG4YT5">attribute</a> of a note <p>A label is an <a href="#root/_help_zEY4DaJG4YT5">attribute</a> of a note which
which has a name and optionally a value.</p> has a name and optionally a value.</p>
<h2>Common use cases</h2> <h2>Common use cases</h2>
<ul> <ul>
<li><strong>Metadata for personal use</strong>: Assign labels with optional <li><strong>Metadata for personal use</strong>: Assign labels with optional
@@ -81,8 +81,7 @@
<td><code>calendarRoot</code> <td><code>calendarRoot</code>
</td> </td>
<td>Marks the note which should be used as root for&nbsp;<a class="reference-link" <td>Marks the note which should be used as root for&nbsp;<a class="reference-link"
href="#root/_help_l0tKav7yLHGF">Day Notes</a>. Only one should be marked href="#root/_help_l0tKav7yLHGF">Day Notes</a>. Only one should be marked as such.</td>
as such.</td>
</tr> </tr>
<tr> <tr>
<td><code>archived</code> <td><code>archived</code>
@@ -154,8 +153,8 @@
<tr> <tr>
<td><code>autoReadOnlyDisabled</code> <td><code>autoReadOnlyDisabled</code>
</td> </td>
<td>Disables automatic <a href="#root/_help_CoFPLs3dRlXc">read-only mode</a> for <td>Disables automatic <a href="#root/_help_CoFPLs3dRlXc">read-only mode</a> for the
the given note.</td> given note.</td>
</tr> </tr>
<tr> <tr>
<td><code>appCss</code> <td><code>appCss</code>
@@ -177,8 +176,7 @@
<td>Set to <code>next</code>, <code>next-light</code>, or <code>next-dark</code> to <td>Set to <code>next</code>, <code>next-light</code>, or <code>next-dark</code> to
use the corresponding TriliumNext theme (auto, light or dark) as the base use the corresponding TriliumNext theme (auto, light or dark) as the base
for a custom theme, instead of the legacy one. See&nbsp;<a class="reference-link" for a custom theme, instead of the legacy one. See&nbsp;<a class="reference-link"
href="#root/_help_WFGzWeUK6arS">Customize the Next theme</a>&nbsp;for more href="#root/_help_WFGzWeUK6arS">Customize the Next theme</a>&nbsp;for more information.</td>
information.</td>
</tr> </tr>
<tr> <tr>
<td><code>cssClass</code> <td><code>cssClass</code>

View File

@@ -1,5 +1,5 @@
<p>A relation is similar to a <a href="#root/_help_HI6GBBIduIgv">label</a>, <p>A relation is similar to a <a href="#root/_help_HI6GBBIduIgv">label</a>, but
but instead of having a text value it refers to another note.</p> instead of having a text value it refers to another note.</p>
<h2>Common use cases</h2> <h2>Common use cases</h2>
<ul> <ul>
<li><strong>Metadata Relationships for personal use</strong>: For example, <li><strong>Metadata Relationships for personal use</strong>: For example,

View File

@@ -1,6 +1,6 @@
<figure class="image"> <figure class="image">
<img style="aspect-ratio:1425/654;" src="Bulk Actions_image.png" width="1425" <img style="aspect-ratio:1425/654;" src="Bulk Actions_image.png"
height="654"> width="1425" height="654">
</figure> </figure>
<p>The <em>Bulk Actions</em> dialog makes it easy to apply changes to multiple <p>The <em>Bulk Actions</em> dialog makes it easy to apply changes to multiple
notes at once, ranging from simple actions such as adding or removing a notes at once, ranging from simple actions such as adding or removing a
@@ -8,8 +8,8 @@
<h2>Interaction</h2> <h2>Interaction</h2>
<ul> <ul>
<li>The first step is to select the notes in the&nbsp;<a class="reference-link" <li>The first step is to select the notes in the&nbsp;<a class="reference-link"
href="#root/_help_oPVyFC7WL2Lp">Note Tree</a>. It's possible to apply bulk href="#root/_help_oPVyFC7WL2Lp">Note Tree</a>. It's possible to apply bulk actions
actions to: to:
<ul> <ul>
<li>A single note (and potentially its child notes) simply by clicking on <li>A single note (and potentially its child notes) simply by clicking on
it (with a left click or a right click).</li> it (with a left click or a right click).</li>
@@ -53,17 +53,17 @@
</li> </li>
<li><strong>Update label value</strong> <li><strong>Update label value</strong>
<ul> <ul>
<li>For each note, if it has a <a href="#root/_help_HI6GBBIduIgv">label</a> of <li>For each note, if it has a <a href="#root/_help_HI6GBBIduIgv">label</a> of the
the given name, it will change its value to the specified one. Leave <em>New value</em> field given name, it will change its value to the specified one. Leave <em>New value</em> field
empty to create a label without a value.</li> empty to create a label without a value.</li>
<li>Notes without the label will not be affected.</li> <li>Notes without the label will not be affected.</li>
</ul> </ul>
</li> </li>
<li><em><strong>Rename label</strong></em> <li><em><strong>Rename label</strong></em>
<ul> <ul>
<li>For each note, if it has a <a href="#root/_help_HI6GBBIduIgv">label</a> of <li>For each note, if it has a <a href="#root/_help_HI6GBBIduIgv">label</a> of the
the given name, it will be renamed/replaced with a label of the new name. given name, it will be renamed/replaced with a label of the new name. The
The value of the label (if present) will be kept intact.</li> value of the label (if present) will be kept intact.</li>
<li>Notes without the label will not be affected.</li> <li>Notes without the label will not be affected.</li>
</ul> </ul>
</li> </li>

View File

@@ -1,8 +1,8 @@
<p>A Trilium instance represents a server. If&nbsp;<a class="reference-link" <p>A Trilium instance represents a server. If&nbsp;<a class="reference-link"
href="#root/_help_cbkrhQjrkKrh">Synchronization</a>&nbsp;is set up, since href="#root/_help_cbkrhQjrkKrh">Synchronization</a>&nbsp;is set up, since multiple
multiple servers are involved (the one from the desktop client and the servers are involved (the one from the desktop client and the one the synchronisation
one the synchronisation is set up with), sometimes it can be useful to is set up with), sometimes it can be useful to distinguish the instance
distinguish the instance you are running on.</p> you are running on.</p>
<h2>Setting the instance name</h2> <h2>Setting the instance name</h2>
<p>To set up a name for the instance, modify the <code>config.ini</code>:</p><pre><code class="language-text-x-trilium-auto">[General] <p>To set up a name for the instance, modify the <code>config.ini</code>:</p><pre><code class="language-text-x-trilium-auto">[General]
instanceName=Hello</code></pre> instanceName=Hello</code></pre>

View File

@@ -23,5 +23,5 @@
<p>If you do not need to preserve any configurations that might be stored <p>If you do not need to preserve any configurations that might be stored
in the <code>config.ini</code> file, you can just delete all of the <a href="#root/_help_tAassRL4RSQL">data directory's</a> contents in the <code>config.ini</code> file, you can just delete all of the <a href="#root/_help_tAassRL4RSQL">data directory's</a> contents
to fully restore the application to its original state. You can also review to fully restore the application to its original state. You can also review
the <a href="#root/_help_Gzjqa934BdH4">configuration</a> file to provide the <a href="#root/_help_Gzjqa934BdH4">configuration</a> file to provide all <code>config.ini</code> values
all <code>config.ini</code> values as environment variables instead.</p> as environment variables instead.</p>

View File

@@ -1,11 +1,13 @@
<aside class="admonition tip">
<p>For a quick start, consult the&nbsp;<a class="reference-link" href="#root/pgxEVkzLl1OP/_help_9qPsTWBorUhQ">API Reference</a>.</p>
</aside>
<p>ETAPI is Trilium's public/external REST API. It is available since Trilium <p>ETAPI is Trilium's public/external REST API. It is available since Trilium
v0.50.</p> v0.50.</p>
<p>The documentation is in OpenAPI format, available <a href="https://github.com/TriliumNext/Trilium/blob/master/src/etapi/etapi.openapi.yaml">here</a>.</p>
<h2>API clients</h2> <h2>API clients</h2>
<p>As an alternative to calling the API directly, there are client libraries <p>As an alternative to calling the API directly, there are client libraries
to simplify this</p> to simplify this</p>
<ul> <ul>
<li><a href="https://github.com/Nriver/trilium-py">trilium-py</a>, you can <li data-list-item-id="e3342ddfa108f6c8c6c47d7d3da8b02fa"><a href="https://github.com/Nriver/trilium-py">trilium-py</a>, you can
use Python to communicate with Trilium.</li> use Python to communicate with Trilium.</li>
</ul> </ul>
<h2>Obtaining a token</h2> <h2>Obtaining a token</h2>
@@ -23,10 +25,10 @@ Authorization: ETAPITOKEN</code></pre>
<p>Since v0.56 you can also use basic auth format:</p><pre><code class="language-text-x-trilium-auto">GET https://myserver.com/etapi/app-info <p>Since v0.56 you can also use basic auth format:</p><pre><code class="language-text-x-trilium-auto">GET https://myserver.com/etapi/app-info
Authorization: Basic BATOKEN</code></pre> Authorization: Basic BATOKEN</code></pre>
<ul> <ul>
<li>Where <code>BATOKEN = BASE64(username + ':' + password)</code> - this is <li data-list-item-id="ec59ac570a3d2a846da38378a5f2428ed">Where <code>BATOKEN = BASE64(username + ':' + password)</code> - this is
a standard Basic Auth serialization</li> a standard Basic Auth serialization</li>
<li>Where <code>username</code> is "etapi"</li> <li data-list-item-id="e18e2e73ebecc949dd4a51cd9f8bb0b91">Where <code>username</code> is "etapi"</li>
<li>And <code>password</code> is the generated ETAPI token described above.</li> <li data-list-item-id="ee892223f95cef4a53caec5477ab31edb">And <code>password</code> is the generated ETAPI token described above.</li>
</ul> </ul>
<p>Basic Auth is meant to be used with tools which support only basic auth.</p> <p>Basic Auth is meant to be used with tools which support only basic auth.</p>
<h2>Interaction using Bash scripts</h2> <h2>Interaction using Bash scripts</h2>
@@ -42,10 +44,10 @@ NOTE_ID="i6ra4ZshJhgN"
curl "$SERVER/etapi/notes/$NOTE_ID/content" -H "Authorization: $TOKEN" </code></pre> curl "$SERVER/etapi/notes/$NOTE_ID/content" -H "Authorization: $TOKEN" </code></pre>
<p>Make sure to replace the values of:</p> <p>Make sure to replace the values of:</p>
<ul> <ul>
<li><code>TOKEN</code> with your ETAPI token.</li> <li data-list-item-id="e68020f83acc951e180bb405d149a64a5"><code>TOKEN</code> with your ETAPI token.</li>
<li><code>SERVER</code> with the correct protocol, host name and port to your <li data-list-item-id="ef4c31df5f6d18811e7de0ee8ff95f3a7"><code>SERVER</code> with the correct protocol, host name and port to your
Trilium instance.</li> Trilium instance.</li>
<li><code>NOTE_ID</code> with an existing note ID to download.</li> <li data-list-item-id="e25086bb4c54d32259f987f9366e22204"><code>NOTE_ID</code> with an existing note ID to download.</li>
</ul> </ul>
<p>As another example, to obtain a .zip export of a note and place it in <p>As another example, to obtain a .zip export of a note and place it in
a directory called <code>out</code>, simply replace the last statement in a directory called <code>out</code>, simply replace the last statement in

View File

@@ -1,6 +1,6 @@
<figure class="image image-style-align-right"> <figure class="image image-style-align-right">
<img style="aspect-ratio:263/445;" src="Hidden Notes_image.png" width="263" <img style="aspect-ratio:263/445;" src="Hidden Notes_image.png"
height="445"> width="263" height="445">
</figure> </figure>
<p>For easy extensibility, a lot of features in Trilium make use of actual <p>For easy extensibility, a lot of features in Trilium make use of actual
notes to store information as opposed to having them stored in a separate notes to store information as opposed to having them stored in a separate
@@ -8,14 +8,13 @@
href="#root/_help_zEY4DaJG4YT5">Attributes</a>,&nbsp;<a class="reference-link" href="#root/_help_zEY4DaJG4YT5">Attributes</a>,&nbsp;<a class="reference-link"
href="#root/_help_Cq5X6iKQop6R">Relations</a>&nbsp;or even&nbsp;<a class="reference-link" href="#root/_help_Cq5X6iKQop6R">Relations</a>&nbsp;or even&nbsp;<a class="reference-link"
href="#root/_help_eIg8jdvaoNNd">Search</a>&nbsp;and&nbsp;<a class="reference-link" href="#root/_help_eIg8jdvaoNNd">Search</a>&nbsp;and&nbsp;<a class="reference-link"
href="#root/_help_QEAPj01N5f7w">Links</a>&nbsp;to be able to operate on href="#root/_help_QEAPj01N5f7w">Links</a>&nbsp;to be able to operate on them.</p>
them.</p>
<p>As the name suggests, these notes are hidden to the user by default to <p>As the name suggests, these notes are hidden to the user by default to
prevent cluttering the note tree and to prevent them from being accidentally prevent cluttering the note tree and to prevent them from being accidentally
deleted.</p> deleted.</p>
<p>The hidden notes are stored in the user's&nbsp;<a class="reference-link" <p>The hidden notes are stored in the user's&nbsp;<a class="reference-link"
href="#root/_help_wX4HbRucYSDD">Database</a>&nbsp;just like normal notes, href="#root/_help_wX4HbRucYSDD">Database</a>&nbsp;just like normal notes, but
but they have a unique&nbsp;<a class="reference-link" href="#root/_help_m1lbrzyKDaRB">Note ID</a>&nbsp;which they have a unique&nbsp;<a class="reference-link" href="#root/_help_m1lbrzyKDaRB">Note ID</a>&nbsp;which
allows them to be distinguished from the normal ones.</p> allows them to be distinguished from the normal ones.</p>
<h2>Accessing the hidden note tree</h2> <h2>Accessing the hidden note tree</h2>
<p>From the&nbsp;<a class="reference-link" href="#root/_help_x3i7MxGccDuM">Global menu</a>, <p>From the&nbsp;<a class="reference-link" href="#root/_help_x3i7MxGccDuM">Global menu</a>,
@@ -51,8 +50,8 @@ class="ck-table-resized">
</td> </td>
<td> <td>
<p>When SQL queries or commands are executed in the&nbsp;<a class="reference-link" <p>When SQL queries or commands are executed in the&nbsp;<a class="reference-link"
href="#root/_help_YKWqdJhzi2VY">SQL Console</a>, they are stored here, href="#root/_help_YKWqdJhzi2VY">SQL Console</a>, they are stored here, grouped
grouped by month. Only the query is stored and not the results.</p> by month. Only the query is stored and not the results.</p>
<p>This section can be accessed without going to the hidden tree by simply <p>This section can be accessed without going to the hidden tree by simply
going to the&nbsp;<a class="reference-link" href="#root/_help_x3i7MxGccDuM">Global menu</a>&nbsp;and going to the&nbsp;<a class="reference-link" href="#root/_help_x3i7MxGccDuM">Global menu</a>&nbsp;and
selecting Advanced → Open SQL Console History.</p> selecting Advanced → Open SQL Console History.</p>
@@ -65,9 +64,8 @@ class="ck-table-resized">
</td> </td>
<td> <td>
<p>Whenever a search is executed from the full&nbsp;<a class="reference-link" <p>Whenever a search is executed from the full&nbsp;<a class="reference-link"
href="#root/_help_eIg8jdvaoNNd">Search</a>, the query will be stored here, href="#root/_help_eIg8jdvaoNNd">Search</a>, the query will be stored here, grouped
grouped by month. Only the search parameters are stored and not the results by month. Only the search parameters are stored and not the results themselves.</p>
themselves.</p>
<p>This section can be accessed without going to the hidden tree by simply <p>This section can be accessed without going to the hidden tree by simply
going to the&nbsp;<a class="reference-link" href="#root/_help_x3i7MxGccDuM">Global menu</a>&nbsp;and going to the&nbsp;<a class="reference-link" href="#root/_help_x3i7MxGccDuM">Global menu</a>&nbsp;and
selecting Advanced → Open Search History.</p> selecting Advanced → Open Search History.</p>

View File

@@ -82,18 +82,18 @@ trilium_notes_total 1234 1701432000
</ul> </ul>
<h2><strong>Grafana Dashboard</strong></h2> <h2><strong>Grafana Dashboard</strong></h2>
<figure class="image"> <figure class="image">
<img style="aspect-ratio:2594/1568;" src="1_Metrics_image.png" width="2594" <img style="aspect-ratio:2594/1568;" src="1_Metrics_image.png"
height="1568"> width="2594" height="1568">
</figure> </figure>
<p>You can also use the Grafana Dashboard that has been created for TriliumNext <p>You can also use the Grafana Dashboard that has been created for TriliumNext
- just take the JSON from&nbsp;<a class="reference-link" href="#root/_help_bOP3TB56fL1V">grafana-dashboard.json</a>&nbsp;and - just take the JSON from&nbsp;<a class="reference-link" href="#root/_help_bOP3TB56fL1V">grafana-dashboard.json</a>&nbsp;and
then import the dashboard, following these screenshots:</p> then import the dashboard, following these screenshots:</p>
<figure class="image"> <figure class="image">
<img style="aspect-ratio:1881/282;" src="2_Metrics_image.png" width="1881" <img style="aspect-ratio:1881/282;" src="2_Metrics_image.png"
height="282"> width="1881" height="282">
</figure> </figure>
<p>Then paste the JSON, and hit load:</p> <p>Then paste the JSON, and hit load:</p>
<figure class="image"> <figure class="image">
<img style="aspect-ratio:1055/830;" src="Metrics_image.png" width="1055" <img style="aspect-ratio:1055/830;" src="Metrics_image.png"
height="830"> width="1055" height="830">
</figure> </figure>

View File

@@ -6,7 +6,16 @@
<li>Note Map, which shows the hierarchical tree structure.</li> <li>Note Map, which shows the hierarchical tree structure.</li>
</ul> </ul>
<h2>Link Map</h2> <h2>Link Map</h2>
<p>Shows <a href="#root/_help_zEY4DaJG4YT5">relations</a> between notes:</p> <p>The Link map is a visualization of links and&nbsp;<a class="reference-link"
href="#root/_help_Cq5X6iKQop6R">Relations</a>&nbsp;incoming to and outgoing from
a particular note.</p>
<p>The map indicates the following types of relations:</p>
<ul>
<li><a class="reference-link" href="#root/_help_hrZ1D00cLbal">Internal (reference) links</a>&nbsp;between
notes.</li>
<li><a class="reference-link" href="#root/_help_Cq5X6iKQop6R">Relations</a>
</li>
</ul>
<p> <p>
<img src="1_Note Map (Link map, Tree m.png"> <img src="1_Note Map (Link map, Tree m.png">
</p> </p>
@@ -21,8 +30,8 @@
in full screen. See&nbsp;<a href="#root/_help_bdUJEHsAPYQR">Note Map</a>&nbsp;for in full screen. See&nbsp;<a href="#root/_help_bdUJEHsAPYQR">Note Map</a>&nbsp;for
more information.</p> more information.</p>
<h2>See also</h2> <h2>See also</h2>
<p><a href="#root/_help_iRwzGnHPzonm">Relation map</a> is a similar concept, <p><a href="#root/_help_iRwzGnHPzonm">Relation map</a> is a similar concept, with
with some differences:</p> some differences:</p>
<ul> <ul>
<li>note map is automatically generated while relation map must be created <li>note map is automatically generated while relation map must be created
manually</li> manually</li>

View File

@@ -5,9 +5,9 @@
<ul> <ul>
<li><a class="reference-link" href="#root/_help_iPIMuisry3hd">Text</a>&nbsp;notes&nbsp;are <li><a class="reference-link" href="#root/_help_iPIMuisry3hd">Text</a>&nbsp;notes&nbsp;are
represented internally as HTML, using the&nbsp;<a class="reference-link" represented internally as HTML, using the&nbsp;<a class="reference-link"
href="#root/_help_MI26XDLSAlCD">CKEditor</a>&nbsp;representation. Note href="#root/_help_MI26XDLSAlCD">CKEditor</a>&nbsp;representation. Note that due
that due to the custom plugins, some HTML elements are specific to Trilium to the custom plugins, some HTML elements are specific to Trilium only,
only, for example the admonitions.</li> for example the admonitions.</li>
<li><a class="reference-link" href="#root/_help_6f9hih2hXXZk">Code</a>&nbsp;notes&nbsp;are <li><a class="reference-link" href="#root/_help_6f9hih2hXXZk">Code</a>&nbsp;notes&nbsp;are
plain text and are represented internally as-is.</li> plain text and are represented internally as-is.</li>
<li><a class="reference-link" href="#root/_help_81SGnPGMk7Xc">Geo Map</a>&nbsp;notes <li><a class="reference-link" href="#root/_help_81SGnPGMk7Xc">Geo Map</a>&nbsp;notes
@@ -22,10 +22,10 @@
</ul> </ul>
<p>Note that some information is also stored as&nbsp;<a class="reference-link" <p>Note that some information is also stored as&nbsp;<a class="reference-link"
href="#root/_help_0vhv7lsOLy82">Attachments</a>. For example&nbsp;<a class="reference-link" href="#root/_help_0vhv7lsOLy82">Attachments</a>. For example&nbsp;<a class="reference-link"
href="#root/_help_grjYqerjn243">Canvas</a>&nbsp;notes use the attachments href="#root/_help_grjYqerjn243">Canvas</a>&nbsp;notes use the attachments feature
feature to store the custom libraries, and alongside with&nbsp;<a class="reference-link" to store the custom libraries, and alongside with&nbsp;<a class="reference-link"
href="#root/_help_gBbsAeiuUxI5">Mind Map</a>&nbsp;and other similar note href="#root/_help_gBbsAeiuUxI5">Mind Map</a>&nbsp;and other similar note types
types it stores an SVG representation of the content for use in other features it stores an SVG representation of the content for use in other features
such as including in other notes, shared notes, etc.</p> such as including in other notes, shared notes, etc.</p>
<p>Here's part of the HTML representation of this note, as it's stored in <p>Here's part of the HTML representation of this note, as it's stored in
the database (but prettified).</p><pre><code class="language-text-x-trilium-auto">&lt;h2&gt; the database (but prettified).</p><pre><code class="language-text-x-trilium-auto">&lt;h2&gt;

View File

@@ -3,8 +3,8 @@
from your Trilium notes, making it accessible to others online.</p> from your Trilium notes, making it accessible to others online.</p>
<figure <figure
class="image"> class="image">
<img style="aspect-ratio:1144/660;" src="Sharing_image.png" width="1144" <img style="aspect-ratio:1144/660;" src="Sharing_image.png"
height="660"> width="1144" height="660">
</figure> </figure>
<h2>Features, interaction and limitations</h2> <h2>Features, interaction and limitations</h2>
@@ -149,7 +149,7 @@ class="image">
</td> </td>
</tr> </tr>
<tr> <tr>
<th><a class="reference-link" href="#root/_help_81SGnPGMk7Xc">Geo Map View</a> <th><a class="reference-link" href="#root/_help_81SGnPGMk7Xc">Geo Map</a>
</th> </th>
<td>Not supported.</td> <td>Not supported.</td>
<td>&nbsp;</td> <td>&nbsp;</td>
@@ -177,8 +177,8 @@ class="image">
<p>Some of these limitations may be addressed in future updates.</p> <p>Some of these limitations may be addressed in future updates.</p>
<h2>Prerequisites</h2> <h2>Prerequisites</h2>
<p>To use the sharing feature, you must have a&nbsp;<a class="reference-link" <p>To use the sharing feature, you must have a&nbsp;<a class="reference-link"
href="#root/_help_WOcw2SLH6tbX">Server Installation</a>&nbsp;of Trilium. href="#root/_help_WOcw2SLH6tbX">Server Installation</a>&nbsp;of Trilium. This
This is necessary because the notes will be hosted from the server.</p> is necessary because the notes will be hosted from the server.</p>
<h2>Sharing a note</h2> <h2>Sharing a note</h2>
<ol> <ol>
<li> <li>
@@ -186,7 +186,8 @@ class="image">
within the note's interface. Once sharing is enabled, an URL will appear, within the note's interface. Once sharing is enabled, an URL will appear,
which you can click to access the shared note.</p> which you can click to access the shared note.</p>
<p> <p>
<img src="Sharing_share-single-note.png" alt="Share Note"> <img src="Sharing_share-single-note.png"
alt="Share Note">
</p> </p>
</li> </li>
<li> <li>
@@ -207,9 +208,19 @@ class="image">
This allows you to manage and navigate through all the notes you have made This allows you to manage and navigate through all the notes you have made
public.</p> public.</p>
<h2>Security considerations</h2> <h2>Security considerations</h2>
<p>Shared notes are published on the open internet and can be accessed by <ul>
anyone with the URL. The URL's randomness does not provide security, so <li>Shared notes are published on the open internet and can be accessed by
it is crucial not to share sensitive information through this feature.</p> anyone with the URL unless the notes are password-protected.</li>
<li>The URL's randomness does not provide security, so it is crucial not to
share sensitive information through this feature.</li>
<li>Trilium takes precautions to protect your publicly shared instance from
leaking information for non-shared notes, including opening a separate
read-only connection to the&nbsp;<a class="reference-link" href="#root/_help_wX4HbRucYSDD">Database</a>.
Depending on your threat model, it might make more sense to use&nbsp;
<a
class="reference-link" href="#root/_help_ycBFjKrrwE9p">Exporting HTML for web publishing</a>&nbsp;and use battle-tested web servers
such as Nginx or Apache to serve static content.</li>
</ul>
<h3>Password protection</h3> <h3>Password protection</h3>
<p>To protect shared notes with a username and password, you can use the <code>#shareCredentials</code> attribute. <p>To protect shared notes with a username and password, you can use the <code>#shareCredentials</code> attribute.
Add this label to the note with the format <code>#shareCredentials="username:password"</code>. Add this label to the note with the format <code>#shareCredentials="username:password"</code>.
@@ -220,10 +231,10 @@ class="image">
it using your own CSS:</p> it using your own CSS:</p>
<ul> <ul>
<li><strong>Custom CSS</strong>: Link a CSS&nbsp;<a class="reference-link" <li><strong>Custom CSS</strong>: Link a CSS&nbsp;<a class="reference-link"
href="#root/_help_6f9hih2hXXZk">Code</a>&nbsp;note to the shared page by href="#root/_help_6f9hih2hXXZk">Code</a>&nbsp;note to the shared page by adding
adding a <code>~shareCss</code> relation to the note. If you want this style a <code>~shareCss</code> relation to the note. If you want this style to
to apply to the entire subtree, make the label inheritable. You can hide apply to the entire subtree, make the label inheritable. You can hide the
the CSS code note from the tree navigation by adding the <code>#shareHiddenFromTree</code> label.</li> CSS code note from the tree navigation by adding the <code>#shareHiddenFromTree</code> label.</li>
<li><strong>Omitting Default CSS</strong>: For extensive styling changes, <li><strong>Omitting Default CSS</strong>: For extensive styling changes,
use the <code>#shareOmitDefaultCss</code> label to avoid conflicts with Trilium's use the <code>#shareOmitDefaultCss</code> label to avoid conflicts with Trilium's
<a <a
@@ -279,6 +290,15 @@ for (const attr of parentNote.attributes) {
<li>Using slashes (<code>/</code>) within aliases to create subpaths is not <li>Using slashes (<code>/</code>) within aliases to create subpaths is not
supported.</li> supported.</li>
</ol> </ol>
<aside class="admonition tip">
<ul>
<li>To easily identify pages that don't have a share alias, run a&nbsp;
<a
class="reference-link" href="#root/_help_eIg8jdvaoNNd">Search</a>&nbsp;with <code>#!shareAlias</code>.</li>
<li>To be able to enter the share alias faster, consider using&nbsp;<a class="reference-link"
href="#root/_help_OFXdgB2nNk1F">Promoted Attributes</a>&nbsp;(for example <code>#label:shareAlias(inheritable)="promoted,alias=Slug,single,text"</code>).</li>
</ul>
</aside>
<h3>Setting a custom favicon</h3> <h3>Setting a custom favicon</h3>
<p>To customize the favicon for your shared pages, create a relation <code>~shareFavicon</code> pointing <p>To customize the favicon for your shared pages, create a relation <code>~shareFavicon</code> pointing
to a file note containing the favicon (e.g., in <code>.ico</code> format).</p> to a file note containing the favicon (e.g., in <code>.ico</code> format).</p>
@@ -299,7 +319,11 @@ for (const attr of parentNote.attributes) {
When viewed, the list of shared roots will be displayed at the bottom of When viewed, the list of shared roots will be displayed at the bottom of
the note.</p> the note.</p>
<h2>Attribute reference</h2> <h2>Attribute reference</h2>
<table> <table class="ck-table-resized">
<colgroup>
<col style="width:18.38%;">
<col style="width:81.62%;">
</colgroup>
<thead> <thead>
<tr> <tr>
<th>Attribute</th> <th>Attribute</th>
@@ -308,40 +332,40 @@ for (const attr of parentNote.attributes) {
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td><code>shareHiddenFromTree</code> <td><code>#shareHiddenFromTree</code>
</td> </td>
<td>this note is hidden from left navigation tree, but still accessible with <td>this note is hidden from left navigation tree, but still accessible with
its URL</td> its URL</td>
</tr> </tr>
<tr> <tr>
<td><code>shareExternalLink</code> <td><code>#shareExternalLink</code>
</td> </td>
<td>note will act as a link to an external website in the share tree</td> <td>note will act as a link to an external website in the share tree</td>
</tr> </tr>
<tr> <tr>
<td><code>shareAlias</code> <td><code>#shareAlias</code>
</td> </td>
<td>define an alias using which the note will be available under <code>https://your_trilium_host/share/[your_alias]</code> <td>define an alias using which the note will be available under <code>https://your_trilium_host/share/[your_alias]</code>
</td> </td>
</tr> </tr>
<tr> <tr>
<td><code>shareOmitDefaultCss</code> <td><code>#shareOmitDefaultCss</code>
</td> </td>
<td>default share page CSS will be omitted. Use when you make extensive styling <td>default share page CSS will be omitted. Use when you make extensive styling
changes.</td> changes.</td>
</tr> </tr>
<tr> <tr>
<td><code>shareRoot</code> <td><code>#shareRoot</code>
</td> </td>
<td>marks note which is served on /share root.</td> <td>marks note which is served on /share root.</td>
</tr> </tr>
<tr> <tr>
<td><code>shareDescription</code> <td><code>#shareDescription</code>
</td> </td>
<td>define text to be added to the HTML meta tag for description</td> <td>define text to be added to the HTML meta tag for description</td>
</tr> </tr>
<tr> <tr>
<td><code>shareRaw</code> <td><code>#shareRaw</code>
</td> </td>
<td>Note will be served in its raw format, without HTML wrapper. See also&nbsp; <td>Note will be served in its raw format, without HTML wrapper. See also&nbsp;
<a <a
@@ -349,7 +373,7 @@ for (const attr of parentNote.attributes) {
without setting an attribute.</td> without setting an attribute.</td>
</tr> </tr>
<tr> <tr>
<td><code>shareDisallowRobotIndexing</code> <td><code>#shareDisallowRobotIndexing</code>
</td> </td>
<td> <td>
<p>Indicates to web crawlers that the page should not be indexed of this <p>Indicates to web crawlers that the page should not be indexed of this
@@ -361,19 +385,19 @@ for (const attr of parentNote.attributes) {
</td> </td>
</tr> </tr>
<tr> <tr>
<td><code>shareCredentials</code> <td><code>#shareCredentials</code>
</td> </td>
<td>require credentials to access this shared note. Value is expected to be <td>require credentials to access this shared note. Value is expected to be
in format <code>username:password</code>. Don't forget to make this inheritable in format <code>username:password</code>. Don't forget to make this inheritable
to apply to child-notes/images.</td> to apply to child-notes/images.</td>
</tr> </tr>
<tr> <tr>
<td><code>shareIndex</code> <td><code>#shareIndex</code>
</td> </td>
<td>Note with this label will list all roots of shared notes.</td> <td>Note with this label will list all roots of shared notes.</td>
</tr> </tr>
<tr> <tr>
<td><code>shareHtmlLocation</code> <td><code>#shareHtmlLocation</code>
</td> </td>
<td>defines where custom HTML injected via <code>~shareHtml</code> relation <td>defines where custom HTML injected via <code>~shareHtml</code> relation
should be placed. Applied to the HTML snippet note itself. Format: <code>location:position</code> where should be placed. Applied to the HTML snippet note itself. Format: <code>location:position</code> where
@@ -383,6 +407,76 @@ for (const attr of parentNote.attributes) {
</tbody> </tbody>
</table> </table>
<h3>Customizing logo</h3>
<p>It's possible to adjust the logo which is displayed on the top-left of
the left pane.</p>
<table>
<thead>
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>~shareLogo</code>
</td>
<td>Relation set to an image to use as logo. The image must be part of the
share tree (it can be hidden if needed).</td>
</tr>
<tr>
<td><code>#shareLogoWidth</code>
</td>
<td>The width (in pixels, without unit) to set for the logo. Default is <code>53</code>.</td>
</tr>
<tr>
<td><code>#shareLogoHeight</code>
</td>
<td>The height (in pixels, without unit) to set for the logo. Default is <code>40</code>.</td>
</tr>
<tr>
<td><code>#shareRootLink</code>
</td>
<td>URL to navigate to when the logo is pressed.</td>
</tr>
</tbody>
</table>
<h3>Customizing OpenGraph</h3>
<table>
<thead>
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>#shareOpenGraphColor</code>
</td>
<td>This adjusts the <code>theme-color</code> meta-property.</td>
</tr>
<tr>
<td><code>#shareOpenGraphURL</code>
</td>
<td>This adjusts the <code>og:url</code> and <code>twitter:url</code> meta-properties.</td>
</tr>
<tr>
<td><code>#shareOpenGraphDomain</code>
</td>
<td>Adjusts the <code>twitter:domain</code> meta-property.</td>
</tr>
<tr>
<td><code>#shareOpenGraphImage</code>
<br><code>~shareOpenGraphImage</code>
</td>
<td>Can be either a label, case in which the value is passed on as-is, or
it can be a relation to an image&nbsp;<a class="reference-link" href="#root/_help_W8vYD3Q1zjCR">File</a>.
This controls the <code>og:image</code> meta-property.</td>
</tr>
</tbody>
</table>
<h2>Credits</h2> <h2>Credits</h2>
<p>Since v0.95.0, a new theme was introduced (and enabled by default) which <p>Since v0.95.0, a new theme was introduced (and enabled by default) which
greatly improves the visual aspect of the Share feature, as well as its greatly improves the visual aspect of the Share feature, as well as its

View File

@@ -0,0 +1,58 @@
<p>As described in&nbsp;<a class="reference-link" href="#root/_help_R9pX4DGra2Vt">Sharing</a>,
Trilium can act as a public server in which the shared notes are displayed
in read-only mode. While this can work in most cases, it's generally not
meant for high-traffic websites and since it's running on a Node.js server
it can be potentially exploited.</p>
<p>Another alternative is to generate static HTML files (just like other
static site generators such as <a href="https://www.mkdocs.org/">MkDocs</a>).
Since the normal HTML ZIP export does not contain any styling or additional
functionality, Trilium provides a way to export the same layout and style
as the&nbsp;<a class="reference-link" href="#root/_help_R9pX4DGra2Vt">Sharing</a>&nbsp;function
into static HTML files.</p>
<p>Apart from the enhanced security, these HTML files are also easy to deploy
on “serverless” deployments such as GitHub Pages or CloudFlare Pages and
cache very easily.</p>
<aside class="admonition tip">
<p>Trilium's documentation, available at <a href="https://docs.triliumnotes.org/">docs.triliumnotes.org</a> is
built using this function of exporting to static HTML files which are then
deployed automatically to CloudFlare Pages.</p>
<p>The process is <a href="https://github.com/TriliumNext/Trilium/blob/main/apps/edit-docs/src/build-docs.ts">automated</a> by
importing the Markdown documentation and exporting it via a script to the
static web format.</p>
</aside>
<h2>Differences from normal sharing</h2>
<p>Apart from normal&nbsp;<a class="reference-link" href="#root/_help_R9pX4DGra2Vt">Sharing</a>,
exporting to static HTML files comes with a few subtle differences:</p>
<ul>
<li>The URL structure is different. Where in normal sharing it's something
along the way of <code>example.com/share/noteid</code>, the notes follow
an hierarchical structure, such as <code>docs.triliumnotes.org/user-guide/concepts/navigation/tree-concepts</code>.</li>
<li>The <code>favicon.ico</code> is not handled automatically, it needs to be
manually added on the server after the export is generated.</li>
<li>The “Last updated” for notes is not available.</li>
<li>The search functionality works slightly different since the normal one
requires an active API to work. In the static export, search still works
but uses a different mechanism so results might be different.</li>
</ul>
<h2>Differences from normal .zip export</h2>
<ul>
<li>The name of the files/URLs will prefer <code>shareAlias</code> to allow
for clean URLs.</li>
<li>The export requires a functional web server as the pages will not render
properly if accessed locally via a web browser due to the use of module
scripts.</li>
</ul>
<h2>Testing locally</h2>
<p>As mentioned previously, the exported static pages require a website to
function. In order to test locally, a web server needs to be used.</p>
<p>One example is to use the Node.js-based <a href="https://www.npmjs.com/package/http-server"><code>http-server</code></a> which
can be installed via:</p><pre><code class="language-text-x-trilium-auto">npm i -g http-server</code></pre>
<p>Once installed simply:</p>
<ol>
<li>Extract the exported .zip file.</li>
<li>Inside the extracted directory, run <code>http-server</code>.</li>
<li>Access the indicated address (e.g. <a href="http://localhost:8080">http://localhost:8080</a>).</li>
</ol>
<h2>Automation</h2>
<p><a class="reference-link" href="#root/_help_pgxEVkzLl1OP">ETAPI (REST API)</a>&nbsp;could
potentially be used to automate an export on a scheduled task.</p>

View File

@@ -0,0 +1,18 @@
<p>It might be desirable to only expose the share functionality of Trilium
to the Internet, and keep the application accessible only within a local
network or via VPN.</p>
<p>To do so, a reverse proxy is required.</p>
<h2>Caddy</h2><pre><code class="language-text-x-trilium-auto">http://domain.com {
reverse_proxy /share http://localhost:8080/share
}</code></pre>
<p>This is for newer versions where the share functionality is isolated,
for older versions it's required to also include <code>/assets</code>.<sup><a href="#fn2b8mg20aol8">[1]</a></sup>
</p>
<ol>
<li>
<p><sup><strong><a href="#fnref2b8mg20aol8">^</a></strong></sup>
</p>
<p><a href="https://github.com/orgs/TriliumNext/discussions/7341#discussioncomment-14679897">https://github.com/orgs/TriliumNext/discussions/7341#discussioncomment-14679897</a>
</p>
</li>
</ol>

View File

@@ -39,7 +39,7 @@
</li> </li>
<li><a href="#root/_help_QEAPj01N5f7w">Reference links</a> <li><a href="#root/_help_QEAPj01N5f7w">Reference links</a>
</li> </li>
<li><a href="#root/_help_NwBbFdNZ9h7O">Admonitions</a>, we ended up creating <li><a href="#root/_help_NwBbFdNZ9h7O">Admonitions</a>, we ended up creating our
our own plugin but <a href="https://github.com/aarkue/ckeditor5-admonition">aarkue/ckeditor5-admonition</a> was own plugin but <a href="https://github.com/aarkue/ckeditor5-admonition">aarkue/ckeditor5-admonition</a> was
a good inspiration (including the toolbar icon).</li> a good inspiration (including the toolbar icon).</li>
</ul> </ul>

View File

@@ -1,5 +1,5 @@
<p><a href="https://excalidraw.com/">Excalidraw</a> is the technology behind <p><a href="https://excalidraw.com/">Excalidraw</a> is the technology behind
the&nbsp;<a href="#root/_help_grjYqerjn243">Canvas</a>&nbsp;notes. The the&nbsp;<a href="#root/_help_grjYqerjn243">Canvas</a>&nbsp;notes. The source
source code of the library is available on <a href="https://github.com/excalidraw/excalidraw">GitHub</a>.</p> code of the library is available on <a href="https://github.com/excalidraw/excalidraw">GitHub</a>.</p>
<p>We are using an unmodified version of it, so it shares the same <a href="https://github.com/excalidraw/excalidraw/issues">issues</a> as <p>We are using an unmodified version of it, so it shares the same <a href="https://github.com/excalidraw/excalidraw/issues">issues</a> as
the original.</p> the original.</p>

View File

@@ -3,10 +3,10 @@
main effects:</p> main effects:</p>
<ol> <ol>
<li><strong>Attribute Inheritance</strong>: All attributes from the template <li><strong>Attribute Inheritance</strong>: All attributes from the template
note are <a href="#root/_help_bwZpz2ajCEwO">inherited</a> by the instance note are <a href="#root/_help_bwZpz2ajCEwO">inherited</a> by the instance notes.
notes. Even attributes with <code>#isInheritable=false</code> are inherited Even attributes with <code>#isInheritable=false</code> are inherited by the
by the instance notes, although only inheritable attributes are further instance notes, although only inheritable attributes are further inherited
inherited by the children of the instance notes.</li> by the children of the instance notes.</li>
<li><strong>Content Duplication</strong>: The content of the template note <li><strong>Content Duplication</strong>: The content of the template note
is copied to the instance note, provided the instance note is empty at is copied to the instance note, provided the instance note is empty at
the time of template assignment.</li> the time of template assignment.</li>
@@ -32,7 +32,8 @@
all attributes from the template are inherited.</p> all attributes from the template are inherited.</p>
<p>To create an instance note through the UI:</p> <p>To create an instance note through the UI:</p>
<p> <p>
<img src="Templates_template-create-.png" alt="show child note templates"> <img src="Templates_template-create-.png"
alt="show child note templates">
</p> </p>
<p>For the template to appear in the menu, the template note must have the <code>#template</code> label. <p>For the template to appear in the menu, the template note must have the <code>#template</code> label.
Do not confuse this with the <code>~template</code> relation, which links Do not confuse this with the <code>~template</code> relation, which links

View File

@@ -0,0 +1,30 @@
<p>Trilium natively supports the following formats for both import and export.</p>
<ul>
<li>HTML:
<ul>
<li>This is the main format used by Trilium, where standard tags are used
to represent basic formatting and layout (e.g. <code>&lt;strong&gt;</code>, <code>&lt;table&gt;</code>, <code>&lt;pre&gt;</code>).</li>
<li>Note that HTML is not a standardized format so some more specific features
such as admonitions or&nbsp;<a class="reference-link" href="#root/_help_hrZ1D00cLbal">Internal (reference) links</a>&nbsp;might
not be supported by other applications.</li>
</ul>
</li>
<li><a class="reference-link" href="#root/_help_Oau6X9rCuegd">Markdown</a>
<ul>
<li>Most of the formatting is preserved, see&nbsp;<a class="reference-link"
href="#root/_help_rJ9grSgoExl9">Supported syntax</a>.</li>
</ul>
</li>
<li>OPML (Outliner Interchange Format)
<ul>
<li>Supports both OPML v1.0 for plain text and v2.0 with HTML support.</li>
</ul>
</li>
</ul>
<p>To import from other applications, see the dedicated pages:</p>
<ul>
<li><a class="reference-link" href="#root/_help_syuSEKf2rUGr">Evernote</a>
</li>
<li><a class="reference-link" href="#root/_help_GnhlmrATVqcH">OneNote</a>
</li>
</ul>

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