mirror of
https://github.com/zadam/trilium.git
synced 2026-04-06 12:09:00 +02:00
Compare commits
2469 Commits
web-clippe
...
feature/cl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d873accf3e | ||
|
|
94b448863c | ||
|
|
32acc8555d | ||
|
|
d68ad84155 | ||
|
|
45e82b7f33 | ||
|
|
55ad0fe9f0 | ||
|
|
559815273e | ||
|
|
af76740fd9 | ||
|
|
7dadd50bfe | ||
|
|
dd4cab22c1 | ||
|
|
c4d3e776a1 | ||
|
|
19bb7f5ddb | ||
|
|
d212120f9b | ||
|
|
42da1872e7 | ||
|
|
a080b50c45 | ||
|
|
6d31e9b028 | ||
|
|
b606afa858 | ||
|
|
f9446304b3 | ||
|
|
fbe312d580 | ||
|
|
8d383caaff | ||
|
|
6caf4fa7ce | ||
|
|
606d58b08c | ||
|
|
09258179f0 | ||
|
|
40e986b188 | ||
|
|
37e47041bf | ||
|
|
543438bca0 | ||
|
|
b31290c1fc | ||
|
|
d41111a209 | ||
|
|
828b523382 | ||
|
|
32409ecbee | ||
|
|
3ca2cec63a | ||
|
|
1ed2db0c82 | ||
|
|
2423b74dd0 | ||
|
|
3f781ea298 | ||
|
|
30c5c49aef | ||
|
|
9421e39c34 | ||
|
|
c46805cf4f | ||
|
|
f181343fca | ||
|
|
8a512e4f73 | ||
|
|
06a3750168 | ||
|
|
35c1a5642d | ||
|
|
f29df2ad28 | ||
|
|
75a5714451 | ||
|
|
2882863b5b | ||
|
|
773b6cca14 | ||
|
|
f97370c8f7 | ||
|
|
afad96a375 | ||
|
|
9e5ababfcb | ||
|
|
dc1e0e8db4 | ||
|
|
1e861d1125 | ||
|
|
baa93cb371 | ||
|
|
61dcc8db47 | ||
|
|
2c557eb015 | ||
|
|
f5a80526ab | ||
|
|
27e1455874 | ||
|
|
278d8428de | ||
|
|
164e667158 | ||
|
|
28b31791e7 | ||
|
|
9515768e62 | ||
|
|
fbbad19cb7 | ||
|
|
eab353ca2e | ||
|
|
cb9ee20763 | ||
|
|
dac12532bc | ||
|
|
1d99734ea0 | ||
|
|
3e764c762a | ||
|
|
7be51168d3 | ||
|
|
530d193734 | ||
|
|
aba5ff75af | ||
|
|
9e34fcb8a8 | ||
|
|
055dd9cd01 | ||
|
|
1437fdc4e3 | ||
|
|
e5c67b16ac | ||
|
|
94987314b8 | ||
|
|
f4f881e839 | ||
|
|
92f5901b95 | ||
|
|
1c0cb601cb | ||
|
|
109f06f8bb | ||
|
|
bf23439792 | ||
|
|
b7a0bc08be | ||
|
|
9d6a26dda9 | ||
|
|
a01ce2c3fc | ||
|
|
ba6298af27 | ||
|
|
3d17e0aa75 | ||
|
|
7e18166160 | ||
|
|
40d8571797 | ||
|
|
25e04e358a | ||
|
|
e473e12c0e | ||
|
|
dfb20df16f | ||
|
|
efcbf439ee | ||
|
|
514f7fedbc | ||
|
|
ee88fedacd | ||
|
|
2933f9c49f | ||
|
|
1cca5d989c | ||
|
|
9981020728 | ||
|
|
56843dcf8b | ||
|
|
e661118192 | ||
|
|
54a7de6cb0 | ||
|
|
13b1e0afbb | ||
|
|
4a48796142 | ||
|
|
9a4fef80b9 | ||
|
|
79dc4b39f1 | ||
|
|
9bc18b774e | ||
|
|
465c36407c | ||
|
|
b99486259e | ||
|
|
ecf5475966 | ||
|
|
90822cc8a3 | ||
|
|
5c46209ddc | ||
|
|
176de87b6b | ||
|
|
7f199c527b | ||
|
|
2432e230c5 | ||
|
|
fc1be0d23d | ||
|
|
d084b9e941 | ||
|
|
6678c0af49 | ||
|
|
37754ecf31 | ||
|
|
709d9633a1 | ||
|
|
7ca57efaad | ||
|
|
342fedca1c | ||
|
|
b1262b0448 | ||
|
|
626aca5181 | ||
|
|
8204322b46 | ||
|
|
70ce86cd53 | ||
|
|
ed3b86cd49 | ||
|
|
b371675494 | ||
|
|
ff06c8e7bd | ||
|
|
8ff41d8fa9 | ||
|
|
5f5b9ba8cb | ||
|
|
a3221470e7 | ||
|
|
0e115bd92a | ||
|
|
95a50c0ba6 | ||
|
|
e323ccb259 | ||
|
|
3294d0b93b | ||
|
|
55e8694990 | ||
|
|
b3888b391a | ||
|
|
f2907ab40f | ||
|
|
7e7218cbdf | ||
|
|
e41c9cb7f4 | ||
|
|
20f96c88e4 | ||
|
|
66afda1343 | ||
|
|
c5a6212065 | ||
|
|
3e7e355575 | ||
|
|
fb9eb3e4b5 | ||
|
|
a35ac82f24 | ||
|
|
66add6b9e4 | ||
|
|
fe81bde1c9 | ||
|
|
6b223098ab | ||
|
|
788e867a6c | ||
|
|
7ad8d307dc | ||
|
|
b6d4ac5ada | ||
|
|
0a069854e5 | ||
|
|
8770afa211 | ||
|
|
312c193b1a | ||
|
|
3700e2bb93 | ||
|
|
a9be72081c | ||
|
|
f57b57791b | ||
|
|
5cf249afa4 | ||
|
|
3f24627f67 | ||
|
|
806c3fdc00 | ||
|
|
e81ee88cda | ||
|
|
db46f63337 | ||
|
|
395102026d | ||
|
|
b62c078de6 | ||
|
|
47c1c08bed | ||
|
|
a23c4f03e0 | ||
|
|
5a6da60fe8 | ||
|
|
588c47aee7 | ||
|
|
36fd51219a | ||
|
|
bc43a79d97 | ||
|
|
5c22c029d7 | ||
|
|
126d9be9d8 | ||
|
|
09be2822e0 | ||
|
|
a93029f789 | ||
|
|
48cf214f4c | ||
|
|
6834bad7b0 | ||
|
|
855458bab0 | ||
|
|
5be48bf8c8 | ||
|
|
80ac0eea62 | ||
|
|
5995ec468d | ||
|
|
e9a876e8f0 | ||
|
|
90223a5ffd | ||
|
|
8331daae5b | ||
|
|
027280954a | ||
|
|
5138a63d23 | ||
|
|
be95cf5510 | ||
|
|
4082328c2b | ||
|
|
729e840af2 | ||
|
|
e4a38fe277 | ||
|
|
a5cb9c7de6 | ||
|
|
7543109583 | ||
|
|
bff2f10fa4 | ||
|
|
37120bf153 | ||
|
|
b88c85db5e | ||
|
|
c682e3dfc0 | ||
|
|
6c0bbb7778 | ||
|
|
bde8c40d16 | ||
|
|
c4d352ba26 | ||
|
|
cc1c0696ad | ||
|
|
186b784004 | ||
|
|
5441d15654 | ||
|
|
bd61af89ae | ||
|
|
eddd77f97f | ||
|
|
ab0338c318 | ||
|
|
1892bec772 | ||
|
|
bf7070a7da | ||
|
|
314331b956 | ||
|
|
6ff949fdb5 | ||
|
|
21d24b7bea | ||
|
|
8522151949 | ||
|
|
3720099b1d | ||
|
|
073873c33c | ||
|
|
25bf62faa3 | ||
|
|
e54cb9c626 | ||
|
|
208330d73a | ||
|
|
343e3e67ed | ||
|
|
6447003927 | ||
|
|
cbdf925703 | ||
|
|
7440e4a610 | ||
|
|
54a5c3fac0 | ||
|
|
42e60da127 | ||
|
|
325dc9c8a8 | ||
|
|
877427f0db | ||
|
|
1a64e7ba63 | ||
|
|
7dfa59a845 | ||
|
|
62fd19368d | ||
|
|
058518fcba | ||
|
|
6e1d10f052 | ||
|
|
af988fec69 | ||
|
|
dd5979aec8 | ||
|
|
657fbeba79 | ||
|
|
4a0d45ad7d | ||
|
|
f47ec21aa8 | ||
|
|
be40d65982 | ||
|
|
faebacb883 | ||
|
|
df0efc39d5 | ||
|
|
57a299de8f | ||
|
|
be724ec45f | ||
|
|
98c70e662d | ||
|
|
4ed9b84d75 | ||
|
|
b7f05acfd3 | ||
|
|
45ebb37a01 | ||
|
|
f77adea800 | ||
|
|
88b855ed47 | ||
|
|
4fa689873f | ||
|
|
d76b9329fc | ||
|
|
1c43ddd3a9 | ||
|
|
1aedbcef94 | ||
|
|
295280861a | ||
|
|
9f70e20fa0 | ||
|
|
a20e96eb6a | ||
|
|
9b238a3ac6 | ||
|
|
0167597ae0 | ||
|
|
a4f6071c8b | ||
|
|
aa0b0bd249 | ||
|
|
c6185a51c2 | ||
|
|
9c9c717025 | ||
|
|
00342ed569 | ||
|
|
1f0a6b4a79 | ||
|
|
3e767b4723 | ||
|
|
e539b11718 | ||
|
|
2fca8c3850 | ||
|
|
0d3f70a231 | ||
|
|
a3a52aaafe | ||
|
|
a6c4401973 | ||
|
|
2e34ec2a17 | ||
|
|
927afec83c | ||
|
|
8bd1da0552 | ||
|
|
4f571fc3d7 | ||
|
|
c3f8e523cc | ||
|
|
9878f76f65 | ||
|
|
23799562ae | ||
|
|
f441a145b5 | ||
|
|
7189764916 | ||
|
|
70bc707e3a | ||
|
|
90215bde8b | ||
|
|
2b3ae5285b | ||
|
|
9b6d0db5b6 | ||
|
|
723da88ff8 | ||
|
|
5bcf2f4356 | ||
|
|
42680574c1 | ||
|
|
82e723c915 | ||
|
|
ac9560d9d7 | ||
|
|
32f95efa54 | ||
|
|
3da416908d | ||
|
|
d79d2e9ad2 | ||
|
|
30ba36894d | ||
|
|
b747402352 | ||
|
|
0398a9bda3 | ||
|
|
72dff88384 | ||
|
|
0314a9755f | ||
|
|
bc967b15b2 | ||
|
|
8ac686a19f | ||
|
|
aafecaa3a4 | ||
|
|
bb23b08b15 | ||
|
|
476396da53 | ||
|
|
5112971848 | ||
|
|
2d852c38ec | ||
|
|
f163cacddc | ||
|
|
6ecb1cb2b0 | ||
|
|
24fefe0711 | ||
|
|
e5eba69d0d | ||
|
|
bdd2b7e317 | ||
|
|
ad29375975 | ||
|
|
cf73a4ef43 | ||
|
|
60a2621928 | ||
|
|
b4e5d9dbc2 | ||
|
|
650b700415 | ||
|
|
212f742164 | ||
|
|
6f2296eb05 | ||
|
|
722efd74c2 | ||
|
|
5dc9b6defe | ||
|
|
605fbaaa4a | ||
|
|
23b46865c5 | ||
|
|
ac310eaaf5 | ||
|
|
010f59df8a | ||
|
|
44a5dccd61 | ||
|
|
acbbf021a1 | ||
|
|
731fece258 | ||
|
|
8d255d1b89 | ||
|
|
64318c92e7 | ||
|
|
49fc7e48d4 | ||
|
|
ec9fa0baee | ||
|
|
ba91d91fd1 | ||
|
|
0aa1fea9dc | ||
|
|
1551f01f49 | ||
|
|
d46748602e | ||
|
|
9cfad0fe6a | ||
|
|
6d3cff84a4 | ||
|
|
010230645c | ||
|
|
5979290f0c | ||
|
|
e648872257 | ||
|
|
e4910ae31a | ||
|
|
d8ea0c7bcf | ||
|
|
6393d2c188 | ||
|
|
d9f0a163cf | ||
|
|
6534beec14 | ||
|
|
6d050340ee | ||
|
|
0e7f7fa208 | ||
|
|
287be0bd25 | ||
|
|
18cf2ff873 | ||
|
|
b626fb448b | ||
|
|
38f6fb5a7f | ||
|
|
5846df7d02 | ||
|
|
9462d6109c | ||
|
|
f0c93cd06e | ||
|
|
14e0507689 | ||
|
|
393b90f7be | ||
|
|
47ee5c1d84 | ||
|
|
1cb6f2d351 | ||
|
|
bb72b0cdfc | ||
|
|
ab2467b074 | ||
|
|
2d652523bb | ||
|
|
55df50253f | ||
|
|
d009914ff9 | ||
|
|
5e97222206 | ||
|
|
038705483b | ||
|
|
10c9ba5783 | ||
|
|
a1d008688b | ||
|
|
78a043c536 | ||
|
|
acdc840f17 | ||
|
|
63d4b8894b | ||
|
|
23ccbf9642 | ||
|
|
a5793ff768 | ||
|
|
a84e2f72c3 | ||
|
|
0d805a01c1 | ||
|
|
ba90a1c396 | ||
|
|
465927e730 | ||
|
|
74f3c14a62 | ||
|
|
2eb40c7b42 | ||
|
|
457c5f85af | ||
|
|
c6ef3d774a | ||
|
|
7f1e4c0969 | ||
|
|
e55cd7841f | ||
|
|
8b5b32fecb | ||
|
|
819c9a7506 | ||
|
|
4b3ef50d4b | ||
|
|
bc945c5196 | ||
|
|
57ea3c576e | ||
|
|
450e15f558 | ||
|
|
a66ef977a0 | ||
|
|
96a474adc1 | ||
|
|
1fe22aeef1 | ||
|
|
a97897527e | ||
|
|
86bbb4d885 | ||
|
|
041f8314ab | ||
|
|
dffdeff798 | ||
|
|
6f08dc3ada | ||
|
|
07e1b86586 | ||
|
|
2deda8947e | ||
|
|
adb9532d1b | ||
|
|
a2959342a9 | ||
|
|
f528833232 | ||
|
|
a6b8785341 | ||
|
|
6e7a14fb3e | ||
|
|
708180a037 | ||
|
|
04efa2742c | ||
|
|
0e2c96d544 | ||
|
|
a45c1818a5 | ||
|
|
f04f47d17a | ||
|
|
cabce14a49 | ||
|
|
5f669684c4 | ||
|
|
4d169809bd | ||
|
|
2929d64fa0 | ||
|
|
20311d31f6 | ||
|
|
c13b68ef42 | ||
|
|
8eff623b67 | ||
|
|
f4b9207379 | ||
|
|
90930e19e7 | ||
|
|
8c0dacd6d7 | ||
|
|
c617bea45a | ||
|
|
bac25c9173 | ||
|
|
acfc3f617e | ||
|
|
4c6aa3baf1 | ||
|
|
ed2d72c008 | ||
|
|
3cb82c58a1 | ||
|
|
d87e3cb24d | ||
|
|
8a4c46c40b | ||
|
|
5f3dcdb7e5 | ||
|
|
8964c316b8 | ||
|
|
230f682a27 | ||
|
|
8f25d048df | ||
|
|
90fcf3153c | ||
|
|
069c4cf5c4 | ||
|
|
f10e55ad71 | ||
|
|
a934c7842b | ||
|
|
a2b6bc0493 | ||
|
|
24e418bf7c | ||
|
|
3fc3ef4ea8 | ||
|
|
952d6b9851 | ||
|
|
841c58ca8c | ||
|
|
41164add15 | ||
|
|
f4858d3684 | ||
|
|
be60479122 | ||
|
|
948f160d14 | ||
|
|
768c733f92 | ||
|
|
1a02be7c91 | ||
|
|
ac75f6f7a6 | ||
|
|
b2befb4feb | ||
|
|
3e49399f82 | ||
|
|
eaaaf3effd | ||
|
|
f2cd1be3af | ||
|
|
b4fcf41420 | ||
|
|
5feccae2a0 | ||
|
|
d28318005d | ||
|
|
fcf39d7786 | ||
|
|
5e9fc614d7 | ||
|
|
a860803cc4 | ||
|
|
c40f5953fa | ||
|
|
241282296e | ||
|
|
8a8143167f | ||
|
|
12797293f0 | ||
|
|
af0eb9551a | ||
|
|
8a492450da | ||
|
|
f3cb356b2b | ||
|
|
8ea1b7afba | ||
|
|
911c1bdd0c | ||
|
|
41f3274c7e | ||
|
|
0fc62dda78 | ||
|
|
e482c911c4 | ||
|
|
0e59126c52 | ||
|
|
abbe6437a9 | ||
|
|
f2d67d4128 | ||
|
|
7c9e02996e | ||
|
|
dc560edb7c | ||
|
|
f7bbcee386 | ||
|
|
2182d4b440 | ||
|
|
c43e10c4af | ||
|
|
25037324ab | ||
|
|
b8f9916d13 | ||
|
|
ed8b9cc943 | ||
|
|
efbe7e0a21 | ||
|
|
46dd500d37 | ||
|
|
261c95fb06 | ||
|
|
41a122f722 | ||
|
|
490406e12a | ||
|
|
d12677094d | ||
|
|
3c69792744 | ||
|
|
395e79adbf | ||
|
|
d5e56d8e29 | ||
|
|
e4c4873aa7 | ||
|
|
293da1d4ef | ||
|
|
d1c206a05a | ||
|
|
37b370511f | ||
|
|
734ef5533a | ||
|
|
0eb9b9fdac | ||
|
|
7817890cfe | ||
|
|
23dbedd139 | ||
|
|
2c8e2251fa | ||
|
|
4c27ed9997 | ||
|
|
d2fd1362c0 | ||
|
|
45e57f0d5e | ||
|
|
660facea96 | ||
|
|
9fa2e940d6 | ||
|
|
0ffcfb8f43 | ||
|
|
ad1b3df74e | ||
|
|
0ccf10bbbb | ||
|
|
59c007e801 | ||
|
|
0654bc1049 | ||
|
|
9fabefc847 | ||
|
|
e70ded0be1 | ||
|
|
16806275e0 | ||
|
|
e8214c3aae | ||
|
|
3a8e148301 | ||
|
|
a0b546614f | ||
|
|
5fcea86b94 | ||
|
|
d8c00ed6c0 | ||
|
|
863e68ec88 | ||
|
|
046ee343dc | ||
|
|
2db9e376d5 | ||
|
|
9458128ad6 | ||
|
|
89638e3f56 | ||
|
|
8d492d7d4b | ||
|
|
246c561b64 | ||
|
|
88295f2462 | ||
|
|
d2d4e1cbac | ||
|
|
261e5b59e0 | ||
|
|
fa7ec01329 | ||
|
|
4c4a29f9cf | ||
|
|
9ddcaf4552 | ||
|
|
c806a99fbc | ||
|
|
ad91d360ce | ||
|
|
cf8d7cd71f | ||
|
|
f370799b1d | ||
|
|
f8655b5de4 | ||
|
|
ed3a5778d0 | ||
|
|
19d213059f | ||
|
|
276a802ab2 | ||
|
|
e756ded89f | ||
|
|
b551f0fe2d | ||
|
|
f6e8bdb0fd | ||
|
|
9029ea8085 | ||
|
|
d61ade9fe9 | ||
|
|
aa1fe549c7 | ||
|
|
e3701bbcb4 | ||
|
|
fb7fc4bf0c | ||
|
|
dc50ca157d | ||
|
|
ff2e775b5e | ||
|
|
584d48c5ab | ||
|
|
25df43b0be | ||
|
|
1af1fcd148 | ||
|
|
516f9aad45 | ||
|
|
79a420de0f | ||
|
|
ac213b6664 | ||
|
|
ff2d74029a | ||
|
|
31ac1d3f2d | ||
|
|
2c32382ca6 | ||
|
|
0d94c20deb | ||
|
|
9904df1611 | ||
|
|
2d945d4fb2 | ||
|
|
c1f9a22bf3 | ||
|
|
22e2e2339e | ||
|
|
b6435bbfc9 | ||
|
|
63387cb958 | ||
|
|
a8d104ec57 | ||
|
|
10377b527f | ||
|
|
4413566e14 | ||
|
|
6c295611cc | ||
|
|
c1c98a6955 | ||
|
|
6e222bb901 | ||
|
|
82b8601e0b | ||
|
|
47e515bc77 | ||
|
|
eef35c3a5f | ||
|
|
a18d0484c5 | ||
|
|
4eaa3d7ac1 | ||
|
|
ad24cf9ab9 | ||
|
|
5467d7719d | ||
|
|
875b3a3f9a | ||
|
|
4ab6a66c75 | ||
|
|
53e157567d | ||
|
|
5725680d3a | ||
|
|
07fe884fd8 | ||
|
|
8d57a593d8 | ||
|
|
fb9f33b9ff | ||
|
|
2c690d4dd2 | ||
|
|
7db7dc287f | ||
|
|
dece273c2b | ||
|
|
bf7449bc90 | ||
|
|
6f3c9e2883 | ||
|
|
49248a636a | ||
|
|
f51b0eb4de | ||
|
|
f0d06815ec | ||
|
|
070701ee9e | ||
|
|
57fefaae1d | ||
|
|
1d109f592b | ||
|
|
29b01c3fe6 | ||
|
|
6cd263a897 | ||
|
|
c9ca1de271 | ||
|
|
c369ba416c | ||
|
|
4b3d923d29 | ||
|
|
64c3d0b36d | ||
|
|
0fdc3590dc | ||
|
|
26fd6a573d | ||
|
|
59d8961111 | ||
|
|
9b733849a9 | ||
|
|
133b847b15 | ||
|
|
ecdbed6bac | ||
|
|
d1deccc23c | ||
|
|
c71d8a87b9 | ||
|
|
0614d92597 | ||
|
|
9ab7e8e2b7 | ||
|
|
0a5543cc72 | ||
|
|
6d000d7b7c | ||
|
|
ac4ca16e85 | ||
|
|
e248d93e29 | ||
|
|
acd786da67 | ||
|
|
ef19d6260c | ||
|
|
638e1ebd1d | ||
|
|
0c5efc3dcb | ||
|
|
a774218429 | ||
|
|
e305be9e75 | ||
|
|
f267dd5fc1 | ||
|
|
6ba736b83f | ||
|
|
5eb8715295 | ||
|
|
7654be5132 | ||
|
|
3f4358a422 | ||
|
|
b3ca412bbd | ||
|
|
d1f60840a2 | ||
|
|
a337ace856 | ||
|
|
0b6f6dee7f | ||
|
|
93f1743432 | ||
|
|
3fb4ab1a31 | ||
|
|
8970d02404 | ||
|
|
b671aa6204 | ||
|
|
7ffb8b0202 | ||
|
|
6564ea2738 | ||
|
|
0a673d2f1b | ||
|
|
05eea0d1f1 | ||
|
|
1215fbf3e1 | ||
|
|
ea206116cb | ||
|
|
7d87c89668 | ||
|
|
b0431f2338 | ||
|
|
81f02209ea | ||
|
|
124d456c60 | ||
|
|
76fc9eaeb0 | ||
|
|
a4b7f54c64 | ||
|
|
53192d202d | ||
|
|
6896ed2c70 | ||
|
|
5a96b9c48d | ||
|
|
6113bfc57f | ||
|
|
9d7bc20f26 | ||
|
|
79788937b9 | ||
|
|
66873f16f2 | ||
|
|
532e001ef0 | ||
|
|
17991bf31f | ||
|
|
2b21b1f75e | ||
|
|
dae1f9302c | ||
|
|
33365cdaf1 | ||
|
|
3ac66ffe72 | ||
|
|
81baf13720 | ||
|
|
e0e96350d6 | ||
|
|
c539c21ced | ||
|
|
3f7f6cf982 | ||
|
|
271d87ae33 | ||
|
|
533a77e606 | ||
|
|
77cf2d4dd9 | ||
|
|
890cb247c1 | ||
|
|
8d7f4dd0fa | ||
|
|
00c4933344 | ||
|
|
cd9b46e1c7 | ||
|
|
b356b355ca | ||
|
|
d1aebb7bb0 | ||
|
|
6cbb595ae8 | ||
|
|
fcf238bc35 | ||
|
|
8c82468ecc | ||
|
|
965905ce00 | ||
|
|
ed280775bd | ||
|
|
8834899012 | ||
|
|
55dea474e9 | ||
|
|
bc74455a64 | ||
|
|
2d0b28367f | ||
|
|
7d8a3e2811 | ||
|
|
79e5d9595a | ||
|
|
1f0fa57218 | ||
|
|
0310626025 | ||
|
|
fefbb40c03 | ||
|
|
12f89078b8 | ||
|
|
8d873c5869 | ||
|
|
27f4ac1d03 | ||
|
|
d533360903 | ||
|
|
49f5dc1c26 | ||
|
|
16419ed4ac | ||
|
|
1595d1b5c9 | ||
|
|
50eb11997c | ||
|
|
d974dfbc31 | ||
|
|
e9b63e50d4 | ||
|
|
b6efb7c9ab | ||
|
|
f84479b1c2 | ||
|
|
8597fa560b | ||
|
|
b29ab93fd5 | ||
|
|
225cdaff46 | ||
|
|
61dfba8c32 | ||
|
|
4fee91d219 | ||
|
|
12e4f76a8b | ||
|
|
ec30598397 | ||
|
|
fdd2cc77e6 | ||
|
|
6f5c618bcd | ||
|
|
8041112414 | ||
|
|
40ab2bc798 | ||
|
|
3a3029cf3a | ||
|
|
e7d1c75cdb | ||
|
|
bc907ee6ad | ||
|
|
0bff3f1fbc | ||
|
|
377864b2c6 | ||
|
|
3db13df245 | ||
|
|
a2e09b40fa | ||
|
|
aa590753d5 | ||
|
|
1c8519d7ec | ||
|
|
686a614bfa | ||
|
|
01261220e3 | ||
|
|
1bf92ab19a | ||
|
|
c0d0d1868d | ||
|
|
da2dec16cc | ||
|
|
787ef7d513 | ||
|
|
dcb0ce79e6 | ||
|
|
9d8202539d | ||
|
|
c46af4bca9 | ||
|
|
610f6652df | ||
|
|
b33635381b | ||
|
|
f20af8cac9 | ||
|
|
29f3b987aa | ||
|
|
e9987b40e6 | ||
|
|
1990a990c3 | ||
|
|
d1159d3af9 | ||
|
|
723dada78a | ||
|
|
0e089af677 | ||
|
|
f4aed5d012 | ||
|
|
860f953962 | ||
|
|
ded692ead7 | ||
|
|
4f5413ebbe | ||
|
|
8f3e210740 | ||
|
|
783cb8b4e9 | ||
|
|
2b94d96930 | ||
|
|
ca349e03f2 | ||
|
|
5b5222b846 | ||
|
|
850f8ad939 | ||
|
|
50e5f89e9a | ||
|
|
603b47f9b0 | ||
|
|
92227c364e | ||
|
|
10ac18a7cc | ||
|
|
e06123e4bd | ||
|
|
b44bd544cd | ||
|
|
4c3a448330 | ||
|
|
7f07c249af | ||
|
|
51958d2ac0 | ||
|
|
67f474d794 | ||
|
|
e6e8ebd881 | ||
|
|
b138fedd35 | ||
|
|
a92d846b57 | ||
|
|
7a544482d1 | ||
|
|
53739ee8d4 | ||
|
|
495145e033 | ||
|
|
6701d09df5 | ||
|
|
e36d7121f1 | ||
|
|
9290a60b23 | ||
|
|
761de79a8c | ||
|
|
b8e9beff1b | ||
|
|
5b13e0ba4f | ||
|
|
b0bab18d00 | ||
|
|
b4fa1392de | ||
|
|
4e58002e13 | ||
|
|
adc149aac8 | ||
|
|
4c02773ddc | ||
|
|
892abe1d70 | ||
|
|
71c23d33ff | ||
|
|
9c110e896e | ||
|
|
afe7a748e1 | ||
|
|
325e582593 | ||
|
|
ccebe6a423 | ||
|
|
f7c92fa4b2 | ||
|
|
d07c2d118f | ||
|
|
94a09edd1d | ||
|
|
f6f939c245 | ||
|
|
0d889426e8 | ||
|
|
c8a546ef1e | ||
|
|
693919b21a | ||
|
|
7c1a2039b1 | ||
|
|
c66e4e0475 | ||
|
|
6bdfbf0d7d | ||
|
|
61393bca90 | ||
|
|
c41b649bff | ||
|
|
ba87487714 | ||
|
|
3e73f38ae2 | ||
|
|
51dd55c3fd | ||
|
|
de49ca37b9 | ||
|
|
8d8080ee09 | ||
|
|
f3613ccb25 | ||
|
|
ad7b5700f3 | ||
|
|
0d17c62d02 | ||
|
|
826690982a | ||
|
|
b438ff9c62 | ||
|
|
43fb9d1a23 | ||
|
|
fb17ce8c8a | ||
|
|
3a8e12535e | ||
|
|
ce0caa3f6d | ||
|
|
00a0315f12 | ||
|
|
da38d56dc7 | ||
|
|
83e47cba2c | ||
|
|
f4d1eebed4 | ||
|
|
f27b394099 | ||
|
|
a66c9ccc1f | ||
|
|
0bc6a830c8 | ||
|
|
f3008b29af | ||
|
|
5b16ff8be1 | ||
|
|
86621e3388 | ||
|
|
1beb0668c3 | ||
|
|
34b09f90fb | ||
|
|
a6f964925b | ||
|
|
196416bb9f | ||
|
|
1535db9f7d | ||
|
|
ae38ac4de8 | ||
|
|
e0aa8d8ecf | ||
|
|
23c1eacf2b | ||
|
|
10e28789e2 | ||
|
|
940f7f77f5 | ||
|
|
83f8b4fcb4 | ||
|
|
42dc801ddf | ||
|
|
5e6e5bfbec | ||
|
|
28fc99dd45 | ||
|
|
9ef501c399 | ||
|
|
6bba908654 | ||
|
|
d423e43312 | ||
|
|
91718f218b | ||
|
|
e623e91a82 | ||
|
|
dce9f50911 | ||
|
|
5f1486cf6a | ||
|
|
2c6bdc79af | ||
|
|
a6b89cfa30 | ||
|
|
21d1cd395b | ||
|
|
981466cbe8 | ||
|
|
0209573fce | ||
|
|
92f8459f28 | ||
|
|
da193b456b | ||
|
|
6c151afca3 | ||
|
|
aba6750c18 | ||
|
|
b9a8e4e4ba | ||
|
|
4134c4ddd0 | ||
|
|
72038fb2ec | ||
|
|
069d8b1ae4 | ||
|
|
ce71068f6d | ||
|
|
dc298a44e1 | ||
|
|
306bfd7673 | ||
|
|
25cf23f507 | ||
|
|
096d5f7c65 | ||
|
|
0e2dee1609 | ||
|
|
ec927d25a9 | ||
|
|
7c8aefb4ef | ||
|
|
e840769dd6 | ||
|
|
4a5d3f01b8 | ||
|
|
71d975f339 | ||
|
|
a4051fc372 | ||
|
|
359b2a68b8 | ||
|
|
8124e4e589 | ||
|
|
5f699996f8 | ||
|
|
c7c0bc4185 | ||
|
|
d422ac7bc5 | ||
|
|
0bd912d18a | ||
|
|
252f2fe72c | ||
|
|
7f29c347e2 | ||
|
|
7a3dc824d6 | ||
|
|
8550c62771 | ||
|
|
66cd657cd8 | ||
|
|
beac80e175 | ||
|
|
5ae9952ba1 | ||
|
|
d4bc1ec444 | ||
|
|
d52f529b24 | ||
|
|
9a9cfdec2b | ||
|
|
6ab421ffa0 | ||
|
|
53b0aafb98 | ||
|
|
6b02ad8421 | ||
|
|
242ebfccc0 | ||
|
|
545cc0782f | ||
|
|
bf6a2917cd | ||
|
|
eaba2a8395 | ||
|
|
c581fb17bc | ||
|
|
9b05b95d77 | ||
|
|
b3ba18ddd0 | ||
|
|
bb2a633ba7 | ||
|
|
913efdef03 | ||
|
|
bf0bea18b1 | ||
|
|
cdebd1f63a | ||
|
|
a6a2635836 | ||
|
|
024b57c2b4 | ||
|
|
6fbc85cbc7 | ||
|
|
5f8a0aee13 | ||
|
|
0c67b292ef | ||
|
|
ba663e6162 | ||
|
|
14925266cf | ||
|
|
702e29bd8c | ||
|
|
27ac3e58c5 | ||
|
|
86e268c06d | ||
|
|
6e4b231319 | ||
|
|
041eff6cbd | ||
|
|
1a3471a516 | ||
|
|
57c8727bb1 | ||
|
|
bd451d0738 | ||
|
|
ced062842d | ||
|
|
a1bf7bfa08 | ||
|
|
2a67c93c20 | ||
|
|
b51bfdfb33 | ||
|
|
9aa84877ee | ||
|
|
9e99670b19 | ||
|
|
744b93dd98 | ||
|
|
5abb77242c | ||
|
|
4ab3b0dd2b | ||
|
|
a6a1594265 | ||
|
|
b06cdd442d | ||
|
|
f7067fb968 | ||
|
|
cf0f5ba4c4 | ||
|
|
309a81a0fe | ||
|
|
caa428c1a2 | ||
|
|
517c721664 | ||
|
|
a8cdaa69f7 | ||
|
|
53d221ef34 | ||
|
|
5450fde472 | ||
|
|
808446cef5 | ||
|
|
921c663199 | ||
|
|
1b8a75b615 | ||
|
|
f78ced5bc3 | ||
|
|
81bf5f4f3b | ||
|
|
aaed368670 | ||
|
|
5e8de14721 | ||
|
|
634ab5b5c0 | ||
|
|
906889a035 | ||
|
|
ab9d50b905 | ||
|
|
e61b7c7cfc | ||
|
|
1c628fba4c | ||
|
|
f8b4c6cb15 | ||
|
|
3edd8f6c5a | ||
|
|
7777f72893 | ||
|
|
9af85b767b | ||
|
|
73260b91eb | ||
|
|
2858f63873 | ||
|
|
15ca328727 | ||
|
|
5b3fbecc0f | ||
|
|
365d0f0aac | ||
|
|
e86d84c463 | ||
|
|
6b974c2ac7 | ||
|
|
d2afcbb98d | ||
|
|
68a122fcf5 | ||
|
|
92f0144b48 | ||
|
|
a5a345728c | ||
|
|
23890e64e9 | ||
|
|
3de712aca4 | ||
|
|
cb5b4d870f | ||
|
|
f81aef2de5 | ||
|
|
06aed16ea1 | ||
|
|
aa2d8af15c | ||
|
|
dc7b91433b | ||
|
|
72951386b1 | ||
|
|
db8df01d82 | ||
|
|
98713ed111 | ||
|
|
3e88fecb15 | ||
|
|
fe4255f2fc | ||
|
|
c046a57654 | ||
|
|
d8fc0d45a8 | ||
|
|
567b96cfb4 | ||
|
|
d25849d280 | ||
|
|
d4d73995db | ||
|
|
f4657b5da9 | ||
|
|
614f43cb8a | ||
|
|
ca2fbf8dba | ||
|
|
a421513442 | ||
|
|
a9599c471a | ||
|
|
415bcac641 | ||
|
|
9527017314 | ||
|
|
1d3d7c77f8 | ||
|
|
e868615fd5 | ||
|
|
80493a52be | ||
|
|
3fed2ba42e | ||
|
|
82592ada54 | ||
|
|
5528701744 | ||
|
|
0ca665fb85 | ||
|
|
7eb452ed8b | ||
|
|
d81dec94a9 | ||
|
|
6631a4a806 | ||
|
|
12f817c896 | ||
|
|
87229600d2 | ||
|
|
471a46a030 | ||
|
|
41220eebd5 | ||
|
|
755872277b | ||
|
|
2cb54d7021 | ||
|
|
5a16bafbbf | ||
|
|
fc6e9d89d9 | ||
|
|
8af35da279 | ||
|
|
7107fec1a4 | ||
|
|
4bb662c5fb | ||
|
|
89297b92f8 | ||
|
|
e019271e74 | ||
|
|
f6d61eefcc | ||
|
|
fabc07be42 | ||
|
|
bccfa7956c | ||
|
|
42a05f411b | ||
|
|
7ba7b98f5f | ||
|
|
2132c2ab38 | ||
|
|
2ce4d512e7 | ||
|
|
1258d32820 | ||
|
|
db763ba229 | ||
|
|
951fdaec70 | ||
|
|
4303f3687e | ||
|
|
540b0e0b83 | ||
|
|
08a0326cb0 | ||
|
|
8b0a45e4fd | ||
|
|
0e0ad2ed73 | ||
|
|
4c73f31aca | ||
|
|
6b2ae8fd12 | ||
|
|
88d84fae1e | ||
|
|
cdc46faaad | ||
|
|
24dbc79961 | ||
|
|
8cb58dcc45 | ||
|
|
fe70b8aee6 | ||
|
|
00f66cfb49 | ||
|
|
3a4b080765 | ||
|
|
41269ef987 | ||
|
|
e521c6a386 | ||
|
|
1c35a557c1 | ||
|
|
99eb8389c5 | ||
|
|
c5e560ef5b | ||
|
|
a7d7a078b1 | ||
|
|
a06fa5222f | ||
|
|
8d3e40a28a | ||
|
|
8e32f99790 | ||
|
|
57bce62e48 | ||
|
|
1c873394d5 | ||
|
|
d652f67364 | ||
|
|
5e54d098c5 | ||
|
|
ec95303c31 | ||
|
|
07aafe7e89 | ||
|
|
dc7acbb70e | ||
|
|
0dcb8b3ff8 | ||
|
|
e4ddff01ca | ||
|
|
015c1161d4 | ||
|
|
ca0c6076c5 | ||
|
|
80a02f88be | ||
|
|
430833bedb | ||
|
|
dc80d83964 | ||
|
|
5f7ade45f4 | ||
|
|
8b36a7ab1e | ||
|
|
fd18276693 | ||
|
|
0becfc16ba | ||
|
|
d480d1f6ba | ||
|
|
f5c9a71ba0 | ||
|
|
c177a8a464 | ||
|
|
c826564c9e | ||
|
|
ccb13fa6b9 | ||
|
|
69e374138f | ||
|
|
3156b2cb59 | ||
|
|
d6217ffed4 | ||
|
|
fc90c6af9d | ||
|
|
a1118419ec | ||
|
|
8599785ee8 | ||
|
|
99ba192a44 | ||
|
|
b86d3587ac | ||
|
|
b2a0baf56a | ||
|
|
22f37817e5 | ||
|
|
6b4fe03625 | ||
|
|
f44b47ec23 | ||
|
|
8d667e838a | ||
|
|
f32385de2e | ||
|
|
90796fc4fa | ||
|
|
4960c49cb2 | ||
|
|
b112e8b56b | ||
|
|
83095130f6 | ||
|
|
d005c0ef2d | ||
|
|
c135578626 | ||
|
|
9a6e20029e | ||
|
|
39bd4ccea1 | ||
|
|
aac4774326 | ||
|
|
ea7aac2030 | ||
|
|
e7f98f08d0 | ||
|
|
8ac9daa5d3 | ||
|
|
0b506c6327 | ||
|
|
d2b62540ec | ||
|
|
64418c7fec | ||
|
|
8c1a58e64f | ||
|
|
b27fd31c1f | ||
|
|
f18a531924 | ||
|
|
3cabb4b661 | ||
|
|
5c88b1c6b8 | ||
|
|
c2adc43780 | ||
|
|
7eaa5352ba | ||
|
|
17e3e3187b | ||
|
|
2ad7cd3a49 | ||
|
|
39aa8d61c2 | ||
|
|
1a3ea977b7 | ||
|
|
4cd8f9a1e6 | ||
|
|
87ce6d1231 | ||
|
|
8fdbeacf77 | ||
|
|
f4f775a1c9 | ||
|
|
fe1154cb2d | ||
|
|
638f479ff3 | ||
|
|
70436bdb04 | ||
|
|
575ecaae07 | ||
|
|
d277e6db94 | ||
|
|
25efcd12d0 | ||
|
|
10129321be | ||
|
|
72710a8f6b | ||
|
|
6a7c5c04d8 | ||
|
|
7f32fe5ef7 | ||
|
|
5d89591dea | ||
|
|
a88bf5a87b | ||
|
|
bbe5d3506e | ||
|
|
c2993d4e7d | ||
|
|
17ba479182 | ||
|
|
a465014bbe | ||
|
|
5dfe253ef6 | ||
|
|
ae7ca6021f | ||
|
|
c389697acd | ||
|
|
c13c3e0f4a | ||
|
|
82c042d045 | ||
|
|
9145ba1690 | ||
|
|
d60653ee17 | ||
|
|
dae8613b4e | ||
|
|
2f8e2c40be | ||
|
|
d85225a0dc | ||
|
|
0cb66df2b2 | ||
|
|
92e0578cb6 | ||
|
|
2eee06786e | ||
|
|
19053dcb3b | ||
|
|
e10c30c59f | ||
|
|
c356159664 | ||
|
|
579be68ca1 | ||
|
|
a6326a682e | ||
|
|
4595a3a5dd | ||
|
|
ee21185e64 | ||
|
|
6d0676c37d | ||
|
|
1d4768a581 | ||
|
|
d086bb7fcb | ||
|
|
2607c4a32e | ||
|
|
624333a2ef | ||
|
|
d4acb37f21 | ||
|
|
6c1a1e9812 | ||
|
|
9a13641f9b | ||
|
|
699e0624c9 | ||
|
|
47ceb0d4d2 | ||
|
|
15c42f4a09 | ||
|
|
bf8401bb26 | ||
|
|
f234433c63 | ||
|
|
1b70101123 | ||
|
|
d610c63c28 | ||
|
|
5e820a407f | ||
|
|
62610979b7 | ||
|
|
700e99e854 | ||
|
|
7767116b3d | ||
|
|
0206e8247b | ||
|
|
5476fe3df9 | ||
|
|
d9a4581d37 | ||
|
|
8d9c888481 | ||
|
|
11e4b672d1 | ||
|
|
bace3daadc | ||
|
|
dee5380e60 | ||
|
|
bc6a6fd860 | ||
|
|
e928337fe9 | ||
|
|
432f86ea4b | ||
|
|
5d2daecee0 | ||
|
|
7c8eb311af | ||
|
|
4ac22678df | ||
|
|
5057c02176 | ||
|
|
d301e56216 | ||
|
|
3c22ab8c9c | ||
|
|
0212398815 | ||
|
|
db0c515bad | ||
|
|
9b4f8c5003 | ||
|
|
85d8c4c8fa | ||
|
|
5afab6938a | ||
|
|
a437169ad5 | ||
|
|
f632d3aeb6 | ||
|
|
513fffcb1a | ||
|
|
d3337eab9c | ||
|
|
8128a8192a | ||
|
|
c80bb9657c | ||
|
|
65514a6fd7 | ||
|
|
93a7f8c711 | ||
|
|
0ca179f990 | ||
|
|
9d104015f3 | ||
|
|
2c4cf2dcf1 | ||
|
|
d2e0124962 | ||
|
|
cd59c75c04 | ||
|
|
caa9143591 | ||
|
|
7e53810c02 | ||
|
|
12efa8dc0b | ||
|
|
4d0ccac7b5 | ||
|
|
8b023a55d0 | ||
|
|
b4df5fcbd9 | ||
|
|
6fbe5718e9 | ||
|
|
908bafca63 | ||
|
|
d7313efd67 | ||
|
|
a51e15c9b8 | ||
|
|
37e9c7d639 | ||
|
|
2d00ac4dfb | ||
|
|
6aec7eae00 | ||
|
|
6bfbc2d35e | ||
|
|
2ffc854ce6 | ||
|
|
ddd4a374e4 | ||
|
|
0d6e2fc00f | ||
|
|
366a8e8726 | ||
|
|
7f0aa0697a | ||
|
|
d123ce33b8 | ||
|
|
55588f5962 | ||
|
|
f32130d5c2 | ||
|
|
03f4ff9e7c | ||
|
|
6de78c7154 | ||
|
|
d331e418d4 | ||
|
|
4ace74bcb8 | ||
|
|
1d4a336256 | ||
|
|
ee6c192ab9 | ||
|
|
b220bdce9c | ||
|
|
4d86c6c4f1 | ||
|
|
4fd68bf12d | ||
|
|
3ffe34964f | ||
|
|
faaf26c174 | ||
|
|
f9c7518db2 | ||
|
|
8357c2a39c | ||
|
|
793dcee562 | ||
|
|
00368fc131 | ||
|
|
f81b686f41 | ||
|
|
4c5aada5d3 | ||
|
|
05551cec9e | ||
|
|
6300a8c8d1 | ||
|
|
ca4d15727d | ||
|
|
2fe076086e | ||
|
|
56b65ddfae | ||
|
|
fcf6673825 | ||
|
|
9eda264f52 | ||
|
|
fe1270c679 | ||
|
|
679e1ac678 | ||
|
|
e309ff2d17 | ||
|
|
c910335155 | ||
|
|
5606cde506 | ||
|
|
0e2f4f4e13 | ||
|
|
1f6c6f2acd | ||
|
|
37d2e9f14b | ||
|
|
0fcf30a3b8 | ||
|
|
8712e7dd16 | ||
|
|
2ee4e9cc14 | ||
|
|
b257b75be2 | ||
|
|
2de2709420 | ||
|
|
3e0ddd90a1 | ||
|
|
b96b004262 | ||
|
|
e1ad48b42a | ||
|
|
420f0917be | ||
|
|
31d8287e1b | ||
|
|
4433d034db | ||
|
|
c96114992e | ||
|
|
b35e0b906f | ||
|
|
104c9ec64a | ||
|
|
6e4b18b57b | ||
|
|
f9460c8f41 | ||
|
|
02601f37d8 | ||
|
|
0feab6d4ed | ||
|
|
5a9d3499d8 | ||
|
|
dce0988409 | ||
|
|
b2d378db6b | ||
|
|
7ecff88da7 | ||
|
|
b434bf8804 | ||
|
|
441484629a | ||
|
|
37a1bd6b25 | ||
|
|
fe3dfc418f | ||
|
|
34ca7912fc | ||
|
|
1d698106da | ||
|
|
b9ce83165f | ||
|
|
34670dd69c | ||
|
|
54be58ba1f | ||
|
|
b9abdcb189 | ||
|
|
9f0f9b8315 | ||
|
|
63ee60ffc7 | ||
|
|
3b2cd5dca1 | ||
|
|
388a6943e9 | ||
|
|
50301be093 | ||
|
|
123e1ada90 | ||
|
|
5c42dbba12 | ||
|
|
a549fd228e | ||
|
|
6e352e5b22 | ||
|
|
1d3df69bb7 | ||
|
|
c6394698fa | ||
|
|
d94f2ac093 | ||
|
|
740974fbfd | ||
|
|
f0b9e0e48b | ||
|
|
deee50f2b4 | ||
|
|
2c9d5368a1 | ||
|
|
819432b4ab | ||
|
|
7efbb4d945 | ||
|
|
64d1b33a4c | ||
|
|
326adc0196 | ||
|
|
b1b9a4461e | ||
|
|
d70f5d3ed6 | ||
|
|
d1fac8f0e2 | ||
|
|
5f7c26eed3 | ||
|
|
bf748cee24 | ||
|
|
79439f6435 | ||
|
|
2a875f8386 | ||
|
|
08e69d405c | ||
|
|
471f380756 | ||
|
|
700edbe2c8 | ||
|
|
d60c117c62 | ||
|
|
4ae395ded5 | ||
|
|
f311db1cb4 | ||
|
|
40be94804c | ||
|
|
5719819947 | ||
|
|
c938bcc657 | ||
|
|
e029379194 | ||
|
|
d56f106964 | ||
|
|
676dea33e1 | ||
|
|
945b00030b | ||
|
|
a47de6c65c | ||
|
|
7c89c66526 | ||
|
|
8554dc249c | ||
|
|
bfcbfac5bb | ||
|
|
59d8a98eea | ||
|
|
c7d74e8b00 | ||
|
|
dc3de5bf36 | ||
|
|
680cd8118f | ||
|
|
1041bf70e1 | ||
|
|
0c6326b678 | ||
|
|
f4d91e48ba | ||
|
|
fd805a5279 | ||
|
|
9374694a0c | ||
|
|
61460daaea | ||
|
|
d64c1f6b0e | ||
|
|
0334166029 | ||
|
|
7fac172ce2 | ||
|
|
3b9f765c24 | ||
|
|
655b016efa | ||
|
|
aa247ef06c | ||
|
|
9e653a87b8 | ||
|
|
dfb44def2b | ||
|
|
f0e8c0f79d | ||
|
|
28fe73911f | ||
|
|
a971640ffc | ||
|
|
44dc8cf00d | ||
|
|
59ca270880 | ||
|
|
abb5fe5b0f | ||
|
|
af0e4088a6 | ||
|
|
6b82943871 | ||
|
|
d7aa744bad | ||
|
|
f417a2e126 | ||
|
|
b937f474e4 | ||
|
|
6a3c4fec98 | ||
|
|
6bda7837d6 | ||
|
|
ab9144972b | ||
|
|
bcb646f42b | ||
|
|
0db75a6cdb | ||
|
|
76c7b8692d | ||
|
|
1061aba212 | ||
|
|
d4eb6f07bd | ||
|
|
f1a83124a8 | ||
|
|
2ad30c6a3d | ||
|
|
0f1533d0a0 | ||
|
|
bf5caaebb5 | ||
|
|
b24d2c65a1 | ||
|
|
2d989dcfe3 | ||
|
|
8e8e6f9ed1 | ||
|
|
e1de98c4ae | ||
|
|
aba7f35d9f | ||
|
|
8c9ad575ef | ||
|
|
fc59ee6e93 | ||
|
|
5ec9770b07 | ||
|
|
1c1895b2eb | ||
|
|
7861bc41f9 | ||
|
|
843e4d45e6 | ||
|
|
416825c9c2 | ||
|
|
6762539b4d | ||
|
|
ae9827c436 | ||
|
|
4b4b427d2b | ||
|
|
33622cd3fe | ||
|
|
807b054a95 | ||
|
|
b223b931ab | ||
|
|
6759fef827 | ||
|
|
896d50b1f8 | ||
|
|
2049c49fdb | ||
|
|
b3c397e847 | ||
|
|
e69b85a988 | ||
|
|
aabc9ec4df | ||
|
|
598501e3f6 | ||
|
|
bfa344a839 | ||
|
|
c466d7ee9f | ||
|
|
2e9c07d3d6 | ||
|
|
9651ca99f3 | ||
|
|
a6e87f5724 | ||
|
|
cf994dac5a | ||
|
|
95c9c375c9 | ||
|
|
f9804eda8e | ||
|
|
88c2bedbd7 | ||
|
|
49bf49c967 | ||
|
|
506b5c44af | ||
|
|
22ea59a63b | ||
|
|
934aaaf045 | ||
|
|
c6bfcea79f | ||
|
|
6e39fb12e2 | ||
|
|
dbe534d8f8 | ||
|
|
04e5197d00 | ||
|
|
3a15878629 | ||
|
|
021a908c9c | ||
|
|
c09ef3af80 | ||
|
|
3151e6dafc | ||
|
|
e9dc97daf8 | ||
|
|
3a3cc565ea | ||
|
|
fcf4ffb445 | ||
|
|
b34c27af1f | ||
|
|
64371a6b9c | ||
|
|
182afab12c | ||
|
|
57e888911d | ||
|
|
535054b2d2 | ||
|
|
d40191257c | ||
|
|
87ee1185f2 | ||
|
|
f4b0f810bd | ||
|
|
0934e33af7 | ||
|
|
b3e88f5a44 | ||
|
|
2f23db0c64 | ||
|
|
ca2f39bacd | ||
|
|
e38b89996a | ||
|
|
8efbb8819b | ||
|
|
e03bd3d716 | ||
|
|
cfb56cb143 | ||
|
|
477e516473 | ||
|
|
fd601eac5b | ||
|
|
df4fa42acd | ||
|
|
b06d390df5 | ||
|
|
7f013a58f5 | ||
|
|
1fd0fb03fa | ||
|
|
7ec718218e | ||
|
|
b5300e5b86 | ||
|
|
19d2f02694 | ||
|
|
fec929dfee | ||
|
|
d7339ff14d | ||
|
|
422bc00ade | ||
|
|
8edf5483a6 | ||
|
|
00046d4145 | ||
|
|
25e67f62d5 | ||
|
|
8d233e66e1 | ||
|
|
39e0d5b629 | ||
|
|
90844d5bc2 | ||
|
|
29df06626b | ||
|
|
d28661fee3 | ||
|
|
dc8c10e531 | ||
|
|
538e1f0fdd | ||
|
|
eaf0c690e1 | ||
|
|
a4a3d6a82c | ||
|
|
e5eab3952b | ||
|
|
9b45639148 | ||
|
|
e53cd7443a | ||
|
|
60b74f5959 | ||
|
|
a3e4044fec | ||
|
|
f380df9c01 | ||
|
|
83fc82a615 | ||
|
|
eaf3632fc9 | ||
|
|
1d947f26ff | ||
|
|
34a08be4cd | ||
|
|
f84a4c4856 | ||
|
|
47aa24d0f4 | ||
|
|
e6e132e905 | ||
|
|
ad2df957c7 | ||
|
|
818ca2c2ab | ||
|
|
72c34eb491 | ||
|
|
22341bf0b1 | ||
|
|
c735870b95 | ||
|
|
56f796bf80 | ||
|
|
225693fa79 | ||
|
|
7f760bff17 | ||
|
|
6b4da33729 | ||
|
|
82cae8ffbf | ||
|
|
31dbbb1881 | ||
|
|
31de1e007a | ||
|
|
a2d0655a75 | ||
|
|
269209dd31 | ||
|
|
32082927b2 | ||
|
|
c10d0b6349 | ||
|
|
11ff1266e5 | ||
|
|
8b5717ff7f | ||
|
|
e69f6bef2c | ||
|
|
2a17a322c2 | ||
|
|
26ddb76338 | ||
|
|
f62f156c93 | ||
|
|
f4b6c65bad | ||
|
|
0a08399d9e | ||
|
|
df1adaad3a | ||
|
|
33b1490de0 | ||
|
|
286720bdbf | ||
|
|
1441ac67ab | ||
|
|
d245fdd1b8 | ||
|
|
e9c9b456e0 | ||
|
|
d9eafff7df | ||
|
|
94eb19d879 | ||
|
|
d7b585230a | ||
|
|
16ed14f85a | ||
|
|
93e59cc3b6 | ||
|
|
c38220892b | ||
|
|
4ef72fb35b | ||
|
|
3f23ce095c | ||
|
|
0ead246ce7 | ||
|
|
0f8259fdf7 | ||
|
|
ebb180b0ab | ||
|
|
c03f50583e | ||
|
|
b8a6cf0099 | ||
|
|
ad3cdc3364 | ||
|
|
d924d3fa4f | ||
|
|
dd4a8c08c8 | ||
|
|
52f2e800e7 | ||
|
|
8d94b62db0 | ||
|
|
c3eb483224 | ||
|
|
e7b1e0a81f | ||
|
|
ca672c68a3 | ||
|
|
416e11a32b | ||
|
|
bbaa2db377 | ||
|
|
cf4e412ab8 | ||
|
|
48ac88dbfe | ||
|
|
4980e9a15b | ||
|
|
290a2ab902 | ||
|
|
6a04d8fce1 | ||
|
|
7286ac743f | ||
|
|
41b6b5f615 | ||
|
|
d0572f7691 | ||
|
|
a8210844cb | ||
|
|
c5c39cedc4 | ||
|
|
8d6ae2da82 | ||
|
|
9eea6b3645 | ||
|
|
6d9638970d | ||
|
|
ecd3638298 | ||
|
|
bbde0e4d24 | ||
|
|
299f694aa9 | ||
|
|
2675698d3a | ||
|
|
3056f3cfcf | ||
|
|
7310d8af30 | ||
|
|
b62f40f8c9 | ||
|
|
ae1aac02ae | ||
|
|
e19f344dc1 | ||
|
|
1525ecdb05 | ||
|
|
4f6a13b2c4 | ||
|
|
4747297adc | ||
|
|
f753974800 | ||
|
|
bd4002529c | ||
|
|
00588eb099 | ||
|
|
81420b6168 | ||
|
|
fe74d2aec9 | ||
|
|
6514701c6a | ||
|
|
9e206ce7ea | ||
|
|
b32ad68e4f | ||
|
|
dfb5322b1a | ||
|
|
47859d401e | ||
|
|
5da90f9e16 | ||
|
|
4b098e2008 | ||
|
|
b4cd66db50 | ||
|
|
4847f4094a | ||
|
|
3fb34e6ae1 | ||
|
|
135ed32374 | ||
|
|
9b1fc77d56 | ||
|
|
5b751fd6e2 | ||
|
|
39ece711d9 | ||
|
|
a77b5601be | ||
|
|
8b5d88bf2b | ||
|
|
1f602f9cad | ||
|
|
5588042ab6 | ||
|
|
bc89bc8270 | ||
|
|
60ae094d3b | ||
|
|
a9facc7ce2 | ||
|
|
f200ac898a | ||
|
|
56ce25b8e8 | ||
|
|
4d5d9b4b70 | ||
|
|
b97ab913bf | ||
|
|
9fe7bdf79b | ||
|
|
4ebc4ece34 | ||
|
|
0110b3c4a2 | ||
|
|
fb20d4998a | ||
|
|
bd06c530e4 | ||
|
|
cd4505bcf0 | ||
|
|
173f4a23a5 | ||
|
|
b33d4e64b9 | ||
|
|
a4c95132bb | ||
|
|
095e797a02 | ||
|
|
aaec171d94 | ||
|
|
42b28993b2 | ||
|
|
09a39379ef | ||
|
|
29f7370c72 | ||
|
|
a07dcef2c4 | ||
|
|
6e696e1123 | ||
|
|
f0b1aa914d | ||
|
|
ce1ae2c9bd | ||
|
|
29597ddb48 | ||
|
|
1c1421fe3a | ||
|
|
918a52005e | ||
|
|
a3564b879f | ||
|
|
b78f3bbaa7 | ||
|
|
4cbdb5a073 | ||
|
|
758021e10c | ||
|
|
374e3560c3 | ||
|
|
57a3524cc3 | ||
|
|
9af4773b45 | ||
|
|
6942773965 | ||
|
|
734b3ee519 | ||
|
|
1b80fa8df2 | ||
|
|
afd6a05e0f | ||
|
|
5a4bd1933d | ||
|
|
a25dfce410 | ||
|
|
fc0490bc6a | ||
|
|
29cdd1d028 | ||
|
|
419e87b0de | ||
|
|
75c7d55e01 | ||
|
|
e006550b9f | ||
|
|
2a424f8dc4 | ||
|
|
5036518458 | ||
|
|
297cbbd8b3 | ||
|
|
87a89f709a | ||
|
|
6f1991e20e | ||
|
|
700de58686 | ||
|
|
57e1208c27 | ||
|
|
b33fe2ca3a | ||
|
|
3c3e73edae | ||
|
|
ec4fd371b5 | ||
|
|
555b138a90 | ||
|
|
c139ff776c | ||
|
|
0c6b5e3b8e | ||
|
|
1138f9a0e9 | ||
|
|
4955bd782b | ||
|
|
516f0052ef | ||
|
|
f4e82acc67 | ||
|
|
a5806c0d1d | ||
|
|
bf302a84a9 | ||
|
|
fcc740d592 | ||
|
|
cee16dc3dc | ||
|
|
47601cd1da | ||
|
|
092a60fdd9 | ||
|
|
e8e7568bdc | ||
|
|
4caca56e3b | ||
|
|
e4432e6feb | ||
|
|
d8275e7ea8 | ||
|
|
952dc634b4 | ||
|
|
7dceca475d | ||
|
|
62a78bc272 | ||
|
|
6aaf277b45 | ||
|
|
a1c61768c4 | ||
|
|
8e4c88c10c | ||
|
|
b57780519c | ||
|
|
c07c4013be | ||
|
|
768211cc26 | ||
|
|
b4a31503ee | ||
|
|
6c2b3e238c | ||
|
|
f2ff834b9c | ||
|
|
86e1688358 | ||
|
|
d259eb1f9d | ||
|
|
568a668e9f | ||
|
|
0621dfbac7 | ||
|
|
827bb9a32f | ||
|
|
fd08654dd5 | ||
|
|
e5d750722e | ||
|
|
b43c4ad666 | ||
|
|
c9f93a4706 | ||
|
|
a38834f7e2 | ||
|
|
fcfc6f6476 | ||
|
|
b23a5348b5 | ||
|
|
782cd59407 | ||
|
|
7964bd3be4 | ||
|
|
3d41ce13b1 | ||
|
|
6f0881ab8a | ||
|
|
a6309715f3 | ||
|
|
5a06193e65 | ||
|
|
4912834537 | ||
|
|
d64f2c72b7 | ||
|
|
358d06a402 | ||
|
|
5deabe4260 | ||
|
|
1b1162e26e | ||
|
|
30ad5d531c | ||
|
|
99efc73e93 | ||
|
|
17c0071dd1 | ||
|
|
a26bec047f | ||
|
|
748e7cc1df | ||
|
|
f653c86965 | ||
|
|
58a41e58ee | ||
|
|
309a55f276 | ||
|
|
df96c6b9fa | ||
|
|
d779e078c7 | ||
|
|
ae224151a0 | ||
|
|
9f11717b69 | ||
|
|
ea25477e3d | ||
|
|
82576c9703 | ||
|
|
80f1fc4c7c | ||
|
|
41cd4bcef6 | ||
|
|
46a414e155 | ||
|
|
70a903f811 | ||
|
|
52db410c82 | ||
|
|
08da8d73e0 | ||
|
|
81a572af25 | ||
|
|
23c50f34fe | ||
|
|
70aa115933 | ||
|
|
0b8cba78d5 | ||
|
|
d8806eaa04 | ||
|
|
b8bc85856b | ||
|
|
cc097c5414 | ||
|
|
7551d0e044 | ||
|
|
489a88b8da | ||
|
|
48013dc264 | ||
|
|
4ee9d45dfc | ||
|
|
e00150a876 | ||
|
|
71668f8f8d | ||
|
|
b71424d239 | ||
|
|
d1a3bceaa6 | ||
|
|
483c57029a | ||
|
|
7e6daf5b36 | ||
|
|
b658253687 | ||
|
|
80b488deec | ||
|
|
10cf1a371e | ||
|
|
81445901fa | ||
|
|
f645d9d721 | ||
|
|
900bfdff9d | ||
|
|
108ca5afb5 | ||
|
|
3df03a551c | ||
|
|
6ffbe19667 | ||
|
|
e3172ebf1c | ||
|
|
9b2876a8ff | ||
|
|
3db2c910e0 | ||
|
|
2799e4392f | ||
|
|
61963fcfda | ||
|
|
b0a3d54276 | ||
|
|
2135412c84 | ||
|
|
7a534c3ea7 | ||
|
|
a6e596a5e3 | ||
|
|
8b3e3c2c3a | ||
|
|
ec8b0a3801 | ||
|
|
197b769838 | ||
|
|
1ba498c0e3 | ||
|
|
5550cb7b95 | ||
|
|
06a005acec | ||
|
|
2103be9d28 | ||
|
|
a02f3c4440 | ||
|
|
4b8d341e00 | ||
|
|
964633f426 | ||
|
|
d11fb38280 | ||
|
|
04f4530990 | ||
|
|
5a77318a9e | ||
|
|
9ed2894a0c | ||
|
|
e0766ad439 | ||
|
|
67acfaab62 | ||
|
|
10b5d29107 | ||
|
|
297dd41170 | ||
|
|
1364223599 | ||
|
|
a6b7761dfa | ||
|
|
2e6290c514 | ||
|
|
78f4928611 | ||
|
|
d044fce9c1 | ||
|
|
11fa815e13 | ||
|
|
8d917eb970 | ||
|
|
e411e5f2cf | ||
|
|
fea8de89c6 | ||
|
|
48773636ca | ||
|
|
5a3c7355c1 | ||
|
|
4afbabb977 | ||
|
|
afa9fe3063 | ||
|
|
178ac088b4 | ||
|
|
b2ebaf111f | ||
|
|
ffd5ebbe79 | ||
|
|
6b78bfecb4 | ||
|
|
9c2b01e3c9 | ||
|
|
dca201ce42 | ||
|
|
d3c0a44c00 | ||
|
|
33ea2de231 | ||
|
|
43ebbfc321 | ||
|
|
1e5b294eb3 | ||
|
|
29855112c8 | ||
|
|
8af7b3c81a | ||
|
|
b72b82ff1a | ||
|
|
1588c8103c | ||
|
|
15e569dcea | ||
|
|
3774ea3768 | ||
|
|
0a9c6a3119 | ||
|
|
a6cbde88bb | ||
|
|
4bdb407404 | ||
|
|
4568cedcd3 | ||
|
|
f290317acc | ||
|
|
645279c8fa | ||
|
|
09436f8d65 | ||
|
|
b616e0e5f9 | ||
|
|
f06a0852a1 | ||
|
|
9e688138be | ||
|
|
5d46970a38 | ||
|
|
ecc441c074 | ||
|
|
f2ce3678c4 | ||
|
|
c9ad390647 | ||
|
|
92acc7accd | ||
|
|
9c13f36ca0 | ||
|
|
fe4a11c5ad | ||
|
|
e29b238161 | ||
|
|
2ef4eb7eae | ||
|
|
7b230706cb | ||
|
|
5a2b04adba | ||
|
|
50dcd3ba44 | ||
|
|
740b02952f | ||
|
|
5d3d42ffdd | ||
|
|
866d3110da | ||
|
|
7a3e7fccec | ||
|
|
3107bc8840 | ||
|
|
2d34cdef5e | ||
|
|
bd1f0909a2 | ||
|
|
ef75de63fe | ||
|
|
a739d28563 | ||
|
|
66ff009b72 | ||
|
|
a68e82c1c8 | ||
|
|
46556c1c14 | ||
|
|
7be637798f | ||
|
|
9b3396349e | ||
|
|
ccff210b4c | ||
|
|
a2264847b6 | ||
|
|
7d103f8c50 | ||
|
|
f3dccc0aec | ||
|
|
311b1d8a64 | ||
|
|
f3094e3079 | ||
|
|
f3b37b16d5 | ||
|
|
5f16ecf02d | ||
|
|
8b75287827 | ||
|
|
bb38e806cd | ||
|
|
8cbc15f1b0 | ||
|
|
870524f9cf | ||
|
|
218343ca14 | ||
|
|
61953fd713 | ||
|
|
62ddf3a11b | ||
|
|
be12658864 | ||
|
|
b618e5a00f | ||
|
|
5da9963f31 | ||
|
|
34e885812f | ||
|
|
a9ac11452d | ||
|
|
04b91308b1 | ||
|
|
b09ef222f5 | ||
|
|
2d0ed06d50 | ||
|
|
8dd7cf6085 | ||
|
|
4999bd4f1e | ||
|
|
22f408addb | ||
|
|
9ca1dbe638 | ||
|
|
26662952e3 | ||
|
|
f0c9fa4ca3 | ||
|
|
b51aa1dd71 | ||
|
|
846253c9e3 | ||
|
|
6ab6ea97ac | ||
|
|
bf41f70b98 | ||
|
|
67ddbedd08 | ||
|
|
2573e219dc | ||
|
|
7e368678ab | ||
|
|
4a9fcf7ab6 | ||
|
|
65856c61c5 | ||
|
|
b5a97bffab | ||
|
|
e6d728715f | ||
|
|
54a52f0589 | ||
|
|
badfa23f86 | ||
|
|
4c36a9cca9 | ||
|
|
30ccd3487a | ||
|
|
75e012f2c9 | ||
|
|
5ecb1d1e2d | ||
|
|
f8c24c838a | ||
|
|
4ad9cfcdf4 | ||
|
|
a57253dd35 | ||
|
|
222e65bd45 | ||
|
|
3192ea3383 | ||
|
|
3a27f873cd | ||
|
|
e8fb279036 | ||
|
|
21ec7078d2 | ||
|
|
94937e9fa4 | ||
|
|
36401a20b8 | ||
|
|
8d1c4e4661 | ||
|
|
14362060c8 | ||
|
|
de47e94f62 | ||
|
|
c78ed78bf6 | ||
|
|
7674c95124 | ||
|
|
ec522c20b2 | ||
|
|
81f9578526 | ||
|
|
20bca751d4 | ||
|
|
49b5c49776 | ||
|
|
5d514fae61 | ||
|
|
9e17e93dd7 | ||
|
|
7f70c641dc | ||
|
|
7e3af4b7bc | ||
|
|
59ff4c0aef | ||
|
|
875e6b8e53 | ||
|
|
fafc44de7c | ||
|
|
e0d7eb10d5 | ||
|
|
ae01eb28a3 | ||
|
|
637c66c04f | ||
|
|
1c061e4428 | ||
|
|
cbe0626572 | ||
|
|
86dc98174a | ||
|
|
f0ac8ea977 | ||
|
|
35d4c2cdfc | ||
|
|
394f7c0d09 | ||
|
|
b83eee9bdc | ||
|
|
e41b2e8d31 | ||
|
|
d93cec2bfd | ||
|
|
9eb87a39cd | ||
|
|
07818ec1df | ||
|
|
d4052dbe37 | ||
|
|
656f5e0a7f | ||
|
|
f3d415a3a7 | ||
|
|
fd8ab990bd | ||
|
|
0cc5e4dac3 | ||
|
|
8bbfff3cb2 | ||
|
|
93059798b0 | ||
|
|
33fae88cad | ||
|
|
4feb23e9ca | ||
|
|
c2b6b7ba72 | ||
|
|
fb76aee258 | ||
|
|
320b1829cc | ||
|
|
601f0255a4 | ||
|
|
b6cc2b227a | ||
|
|
cc7da4b948 | ||
|
|
1ae3be2fda | ||
|
|
5b4d35ea86 | ||
|
|
00735e6c8e | ||
|
|
66a42a38c9 | ||
|
|
05af1fba80 | ||
|
|
3b2dd0f5e9 | ||
|
|
1493a66a36 | ||
|
|
b4bf103fd8 | ||
|
|
94286becfd | ||
|
|
a68aade58c | ||
|
|
014201edf4 | ||
|
|
8ae6297148 | ||
|
|
5e0300aa8e | ||
|
|
80a7e18413 | ||
|
|
5c007cdebc | ||
|
|
ef6c733f93 | ||
|
|
e7d6658c7a | ||
|
|
43be0a1a3f | ||
|
|
5eb32744c3 | ||
|
|
89d39f5f2b | ||
|
|
1f4900dd1e | ||
|
|
1c561c1483 | ||
|
|
6baaf60b67 | ||
|
|
dde73f6c2b | ||
|
|
f445a49b34 | ||
|
|
29016d1cf5 | ||
|
|
c06435046b | ||
|
|
134422802f | ||
|
|
5e00d6a305 | ||
|
|
b5f0137d8e | ||
|
|
081d041cbc | ||
|
|
95e733a67c | ||
|
|
a664057312 | ||
|
|
5b1a2d93bf | ||
|
|
0323f95828 | ||
|
|
375838449f | ||
|
|
4562de8c2c | ||
|
|
68d21669e7 | ||
|
|
625e0cf159 | ||
|
|
551ef00c61 | ||
|
|
10518f6364 | ||
|
|
1eafda36a9 | ||
|
|
871ecf0158 | ||
|
|
429000bdcb | ||
|
|
607940ed60 | ||
|
|
46f61a4311 | ||
|
|
3721df0502 | ||
|
|
11add681ec | ||
|
|
6e36eea6c8 | ||
|
|
6a82e7a24c | ||
|
|
5f625fa9f3 | ||
|
|
a95527674f | ||
|
|
f6149c67dc | ||
|
|
00c2a07e33 | ||
|
|
bc49b22c32 | ||
|
|
fe1b1c8bc3 | ||
|
|
a2825a06d6 | ||
|
|
3c33b5b169 | ||
|
|
639b81b228 | ||
|
|
0c552eb0c0 | ||
|
|
ae723f9557 | ||
|
|
34d691341b | ||
|
|
8574a11cf7 | ||
|
|
3742cd4a51 | ||
|
|
934a867c83 | ||
|
|
a36337fba8 | ||
|
|
b3bd53bdd0 | ||
|
|
55518d4a8e | ||
|
|
2949c330d7 | ||
|
|
7ec056dbe0 | ||
|
|
983b60a8b9 | ||
|
|
d7d411caf9 | ||
|
|
000c31b66c | ||
|
|
2cd3d4bfb7 | ||
|
|
9d9065c801 | ||
|
|
10e7fe56ab | ||
|
|
c832e62389 | ||
|
|
328e488322 | ||
|
|
fd5a43cdb4 | ||
|
|
fd7780abb0 | ||
|
|
11c23e0b5e | ||
|
|
1170cfd4a7 | ||
|
|
2eddaa954e | ||
|
|
2c472fd03f | ||
|
|
16019a787e | ||
|
|
717d0a75f4 | ||
|
|
cc9487bae8 | ||
|
|
5ed9ec8f46 | ||
|
|
6ca37ca7f4 | ||
|
|
1007b8b15d | ||
|
|
be3a95fd54 | ||
|
|
109cb6cc3f | ||
|
|
fe1509dcfc | ||
|
|
1797e33989 | ||
|
|
6c504eeb3e | ||
|
|
d4b16fcdd1 | ||
|
|
9a08c079b5 | ||
|
|
98e75a7d6c | ||
|
|
675fd13391 | ||
|
|
e4f042aba4 | ||
|
|
19527845d1 | ||
|
|
3aa981649c | ||
|
|
330d48f70d | ||
|
|
90e14aae99 | ||
|
|
77e2ed7e01 | ||
|
|
f720f921c3 | ||
|
|
328740909b | ||
|
|
c8a981e8d6 | ||
|
|
faac45784c | ||
|
|
25667e84b7 | ||
|
|
72e0d77be5 | ||
|
|
9ac4b9ed4f | ||
|
|
b3b89ba05c | ||
|
|
00dc04df25 | ||
|
|
21d47c3fef | ||
|
|
66de94f050 | ||
|
|
1917adb322 | ||
|
|
3360b29354 | ||
|
|
646d281759 | ||
|
|
e268d92d52 | ||
|
|
fa81db2f03 | ||
|
|
830199ba3a | ||
|
|
ea8dc506d3 | ||
|
|
c95483ed94 | ||
|
|
d9cb4480b2 | ||
|
|
c69afd6074 | ||
|
|
f541790ab4 | ||
|
|
707ac4ec36 | ||
|
|
cd55133e96 | ||
|
|
37a91f8529 | ||
|
|
0ed0fa37a1 | ||
|
|
26728b79b2 | ||
|
|
f7c8723539 | ||
|
|
c313916771 | ||
|
|
f0b30c5e91 | ||
|
|
73e3196124 | ||
|
|
8a7bcc316e | ||
|
|
a2921cb982 | ||
|
|
29ce004974 | ||
|
|
026ba5ddce | ||
|
|
ab0585609a | ||
|
|
14a8bdb0c0 | ||
|
|
397d04dd88 | ||
|
|
fbb0bb7491 | ||
|
|
ee987dae99 | ||
|
|
720281a8db | ||
|
|
ff0c89e5a3 | ||
|
|
442937f540 | ||
|
|
dc01b787c1 | ||
|
|
c709b5d34c | ||
|
|
f8b386e42d | ||
|
|
f6b454cb9a | ||
|
|
a82f8ce3ad | ||
|
|
529d45b762 | ||
|
|
d31135bf21 | ||
|
|
75a77acefe | ||
|
|
715f42b6c3 | ||
|
|
199bfc8a37 | ||
|
|
e82ae762f0 | ||
|
|
f90cc9aff7 | ||
|
|
ec915177ad | ||
|
|
5adee3e217 | ||
|
|
278d82645e | ||
|
|
e66f13b471 | ||
|
|
0e2955b57e | ||
|
|
2a4d5ec1ec | ||
|
|
07ce63de69 | ||
|
|
b539862eef | ||
|
|
ac4be3f8a8 | ||
|
|
0dc2d07b58 | ||
|
|
b097f9dc21 | ||
|
|
8aa4a97480 | ||
|
|
3e54d0ceae | ||
|
|
e1cec3404a | ||
|
|
9a2b7fbda1 | ||
|
|
e0b4ebed93 | ||
|
|
e00e3999c5 | ||
|
|
2cbe96d815 | ||
|
|
ac3b289c9e | ||
|
|
62534e0e93 | ||
|
|
b802c3174c | ||
|
|
aee1a6e1f0 | ||
|
|
46f1cd38e0 | ||
|
|
7f891ef523 | ||
|
|
06af5e15cd | ||
|
|
af89a0a883 | ||
|
|
fa72eb2edb | ||
|
|
c1ea94423b | ||
|
|
1e70d066bd | ||
|
|
ab89f16e7c | ||
|
|
8c848a4cb5 | ||
|
|
e021a54d2d | ||
|
|
70523574b0 | ||
|
|
66e0f1ab19 | ||
|
|
671a05470e | ||
|
|
99eec0c41e | ||
|
|
48d06dcb06 | ||
|
|
e38df0c731 | ||
|
|
0f3f49915e | ||
|
|
416144265b | ||
|
|
2e7ced8e60 | ||
|
|
563463782c | ||
|
|
fe02871e91 | ||
|
|
bb05aeeaf7 | ||
|
|
846358ccb0 | ||
|
|
dabc779727 | ||
|
|
08fd2ec64b | ||
|
|
c42c06d048 | ||
|
|
e951d60800 | ||
|
|
0d8453f6a7 | ||
|
|
52b41b1bb0 | ||
|
|
c7265017b3 | ||
|
|
634e0b6d30 | ||
|
|
1c260f5890 | ||
|
|
177aedeaae | ||
|
|
3f6f3d2565 | ||
|
|
38489dbfeb | ||
|
|
ff2a3d6a28 | ||
|
|
2c74697fb1 | ||
|
|
110e9200b9 | ||
|
|
6e792f9735 | ||
|
|
51d8b13a81 | ||
|
|
a05691fd07 | ||
|
|
d25e7915d9 | ||
|
|
1a025dfef3 | ||
|
|
84cc4194aa | ||
|
|
331a56277c | ||
|
|
bc2915adb9 | ||
|
|
703fe9a71b | ||
|
|
6c50664046 | ||
|
|
673cbc97e1 | ||
|
|
3e83766099 | ||
|
|
b453589077 | ||
|
|
654fa18ab1 | ||
|
|
7b0d91534c | ||
|
|
8d4801bb6f | ||
|
|
9e36f4f625 | ||
|
|
d83a824812 | ||
|
|
ca128f2fa9 | ||
|
|
c02642d0f9 | ||
|
|
7340709111 | ||
|
|
56d0383372 | ||
|
|
49d33ea19a | ||
|
|
979fa0359a | ||
|
|
c7381d058a | ||
|
|
5db298f031 | ||
|
|
171d948a00 | ||
|
|
facd56cdf4 | ||
|
|
ba17ec4be4 | ||
|
|
6c163b5479 | ||
|
|
79649805b8 | ||
|
|
220ca8a570 | ||
|
|
348c00f86d | ||
|
|
12b641b522 | ||
|
|
6855bc1de6 | ||
|
|
a9c5b99ae8 | ||
|
|
76f36e2fd3 | ||
|
|
afe710321c | ||
|
|
0d444daaca | ||
|
|
c8a0c9fd23 | ||
|
|
79f07ae923 | ||
|
|
c77e7a568b | ||
|
|
ff9ec2057b | ||
|
|
6a313b99e4 | ||
|
|
8a92370042 | ||
|
|
411a59ec54 | ||
|
|
2d4022044d | ||
|
|
bbc5ebd76b | ||
|
|
e9c90fcde8 | ||
|
|
911f78867f | ||
|
|
5507cc5abc | ||
|
|
0e5aa401ef | ||
|
|
d48473ab87 | ||
|
|
734efaf40c | ||
|
|
f89718d88a | ||
|
|
aa4942a0da | ||
|
|
90bb162a88 | ||
|
|
0382a4b30e | ||
|
|
490d940cd1 | ||
|
|
b090eb9359 | ||
|
|
cb9e67ce84 | ||
|
|
c4d131dd23 | ||
|
|
2667f266bf | ||
|
|
8258936d6c | ||
|
|
e4e7449078 | ||
|
|
11b020e859 | ||
|
|
72d6b83ec5 | ||
|
|
fbe5152cb3 | ||
|
|
6bef01f755 | ||
|
|
f0d4b4a6d9 | ||
|
|
a54fe62643 | ||
|
|
eb4bbd49fb | ||
|
|
ab4f1bd4f4 | ||
|
|
f8b414c354 | ||
|
|
82a21624c3 | ||
|
|
1b212ac720 | ||
|
|
c36ce3ea14 | ||
|
|
841fab77a8 | ||
|
|
fd6f910824 | ||
|
|
ce9ca1917d | ||
|
|
c702fb273c | ||
|
|
4c72d8691b | ||
|
|
35ac5fc514 | ||
|
|
92991cc03c | ||
|
|
76492475e3 | ||
|
|
e2363d860c | ||
|
|
c06a90913a | ||
|
|
e88c0f7326 | ||
|
|
2a4280b5bf | ||
|
|
d3c733c57f | ||
|
|
f91add3cd4 | ||
|
|
90e3f7508a | ||
|
|
5e981da4df | ||
|
|
2ddd5d75fc | ||
|
|
88f509cbb6 | ||
|
|
ca161bc881 | ||
|
|
676ca44cdf | ||
|
|
5d0c91202f | ||
|
|
a166f049d5 | ||
|
|
0dc4692dfc | ||
|
|
996607d096 | ||
|
|
bd907ea008 | ||
|
|
b1573b1f3b | ||
|
|
246849ce94 | ||
|
|
2c2c68261a | ||
|
|
e38a0361bf | ||
|
|
cbf879bd32 | ||
|
|
808625e564 | ||
|
|
19781bb14c | ||
|
|
7fd2bc30cc | ||
|
|
c3b4c2f7d4 | ||
|
|
14f521fdd7 | ||
|
|
087831df5a | ||
|
|
07f273fda4 | ||
|
|
6b0542a5bf | ||
|
|
ac57856f00 | ||
|
|
2ab1587df0 | ||
|
|
632aa6e003 | ||
|
|
9142f2df4b | ||
|
|
eea4cbbd6c | ||
|
|
bb31c20282 | ||
|
|
f8ab206744 | ||
|
|
4129b3a96e | ||
|
|
0de704bd3e | ||
|
|
5f20ce87a7 | ||
|
|
ff80154fda | ||
|
|
0d99cf9fb9 | ||
|
|
a5306b2067 | ||
|
|
e9b826e498 | ||
|
|
e7f356b87c | ||
|
|
d2abde714f | ||
|
|
20eaa79079 | ||
|
|
3cb74bb844 | ||
|
|
a72d4f425a | ||
|
|
8f3545624e | ||
|
|
8f6cfe8a04 | ||
|
|
bec7943e05 | ||
|
|
a486f5951e | ||
|
|
e8158aadec | ||
|
|
b6f107b85b | ||
|
|
5abd27f252 | ||
|
|
39648b6df8 | ||
|
|
0a7b2e3304 | ||
|
|
48db6e1756 | ||
|
|
2a38af5db6 | ||
|
|
740b1093d7 | ||
|
|
6b70412f6e | ||
|
|
43f147ec60 | ||
|
|
bf0fc57493 | ||
|
|
325b8b886c | ||
|
|
a02bbdc550 | ||
|
|
4285fd7708 | ||
|
|
96fa6eac44 | ||
|
|
05fa1ef2fb | ||
|
|
13aebc060e | ||
|
|
1aae4098d6 | ||
|
|
3367bb2e5b | ||
|
|
49fc5e1559 | ||
|
|
3a9b448a83 | ||
|
|
a45fb975c0 | ||
|
|
e070fc2f52 | ||
|
|
5f8aac31e1 | ||
|
|
07f2e2eafc | ||
|
|
2b41fb7108 | ||
|
|
81c18f1869 | ||
|
|
61fd2fe87d | ||
|
|
054cb974f1 | ||
|
|
50a19ecd74 | ||
|
|
1232909a3b | ||
|
|
9ba0e076a6 | ||
|
|
ede91c645d | ||
|
|
b6a91723e7 | ||
|
|
fddd73fdb1 | ||
|
|
ffbe8f9dc4 | ||
|
|
f80763ffb4 | ||
|
|
f65aa1b875 | ||
|
|
0c4de9a5e0 | ||
|
|
1822970e23 | ||
|
|
80615d0382 | ||
|
|
c1002ed52a | ||
|
|
83e585ed35 | ||
|
|
0e164b9daa | ||
|
|
1c9f8a2540 | ||
|
|
88ba4451eb | ||
|
|
305f195539 | ||
|
|
fbc6b853ed | ||
|
|
f3bcab813a | ||
|
|
2fa9b2e4dd | ||
|
|
fc756ba46e | ||
|
|
85a82124b1 | ||
|
|
b5cfbc92af | ||
|
|
e4f260e242 | ||
|
|
7c6c0c1fbd | ||
|
|
2f5f4dbebd | ||
|
|
94adc6af95 | ||
|
|
e3ea703f3d | ||
|
|
a14753e5f3 | ||
|
|
2ffd55c2d8 | ||
|
|
ad0ee8da32 | ||
|
|
e5cfe37b17 | ||
|
|
9247dd8b17 | ||
|
|
2f69b1d6e1 | ||
|
|
9c43930e7b | ||
|
|
f18ecfa524 | ||
|
|
b6f7453ed9 | ||
|
|
4a0b77dabb | ||
|
|
de7687b3ab | ||
|
|
85f2ec9d92 | ||
|
|
ed6b8dfc9b | ||
|
|
1539a6eabc | ||
|
|
6424d96703 | ||
|
|
15f6ac8e89 | ||
|
|
f9803a4694 | ||
|
|
b08126ec2b | ||
|
|
e0824a5426 | ||
|
|
c4f5471e13 | ||
|
|
13de9975e3 | ||
|
|
99215c272c | ||
|
|
a64c4ef66f | ||
|
|
36e85eb3a7 | ||
|
|
20ffe7e082 | ||
|
|
ea1dc58b9a | ||
|
|
cd292ad605 | ||
|
|
03d9a6c0e5 | ||
|
|
fa54a2e67c | ||
|
|
7f2530470d | ||
|
|
a284934136 | ||
|
|
2ca6606508 | ||
|
|
bb1c691b34 | ||
|
|
19d3e1b11c | ||
|
|
e35e64caaa | ||
|
|
a3cf72c76c | ||
|
|
710e95bdee | ||
|
|
d281fb7065 | ||
|
|
e669d5041b | ||
|
|
d8d91451c8 | ||
|
|
b0910baaf0 | ||
|
|
ce3f70adc3 | ||
|
|
c0d5c26f0c | ||
|
|
1bf8a76cc3 | ||
|
|
7b1f74a413 | ||
|
|
3d2fde77a5 | ||
|
|
e4cc3bef73 | ||
|
|
f384c422c4 | ||
|
|
a373d2e7e0 | ||
|
|
1aaf630979 | ||
|
|
b7ac3aba72 | ||
|
|
ed89250624 | ||
|
|
d9a7f0c7fe | ||
|
|
a07405bec3 | ||
|
|
4c6efeb0d8 | ||
|
|
501b380d5e | ||
|
|
ddc4e34dcd | ||
|
|
d668d9f24d | ||
|
|
0ec4423ad4 | ||
|
|
51313ff0d5 | ||
|
|
37381b7c36 | ||
|
|
6de632d117 | ||
|
|
4a8fa7293b | ||
|
|
b75a2e9592 | ||
|
|
c45c1b0f93 | ||
|
|
af7057f062 | ||
|
|
85bf1eb4ec | ||
|
|
bd45043a36 | ||
|
|
fbb41168a2 | ||
|
|
674fe4fa20 | ||
|
|
4db86f9322 | ||
|
|
5c814155d2 | ||
|
|
c08fb9af16 | ||
|
|
1dac4fea9c | ||
|
|
ac19000ad0 | ||
|
|
221182389a | ||
|
|
5d5947f676 | ||
|
|
8fc889ae08 | ||
|
|
ff46493775 | ||
|
|
a1cb3b8371 | ||
|
|
51131433d3 | ||
|
|
eaccd641ed | ||
|
|
3e2b647f06 | ||
|
|
0fbf9bafbc | ||
|
|
924a5e3110 | ||
|
|
be71a4b5c4 | ||
|
|
1cb5a13ea4 | ||
|
|
e145cd80a9 | ||
|
|
58ea661d4b | ||
|
|
ba317eff3f | ||
|
|
ead0e14118 | ||
|
|
d3dd20b50f | ||
|
|
d621fb4105 | ||
|
|
a239604dad | ||
|
|
f7986b9049 | ||
|
|
0a34ca031a | ||
|
|
ce63fec413 | ||
|
|
719451bf23 | ||
|
|
10a27cbe86 | ||
|
|
51325e2f4a | ||
|
|
3c8a066f76 | ||
|
|
6856a98d50 | ||
|
|
120b767a68 | ||
|
|
8c0d4cde86 | ||
|
|
280697f2f7 | ||
|
|
0650be664d | ||
|
|
60c61f553a | ||
|
|
022c967781 | ||
|
|
bd7e47d8f0 | ||
|
|
457a7a03fb | ||
|
|
6e486c64f1 | ||
|
|
4f3575d765 | ||
|
|
f5f1b27754 | ||
|
|
b9cef158d8 | ||
|
|
a3a3b3cb5c | ||
|
|
5ec6141369 | ||
|
|
55ac1e01f2 | ||
|
|
65b58c3668 | ||
|
|
2cb4e5e8dc | ||
|
|
72cea245f1 | ||
|
|
08ca86c68a | ||
|
|
925c9c1e7b | ||
|
|
6212ea0304 | ||
|
|
f295592134 | ||
|
|
69b0973e6d | ||
|
|
422d318dac | ||
|
|
c55aa6ee88 | ||
|
|
090b175152 | ||
|
|
11e9b097a2 | ||
|
|
2adfc1d32b | ||
|
|
99fa5d89e7 | ||
|
|
ca8cbf8ccf | ||
|
|
6722d2d266 | ||
|
|
508cbeaa1b | ||
|
|
e040865905 | ||
|
|
a7878dd2c6 | ||
|
|
02980834ad | ||
|
|
2a8c8871c4 | ||
|
|
893be24c1d | ||
|
|
9029f59410 | ||
|
|
d4aaf4ca9b | ||
|
|
4b5e8d33a6 | ||
|
|
09196c045f | ||
|
|
7868ebec1e | ||
|
|
80a9182f05 | ||
|
|
d20b3d854f | ||
|
|
f1356228a3 | ||
|
|
a4adc51e50 | ||
|
|
864543e4f9 | ||
|
|
33a549202b | ||
|
|
c4a0219b18 | ||
|
|
e7450b5143 | ||
|
|
fd90454eb6 | ||
|
|
f327b54c0e | ||
|
|
f38105ef05 | ||
|
|
6f6041ee7b | ||
|
|
2c1517d259 |
@@ -1,6 +1,6 @@
|
||||
root = true
|
||||
|
||||
[*.{js,ts,tsx,css}]
|
||||
[*.{js,cjs,ts,tsx,css}]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
|
||||
1
.github/actions/build-electron/action.yml
vendored
1
.github/actions/build-electron/action.yml
vendored
@@ -85,6 +85,7 @@ runs:
|
||||
APPLE_ID: ${{ env.APPLE_ID }}
|
||||
APPLE_ID_PASSWORD: ${{ env.APPLE_ID_PASSWORD }}
|
||||
WINDOWS_SIGN_EXECUTABLE: ${{ env.WINDOWS_SIGN_EXECUTABLE }}
|
||||
WINDOWS_SIGN_ERROR_LOG: ${{ env.WINDOWS_SIGN_ERROR_LOG }}
|
||||
TRILIUM_ARTIFACT_NAME_HINT: TriliumNotes-${{ github.ref_name }}-${{ inputs.os }}-${{ inputs.arch }}
|
||||
TARGET_ARCH: ${{ inputs.arch }}
|
||||
run: pnpm run --filter desktop electron-forge:make --arch=${{ inputs.arch }} --platform=${{ inputs.forge_platform }}
|
||||
|
||||
2
.github/actions/build-server/action.yml
vendored
2
.github/actions/build-server/action.yml
vendored
@@ -8,7 +8,7 @@ inputs:
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
|
||||
2
.github/actions/report-size/action.yml
vendored
2
.github/actions/report-size/action.yml
vendored
@@ -69,7 +69,7 @@ runs:
|
||||
|
||||
# Post github action comment
|
||||
- name: Post comment
|
||||
uses: marocchino/sticky-pull-request-comment@v2
|
||||
uses: marocchino/sticky-pull-request-comment@v3
|
||||
if: ${{ steps.bundleSize.outputs.hasDifferences == 'true' }} # post only in case of changes
|
||||
with:
|
||||
number: ${{ github.event.pull_request.number }}
|
||||
|
||||
22
.github/copilot-instructions.md
vendored
22
.github/copilot-instructions.md
vendored
@@ -186,6 +186,14 @@ When adding query parameters to ETAPI endpoints (`apps/server/src/etapi/`), main
|
||||
|
||||
**Auth note**: ETAPI uses basic auth with tokens. Internal API endpoints trust the frontend.
|
||||
|
||||
### Adding New LLM Tools
|
||||
Tools are defined using `defineTools()` in `apps/server/src/services/llm/tools/` and automatically registered for both the LLM chat and MCP server.
|
||||
|
||||
1. Add the tool definition in the appropriate module (`note_tools.ts`, `attribute_tools.ts`, `hierarchy_tools.ts`) or create a new module
|
||||
2. Each tool needs: `description`, `inputSchema` (Zod), `execute` function, and optionally `mutates: true` for write operations or `needsContext: true` for tools that need the current note context
|
||||
3. If creating a new module, wrap tools in `defineTools({...})` and add the registry to `allToolRegistries` in `tools/index.ts`
|
||||
4. Add a client-side friendly name in `apps/client/src/translations/en/translation.json` under `llm.tools.<tool_name>` — use **imperative tense** (e.g. "Search notes", "Create note", "Get attributes"), not present continuous
|
||||
|
||||
### Database Migrations
|
||||
- Add scripts in `apps/server/src/migrations/YYMMDD_HHMM__description.sql`
|
||||
- Update schema in `apps/server/src/assets/db/schema.sql`
|
||||
@@ -213,6 +221,12 @@ When adding query parameters to ETAPI endpoints (`apps/server/src/etapi/`), main
|
||||
|
||||
10. **Attribute inheritance can be complex** - When checking for labels/relations, use `note.getOwnedAttribute()` for direct attributes or `note.getAttribute()` for inherited ones. Don't assume attributes are directly on the note.
|
||||
|
||||
## MCP Server
|
||||
- Trilium exposes an MCP (Model Context Protocol) server at `http://localhost:8080/mcp`, configured in `.mcp.json`
|
||||
- The MCP server is **only available when the Trilium server is running** (`pnpm run server:start`)
|
||||
- It provides tools for reading, searching, and modifying notes directly from the AI assistant
|
||||
- Use it to interact with actual note data when developing or debugging note-related features
|
||||
|
||||
## TypeScript Configuration
|
||||
|
||||
- **Project references**: Monorepo uses TypeScript project references (`tsconfig.json`)
|
||||
@@ -275,6 +289,12 @@ View types are configured via `#viewType` label (e.g., `#viewType=table`). Each
|
||||
- Register in `packages/ckeditor5/src/plugins.ts`
|
||||
- See `ckeditor5-admonition`, `ckeditor5-footnotes`, `ckeditor5-math`, `ckeditor5-mermaid` for examples
|
||||
|
||||
### Updating PDF.js
|
||||
1. Update `pdfjs-dist` version in `packages/pdfjs-viewer/package.json`
|
||||
2. Run `npx tsx scripts/update-viewer.ts` from that directory
|
||||
3. Run `pnpm build` to verify success
|
||||
4. Commit all changes including updated viewer files
|
||||
|
||||
### Database Migrations
|
||||
- Add migration scripts in `apps/server/src/migrations/YYMMDD_HHMM__description.sql`
|
||||
- Update schema in `apps/server/src/assets/db/schema.sql`
|
||||
@@ -299,6 +319,8 @@ Trilium provides powerful user scripting capabilities:
|
||||
- Translation files in `apps/client/src/translations/`
|
||||
- Use translation system via `t()` function
|
||||
- Automatic pluralization: Add `_other` suffix to translation keys (e.g., `item` and `item_other` for singular/plural)
|
||||
- When a translated string contains **interpolated components** (e.g. links, note references) whose order may vary across languages, use `<Trans>` from `react-i18next` instead of `t()`. This lets translators reorder components freely (e.g. `"<Note/> in <Parent/>"` vs `"in <Parent/>, <Note/>"`)
|
||||
- When adding a new locale, follow the step-by-step guide in `docs/Developer Guide/Developer Guide/Concepts/Internationalisation Translations/Adding a new locale.md`
|
||||
|
||||
## Testing Conventions
|
||||
|
||||
|
||||
2
.github/workflows/checks.yml
vendored
2
.github/workflows/checks.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
steps:
|
||||
- name: Check if PRs have conflicts
|
||||
uses: eps1lon/actions-label-merge-conflict@v3
|
||||
if: github.repository == ${{ vars.REPO_MAIN }}
|
||||
if: ${{ github.repository == vars.REPO_MAIN }}
|
||||
with:
|
||||
dirtyLabel: "merge-conflicts"
|
||||
repoToken: "${{ secrets.MERGE_CONFLICT_LABEL_PAT }}"
|
||||
|
||||
4
.github/workflows/deploy-docs.yml
vendored
4
.github/workflows/deploy-docs.yml
vendored
@@ -45,7 +45,7 @@ jobs:
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
uses: pnpm/action-setup@v5
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
@@ -67,7 +67,7 @@ jobs:
|
||||
|
||||
- name: Deploy
|
||||
uses: ./.github/actions/deploy-to-cloudflare-pages
|
||||
if: github.repository == ${{ vars.REPO_MAIN }}
|
||||
if: ${{ github.repository == vars.REPO_MAIN }}
|
||||
with:
|
||||
project_name: "trilium-docs"
|
||||
comment_body: "📚 Documentation preview is ready"
|
||||
|
||||
53
.github/workflows/dev.yml
vendored
53
.github/workflows/dev.yml
vendored
@@ -1,9 +1,13 @@
|
||||
name: Dev
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
branches:
|
||||
- main
|
||||
- "release/*"
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
branches:
|
||||
- main
|
||||
- "release/*"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -26,7 +30,7 @@ jobs:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
@@ -37,8 +41,35 @@ jobs:
|
||||
- name: Typecheck
|
||||
run: pnpm typecheck
|
||||
|
||||
- name: Run the unit tests
|
||||
run: pnpm run test:all
|
||||
- name: Run the client-side tests
|
||||
run: pnpm run --filter=client test
|
||||
|
||||
- name: Upload client test report
|
||||
uses: actions/upload-artifact@v7
|
||||
if: always()
|
||||
with:
|
||||
name: client-test-report
|
||||
path: apps/client/test-output/vitest/html/
|
||||
retention-days: 30
|
||||
|
||||
- name: Run the server-side tests
|
||||
run: pnpm run --filter=server test
|
||||
|
||||
- name: Upload server test report
|
||||
uses: actions/upload-artifact@v7
|
||||
if: always()
|
||||
with:
|
||||
name: server-test-report
|
||||
path: apps/server/test-output/vitest/html/
|
||||
retention-days: 30
|
||||
|
||||
- name: Run CKEditor e2e tests
|
||||
run: |
|
||||
pnpm run --filter=ckeditor5-mermaid test
|
||||
pnpm run --filter=ckeditor5-math test
|
||||
|
||||
- name: Run the rest of the tests
|
||||
run: pnpm run --filter=\!client --filter=\!server --filter=\!ckeditor5-mermaid --filter=\!ckeditor5-math test
|
||||
|
||||
build_docker:
|
||||
name: Build Docker image
|
||||
@@ -47,7 +78,7 @@ jobs:
|
||||
- test_dev
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Update build info
|
||||
@@ -62,8 +93,8 @@ jobs:
|
||||
key: ${{ secrets.RELATIVE_CI_CLIENT_KEY }}
|
||||
- name: Trigger server build
|
||||
run: pnpm run server:build
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- uses: docker/build-push-action@v6
|
||||
- uses: docker/setup-buildx-action@v4
|
||||
- uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: apps/server
|
||||
cache-from: type=gha
|
||||
@@ -82,7 +113,7 @@ jobs:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
@@ -97,10 +128,10 @@ jobs:
|
||||
run: echo "TEST_TAG=${TEST_TAG,,}" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Build and export to Docker
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: apps/server
|
||||
file: apps/server/${{ matrix.dockerfile }}
|
||||
|
||||
2
.github/workflows/i18n.yml
vendored
2
.github/workflows/i18n.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
|
||||
146
.github/workflows/main-docker.yml
vendored
146
.github/workflows/main-docker.yml
vendored
@@ -40,9 +40,9 @@ jobs:
|
||||
run: echo "TEST_TAG=${TEST_TAG,,}" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
@@ -59,7 +59,7 @@ jobs:
|
||||
run: pnpm run server:build
|
||||
|
||||
- name: Build and export to Docker
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: apps/server
|
||||
file: apps/server/${{ matrix.dockerfile }}
|
||||
@@ -86,12 +86,12 @@ jobs:
|
||||
|
||||
- name: Upload Playwright trace
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: Playwright trace (${{ matrix.dockerfile }})
|
||||
path: test-output/playwright/output
|
||||
|
||||
- uses: actions/upload-artifact@v6
|
||||
- uses: actions/upload-artifact@v7
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
name: Playwright report (${{ matrix.dockerfile }})
|
||||
@@ -142,7 +142,7 @@ jobs:
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
@@ -164,11 +164,9 @@ jobs:
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
uses: docker/metadata-action@v6
|
||||
with:
|
||||
images: |
|
||||
${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
images: ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
@@ -177,28 +175,21 @@ jobs:
|
||||
latest=false
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
uses: docker/setup-qemu-action@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ${{ env.GHCR_REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.DOCKERHUB_REGISTRY }}
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build and push by digest
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: apps/server
|
||||
file: apps/server/${{ matrix.dockerfile }}
|
||||
@@ -213,7 +204,7 @@ jobs:
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: digests-${{ env.PLATFORM_PAIR }}-${{ matrix.dockerfile }}
|
||||
path: /tmp/digests/*
|
||||
@@ -227,7 +218,7 @@ jobs:
|
||||
- build
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v7
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
path: /tmp/digests
|
||||
pattern: digests-*
|
||||
@@ -237,75 +228,86 @@ jobs:
|
||||
- name: Set TEST_TAG to lowercase
|
||||
run: echo "TEST_TAG=${TEST_TAG,,}" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
flavor: |
|
||||
latest=false
|
||||
- name: Set up crane
|
||||
uses: imjasonh/setup-crane@v0.5
|
||||
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ${{ env.GHCR_REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ${{ env.DOCKERHUB_REGISTRY }}
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Create manifest list and push
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v6
|
||||
with:
|
||||
images: ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha
|
||||
flavor: |
|
||||
latest=false
|
||||
|
||||
- name: Verify digests exist on GHCR
|
||||
working-directory: /tmp/digests
|
||||
run: |
|
||||
# Extract the branch or tag name from the ref
|
||||
REF_NAME=$(echo "${GITHUB_REF}" | sed 's/refs\/heads\///' | sed 's/refs\/tags\///')
|
||||
echo "Verifying all digests are available on GHCR..."
|
||||
for DIGEST_FILE in *; do
|
||||
DIGEST="sha256:${DIGEST_FILE}"
|
||||
echo -n " ${DIGEST}: "
|
||||
crane manifest "${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}@${DIGEST}" > /dev/null
|
||||
echo "OK"
|
||||
done
|
||||
|
||||
# Create and push the manifest list with both the branch/tag name and the commit SHA
|
||||
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||
-t ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:${REF_NAME} \
|
||||
$(printf '${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
|
||||
- name: Create and push multi-arch manifest
|
||||
working-directory: /tmp/digests
|
||||
run: |
|
||||
GHCR_IMAGE="${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}"
|
||||
DOCKERHUB_IMAGE="${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}"
|
||||
|
||||
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||
-t ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${REF_NAME} \
|
||||
$(printf '${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
|
||||
# Build -m flags for crane index append from digest files
|
||||
MANIFEST_ARGS=""
|
||||
for d in *; do
|
||||
MANIFEST_ARGS="${MANIFEST_ARGS} -m ${GHCR_IMAGE}@sha256:${d}"
|
||||
done
|
||||
|
||||
# If the ref is a tag, also tag the image as stable as this is part of a 'release'
|
||||
# and only go in the `if` if there is NOT a `-` in the tag's name, due to tagging of `-alpha`, `-beta`, etc...
|
||||
# Create multi-arch manifest for each tag from metadata, plus copy to DockerHub
|
||||
while IFS= read -r TAG; do
|
||||
echo "Creating manifest: ${TAG}"
|
||||
crane index append ${MANIFEST_ARGS} -t "${TAG}"
|
||||
|
||||
SUFFIX="${TAG#*:}"
|
||||
echo "Copying to DockerHub: ${DOCKERHUB_IMAGE}:${SUFFIX}"
|
||||
crane copy "${TAG}" "${DOCKERHUB_IMAGE}:${SUFFIX}"
|
||||
done <<< "${{ steps.meta.outputs.tags }}"
|
||||
|
||||
# For stable releases (tags without hyphens), also create stable + latest
|
||||
REF_NAME="${GITHUB_REF#refs/tags/}"
|
||||
if [[ "${GITHUB_REF}" == refs/tags/* && ! "${REF_NAME}" =~ - ]]; then
|
||||
# First create stable tags
|
||||
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||
-t ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:stable \
|
||||
$(printf '${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
|
||||
|
||||
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||
-t ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:stable \
|
||||
$(printf '${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
|
||||
|
||||
# Small delay to ensure stable tag is fully propagated
|
||||
sleep 5
|
||||
|
||||
# Now update latest tags
|
||||
docker buildx imagetools create \
|
||||
-t ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:latest \
|
||||
${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:stable
|
||||
|
||||
docker buildx imagetools create \
|
||||
-t ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest \
|
||||
${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:stable
|
||||
echo "Creating stable tags..."
|
||||
crane index append ${MANIFEST_ARGS} -t "${GHCR_IMAGE}:stable"
|
||||
crane copy "${GHCR_IMAGE}:stable" "${DOCKERHUB_IMAGE}:stable"
|
||||
|
||||
echo "Creating latest tags..."
|
||||
crane copy "${GHCR_IMAGE}:stable" "${GHCR_IMAGE}:latest"
|
||||
crane copy "${GHCR_IMAGE}:latest" "${DOCKERHUB_IMAGE}:latest"
|
||||
fi
|
||||
|
||||
- name: Inspect image
|
||||
- name: Inspect manifests
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}
|
||||
docker buildx imagetools inspect ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}
|
||||
REF_NAME="${GITHUB_REF#refs/heads/}"
|
||||
REF_NAME="${REF_NAME#refs/tags/}"
|
||||
echo "=== GHCR ==="
|
||||
crane manifest "${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:${REF_NAME}"
|
||||
echo ""
|
||||
echo "=== DockerHub ==="
|
||||
crane manifest "${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${REF_NAME}"
|
||||
|
||||
15
.github/workflows/nightly.yml
vendored
15
.github/workflows/nightly.yml
vendored
@@ -26,7 +26,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
nightly-electron:
|
||||
if: github.repository == ${{ vars.REPO_MAIN }}
|
||||
if: ${{ github.repository == vars.REPO_MAIN }}
|
||||
name: Deploy nightly
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -61,7 +61,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os.image }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
@@ -69,6 +69,8 @@ jobs:
|
||||
cache: 'pnpm'
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
env:
|
||||
npm_config_package_import_method: copy
|
||||
- name: Update nightly version
|
||||
run: pnpm run chore:ci-update-nightly-version
|
||||
- name: Run the build
|
||||
@@ -87,10 +89,11 @@ jobs:
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||
WINDOWS_SIGN_EXECUTABLE: ${{ vars.WINDOWS_SIGN_EXECUTABLE }}
|
||||
WINDOWS_SIGN_ERROR_LOG: ${{ vars.WINDOWS_SIGN_ERROR_LOG }}
|
||||
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGN_KEY }}
|
||||
|
||||
- name: Publish release
|
||||
uses: softprops/action-gh-release@v2.5.0
|
||||
uses: softprops/action-gh-release@v2.6.1
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
with:
|
||||
make_latest: false
|
||||
@@ -102,14 +105,14 @@ jobs:
|
||||
name: Nightly Build
|
||||
|
||||
- name: Publish artifacts
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v7
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
with:
|
||||
name: TriliumNotes ${{ matrix.os.name }} ${{ matrix.arch }}
|
||||
path: apps/desktop/upload
|
||||
|
||||
nightly-server:
|
||||
if: github.repository == ${{ vars.REPO_MAIN }}
|
||||
if: ${{ github.repository == vars.REPO_MAIN }}
|
||||
name: Deploy server nightly
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -131,7 +134,7 @@ jobs:
|
||||
arch: ${{ matrix.arch }}
|
||||
|
||||
- name: Publish release
|
||||
uses: softprops/action-gh-release@v2.5.0
|
||||
uses: softprops/action-gh-release@v2.6.1
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
with:
|
||||
make_latest: false
|
||||
|
||||
4
.github/workflows/playwright.yml
vendored
4
.github/workflows/playwright.yml
vendored
@@ -38,7 +38,7 @@ jobs:
|
||||
filter: tree:0
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
@@ -77,7 +77,7 @@ jobs:
|
||||
|
||||
- name: Upload test report
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: e2e report ${{ matrix.arch }}
|
||||
path: apps/server-e2e/test-output
|
||||
|
||||
25
.github/workflows/release.yml
vendored
25
.github/workflows/release.yml
vendored
@@ -17,10 +17,22 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: pnpm/action-setup@v5
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --filter source --frozen-lockfile --ignore-scripts
|
||||
|
||||
- name: Check version consistency
|
||||
run: pnpm tsx ${{ github.workspace }}/scripts/check-version-consistency.ts ${{ github.ref_name }}
|
||||
make-electron:
|
||||
name: Make Electron
|
||||
needs:
|
||||
- sanity-check
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -54,7 +66,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os.image }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
@@ -78,16 +90,19 @@ jobs:
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||
WINDOWS_SIGN_EXECUTABLE: ${{ vars.WINDOWS_SIGN_EXECUTABLE }}
|
||||
WINDOWS_SIGN_ERROR_LOG: ${{ vars.WINDOWS_SIGN_ERROR_LOG }}
|
||||
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGN_KEY }}
|
||||
|
||||
- name: Upload the artifact
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: release-desktop-${{ matrix.os.name }}-${{ matrix.arch }}
|
||||
path: apps/desktop/upload/*.*
|
||||
|
||||
build_server:
|
||||
name: Build Linux Server
|
||||
needs:
|
||||
- sanity-check
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -108,7 +123,7 @@ jobs:
|
||||
arch: ${{ matrix.arch }}
|
||||
|
||||
- name: Upload the artifact
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: release-server-linux-${{ matrix.arch }}
|
||||
path: upload/*.*
|
||||
@@ -128,14 +143,14 @@ jobs:
|
||||
docs/Release Notes
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v7
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
merge-multiple: true
|
||||
pattern: release-*
|
||||
path: upload
|
||||
|
||||
- name: Publish stable release
|
||||
uses: softprops/action-gh-release@v2.5.0
|
||||
uses: softprops/action-gh-release@v2.6.1
|
||||
with:
|
||||
draft: false
|
||||
body_path: docs/Release Notes/Release Notes/${{ github.ref_name }}.md
|
||||
|
||||
6
.github/workflows/web-clipper.yml
vendored
6
.github/workflows/web-clipper.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
pnpm --filter web-clipper zip:firefox
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v7
|
||||
if: ${{ !startsWith(github.ref, 'refs/tags/web-clipper-v') }}
|
||||
with:
|
||||
name: web-clipper-extension
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
compression-level: 0
|
||||
|
||||
- name: Release web clipper extension
|
||||
uses: softprops/action-gh-release@v2.5.0
|
||||
uses: softprops/action-gh-release@v2.6.1
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/web-clipper-v') }}
|
||||
with:
|
||||
draft: false
|
||||
|
||||
2
.github/workflows/website.yml
vendored
2
.github/workflows/website.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -46,7 +46,6 @@ upload
|
||||
|
||||
/.direnv
|
||||
/result
|
||||
.svelte-kit
|
||||
|
||||
# docs
|
||||
site/
|
||||
|
||||
8
.mcp.json
Normal file
8
.mcp.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"trilium": {
|
||||
"type": "http",
|
||||
"url": "http://localhost:8080/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
57
.vscode/launch.json
vendored
Normal file
57
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch client (Chrome)",
|
||||
"request": "launch",
|
||||
"type": "chrome",
|
||||
"url": "http://localhost:8080",
|
||||
"webRoot": "${workspaceFolder}/apps/client"
|
||||
},
|
||||
{
|
||||
"name": "Launch server",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/apps/server/src/main.ts",
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/tsx",
|
||||
"env": {
|
||||
"NODE_ENV": "development",
|
||||
"TRILIUM_ENV": "dev",
|
||||
"TRILIUM_DATA_DIR": "${input:trilium_data_dir}",
|
||||
"TRILIUM_RESOURCE_DIR": "${workspaceFolder}/apps/server/src"
|
||||
},
|
||||
"autoAttachChildProcesses": true,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"skipFiles": ["<node_internals>/**", "${workspaceFolder}/node_modules/**"]
|
||||
},
|
||||
{
|
||||
"name": "Launch Vitest with current test file",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"autoAttachChildProcesses": true,
|
||||
"program": "${workspaceFolder}/node_modules/vitest/vitest.mjs",
|
||||
"args": ["run", "${relativeFile}"],
|
||||
"smartStep": true,
|
||||
"console": "integratedTerminal",
|
||||
"skipFiles": ["<node_internals>/**", "**/node_modules/**"],
|
||||
"cwd": "${workspaceFolder}"
|
||||
}
|
||||
],
|
||||
"compounds": [
|
||||
{
|
||||
"name": "Launch client (Chrome) and server",
|
||||
"configurations": ["Launch server","Launch client (Chrome)"],
|
||||
"stopAll": true
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"id": "trilium_data_dir",
|
||||
"type": "promptString",
|
||||
"description": "Select Trilum Notes data directory",
|
||||
"default": "${workspaceFolder}/apps/server/data"
|
||||
}
|
||||
]
|
||||
}
|
||||
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@@ -42,5 +42,8 @@
|
||||
},
|
||||
"eslint.rules.customizations": [
|
||||
{ "rule": "*", "severity": "warn" }
|
||||
],
|
||||
"cSpell.words": [
|
||||
"Trilium"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
40
CLAUDE.md
40
CLAUDE.md
@@ -118,6 +118,10 @@ Trilium provides powerful user scripting capabilities:
|
||||
### Internationalization
|
||||
- Translation files in `apps/client/src/translations/`
|
||||
- Supported languages: English, German, Spanish, French, Romanian, Chinese
|
||||
- **Only add new translation keys to `en/translation.json`** — translations for other languages are managed via Weblate and will be contributed by the community
|
||||
- Third-party components (e.g., mind-map context menu) should use i18next `t()` for their labels, with the English strings added to `en/translation.json` under a dedicated namespace (e.g., `"mind-map"`)
|
||||
- When a translated string contains **interpolated components** (e.g. links, note references) whose order may vary across languages, use `<Trans>` from `react-i18next` instead of `t()`. This lets translators reorder components freely (e.g. `"<Note/> in <Parent/>"` vs `"in <Parent/>, <Note/>"`)
|
||||
- When adding a new locale, follow the step-by-step guide in `docs/Developer Guide/Developer Guide/Concepts/Internationalisation Translations/Adding a new locale.md`
|
||||
|
||||
### Security Considerations
|
||||
- Per-note encryption with granular protected sessions
|
||||
@@ -125,6 +129,15 @@ Trilium provides powerful user scripting capabilities:
|
||||
- OpenID and TOTP authentication support
|
||||
- Sanitization of user-generated content
|
||||
|
||||
### Client-Side API Restrictions
|
||||
- **Do not use `crypto.randomUUID()`** or other Web Crypto APIs that require secure contexts - Trilium can run over HTTP, not just HTTPS
|
||||
- Use `randomString()` from `apps/client/src/services/utils.ts` for generating IDs instead
|
||||
|
||||
### Shared Types Policy
|
||||
- Types shared between client and server belong in `@triliumnext/commons` (`packages/commons/src/lib/`)
|
||||
- Import shared types directly from `@triliumnext/commons` - do not re-export them from app-specific modules
|
||||
- Keep app-specific types (e.g., `LlmProvider` for server, `StreamCallbacks` for client) in their respective apps
|
||||
|
||||
## Common Development Tasks
|
||||
|
||||
### Adding New Note Types
|
||||
@@ -140,10 +153,37 @@ Trilium provides powerful user scripting capabilities:
|
||||
- Create new package in `packages/` following existing plugin structure
|
||||
- Register in `packages/ckeditor5/src/plugins.ts`
|
||||
|
||||
### Adding New LLM Tools
|
||||
Tools are defined using `defineTools()` in `apps/server/src/services/llm/tools/` and automatically registered for both the LLM chat and MCP server.
|
||||
|
||||
1. Add the tool definition in the appropriate module (`note_tools.ts`, `attribute_tools.ts`, `attachment_tools.ts`, `hierarchy_tools.ts`) or create a new module
|
||||
2. Each tool needs: `description`, `inputSchema` (Zod), `execute` function, and optionally `mutates: true` for write operations
|
||||
3. If creating a new module, wrap tools in `defineTools({...})` and add the registry to `allToolRegistries` in `tools/index.ts`
|
||||
4. Add a client-side friendly name in `apps/client/src/translations/en/translation.json` under `llm.tools.<tool_name>` — use **imperative tense** (e.g. "Search notes", "Create note", "Get attributes"), not present continuous
|
||||
5. Use ETAPI (`apps/server/src/etapi/`) as inspiration for what fields to expose, but **do not import ETAPI mappers** — inline the field mappings directly in the tool so the LLM layer stays decoupled from the API layer
|
||||
|
||||
### Updating PDF.js
|
||||
1. Update `pdfjs-dist` version in `packages/pdfjs-viewer/package.json`
|
||||
2. Run `npx tsx scripts/update-viewer.ts` from that directory
|
||||
3. Run `pnpm build` to verify success
|
||||
4. Commit all changes including updated viewer files
|
||||
|
||||
### Database Migrations
|
||||
- Add migration scripts in `apps/server/src/migrations/`
|
||||
- Update schema in `apps/server/src/assets/db/schema.sql`
|
||||
|
||||
### Server-Side Static Assets
|
||||
- Static assets (templates, SQL, translations, etc.) go in `apps/server/src/assets/`
|
||||
- Access them at runtime via `RESOURCE_DIR` from `apps/server/src/services/resource_dir.ts` (e.g. `path.join(RESOURCE_DIR, "llm", "skills", "file.md")`)
|
||||
- **Do not use `import.meta.url`/`fileURLToPath`** to resolve file paths — the server is bundled into CJS for production, so `import.meta.url` will not point to the source directory
|
||||
- **Do not use `__dirname` with relative paths** from source files — after bundling, `__dirname` points to the bundle output, not the original source tree
|
||||
|
||||
## MCP Server
|
||||
- Trilium exposes an MCP (Model Context Protocol) server at `http://localhost:8080/mcp`, configured in `.mcp.json`
|
||||
- The MCP server is **only available when the Trilium server is running** (`pnpm run server:start`)
|
||||
- It provides tools for reading, searching, and modifying notes directly from the AI assistant
|
||||
- Use it to interact with actual note data when developing or debugging note-related features
|
||||
|
||||
## Build System Notes
|
||||
- Uses pnpm for monorepo management
|
||||
- Vite for fast development builds
|
||||
|
||||
83
SECURITY.md
83
SECURITY.md
@@ -2,12 +2,87 @@
|
||||
|
||||
## Supported Versions
|
||||
|
||||
In the (still active) 0.X phase of the project only the latest stable minor release is getting bugfixes (including security ones).
|
||||
Only the latest stable minor release receives security fixes.
|
||||
|
||||
So e.g. if the latest stable version is 0.42.3 and the latest beta version is 0.43.0-beta, then 0.42 line will still get security fixes but older versions (like 0.41.X) won't get any fixes.
|
||||
For example, if the latest stable version is 0.92.3 and the latest beta is 0.93.0-beta, then only the 0.92.x line will receive security patches. Older versions (like 0.91.x) will not receive fixes.
|
||||
|
||||
Description above is a general rule and may be altered on case by case basis.
|
||||
This policy may be altered on a case-by-case basis for critical vulnerabilities.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
You can report low severity vulnerabilities as GitHub issues, more severe vulnerabilities should be reported to the email [contact@eliandoran.me](mailto:contact@eliandoran.me)
|
||||
**Please report all security vulnerabilities through [GitHub Security Advisories](https://github.com/TriliumNext/Notes/security/advisories/new).**
|
||||
|
||||
We do not accept security reports via email, public issues, or other channels. GitHub Security Advisories allows us to:
|
||||
- Discuss and triage vulnerabilities privately
|
||||
- Coordinate fixes before public disclosure
|
||||
- Credit reporters appropriately
|
||||
- Publish advisories with CVE identifiers
|
||||
|
||||
### What to Include
|
||||
|
||||
When reporting, please provide:
|
||||
- A clear description of the vulnerability
|
||||
- Steps to reproduce or proof-of-concept
|
||||
- Affected versions (if known)
|
||||
- Potential impact assessment
|
||||
- Any suggested mitigations or fixes
|
||||
|
||||
### Response Timeline
|
||||
|
||||
- **Initial response**: Within 7 days
|
||||
- **Triage decision**: Within 14 days
|
||||
- **Fix timeline**: Depends on severity and complexity
|
||||
|
||||
## Scope
|
||||
|
||||
### In Scope
|
||||
|
||||
- Remote code execution
|
||||
- Authentication/authorization bypass
|
||||
- Cross-site scripting (XSS) that affects other users
|
||||
- SQL injection
|
||||
- Path traversal
|
||||
- Sensitive data exposure
|
||||
- Privilege escalation
|
||||
|
||||
### Out of Scope (Won't Fix)
|
||||
|
||||
The following are considered out of scope or accepted risks:
|
||||
|
||||
#### Self-XSS / Self-Injection
|
||||
Trilium is a personal knowledge base where users have full control over their own data. Users can intentionally create notes containing scripts, HTML, or other executable content. This is by design - Trilium's scripting system allows users to extend functionality with custom JavaScript.
|
||||
|
||||
Vulnerabilities that require a user to inject malicious content into their own notes and then view it themselves are not considered security issues.
|
||||
|
||||
#### Electron Architecture (nodeIntegration)
|
||||
Trilium's desktop application runs with `nodeIntegration: true` to enable its powerful scripting features. This is an intentional design decision, similar to VS Code extensions having full system access. We mitigate risks by:
|
||||
- Sanitizing content at input boundaries
|
||||
- Fixing specific XSS vectors as they're discovered
|
||||
- Using Electron fuses to prevent external abuse
|
||||
|
||||
#### Authenticated User Actions
|
||||
Actions that require valid authentication and only affect the authenticated user's own data are generally not vulnerabilities.
|
||||
|
||||
#### Denial of Service via Resource Exhaustion
|
||||
Creating extremely large notes or performing many operations is expected user behavior in a note-taking application.
|
||||
|
||||
#### Missing Security Headers on Non-Sensitive Endpoints
|
||||
We implement security headers where they provide meaningful protection, but may omit them on endpoints where they provide no practical benefit.
|
||||
|
||||
## Coordinated Disclosure
|
||||
|
||||
We follow a coordinated disclosure process:
|
||||
|
||||
1. **Report received** - We acknowledge receipt and begin triage
|
||||
2. **Fix developed** - We develop and test a fix privately
|
||||
3. **Release prepared** - Security release is prepared with vague changelog
|
||||
4. **Users notified** - Release is published, users encouraged to upgrade
|
||||
5. **Advisory published** - After reasonable upgrade window (typically 2-4 weeks), full advisory is published
|
||||
|
||||
We appreciate reporters allowing us time to fix issues before public disclosure. We aim to credit all reporters in published advisories unless they prefer to remain anonymous.
|
||||
|
||||
## Security Updates
|
||||
|
||||
Security fixes are released as patch versions (e.g., 0.92.1 → 0.92.2) to minimize upgrade friction. We recommend all users keep their installations up to date.
|
||||
|
||||
Subscribe to GitHub releases or watch the repository to receive notifications of new releases.
|
||||
|
||||
@@ -1,22 +1,26 @@
|
||||
{
|
||||
"name": "build-docs",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"description": "Build documentation from Trilium notes",
|
||||
"main": "src/main.ts",
|
||||
"bin": {
|
||||
"trilium-build-docs": "dist/cli.js"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "tsx ."
|
||||
"start": "tsx .",
|
||||
"cli": "tsx src/cli.ts",
|
||||
"build": "tsx scripts/build.ts"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Elian Doran <contact@eliandoran.me>",
|
||||
"license": "AGPL-3.0-only",
|
||||
"packageManager": "pnpm@10.28.1",
|
||||
"packageManager": "pnpm@10.33.0",
|
||||
"devDependencies": {
|
||||
"@redocly/cli": "2.14.9",
|
||||
"@redocly/cli": "2.25.4",
|
||||
"archiver": "7.0.1",
|
||||
"fs-extra": "11.3.3",
|
||||
"react": "19.2.3",
|
||||
"react-dom": "19.2.3",
|
||||
"typedoc": "0.28.16",
|
||||
"fs-extra": "11.3.4",
|
||||
"js-yaml": "4.1.1",
|
||||
"typedoc": "0.28.18",
|
||||
"typedoc-plugin-missing-exports": "4.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
23
apps/build-docs/scripts/build.ts
Normal file
23
apps/build-docs/scripts/build.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import BuildHelper from "../../../scripts/build-utils";
|
||||
|
||||
const build = new BuildHelper("apps/build-docs");
|
||||
|
||||
async function main() {
|
||||
// Build the CLI and other TypeScript files
|
||||
await build.buildBackend([
|
||||
"src/cli.ts",
|
||||
"src/main.ts",
|
||||
"src/build-docs.ts",
|
||||
"src/swagger.ts",
|
||||
"src/script-api.ts",
|
||||
"src/context.ts"
|
||||
]);
|
||||
|
||||
// Copy HTML template
|
||||
build.copy("src/index.html", "index.html");
|
||||
|
||||
// Copy node modules dependencies if needed
|
||||
build.copyNodeModules([ "better-sqlite3", "bindings", "file-uri-to-path" ]);
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -13,8 +13,12 @@
|
||||
* 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 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";
|
||||
@@ -31,6 +35,7 @@ export type { Api };
|
||||
const fakeNote = new BNote();
|
||||
|
||||
/**
|
||||
* The `api` global variable allows access to the backend script API, which is documented in {@link Api}.
|
||||
* The `api` global variable allows access to the backend script API,
|
||||
* which is documented in {@link Api}.
|
||||
*/
|
||||
export const api: Api = new BackendScriptApi(fakeNote, {});
|
||||
|
||||
@@ -1,19 +1,90 @@
|
||||
process.env.TRILIUM_INTEGRATION_TEST = "memory-no-store";
|
||||
process.env.TRILIUM_RESOURCE_DIR = "../server/src";
|
||||
// Only set TRILIUM_RESOURCE_DIR if not already set (e.g., by Nix wrapper)
|
||||
if (!process.env.TRILIUM_RESOURCE_DIR) {
|
||||
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 archiver from "archiver";
|
||||
import { execSync } from "child_process";
|
||||
import { WriteStream } from "fs";
|
||||
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 yaml from "js-yaml";
|
||||
import { dirname, join, resolve } from "path";
|
||||
|
||||
import BuildContext from "./context.js";
|
||||
|
||||
interface NoteMapping {
|
||||
rootNoteId: string;
|
||||
path: string;
|
||||
format: "markdown" | "html" | "share";
|
||||
ignoredFiles?: string[];
|
||||
exportOnly?: boolean;
|
||||
}
|
||||
|
||||
interface Config {
|
||||
baseUrl: string;
|
||||
noteMappings: NoteMapping[];
|
||||
}
|
||||
|
||||
const DOCS_ROOT = "../../../docs";
|
||||
const OUTPUT_DIR = "../../site";
|
||||
|
||||
// Load configuration from edit-docs-config.yaml
|
||||
async function loadConfig(configPath?: string): Promise<Config | null> {
|
||||
const pathsToTry = configPath
|
||||
? [resolve(configPath)]
|
||||
: [
|
||||
join(process.cwd(), "edit-docs-config.yaml"),
|
||||
join(__dirname, "../../../edit-docs-config.yaml")
|
||||
];
|
||||
|
||||
for (const path of pathsToTry) {
|
||||
try {
|
||||
const configContent = await fs.readFile(path, "utf-8");
|
||||
const config = yaml.load(configContent) as Config;
|
||||
|
||||
// Resolve all paths relative to the config file's directory
|
||||
const CONFIG_DIR = dirname(path);
|
||||
config.noteMappings = config.noteMappings.map((mapping) => ({
|
||||
...mapping,
|
||||
path: resolve(CONFIG_DIR, mapping.path)
|
||||
}));
|
||||
|
||||
return config;
|
||||
} catch (error) {
|
||||
if (error.code !== "ENOENT") {
|
||||
throw error; // rethrow unexpected errors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null; // No config file found
|
||||
}
|
||||
|
||||
async function exportDocs(
|
||||
noteId: string,
|
||||
format: "markdown" | "html" | "share",
|
||||
outputPath: string,
|
||||
ignoredFiles?: string[]
|
||||
) {
|
||||
const zipFilePath = `output-${noteId}.zip`;
|
||||
try {
|
||||
const { exportToZipFile } = (await import("@triliumnext/server/src/services/export/zip.js"))
|
||||
.default;
|
||||
await exportToZipFile(noteId, format, zipFilePath, {});
|
||||
|
||||
const ignoredSet = ignoredFiles ? new Set(ignoredFiles) : undefined;
|
||||
await extractZip(zipFilePath, outputPath, ignoredSet);
|
||||
} finally {
|
||||
if (await fsExtra.exists(zipFilePath)) {
|
||||
await fsExtra.rm(zipFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function importAndExportDocs(sourcePath: string, outputSubDir: string) {
|
||||
const note = await importData(sourcePath);
|
||||
|
||||
@@ -21,15 +92,18 @@ async function importAndExportDocs(sourcePath: string, outputSubDir: string) {
|
||||
const zipName = outputSubDir || "user-guide";
|
||||
const zipFilePath = `output-${zipName}.zip`;
|
||||
try {
|
||||
const { exportToZip } = (await import("@triliumnext/server/src/services/export/zip.js")).default;
|
||||
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 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);
|
||||
const { waitForStreamToFinish } = await import("@triliumnext/server/src/services/utils.js");
|
||||
await waitForStreamToFinish(fileOutputStream);
|
||||
|
||||
// Output to root directory if outputSubDir is empty, otherwise to subdirectory
|
||||
@@ -42,7 +116,7 @@ async function importAndExportDocs(sourcePath: string, outputSubDir: string) {
|
||||
}
|
||||
}
|
||||
|
||||
async function buildDocsInner() {
|
||||
async function buildDocsInner(config?: Config) {
|
||||
const i18n = await import("@triliumnext/server/src/services/i18n.js");
|
||||
await i18n.initializeTranslations();
|
||||
|
||||
@@ -53,18 +127,49 @@ async function buildDocsInner() {
|
||||
const beccaLoader = await import("../../server/src/becca/becca_loader.js");
|
||||
await beccaLoader.beccaLoaded;
|
||||
|
||||
// Build User Guide
|
||||
console.log("Building User Guide...");
|
||||
await importAndExportDocs(join(__dirname, DOCS_ROOT, "User Guide"), "user-guide");
|
||||
if (config) {
|
||||
// Config-based build (reads from edit-docs-config.yaml)
|
||||
console.log("Building documentation from config file...");
|
||||
|
||||
// Build Developer Guide
|
||||
console.log("Building Developer Guide...");
|
||||
await importAndExportDocs(join(__dirname, DOCS_ROOT, "Developer Guide"), "developer-guide");
|
||||
// Import all non-export-only mappings
|
||||
for (const mapping of config.noteMappings) {
|
||||
if (!mapping.exportOnly) {
|
||||
console.log(`Importing from ${mapping.path}...`);
|
||||
await importData(mapping.path);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy favicon.
|
||||
await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "favicon.ico"));
|
||||
await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "user-guide", "favicon.ico"));
|
||||
await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "developer-guide", "favicon.ico"));
|
||||
// Export all mappings
|
||||
for (const mapping of config.noteMappings) {
|
||||
if (mapping.exportOnly) {
|
||||
console.log(`Exporting ${mapping.format} to ${mapping.path}...`);
|
||||
await exportDocs(
|
||||
mapping.rootNoteId,
|
||||
mapping.format,
|
||||
mapping.path,
|
||||
mapping.ignoredFiles
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Legacy hardcoded build (for backward compatibility)
|
||||
console.log("Building User Guide...");
|
||||
await importAndExportDocs(join(__dirname, DOCS_ROOT, "User Guide"), "user-guide");
|
||||
|
||||
console.log("Building Developer Guide...");
|
||||
await importAndExportDocs(
|
||||
join(__dirname, DOCS_ROOT, "Developer Guide"),
|
||||
"developer-guide"
|
||||
);
|
||||
|
||||
// Copy favicon.
|
||||
await fs.copyFile("../../apps/website/src/assets/favicon.ico",
|
||||
join(OUTPUT_DIR, "favicon.ico"));
|
||||
await fs.copyFile("../../apps/website/src/assets/favicon.ico",
|
||||
join(OUTPUT_DIR, "user-guide", "favicon.ico"));
|
||||
await fs.copyFile("../../apps/website/src/assets/favicon.ico",
|
||||
join(OUTPUT_DIR, "developer-guide", "favicon.ico"));
|
||||
}
|
||||
|
||||
console.log("Documentation built successfully!");
|
||||
}
|
||||
@@ -91,12 +196,13 @@ async function createImportZip(path: string) {
|
||||
zlib: { level: 0 }
|
||||
});
|
||||
|
||||
console.log("Archive path is ", resolve(path))
|
||||
console.log("Archive path is ", resolve(path));
|
||||
archive.directory(path, "/");
|
||||
|
||||
const outputStream = fsExtra.createWriteStream(inputFile);
|
||||
archive.pipe(outputStream);
|
||||
archive.finalize();
|
||||
const { waitForStreamToFinish } = await import("@triliumnext/server/src/services/utils.js");
|
||||
await waitForStreamToFinish(outputStream);
|
||||
|
||||
try {
|
||||
@@ -106,15 +212,15 @@ async function createImportZip(path: string) {
|
||||
}
|
||||
}
|
||||
|
||||
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"));
|
||||
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)) {
|
||||
@@ -129,6 +235,27 @@ export async function extractZip(zipFilePath: string, outputPath: string, ignore
|
||||
});
|
||||
}
|
||||
|
||||
export async function buildDocsFromConfig(configPath?: string, gitRootDir?: string) {
|
||||
const config = await loadConfig(configPath);
|
||||
|
||||
if (gitRootDir) {
|
||||
// Build the share theme if we have a gitRootDir (for Trilium project)
|
||||
execSync(`pnpm run --filter share-theme build`, {
|
||||
stdio: "inherit",
|
||||
cwd: gitRootDir
|
||||
});
|
||||
}
|
||||
|
||||
// Trigger the actual build.
|
||||
await new Promise((res, rej) => {
|
||||
cls.init(() => {
|
||||
buildDocsInner(config ?? undefined)
|
||||
.catch(rej)
|
||||
.then(res);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export default async function buildDocs({ gitRootDir }: BuildContext) {
|
||||
// Build the share theme.
|
||||
execSync(`pnpm run --filter share-theme build`, {
|
||||
|
||||
89
apps/build-docs/src/cli.ts
Normal file
89
apps/build-docs/src/cli.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import packageJson from "../package.json" with { type: "json" };
|
||||
import { buildDocsFromConfig } from "./build-docs.js";
|
||||
|
||||
// Parse command-line arguments
|
||||
function parseArgs() {
|
||||
const args = process.argv.slice(2);
|
||||
let configPath: string | undefined;
|
||||
let showHelp = false;
|
||||
let showVersion = false;
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (args[i] === "--config" || args[i] === "-c") {
|
||||
configPath = args[i + 1];
|
||||
if (!configPath) {
|
||||
console.error("Error: --config/-c requires a path argument");
|
||||
process.exit(1);
|
||||
}
|
||||
i++; // Skip the next argument as it's the value
|
||||
} else if (args[i] === "--help" || args[i] === "-h") {
|
||||
showHelp = true;
|
||||
} else if (args[i] === "--version" || args[i] === "-v") {
|
||||
showVersion = true;
|
||||
}
|
||||
}
|
||||
|
||||
return { configPath, showHelp, showVersion };
|
||||
}
|
||||
|
||||
function getVersion(): string {
|
||||
return packageJson.version;
|
||||
}
|
||||
|
||||
function printHelp() {
|
||||
const version = getVersion();
|
||||
console.log(`
|
||||
Usage: trilium-build-docs [options]
|
||||
|
||||
Options:
|
||||
-c, --config <path> Path to the configuration file
|
||||
(default: edit-docs-config.yaml in current directory)
|
||||
-h, --help Display this help message
|
||||
-v, --version Display version information
|
||||
|
||||
Description:
|
||||
Builds documentation from Trilium note structure and exports to various formats.
|
||||
Configuration file should be in YAML format with the following structure:
|
||||
|
||||
baseUrl: "https://example.com"
|
||||
noteMappings:
|
||||
- rootNoteId: "noteId123"
|
||||
path: "docs"
|
||||
format: "markdown"
|
||||
- rootNoteId: "noteId456"
|
||||
path: "public/docs"
|
||||
format: "share"
|
||||
exportOnly: true
|
||||
|
||||
Version: ${version}
|
||||
`);
|
||||
}
|
||||
|
||||
function printVersion() {
|
||||
const version = getVersion();
|
||||
console.log(version);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const { configPath, showHelp, showVersion } = parseArgs();
|
||||
|
||||
if (showHelp) {
|
||||
printHelp();
|
||||
process.exit(0);
|
||||
} else if (showVersion) {
|
||||
printVersion();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
try {
|
||||
await buildDocsFromConfig(configPath);
|
||||
process.exit(0);
|
||||
} catch (error) {
|
||||
console.error("Error building documentation:", error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -13,16 +13,19 @@
|
||||
* 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 BasicWidget } from "../../client/src/widgets/basic_widget.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
|
||||
|
||||
// @ts-expect-error - FrontendScriptApi is not directly exportable as Api without this simulation.
|
||||
export const api: Api = new FrontendScriptApi();
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { join } from "path";
|
||||
import BuildContext from "./context";
|
||||
import buildSwagger from "./swagger";
|
||||
import { cpSync, existsSync, mkdirSync, rmSync } from "fs";
|
||||
import { join } from "path";
|
||||
|
||||
import buildDocs from "./build-docs";
|
||||
import BuildContext from "./context";
|
||||
import buildScriptApi from "./script-api";
|
||||
import buildSwagger from "./swagger";
|
||||
|
||||
const context: BuildContext = {
|
||||
gitRootDir: join(__dirname, "../../../"),
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { execSync } from "child_process";
|
||||
import BuildContext from "./context";
|
||||
import { join } from "path";
|
||||
|
||||
import BuildContext from "./context";
|
||||
|
||||
export default function buildScriptApi({ baseDir, gitRootDir }: BuildContext) {
|
||||
// Generate types
|
||||
execSync(`pnpm typecheck`, { stdio: "inherit", cwd: gitRootDir });
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import BuildContext from "./context";
|
||||
import { join } from "path";
|
||||
import { execSync } from "child_process";
|
||||
import { mkdirSync } from "fs";
|
||||
import { join } from "path";
|
||||
|
||||
import BuildContext from "./context";
|
||||
|
||||
interface BuildInfo {
|
||||
specPath: string;
|
||||
@@ -27,6 +28,9 @@ export default function buildSwagger({ baseDir, gitRootDir }: BuildContext) {
|
||||
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" });
|
||||
execSync(
|
||||
`pnpm redocly build-docs ${absSpecPath} -o ${targetDir}/index.html`,
|
||||
{ stdio: "inherit" }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"include": [],
|
||||
"include": [
|
||||
"scripts/**/*.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../server"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"entryPoints": [
|
||||
"src/backend_script_entrypoint.ts"
|
||||
],
|
||||
"tsconfig": "tsconfig.app.json",
|
||||
"plugin": [
|
||||
"typedoc-plugin-missing-exports"
|
||||
]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"entryPoints": [
|
||||
"src/frontend_script_entrypoint.ts"
|
||||
],
|
||||
"tsconfig": "tsconfig.app.json",
|
||||
"plugin": [
|
||||
"typedoc-plugin-missing-exports"
|
||||
]
|
||||
|
||||
@@ -13,13 +13,14 @@
|
||||
<body id="trilium-app">
|
||||
<noscript>Trilium requires JavaScript to be enabled.</noscript>
|
||||
|
||||
<div id="context-menu-cover"></div>
|
||||
<div class="dropdown-menu dropdown-menu-sm" id="context-menu-container" style="display: none"></div>
|
||||
|
||||
<!-- Required to match the PWA's top bar color with the theme -->
|
||||
<!-- This works even when the user directly changes --root-background in CSS -->
|
||||
<div id="background-color-tracker" style="position: absolute; visibility: hidden; color: var(--root-background); transition: color 1ms;"></div>
|
||||
|
||||
<script src="./index.ts" type="module"></script>
|
||||
<script src="./src/index.ts" type="module"></script>
|
||||
|
||||
<!-- Required for correct loading of scripts in Electron -->
|
||||
<script>
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@triliumnext/client",
|
||||
"version": "0.101.3",
|
||||
"version": "0.102.2",
|
||||
"description": "JQuery-based client for TriliumNext, used for both web and desktop (via Electron)",
|
||||
"private": true,
|
||||
"license": "AGPL-3.0-only",
|
||||
@@ -22,65 +22,71 @@
|
||||
"@fullcalendar/interaction": "6.1.20",
|
||||
"@fullcalendar/list": "6.1.20",
|
||||
"@fullcalendar/multimonth": "6.1.20",
|
||||
"@fullcalendar/rrule": "6.1.20",
|
||||
"@fullcalendar/timegrid": "6.1.20",
|
||||
"@maplibre/maplibre-gl-leaflet": "0.1.3",
|
||||
"@mermaid-js/layout-elk": "0.2.0",
|
||||
"@mermaid-js/layout-elk": "0.2.1",
|
||||
"@mind-elixir/node-menu": "5.0.1",
|
||||
"@popperjs/core": "2.11.8",
|
||||
"@preact/signals": "2.6.1",
|
||||
"@preact/signals": "2.9.0",
|
||||
"@triliumnext/ckeditor5": "workspace:*",
|
||||
"@triliumnext/codemirror": "workspace:*",
|
||||
"@triliumnext/commons": "workspace:*",
|
||||
"@triliumnext/highlightjs": "workspace:*",
|
||||
"@triliumnext/share-theme": "workspace:*",
|
||||
"@triliumnext/split.js": "workspace:*",
|
||||
"@zumer/snapdom": "2.0.2",
|
||||
"@univerjs/preset-sheets-conditional-formatting": "0.19.0",
|
||||
"@univerjs/preset-sheets-core": "0.19.0",
|
||||
"@univerjs/preset-sheets-data-validation": "0.19.0",
|
||||
"@univerjs/preset-sheets-filter": "0.19.0",
|
||||
"@univerjs/preset-sheets-find-replace": "0.19.0",
|
||||
"@univerjs/preset-sheets-note": "0.19.0",
|
||||
"@univerjs/preset-sheets-sort": "0.19.0",
|
||||
"@univerjs/presets": "0.19.0",
|
||||
"@zumer/snapdom": "2.7.0",
|
||||
"autocomplete.js": "0.38.1",
|
||||
"bootstrap": "5.3.8",
|
||||
"boxicons": "2.1.4",
|
||||
"clsx": "2.1.1",
|
||||
"color": "5.0.3",
|
||||
"debounce": "3.0.0",
|
||||
"dompurify": "3.3.3",
|
||||
"draggabilly": "3.0.0",
|
||||
"force-graph": "1.51.0",
|
||||
"globals": "17.0.0",
|
||||
"i18next": "25.8.0",
|
||||
"i18next-http-backend": "3.0.2",
|
||||
"force-graph": "1.51.2",
|
||||
"i18next": "26.0.3",
|
||||
"i18next-http-backend": "3.0.4",
|
||||
"jquery": "4.0.0",
|
||||
"jquery.fancytree": "2.38.5",
|
||||
"jsplumb": "2.15.6",
|
||||
"katex": "0.16.28",
|
||||
"knockout": "3.5.1",
|
||||
"katex": "0.16.44",
|
||||
"leaflet": "1.9.4",
|
||||
"leaflet-gpx": "2.2.0",
|
||||
"mark.js": "8.11.1",
|
||||
"marked": "17.0.1",
|
||||
"mermaid": "11.12.2",
|
||||
"mind-elixir": "5.6.1",
|
||||
"normalize.css": "8.0.1",
|
||||
"panzoom": "9.4.3",
|
||||
"preact": "10.28.2",
|
||||
"react-i18next": "16.5.3",
|
||||
"react-window": "2.2.5",
|
||||
"reveal.js": "5.2.1",
|
||||
"marked": "17.0.5",
|
||||
"mermaid": "11.14.0",
|
||||
"mind-elixir": "5.10.0",
|
||||
"panzoom": "9.4.4",
|
||||
"preact": "10.29.0",
|
||||
"react-i18next": "17.0.2",
|
||||
"react-window": "2.2.7",
|
||||
"reveal.js": "6.0.0",
|
||||
"rrule": "2.8.1",
|
||||
"svg-pan-zoom": "3.6.2",
|
||||
"tabulator-tables": "6.3.1",
|
||||
"tabulator-tables": "6.4.0",
|
||||
"vanilla-js-wheel-zoom": "9.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ckeditor/ckeditor5-inspector": "5.0.0",
|
||||
"@prefresh/vite": "2.4.11",
|
||||
"@prefresh/vite": "2.4.12",
|
||||
"@types/bootstrap": "5.2.10",
|
||||
"@types/jquery": "3.5.33",
|
||||
"@types/jquery": "4.0.0",
|
||||
"@types/leaflet": "1.9.21",
|
||||
"@types/leaflet-gpx": "1.3.8",
|
||||
"@types/mark.js": "8.11.12",
|
||||
"@types/reveal.js": "5.2.2",
|
||||
"@types/tabulator-tables": "6.3.1",
|
||||
"copy-webpack-plugin": "13.0.1",
|
||||
"happy-dom": "20.3.9",
|
||||
"lightningcss": "1.31.1",
|
||||
"copy-webpack-plugin": "14.0.0",
|
||||
"happy-dom": "20.8.9",
|
||||
"lightningcss": "1.32.0",
|
||||
"script-loader": "0.7.2",
|
||||
"vite-plugin-static-copy": "3.1.5"
|
||||
"vite-plugin-static-copy": "4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import type { CKTextEditor } from "@triliumnext/ckeditor5";
|
||||
import type CodeMirror from "@triliumnext/codemirror";
|
||||
import { SqlExecuteResponse } from "@triliumnext/commons";
|
||||
import { type LOCALE_IDS, SqlExecuteResponse } from "@triliumnext/commons";
|
||||
import type { NativeImage, TouchBar } from "electron";
|
||||
import { ColumnComponent } from "tabulator-tables";
|
||||
|
||||
import type { Attribute } from "../services/attribute_parser.js";
|
||||
import bundleService from "../services/bundle.js";
|
||||
import froca from "../services/froca.js";
|
||||
import { initLocale, t } from "../services/i18n.js";
|
||||
import keyboardActionsService from "../services/keyboard_actions.js";
|
||||
@@ -101,8 +102,6 @@ export type CommandMappings = {
|
||||
showRevisions: CommandData & {
|
||||
noteId?: string | null;
|
||||
};
|
||||
showLlmChat: CommandData;
|
||||
createAiChat: CommandData;
|
||||
showOptions: CommandData & {
|
||||
section: string;
|
||||
};
|
||||
@@ -304,6 +303,7 @@ export type CommandMappings = {
|
||||
ninthTab: CommandData;
|
||||
lastTab: CommandData;
|
||||
showNoteSource: CommandData;
|
||||
showNoteOCRText: CommandData;
|
||||
showSQLConsole: CommandData;
|
||||
showBackendLog: CommandData;
|
||||
showCheatsheet: CommandData;
|
||||
@@ -510,7 +510,7 @@ type EventMappings = {
|
||||
contentSafeMarginChanged: {
|
||||
top: number;
|
||||
noteContext: NoteContext;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export type EventListener<T extends EventNames> = {
|
||||
@@ -564,7 +564,7 @@ export class AppContext extends Component {
|
||||
*/
|
||||
async earlyInit() {
|
||||
await options.initializedPromise;
|
||||
await initLocale();
|
||||
await initLocale((options.get("locale") || "en") as LOCALE_IDS);
|
||||
}
|
||||
|
||||
setLayout(layout: Layout) {
|
||||
@@ -579,7 +579,6 @@ export class AppContext extends Component {
|
||||
|
||||
this.tabManager.loadTabs();
|
||||
|
||||
const bundleService = (await import("../services/bundle.js")).default;
|
||||
setTimeout(() => bundleService.executeStartupBundles(), 2000);
|
||||
}
|
||||
|
||||
|
||||
@@ -381,6 +381,10 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
|
||||
|
||||
// Collections must always display a note list, even if no children.
|
||||
if (note.type === "book") {
|
||||
if (note.isProtected && !protectedSessionHolder.isProtectedSessionAvailable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const viewType = note.getLabelValue("viewType") ?? "grid";
|
||||
if (!["list", "grid"].includes(viewType)) {
|
||||
return true;
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import dateNoteService from "../services/date_notes.js";
|
||||
import froca from "../services/froca.js";
|
||||
import noteCreateService from "../services/note_create.js";
|
||||
import openService from "../services/open.js";
|
||||
import options from "../services/options.js";
|
||||
import protectedSessionService from "../services/protected_session.js";
|
||||
import toastService from "../services/toast.js";
|
||||
import treeService from "../services/tree.js";
|
||||
import utils, { openInReusableSplit } from "../services/utils.js";
|
||||
import appContext, { type CommandListenerData } from "./app_context.js";
|
||||
@@ -150,6 +148,19 @@ export default class RootCommandExecutor extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
async showNoteOCRTextCommand() {
|
||||
const notePath = appContext.tabManager.getActiveContextNotePath();
|
||||
|
||||
if (notePath) {
|
||||
await appContext.tabManager.openTabWithNoteWithHoisting(notePath, {
|
||||
activate: true,
|
||||
viewScope: {
|
||||
viewMode: "ocr"
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async showAttachmentsCommand() {
|
||||
const notePath = appContext.tabManager.getActiveContextNotePath();
|
||||
|
||||
@@ -248,34 +259,4 @@ export default class RootCommandExecutor extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
async createAiChatCommand() {
|
||||
try {
|
||||
// Create a new AI Chat note at the root level
|
||||
const rootNoteId = "root";
|
||||
|
||||
const result = await noteCreateService.createNote(rootNoteId, {
|
||||
title: "New AI Chat",
|
||||
type: "aiChat",
|
||||
content: JSON.stringify({
|
||||
messages: [],
|
||||
title: "New AI Chat"
|
||||
})
|
||||
});
|
||||
|
||||
if (!result.note) {
|
||||
toastService.showError("Failed to create AI Chat note");
|
||||
return;
|
||||
}
|
||||
|
||||
await appContext.tabManager.openTabWithNoteWithHoisting(result.note.noteId, {
|
||||
activate: true
|
||||
});
|
||||
|
||||
toastService.showMessage("Created new AI Chat note");
|
||||
}
|
||||
catch (e) {
|
||||
console.error("Error creating AI Chat note:", e);
|
||||
toastService.showError(`Failed to create AI Chat note: ${(e as Error).message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,10 +46,6 @@ if (utils.isElectron()) {
|
||||
electronContextMenu.setupContextMenu();
|
||||
}
|
||||
|
||||
if (utils.isPWA()) {
|
||||
initPWATopbarColor();
|
||||
}
|
||||
|
||||
function initOnElectron() {
|
||||
const electron: typeof Electron = utils.dynamicRequire("electron");
|
||||
electron.ipcRenderer.on("globalShortcut", async (event, actionName) => appContext.triggerCommand(actionName));
|
||||
@@ -99,15 +95,22 @@ function initFullScreenDetection(currentWindow: Electron.BrowserWindow) {
|
||||
}
|
||||
|
||||
function initTransparencyEffects(style: CSSStyleDeclaration, currentWindow: Electron.BrowserWindow) {
|
||||
const material = style.getPropertyValue("--background-material").trim();
|
||||
if (window.glob.platform === "win32") {
|
||||
const material = style.getPropertyValue("--background-material");
|
||||
// TriliumNextTODO: find a nicer way to make TypeScript happy – unfortunately TS did not like Array.includes here
|
||||
const bgMaterialOptions = ["auto", "none", "mica", "acrylic", "tabbed"] as const;
|
||||
const foundBgMaterialOption = bgMaterialOptions.find((bgMaterialOption) => material === bgMaterialOption);
|
||||
if (foundBgMaterialOption) {
|
||||
currentWindow.setBackgroundMaterial(foundBgMaterialOption);
|
||||
}
|
||||
}
|
||||
|
||||
if (window.glob.platform === "darwin") {
|
||||
const bgMaterialOptions = [ "popover", "tooltip", "titlebar", "selection", "menu", "sidebar", "header", "sheet", "window", "hud", "fullscreen-ui", "content", "under-window", "under-page" ] as const;
|
||||
const foundBgMaterialOption = bgMaterialOptions.find((bgMaterialOption) => material === bgMaterialOption);
|
||||
if (foundBgMaterialOption) {
|
||||
currentWindow.setVibrancy(foundBgMaterialOption);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,20 +130,3 @@ function initDarkOrLightMode(style: CSSStyleDeclaration) {
|
||||
const { nativeTheme } = utils.dynamicRequire("@electron/remote") as typeof ElectronRemote;
|
||||
nativeTheme.themeSource = themeSource;
|
||||
}
|
||||
|
||||
function initPWATopbarColor() {
|
||||
const tracker = $("#background-color-tracker");
|
||||
|
||||
if (tracker.length) {
|
||||
const applyThemeColor = () => {
|
||||
let meta = $("meta[name='theme-color']");
|
||||
if (!meta.length) {
|
||||
meta = $(`<meta name="theme-color">`).appendTo($("head"));
|
||||
}
|
||||
meta.attr("content", tracker.css("color"));
|
||||
};
|
||||
|
||||
tracker.on("transitionend", applyThemeColor);
|
||||
applyThemeColor();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { getNoteIcon } from "@triliumnext/commons";
|
||||
|
||||
import bundleService from "../services/bundle.js";
|
||||
import cssClassManager from "../services/css_class_manager.js";
|
||||
import type { Froca } from "../services/froca-interface.js";
|
||||
import noteAttributeCache from "../services/note_attribute_cache.js";
|
||||
@@ -18,7 +19,7 @@ const RELATION = "relation";
|
||||
* end user. Those types should be used only for checking against, they are
|
||||
* not for direct use.
|
||||
*/
|
||||
export type NoteType = "file" | "image" | "search" | "noteMap" | "launcher" | "doc" | "contentWidget" | "text" | "relationMap" | "render" | "canvas" | "mermaid" | "book" | "webView" | "code" | "mindMap" | "aiChat";
|
||||
export type NoteType = "file" | "image" | "search" | "noteMap" | "launcher" | "doc" | "contentWidget" | "text" | "relationMap" | "render" | "canvas" | "mermaid" | "book" | "webView" | "code" | "mindMap" | "spreadsheet" | "llmChat";
|
||||
|
||||
export interface NotePathRecord {
|
||||
isArchived: boolean;
|
||||
@@ -700,6 +701,15 @@ export default class FNote {
|
||||
return this.hasAttribute(LABEL, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if the note has a label with the given name (same as {@link hasOwnedLabel}), or it has a label with the `disabled:` prefix (for example due to a safe import).
|
||||
* @param name the name of the label to look for.
|
||||
* @returns `true` if the label exists, or its version with the `disabled:` prefix.
|
||||
*/
|
||||
hasLabelOrDisabled(name: string) {
|
||||
return this.hasLabel(name) || this.hasLabel(`disabled:${name}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name - label name
|
||||
* @returns true if label exists (including inherited) and does not have "false" value.
|
||||
@@ -1005,7 +1015,6 @@ export default class FNote {
|
||||
const env = this.getScriptEnv();
|
||||
|
||||
if (env === "frontend") {
|
||||
const bundleService = (await import("../services/bundle.js")).default;
|
||||
return await bundleService.getAndExecuteBundle(this.noteId);
|
||||
} else if (env === "backend") {
|
||||
await server.post(`script/run/${this.noteId}`);
|
||||
|
||||
@@ -30,7 +30,7 @@ async function initJQuery() {
|
||||
}
|
||||
|
||||
async function setupGlob() {
|
||||
const response = await fetch(`/bootstrap${window.location.search}`);
|
||||
const response = await fetch(`./bootstrap${window.location.search}`);
|
||||
const json = await response.json();
|
||||
|
||||
window.global = globalThis; /* fixes https://github.com/webpack/webpack/issues/10035 */
|
||||
|
||||
76
apps/client/src/layouts/mobile_layout.css
Normal file
76
apps/client/src/layouts/mobile_layout.css
Normal file
@@ -0,0 +1,76 @@
|
||||
#background-color-tracker {
|
||||
color: var(--main-background-color) !important;
|
||||
}
|
||||
|
||||
span.keyboard-shortcut,
|
||||
kbd {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 1.25em;
|
||||
padding-inline-start: 0.5em;
|
||||
padding-inline-end: 0.5em;
|
||||
color: var(--main-text-color);
|
||||
}
|
||||
.quick-search {
|
||||
margin: 0;
|
||||
}
|
||||
.quick-search .dropdown-menu {
|
||||
max-width: 350px;
|
||||
}
|
||||
|
||||
/* #region Tree */
|
||||
.tree-wrapper {
|
||||
max-height: 100%;
|
||||
margin-top: 0px;
|
||||
overflow-y: auto;
|
||||
contain: content;
|
||||
padding-inline-start: 10px;
|
||||
}
|
||||
|
||||
.fancytree-title {
|
||||
margin-inline-start: 0.6em !important;
|
||||
}
|
||||
|
||||
.fancytree-node {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
span.fancytree-expander {
|
||||
width: 24px !important;
|
||||
margin-inline-end: 5px;
|
||||
}
|
||||
|
||||
.fancytree-loading span.fancytree-expander {
|
||||
width: 24px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.fancytree-loading span.fancytree-expander:after {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-top: 4px;
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
.tree-wrapper .collapse-tree-button,
|
||||
.tree-wrapper .scroll-to-active-note-button,
|
||||
.tree-wrapper .tree-settings-button {
|
||||
position: fixed;
|
||||
margin-inline-end: 16px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tree-wrapper .unhoist-button {
|
||||
font-size: 200%;
|
||||
}
|
||||
/* #endregion */
|
||||
@@ -1,128 +1,38 @@
|
||||
import "./mobile_layout.css";
|
||||
|
||||
import type AppContext from "../components/app_context.js";
|
||||
import GlobalMenuWidget from "../widgets/buttons/global_menu.js";
|
||||
import CloseZenModeButton from "../widgets/close_zen_button.js";
|
||||
import NoteList from "../widgets/collections/NoteList.jsx";
|
||||
import ContentHeader from "../widgets/containers/content_header.js";
|
||||
import FlexContainer from "../widgets/containers/flex_container.js";
|
||||
import RootContainer from "../widgets/containers/root_container.js";
|
||||
import ScrollingContainer from "../widgets/containers/scrolling_container.js";
|
||||
import SplitNoteContainer from "../widgets/containers/split_note_container.js";
|
||||
import FloatingButtons from "../widgets/FloatingButtons.jsx";
|
||||
import { MOBILE_FLOATING_BUTTONS } from "../widgets/FloatingButtonsDefinitions.jsx";
|
||||
import FindWidget from "../widgets/find.js";
|
||||
import LauncherContainer from "../widgets/launch_bar/LauncherContainer.jsx";
|
||||
import InlineTitle from "../widgets/layout/InlineTitle.jsx";
|
||||
import NoteBadges from "../widgets/layout/NoteBadges.jsx";
|
||||
import NoteTitleActions from "../widgets/layout/NoteTitleActions.jsx";
|
||||
import MobileDetailMenu from "../widgets/mobile_widgets/mobile_detail_menu.js";
|
||||
import ScreenContainer from "../widgets/mobile_widgets/screen_container.js";
|
||||
import SidebarContainer from "../widgets/mobile_widgets/sidebar_container.js";
|
||||
import ToggleSidebarButton from "../widgets/mobile_widgets/toggle_sidebar_button.jsx";
|
||||
import NoteIconWidget from "../widgets/note_icon.jsx";
|
||||
import NoteTitleWidget from "../widgets/note_title.js";
|
||||
import NoteTreeWidget from "../widgets/note_tree.js";
|
||||
import NoteWrapperWidget from "../widgets/note_wrapper.js";
|
||||
import NoteDetail from "../widgets/NoteDetail.jsx";
|
||||
import PromotedAttributes from "../widgets/PromotedAttributes.jsx";
|
||||
import QuickSearchWidget from "../widgets/quick_search.js";
|
||||
import { useNoteContext } from "../widgets/react/hooks.jsx";
|
||||
import ReadOnlyNoteInfoBar from "../widgets/ReadOnlyNoteInfoBar.jsx";
|
||||
import StandaloneRibbonAdapter from "../widgets/ribbon/components/StandaloneRibbonAdapter.jsx";
|
||||
import FilePropertiesTab from "../widgets/ribbon/FilePropertiesTab.jsx";
|
||||
import SearchDefinitionTab from "../widgets/ribbon/SearchDefinitionTab.jsx";
|
||||
import ScrollPadding from "../widgets/scroll_padding";
|
||||
import SearchResult from "../widgets/search_result.jsx";
|
||||
import SharedInfoWidget from "../widgets/shared_info.js";
|
||||
import TabRowWidget from "../widgets/tab_row.js";
|
||||
import MobileEditorToolbar from "../widgets/type_widgets/text/mobile_editor_toolbar.jsx";
|
||||
import { applyModals } from "./layout_commons.js";
|
||||
|
||||
const MOBILE_CSS = `
|
||||
<style>
|
||||
span.keyboard-shortcut,
|
||||
kbd {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 1.25em;
|
||||
padding-inline-start: 0.5em;
|
||||
padding-inline-end: 0.5em;
|
||||
color: var(--main-text-color);
|
||||
}
|
||||
.quick-search {
|
||||
margin: 0;
|
||||
}
|
||||
.quick-search .dropdown-menu {
|
||||
max-width: 350px;
|
||||
}
|
||||
</style>`;
|
||||
|
||||
const FANCYTREE_CSS = `
|
||||
<style>
|
||||
.tree-wrapper {
|
||||
max-height: 100%;
|
||||
margin-top: 0px;
|
||||
overflow-y: auto;
|
||||
contain: content;
|
||||
padding-inline-start: 10px;
|
||||
}
|
||||
|
||||
.fancytree-custom-icon {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.fancytree-title {
|
||||
font-size: 1.5em;
|
||||
margin-inline-start: 0.6em !important;
|
||||
}
|
||||
|
||||
.fancytree-node {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.fancytree-node .fancytree-expander:before {
|
||||
font-size: 2em !important;
|
||||
}
|
||||
|
||||
span.fancytree-expander {
|
||||
width: 24px !important;
|
||||
margin-inline-end: 5px;
|
||||
}
|
||||
|
||||
.fancytree-loading span.fancytree-expander {
|
||||
width: 24px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.fancytree-loading span.fancytree-expander:after {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-top: 4px;
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
.tree-wrapper .collapse-tree-button,
|
||||
.tree-wrapper .scroll-to-active-note-button,
|
||||
.tree-wrapper .tree-settings-button {
|
||||
position: fixed;
|
||||
margin-inline-end: 16px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tree-wrapper .unhoist-button {
|
||||
font-size: 200%;
|
||||
}
|
||||
</style>`;
|
||||
|
||||
export default class MobileLayout {
|
||||
getRootWidget(appContext: typeof AppContext) {
|
||||
const rootContainer = new RootContainer(true)
|
||||
.setParent(appContext)
|
||||
.class("horizontal-layout")
|
||||
.cssBlock(MOBILE_CSS)
|
||||
.child(new FlexContainer("column").id("mobile-sidebar-container"))
|
||||
.child(
|
||||
new FlexContainer("row")
|
||||
@@ -136,7 +46,7 @@ export default class MobileLayout {
|
||||
.css("padding-inline-start", "0")
|
||||
.css("padding-inline-end", "0")
|
||||
.css("contain", "content")
|
||||
.child(new FlexContainer("column").filling().id("mobile-sidebar-wrapper").child(new QuickSearchWidget()).child(new NoteTreeWidget().cssBlock(FANCYTREE_CSS)))
|
||||
.child(new FlexContainer("column").filling().id("mobile-sidebar-wrapper").child(new QuickSearchWidget()).child(new NoteTreeWidget()))
|
||||
)
|
||||
.child(
|
||||
new ScreenContainer("detail", "row")
|
||||
@@ -147,30 +57,28 @@ export default class MobileLayout {
|
||||
new NoteWrapperWidget()
|
||||
.child(
|
||||
new FlexContainer("row")
|
||||
.class("title-row note-split-title")
|
||||
.contentSized()
|
||||
.css("font-size", "larger")
|
||||
.css("align-items", "center")
|
||||
.child(<ToggleSidebarButton />)
|
||||
.child(<NoteIconWidget />)
|
||||
.child(<NoteTitleWidget />)
|
||||
.child(<NoteBadges />)
|
||||
.child(<MobileDetailMenu />)
|
||||
)
|
||||
.child(<FloatingButtons items={MOBILE_FLOATING_BUTTONS} />)
|
||||
.child(<PromotedAttributes />)
|
||||
.child(
|
||||
new ScrollingContainer()
|
||||
.filling()
|
||||
.contentSized()
|
||||
.child(new ContentHeader()
|
||||
.child(<ReadOnlyNoteInfoBar />)
|
||||
.child(<SharedInfoWidget />)
|
||||
)
|
||||
.child(<InlineTitle />)
|
||||
.child(<NoteTitleActions />)
|
||||
.child(<NoteDetail />)
|
||||
.child(<NoteList media="screen" />)
|
||||
.child(<StandaloneRibbonAdapter component={SearchDefinitionTab} />)
|
||||
.child(<SearchResult />)
|
||||
.child(<FilePropertiesWrapper />)
|
||||
.child(<ScrollPadding />)
|
||||
)
|
||||
.child(<MobileEditorToolbar />)
|
||||
.child(new FindWidget())
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -179,7 +87,6 @@ export default class MobileLayout {
|
||||
new FlexContainer("column")
|
||||
.contentSized()
|
||||
.id("mobile-bottom-bar")
|
||||
.child(new TabRowWidget().css("height", "40px"))
|
||||
.child(new FlexContainer("row")
|
||||
.class("horizontal")
|
||||
.css("height", "53px")
|
||||
@@ -192,13 +99,3 @@ export default class MobileLayout {
|
||||
return rootContainer;
|
||||
}
|
||||
}
|
||||
|
||||
function FilePropertiesWrapper() {
|
||||
const { note, ntxId } = useNoteContext();
|
||||
|
||||
return (
|
||||
<div>
|
||||
{note?.type === "file" && <FilePropertiesTab note={note} ntxId={ntxId} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { KeyboardActionNames } from "@triliumnext/commons";
|
||||
import { h, JSX, render } from "preact";
|
||||
|
||||
import keyboardActionService, { getActionSync } from "../services/keyboard_actions.js";
|
||||
import note_tooltip from "../services/note_tooltip.js";
|
||||
import utils from "../services/utils.js";
|
||||
import { h, JSX, render } from "preact";
|
||||
|
||||
export interface ContextMenuOptions<T> {
|
||||
x: number;
|
||||
@@ -62,17 +63,17 @@ export type ContextMenuEvent = PointerEvent | MouseEvent | JQuery.ContextMenuEve
|
||||
|
||||
class ContextMenu {
|
||||
private $widget: JQuery<HTMLElement>;
|
||||
private $cover: JQuery<HTMLElement>;
|
||||
private $cover?: JQuery<HTMLElement>;
|
||||
private options?: ContextMenuOptions<any>;
|
||||
private isMobile: boolean;
|
||||
|
||||
constructor() {
|
||||
this.$widget = $("#context-menu-container");
|
||||
this.$cover = $("#context-menu-cover");
|
||||
this.$widget.addClass("dropend");
|
||||
this.isMobile = utils.isMobile();
|
||||
|
||||
if (this.isMobile) {
|
||||
this.$cover = $("#context-menu-cover");
|
||||
this.$cover.on("click", () => this.hide());
|
||||
} else {
|
||||
$(document).on("click", (e) => this.hide());
|
||||
@@ -91,7 +92,7 @@ class ContextMenu {
|
||||
}
|
||||
|
||||
this.$widget.toggleClass("mobile-bottom-menu", !this.options.forcePositionOnMobile);
|
||||
this.$cover.addClass("show");
|
||||
this.$cover?.addClass("show");
|
||||
$("body").addClass("context-menu-shown");
|
||||
|
||||
this.$widget.empty();
|
||||
@@ -140,16 +141,14 @@ class ContextMenu {
|
||||
} else {
|
||||
left = this.options.x - contextMenuWidth + CONTEXT_MENU_OFFSET;
|
||||
}
|
||||
} else if (contextMenuWidth && this.options.x + contextMenuWidth - CONTEXT_MENU_OFFSET > clientWidth - CONTEXT_MENU_PADDING) {
|
||||
// Overflow: right
|
||||
left = clientWidth - contextMenuWidth - CONTEXT_MENU_PADDING;
|
||||
} else if (this.options.x - CONTEXT_MENU_OFFSET < CONTEXT_MENU_PADDING) {
|
||||
// Overflow: left
|
||||
left = CONTEXT_MENU_PADDING;
|
||||
} else {
|
||||
if (contextMenuWidth && this.options.x + contextMenuWidth - CONTEXT_MENU_OFFSET > clientWidth - CONTEXT_MENU_PADDING) {
|
||||
// Overflow: right
|
||||
left = clientWidth - contextMenuWidth - CONTEXT_MENU_PADDING;
|
||||
} else if (this.options.x - CONTEXT_MENU_OFFSET < CONTEXT_MENU_PADDING) {
|
||||
// Overflow: left
|
||||
left = CONTEXT_MENU_PADDING;
|
||||
} else {
|
||||
left = this.options.x - CONTEXT_MENU_OFFSET;
|
||||
}
|
||||
left = this.options.x - CONTEXT_MENU_OFFSET;
|
||||
}
|
||||
|
||||
this.$widget
|
||||
@@ -249,7 +248,7 @@ class ContextMenu {
|
||||
if ("uiIcon" in item || "checked" in item) {
|
||||
const icon = (item.checked ? "bx bx-check" : item.uiIcon);
|
||||
if (icon) {
|
||||
$icon.addClass(icon);
|
||||
$icon.addClass([icon, "tn-icon"]);
|
||||
} else {
|
||||
$icon.append(" ");
|
||||
}
|
||||
@@ -261,7 +260,7 @@ class ContextMenu {
|
||||
.append(item.title);
|
||||
|
||||
if ("badges" in item && item.badges) {
|
||||
for (let badge of item.badges) {
|
||||
for (const badge of item.badges) {
|
||||
const badgeElement = $(`<span class="badge">`).text(badge.title);
|
||||
|
||||
if (badge.className) {
|
||||
@@ -352,7 +351,7 @@ class ContextMenu {
|
||||
async hide() {
|
||||
this.options?.onHide?.();
|
||||
this.$widget.removeClass("show");
|
||||
this.$cover.removeClass("show");
|
||||
this.$cover?.removeClass("show");
|
||||
$("body").removeClass("context-menu-shown");
|
||||
this.$widget.hide();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import utils from "../services/utils.js";
|
||||
import options from "../services/options.js";
|
||||
import zoomService from "../components/zoom.js";
|
||||
import contextMenu, { type MenuItem } from "./context_menu.js";
|
||||
import { t } from "../services/i18n.js";
|
||||
import type { BrowserWindow } from "electron";
|
||||
import type { CommandNames, AppContext } from "../components/app_context.js";
|
||||
|
||||
import type { CommandNames } from "../components/app_context.js";
|
||||
import appContext from "../components/app_context.js";
|
||||
import zoomService from "../components/zoom.js";
|
||||
import * as clipboardExt from "../services/clipboard_ext.js";
|
||||
import { t } from "../services/i18n.js";
|
||||
import options from "../services/options.js";
|
||||
import server from "../services/server.js";
|
||||
import utils from "../services/utils.js";
|
||||
import contextMenu, { type MenuItem } from "./context_menu.js";
|
||||
|
||||
function setupContextMenu() {
|
||||
const electron = utils.dynamicRequire("electron");
|
||||
@@ -13,8 +17,6 @@ function setupContextMenu() {
|
||||
// FIXME: Remove typecast once Electron is properly integrated.
|
||||
const { webContents } = remote.getCurrentWindow() as BrowserWindow;
|
||||
|
||||
let appContext: AppContext;
|
||||
|
||||
webContents.on("context-menu", (event, params) => {
|
||||
const { editFlags } = params;
|
||||
const hasText = params.selectionText.trim().length > 0;
|
||||
@@ -60,6 +62,33 @@ function setupContextMenu() {
|
||||
uiIcon: "bx bx-copy",
|
||||
handler: () => webContents.copy()
|
||||
});
|
||||
|
||||
items.push({
|
||||
enabled: hasText,
|
||||
title: t("electron_context_menu.copy-as-markdown"),
|
||||
uiIcon: "bx bx-copy-alt",
|
||||
handler: async () => {
|
||||
const selection = window.getSelection();
|
||||
if (!selection || !selection.rangeCount) return '';
|
||||
|
||||
const range = selection.getRangeAt(0);
|
||||
const div = document.createElement('div');
|
||||
div.appendChild(range.cloneContents());
|
||||
|
||||
const htmlContent = div.innerHTML;
|
||||
if (htmlContent) {
|
||||
try {
|
||||
const { markdownContent } = await server.post<{ markdownContent: string }>(
|
||||
"other/to-markdown",
|
||||
{ htmlContent }
|
||||
);
|
||||
await clipboardExt.copyTextWithToast(markdownContent);
|
||||
} catch (error) {
|
||||
console.error("Failed to copy as markdown:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!["", "javascript:", "about:blank#blocked"].includes(params.linkURL) && params.mediaType === "none") {
|
||||
@@ -112,7 +141,7 @@ function setupContextMenu() {
|
||||
}
|
||||
|
||||
// Replace the placeholder with the real search keyword.
|
||||
let searchUrl = searchEngineUrl.replace("{keyword}", encodeURIComponent(params.selectionText));
|
||||
const searchUrl = searchEngineUrl.replace("{keyword}", encodeURIComponent(params.selectionText));
|
||||
|
||||
items.push({ kind: "separator" });
|
||||
|
||||
@@ -126,10 +155,6 @@ function setupContextMenu() {
|
||||
title: t("electron_context_menu.search_in_trilium", { term: shortenedSelection }),
|
||||
uiIcon: "bx bx-search",
|
||||
handler: async () => {
|
||||
if (!appContext) {
|
||||
appContext = (await import("../components/app_context.js")).default;
|
||||
}
|
||||
|
||||
await appContext.triggerCommand("searchNotes", {
|
||||
searchString: params.selectionText
|
||||
});
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import treeService from "../services/tree.js";
|
||||
import froca from "../services/froca.js";
|
||||
import contextMenu, { type MenuCommandItem, type MenuItem } from "./context_menu.js";
|
||||
import dialogService from "../services/dialog.js";
|
||||
import server from "../services/server.js";
|
||||
import { t } from "../services/i18n.js";
|
||||
import type { ContextMenuCommandData,FilteredCommandNames } from "../components/app_context.js";
|
||||
import type { SelectMenuItemEventListener } from "../components/events.js";
|
||||
import dialogService from "../services/dialog.js";
|
||||
import froca from "../services/froca.js";
|
||||
import { t } from "../services/i18n.js";
|
||||
import server from "../services/server.js";
|
||||
import treeService from "../services/tree.js";
|
||||
import type NoteTreeWidget from "../widgets/note_tree.js";
|
||||
import type { FilteredCommandNames, ContextMenuCommandData } from "../components/app_context.js";
|
||||
import contextMenu, { type MenuCommandItem, type MenuItem } from "./context_menu.js";
|
||||
|
||||
type LauncherCommandNames = FilteredCommandNames<ContextMenuCommandData>;
|
||||
|
||||
@@ -32,8 +32,8 @@ export default class LauncherContextMenu implements SelectMenuItemEventListener<
|
||||
const note = this.node.data.noteId ? await froca.getNote(this.node.data.noteId) : null;
|
||||
const parentNoteId = this.node.getParent().data.noteId;
|
||||
|
||||
const isVisibleRoot = note?.noteId === "_lbVisibleLaunchers";
|
||||
const isAvailableRoot = note?.noteId === "_lbAvailableLaunchers";
|
||||
const isVisibleRoot = note?.noteId === "_lbVisibleLaunchers" || note?.noteId === "_lbMobileVisibleLaunchers";
|
||||
const isAvailableRoot = note?.noteId === "_lbAvailableLaunchers" || note?.noteId === "_lbMobileAvailableLaunchers";
|
||||
const isVisibleItem = parentNoteId === "_lbVisibleLaunchers" || parentNoteId === "_lbMobileVisibleLaunchers";
|
||||
const isAvailableItem = parentNoteId === "_lbAvailableLaunchers" || parentNoteId === "_lbMobileAvailableLaunchers";
|
||||
const isItem = isVisibleItem || isAvailableItem;
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useCallback, useLayoutEffect, useRef } from "preact/hooks";
|
||||
import FNote from "./entities/fnote";
|
||||
import content_renderer from "./services/content_renderer";
|
||||
import { applyInlineMermaid } from "./services/content_renderer_text";
|
||||
import froca from "./services/froca";
|
||||
import { dynamicRequire, isElectron } from "./services/utils";
|
||||
import { CustomNoteList, useNoteViewType } from "./widgets/collections/NoteList";
|
||||
|
||||
@@ -18,6 +19,10 @@ export type PrintReport = {
|
||||
} | {
|
||||
type: "collection";
|
||||
ignoredNoteIds: string[];
|
||||
} | {
|
||||
type: "error";
|
||||
message: string;
|
||||
stack?: string;
|
||||
};
|
||||
|
||||
async function main() {
|
||||
@@ -26,7 +31,6 @@ async function main() {
|
||||
if (!noteId) return;
|
||||
|
||||
await import("./print.css");
|
||||
const froca = (await import("./services/froca")).default;
|
||||
const note = await froca.getNote(noteId);
|
||||
|
||||
const bodyWrapper = document.createElement("div");
|
||||
|
||||
@@ -168,6 +168,49 @@ function isAffecting(attrRow: AttributeRow, affectedNote: FNote | null | undefin
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles whether a dangerous attribute is enabled or not. When an attribute is disabled, its name is prefixed with `disabled:`.
|
||||
*
|
||||
* Note that this work for non-dangerous attributes as well.
|
||||
*
|
||||
* If there are multiple attributes with the same name, all of them will be toggled at the same time.
|
||||
*
|
||||
* @param note the note whose attribute to change.
|
||||
* @param type the type of dangerous attribute (label or relation).
|
||||
* @param name the name of the dangerous attribute.
|
||||
* @param willEnable whether to enable or disable the attribute.
|
||||
* @returns a promise that will resolve when the request to the server completes.
|
||||
*/
|
||||
async function toggleDangerousAttribute(note: FNote, type: "label" | "relation", name: string, willEnable: boolean) {
|
||||
const attrs = [
|
||||
...note.getOwnedAttributes(type, name),
|
||||
...note.getOwnedAttributes(type, `disabled:${name}`)
|
||||
];
|
||||
|
||||
for (const attr of attrs) {
|
||||
const baseName = getNameWithoutDangerousPrefix(attr.name);
|
||||
const newName = willEnable ? baseName : `disabled:${baseName}`;
|
||||
if (newName === attr.name) continue;
|
||||
|
||||
// We are adding and removing afterwards to avoid a flicker (because for a moment there would be no active content attribute anymore) because the operations are done in sequence and not atomically.
|
||||
if (attr.type === "label") {
|
||||
await setLabel(note.noteId, newName, attr.value);
|
||||
} else {
|
||||
await setRelation(note.noteId, newName, attr.value);
|
||||
}
|
||||
await removeAttributeById(note.noteId, attr.attributeId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of an attribute without the `disabled:` prefix, or the same name if it's not disabled.
|
||||
* @param name the name of an attribute.
|
||||
* @returns the name without the `disabled:` prefix.
|
||||
*/
|
||||
function getNameWithoutDangerousPrefix(name: string) {
|
||||
return name.startsWith("disabled:") ? name.substring(9) : name;
|
||||
}
|
||||
|
||||
export default {
|
||||
addLabel,
|
||||
setLabel,
|
||||
@@ -177,5 +220,7 @@ export default {
|
||||
removeAttributeById,
|
||||
removeOwnedLabelByName,
|
||||
removeOwnedRelationByName,
|
||||
isAffecting
|
||||
isAffecting,
|
||||
toggleDangerousAttribute,
|
||||
getNameWithoutDangerousPrefix
|
||||
};
|
||||
|
||||
@@ -2,7 +2,6 @@ import { h, VNode } from "preact";
|
||||
|
||||
import BasicWidget, { ReactWrappedWidget } from "../widgets/basic_widget.js";
|
||||
import RightPanelWidget from "../widgets/right_panel_widget.js";
|
||||
import froca from "./froca.js";
|
||||
import type { Entity } from "./frontend_script_api.js";
|
||||
import { WidgetDefinitionWithType } from "./frontend_script_api_preact.js";
|
||||
import { t } from "./i18n.js";
|
||||
@@ -27,7 +26,7 @@ type WithNoteId<T> = T & {
|
||||
};
|
||||
export type Widget = WithNoteId<(LegacyWidget | WidgetDefinitionWithType)>;
|
||||
|
||||
async function getAndExecuteBundle(noteId: string, originEntity = null, script = null, params = null) {
|
||||
async function getAndExecuteBundle(noteId: string, originEntity: Entity | null = null, script: string | null = null, params: string | null = null) {
|
||||
const bundle = await server.post<Bundle>(`script/bundle/${noteId}`, {
|
||||
script,
|
||||
params
|
||||
@@ -38,15 +37,18 @@ async function getAndExecuteBundle(noteId: string, originEntity = null, script =
|
||||
|
||||
export type ParentName = "left-pane" | "center-pane" | "note-detail-pane" | "right-pane";
|
||||
|
||||
export async function executeBundle(bundle: Bundle, originEntity?: Entity | null, $container?: JQuery<HTMLElement>) {
|
||||
export async function executeBundleWithoutErrorHandling(bundle: Bundle, originEntity?: Entity | null, $container?: JQuery<HTMLElement>) {
|
||||
const apiContext = await ScriptContext(bundle.noteId, bundle.allNoteIds, originEntity, $container);
|
||||
return await function () {
|
||||
return eval(`const apiContext = this; (async function() { ${bundle.script}\r\n})()`);
|
||||
}.call(apiContext);
|
||||
}
|
||||
|
||||
export async function executeBundle(bundle: Bundle, originEntity?: Entity | null, $container?: JQuery<HTMLElement>) {
|
||||
try {
|
||||
return await function () {
|
||||
return eval(`const apiContext = this; (async function() { ${bundle.script}\r\n})()`);
|
||||
}.call(apiContext);
|
||||
} catch (e: any) {
|
||||
showErrorForScriptNote(bundle.noteId, t("toast.bundle-error.message", { message: e.message }));
|
||||
return await executeBundleWithoutErrorHandling(bundle, originEntity, $container);
|
||||
} catch (e: unknown) {
|
||||
showErrorForScriptNote(bundle.noteId, t("toast.bundle-error.message", { message: getErrorMessage(e) }));
|
||||
logError("Widget initialization failed: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import { t } from "./i18n.js";
|
||||
import toast from "./toast.js";
|
||||
|
||||
export function copyText(text: string) {
|
||||
if (!text) {
|
||||
return;
|
||||
@@ -6,29 +9,26 @@ export function copyText(text: string) {
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(text);
|
||||
return true;
|
||||
} else {
|
||||
// Fallback method: https://stackoverflow.com/a/72239825
|
||||
const textArea = document.createElement("textarea");
|
||||
textArea.value = text;
|
||||
try {
|
||||
document.body.appendChild(textArea);
|
||||
textArea.focus();
|
||||
textArea.select();
|
||||
return document.execCommand('copy');
|
||||
} finally {
|
||||
document.body.removeChild(textArea);
|
||||
}
|
||||
}
|
||||
// Fallback method: https://stackoverflow.com/a/72239825
|
||||
const textArea = document.createElement("textarea");
|
||||
textArea.value = text;
|
||||
try {
|
||||
document.body.appendChild(textArea);
|
||||
textArea.focus();
|
||||
textArea.select();
|
||||
return document.execCommand('copy');
|
||||
} finally {
|
||||
document.body.removeChild(textArea);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export async function copyTextWithToast(text: string) {
|
||||
const t = (await import("./i18n.js")).t;
|
||||
const toast = (await import("./toast.js")).default;
|
||||
|
||||
export function copyTextWithToast(text: string) {
|
||||
if (copyText(text)) {
|
||||
toast.showMessage(t("clipboard.copy_success"));
|
||||
} else {
|
||||
|
||||
9
apps/client/src/services/content_renderer.css
Normal file
9
apps/client/src/services/content_renderer.css
Normal file
@@ -0,0 +1,9 @@
|
||||
.rendered-content.no-preview > div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
font-size: 500%;
|
||||
flex-grow: 1;
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
import { normalizeMimeTypeForCKEditor } from "@triliumnext/commons";
|
||||
import "./content_renderer.css";
|
||||
|
||||
import { normalizeMimeTypeForCKEditor, type TextRepresentationResponse } from "@triliumnext/commons";
|
||||
import { h, render } from "preact";
|
||||
import WheelZoom from 'vanilla-js-wheel-zoom';
|
||||
|
||||
import FAttachment from "../entities/fattachment.js";
|
||||
@@ -12,8 +15,9 @@ import openService from "./open.js";
|
||||
import protectedSessionService from "./protected_session.js";
|
||||
import protectedSessionHolder from "./protected_session_holder.js";
|
||||
import renderService from "./render.js";
|
||||
import server from "./server.js";
|
||||
import { applySingleBlockSyntaxHighlight } from "./syntax_highlight.js";
|
||||
import utils from "./utils.js";
|
||||
import utils, { getErrorMessage } from "./utils.js";
|
||||
|
||||
let idCounter = 1;
|
||||
|
||||
@@ -29,6 +33,7 @@ export interface RenderOptions {
|
||||
includeArchivedNotes?: boolean;
|
||||
/** Set of note IDs that have already been seen during rendering to prevent infinite recursion. */
|
||||
seenNoteIds?: Set<string>;
|
||||
showTextRepresentation?: boolean;
|
||||
}
|
||||
|
||||
const CODE_MIME_TYPES = new Set(["application/json"]);
|
||||
@@ -51,16 +56,19 @@ export async function getRenderedContent(this: {} | { ctx: string }, entity: FNo
|
||||
await renderText(entity, $renderedContent, options);
|
||||
} else if (type === "code") {
|
||||
await renderCode(entity, $renderedContent);
|
||||
} else if (["image", "canvas", "mindMap"].includes(type)) {
|
||||
renderImage(entity, $renderedContent, options);
|
||||
} else if (["image", "canvas", "mindMap", "spreadsheet"].includes(type)) {
|
||||
await renderImage(entity, $renderedContent, options);
|
||||
} else if (!options.tooltip && ["file", "pdf", "audio", "video"].includes(type)) {
|
||||
renderFile(entity, type, $renderedContent);
|
||||
await renderFile(entity, type, $renderedContent, options);
|
||||
} else if (type === "mermaid") {
|
||||
await renderMermaid(entity, $renderedContent);
|
||||
} else if (type === "render" && entity instanceof FNote) {
|
||||
const $content = $("<div>");
|
||||
|
||||
await renderService.render(entity, $content);
|
||||
await renderService.render(entity, $content, (e) => {
|
||||
const $error = $("<div>").addClass("admonition caution").text(typeof e === "string" ? e : getErrorMessage(e));
|
||||
$content.empty().append($error);
|
||||
});
|
||||
|
||||
$renderedContent.append($content);
|
||||
} else if (type === "doc" && "noteId" in entity) {
|
||||
@@ -71,18 +79,9 @@ export async function getRenderedContent(this: {} | { ctx: string }, entity: FNo
|
||||
|
||||
$renderedContent.append($("<div>").append("<div>This note is protected and to access it you need to enter password.</div>").append("<br/>").append($button));
|
||||
} else if (entity instanceof FNote) {
|
||||
$renderedContent
|
||||
.css("display", "flex")
|
||||
.css("flex-direction", "column");
|
||||
$renderedContent.addClass("no-preview");
|
||||
$renderedContent.append(
|
||||
$("<div>")
|
||||
.css("display", "flex")
|
||||
.css("justify-content", "space-around")
|
||||
.css("align-items", "center")
|
||||
.css("height", "100%")
|
||||
.css("font-size", "500%")
|
||||
.css("flex-grow", "1")
|
||||
.append($("<span>").addClass(entity.getIcon()))
|
||||
$("<div>").append($("<span>").addClass(entity.getIcon()))
|
||||
);
|
||||
|
||||
if (entity.type === "webView" && entity.hasLabel("webViewSrc")) {
|
||||
@@ -141,7 +140,7 @@ async function renderCode(note: FNote | FAttachment, $renderedContent: JQuery<HT
|
||||
await applySingleBlockSyntaxHighlight($codeBlock, normalizeMimeTypeForCKEditor(note.mime));
|
||||
}
|
||||
|
||||
function renderImage(entity: FNote | FAttachment, $renderedContent: JQuery<HTMLElement>, options: RenderOptions = {}) {
|
||||
async function renderImage(entity: FNote | FAttachment, $renderedContent: JQuery<HTMLElement>, options: RenderOptions = {}) {
|
||||
const encodedTitle = encodeURIComponent(entity.title);
|
||||
|
||||
let url;
|
||||
@@ -149,13 +148,14 @@ function renderImage(entity: FNote | FAttachment, $renderedContent: JQuery<HTMLE
|
||||
if (entity instanceof FNote) {
|
||||
url = `api/images/${entity.noteId}/${encodedTitle}?${Math.random()}`;
|
||||
} else if (entity instanceof FAttachment) {
|
||||
url = `api/attachments/${entity.attachmentId}/image/${encodedTitle}?${entity.utcDateModified}">`;
|
||||
url = `api/attachments/${entity.attachmentId}/image/${encodedTitle}?${entity.utcDateModified}`;
|
||||
}
|
||||
|
||||
$renderedContent // styles needed for the zoom to work well
|
||||
.css("display", "flex")
|
||||
.css("align-items", "center")
|
||||
.css("justify-content", "center");
|
||||
.css("justify-content", "center")
|
||||
.css("flex-direction", "column"); // OCR text is displayed below the image.
|
||||
|
||||
const $img = $("<img>")
|
||||
.attr("src", url || "")
|
||||
@@ -181,9 +181,35 @@ function renderImage(entity: FNote | FAttachment, $renderedContent: JQuery<HTMLE
|
||||
}
|
||||
|
||||
imageContextMenuService.setupContextMenu($img);
|
||||
|
||||
if (entity instanceof FNote && options.showTextRepresentation) {
|
||||
await addOCRTextIfAvailable(entity, $renderedContent);
|
||||
}
|
||||
}
|
||||
|
||||
function renderFile(entity: FNote | FAttachment, type: string, $renderedContent: JQuery<HTMLElement>) {
|
||||
async function addOCRTextIfAvailable(note: FNote, $content: JQuery<HTMLElement>) {
|
||||
try {
|
||||
const data = await server.get<TextRepresentationResponse>(`ocr/notes/${note.noteId}/text`);
|
||||
if (data.success && data.hasOcr && data.text) {
|
||||
const $ocrSection = $(`
|
||||
<div class="ocr-text-section">
|
||||
<div class="ocr-header">
|
||||
<span class="bx bx-text"></span> ${t("ocr.extracted_text")}
|
||||
</div>
|
||||
<div class="ocr-content"></div>
|
||||
</div>
|
||||
`);
|
||||
|
||||
$ocrSection.find('.ocr-content').text(data.text);
|
||||
$content.append($ocrSection);
|
||||
}
|
||||
} catch (error) {
|
||||
// Silently fail if OCR API is not available
|
||||
console.debug('Failed to fetch OCR text:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function renderFile(entity: FNote | FAttachment, type: string, $renderedContent: JQuery<HTMLElement>, options: RenderOptions = {}) {
|
||||
let entityType, entityId;
|
||||
|
||||
if (entity instanceof FNote) {
|
||||
@@ -196,13 +222,17 @@ function renderFile(entity: FNote | FAttachment, type: string, $renderedContent:
|
||||
throw new Error(`Can't recognize entity type of '${entity}'`);
|
||||
}
|
||||
|
||||
const $content = $('<div style="display: flex; flex-direction: column; height: 100%;">');
|
||||
const $content = $('<div style="display: flex; flex-direction: column; height: 100%; justify-content: end;">');
|
||||
|
||||
if (type === "pdf") {
|
||||
const $pdfPreview = $('<iframe class="pdf-preview" style="width: 100%; flex-grow: 100;"></iframe>');
|
||||
$pdfPreview.attr("src", openService.getUrlForDownload(`pdfjs/web/viewer.html?file=../../api/${entityType}/${entityId}/open`));
|
||||
const url = `../../api/${entityType}/${entityId}/open`;
|
||||
const $viewer = $(`<div style="height: 100%">`);
|
||||
const PdfViewer = (await import("../widgets/type_widgets/file/PdfViewer")).default;
|
||||
render(h(PdfViewer, {pdfUrl: url, editable: false}), $viewer.get(0)!);
|
||||
|
||||
$content.append($viewer);
|
||||
|
||||
|
||||
$content.append($pdfPreview);
|
||||
} else if (type === "audio") {
|
||||
const $audioPreview = $("<audio controls></audio>")
|
||||
.attr("src", openService.getUrlForDownload(`api/${entityType}/${entityId}/open-partial`))
|
||||
@@ -219,6 +249,10 @@ function renderFile(entity: FNote | FAttachment, type: string, $renderedContent:
|
||||
$content.append($videoPreview);
|
||||
}
|
||||
|
||||
if (entity instanceof FNote && options.showTextRepresentation) {
|
||||
await addOCRTextIfAvailable(entity, $content);
|
||||
}
|
||||
|
||||
if (entityType === "notes" && "noteId" in entity) {
|
||||
// TODO: we should make this available also for attachments, but there's a problem with "Open externally" support
|
||||
// in attachment list
|
||||
@@ -292,10 +326,11 @@ function getRenderingType(entity: FNote | FAttachment) {
|
||||
}
|
||||
|
||||
const mime = "mime" in entity && entity.mime;
|
||||
const isIconPack = entity instanceof FNote && entity.hasLabel("iconPack");
|
||||
|
||||
if (type === "file" && mime === "application/pdf") {
|
||||
type = "pdf";
|
||||
} else if ((type === "file" || type === "viewConfig") && mime && CODE_MIME_TYPES.has(mime)) {
|
||||
} else if ((type === "file" || type === "viewConfig") && mime && CODE_MIME_TYPES.has(mime) && !isIconPack) {
|
||||
type = "code";
|
||||
} else if (type === "file" && mime && mime.startsWith("audio/")) {
|
||||
type = "audio";
|
||||
|
||||
@@ -120,7 +120,6 @@ async function renderChildrenList($renderedContent: JQuery<HTMLElement>, note: F
|
||||
return;
|
||||
}
|
||||
|
||||
$renderedContent.css("padding", "10px");
|
||||
$renderedContent.addClass("text-with-ellipsis");
|
||||
|
||||
// just load the first 10 child notes
|
||||
|
||||
@@ -49,7 +49,7 @@ function createClassForColor(colorString: string | null) {
|
||||
return clsx("use-note-color", className, colorsWithHue.has(className) && "with-hue");
|
||||
}
|
||||
|
||||
function parseColor(color: string) {
|
||||
export function parseColor(color: string) {
|
||||
try {
|
||||
return Color(color.toLowerCase());
|
||||
} catch (ex) {
|
||||
@@ -77,7 +77,7 @@ function adjustColorLightness(color: ColorInstance, lightThemeMaxLightness: numb
|
||||
}
|
||||
|
||||
/** Returns the hue of the specified color, or undefined if the color is grayscale. */
|
||||
function getHue(color: ColorInstance) {
|
||||
export function getHue(color: ColorInstance) {
|
||||
const hslColor = color.hsl();
|
||||
if (hslColor.saturationl() > 0) {
|
||||
return hslColor.hue();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { dayjs } from "@triliumnext/commons";
|
||||
|
||||
import type { FNoteRow } from "../entities/fnote.js";
|
||||
import froca from "./froca.js";
|
||||
import server from "./server.js";
|
||||
@@ -14,8 +15,13 @@ async function getTodayNote() {
|
||||
return await getDayNote(dayjs().format("YYYY-MM-DD"));
|
||||
}
|
||||
|
||||
async function getDayNote(date: string) {
|
||||
const note = await server.get<FNoteRow>(`special-notes/days/${date}`, "date-note");
|
||||
async function getDayNote(date: string, calendarRootId?: string) {
|
||||
let url = `special-notes/days/${date}`;
|
||||
if (calendarRootId) {
|
||||
url += `?calendarRootId=${calendarRootId}`;
|
||||
}
|
||||
|
||||
const note = await server.get<FNoteRow>(url, "date-note");
|
||||
|
||||
await ws.waitForMaxKnownEntityChangeId();
|
||||
|
||||
@@ -78,6 +84,55 @@ async function createSearchNote(opts = {}) {
|
||||
return await froca.getNote(note.noteId);
|
||||
}
|
||||
|
||||
async function createLlmChat() {
|
||||
const note = await server.post<FNoteRow>("special-notes/llm-chat");
|
||||
|
||||
await ws.waitForMaxKnownEntityChangeId();
|
||||
|
||||
return await froca.getNote(note.noteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the most recently modified LLM chat.
|
||||
* Returns null if no chat exists.
|
||||
*/
|
||||
async function getMostRecentLlmChat() {
|
||||
const note = await server.get<FNoteRow | null>("special-notes/most-recent-llm-chat");
|
||||
|
||||
if (!note) {
|
||||
return null;
|
||||
}
|
||||
|
||||
await ws.waitForMaxKnownEntityChangeId();
|
||||
|
||||
return await froca.getNote(note.noteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the most recent LLM chat, or creates a new one if none exists.
|
||||
* Used by sidebar chat for persistent conversations across page refreshes.
|
||||
*/
|
||||
async function getOrCreateLlmChat() {
|
||||
const note = await server.get<FNoteRow>("special-notes/get-or-create-llm-chat");
|
||||
|
||||
await ws.waitForMaxKnownEntityChangeId();
|
||||
|
||||
return await froca.getNote(note.noteId);
|
||||
}
|
||||
|
||||
export interface RecentLlmChat {
|
||||
noteId: string;
|
||||
title: string;
|
||||
dateModified: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of recent LLM chats for the history popup.
|
||||
*/
|
||||
async function getRecentLlmChats(limit: number = 10): Promise<RecentLlmChat[]> {
|
||||
return await server.get<RecentLlmChat[]>(`special-notes/recent-llm-chats?limit=${limit}`);
|
||||
}
|
||||
|
||||
export default {
|
||||
getInboxNote,
|
||||
getTodayNote,
|
||||
@@ -88,5 +143,9 @@ export default {
|
||||
getMonthNote,
|
||||
getYearNote,
|
||||
createSqlConsole,
|
||||
createSearchNote
|
||||
createSearchNote,
|
||||
createLlmChat,
|
||||
getMostRecentLlmChat,
|
||||
getOrCreateLlmChat,
|
||||
getRecentLlmChats
|
||||
};
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { Modal } from "bootstrap";
|
||||
|
||||
import appContext from "../components/app_context.js";
|
||||
import type { ConfirmDialogOptions, ConfirmDialogResult, ConfirmWithMessageOptions, MessageType } from "../widgets/dialogs/confirm.js";
|
||||
import { InfoExtraProps } from "../widgets/dialogs/info.jsx";
|
||||
import type { PromptDialogOptions } from "../widgets/dialogs/prompt.js";
|
||||
import { focusSavedElement, saveFocusedElement } from "./focus.js";
|
||||
import { InfoExtraProps } from "../widgets/dialogs/info.jsx";
|
||||
import keyboardActionsService from "./keyboard_actions.js";
|
||||
|
||||
export async function openDialog($dialog: JQuery<HTMLElement>, closeActDialog = true, config?: Partial<Modal.Options>) {
|
||||
if (closeActDialog) {
|
||||
@@ -25,7 +27,6 @@ export async function openDialog($dialog: JQuery<HTMLElement>, closeActDialog =
|
||||
}
|
||||
});
|
||||
|
||||
const keyboardActionsService = (await import("./keyboard_actions.js")).default;
|
||||
keyboardActionsService.updateDisplayedShortcuts($dialog);
|
||||
|
||||
return $dialog;
|
||||
|
||||
30
apps/client/src/services/doc_renderer.spec.ts
Normal file
30
apps/client/src/services/doc_renderer.spec.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { isValidDocName } from "./doc_renderer.js";
|
||||
|
||||
describe("isValidDocName", () => {
|
||||
it("accepts valid docNames", () => {
|
||||
expect(isValidDocName("launchbar_intro")).toBe(true);
|
||||
expect(isValidDocName("User Guide/Quick Start")).toBe(true);
|
||||
expect(isValidDocName("User Guide/User Guide/Quick Start")).toBe(true);
|
||||
expect(isValidDocName("Quick Start Guide")).toBe(true);
|
||||
expect(isValidDocName("quick_start_guide")).toBe(true);
|
||||
expect(isValidDocName("quick-start-guide")).toBe(true);
|
||||
});
|
||||
|
||||
it("rejects path traversal attacks", () => {
|
||||
expect(isValidDocName("..")).toBe(false);
|
||||
expect(isValidDocName("../etc/passwd")).toBe(false);
|
||||
expect(isValidDocName("foo/../bar")).toBe(false);
|
||||
expect(isValidDocName("../../../../api/notes/_malicious/open")).toBe(false);
|
||||
expect(isValidDocName("..\\etc\\passwd")).toBe(false);
|
||||
expect(isValidDocName("foo\\bar")).toBe(false);
|
||||
});
|
||||
|
||||
it("rejects URL manipulation attacks", () => {
|
||||
expect(isValidDocName("../../../../api/notes/_malicious/open?x=")).toBe(false);
|
||||
expect(isValidDocName("foo#bar")).toBe(false);
|
||||
expect(isValidDocName("%2e%2e")).toBe(false);
|
||||
expect(isValidDocName("%2e%2e%2f%2e%2e%2fapi")).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -3,22 +3,39 @@ import { applyReferenceLinks } from "../widgets/type_widgets/text/read_only_help
|
||||
import { getCurrentLanguage } from "./i18n.js";
|
||||
import { formatCodeBlocks } from "./syntax_highlight.js";
|
||||
|
||||
/**
|
||||
* Validates a docName to prevent path traversal attacks.
|
||||
* Allows forward slashes for subdirectories (e.g., "User Guide/Quick Start")
|
||||
* but blocks traversal sequences and URL manipulation characters.
|
||||
*/
|
||||
export function isValidDocName(docName: string): boolean {
|
||||
// Allow alphanumeric characters, spaces, underscores, hyphens, and forward slashes.
|
||||
const validDocNameRegex = /^[a-zA-Z0-9_/\- ]+$/;
|
||||
return validDocNameRegex.test(docName);
|
||||
}
|
||||
|
||||
export default function renderDoc(note: FNote) {
|
||||
return new Promise<JQuery<HTMLElement>>((resolve) => {
|
||||
let docName = note.getLabelValue("docName");
|
||||
const docName = note.getLabelValue("docName");
|
||||
const $content = $("<div>");
|
||||
|
||||
if (docName) {
|
||||
// find doc based on language
|
||||
const url = getUrl(docName, getCurrentLanguage());
|
||||
// find doc based on language
|
||||
const url = getUrl(docName, getCurrentLanguage());
|
||||
|
||||
if (url) {
|
||||
$content.load(url, async (response, status) => {
|
||||
// fallback to english doc if no translation available
|
||||
if (status === "error") {
|
||||
const fallbackUrl = getUrl(docName, "en");
|
||||
$content.load(fallbackUrl, async () => {
|
||||
await processContent(fallbackUrl, $content)
|
||||
|
||||
if (fallbackUrl) {
|
||||
$content.load(fallbackUrl, async () => {
|
||||
await processContent(fallbackUrl, $content);
|
||||
resolve($content);
|
||||
});
|
||||
} else {
|
||||
resolve($content);
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -28,8 +45,6 @@ export default function renderDoc(note: FNote) {
|
||||
} else {
|
||||
resolve($content);
|
||||
}
|
||||
|
||||
return $content;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -39,7 +54,7 @@ async function processContent(url: string, $content: JQuery<HTMLElement>) {
|
||||
// Images are relative to the docnote but that will not work when rendered in the application since the path breaks.
|
||||
$content.find("img").each((i, el) => {
|
||||
const $img = $(el);
|
||||
$img.attr("src", dir + "/" + $img.attr("src"));
|
||||
$img.attr("src", `${dir}/${$img.attr("src")}`);
|
||||
});
|
||||
|
||||
formatCodeBlocks($content);
|
||||
@@ -48,10 +63,17 @@ async function processContent(url: string, $content: JQuery<HTMLElement>) {
|
||||
await applyReferenceLinks($content[0]);
|
||||
}
|
||||
|
||||
function getUrl(docNameValue: string, language: string) {
|
||||
function getUrl(docNameValue: string | null, language: string) {
|
||||
if (!docNameValue) return;
|
||||
|
||||
if (!isValidDocName(docNameValue)) {
|
||||
console.error(`Invalid docName: ${docNameValue}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Cannot have spaces in the URL due to how JQuery.load works.
|
||||
docNameValue = docNameValue.replaceAll(" ", "%20");
|
||||
|
||||
const basePath = window.glob.isDev ? window.glob.assetPath + "/.." : window.glob.assetPath;
|
||||
const basePath = window.glob.isDev ? `${window.glob.assetPath }/..` : window.glob.assetPath;
|
||||
return `${basePath}/doc_notes/${language}/${docNameValue}.html`;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { t } from "./i18n";
|
||||
import options from "./options";
|
||||
import { isMobile } from "./utils";
|
||||
|
||||
export interface ExperimentalFeature {
|
||||
id: string;
|
||||
@@ -12,6 +13,11 @@ export const experimentalFeatures = [
|
||||
id: "new-layout",
|
||||
name: t("experimental_features.new_layout_name"),
|
||||
description: t("experimental_features.new_layout_description"),
|
||||
},
|
||||
{
|
||||
id: "llm",
|
||||
name: t("experimental_features.llm_name"),
|
||||
description: t("experimental_features.llm_description"),
|
||||
}
|
||||
] as const satisfies ExperimentalFeature[];
|
||||
|
||||
@@ -21,7 +27,7 @@ let enabledFeatures: Set<ExperimentalFeatureId> | null = null;
|
||||
|
||||
export function isExperimentalFeatureEnabled(featureId: ExperimentalFeatureId): boolean {
|
||||
if (featureId === "new-layout") {
|
||||
return options.is("newLayout");
|
||||
return (isMobile() || options.is("newLayout"));
|
||||
}
|
||||
|
||||
return getEnabledFeatures().has(featureId);
|
||||
@@ -29,7 +35,7 @@ export function isExperimentalFeatureEnabled(featureId: ExperimentalFeatureId):
|
||||
|
||||
export function getEnabledExperimentalFeatureIds() {
|
||||
const values = [ ...getEnabledFeatures().values() ];
|
||||
if (options.is("newLayout")) {
|
||||
if (isMobile() || options.is("newLayout")) {
|
||||
values.push("new-layout");
|
||||
}
|
||||
return values;
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import LoadResults from "./load_results.js";
|
||||
import froca from "./froca.js";
|
||||
import utils from "./utils.js";
|
||||
import options from "./options.js";
|
||||
import noteAttributeCache from "./note_attribute_cache.js";
|
||||
import FBranch, { type FBranchRow } from "../entities/fbranch.js";
|
||||
import FAttribute, { type FAttributeRow } from "../entities/fattribute.js";
|
||||
import type { OptionNames } from "@triliumnext/commons";
|
||||
|
||||
import appContext from "../components/app_context.js";
|
||||
import FAttachment, { type FAttachmentRow } from "../entities/fattachment.js";
|
||||
import FAttribute, { type FAttributeRow } from "../entities/fattribute.js";
|
||||
import FBranch, { type FBranchRow } from "../entities/fbranch.js";
|
||||
import type { default as FNote, FNoteRow } from "../entities/fnote.js";
|
||||
import type { EntityChange } from "../server_types.js";
|
||||
import type { OptionNames } from "@triliumnext/commons";
|
||||
import froca from "./froca.js";
|
||||
import LoadResults from "./load_results.js";
|
||||
import noteAttributeCache from "./note_attribute_cache.js";
|
||||
import options from "./options.js";
|
||||
import utils from "./utils.js";
|
||||
|
||||
async function processEntityChanges(entityChanges: EntityChange[]) {
|
||||
const loadResults = new LoadResults(entityChanges);
|
||||
@@ -63,7 +65,7 @@ async function processEntityChanges(entityChanges: EntityChange[]) {
|
||||
if (entityName === "branches" && !((entity as FBranchRow).parentNoteId in froca.notes)) {
|
||||
missingNoteIds.push((entity as FBranchRow).parentNoteId);
|
||||
} else if (entityName === "attributes") {
|
||||
let attributeEntity = entity as FAttributeRow;
|
||||
const attributeEntity = entity as FAttributeRow;
|
||||
if (attributeEntity.type === "relation" && (attributeEntity.name === "template" || attributeEntity.name === "inherit") && !(attributeEntity.value in froca.notes)) {
|
||||
missingNoteIds.push(attributeEntity.value);
|
||||
}
|
||||
@@ -79,7 +81,6 @@ async function processEntityChanges(entityChanges: EntityChange[]) {
|
||||
noteAttributeCache.invalidate();
|
||||
}
|
||||
|
||||
const appContext = (await import("../components/app_context.js")).default;
|
||||
await appContext.triggerEvent("entitiesReloaded", { loadResults });
|
||||
}
|
||||
}
|
||||
@@ -110,7 +111,12 @@ function processNoteChange(loadResults: LoadResults, ec: EntityChange) {
|
||||
}
|
||||
}
|
||||
|
||||
if (ec.componentId) {
|
||||
// Only register as a content change if the protection status didn't change.
|
||||
// When isProtected changes, the blobId change is a side effect of re-encryption,
|
||||
// not a content edit. Registering it as content would cause the tree's content-only
|
||||
// filter to incorrectly skip the note update (since both changes share the same
|
||||
// componentId).
|
||||
if (ec.componentId && note.isProtected === (ec.entity as FNoteRow).isProtected) {
|
||||
loadResults.addNoteContent(note.noteId, ec.componentId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,14 @@
|
||||
import options from "./options.js";
|
||||
import { LOCALE_IDS, LOCALES, setDayjsLocale } from "@triliumnext/commons";
|
||||
import i18next from "i18next";
|
||||
import i18nextHttpBackend from "i18next-http-backend";
|
||||
import server from "./server.js";
|
||||
import { LOCALE_IDS, setDayjsLocale, type Locale } from "@triliumnext/commons";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
|
||||
let locales: Locale[] | null;
|
||||
|
||||
/**
|
||||
* A deferred promise that resolves when translations are initialized.
|
||||
*/
|
||||
export let translationsInitializedPromise = $.Deferred();
|
||||
export const translationsInitializedPromise = $.Deferred();
|
||||
|
||||
export async function initLocale() {
|
||||
const locale = ((options.get("locale") as string) || "en") as LOCALE_IDS;
|
||||
|
||||
locales = await server.get<Locale[]>("options/locales");
|
||||
export async function initLocale(locale: LOCALE_IDS = "en") {
|
||||
|
||||
i18next.use(initReactI18next);
|
||||
await i18next.use(i18nextHttpBackend).init({
|
||||
@@ -32,11 +25,7 @@ export async function initLocale() {
|
||||
}
|
||||
|
||||
export function getAvailableLocales() {
|
||||
if (!locales) {
|
||||
throw new Error("Tried to load list of locales, but localization is not yet initialized.")
|
||||
}
|
||||
|
||||
return locales;
|
||||
return LOCALES;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,7 +36,7 @@ export function getAvailableLocales() {
|
||||
*/
|
||||
export function getLocaleById(localeId: string | null | undefined) {
|
||||
if (!localeId) return null;
|
||||
return locales?.find((l) => l.id === localeId) ?? null;
|
||||
return LOCALES.find((l) => l.id === localeId) ?? null;
|
||||
}
|
||||
|
||||
export const t = i18next.t;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { NoteType } from "@triliumnext/commons";
|
||||
|
||||
import FNote from "../entities/fnote";
|
||||
import { ViewTypeOptions } from "../widgets/collections/interface";
|
||||
|
||||
@@ -18,7 +19,8 @@ export const byNoteType: Record<Exclude<NoteType, "book">, string | null> = {
|
||||
search: null,
|
||||
text: null,
|
||||
webView: null,
|
||||
aiChat: null
|
||||
spreadsheet: null,
|
||||
llmChat: null
|
||||
};
|
||||
|
||||
export const byBookType: Record<ViewTypeOptions, string | null> = {
|
||||
@@ -39,6 +41,6 @@ export function getHelpUrlForNote(note: FNote | null | undefined) {
|
||||
} else if (note?.hasLabel("textSnippet")) {
|
||||
return "pwc194wlRzcH";
|
||||
} else if (note && note.type === "book") {
|
||||
return byBookType[note.getAttributeValue("label", "viewType") as ViewTypeOptions ?? ""]
|
||||
return byBookType[note.getAttributeValue("label", "viewType") as ViewTypeOptions ?? ""];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ async function getLinkIcon(noteId: string, viewMode: ViewMode | undefined) {
|
||||
return icon;
|
||||
}
|
||||
|
||||
export type ViewMode = "default" | "source" | "attachments" | "contextual-help" | "note-map";
|
||||
export type ViewMode = "default" | "source" | "attachments" | "contextual-help" | "note-map" | "ocr";
|
||||
|
||||
export interface ViewScope {
|
||||
/**
|
||||
|
||||
114
apps/client/src/services/llm_chat.ts
Normal file
114
apps/client/src/services/llm_chat.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
import type { LlmChatConfig, LlmCitation, LlmMessage, LlmModelInfo,LlmUsage } from "@triliumnext/commons";
|
||||
|
||||
import server from "./server.js";
|
||||
|
||||
/**
|
||||
* Fetch available models from all configured providers.
|
||||
*/
|
||||
export async function getAvailableModels(): Promise<LlmModelInfo[]> {
|
||||
const response = await server.get<{ models?: LlmModelInfo[] }>("llm-chat/models");
|
||||
return response.models ?? [];
|
||||
}
|
||||
|
||||
export interface StreamCallbacks {
|
||||
onChunk: (text: string) => void;
|
||||
onThinking?: (text: string) => void;
|
||||
onToolUse?: (toolName: string, input: Record<string, unknown>) => void;
|
||||
onToolResult?: (toolName: string, result: string, isError?: boolean) => void;
|
||||
onCitation?: (citation: LlmCitation) => void;
|
||||
onUsage?: (usage: LlmUsage) => void;
|
||||
onError: (error: string) => void;
|
||||
onDone: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stream a chat completion from the LLM API using Server-Sent Events.
|
||||
*/
|
||||
export async function streamChatCompletion(
|
||||
messages: LlmMessage[],
|
||||
config: LlmChatConfig,
|
||||
callbacks: StreamCallbacks
|
||||
): Promise<void> {
|
||||
const headers = await server.getHeaders();
|
||||
|
||||
const response = await fetch(`${window.glob.baseApiUrl}llm-chat/stream`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
...headers,
|
||||
"Content-Type": "application/json"
|
||||
} as HeadersInit,
|
||||
body: JSON.stringify({ messages, config })
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
callbacks.onError(`HTTP ${response.status}: ${response.statusText}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const reader = response.body?.getReader();
|
||||
if (!reader) {
|
||||
callbacks.onError("No response body");
|
||||
return;
|
||||
}
|
||||
|
||||
const decoder = new TextDecoder();
|
||||
let buffer = "";
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
const lines = buffer.split("\n");
|
||||
buffer = lines.pop() || "";
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.startsWith("data: ")) {
|
||||
try {
|
||||
const data = JSON.parse(line.slice(6));
|
||||
|
||||
switch (data.type) {
|
||||
case "text":
|
||||
callbacks.onChunk(data.content);
|
||||
break;
|
||||
case "thinking":
|
||||
callbacks.onThinking?.(data.content);
|
||||
break;
|
||||
case "tool_use":
|
||||
callbacks.onToolUse?.(data.toolName, data.toolInput);
|
||||
// Yield to force Preact to commit the pending tool call
|
||||
// state before we process the result.
|
||||
await new Promise((r) => setTimeout(r, 1));
|
||||
break;
|
||||
case "tool_result":
|
||||
callbacks.onToolResult?.(data.toolName, data.result, data.isError);
|
||||
await new Promise((r) => setTimeout(r, 1));
|
||||
break;
|
||||
case "citation":
|
||||
if (data.citation) {
|
||||
callbacks.onCitation?.(data.citation);
|
||||
}
|
||||
break;
|
||||
case "usage":
|
||||
if (data.usage) {
|
||||
callbacks.onUsage?.(data.usage);
|
||||
}
|
||||
break;
|
||||
case "error":
|
||||
callbacks.onError(data.error);
|
||||
break;
|
||||
case "done":
|
||||
callbacks.onDone();
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to parse SSE data line:", line, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
reader.releaseLock();
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,17 @@
|
||||
import type { CKTextEditor } from "@triliumnext/ckeditor5";
|
||||
import { AttributeRow } from "@triliumnext/commons";
|
||||
|
||||
import appContext from "../components/app_context.js";
|
||||
import type FBranch from "../entities/fbranch.js";
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import type { ChooseNoteTypeResponse } from "../widgets/dialogs/note_type_chooser.js";
|
||||
import froca from "./froca.js";
|
||||
import { t } from "./i18n.js";
|
||||
import protectedSessionHolder from "./protected_session_holder.js";
|
||||
import server from "./server.js";
|
||||
import ws from "./ws.js";
|
||||
import froca from "./froca.js";
|
||||
import treeService from "./tree.js";
|
||||
import toastService from "./toast.js";
|
||||
import { t } from "./i18n.js";
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import type FBranch from "../entities/fbranch.js";
|
||||
import type { ChooseNoteTypeResponse } from "../widgets/dialogs/note_type_chooser.js";
|
||||
import type { CKTextEditor } from "@triliumnext/ckeditor5";
|
||||
import treeService from "./tree.js";
|
||||
import ws from "./ws.js";
|
||||
|
||||
export interface CreateNoteOpts {
|
||||
isProtected?: boolean;
|
||||
@@ -24,6 +26,8 @@ export interface CreateNoteOpts {
|
||||
target?: string;
|
||||
targetBranchId?: string;
|
||||
textEditor?: CKTextEditor;
|
||||
/** Attributes to be set on the note. These are set atomically on note creation, so entity changes are not sent for attributes defined here. */
|
||||
attributes?: Omit<AttributeRow, "noteId" | "attributeId">[];
|
||||
}
|
||||
|
||||
interface Response {
|
||||
@@ -37,7 +41,7 @@ interface DuplicateResponse {
|
||||
note: FNote;
|
||||
}
|
||||
|
||||
async function createNote(parentNotePath: string | undefined, options: CreateNoteOpts = {}) {
|
||||
async function createNote(parentNotePath: string | undefined, options: CreateNoteOpts = {}, componentId?: string) {
|
||||
options = Object.assign(
|
||||
{
|
||||
activate: true,
|
||||
@@ -63,22 +67,15 @@ async function createNote(parentNotePath: string | undefined, options: CreateNot
|
||||
|
||||
const parentNoteId = treeService.getNoteIdFromUrl(parentNotePath);
|
||||
|
||||
if (options.type === "mermaid" && !options.content && !options.templateNoteId) {
|
||||
options.content = `graph TD;
|
||||
A-->B;
|
||||
A-->C;
|
||||
B-->D;
|
||||
C-->D;`;
|
||||
}
|
||||
|
||||
const { note, branch } = await server.post<Response>(`notes/${parentNoteId}/children?target=${options.target}&targetBranchId=${options.targetBranchId || ""}`, {
|
||||
title: options.title,
|
||||
content: options.content || "",
|
||||
isProtected: options.isProtected,
|
||||
type: options.type,
|
||||
mime: options.mime,
|
||||
templateNoteId: options.templateNoteId
|
||||
});
|
||||
templateNoteId: options.templateNoteId,
|
||||
attributes: options.attributes
|
||||
}, componentId);
|
||||
|
||||
if (options.saveSelection) {
|
||||
// we remove the selection only after it was saved to server to make sure we don't lose anything
|
||||
@@ -140,9 +137,8 @@ function parseSelectedHtml(selectedHtml: string) {
|
||||
const content = selectedHtml.replace(dom[0].outerHTML, "");
|
||||
|
||||
return [title, content];
|
||||
} else {
|
||||
return [null, selectedHtml];
|
||||
}
|
||||
return [null, selectedHtml];
|
||||
}
|
||||
|
||||
async function duplicateSubtree(noteId: string, parentNotePath: string) {
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import treeService from "./tree.js";
|
||||
import linkService from "./link.js";
|
||||
import froca from "./froca.js";
|
||||
import utils from "./utils.js";
|
||||
import attributeRenderer from "./attribute_renderer.js";
|
||||
import contentRenderer from "./content_renderer.js";
|
||||
import appContext from "../components/app_context.js";
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import attributeRenderer from "./attribute_renderer.js";
|
||||
import contentRenderer from "./content_renderer.js";
|
||||
import froca from "./froca.js";
|
||||
import { t } from "./i18n.js";
|
||||
import linkService from "./link.js";
|
||||
import treeService from "./tree.js";
|
||||
import utils from "./utils.js";
|
||||
|
||||
// Track all elements that open tooltips
|
||||
let openTooltipElements: JQuery<HTMLElement>[] = [];
|
||||
let dismissTimer: ReturnType<typeof setTimeout>;
|
||||
|
||||
function setupGlobalTooltip() {
|
||||
$(document).on("mouseenter", "a:not(.no-tooltip-preview)", mouseEnterHandler);
|
||||
$(document).on("mouseenter", "[data-href]:not(.no-tooltip-preview)", mouseEnterHandler);
|
||||
$(document).on("pointerenter", "a:not(.no-tooltip-preview)", mouseEnterHandler);
|
||||
$(document).on("pointerenter", "[data-href]:not(.no-tooltip-preview)", mouseEnterHandler);
|
||||
|
||||
// close any note tooltip after click, this fixes the problem that sometimes tooltips remained on the screen
|
||||
$(document).on("click", (e) => {
|
||||
@@ -37,10 +37,12 @@ function dismissAllTooltips() {
|
||||
}
|
||||
|
||||
function setupElementTooltip($el: JQuery<HTMLElement>) {
|
||||
$el.on("mouseenter", mouseEnterHandler);
|
||||
$el.on("pointerenter", mouseEnterHandler);
|
||||
}
|
||||
|
||||
async function mouseEnterHandler(this: HTMLElement) {
|
||||
async function mouseEnterHandler<T>(this: HTMLElement, e: JQuery.TriggeredEvent<T, undefined, T, T>) {
|
||||
if (e.pointerType !== "mouse") return;
|
||||
|
||||
const $link = $(this);
|
||||
|
||||
if ($link.hasClass("no-tooltip-preview") || $link.hasClass("disabled")) {
|
||||
@@ -91,7 +93,7 @@ async function mouseEnterHandler(this: HTMLElement) {
|
||||
}
|
||||
|
||||
const html = `<div class="note-tooltip-content">${content}</div>`;
|
||||
const tooltipClass = "tooltip-" + Math.floor(Math.random() * 999_999_999);
|
||||
const tooltipClass = `tooltip-${ Math.floor(Math.random() * 999_999_999)}`;
|
||||
|
||||
// we need to check if we're still hovering over the element
|
||||
// since the operation to get tooltip content was async, it is possible that
|
||||
@@ -224,7 +226,7 @@ function renderFootnoteOrAnchor($link: JQuery<HTMLElement>, url: string) {
|
||||
}
|
||||
|
||||
let footnoteContent = $targetContent.html();
|
||||
footnoteContent = `<div class="ck-content">${footnoteContent}</div>`
|
||||
footnoteContent = `<div class="ck-content">${footnoteContent}</div>`;
|
||||
return footnoteContent || "";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { t } from "./i18n.js";
|
||||
import froca from "./froca.js";
|
||||
import server from "./server.js";
|
||||
import type { MenuCommandItem, MenuItem, MenuItemBadge, MenuSeparatorItem } from "../menus/context_menu.js";
|
||||
import type { NoteType } from "../entities/fnote.js";
|
||||
import type { MenuCommandItem, MenuItem, MenuItemBadge, MenuSeparatorItem } from "../menus/context_menu.js";
|
||||
import type { TreeCommandNames } from "../menus/tree_context_menu.js";
|
||||
import { isExperimentalFeatureEnabled } from "./experimental_features.js";
|
||||
import froca from "./froca.js";
|
||||
import { t } from "./i18n.js";
|
||||
import server from "./server.js";
|
||||
|
||||
export interface NoteTypeMapping {
|
||||
type: NoteType;
|
||||
@@ -26,6 +27,7 @@ export const NOTE_TYPES: NoteTypeMapping[] = [
|
||||
|
||||
// The default note type (always the first item)
|
||||
{ type: "text", mime: "text/html", title: t("note_types.text"), icon: "bx-note" },
|
||||
{ type: "spreadsheet", mime: "application/json", title: t("note_types.spreadsheet"), icon: "bx-table", isBeta: true },
|
||||
|
||||
// Text notes group
|
||||
{ type: "book", mime: "", title: t("note_types.book"), icon: "bx-book" },
|
||||
@@ -40,6 +42,7 @@ export const NOTE_TYPES: NoteTypeMapping[] = [
|
||||
{ type: "relationMap", mime: "application/json", title: t("note_types.relation-map"), icon: "bxs-network-chart" },
|
||||
|
||||
// Misc note types
|
||||
{ type: "llmChat", mime: "application/json", title: t("note_types.llm-chat"), icon: "bx-message-square-dots", isBeta: true },
|
||||
{ type: "render", mime: "", title: t("note_types.render-note"), icon: "bx-extension" },
|
||||
{ type: "search", title: t("note_types.saved-search"), icon: "bx-file-find", static: true },
|
||||
{ type: "webView", mime: "", title: t("note_types.web-view"), icon: "bx-globe-alt" },
|
||||
@@ -53,7 +56,6 @@ export const NOTE_TYPES: NoteTypeMapping[] = [
|
||||
{ type: "file", title: t("note_types.file"), reserved: true },
|
||||
{ type: "image", title: t("note_types.image"), reserved: true },
|
||||
{ type: "launcher", mime: "", title: t("note_types.launcher"), reserved: true },
|
||||
{ type: "aiChat", mime: "application/json", title: t("note_types.ai-chat"), reserved: true }
|
||||
];
|
||||
|
||||
/** The maximum age in days for a template to be marked with the "New" badge */
|
||||
@@ -92,14 +94,15 @@ async function getNoteTypeItems(command?: TreeCommandNames) {
|
||||
function getBlankNoteTypes(command?: TreeCommandNames): MenuItem<TreeCommandNames>[] {
|
||||
return NOTE_TYPES
|
||||
.filter((nt) => !nt.reserved && nt.type !== "book")
|
||||
.filter((nt) => nt.type !== "llmChat" || isExperimentalFeatureEnabled("llm"))
|
||||
.map((nt) => {
|
||||
const menuItem: MenuCommandItem<TreeCommandNames> = {
|
||||
title: nt.title,
|
||||
command,
|
||||
type: nt.type,
|
||||
uiIcon: "bx " + nt.icon,
|
||||
uiIcon: `bx ${nt.icon}`,
|
||||
badges: []
|
||||
}
|
||||
};
|
||||
|
||||
if (nt.isNew) {
|
||||
menuItem.badges?.push(NEW_BADGE);
|
||||
@@ -131,7 +134,7 @@ async function getUserTemplates(command?: TreeCommandNames) {
|
||||
const item: MenuItem<TreeCommandNames> = {
|
||||
title: templateNote.title,
|
||||
uiIcon: templateNote.getIcon(),
|
||||
command: command,
|
||||
command,
|
||||
type: templateNote.type,
|
||||
templateNoteId: templateNote.noteId
|
||||
};
|
||||
@@ -160,7 +163,7 @@ async function getBuiltInTemplates(title: string | null, command: TreeCommandNam
|
||||
const items: MenuItem<TreeCommandNames>[] = [];
|
||||
if (title) {
|
||||
items.push({
|
||||
title: title,
|
||||
title,
|
||||
kind: "header"
|
||||
});
|
||||
} else {
|
||||
@@ -176,7 +179,7 @@ async function getBuiltInTemplates(title: string | null, command: TreeCommandNam
|
||||
const item: MenuItem<TreeCommandNames> = {
|
||||
title: templateNote.title,
|
||||
uiIcon: templateNote.getIcon(),
|
||||
command: command,
|
||||
command,
|
||||
type: templateNote.type,
|
||||
templateNoteId: templateNote.noteId
|
||||
};
|
||||
@@ -194,7 +197,7 @@ async function isNewTemplate(templateNoteId) {
|
||||
if (rootCreationDate === undefined) {
|
||||
// Retrieve the root note creation date
|
||||
try {
|
||||
let rootNoteInfo: any = await server.get("notes/root");
|
||||
const rootNoteInfo: any = await server.get("notes/root");
|
||||
if ("dateCreated" in rootNoteInfo) {
|
||||
rootCreationDate = new Date(rootNoteInfo.dateCreated);
|
||||
}
|
||||
@@ -209,7 +212,7 @@ async function isNewTemplate(templateNoteId) {
|
||||
if (creationDate === undefined) {
|
||||
// The creation date isn't available in the cache, try to retrieve it from the server
|
||||
try {
|
||||
const noteInfo: any = await server.get("notes/" + templateNoteId);
|
||||
const noteInfo: any = await server.get(`notes/${templateNoteId}`);
|
||||
if ("dateCreated" in noteInfo) {
|
||||
creationDate = new Date(noteInfo.dateCreated);
|
||||
creationDateCache.set(templateNoteId, creationDate);
|
||||
@@ -231,9 +234,8 @@ async function isNewTemplate(templateNoteId) {
|
||||
const age = (new Date().getTime() - creationDate.getTime()) / DAY_LENGTH;
|
||||
// Return true if the template is at most NEW_TEMPLATE_MAX_AGE days old
|
||||
return (age <= NEW_TEMPLATE_MAX_AGE);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export type LabelType = "text" | "number" | "boolean" | "date" | "datetime" | "time" | "url" | "color";
|
||||
export type LabelType = "text" | "textarea" | "number" | "boolean" | "date" | "datetime" | "time" | "url" | "color";
|
||||
type Multiplicity = "single" | "multi";
|
||||
|
||||
export interface DefinitionObject {
|
||||
@@ -17,7 +17,7 @@ function parse(value: string) {
|
||||
for (const token of tokens) {
|
||||
if (token === "promoted") {
|
||||
defObj.isPromoted = true;
|
||||
} else if (["text", "number", "boolean", "date", "datetime", "time", "url", "color"].includes(token)) {
|
||||
} else if (["text", "textarea", "number", "boolean", "date", "datetime", "time", "url", "color"].includes(token)) {
|
||||
defObj.labelType = token as LabelType;
|
||||
} else if (["single", "multi"].includes(token)) {
|
||||
defObj.multiplicity = token as Multiplicity;
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
import { h, VNode } from "preact";
|
||||
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import { renderReactWidgetAtElement } from "../widgets/react/react_utils.jsx";
|
||||
import bundleService, { type Bundle } from "./bundle.js";
|
||||
import froca from "./froca.js";
|
||||
import server from "./server.js";
|
||||
|
||||
async function render(note: FNote, $el: JQuery<HTMLElement>) {
|
||||
const relations = note.getRelations("renderNote");
|
||||
const renderNoteIds = relations.map((rel) => rel.value).filter((noteId) => noteId);
|
||||
|
||||
$el.empty().toggle(renderNoteIds.length > 0);
|
||||
|
||||
for (const renderNoteId of renderNoteIds) {
|
||||
const bundle = await server.post<Bundle>(`script/bundle/${renderNoteId}`);
|
||||
|
||||
const $scriptContainer = $("<div>");
|
||||
$el.append($scriptContainer);
|
||||
|
||||
$scriptContainer.append(bundle.html);
|
||||
|
||||
// async so that scripts cannot block trilium execution
|
||||
bundleService.executeBundle(bundle, note, $scriptContainer).then(result => {
|
||||
// Render JSX
|
||||
if (bundle.html === "") {
|
||||
renderIfJsx(bundle, result, $el);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return renderNoteIds.length > 0;
|
||||
}
|
||||
|
||||
async function renderIfJsx(bundle: Bundle, result: unknown, $el: JQuery<HTMLElement>) {
|
||||
// Ensure the root script note is actually a JSX.
|
||||
const rootScriptNoteId = await froca.getNote(bundle.noteId);
|
||||
if (rootScriptNoteId?.mime !== "text/jsx") return;
|
||||
|
||||
// Ensure the output is a valid el.
|
||||
if (typeof result !== "function") return;
|
||||
|
||||
// Obtain the parent component.
|
||||
const closestComponent = glob.getComponentByEl($el.closest(".component")[0]);
|
||||
if (!closestComponent) return;
|
||||
|
||||
// Render the element.
|
||||
const el = h(result as () => VNode, {});
|
||||
renderReactWidgetAtElement(closestComponent, el, $el[0]);
|
||||
}
|
||||
|
||||
export default {
|
||||
render
|
||||
};
|
||||
86
apps/client/src/services/render.tsx
Normal file
86
apps/client/src/services/render.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
import { Component, h, VNode } from "preact";
|
||||
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import { renderReactWidgetAtElement } from "../widgets/react/react_utils.jsx";
|
||||
import { type Bundle, executeBundleWithoutErrorHandling } from "./bundle.js";
|
||||
import froca from "./froca.js";
|
||||
import server from "./server.js";
|
||||
|
||||
type ErrorHandler = (e: unknown) => void;
|
||||
|
||||
async function render(note: FNote, $el: JQuery<HTMLElement>, onError?: ErrorHandler) {
|
||||
const relations = note.getRelations("renderNote");
|
||||
const renderNoteIds = relations.map((rel) => rel.value).filter((noteId) => noteId);
|
||||
|
||||
$el.empty().toggle(renderNoteIds.length > 0);
|
||||
|
||||
try {
|
||||
for (const renderNoteId of renderNoteIds) {
|
||||
const bundle = await server.postWithSilentInternalServerError<Bundle>(`script/bundle/${renderNoteId}`);
|
||||
|
||||
const $scriptContainer = $("<div>");
|
||||
$el.append($scriptContainer);
|
||||
|
||||
$scriptContainer.append(bundle.html);
|
||||
|
||||
// async so that scripts cannot block trilium execution
|
||||
executeBundleWithoutErrorHandling(bundle, note, $scriptContainer)
|
||||
.catch(onError)
|
||||
.then(result => {
|
||||
// Render JSX
|
||||
if (bundle.html === "") {
|
||||
renderIfJsx(bundle, result, $el, onError).catch(onError);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return renderNoteIds.length > 0;
|
||||
} catch (e) {
|
||||
if (typeof e === "string" && e.startsWith("{") && e.endsWith("}")) {
|
||||
try {
|
||||
onError?.(JSON.parse(e));
|
||||
} catch (e) {
|
||||
onError?.(e);
|
||||
}
|
||||
} else {
|
||||
onError?.(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function renderIfJsx(bundle: Bundle, result: unknown, $el: JQuery<HTMLElement>, onError?: ErrorHandler) {
|
||||
// Ensure the root script note is actually a JSX.
|
||||
const rootScriptNoteId = await froca.getNote(bundle.noteId);
|
||||
if (rootScriptNoteId?.mime !== "text/jsx") return;
|
||||
|
||||
// Ensure the output is a valid el.
|
||||
if (typeof result !== "function") return;
|
||||
|
||||
// Obtain the parent component.
|
||||
const closestComponent = glob.getComponentByEl($el.closest(".component")[0]);
|
||||
if (!closestComponent) return;
|
||||
|
||||
// Render the element.
|
||||
const UserErrorBoundary = class UserErrorBoundary extends Component {
|
||||
constructor(props: object) {
|
||||
super(props);
|
||||
this.state = { error: null };
|
||||
}
|
||||
|
||||
componentDidCatch(error: unknown) {
|
||||
onError?.(error);
|
||||
this.setState({ error });
|
||||
}
|
||||
|
||||
render() {
|
||||
if ("error" in this.state && this.state?.error) return null;
|
||||
return this.props.children;
|
||||
}
|
||||
};
|
||||
const el = h(UserErrorBoundary, {}, h(result as () => VNode, {}));
|
||||
renderReactWidgetAtElement(closestComponent, el, $el[0]);
|
||||
}
|
||||
|
||||
export default {
|
||||
render
|
||||
};
|
||||
@@ -1,3 +1,4 @@
|
||||
import { t } from "./i18n.js";
|
||||
import utils, { isShare } from "./utils.js";
|
||||
import ValidationError from "./validation_error.js";
|
||||
|
||||
@@ -32,8 +33,7 @@ async function getHeaders(headers?: Headers) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const appContext = (await import("../components/app_context.js")).default;
|
||||
const activeNoteContext = appContext.tabManager ? appContext.tabManager.getActiveContext() : null;
|
||||
const activeNoteContext = glob.appContext?.tabManager ? glob.appContext.tabManager.getActiveContext() : null;
|
||||
|
||||
// headers need to be lowercase because node.js automatically converts them to lower case
|
||||
// also avoiding using underscores instead of dashes since nginx filters them out by default
|
||||
@@ -73,6 +73,10 @@ async function post<T>(url: string, data?: unknown, componentId?: string) {
|
||||
return await call<T>("POST", url, componentId, { data });
|
||||
}
|
||||
|
||||
async function postWithSilentInternalServerError<T>(url: string, data?: unknown, componentId?: string) {
|
||||
return await call<T>("POST", url, componentId, { data, silentInternalServerError: true });
|
||||
}
|
||||
|
||||
async function put<T>(url: string, data?: unknown, componentId?: string) {
|
||||
return await call<T>("PUT", url, componentId, { data });
|
||||
}
|
||||
@@ -85,21 +89,33 @@ async function remove<T>(url: string, componentId?: string) {
|
||||
return await call<T>("DELETE", url, componentId);
|
||||
}
|
||||
|
||||
async function upload(url: string, fileToUpload: File, componentId?: string) {
|
||||
async function upload(url: string, fileToUpload: File, componentId?: string, method = "PUT") {
|
||||
const formData = new FormData();
|
||||
formData.append("upload", fileToUpload);
|
||||
|
||||
return await $.ajax({
|
||||
const doUpload = async () => $.ajax({
|
||||
url: window.glob.baseApiUrl + url,
|
||||
headers: await getHeaders(componentId ? {
|
||||
"trilium-component-id": componentId
|
||||
} : undefined),
|
||||
data: formData,
|
||||
type: "PUT",
|
||||
type: method,
|
||||
timeout: 60 * 60 * 1000,
|
||||
contentType: false, // NEEDED, DON'T REMOVE THIS
|
||||
processData: false // NEEDED, DON'T REMOVE THIS
|
||||
});
|
||||
|
||||
try {
|
||||
return await doUpload();
|
||||
} catch (e: unknown) {
|
||||
// jQuery rejects with the jqXHR object
|
||||
const jqXhr = e as JQuery.jqXHR;
|
||||
if (jqXhr?.status && isCsrfError(jqXhr.status, jqXhr.responseText)) {
|
||||
await refreshCsrfToken();
|
||||
return await doUpload();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
let idCounter = 1;
|
||||
@@ -108,11 +124,55 @@ const idToRequestMap: Record<string, RequestData> = {};
|
||||
|
||||
let maxKnownEntityChangeId = 0;
|
||||
|
||||
let csrfRefreshInProgress: Promise<void> | null = null;
|
||||
|
||||
/**
|
||||
* Re-fetches /bootstrap to obtain a fresh CSRF token. This is needed when the
|
||||
* server session expires (e.g. mobile tab backgrounded for a long time) and the
|
||||
* existing CSRF token is no longer valid.
|
||||
*
|
||||
* Coalesces concurrent calls so only one bootstrap request is in-flight at a time.
|
||||
*/
|
||||
async function refreshCsrfToken(): Promise<void> {
|
||||
if (csrfRefreshInProgress) {
|
||||
return csrfRefreshInProgress;
|
||||
}
|
||||
|
||||
csrfRefreshInProgress = (async () => {
|
||||
try {
|
||||
const response = await fetch(`./bootstrap${window.location.search}`, { cache: "no-store" });
|
||||
if (response.ok) {
|
||||
const json = await response.json();
|
||||
glob.csrfToken = json.csrfToken;
|
||||
}
|
||||
} finally {
|
||||
csrfRefreshInProgress = null;
|
||||
}
|
||||
})();
|
||||
|
||||
return csrfRefreshInProgress;
|
||||
}
|
||||
|
||||
function isCsrfError(status: number, responseText: string): boolean {
|
||||
if (status !== 403) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
const body = JSON.parse(responseText);
|
||||
return body.message === "Invalid CSRF token";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
interface CallOptions {
|
||||
data?: unknown;
|
||||
silentNotFound?: boolean;
|
||||
silentInternalServerError?: boolean;
|
||||
// If `true`, the value will be returned as a string instead of a JavaScript object if JSON, XMLDocument if XML, etc.
|
||||
raw?: boolean;
|
||||
/** Used internally to prevent infinite retry loops on CSRF refresh. */
|
||||
csrfRetried?: boolean;
|
||||
}
|
||||
|
||||
async function call<T>(method: string, url: string, componentId?: string, options: CallOptions = {}) {
|
||||
@@ -143,7 +203,7 @@ async function call<T>(method: string, url: string, componentId?: string, option
|
||||
});
|
||||
})) as any;
|
||||
} else {
|
||||
resp = await ajax(url, method, data, headers, !!options.silentNotFound, options.raw);
|
||||
resp = await ajax(url, method, data, headers, options);
|
||||
}
|
||||
|
||||
const maxEntityChangeIdStr = resp.headers["trilium-max-entity-change-id"];
|
||||
@@ -155,17 +215,14 @@ async function call<T>(method: string, url: string, componentId?: string, option
|
||||
return resp.body as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param raw if `true`, the value will be returned as a string instead of a JavaScript object if JSON, XMLDocument if XML, etc.
|
||||
*/
|
||||
function ajax(url: string, method: string, data: unknown, headers: Headers, silentNotFound: boolean, raw?: boolean): Promise<Response> {
|
||||
function ajax(url: string, method: string, data: unknown, headers: Headers, opts: CallOptions): Promise<Response> {
|
||||
return new Promise((res, rej) => {
|
||||
const options: JQueryAjaxSettings = {
|
||||
url: window.glob.baseApiUrl + url,
|
||||
type: method,
|
||||
headers,
|
||||
timeout: 60000,
|
||||
success: (body, textStatus, jqXhr) => {
|
||||
success: (body, _textStatus, jqXhr) => {
|
||||
const respHeaders: Headers = {};
|
||||
|
||||
jqXhr
|
||||
@@ -190,17 +247,41 @@ function ajax(url: string, method: string, data: unknown, headers: Headers, sile
|
||||
// don't report requests that are rejected by the browser, usually when the user is refreshing or going to a different page.
|
||||
rej("rejected by browser");
|
||||
return;
|
||||
} else if (silentNotFound && jqXhr.status === 404) {
|
||||
}
|
||||
|
||||
// If the CSRF token is stale (e.g. session expired while tab was backgrounded),
|
||||
// refresh it and retry the request once.
|
||||
if (!opts.csrfRetried && isCsrfError(jqXhr.status, jqXhr.responseText)) {
|
||||
try {
|
||||
await refreshCsrfToken();
|
||||
// Rebuild headers so the fresh glob.csrfToken is picked up
|
||||
const retryHeaders = await getHeaders({ "trilium-component-id": headers["trilium-component-id"] });
|
||||
const retryResult = await ajax(url, method, data, retryHeaders, { ...opts, csrfRetried: true });
|
||||
res(retryResult);
|
||||
return;
|
||||
} catch (retryErr) {
|
||||
rej(retryErr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.silentNotFound && jqXhr.status === 404) {
|
||||
// report nothing
|
||||
} else if (opts.silentInternalServerError && jqXhr.status === 500) {
|
||||
// report nothing
|
||||
} else {
|
||||
await reportError(method, url, jqXhr.status, jqXhr.responseText);
|
||||
try {
|
||||
await reportError(method, url, jqXhr.status, jqXhr.responseText);
|
||||
} catch {
|
||||
// reportError may throw (e.g. ValidationError); ensure rej() is still called below.
|
||||
}
|
||||
}
|
||||
|
||||
rej(jqXhr.responseText);
|
||||
}
|
||||
};
|
||||
|
||||
if (raw) {
|
||||
if (opts.raw) {
|
||||
options.dataType = "text";
|
||||
}
|
||||
|
||||
@@ -263,6 +344,7 @@ async function reportError(method: string, url: string, statusCode: number, resp
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// Dynamic import to avoid circular dependency (toast → app_context → options → server).
|
||||
const toastService = (await import("./toast.js")).default;
|
||||
|
||||
const messageStr = (typeof message === "string" ? message : JSON.stringify(message)) || "-";
|
||||
@@ -276,7 +358,6 @@ async function reportError(method: string, url: string, statusCode: number, resp
|
||||
...response
|
||||
});
|
||||
} else {
|
||||
const { t } = await import("./i18n.js");
|
||||
if (statusCode === 400 && (url.includes("%23") || url.includes("%2F"))) {
|
||||
toastService.showPersistent({
|
||||
id: "trafik-blocked",
|
||||
@@ -290,8 +371,7 @@ async function reportError(method: string, url: string, statusCode: number, resp
|
||||
t("server.unknown_http_error_content", { statusCode, method, url, message: messageStr }),
|
||||
15_000);
|
||||
}
|
||||
const { logError } = await import("./ws.js");
|
||||
logError(`${statusCode} ${method} ${url} - ${message}`);
|
||||
window.logError(`${statusCode} ${method} ${url} - ${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,6 +379,7 @@ export default {
|
||||
get,
|
||||
getWithSilentNotFound,
|
||||
post,
|
||||
postWithSilentInternalServerError,
|
||||
put,
|
||||
patch,
|
||||
remove,
|
||||
|
||||
@@ -12,6 +12,7 @@ export default class SpacedUpdate {
|
||||
private updateInterval: number;
|
||||
private changeForbidden?: boolean;
|
||||
private stateCallback?: StateCallback;
|
||||
private lastState: SaveState = "saved";
|
||||
|
||||
constructor(updater: Callback, updateInterval = 1000, stateCallback?: StateCallback) {
|
||||
this.updater = updater;
|
||||
@@ -24,7 +25,7 @@ export default class SpacedUpdate {
|
||||
scheduleUpdate() {
|
||||
if (!this.changeForbidden) {
|
||||
this.changed = true;
|
||||
this.stateCallback?.("unsaved");
|
||||
this.onStateChanged("unsaved");
|
||||
setTimeout(() => this.triggerUpdate());
|
||||
}
|
||||
}
|
||||
@@ -34,12 +35,12 @@ export default class SpacedUpdate {
|
||||
this.changed = false; // optimistic...
|
||||
|
||||
try {
|
||||
this.stateCallback?.("saving");
|
||||
this.onStateChanged("saving");
|
||||
await this.updater();
|
||||
this.stateCallback?.("saved");
|
||||
this.onStateChanged("saved");
|
||||
} catch (e) {
|
||||
this.changed = true;
|
||||
this.stateCallback?.("error");
|
||||
this.onStateChanged("error");
|
||||
logError(getErrorMessage(e));
|
||||
throw e;
|
||||
}
|
||||
@@ -76,13 +77,13 @@ export default class SpacedUpdate {
|
||||
}
|
||||
|
||||
if (Date.now() - this.lastUpdated > this.updateInterval) {
|
||||
this.stateCallback?.("saving");
|
||||
this.onStateChanged("saving");
|
||||
try {
|
||||
await this.updater();
|
||||
this.stateCallback?.("saved");
|
||||
this.onStateChanged("saved");
|
||||
this.changed = false;
|
||||
} catch (e) {
|
||||
this.stateCallback?.("error");
|
||||
this.onStateChanged("error");
|
||||
logError(getErrorMessage(e));
|
||||
}
|
||||
this.lastUpdated = Date.now();
|
||||
@@ -92,6 +93,13 @@ export default class SpacedUpdate {
|
||||
}
|
||||
}
|
||||
|
||||
onStateChanged(state: SaveState) {
|
||||
if (state === this.lastState) return;
|
||||
|
||||
this.stateCallback?.(state);
|
||||
this.lastState = state;
|
||||
}
|
||||
|
||||
async allowUpdateWithoutChange(callback: Callback) {
|
||||
this.changeForbidden = true;
|
||||
|
||||
|
||||
@@ -14,7 +14,9 @@ export function reloadFrontendApp(reason?: string) {
|
||||
}
|
||||
|
||||
if (isElectron()) {
|
||||
dynamicRequire("@electron/remote").BrowserWindow.getFocusedWindow()?.reload();
|
||||
for (const window of dynamicRequire("@electron/remote").BrowserWindow.getAllWindows()) {
|
||||
window.reload();
|
||||
}
|
||||
} else {
|
||||
window.location.reload();
|
||||
}
|
||||
@@ -453,9 +455,7 @@ export function openInAppHelpFromUrl(inAppHelpPage: string) {
|
||||
export async function openInReusableSplit(targetNoteId: string, targetViewMode: ViewMode, openOpts: {
|
||||
hoistedNoteId?: string;
|
||||
} = {}) {
|
||||
// Dynamic import to avoid import issues in tests.
|
||||
const appContext = (await import("../components/app_context.js")).default;
|
||||
const activeContext = appContext.tabManager.getActiveContext();
|
||||
const activeContext = glob.appContext?.tabManager?.getActiveContext();
|
||||
if (!activeContext) {
|
||||
return;
|
||||
}
|
||||
@@ -465,7 +465,7 @@ export async function openInReusableSplit(targetNoteId: string, targetViewMode:
|
||||
if (!existingSubcontext) {
|
||||
// The target split is not already open, open a new split with it.
|
||||
const { ntxId } = subContexts[subContexts.length - 1];
|
||||
appContext.triggerCommand("openNewNoteSplit", {
|
||||
glob.appContext?.triggerCommand("openNewNoteSplit", {
|
||||
ntxId,
|
||||
notePath: targetNoteId,
|
||||
hoistedNoteId: openOpts.hoistedNoteId,
|
||||
@@ -920,6 +920,7 @@ export default {
|
||||
parseDate,
|
||||
formatDateISO,
|
||||
formatDateTime,
|
||||
formatTime,
|
||||
formatTimeInterval,
|
||||
formatSize,
|
||||
localNowDateTime,
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import utils from "./utils.js";
|
||||
import toastService from "./toast.js";
|
||||
import server from "./server.js";
|
||||
import options from "./options.js";
|
||||
import frocaUpdater from "./froca_updater.js";
|
||||
import appContext from "../components/app_context.js";
|
||||
import { t } from "./i18n.js";
|
||||
import type { EntityChange } from "../server_types.js";
|
||||
import { WebSocketMessage } from "@triliumnext/commons";
|
||||
|
||||
import appContext from "../components/app_context.js";
|
||||
import type { EntityChange } from "../server_types.js";
|
||||
import bundleService from "./bundle.js";
|
||||
import froca from "./froca.js";
|
||||
import frocaUpdater from "./froca_updater.js";
|
||||
import { t } from "./i18n.js";
|
||||
import options from "./options.js";
|
||||
import server from "./server.js";
|
||||
import toast from "./toast.js";
|
||||
import utils from "./utils.js";
|
||||
|
||||
type MessageHandler = (message: WebSocketMessage) => void;
|
||||
let messageHandlers: MessageHandler[] = [];
|
||||
@@ -126,63 +128,14 @@ async function handleMessage(event: MessageEvent<any>) {
|
||||
} else if (message.type === "frontend-update") {
|
||||
await executeFrontendUpdate(message.data.entityChanges);
|
||||
} else if (message.type === "sync-hash-check-failed") {
|
||||
toastService.showError(t("ws.sync-check-failed"), 60000);
|
||||
toast.showError(t("ws.sync-check-failed"), 60000);
|
||||
} else if (message.type === "consistency-checks-failed") {
|
||||
toastService.showError(t("ws.consistency-checks-failed"), 50 * 60000);
|
||||
toast.showError(t("ws.consistency-checks-failed"), 50 * 60000);
|
||||
} else if (message.type === "api-log-messages") {
|
||||
appContext.triggerEvent("apiLogMessages", { noteId: message.noteId, messages: message.messages });
|
||||
} else if (message.type === "toast") {
|
||||
toastService.showMessage(message.message);
|
||||
} else if (message.type === "llm-stream") {
|
||||
// ENHANCED LOGGING FOR DEBUGGING
|
||||
console.log(`[WS-CLIENT] >>> RECEIVED LLM STREAM MESSAGE <<<`);
|
||||
console.log(`[WS-CLIENT] Message details: sessionId=${message.sessionId}, hasContent=${!!message.content}, contentLength=${message.content ? message.content.length : 0}, hasThinking=${!!message.thinking}, hasToolExecution=${!!message.toolExecution}, isDone=${!!message.done}`);
|
||||
|
||||
if (message.content) {
|
||||
console.log(`[WS-CLIENT] CONTENT PREVIEW: "${message.content.substring(0, 50)}..."`);
|
||||
}
|
||||
|
||||
// Create the event with detailed logging
|
||||
console.log(`[WS-CLIENT] Creating CustomEvent 'llm-stream-message'`);
|
||||
const llmStreamEvent = new CustomEvent('llm-stream-message', { detail: message });
|
||||
|
||||
// Dispatch to multiple targets to ensure delivery
|
||||
try {
|
||||
console.log(`[WS-CLIENT] Dispatching event to window`);
|
||||
window.dispatchEvent(llmStreamEvent);
|
||||
console.log(`[WS-CLIENT] Event dispatched to window`);
|
||||
|
||||
// Also try document for completeness
|
||||
console.log(`[WS-CLIENT] Dispatching event to document`);
|
||||
document.dispatchEvent(new CustomEvent('llm-stream-message', { detail: message }));
|
||||
console.log(`[WS-CLIENT] Event dispatched to document`);
|
||||
} catch (err) {
|
||||
console.error(`[WS-CLIENT] Error dispatching event:`, err);
|
||||
}
|
||||
|
||||
// Debug current listeners (though we can't directly check for specific event listeners)
|
||||
console.log(`[WS-CLIENT] Active event listeners should receive this message now`);
|
||||
|
||||
// Detailed logging based on message type
|
||||
if (message.content) {
|
||||
console.log(`[WS-CLIENT] Content message: ${message.content.length} chars`);
|
||||
} else if (message.thinking) {
|
||||
console.log(`[WS-CLIENT] Thinking update: "${message.thinking}"`);
|
||||
} else if (message.toolExecution) {
|
||||
console.log(`[WS-CLIENT] Tool execution: action=${message.toolExecution.action}, tool=${message.toolExecution.tool || 'unknown'}`);
|
||||
if (message.toolExecution.result) {
|
||||
console.log(`[WS-CLIENT] Tool result preview: "${String(message.toolExecution.result).substring(0, 50)}..."`);
|
||||
}
|
||||
} else if (message.done) {
|
||||
console.log(`[WS-CLIENT] Completion signal received`);
|
||||
}
|
||||
toast.showMessage(message.message);
|
||||
} else if (message.type === "execute-script") {
|
||||
// TODO: Remove after porting the file
|
||||
// @ts-ignore
|
||||
const bundleService = (await import("./bundle.js")).default as any;
|
||||
// TODO: Remove after porting the file
|
||||
// @ts-ignore
|
||||
const froca = (await import("./froca.js")).default as any;
|
||||
const originEntity = message.originEntityId ? await froca.getNote(message.originEntityId) : null;
|
||||
|
||||
bundleService.getAndExecuteBundle(message.currentNoteId, originEntity, message.script, message.params);
|
||||
@@ -204,7 +157,7 @@ function waitForEntityChangeId(desiredEntityChangeId: number) {
|
||||
|
||||
return new Promise<void>((res, rej) => {
|
||||
entityChangeIdReachedListeners.push({
|
||||
desiredEntityChangeId: desiredEntityChangeId,
|
||||
desiredEntityChangeId,
|
||||
resolvePromise: res,
|
||||
start: Date.now()
|
||||
});
|
||||
@@ -248,7 +201,7 @@ async function consumeFrontendUpdateData() {
|
||||
} else {
|
||||
console.log("nonProcessedEntityChanges causing the timeout", nonProcessedEntityChanges);
|
||||
|
||||
toastService.showError(t("ws.encountered-error", { message: e.message }));
|
||||
toast.showError(t("ws.encountered-error", { message: e.message }));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,66 +1,107 @@
|
||||
import "jquery";
|
||||
|
||||
import utils from "./services/utils.js";
|
||||
import ko from "knockout";
|
||||
|
||||
// TriliumNextTODO: properly make use of below types
|
||||
// type SetupModelSetupType = "new-document" | "sync-from-desktop" | "sync-from-server" | "";
|
||||
// type SetupModelStep = "sync-in-progress" | "setup-type" | "new-document-in-progress" | "sync-from-desktop";
|
||||
type SetupStep = "sync-in-progress" | "setup-type" | "new-document-in-progress" | "sync-from-desktop" | "sync-from-server";
|
||||
type SetupType = "new-document" | "sync-from-desktop" | "sync-from-server" | "";
|
||||
|
||||
class SetupModel {
|
||||
syncInProgress: boolean;
|
||||
step: ko.Observable<string>;
|
||||
setupType: ko.Observable<string>;
|
||||
setupNewDocument: ko.Observable<boolean>;
|
||||
setupSyncFromDesktop: ko.Observable<boolean>;
|
||||
setupSyncFromServer: ko.Observable<boolean>;
|
||||
syncServerHost: ko.Observable<string | undefined>;
|
||||
syncProxy: ko.Observable<string | undefined>;
|
||||
password: ko.Observable<string | undefined>;
|
||||
class SetupController {
|
||||
private step: SetupStep;
|
||||
private setupType: SetupType = "";
|
||||
private syncPollIntervalId: number | null = null;
|
||||
private rootNode: HTMLElement;
|
||||
private setupTypeForm: HTMLFormElement;
|
||||
private syncFromServerForm: HTMLFormElement;
|
||||
private setupTypeNextButton: HTMLButtonElement;
|
||||
private setupTypeInputs: HTMLInputElement[];
|
||||
private syncServerHostInput: HTMLInputElement;
|
||||
private syncProxyInput: HTMLInputElement;
|
||||
private passwordInput: HTMLInputElement;
|
||||
private sections: Record<SetupStep, HTMLElement>;
|
||||
|
||||
constructor(syncInProgress: boolean) {
|
||||
this.syncInProgress = syncInProgress;
|
||||
this.step = ko.observable(syncInProgress ? "sync-in-progress" : "setup-type");
|
||||
this.setupType = ko.observable("");
|
||||
this.setupNewDocument = ko.observable(false);
|
||||
this.setupSyncFromDesktop = ko.observable(false);
|
||||
this.setupSyncFromServer = ko.observable(false);
|
||||
this.syncServerHost = ko.observable();
|
||||
this.syncProxy = ko.observable();
|
||||
this.password = ko.observable();
|
||||
constructor(rootNode: HTMLElement, syncInProgress: boolean) {
|
||||
this.rootNode = rootNode;
|
||||
this.step = syncInProgress ? "sync-in-progress" : "setup-type";
|
||||
this.setupTypeForm = mustGetElement("setup-type-form", HTMLFormElement);
|
||||
this.syncFromServerForm = mustGetElement("sync-from-server-form", HTMLFormElement);
|
||||
this.setupTypeNextButton = mustGetElement("setup-type-next", HTMLButtonElement);
|
||||
this.setupTypeInputs = Array.from(document.querySelectorAll<HTMLInputElement>("input[name='setup-type']"));
|
||||
this.syncServerHostInput = mustGetElement("sync-server-host", HTMLInputElement);
|
||||
this.syncProxyInput = mustGetElement("sync-proxy", HTMLInputElement);
|
||||
this.passwordInput = mustGetElement("password", HTMLInputElement);
|
||||
this.sections = {
|
||||
"setup-type": mustGetElement("setup-type-section", HTMLElement),
|
||||
"new-document-in-progress": mustGetElement("new-document-in-progress-section", HTMLElement),
|
||||
"sync-from-desktop": mustGetElement("sync-from-desktop-section", HTMLElement),
|
||||
"sync-from-server": mustGetElement("sync-from-server-section", HTMLElement),
|
||||
"sync-in-progress": mustGetElement("sync-in-progress-section", HTMLElement)
|
||||
};
|
||||
}
|
||||
|
||||
if (this.syncInProgress) {
|
||||
setInterval(checkOutstandingSyncs, 1000);
|
||||
init() {
|
||||
this.setupTypeForm.addEventListener("submit", (event) => {
|
||||
event.preventDefault();
|
||||
void this.selectSetupType();
|
||||
});
|
||||
|
||||
this.syncFromServerForm.addEventListener("submit", (event) => {
|
||||
event.preventDefault();
|
||||
void this.finish();
|
||||
});
|
||||
|
||||
for (const input of this.setupTypeInputs) {
|
||||
input.addEventListener("change", () => {
|
||||
this.setupType = input.value as SetupType;
|
||||
this.render();
|
||||
});
|
||||
}
|
||||
|
||||
for (const backButton of document.querySelectorAll<HTMLElement>("[data-action='back']")) {
|
||||
backButton.addEventListener("click", () => {
|
||||
this.back();
|
||||
});
|
||||
}
|
||||
|
||||
const serverAddress = `${location.protocol}//${location.host}`;
|
||||
$("#current-host").html(serverAddress);
|
||||
|
||||
if (this.step === "sync-in-progress") {
|
||||
this.startSyncPolling();
|
||||
}
|
||||
|
||||
this.render();
|
||||
this.rootNode.style.display = "";
|
||||
}
|
||||
|
||||
// this is called in setup.ejs
|
||||
setupTypeSelected() {
|
||||
return !!this.setupType();
|
||||
}
|
||||
private async selectSetupType() {
|
||||
if (this.setupType === "new-document") {
|
||||
this.setStep("new-document-in-progress");
|
||||
|
||||
selectSetupType() {
|
||||
if (this.setupType() === "new-document") {
|
||||
this.step("new-document-in-progress");
|
||||
await $.post("api/setup/new-document");
|
||||
window.location.replace("./setup");
|
||||
return;
|
||||
}
|
||||
|
||||
$.post("api/setup/new-document").then(() => {
|
||||
window.location.replace("./setup");
|
||||
});
|
||||
} else {
|
||||
this.step(this.setupType());
|
||||
if (this.setupType) {
|
||||
this.setStep(this.setupType);
|
||||
}
|
||||
}
|
||||
|
||||
back() {
|
||||
this.step("setup-type");
|
||||
this.setupType("");
|
||||
private back() {
|
||||
this.setStep("setup-type");
|
||||
this.setupType = "";
|
||||
|
||||
for (const input of this.setupTypeInputs) {
|
||||
input.checked = false;
|
||||
}
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
async finish() {
|
||||
const syncServerHost = this.syncServerHost();
|
||||
const syncProxy = this.syncProxy();
|
||||
const password = this.password();
|
||||
private async finish() {
|
||||
const syncServerHost = this.syncServerHostInput.value.trim();
|
||||
const syncProxy = this.syncProxyInput.value.trim();
|
||||
const password = this.passwordInput.value;
|
||||
|
||||
if (!syncServerHost) {
|
||||
showAlert("Trilium server address can't be empty");
|
||||
@@ -74,21 +115,44 @@ class SetupModel {
|
||||
|
||||
// not using server.js because it loads too many dependencies
|
||||
const resp = await $.post("api/setup/sync-from-server", {
|
||||
syncServerHost: syncServerHost,
|
||||
syncProxy: syncProxy,
|
||||
password: password
|
||||
syncServerHost,
|
||||
syncProxy,
|
||||
password
|
||||
});
|
||||
|
||||
if (resp.result === "success") {
|
||||
this.step("sync-in-progress");
|
||||
|
||||
setInterval(checkOutstandingSyncs, 1000);
|
||||
|
||||
hideAlert();
|
||||
this.setStep("sync-in-progress");
|
||||
this.startSyncPolling();
|
||||
} else {
|
||||
showAlert(`Sync setup failed: ${resp.error}`);
|
||||
}
|
||||
}
|
||||
|
||||
private setStep(step: SetupStep) {
|
||||
this.step = step;
|
||||
this.render();
|
||||
}
|
||||
|
||||
private render() {
|
||||
for (const [step, section] of Object.entries(this.sections) as [SetupStep, HTMLElement][]) {
|
||||
section.style.display = step === this.step ? "" : "none";
|
||||
}
|
||||
|
||||
this.setupTypeNextButton.disabled = !this.setupType;
|
||||
}
|
||||
|
||||
private getSelectedSetupType(): SetupType {
|
||||
return (this.setupTypeInputs.find((input) => input.checked)?.value ?? "") as SetupType;
|
||||
}
|
||||
|
||||
private startSyncPolling() {
|
||||
if (this.syncPollIntervalId !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.syncPollIntervalId = window.setInterval(checkOutstandingSyncs, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
async function checkOutstandingSyncs() {
|
||||
@@ -122,7 +186,19 @@ function getSyncInProgress() {
|
||||
return !!parseInt(el.content);
|
||||
}
|
||||
|
||||
function mustGetElement<T extends typeof HTMLElement>(id: string, ctor: T): InstanceType<T> {
|
||||
const element = document.getElementById(id);
|
||||
|
||||
if (!element || !(element instanceof ctor)) {
|
||||
throw new Error(`Expected element #${id}`);
|
||||
}
|
||||
|
||||
return element as InstanceType<T>;
|
||||
}
|
||||
|
||||
addEventListener("DOMContentLoaded", (event) => {
|
||||
ko.applyBindings(new SetupModel(getSyncInProgress()), document.getElementById("setup-dialog"));
|
||||
$("#setup-dialog").show();
|
||||
const rootNode = document.getElementById("setup-dialog");
|
||||
if (!rootNode || !(rootNode instanceof HTMLElement)) return;
|
||||
|
||||
new SetupController(rootNode, getSyncInProgress()).init();
|
||||
});
|
||||
|
||||
@@ -1,450 +0,0 @@
|
||||
/* LLM Chat Panel Styles */
|
||||
.note-context-chat {
|
||||
background-color: var(--main-background-color);
|
||||
}
|
||||
|
||||
/* Message Styling */
|
||||
.chat-message {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.message-avatar {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
font-size: 1.25rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
background-color: var(--input-background-color);
|
||||
color: var(--cmd-button-icon-color);
|
||||
}
|
||||
|
||||
.assistant-avatar {
|
||||
background-color: var(--subtle-border-color, var(--main-border-color));
|
||||
color: var(--hover-item-text-color);
|
||||
}
|
||||
|
||||
.message-content {
|
||||
max-width: calc(100% - 50px);
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||||
color: var(--main-text-color);
|
||||
}
|
||||
|
||||
.user-content {
|
||||
border-radius: 0.5rem 0.5rem 0 0.5rem !important;
|
||||
background-color: var(--input-background-color) !important;
|
||||
}
|
||||
|
||||
.assistant-content {
|
||||
border-radius: 0.5rem 0.5rem 0.5rem 0 !important;
|
||||
background-color: var(--main-background-color);
|
||||
border: 1px solid var(--subtle-border-color, var(--main-border-color));
|
||||
}
|
||||
|
||||
/* Tool Execution Styling */
|
||||
.tool-execution-info {
|
||||
margin-top: 0.75rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border: 1px solid var(--subtle-border-color);
|
||||
border-radius: 0.5rem;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
|
||||
background-color: var(--main-background-color);
|
||||
/* Add a subtle transition effect */
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.tool-execution-status {
|
||||
background-color: var(--accented-background-color, rgba(0, 0, 0, 0.03)) !important;
|
||||
border-radius: 0 !important;
|
||||
padding: 0.5rem !important;
|
||||
max-height: 250px !important;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.tool-execution-status .d-flex {
|
||||
border-bottom: 1px solid var(--subtle-border-color);
|
||||
padding-bottom: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.tool-step {
|
||||
padding: 0.5rem;
|
||||
margin-bottom: 0.75rem;
|
||||
border-radius: 0.375rem;
|
||||
background-color: var(--main-background-color);
|
||||
border: 1px solid var(--subtle-border-color);
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.tool-step:hover {
|
||||
background-color: rgba(0, 0, 0, 0.01);
|
||||
}
|
||||
|
||||
.tool-step:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Tool step specific styling */
|
||||
.tool-step.executing {
|
||||
background-color: rgba(0, 123, 255, 0.05);
|
||||
border-color: rgba(0, 123, 255, 0.2);
|
||||
}
|
||||
|
||||
.tool-step.result {
|
||||
background-color: rgba(40, 167, 69, 0.05);
|
||||
border-color: rgba(40, 167, 69, 0.2);
|
||||
}
|
||||
|
||||
.tool-step.error {
|
||||
background-color: rgba(220, 53, 69, 0.05);
|
||||
border-color: rgba(220, 53, 69, 0.2);
|
||||
}
|
||||
|
||||
/* Tool result formatting */
|
||||
.tool-result pre {
|
||||
margin: 0.5rem 0;
|
||||
padding: 0.5rem;
|
||||
background-color: rgba(0, 0, 0, 0.03);
|
||||
border-radius: 0.25rem;
|
||||
overflow: auto;
|
||||
max-height: 300px;
|
||||
}
|
||||
|
||||
.tool-result code {
|
||||
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.tool-args code {
|
||||
display: block;
|
||||
padding: 0.5rem;
|
||||
background-color: rgba(0, 0, 0, 0.03);
|
||||
border-radius: 0.25rem;
|
||||
margin-top: 0.25rem;
|
||||
font-size: 0.85em;
|
||||
color: var(--muted-text-color);
|
||||
white-space: pre-wrap;
|
||||
overflow: auto;
|
||||
max-height: 100px;
|
||||
}
|
||||
|
||||
/* Tool Execution in Chat Styling */
|
||||
.chat-tool-execution {
|
||||
padding: 0 0 0 36px; /* Aligned with message content, accounting for avatar width */
|
||||
width: 100%;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.tool-execution-container {
|
||||
background-color: var(--accented-background-color, rgba(245, 247, 250, 0.7));
|
||||
border: 1px solid var(--subtle-border-color);
|
||||
border-radius: 0.375rem;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||||
overflow: hidden;
|
||||
max-width: calc(100% - 20px);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.tool-execution-container.collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tool-execution-header {
|
||||
background-color: var(--main-background-color);
|
||||
border-bottom: 1px solid var(--subtle-border-color);
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--muted-text-color);
|
||||
font-weight: 500;
|
||||
padding: 0.6rem 0.8rem;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.tool-execution-header:hover {
|
||||
background-color: var(--hover-item-background-color, rgba(0, 0, 0, 0.03));
|
||||
}
|
||||
|
||||
.tool-execution-toggle {
|
||||
color: var(--muted-text-color) !important;
|
||||
background: transparent !important;
|
||||
padding: 0.2rem 0.4rem !important;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.tool-execution-toggle:hover {
|
||||
color: var(--main-text-color) !important;
|
||||
}
|
||||
|
||||
.tool-execution-toggle i.bx-chevron-down {
|
||||
transform: rotate(0deg);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.tool-execution-toggle i.bx-chevron-right {
|
||||
transform: rotate(-90deg);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.tool-execution-chat-steps {
|
||||
padding: 0.5rem;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* Make error text more visible */
|
||||
.text-danger {
|
||||
color: #dc3545 !important;
|
||||
}
|
||||
|
||||
/* Sources Styling */
|
||||
.sources-container {
|
||||
background-color: var(--accented-background-color, var(--main-background-color));
|
||||
border-top: 1px solid var(--main-border-color);
|
||||
color: var(--main-text-color);
|
||||
}
|
||||
|
||||
.source-item {
|
||||
transition: all 0.2s ease;
|
||||
background-color: var(--main-background-color);
|
||||
border-color: var(--subtle-border-color, var(--main-border-color)) !important;
|
||||
}
|
||||
|
||||
.source-item:hover {
|
||||
background-color: var(--link-hover-background, var(--hover-item-background-color));
|
||||
}
|
||||
|
||||
.source-link {
|
||||
color: var(--link-color, var(--hover-item-text-color));
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.source-link:hover {
|
||||
color: var(--link-hover-color, var(--hover-item-text-color));
|
||||
}
|
||||
|
||||
/* Input Area Styling */
|
||||
.note-context-chat-form {
|
||||
background-color: var(--main-background-color);
|
||||
border-top: 1px solid var(--main-border-color);
|
||||
}
|
||||
|
||||
.context-option-container {
|
||||
padding: 0.5rem 0;
|
||||
border-bottom: 1px solid var(--subtle-border-color, var(--main-border-color));
|
||||
color: var(--main-text-color);
|
||||
}
|
||||
|
||||
.chat-input-container {
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
|
||||
.note-context-chat-input {
|
||||
border-color: var(--subtle-border-color, var(--main-border-color));
|
||||
background-color: var(--input-background-color) !important;
|
||||
color: var(--input-text-color) !important;
|
||||
resize: none;
|
||||
transition: all 0.2s ease;
|
||||
min-height: 50px;
|
||||
max-height: 150px;
|
||||
}
|
||||
|
||||
.note-context-chat-input:focus {
|
||||
border-color: var(--input-focus-outline-color, var(--main-border-color));
|
||||
box-shadow: 0 0 0 0.25rem var(--input-focus-outline-color, rgba(13, 110, 253, 0.25));
|
||||
}
|
||||
|
||||
.note-context-chat-send-button {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
align-self: flex-end;
|
||||
background-color: var(--cmd-button-background-color) !important;
|
||||
color: var(--cmd-button-text-color) !important;
|
||||
}
|
||||
|
||||
/* Loading Indicator */
|
||||
.loading-indicator {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 1rem;
|
||||
color: var(--muted-text-color);
|
||||
}
|
||||
|
||||
/* Thinking display styles */
|
||||
.llm-thinking-container {
|
||||
margin: 1rem 0;
|
||||
animation: fadeInUp 0.3s ease-out;
|
||||
}
|
||||
|
||||
.thinking-bubble {
|
||||
background-color: var(--accented-background-color, var(--main-background-color));
|
||||
border: 1px solid var(--subtle-border-color, var(--main-border-color));
|
||||
border-radius: 0.75rem;
|
||||
padding: 0.75rem;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.thinking-bubble:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.thinking-bubble::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-start: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, var(--hover-item-background-color, rgba(0, 0, 0, 0.03)), transparent);
|
||||
animation: shimmer 2s infinite;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.thinking-header {
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.thinking-header:hover {
|
||||
background-color: var(--hover-item-background-color, rgba(0, 0, 0, 0.03));
|
||||
padding: 0.25rem;
|
||||
margin: -0.25rem;
|
||||
}
|
||||
|
||||
.thinking-dots {
|
||||
display: flex;
|
||||
gap: 3px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.thinking-dots span {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background-color: var(--link-color, var(--hover-item-text-color));
|
||||
border-radius: 50%;
|
||||
animation: thinkingPulse 1.4s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.thinking-dots span:nth-child(1) {
|
||||
animation-delay: -0.32s;
|
||||
}
|
||||
|
||||
.thinking-dots span:nth-child(2) {
|
||||
animation-delay: -0.16s;
|
||||
}
|
||||
|
||||
.thinking-dots span:nth-child(3) {
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.thinking-label {
|
||||
font-weight: 500;
|
||||
color: var(--link-color, var(--hover-item-text-color)) !important;
|
||||
}
|
||||
|
||||
.thinking-toggle {
|
||||
color: var(--muted-text-color) !important;
|
||||
transition: transform 0.2s ease;
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.thinking-toggle:hover {
|
||||
color: var(--main-text-color) !important;
|
||||
}
|
||||
|
||||
.thinking-toggle.expanded {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.thinking-content {
|
||||
margin-top: 0.75rem;
|
||||
padding-top: 0.75rem;
|
||||
border-top: 1px solid var(--subtle-border-color, var(--main-border-color));
|
||||
animation: expandDown 0.3s ease-out;
|
||||
}
|
||||
|
||||
.thinking-text {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5;
|
||||
color: var(--main-text-color);
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
background-color: var(--input-background-color);
|
||||
padding: 0.75rem;
|
||||
border-radius: 0.5rem;
|
||||
border: 1px solid var(--subtle-border-color, var(--main-border-color));
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
transition: border-color 0.2s ease;
|
||||
}
|
||||
|
||||
.thinking-text:hover {
|
||||
border-color: var(--main-border-color);
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
@keyframes thinkingPulse {
|
||||
0%, 80%, 100% {
|
||||
transform: scale(0.8);
|
||||
opacity: 0.6;
|
||||
}
|
||||
40% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
inset-inline-start: -100%;
|
||||
}
|
||||
100% {
|
||||
inset-inline-start: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes expandDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
max-height: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
max-height: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.thinking-bubble {
|
||||
margin: 0.5rem 0;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.thinking-text {
|
||||
font-size: 0.8rem;
|
||||
padding: 0.5rem;
|
||||
max-height: 200px;
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@
|
||||
--bs-body-color: var(--main-text-color) !important;
|
||||
--bs-body-bg: var(--main-background-color) !important;
|
||||
--ck-mention-list-max-height: 500px;
|
||||
--tn-modal-max-height: 90vh;
|
||||
--tn-modal-max-height: 90svh;
|
||||
|
||||
--tree-item-light-theme-max-color-lightness: 50;
|
||||
--tree-item-dark-theme-min-color-lightness: 75;
|
||||
@@ -111,6 +111,7 @@ body.mobile #root-widget.virtual-keyboard-opened #mobile-bottom-bar {
|
||||
}
|
||||
|
||||
#mobile-bottom-bar {
|
||||
border-top: 1px solid var(--main-border-color);
|
||||
padding-bottom: var(--mobile-bottom-offset);
|
||||
}
|
||||
|
||||
@@ -152,6 +153,11 @@ textarea,
|
||||
background: var(--input-background-color);
|
||||
}
|
||||
|
||||
.form-control:disabled {
|
||||
background-color: var(--input-background-color);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
color: var(--input-text-color);
|
||||
background: var(--input-background-color);
|
||||
@@ -224,10 +230,6 @@ body.mobile .modal .modal-dialog {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
body.mobile .modal .modal-content {
|
||||
border-radius: var(--bs-modal-border-radius) var(--bs-modal-border-radius) 0 0;
|
||||
}
|
||||
|
||||
.component {
|
||||
contain: size;
|
||||
}
|
||||
@@ -413,6 +415,7 @@ body.desktop .tabulator-popup-container,
|
||||
|
||||
.dropdown-menu.static {
|
||||
box-shadow: unset;
|
||||
backdrop-filter: unset !important;
|
||||
}
|
||||
|
||||
.dropend .dropdown-toggle::after {
|
||||
@@ -458,7 +461,7 @@ body.desktop .tabulator-popup-container,
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
body.desktop .dropdown-menu:not(#context-menu-container) .dropdown-item,
|
||||
.dropdown-menu:not(#context-menu-container) .dropdown-item,
|
||||
body.desktop .dropdown-menu .dropdown-toggle,
|
||||
body #context-menu-container .dropdown-item > span,
|
||||
body.mobile .dropdown .dropdown-submenu > span {
|
||||
@@ -466,6 +469,15 @@ body.mobile .dropdown .dropdown-submenu > span {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
body.mobile .dropdown .dropdown-submenu {
|
||||
flex-wrap: wrap;
|
||||
|
||||
& > span {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-item span.keyboard-shortcut,
|
||||
.dropdown-item *:not(.keyboard-shortcut) > kbd {
|
||||
flex-grow: 1;
|
||||
@@ -935,6 +947,7 @@ table.promoted-attributes-in-tooltip th {
|
||||
color: var(--muted-text-color);
|
||||
opacity: 0.6;
|
||||
line-height: 1;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.aa-dropdown-menu .aa-suggestion p {
|
||||
@@ -1255,7 +1268,7 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: 0;
|
||||
bottom: 0;
|
||||
z-index: 1000;
|
||||
z-index: 2500;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
@@ -1329,15 +1342,12 @@ body.desktop .dropdown-submenu > .dropdown-menu {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.dropdown-submenu.dropstart > .dropdown-menu {
|
||||
.dropdown-submenu.dropstart > .dropdown-menu,
|
||||
body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
|
||||
inset-inline-start: auto;
|
||||
inset-inline-end: calc(100% - 2px);
|
||||
}
|
||||
|
||||
body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
|
||||
inset-inline-start: calc(-100% + 10px);
|
||||
}
|
||||
|
||||
.right-dropdown-widget {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -1534,7 +1544,8 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
|
||||
|
||||
@media (max-width: 991px) {
|
||||
body.mobile #launcher-pane .dropdown.global-menu > .dropdown-menu.show,
|
||||
body.mobile #launcher-container .dropdown > .dropdown-menu.show {
|
||||
body.mobile #launcher-container .dropdown > .dropdown-menu.show,
|
||||
body.mobile .dropdown-menu.mobile-bottom-menu.show {
|
||||
--dropdown-bottom: calc(var(--mobile-bottom-offset) + var(--launcher-pane-size));
|
||||
position: fixed !important;
|
||||
bottom: var(--dropdown-bottom) !important;
|
||||
@@ -1546,6 +1557,16 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
|
||||
max-height: calc(var(--tn-modal-max-height) - var(--dropdown-bottom));
|
||||
}
|
||||
|
||||
body.mobile #launcher-container .dropdown > .dropdown-menu.show {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
body.mobile .dropdown-menu.mobile-bottom-menu.show {
|
||||
--dropdown-bottom: 0px;
|
||||
padding-bottom: calc(max(var(--menu-padding-size), env(safe-area-inset-bottom))) !important;
|
||||
}
|
||||
|
||||
#mobile-sidebar-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
@@ -1566,7 +1587,7 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
bottom: 0;
|
||||
height: 100dvh;
|
||||
width: 85vw;
|
||||
padding-top: env(safe-area-inset-top);
|
||||
transition: transform 250ms ease-in-out;
|
||||
@@ -1591,11 +1612,7 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
|
||||
}
|
||||
|
||||
body.mobile #launcher-container {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
body.mobile #launcher-container button {
|
||||
margin: 0 16px;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
body.mobile .modal.show {
|
||||
@@ -1614,6 +1631,7 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
|
||||
|
||||
body.mobile .modal-content {
|
||||
overflow-y: auto;
|
||||
border-radius: var(--bs-modal-border-radius) var(--bs-modal-border-radius) 0 0;
|
||||
}
|
||||
|
||||
body.mobile .modal-footer {
|
||||
@@ -1629,13 +1647,27 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
body.mobile .jump-to-note-dialog .modal-content {
|
||||
overflow-y: auto;
|
||||
}
|
||||
body.mobile .jump-to-note-dialog {
|
||||
.modal-header {
|
||||
padding-bottom: 0.75rem !important;
|
||||
}
|
||||
|
||||
body.mobile .jump-to-note-dialog .modal-dialog .aa-dropdown-menu {
|
||||
max-height: unset;
|
||||
overflow: auto;
|
||||
.modal-content {
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.aa-dropdown-menu {
|
||||
max-height: unset;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.aa-suggestion {
|
||||
padding-inline: 0;
|
||||
}
|
||||
}
|
||||
|
||||
body.mobile .modal-dialog .dropdown-menu {
|
||||
@@ -1669,39 +1701,16 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
|
||||
#detail-container {
|
||||
background: var(--main-background-color);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 991px) {
|
||||
body.mobile.force-fixed-tree #mobile-sidebar-wrapper {
|
||||
padding-top: 0;
|
||||
position: static;
|
||||
height: 40vh;
|
||||
width: 100vw;
|
||||
transform: none !important;
|
||||
background-color: var(--left-pane-background-color) !important;
|
||||
border-bottom: 0.5px solid var(--main-border-color);
|
||||
}
|
||||
body.mobile {
|
||||
.modal-dialog {
|
||||
margin: var(--bs-modal-margin);
|
||||
max-width: 80%;
|
||||
}
|
||||
|
||||
body.mobile.force-fixed-tree #mobile-sidebar-container {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
body.mobile.force-fixed-tree #mobile-sidebar-wrapper .quick-search {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body.mobile.force-fixed-tree .component > button.bx-sidebar {
|
||||
visibility: hidden;
|
||||
padding: 0;
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
body.mobile.force-fixed-tree #mobile-rest-container {
|
||||
flex-direction: column !important;
|
||||
}
|
||||
|
||||
body.mobile.force-fixed-tree #detail-container {
|
||||
flex-grow: 1;
|
||||
.modal-content {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1741,10 +1750,13 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
color: var(--muted-text-color) !important;
|
||||
}
|
||||
|
||||
#right-pane .card-header-title {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
#right-pane .card-header-buttons {
|
||||
display: flex;
|
||||
transform: scale(0.9);
|
||||
@@ -2617,15 +2629,38 @@ iframe.print-iframe {
|
||||
}
|
||||
}
|
||||
|
||||
#root-widget.virtual-keyboard-opened .note-split:not(:focus-within) {
|
||||
body:not(.ios) #root-widget.virtual-keyboard-opened .note-split:not(.active) {
|
||||
max-height: 80px;
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body.desktop .title-row {
|
||||
.title-row {
|
||||
height: 50px;
|
||||
min-height: 50px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ocr-text-section {
|
||||
padding: 10px;
|
||||
background: var(--accented-background-color);
|
||||
border-left: 3px solid var(--main-border-color);
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ocr-header {
|
||||
font-weight: bold;
|
||||
margin-bottom: 8px;
|
||||
font-size: 0.9em;
|
||||
color: var(--muted-text-color);
|
||||
}
|
||||
|
||||
.ocr-content {
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
font-size: 0.9em;
|
||||
line-height: 1.4;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
@@ -134,6 +134,7 @@
|
||||
--left-pane-collapsed-border-color: #0009;
|
||||
--left-pane-background-color: #1f1f1f;
|
||||
--left-pane-text-color: #aaaaaa;
|
||||
--left-pane-icon-color: #c5c5c5;
|
||||
--left-pane-item-hover-background: #ffffff0d;
|
||||
--left-pane-item-selected-background: #ffffff25;
|
||||
--left-pane-item-selected-color: #dfdfdf;
|
||||
@@ -209,6 +210,7 @@
|
||||
--badge-share-background-color: #4d4d4d;
|
||||
--badge-clipped-note-background-color: #295773;
|
||||
--badge-execute-background-color: #604180;
|
||||
--badge-active-content-background-color: rgb(12, 68, 70);
|
||||
|
||||
--note-icon-background-color: #444444;
|
||||
--note-icon-color: #d4d4d4;
|
||||
@@ -237,9 +239,9 @@
|
||||
|
||||
--bottom-panel-background-color: #11111180;
|
||||
--bottom-panel-title-bar-background-color: #3F3F3F80;
|
||||
|
||||
|
||||
--status-bar-border-color: var(--main-border-color);
|
||||
|
||||
|
||||
--scrollbar-thumb-color: #fdfdfd5c;
|
||||
--scrollbar-thumb-hover-color: #ffffff7d;
|
||||
--scrollbar-background-color: transparent;
|
||||
@@ -289,6 +291,15 @@
|
||||
--ck-editor-toolbar-button-on-shadow: 1px 1px 2px rgba(0, 0, 0, .75);
|
||||
--ck-editor-toolbar-dropdown-button-open-background: #ffffff14;
|
||||
|
||||
--note-list-view-icon-color: var(--left-pane-icon-color);
|
||||
--note-list-view-large-icon-background: var(--note-icon-background-color);
|
||||
--note-list-view-large-icon-color: var(--note-icon-color);
|
||||
--note-list-view-search-result-highlight-background: transparent;
|
||||
--note-list-view-search-result-highlight-color: var(--quick-search-result-highlight-color);
|
||||
--note-list-view-content-background: rgba(0, 0, 0, .2);
|
||||
--note-list-view-content-search-result-highlight-background: var(--quick-search-result-highlight-color);
|
||||
--note-list-view-content-search-result-highlight-color: black;
|
||||
|
||||
--calendar-coll-event-background-saturation: 25%;
|
||||
--calendar-coll-event-background-lightness: 20%;
|
||||
--calendar-coll-event-background-color: #3c3c3c;
|
||||
@@ -302,7 +313,9 @@
|
||||
* Dark color scheme tweaks
|
||||
*/
|
||||
|
||||
#left-pane .fancytree-node.tinted {
|
||||
#left-pane .fancytree-node.tinted,
|
||||
.nested-note-list-item.use-note-color,
|
||||
.note-book-card .note-book-header.use-note-color {
|
||||
--custom-color: var(--dark-theme-custom-color);
|
||||
|
||||
/* The background color of the active item in the note tree.
|
||||
@@ -336,12 +349,25 @@ body .todo-list input[type="checkbox"]:not(:checked):before {
|
||||
--promoted-attribute-card-background-color: hsl(var(--custom-color-hue), 13.2%, 20.8%);
|
||||
}
|
||||
|
||||
.modal.tab-bar-modal .tabs .tab-card.with-hue {
|
||||
background-color: hsl(var(--bg-hue), 8.8%, 11.2%);
|
||||
border-color: hsl(var(--bg-hue), 9.4%, 25.1%);
|
||||
}
|
||||
|
||||
.modal.tab-bar-modal .tabs .tab-card.active.with-hue {
|
||||
background-color: hsl(var(--bg-hue), 8.8%, 16.2%);
|
||||
border-color: hsl(var(--bg-hue), 9.4%, 25.1%);
|
||||
}
|
||||
|
||||
|
||||
.use-note-color {
|
||||
--custom-color: var(--dark-theme-custom-color);
|
||||
}
|
||||
|
||||
.note-split.with-hue,
|
||||
.quick-edit-dialog-wrapper.with-hue {
|
||||
.quick-edit-dialog-wrapper.with-hue,
|
||||
.nested-note-list-item.with-hue,
|
||||
.note-book-card.with-hue .note-book-header {
|
||||
--note-icon-custom-background-color: hsl(var(--custom-color-hue), 15.8%, 30.9%);
|
||||
--note-icon-custom-color: hsl(var(--custom-color-hue), 100%, 76.5%);
|
||||
--note-icon-hover-custom-background-color: hsl(var(--custom-color-hue), 28.3%, 36.7%);
|
||||
@@ -350,4 +376,9 @@ body .todo-list input[type="checkbox"]:not(:checked):before {
|
||||
.note-split.with-hue *::selection,
|
||||
.quick-edit-dialog-wrapper.with-hue *::selection {
|
||||
--selection-background-color: hsl(var(--custom-color-hue), 49.2%, 35%);
|
||||
}
|
||||
|
||||
.note-book-card.with-hue {
|
||||
--card-background-color: hsl(var(--custom-color-hue), 6%, 21%);
|
||||
--card-background-hover-color: hsl(var(--custom-color-hue), 8%, 25%);
|
||||
}
|
||||
@@ -127,6 +127,7 @@
|
||||
--left-pane-collapsed-border-color: #0000000d;
|
||||
--left-pane-background-color: #f2f2f2;
|
||||
--left-pane-text-color: #383838;
|
||||
--left-pane-icon-color: currentColor;
|
||||
--left-pane-item-hover-background: rgba(0, 0, 0, 0.032);
|
||||
--left-pane-item-selected-background: white;
|
||||
--left-pane-item-selected-color: black;
|
||||
@@ -201,6 +202,7 @@
|
||||
--badge-share-background-color: #6b6b6b;
|
||||
--badge-clipped-note-background-color: #2284c0;
|
||||
--badge-execute-background-color: #7b47af;
|
||||
--badge-active-content-background-color: rgb(27, 164, 168);
|
||||
|
||||
--note-icon-background-color: #4f4f4f;
|
||||
--note-icon-color: white;
|
||||
@@ -287,6 +289,15 @@
|
||||
--ck-editor-toolbar-button-on-shadow: none;
|
||||
--ck-editor-toolbar-dropdown-button-open-background: #0000000f;
|
||||
|
||||
--note-list-view-icon-color: var(--left-pane-icon-color);
|
||||
--note-list-view-large-icon-background: var(--note-icon-background-color);
|
||||
--note-list-view-large-icon-color: var(--note-icon-color);
|
||||
--note-list-view-search-result-highlight-background: transparent;
|
||||
--note-list-view-search-result-highlight-color: var(--quick-search-result-highlight-color);
|
||||
--note-list-view-content-background: #b1b1b133;
|
||||
--note-list-view-content-search-result-highlight-background: var(--quick-search-result-highlight-color);
|
||||
--note-list-view-content-search-result-highlight-color: white;
|
||||
|
||||
--calendar-coll-event-background-lightness: 95%;
|
||||
--calendar-coll-event-background-saturation: 80%;
|
||||
--calendar-coll-event-background-color: #eaeaea;
|
||||
@@ -296,7 +307,9 @@
|
||||
--calendar-coll-today-background-color: #00000006;
|
||||
}
|
||||
|
||||
#left-pane .fancytree-node.tinted {
|
||||
#left-pane .fancytree-node.tinted,
|
||||
.nested-note-list-item.use-note-color,
|
||||
.note-book-card .note-book-header.use-note-color {
|
||||
--custom-color: var(--light-theme-custom-color);
|
||||
|
||||
/* The background color of the active item in the note tree.
|
||||
@@ -311,8 +324,20 @@
|
||||
--promoted-attribute-card-background-color: hsl(var(--custom-color-hue), 40%, 88%);
|
||||
}
|
||||
|
||||
.modal.tab-bar-modal .tabs .tab-card.with-hue {
|
||||
background-color: hsl(var(--bg-hue), 56%, 96%);
|
||||
border-color: hsl(var(--bg-hue), 33%, 41%);
|
||||
}
|
||||
|
||||
.modal.tab-bar-modal .tabs .tab-card.active.with-hue {
|
||||
background-color: hsl(var(--bg-hue), 86%, 96%);
|
||||
border-color: hsl(var(--bg-hue), 33%, 41%);
|
||||
}
|
||||
|
||||
.note-split.with-hue,
|
||||
.quick-edit-dialog-wrapper.with-hue {
|
||||
.quick-edit-dialog-wrapper.with-hue,
|
||||
.nested-note-list-item.with-hue,
|
||||
.note-book-card.with-hue .note-book-header {
|
||||
--note-icon-custom-background-color: hsl(var(--custom-color-hue), 44.5%, 43.1%);
|
||||
--note-icon-custom-color: hsl(var(--custom-color-hue), 91.3%, 91%);
|
||||
--note-icon-hover-custom-background-color: hsl(var(--custom-color-hue), 55.1%, 50.2%);
|
||||
@@ -321,4 +346,9 @@
|
||||
.note-split.with-hue *::selection,
|
||||
.quick-edit-dialog-wrapper.with-hue *::selection {
|
||||
--selection-background-color: hsl(var(--custom-color-hue), 60%, 90%);
|
||||
}
|
||||
|
||||
.note-book-card.with-hue {
|
||||
--card-background-color: hsl(var(--custom-color-hue), 21%, 94%);
|
||||
--card-background-hover-color: hsl(var(--custom-color-hue), 21%, 87%);
|
||||
}
|
||||
@@ -544,14 +544,11 @@ li.dropdown-item a.dropdown-item-button:focus-visible {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#toast-container .toast .toast-header .btn-close {
|
||||
#toast-container .toast .toast-header .btn-close,
|
||||
#toast-container .toast .toast-close .btn-close {
|
||||
margin: 0 0 0 12px;
|
||||
}
|
||||
|
||||
#toast-container .toast.no-title {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#toast-container .toast .toast-body {
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
@@ -643,139 +640,6 @@ li.dropdown-item a.dropdown-item-button:focus-visible {
|
||||
transform: translateY(4%);
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE LIST
|
||||
*/
|
||||
|
||||
.note-list .note-book-card {
|
||||
--note-list-horizontal-padding: 22px;
|
||||
--note-list-vertical-padding: 15px;
|
||||
background-color: var(--card-background-color);
|
||||
border: 1px solid var(--card-border-color) !important;
|
||||
border-radius: 12px;
|
||||
user-select: none;
|
||||
padding: 0;
|
||||
margin: 5px 10px 5px 0;
|
||||
}
|
||||
|
||||
:root .note-list .note-book-card:hover {
|
||||
background-color: var(--card-background-hover-color);
|
||||
transition: background-color 200ms ease-out;
|
||||
}
|
||||
|
||||
:root .note-list.grid-view .note-book-card:active {
|
||||
transform: scale(.98);
|
||||
}
|
||||
|
||||
.note-list.list-view .note-book-card {
|
||||
box-shadow: 0 0 3px var(--card-shadow-color);
|
||||
}
|
||||
|
||||
.note-list.list-view .note-book-card .note-book-header .note-icon {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card a {
|
||||
color: inherit !important;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-header {
|
||||
font-size: 1em;
|
||||
font-weight: bold;
|
||||
padding: 0.5em 1rem;
|
||||
border-bottom-color: var(--card-border-color);
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-header .note-icon {
|
||||
font-size: 17px;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-header .note-book-title {
|
||||
font-size: 1em;
|
||||
color: var(--active-item-text-color);
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-header .rendered-note-attributes {
|
||||
font-size: 0.7em;
|
||||
font-weight: normal;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-header:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-content {
|
||||
padding: 0 !important;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-content .rendered-content {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-content.type-image .rendered-content,
|
||||
.note-list-wrapper .note-book-card .note-book-content.type-pdf .rendered-content {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-content .rendered-content.text-with-ellipsis {
|
||||
padding: 1rem !important;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-content h1,
|
||||
.note-list-wrapper .note-book-card .note-book-content h2,
|
||||
.note-list-wrapper .note-book-card .note-book-content h3,
|
||||
.note-list-wrapper .note-book-card .note-book-content h4,
|
||||
.note-list-wrapper .note-book-card .note-book-content h5,
|
||||
.note-list-wrapper .note-book-card .note-book-content h6 {
|
||||
font-size: 1rem;
|
||||
color: var(--active-item-text-color);
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-content p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-content.type-canvas .rendered-content,
|
||||
.note-list-wrapper .note-book-card .note-book-content.type-mindMap .rendered-content,
|
||||
.note-list-wrapper .note-book-card .note-book-content.type-code .rendered-content,
|
||||
.note-list-wrapper .note-book-card .note-book-content.type-video .rendered-content {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-content.type-code {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-content.type-code pre {
|
||||
height: 100%;
|
||||
padding: 1em;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .tn-icon {
|
||||
color: var(--left-pane-icon-color) !important;
|
||||
}
|
||||
|
||||
.note-list.grid-view .note-book-card:hover {
|
||||
filter: contrast(105%);
|
||||
}
|
||||
|
||||
.note-list.grid-view .ck-content {
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.note-list.grid-view .ck-content p {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.note-list.grid-view .ck-content figure.image {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE SEARCH SUGGESTIONS
|
||||
*/
|
||||
@@ -800,3 +664,19 @@ li.dropdown-item a.dropdown-item-button:focus-visible {
|
||||
background: var(--hover-item-background-color);
|
||||
color: var(--hover-item-text-color);
|
||||
}
|
||||
|
||||
/*
|
||||
* Alert bars
|
||||
*/
|
||||
|
||||
div.alert {
|
||||
margin-bottom: 8px;
|
||||
background: var(--alert-bar-background) !important;
|
||||
color: var(--main-text-color);
|
||||
border-radius: 8px;
|
||||
font-size: .85em;
|
||||
}
|
||||
|
||||
div.alert p + p {
|
||||
margin-block: 1em 0;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
.modal .modal-header .btn-close,
|
||||
.modal .modal-header .help-button,
|
||||
.modal .modal-header .custom-title-bar-button,
|
||||
#toast-container .toast .toast-header .btn-close {
|
||||
#toast-container .toast .toast-header .btn-close,
|
||||
#toast-container .toast .toast-close .btn-close {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@@ -46,12 +47,14 @@
|
||||
}
|
||||
|
||||
.modal .modal-header .btn-close,
|
||||
#toast-container .toast .toast-header .btn-close {
|
||||
#toast-container .toast .toast-header .btn-close,
|
||||
#toast-container .toast .toast-close .btn-close {
|
||||
--modal-control-button-hover-background: var(--modal-close-button-hover-background);
|
||||
}
|
||||
|
||||
.modal .modal-header .btn-close::after,
|
||||
#toast-container .toast .toast-header .btn-close::after {
|
||||
#toast-container .toast .toast-header .btn-close::after,
|
||||
#toast-container .toast .toast-close .btn-close::after {
|
||||
content: "\ec8d";
|
||||
font-family: boxicons;
|
||||
}
|
||||
@@ -67,7 +70,8 @@
|
||||
.modal .modal-header .btn-close:hover,
|
||||
.modal .modal-header .help-button:hover,
|
||||
.modal .modal-header .custom-title-bar-button:hover,
|
||||
#toast-container .toast .toast-header .btn-close:hover {
|
||||
#toast-container .toast .toast-header .btn-close:hover,
|
||||
#toast-container .toast .toast-close .btn-close:hover {
|
||||
background: var(--modal-control-button-hover-background);
|
||||
color: var(--modal-control-button-hover-color);
|
||||
}
|
||||
@@ -75,19 +79,22 @@
|
||||
.modal .modal-header .btn-close:active,
|
||||
.modal .modal-header .help-button:active,
|
||||
.modal .modal-header .custom-title-bar-button:active,
|
||||
#toast-container .toast .toast-header .btn-close:active {
|
||||
#toast-container .toast .toast-header .btn-close:active,
|
||||
#toast-container .toast .toast-close .btn-close:active {
|
||||
transform: scale(.85);
|
||||
}
|
||||
|
||||
.modal .modal-header .btn-close:focus,
|
||||
.modal .modal-header .help-button:focus,
|
||||
#toast-container .toast .toast-header .btn-close:focus {
|
||||
#toast-container .toast .toast-header .btn-close:focus,
|
||||
#toast-container .toast .toast-close .btn-close:focus {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.modal .modal-header .btn-close:focus-visible,
|
||||
.modal .modal-header .help-button:focus-visible,
|
||||
#toast-container .toast .toast-header .btn-close:focus-visible {
|
||||
#toast-container .toast .toast-header .btn-close:focus-visible,
|
||||
#toast-container .toast .toast-close .btn-close:focus-visible {
|
||||
outline: 2px solid var(--input-focus-outline-color);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,22 @@ button.btn.btn-success kbd {
|
||||
letter-spacing: 0.5pt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Low profile buttons
|
||||
*/
|
||||
|
||||
button.tn-low-profile {
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
border-radius: 8px;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
button.tn-low-profile:hover {
|
||||
background-color: var(--icon-button-hover-background);
|
||||
}
|
||||
|
||||
/*
|
||||
* Icon buttons
|
||||
*/
|
||||
@@ -129,6 +145,10 @@ button.btn.btn-success kbd {
|
||||
font-size: calc(var(--icon-button-size) * var(--icon-button-icon-ratio));
|
||||
}
|
||||
|
||||
:root .icon-action.disabled::before {
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
:root .icon-action:not(.global-menu-button):hover,
|
||||
:root .icon-action:not(.global-menu-button).show,
|
||||
:root .tn-tool-button:hover,
|
||||
@@ -794,3 +814,35 @@ input[type="range"] {
|
||||
scrollbar-width: unset;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Centered forms
|
||||
*/
|
||||
|
||||
.tn-centered-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-bottom: 20vh;
|
||||
}
|
||||
|
||||
.tn-centered-form .form-group {
|
||||
text-align: center;
|
||||
color: var(--muted-text-color);
|
||||
}
|
||||
|
||||
.tn-centered-form .form-icon {
|
||||
font-size: 140px;
|
||||
color: var(--main-border-color);
|
||||
}
|
||||
|
||||
.tn-centered-form .protected-session-password {
|
||||
margin-inline: auto;
|
||||
max-width: 350px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tn-centered-form .input-group,
|
||||
.tn-centered-form button {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
/* LLM Chat Launcher Widget Styles */
|
||||
.note-context-chat {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.note-context-chat-container {
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.chat-message {
|
||||
display: flex;
|
||||
margin-bottom: 15px;
|
||||
max-width: 85%;
|
||||
}
|
||||
|
||||
.chat-message.user-message {
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
|
||||
.chat-message.assistant-message {
|
||||
margin-inline-end: auto;
|
||||
}
|
||||
|
||||
.message-avatar {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-inline-end: 8px;
|
||||
}
|
||||
|
||||
.user-message .message-avatar {
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.assistant-message .message-avatar {
|
||||
background-color: var(--secondary-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.message-content {
|
||||
background-color: var(--more-accented-background-color);
|
||||
border-radius: 12px;
|
||||
padding: 10px 15px;
|
||||
max-width: calc(100% - 40px);
|
||||
}
|
||||
|
||||
.user-message .message-content {
|
||||
background-color: var(--accented-background-color);
|
||||
}
|
||||
|
||||
.message-content pre {
|
||||
background-color: var(--code-background-color);
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
overflow-x: auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.message-content code {
|
||||
background-color: var(--code-background-color);
|
||||
padding: 2px 4px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.loading-indicator {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 10px 0;
|
||||
color: var(--muted-text-color);
|
||||
}
|
||||
|
||||
.sources-container {
|
||||
background-color: var(--accented-background-color);
|
||||
border-top: 1px solid var(--main-border-color);
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.sources-list {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.source-item {
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.source-link {
|
||||
color: var(--link-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.source-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.note-context-chat-form {
|
||||
display: flex;
|
||||
background-color: var(--main-background-color);
|
||||
border-top: 1px solid var(--main-border-color);
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.note-context-chat-input {
|
||||
resize: vertical;
|
||||
min-height: 44px;
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.chat-message {
|
||||
max-width: 95%;
|
||||
}
|
||||
}
|
||||
@@ -47,9 +47,14 @@
|
||||
}
|
||||
|
||||
/* The toolbar show / hide button for the current text block */
|
||||
.ck.ck-block-toolbar-button {
|
||||
:root .ck.ck-block-toolbar-button {
|
||||
--ck-color-block-toolbar-button: var(--muted-text-color);
|
||||
--ck-color-button-on-background: transparent;
|
||||
--ck-color-button-on-color: currentColor;
|
||||
--ck-color-button-on-color: var(--ck-editor-toolbar-button-on-color);
|
||||
translate: -40% 0;
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
z-index: 1600;
|
||||
}
|
||||
|
||||
:root .ck.ck-toolbar .ck-button:not(.ck-disabled):active,
|
||||
@@ -517,6 +522,10 @@ button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel).ck
|
||||
* EDITOR'S CONTENT
|
||||
*/
|
||||
|
||||
.note-detail-editable-text-editor > .ck-placeholder {
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
/*
|
||||
* Code Blocks
|
||||
*/
|
||||
@@ -638,10 +647,10 @@ html .note-detail-editable-text :not(figure, .include-note, hr):first-child {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.ck-content hr {
|
||||
margin: 5px 0;
|
||||
height: 1px;
|
||||
background-color: var(--main-border-color);
|
||||
:root .ck-content hr {
|
||||
margin-block: 5px;
|
||||
height: 0;
|
||||
border: thin solid var(--main-border-color);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,12 +57,12 @@
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* SEARCH PAGE
|
||||
*/
|
||||
|
||||
/* Button bar */
|
||||
.search-definition-widget .search-setting-table tbody:last-child div {
|
||||
.search-definition-widget .search-setting-table .search-actions-container {
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
}
|
||||
@@ -143,7 +143,7 @@
|
||||
/*
|
||||
* OPTIONS PAGES
|
||||
*/
|
||||
|
||||
|
||||
:root {
|
||||
--options-card-min-width: 500px;
|
||||
--options-card-max-width: 900px;
|
||||
@@ -156,6 +156,10 @@
|
||||
--preferred-max-content-width: var(--options-card-max-width);
|
||||
}
|
||||
|
||||
.note-split.options .collection-properties {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/* Create a gap at the top of the option pages */
|
||||
.note-detail-content-widget-content.options>*:first-child {
|
||||
margin-top: var(--options-first-item-top-margin, 1em);
|
||||
@@ -261,13 +265,6 @@ body.desktop .options-section:not(.tn-no-card) {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.options-section .alert {
|
||||
margin-bottom: 8px;
|
||||
background: var(--alert-bar-background) !important;
|
||||
border-radius: 8px;
|
||||
font-size: .85em;
|
||||
}
|
||||
|
||||
nav.options-section-tabs {
|
||||
min-width: var(--options-card-min-width);
|
||||
max-width: var(--options-card-max-width);
|
||||
@@ -331,4 +328,4 @@ nav.options-section-tabs + .options-section {
|
||||
|
||||
.etapi-options-section div {
|
||||
height: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,13 +40,30 @@ body.mobile {
|
||||
|
||||
/* #region Mica */
|
||||
|
||||
/* Quirk: --background-material is read before "theme-supports-background-effects" class
|
||||
* is applied. Apply the matterial even if the theme doesn't support it. */
|
||||
body.background-effects.platform-win32 {
|
||||
/* Quirk: --background-material is read before "theme-supports-background-effects" class
|
||||
* is applied. Apply the matterial even if the theme doesn't support it. */
|
||||
--background-material: tabbed;
|
||||
&.layout-vertical {
|
||||
--background-material: mica;
|
||||
}
|
||||
|
||||
&.layout-horizontal {
|
||||
--background-material: tabbed;
|
||||
}
|
||||
}
|
||||
|
||||
body.background-effects.theme-supports-background-effects.platform-win32 {
|
||||
body.background-effects.platform-darwin {
|
||||
/** Reference: https://developer.apple.com/documentation/appkit/nsvisualeffectview?preferredLanguage=objc **/
|
||||
&.layout-vertical {
|
||||
--background-material: under-window;
|
||||
}
|
||||
|
||||
&.layout-horizontal {
|
||||
--background-material: hud;
|
||||
}
|
||||
}
|
||||
|
||||
body.background-effects.theme-supports-background-effects {
|
||||
--launcher-pane-horiz-border-color: var(--launcher-pane-horiz-border-color-bgfx);
|
||||
--launcher-pane-horiz-background-color: var(--launcher-pane-horiz-background-color-bgfx);
|
||||
--launcher-pane-vert-background-color: var(--launcher-pane-vert-background-color-bgfx);
|
||||
@@ -56,33 +73,29 @@ body.background-effects.theme-supports-background-effects.platform-win32 {
|
||||
--root-background: transparent;
|
||||
}
|
||||
|
||||
body.background-effects.platform-win32.layout-vertical {
|
||||
--background-material: mica;
|
||||
}
|
||||
|
||||
body.background-effects.theme-supports-background-effects.platform-win32.layout-vertical {
|
||||
body.background-effects.theme-supports-background-effects.layout-vertical {
|
||||
--left-pane-background-color: var(--window-background-color-bgfx);
|
||||
--center-pane-background-color-bgfx: var(--center-pane-vert-layout-background-color-bgfx);
|
||||
--right-pane-background-color: var(--right-pane-background-color-bgfx);
|
||||
}
|
||||
|
||||
body.background-effects.theme-supports-background-effects.platform-win32.layout-horizontal {
|
||||
body.background-effects.theme-supports-background-effects.layout-horizontal {
|
||||
--center-pane-background-color-bgfx: var(--center-pane-horiz-layout-background-color-bgfx);
|
||||
--gutter-color: var(--left-pane-background-color);
|
||||
}
|
||||
|
||||
body.background-effects.theme-supports-background-effects.platform-win32,
|
||||
body.background-effects.theme-supports-background-effects.platform-win32 #root-widget {
|
||||
body.background-effects.theme-supports-background-effects,
|
||||
body.background-effects.theme-supports-background-effects #root-widget {
|
||||
background: var(--window-background-color-bgfx) !important;
|
||||
}
|
||||
|
||||
body.background-effects.theme-supports-background-effects.platform-win32.layout-horizontal #horizontal-main-container,
|
||||
body.background-effects.theme-supports-background-effects.platform-win32.layout-vertical #vertical-main-container {
|
||||
body.background-effects.theme-supports-background-effects.layout-horizontal #horizontal-main-container,
|
||||
body.background-effects.theme-supports-background-effects.layout-vertical #vertical-main-container {
|
||||
background-color: var(--root-background);
|
||||
}
|
||||
|
||||
/* Note split with background effects */
|
||||
body.background-effects.theme-supports-background-effects.platform-win32 #center-pane .note-split.bgfx {
|
||||
body.background-effects.theme-supports-background-effects #center-pane .note-split.bgfx {
|
||||
--note-split-background-color: var(--center-pane-background-color-bgfx);
|
||||
}
|
||||
|
||||
@@ -359,10 +372,6 @@ body[dir=ltr] #launcher-container {
|
||||
.calendar-dropdown-widget .calendar-header [data-calendar-input="month"] {
|
||||
--input-background-color: transparent;
|
||||
--menu-background-color: transparent;
|
||||
|
||||
text-align: center;
|
||||
font-size: 1.4em;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.calendar-dropdown-widget .calendar-header input:not(:focus) {
|
||||
@@ -412,8 +421,6 @@ body[dir=ltr] #launcher-container {
|
||||
}
|
||||
|
||||
.calendar-dropdown-widget .calendar-week span {
|
||||
font-size: 0.85em;
|
||||
font-weight: 500;
|
||||
color: var(--calendar-weekday-labels-color);
|
||||
}
|
||||
|
||||
@@ -676,9 +683,10 @@ body.layout-vertical.background-effects div.quick-search .dropdown-menu {
|
||||
padding-inline-start: 12px;
|
||||
}
|
||||
|
||||
#left-pane span.fancytree-node.fancytree-active {
|
||||
#left-pane span.fancytree-node.fancytree-active,
|
||||
#left-pane span.fancytree-node.fancytree-active:hover {
|
||||
position: relative;
|
||||
background: transparent !important;
|
||||
background: transparent;
|
||||
color: var(--custom-color, var(--left-pane-item-selected-color));
|
||||
}
|
||||
|
||||
@@ -691,6 +699,14 @@ body.layout-vertical.background-effects div.quick-search .dropdown-menu {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* .fancytree-node pseudo-elements:
|
||||
*
|
||||
* - ::before: the active tree item decorator.
|
||||
* - ::after: the selected tree item background. A pseudo-element is used instead of the
|
||||
* element's background color, to allow alpha compositing for the hover state.
|
||||
*/
|
||||
|
||||
#left-pane span.fancytree-node.fancytree-active::before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
@@ -705,6 +721,24 @@ body.layout-vertical.background-effects div.quick-search .dropdown-menu {
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
#left-pane span.fancytree-node.fancytree-selected {
|
||||
--left-pane-item-selected-shadow-size: 4px;
|
||||
|
||||
position: relative;
|
||||
background-color: transparent;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
#left-pane span.fancytree-node.fancytree-selected::after {
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: -2;
|
||||
content: "";
|
||||
inset: 0;
|
||||
background: var(--selection-background-color);
|
||||
animation: left-pane-item-select 100ms ease-out;
|
||||
}
|
||||
|
||||
#left-pane span.fancytree-node.protected > span.fancytree-custom-icon {
|
||||
position: relative;
|
||||
filter: unset !important;
|
||||
@@ -726,39 +760,35 @@ body[dir=rtl] #left-pane span.fancytree-node.protected > span.fancytree-custom-i
|
||||
transform: translateX(-25%);
|
||||
}
|
||||
|
||||
body.mobile .fancytree-expander::before,
|
||||
body.mobile .fancytree-title,
|
||||
body.mobile .fancytree-node > span {
|
||||
font-size: 1rem !important;
|
||||
}
|
||||
|
||||
@media (max-width: 991px) {
|
||||
body.mobile #mobile-sidebar-container {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
body.mobile:not(.force-fixed-tree) #mobile-sidebar-wrapper {
|
||||
body.mobile #mobile-sidebar-wrapper {
|
||||
border-top-right-radius: 12px;
|
||||
border-bottom-right-radius: 12px;
|
||||
border-inline-end: 1px solid var(--subtle-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
#left-pane .fancytree-expander {
|
||||
#left-pane .fancytree-expander,
|
||||
.nested-note-list-item .note-expander {
|
||||
opacity: 0.65;
|
||||
transition: opacity 150ms ease-in;
|
||||
}
|
||||
|
||||
#left-pane .fancytree-expander:hover {
|
||||
#left-pane .fancytree-expander:hover,
|
||||
.nested-note-list-item .note-expander:hover {
|
||||
opacity: 1;
|
||||
transition: opacity 300ms ease-out;
|
||||
}
|
||||
|
||||
#left-pane .fancytree-custom-icon {
|
||||
margin-top: 0; /* Use this to align the icon with the tree view item's caption */
|
||||
color: var(--custom-color, var(--left-pane-icon-color));
|
||||
}
|
||||
|
||||
|
||||
#left-pane span.fancytree-active .fancytree-title {
|
||||
font-weight: normal;
|
||||
}
|
||||
@@ -771,7 +801,8 @@ body.mobile .fancytree-node > span {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#left-pane .tree-item-button {
|
||||
#left-pane .tree-item-button,
|
||||
#left-pane span.fancytree-node.fancytree-selected .fancytree-custom-icon {
|
||||
margin-inline-end: 6px;
|
||||
border: unset;
|
||||
border-radius: 50%;
|
||||
@@ -782,7 +813,8 @@ body.mobile .fancytree-node > span {
|
||||
box-shadow 200ms ease-out;
|
||||
}
|
||||
|
||||
#left-pane .tree-item-button:hover {
|
||||
#left-pane .tree-item-button:hover,
|
||||
#left-pane span.fancytree-node.fancytree-selected .fancytree-custom-icon:hover {
|
||||
background: var(--left-pane-item-action-button-hover-background);
|
||||
box-shadow: var(--left-pane-item-action-button-hover-shadow);
|
||||
transition:
|
||||
@@ -790,10 +822,41 @@ body.mobile .fancytree-node > span {
|
||||
box-shadow 100ms ease-in;
|
||||
}
|
||||
|
||||
#left-pane span.fancytree-node.fancytree-active .tree-item-button:hover {
|
||||
#left-pane span.fancytree-node.fancytree-active .tree-item-button:hover,
|
||||
#left-pane span.fancytree-node.fancytree-active.fancytree-selected .fancytree-custom-icon:hover {
|
||||
box-shadow: var(--left-pane-item-selected-action-button-hover-shadow);
|
||||
}
|
||||
|
||||
/* Selected item bulk action button */
|
||||
|
||||
@keyframes bulk-action-button-blink {
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
opacity: .3;
|
||||
}
|
||||
}
|
||||
|
||||
#left-pane span.fancytree-node.fancytree-selected .fancytree-custom-icon {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#left-pane span.fancytree-node.fancytree-selected .fancytree-custom-icon::before {
|
||||
border: 0;
|
||||
font-size: .65em;
|
||||
}
|
||||
|
||||
#left-pane span.fancytree-node.fancytree-selected:hover .fancytree-custom-icon:not(:hover)::before {
|
||||
animation: bulk-action-button-blink 500ms linear infinite alternate;
|
||||
}
|
||||
|
||||
#left-pane span.fancytree-node.fancytree-selected.protected .fancytree-custom-icon::after {
|
||||
/* Protected note indicator */
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
#context-menu-container {
|
||||
/* The context menu of the tree */
|
||||
--menu-item-icon-vert-offset: -1px;
|
||||
@@ -1024,7 +1087,7 @@ body.layout-vertical.electron.platform-darwin .tab-row-container {
|
||||
height: var(--tab-height) !important;
|
||||
}
|
||||
|
||||
.tab-row-widget > * {
|
||||
body.layout-vertical .tab-row-widget > * {
|
||||
margin-top: calc((var(--tab-bar-height) - var(--tab-height)) / 2);
|
||||
}
|
||||
|
||||
@@ -1054,7 +1117,7 @@ body.layout-horizontal .tab-row-widget-container {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
body.desktop:not(.background-effects.platform-win32) #root-widget.horizontal-layout {
|
||||
body.desktop:not(.background-effects) #root-widget.horizontal-layout {
|
||||
background-color: var(--root-background) !important;
|
||||
}
|
||||
|
||||
@@ -1259,7 +1322,7 @@ body.layout-horizontal #rest-pane > .classic-toolbar-widget {
|
||||
#center-pane .note-split {
|
||||
padding-top: 2px;
|
||||
background-color: var(--note-split-background-color, var(--main-background-color));
|
||||
transition: border-color 250ms ease-in;
|
||||
transition: border-color 150ms ease-out;
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
@@ -1309,7 +1372,7 @@ body.mobile .note-title {
|
||||
margin-inline-start: 0;
|
||||
}
|
||||
|
||||
.title-row {
|
||||
body.desktop .title-row {
|
||||
/* Aligns the "Create new split" button with the note menu button (the three dots button) */
|
||||
padding-inline-end: 3px;
|
||||
}
|
||||
|
||||
@@ -140,10 +140,22 @@ ul.fancytree-container {
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
|
||||
.fancytree-custom-icon {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
/* Fallback icon */
|
||||
:where(.fancytree-custom-icon)::before {
|
||||
content: "?";
|
||||
}
|
||||
|
||||
/* Protected note icon badge */
|
||||
span.fancytree-node.protected > span.fancytree-custom-icon {
|
||||
filter: drop-shadow(2px 2px 2px var(--main-text-color));
|
||||
}
|
||||
@@ -185,7 +197,7 @@ span.fancytree-node.fancytree-active-clone:not(.fancytree-active) .fancytree-tit
|
||||
|
||||
span.fancytree-active {
|
||||
color: var(--active-item-text-color);
|
||||
background-color: var(--active-item-background-color) !important;
|
||||
background-color: var(--active-item-background-color);
|
||||
border-color: transparent; /* invisible border */
|
||||
border-radius: 5px;
|
||||
}
|
||||
@@ -195,19 +207,15 @@ span.fancytree-active .fancytree-title {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
span.fancytree-selected {
|
||||
border-color: var(--main-border-color) !important;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
span.fancytree-selected .fancytree-title {
|
||||
text-decoration: underline;
|
||||
font-style: italic;
|
||||
span.fancytree-node.fancytree-selected {
|
||||
background-color: var(--selection-background-color);
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
span.fancytree-selected .fancytree-custom-icon::before {
|
||||
content: "\eb43";
|
||||
border: 1px solid var(--main-border-color);
|
||||
font-family: "boxicons";
|
||||
content: "\ef05";
|
||||
border: 1px solid var(--main-text-color);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,9 @@
|
||||
"widget-render-error": {
|
||||
"title": "فشل عرض عنصر واجهة مستخدم React مخصص"
|
||||
},
|
||||
"widget-missing-parent": "لا تحتوي الأداة المخصصة على خاصية إلزامية '{{property}}'.\n\nإذا كان من المفترض تشغيل هذا البرنامج النصي بدون عنصر واجهة مستخدم، فاستخدم '#run=frontendStartup' بدلاً من ذلك."
|
||||
"widget-missing-parent": "لا تحتوي الأداة المخصصة على خاصية إلزامية '{{property}}'.\n\nإذا كان من المفترض تشغيل هذا البرنامج النصي بدون عنصر واجهة مستخدم، فاستخدم '#run=frontendStartup' بدلاً من ذلك.",
|
||||
"open-script-note": "فتح ملاحظة برمجية",
|
||||
"scripting-error": "خطأ في النص البرمجي المخصص: {{title}}"
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "أضافة رابط",
|
||||
@@ -37,14 +39,19 @@
|
||||
"search_note": "البحث عن الملاحظة بالاسم",
|
||||
"link_title": "عنوان الرابط",
|
||||
"button_add_link": "اضافة رابط",
|
||||
"help_on_links": "مساعدة حول الارتباطات التشعبية"
|
||||
"help_on_links": "مساعدة حول الارتباطات التشعبية",
|
||||
"link_title_mirrors": "عنوان الرابط يعكس العنوان الحالي للملاحظة",
|
||||
"link_title_arbitrary": "يمكن تغيير عنوان الرابط حسب الرغبة"
|
||||
},
|
||||
"branch_prefix": {
|
||||
"edit_branch_prefix": "تعديل بادئة الفرع",
|
||||
"prefix": "البادئة: ",
|
||||
"save": "حفظ",
|
||||
"help_on_tree_prefix": "مساعدة حول بادئة الشجرة",
|
||||
"branch_prefix_saved": "تم حفظ بادئة الفرع."
|
||||
"branch_prefix_saved": "تم حفظ بادئة الفرع.",
|
||||
"edit_branch_prefix_multiple": "تعديل البادئة لـ {{count}} من تفرعات الملاحظات",
|
||||
"branch_prefix_saved_multiple": "تم حفظ بادئة التفرع لـ {{count}} من التفرعات.",
|
||||
"affected_branches": "الفروع المتأثرة ({{count}}):"
|
||||
},
|
||||
"bulk_actions": {
|
||||
"bulk_actions": "اجراءات جماعية",
|
||||
@@ -559,113 +566,6 @@
|
||||
"enable-smooth-scroll": "تمكين التمرير السلس",
|
||||
"enable-motion": "تمكين الانتقالات والرسوم المتحركة"
|
||||
},
|
||||
"ai_llm": {
|
||||
"progress": "تقدم",
|
||||
"openai_tab": "OpenAI",
|
||||
"actions": "أجراءات",
|
||||
"retry": "أعد المحاولة",
|
||||
"reprocessing_index": "جار اعادة البناء...",
|
||||
"never": "ابدٱ",
|
||||
"agent": {
|
||||
"processing": "جار المعالجة...",
|
||||
"thinking": "جار التفكير...",
|
||||
"loading": "جار التحميل...",
|
||||
"generating": "جار الانشاء..."
|
||||
},
|
||||
"name": "الذكاء الأصطناعي",
|
||||
"openai": "OpenAI",
|
||||
"sources": "مصادر",
|
||||
"temperature": "درجة الحرارة",
|
||||
"model": "نموذج",
|
||||
"refreshing_models": "جار التحديث...",
|
||||
"error": "خطأ",
|
||||
"refreshing": "جار التحديث...",
|
||||
"ollama_tab": "Ollama",
|
||||
"anthropic_tab": "انتروبيك",
|
||||
"not_started": "لم يبدأ بعد",
|
||||
"title": "اعدادات AI",
|
||||
"processed_notes": "الملاحظات المعالجة",
|
||||
"total_notes": "الملاحظات الكلية",
|
||||
"queued_notes": "الملاحظات في قائمة الانتظار",
|
||||
"failed_notes": "الملاحظات الفاشلة",
|
||||
"last_processed": "اخر معالجة",
|
||||
"refresh_stats": "تحديث الاحصائيات",
|
||||
"voyage_tab": "استكشاف AI",
|
||||
"provider_precedence": "اولوية المزود",
|
||||
"system_prompt": "موجه النظام",
|
||||
"openai_configuration": "اعدادات OpenAI",
|
||||
"openai_settings": "اعدادات OpenAI",
|
||||
"api_key": "مفتاح واجهة برمجة التطبيقات",
|
||||
"url": "عنوان URL الاساسي",
|
||||
"default_model": "النموذج الافتراضي",
|
||||
"base_url": "عنوان URL الأساسي",
|
||||
"openai_url_description": "افتراضيا: https://api.openai.com/v1",
|
||||
"anthropic_settings": "اعدادات انتروبيك",
|
||||
"ollama_settings": "اعدادات Ollama",
|
||||
"anthropic_configuration": "تهيئة انتروبيك",
|
||||
"voyage_url_description": "افتراضيا: https://api.voyageai.com/v1",
|
||||
"ollama_configuration": "تهيئة Ollama",
|
||||
"enable_ollama": "تمكين Ollama",
|
||||
"last_attempt": "اخر محاولة",
|
||||
"active_providers": "المزودون النشطون",
|
||||
"disabled_providers": "المزودون المعطلون",
|
||||
"similarity_threshold": "عتبة التشابه",
|
||||
"complete": "اكتمل (100%)",
|
||||
"ai_settings": "اعدادات AI",
|
||||
"show_thinking": "عرض التفكير",
|
||||
"index_status": "حالة الفهرس",
|
||||
"indexed_notes": "الملاحظات المفهرسة",
|
||||
"indexing_stopped": "تم ايقاف الفهرسة",
|
||||
"last_indexed": "اخر فهرسة",
|
||||
"note_chat": "دردشة الملاحظة",
|
||||
"start_indexing": "بدء الفهرسة",
|
||||
"chat": {
|
||||
"root_note_title": "دردشات AI",
|
||||
"new_chat_title": "دردشة جديدة",
|
||||
"create_new_ai_chat": "انشاء دردشة AI جديدة"
|
||||
},
|
||||
"selected_provider": "المزود المحدد",
|
||||
"select_model": "اختر النموذج...",
|
||||
"select_provider": "اختر المزود...",
|
||||
"ollama_model": "نموذج Ollama",
|
||||
"refresh_models": "تحديث النماذج",
|
||||
"rebuild_index": "اعادة بناء الفهرس",
|
||||
"note_title": "عنوان الملاحظة",
|
||||
"processing": "جاري المعالجة ({{percentage}}%)",
|
||||
"incomplete": "غير مكتمل ({{percentage}}%)",
|
||||
"ollama_url": "عنوان URL الخاص ب Ollama",
|
||||
"provider_configuration": "تكوين موفر AI",
|
||||
"voyage_settings": "استكشاف اعدادات AI",
|
||||
"enable_automatic_indexing": "تمكين الفهرسة التلقائية",
|
||||
"index_rebuild_progress": "تقدم اعادة انشاء الفهرس",
|
||||
"index_rebuild_complete": "اكتملت عملية تحسين الفهرس",
|
||||
"use_enhanced_context": "استخدام السياق المحسن",
|
||||
"enter_message": "ادخل رسالتك...",
|
||||
"index_all_notes": "فهرسة جميع الملاحظات",
|
||||
"indexing_in_progress": "جار فهرسة الملاحظات...",
|
||||
"use_advanced_context": "استخدم السياق المتقدم",
|
||||
"ai_enabled": "تمكين مميزات AI",
|
||||
"ai_disabled": "الغاء تمكين مميزات AI",
|
||||
"enable_ai_features": "تمكين خصائص AI/LLM",
|
||||
"enable_ai": "تمكين خصائص AI/LLM",
|
||||
"reprocess_index": "اعادة بناء فهرس البحث",
|
||||
"index_rebuilding": "جار تحسين الفهرس {{percentage}}",
|
||||
"voyage_configuration": "اعدادت Voyage AI",
|
||||
"openai_model_description": "الامثلة: gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
|
||||
"partial": "{{ percentage }} % مكتمل",
|
||||
"retry_queued": "تم جدولة الملاحظة لاعادة المحاولة",
|
||||
"max_notes_per_llm_query": "اكبر عدد للملاحظات لكل استعلام",
|
||||
"remove_provider": "احذف المزود من البحث",
|
||||
"restore_provider": "استعادة المزود الى البحث",
|
||||
"reprocess_index_error": "حدث خطأ اثناء اعادة بناء فهرس البحث",
|
||||
"auto_refresh_notice": "تحديث تلقائي كل {{seconds}} ثانية",
|
||||
"note_queued_for_retry": "الملاحظة جاهزة لاعادة المحاولة لاحقا",
|
||||
"failed_to_retry_note": "فشل في اعادة محاولة معالجة المحاولة",
|
||||
"failed_to_retry_all": "فشل في اعادة محاولة معالجة الملاحظة",
|
||||
"error_generating_response": "فشل في توليد استجابة من ال AI",
|
||||
"create_new_ai_chat": "انشاء دردشة AI جديدة",
|
||||
"error_fetching": "فشل في استرجاع النماذج: {{error}}"
|
||||
},
|
||||
"code_auto_read_only_size": {
|
||||
"unit": "حروف",
|
||||
"title": "الحجم التلقائي للقراءه فقط"
|
||||
@@ -903,13 +803,13 @@
|
||||
"web-view": "عرض الويب",
|
||||
"mind-map": "خريطة ذهنية",
|
||||
"geo-map": "خريطة جغرافية",
|
||||
"ai-chat": "دردشة AI",
|
||||
"task-list": "قائمة المهام"
|
||||
"task-list": "قائمة المهام",
|
||||
"spreadsheet": "جدول البيانات"
|
||||
},
|
||||
"shared_switch": {
|
||||
"shared": "مشترك",
|
||||
"toggle-on-title": "مشاركة الملاحظة",
|
||||
"toggle-off-title": "الغاء مشاركة الملاحظة"
|
||||
"toggle-off-title": "إلغاء مشاركة الملاحظة"
|
||||
},
|
||||
"template_switch": {
|
||||
"template": "قالب"
|
||||
@@ -983,6 +883,7 @@
|
||||
"electron_context_menu": {
|
||||
"cut": "قص",
|
||||
"copy": "نسخ",
|
||||
"copy-as-markdown": "نسخ كـ Markdown",
|
||||
"paste": "لصق",
|
||||
"copy-link": "نسخ الرابط",
|
||||
"add-term-to-dictionary": "اضافة \"{{term}}\" الى القاموس",
|
||||
@@ -1168,14 +1069,10 @@
|
||||
"rename_note": "اعادة تسمية الملاحظة",
|
||||
"remove_relation": "حذف العلاقة",
|
||||
"default_new_note_title": "ملاحظة جديدة",
|
||||
"open_in_new_tab": "فتح في تبويب جديد",
|
||||
"enter_new_title": "ادخل عنوان ملاحظة جديدة:",
|
||||
"note_not_found": "الملاحظة {{noteId}} غير موجودة!",
|
||||
"cannot_match_transform": "تعذر مطابقة التحويل: {{transform}}"
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "عرض الويب"
|
||||
},
|
||||
"consistency_checks": {
|
||||
"title": "فحوصات التناسق"
|
||||
},
|
||||
@@ -1389,8 +1286,10 @@
|
||||
"search-for": "بحث ل \"{{term}}\""
|
||||
},
|
||||
"protect_note": {
|
||||
"toggle-off": "ازالة الحماية عن الملاحظة",
|
||||
"toggle-on": "حماية الملاحظة"
|
||||
"toggle-off": "إزالة الحماية عن الملاحظة",
|
||||
"toggle-on": "حماية الملاحظة",
|
||||
"toggle-on-hint": "الملاحظة غير محمة، انقر لحمايتها",
|
||||
"toggle-off-hint": "الملاحظة محمية، انقر لإزالة الحماية منها"
|
||||
},
|
||||
"open-help-page": "فتح صفحة المساعدة",
|
||||
"empty": {
|
||||
|
||||
@@ -93,7 +93,10 @@
|
||||
"digits": "dígits",
|
||||
"inheritable": "Heretable",
|
||||
"delete": "Suprimeix",
|
||||
"color_type": "Color"
|
||||
"color_type": "Color",
|
||||
"textarea": "Text multi linia",
|
||||
"date_time": "Data i hora",
|
||||
"precision_title": "Quants dígits han d'estar disponibles per a coma flotant a la interfície de configuració."
|
||||
},
|
||||
"rename_label": {
|
||||
"to": "Per"
|
||||
|
||||
@@ -446,7 +446,8 @@
|
||||
"and_more": "... 以及另外 {{count}} 个。",
|
||||
"print_landscape": "导出为 PDF 时,将页面方向更改为横向而不是纵向。",
|
||||
"print_page_size": "导出为 PDF 时,更改页面大小。支持的值:<code>A0</code>、<code>A1</code>、<code>A2</code>、<code>A3</code>、<code>A4</code>、<code>A5</code>、<code>A6</code>、<code>Legal</code>、<code>Letter</code>、<code>Tabloid</code>、<code>Ledger</code>。",
|
||||
"color_type": "颜色"
|
||||
"color_type": "颜色",
|
||||
"textarea": "多行文本"
|
||||
},
|
||||
"attribute_editor": {
|
||||
"help_text_body1": "要添加标签,只需输入例如 <code>#rock</code> 或者如果您还想添加值,则例如 <code>#year = 2020</code>",
|
||||
@@ -662,7 +663,8 @@
|
||||
"show-cheatsheet": "显示快捷帮助",
|
||||
"toggle-zen-mode": "禅模式",
|
||||
"new-version-available": "新更新可用",
|
||||
"download-update": "取得版本 {{latestVersion}}"
|
||||
"download-update": "取得版本 {{latestVersion}}",
|
||||
"search_notes": "搜索笔记"
|
||||
},
|
||||
"zen_mode": {
|
||||
"button_exit": "退出禅模式"
|
||||
@@ -707,7 +709,8 @@
|
||||
"advanced": "高级",
|
||||
"export_as_image": "导出为图像",
|
||||
"export_as_image_png": "PNG(栅格)",
|
||||
"export_as_image_svg": "SVG(矢量图)"
|
||||
"export_as_image_svg": "SVG(矢量图)",
|
||||
"view_ocr_text": "查看 OCR 文本"
|
||||
},
|
||||
"onclick_button": {
|
||||
"no_click_handler": "按钮组件'{{componentId}}'没有定义点击处理程序"
|
||||
@@ -745,7 +748,7 @@
|
||||
"button_title": "导出SVG格式图片"
|
||||
},
|
||||
"relation_map_buttons": {
|
||||
"create_child_note_title": "创建新的子笔记并添加到关系图",
|
||||
"create_child_note_title": "创建子笔记并添加到图",
|
||||
"reset_pan_zoom_title": "重置平移和缩放到初始坐标和放大倍率",
|
||||
"zoom_in_title": "放大",
|
||||
"zoom_out_title": "缩小"
|
||||
@@ -759,7 +762,9 @@
|
||||
"delete_this_note": "删除此笔记",
|
||||
"error_cannot_get_branch_id": "无法获取 notePath '{{notePath}}' 的 branchId",
|
||||
"error_unrecognized_command": "无法识别的命令 {{command}}",
|
||||
"note_revisions": "笔记历史版本"
|
||||
"note_revisions": "笔记历史版本",
|
||||
"backlinks": "反链",
|
||||
"content_language_switcher": "内容语言: {{language}}"
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "更改笔记图标",
|
||||
@@ -910,7 +915,8 @@
|
||||
"unknown_search_option": "未知的搜索选项 {{searchOptionName}}",
|
||||
"search_note_saved": "搜索笔记已保存到 {{- notePathTitle}}",
|
||||
"actions_executed": "操作已执行。",
|
||||
"view_options": "查看选项:"
|
||||
"view_options": "查看选项:",
|
||||
"option": "选项"
|
||||
},
|
||||
"similar_notes": {
|
||||
"title": "相似笔记",
|
||||
@@ -1004,7 +1010,7 @@
|
||||
"no_attachments": "此笔记没有附件。"
|
||||
},
|
||||
"book": {
|
||||
"no_children_help": "此类型为书籍的笔记没有任何子笔记,因此没有内容显示。请参阅 <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> 了解详情。",
|
||||
"no_children_help": "此集合没有任何子笔记,因此没有内容显示。",
|
||||
"drag_locked_title": "锁定编辑",
|
||||
"drag_locked_message": "无法拖拽,因为集合已被锁定编辑。"
|
||||
},
|
||||
@@ -1043,7 +1049,6 @@
|
||||
"unprotecting-title": "解除保护状态"
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "在新标签页中打开",
|
||||
"remove_note": "删除笔记",
|
||||
"edit_title": "编辑标题",
|
||||
"rename_note": "重命名笔记",
|
||||
@@ -1060,15 +1065,6 @@
|
||||
"default_new_note_title": "新笔记",
|
||||
"click_on_canvas_to_place_new_note": "点击画布以放置新笔记"
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_1": "之所以显示此帮助说明,是因为这个类型为渲染 HTML 的笔记没有正常工作所需的关系。",
|
||||
"note_detail_render_help_2": "渲染 HTML 笔记类型用于<a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">编写脚本</a>。简而言之,您有一份 HTML 代码笔记(可包含一些 JavaScript),然后这个笔记会把页面渲染出来。要使其正常工作,您需要定义一个名为 \"renderNote\" 的<a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">关系</a>指向要渲染的 HTML 笔记。"
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "网页视图",
|
||||
"embed_websites": "网页视图类型的笔记允许您将网站嵌入到 Trilium 中。",
|
||||
"create_label": "首先,请创建一个带有您要嵌入的 URL 地址的标签,例如 #webViewSrc=\"https://www.bing.com\""
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "刷新"
|
||||
},
|
||||
@@ -1202,12 +1198,28 @@
|
||||
},
|
||||
"images": {
|
||||
"images_section_title": "图片",
|
||||
"download_images_automatically": "自动下载图片以供离线使用。",
|
||||
"download_images_description": "粘贴的 HTML 可能包含在线图片的引用,Trilium 会找到这些引用并下载图片,以便它们可以离线使用。",
|
||||
"enable_image_compression": "启用图片压缩",
|
||||
"max_image_dimensions": "图片的最大宽度/高度(超过此限制的图像将会被缩放)。",
|
||||
"jpeg_quality_description": "JPEG 质量(10 - 最差质量,100 最佳质量,建议为 50 - 85)",
|
||||
"max_image_dimensions_unit": "像素"
|
||||
"download_images_automatically": "自动下载图片",
|
||||
"download_images_description": "从粘贴的 HTML 代码中下载引用的在线图片,以便离线使用。",
|
||||
"enable_image_compression": "图片压缩",
|
||||
"max_image_dimensions": "最大图像尺寸",
|
||||
"jpeg_quality_description": "建议范围为 50–85。较低的值可以减小文件大小,较高的值可以保留细节。",
|
||||
"max_image_dimensions_unit": "像素",
|
||||
"enable_image_compression_description": "上传或粘贴图片时,对其进行压缩和调整大小。",
|
||||
"max_image_dimensions_description": "超过此尺寸的图片将自动调整大小。",
|
||||
"jpeg_quality": "JPEG质量",
|
||||
"ocr_section_title": "文本提取(OCR)",
|
||||
"ocr_related_content_languages": "内容语言(用于文本提取)",
|
||||
"ocr_auto_process": "自动处理新文件",
|
||||
"ocr_auto_process_description": "自动从新上传或粘贴的文件中提取文本。",
|
||||
"ocr_min_confidence": "最低置信度",
|
||||
"ocr_confidence_description": "仅提取置信度高于此阈值的文本。较低的置信度阈值会包含更多文本,但可能准确性较低。",
|
||||
"batch_ocr_title": "处理现有文件",
|
||||
"batch_ocr_description": "从笔记中的所有现有图像、PDF 和 Office 文档中提取文本。这可能需要一些时间,具体取决于文件数量。",
|
||||
"batch_ocr_start": "开始批量处理",
|
||||
"batch_ocr_starting": "开始批量处理...",
|
||||
"batch_ocr_progress": "正在处理 {{processed}} 个文件,共 {{total}} 个文件...",
|
||||
"batch_ocr_completed": "批量处理完成!已处理 {{processed}} 个文件。",
|
||||
"batch_ocr_error": "批量处理过程中出错:{{error}}"
|
||||
},
|
||||
"attachment_erasure_timeout": {
|
||||
"attachment_erasure_timeout": "附件清理超时",
|
||||
@@ -1417,7 +1429,8 @@
|
||||
"description": "描述",
|
||||
"reload_app": "重载应用以应用更改",
|
||||
"set_all_to_default": "将所有快捷键重置为默认值",
|
||||
"confirm_reset": "您确定要将所有键盘快捷键重置为默认值吗?"
|
||||
"confirm_reset": "您确定要将所有键盘快捷键重置为默认值吗?",
|
||||
"no_results": "未找到与“{{filter}}”匹配的快捷方式"
|
||||
},
|
||||
"spellcheck": {
|
||||
"title": "拼写检查",
|
||||
@@ -1536,10 +1549,12 @@
|
||||
"geo-map": "地理地图",
|
||||
"beta-feature": "测试版",
|
||||
"task-list": "任务列表",
|
||||
"ai-chat": "AI聊天",
|
||||
"new-feature": "新建",
|
||||
"collections": "集合",
|
||||
"book": "集合"
|
||||
"book": "集合",
|
||||
"ai-chat": "AI对话",
|
||||
"spreadsheet": "电子表格",
|
||||
"llm-chat": "AI对话"
|
||||
},
|
||||
"protect_note": {
|
||||
"toggle-on": "保护笔记",
|
||||
@@ -1618,7 +1633,9 @@
|
||||
"print_report_title": "打印报告",
|
||||
"print_report_collection_content_other": "集合中的 {{count}} 篇笔记无法打印,因为它们不受支持或受到保护。",
|
||||
"print_report_collection_details_button": "查看详情",
|
||||
"print_report_collection_details_ignored_notes": "忽略的笔记"
|
||||
"print_report_collection_details_ignored_notes": "忽略的笔记",
|
||||
"print_report_error_title": "打印失败",
|
||||
"print_report_stack_trace": "堆栈跟踪"
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "请输入笔记标题...",
|
||||
@@ -1633,7 +1650,8 @@
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "没有找到符合搜索条件的笔记。",
|
||||
"search_not_executed": "尚未执行搜索。请点击上方的\"搜索\"按钮查看结果。"
|
||||
"search_not_executed": "尚未执行搜索。",
|
||||
"search_now": "立即搜索"
|
||||
},
|
||||
"spacer": {
|
||||
"configure_launchbar": "配置启动栏"
|
||||
@@ -1761,6 +1779,7 @@
|
||||
"add-term-to-dictionary": "将 \"{{term}}\" 添加到字典",
|
||||
"cut": "剪切",
|
||||
"copy": "复制",
|
||||
"copy-as-markdown": "复制为 Markdown",
|
||||
"copy-link": "复制链接",
|
||||
"paste": "粘贴",
|
||||
"paste-as-plain-text": "以纯文本粘贴",
|
||||
@@ -1782,8 +1801,8 @@
|
||||
"desktop-application": "桌面应用程序",
|
||||
"native-title-bar": "原生标题栏",
|
||||
"native-title-bar-description": "对于 Windows 和 macOS,关闭原生标题栏可使应用程序看起来更紧凑。在 Linux 上,保留原生标题栏可以更好地与系统集成。",
|
||||
"background-effects": "启用背景效果(仅适用于 Windows 11)",
|
||||
"background-effects-description": "Mica 效果为应用窗口添加模糊且时尚的背景,营造出深度感和现代外观。「原生标题栏」必須被禁用。",
|
||||
"background-effects": "启用背景效果",
|
||||
"background-effects-description": "为应用窗口添加模糊且时尚的背景,营造出深度感和现代外观。「原生标题栏」必須被禁用。",
|
||||
"restart-app-button": "重启应用程序以查看更改",
|
||||
"zoom-factor": "缩放系数"
|
||||
},
|
||||
@@ -1802,7 +1821,8 @@
|
||||
"geo-map": {
|
||||
"create-child-note-title": "创建一个新的子笔记并将其添加到地图中",
|
||||
"create-child-note-instruction": "单击地图以在该位置创建新笔记,或按 Escape 以取消。",
|
||||
"unable-to-load-map": "无法加载地图。"
|
||||
"unable-to-load-map": "无法加载地图。",
|
||||
"create-child-note-text": "添加标记"
|
||||
},
|
||||
"geo-map-context": {
|
||||
"open-location": "打开位置",
|
||||
@@ -1840,149 +1860,6 @@
|
||||
"yesterday": "昨天"
|
||||
}
|
||||
},
|
||||
"ai_llm": {
|
||||
"not_started": "未开始",
|
||||
"title": "AI设置",
|
||||
"processed_notes": "已处理笔记",
|
||||
"total_notes": "笔记总数",
|
||||
"progress": "进度",
|
||||
"queued_notes": "排队中笔记",
|
||||
"failed_notes": "失败笔记",
|
||||
"last_processed": "最后处理时间",
|
||||
"refresh_stats": "刷新统计数据",
|
||||
"enable_ai_features": "启用AI/LLM功能",
|
||||
"enable_ai_description": "启用笔记摘要、内容生成等AI功能及其他LLM能力",
|
||||
"openai_tab": "OpenAI",
|
||||
"anthropic_tab": "Anthropic",
|
||||
"voyage_tab": "Voyage AI",
|
||||
"ollama_tab": "Ollama",
|
||||
"enable_ai": "启用AI/LLM功能",
|
||||
"enable_ai_desc": "启用笔记摘要、内容生成等AI功能及其他LLM能力",
|
||||
"provider_configuration": "AI提供商配置",
|
||||
"provider_precedence": "提供商优先级",
|
||||
"provider_precedence_description": "按优先级排序的提供商列表(用逗号分隔,例如:'openai,anthropic,ollama')",
|
||||
"temperature": "温度参数",
|
||||
"temperature_description": "控制响应的随机性(0 = 确定性输出,2 = 最大随机性)",
|
||||
"system_prompt": "系统提示词",
|
||||
"system_prompt_description": "所有AI交互使用的默认系统提示词",
|
||||
"openai_configuration": "OpenAI配置",
|
||||
"openai_settings": "OpenAI设置",
|
||||
"api_key": "API密钥",
|
||||
"url": "基础URL",
|
||||
"model": "模型",
|
||||
"openai_api_key_description": "用于访问OpenAI服务的API密钥",
|
||||
"anthropic_api_key_description": "用于访问Claude模型的Anthropic API密钥",
|
||||
"default_model": "默认模型",
|
||||
"openai_model_description": "示例:gpt-4o、gpt-4-turbo、gpt-3.5-turbo",
|
||||
"base_url": "基础URL",
|
||||
"openai_url_description": "默认:https://api.openai.com/v1",
|
||||
"anthropic_settings": "Anthropic设置",
|
||||
"anthropic_url_description": "Anthropic API的基础URL(默认:https://api.anthropic.com)",
|
||||
"anthropic_model_description": "用于聊天补全的Anthropic Claude模型",
|
||||
"voyage_settings": "Voyage AI设置",
|
||||
"ollama_settings": "Ollama设置",
|
||||
"ollama_url_description": "Ollama API的URL(默认:http://localhost:11434)",
|
||||
"ollama_model_description": "用于聊天补全的 Ollama 模型",
|
||||
"anthropic_configuration": "Anthropic配置",
|
||||
"voyage_configuration": "Voyage AI配置",
|
||||
"voyage_url_description": "默认:https://api.voyageai.com/v1",
|
||||
"ollama_configuration": "Ollama配置",
|
||||
"enable_ollama": "启用Ollama",
|
||||
"enable_ollama_description": "启用Ollama以使用本地AI模型",
|
||||
"ollama_url": "Ollama URL",
|
||||
"ollama_model": "Ollama模型",
|
||||
"refresh_models": "刷新模型",
|
||||
"refreshing_models": "刷新中...",
|
||||
"enable_automatic_indexing": "启用自动索引",
|
||||
"rebuild_index": "重建索引",
|
||||
"rebuild_index_error": "启动索引重建失败。请查看日志了解详情。",
|
||||
"note_title": "笔记标题",
|
||||
"error": "错误",
|
||||
"last_attempt": "最后尝试时间",
|
||||
"actions": "操作",
|
||||
"retry": "重试",
|
||||
"partial": "{{ percentage }}% 已完成",
|
||||
"retry_queued": "笔记已加入重试队列",
|
||||
"retry_failed": "笔记加入重试队列失败",
|
||||
"max_notes_per_llm_query": "每次查询的最大笔记数",
|
||||
"max_notes_per_llm_query_description": "AI上下文包含的最大相似笔记数量",
|
||||
"active_providers": "活跃提供商",
|
||||
"disabled_providers": "已禁用提供商",
|
||||
"remove_provider": "从搜索中移除提供商",
|
||||
"restore_provider": "将提供商恢复到搜索中",
|
||||
"similarity_threshold": "相似度阈值",
|
||||
"similarity_threshold_description": "纳入LLM查询上下文的笔记最低相似度分数(0-1)",
|
||||
"reprocess_index": "重建搜索索引",
|
||||
"reprocessing_index": "重建中...",
|
||||
"reprocess_index_started": "搜索索引优化已在后台启动",
|
||||
"reprocess_index_error": "重建搜索索引失败",
|
||||
"index_rebuild_progress": "索引重建进度",
|
||||
"index_rebuilding": "正在优化索引({{percentage}}%)",
|
||||
"index_rebuild_complete": "索引优化完成",
|
||||
"index_rebuild_status_error": "检查索引重建状态失败",
|
||||
"never": "从未",
|
||||
"processing": "处理中({{percentage}}%)",
|
||||
"incomplete": "未完成({{percentage}}%)",
|
||||
"complete": "已完成(100%)",
|
||||
"refreshing": "刷新中...",
|
||||
"auto_refresh_notice": "每 {{seconds}} 秒自动刷新",
|
||||
"note_queued_for_retry": "笔记已加入重试队列",
|
||||
"failed_to_retry_note": "重试笔记失败",
|
||||
"all_notes_queued_for_retry": "所有失败笔记已加入重试队列",
|
||||
"failed_to_retry_all": "重试笔记失败",
|
||||
"ai_settings": "AI设置",
|
||||
"api_key_tooltip": "用于访问服务的API密钥",
|
||||
"empty_key_warning": {
|
||||
"anthropic": "Anthropic API密钥为空。请输入有效的API密钥。",
|
||||
"openai": "OpenAI API密钥为空。请输入有效的API密钥。",
|
||||
"voyage": "Voyage API密钥为空。请输入有效的API密钥。",
|
||||
"ollama": "Ollama API密钥为空。请输入有效的API密钥。"
|
||||
},
|
||||
"agent": {
|
||||
"processing": "处理中...",
|
||||
"thinking": "思考中...",
|
||||
"loading": "加载中...",
|
||||
"generating": "生成中..."
|
||||
},
|
||||
"name": "AI",
|
||||
"openai": "OpenAI",
|
||||
"use_enhanced_context": "使用增强上下文",
|
||||
"enhanced_context_description": "为AI提供来自笔记及其相关笔记的更多上下文,以获得更好的响应",
|
||||
"show_thinking": "显示思考过程",
|
||||
"show_thinking_description": "显示AI的思维链过程",
|
||||
"enter_message": "输入你的消息...",
|
||||
"error_contacting_provider": "联系AI提供商失败。请检查你的设置和网络连接。",
|
||||
"error_generating_response": "生成AI响应失败",
|
||||
"index_all_notes": "为所有笔记建立索引",
|
||||
"index_status": "索引状态",
|
||||
"indexed_notes": "已索引笔记",
|
||||
"indexing_stopped": "索引已停止",
|
||||
"indexing_in_progress": "索引进行中...",
|
||||
"last_indexed": "最后索引时间",
|
||||
"note_chat": "笔记聊天",
|
||||
"sources": "来源",
|
||||
"start_indexing": "开始索引",
|
||||
"use_advanced_context": "使用高级上下文",
|
||||
"ollama_no_url": "Ollama 未配置。请输入有效的URL。",
|
||||
"chat": {
|
||||
"root_note_title": "AI聊天记录",
|
||||
"root_note_content": "此笔记包含你保存的AI聊天对话。",
|
||||
"new_chat_title": "新聊天",
|
||||
"create_new_ai_chat": "创建新的AI聊天"
|
||||
},
|
||||
"create_new_ai_chat": "创建新的AI聊天",
|
||||
"configuration_warnings": "你的AI配置存在一些问题。请检查你的设置。",
|
||||
"experimental_warning": "LLM功能目前处于实验阶段 - 特此提醒。",
|
||||
"selected_provider": "已选提供商",
|
||||
"selected_provider_description": "选择用于聊天和补全功能的AI提供商",
|
||||
"select_model": "选择模型...",
|
||||
"select_provider": "选择提供商...",
|
||||
"ai_enabled": "已启用 AI 功能",
|
||||
"ai_disabled": "已禁用 AI 功能",
|
||||
"no_models_found_online": "找不到模型。请检查您的 API 密钥及设置。",
|
||||
"no_models_found_ollama": "找不到 Ollama 模型。请确认 Ollama 是否正在运行。",
|
||||
"error_fetching": "获取模型失败:{{error}}"
|
||||
},
|
||||
"code-editor-options": {
|
||||
"title": "编辑器"
|
||||
},
|
||||
@@ -2070,7 +1947,8 @@
|
||||
"raster": "栅格",
|
||||
"vector_light": "矢量(浅色)",
|
||||
"vector_dark": "矢量(深色)",
|
||||
"show-scale": "显示比例尺"
|
||||
"show-scale": "显示比例尺",
|
||||
"show-labels": "显示标记名称"
|
||||
},
|
||||
"table_context_menu": {
|
||||
"delete_row": "删除行"
|
||||
@@ -2117,7 +1995,7 @@
|
||||
},
|
||||
"call_to_action": {
|
||||
"background_effects_title": "背景效果现已推出稳定版本",
|
||||
"background_effects_message": "在 Windows 装置上,背景效果现在已完全稳定。背景效果通过模糊背后的背景,为使用者界面增添一抹色彩。此技术也用于其他应用程序,例如 Windows 资源管理器。",
|
||||
"background_effects_message": "在 Windows 和 macOS 设备上,背景效果现在已稳定。背景效果通过模糊背后的背景,为使用者界面增添一抹色彩。",
|
||||
"background_effects_button": "启用背景效果",
|
||||
"next_theme_title": "试用新 Trilium 主题",
|
||||
"next_theme_message": "当前使用旧版主题,要试用新主题吗?",
|
||||
@@ -2149,8 +2027,9 @@
|
||||
"app-restart-required": "(需重启程序以应用更改)"
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "第 {{startIndex}} 页 - 第 {{endIndex}} 页",
|
||||
"total_notes": "{{count}} 篇笔记"
|
||||
"total_notes": "{{count}} 篇笔记",
|
||||
"prev_page": "上一页",
|
||||
"next_page": "下一页"
|
||||
},
|
||||
"collections": {
|
||||
"rendering_error": "出现错误无法显示内容。"
|
||||
@@ -2185,7 +2064,9 @@
|
||||
"title": "实验选项",
|
||||
"disclaimer": "这些选项处于实验阶段,可能导致系统不稳定。请谨慎使用。",
|
||||
"new_layout_name": "新布局",
|
||||
"new_layout_description": "尝试全新布局,呈现更现代的外观并提升易用性。后续版本将进行重大调整。"
|
||||
"new_layout_description": "尝试全新布局,呈现更现代的外观并提升易用性。后续版本将进行重大调整。",
|
||||
"llm_name": "AI/大语言模型对话",
|
||||
"llm_description": "启用由大语言模型驱动的 AI对话侧边栏和大语言模型对话笔记。"
|
||||
},
|
||||
"tab_history_navigation_buttons": {
|
||||
"go-back": "返回前一笔记",
|
||||
@@ -2253,5 +2134,178 @@
|
||||
"pages_alt": "第{{pageNumber}}页",
|
||||
"pages_loading": "加载中...",
|
||||
"layers_other": "{{count}} 层"
|
||||
},
|
||||
"platform_indicator": {
|
||||
"available_on": "在 {{platform}} 上可用"
|
||||
},
|
||||
"mobile_tab_switcher": {
|
||||
"title_other": "{{count}} 选项卡",
|
||||
"more_options": "更多选项"
|
||||
},
|
||||
"bookmark_buttons": {
|
||||
"bookmarks": "书签"
|
||||
},
|
||||
"web_view_setup": {
|
||||
"title": "直接在 Trilium 中创建网页的实时视图",
|
||||
"url_placeholder": "输入或粘贴网站地址,例如 https://triliumnotes.org",
|
||||
"create_button": "创建网页视图",
|
||||
"invalid_url_title": "无效的地址",
|
||||
"invalid_url_message": "请输入有效的网址,例如 https://triliumnotes.org。",
|
||||
"disabled_description": "此网页视图来自外部来源。为保护您免受网络钓鱼或恶意内容侵害,该视图不会自动加载。若您信任该来源,可手动启用加载功能。",
|
||||
"disabled_button_enable": "启用网页视图"
|
||||
},
|
||||
"render": {
|
||||
"setup_title": "在此笔记中显示自定义 HTML 或 Preact JSX",
|
||||
"setup_create_sample_preact": "使用 Preact 建立范例笔记",
|
||||
"setup_create_sample_html": "使用 HTML 建立范例笔记",
|
||||
"setup_sample_created": "已建立一个范例笔记作为子笔记。",
|
||||
"disabled_description": "此渲染笔记来自外部来源。为保护您免受恶意内容侵害,该功能默认处于禁用状态。启用前请确保您信任该来源。",
|
||||
"disabled_button_enable": "启用渲染笔记"
|
||||
},
|
||||
"active_content_badges": {
|
||||
"type_icon_pack": "图标包",
|
||||
"type_backend_script": "后端脚本",
|
||||
"type_frontend_script": "前端脚本",
|
||||
"type_widget": "小部件",
|
||||
"type_app_css": "自定义 CSS",
|
||||
"type_render_note": "渲染笔记",
|
||||
"type_web_view": "网页视图",
|
||||
"type_app_theme": "自定义主题",
|
||||
"toggle_tooltip_enable_tooltip": "点击以启用此 {{type}}。",
|
||||
"toggle_tooltip_disable_tooltip": "点击以禁用此 {{type}}。",
|
||||
"menu_docs": "打开文档",
|
||||
"menu_execute_now": "立即执行脚本",
|
||||
"menu_run": "自动执行",
|
||||
"menu_run_disabled": "手动",
|
||||
"menu_run_backend_startup": "当后端启动时",
|
||||
"menu_run_hourly": "每小时",
|
||||
"menu_run_daily": "每日",
|
||||
"menu_run_frontend_startup": "当桌面前端启动时",
|
||||
"menu_run_mobile_startup": "当移动前端启动时",
|
||||
"menu_change_to_widget": "更改为小部件",
|
||||
"menu_change_to_frontend_script": "更改为前端脚本",
|
||||
"menu_theme_base": "主题基底"
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "了解更多"
|
||||
},
|
||||
"media": {
|
||||
"play": "播放(空格)",
|
||||
"pause": "暂停(空格)",
|
||||
"back-10s": "后退10秒(左箭头键)",
|
||||
"forward-30s": "前进30秒",
|
||||
"mute": "静音(M)",
|
||||
"unmute": "取消静音(M)",
|
||||
"playback-speed": "播放速度",
|
||||
"loop": "循环播放",
|
||||
"disable-loop": "禁用循环播放",
|
||||
"rotate": "旋转",
|
||||
"picture-in-picture": "画中画",
|
||||
"exit-picture-in-picture": "退出画中画",
|
||||
"fullscreen": "全屏(F)",
|
||||
"exit-fullscreen": "退出全屏",
|
||||
"unsupported-format": "此文件格式不支持媒体预览:\n{{mime}}",
|
||||
"zoom-to-fit": "缩放以填充",
|
||||
"zoom-reset": "重置缩放以填充"
|
||||
},
|
||||
"mermaid": {
|
||||
"sample_diagrams": "示例图:",
|
||||
"sample_flowchart": "流程图",
|
||||
"sample_class": "类图",
|
||||
"sample_sequence": "时序图",
|
||||
"sample_entity_relationship": "实体关系图",
|
||||
"sample_state": "状态图",
|
||||
"sample_mindmap": "思维导图",
|
||||
"sample_architecture": "架构图",
|
||||
"sample_block": "模块图",
|
||||
"sample_c4": "C4 图",
|
||||
"sample_gantt": "甘特图",
|
||||
"sample_git": "Git 流程图",
|
||||
"sample_kanban": "看板图",
|
||||
"sample_packet": "数据包图",
|
||||
"sample_pie": "饼图",
|
||||
"sample_quadrant": "象限图",
|
||||
"sample_radar": "雷达图",
|
||||
"sample_requirement": "需求图",
|
||||
"sample_sankey": "桑基图",
|
||||
"sample_timeline": "时间轴图",
|
||||
"sample_treemap": "树形图",
|
||||
"sample_user_journey": "用户旅程图",
|
||||
"sample_xy": "散点图",
|
||||
"sample_venn": "韦恩图",
|
||||
"sample_ishikawa": "鱼骨图",
|
||||
"placeholder": "输入你的美人鱼图的内容,或者使用下面的示例图之一。"
|
||||
},
|
||||
"llm_chat": {
|
||||
"placeholder": "输入消息…",
|
||||
"send": "发送",
|
||||
"sending": "正在发送...",
|
||||
"empty_state": "在下方输入消息,即可开始对话。",
|
||||
"searching_web": "在网上搜索…",
|
||||
"web_search": "联网搜索",
|
||||
"sources": "来源",
|
||||
"extended_thinking": "延伸思考",
|
||||
"legacy_models": "传统模型",
|
||||
"thinking": "正在思考...",
|
||||
"thought_process": "思考过程",
|
||||
"tool_calls": "{{count}} 次工具调用",
|
||||
"input": "输入",
|
||||
"result": "结果",
|
||||
"error": "错误",
|
||||
"tool_error": "失败",
|
||||
"total_tokens": "{{total}} 个词元",
|
||||
"tokens_detail": "{{prompt}} 提示词 + {{completion}} 补全",
|
||||
"tokens_used": "{{prompt}} 提示词 + {{completion}} 补全 = {{total}} 个词元",
|
||||
"tokens_used_with_cost": "{{prompt}} 提示词 + {{completion}} 补全 = {{total}} 个词元(约 ${{cost}})",
|
||||
"tokens_used_with_model": "{{model}}: {{prompt}} 提示词 + {{completion}} 补全 = {{total}} 个词元",
|
||||
"tokens_used_with_model_and_cost": "{{model}}: {{prompt}} 提示词 + {{completion}} 补全 = {{total}} 个词元(约 ${{cost}})",
|
||||
"tokens": "词元",
|
||||
"context_used": "{{percentage}}% 使用率",
|
||||
"note_context_enabled": "点击即可禁用笔记上下文:{{title}}",
|
||||
"note_context_disabled": "点击即可将当前注释添加到上下文中",
|
||||
"no_provider_message": "未配置人工智能提供商。添加一个即可开始对话。",
|
||||
"add_provider": "添加人工智能提供商",
|
||||
"note_tools": "笔记访问"
|
||||
},
|
||||
"sidebar_chat": {
|
||||
"title": "AI对话",
|
||||
"launcher_title": "打开AI对话",
|
||||
"new_chat": "开始新对话",
|
||||
"save_chat": "将对话保存到笔记",
|
||||
"empty_state": "开始对话",
|
||||
"history": "对话历史",
|
||||
"recent_chats": "最近对话",
|
||||
"no_chats": "无历史对话"
|
||||
},
|
||||
"ocr": {
|
||||
"extracted_text": "提取文本(OCR)",
|
||||
"extracted_text_title": "提取文本(OCR)",
|
||||
"loading_text": "正在加载OCR文本...",
|
||||
"no_text_available": "暂无OCR文本",
|
||||
"no_text_explanation": "该笔记未进行 OCR 文本提取处理,或未找到文本。",
|
||||
"failed_to_load": "OCR文本加载失败",
|
||||
"process_now": "处理 OCR",
|
||||
"processing": "正在处理...",
|
||||
"processing_started": "OCR识别已开始。请稍候片刻并刷新页面。",
|
||||
"processing_failed": "OCR处理启动失败",
|
||||
"view_extracted_text": "查看提取的文本(OCR)"
|
||||
},
|
||||
"mind-map": {
|
||||
"addChild": "添加子节点",
|
||||
"addParent": "添加父节点",
|
||||
"addSibling": "添加同级节点",
|
||||
"removeNode": "删除节点",
|
||||
"focus": "专注模式",
|
||||
"cancelFocus": "退出专注模式",
|
||||
"moveUp": "上移",
|
||||
"moveDown": "下移",
|
||||
"link": "链接",
|
||||
"linkBidirectional": "双向链接",
|
||||
"clickTips": "请点击目标节点",
|
||||
"summary": "总结"
|
||||
},
|
||||
"llm": {
|
||||
"settings_description": "配置人工智能和大语言模型集成。",
|
||||
"add_provider": "添加提供商"
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"about": {
|
||||
"title": "Über Trilium Notizen",
|
||||
"title": "Über Trilium Notes",
|
||||
"homepage": "Startseite:",
|
||||
"app_version": "App-Version:",
|
||||
"db_version": "DB-Version:",
|
||||
@@ -28,9 +28,9 @@
|
||||
},
|
||||
"open-script-note": "Script-Notiz öffnen",
|
||||
"widget-render-error": {
|
||||
"title": "Eine externe React Integration konnte nicht dargestellt werden"
|
||||
"title": "Benutzerdefiniertes React-Widget konnte nicht dargestellt werden"
|
||||
},
|
||||
"widget-missing-parent": "Der externen Integration fehlt die erforderliche Eigenschaft '{{property}}'\n\nFalls dieses Skript ohne UI-Element ausgeführt werden soll, benutze stattdessen '#run=frontendStartup'.",
|
||||
"widget-missing-parent": "Benutzerdefiniertes Widget hat die erforderliche '{{property}}'-Eigenschaft nicht korrekt definiert.\n\nFalls dieses Skript ohne UI-Element ausgeführt werden soll, benutze stattdessen '#run=frontendStartup'.",
|
||||
"scripting-error": "Benutzerdefinierter Skriptfehler: {{title}}"
|
||||
},
|
||||
"add_link": {
|
||||
@@ -129,7 +129,7 @@
|
||||
"scrollToActiveNote": "Scrolle zur aktiven Notiz",
|
||||
"jumpToParentNote": "Zur übergeordneten Notiz springen",
|
||||
"collapseWholeTree": "Reduziere den gesamten Notizbaum",
|
||||
"collapseSubTree": "Teilbaum einklappen",
|
||||
"collapseSubTree": "Zweig einklappen",
|
||||
"tabShortcuts": "Tab-Tastenkürzel",
|
||||
"newTabNoteLink": "auf den Notizlink öffnet die Notiz in einem neuen Tab",
|
||||
"onlyInDesktop": "Nur im Desktop (Electron Build)",
|
||||
@@ -230,7 +230,7 @@
|
||||
"move_to": {
|
||||
"dialog_title": "Notizen verschieben nach ...",
|
||||
"notes_to_move": "Notizen zum Verschieben",
|
||||
"target_parent_note": "Ziel-Elternnotiz",
|
||||
"target_parent_note": "Übergeordnete Notiz bestimmen",
|
||||
"search_placeholder": "Suche nach einer Notiz anhand ihres Namens",
|
||||
"move_button": "Zur ausgewählten Notiz wechseln",
|
||||
"error_no_path": "Kein Weg, auf den man sich bewegen kann.",
|
||||
@@ -333,8 +333,8 @@
|
||||
"target_note_title": "Eine Beziehung ist eine benannte Verbindung zwischen Quellnotiz und Zielnotiz.",
|
||||
"target_note": "Zielnotiz",
|
||||
"promoted_title": "Das heraufgestufte Attribut wird deutlich in der Notiz angezeigt.",
|
||||
"promoted": "Gefördert",
|
||||
"promoted_alias_title": "Der Name, der in der Benutzeroberfläche für heraufgestufte Attribute angezeigt werden soll.",
|
||||
"promoted": "Hervorgehoben",
|
||||
"promoted_alias_title": "Der Name, der in der Benutzeroberfläche für hervorgehobene Attribute angezeigt werden soll.",
|
||||
"promoted_alias": "Alias",
|
||||
"multiplicity_title": "Multiplizität definiert, wie viele Attribute mit demselben Namen erstellt werden können – maximal 1 oder mehr als 1.",
|
||||
"multiplicity": "Vielzahl",
|
||||
@@ -367,7 +367,7 @@
|
||||
"disable_versioning": "deaktiviert die automatische Versionierung. Nützlich z.B. große, aber unwichtige Notizen – z.B. große JS-Bibliotheken, die für die Skripterstellung verwendet werden",
|
||||
"calendar_root": "Markiert eine Notiz, die als Basis für Tagesnotizen verwendet werden soll. Nur einer sollte als solcher gekennzeichnet sein.",
|
||||
"archived": "Notizen mit dieser Bezeichnung werden standardmäßig nicht in den Suchergebnissen angezeigt (auch nicht in den Dialogen „Springen zu“, „Link hinzufügen“ usw.).",
|
||||
"exclude_from_export": "Notizen (mit ihrem Unterbaum) werden nicht in den Notizexport einbezogen",
|
||||
"exclude_from_export": "Notizen (mit ihrem Unterbaum) werden nicht im Notizexport inkludiert",
|
||||
"run": "Definiert, bei welchen Ereignissen das Skript ausgeführt werden soll. Mögliche Werte sind:\n<ul>\n<li>frontendStartup - wenn das Trilium-Frontend startet (oder aktualisiert wird), außer auf mobilen Geräten.</li>\n<li>mobileStartup - wenn das Trilium-Frontend auf einem mobilen Gerät startet (oder aktualisiert wird).</li>\n<li>backendStartup - wenn das Trilium-Backend startet</li>\n<li>hourly - einmal pro Stunde ausführen. Du kannst das zusätzliche Label <code>runAtHour</code> verwenden, um die genaue Stunde festzulegen.</li>\n<li>daily - einmal pro Tag ausführen</li>\n</ul>",
|
||||
"run_on_instance": "Definiere, auf welcher Trilium-Instanz dies ausgeführt werden soll. Standardmäßig alle Instanzen.",
|
||||
"run_at_hour": "Zu welcher Stunde soll das laufen? Sollte zusammen mit <code>#runu003dhourly</code> verwendet werden. Kann für mehr Läufe im Laufe des Tages mehrfach definiert werden.",
|
||||
@@ -376,7 +376,7 @@
|
||||
"sort_direction": "ASC (Standard) oder DESC",
|
||||
"sort_folders_first": "Ordner (Notizen mit Unternotizen) sollten oben sortiert werden",
|
||||
"top": "Behalte die angegebene Notiz oben in der übergeordneten Notiz (gilt nur für sortierte übergeordnete Notizen)",
|
||||
"hide_promoted_attributes": "Heraufgestufte Attribute für diese Notiz ausblenden",
|
||||
"hide_promoted_attributes": "Hervorgehobene Attribute für diese Notiz ausblenden",
|
||||
"read_only": "Der Editor befindet sich im schreibgeschützten Modus. Funktioniert nur für Text- und Codenotizen.",
|
||||
"auto_read_only_disabled": "Text-/Codenotizen können automatisch in den Lesemodus versetzt werden, wenn sie zu groß sind. Du kannst dieses Verhalten für jede einzelne Notiz deaktivieren, indem du diese Beschriftung zur Notiz hinzufügst",
|
||||
"app_css": "markiert CSS-Notizen, die in die Trilium-Anwendung geladen werden und somit zur Änderung des Aussehens von Trilium verwendet werden können.",
|
||||
@@ -416,25 +416,25 @@
|
||||
"toc": "<code>#toc</code> oder <code>#tocu003dshow</code> erzwingen die Anzeige des Inhaltsverzeichnisses, <code>#tocu003dhide</code> erzwingt das Ausblenden. Wenn die Bezeichnung nicht vorhanden ist, wird die globale Einstellung beachtet",
|
||||
"color": "Definiert die Farbe der Notiz im Notizbaum, in Links usw. Verwende einen beliebigen gültigen CSS-Farbwert wie „rot“ oder #a13d5f",
|
||||
"keyboard_shortcut": "Definiert eine Tastenkombination, die sofort zu dieser Notiz springt. Beispiel: „Strg+Alt+E“. Erfordert ein Neuladen des Frontends, damit die Änderung wirksam wird.",
|
||||
"keep_current_hoisting": "Das Öffnen dieses Links ändert das Hochziehen nicht, selbst wenn die Notiz im aktuell hochgezogenen Unterbaum nicht angezeigt werden kann.",
|
||||
"keep_current_hoisting": "Das Öffnen dieses Links ändert das Hochziehen nicht, selbst wenn die Notiz im aktuell hochgezogenen Zweig nicht angezeigt werden kann.",
|
||||
"execute_button": "Titel der Schaltfläche, welche die aktuelle Codenotiz ausführt",
|
||||
"execute_description": "Längere Beschreibung der aktuellen Codenotiz, die zusammen mit der Schaltfläche „Ausführen“ angezeigt wird",
|
||||
"exclude_from_note_map": "Notizen mit dieser Bezeichnung werden in der Notizenkarte ausgeblendet",
|
||||
"new_notes_on_top": "Neue Notizen werden oben in der übergeordneten Notiz erstellt, nicht unten.",
|
||||
"hide_highlight_widget": "Widget „Markierungsliste“ ausblenden",
|
||||
"run_on_note_creation": "Wird ausgeführt, wenn eine Notiz im Backend erstellt wird. Verwende diese Beziehung, wenn du das Skript für alle Notizen ausführen möchtest, die unter einer bestimmten Unternotiz erstellt wurden. Erstelle es in diesem Fall auf der Unternotiz-Stammnotiz und mache es vererbbar. Eine neue Notiz, die innerhalb der Unternotiz (beliebige Tiefe) erstellt wird, löst das Skript aus.",
|
||||
"run_on_note_creation": "Wird ausgeführt, wenn eine Notiz im Backend erstellt wird. Verwende diese Beziehung, wenn du das Skript für alle Notizen ausführen möchtest, die unter einem bestimmten Zweig erstellt wurden. Erstelle es in diesem Fall auf der Stammnotiz und mache es vererbbar. Eine neue Notiz, die innerhalb des Zweigs (beliebige Tiefe) erstellt wird, löst das Skript aus.",
|
||||
"run_on_child_note_creation": "Wird ausgeführt, wenn eine neue Notiz unter der Notiz erstellt wird, in der diese Beziehung definiert ist",
|
||||
"run_on_note_title_change": "Wird ausgeführt, wenn der Notiztitel geändert wird (einschließlich der Notizerstellung)",
|
||||
"run_on_note_content_change": "Wird ausgeführt, wenn der Inhalt einer Notiz geändert wird (einschließlich der Erstellung von Notizen).",
|
||||
"run_on_note_change": "Wird ausgeführt, wenn eine Notiz geändert wird (einschließlich der Erstellung von Notizen). Enthält keine Inhaltsänderungen",
|
||||
"run_on_note_deletion": "Wird ausgeführt, wenn eine Notiz gelöscht wird",
|
||||
"run_on_branch_creation": "wird ausgeführt, wenn ein Zweig erstellt wird. Der Zweig ist eine Verbindung zwischen der übergeordneten Notiz und der untergeordneten Notiz und wird z. B. erstellt. beim Klonen oder Verschieben von Notizen.",
|
||||
"run_on_branch_creation": "wird ausgeführt, wenn ein Zweig erstellt wird. Der Zweig ist eine Verbindung zwischen der übergeordneten und der untergeordneten Notiz und wird z. B. beim Klonen oder Verschieben von Notizen erstellt.",
|
||||
"run_on_branch_change": "wird ausgeführt, wenn ein Zweig aktualisiert wird.",
|
||||
"run_on_branch_deletion": "wird ausgeführt, wenn ein Zweig gelöscht wird. Der Zweig ist eine Verknüpfung zwischen der übergeordneten Notiz und der untergeordneten Notiz und wird z. B. gelöscht. beim Verschieben der Notiz (alter Zweig/Link wird gelöscht).",
|
||||
"run_on_branch_deletion": "wird ausgeführt, wenn ein Zweig gelöscht wird. Der Zweig ist eine Verknüpfung zwischen der übergeordneten und der untergeordneten Notiz und wird z. B. beim Verschieben der Notiz gelöscht (alter Zweig/Link wird gelöscht).",
|
||||
"run_on_attribute_creation": "wird ausgeführt, wenn für die Notiz ein neues Attribut erstellt wird, das diese Beziehung definiert",
|
||||
"run_on_attribute_change": " wird ausgeführt, wenn das Attribut einer Notiz geändert wird, die diese Beziehung definiert. Dies wird auch ausgelöst, wenn das Attribut gelöscht wird",
|
||||
"relation_template": "Die Attribute der Notiz werden auch ohne eine Eltern-Kind-Beziehung vererbt. Der Inhalt und der Unterbaum der Notiz werden den Instanznotizen hinzugefügt, wenn sie leer sind. Einzelheiten findest du in der Dokumentation.",
|
||||
"inherit": "Die Attribute einer Notiz werden auch ohne eine Eltern-Kind-Beziehung vererbt. Ein ähnliches Konzept findest du unter Vorlagenbeziehung. Siehe Attributvererbung in der Dokumentation.",
|
||||
"relation_template": "Die Attribute der Notiz werden auch ohne eine Hierarchische-Beziehung vererbt. Der Inhalt und der Zweig werden den Instanznotizen hinzugefügt, wenn sie leer sind. Einzelheiten findest du in der Dokumentation.",
|
||||
"inherit": "Die Attribute einer Notiz werden auch ohne eine Hierarchische-Beziehung vererbt. Ein ähnliches Konzept findest du unter Vorlagenbeziehung. Siehe Attributsvererbung in der Dokumentation.",
|
||||
"render_note": "Notizen vom Typ \"HTML-Notiz rendern\" werden mit einer Code-Notiz (HTML oder Skript) gerendert, und es ist notwendig, über diese Beziehung anzugeben, welche Notiz gerendert werden soll",
|
||||
"widget_relation": "Das Ziel dieser Beziehung wird ausgeführt und als Widget in der Seitenleiste gerendert",
|
||||
"share_css": "CSS-Hinweis, der in die Freigabeseite eingefügt wird. Die CSS-Notiz muss sich ebenfalls im gemeinsamen Unterbaum befinden. Erwäge auch die Verwendung von „share_hidden_from_tree“ und „share_omit_default_css“.",
|
||||
@@ -446,7 +446,8 @@
|
||||
"and_more": "... und {{count}} mehr.",
|
||||
"print_landscape": "Beim Export als PDF, wird die Seitenausrichtung Querformat anstatt Hochformat verwendet.",
|
||||
"print_page_size": "Beim Export als PDF, wird die Größe der Seite angepasst. Unterstützte Größen: <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>.",
|
||||
"color_type": "Farbe"
|
||||
"color_type": "Farbe",
|
||||
"textarea": "Mehrzeilen-Text"
|
||||
},
|
||||
"attribute_editor": {
|
||||
"help_text_body1": "Um ein Label hinzuzufügen, gebe einfach z.B. ein. <code>#rock</code> oder wenn du auch einen Wert hinzufügen möchten, dann z.B. <code>#year = 2024</code>",
|
||||
@@ -646,7 +647,7 @@
|
||||
"reset_zoom_level": "Zoomstufe zurücksetzen",
|
||||
"zoom_in": "Hineinzoomen",
|
||||
"configure_launchbar": "Konfiguriere die Starterleiste",
|
||||
"show_shared_notes_subtree": "Unterbaum „Freigegebene Notizen“ anzeigen",
|
||||
"show_shared_notes_subtree": "Zweig „Freigegebene Notizen“ anzeigen",
|
||||
"advanced": "Erweitert",
|
||||
"open_dev_tools": "Öffne die Entwicklungstools",
|
||||
"open_sql_console": "Öffne die SQL-Konsole",
|
||||
@@ -655,14 +656,15 @@
|
||||
"show_backend_log": "Backend-Protokoll anzeigen",
|
||||
"reload_hint": "Ein Neuladen kann bei einigen visuellen Störungen Abhilfe schaffen, ohne die gesamte App neu starten zu müssen.",
|
||||
"reload_frontend": "Frontend neu laden",
|
||||
"show_hidden_subtree": "Versteckten Teilbaum anzeigen",
|
||||
"show_hidden_subtree": "Versteckten Zweig anzeigen",
|
||||
"show_help": "Hilfe anzeigen",
|
||||
"about": "Über Trilium Notes",
|
||||
"logout": "Abmelden",
|
||||
"show-cheatsheet": "Cheatsheet anzeigen",
|
||||
"toggle-zen-mode": "Zen Modus",
|
||||
"new-version-available": "Neues Update verfügbar",
|
||||
"download-update": "Version {{latestVersion}} herunterladen"
|
||||
"download-update": "Version {{latestVersion}} herunterladen",
|
||||
"search_notes": "Notizen durchsuchen"
|
||||
},
|
||||
"sync_status": {
|
||||
"unknown": "<p>Der Synchronisations-Status wird bekannt, sobald der nächste Synchronisierungsversuch gestartet wird.</p><p>Klicke, um eine Synchronisierung jetzt auszulösen.</p>",
|
||||
@@ -703,8 +705,8 @@
|
||||
"export_as_image_png": "PNG (Raster)",
|
||||
"export_as_image_svg": "SVG (Vektor)",
|
||||
"note_map": "Notizen Karte",
|
||||
"view_revisions": "Änderungshistorie...",
|
||||
"advanced": "Fortgeschritten"
|
||||
"view_revisions": "Notizrevisionen...",
|
||||
"advanced": "Erweitert"
|
||||
},
|
||||
"onclick_button": {
|
||||
"no_click_handler": "Das Schaltflächen-Widget „{{componentId}}“ hat keinen definierten Klick-Handler"
|
||||
@@ -742,7 +744,7 @@
|
||||
"button_title": "Diagramm als SVG exportieren"
|
||||
},
|
||||
"relation_map_buttons": {
|
||||
"create_child_note_title": "Erstelle eine neue untergeordnete Notiz und füge sie dieser Beziehungskarte hinzu",
|
||||
"create_child_note_title": "Erstelle eine untergeordnete Notiz und füge sie dieser Karte hinzu",
|
||||
"reset_pan_zoom_title": "Schwenken und Zoomen auf die ursprünglichen Koordinaten und Vergrößerung zurücksetzen",
|
||||
"zoom_in_title": "Hineinzoom",
|
||||
"zoom_out_title": "Herauszoomen"
|
||||
@@ -757,7 +759,9 @@
|
||||
"delete_this_note": "Diese Notiz löschen",
|
||||
"error_cannot_get_branch_id": "BranchId für notePath „{{notePath}}“ kann nicht abgerufen werden",
|
||||
"error_unrecognized_command": "Unbekannter Befehl {{command}}",
|
||||
"note_revisions": "Notiz Revisionen"
|
||||
"note_revisions": "Notiz Revisionen",
|
||||
"backlinks": "Rücklinks",
|
||||
"content_language_switcher": "Inhaltssprache: {{language}}"
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "Notiz-Icon ändern",
|
||||
@@ -798,7 +802,7 @@
|
||||
"expand_tooltip": "Erweitert die direkten Unterelemente dieser Sammlung (eine Ebene tiefer). Für weitere Optionen auf den Pfeil rechts klicken.",
|
||||
"expand_first_level": "Direkte Unterelemente erweitern",
|
||||
"expand_nth_level": "{{depth}} Ebenen erweitern",
|
||||
"hide_child_notes": "Unterknoten im Baum ausblenden"
|
||||
"hide_child_notes": "Untergeordnete Notizen im Baum ausblenden"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "An diesem Tag wurden noch keine Notizen bearbeitet...",
|
||||
@@ -842,7 +846,7 @@
|
||||
"note_size": "Notengröße",
|
||||
"note_size_info": "Die Notizgröße bietet eine grobe Schätzung des Speicherbedarfs für diese Notiz. Es berücksichtigt den Inhalt der Notiz und den Inhalt ihrer Notizrevisionen.",
|
||||
"calculate": "berechnen",
|
||||
"subtree_size": "(Teilbaumgröße: {{size}} in {{count}} Notizen)",
|
||||
"subtree_size": "(Zweiggröße: {{size}} in {{count}} Notizen)",
|
||||
"title": "Notizinfo",
|
||||
"mime": "MIME Typ",
|
||||
"show_similar_notes": "Zeige ähnliche Notizen"
|
||||
@@ -871,7 +875,7 @@
|
||||
"owned_attributes": "Eigene Attribute"
|
||||
},
|
||||
"promoted_attributes": {
|
||||
"promoted_attributes": "Übergebene Attribute",
|
||||
"promoted_attributes": "Hervorgehobene Attribute",
|
||||
"url_placeholder": "http://website...",
|
||||
"open_external_link": "Externen Link öffnen",
|
||||
"unknown_label_type": "Unbekannter Labeltyp „{{type}}“",
|
||||
@@ -909,7 +913,8 @@
|
||||
"unknown_search_option": "Unbekannte Suchoption {{searchOptionName}}",
|
||||
"search_note_saved": "Suchnotiz wurde in {{-notePathTitle}} gespeichert",
|
||||
"actions_executed": "Aktionen wurden ausgeführt.",
|
||||
"view_options": "Optionen anzeigen:"
|
||||
"view_options": "Optionen anzeigen:",
|
||||
"option": "Option"
|
||||
},
|
||||
"similar_notes": {
|
||||
"title": "Ähnliche Notizen",
|
||||
@@ -1003,7 +1008,7 @@
|
||||
"no_attachments": "Diese Notiz enthält keine Anhänge."
|
||||
},
|
||||
"book": {
|
||||
"no_children_help": "Diese Notiz mit dem Notiztyp Buch besitzt keine Unternotizen, deshalb ist nichts zum Anzeigen vorhanden. Siehe <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">Wiki</a> für mehr Details.",
|
||||
"no_children_help": "Diese Sammlung enthält keine untergeordnete Notizen, daher gibt es nichts anzuzeigen.",
|
||||
"drag_locked_title": "Für Bearbeitung gesperrt",
|
||||
"drag_locked_message": "Das Ziehen ist nicht möglich, da die Sammlung für die Bearbeitung gesperrt ist."
|
||||
},
|
||||
@@ -1042,7 +1047,6 @@
|
||||
"unprotecting-title": "Ungeschützt-Status"
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "In neuem Tab öffnen",
|
||||
"remove_note": "Notiz entfernen",
|
||||
"edit_title": "Titel bearbeiten",
|
||||
"rename_note": "Notiz umbenennen",
|
||||
@@ -1059,15 +1063,6 @@
|
||||
"default_new_note_title": "neue Notiz",
|
||||
"click_on_canvas_to_place_new_note": "Klicke auf den Canvas, um eine neue Notiz zu platzieren"
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_1": "Diese Hilfesnotiz wird angezeigt, da diese Notiz vom Typ „HTML rendern“ nicht über die erforderliche Beziehung verfügt, um ordnungsgemäß zu funktionieren.",
|
||||
"note_detail_render_help_2": "Render-HTML-Notiztyp wird benutzt für <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">scripting</a>. Kurzgesagt, du hast ein HTML-Code-Notiz (optional mit JavaScript) und diese Notiz rendert es. Damit es funktioniert, musst du eine a <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">Beziehung</a> namens \"renderNote\" zeigend auf die HTML-Notiz zum rendern definieren."
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "Webansicht",
|
||||
"embed_websites": "Notiz vom Typ Web View ermöglicht das Einbetten von Websites in Trilium.",
|
||||
"create_label": "Um zu beginnen, erstelle bitte ein Label mit einer URL-Adresse, die eingebettet werden soll, z. B. #webViewSrc=\"https://www.google.com\""
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "Aktualisieren"
|
||||
},
|
||||
@@ -1115,7 +1110,7 @@
|
||||
"vacuum_database": {
|
||||
"title": "Datenbank aufräumen",
|
||||
"description": "Dadurch wird die Datenbank neu erstellt, was normalerweise zu einer kleineren Datenbankdatei führt. Es werden keine Daten tatsächlich geändert.",
|
||||
"button_text": "Vakuumdatenbank",
|
||||
"button_text": "Datenbank aufräumen",
|
||||
"vacuuming_database": "Datenbank wird geleert...",
|
||||
"database_vacuumed": "Die Datenbank wurde geleert"
|
||||
},
|
||||
@@ -1156,7 +1151,7 @@
|
||||
},
|
||||
"ribbon": {
|
||||
"widgets": "Multifunktionsleisten-Widgets",
|
||||
"promoted_attributes_message": "Die Multifunktionsleisten-Registerkarte „Heraufgestufte Attribute“ wird automatisch geöffnet, wenn in der Notiz heraufgestufte Attribute vorhanden sind",
|
||||
"promoted_attributes_message": "Die „Hervorgehobene Attribute“-Leiste wird automatisch geöffnet, wenn in der Notiz hervorgehobene Attribute vorhanden sind",
|
||||
"edited_notes_message": "Die Multifunktionsleisten-Registerkarte „Bearbeitete Notizen“ wird bei Tagesnotizen automatisch geöffnet"
|
||||
},
|
||||
"theme": {
|
||||
@@ -1192,7 +1187,7 @@
|
||||
"tooltip_code_note_syntax": "Code-Notizen"
|
||||
},
|
||||
"vim_key_bindings": {
|
||||
"use_vim_keybindings_in_code_notes": "Verwende VIM-Tastenkombinationen in Codenotizen (kein Ex-Modus)",
|
||||
"use_vim_keybindings_in_code_notes": "Vim Tastenbelegung",
|
||||
"enable_vim_keybindings": "Aktiviere Vim-Tastenkombinationen"
|
||||
},
|
||||
"wrap_lines": {
|
||||
@@ -1383,7 +1378,8 @@
|
||||
"description": "Beschreibung",
|
||||
"reload_app": "Lade die App neu, um die Änderungen zu übernehmen",
|
||||
"set_all_to_default": "Setze alle Verknüpfungen auf die Standardeinstellungen",
|
||||
"confirm_reset": "Möchtest du wirklich alle Tastaturkürzel auf die Standardeinstellungen zurücksetzen?"
|
||||
"confirm_reset": "Möchtest du wirklich alle Tastaturkürzel auf die Standardeinstellungen zurücksetzen?",
|
||||
"no_results": "Keine Tastenkürzel für '{{filter}}' gefunden"
|
||||
},
|
||||
"spellcheck": {
|
||||
"title": "Rechtschreibprüfung",
|
||||
@@ -1443,21 +1439,21 @@
|
||||
"open-in-a-new-tab": "In neuem Tab öffnen",
|
||||
"open-in-a-new-split": "In neuem Split öffnen",
|
||||
"insert-note-after": "Notiz dahinter einfügen",
|
||||
"insert-child-note": "Unternotiz einfügen",
|
||||
"insert-child-note": "Untergeordnete Notiz einfügen",
|
||||
"delete": "Löschen",
|
||||
"search-in-subtree": "Im Notizbaum suchen",
|
||||
"search-in-subtree": "Im Zweig suchen",
|
||||
"hoist-note": "Notiz-Fokus setzen",
|
||||
"unhoist-note": "Notiz-Fokus aufheben",
|
||||
"edit-branch-prefix": "Zweig-Präfix bearbeiten",
|
||||
"advanced": "Erweitert",
|
||||
"expand-subtree": "Unterzweig aufklappen",
|
||||
"collapse-subtree": "Notizbaum einklappen",
|
||||
"expand-subtree": "Zweig aufklappen",
|
||||
"collapse-subtree": "Zweig einklappen",
|
||||
"sort-by": "Sortieren nach...",
|
||||
"recent-changes-in-subtree": "Kürzliche Änderungen im Notizbaum",
|
||||
"recent-changes-in-subtree": "Kürzliche Änderungen im Zweig",
|
||||
"convert-to-attachment": "Als Anhang konvertieren",
|
||||
"copy-note-path-to-clipboard": "Notiz-Pfad in die Zwischenablage kopieren",
|
||||
"protect-subtree": "Notizbaum schützen",
|
||||
"unprotect-subtree": "Notizenbaum-Schutz aufheben",
|
||||
"protect-subtree": "Zweig schützen",
|
||||
"unprotect-subtree": "Zweig-Schutz aufheben",
|
||||
"copy-clone": "Kopieren / Klonen",
|
||||
"clone-to": "Klonen nach...",
|
||||
"cut": "Ausschneiden",
|
||||
@@ -1474,12 +1470,12 @@
|
||||
"archive": "Archiviere",
|
||||
"unarchive": "Entarchivieren",
|
||||
"open-in-a-new-window": "In neuem Fenster öffnen",
|
||||
"hide-subtree": "Teilbaum ausblenden",
|
||||
"show-subtree": "Teilbaum anzeigen"
|
||||
"hide-subtree": "Zweig ausblenden",
|
||||
"show-subtree": "Zweig anzeigen"
|
||||
},
|
||||
"shared_info": {
|
||||
"shared_publicly": "Diese Notiz ist öffentlich geteilt auf {{- link}}.",
|
||||
"shared_locally": "Diese Notiz ist lokal geteilt auf {{- link}}.",
|
||||
"shared_publicly": "Diese Notiz ist öffentlich freigegeben über {{- link}}.",
|
||||
"shared_locally": "Diese Notiz ist lokal freigegeben über {{- link}}.",
|
||||
"help_link": "Für Hilfe besuche <a href=\"https://triliumnext.github.io/Docs/Wiki/sharing.html\">wiki</a>."
|
||||
},
|
||||
"note_types": {
|
||||
@@ -1492,20 +1488,21 @@
|
||||
"mermaid-diagram": "Mermaid Diagramm",
|
||||
"canvas": "Leinwand",
|
||||
"web-view": "Webansicht",
|
||||
"mind-map": "Mind Map",
|
||||
"mind-map": "Mindmap",
|
||||
"file": "Datei",
|
||||
"image": "Bild",
|
||||
"launcher": "Starter",
|
||||
"doc": "Dokument",
|
||||
"widget": "Widget",
|
||||
"confirm-change": "Es is nicht empfehlenswert den Notiz-Typ zu ändern, wenn der Inhalt der Notiz nicht leer ist. Möchtest du dennoch fortfahren?",
|
||||
"confirm-change": "Es ist nicht empfehlenswert den Notiz-Typ zu ändern, wenn der Inhalt der Notiz nicht leer ist. Möchtest du dennoch fortfahren?",
|
||||
"geo-map": "Geo-Karte",
|
||||
"beta-feature": "Beta",
|
||||
"book": "Sammlung",
|
||||
"ai-chat": "KI Chat",
|
||||
"ai-chat": "KI-Chat",
|
||||
"task-list": "Aufgabenliste",
|
||||
"new-feature": "Neu",
|
||||
"collections": "Sammlungen"
|
||||
"collections": "Sammlungen",
|
||||
"spreadsheet": "Tabelle"
|
||||
},
|
||||
"protect_note": {
|
||||
"toggle-on": "Notiz schützen",
|
||||
@@ -1514,10 +1511,10 @@
|
||||
"toggle-off-hint": "Notiz ist geschützt, klicken, um den Schutz aufzuheben"
|
||||
},
|
||||
"shared_switch": {
|
||||
"shared": "Teilen",
|
||||
"toggle-on-title": "Notiz teilen",
|
||||
"shared": "Freigegeben",
|
||||
"toggle-on-title": "Notiz freigeben",
|
||||
"toggle-off-title": "Notiz-Freigabe aufheben",
|
||||
"shared-branch": "Diese Notiz existiert nur als geteilte Notiz, das Aufheben der Freigabe würde sie löschen. Möchtest du fortfahren und die Notiz damit löschen?",
|
||||
"shared-branch": "Diese Notiz existiert nur als freigegebene Notiz, das Aufheben der Freigabe würde sie löschen. Möchtest du fortfahren und die Notiz damit löschen?",
|
||||
"inherited": "Die Notiz kann hier nicht von der Freigabe entfernt werden, da sie über Vererbung von einer übergeordneten Notiz geteilt wird."
|
||||
},
|
||||
"template_switch": {
|
||||
@@ -1562,19 +1559,19 @@
|
||||
"saved-search-note-refreshed": "Gespeicherte Such-Notiz wurde aktualisiert.",
|
||||
"hoist-this-note-workspace": "Diese Notiz fokussieren (Arbeitsbereich)",
|
||||
"refresh-saved-search-results": "Gespeicherte Suchergebnisse aktualisieren",
|
||||
"create-child-note": "Unternotiz anlegen",
|
||||
"create-child-note": "Untergeordnete Notiz anlegen",
|
||||
"unhoist": "Fokus verlassen",
|
||||
"toggle-sidebar": "Seitenleiste ein-/ausblenden",
|
||||
"dropping-not-allowed": "Ablegen von Notizen an dieser Stelle ist nicht zulässig.",
|
||||
"clone-indicator-tooltip": "Diese Notiz hat {{- count}} Elterknoten: {{- parents}}",
|
||||
"clone-indicator-tooltip-single": "Diese Notiz ist geklont (1 weiterer Elternknoten: {{- parent}})",
|
||||
"shared-indicator-tooltip": "Diese Notiz ist öffentlich einsehbar",
|
||||
"shared-indicator-tooltip-with-url": "Diese Notiz ist unter {{- url}} öffentlich einsehbar",
|
||||
"subtree-hidden-tooltip_one": "{{count}} Unterknoten, der im Baum ausgeblendet ist",
|
||||
"subtree-hidden-tooltip_other": "{{count}} Unterknoten, die im Baum ausgeblendet sind",
|
||||
"clone-indicator-tooltip": "Diese Notiz hat {{- count}} übergeordnete Knoten: {{- parents}}",
|
||||
"clone-indicator-tooltip-single": "Diese Notiz ist geklont (1 weitere Quelle: {{- parent}})",
|
||||
"shared-indicator-tooltip": "Diese Notiz ist öffentlich freigegeben",
|
||||
"shared-indicator-tooltip-with-url": "Diese Notiz ist öffentlich freigegeben unter: {{- url}}",
|
||||
"subtree-hidden-tooltip_one": "{{count}} untergeordnete Notiz, die im Baum ausgeblendet ist",
|
||||
"subtree-hidden-tooltip_other": "{{count}} untergeordnete Notizen, die im Baum ausgeblendet sind",
|
||||
"subtree-hidden-moved-title": "Zu {{title}} hinzugefügt",
|
||||
"subtree-hidden-moved-description-collection": "Diese Sammlung blendet ihre Unternotizem im Baum aus.",
|
||||
"subtree-hidden-moved-description-other": "Diese Sammlung blendet ihre Unterknoten im Baum aus."
|
||||
"subtree-hidden-moved-description-collection": "Diese Sammlung blendet ihre untergeordneten Notizen im Baum aus.",
|
||||
"subtree-hidden-moved-description-other": "Untergeordnete Notizen sind im Baum für diese Notiz ausgeblendet."
|
||||
},
|
||||
"title_bar_buttons": {
|
||||
"window-on-top": "Dieses Fenster immer oben halten"
|
||||
@@ -1586,8 +1583,10 @@
|
||||
"print_report_title": "Druckreport",
|
||||
"print_report_collection_details_button": "Details anzeigen",
|
||||
"print_report_collection_details_ignored_notes": "Ignorierte Notizen",
|
||||
"print_report_collection_content_one": "{{count}} Notiz in der Sammlung konnte nicht gedruckt werden, weil sie nicht unterstützt ist oder geschützt ist.",
|
||||
"print_report_collection_content_other": "{{count}} Notizen in der Sammlung konnten nicht gedruckt werden, weil sie nicht unterstützt sind oder geschützt sind."
|
||||
"print_report_collection_content_one": "{{count}} Notiz in der Sammlung konnte nicht gedruckt werden, weil sie nicht unterstützt oder geschützt ist.",
|
||||
"print_report_collection_content_other": "{{count}} Notizen in der Sammlung konnten nicht gedruckt werden, weil sie nicht unterstützt oder geschützt sind.",
|
||||
"print_report_error_title": "Druck fehlgeschlagen",
|
||||
"print_report_stack_trace": "Stapelzurückverfolgung"
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "Titel der Notiz hier eingeben…",
|
||||
@@ -1602,7 +1601,8 @@
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "Es wurden keine Notizen mit den angegebenen Suchparametern gefunden.",
|
||||
"search_not_executed": "Die Suche wurde noch nicht ausgeführt. Klicke oben auf „Suchen“, um die Ergebnisse anzuzeigen."
|
||||
"search_not_executed": "Die Suche wurde noch nicht ausgeführt.",
|
||||
"search_now": "Jetzt suchen"
|
||||
},
|
||||
"spacer": {
|
||||
"configure_launchbar": "Starterleiste konfigurieren"
|
||||
@@ -1730,6 +1730,7 @@
|
||||
"add-term-to-dictionary": "Begriff \"{{term}}\" zum Wörterbuch hinzufügen",
|
||||
"cut": "Ausschneiden",
|
||||
"copy": "Kopieren",
|
||||
"copy-as-markdown": "Als Markdown kopieren",
|
||||
"copy-link": "Link kopieren",
|
||||
"paste": "Einfügen",
|
||||
"paste-as-plain-text": "Als unformatierten Text einfügen",
|
||||
@@ -1751,14 +1752,14 @@
|
||||
"desktop-application": "Desktop Anwendung",
|
||||
"native-title-bar": "Native Anwendungsleiste",
|
||||
"native-title-bar-description": "In Windows und macOS, sorgt das Deaktivieren der nativen Anwendungsleiste für ein kompakteres Aussehen. Unter Linux, sorgt das Aktivieren der nativen Anwendungsleiste für eine bessere Integration mit anderen Teilen des Systems.",
|
||||
"background-effects": "Hintergrundeffekte aktivieren (nur Windows 11)",
|
||||
"background-effects-description": "Der Mica Effekt fügt einen unscharfen, stylischen Hintergrund in Anwendungsfenstern ein. Dieser erzeugt Tiefe und ein modernes Auftreten. \"Native Titelleiste\" muss deaktiviert sein.",
|
||||
"background-effects": "Hintergrundeffekte aktivieren",
|
||||
"background-effects-description": "Fügt einen unscharfen, stylischen Hintergrund in das Anwendungsfenstern ein. Dies erzeugt Tiefe und ein modernes Auftreten. \"Native Titelleiste\" muss deaktiviert sein.",
|
||||
"restart-app-button": "Anwendung neustarten um Änderungen anzuwenden",
|
||||
"zoom-factor": "Zoomfaktor"
|
||||
},
|
||||
"note_autocomplete": {
|
||||
"search-for": "Suche nach \"{{term}}\"",
|
||||
"create-note": "Erstelle und verlinke Unternotiz \"{{term}}\"",
|
||||
"create-note": "Erstelle und verlinke untergeordnete Notiz \"{{term}}\"",
|
||||
"insert-external-link": "Einfügen von Externen Link zu \"{{term}}\"",
|
||||
"clear-text-field": "Textfeldinhalt löschen",
|
||||
"show-recent-notes": "Aktuelle Notizen anzeigen",
|
||||
@@ -1769,9 +1770,10 @@
|
||||
"quick-edit": "Schnellbearbeitung"
|
||||
},
|
||||
"geo-map": {
|
||||
"create-child-note-title": "Neue Unternotiz anlegen und zur Karte hinzufügen",
|
||||
"create-child-note-title": "Neue untergeordnete Notiz anlegen und zur Karte hinzufügen",
|
||||
"create-child-note-instruction": "Auf die Karte klicken, um eine neue Notiz an der Stelle zu erstellen oder Escape drücken um abzubrechen.",
|
||||
"unable-to-load-map": "Karte konnte nicht geladen werden."
|
||||
"unable-to-load-map": "Karte konnte nicht geladen werden.",
|
||||
"create-child-note-text": "Marker hinzufügen"
|
||||
},
|
||||
"geo-map-context": {
|
||||
"open-location": "Ort öffnen",
|
||||
@@ -1795,149 +1797,6 @@
|
||||
"close": "Schließen",
|
||||
"help_title": "Zeige mehr Informationen zu diesem Fenster"
|
||||
},
|
||||
"ai_llm": {
|
||||
"not_started": "Nicht gestartet",
|
||||
"title": "KI Einstellungen",
|
||||
"processed_notes": "Verarbeitete Notizen",
|
||||
"total_notes": "Gesamt Notizen",
|
||||
"progress": "Fortschritt",
|
||||
"queued_notes": "Eingereihte Notizen",
|
||||
"failed_notes": "Fehlgeschlagenen Notizen",
|
||||
"last_processed": "Zuletzt verarbeitet",
|
||||
"refresh_stats": "Statistiken neu laden",
|
||||
"enable_ai_features": "Aktiviere KI/LLM Funktionen",
|
||||
"enable_ai_description": "Aktiviere KI-Funktionen wie Notizzusammenfassungen, Inhaltserzeugung und andere LLM-Funktionen",
|
||||
"openai_tab": "OpenAI",
|
||||
"anthropic_tab": "Anthropic",
|
||||
"voyage_tab": "Voyage AI",
|
||||
"ollama_tab": "Ollama",
|
||||
"enable_ai": "Aktiviere KI/LLM Funktionen",
|
||||
"enable_ai_desc": "Aktiviere KI-Funktionen wie Notizzusammenfassungen, Inhaltserzeugung und andere LLM-Funktionen",
|
||||
"provider_configuration": "KI-Anbieterkonfiguration",
|
||||
"provider_precedence": "Anbieter Priorität",
|
||||
"provider_precedence_description": "Komma-getrennte Liste von Anbieter in der Reihenfolge ihrer Priorität (z.B. 'openai, anthropic,ollama')",
|
||||
"temperature": "Temperatur",
|
||||
"temperature_description": "Regelt die Zufälligkeit in Antworten (0 = deterministisch, 2 = maximale Zufälligkeit)",
|
||||
"system_prompt": "Systemaufforderung",
|
||||
"system_prompt_description": "Standard Systemaufforderung für alle KI-Interaktionen",
|
||||
"openai_configuration": "OpenAI Konfiguration",
|
||||
"openai_settings": "OpenAI Einstellungen",
|
||||
"api_key": "API Schlüssel",
|
||||
"url": "Basis-URL",
|
||||
"model": "Modell",
|
||||
"anthropic_settings": "Anthropic Einstellungen",
|
||||
"partial": "{{ percentage }}% verarbeitet",
|
||||
"anthropic_api_key_description": "Dein Anthropic API-Key für den Zugriff auf Claude Modelle",
|
||||
"anthropic_model_description": "Anthropic Claude Modell für Chat-Vervollständigung",
|
||||
"voyage_settings": "Einstellungen für Voyage AI",
|
||||
"ollama_url_description": "URL für die Ollama API (Standard: http://localhost:11434)",
|
||||
"ollama_model_description": "Ollama Modell für Chat-Vervollständigung",
|
||||
"anthropic_configuration": "Anthropic Konfiguration",
|
||||
"voyage_configuration": "Voyage AI Konfiguration",
|
||||
"voyage_url_description": "Standard: https://api.voyageai.com/v1",
|
||||
"ollama_configuration": "Ollama Konfiguration",
|
||||
"enable_ollama": "Aktiviere Ollama",
|
||||
"enable_ollama_description": "Aktiviere Ollama für lokale KI Modell Nutzung",
|
||||
"ollama_url": "Ollama URL",
|
||||
"ollama_model": "Ollama Modell",
|
||||
"refresh_models": "Aktualisiere Modelle",
|
||||
"refreshing_models": "Aktualisiere...",
|
||||
"enable_automatic_indexing": "Aktiviere automatische Indizierung",
|
||||
"rebuild_index": "Index neu aufbauen",
|
||||
"rebuild_index_error": "Fehler beim Neuaufbau des Index. Prüfe Log für mehr Informationen.",
|
||||
"retry_failed": "Fehler: Notiz konnte nicht erneut eingereiht werden",
|
||||
"max_notes_per_llm_query": "Max. Notizen je Abfrage",
|
||||
"max_notes_per_llm_query_description": "Maximale Anzahl ähnlicher Notizen zum Einbinden als KI Kontext",
|
||||
"active_providers": "Aktive Anbieter",
|
||||
"disabled_providers": "Inaktive Anbieter",
|
||||
"remove_provider": "Entferne Anbieter von Suche",
|
||||
"restore_provider": "Anbieter zur Suche wiederherstellen",
|
||||
"similarity_threshold": "Ähnlichkeitsschwelle",
|
||||
"similarity_threshold_description": "Mindestähnlichkeitswert (0-1) für Notizen, die im Kontext für LLM-Abfragen berücksichtigt werden sollen",
|
||||
"reprocess_index": "Suchindex neu erstellen",
|
||||
"reprocessing_index": "Neuerstellung...",
|
||||
"reprocess_index_started": "Suchindex-Optimierung wurde im Hintergrund gestartet",
|
||||
"reprocess_index_error": "Fehler beim Wiederaufbau des Suchindex",
|
||||
"index_rebuild_progress": "Fortschritt der Index-Neuerstellung",
|
||||
"index_rebuilding": "Optimierung Index ({{percentage}}%)",
|
||||
"index_rebuild_complete": "Index Optimierung abgeschlossen",
|
||||
"index_rebuild_status_error": "Fehler bei Überprüfung Status Index Neuerstellung",
|
||||
"never": "Niemals",
|
||||
"processing": "Verarbeitung ({{percentage}}%)",
|
||||
"refreshing": "Aktualisiere...",
|
||||
"incomplete": "Unvollständig ({{percentage}}%)",
|
||||
"complete": "Abgeschlossen (100%)",
|
||||
"auto_refresh_notice": "Auto-Aktualisierung alle {{seconds}} Sekunden",
|
||||
"note_queued_for_retry": "Notiz in Warteschlange für erneuten Versuch hinzugefügt",
|
||||
"failed_to_retry_note": "Wiederholungsversuch fehlgeschlagen für Notiz",
|
||||
"ai_settings": "KI Einstellungen",
|
||||
"agent": {
|
||||
"processing": "Verarbeite...",
|
||||
"thinking": "Nachdenken...",
|
||||
"loading": "Lade...",
|
||||
"generating": "Generiere..."
|
||||
},
|
||||
"name": "KI",
|
||||
"openai": "OpenAI",
|
||||
"use_enhanced_context": "Benutze verbesserten Kontext",
|
||||
"openai_api_key_description": "Dein OpenAPI-Key für den Zugriff auf den KI-Dienst",
|
||||
"default_model": "Standardmodell",
|
||||
"openai_model_description": "Beispiele: gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
|
||||
"base_url": "Basis URL",
|
||||
"openai_url_description": "Standard: https://api.openai.com/v1",
|
||||
"anthropic_url_description": "Basis URL für Anthropic API (Standard: https://api.anthropic.com)",
|
||||
"ollama_settings": "Ollama Einstellungen",
|
||||
"note_title": "Notiz Titel",
|
||||
"error": "Fehler",
|
||||
"last_attempt": "Letzter Versuch",
|
||||
"actions": "Aktionen",
|
||||
"retry": "Erneut versuchen",
|
||||
"retry_queued": "Notiz für weiteren Versuch eingereiht",
|
||||
"empty_key_warning": {
|
||||
"anthropic": "Anthropic API-Key ist leer. Bitte gültigen API-Key eingeben.",
|
||||
"openai": "OpenAI API-Key ist leer. Bitte gültigen API-Key eingeben.",
|
||||
"voyage": "Voyage API-Key ist leer. Bitte gültigen API-Key eingeben.",
|
||||
"ollama": "Ollama API-Key ist leer. Bitte gültigen API-Key eingeben."
|
||||
},
|
||||
"api_key_tooltip": "API-Key für den Zugriff auf den Dienst",
|
||||
"failed_to_retry_all": "Wiederholungsversuch für Notizen fehlgeschlagen",
|
||||
"all_notes_queued_for_retry": "Alle fehlgeschlagenen Notizen wurden zur Wiederholung in die Warteschlange gestellt",
|
||||
"enhanced_context_description": "Versorgt die KI mit mehr Kontext aus der Notiz und den zugehörigen Notizen, um bessere Antworten zu ermöglichen",
|
||||
"show_thinking": "Zeige Denkprozess",
|
||||
"show_thinking_description": "Zeige den Denkprozess der KI",
|
||||
"enter_message": "Geben Sie Ihre Nachricht ein...",
|
||||
"error_contacting_provider": "Fehler beim Kontaktieren des KI-Anbieters. Bitte überprüfe die Einstellungen und die Internetverbindung.",
|
||||
"error_generating_response": "Fehler beim Generieren der KI Antwort",
|
||||
"index_all_notes": "Indiziere alle Notizen",
|
||||
"index_status": "Indizierungsstatus",
|
||||
"indexed_notes": "Indizierte Notizen",
|
||||
"indexing_stopped": "Indizierung gestoppt",
|
||||
"indexing_in_progress": "Indizierung in Bearbeitung...",
|
||||
"last_indexed": "Zuletzt Indiziert",
|
||||
"note_chat": "Notizen-Chat",
|
||||
"sources": "Quellen",
|
||||
"start_indexing": "Starte Indizierung",
|
||||
"use_advanced_context": "Benutze erweiterten Kontext",
|
||||
"ollama_no_url": "Ollama ist nicht konfiguriert. Bitte trage eine gültige URL ein.",
|
||||
"chat": {
|
||||
"root_note_title": "KI Chats",
|
||||
"root_note_content": "Diese Notiz enthält gespeicherte KI-Chat-Unterhaltungen.",
|
||||
"new_chat_title": "Neuer Chat",
|
||||
"create_new_ai_chat": "Erstelle neuen KI Chat"
|
||||
},
|
||||
"create_new_ai_chat": "Erstelle neuen KI Chat",
|
||||
"configuration_warnings": "Es wurden Probleme mit der KI Konfiguration festgestellt. Bitte überprüfe die Einstellungen.",
|
||||
"experimental_warning": "Die LLM-Funktionen sind aktuell experimentell - sei an dieser Stelle gewarnt.",
|
||||
"selected_provider": "Ausgewählter Anbieter",
|
||||
"selected_provider_description": "Wähle einen KI-Anbieter für Chat- und Vervollständigungsfunktionen",
|
||||
"select_model": "Wähle Modell...",
|
||||
"select_provider": "Wähle Anbieter...",
|
||||
"ai_enabled": "KI Funktionen aktiviert",
|
||||
"ai_disabled": "KI Funktionen deaktiviert",
|
||||
"no_models_found_online": "Keine Modelle gefunden. Bitte überprüfe den API-Key und die Einstellungen.",
|
||||
"no_models_found_ollama": "Kein Ollama Modell gefunden. Bitte prüfe, ob Ollama gerade läuft.",
|
||||
"error_fetching": "Fehler beim Abrufen der Modelle: {{error}}"
|
||||
},
|
||||
"zen_mode": {
|
||||
"button_exit": "Verlasse Zen Modus"
|
||||
},
|
||||
@@ -1972,7 +1831,7 @@
|
||||
"no_totp_secret_warning": "Um TOTP zu aktivieren, muss zunächst ein TOTP Geheimnis generiert werden.",
|
||||
"totp_secret_description_warning": "Nach der Generierung des TOTP Geheimnisses ist eine Neuanmeldung mit dem TOTP Geheimnis erforderlich.",
|
||||
"totp_secret_generated": "TOTP Geheimnis generiert",
|
||||
"totp_secret_warning": "Bitte speichere das TOTP Geheimnis an einem sicheren Ort. Es wird nicht noch einmal angezeigt.",
|
||||
"totp_secret_warning": "Bitte speichere das generierte Geheimnis an einem sicheren Ort. Es wird nicht noch einmal angezeigt.",
|
||||
"totp_secret_regenerate_confirm": "Möchten Sie das TOTP-Geheimnis wirklich neu generieren? Dadurch werden das bisherige TOTP-Geheimnis und alle vorhandenen Wiederherstellungscodes ungültig.",
|
||||
"recovery_keys_title": "Einmalige Wiederherstellungsschlüssel",
|
||||
"recovery_keys_description": "Einmalige Wiederherstellungsschlüssel werden verwendet, um sich anzumelden, falls Sie keinen Zugriff auf Ihre Authentifizierungscodes haben.",
|
||||
@@ -2000,7 +1859,7 @@
|
||||
"check_share_root": "Status des Freigabe-Roots prüfen",
|
||||
"share_root_found": "Freigabe-Root-Notiz '{{noteTitle}}' ist bereit",
|
||||
"share_root_not_found": "Keine Notiz mit #shareRoot Label gefunden",
|
||||
"share_root_not_shared": "Notiz '{{noteTitle}}' hat das #shareRoot Label, wurde jedoch noch nicht geteilt"
|
||||
"share_root_not_shared": "Notiz '{{noteTitle}}' hat das #shareRoot Label, wurde jedoch noch nicht freigegeben"
|
||||
},
|
||||
"tasks": {
|
||||
"due": {
|
||||
@@ -2070,7 +1929,7 @@
|
||||
"show-hide-columns": "Zeige/verberge Spalten",
|
||||
"row-insert-above": "Zeile oberhalb einfügen",
|
||||
"row-insert-below": "Zeile unterhalb einfügen",
|
||||
"row-insert-child": "Unternotiz einfügen",
|
||||
"row-insert-child": "Untergeordnete Notiz einfügen",
|
||||
"add-column-to-the-left": "Spalte links einfügen",
|
||||
"add-column-to-the-right": "Spalte rechts einfügen",
|
||||
"edit-column": "Spalte editieren",
|
||||
@@ -2087,7 +1946,8 @@
|
||||
"raster": "Raster",
|
||||
"vector_light": "Vektor (Hell)",
|
||||
"vector_dark": "Vektor (Dunkel)",
|
||||
"show-scale": "Zeige Skalierung"
|
||||
"show-scale": "Zeige Skalierung",
|
||||
"show-labels": "Zeige Markierungsnamen"
|
||||
},
|
||||
"table_context_menu": {
|
||||
"delete_row": "Zeile entfernen"
|
||||
@@ -2118,8 +1978,8 @@
|
||||
"show_attachments_description": "Notizanhänge anzeigen",
|
||||
"search_notes_title": "Suche Notiz",
|
||||
"search_notes_description": "Öffne erweiterte Suche",
|
||||
"search_subtree_title": "Im Unterzweig suchen",
|
||||
"search_subtree_description": "Im aktuellen Unterzweig suchen",
|
||||
"search_subtree_title": "Im Zweig suchen",
|
||||
"search_subtree_description": "Im aktuellen Zweig suchen",
|
||||
"search_history_title": "Zeige Suchhistorie",
|
||||
"search_history_description": "Zeige vorherige Suchen",
|
||||
"configure_launch_bar_title": "Startleiste anpassen",
|
||||
@@ -2133,7 +1993,7 @@
|
||||
"next_theme_message": "Es wird aktuell das alte Design verwendet. Möchten Sie das neue Design ausprobieren?",
|
||||
"next_theme_button": "Teste das neue Design",
|
||||
"background_effects_title": "Hintergrundeffekte sind jetzt zuverlässig nutzbar",
|
||||
"background_effects_message": "Auf Windows-Geräten sind die Hintergrundeffekte nun vollständig stabil. Die Hintergrundeffekte verleihen der Benutzeroberfläche einen Farbakzent, indem der Hintergrund dahinter weichgezeichnet wird. Diese Technik wird auch in anderen Anwendungen wie dem Windows-Explorer eingesetzt.",
|
||||
"background_effects_message": "Auf Windows- und macOS-Geräten sind die Hintergrundeffekte nun stabil. Die Hintergrundeffekte verleihen der Benutzeroberfläche einen Farbakzent, indem der Hintergrund dahinter weichgezeichnet wird.",
|
||||
"background_effects_button": "Aktiviere Hintergrundeffekte",
|
||||
"dismiss": "Ablehnen",
|
||||
"new_layout_title": "Neues Layout",
|
||||
@@ -2154,8 +2014,9 @@
|
||||
"percentage": "%"
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "Seite {{startIndex}} von {{endIndex}}",
|
||||
"total_notes": "{{count}} Notizen"
|
||||
"total_notes": "{{count}} Notizen",
|
||||
"prev_page": "Vorherige Seite",
|
||||
"next_page": "Nächste Seite"
|
||||
},
|
||||
"collections": {
|
||||
"rendering_error": "Aufgrund eines Fehlers können keine Inhalte angezeigt werden."
|
||||
@@ -2188,9 +2049,9 @@
|
||||
"new_layout_description": "Probiere das neue Layout für eine modernere Darstellung und verbesserte Benutzbarkeit aus. Kann sich in Zukunft stark ändern."
|
||||
},
|
||||
"server": {
|
||||
"unknown_http_error_title": "Bei der Kommunikation mit dem Server ist ein Fehler aufgetreten",
|
||||
"unknown_http_error_title": "Kommunikationsfehler mit dem Server",
|
||||
"unknown_http_error_content": "Statuscode: {{statusCode}}\nURL: {{method}} {{url}}\nNachricht: {{message}}",
|
||||
"traefik_blocks_requests": "Der Traefik Reverse-Proxy hat ein fatales Update bekommen, welche die Kommunikation mit dem Server stört."
|
||||
"traefik_blocks_requests": "Der Traefik Reverse-Proxy hat eine Änderung erfahren, welches die Kommunikation mit dem Server beeinflusst."
|
||||
},
|
||||
"tab_history_navigation_buttons": {
|
||||
"go-back": "Zur vorherigen Notiz zurück kehren",
|
||||
@@ -2201,34 +2062,34 @@
|
||||
"hoisted_badge_title": "Abgesenkt",
|
||||
"workspace_badge": "Arbeitsfläche",
|
||||
"scroll_to_top_title": "Zum Anfang der Notiz springen",
|
||||
"create_new_note": "Neue Unternotiz erstellen",
|
||||
"create_new_note": "Neue untergeordnete Notiz erstellen",
|
||||
"empty_hide_archived_notes": "Archivierte Notizen ausblenden"
|
||||
},
|
||||
"breadcrumb_badges": {
|
||||
"read_only_explicit": "Nicht Änderbar",
|
||||
"read_only_explicit_description": "Diese Notiz wurde händisch als nicht änderbar markiert.\nKlicke hier um sie temporär zu bearbeiten.",
|
||||
"read_only_auto": "Automatisch nicht änderbar",
|
||||
"read_only_auto_description": "Diese Notiz wurde automatisch aus Leistungsgründen als nicht änderbar markiert. Dieses automatische Limit kann in den Einstellungen angepasst werden.\n\nKlicke hier, um sie temporär zu bearbeiten.",
|
||||
"read_only_explicit": "Schreibgeschützt",
|
||||
"read_only_explicit_description": "Diese Notiz wurde händisch schreibgeschützt.\nKlicke hier um sie temporär zu bearbeiten.",
|
||||
"read_only_auto": "Automatisch schreibgeschützt",
|
||||
"read_only_auto_description": "Diese Notiz wurde automatisch aus Leistungsgründen als schreibgeschützt markiert. Dieses automatische Limit kann in den Einstellungen angepasst werden.\n\nKlicke hier, um sie temporär zu bearbeiten.",
|
||||
"read_only_temporarily_disabled": "Temporär bearbeitbar",
|
||||
"read_only_temporarily_disabled_description": "Diese Notiz ist aktuell bearbeitbar, ist aber normalerweise nicht änderbar. Sobald du zu einer anderen Notiz navigierst, kehrt diese Notiz in ihren Normalzustand zurück.\n\nKlicke hier, um die Notiz wieder nicht änderbar zu machen.",
|
||||
"shared_publicly": "Öffentlich geteilt",
|
||||
"shared_locally": "Lokal geteilt",
|
||||
"read_only_temporarily_disabled_description": "Diese Notiz ist aktuell bearbeitbar, ist aber normalerweise schreibgeschützt. Sobald du zu einer anderen Notiz navigierst wird diese wieder schreibgeschützt.\n\nKlicke hier, um die Notiz wieder schreibgeschützt zu machen.",
|
||||
"shared_publicly": "Öffentlich freigegeben",
|
||||
"shared_locally": "Lokal freigegeben",
|
||||
"shared_copy_to_clipboard": "Link in die Zwischenablage kopieren",
|
||||
"shared_open_in_browser": "Link öffnen",
|
||||
"shared_unshare": "Teilen aufheben",
|
||||
"shared_open_in_browser": "Link im Browser öffnen",
|
||||
"shared_unshare": "Freigabe aufheben",
|
||||
"clipped_note": "Internetschnellverweis",
|
||||
"clipped_note_description": "Diese Notiz wurde von {{url}} übernommen.\n\nKlicke hier, um zum Ursprung zu gehen.",
|
||||
"clipped_note_description": "Diese Notiz wurde von {{url}} übernommen.\n\nKlicke hier, um zur Quelle zu gehen.",
|
||||
"execute_script": "Skript ausführen",
|
||||
"execute_script_description": "Diese Notiz ist eine Skriptnotiz. Klicke hier, um das Skript auszuführen.",
|
||||
"execute_sql": "SQL ausführen",
|
||||
"execute_sql_description": "Diese Notiz ist eine SQL-Notiz. Klicke hier, um die SQL-Abfrage auszuführen.",
|
||||
"save_status_saved": "Gespeichert",
|
||||
"save_status_saving": "Speichern...",
|
||||
"save_status_saving": "Speichere...",
|
||||
"save_status_unsaved": "Nicht gespeichert",
|
||||
"save_status_error": "Speichern fehlgeschlagen",
|
||||
"save_status_saving_tooltip": "Änderungen werden gespeichert.",
|
||||
"save_status_unsaved_tooltip": "Es gibt ungespeicherte Änderungen, welche gleich automatisch gespeichert werden.",
|
||||
"save_status_error_tooltip": "Beim speichern der Notiz ist ein Fehler aufgetreten. Wenn möglich, versuche die Notiz woandershin zu kopieren und die Applikation neu zu laden."
|
||||
"save_status_error_tooltip": "Beim speichern der Notiz ist ein Fehler aufgetreten. Wenn möglich, versuche die Notiz woandershin zu kopieren und die Anwendung neu zu laden."
|
||||
},
|
||||
"status_bar": {
|
||||
"language_title": "Inhaltssprache ändern",
|
||||
@@ -2241,7 +2102,7 @@
|
||||
"attachments_other": "{{count}} Anhänge",
|
||||
"attachments_title_one": "Anhang in einem neuen Tab öffnen",
|
||||
"attachments_title_other": "Anhänge in einem neuen Tab öffnen",
|
||||
"attributes_one": "{{count}} Attribute",
|
||||
"attributes_one": "{{count}} Attribut",
|
||||
"attributes_other": "{{count}} Attribute",
|
||||
"attributes_title": "Eigene und geerbte Attribute",
|
||||
"note_paths_one": "{{count}} Pfad",
|
||||
@@ -2254,9 +2115,9 @@
|
||||
},
|
||||
"right_pane": {
|
||||
"empty_message": "Für diese Notiz gibt es nichts anzuzeigen",
|
||||
"empty_button": "Anzeige ausblenden",
|
||||
"toggle": "Rechte Anzeige umschalten",
|
||||
"custom_widget_go_to_source": "Zum Ursprungscode"
|
||||
"empty_button": "Leiste ausblenden",
|
||||
"toggle": "Rechte Leiste umschalten",
|
||||
"custom_widget_go_to_source": "Zum Quellcode"
|
||||
},
|
||||
"pdf": {
|
||||
"attachments_one": "{{count}} Anhang",
|
||||
@@ -2266,6 +2127,108 @@
|
||||
"pages_one": "{{count}} Seite",
|
||||
"pages_other": "{{count}} Seiten",
|
||||
"pages_alt": "Seite {{pageNumber}}",
|
||||
"pages_loading": "Laden..."
|
||||
"pages_loading": "Lädt..."
|
||||
},
|
||||
"platform_indicator": {
|
||||
"available_on": "Verfügbar auf {{platform}}"
|
||||
},
|
||||
"mobile_tab_switcher": {
|
||||
"title_one": "{{count}} Tab",
|
||||
"title_other": "{{count}} Tabs",
|
||||
"more_options": "Weitere Optionen"
|
||||
},
|
||||
"bookmark_buttons": {
|
||||
"bookmarks": "Lesezeichen"
|
||||
},
|
||||
"web_view_setup": {
|
||||
"title": "Erstelle eine Live-Ansicht einer Webseite direkt in Trilium",
|
||||
"url_placeholder": "Gib oder füge die Adresse der Webseite ein, zum Beispiel https://triliumnotes.org",
|
||||
"create_button": "Erstelle Web Ansicht",
|
||||
"invalid_url_title": "Ungültige Adresse",
|
||||
"invalid_url_message": "Füge eine valide Webadresse ein, zum Beispiel https://triliumnotes.org.",
|
||||
"disabled_description": "Diese Webansicht wurde von einer externen Quelle importiert. Um Sie vor Phishing oder schädlichen Inhalten zu schützen, wird sie nicht automatisch geladen. Sie können sie aktivieren, wenn Sie der Quelle vertrauen.",
|
||||
"disabled_button_enable": "Webansicht aktivieren"
|
||||
},
|
||||
"render": {
|
||||
"setup_create_sample_html": "Eine Beispielnotiz mit HTML erstellen",
|
||||
"setup_create_sample_preact": "Eine Beispielnotiz mit Preact erstellen",
|
||||
"setup_title": "Benutzerdefiniertes HTML oder Preact JSX in dieser Notiz anzeigen",
|
||||
"setup_sample_created": "Eine Beispielnotiz wurde als untergeordnete Notiz erstellt.",
|
||||
"disabled_description": "Diese Rendering-Notizen stammen aus einer externen Quelle. Um Sie vor schädlichen Inhalten zu schützen, ist diese Funktion standardmäßig deaktiviert. Stellen Sie sicher, dass Sie der Quelle vertrauen, bevor Sie sie aktivieren.",
|
||||
"disabled_button_enable": "Rendering-Notiz aktivieren"
|
||||
},
|
||||
"active_content_badges": {
|
||||
"type_icon_pack": "Icon-Paket",
|
||||
"type_backend_script": "Backend-Skript",
|
||||
"type_frontend_script": "Frontend-Skript",
|
||||
"type_widget": "Widget",
|
||||
"type_app_css": "Benutzerdefiniertes CSS",
|
||||
"type_render_note": "Rendering-Notiz",
|
||||
"type_web_view": "Webansicht",
|
||||
"type_app_theme": "Benutzerdefiniertes Thema",
|
||||
"toggle_tooltip_enable_tooltip": "Klicken, um diesen {{type}} zu aktivieren.",
|
||||
"toggle_tooltip_disable_tooltip": "Klicken, um diesen {{type}} zu deaktivieren.",
|
||||
"menu_docs": "Dokumentation öffnen",
|
||||
"menu_execute_now": "Skript jetzt ausführen",
|
||||
"menu_run": "Automatisch ausführen",
|
||||
"menu_run_disabled": "Manuell",
|
||||
"menu_run_backend_startup": "Wenn das Backend startet",
|
||||
"menu_run_hourly": "Stündlich",
|
||||
"menu_run_daily": "Täglich",
|
||||
"menu_run_frontend_startup": "Wenn das Desktop-Frontend startet",
|
||||
"menu_run_mobile_startup": "Wenn das mobile Frontend startet",
|
||||
"menu_change_to_widget": "Zum Widget wechseln",
|
||||
"menu_change_to_frontend_script": "Zum Frontend-Skript wechseln",
|
||||
"menu_theme_base": "Themenbasis"
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "Mehr erfahren"
|
||||
},
|
||||
"media": {
|
||||
"play": "Abspielen (Arbeitsbereich)",
|
||||
"pause": "Pausieren (Arbeitsbereich)",
|
||||
"back-10s": "10 s zurück (Linke Pfeiltaste)",
|
||||
"forward-30s": "30 s vorwärts",
|
||||
"mute": "Stumm (M)",
|
||||
"unmute": "Stummschaltung aufheben (M)",
|
||||
"playback-speed": "Wiedergabegeschwindigkeit",
|
||||
"loop": "Schleife",
|
||||
"disable-loop": "Schleife deaktivieren",
|
||||
"rotate": "Rotieren",
|
||||
"picture-in-picture": "Bild-in-Bild",
|
||||
"exit-picture-in-picture": "Bild-in-Bild verlassen",
|
||||
"fullscreen": "Vollbild (F)",
|
||||
"exit-fullscreen": "Vollbild verlassen",
|
||||
"unsupported-format": "Medienvorschau ist für dieses Format nicht verfügbar:\n{{mime}}",
|
||||
"zoom-to-fit": "Zoomen um auszufüllen",
|
||||
"zoom-reset": "Zoomen um auszufüllen zurücksetzen"
|
||||
},
|
||||
"mermaid": {
|
||||
"placeholder": "Geben den Inhalt des Mermaid-Diagramms ein oder verwenden eine der folgenden Beispieldiagramme.",
|
||||
"sample_diagrams": "Beispieldiagramme:",
|
||||
"sample_flowchart": "Flussdiagramm",
|
||||
"sample_class": "Klasse",
|
||||
"sample_sequence": "Abfolge",
|
||||
"sample_entity_relationship": "Entität Beziehung",
|
||||
"sample_state": "Zustandsübergangsdiagramm",
|
||||
"sample_mindmap": "Mindmap",
|
||||
"sample_architecture": "Architektur",
|
||||
"sample_block": "Block",
|
||||
"sample_c4": "C4",
|
||||
"sample_gantt": "Gantt",
|
||||
"sample_git": "GitGraph",
|
||||
"sample_kanban": "Kanban",
|
||||
"sample_packet": "Paket",
|
||||
"sample_pie": "Kuchen",
|
||||
"sample_quadrant": "Quadrant",
|
||||
"sample_radar": "Radar",
|
||||
"sample_requirement": "Anforderung",
|
||||
"sample_sankey": "Sankey",
|
||||
"sample_timeline": "Zeitstrahl",
|
||||
"sample_treemap": "Kachel",
|
||||
"sample_user_journey": "Benutzererfahrung",
|
||||
"sample_xy": "XY",
|
||||
"sample_venn": "Mengen",
|
||||
"sample_ishikawa": "Ursache-Wirkung"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"about": {
|
||||
"title": "Πληροφορίες για το Trilium Notes",
|
||||
"title": "Σχετικά με το Trilium Notes",
|
||||
"homepage": "Αρχική Σελίδα:",
|
||||
"app_version": "Έκδοση εφαρμογής:",
|
||||
"db_version": "Έκδοση βάσης δεδομένων:",
|
||||
@@ -13,6 +13,61 @@
|
||||
"critical-error": {
|
||||
"title": "Κρίσιμο σφάλμα",
|
||||
"message": "Συνέβη κάποιο κρίσιμο σφάλμα, το οποίο δεν επιτρέπει στην εφαρμογή χρήστη να ξεκινήσει:\n\n{{message}}\n\nΤο πιθανότερο είναι να προκλήθηκε από κάποιο script που απέτυχε απρόοπτα. Δοκιμάστε να ξεκινήσετε την εφαρμογή σε ασφαλή λειτουργία για να λύσετε το πρόβλημα."
|
||||
}
|
||||
},
|
||||
"widget-error": {
|
||||
"title": "Δεν ήταν δυνατή η αρχικοποίηση του widget",
|
||||
"message-custom": "Προσαρμοσμένο widget της σημείωσης με ID \"{{id}}\", με τίτλο \"{{title}}\", δεν ήταν δυνατό να αρχικοποιηθεί λόγω:\n\n{{message}}",
|
||||
"message-unknown": "Άγνωστο widget δεν ήταν δυνατό να αρχικοποιηθεί λόγω:\n\n{{message}}"
|
||||
},
|
||||
"bundle-error": {
|
||||
"title": "Δεν ήταν δυνατή η φόρτωση προσαρμοσμένου script",
|
||||
"message": "Το script δεν ήταν δυνατό να εκτελεστεί λόγω:\n\n{{message}}"
|
||||
},
|
||||
"widget-list-error": {
|
||||
"title": "Δεν ήταν δυνατή η λήψη της λίστας των widgets από τον server"
|
||||
},
|
||||
"widget-render-error": {
|
||||
"title": "Δεν ήταν δυνατή η απόδοση προσαρμοσμένου React widget"
|
||||
},
|
||||
"widget-missing-parent": "Το προσαρμοσμένο widget δεν έχει ορισμένη την υποχρεωτική ιδιότητα '{{property}}'.\n\nΕάν το script προορίζεται για εκτέλεση χωρίς UI element, χρησιμοποιήστε '#run=frontendStartup' αντί για αυτό.",
|
||||
"open-script-note": "Άνοιγμα σημείωσης script",
|
||||
"scripting-error": "Σφάλμα προσαρμοσμένου script: {{title}}"
|
||||
},
|
||||
"bookmark_buttons": {
|
||||
"bookmarks": "Σελιδοδείκτες"
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "Προσθήκη συνδέσμου",
|
||||
"help_on_links": "Βοήθεια για συνδέσμους",
|
||||
"note": "Σημείωση",
|
||||
"search_note": "Αναζήτηση σημείωσης με βάση το όνομά της",
|
||||
"link_title_mirrors": "Ο τίτλος του συνδέσμου αντικατοπτρίζει τον τρέχοντα τίτλο της σημείωσης",
|
||||
"link_title_arbitrary": "Ο τίτλος του συνδέσμου μπορεί να τροποποιηθεί ελεύθερα",
|
||||
"link_title": "Τίτλος συνδέσμου",
|
||||
"button_add_link": "Προσθήκη συνδέσμου"
|
||||
},
|
||||
"branch_prefix": {
|
||||
"edit_branch_prefix": "Επεξεργασία προθέματος κλάδου",
|
||||
"edit_branch_prefix_multiple": "Επεξεργασία προθέματος κλάδου για {{count}} κλάδους",
|
||||
"help_on_tree_prefix": "Βοήθεια για πρόθεμα δέντρου",
|
||||
"prefix": "Πρόθεμα: ",
|
||||
"save": "Αποθήκευση",
|
||||
"branch_prefix_saved": "Το πρόθεμα κλάδου αποθηκεύτηκε.",
|
||||
"branch_prefix_saved_multiple": "Το πρόθεμα κλάδου αποθηκεύτηκε για {{count}} κλάδους.",
|
||||
"affected_branches": "Επηρεαζόμενοι κλάδοι ({{count}}):"
|
||||
},
|
||||
"bulk_actions": {
|
||||
"bulk_actions": "Μαζικές ενέργειες",
|
||||
"affected_notes": "Επηρεαζόμενες σημειώσεις",
|
||||
"include_descendants": "Συμπερίληψη απογόνων των επιλεγμένων σημειώσεων",
|
||||
"available_actions": "Διαθέσιμες ενέργειες",
|
||||
"chosen_actions": "Επιλεγμένες ενέργειες",
|
||||
"execute_bulk_actions": "Εκτέλεση μαζικών ενεργειών",
|
||||
"bulk_actions_executed": "Οι μαζικές ενέργειες εκτελέστηκαν επιτυχώς.",
|
||||
"none_yet": "Καμία ακόμη… προσθέστε μια ενέργεια επιλέγοντας μία από τις διαθέσιμες παραπάνω.",
|
||||
"labels": "Ετικέτες",
|
||||
"relations": "Συσχετίσεις",
|
||||
"notes": "Σημειώσεις",
|
||||
"other": "Λοιπά"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,11 +47,6 @@
|
||||
"attachment_detail_2": {
|
||||
"unrecognized_role": "Unrecognised attachment role '{{role}}'."
|
||||
},
|
||||
"ai_llm": {
|
||||
"reprocess_index_started": "Search index optimisation started in the background",
|
||||
"index_rebuilding": "Optimising index ({{percentage}}%)",
|
||||
"index_rebuild_complete": "Index optimisation complete"
|
||||
},
|
||||
"highlighting": {
|
||||
"color-scheme": "Colour Scheme"
|
||||
},
|
||||
|
||||
@@ -343,6 +343,7 @@
|
||||
"label_type_title": "Type of the label will help Trilium to choose suitable interface to enter the label value.",
|
||||
"label_type": "Type",
|
||||
"text": "Text",
|
||||
"textarea": "Multi-line Text",
|
||||
"number": "Number",
|
||||
"boolean": "Boolean",
|
||||
"date": "Date",
|
||||
@@ -368,7 +369,7 @@
|
||||
"calendar_root": "marks note which should be used as root for day notes. Only one should be marked as such.",
|
||||
"archived": "notes with this label won't be visible by default in search results (also in Jump To, Add Link dialogs etc).",
|
||||
"exclude_from_export": "notes (with their sub-tree) won't be included in any note export",
|
||||
"run": "defines on which events script should run. Possible values are:\n<ul>\n<li>frontendStartup - when Trilium frontend starts up (or is refreshed), but not on mobile.</li>\n<li>mobileStartup - when Trilium frontend starts up (or is refreshed), on mobile.</li>\n<li>backendStartup - when Trilium backend starts up</li>\n<li>hourly - run once an hour. You can use additional label <code>runAtHour</code> to specify at which hour.</li>\n<li>daily - run once a day</li>\n</ul>",
|
||||
"run": "defines on which events script should run. Possible values are:\n<ul>\n<li>frontendStartup - when Trilium frontend starts up (or is refreshed), but not on mobile.</li>\n<li>mobileStartup - when Trilium frontend starts up (or is refreshed), on mobile.</li>\n<li>backendStartup - when Trilium backend starts up.</li>\n<li>hourly - run once an hour. You can use additional label <code>runAtHour</code> to specify at which hour.</li>\n<li>daily - run once a day.</li>\n</ul>",
|
||||
"run_on_instance": "Define which trilium instance should run this on. Default to all instances.",
|
||||
"run_at_hour": "On which hour should this run. Should be used together with <code>#run=hourly</code>. Can be defined multiple times for more runs during the day.",
|
||||
"disable_inclusion": "scripts with this label won't be included into parent script execution.",
|
||||
@@ -662,7 +663,8 @@
|
||||
"show-cheatsheet": "Show Cheatsheet",
|
||||
"toggle-zen-mode": "Zen Mode",
|
||||
"new-version-available": "New Update Available",
|
||||
"download-update": "Get Version {{latestVersion}}"
|
||||
"download-update": "Get Version {{latestVersion}}",
|
||||
"search_notes": "Search notes"
|
||||
},
|
||||
"zen_mode": {
|
||||
"button_exit": "Exit Zen Mode"
|
||||
@@ -689,6 +691,7 @@
|
||||
"search_in_note": "Search in note",
|
||||
"note_source": "Note source",
|
||||
"note_attachments": "Note attachments",
|
||||
"view_ocr_text": "View OCR text",
|
||||
"open_note_externally": "Open note externally",
|
||||
"open_note_externally_title": "File will be open in an external application and watched for changes. You'll then be able to upload the modified version back to Trilium.",
|
||||
"open_note_custom": "Open note custom",
|
||||
@@ -745,7 +748,7 @@
|
||||
"button_title": "Export diagram as SVG"
|
||||
},
|
||||
"relation_map_buttons": {
|
||||
"create_child_note_title": "Create new child note and add it into this relation map",
|
||||
"create_child_note_title": "Create child note and add it to map",
|
||||
"reset_pan_zoom_title": "Reset pan & zoom to initial coordinates and magnification",
|
||||
"zoom_in_title": "Zoom In",
|
||||
"zoom_out_title": "Zoom Out"
|
||||
@@ -760,7 +763,9 @@
|
||||
"delete_this_note": "Delete this note",
|
||||
"note_revisions": "Note revisions",
|
||||
"error_cannot_get_branch_id": "Cannot get branchId for notePath '{{notePath}}'",
|
||||
"error_unrecognized_command": "Unrecognized command {{command}}"
|
||||
"error_unrecognized_command": "Unrecognized command {{command}}",
|
||||
"backlinks": "Backlinks",
|
||||
"content_language_switcher": "Content language: {{language}}"
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "Change note icon",
|
||||
@@ -905,6 +910,7 @@
|
||||
"debug": "debug",
|
||||
"debug_description": "Debug will print extra debugging information into the console to aid in debugging complex queries",
|
||||
"action": "action",
|
||||
"option": "option",
|
||||
"search_button": "Search",
|
||||
"search_execute": "Search & Execute actions",
|
||||
"save_to_note": "Save to note",
|
||||
@@ -1006,7 +1012,7 @@
|
||||
"no_attachments": "This note has no attachments."
|
||||
},
|
||||
"book": {
|
||||
"no_children_help": "This collection doesn't have any child notes so there's nothing to display. See <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> for details.",
|
||||
"no_children_help": "This collection doesn't have any child notes so there's nothing to display.",
|
||||
"drag_locked_title": "Locked for editing",
|
||||
"drag_locked_message": "Dragging not allowed since the collection is locked for editing."
|
||||
},
|
||||
@@ -1032,6 +1038,25 @@
|
||||
"file_preview_not_available": "File preview is not available for this file format.",
|
||||
"too_big": "The preview only shows the first {{maxNumChars}} characters of the file for performance reasons. Download the file and open it externally to be able to see the entire content."
|
||||
},
|
||||
"media": {
|
||||
"play": "Play (Space)",
|
||||
"pause": "Pause (Space)",
|
||||
"back-10s": "Back 10s (Left arrow key)",
|
||||
"forward-30s": "Forward 30s",
|
||||
"mute": "Mute (M)",
|
||||
"unmute": "Unmute (M)",
|
||||
"playback-speed": "Playback speed",
|
||||
"loop": "Loop",
|
||||
"disable-loop": "Disable loop",
|
||||
"rotate": "Rotate",
|
||||
"picture-in-picture": "Picture-in-picture",
|
||||
"exit-picture-in-picture": "Exit picture-in-picture",
|
||||
"fullscreen": "Fullscreen (F)",
|
||||
"exit-fullscreen": "Exit fullscreen",
|
||||
"unsupported-format": "Media preview is not available for this file format:\n{{mime}}",
|
||||
"zoom-to-fit": "Zoom to fill",
|
||||
"zoom-reset": "Reset zoom to fill"
|
||||
},
|
||||
"protected_session": {
|
||||
"enter_password_instruction": "Showing protected note requires entering your password:",
|
||||
"start_session_button": "Start protected session",
|
||||
@@ -1045,7 +1070,6 @@
|
||||
"unprotecting-title": "Unprotecting status"
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "Open in new tab",
|
||||
"remove_note": "Remove note",
|
||||
"edit_title": "Edit title",
|
||||
"rename_note": "Rename note",
|
||||
@@ -1063,13 +1087,21 @@
|
||||
"click_on_canvas_to_place_new_note": "Click on canvas to place new note"
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_1": "This help note is shown because this note of type Render HTML doesn't have required relation to function properly.",
|
||||
"note_detail_render_help_2": "Render HTML note type is used for <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">scripting</a>. In short, you have a HTML code note (optionally with some JavaScript) and this note will render it. To make it work, you need to define a <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">relation</a> called \"renderNote\" pointing to the HTML note to render."
|
||||
"setup_title": "Display custom HTML or Preact JSX inside this note",
|
||||
"setup_create_sample_preact": "Create sample note with Preact",
|
||||
"setup_create_sample_html": "Create sample note with HTML",
|
||||
"setup_sample_created": "A sample note was created as a child note.",
|
||||
"disabled_description": "This render notes comes from an external source. To protect you from malicious content, it is not enabled by default. Make sure you trust the source before enabling it.",
|
||||
"disabled_button_enable": "Enable render note"
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "Web View",
|
||||
"embed_websites": "Note of type Web View allows you to embed websites into Trilium.",
|
||||
"create_label": "To start, please create a label with a URL address you want to embed, e.g. #webViewSrc=\"https://www.google.com\""
|
||||
"web_view_setup": {
|
||||
"title": "Create a live view of a webpage directly into Trilium",
|
||||
"url_placeholder": "Enter or paste the website address, for example https://triliumnotes.org",
|
||||
"create_button": "Create Web View",
|
||||
"invalid_url_title": "Invalid address",
|
||||
"invalid_url_message": "Insert a valid web address, for example https://triliumnotes.org.",
|
||||
"disabled_description": "This web view was imported from an external source. To help protect you from phishing or malicious content, it isn’t loading automatically. You can enable it if you trust the source.",
|
||||
"disabled_button_enable": "Enable web view"
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "Refresh"
|
||||
@@ -1126,7 +1158,9 @@
|
||||
"title": "Experimental Options",
|
||||
"disclaimer": "These options are experimental and may cause instability. Use with caution.",
|
||||
"new_layout_name": "New Layout",
|
||||
"new_layout_description": "Try out the new layout for a more modern look and improved usability. Subject to heavy change in the upcoming releases."
|
||||
"new_layout_description": "Try out the new layout for a more modern look and improved usability. Subject to heavy change in the upcoming releases.",
|
||||
"llm_name": "AI / LLM Chat",
|
||||
"llm_description": "Enable the AI chat sidebar and LLM chat notes powered by large language models."
|
||||
},
|
||||
"fonts": {
|
||||
"theme_defined": "Theme defined",
|
||||
@@ -1192,149 +1226,6 @@
|
||||
"enable-smooth-scroll": "Enable smooth scrolling",
|
||||
"app-restart-required": "(a restart of the application is required for the change to take effect)"
|
||||
},
|
||||
"ai_llm": {
|
||||
"not_started": "Not started",
|
||||
"title": "AI Settings",
|
||||
"processed_notes": "Processed Notes",
|
||||
"total_notes": "Total Notes",
|
||||
"progress": "Progress",
|
||||
"queued_notes": "Queued Notes",
|
||||
"failed_notes": "Failed Notes",
|
||||
"last_processed": "Last Processed",
|
||||
"refresh_stats": "Refresh Statistics",
|
||||
"enable_ai_features": "Enable AI/LLM features",
|
||||
"enable_ai_description": "Enable AI features like note summarization, content generation, and other LLM capabilities",
|
||||
"openai_tab": "OpenAI",
|
||||
"anthropic_tab": "Anthropic",
|
||||
"voyage_tab": "Voyage AI",
|
||||
"ollama_tab": "Ollama",
|
||||
"enable_ai": "Enable AI/LLM features",
|
||||
"enable_ai_desc": "Enable AI features like note summarization, content generation, and other LLM capabilities",
|
||||
"provider_configuration": "AI Provider Configuration",
|
||||
"provider_precedence": "Provider Precedence",
|
||||
"provider_precedence_description": "Comma-separated list of providers in order of precedence (e.g., 'openai,anthropic,ollama')",
|
||||
"temperature": "Temperature",
|
||||
"temperature_description": "Controls randomness in responses (0 = deterministic, 2 = maximum randomness)",
|
||||
"system_prompt": "System Prompt",
|
||||
"system_prompt_description": "Default system prompt used for all AI interactions",
|
||||
"openai_configuration": "OpenAI Configuration",
|
||||
"openai_settings": "OpenAI Settings",
|
||||
"api_key": "API Key",
|
||||
"url": "Base URL",
|
||||
"model": "Model",
|
||||
"openai_api_key_description": "Your OpenAI API key for accessing their AI services",
|
||||
"anthropic_api_key_description": "Your Anthropic API key for accessing Claude models",
|
||||
"default_model": "Default Model",
|
||||
"openai_model_description": "Examples: gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
|
||||
"base_url": "Base URL",
|
||||
"openai_url_description": "Default: https://api.openai.com/v1",
|
||||
"anthropic_settings": "Anthropic Settings",
|
||||
"anthropic_url_description": "Base URL for the Anthropic API (default: https://api.anthropic.com)",
|
||||
"anthropic_model_description": "Anthropic Claude models for chat completion",
|
||||
"voyage_settings": "Voyage AI Settings",
|
||||
"ollama_settings": "Ollama Settings",
|
||||
"ollama_url_description": "URL for the Ollama API (default: http://localhost:11434)",
|
||||
"ollama_model_description": "Ollama model to use for chat completion",
|
||||
"anthropic_configuration": "Anthropic Configuration",
|
||||
"voyage_configuration": "Voyage AI Configuration",
|
||||
"voyage_url_description": "Default: https://api.voyageai.com/v1",
|
||||
"ollama_configuration": "Ollama Configuration",
|
||||
"enable_ollama": "Enable Ollama",
|
||||
"enable_ollama_description": "Enable Ollama for local AI model usage",
|
||||
"ollama_url": "Ollama URL",
|
||||
"ollama_model": "Ollama Model",
|
||||
"refresh_models": "Refresh Models",
|
||||
"refreshing_models": "Refreshing...",
|
||||
"enable_automatic_indexing": "Enable Automatic Indexing",
|
||||
"rebuild_index": "Rebuild Index",
|
||||
"rebuild_index_error": "Error starting index rebuild. Check logs for details.",
|
||||
"note_title": "Note Title",
|
||||
"error": "Error",
|
||||
"last_attempt": "Last Attempt",
|
||||
"actions": "Actions",
|
||||
"retry": "Retry",
|
||||
"partial": "{{ percentage }}% completed",
|
||||
"retry_queued": "Note queued for retry",
|
||||
"retry_failed": "Failed to queue note for retry",
|
||||
"max_notes_per_llm_query": "Max Notes Per Query",
|
||||
"max_notes_per_llm_query_description": "Maximum number of similar notes to include in AI context",
|
||||
"active_providers": "Active Providers",
|
||||
"disabled_providers": "Disabled Providers",
|
||||
"remove_provider": "Remove provider from search",
|
||||
"restore_provider": "Restore provider to search",
|
||||
"similarity_threshold": "Similarity Threshold",
|
||||
"similarity_threshold_description": "Minimum similarity score (0-1) for notes to be included in context for LLM queries",
|
||||
"reprocess_index": "Rebuild Search Index",
|
||||
"reprocessing_index": "Rebuilding...",
|
||||
"reprocess_index_started": "Search index optimization started in the background",
|
||||
"reprocess_index_error": "Error rebuilding search index",
|
||||
"index_rebuild_progress": "Index Rebuild Progress",
|
||||
"index_rebuilding": "Optimizing index ({{percentage}}%)",
|
||||
"index_rebuild_complete": "Index optimization complete",
|
||||
"index_rebuild_status_error": "Error checking index rebuild status",
|
||||
"never": "Never",
|
||||
"processing": "Processing ({{percentage}}%)",
|
||||
"incomplete": "Incomplete ({{percentage}}%)",
|
||||
"complete": "Complete (100%)",
|
||||
"refreshing": "Refreshing...",
|
||||
"auto_refresh_notice": "Auto-refreshes every {{seconds}} seconds",
|
||||
"note_queued_for_retry": "Note queued for retry",
|
||||
"failed_to_retry_note": "Failed to retry note",
|
||||
"all_notes_queued_for_retry": "All failed notes queued for retry",
|
||||
"failed_to_retry_all": "Failed to retry notes",
|
||||
"ai_settings": "AI Settings",
|
||||
"api_key_tooltip": "API key for accessing the service",
|
||||
"empty_key_warning": {
|
||||
"anthropic": "Anthropic API key is empty. Please enter a valid API key.",
|
||||
"openai": "OpenAI API key is empty. Please enter a valid API key.",
|
||||
"voyage": "Voyage API key is empty. Please enter a valid API key.",
|
||||
"ollama": "Ollama API key is empty. Please enter a valid API key."
|
||||
},
|
||||
"agent": {
|
||||
"processing": "Processing...",
|
||||
"thinking": "Thinking...",
|
||||
"loading": "Loading...",
|
||||
"generating": "Generating..."
|
||||
},
|
||||
"name": "AI",
|
||||
"openai": "OpenAI",
|
||||
"use_enhanced_context": "Use enhanced context",
|
||||
"enhanced_context_description": "Provides the AI with more context from the note and its related notes for better responses",
|
||||
"show_thinking": "Show thinking",
|
||||
"show_thinking_description": "Show the AI's chain of thought process",
|
||||
"enter_message": "Enter your message...",
|
||||
"error_contacting_provider": "Error contacting AI provider. Please check your settings and internet connection.",
|
||||
"error_generating_response": "Error generating AI response",
|
||||
"index_all_notes": "Index All Notes",
|
||||
"index_status": "Index Status",
|
||||
"indexed_notes": "Indexed Notes",
|
||||
"indexing_stopped": "Indexing stopped",
|
||||
"indexing_in_progress": "Indexing in progress...",
|
||||
"last_indexed": "Last Indexed",
|
||||
"note_chat": "Note Chat",
|
||||
"sources": "Sources",
|
||||
"start_indexing": "Start Indexing",
|
||||
"use_advanced_context": "Use Advanced Context",
|
||||
"ollama_no_url": "Ollama is not configured. Please enter a valid URL.",
|
||||
"chat": {
|
||||
"root_note_title": "AI Chats",
|
||||
"root_note_content": "This note contains your saved AI chat conversations.",
|
||||
"new_chat_title": "New Chat",
|
||||
"create_new_ai_chat": "Create new AI Chat"
|
||||
},
|
||||
"create_new_ai_chat": "Create new AI Chat",
|
||||
"configuration_warnings": "There are some issues with your AI configuration. Please check your settings.",
|
||||
"experimental_warning": "The LLM feature is currently experimental - you have been warned.",
|
||||
"selected_provider": "Selected Provider",
|
||||
"selected_provider_description": "Choose the AI provider for chat and completion features",
|
||||
"select_model": "Select model...",
|
||||
"select_provider": "Select provider...",
|
||||
"ai_enabled": "AI features enabled",
|
||||
"ai_disabled": "AI features disabled",
|
||||
"no_models_found_online": "No models found. Please check your API key and settings.",
|
||||
"no_models_found_ollama": "No Ollama models found. Please check if Ollama is running.",
|
||||
"error_fetching": "Error fetching models: {{error}}"
|
||||
},
|
||||
"zoom_factor": {
|
||||
"title": "Zoom Factor (desktop build only)",
|
||||
"description": "Zooming can be controlled with CTRL+- and CTRL+= shortcuts as well."
|
||||
@@ -1364,12 +1255,28 @@
|
||||
},
|
||||
"images": {
|
||||
"images_section_title": "Images",
|
||||
"download_images_automatically": "Download images automatically for offline use.",
|
||||
"download_images_description": "Pasted HTML can contain references to online images, Trilium will find those references and download the images so that they are available offline.",
|
||||
"enable_image_compression": "Enable image compression",
|
||||
"max_image_dimensions": "Max width / height of an image (image will be resized if it exceeds this setting).",
|
||||
"download_images_automatically": "Download images automatically",
|
||||
"download_images_description": "Download referenced online images from pasted HTML so they are available offline.",
|
||||
"enable_image_compression": "Image compression",
|
||||
"enable_image_compression_description": "Compress and resize images when they are uploaded or pasted.",
|
||||
"max_image_dimensions": "Max image dimensions",
|
||||
"max_image_dimensions_description": "Images exceeding this size will be resized automatically.",
|
||||
"max_image_dimensions_unit": "pixels",
|
||||
"jpeg_quality_description": "JPEG quality (10 - worst quality, 100 - best quality, 50 - 85 is recommended)"
|
||||
"jpeg_quality": "JPEG quality",
|
||||
"jpeg_quality_description": "Recommended range is 50–85. Lower values reduce file size, higher values preserve detail.",
|
||||
"ocr_section_title": "Text Extraction (OCR)",
|
||||
"ocr_related_content_languages": "Content languages (used for text extraction)",
|
||||
"ocr_auto_process": "Auto-process new files",
|
||||
"ocr_auto_process_description": "Automatically extract text from newly uploaded or pasted files.",
|
||||
"ocr_min_confidence": "Minimum confidence",
|
||||
"ocr_confidence_description": "Only extract text above this confidence threshold. Lower values include more text but may be less accurate.",
|
||||
"batch_ocr_title": "Process Existing Files",
|
||||
"batch_ocr_description": "Extract text from all existing images, PDFs, and Office documents in your notes. This may take some time depending on the number of files.",
|
||||
"batch_ocr_start": "Start Batch Processing",
|
||||
"batch_ocr_starting": "Starting batch processing...",
|
||||
"batch_ocr_progress": "Processing {{processed}} of {{total}} files...",
|
||||
"batch_ocr_completed": "Batch processing completed! Processed {{processed}} files.",
|
||||
"batch_ocr_error": "Error during batch processing: {{error}}"
|
||||
},
|
||||
"attachment_erasure_timeout": {
|
||||
"attachment_erasure_timeout": "Attachment Erasure Timeout",
|
||||
@@ -1415,7 +1322,7 @@
|
||||
"custom_name_label": "Custom search engine name",
|
||||
"custom_name_placeholder": "Customize search engine name",
|
||||
"custom_url_label": "Custom search engine URL should include {keyword} as a placeholder for the search term.",
|
||||
"custom_url_placeholder": "Customize search engine url",
|
||||
"custom_url_placeholder": "Customize search engine URL",
|
||||
"save_button": "Save"
|
||||
},
|
||||
"tray": {
|
||||
@@ -1585,7 +1492,8 @@
|
||||
"description": "Description",
|
||||
"reload_app": "Reload app to apply changes",
|
||||
"set_all_to_default": "Set all shortcuts to the default",
|
||||
"confirm_reset": "Do you really want to reset all keyboard shortcuts to the default?"
|
||||
"confirm_reset": "Do you really want to reset all keyboard shortcuts to the default?",
|
||||
"no_results": "No shortcuts found matching '{{filter}}'"
|
||||
},
|
||||
"spellcheck": {
|
||||
"title": "Spell Check",
|
||||
@@ -1710,9 +1618,11 @@
|
||||
"geo-map": "Geo Map",
|
||||
"beta-feature": "Beta",
|
||||
"ai-chat": "AI Chat",
|
||||
"llm-chat": "AI Chat",
|
||||
"task-list": "Task List",
|
||||
"new-feature": "New",
|
||||
"collections": "Collections"
|
||||
"collections": "Collections",
|
||||
"spreadsheet": "Spreadsheet"
|
||||
},
|
||||
"protect_note": {
|
||||
"toggle-on": "Protect the note",
|
||||
@@ -1720,6 +1630,48 @@
|
||||
"toggle-on-hint": "Note is not protected, click to make it protected",
|
||||
"toggle-off-hint": "Note is protected, click to make it unprotected"
|
||||
},
|
||||
"llm_chat": {
|
||||
"placeholder": "Type a message...",
|
||||
"send": "Send",
|
||||
"sending": "Sending...",
|
||||
"empty_state": "Start a conversation by typing a message below.",
|
||||
"searching_web": "Searching the web...",
|
||||
"web_search": "Web search",
|
||||
"note_tools": "Note access",
|
||||
"sources": "Sources",
|
||||
"sources_summary": "{{count}} sources from {{sites}} sites",
|
||||
"extended_thinking": "Extended thinking",
|
||||
"legacy_models": "Legacy models",
|
||||
"thinking": "Thinking...",
|
||||
"thought_process": "Thought process",
|
||||
"tool_calls": "{{count}} tool call(s)",
|
||||
"input": "Input",
|
||||
"result": "Result",
|
||||
"error": "Error",
|
||||
"tool_error": "failed",
|
||||
"total_tokens": "{{total}} tokens",
|
||||
"tokens_detail": "{{prompt}} prompt + {{completion}} completion",
|
||||
"tokens_used": "{{prompt}} prompt + {{completion}} completion = {{total}} tokens",
|
||||
"tokens_used_with_cost": "{{prompt}} prompt + {{completion}} completion = {{total}} tokens (~${{cost}})",
|
||||
"tokens_used_with_model": "{{model}}: {{prompt}} prompt + {{completion}} completion = {{total}} tokens",
|
||||
"tokens_used_with_model_and_cost": "{{model}}: {{prompt}} prompt + {{completion}} completion = {{total}} tokens (~${{cost}})",
|
||||
"tokens": "tokens",
|
||||
"context_used": "{{percentage}}% used",
|
||||
"note_context_enabled": "Click to disable note context: {{title}}",
|
||||
"note_context_disabled": "Click to include current note in context",
|
||||
"no_provider_message": "No AI provider configured. Add one to start chatting.",
|
||||
"add_provider": "Add AI Provider"
|
||||
},
|
||||
"sidebar_chat": {
|
||||
"title": "AI Chat",
|
||||
"launcher_title": "Open AI Chat",
|
||||
"new_chat": "Start new chat",
|
||||
"save_chat": "Save chat to notes",
|
||||
"empty_state": "Start a conversation",
|
||||
"history": "Chat history",
|
||||
"recent_chats": "Recent chats",
|
||||
"no_chats": "No previous chats"
|
||||
},
|
||||
"shared_switch": {
|
||||
"shared": "Shared",
|
||||
"toggle-on-title": "Share the note",
|
||||
@@ -1791,6 +1743,8 @@
|
||||
"printing": "Printing in progress...",
|
||||
"printing_pdf": "Exporting to PDF in progress...",
|
||||
"print_report_title": "Print report",
|
||||
"print_report_error_title": "Failed to print",
|
||||
"print_report_stack_trace": "Stack trace",
|
||||
"print_report_collection_content_one": "{{count}} note in the collection could not be printed because they are not supported or they are protected.",
|
||||
"print_report_collection_content_other": "{{count}} notes in the collection could not be printed because they are not supported or they are protected.",
|
||||
"print_report_collection_details_button": "See details",
|
||||
@@ -1809,7 +1763,8 @@
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "No notes have been found for given search parameters.",
|
||||
"search_not_executed": "Search has not been executed yet. Click on \"Search\" button above to see the results."
|
||||
"search_not_executed": "Search has not been executed yet.",
|
||||
"search_now": "Search now"
|
||||
},
|
||||
"spacer": {
|
||||
"configure_launchbar": "Configure Launchbar"
|
||||
@@ -1937,6 +1892,7 @@
|
||||
"add-term-to-dictionary": "Add \"{{term}}\" to dictionary",
|
||||
"cut": "Cut",
|
||||
"copy": "Copy",
|
||||
"copy-as-markdown": "Copy as Markdown",
|
||||
"copy-link": "Copy link",
|
||||
"paste": "Paste",
|
||||
"paste-as-plain-text": "Paste as plain text",
|
||||
@@ -1958,8 +1914,8 @@
|
||||
"desktop-application": "Desktop Application",
|
||||
"native-title-bar": "Native title bar",
|
||||
"native-title-bar-description": "For Windows and macOS, keeping the native title bar off makes the application look more compact. On Linux, keeping the native title bar on integrates better with the rest of the system.",
|
||||
"background-effects": "Enable background effects (Windows 11 only)",
|
||||
"background-effects-description": "The Mica effect adds a blurred, stylish background to app windows, creating depth and a modern look. \"Native title bar\" must be disabled.",
|
||||
"background-effects": "Enable background effects",
|
||||
"background-effects-description": "Adds a blurred, stylish background to app windows, creating depth and a modern look. \"Native title bar\" must be disabled.",
|
||||
"restart-app-button": "Restart the application to view the changes",
|
||||
"zoom-factor": "Zoom factor"
|
||||
},
|
||||
@@ -1977,6 +1933,7 @@
|
||||
},
|
||||
"geo-map": {
|
||||
"create-child-note-title": "Create a new child note and add it to the map",
|
||||
"create-child-note-text": "Add marker",
|
||||
"create-child-note-instruction": "Click on the map to create a new note at that location or press Escape to dismiss.",
|
||||
"unable-to-load-map": "Unable to load map."
|
||||
},
|
||||
@@ -2026,7 +1983,7 @@
|
||||
},
|
||||
"content_language": {
|
||||
"title": "Content languages",
|
||||
"description": "Select one or more languages that should appear in the language selection in the Basic Properties section of a read-only or editable text note. This will allow features such as spell-checking or right-to-left support."
|
||||
"description": "Select one or more languages that should appear in the language selection in the Basic Properties section of a read-only or editable text note. This will allow features such as spell-checking, right-to-left support and text extraction (OCR)."
|
||||
},
|
||||
"switch_layout_button": {
|
||||
"title_vertical": "Move editing pane to the bottom",
|
||||
@@ -2094,7 +2051,8 @@
|
||||
"raster": "Raster",
|
||||
"vector_light": "Vector (Light)",
|
||||
"vector_dark": "Vector (Dark)",
|
||||
"show-scale": "Show scale"
|
||||
"show-scale": "Show scale",
|
||||
"show-labels": "Show marker names"
|
||||
},
|
||||
"table_context_menu": {
|
||||
"delete_row": "Delete row"
|
||||
@@ -2125,6 +2083,22 @@
|
||||
"calendar_view": {
|
||||
"delete_note": "Delete note..."
|
||||
},
|
||||
"ocr": {
|
||||
"extracted_text": "Extracted Text (OCR)",
|
||||
"extracted_text_title": "Extracted Text (OCR)",
|
||||
"loading_text": "Loading OCR text...",
|
||||
"no_text_available": "No OCR text available",
|
||||
"no_text_explanation": "This note has not been processed for OCR text extraction or no text was found.",
|
||||
"failed_to_load": "Failed to load OCR text",
|
||||
"process_now": "Process OCR",
|
||||
"processing": "Processing...",
|
||||
"processing_started": "OCR processing has been started. Please wait a moment and refresh.",
|
||||
"processing_complete": "OCR processing complete.",
|
||||
"processing_failed": "Failed to start OCR processing",
|
||||
"text_filtered_low_confidence": "OCR detected text with {{confidence}}% confidence, but it was discarded because your minimum threshold is {{threshold}}%.",
|
||||
"open_media_settings": "Open Settings",
|
||||
"view_extracted_text": "View extracted text (OCR)"
|
||||
},
|
||||
"command_palette": {
|
||||
"tree-action-name": "Tree: {{name}}",
|
||||
"export_note_title": "Export Note",
|
||||
@@ -2152,7 +2126,7 @@
|
||||
"next_theme_message": "You are currently using the legacy theme, would you like to try the new theme?",
|
||||
"next_theme_button": "Try the new theme",
|
||||
"background_effects_title": "Background effects are now stable",
|
||||
"background_effects_message": "On Windows devices, background effects are now fully stable. The background effects adds a touch of color to the user interface by blurring the background behind it. This technique is also used in other applications such as Windows Explorer.",
|
||||
"background_effects_message": "On Windows and macOS devices, background effects are now stable. The background effects adds a touch of color to the user interface by blurring the background behind it.",
|
||||
"background_effects_button": "Enable background effects",
|
||||
"new_layout_title": "New layout",
|
||||
"new_layout_message": "We’ve introduced a modernized layout for Trilium. The ribbon has been removed and seamlessly integrated into the main interface, with a new status bar and expandable sections (such as promoted attributes) taking over key functions.\n\nThe new layout is enabled by default, and can be temporarily disabled via Options → Appearance.",
|
||||
@@ -2173,8 +2147,9 @@
|
||||
"percentage": "%"
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "Page of {{startIndex}} - {{endIndex}}",
|
||||
"total_notes": "{{count}} notes"
|
||||
"total_notes": "{{count}} notes",
|
||||
"prev_page": "Previous page",
|
||||
"next_page": "Next page"
|
||||
},
|
||||
"collections": {
|
||||
"rendering_error": "Unable to show content due to an error."
|
||||
@@ -2267,5 +2242,128 @@
|
||||
"pages_other": "{{count}} pages",
|
||||
"pages_alt": "Page {{pageNumber}}",
|
||||
"pages_loading": "Loading..."
|
||||
},
|
||||
"platform_indicator": {
|
||||
"available_on": "Available on {{platform}}"
|
||||
},
|
||||
"mobile_tab_switcher": {
|
||||
"title_one": "{{count}} tab",
|
||||
"title_other": "{{count}} tabs",
|
||||
"more_options": "More options"
|
||||
},
|
||||
"bookmark_buttons": {
|
||||
"bookmarks": "Bookmarks"
|
||||
},
|
||||
"active_content_badges": {
|
||||
"type_icon_pack": "Icon pack",
|
||||
"type_backend_script": "Backend script",
|
||||
"type_frontend_script": "Frontend script",
|
||||
"type_widget": "Widget",
|
||||
"type_app_css": "Custom CSS",
|
||||
"type_render_note": "Render note",
|
||||
"type_web_view": "Web view",
|
||||
"type_app_theme": "Custom theme",
|
||||
"toggle_tooltip_enable_tooltip": "Click to enable this {{type}}.",
|
||||
"toggle_tooltip_disable_tooltip": "Click to disable this {{type}}.",
|
||||
"menu_docs": "Open documentation",
|
||||
"menu_execute_now": "Execute script now",
|
||||
"menu_run": "Run automatically",
|
||||
"menu_run_disabled": "Manually",
|
||||
"menu_run_backend_startup": "When the backend starts up",
|
||||
"menu_run_hourly": "Hourly",
|
||||
"menu_run_daily": "Daily",
|
||||
"menu_run_frontend_startup": "When the desktop frontend starts up",
|
||||
"menu_run_mobile_startup": "When the mobile frontend starts up",
|
||||
"menu_change_to_widget": "Change to widget",
|
||||
"menu_change_to_frontend_script": "Change to frontend script",
|
||||
"menu_theme_base": "Theme base"
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "Learn more"
|
||||
},
|
||||
"mermaid": {
|
||||
"placeholder": "Type the content of your Mermaid diagram or use one of the sample diagrams below.",
|
||||
"sample_diagrams": "Sample diagrams:",
|
||||
"sample_flowchart": "Flowchart",
|
||||
"sample_class": "Class",
|
||||
"sample_sequence": "Sequence",
|
||||
"sample_entity_relationship": "Entity Relationship",
|
||||
"sample_state": "State",
|
||||
"sample_mindmap": "Mindmap",
|
||||
"sample_architecture": "Architecture",
|
||||
"sample_block": "Block",
|
||||
"sample_c4": "C4",
|
||||
"sample_gantt": "Gantt",
|
||||
"sample_git": "Git",
|
||||
"sample_kanban": "Kanban",
|
||||
"sample_packet": "Packet",
|
||||
"sample_pie": "Pie",
|
||||
"sample_quadrant": "Quadrant",
|
||||
"sample_radar": "Radar",
|
||||
"sample_requirement": "Requirement",
|
||||
"sample_sankey": "Sankey",
|
||||
"sample_timeline": "Timeline",
|
||||
"sample_treemap": "Treemap",
|
||||
"sample_user_journey": "User Journey",
|
||||
"sample_xy": "XY",
|
||||
"sample_venn": "Venn",
|
||||
"sample_ishikawa": "Ishikawa",
|
||||
"sample_treeview": "TreeView",
|
||||
"sample_wardley": "Wardley Map"
|
||||
},
|
||||
"mind-map": {
|
||||
"addChild": "Add child",
|
||||
"addParent": "Add parent",
|
||||
"addSibling": "Add sibling",
|
||||
"removeNode": "Remove node",
|
||||
"focus": "Focus Mode",
|
||||
"cancelFocus": "Cancel Focus Mode",
|
||||
"moveUp": "Move up",
|
||||
"moveDown": "Move down",
|
||||
"link": "Link",
|
||||
"linkBidirectional": "Bidirectional Link",
|
||||
"clickTips": "Please click the target node",
|
||||
"summary": "Summary"
|
||||
},
|
||||
"llm": {
|
||||
"settings_title": "AI / LLM",
|
||||
"settings_description": "Configure AI and Large Language Model integrations.",
|
||||
"feature_not_enabled": "Enable the LLM experimental feature in Settings → Advanced → Experimental features to use AI integrations.",
|
||||
"add_provider": "Add Provider",
|
||||
"add_provider_title": "Add AI Provider",
|
||||
"configured_providers": "Configured Providers",
|
||||
"no_providers_configured": "No providers configured yet.",
|
||||
"provider_name": "Name",
|
||||
"provider_type": "Provider",
|
||||
"actions": "Actions",
|
||||
"delete_provider": "Delete",
|
||||
"delete_provider_confirmation": "Are you sure you want to delete the provider \"{{name}}\"?",
|
||||
"api_key": "API Key",
|
||||
"api_key_placeholder": "Enter your API key",
|
||||
"cancel": "Cancel",
|
||||
"mcp_title": "MCP (Model Context Protocol)",
|
||||
"mcp_enabled": "MCP server",
|
||||
"mcp_enabled_description": "Expose a Model Context Protocol (MCP) endpoint so that AI coding assistants (e.g. Claude Code, GitHub Copilot) can read and modify your notes. The endpoint is only accessible from localhost.",
|
||||
"mcp_endpoint_title": "Endpoint URL",
|
||||
"mcp_endpoint_description": "Add this URL to your AI assistant's MCP configuration",
|
||||
"tools": {
|
||||
"search_notes": "Search notes",
|
||||
"get_note": "Get note",
|
||||
"get_note_content": "Get note content",
|
||||
"update_note_content": "Update note content",
|
||||
"append_to_note": "Append to note",
|
||||
"create_note": "Create note",
|
||||
"get_attributes": "Get attributes",
|
||||
"get_attribute": "Get attribute",
|
||||
"set_attribute": "Set attribute",
|
||||
"delete_attribute": "Delete attribute",
|
||||
"get_child_notes": "Get child notes",
|
||||
"get_subtree": "Get subtree",
|
||||
"load_skill": "Load skill",
|
||||
"web_search": "Web search",
|
||||
"note_in_parent": "<Note/> in <Parent/>",
|
||||
"get_attachment": "Get attachment",
|
||||
"get_attachment_content": "Read attachment content"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -662,13 +662,14 @@
|
||||
"show-cheatsheet": "Mostrar hoja de trucos",
|
||||
"toggle-zen-mode": "Modo Zen",
|
||||
"new-version-available": "Nueva actualización disponible",
|
||||
"download-update": "Obtener versión {{latestVersion}}"
|
||||
"download-update": "Obtener versión {{latestVersion}}",
|
||||
"search_notes": "Buscar notas"
|
||||
},
|
||||
"zen_mode": {
|
||||
"button_exit": "Salir del modo Zen"
|
||||
},
|
||||
"sync_status": {
|
||||
"unknown": "<p>El estado de sincronización será conocido una vez que el siguiente intento de sincronización comience.</p><p>Dé clic para activar la sincronización ahora</p>",
|
||||
"unknown": "<p>El estado de sincronización será conocido una vez que el siguiente intento de sincronización comience.</p><p>Dé clic para activar la sincronización ahora.</p>",
|
||||
"connected_with_changes": "<p>Conectado al servidor de sincronización. <br>Hay cambios pendientes que aún no se han sincronizado.</p><p>Dé clic para activar la sincronización.</p>",
|
||||
"connected_no_changes": "<p>Conectado al servidor de sincronización.<br>Todos los cambios ya han sido sincronizados.</p><p>Dé clic para activar la sincronización.</p>",
|
||||
"disconnected_with_changes": "<p>El establecimiento de la conexión con el servidor de sincronización no ha tenido éxito.<br>Hay algunos cambios pendientes que aún no se han sincronizado.</p><p>Dé clic para activar la sincronización.</p>",
|
||||
@@ -745,7 +746,7 @@
|
||||
"button_title": "Exportar diagrama como SVG"
|
||||
},
|
||||
"relation_map_buttons": {
|
||||
"create_child_note_title": "Crear una nueva subnota y agregarla a este mapa de relaciones",
|
||||
"create_child_note_title": "Crear una subnota y agregarla al mapa",
|
||||
"reset_pan_zoom_title": "Restablecer la panorámica y el zoom a las coordenadas y ampliación iniciales",
|
||||
"zoom_in_title": "Acercar",
|
||||
"zoom_out_title": "Alejar"
|
||||
@@ -754,14 +755,16 @@
|
||||
"relation": "relación",
|
||||
"backlink_one": "{{count}} Vínculo de retroceso",
|
||||
"backlink_many": "{{count}} Vínculos de retroceso",
|
||||
"backlink_other": "{{count}} vínculos de retroceso"
|
||||
"backlink_other": "{{count}} Vínculos de retroceso"
|
||||
},
|
||||
"mobile_detail_menu": {
|
||||
"insert_child_note": "Insertar subnota",
|
||||
"delete_this_note": "Eliminar esta nota",
|
||||
"error_cannot_get_branch_id": "No se puede obtener el branchID del notePath '{{notePath}}'",
|
||||
"error_cannot_get_branch_id": "No se puede obtener el branchId del notePath '{{notePath}}'",
|
||||
"error_unrecognized_command": "Comando no reconocido {{command}}",
|
||||
"note_revisions": "Revisiones de notas"
|
||||
"note_revisions": "Revisiones de notas",
|
||||
"backlinks": "Vínculos de retroceso",
|
||||
"content_language_switcher": "Idioma de contenido: {{language}}"
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "Cambiar icono de nota",
|
||||
@@ -799,11 +802,11 @@
|
||||
"board": "Tablero",
|
||||
"include_archived_notes": "Mostrar notas archivadas",
|
||||
"presentation": "Presentación",
|
||||
"expand_tooltip": "Expande las notas hijas inmediatas de esta colección (un nivel). Para más opciones, pulsa la flecha a la derecha.",
|
||||
"expand_tooltip": "Expande las subnotas inmediatas de esta colección (un nivel). Para más opciones, pulsa la flecha a la derecha.",
|
||||
"expand_first_level": "Expandir hijos inmediatos",
|
||||
"expand_nth_level": "Expandir {{depth}} niveles",
|
||||
"expand_all_levels": "Expandir todos los niveles",
|
||||
"hide_child_notes": "Ocultar notas hijas en el árbol"
|
||||
"hide_child_notes": "Ocultar subnotas en el árbol"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "Aún no hay notas editadas en este día...",
|
||||
@@ -849,7 +852,8 @@
|
||||
"calculate": "calcular",
|
||||
"subtree_size": "(tamaño del subárbol: {{size}} en {{count}} notas)",
|
||||
"title": "Información de nota",
|
||||
"mime": "Tipo MIME"
|
||||
"mime": "Tipo MIME",
|
||||
"show_similar_notes": "Mostrar notas similares"
|
||||
},
|
||||
"note_map": {
|
||||
"open_full": "Ampliar al máximo",
|
||||
@@ -912,7 +916,9 @@
|
||||
"search_parameters": "Parámetros de búsqueda",
|
||||
"unknown_search_option": "Opción de búsqueda desconocida {{searchOptionName}}",
|
||||
"search_note_saved": "La nota de búsqueda se ha guardado en {{- notePathTitle}}",
|
||||
"actions_executed": "Las acciones han sido ejecutadas."
|
||||
"actions_executed": "Las acciones han sido ejecutadas.",
|
||||
"view_options": "Ver opciones:",
|
||||
"option": "opción"
|
||||
},
|
||||
"similar_notes": {
|
||||
"title": "Notas similares",
|
||||
@@ -1006,7 +1012,7 @@
|
||||
"no_attachments": "Esta nota no tiene archivos adjuntos."
|
||||
},
|
||||
"book": {
|
||||
"no_children_help": "Esta nota de tipo libro no tiene ninguna subnota así que no hay nada que mostrar. Véa la <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> para más detalles.",
|
||||
"no_children_help": "Esta colección no tiene ninguna subnota así que no hay nada que mostrar.",
|
||||
"drag_locked_title": "Bloqueado para edición",
|
||||
"drag_locked_message": "No se permite Arrastrar pues la colección está bloqueada para edición."
|
||||
},
|
||||
@@ -1015,7 +1021,13 @@
|
||||
},
|
||||
"editable_text": {
|
||||
"placeholder": "Escribe aquí el contenido de tu nota...",
|
||||
"auto-detect-language": "Detectado automáticamente"
|
||||
"auto-detect-language": "Detectado automáticamente",
|
||||
"editor_crashed_title": "El editor de texto ha dejado de responder",
|
||||
"editor_crashed_content": "Su contenido ha sido recuperado con éxito, pero puede que algunos de sus cambios más recientes no se hayan guardado.",
|
||||
"editor_crashed_details_button": "Ver más detalles...",
|
||||
"editor_crashed_details_intro": "Si experimenta este error varias veces, considere informarlo en GitHub adjuntando la siguiente información.",
|
||||
"editor_crashed_details_title": "Información técnica",
|
||||
"keeps-crashing": "El componente de edición sigue fallando. Por favor, intente reiniciar Trilium. Si el problema persiste, considere crear un informe de fallos."
|
||||
},
|
||||
"empty": {
|
||||
"open_note_instruction": "Abra una nota escribiendo el título de la nota en la entrada a continuación o elija una nota en el árbol.",
|
||||
@@ -1039,7 +1051,6 @@
|
||||
"unprotecting-title": "Estado de desprotección"
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "Abrir en nueva pestaña",
|
||||
"remove_note": "Quitar nota",
|
||||
"edit_title": "Editar título",
|
||||
"rename_note": "Cambiar nombre de nota",
|
||||
@@ -1056,15 +1067,6 @@
|
||||
"default_new_note_title": "nueva nota",
|
||||
"click_on_canvas_to_place_new_note": "Haga clic en el lienzo para colocar una nueva nota"
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_1": "Esta nota de ayuda se muestra porque esta nota de tipo Renderizar HTML no tiene la relación requerida para funcionar correctamente.",
|
||||
"note_detail_render_help_2": "El tipo de nota Render HTML es usado para <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">scripting</a>. De forma resumida, tiene una nota con código HTML (opcionalmente con algo de JavaScript) y esta nota la renderizará. Para que funcione, es necesario definir una <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">relación</a> llamada \"renderNote\" apuntando a la nota HTML nota a renderizar."
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "Vista web",
|
||||
"embed_websites": "La nota de tipo Web View le permite insertar sitios web en Trilium.",
|
||||
"create_label": "Para comenzar, por favor cree una etiqueta con una dirección URL que desee empotrar, e.g. #webViewSrc=\"https://www.google.com\""
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "Refrescar"
|
||||
},
|
||||
@@ -1172,149 +1174,6 @@
|
||||
"light_theme": "Heredado (Claro)",
|
||||
"dark_theme": "Heredado (Oscuro)"
|
||||
},
|
||||
"ai_llm": {
|
||||
"not_started": "No iniciado",
|
||||
"title": "IA y ajustes de embeddings",
|
||||
"processed_notes": "Notas procesadas",
|
||||
"total_notes": "Notas totales",
|
||||
"progress": "Progreso",
|
||||
"queued_notes": "Notas en fila",
|
||||
"failed_notes": "Notas fallidas",
|
||||
"last_processed": "Última procesada",
|
||||
"refresh_stats": "Recargar estadísticas",
|
||||
"enable_ai_features": "Habilitar características IA/LLM",
|
||||
"enable_ai_description": "Habilitar características de IA como resumen de notas, generación de contenido y otras capacidades LLM",
|
||||
"openai_tab": "OpenAI",
|
||||
"anthropic_tab": "Anthropic",
|
||||
"voyage_tab": "Voyage AI",
|
||||
"ollama_tab": "Ollama",
|
||||
"enable_ai": "Habilitar características IA/LLM",
|
||||
"enable_ai_desc": "Habilitar características de IA como resumen de notas, generación de contenido y otras capacidades LLM",
|
||||
"provider_configuration": "Configuración de proveedor de IA",
|
||||
"provider_precedence": "Precedencia de proveedor",
|
||||
"provider_precedence_description": "Lista de proveedores en orden de precedencia separada por comas (p.e., 'openai,anthropic,ollama')",
|
||||
"temperature": "Temperatura",
|
||||
"temperature_description": "Controla la aleatoriedad de las respuestas (0 = determinista, 2 = aleatoriedad máxima)",
|
||||
"system_prompt": "Mensaje de sistema",
|
||||
"system_prompt_description": "Mensaje de sistema predeterminado utilizado para todas las interacciones de IA",
|
||||
"openai_configuration": "Configuración de OpenAI",
|
||||
"openai_settings": "Ajustes de OpenAI",
|
||||
"api_key": "Clave API",
|
||||
"url": "URL base",
|
||||
"model": "Modelo",
|
||||
"openai_api_key_description": "Tu clave API de OpenAI para acceder a sus servicios de IA",
|
||||
"anthropic_api_key_description": "Tu clave API de Anthropic para acceder a los modelos Claude",
|
||||
"default_model": "Modelo por defecto",
|
||||
"openai_model_description": "Ejemplos: gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
|
||||
"base_url": "URL base",
|
||||
"openai_url_description": "Por defecto: https://api.openai.com/v1",
|
||||
"anthropic_settings": "Ajustes de Anthropic",
|
||||
"anthropic_url_description": "URL base para la API de Anthropic (por defecto: https://api.anthropic.com)",
|
||||
"anthropic_model_description": "Modelos Claude de Anthropic para el completado de chat",
|
||||
"voyage_settings": "Ajustes de Voyage AI",
|
||||
"ollama_settings": "Ajustes de Ollama",
|
||||
"ollama_url_description": "URL para la API de Ollama (por defecto: http://localhost:11434)",
|
||||
"ollama_model_description": "Modelo de Ollama a usar para el completado de chat",
|
||||
"anthropic_configuration": "Configuración de Anthropic",
|
||||
"voyage_configuration": "Configuración de Voyage AI",
|
||||
"voyage_url_description": "Por defecto: https://api.voyageai.com/v1",
|
||||
"ollama_configuration": "Configuración de Ollama",
|
||||
"enable_ollama": "Habilitar Ollama",
|
||||
"enable_ollama_description": "Habilitar Ollama para uso de modelo de IA local",
|
||||
"ollama_url": "URL de Ollama",
|
||||
"ollama_model": "Modelo de Ollama",
|
||||
"refresh_models": "Refrescar modelos",
|
||||
"refreshing_models": "Refrescando...",
|
||||
"enable_automatic_indexing": "Habilitar indexado automático",
|
||||
"rebuild_index": "Recrear índice",
|
||||
"rebuild_index_error": "Error al comenzar la reconstrucción del índice. Consulte los registros para más detalles.",
|
||||
"note_title": "Título de nota",
|
||||
"error": "Error",
|
||||
"last_attempt": "Último intento",
|
||||
"actions": "Acciones",
|
||||
"retry": "Reintentar",
|
||||
"partial": "{{ percentage }}% completado",
|
||||
"retry_queued": "Nota en la cola para reintento",
|
||||
"retry_failed": "Hubo un fallo al poner en la cola a la nota para reintento",
|
||||
"max_notes_per_llm_query": "Máximo de notas por consulta",
|
||||
"max_notes_per_llm_query_description": "Número máximo de notas similares a incluir en el contexto IA",
|
||||
"active_providers": "Proveedores activos",
|
||||
"disabled_providers": "Proveedores deshabilitados",
|
||||
"remove_provider": "Eliminar proveedor de la búsqueda",
|
||||
"restore_provider": "Restaurar proveedor a la búsqueda",
|
||||
"similarity_threshold": "Bias de similaridad",
|
||||
"similarity_threshold_description": "Puntuación de similaridad mínima (0-1) para incluir notas en el contexto para consultas LLM",
|
||||
"reprocess_index": "Reconstruir el índice de búsqueda",
|
||||
"reprocessing_index": "Reconstruyendo...",
|
||||
"reprocess_index_started": "La optimización de índice de búsqueda comenzó en segundo plano",
|
||||
"reprocess_index_error": "Error al reconstruir el índice de búsqueda",
|
||||
"index_rebuild_progress": "Progreso de reconstrucción de índice",
|
||||
"index_rebuilding": "Optimizando índice ({{percentage}}%)",
|
||||
"index_rebuild_complete": "Optimización de índice completa",
|
||||
"index_rebuild_status_error": "Error al comprobar el estado de reconstrucción del índice",
|
||||
"never": "Nunca",
|
||||
"processing": "Procesando ({{percentage}}%)",
|
||||
"incomplete": "Incompleto ({{percentage}}%)",
|
||||
"complete": "Completo (100%)",
|
||||
"refreshing": "Refrescando...",
|
||||
"auto_refresh_notice": "Refrescar automáticamente cada {{seconds}} segundos",
|
||||
"note_queued_for_retry": "Nota en la cola para reintento",
|
||||
"failed_to_retry_note": "Hubo un fallo al reintentar nota",
|
||||
"all_notes_queued_for_retry": "Todas las notas con fallo agregadas a la cola para reintento",
|
||||
"failed_to_retry_all": "Hubo un fallo al reintentar notas",
|
||||
"ai_settings": "Ajustes de IA",
|
||||
"api_key_tooltip": "Clave API para acceder al servicio",
|
||||
"empty_key_warning": {
|
||||
"anthropic": "La clave API de Anthropic está vacía. Por favor, ingrese una clave API válida.",
|
||||
"openai": "La clave API de OpenAI está vacía. Por favor, ingrese una clave API válida.",
|
||||
"voyage": "La clave API de Voyage está vacía. Por favor, ingrese una clave API válida.",
|
||||
"ollama": "La clave API de Ollama está vacía. Por favor, ingrese una clave API válida."
|
||||
},
|
||||
"agent": {
|
||||
"processing": "Procesando...",
|
||||
"thinking": "Pensando...",
|
||||
"loading": "Cargando...",
|
||||
"generating": "Generando..."
|
||||
},
|
||||
"name": "IA",
|
||||
"openai": "OpenAI",
|
||||
"use_enhanced_context": "Utilizar contexto mejorado",
|
||||
"enhanced_context_description": "Provee a la IA con más contexto de la nota y sus notas relacionadas para obtener mejores respuestas",
|
||||
"show_thinking": "Mostrar pensamiento",
|
||||
"show_thinking_description": "Mostrar la cadena del proceso de pensamiento de la IA",
|
||||
"enter_message": "Ingrese su mensaje...",
|
||||
"error_contacting_provider": "Error al contactar con su proveedor de IA. Por favor compruebe sus ajustes y conexión a internet.",
|
||||
"error_generating_response": "Error al generar respuesta de IA",
|
||||
"index_all_notes": "Indexar todas las notas",
|
||||
"index_status": "Estado de índice",
|
||||
"indexed_notes": "Notas indexadas",
|
||||
"indexing_stopped": "Indexado detenido",
|
||||
"indexing_in_progress": "Indexado en progreso...",
|
||||
"last_indexed": "Último indexado",
|
||||
"note_chat": "Chat de nota",
|
||||
"sources": "Fuentes",
|
||||
"start_indexing": "Comenzar indexado",
|
||||
"use_advanced_context": "Usar contexto avanzado",
|
||||
"ollama_no_url": "Ollama no está configurado. Por favor ingrese una URL válida.",
|
||||
"chat": {
|
||||
"root_note_title": "Chats de IA",
|
||||
"root_note_content": "Esta nota contiene tus conversaciones de chat de IA guardadas.",
|
||||
"new_chat_title": "Nuevo chat",
|
||||
"create_new_ai_chat": "Crear nuevo chat de IA"
|
||||
},
|
||||
"create_new_ai_chat": "Crear nuevo chat de IA",
|
||||
"configuration_warnings": "Hay algunos problemas con su configuración de IA. Por favor compruebe sus ajustes.",
|
||||
"experimental_warning": "La característica de LLM aún es experimental - ha sido advertido.",
|
||||
"selected_provider": "Proveedor seleccionado",
|
||||
"selected_provider_description": "Elija el proveedor de IA para el chat y características de completado",
|
||||
"select_model": "Seleccionar modelo...",
|
||||
"select_provider": "Seleccionar proveedor...",
|
||||
"ai_enabled": "Características de IA activadas",
|
||||
"ai_disabled": "Características de IA desactivadas",
|
||||
"no_models_found_online": "No se encontraron modelos. Por favor, comprueba tu clave de API y la configuración.",
|
||||
"no_models_found_ollama": "No se encontraron modelos de Ollama. Por favor, comprueba si Ollama se está ejecutando.",
|
||||
"error_fetching": "Error al obtener los modelos: {{error}}"
|
||||
},
|
||||
"zoom_factor": {
|
||||
"title": "Factor de zoom (solo versión de escritorio)",
|
||||
"description": "El zoom también se puede controlar con los atajos CTRL+- y CTRL+=."
|
||||
@@ -1331,8 +1190,8 @@
|
||||
"code_mime_types": {
|
||||
"title": "Tipos MIME disponibles en el menú desplegable",
|
||||
"tooltip_syntax_highlighting": "Resaltado de sintaxis",
|
||||
"tooltip_code_block_syntax": "Bloques de Código en notas de Texto",
|
||||
"tooltip_code_note_syntax": "Notas de Código"
|
||||
"tooltip_code_block_syntax": "Bloques de código en Notas de texto",
|
||||
"tooltip_code_note_syntax": "Notas de código"
|
||||
},
|
||||
"vim_key_bindings": {
|
||||
"use_vim_keybindings_in_code_notes": "Combinaciones de teclas Vim",
|
||||
@@ -1409,16 +1268,16 @@
|
||||
"markdown": "Estilo Markdown"
|
||||
},
|
||||
"highlights_list": {
|
||||
"title": "Lista de aspectos destacados",
|
||||
"description": "Puede personalizar la lista de aspectos destacados que se muestra en el panel derecho:",
|
||||
"title": "Lista de puntos destacados",
|
||||
"description": "Puede personalizar la lista de puntos destacados que se muestra en el panel derecho:",
|
||||
"bold": "Texto en negrita",
|
||||
"italic": "Texto en cursiva",
|
||||
"underline": "Texto subrayado",
|
||||
"color": "Texto con color",
|
||||
"bg_color": "Texto con color de fondo",
|
||||
"visibility_title": "Visibilidad de la lista de aspectos destacados",
|
||||
"visibility_description": "Puede ocultar el widget de aspectos destacados por nota agregando una etiqueta #hideHighlightWidget.",
|
||||
"shortcut_info": "Puede configurar un método abreviado de teclado para alternar rápidamente el panel derecho (incluidos los aspectos destacados) en Opciones -> Atajos (nombre 'toggleRightPane')."
|
||||
"visibility_title": "Visibilidad de la lista de puntos destacados",
|
||||
"visibility_description": "Puede ocultar el widget de puntos destacados por nota agregando la etiqueta #hideHighlightWidget.",
|
||||
"shortcut_info": "Puede configurar un método abreviado de teclado para alternar rápidamente el panel derecho (incluidos los puntos destacados) en Opciones -> Atajos (nombre 'toggleRightPane')."
|
||||
},
|
||||
"table_of_contents": {
|
||||
"title": "Tabla de contenido",
|
||||
@@ -1557,7 +1416,7 @@
|
||||
"shortcuts": {
|
||||
"keyboard_shortcuts": "Atajos de teclado",
|
||||
"multiple_shortcuts": "Varios atajos para la misma acción se pueden separar mediante comas.",
|
||||
"electron_documentation": "Véa la <a href=\"https://www.electronjs.org/docs/latest/api/accelerator\">documentación de Electron </a> para los modificadores y códigos de tecla disponibles.",
|
||||
"electron_documentation": "Consulte la <a href=\"https://www.electronjs.org/docs/latest/api/accelerator\">documentación de Electron</a> para los modificadores y códigos de tecla disponibles.",
|
||||
"type_text_to_filter": "Escriba texto para filtrar los accesos directos...",
|
||||
"action_name": "Nombre de la acción",
|
||||
"shortcuts": "Atajos",
|
||||
@@ -1565,7 +1424,8 @@
|
||||
"description": "Descripción",
|
||||
"reload_app": "Vuelva a cargar la aplicación para aplicar los cambios",
|
||||
"set_all_to_default": "Establecer todos los accesos directos al valor predeterminado",
|
||||
"confirm_reset": "¿Realmente desea restablecer todos los atajos de teclado a sus valores predeterminados?"
|
||||
"confirm_reset": "¿Realmente desea restablecer todos los atajos de teclado a sus valores predeterminados?",
|
||||
"no_results": "No se encontraron atajos que coincidan con '{{filter}} '"
|
||||
},
|
||||
"spellcheck": {
|
||||
"title": "Revisión ortográfica",
|
||||
@@ -1606,7 +1466,7 @@
|
||||
},
|
||||
"bookmark_switch": {
|
||||
"bookmark": "Marcador",
|
||||
"bookmark_this_note": "Añadir esta nota a marcadores en el panel lateral izquierdo",
|
||||
"bookmark_this_note": "Agregar esta nota a marcadores en el panel lateral izquierdo",
|
||||
"remove_bookmark": "Eliminar marcador"
|
||||
},
|
||||
"editability_select": {
|
||||
@@ -1654,7 +1514,10 @@
|
||||
"convert-to-attachment-confirm": "¿Está seguro que desea convertir las notas seleccionadas en archivos adjuntos de sus notas padres? Esta operación solo aplica a notas de Imagen, otras notas serán omitidas.",
|
||||
"open-in-popup": "Edición rápida",
|
||||
"archive": "Archivar",
|
||||
"unarchive": "Desarchivar"
|
||||
"unarchive": "Desarchivar",
|
||||
"open-in-a-new-window": "Abrir en una nueva ventana",
|
||||
"hide-subtree": "Ocultar subárbol",
|
||||
"show-subtree": "Mostrar subárbol"
|
||||
},
|
||||
"shared_info": {
|
||||
"shared_publicly": "Esta nota está compartida públicamente en {{- link}}.",
|
||||
@@ -1684,7 +1547,8 @@
|
||||
"task-list": "Lista de tareas",
|
||||
"book": "Colección",
|
||||
"new-feature": "Nuevo",
|
||||
"collections": "Colecciones"
|
||||
"collections": "Colecciones",
|
||||
"spreadsheet": "Hoja de cálculo"
|
||||
},
|
||||
"protect_note": {
|
||||
"toggle-on": "Proteger la nota",
|
||||
@@ -1715,7 +1579,13 @@
|
||||
},
|
||||
"highlights_list_2": {
|
||||
"title": "Lista de destacados",
|
||||
"options": "Opciones"
|
||||
"options": "Opciones",
|
||||
"title_with_count_one": "{{count}} punto destacado",
|
||||
"title_with_count_many": "{{count}} puntos destacados",
|
||||
"title_with_count_other": "{{count}} puntos destacados",
|
||||
"modal_title": "Configurar la lista de puntos destacados",
|
||||
"menu_configure": "Configurar la lista de puntos destacados...",
|
||||
"no_highlights": "Ningún punto destacado encontrado."
|
||||
},
|
||||
"quick-search": {
|
||||
"placeholder": "Búsqueda rápida",
|
||||
@@ -1738,7 +1608,18 @@
|
||||
"refresh-saved-search-results": "Refrescar resultados de búsqueda guardados",
|
||||
"create-child-note": "Crear subnota",
|
||||
"unhoist": "Desanclar",
|
||||
"toggle-sidebar": "Alternar barra lateral"
|
||||
"toggle-sidebar": "Alternar barra lateral",
|
||||
"dropping-not-allowed": "No está permitido soltar notas en esta ubicación.",
|
||||
"clone-indicator-tooltip": "Esta nota tiene {{- count}} padres: {{- parents}}",
|
||||
"clone-indicator-tooltip-single": "Esta nota está clonada (1 padre adicional: {{- parent}})",
|
||||
"shared-indicator-tooltip": "Esta nota está compartida públicamente",
|
||||
"shared-indicator-tooltip-with-url": "Esta nota está compartida públicamente en: {{- url}}",
|
||||
"subtree-hidden-tooltip_one": "{{count}} subnota que está oculta del árbol",
|
||||
"subtree-hidden-tooltip_many": "{{count}} subnotas que están ocultas del árbol",
|
||||
"subtree-hidden-tooltip_other": "{{count}} subnotas que están ocultas del árbol",
|
||||
"subtree-hidden-moved-title": "Agregado a {{title}}",
|
||||
"subtree-hidden-moved-description-collection": "Esta colección oculta sus subnotas en el árbol.",
|
||||
"subtree-hidden-moved-description-other": "Las subnotas están ocultas en el árbol para esta nota."
|
||||
},
|
||||
"title_bar_buttons": {
|
||||
"window-on-top": "Mantener esta ventana en la parte superior"
|
||||
@@ -1749,20 +1630,38 @@
|
||||
"printing_pdf": "Exportando a PDF en curso..",
|
||||
"print_report_collection_content_one": "{{count}} nota en la colección no se puede imprimir porque no son compatibles o está protegida.",
|
||||
"print_report_collection_content_many": "{{count}} notas en la colección no se pueden imprimir porque no son compatibles o están protegidas.",
|
||||
"print_report_collection_content_other": "{{count}} notas en la colección no se pueden imprimir porque no son compatibles o están protegidas."
|
||||
"print_report_collection_content_other": "{{count}} notas en la colección no se pueden imprimir porque no son compatibles o están protegidas.",
|
||||
"print_report_title": "Imprimir informe",
|
||||
"print_report_collection_details_button": "Ver detalles",
|
||||
"print_report_collection_details_ignored_notes": "Notas ignoradas",
|
||||
"print_report_stack_trace": "Rastreo de pila",
|
||||
"print_report_error_title": "Fallo al imprimir"
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "escriba el título de la nota aquí..."
|
||||
"placeholder": "escriba el título de la nota aquí...",
|
||||
"created_on": "Creado en <Value />",
|
||||
"last_modified": "Modificado en <Value />",
|
||||
"note_type_switcher_label": "Cambiar de {{type}} a:",
|
||||
"note_type_switcher_others": "Otro tipo de nota",
|
||||
"note_type_switcher_templates": "Plantilla",
|
||||
"note_type_switcher_collection": "Colección",
|
||||
"edited_notes": "Notas editadas en este día",
|
||||
"promoted_attributes": "Atributos promovidos"
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "No se han encontrado notas para los parámetros de búsqueda dados.",
|
||||
"search_not_executed": "La búsqueda aún no se ha ejecutado. Dé clic en el botón «Buscar» para ver los resultados."
|
||||
"search_not_executed": "La búsqueda aún no se ha ejecutado.",
|
||||
"search_now": "Buscar ahora"
|
||||
},
|
||||
"spacer": {
|
||||
"configure_launchbar": "Configurar barra de lanzamiento"
|
||||
},
|
||||
"sql_result": {
|
||||
"no_rows": "No se han devuelto filas para esta consulta"
|
||||
"no_rows": "No se han devuelto filas para esta consulta",
|
||||
"not_executed": "La consulta aún no ha sido ejecutada.",
|
||||
"failed": "La ejecución de la consulta SQL ha fallado",
|
||||
"statement_result": "Resultado de declaración",
|
||||
"execute_now": "Ejecutar ahora"
|
||||
},
|
||||
"sql_table_schemas": {
|
||||
"tables": "Tablas"
|
||||
@@ -1781,10 +1680,11 @@
|
||||
},
|
||||
"toc": {
|
||||
"table_of_contents": "Tabla de contenido",
|
||||
"options": "Opciones"
|
||||
"options": "Opciones",
|
||||
"no_headings": "Sin encabezados."
|
||||
},
|
||||
"watched_file_update_status": {
|
||||
"file_last_modified": "Archivo <code class=\"file-path\"></code> ha sido modificado por última vez en<span class=\"file-last-modified\"></span>.",
|
||||
"file_last_modified": "El archivo <code class=\"file-path\"></code> ha sido modificado por última vez en <span class=\"file-last-modified\"></span>.",
|
||||
"upload_modified_file": "Subir archivo modificado",
|
||||
"ignore_this_change": "Ignorar este cambio"
|
||||
},
|
||||
@@ -1879,6 +1779,7 @@
|
||||
"add-term-to-dictionary": "Agregar \"{{term}}\" al diccionario",
|
||||
"cut": "Cortar",
|
||||
"copy": "Copiar",
|
||||
"copy-as-markdown": "Copiar como markdown",
|
||||
"copy-link": "Copiar enlace",
|
||||
"paste": "Pegar",
|
||||
"paste-as-plain-text": "Pegar como texto plano",
|
||||
@@ -1893,14 +1794,15 @@
|
||||
"open_note_in_new_tab": "Abrir nota en una pestaña nueva",
|
||||
"open_note_in_new_split": "Abrir nota en una nueva división",
|
||||
"open_note_in_new_window": "Abrir nota en una nueva ventana",
|
||||
"open_note_in_popup": "Edición rápida"
|
||||
"open_note_in_popup": "Edición rápida",
|
||||
"open_note_in_other_split": "Abrir nota en la otra división"
|
||||
},
|
||||
"electron_integration": {
|
||||
"desktop-application": "Aplicación de escritorio",
|
||||
"native-title-bar": "Barra de título nativa",
|
||||
"native-title-bar-description": "Para Windows y macOS, quitar la barra de título nativa hace que la aplicación se vea más compacta. En Linux, mantener la barra de título nativa hace que se integre mejor con el resto del sistema.",
|
||||
"background-effects": "Habilitar efectos de fondo (sólo en Windows 11)",
|
||||
"background-effects-description": "El efecto Mica agrega un fondo borroso y elegante a las ventanas de la aplicación, creando profundidad y un aspecto moderno. \"Título nativo de la barra\" debe deshabilitarse.",
|
||||
"background-effects": "Habilitar efectos de fondo",
|
||||
"background-effects-description": "Agrega un fondo borroso y elegante a las ventanas de la aplicación, creando profundidad y un aspecto moderno. \"Título nativo de la barra\" debe deshabilitarse.",
|
||||
"restart-app-button": "Reiniciar la aplicación para ver los cambios",
|
||||
"zoom-factor": "Factor de zoom"
|
||||
},
|
||||
@@ -1919,7 +1821,8 @@
|
||||
"geo-map": {
|
||||
"create-child-note-title": "Crear una nueva subnota y agregarla al mapa",
|
||||
"create-child-note-instruction": "Dé clic en el mapa para crear una nueva nota en esa ubicación o presione Escape para cancelar.",
|
||||
"unable-to-load-map": "No se puede cargar el mapa."
|
||||
"unable-to-load-map": "No se puede cargar el mapa.",
|
||||
"create-child-note-text": "Agregar marcador"
|
||||
},
|
||||
"geo-map-context": {
|
||||
"open-location": "Abrir ubicación",
|
||||
@@ -1962,10 +1865,11 @@
|
||||
},
|
||||
"note_language": {
|
||||
"not_set": "Idioma no establecido",
|
||||
"configure-languages": "Configurar idiomas..."
|
||||
"configure-languages": "Configurar idiomas...",
|
||||
"help-on-languages": "Ayuda en idiomas de contenido..."
|
||||
},
|
||||
"content_language": {
|
||||
"title": "Contenido de idiomas",
|
||||
"title": "Idiomas de contenido",
|
||||
"description": "Seleccione uno o más idiomas que deben aparecer en la selección del idioma en la sección Propiedades Básicas de una nota de texto de solo lectura o editable. Esto permitirá características tales como corrección de ortografía o soporte de derecha a izquierda."
|
||||
},
|
||||
"switch_layout_button": {
|
||||
@@ -1980,7 +1884,8 @@
|
||||
"button_title": "Exportar diagrama como PNG"
|
||||
},
|
||||
"svg": {
|
||||
"export_to_png": "El diagrama no pudo ser exportado a PNG."
|
||||
"export_to_png": "El diagrama no pudo ser exportado a PNG.",
|
||||
"export_to_svg": "El diagrama no pudo ser exportado a SVG."
|
||||
},
|
||||
"code_theme": {
|
||||
"title": "Apariencia",
|
||||
@@ -2004,7 +1909,8 @@
|
||||
"max-nesting-depth": "Máxima profundidad de anidamiento:",
|
||||
"vector_light": "Vector (claro)",
|
||||
"vector_dark": "Vector (oscuro)",
|
||||
"raster": "Trama"
|
||||
"raster": "Trama",
|
||||
"show-labels": "Mostrar nombres de marcadores"
|
||||
},
|
||||
"table_context_menu": {
|
||||
"delete_row": "Eliminar fila"
|
||||
@@ -2083,9 +1989,12 @@
|
||||
"next_theme_message": "Estás usando actualmente el tema heredado. ¿Te gustaría probar el nuevo tema?",
|
||||
"next_theme_button": "Prueba el nuevo tema",
|
||||
"background_effects_title": "Los efectos de fondo son ahora estables",
|
||||
"background_effects_message": "En los dispositivos Windows, los efectos de fondo ya son totalmente estables. Los efectos de fondo añaden un toque de color a la interfaz de usuario difuminando el fondo que hay detrás. Esta técnica también se utiliza en otras aplicaciones como el Explorador de Windows.",
|
||||
"background_effects_message": "En los dispositivos Windows y macOS, los efectos de fondo ya son estables. Los efectos de fondo añaden un toque de color a la interfaz de usuario difuminando el fondo que hay detrás.",
|
||||
"background_effects_button": "Activar efectos de fondo",
|
||||
"dismiss": "Desestimar"
|
||||
"dismiss": "Desestimar",
|
||||
"new_layout_title": "Nuevo diseño",
|
||||
"new_layout_message": "Hemos introducido un diseño modernizado para Trilium. La cinta se ha eliminado y se ha integrado perfectamente en la interfaz principal, con una nueva barra de estado y secciones ampliables (como los atributos promovidos) que tienen funciones clave.\n\nEl nuevo diseño está habilitado por defecto, y puede ser deshabilitado temporalmente a través de Opciones → Apariencia.",
|
||||
"new_layout_button": "Más información"
|
||||
},
|
||||
"ui-performance": {
|
||||
"title": "Rendimiento",
|
||||
@@ -2100,14 +2009,18 @@
|
||||
},
|
||||
"settings_appearance": {
|
||||
"related_code_blocks": "Esquema de colores para bloques de código en notas de texto",
|
||||
"related_code_notes": "Esquema de colores para notas de código"
|
||||
"related_code_notes": "Esquema de colores para notas de código",
|
||||
"ui": "Interfaz de usuario",
|
||||
"ui_old_layout": "Antiguo diseño",
|
||||
"ui_new_layout": "Nuevo diseño"
|
||||
},
|
||||
"units": {
|
||||
"percentage": "%"
|
||||
},
|
||||
"pagination": {
|
||||
"total_notes": "{{count}} notas",
|
||||
"page_title": "Página de {{startIndex}} - {{endIndex}}"
|
||||
"prev_page": "Página anterior",
|
||||
"next_page": "Página siguiente"
|
||||
},
|
||||
"presentation_view": {
|
||||
"edit-slide": "Editar este slide",
|
||||
@@ -2148,7 +2061,12 @@
|
||||
"attributes_other": "{{count}} atributos",
|
||||
"note_paths_one": "{{count}} ruta",
|
||||
"note_paths_many": "{{count}} rutas",
|
||||
"note_paths_other": "{{count}} rutas"
|
||||
"note_paths_other": "{{count}} rutas",
|
||||
"language_title": "Cambiar el idioma del contenido",
|
||||
"note_info_title": "Ver información de la nota (p. e., fechas, tamaño de la nota)",
|
||||
"attributes_title": "Atributos propios y atributos heredados",
|
||||
"note_paths_title": "Rutas de nota",
|
||||
"code_note_switcher": "Cambiar modo de idioma"
|
||||
},
|
||||
"pdf": {
|
||||
"attachments_one": "{{count}} adjunto",
|
||||
@@ -2159,6 +2077,172 @@
|
||||
"layers_other": "{{count}} capas",
|
||||
"pages_one": "{{count}} página",
|
||||
"pages_many": "{{count}} páginas",
|
||||
"pages_other": "{{count}} páginas"
|
||||
"pages_other": "{{count}} páginas",
|
||||
"pages_alt": "Página {{pageNumber}}",
|
||||
"pages_loading": "Cargando..."
|
||||
},
|
||||
"experimental_features": {
|
||||
"title": "Opciones experimentales",
|
||||
"disclaimer": "Estas opciones son experimentales y pueden causar inestabilidad. Úselas con precaución.",
|
||||
"new_layout_name": "Nuevo diseño",
|
||||
"new_layout_description": "Pruebe el nuevo diseño para tener un aspecto más moderno y usabilidad mejorada. Sujeto a grandes cambios en las próximas versiones."
|
||||
},
|
||||
"popup-editor": {
|
||||
"maximize": "Cambiar a editor completo"
|
||||
},
|
||||
"server": {
|
||||
"unknown_http_error_title": "Error de comunicación con el servidor",
|
||||
"unknown_http_error_content": "Código de estado: {{statusCode}}\nURL: {{method}} {{url}}\nMensaje: {{message}}",
|
||||
"traefik_blocks_requests": "Si está usando el proxy inverso Traefik, este introdujo un cambio que afecta la comunicación con el servidor."
|
||||
},
|
||||
"tab_history_navigation_buttons": {
|
||||
"go-back": "Volver a la nota anterior",
|
||||
"go-forward": "Avanzar a la siguiente nota"
|
||||
},
|
||||
"breadcrumb": {
|
||||
"hoisted_badge": "Anclada",
|
||||
"hoisted_badge_title": "Desanclar",
|
||||
"workspace_badge": "Espacio de trabajo",
|
||||
"scroll_to_top_title": "Saltar al inicio de la nota",
|
||||
"create_new_note": "Crear nueva subnota",
|
||||
"empty_hide_archived_notes": "Ocultar notas archivadas"
|
||||
},
|
||||
"breadcrumb_badges": {
|
||||
"read_only_explicit": "Sólo lectura",
|
||||
"read_only_explicit_description": "Esta nota se ha fijado manualmente como sólo lectura.\nHaga clic para editarla temporalmente.",
|
||||
"read_only_auto": "Sólo lectura automática",
|
||||
"read_only_auto_description": "Esta nota se fijó automáticamente con el modo de sólo lectura por razones de rendimiento. Este límite automático es ajustable desde los ajustes.\n\nHaga clic para editarla temporalmente.",
|
||||
"read_only_temporarily_disabled": "Temporalmente editable",
|
||||
"read_only_temporarily_disabled_description": "Esta nota actualmente es editable, pero normalmente es de sólo lectura. La nota volverá a ser de sólo lectura tan pronto como navegue a otra nota.\n\nHaga clic para volver a habilitar el modo de sólo lectura.",
|
||||
"shared_publicly": "Compartida públicamente",
|
||||
"shared_locally": "Compartida localmente",
|
||||
"shared_copy_to_clipboard": "Copiar enlace al portapapeles",
|
||||
"shared_open_in_browser": "Abrir enlace en el navegador",
|
||||
"shared_unshare": "Eliminar compartido",
|
||||
"clipped_note_description": "Esta nota fue tomada originalmente de {{url}}.\n\nHaga clic para navegar a la página web de origen.",
|
||||
"execute_script": "Ejecutar script",
|
||||
"execute_script_description": "Esta nota es una nota de script. Haga clic para ejecutar el script.",
|
||||
"execute_sql": "Ejecutar SQL",
|
||||
"execute_sql_description": "Esta nota es una nota SQL. Haga clic para ejecutar la consulta SQL.",
|
||||
"save_status_saved": "Guardado",
|
||||
"save_status_saving": "Guardando...",
|
||||
"save_status_unsaved": "Sin guardar",
|
||||
"save_status_error": "Fallo al guardar",
|
||||
"save_status_saving_tooltip": "Los cambios están siendo guardados.",
|
||||
"save_status_unsaved_tooltip": "Hay cambios sin guardar. Se guardarán automáticamente en un momento.",
|
||||
"save_status_error_tooltip": "Se produjo un error al guardar la nota. Si es posible, trate de copiar el contenido de la nota en otro lugar y recargar la aplicación.",
|
||||
"clipped_note": "Clip web"
|
||||
},
|
||||
"attributes_panel": {
|
||||
"title": "Atributos de nota"
|
||||
},
|
||||
"right_pane": {
|
||||
"empty_message": "Nada que mostrar para esta nota",
|
||||
"empty_button": "Ocultar el panel",
|
||||
"toggle": "Alternar panel derecho",
|
||||
"custom_widget_go_to_source": "Ir al código fuente"
|
||||
},
|
||||
"platform_indicator": {
|
||||
"available_on": "Disponible en {{platform}}"
|
||||
},
|
||||
"mobile_tab_switcher": {
|
||||
"title_one": "{{count}} pestaña",
|
||||
"title_many": "{{count}} pestañas",
|
||||
"title_other": "{{count}} pestañas",
|
||||
"more_options": "Más opciones"
|
||||
},
|
||||
"bookmark_buttons": {
|
||||
"bookmarks": "Marcadores"
|
||||
},
|
||||
"web_view_setup": {
|
||||
"title": "Crear una vista en vivo de una página web directamente en Trilium",
|
||||
"url_placeholder": "Ingresar o pegar la dirección del sitio web, por ejemplo https://triliumnotes.org",
|
||||
"create_button": "Crear Vista Web",
|
||||
"invalid_url_title": "Dirección inválida",
|
||||
"invalid_url_message": "Ingrese una dirección web válida, por ejemplo https://triliumnotes.org.",
|
||||
"disabled_description": "Esta vista web fue importada de una fuente externa. Para ayudarlo a protegerse del phishing o el contenido malicioso, no se está cargando automáticamente. Puede activarlo si confía en la fuente.",
|
||||
"disabled_button_enable": "Habilita vista web"
|
||||
},
|
||||
"render": {
|
||||
"setup_title": "Mostrar HTML personalizado o Preact JSX dentro de esta nota",
|
||||
"setup_create_sample_preact": "Crear nota de muestra con Preact",
|
||||
"setup_create_sample_html": "Crear nota de muestra con HTML",
|
||||
"setup_sample_created": "Se creó una nota de muestra como subnota.",
|
||||
"disabled_description": "Esta nota de renderización proviene de una fuente externa. Para protegerlo de contenido malicioso, no está habilitado por defecto. Asegúrese de confiar en la fuente antes de habilitarla.",
|
||||
"disabled_button_enable": "Habilitar nota de renderización"
|
||||
},
|
||||
"active_content_badges": {
|
||||
"type_icon_pack": "Paquete de iconos",
|
||||
"type_backend_script": "Script de backend",
|
||||
"type_frontend_script": "Script de frontend",
|
||||
"type_widget": "Widget",
|
||||
"type_app_css": "CSS personalizado",
|
||||
"type_render_note": "Nota de renderización",
|
||||
"type_web_view": "Vista web",
|
||||
"type_app_theme": "Tema personalizado",
|
||||
"toggle_tooltip_enable_tooltip": "Haga clic para habilitar este {{type}}.",
|
||||
"toggle_tooltip_disable_tooltip": "Haga clic para deshabilitar este {{type}}.",
|
||||
"menu_docs": "Abrir documentación",
|
||||
"menu_execute_now": "Ejecutar script ahora",
|
||||
"menu_run": "Ejecutar automáticamente",
|
||||
"menu_run_disabled": "Manualmente",
|
||||
"menu_run_backend_startup": "Cuando el backend inicia",
|
||||
"menu_run_hourly": "Cada hora",
|
||||
"menu_run_daily": "Diariamente",
|
||||
"menu_run_frontend_startup": "Cuando el frontend de escritorio inicia",
|
||||
"menu_run_mobile_startup": "Cuando el frontend móvil inicia",
|
||||
"menu_change_to_widget": "Cambiar a widget",
|
||||
"menu_change_to_frontend_script": "Cambiar a script de frontend",
|
||||
"menu_theme_base": "Tema base"
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "Para saber más"
|
||||
},
|
||||
"media": {
|
||||
"play": "Reproducir (Espacio)",
|
||||
"pause": "Pausa (Espacio)",
|
||||
"back-10s": "Retroceder 10s (tecla de flecha izquierda)",
|
||||
"forward-30s": "Adelantar 30s",
|
||||
"mute": "Silenciar (M)",
|
||||
"unmute": "Activar sonido (M)",
|
||||
"playback-speed": "Velocidad de reproducción",
|
||||
"loop": "Bucle",
|
||||
"disable-loop": "Deshabilitar bucle",
|
||||
"rotate": "Rotar",
|
||||
"picture-in-picture": "Imagen en imagen",
|
||||
"exit-picture-in-picture": "Salir del modo imagen en imagen",
|
||||
"fullscreen": "Pantalla completa (F)",
|
||||
"exit-fullscreen": "Salir de la pantalla completa",
|
||||
"unsupported-format": "La vista previa del medio no está disponible para este formato de archivo:\n{{mime}}",
|
||||
"zoom-to-fit": "Acercamiento para llenar",
|
||||
"zoom-reset": "Reiniciar acercamiento para llenar"
|
||||
},
|
||||
"mermaid": {
|
||||
"placeholder": "Ingrese el contenido de su diagrama Mermaid o utilice uno de los diagramas de muestra a continuación.",
|
||||
"sample_diagrams": "Diagramas de muestra:",
|
||||
"sample_flowchart": "Diagrama de flujo",
|
||||
"sample_class": "Clase",
|
||||
"sample_sequence": "Secuencia",
|
||||
"sample_entity_relationship": "Relación entre entidades",
|
||||
"sample_state": "Estado",
|
||||
"sample_mindmap": "Mapa mental",
|
||||
"sample_architecture": "Arquitectura",
|
||||
"sample_block": "Bloque",
|
||||
"sample_c4": "C4",
|
||||
"sample_gantt": "Gantt",
|
||||
"sample_git": "Git",
|
||||
"sample_kanban": "Kanban",
|
||||
"sample_packet": "Paquete",
|
||||
"sample_pie": "Pastel",
|
||||
"sample_quadrant": "Cuadrante",
|
||||
"sample_radar": "Radar",
|
||||
"sample_requirement": "Requerimiento",
|
||||
"sample_sankey": "Sankey",
|
||||
"sample_timeline": "Línea de tiempo",
|
||||
"sample_user_journey": "Jornada de usuario",
|
||||
"sample_xy": "XY",
|
||||
"sample_venn": "Venn",
|
||||
"sample_ishikawa": "Ishikawa",
|
||||
"sample_treemap": "Mapa de árbol"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,10 @@
|
||||
},
|
||||
"widget-render-error": {
|
||||
"title": "Rendu impossible d'un widget React custom"
|
||||
}
|
||||
},
|
||||
"widget-missing-parent": "Le widget personnalisé ne comprend pas de propriété '{{property}}' définie\n\nSi ce script est prévu pour être exécuté sans fonctionnalité UI, utilisez '#run=frontendStartup' plutôt.",
|
||||
"open-script-note": "Ouvrir une note script",
|
||||
"scripting-error": "Échec du script personnalisé : {{title}}"
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "Ajouter un lien",
|
||||
@@ -46,7 +49,7 @@
|
||||
"prefix": "Préfixe : ",
|
||||
"save": "Sauvegarder",
|
||||
"branch_prefix_saved": "Le préfixe de la branche a été enregistré.",
|
||||
"edit_branch_prefix_multiple": "Modifier le préfixe de branche pour {{count}} branches",
|
||||
"edit_branch_prefix_multiple": "Modifier le préfixe pour {{count}} branches",
|
||||
"branch_prefix_saved_multiple": "Le préfixe de la branche a été sauvegardé pour {{count}} branches.",
|
||||
"affected_branches": "Branches impactées ({{count}}):"
|
||||
},
|
||||
@@ -114,7 +117,7 @@
|
||||
"export_in_progress": "Exportation en cours : {{progressCount}}",
|
||||
"export_finished_successfully": "L'exportation s'est terminée avec succès.",
|
||||
"format_pdf": "PDF - pour l'impression ou le partage de documents.",
|
||||
"share-format": "HTML pour la publication Web - utilise le même thème que celui utilisé pour les notes partagées, mais peut être publié sous forme de site Web statique."
|
||||
"share-format": "HTML pour la publication Web : utilise le même thème que celui utilisé pour les notes partagées, mais peut être publié sous forme de site Web statique."
|
||||
},
|
||||
"help": {
|
||||
"noteNavigation": "Navigation dans les notes",
|
||||
@@ -443,7 +446,8 @@
|
||||
"and_more": "... et {{count}} plus.",
|
||||
"print_landscape": "Lors de l'exportation en PDF, change l'orientation de la page en paysage au lieu de portrait.",
|
||||
"print_page_size": "Lors de l'exportation en PDF, change la taille de la page. Valeurs supportées : <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>.",
|
||||
"color_type": "Couleur"
|
||||
"color_type": "Couleur",
|
||||
"textarea": "Texte multiligne"
|
||||
},
|
||||
"attribute_editor": {
|
||||
"help_text_body1": "Pour ajouter un label, tapez simplement par ex. <code>#rock</code>, ou si vous souhaitez également ajouter une valeur, tapez par ex. <code>#année = 2020</code>",
|
||||
@@ -659,7 +663,8 @@
|
||||
"show-cheatsheet": "Afficher l'aide rapide",
|
||||
"toggle-zen-mode": "Zen Mode",
|
||||
"new-version-available": "Nouvelle mise à jour disponible",
|
||||
"download-update": "Obtenir la version {{latestVersion}}"
|
||||
"download-update": "Obtenir la version {{latestVersion}}",
|
||||
"search_notes": "Rechercher notes"
|
||||
},
|
||||
"zen_mode": {
|
||||
"button_exit": "Sortir du Zen mode"
|
||||
@@ -703,7 +708,8 @@
|
||||
"advanced": "Avancé",
|
||||
"export_as_image": "Exporter en tant qu'image",
|
||||
"export_as_image_png": "PNG",
|
||||
"export_as_image_svg": "SVG (vectoriel)"
|
||||
"export_as_image_svg": "SVG (vectoriel)",
|
||||
"note_map": "Note Carte"
|
||||
},
|
||||
"onclick_button": {
|
||||
"no_click_handler": "Le widget bouton '{{componentId}}' n'a pas de gestionnaire de clic défini"
|
||||
@@ -741,23 +747,25 @@
|
||||
"button_title": "Exporter le diagramme au format SVG"
|
||||
},
|
||||
"relation_map_buttons": {
|
||||
"create_child_note_title": "Créer une nouvelle note enfant et l'ajouter à cette carte de relation",
|
||||
"create_child_note_title": "Créer une note enfant et l'ajouter à la carte",
|
||||
"reset_pan_zoom_title": "Réinitialiser le panoramique et le zoom aux coordonnées et à la position initiales",
|
||||
"zoom_in_title": "Zoomer",
|
||||
"zoom_out_title": "Zoom arrière"
|
||||
},
|
||||
"zpetne_odkazy": {
|
||||
"relation": "relation",
|
||||
"backlink_one": "{{count}} Lien inverse",
|
||||
"backlink_many": "",
|
||||
"backlink_other": "{{count}} Liens inverses"
|
||||
"backlink_one": "{{count}} Rétrolien",
|
||||
"backlink_many": "{{count}} Rétroliens",
|
||||
"backlink_other": "{{count}} Rétrolien"
|
||||
},
|
||||
"mobile_detail_menu": {
|
||||
"insert_child_note": "Insérer une note enfant",
|
||||
"delete_this_note": "Supprimer cette note",
|
||||
"error_cannot_get_branch_id": "Impossible d'obtenir branchId pour notePath '{{notePath}}'",
|
||||
"error_unrecognized_command": "Commande non reconnue {{command}}",
|
||||
"note_revisions": "Révision de la note"
|
||||
"note_revisions": "Révision de la note",
|
||||
"backlinks": "Rétro-liens",
|
||||
"content_language_switcher": "Langue du contenu: {{language}}"
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "Changer l'icône de note",
|
||||
@@ -766,7 +774,12 @@
|
||||
"filter": "Filtre",
|
||||
"filter-none": "Toutes les icônes",
|
||||
"filter-default": "Icônes par défaut",
|
||||
"icon_tooltip": "{{name}}\nPack d'icônes : {{iconPack}}"
|
||||
"icon_tooltip": "{{name}}\nPack d'icônes : {{iconPack}}",
|
||||
"no_results": "Aucune icône trouvée.",
|
||||
"search_placeholder_one": "{{number}} icône recherchées parmi {{count}} packs.",
|
||||
"search_placeholder_many": "{{number}} icônes recherchées parmi {{count}} packs.",
|
||||
"search_placeholder_other": "{{number}} icônes recherchées parmi {{count}} packs.",
|
||||
"search_placeholder_filtered": "Rechercher {{number}} icônes dans {{name}}"
|
||||
},
|
||||
"basic_properties": {
|
||||
"note_type": "Type de note",
|
||||
@@ -782,7 +795,7 @@
|
||||
"collapse_all_notes": "Réduire toutes les notes",
|
||||
"collapse": "Réduire",
|
||||
"expand": "Développer",
|
||||
"invalid_view_type": "Type de vue non valide '{{type}}'",
|
||||
"invalid_view_type": "Type de vue '{{type}}' non valide",
|
||||
"calendar": "Calendrier",
|
||||
"book_properties": "Propriétés de la collection",
|
||||
"table": "Tableau",
|
||||
@@ -793,7 +806,8 @@
|
||||
"expand_tooltip": "Développe les éléments enfants directs de cette collection (à un niveau). Pour plus d'options, appuyez sur la flèche à droite.",
|
||||
"expand_first_level": "Développer les enfants directs",
|
||||
"expand_nth_level": "Développer sur {{depth}} niveaux",
|
||||
"expand_all_levels": "Développer tous les niveaux"
|
||||
"expand_all_levels": "Développer tous les niveaux",
|
||||
"hide_child_notes": "Masquer les notes enfants dans l’arborescence"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "Aucune note modifiée ce jour-là...",
|
||||
@@ -806,7 +820,7 @@
|
||||
"file_type": "Type de fichier",
|
||||
"file_size": "Taille du fichier",
|
||||
"download": "Télécharger",
|
||||
"open": "Ouvrir",
|
||||
"open": "Ouvrir dans une nouvelle fenêtre",
|
||||
"upload_new_revision": "Téléverser une nouvelle version",
|
||||
"upload_success": "Une nouvelle version de fichier a été téléversée.",
|
||||
"upload_failed": "Le téléversement d'une nouvelle version de fichier a échoué.",
|
||||
@@ -826,7 +840,8 @@
|
||||
},
|
||||
"inherited_attribute_list": {
|
||||
"title": "Attributs hérités",
|
||||
"no_inherited_attributes": "Aucun attribut hérité."
|
||||
"no_inherited_attributes": "Aucun attribut hérité.",
|
||||
"none": "aucun"
|
||||
},
|
||||
"note_info_widget": {
|
||||
"note_id": "Identifiant de la note",
|
||||
@@ -903,7 +918,8 @@
|
||||
"unknown_search_option": "Option de recherche inconnue {{searchOptionName}}",
|
||||
"search_note_saved": "La note de recherche a été enregistrée dans {{- notePathTitle}}",
|
||||
"actions_executed": "Les actions ont été exécutées.",
|
||||
"view_options": "Afficher les options:"
|
||||
"view_options": "Afficher les options:",
|
||||
"option": "option"
|
||||
},
|
||||
"similar_notes": {
|
||||
"title": "Notes similaires",
|
||||
@@ -997,7 +1013,7 @@
|
||||
"no_attachments": "Cette note ne contient aucune pièce jointe."
|
||||
},
|
||||
"book": {
|
||||
"no_children_help": "Cette note de type Livre n'a aucune note enfant, donc il n'y a rien à afficher. Consultez le <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> pour plus de détails.",
|
||||
"no_children_help": "Cette collection ne contient pas de notes enfants, il n'y a donc rien à afficher.",
|
||||
"drag_locked_title": "Edition verrouillée",
|
||||
"drag_locked_message": "Le glisser-déposer n'est pas autorisé car l'édition de cette collection est verrouillé."
|
||||
},
|
||||
@@ -1036,7 +1052,6 @@
|
||||
"unprotecting-title": "Statut de la non-protection"
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "Ouvrir dans un nouvel onglet",
|
||||
"remove_note": "Supprimer la note",
|
||||
"edit_title": "Modifier le titre",
|
||||
"rename_note": "Renommer la note",
|
||||
@@ -1053,15 +1068,6 @@
|
||||
"default_new_note_title": "nouvelle note",
|
||||
"click_on_canvas_to_place_new_note": "Cliquez sur le canevas pour placer une nouvelle note"
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_1": "Cette note d'aide s'affiche car cette note de type Rendu HTML n'a pas la relation requise pour fonctionner correctement.",
|
||||
"note_detail_render_help_2": "Le type de note Rendu HTML est utilisé pour les <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">scripts</a>. En résumé, vous disposez d'une note de code HTML (éventuellement contenant JavaScript) et cette note affichera le rendu. Pour que cela fonctionne, vous devez définir une <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">relation</a> appelée \"renderNote\" pointant vers la note HTML à rendre."
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "Affichage Web",
|
||||
"embed_websites": "Les notes de type Affichage Web vous permet d'intégrer des sites Web dans Trilium.",
|
||||
"create_label": "Pour commencer, veuillez créer un label avec l'adresse URL que vous souhaitez intégrer, par ex. #webViewSrc=\"https://www.google.com\""
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "Rafraîchir"
|
||||
},
|
||||
@@ -1181,8 +1187,8 @@
|
||||
},
|
||||
"code_mime_types": {
|
||||
"title": "Types MIME disponibles dans la liste déroulante",
|
||||
"tooltip_syntax_highlighting": "Souligner la syntaxe",
|
||||
"tooltip_code_block_syntax": "Blocs de code dans les notes de texte",
|
||||
"tooltip_syntax_highlighting": "Mise en évidence de la syntaxe",
|
||||
"tooltip_code_block_syntax": "Blocs de code dans les notes textuelles",
|
||||
"tooltip_code_note_syntax": "Notes de code"
|
||||
},
|
||||
"vim_key_bindings": {
|
||||
@@ -1377,7 +1383,8 @@
|
||||
"description": "Description",
|
||||
"reload_app": "Recharger l'application pour appliquer les modifications",
|
||||
"set_all_to_default": "Réinitialiser aux valeurs par défaut",
|
||||
"confirm_reset": "Voulez-vous vraiment réinitialiser tous les raccourcis clavier par défaut ?"
|
||||
"confirm_reset": "Voulez-vous vraiment réinitialiser tous les raccourcis clavier par défaut ?",
|
||||
"no_results": "Aucun raccourci correspondant à '{{filter}}'"
|
||||
},
|
||||
"spellcheck": {
|
||||
"title": "Vérification orthographique",
|
||||
@@ -1412,7 +1419,7 @@
|
||||
"will_be_deleted_in": "Cette pièce jointe sera automatiquement supprimée dans {{time}}",
|
||||
"will_be_deleted_soon": "Cette pièce jointe sera bientôt supprimée automatiquement",
|
||||
"deletion_reason": ", car la pièce jointe n'est pas liée dans le contenu de la note. Pour empêcher la suppression, ajoutez à nouveau le lien de la pièce jointe dans le contenu d'une note ou convertissez la pièce jointe en note.",
|
||||
"role_and_size": "Rôle : {{role}}, Taille : {{size}}",
|
||||
"role_and_size": "Rôle : {{role}}, Taille : {{size}}, MIME: {{- mimeType}}",
|
||||
"link_copied": "Lien de pièce jointe copié dans le presse-papiers.",
|
||||
"unrecognized_role": "Rôle de pièce jointe « {{role}} » non reconnu."
|
||||
},
|
||||
@@ -1463,10 +1470,13 @@
|
||||
"import-into-note": "Importer dans la note",
|
||||
"apply-bulk-actions": "Appliquer des Actions groupées",
|
||||
"converted-to-attachments": "Les notes {{count}} ont été converties en pièces jointes.",
|
||||
"convert-to-attachment-confirm": "Êtes-vous sûr de vouloir convertir les notes sélectionnées en pièces jointes de leurs notes parentes ?",
|
||||
"convert-to-attachment-confirm": "Êtes-vous sûr de vouloir convertir les notes sélectionnées en pièces jointes de leurs notes parentales ? Cette opération s'applique uniquement aux notes d'image, les autres notes seront ignorées.",
|
||||
"archive": "Archive",
|
||||
"unarchive": "Désarchiver",
|
||||
"open-in-popup": "Modification rapide"
|
||||
"open-in-popup": "Modification rapide",
|
||||
"open-in-a-new-window": "Ouvrir dans une nouvelle fenêtre",
|
||||
"hide-subtree": "Masquer le sous-arbre",
|
||||
"show-subtree": "Afficher le sous-arbre"
|
||||
},
|
||||
"shared_info": {
|
||||
"shared_publicly": "Cette note est partagée publiquement sur {{- link}}.",
|
||||
@@ -1494,9 +1504,11 @@
|
||||
"beta-feature": "Beta",
|
||||
"task-list": "Liste de tâches",
|
||||
"book": "Collection",
|
||||
"ai-chat": "Chat IA",
|
||||
"new-feature": "Nouveau",
|
||||
"collections": "Collections"
|
||||
"collections": "Collections",
|
||||
"ai-chat": "Chat IA",
|
||||
"llm-chat": "Chat AI",
|
||||
"spreadsheet": "Feuille de calcul"
|
||||
},
|
||||
"protect_note": {
|
||||
"toggle-on": "Protéger la note",
|
||||
@@ -1527,7 +1539,13 @@
|
||||
},
|
||||
"highlights_list_2": {
|
||||
"title": "Accentuations",
|
||||
"options": "Options"
|
||||
"options": "Options",
|
||||
"title_with_count_one": "{{count}} mise en évidence",
|
||||
"title_with_count_many": "{{count}} mises en évidence",
|
||||
"title_with_count_other": "{{count}} mises en évidence",
|
||||
"modal_title": "Configurer les mises en évidence",
|
||||
"menu_configure": "Configuration des mises en évidence...",
|
||||
"no_highlights": "Aucune mise en évidence."
|
||||
},
|
||||
"quick-search": {
|
||||
"placeholder": "Recherche rapide",
|
||||
@@ -1551,7 +1569,17 @@
|
||||
"create-child-note": "Créer une note enfant",
|
||||
"unhoist": "Désactiver le focus",
|
||||
"toggle-sidebar": "Basculer la barre latérale",
|
||||
"dropping-not-allowed": "Lâcher des notes à cet endroit n'est pas autorisé"
|
||||
"dropping-not-allowed": "Déplacer des notes à cet emplacement n'est pas autorisé.",
|
||||
"clone-indicator-tooltip": "Cette note a {{- count}} parents: {{- parents}}",
|
||||
"clone-indicator-tooltip-single": "Cette note est clonée (1 parent supplémentaire: {{- parent}})",
|
||||
"shared-indicator-tooltip": "Cette note est partagée publiquement",
|
||||
"shared-indicator-tooltip-with-url": "Cette note est partagée publiquement sur: {{- url}}",
|
||||
"subtree-hidden-tooltip_one": "{{count}} note enfant cachée de l'arbre",
|
||||
"subtree-hidden-tooltip_many": "{{count}} notes enfants cachées de l'arbre",
|
||||
"subtree-hidden-tooltip_other": "{{count}} notes enfants cachées de l'arbre",
|
||||
"subtree-hidden-moved-title": "Ajouté à {{title}}",
|
||||
"subtree-hidden-moved-description-collection": "Cette collection cache ses notes enfants dans l'arbre.",
|
||||
"subtree-hidden-moved-description-other": "Les notes enfants sont cachées dans l'arbre pour cette note."
|
||||
},
|
||||
"title_bar_buttons": {
|
||||
"window-on-top": "Épingler cette fenêtre au premier plan"
|
||||
@@ -1562,7 +1590,12 @@
|
||||
"printing_pdf": "Export au format PDF en cours...",
|
||||
"print_report_title": "Imprimer le rapport",
|
||||
"print_report_collection_details_button": "Consulter les détails",
|
||||
"print_report_collection_details_ignored_notes": "Notes ignorées"
|
||||
"print_report_collection_details_ignored_notes": "Notes ignorées",
|
||||
"print_report_error_title": "Échec de l'impression",
|
||||
"print_report_stack_trace": "Trace de la pile",
|
||||
"print_report_collection_content_one": "La {{count}} note de la collection n'a pas pu être imprimée car elle n'est pas prises en charge ou est protégée.",
|
||||
"print_report_collection_content_many": "Les {{count}} notes de la collection n'ont pas pu être imprimées car elles ne sont pas prises en charge ou sont protégées.",
|
||||
"print_report_collection_content_other": "Les {{count}} notes de la collection n'ont pas pu être imprimées car elles ne sont pas prises en charge ou sont protégées."
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "saisir le titre de la note ici...",
|
||||
@@ -1571,17 +1604,24 @@
|
||||
"note_type_switcher_label": "Basculer de {{type}} à :",
|
||||
"note_type_switcher_others": "Autre type de note",
|
||||
"note_type_switcher_templates": "Modèle",
|
||||
"note_type_switcher_collection": "Collection"
|
||||
"note_type_switcher_collection": "Collection",
|
||||
"edited_notes": "Notes éditées ce jour",
|
||||
"promoted_attributes": "Attributs promus"
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "Aucune note n'a été trouvée pour les paramètres de recherche donnés.",
|
||||
"search_not_executed": "La recherche n'a pas encore été exécutée. Cliquez sur le bouton \"Rechercher\" ci-dessus pour voir les résultats."
|
||||
"search_not_executed": "La recherche n'a pas encore été exécutée.",
|
||||
"search_now": "Recherche maintenant"
|
||||
},
|
||||
"spacer": {
|
||||
"configure_launchbar": "Configurer la Barre de raccourcis"
|
||||
},
|
||||
"sql_result": {
|
||||
"no_rows": "Aucune ligne n'a été renvoyée pour cette requête"
|
||||
"no_rows": "Aucune ligne n'a été renvoyée pour cette requête",
|
||||
"not_executed": "La requête n'a pas encore été exécutée.",
|
||||
"failed": "L'exécution de requêtes SQL a échoué",
|
||||
"statement_result": "Résultat de la déclaration",
|
||||
"execute_now": "Exécuter maintenant"
|
||||
},
|
||||
"sql_table_schemas": {
|
||||
"tables": "Tableaux"
|
||||
@@ -1699,11 +1739,12 @@
|
||||
"add-term-to-dictionary": "Ajouter «{{term}}» au dictionnaire",
|
||||
"cut": "Couper",
|
||||
"copy": "Copier",
|
||||
"copy-as-markdown": "Copier en markdown",
|
||||
"copy-link": "Copier le lien",
|
||||
"paste": "Coller",
|
||||
"paste-as-plain-text": "Coller comme texte brut",
|
||||
"search_online": "Rechercher «{{term}}» avec {{searchEngine}}",
|
||||
"search_in_trilium": "Rechercher \"{{term}}\" dans Trilium"
|
||||
"search_in_trilium": "Rechercher « {{term}} » dans Trilium"
|
||||
},
|
||||
"image_context_menu": {
|
||||
"copy_reference_to_clipboard": "Copier la référence dans le presse-papiers",
|
||||
@@ -1713,14 +1754,15 @@
|
||||
"open_note_in_new_tab": "Ouvrir la note dans un nouvel onglet",
|
||||
"open_note_in_new_split": "Ouvrir la note dans une nouvelle division",
|
||||
"open_note_in_new_window": "Ouvrir la note dans une nouvelle fenêtre",
|
||||
"open_note_in_popup": "Édition rapide"
|
||||
"open_note_in_popup": "Édition rapide",
|
||||
"open_note_in_other_split": "Ouvrir la note dans l'autre volet"
|
||||
},
|
||||
"electron_integration": {
|
||||
"desktop-application": "Application de bureau",
|
||||
"native-title-bar": "Barre de titre native",
|
||||
"native-title-bar-description": "Sous Windows et macOS, désactiver la barre de titre native rend l'application plus compacte. Sous Linux, le maintien de la barre de titre native permet une meilleure intégration avec le reste du système.",
|
||||
"background-effects": "Activer les effets d'arrière-plan (Windows 11 uniquement)",
|
||||
"background-effects-description": "L'effet Mica ajoute un fond flou et élégant aux fenêtres de l'application, créant une profondeur et un style moderne.",
|
||||
"background-effects": "Activer les effets d'arrière-plan",
|
||||
"background-effects-description": "Ajoute un arrière-plan flou et élégant aux fenêtres d'application, créant de la profondeur et un style moderne. La « barre de titre native » doit être désactivée.",
|
||||
"restart-app-button": "Redémarrez l'application pour afficher les modifications",
|
||||
"zoom-factor": "Facteur de zoom"
|
||||
},
|
||||
@@ -1739,7 +1781,8 @@
|
||||
"geo-map": {
|
||||
"create-child-note-title": "Créer une nouvelle note enfant et l'ajouter à la carte",
|
||||
"create-child-note-instruction": "Cliquez sur la carte pour créer une nouvelle note à cet endroit ou appuyez sur Échap pour la supprimer.",
|
||||
"unable-to-load-map": "Impossible de charger la carte."
|
||||
"unable-to-load-map": "Impossible de charger la carte.",
|
||||
"create-child-note-text": "Ajouter le marqueur"
|
||||
},
|
||||
"geo-map-context": {
|
||||
"open-location": "Ouvrir la position",
|
||||
@@ -1807,149 +1850,6 @@
|
||||
"close": "Fermer",
|
||||
"help_title": "Afficher plus d'informations sur cet écran"
|
||||
},
|
||||
"ai_llm": {
|
||||
"not_started": "Non démarré",
|
||||
"title": "Paramètres IA",
|
||||
"processed_notes": "Notes traitées",
|
||||
"anthropic_url_description": "URL de base pour l'API Anthropic (par défaut : https ://api.anthropic.com)",
|
||||
"anthropic_model_description": "Modèles Anthropic Claude pour la complétion",
|
||||
"voyage_settings": "Réglages d'IA Voyage",
|
||||
"ollama_settings": "Réglages Ollama",
|
||||
"ollama_url_description": "URL pour l'API Ollama (par défaut: http://localhost:11434)",
|
||||
"ollama_model_description": "Model Ollama utilisé pour la complétion",
|
||||
"anthropic_configuration": "Configuration Anthropic",
|
||||
"voyage_configuration": "Configuration IA Voyage",
|
||||
"voyage_url_description": "Défaut: https://api.voyageai.com/v1",
|
||||
"ollama_configuration": "Configuration Ollama",
|
||||
"total_notes": "Notes totales",
|
||||
"progress": "Progrès",
|
||||
"queued_notes": "Notes dans la file d'attente",
|
||||
"refresh_stats": "Rafraîchir les statistiques",
|
||||
"enable_ai_features": "Activer les fonctionnalités IA/LLM",
|
||||
"enable_ai_description": "Activer les fonctionnalités IA telles que le résumé des notes, la génération de contenu et autres fonctionnalités LLM",
|
||||
"openai_tab": "OpenAI",
|
||||
"anthropic_tab": "Anthropic",
|
||||
"voyage_tab": "Voyage AI",
|
||||
"ollama_tab": "Ollama",
|
||||
"enable_ai": "Activer les fonctionnalités IA/LLM",
|
||||
"enable_ai_desc": "Activer les fonctionnalités IA telles que le résumé des notes, la génération de contenu et autres fonctionnalités LLM",
|
||||
"provider_configuration": "Configuration du fournisseur IA",
|
||||
"provider_precedence_description": "Liste de fournisseurs séparés par virgule, par ordre de préférence (ex. 'openai,anthopic,ollama')",
|
||||
"temperature": "Température",
|
||||
"temperature_description": "Contrôle de l'aléatoirité dans les réponses (0 = déterministe, 2 = hasard maximum)",
|
||||
"system_prompt": "Prompt système",
|
||||
"system_prompt_description": "Prompt système par défaut pour toutes les intéractions IA",
|
||||
"openai_configuration": "Configuration OpenAI",
|
||||
"openai_settings": "Options OpenAI",
|
||||
"api_key": "Clef API",
|
||||
"url": "URL de base",
|
||||
"model": "Modèle",
|
||||
"openai_api_key_description": "Votre clef API OpenAI pour accéder à leurs services IA",
|
||||
"anthropic_api_key_description": "Votre clef API Anthropic pour accéder aux modèles Claude",
|
||||
"default_model": "Modèle par défaut",
|
||||
"openai_model_description": "Exemples : gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
|
||||
"base_url": "URL de base",
|
||||
"openai_url_description": "Défaut : https://api.openai.com/v1",
|
||||
"anthropic_settings": "Réglages Anthropic",
|
||||
"enable_ollama": "Activer Ollama",
|
||||
"enable_ollama_description": "Activer Ollama comme modèle d'IA local",
|
||||
"ollama_url": "URL Ollama",
|
||||
"ollama_model": "Modèle Ollama",
|
||||
"refresh_models": "Rafraîchir les modèles",
|
||||
"refreshing_models": "Mise à jour...",
|
||||
"enable_automatic_indexing": "Activer l'indexage automatique",
|
||||
"rebuild_index": "Rafraîchir l'index",
|
||||
"rebuild_index_error": "Erreur dans le démarrage du rafraichissement de l'index. Veuillez consulter les logs pour plus de détails.",
|
||||
"note_title": "Titre de la note",
|
||||
"error": "Erreur",
|
||||
"last_attempt": "Dernier essai",
|
||||
"actions": "Actions",
|
||||
"retry": "Réessayer",
|
||||
"partial": "Complété à {{ percentage }}%",
|
||||
"retry_queued": "Note ajoutée à la file d'attente",
|
||||
"retry_failed": "Echec de l'ajout de la note à la file d'attente",
|
||||
"max_notes_per_llm_query": "Notes maximum par requête",
|
||||
"max_notes_per_llm_query_description": "Nombre maximum de notes similaires à inclure dans le contexte IA",
|
||||
"active_providers": "Fournisseurs actifs",
|
||||
"disabled_providers": "Fournisseurs désactivés",
|
||||
"remove_provider": "Retirer le fournisseur de la recherche",
|
||||
"similarity_threshold": "Seuil de similarité",
|
||||
"similarity_threshold_description": "Seuil de similarité minimum (0-1) pour que inclure les notes dans le contexte d'une requête IA",
|
||||
"reprocess_index": "Rafraîchir l'index de recherche",
|
||||
"reprocessing_index": "Mise à jour...",
|
||||
"reprocess_index_started": "L'optimisation de l'indice de recherche à commencer en arrière-plan",
|
||||
"reprocess_index_error": "Erreur dans le rafraichissement de l'indice de recherche",
|
||||
"failed_notes": "Notes en erreur",
|
||||
"last_processed": "Dernier traitement",
|
||||
"restore_provider": "Restaurer le fournisseur de recherche",
|
||||
"index_rebuild_progress": "Progression de la reconstruction de l'index",
|
||||
"index_rebuilding": "Optimisation de l'index ({{percentage}}%)",
|
||||
"index_rebuild_complete": "Optimisation de l'index terminée",
|
||||
"index_rebuild_status_error": "Erreur lors de la vérification de l'état de reconstruction de l'index",
|
||||
"provider_precedence": "Priorité du fournisseur",
|
||||
"never": "Jamais",
|
||||
"processing": "Traitement en cours ({{percentage}}%)",
|
||||
"incomplete": "Incomplet ({{percentage}}%)",
|
||||
"complete": "Terminé (100%)",
|
||||
"refreshing": "Mise à jour...",
|
||||
"auto_refresh_notice": "Actualisation automatique toutes les {{seconds}} secondes",
|
||||
"note_queued_for_retry": "Note mise en file d'attente pour une nouvelle tentative",
|
||||
"failed_to_retry_note": "Échec de la nouvelle tentative de note",
|
||||
"all_notes_queued_for_retry": "Toutes les notes ayant échoué sont mises en file d'attente pour une nouvelle tentative",
|
||||
"failed_to_retry_all": "Échec du ré essai des notes",
|
||||
"ai_settings": "Paramètres IA",
|
||||
"api_key_tooltip": "Clé API pour accéder au service",
|
||||
"empty_key_warning": {
|
||||
"anthropic": "La clé API Anthropic est vide. Veuillez saisir une clé API valide.",
|
||||
"openai": "La clé API OpenAI est vide. Veuillez saisir une clé API valide.",
|
||||
"voyage": "La clé API Voyage est vide. Veuillez saisir une clé API valide.",
|
||||
"ollama": "La clé API Ollama est vide. Veuillez saisir une clé API valide."
|
||||
},
|
||||
"agent": {
|
||||
"processing": "Traitement...",
|
||||
"thinking": "Réflexion...",
|
||||
"loading": "Chargement...",
|
||||
"generating": "Génération..."
|
||||
},
|
||||
"name": "IA",
|
||||
"openai": "OpenAI",
|
||||
"use_enhanced_context": "Utiliser un contexte amélioré",
|
||||
"enhanced_context_description": "Fournit à l'IA plus de contexte à partir de la note et de ses notes associées pour de meilleures réponses",
|
||||
"show_thinking": "Montrer la réflexion",
|
||||
"show_thinking_description": "Montrer la chaîne de pensée de l'IA",
|
||||
"enter_message": "Entrez votre message...",
|
||||
"error_contacting_provider": "Erreur lors de la connexion au fournisseur d'IA. Veuillez vérifier vos paramètres et votre connexion Internet.",
|
||||
"error_generating_response": "Erreur lors de la génération de la réponse de l'IA",
|
||||
"index_all_notes": "Indexer toutes les notes",
|
||||
"index_status": "Statut de l'index",
|
||||
"indexed_notes": "Notes indexées",
|
||||
"indexing_stopped": "Arrêt de l'indexation",
|
||||
"indexing_in_progress": "Indexation en cours...",
|
||||
"last_indexed": "Dernière indexée",
|
||||
"note_chat": "Note discussion",
|
||||
"sources": "Sources",
|
||||
"start_indexing": "Démarrage de l'indexation",
|
||||
"use_advanced_context": "Utiliser le contexte avancé",
|
||||
"ollama_no_url": "Ollama n'est pas configuré. Veuillez saisir une URL valide.",
|
||||
"chat": {
|
||||
"root_note_title": "Discussions IA",
|
||||
"root_note_content": "Cette note contient vos conversations de chat IA enregistrées.",
|
||||
"new_chat_title": "Nouvelle discussion",
|
||||
"create_new_ai_chat": "Créer une nouvelle discussion IA"
|
||||
},
|
||||
"create_new_ai_chat": "Créer une nouvelle discussion IA",
|
||||
"configuration_warnings": "Il y a quelques problèmes avec la configuration de votre IA. Veuillez vérifier vos paramètres.",
|
||||
"experimental_warning": "La fonctionnalité LLM est actuellement expérimentale – vous êtes prévenu.",
|
||||
"selected_provider": "Fournisseur sélectionné",
|
||||
"selected_provider_description": "Choisissez le fournisseur d’IA pour les fonctionnalités de discussion et de complétion",
|
||||
"select_model": "Sélectionner le modèle...",
|
||||
"select_provider": "Sélectionnez un fournisseur...",
|
||||
"ai_enabled": "Fonctionnalités d'IA activées",
|
||||
"ai_disabled": "Fonctionnalités d'IA désactivées",
|
||||
"no_models_found_online": "Aucun modèle trouvé. Veuillez vérifier votre clé API et vos paramètres.",
|
||||
"no_models_found_ollama": "Aucun modèle Ollama trouvé. Veuillez vérifier si Ollama est en cours d'exécution.",
|
||||
"error_fetching": "Erreur lors de la récupération des modèles : {{error}}"
|
||||
},
|
||||
"ui-performance": {
|
||||
"title": "Performance",
|
||||
"enable-motion": "Activer les transitions et animations",
|
||||
@@ -1987,12 +1887,13 @@
|
||||
"book_properties_config": {
|
||||
"hide-weekends": "Masquer les week-ends",
|
||||
"display-week-numbers": "Afficher les numéros de semaine",
|
||||
"map-style": "Style de carte :",
|
||||
"map-style": "Style de carte",
|
||||
"max-nesting-depth": "Profondeur d'imbrication maximale :",
|
||||
"raster": "Trame",
|
||||
"vector_light": "Vecteur (clair)",
|
||||
"vector_dark": "Vecteur (foncé)",
|
||||
"show-scale": "Afficher l'échelle"
|
||||
"show-scale": "Afficher l'échelle",
|
||||
"show-labels": "Afficher les noms des marqueurs"
|
||||
},
|
||||
"table_context_menu": {
|
||||
"delete_row": "Supprimer la ligne"
|
||||
@@ -2013,7 +1914,7 @@
|
||||
"add-column-placeholder": "Entrez le nom de la colonne...",
|
||||
"edit-note-title": "Cliquez pour modifier le titre de la note",
|
||||
"edit-column-title": "Cliquez pour modifier le titre de la colonne",
|
||||
"column-already-exists": "Cette colonne existe déjà dans le tableau."
|
||||
"column-already-exists": "Cette colonne existe déjà sur le tableau."
|
||||
},
|
||||
"presentation_view": {
|
||||
"edit-slide": "Modifier cette diapositive",
|
||||
@@ -2043,23 +1944,30 @@
|
||||
"next_theme_message": "Vous utilisez actuellement le thème hérité de l'ancienne version, souhaitez-vous essayer le nouveau thème ?",
|
||||
"next_theme_button": "Essayez le nouveau thème",
|
||||
"background_effects_title": "Les effets d'arrière-plan sont désormais stables",
|
||||
"background_effects_message": "Sur les appareils Windows, les effets d'arrière-plan sont désormais parfaitement stables. Ils ajoutent une touche de couleur à l'interface utilisateur en floutant l'arrière-plan. Cette technique est également utilisée dans d'autres applications comme l'Explorateur Windows.",
|
||||
"background_effects_message": "Sur les appareils Windows et macOS les effets d'arrière-plan sont désormais stables. Ils ajoutent une touche de couleur à l'interface utilisateur en floutant l'arrière-plan.",
|
||||
"background_effects_button": "Activer les effets d'arrière-plan",
|
||||
"dismiss": "Rejeter"
|
||||
"dismiss": "Rejeter",
|
||||
"new_layout_title": "Nouvelle mise en page",
|
||||
"new_layout_message": "Nous avons introduit une mise en page modernisée pour Trilium. Le ruban a été supprimé et intégré de manière transparente dans l'interface principale, avec une nouvelle barre d'état et des sections extensibles (telles que les attributs promus) reprenant les fonctions clés.\n\nLa nouvelle mise en page est activée par défaut et peut être temporairement désactivée via Options → Apparence.",
|
||||
"new_layout_button": "Plus d'infos"
|
||||
},
|
||||
"settings": {
|
||||
"related_settings": "Paramètres associés"
|
||||
},
|
||||
"settings_appearance": {
|
||||
"related_code_blocks": "Schéma de coloration syntaxique pour les blocs de code dans les notes de texte",
|
||||
"related_code_notes": "Schéma de couleurs pour les notes de code"
|
||||
"related_code_notes": "Schéma de couleurs pour les notes de code",
|
||||
"ui": "Interface utilisateur",
|
||||
"ui_old_layout": "Ancienne mise en page",
|
||||
"ui_new_layout": "Nouvelle mise en page"
|
||||
},
|
||||
"units": {
|
||||
"percentage": "%"
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "Page de {{startIndex}} - {{endIndex}}",
|
||||
"total_notes": "{{count}} notes"
|
||||
"total_notes": "{{count}} notes",
|
||||
"prev_page": "Page précédente",
|
||||
"next_page": "Page suivante"
|
||||
},
|
||||
"collections": {
|
||||
"rendering_error": "Impossible d'afficher le contenu en raison d'une erreur."
|
||||
@@ -2078,8 +1986,9 @@
|
||||
"unknown_widget": "Widget inconnu pour « {{id}} »."
|
||||
},
|
||||
"note_language": {
|
||||
"not_set": "Non défini",
|
||||
"configure-languages": "Configurer les langues..."
|
||||
"not_set": "Langage non défini",
|
||||
"configure-languages": "Configurer les langues...",
|
||||
"help-on-languages": "Aide sur les langues de contenu..."
|
||||
},
|
||||
"content_language": {
|
||||
"title": "Contenu des langues",
|
||||
@@ -2127,14 +2036,288 @@
|
||||
"title": "Options expérimentales",
|
||||
"disclaimer": "Ces options sont expérimentales et peuvent provoquer une instabilité. Utilisez avec prudence.",
|
||||
"new_layout_name": "Nouvelle mise en page",
|
||||
"new_layout_description": "Essayez la nouvelle mise en page pour un look plus moderne et un usage améliorée. Sous réserve de changements importants dans les prochaines versions."
|
||||
"new_layout_description": "Essayez la nouvelle mise en page pour un look plus moderne et un usage améliorée. Sous réserve de changements importants dans les prochaines versions.",
|
||||
"llm_name": "AI / LLM Chat",
|
||||
"llm_description": "Activer la barre de chat AI et les notes de chat LLM alimentées par de grands modèles de langage."
|
||||
},
|
||||
"read-only-info": {
|
||||
"read-only-note": "Vous consultez actuellement une note en lecture seule.",
|
||||
"auto-read-only-note": "Cette note s'affiche en mode lecture seule pour un chargement plus rapide.",
|
||||
"edit-note": "Editer la note"
|
||||
"edit-note": "Modifier la note"
|
||||
},
|
||||
"calendar_view": {
|
||||
"delete_note": "Effacer la note..."
|
||||
"delete_note": "Supprimer la note..."
|
||||
},
|
||||
"media": {
|
||||
"play": "Lire (Espace)",
|
||||
"pause": "Pause (Espace)",
|
||||
"back-10s": "Retour arrière 10s (flèche gauche)",
|
||||
"forward-30s": "Avance 30s",
|
||||
"mute": "Silence (M)",
|
||||
"unmute": "Réactiver le son (M)",
|
||||
"playback-speed": "Vitesse de lecture",
|
||||
"loop": "Boucle",
|
||||
"disable-loop": "Désactiver la boucle",
|
||||
"rotate": "Rotation",
|
||||
"picture-in-picture": "Image dans l'image",
|
||||
"exit-picture-in-picture": "Sortir de Image dans l'image",
|
||||
"fullscreen": "Plein-écran (F)",
|
||||
"exit-fullscreen": "Sortir du mode plein-écran",
|
||||
"unsupported-format": "L'aperçu multimédia n'est pas disponible pour ce format de fichier:\n{{mime}}",
|
||||
"zoom-to-fit": "Zoom pour remplir",
|
||||
"zoom-reset": "Annuler zoom pour remplir"
|
||||
},
|
||||
"render": {
|
||||
"setup_title": "Afficher du HTML personnalisé ou Preact JSX dans cette note",
|
||||
"setup_create_sample_preact": "Créer un exemple de note avec Preact",
|
||||
"setup_create_sample_html": "Créer un exemple de note avec HTML",
|
||||
"setup_sample_created": "Un exemple de note a été créé en tant que note enfant.",
|
||||
"disabled_description": "Ces notes de rendu proviennent d'une source externe. Pour vous protéger de contenu malveillant, elle n'est pas activée par défaut. Assurez-vous de faire confiance à la source avant de l’activer.",
|
||||
"disabled_button_enable": "Activer la note de rendu"
|
||||
},
|
||||
"web_view_setup": {
|
||||
"title": "Créez la vue de la page Web directement dans Trilium",
|
||||
"url_placeholder": "Entrez ou collez l'adresse du site Web, par exemple https://triliumnotes.org",
|
||||
"create_button": "Créer une vue Web",
|
||||
"invalid_url_title": "Adresse invalide",
|
||||
"invalid_url_message": "Insérer une adresse Web valide, par exemple https://triliumnotes.org.",
|
||||
"disabled_description": "Cette vue Web a été importée à partir d'une source externe. Pour vous protéger du phishing ou du contenu malveillant, elle ne se charge pas automatiquement. Vous pouvez l'activer si vous faites confiance à la source.",
|
||||
"disabled_button_enable": "Activer la vue Web"
|
||||
},
|
||||
"llm_chat": {
|
||||
"placeholder": "Tapez un message...",
|
||||
"send": "Envoyer",
|
||||
"sending": "Envoi...",
|
||||
"empty_state": "Démarrez une conversation en tapant un message ci-dessous.",
|
||||
"searching_web": "Recherche sur le Web...",
|
||||
"web_search": "Recherche sur le Web",
|
||||
"note_tools": "Accès aux notes",
|
||||
"sources": "Sources",
|
||||
"extended_thinking": "Réflexion étendue",
|
||||
"legacy_models": "Modèles hérités",
|
||||
"thinking": "Réflexion...",
|
||||
"thought_process": "Processus de réflexion",
|
||||
"tool_calls": "{{count}} appel(s) d'outil",
|
||||
"input": "Entrée",
|
||||
"result": "Résultat",
|
||||
"error": "Erreur",
|
||||
"tool_error": "échoué",
|
||||
"total_tokens": "{{total}} jetons",
|
||||
"tokens_detail": "{{prompt}} prompt + {{completion}} achèvement",
|
||||
"tokens_used": "{{prompt}} prompt + {{completion}} achèvement = {{total}} jetons",
|
||||
"tokens_used_with_cost": "{{prompt}} prompt + {{completion}} achèvement = {{total}} jetons (~${{cost}})",
|
||||
"tokens_used_with_model": "{{model}}: {{prompt}} prompt + {{completion}} achèvement = {{total}} jetons",
|
||||
"tokens_used_with_model_and_cost": "{{model}}: {{prompt}} prompt + {{completion}} achèvement = {{total}} jetons (~${{cost}})",
|
||||
"tokens": "jetons",
|
||||
"context_used": "{{percentage}}% utilisé",
|
||||
"note_context_enabled": "Cliquez pour désactiver le contexte de la note : {{title}}",
|
||||
"note_context_disabled": "Cliquez pour inclure la note actuelle dans le contexte",
|
||||
"no_provider_message": "Aucun fournisseur d'IA configuré. Ajoutez en un pour commencer à discuter.",
|
||||
"add_provider": "Ajouter un fournisseur d'IA"
|
||||
},
|
||||
"sidebar_chat": {
|
||||
"title": "discussion IA",
|
||||
"launcher_title": "Ouvrir la discussion IA",
|
||||
"new_chat": "Démarrer une nouvelle discussion",
|
||||
"save_chat": "Enregistrer la discussion dans les notes",
|
||||
"empty_state": "Démarrer une conversation",
|
||||
"history": "Historique des discussions",
|
||||
"recent_chats": "Discussions récentes",
|
||||
"no_chats": "Pas de discussions précédentes"
|
||||
},
|
||||
"note-color": {
|
||||
"clear-color": "Retirer la couleur de la note",
|
||||
"set-color": "Définir la couleur de la note",
|
||||
"set-custom-color": "Définir la couleur personnalisée de la note"
|
||||
},
|
||||
"popup-editor": {
|
||||
"maximize": "Basculer sur l'éditeur complet"
|
||||
},
|
||||
"server": {
|
||||
"unknown_http_error_title": "Erreur de communication avec le serveur",
|
||||
"unknown_http_error_content": "Code de statut: {{statusCode}}\nURL: {{method}} {{url}}\nMessage: {{message}}",
|
||||
"traefik_blocks_requests": "Si vous utilisez le reverse proxy Traefik, celui-ci a introduit un changement de rupture qui affecte la communication avec le serveur."
|
||||
},
|
||||
"tab_history_navigation_buttons": {
|
||||
"go-back": "Revenir à la note précédente",
|
||||
"go-forward": "Aller vers la note suivante"
|
||||
},
|
||||
"breadcrumb": {
|
||||
"hoisted_badge": "Remonté",
|
||||
"hoisted_badge_title": "Redescendu",
|
||||
"workspace_badge": "Espace de travail",
|
||||
"scroll_to_top_title": "Aller au début de la note",
|
||||
"create_new_note": "Créer une nouvelle note enfant",
|
||||
"empty_hide_archived_notes": "Cacher les notes archivées"
|
||||
},
|
||||
"breadcrumb_badges": {
|
||||
"read_only_explicit": "Lecture seule",
|
||||
"read_only_explicit_description": "Cette note a été paramétrée manuellement en lecture seule.\nCliquer pour temporairement l'éditer.",
|
||||
"read_only_auto": "Lecture seule automatique",
|
||||
"read_only_auto_description": "Cette note a été réglée automatiquement en mode lecture seule pour des raisons de performances. Cette limite automatique est réglable à partir des paramètres.\n\nCliquez pour la modifier temporairement.",
|
||||
"read_only_temporarily_disabled": "Temporairement modifiable",
|
||||
"read_only_temporarily_disabled_description": "Cette note est actuellement modifiable, mais elle est normalement en lecture seule. La note redeviendra en lecture seule dès que vous accéderez à une autre note.\n\nCliquez pour réactiver le mode lecture seule.",
|
||||
"shared_publicly": "Partagés publiquement",
|
||||
"shared_locally": "Partagé localement",
|
||||
"shared_copy_to_clipboard": "Copier le lien vers le presse-papier",
|
||||
"shared_open_in_browser": "Ouvrir le lien dans le navigateur",
|
||||
"shared_unshare": "Supprimer le partage",
|
||||
"clipped_note": "Clip Web",
|
||||
"clipped_note_description": "Cette note a été initialement construite depuis l'url {{url}}.\n\nCliquez pour accéder à la page Web source.",
|
||||
"execute_script": "Exécuter le script",
|
||||
"execute_script_description": "Cette note est une note de script. Cliquez pour exécuter le script.",
|
||||
"execute_sql": "Exécuter la commande SQL",
|
||||
"execute_sql_description": "Cette note est une note SQL. Cliquer pour exécuter la requête SQL.",
|
||||
"save_status_saved": "Enregister",
|
||||
"save_status_saving": "Enregistrement...",
|
||||
"save_status_unsaved": "Non sauvée",
|
||||
"save_status_error": "La sauvegarde a échoué",
|
||||
"save_status_saving_tooltip": "Les modifications sont enregistrées.",
|
||||
"save_status_unsaved_tooltip": "Il y a des changements non enregistrés. Ils seront enregistrés automatiquement dans un instant.",
|
||||
"save_status_error_tooltip": "Une erreur s'est produite lors de l'enregistrement de la note. Si possible, essayez de copier le contenu de la note ailleurs et de recharger l'application."
|
||||
},
|
||||
"right_pane": {
|
||||
"toggle": "Basculer le panneau de droite",
|
||||
"custom_widget_go_to_source": "Aller sur le code source",
|
||||
"empty_message": "Rien à afficher pour cette note",
|
||||
"empty_button": "Cacher le panneau"
|
||||
},
|
||||
"pdf": {
|
||||
"attachments_one": "{{count}} pièce jointe",
|
||||
"attachments_many": "{{count}} pièces jointes",
|
||||
"attachments_other": "{{count}} pièces jointes",
|
||||
"layers_one": "{{count}} couche",
|
||||
"layers_many": "{{count}} couches",
|
||||
"layers_other": "{{count}} couches",
|
||||
"pages_one": "{{count}} page",
|
||||
"pages_many": "{{count}} pages",
|
||||
"pages_other": "{{count}} pages",
|
||||
"pages_alt": "Page {{pageNumber}}",
|
||||
"pages_loading": "Chargement..."
|
||||
},
|
||||
"platform_indicator": {
|
||||
"available_on": "Disponible sur {{platform}}"
|
||||
},
|
||||
"mobile_tab_switcher": {
|
||||
"title_one": "{{count}} onglet",
|
||||
"title_many": "{{count}} onglets",
|
||||
"title_other": "{{count}} onglets",
|
||||
"more_options": "Autres options"
|
||||
},
|
||||
"bookmark_buttons": {
|
||||
"bookmarks": "Signets"
|
||||
},
|
||||
"active_content_badges": {
|
||||
"type_icon_pack": "pack d'icônes",
|
||||
"type_backend_script": "Script backend",
|
||||
"type_frontend_script": "Script frontend",
|
||||
"type_widget": "Widget",
|
||||
"type_app_css": "CSS personnalisé",
|
||||
"type_render_note": "Note de rendu",
|
||||
"type_web_view": "Vue Web",
|
||||
"type_app_theme": "Thème personnalisé",
|
||||
"toggle_tooltip_enable_tooltip": "Cliquer pour activer {{type}}.",
|
||||
"toggle_tooltip_disable_tooltip": "Cliquer pour désactiver ce {{type}}.",
|
||||
"menu_docs": "Ouvrir la documentation",
|
||||
"menu_execute_now": "Exécuter le script maintenant",
|
||||
"menu_run": "Démarrer automatiquement",
|
||||
"menu_run_disabled": "Manuellement",
|
||||
"menu_run_backend_startup": "Lorsque le backend commence",
|
||||
"menu_run_hourly": "Horaire",
|
||||
"menu_run_daily": "Quotidien",
|
||||
"menu_run_frontend_startup": "Lorsque le frontend du bureau démarre",
|
||||
"menu_run_mobile_startup": "Lorsque le frontend mobile démarre",
|
||||
"menu_change_to_widget": "Passer au widget",
|
||||
"menu_change_to_frontend_script": "Passer au script frontend",
|
||||
"menu_theme_base": "Thème de base"
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "En savoir plus"
|
||||
},
|
||||
"mermaid": {
|
||||
"placeholder": "Tapez le contenu de votre diagramme Mermaid ou utilisez l'un des diagrammes de l'échantillon ci-dessous.",
|
||||
"sample_diagrams": "Diagrammes d 'exemple:",
|
||||
"sample_flowchart": "Organigramme",
|
||||
"sample_class": "Classe",
|
||||
"sample_sequence": "Séquence",
|
||||
"sample_entity_relationship": "Entité relationnelle",
|
||||
"sample_state": "État",
|
||||
"sample_mindmap": "Carte mentale",
|
||||
"sample_architecture": "Architecture",
|
||||
"sample_block": "Bloc",
|
||||
"sample_c4": "C4",
|
||||
"sample_gantt": "Gantt",
|
||||
"sample_git": "Git",
|
||||
"sample_kanban": "Kanban",
|
||||
"sample_packet": "Paquet",
|
||||
"sample_pie": "Camembert",
|
||||
"sample_quadrant": "Quadrant",
|
||||
"sample_radar": "Radar",
|
||||
"sample_requirement": "Exigence",
|
||||
"sample_sankey": "Sankey",
|
||||
"sample_timeline": "Chronologie",
|
||||
"sample_treemap": "Arborescence",
|
||||
"sample_user_journey": "Utilisateur Journey",
|
||||
"sample_xy": "XY",
|
||||
"sample_venn": "Venn",
|
||||
"sample_ishikawa": "Ishikawa"
|
||||
},
|
||||
"mind-map": {
|
||||
"addChild": "Ajouter un enfant",
|
||||
"addParent": "Ajouter parent",
|
||||
"addSibling": "Ajouter un frère",
|
||||
"removeNode": "Supprimer le nœud",
|
||||
"focus": "Mode Focus",
|
||||
"cancelFocus": "Annuler le mode Focus",
|
||||
"moveUp": "Monter",
|
||||
"moveDown": "Descendre",
|
||||
"link": "Lien",
|
||||
"linkBidirectional": "Lien bidirectionnel",
|
||||
"clickTips": "Cliquer sur le nœud cible",
|
||||
"summary": "Résumé"
|
||||
},
|
||||
"llm": {
|
||||
"settings_title": "AI / LLM",
|
||||
"settings_description": "Configurer les intégrations AI et les LLM (Large Language Model).",
|
||||
"add_provider": "Ajouter le fournisseur",
|
||||
"add_provider_title": "Ajouter le fournisseur d'IA",
|
||||
"configured_providers": "Fournisseurs configurés",
|
||||
"no_providers_configured": "Aucun fournisseur n'est encore configuré.",
|
||||
"provider_name": "Nom",
|
||||
"provider_type": "Fournisseur",
|
||||
"actions": "Actions",
|
||||
"delete_provider": "Supprimer",
|
||||
"delete_provider_confirmation": "Êtes-vous sûr de vouloir supprimer le fournisseur \"{{name}}\" ?",
|
||||
"api_key": "Clé API",
|
||||
"api_key_placeholder": "Entrer votre clé API",
|
||||
"cancel": "Annuler"
|
||||
},
|
||||
"status_bar": {
|
||||
"language_title": "Changer de langue",
|
||||
"note_info_title": "Afficher les informations sur les notes (par exemple, dates, taille des notes)",
|
||||
"backlinks_one": "{{count}} rétrolien",
|
||||
"backlinks_many": "{{count}} rétroliens",
|
||||
"backlinks_other": "{{count}} rétroliens",
|
||||
"backlinks_title_one": "voir le rétrolien",
|
||||
"backlinks_title_many": "voir les rétroliens",
|
||||
"backlinks_title_other": "voir les rétroliens",
|
||||
"attachments_one": "{{count}} pièce-jointe",
|
||||
"attachments_many": "{{count}} pièces-jointes",
|
||||
"attachments_other": "{{count}} pièces-jointes",
|
||||
"attachments_title_one": "Voir la pièce-jointe dans un nouvel onglet",
|
||||
"attachments_title_many": "Voir les pièces-jointes dans un nouvel onglet",
|
||||
"attachments_title_other": "Voir les pièces-jointes dans un nouvel onglet",
|
||||
"attributes_one": "{{count}} attribut",
|
||||
"attributes_many": "{{count}} attributs",
|
||||
"attributes_other": "{{count}} attributs",
|
||||
"attributes_title": "Attributs propres et attributs hérités",
|
||||
"note_paths_one": "{{count}} chemin",
|
||||
"note_paths_many": "{{count}} chemins",
|
||||
"note_paths_other": "{{count}} chemins",
|
||||
"note_paths_title": "Chemins de la note",
|
||||
"code_note_switcher": "Changer de langue"
|
||||
},
|
||||
"attributes_panel": {
|
||||
"title": "Attributs de la note"
|
||||
}
|
||||
}
|
||||
|
||||
2409
apps/client/src/translations/ga/translation.json
Normal file
2409
apps/client/src/translations/ga/translation.json
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user