mirror of
https://github.com/zadam/trilium.git
synced 2026-02-24 07:10:52 +01:00
Compare commits
1708 Commits
v0.100.0
...
feature/be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47a7fb5708 | ||
|
|
a7c0c52610 | ||
|
|
51513d3779 | ||
|
|
13ce8cf498 | ||
|
|
6c2afc086c | ||
|
|
93d50712a9 | ||
|
|
ed91a44928 | ||
|
|
cd10e66fbb | ||
|
|
d6aa126fcc | ||
|
|
3308c7bdf4 | ||
|
|
56341a1a73 | ||
|
|
0857e1a536 | ||
|
|
5d6b25a29e | ||
|
|
5bc15a5448 | ||
|
|
51a19d0544 | ||
|
|
fb4e912ed0 | ||
|
|
20c2652013 | ||
|
|
971d6ad9e3 | ||
|
|
757fc7a7fe | ||
|
|
e4d0a4554a | ||
|
|
dfab7dbc4b | ||
|
|
0039f4c155 | ||
|
|
23f7dc63b8 | ||
|
|
e485b75a44 | ||
|
|
dbef57d329 | ||
|
|
c650441655 | ||
|
|
e573a8af77 | ||
|
|
b23252d046 | ||
|
|
2f7448dbd4 | ||
|
|
9bf4aa2968 | ||
|
|
d78a7bad3b | ||
|
|
b812177e78 | ||
|
|
4710a6af41 | ||
|
|
a613980ea4 | ||
|
|
20ae1f844b | ||
|
|
69511134e5 | ||
|
|
75952563e4 | ||
|
|
21cf5e1df7 | ||
|
|
9df5505989 | ||
|
|
1809d59193 | ||
|
|
feaa54d660 | ||
|
|
c94bd41162 | ||
|
|
f1f3e66537 | ||
|
|
80363cdc73 | ||
|
|
02e08fdf12 | ||
|
|
42283b2469 | ||
|
|
d3b598a5b2 | ||
|
|
0dd3a03c6b | ||
|
|
2144888447 | ||
|
|
b2549066dc | ||
|
|
cd1f3aa9a7 | ||
|
|
1674401342 | ||
|
|
7ba8dbbf6e | ||
|
|
ad27d9ed0e | ||
|
|
482d2f9624 | ||
|
|
824ef704d4 | ||
|
|
58b73cfc7d | ||
|
|
0465fea2db | ||
|
|
39b75e3561 | ||
|
|
2933db9b16 | ||
|
|
d94914046b | ||
|
|
9cf384b14b | ||
|
|
614a2f0ccb | ||
|
|
5cecc72384 | ||
|
|
3ad37fb602 | ||
|
|
42b048c2bf | ||
|
|
a01bf3dfa1 | ||
|
|
ad60988553 | ||
|
|
c9ae4e4cc6 | ||
|
|
d2639851d5 | ||
|
|
8dc5f9cfa4 | ||
|
|
d99a408e04 | ||
|
|
5f14861682 | ||
|
|
8f8493f3ec | ||
|
|
62af66b5ae | ||
|
|
e8d1fa7447 | ||
|
|
ee03871405 | ||
|
|
345378d97f | ||
|
|
07a463ee52 | ||
|
|
3157047160 | ||
|
|
a1dda3b578 | ||
|
|
e161ffce57 | ||
|
|
0c1859dc43 | ||
|
|
e4dcc0f768 | ||
|
|
74ab591214 | ||
|
|
7bd7996893 | ||
|
|
505ae4eeb5 | ||
|
|
951d6d3ce3 | ||
|
|
5ff7764699 | ||
|
|
0d74998625 | ||
|
|
29b70a12bd | ||
|
|
d84150e97b | ||
|
|
2b2ef4251f | ||
|
|
2840ea0f38 | ||
|
|
542d485267 | ||
|
|
cdd4fbc81d | ||
|
|
bfdddab0a0 | ||
|
|
44d1d01105 | ||
|
|
120bb09171 | ||
|
|
b7af99c671 | ||
|
|
869e0b3973 | ||
|
|
b68613dee4 | ||
|
|
ce0f32e7d5 | ||
|
|
78bc9b59c2 | ||
|
|
23cf3d2923 | ||
|
|
335136f3a3 | ||
|
|
11dd7aef09 | ||
|
|
2d1769e2f9 | ||
|
|
21e26147b0 | ||
|
|
ba301f8c12 | ||
|
|
3420374649 | ||
|
|
644d3a181f | ||
|
|
4be3011a8a | ||
|
|
5aa0a956dd | ||
|
|
7fdb1bdce8 | ||
|
|
57c6cef2bd | ||
|
|
e5599adca1 | ||
|
|
ab392ffb7f | ||
|
|
7585d4b258 | ||
|
|
ff82d9c38c | ||
|
|
920fde69bb | ||
|
|
053812e5f0 | ||
|
|
c2f59c4b6c | ||
|
|
06980fe9b5 | ||
|
|
3f5616f1fc | ||
|
|
b6af3b70b0 | ||
|
|
d8e4547988 | ||
|
|
34f649155e | ||
|
|
11779fe3e3 | ||
|
|
032cde67b0 | ||
|
|
229636a796 | ||
|
|
da9c9ac346 | ||
|
|
3fecc4c648 | ||
|
|
98cefcf77b | ||
|
|
413ee81ffa | ||
|
|
578ca8785e | ||
|
|
da4112c078 | ||
|
|
704c7c881d | ||
|
|
63b6abdb9d | ||
|
|
2e936a3d5c | ||
|
|
606574e18e | ||
|
|
1021879167 | ||
|
|
dc4aa9c607 | ||
|
|
b2c3d78773 | ||
|
|
8d3a0b5295 | ||
|
|
9879d07bec | ||
|
|
7bfce851e7 | ||
|
|
34e81881ec | ||
|
|
0143d6c60d | ||
|
|
267c2bc907 | ||
|
|
316f27d88c | ||
|
|
452b56f470 | ||
|
|
43aeaa4455 | ||
|
|
08b7a6985e | ||
|
|
4bbd8e28c1 | ||
|
|
fcf4c09389 | ||
|
|
2c323cbe80 | ||
|
|
7ec7b6bd7b | ||
|
|
b2378f2a53 | ||
|
|
8bf8d85bb7 | ||
|
|
676173e895 | ||
|
|
d8649c87e0 | ||
|
|
b9456ca466 | ||
|
|
cfccbb8927 | ||
|
|
a18578362a | ||
|
|
2f9f94dee0 | ||
|
|
c84e45ddee | ||
|
|
ea558d8c9d | ||
|
|
b936a35b63 | ||
|
|
b4ef4c2143 | ||
|
|
0ff4756ef4 | ||
|
|
94204b4739 | ||
|
|
bf3a2b768e | ||
|
|
5fb7badfb4 | ||
|
|
239d56f9a3 | ||
|
|
9163fc23f4 | ||
|
|
d225c28fde | ||
|
|
8a3f02e845 | ||
|
|
d0dc92c891 | ||
|
|
8d660f5a2f | ||
|
|
b41b4e77b2 | ||
|
|
267a37d3bd | ||
|
|
0cf23c7d7c | ||
|
|
a632486229 | ||
|
|
64a518a00b | ||
|
|
2f3a914027 | ||
|
|
7182d32d9c | ||
|
|
18381c5d32 | ||
|
|
79327073b4 | ||
|
|
018f2fd789 | ||
|
|
3889392aed | ||
|
|
bd976a25f1 | ||
|
|
01f05ac6fd | ||
|
|
52292cb5a5 | ||
|
|
c6dd1ba0ca | ||
|
|
84f069087c | ||
|
|
76cfced60f | ||
|
|
5c2aea0a6b | ||
|
|
7a883c62df | ||
|
|
ff97461ff8 | ||
|
|
51b0eb74a5 | ||
|
|
2304407986 | ||
|
|
a1ebdc3004 | ||
|
|
fef30f4bea | ||
|
|
eee8d9ab7c | ||
|
|
4f2678d321 | ||
|
|
c473fba628 | ||
|
|
9a9cd8e6a5 | ||
|
|
f5a89aa81a | ||
|
|
3c1beab725 | ||
|
|
79f03ad3ac | ||
|
|
574138a1fb | ||
|
|
6513e2cfca | ||
|
|
43a749b6a7 | ||
|
|
c1d6b3121a | ||
|
|
0d9c8ae4df | ||
|
|
62d8c089ed | ||
|
|
971a76ce11 | ||
|
|
cb33404122 | ||
|
|
bcf72f4624 | ||
|
|
77ad6950e8 | ||
|
|
e2d29aadca | ||
|
|
64ca04ad07 | ||
|
|
b6506a9331 | ||
|
|
fd7222242a | ||
|
|
e36049cd43 | ||
|
|
257f6c5994 | ||
|
|
9098bfb63a | ||
|
|
118d22c4ec | ||
|
|
758df0d85a | ||
|
|
59bbd902fc | ||
|
|
d96528dae4 | ||
|
|
f3cfa84d1d | ||
|
|
dc2ffa516b | ||
|
|
fffab73061 | ||
|
|
0a9ce84cf2 | ||
|
|
07a1734d4b | ||
|
|
6e41d3591d | ||
|
|
4134e5054a | ||
|
|
bb374a5ce2 | ||
|
|
359f398afa | ||
|
|
84425e86e9 | ||
|
|
ebf725c949 | ||
|
|
fc0ea36cf3 | ||
|
|
7836de3f08 | ||
|
|
406232c478 | ||
|
|
9e0c29496f | ||
|
|
480954ee87 | ||
|
|
94039bd9b1 | ||
|
|
667eaca9f2 | ||
|
|
446822a7ae | ||
|
|
f09a3e06f4 | ||
|
|
7c4a56f5f2 | ||
|
|
08f6a32c34 | ||
|
|
3e255fa647 | ||
|
|
c0a90402ef | ||
|
|
37c0f7ec75 | ||
|
|
5e42627bce | ||
|
|
41bcf9524a | ||
|
|
914cf10911 | ||
|
|
855d4d139d | ||
|
|
abb7b0f8c8 | ||
|
|
d78ad52662 | ||
|
|
25b4bcd311 | ||
|
|
a14eed81f6 | ||
|
|
54f51b365a | ||
|
|
c0e0a712ad | ||
|
|
3ab5bbae4d | ||
|
|
cafeb3920a | ||
|
|
fb465b442c | ||
|
|
d3a559a700 | ||
|
|
7768003735 | ||
|
|
f02b3b48e8 | ||
|
|
ba273bb9f4 | ||
|
|
490c539d63 | ||
|
|
ebd60519dd | ||
|
|
56304a4d71 | ||
|
|
32f0f98522 | ||
|
|
b18dd22341 | ||
|
|
8eebae0955 | ||
|
|
ed229e0578 | ||
|
|
dbfaad6c06 | ||
|
|
6e5176b088 | ||
|
|
becf4d7426 | ||
|
|
082040c6e1 | ||
|
|
1ae11ce3a5 | ||
|
|
cf968b3590 | ||
|
|
a3db1ab156 | ||
|
|
7440110a44 | ||
|
|
3638e6b12c | ||
|
|
621ed5b9de | ||
|
|
1e3135dea0 | ||
|
|
8f21c0b34a | ||
|
|
b3feb38369 | ||
|
|
2bf862d5b9 | ||
|
|
cbb7b4ffea | ||
|
|
b2f496048f | ||
|
|
e084bc4c07 | ||
|
|
d9b0660def | ||
|
|
b997452733 | ||
|
|
e699566e62 | ||
|
|
2bd83e6285 | ||
|
|
46e5090445 | ||
|
|
035a311e4d | ||
|
|
850528750c | ||
|
|
645720a725 | ||
|
|
a6c74449aa | ||
|
|
7f05d9cdff | ||
|
|
02d42dc5ff | ||
|
|
e730378b27 | ||
|
|
c14d95f561 | ||
|
|
13b700e0e5 | ||
|
|
f849c4b315 | ||
|
|
c2c19e8ecd | ||
|
|
12875ec308 | ||
|
|
5d12d57a22 | ||
|
|
5cc2296768 | ||
|
|
7c1175995f | ||
|
|
d834cd78a7 | ||
|
|
79d2010bfa | ||
|
|
3f86c809ce | ||
|
|
1570ea77d8 | ||
|
|
99bdd2e433 | ||
|
|
7646061215 | ||
|
|
505a985755 | ||
|
|
e895ea406a | ||
|
|
8b8a78e949 | ||
|
|
1c940ff8a2 | ||
|
|
841cb32835 | ||
|
|
61e96f91d0 | ||
|
|
9f6c07f5cc | ||
|
|
1efb21c627 | ||
|
|
d5b04864c8 | ||
|
|
da28f4505a | ||
|
|
5174deac07 | ||
|
|
e2a628fa2f | ||
|
|
290f488c78 | ||
|
|
b00cb52da5 | ||
|
|
c7bb5ff119 | ||
|
|
faa069b8a1 | ||
|
|
e57f1e6f23 | ||
|
|
73975ab521 | ||
|
|
761a67f238 | ||
|
|
736c69816d | ||
|
|
270339da11 | ||
|
|
aa93bc5492 | ||
|
|
0c9c36ea7e | ||
|
|
af67967502 | ||
|
|
78bec0c782 | ||
|
|
0c77563672 | ||
|
|
241a9e2e7f | ||
|
|
59b691d670 | ||
|
|
a6c515aea0 | ||
|
|
850710926e | ||
|
|
904da14895 | ||
|
|
4c5bc3a3d3 | ||
|
|
ecec661b72 | ||
|
|
fb629f7693 | ||
|
|
13fff33aa4 | ||
|
|
8053221b12 | ||
|
|
ba699f9842 | ||
|
|
eb5ebb53cb | ||
|
|
c26357be40 | ||
|
|
db4af96040 | ||
|
|
5cb3983fe0 | ||
|
|
92292de0ff | ||
|
|
a26923cc6d | ||
|
|
2c4ac4ba30 | ||
|
|
254511bfbf | ||
|
|
e2f6f8a4e4 | ||
|
|
e346963e76 | ||
|
|
5f1bdf7264 | ||
|
|
93a3b29677 | ||
|
|
b157cd909c | ||
|
|
2f24703690 | ||
|
|
27efa8844e | ||
|
|
98de4b6dc3 | ||
|
|
d121de5152 | ||
|
|
5ad7323d03 | ||
|
|
183020a4e3 | ||
|
|
a56a5fe1f5 | ||
|
|
af4fc11a4e | ||
|
|
a63b8b2031 | ||
|
|
7b02d87558 | ||
|
|
16737b93dd | ||
|
|
c23fe7cf13 | ||
|
|
6d80323a76 | ||
|
|
8b630c6e2e | ||
|
|
047a8d9644 | ||
|
|
f14ae01fab | ||
|
|
785470b0ae | ||
|
|
73918c042b | ||
|
|
1d3e971ed7 | ||
|
|
7e7f3ba78f | ||
|
|
03eaebc71c | ||
|
|
3d1f6c4f91 | ||
|
|
8368969932 | ||
|
|
afcd23cb99 | ||
|
|
94d1181fe8 | ||
|
|
7e45aaa1da | ||
|
|
cb016c4307 | ||
|
|
7c7797d35a | ||
|
|
8d6eb6fa53 | ||
|
|
f97fbf8325 | ||
|
|
e7d6e646be | ||
|
|
839444af47 | ||
|
|
24a58da4b6 | ||
|
|
aa37196169 | ||
|
|
f821d7fcd6 | ||
|
|
b417831507 | ||
|
|
a4dbefd7ef | ||
|
|
2d486c9934 | ||
|
|
47cfbd0740 | ||
|
|
f09d918695 | ||
|
|
33098a1120 | ||
|
|
73f7c42437 | ||
|
|
4ff0e2a1d9 | ||
|
|
afeaf51831 | ||
|
|
98db2fcd7b | ||
|
|
6b4d069211 | ||
|
|
cecf7e6afb | ||
|
|
920e53957c | ||
|
|
27c3d4da3c | ||
|
|
00a1a63d7e | ||
|
|
b0e7b6ce67 | ||
|
|
e06c004e0d | ||
|
|
a47ea0d653 | ||
|
|
86c04cae96 | ||
|
|
9eedbb8cd5 | ||
|
|
85404b02fc | ||
|
|
ae08c47929 | ||
|
|
c97a6d82c3 | ||
|
|
656b261946 | ||
|
|
13fb57b46d | ||
|
|
fe38689a26 | ||
|
|
62263e3eea | ||
|
|
22d258b6bc | ||
|
|
51242f9bcb | ||
|
|
ab0a0d3807 | ||
|
|
cc37da9f11 | ||
|
|
404618ed79 | ||
|
|
3deda84b38 | ||
|
|
ccf8e07316 | ||
|
|
9c73b71feb | ||
|
|
bbec2f6082 | ||
|
|
924bd4512b | ||
|
|
ecb8bc0158 | ||
|
|
67b01ec1d8 | ||
|
|
7ca7dd8867 | ||
|
|
ac086bc2a4 | ||
|
|
a583369658 | ||
|
|
4bc2e9743c | ||
|
|
ba2ba4fd80 | ||
|
|
52aaa72935 | ||
|
|
4123c24a9f | ||
|
|
4bba910501 | ||
|
|
3b31916b26 | ||
|
|
4234ee97fb | ||
|
|
a5c8287446 | ||
|
|
77a90e524a | ||
|
|
814f81adfc | ||
|
|
45c8b24b9c | ||
|
|
2a7023ea16 | ||
|
|
4a2ff25052 | ||
|
|
93582c1489 | ||
|
|
37d647261a | ||
|
|
8af549aba4 | ||
|
|
662423221e | ||
|
|
d6cd252f23 | ||
|
|
5af87788c6 | ||
|
|
c329ab7eee | ||
|
|
2340c307cf | ||
|
|
219454c7d3 | ||
|
|
3c14750e90 | ||
|
|
b49ca3efe3 | ||
|
|
d21127e3a7 | ||
|
|
9adf24da01 | ||
|
|
571cdfdeea | ||
|
|
c2214493dc | ||
|
|
293ef60350 | ||
|
|
60866c959f | ||
|
|
84c40eb233 | ||
|
|
2afc8d181d | ||
|
|
66cdee82a4 | ||
|
|
502c896616 | ||
|
|
b5af513371 | ||
|
|
30cc221eca | ||
|
|
db3aedf39d | ||
|
|
fd760951cc | ||
|
|
b84cdd648f | ||
|
|
b94b30e864 | ||
|
|
0027bca415 | ||
|
|
4ac3634b04 | ||
|
|
3207f37ac3 | ||
|
|
28d3e61199 | ||
|
|
e476a2d306 | ||
|
|
1d6766d9f3 | ||
|
|
b429861e8f | ||
|
|
81c55aab72 | ||
|
|
f67e06c8b2 | ||
|
|
b3d92f932f | ||
|
|
478c0e93f0 | ||
|
|
bd24cf68b6 | ||
|
|
faea35b363 | ||
|
|
6b66d2089f | ||
|
|
df05101e93 | ||
|
|
7a1ea8833f | ||
|
|
3600192933 | ||
|
|
d6d75a0e48 | ||
|
|
102e10efe3 | ||
|
|
a516185a2e | ||
|
|
ae81b20334 | ||
|
|
8fffbdc748 | ||
|
|
14d7d1da03 | ||
|
|
9cb565e821 | ||
|
|
e3595a43c2 | ||
|
|
963fcd615a | ||
|
|
fc8605a14f | ||
|
|
04fffb7ee0 | ||
|
|
86307b482f | ||
|
|
3e50262665 | ||
|
|
4e5c97d548 | ||
|
|
1185d4b10b | ||
|
|
19cd7a0cad | ||
|
|
8fda283977 | ||
|
|
6e3a020d0f | ||
|
|
2fef25e57b | ||
|
|
89ef38ba97 | ||
|
|
e96ee87472 | ||
|
|
ae83126903 | ||
|
|
a6c7610fcc | ||
|
|
d8ce0e5f16 | ||
|
|
1eebc8ff77 | ||
|
|
00592025c0 | ||
|
|
1ac7db41d3 | ||
|
|
ce84e7a861 | ||
|
|
cf039916d3 | ||
|
|
bfb3ed3ddf | ||
|
|
a4f34ce6c5 | ||
|
|
2ac3d3aaed | ||
|
|
494b99d073 | ||
|
|
8434549a9b | ||
|
|
c1e01467a5 | ||
|
|
4bd8eeb52a | ||
|
|
f4a6edbc9f | ||
|
|
0d0a1866e4 | ||
|
|
cd47e79a1b | ||
|
|
d0a83f7c05 | ||
|
|
26160b44ea | ||
|
|
9df7b04d7d | ||
|
|
b8d933d308 | ||
|
|
9021b119b2 | ||
|
|
35034fe9df | ||
|
|
2eef655ec2 | ||
|
|
57ff2f4023 | ||
|
|
df6331e3a0 | ||
|
|
b84da65a81 | ||
|
|
58e04a6f72 | ||
|
|
450bdeb39e | ||
|
|
79494e8cfe | ||
|
|
2afba34055 | ||
|
|
c391234eeb | ||
|
|
a3fca323c7 | ||
|
|
9332b9ca8f | ||
|
|
8740bf84cf | ||
|
|
1554085d7a | ||
|
|
7dd4c09057 | ||
|
|
eafd5140ea | ||
|
|
cddde353cd | ||
|
|
e4ef8f2352 | ||
|
|
2561c7ca0d | ||
|
|
b4e4950d20 | ||
|
|
a4be86dbd8 | ||
|
|
b6ca6476de | ||
|
|
db1f632859 | ||
|
|
7af8acec0f | ||
|
|
3f1b0fa71e | ||
|
|
519323292c | ||
|
|
2d6f17aeaa | ||
|
|
7507d6b385 | ||
|
|
d4fa21e7c1 | ||
|
|
608f156b82 | ||
|
|
0c965bfdf4 | ||
|
|
d407c72fae | ||
|
|
bdc0b062d5 | ||
|
|
0b912b9c7d | ||
|
|
99ac6b4df1 | ||
|
|
b0a97208a2 | ||
|
|
6e044b19c8 | ||
|
|
198dd15fb4 | ||
|
|
18f3b83827 | ||
|
|
8142b7489a | ||
|
|
7bf0a4134e | ||
|
|
29ed08d062 | ||
|
|
68dc7eedec | ||
|
|
3fc195998c | ||
|
|
b6d550f682 | ||
|
|
1f55ff536e | ||
|
|
67fb8d0354 | ||
|
|
1408b159d7 | ||
|
|
74b00e60e3 | ||
|
|
1b18a964b9 | ||
|
|
931f0a694e | ||
|
|
0d32e1f0d8 | ||
|
|
d0f91e7709 | ||
|
|
353d626d45 | ||
|
|
af67a3ba11 | ||
|
|
a867c646e4 | ||
|
|
150e2504b1 | ||
|
|
aa7ae150dc | ||
|
|
d99e08bfdd | ||
|
|
29d038c76b | ||
|
|
f1615bb4f6 | ||
|
|
0688ea7de3 | ||
|
|
af37c175a3 | ||
|
|
7567903da3 | ||
|
|
531698cafb | ||
|
|
f45920e506 | ||
|
|
6fdd418edd | ||
|
|
409ecb84a8 | ||
|
|
f68f99806b | ||
|
|
ea1efb785b | ||
|
|
308943f754 | ||
|
|
d43409f6e4 | ||
|
|
4f51aa7a43 | ||
|
|
c4f55395a9 | ||
|
|
444c0c6107 | ||
|
|
4da5cb43fc | ||
|
|
e6b79e83c4 | ||
|
|
6e67da7b1f | ||
|
|
9071e54bfe | ||
|
|
783b5ac8e3 | ||
|
|
f3f491d141 | ||
|
|
a9f58262fc | ||
|
|
3ef39784ed | ||
|
|
24d0d562a9 | ||
|
|
86c5a4d10c | ||
|
|
f8bf301d12 | ||
|
|
32f0d81c07 | ||
|
|
2c25786fa2 | ||
|
|
1093acfe45 | ||
|
|
76f054bbd5 | ||
|
|
1ed4192c93 | ||
|
|
c558255450 | ||
|
|
1e94125133 | ||
|
|
64a770175f | ||
|
|
e0416097e1 | ||
|
|
6c1b327f5f | ||
|
|
17a9550803 | ||
|
|
284b66acd2 | ||
|
|
dcd73ff9f9 | ||
|
|
645557b505 | ||
|
|
22a83d9f82 | ||
|
|
f64de3acca | ||
|
|
34d5793888 | ||
|
|
0de9b219a5 | ||
|
|
44ca9f457c | ||
|
|
93eead04a9 | ||
|
|
8ff1f7ec84 | ||
|
|
4d7e5bc8f6 | ||
|
|
644ff07a50 | ||
|
|
41220a9d1d | ||
|
|
88945788d6 | ||
|
|
fe8f033409 | ||
|
|
eee7c49f6e | ||
|
|
d036bf0870 | ||
|
|
fa8ff4bfbf | ||
|
|
3619c0c3e4 | ||
|
|
883e32f5c9 | ||
|
|
8722ed405e | ||
|
|
201c3a6eba | ||
|
|
5a46f6ad04 | ||
|
|
4f20ffe933 | ||
|
|
061b0966bb | ||
|
|
bd799823b8 | ||
|
|
c581ee7252 | ||
|
|
666c434c74 | ||
|
|
78ac59581e | ||
|
|
d7b370253d | ||
|
|
1e885625f6 | ||
|
|
8cf6a6b9ae | ||
|
|
f1ca8881a1 | ||
|
|
ea76fd797c | ||
|
|
b248805905 | ||
|
|
7af5c77bcb | ||
|
|
35afd60d00 | ||
|
|
2b827991ef | ||
|
|
bc8c852a4d | ||
|
|
cd49c36529 | ||
|
|
a0577dc202 | ||
|
|
dced799976 | ||
|
|
eeea96b98c | ||
|
|
e82e92c22c | ||
|
|
e1df65adce | ||
|
|
b7b7610f4d | ||
|
|
37ea1584c9 | ||
|
|
aac4316fb8 | ||
|
|
fb96b3f80a | ||
|
|
243d8158cf | ||
|
|
6861a61cac | ||
|
|
d3299d8aa4 | ||
|
|
0be5581fe5 | ||
|
|
60572a28ff | ||
|
|
422c391c82 | ||
|
|
457d30cd80 | ||
|
|
9caa058b18 | ||
|
|
33bde688c1 | ||
|
|
e79da6b0f3 | ||
|
|
3e527b9f5c | ||
|
|
ba242a6169 | ||
|
|
489113f582 | ||
|
|
0fa6335d0f | ||
|
|
8f1614f603 | ||
|
|
a5f322617d | ||
|
|
6da42fac20 | ||
|
|
fad6414e1d | ||
|
|
c0cd9e36d9 | ||
|
|
e94704ce64 | ||
|
|
7a5d24f968 | ||
|
|
9d351ae479 | ||
|
|
01d4fa8afd | ||
|
|
7d386c249a | ||
|
|
45dd47d039 | ||
|
|
06ad0bfa90 | ||
|
|
3d9efb23ec | ||
|
|
9acef4d502 | ||
|
|
d22583457f | ||
|
|
290469d1df | ||
|
|
de5b766d0c | ||
|
|
cbeb5dfb58 | ||
|
|
be5448eba2 | ||
|
|
200e5d04a4 | ||
|
|
c7bbf709a1 | ||
|
|
23c2a59eba | ||
|
|
bf74c40f73 | ||
|
|
2af1ceda0b | ||
|
|
44ae60005c | ||
|
|
3d591922bb | ||
|
|
31b2aba44c | ||
|
|
df1c6196bf | ||
|
|
96f4567ba1 | ||
|
|
3e783817b6 | ||
|
|
f7f3f707f1 | ||
|
|
5ce81f1a32 | ||
|
|
53df319aeb | ||
|
|
c56a253e49 | ||
|
|
551b2aa33a | ||
|
|
8e245ccad8 | ||
|
|
03cea8b702 | ||
|
|
c94b5bc6c9 | ||
|
|
69dc1ba68f | ||
|
|
32f7ae1edd | ||
|
|
0de05ed16e | ||
|
|
58e24c98ed | ||
|
|
46da118749 | ||
|
|
3f7514c9c7 | ||
|
|
5123f7b678 | ||
|
|
b8af961690 | ||
|
|
5bcec9fcfd | ||
|
|
0a2d4131d7 | ||
|
|
9ef4ab9983 | ||
|
|
2a237e9a49 | ||
|
|
29115f5e61 | ||
|
|
3411ed79d8 | ||
|
|
b9c6cae5b4 | ||
|
|
cc84d09230 | ||
|
|
a82b12a599 | ||
|
|
65ebbc71f5 | ||
|
|
77c1a00831 | ||
|
|
8eb6bf402d | ||
|
|
e45beb541e | ||
|
|
334c31e79d | ||
|
|
a986c84ce7 | ||
|
|
9b21e042ec | ||
|
|
c44bb6c203 | ||
|
|
ddb6b3ea8a | ||
|
|
a4024d17ba | ||
|
|
57081a1bfb | ||
|
|
7af063e7cd | ||
|
|
7b04ca8cc7 | ||
|
|
02294206ec | ||
|
|
7f7ec5d858 | ||
|
|
ea3222cf12 | ||
|
|
5dacfd3ac6 | ||
|
|
682c61305c | ||
|
|
b5bfb02d96 | ||
|
|
fc3692333a | ||
|
|
28d9d98964 | ||
|
|
751a874c51 | ||
|
|
d18ac0c613 | ||
|
|
cd9654cd5f | ||
|
|
925049357a | ||
|
|
d920da9e6f | ||
|
|
b42a4dcb36 | ||
|
|
7085e62cfc | ||
|
|
73f2f56932 | ||
|
|
dbf29ed23f | ||
|
|
b0e1751dc7 | ||
|
|
bf5c56a61a | ||
|
|
96ccb1e67e | ||
|
|
704dcd011e | ||
|
|
b93c80fe7b | ||
|
|
41751c205c | ||
|
|
852398426e | ||
|
|
73f1b91d34 | ||
|
|
28da93fc65 | ||
|
|
87a98201b4 | ||
|
|
60342c0f6f | ||
|
|
97a3e439d2 | ||
|
|
ee6f988c35 | ||
|
|
7cfc67cf9f | ||
|
|
ea2dd0293f | ||
|
|
76c16f3a62 | ||
|
|
094f77b1af | ||
|
|
b2bcbdde3f | ||
|
|
eceb7179b8 | ||
|
|
3a46a9fbc3 | ||
|
|
2e484a11e6 | ||
|
|
98ed442d27 | ||
|
|
dac923e45d | ||
|
|
f46de50f17 | ||
|
|
616af1502f | ||
|
|
c9fae88a86 | ||
|
|
9872a3d522 | ||
|
|
851169e061 | ||
|
|
f3b274650e | ||
|
|
3293ed2ce0 | ||
|
|
231ec39025 | ||
|
|
ecb972c71c | ||
|
|
c7f1e46b26 | ||
|
|
b9c39d757b | ||
|
|
ea4a3b7f07 | ||
|
|
cbecc24999 | ||
|
|
261c1f77cf | ||
|
|
87d99aaffa | ||
|
|
d0b0a13b6d | ||
|
|
1ed83b3598 | ||
|
|
2759beb5d0 | ||
|
|
d623b2ffa0 | ||
|
|
3ed613cf1d | ||
|
|
948a6f84d6 | ||
|
|
334024b2d1 | ||
|
|
6aa14d17d7 | ||
|
|
e1da74d4d1 | ||
|
|
a6012283da | ||
|
|
e450e0299f | ||
|
|
816f851709 | ||
|
|
514ded5b8d | ||
|
|
35a109616c | ||
|
|
641176011f | ||
|
|
304fd37ce2 | ||
|
|
51ef473964 | ||
|
|
96f148a870 | ||
|
|
150bc07d28 | ||
|
|
dcec780846 | ||
|
|
03602addc5 | ||
|
|
fc9f47a801 | ||
|
|
3b6a823556 | ||
|
|
b8ceb10e68 | ||
|
|
ddca68eafa | ||
|
|
468d4a4369 | ||
|
|
c31f35dbd7 | ||
|
|
b5129402be | ||
|
|
f38dfb035a | ||
|
|
c2bee1a968 | ||
|
|
84f7ae9f05 | ||
|
|
c4df640ea4 | ||
|
|
fe5e1eb066 | ||
|
|
6abc5a777f | ||
|
|
08730dd821 | ||
|
|
b08ea33eb0 | ||
|
|
f389fc3414 | ||
|
|
cb024d0455 | ||
|
|
286d2e8e5b | ||
|
|
5446d8a932 | ||
|
|
07dcdf3078 | ||
|
|
143b1827e6 | ||
|
|
6f494e3e38 | ||
|
|
e88623e9fa | ||
|
|
cad86d4b21 | ||
|
|
5ffae303c4 | ||
|
|
35218aca71 | ||
|
|
9542c9776a | ||
|
|
af02685f2f | ||
|
|
737e5b85b4 | ||
|
|
90a7217b32 | ||
|
|
77b92385cb | ||
|
|
22e0776049 | ||
|
|
db51198449 | ||
|
|
998a16ab87 | ||
|
|
4f1c19f1e2 | ||
|
|
1835676d09 | ||
|
|
2eaa4ef206 | ||
|
|
a5fcee500e | ||
|
|
613764d423 | ||
|
|
0518e64576 | ||
|
|
713900b2b3 | ||
|
|
c0eb34927f | ||
|
|
ec3c9a9ae5 | ||
|
|
70374b622e | ||
|
|
7fcc0ae290 | ||
|
|
1de4db1a08 | ||
|
|
74ac58d3a6 | ||
|
|
993f56976e | ||
|
|
94859f2303 | ||
|
|
db116981b8 | ||
|
|
2e563b0a1f | ||
|
|
7222b233f0 | ||
|
|
bea15c46e5 | ||
|
|
d96157de47 | ||
|
|
120b5c678d | ||
|
|
8c008e2e3a | ||
|
|
7e07280eb3 | ||
|
|
d28c3f0851 | ||
|
|
0390fd3174 | ||
|
|
193c9d8fa6 | ||
|
|
3a4cff6529 | ||
|
|
5449d033bf | ||
|
|
66ed88c409 | ||
|
|
94df5c9126 | ||
|
|
181ea31c1c | ||
|
|
f235839d03 | ||
|
|
d97b68fcd7 | ||
|
|
79d1a509e5 | ||
|
|
0af5fa9f0c | ||
|
|
2693b18ee6 | ||
|
|
34343ce356 | ||
|
|
c9025f2304 | ||
|
|
ec22fd9e99 | ||
|
|
15f9b2cadf | ||
|
|
7c85fe1c37 | ||
|
|
d1820a6bc3 | ||
|
|
d1575a28ad | ||
|
|
d13e19cf59 | ||
|
|
0b7ffdf109 | ||
|
|
e91cb1a198 | ||
|
|
51fcda646d | ||
|
|
cb8e35c4dc | ||
|
|
9d581347f1 | ||
|
|
96a6ea4c7a | ||
|
|
587ea42700 | ||
|
|
8a5c7b3551 | ||
|
|
f1fa44feb6 | ||
|
|
569cb6bf53 | ||
|
|
3445b594e8 | ||
|
|
676595dd6b | ||
|
|
f8c84602f4 | ||
|
|
d41842bc2a | ||
|
|
ced47e64db | ||
|
|
16a6344687 | ||
|
|
7bac0b25ce | ||
|
|
6094f738f2 | ||
|
|
c3a6d1bba8 | ||
|
|
1feeb350ce | ||
|
|
f21ba207fe | ||
|
|
07c8ff4571 | ||
|
|
71d8588091 | ||
|
|
3c41b7e5a9 | ||
|
|
41b7a295b9 | ||
|
|
ca8e889e1e | ||
|
|
6d4e52c928 | ||
|
|
e2fac8ab05 | ||
|
|
af3883fdac | ||
|
|
83777d7ea0 | ||
|
|
c6854c84b9 | ||
|
|
eb99352fff | ||
|
|
7dac5d424b | ||
|
|
441958028d | ||
|
|
80b61a35a9 | ||
|
|
61df0f3d31 | ||
|
|
23ece9fc86 | ||
|
|
220e3d7195 | ||
|
|
392c0311e5 | ||
|
|
3abdcfa7a5 | ||
|
|
4896042fc4 | ||
|
|
7edfd5d7b4 | ||
|
|
ad8e52f744 | ||
|
|
455dc5dc11 | ||
|
|
158f5ac310 | ||
|
|
fb70029091 | ||
|
|
b370512893 | ||
|
|
764607314c | ||
|
|
dbcf9b01c5 | ||
|
|
93ce77438f | ||
|
|
14c30661e6 | ||
|
|
37efc44f43 | ||
|
|
6aaade846a | ||
|
|
bd2402396b | ||
|
|
a9b3479216 | ||
|
|
05e98877b0 | ||
|
|
862ddf3a71 | ||
|
|
c1df2c45de | ||
|
|
065e97c940 | ||
|
|
adae7fa03b | ||
|
|
b725dbea7e | ||
|
|
4b80eec000 | ||
|
|
d7722a1e05 | ||
|
|
35cfcc59f6 | ||
|
|
192190d685 | ||
|
|
d6cc4bfa9c | ||
|
|
ed284fbc5f | ||
|
|
cb0efe25f5 | ||
|
|
906fe4f8da | ||
|
|
04a641199b | ||
|
|
50cbad22d0 | ||
|
|
4cfe59271f | ||
|
|
ba7969dad4 | ||
|
|
43b6440bf9 | ||
|
|
3e19a163c2 | ||
|
|
ca39282269 | ||
|
|
016389df68 | ||
|
|
17db2a6b38 | ||
|
|
bc8f17ee5c | ||
|
|
0c8944ab8e | ||
|
|
0960b585bd | ||
|
|
55649c3750 | ||
|
|
51bbf71577 | ||
|
|
728fab1dda | ||
|
|
d5ec80d85d | ||
|
|
15ef93d7e6 | ||
|
|
9711b22ea9 | ||
|
|
b9c7d2b01d | ||
|
|
9834846a23 | ||
|
|
65f425df2c | ||
|
|
a551dfe4d6 | ||
|
|
e9bfacdb7c | ||
|
|
3ba7b7d439 | ||
|
|
381943818d | ||
|
|
d1ae2db587 | ||
|
|
8fa6e38382 | ||
|
|
749074ea94 | ||
|
|
f1bb786a49 | ||
|
|
42bde3873b | ||
|
|
4877238015 | ||
|
|
16374aaf1d | ||
|
|
19709f749a | ||
|
|
09c7affc16 | ||
|
|
01e197fd46 | ||
|
|
0fe129ac16 | ||
|
|
3c52ceb4e6 | ||
|
|
8ba2357d91 | ||
|
|
20f4990d48 | ||
|
|
8c793bf0fe | ||
|
|
12a0eebafe | ||
|
|
092c7dff6b | ||
|
|
7a1ff42d67 | ||
|
|
5a09a80902 | ||
|
|
a7ca839afb | ||
|
|
6b9b9a96c3 | ||
|
|
272888acab | ||
|
|
283e3c9de1 | ||
|
|
859087b850 | ||
|
|
f7b911dc0b | ||
|
|
9d7e2855d3 | ||
|
|
8e6ea87754 | ||
|
|
34bc444b18 | ||
|
|
860a903336 | ||
|
|
be923ad2b7 | ||
|
|
d2da1ed1e7 | ||
|
|
1c05f5e5c3 | ||
|
|
e043f30cc6 | ||
|
|
e1611d83a3 | ||
|
|
58e2111a8f | ||
|
|
c5e4c484dc | ||
|
|
75a6dece7a | ||
|
|
5c0e7736d6 | ||
|
|
2562ecd055 | ||
|
|
aaaa47b575 | ||
|
|
21d82ec1d7 | ||
|
|
5af8444cac | ||
|
|
cd82c34b93 | ||
|
|
d182659d62 | ||
|
|
171f428b9d | ||
|
|
da4ca9c804 | ||
|
|
c019341503 | ||
|
|
7234f04b56 | ||
|
|
1998cbc005 | ||
|
|
5914073c3f | ||
|
|
d5aadf2604 | ||
|
|
1fe22f940b | ||
|
|
0cdaf70efe | ||
|
|
8174c65243 | ||
|
|
2645801277 | ||
|
|
fb8c31cb9c | ||
|
|
7287dbd64f | ||
|
|
6569d64931 | ||
|
|
e9f3216926 | ||
|
|
ca0af9646d | ||
|
|
92dfafd1ff | ||
|
|
d04dde3b97 | ||
|
|
4c520c6df3 | ||
|
|
65d6ed1cdc | ||
|
|
3352a92445 | ||
|
|
bc8c55b8fb | ||
|
|
7660914eb8 | ||
|
|
869aec778c | ||
|
|
255726dcc4 | ||
|
|
9969000807 | ||
|
|
3b909fd739 | ||
|
|
ad08fb8132 | ||
|
|
8d536a6040 | ||
|
|
2b1bc8e2b9 | ||
|
|
563194ff6c | ||
|
|
0c9ff4dae4 | ||
|
|
b10e7f1811 | ||
|
|
f93ad499e2 | ||
|
|
87a51251ca | ||
|
|
b56e5b2483 | ||
|
|
476c162016 | ||
|
|
4182f6043a | ||
|
|
aa528c65b7 | ||
|
|
4998560e31 | ||
|
|
86f36922c4 | ||
|
|
4f617b86d3 | ||
|
|
b28527e10d | ||
|
|
fbb8924ebf | ||
|
|
f68c9b751f | ||
|
|
8091f02b16 | ||
|
|
f4c68d115b | ||
|
|
6c70d6b9ae | ||
|
|
1ea12567a3 | ||
|
|
2d16ab7a70 | ||
|
|
a228ba5273 | ||
|
|
d0477e9ebf | ||
|
|
c99907972d | ||
|
|
b9ebc7d7ea | ||
|
|
4f9e2c5eca | ||
|
|
ab1f8ee5ae | ||
|
|
89276ad51a | ||
|
|
eca533a517 | ||
|
|
0be578c517 | ||
|
|
198b315602 | ||
|
|
6474abc983 | ||
|
|
2137dbe849 | ||
|
|
b7b46703d9 | ||
|
|
d2d96a1421 | ||
|
|
cfcc309e5a | ||
|
|
7d87ec942e | ||
|
|
4def13272f | ||
|
|
c4f914bb7b | ||
|
|
6bf213a0b0 | ||
|
|
694cd2bc7c | ||
|
|
3851a94400 | ||
|
|
e296416a54 | ||
|
|
0bd89a659c | ||
|
|
0ada6523a8 | ||
|
|
56570d7ba1 | ||
|
|
0ffdedcfa6 | ||
|
|
f391bb8eec | ||
|
|
7000076961 | ||
|
|
e0f6ba808c | ||
|
|
4c2fe8a846 | ||
|
|
2ea23368bc | ||
|
|
87666005a6 | ||
|
|
7666f44b7a | ||
|
|
470f6e5334 | ||
|
|
a2b007874b | ||
|
|
9946d8c6b9 | ||
|
|
02fab16475 | ||
|
|
5145ce2d23 | ||
|
|
e06abe6e5b | ||
|
|
50a847777e | ||
|
|
4473f80d73 | ||
|
|
70c918c9c6 | ||
|
|
0939975631 | ||
|
|
0ef90c6165 | ||
|
|
cef14a3b19 | ||
|
|
61d3141bce | ||
|
|
f040a0b6d1 | ||
|
|
e9dfec88c9 | ||
|
|
6fa97c845a | ||
|
|
f686d9ecd0 | ||
|
|
621ebe4396 | ||
|
|
ac2a566685 | ||
|
|
ac3d57d5da | ||
|
|
9ab5eef984 | ||
|
|
912f90accf | ||
|
|
6463b0dcaa | ||
|
|
0b45fb6764 | ||
|
|
330d71847b | ||
|
|
60c8f0c78b | ||
|
|
fcbd1ab0b1 | ||
|
|
3549bfb328 | ||
|
|
c97038fffd | ||
|
|
15b5885982 | ||
|
|
6aa8d9fbf9 | ||
|
|
eccf4620ac | ||
|
|
f08fbe9bb2 | ||
|
|
bfa87af489 | ||
|
|
a7899b7505 | ||
|
|
e80b5cddcd | ||
|
|
db12f9b8dc | ||
|
|
f4c95195c9 | ||
|
|
e2cbff7b3a | ||
|
|
98a3c8150c | ||
|
|
447e09fec1 | ||
|
|
7d2a1bb2e5 | ||
|
|
40fcf79778 | ||
|
|
88a779bbdb | ||
|
|
db04514769 | ||
|
|
23062470f5 | ||
|
|
5bad043ed5 | ||
|
|
4ab8af0995 | ||
|
|
1a65c5e13e | ||
|
|
fc08946038 | ||
|
|
4d6dba06ad | ||
|
|
d7887fe25f | ||
|
|
81dd50e752 | ||
|
|
fe13065ef8 | ||
|
|
eb02330fdf | ||
|
|
738fa6fd0e | ||
|
|
0c1c7e4f8e | ||
|
|
9eb9b66398 | ||
|
|
9db046b401 | ||
|
|
914272eee0 | ||
|
|
2b7e203bcc | ||
|
|
a61ddedc0b | ||
|
|
60fc34ffac | ||
|
|
685109556c | ||
|
|
45927053f3 | ||
|
|
5d438a877b | ||
|
|
870499bc3a | ||
|
|
c6d97e3d4b | ||
|
|
efff38b116 | ||
|
|
1b725175c6 | ||
|
|
6eff62f73f | ||
|
|
95d2160c76 | ||
|
|
2b195155ed | ||
|
|
28e9abc8bb | ||
|
|
0162b9d441 | ||
|
|
0545b929e1 | ||
|
|
d2b32ff5af | ||
|
|
2d3776cd5f | ||
|
|
2638963171 | ||
|
|
24ed97f65d | ||
|
|
c099634e39 | ||
|
|
12be14e6cf | ||
|
|
4dc773c1a3 | ||
|
|
31c5323fd9 | ||
|
|
74b6e7bf63 | ||
|
|
34025fa646 | ||
|
|
df9554194a | ||
|
|
4e1188484d | ||
|
|
2f44b9dc59 | ||
|
|
9ee3c48485 | ||
|
|
78b9c94829 | ||
|
|
4c8225ed73 | ||
|
|
88aad6d351 | ||
|
|
d99d701095 | ||
|
|
61fe27abbe | ||
|
|
24cd5006d5 | ||
|
|
726d6aad65 | ||
|
|
bd9fe14a6c | ||
|
|
792a10ace5 | ||
|
|
e9ac69b8e5 | ||
|
|
c76ff2d371 | ||
|
|
8ab9e30404 | ||
|
|
53b7d93efb | ||
|
|
00df3c3d1f | ||
|
|
e766b82418 | ||
|
|
9f4757af5b | ||
|
|
1a9fb34a6e | ||
|
|
a1513a3567 | ||
|
|
0de67b6a69 | ||
|
|
fec5ee9335 | ||
|
|
b540111fa4 | ||
|
|
0eed72b888 | ||
|
|
0856d3dbdf | ||
|
|
a9b453c27a | ||
|
|
fa8287269f | ||
|
|
1eee471018 | ||
|
|
c3829f82ab | ||
|
|
a51820f5df | ||
|
|
68591fb511 | ||
|
|
3795ce2143 | ||
|
|
3561a4f14d | ||
|
|
84cda001aa | ||
|
|
481127a560 | ||
|
|
c708e7cd61 | ||
|
|
fee0268792 | ||
|
|
953593c9d4 | ||
|
|
5ff60e53cb | ||
|
|
b38ee36fae | ||
|
|
38a415faf0 | ||
|
|
1e26864842 | ||
|
|
4b74ad5577 | ||
|
|
e5696713de | ||
|
|
2e44397c88 | ||
|
|
5d19881981 | ||
|
|
1711384eaa | ||
|
|
9897efe4af | ||
|
|
884578ea95 | ||
|
|
e404e76299 | ||
|
|
1db54cba3e | ||
|
|
77e3cc4021 | ||
|
|
242c63dfb4 | ||
|
|
f5440576b5 | ||
|
|
b020365af4 | ||
|
|
25e5bf0b86 | ||
|
|
19b32dd3a6 | ||
|
|
1ab89d0db0 | ||
|
|
6e8e10323f | ||
|
|
58bc5dc66a | ||
|
|
db42bb603b | ||
|
|
cb382c9537 | ||
|
|
a4b79a2dc9 | ||
|
|
0f867e02c4 | ||
|
|
ab1b4b37f4 | ||
|
|
5a1d138f29 | ||
|
|
06a5298efa | ||
|
|
db720acc18 | ||
|
|
8d8ff25bae | ||
|
|
6f85b7cc09 | ||
|
|
77f5770bff | ||
|
|
14cda5b921 | ||
|
|
36b1182565 | ||
|
|
483327c808 | ||
|
|
efb2f9a048 | ||
|
|
01978dabf0 | ||
|
|
cfbd2bf53a | ||
|
|
9262f94190 | ||
|
|
b36a0bd10b | ||
|
|
2dc8948f33 | ||
|
|
9f2ed2f9d4 | ||
|
|
e0f7d65f77 | ||
|
|
f18ac3a923 | ||
|
|
b39a6bcc97 | ||
|
|
8fa9c25f2a | ||
|
|
84bde62e05 | ||
|
|
5bb4621097 | ||
|
|
f1edf84f4d | ||
|
|
f7955a9040 | ||
|
|
7c5df21685 | ||
|
|
2060bb8cdd | ||
|
|
a9b4e7b1e2 | ||
|
|
82528c4478 | ||
|
|
4dcfc3e0bc | ||
|
|
999315d3c6 | ||
|
|
aef0b03c34 | ||
|
|
49f008c46f | ||
|
|
bd81db4117 | ||
|
|
9f274883e3 | ||
|
|
07b76b80f4 | ||
|
|
0014f0a88d | ||
|
|
63f7a78d31 | ||
|
|
e556c090ff | ||
|
|
c4f483c250 | ||
|
|
4031332b98 | ||
|
|
10cb7c8d6a | ||
|
|
be190bfe33 | ||
|
|
4d7d642952 | ||
|
|
737711e5eb | ||
|
|
42fc128f97 | ||
|
|
b03e6c3b19 | ||
|
|
66008489c4 | ||
|
|
3262e3490a | ||
|
|
16a73b0848 | ||
|
|
52bb4d7a0e | ||
|
|
40b5e4d549 | ||
|
|
b014ea8950 | ||
|
|
61592716f9 | ||
|
|
efe7fc0ee7 | ||
|
|
a810db3641 | ||
|
|
f8b292dfa3 | ||
|
|
fc2ab91280 | ||
|
|
668ee219c6 | ||
|
|
ee6512a1a6 | ||
|
|
fe1f590286 | ||
|
|
876e8f843a | ||
|
|
a45c1a1dc8 | ||
|
|
f8377169e6 | ||
|
|
a197a33d35 | ||
|
|
3060207d04 | ||
|
|
28c1d0b3f5 | ||
|
|
644d051477 | ||
|
|
f42031c8de | ||
|
|
6b50d9b087 | ||
|
|
a0f0da64b4 | ||
|
|
1e72ebd104 | ||
|
|
1184a95697 | ||
|
|
cd0e4a5678 | ||
|
|
394f6c3110 | ||
|
|
e2b6d0c256 | ||
|
|
fe7ca210dd | ||
|
|
e58d6bf2a3 | ||
|
|
460d20d6b2 | ||
|
|
ae154212fe | ||
|
|
28bb4edbac | ||
|
|
1ceed1b47b | ||
|
|
9445e64c2e | ||
|
|
e6fba03ba7 | ||
|
|
b027ca5c09 | ||
|
|
e98df30500 | ||
|
|
111c44dadf | ||
|
|
cb31c25e6c | ||
|
|
5d59c953c2 | ||
|
|
a2cff42981 | ||
|
|
cae892a971 | ||
|
|
f8447d923e | ||
|
|
3b8dabc9d2 | ||
|
|
cda39e967c | ||
|
|
7da9367dc9 | ||
|
|
82d97ef26f | ||
|
|
9e094f1d96 | ||
|
|
da7e15c268 | ||
|
|
24806a810c | ||
|
|
a2ace4510a | ||
|
|
5c8132088f | ||
|
|
7ee060b228 | ||
|
|
4b2a4b8f7b | ||
|
|
5a668ede01 | ||
|
|
9e099444b6 | ||
|
|
e3f5b3535a | ||
|
|
346ad1e8a3 | ||
|
|
2a9558e9c5 | ||
|
|
c324f66aef | ||
|
|
e688f2cdb6 | ||
|
|
2ff8762a22 | ||
|
|
4d75221938 | ||
|
|
658b699b71 | ||
|
|
72b0d03546 | ||
|
|
19980807f2 | ||
|
|
3514e3d057 | ||
|
|
fb6c82740c | ||
|
|
8df5a010c9 | ||
|
|
895e9b8bf0 | ||
|
|
bfcf85e0d2 | ||
|
|
5770222304 | ||
|
|
d5d2815bdf | ||
|
|
7fc3d413e5 | ||
|
|
474228b630 | ||
|
|
0805e077a1 | ||
|
|
6b059a9a75 | ||
|
|
7377e4e34d | ||
|
|
6fac947d9c | ||
|
|
5973e5ca26 | ||
|
|
5907b7090e | ||
|
|
6570a55e7e | ||
|
|
608ab53933 | ||
|
|
05679f7a8d | ||
|
|
f4838bb3b5 | ||
|
|
edb2a65196 | ||
|
|
fd721cac51 | ||
|
|
a1ff3cc8f7 | ||
|
|
3fa6b264e5 | ||
|
|
fcf51ec6da | ||
|
|
d15b5f8cbc | ||
|
|
ef3cbcac6d | ||
|
|
b16893c4d2 | ||
|
|
a365814aaa | ||
|
|
eca2116adc | ||
|
|
4cfa403657 | ||
|
|
70ded4c2cd | ||
|
|
3fe45db6ef | ||
|
|
11467775b6 | ||
|
|
1e5fcf635e | ||
|
|
223ba4643f | ||
|
|
200fd76929 | ||
|
|
c5c4ecd6e6 | ||
|
|
bedca9f82c | ||
|
|
adc356eff3 | ||
|
|
c4285772b3 | ||
|
|
a02235f2bd | ||
|
|
5f215b14c2 | ||
|
|
6e29fe8d58 | ||
|
|
43ceb1982d | ||
|
|
d02ec47d77 | ||
|
|
9942950710 | ||
|
|
a6682be251 | ||
|
|
baee2cd6b2 | ||
|
|
3ee8eac635 | ||
|
|
ce5a775160 | ||
|
|
2cf66d1c53 | ||
|
|
eaee67d742 | ||
|
|
c681496b1b | ||
|
|
829d3e046d | ||
|
|
5c8df540db | ||
|
|
8920e6e448 | ||
|
|
3cb860232e | ||
|
|
d588518ba1 | ||
|
|
d6f727d17a | ||
|
|
82c40302bd | ||
|
|
c40c62a247 | ||
|
|
8048b5ebca | ||
|
|
03ba43df5d | ||
|
|
a4b95b45ec | ||
|
|
59513962fe | ||
|
|
a201b43cde | ||
|
|
f98c77bd16 | ||
|
|
2596359b25 | ||
|
|
e0a0263607 | ||
|
|
2d3feedb07 | ||
|
|
af392fad3d | ||
|
|
ef74490c44 | ||
|
|
b6856e18a8 | ||
|
|
de1d4424d9 | ||
|
|
5ec45bb575 | ||
|
|
cb3aced2ed | ||
|
|
2f13a1ad21 | ||
|
|
045127adee | ||
|
|
db1a0c0362 | ||
|
|
dcaf91a878 | ||
|
|
a9209f5103 | ||
|
|
ea613986c2 | ||
|
|
1ed46bd47c | ||
|
|
f1ee79e75a | ||
|
|
cd27160905 | ||
|
|
9ddf4a1308 | ||
|
|
a1c5ed9eb5 | ||
|
|
7a4f19eada | ||
|
|
397fb785d6 | ||
|
|
75a1fcc933 | ||
|
|
292cbf1383 | ||
|
|
37a14fefb3 | ||
|
|
f424633d8c | ||
|
|
048258d2d1 | ||
|
|
f779108b6c | ||
|
|
522f3ae0a1 | ||
|
|
3fc7067c59 | ||
|
|
c600e8ef89 | ||
|
|
5ad267fe1b | ||
|
|
d8b3e438f8 | ||
|
|
2834af66e9 | ||
|
|
1bbf86fbeb | ||
|
|
f662b95dc9 | ||
|
|
9ad4b725ac | ||
|
|
0182c61aec | ||
|
|
78362535c7 | ||
|
|
ae7b31f343 | ||
|
|
f16441bba4 | ||
|
|
d3f9bb6def | ||
|
|
e02440aa59 | ||
|
|
f1d87c29d3 | ||
|
|
21335b1b00 | ||
|
|
7463570e76 | ||
|
|
da17a63ef5 | ||
|
|
eb8f2021cb | ||
|
|
888ff33be1 | ||
|
|
b46850e86e | ||
|
|
f053587f09 | ||
|
|
7a3092a23b | ||
|
|
d95450ae07 | ||
|
|
230def10fe | ||
|
|
036f8e49a4 | ||
|
|
4eca8a5640 | ||
|
|
08f96a91f3 | ||
|
|
2e915eccd6 | ||
|
|
c05c58c82b | ||
|
|
572feed918 | ||
|
|
d30d207ab5 | ||
|
|
2a6b91dd04 | ||
|
|
3dee1725b3 | ||
|
|
f7ac465e67 | ||
|
|
912f14549c | ||
|
|
21079335e7 | ||
|
|
85741240f1 | ||
|
|
3df9a87b29 | ||
|
|
acd60007ac | ||
|
|
f66c9630e3 | ||
|
|
50a5892a31 | ||
|
|
c5f58437b1 | ||
|
|
a915424d9a | ||
|
|
be7699c600 | ||
|
|
a7c946ddae | ||
|
|
4b741a9434 | ||
|
|
cd963272d4 | ||
|
|
9de17ead91 | ||
|
|
d98b133d63 | ||
|
|
361e8e0066 | ||
|
|
523c44b796 | ||
|
|
4bd60ed6a1 | ||
|
|
7d57f08baf | ||
|
|
5e7f54dbc3 | ||
|
|
dfb9ce990d | ||
|
|
e87a368e87 | ||
|
|
44506057fd | ||
|
|
ff08eadb23 | ||
|
|
ebb1a3feb2 | ||
|
|
81bc85b8e4 | ||
|
|
4a749f52e9 | ||
|
|
25e37ddd78 | ||
|
|
46a9cfcc67 | ||
|
|
66ff944660 | ||
|
|
988db59197 | ||
|
|
34e321407a | ||
|
|
44c0028a51 | ||
|
|
264b75cd68 | ||
|
|
cf9ccdcab6 | ||
|
|
48e18e533c | ||
|
|
12ef778bf4 | ||
|
|
6c31a1788a | ||
|
|
aa7c6da8ef | ||
|
|
1ff40cace0 | ||
|
|
0a1dadbea1 | ||
|
|
24edbdba5e | ||
|
|
db504eff88 | ||
|
|
5e09925659 | ||
|
|
d1b2b351c8 | ||
|
|
50b0dc178e | ||
|
|
b34118e395 | ||
|
|
e6436f9021 | ||
|
|
831d1b4f3a | ||
|
|
0456d1ca29 | ||
|
|
fcd151022e | ||
|
|
0c1998002e | ||
|
|
b8c33ce7fa | ||
|
|
454cd633e8 | ||
|
|
53cb9a6e10 | ||
|
|
8d6ff763d6 | ||
|
|
ecf15af3a0 | ||
|
|
716823789d | ||
|
|
3c192badce | ||
|
|
d94b611d10 | ||
|
|
e2ce329b6c | ||
|
|
ef902fc706 | ||
|
|
a7fc94c303 | ||
|
|
c8c6d1bb1e | ||
|
|
a205108681 | ||
|
|
31561879b3 | ||
|
|
fdb6677153 | ||
|
|
17241be4bc | ||
|
|
3bf6de9c76 | ||
|
|
a53322e7cb | ||
|
|
a107c126e4 | ||
|
|
3a8dcae53a | ||
|
|
b99d4532df | ||
|
|
6e8f8ea357 | ||
|
|
83838bbe76 | ||
|
|
66620aabe2 | ||
|
|
74fcf8270d | ||
|
|
91b4e32a38 | ||
|
|
3f0c114f24 | ||
|
|
30fe6b93c4 | ||
|
|
ec99242314 | ||
|
|
9149fb7a85 | ||
|
|
3c919d9a8a | ||
|
|
22f9ce1e2e | ||
|
|
72b01cec70 | ||
|
|
57b8bc2645 | ||
|
|
3ad4ca3943 | ||
|
|
237ffeff52 | ||
|
|
fb491d9790 | ||
|
|
facd03b6ad | ||
|
|
f5f38ca670 | ||
|
|
83e599f0e9 | ||
|
|
48cd06f37e | ||
|
|
aac9d2d1c4 | ||
|
|
7e2e1c12b9 | ||
|
|
3410dd4eba | ||
|
|
d511085db3 | ||
|
|
caaa3583a7 | ||
|
|
185e5691a4 | ||
|
|
20f44cc64f | ||
|
|
07ef94afd9 | ||
|
|
2d33b8a958 | ||
|
|
d283f5dbb4 | ||
|
|
1af76c4d06 | ||
|
|
07498c6bef | ||
|
|
18f9ebbc4f | ||
|
|
85b4f652f4 | ||
|
|
eec6f7336c | ||
|
|
f976dd8d30 | ||
|
|
2d3aa3a96e | ||
|
|
1195cbd772 | ||
|
|
cebfa674ef | ||
|
|
3ed596496d | ||
|
|
d99ef78348 | ||
|
|
2666c1e196 | ||
|
|
4b8c8888ee | ||
|
|
ce1fd64aa9 | ||
|
|
bd1479b14a | ||
|
|
baee9520d1 | ||
|
|
adb30a526e | ||
|
|
60c40457fc | ||
|
|
a6df457c9c | ||
|
|
3fd8fb0308 | ||
|
|
7d4a7d4ab6 | ||
|
|
4571b95683 | ||
|
|
a65d2a1bba | ||
|
|
5c9503732d | ||
|
|
2dbbf7f350 | ||
|
|
e1cce220b3 | ||
|
|
e0aed26f63 | ||
|
|
62fd07258e | ||
|
|
0d8127140f | ||
|
|
bab5326d7c | ||
|
|
5c8445f3fe | ||
|
|
604488b166 | ||
|
|
b7d7fc8b67 | ||
|
|
1f4872f72b | ||
|
|
f89c40cde6 | ||
|
|
670edbc22a | ||
|
|
54f70c8158 | ||
|
|
0d6bcba023 | ||
|
|
06a9f95979 | ||
|
|
03cdfc259e | ||
|
|
1963b5732a | ||
|
|
1e05dc937c | ||
|
|
c3b22ff737 | ||
|
|
991f07e148 | ||
|
|
8efb849391 | ||
|
|
5b310f3e46 | ||
|
|
5f54e42a43 | ||
|
|
a83f20e454 | ||
|
|
cdab86bd83 | ||
|
|
48cbb80e79 | ||
|
|
1af6200655 | ||
|
|
b8585594cd |
@@ -1,6 +1,6 @@
|
||||
root = true
|
||||
|
||||
[*.{js,ts,tsx}]
|
||||
[*.{js,ts,tsx,css}]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
|
||||
4
.github/actions/build-electron/action.yml
vendored
4
.github/actions/build-electron/action.yml
vendored
@@ -21,7 +21,7 @@ runs:
|
||||
# Certificate setup
|
||||
- name: Import Apple certificates
|
||||
if: inputs.os == 'macos'
|
||||
uses: apple-actions/import-codesign-certs@v5
|
||||
uses: apple-actions/import-codesign-certs@v6
|
||||
with:
|
||||
p12-file-base64: ${{ env.APPLE_APP_CERTIFICATE_BASE64 }}
|
||||
p12-password: ${{ env.APPLE_APP_CERTIFICATE_PASSWORD }}
|
||||
@@ -30,7 +30,7 @@ runs:
|
||||
|
||||
- name: Install Installer certificate
|
||||
if: inputs.os == 'macos'
|
||||
uses: apple-actions/import-codesign-certs@v5
|
||||
uses: apple-actions/import-codesign-certs@v6
|
||||
with:
|
||||
p12-file-base64: ${{ env.APPLE_INSTALLER_CERTIFICATE_BASE64 }}
|
||||
p12-password: ${{ env.APPLE_INSTALLER_CERTIFICATE_PASSWORD }}
|
||||
|
||||
8
.github/workflows/main-docker.yml
vendored
8
.github/workflows/main-docker.yml
vendored
@@ -86,12 +86,12 @@ jobs:
|
||||
|
||||
- name: Upload Playwright trace
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: Playwright trace (${{ matrix.dockerfile }})
|
||||
path: test-output/playwright/output
|
||||
|
||||
- uses: actions/upload-artifact@v5
|
||||
- uses: actions/upload-artifact@v6
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
name: Playwright report (${{ matrix.dockerfile }})
|
||||
@@ -213,7 +213,7 @@ jobs:
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: digests-${{ env.PLATFORM_PAIR }}-${{ matrix.dockerfile }}
|
||||
path: /tmp/digests/*
|
||||
@@ -227,7 +227,7 @@ jobs:
|
||||
- build
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
path: /tmp/digests
|
||||
pattern: digests-*
|
||||
|
||||
6
.github/workflows/nightly.yml
vendored
6
.github/workflows/nightly.yml
vendored
@@ -90,7 +90,7 @@ jobs:
|
||||
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGN_KEY }}
|
||||
|
||||
- name: Publish release
|
||||
uses: softprops/action-gh-release@v2.4.2
|
||||
uses: softprops/action-gh-release@v2.5.0
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
with:
|
||||
make_latest: false
|
||||
@@ -102,7 +102,7 @@ jobs:
|
||||
name: Nightly Build
|
||||
|
||||
- name: Publish artifacts
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
with:
|
||||
name: TriliumNotes ${{ matrix.os.name }} ${{ matrix.arch }}
|
||||
@@ -131,7 +131,7 @@ jobs:
|
||||
arch: ${{ matrix.arch }}
|
||||
|
||||
- name: Publish release
|
||||
uses: softprops/action-gh-release@v2.4.2
|
||||
uses: softprops/action-gh-release@v2.5.0
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
with:
|
||||
make_latest: false
|
||||
|
||||
2
.github/workflows/playwright.yml
vendored
2
.github/workflows/playwright.yml
vendored
@@ -77,7 +77,7 @@ jobs:
|
||||
|
||||
- name: Upload test report
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: e2e report ${{ matrix.arch }}
|
||||
path: apps/server-e2e/test-output
|
||||
|
||||
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
@@ -73,7 +73,7 @@ jobs:
|
||||
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGN_KEY }}
|
||||
|
||||
- name: Upload the artifact
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: release-desktop-${{ matrix.os.name }}-${{ matrix.arch }}
|
||||
path: apps/desktop/upload/*.*
|
||||
@@ -100,7 +100,7 @@ jobs:
|
||||
arch: ${{ matrix.arch }}
|
||||
|
||||
- name: Upload the artifact
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: release-server-linux-${{ matrix.arch }}
|
||||
path: upload/*.*
|
||||
@@ -120,14 +120,14 @@ jobs:
|
||||
docs/Release Notes
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
merge-multiple: true
|
||||
pattern: release-*
|
||||
path: upload
|
||||
|
||||
- name: Publish stable release
|
||||
uses: softprops/action-gh-release@v2.4.2
|
||||
uses: softprops/action-gh-release@v2.5.0
|
||||
with:
|
||||
draft: false
|
||||
body_path: docs/Release Notes/Release Notes/${{ github.ref_name }}.md
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -44,8 +44,11 @@ upload
|
||||
.rollup.cache
|
||||
*.tsbuildinfo
|
||||
|
||||
/.direnv
|
||||
/result
|
||||
.svelte-kit
|
||||
|
||||
# docs
|
||||
site/
|
||||
apps/*/coverage
|
||||
scripts/translation/.language*.json
|
||||
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
@@ -9,7 +9,6 @@
|
||||
"tobermory.es6-string-html",
|
||||
"vitest.explorer",
|
||||
"yzhang.markdown-all-in-one",
|
||||
"svelte.svelte-vscode",
|
||||
"bradlc.vscode-tailwindcss"
|
||||
"usernamehw.errorlens"
|
||||
]
|
||||
}
|
||||
|
||||
8
.vscode/settings.json
vendored
8
.vscode/settings.json
vendored
@@ -36,5 +36,11 @@
|
||||
"docs/**/*.png": true,
|
||||
"apps/server/src/assets/doc_notes/**": true,
|
||||
"apps/edit-docs/demo/**": true
|
||||
}
|
||||
},
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
},
|
||||
"eslint.rules.customizations": [
|
||||
{ "rule": "*", "severity": "warn" }
|
||||
]
|
||||
}
|
||||
63
README.md
63
README.md
@@ -16,13 +16,14 @@
|
||||

|
||||
[](https://app.relative-ci.com/projects/Di5q7dz9daNDZ9UXi0Bp) [](https://hosted.weblate.org/engage/trilium/)
|
||||
|
||||
[English](./README.md) | [Chinese (Simplified)](./docs/README-ZH_CN.md) | [Chinese (Traditional)](./docs/README-ZH_TW.md) | [Russian](./docs/README-ru.md) | [Japanese](./docs/README-ja.md) | [Italian](./docs/README-it.md) | [Spanish](./docs/README-es.md)
|
||||
<!-- translate:off -->
|
||||
<!-- LANGUAGE SWITCHER -->
|
||||
[Chinese (Simplified Han script)](./docs/README-ZH_CN.md) | [Chinese (Traditional Han script)](./docs/README-ZH_TW.md) | [English](./docs/README.md) | [French](./docs/README-fr.md) | [German](./docs/README-de.md) | [Greek](./docs/README-el.md) | [Italian](./docs/README-it.md) | [Japanese](./docs/README-ja.md) | [Romanian](./docs/README-ro.md) | [Spanish](./docs/README-es.md)
|
||||
<!-- translate:on -->
|
||||
|
||||
Trilium Notes is a free and open-source, cross-platform hierarchical note taking application with focus on building large personal knowledge bases.
|
||||
|
||||
See [screenshots](https://triliumnext.github.io/Docs/Wiki/screenshot-tour) for quick overview:
|
||||
|
||||
<a href="https://triliumnext.github.io/Docs/Wiki/screenshot-tour"><img src="./docs/app.png" alt="Trilium Screenshot" width="1000"></a>
|
||||
<img src="./docs/app.png" alt="Trilium Screenshot" width="1000">
|
||||
|
||||
## ⏬ Download
|
||||
- [Latest release](https://github.com/TriliumNext/Trilium/releases/latest) – stable version, recommended for most users.
|
||||
@@ -39,39 +40,39 @@ Our documentation is available in multiple formats:
|
||||
|
||||
### Quick Links
|
||||
- [Getting Started Guide](https://docs.triliumnotes.org/)
|
||||
- [Installation Instructions](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation.md)
|
||||
- [Docker Setup](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation/1.%20Installing%20the%20server/Using%20Docker.md)
|
||||
- [Upgrading TriliumNext](./docs/User%20Guide/User%20Guide/Installation%20%26%20Setup/Upgrading%20TriliumNext.md)
|
||||
- [Basic Concepts and Features](./docs/User%20Guide/User%20Guide/Basic%20Concepts%20and%20Features/Notes.md)
|
||||
- [Patterns of Personal Knowledge Base](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge)
|
||||
- [Installation Instructions](https://docs.triliumnotes.org/user-guide/setup)
|
||||
- [Docker Setup](https://docs.triliumnotes.org/user-guide/setup/server/installation/docker)
|
||||
- [Upgrading TriliumNext](https://docs.triliumnotes.org/user-guide/setup/upgrading)
|
||||
- [Basic Concepts and Features](https://docs.triliumnotes.org/user-guide/concepts/notes)
|
||||
- [Patterns of Personal Knowledge Base](https://docs.triliumnotes.org/user-guide/misc/patterns-of-personal-knowledge)
|
||||
|
||||
## 🎁 Features
|
||||
|
||||
* Notes can be arranged into arbitrarily deep tree. Single note can be placed into multiple places in the tree (see [cloning](https://triliumnext.github.io/Docs/Wiki/cloning-notes))
|
||||
* Rich WYSIWYG note editor including e.g. tables, images and [math](https://triliumnext.github.io/Docs/Wiki/text-notes) with markdown [autoformat](https://triliumnext.github.io/Docs/Wiki/text-notes#autoformat)
|
||||
* Support for editing [notes with source code](https://triliumnext.github.io/Docs/Wiki/code-notes), including syntax highlighting
|
||||
* Fast and easy [navigation between notes](https://triliumnext.github.io/Docs/Wiki/note-navigation), full text search and [note hoisting](https://triliumnext.github.io/Docs/Wiki/note-hoisting)
|
||||
* Seamless [note versioning](https://triliumnext.github.io/Docs/Wiki/note-revisions)
|
||||
* Note [attributes](https://triliumnext.github.io/Docs/Wiki/attributes) can be used for note organization, querying and advanced [scripting](https://triliumnext.github.io/Docs/Wiki/scripts)
|
||||
* Notes can be arranged into arbitrarily deep tree. Single note can be placed into multiple places in the tree (see [cloning](https://docs.triliumnotes.org/user-guide/concepts/notes/cloning))
|
||||
* Rich WYSIWYG note editor including e.g. tables, images and [math](https://docs.triliumnotes.org/user-guide/note-types/text) with markdown [autoformat](https://docs.triliumnotes.org/user-guide/note-types/text/markdown-formatting)
|
||||
* Support for editing [notes with source code](https://docs.triliumnotes.org/user-guide/note-types/code), including syntax highlighting
|
||||
* Fast and easy [navigation between notes](https://docs.triliumnotes.org/user-guide/concepts/navigation/note-navigation), full text search and [note hoisting](https://docs.triliumnotes.org/user-guide/concepts/navigation/note-hoisting)
|
||||
* Seamless [note versioning](https://docs.triliumnotes.org/user-guide/concepts/notes/note-revisions)
|
||||
* Note [attributes](https://docs.triliumnotes.org/user-guide/advanced-usage/attributes) can be used for note organization, querying and advanced [scripting](https://docs.triliumnotes.org/user-guide/scripts)
|
||||
* UI available in English, German, Spanish, French, Romanian, and Chinese (simplified and traditional)
|
||||
* Direct [OpenID and TOTP integration](./docs/User%20Guide/User%20Guide/Installation%20%26%20Setup/Server%20Installation/Multi-Factor%20Authentication.md) for more secure login
|
||||
* [Synchronization](https://triliumnext.github.io/Docs/Wiki/synchronization) with self-hosted sync server
|
||||
* there's a [3rd party service for hosting synchronisation server](https://trilium.cc/paid-hosting)
|
||||
* [Sharing](https://triliumnext.github.io/Docs/Wiki/sharing) (publishing) notes to public internet
|
||||
* Strong [note encryption](https://triliumnext.github.io/Docs/Wiki/protected-notes) with per-note granularity
|
||||
* Direct [OpenID and TOTP integration](https://docs.triliumnotes.org/user-guide/setup/server/mfa) for more secure login
|
||||
* [Synchronization](https://docs.triliumnotes.org/user-guide/setup/synchronization) with self-hosted sync server
|
||||
* there are [3rd party services for hosting synchronisation server](https://docs.triliumnotes.org/user-guide/setup/server/cloud-hosting)
|
||||
* [Sharing](https://docs.triliumnotes.org/user-guide/advanced-usage/sharing) (publishing) notes to public internet
|
||||
* Strong [note encryption](https://docs.triliumnotes.org/user-guide/concepts/notes/protected-notes) with per-note granularity
|
||||
* Sketching diagrams, based on [Excalidraw](https://excalidraw.com/) (note type "canvas")
|
||||
* [Relation maps](https://triliumnext.github.io/Docs/Wiki/relation-map) and [link maps](https://triliumnext.github.io/Docs/Wiki/link-map) for visualizing notes and their relations
|
||||
* [Relation maps](https://docs.triliumnotes.org/user-guide/note-types/relation-map) and [note/link maps](https://docs.triliumnotes.org/user-guide/note-types/note-map) for visualizing notes and their relations
|
||||
* Mind maps, based on [Mind Elixir](https://docs.mind-elixir.com/)
|
||||
* [Geo maps](./docs/User%20Guide/User%20Guide/Note%20Types/Geo%20Map.md) with location pins and GPX tracks
|
||||
* [Scripting](https://triliumnext.github.io/Docs/Wiki/scripts) - see [Advanced showcases](https://triliumnext.github.io/Docs/Wiki/advanced-showcases)
|
||||
* [REST API](https://triliumnext.github.io/Docs/Wiki/etapi) for automation
|
||||
* [Geo maps](https://docs.triliumnotes.org/user-guide/collections/geomap) with location pins and GPX tracks
|
||||
* [Scripting](https://docs.triliumnotes.org/user-guide/scripts) - see [Advanced showcases](https://docs.triliumnotes.org/user-guide/advanced-usage/advanced-showcases)
|
||||
* [REST API](https://docs.triliumnotes.org/user-guide/advanced-usage/etapi) for automation
|
||||
* Scales well in both usability and performance upwards of 100 000 notes
|
||||
* Touch optimized [mobile frontend](https://triliumnext.github.io/Docs/Wiki/mobile-frontend) for smartphones and tablets
|
||||
* Built-in [dark theme](https://triliumnext.github.io/Docs/Wiki/themes), support for user themes
|
||||
* [Evernote](https://triliumnext.github.io/Docs/Wiki/evernote-import) and [Markdown import & export](https://triliumnext.github.io/Docs/Wiki/markdown)
|
||||
* [Web Clipper](https://triliumnext.github.io/Docs/Wiki/web-clipper) for easy saving of web content
|
||||
* Touch optimized [mobile frontend](https://docs.triliumnotes.org/user-guide/setup/mobile-frontend) for smartphones and tablets
|
||||
* Built-in [dark theme](https://docs.triliumnotes.org/user-guide/concepts/themes), support for user themes
|
||||
* [Evernote](https://docs.triliumnotes.org/user-guide/concepts/import-export/evernote) and [Markdown import & export](https://docs.triliumnotes.org/user-guide/concepts/import-export/markdown)
|
||||
* [Web Clipper](https://docs.triliumnotes.org/user-guide/setup/web-clipper) for easy saving of web content
|
||||
* Customizable UI (sidebar buttons, user-defined widgets, ...)
|
||||
* [Metrics](./docs/User%20Guide/User%20Guide/Advanced%20Usage/Metrics.md), along with a [Grafana Dashboard](./docs/User%20Guide/User%20Guide/Advanced%20Usage/Metrics/grafana-dashboard.json)
|
||||
* [Metrics](https://docs.triliumnotes.org/user-guide/advanced-usage/metrics), along with a Grafana Dashboard.
|
||||
|
||||
✨ Check out the following third-party resources/communities for more TriliumNext related goodies:
|
||||
|
||||
@@ -131,7 +132,7 @@ Note: It is best to disable automatic updates on your server installation (see b
|
||||
|
||||
### Server
|
||||
|
||||
To install TriliumNext on your own server (including via Docker from [Dockerhub](https://hub.docker.com/r/triliumnext/trilium)) follow [the server installation docs](https://triliumnext.github.io/Docs/Wiki/server-installation).
|
||||
To install TriliumNext on your own server (including via Docker from [Dockerhub](https://hub.docker.com/r/triliumnext/trilium)) follow [the server installation docs](https://docs.triliumnotes.org/user-guide/setup/server).
|
||||
|
||||
|
||||
## 💻 Contribute
|
||||
@@ -198,7 +199,7 @@ Trilium would not be possible without the technologies behind it:
|
||||
* [Leaflet](https://github.com/Leaflet/Leaflet) - for rendering geographical maps.
|
||||
* [Tabulator](https://github.com/olifolkerd/tabulator) - for the interactive table used in collections.
|
||||
* [FancyTree](https://github.com/mar10/fancytree) - feature-rich tree library without real competition.
|
||||
* [jsPlumb](https://github.com/jsplumb/jsplumb) - visual connectivity library. Used in [relation maps](https://triliumnext.github.io/Docs/Wiki/relation-map.html) and [link maps](https://triliumnext.github.io/Docs/Wiki/note-map.html#link-map)
|
||||
* [jsPlumb](https://github.com/jsplumb/jsplumb) - visual connectivity library. Used in [relation maps](https://docs.triliumnotes.org/user-guide/note-types/relation-map) and [link maps](https://docs.triliumnotes.org/user-guide/advanced-usage/note-map#link-map)
|
||||
|
||||
## 🤝 Support
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import anonymizationService from "../src/services/anonymization.js";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
fs.writeFileSync(path.resolve(__dirname, "tpl", "anonymize-database.sql"), anonymizationService.getFullAnonymizationScript());
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
SCHEMA_FILE_PATH=db/schema.sql
|
||||
|
||||
sqlite3 ./data/document.db .schema | grep -v "sqlite_sequence" > "$SCHEMA_FILE_PATH"
|
||||
|
||||
echo "DB schema exported to $SCHEMA_FILE_PATH"
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [[ $# -eq 0 ]] ; then
|
||||
echo "Missing argument of new version"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VERSION=$1
|
||||
SERIES=${VERSION:0:4}-latest
|
||||
|
||||
docker push zadam/trilium:$VERSION
|
||||
docker push zadam/trilium:$SERIES
|
||||
|
||||
if [[ $1 != *"beta"* ]]; then
|
||||
docker push zadam/trilium:latest
|
||||
fi
|
||||
@@ -1,57 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [[ $# -eq 0 ]] ; then
|
||||
echo "Missing argument of new version"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VERSION=$1
|
||||
|
||||
if ! [[ ${VERSION} =~ ^[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}(-.+)?$ ]] ;
|
||||
then
|
||||
echo "Version ${VERSION} isn't in format X.Y.Z"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VERSION_DATE=$(git log -1 --format=%aI "v${VERSION}" | cut -c -10)
|
||||
VERSION_COMMIT=$(git rev-list -n 1 "v${VERSION}")
|
||||
|
||||
# expecting the directory at a specific path
|
||||
cd ~/trilium-flathub || exit
|
||||
|
||||
if ! git diff-index --quiet HEAD --; then
|
||||
echo "There are uncommitted changes"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BASE_BRANCH=main
|
||||
|
||||
if [[ "$VERSION" == *"beta"* ]]; then
|
||||
BASE_BRANCH=beta
|
||||
fi
|
||||
|
||||
git switch "${BASE_BRANCH}"
|
||||
git pull
|
||||
|
||||
BRANCH=b${VERSION}
|
||||
|
||||
git branch "${BRANCH}"
|
||||
git switch "${BRANCH}"
|
||||
|
||||
echo "Updating files with version ${VERSION}, date ${VERSION_DATE} and commit ${VERSION_COMMIT}"
|
||||
|
||||
flatpak-node-generator npm ../trilium/package-lock.json
|
||||
|
||||
xmlstarlet ed --inplace --update "/component/releases/release/@version" --value "${VERSION}" --update "/component/releases/release/@date" --value "${VERSION_DATE}" ./com.github.zadam.trilium.metainfo.xml
|
||||
|
||||
yq --inplace "(.modules[0].sources[0].tag = \"v${VERSION}\") | (.modules[0].sources[0].commit = \"${VERSION_COMMIT}\")" ./com.github.zadam.trilium.yml
|
||||
|
||||
git add ./generated-sources.json
|
||||
git add ./com.github.zadam.trilium.metainfo.xml
|
||||
git add ./com.github.zadam.trilium.yml
|
||||
|
||||
git commit -m "release $VERSION"
|
||||
git push --set-upstream origin "${BRANCH}"
|
||||
|
||||
gh pr create --fill -B "${BASE_BRANCH}"
|
||||
gh pr merge --auto --merge --delete-branch
|
||||
@@ -1,49 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
if [[ $# -eq 0 ]] ; then
|
||||
echo "Missing argument of new version"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v jq &> /dev/null; then
|
||||
echo "Missing command: jq"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VERSION=$1
|
||||
|
||||
if ! [[ ${VERSION} =~ ^[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}(-.+)?$ ]] ;
|
||||
then
|
||||
echo "Version ${VERSION} isn't in format X.Y.Z"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! git diff-index --quiet HEAD --; then
|
||||
echo "There are uncommitted changes"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Releasing Trilium $VERSION"
|
||||
|
||||
jq '.version = "'$VERSION'"' package.json > package.json.tmp
|
||||
mv package.json.tmp package.json
|
||||
|
||||
git add package.json
|
||||
|
||||
npm run chore:update-build-info
|
||||
|
||||
git add src/services/build.ts
|
||||
|
||||
TAG=v$VERSION
|
||||
|
||||
echo "Committing package.json version change"
|
||||
|
||||
git commit -m "chore(release): $VERSION"
|
||||
git push
|
||||
|
||||
echo "Tagging commit with $TAG"
|
||||
|
||||
git tag $TAG
|
||||
git push origin $TAG
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,51 +0,0 @@
|
||||
import eslint from "@eslint/js";
|
||||
import tseslint from "typescript-eslint";
|
||||
import simpleImportSort from "eslint-plugin-simple-import-sort";
|
||||
|
||||
export default tseslint.config(
|
||||
eslint.configs.recommended,
|
||||
tseslint.configs.recommended,
|
||||
// consider using rules below, once we have a full TS codebase and can be more strict
|
||||
// tseslint.configs.strictTypeChecked,
|
||||
// tseslint.configs.stylisticTypeChecked,
|
||||
// tseslint.configs.recommendedTypeChecked,
|
||||
{
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
projectService: true,
|
||||
tsconfigRootDir: import.meta.dirname
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
plugins: {
|
||||
"simple-import-sort": simpleImportSort
|
||||
}
|
||||
},
|
||||
{
|
||||
rules: {
|
||||
// add rule overrides here
|
||||
"no-undef": "off",
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
argsIgnorePattern: "^_",
|
||||
varsIgnorePattern: "^_"
|
||||
}
|
||||
],
|
||||
"simple-import-sort/imports": "error",
|
||||
"simple-import-sort/exports": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
ignores: [
|
||||
"build/*",
|
||||
"dist/*",
|
||||
"docs/*",
|
||||
"demo/*",
|
||||
"src/public/app-dist/*",
|
||||
"src/public/app/doc_notes/*"
|
||||
]
|
||||
}
|
||||
);
|
||||
@@ -1,47 +0,0 @@
|
||||
import stylistic from "@stylistic/eslint-plugin";
|
||||
import tsParser from "@typescript-eslint/parser";
|
||||
|
||||
// eslint config just for formatting rules
|
||||
// potentially to be merged with the linting rules into one single config,
|
||||
// once we have fixed the majority of lint errors
|
||||
|
||||
// Go to https://eslint.style/rules/default/${rule_without_prefix} to check the rule details
|
||||
export const stylisticRules = {
|
||||
"@stylistic/indent": [ "error", 4 ],
|
||||
"@stylistic/quotes": [ "error", "double", { avoidEscape: true, allowTemplateLiterals: "always" } ],
|
||||
"@stylistic/semi": [ "error", "always" ],
|
||||
"@stylistic/quote-props": [ "error", "consistent-as-needed" ],
|
||||
"@stylistic/max-len": [ "error", { code: 100 } ],
|
||||
"@stylistic/comma-dangle": [ "error", "never" ],
|
||||
"@stylistic/linebreak-style": [ "error", "unix" ],
|
||||
"@stylistic/array-bracket-spacing": [ "error", "always" ],
|
||||
"@stylistic/object-curly-spacing": [ "error", "always" ],
|
||||
"@stylistic/padded-blocks": [ "error", { classes: "always" } ]
|
||||
};
|
||||
|
||||
export default [
|
||||
{
|
||||
files: [ "**/*.{js,ts,mjs,cjs}" ],
|
||||
languageOptions: {
|
||||
parser: tsParser
|
||||
},
|
||||
plugins: {
|
||||
"@stylistic": stylistic
|
||||
},
|
||||
rules: {
|
||||
...stylisticRules
|
||||
}
|
||||
},
|
||||
{
|
||||
ignores: [
|
||||
"build/*",
|
||||
"dist/*",
|
||||
"docs/*",
|
||||
"demo/*",
|
||||
// TriliumNextTODO: check if we want to format packages here as well - for now skipping it
|
||||
"packages/*",
|
||||
"src/public/app-dist/*",
|
||||
"src/public/app/doc_notes/*"
|
||||
]
|
||||
}
|
||||
];
|
||||
@@ -1,17 +0,0 @@
|
||||
import { test as setup, expect } from "@playwright/test";
|
||||
|
||||
const authFile = "playwright/.auth/user.json";
|
||||
|
||||
const ROOT_URL = "http://localhost:8082";
|
||||
const LOGIN_PASSWORD = "demo1234";
|
||||
|
||||
// Reference: https://playwright.dev/docs/auth#basic-shared-account-in-all-tests
|
||||
|
||||
setup("authenticate", async ({ page }) => {
|
||||
await page.goto(ROOT_URL);
|
||||
await expect(page).toHaveURL(`${ROOT_URL}/login`);
|
||||
|
||||
await page.getByRole("textbox", { name: "Password" }).fill(LOGIN_PASSWORD);
|
||||
await page.getByRole("button", { name: "Login" }).click();
|
||||
await page.context().storageState({ path: authFile });
|
||||
});
|
||||
@@ -1,9 +0,0 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
|
||||
test("Can duplicate note with broken links", async ({ page }) => {
|
||||
await page.goto(`http://localhost:8082/#2VammGGdG6Ie`);
|
||||
await page.locator(".tree-wrapper .fancytree-active").getByText("Note map").click({ button: "right" });
|
||||
await page.getByText("Duplicate subtree").click();
|
||||
await expect(page.locator(".toast-body")).toBeHidden();
|
||||
await expect(page.locator(".tree-wrapper").getByText("Note map (dup)")).toBeVisible();
|
||||
});
|
||||
@@ -1,18 +0,0 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
|
||||
test("has title", async ({ page }) => {
|
||||
await page.goto("https://playwright.dev/");
|
||||
|
||||
// Expect a title "to contain" a substring.
|
||||
await expect(page).toHaveTitle(/Playwright/);
|
||||
});
|
||||
|
||||
test("get started link", async ({ page }) => {
|
||||
await page.goto("https://playwright.dev/");
|
||||
|
||||
// Click the get started link.
|
||||
await page.getByRole("link", { name: "Get started" }).click();
|
||||
|
||||
// Expects page to have a heading with the name of Installation.
|
||||
await expect(page.getByRole("heading", { name: "Installation" })).toBeVisible();
|
||||
});
|
||||
@@ -1,21 +0,0 @@
|
||||
import test, { expect } from "@playwright/test";
|
||||
|
||||
test("Native Title Bar not displayed on web", async ({ page }) => {
|
||||
await page.goto("http://localhost:8082/#root/_hidden/_options/_optionsAppearance");
|
||||
await expect(page.getByRole("heading", { name: "Theme" })).toBeVisible();
|
||||
await expect(page.getByRole("heading", { name: "Native Title Bar (requires" })).toBeHidden();
|
||||
});
|
||||
|
||||
test("Tray settings not displayed on web", async ({ page }) => {
|
||||
await page.goto("http://localhost:8082/#root/_hidden/_options/_optionsOther");
|
||||
await expect(page.getByRole("heading", { name: "Note Erasure Timeout" })).toBeVisible();
|
||||
await expect(page.getByRole("heading", { name: "Tray" })).toBeHidden();
|
||||
});
|
||||
|
||||
test("Spellcheck settings not displayed on web", async ({ page }) => {
|
||||
await page.goto("http://localhost:8082/#root/_hidden/_options/_optionsSpellcheck");
|
||||
await expect(page.getByRole("heading", { name: "Spell Check" })).toBeVisible();
|
||||
await expect(page.getByRole("heading", { name: "Tray" })).toBeHidden();
|
||||
await expect(page.getByText("These options apply only for desktop builds")).toBeVisible();
|
||||
await expect(page.getByText("Enable spellcheck")).toBeHidden();
|
||||
});
|
||||
@@ -1,18 +0,0 @@
|
||||
import test, { expect } from "@playwright/test";
|
||||
|
||||
test("Renders on desktop", async ({ page, context }) => {
|
||||
await page.goto("http://localhost:8082");
|
||||
await expect(page.locator(".tree")).toContainText("Trilium Integration Test");
|
||||
});
|
||||
|
||||
test("Renders on mobile", async ({ page, context }) => {
|
||||
await context.addCookies([
|
||||
{
|
||||
url: "http://localhost:8082",
|
||||
name: "trilium-device",
|
||||
value: "mobile"
|
||||
}
|
||||
]);
|
||||
await page.goto("http://localhost:8082");
|
||||
await expect(page.locator(".tree")).toContainText("Trilium Integration Test");
|
||||
});
|
||||
@@ -1,12 +0,0 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
|
||||
const expectedVersion = "0.90.3";
|
||||
|
||||
test("Displays update badge when there is a version available", async ({ page }) => {
|
||||
await page.goto("http://localhost:8080");
|
||||
await page.getByRole("button", { name: "" }).click();
|
||||
await page.getByText(`Version ${expectedVersion} is available,`).click();
|
||||
|
||||
const page1 = await page.waitForEvent("popup");
|
||||
expect(page1.url()).toBe(`https://github.com/TriliumNext/Trilium/releases/tag/v${expectedVersion}`);
|
||||
});
|
||||
@@ -1,56 +0,0 @@
|
||||
{
|
||||
"main": "./electron-main.js",
|
||||
"bin": {
|
||||
"trilium": "src/main.js"
|
||||
},
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"server:start-safe": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev nodemon src/main.ts",
|
||||
"server:start-no-dir": "cross-env TRILIUM_ENV=dev nodemon src/main.ts",
|
||||
"server:start-test": "npm run server:switch && rimraf ./data-test && cross-env TRILIUM_DATA_DIR=./data-test TRILIUM_ENV=dev TRILIUM_PORT=9999 nodemon src/main.ts",
|
||||
"server:qstart": "npm run server:switch && npm run server:start",
|
||||
"server:switch": "rimraf ./node_modules/better-sqlite3 && npm install",
|
||||
"electron:start-no-dir": "cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_ENV=dev TRILIUM_PORT=37742 electron --inspect=5858 .",
|
||||
"electron:start-nix": "electron-rebuild --version 33.3.1 && cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./electron-main.ts --inspect=5858 .\"",
|
||||
"electron:start-nix-no-dir": "electron-rebuild --version 33.3.1 && cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_ENV=dev TRILIUM_PORT=37742 nix-shell -p electron_33 --run \"electron ./electron-main.ts --inspect=5858 .\"",
|
||||
"electron:start-prod-no-dir": "npm run build:prepare-dist && cross-env TRILIUM_ENV=prod electron --inspect=5858 .",
|
||||
"electron:start-prod-nix": "electron-rebuild --version 33.3.1 && npm run build:prepare-dist && cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./dist/electron-main.js --inspect=5858 .\"",
|
||||
"electron:start-prod-nix-no-dir": "electron-rebuild --version 33.3.1 && npm run build:prepare-dist && cross-env TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./dist/electron-main.js --inspect=5858 .\"",
|
||||
"electron:qstart": "npm run electron:switch && npm run electron:start",
|
||||
"electron:switch": "electron-rebuild",
|
||||
"docs:build": "typedoc",
|
||||
"test": "npm run client:test && npm run server:test",
|
||||
"client:test": "cross-env TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db TRILIUM_INTEGRATION_TEST=memory vitest --root src/public/app",
|
||||
"client:coverage": "cross-env TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db TRILIUM_INTEGRATION_TEST=memory vitest --root src/public/app --coverage",
|
||||
"test:playwright": "playwright test --workers 1",
|
||||
"test:integration-edit-db": "cross-env TRILIUM_INTEGRATION_TEST=edit TRILIUM_PORT=8081 TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db nodemon src/main.ts",
|
||||
"test:integration-mem-db": "cross-env nodemon src/main.ts",
|
||||
"test:integration-mem-db-dev": "cross-env TRILIUM_INTEGRATION_TEST=memory TRILIUM_PORT=8082 TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db nodemon src/main.ts",
|
||||
"dev:watch-dist": "tsx ./bin/watch-dist.ts",
|
||||
"dev:format-check": "eslint -c eslint.format.config.js .",
|
||||
"dev:format-fix": "eslint -c eslint.format.config.js . --fix",
|
||||
"dev:linter-check": "eslint .",
|
||||
"dev:linter-fix": "eslint . --fix",
|
||||
"chore:generate-document": "cross-env nodemon ./bin/generate_document.ts 1000",
|
||||
"chore:generate-openapi": "tsx bin/generate-openapi.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "1.57.0",
|
||||
"@stylistic/eslint-plugin": "5.6.1",
|
||||
"@types/express": "5.0.5",
|
||||
"@types/node": "24.10.1",
|
||||
"@types/yargs": "17.0.35",
|
||||
"@vitest/coverage-v8": "4.0.14",
|
||||
"eslint": "9.39.1",
|
||||
"eslint-plugin-simple-import-sort": "12.1.1",
|
||||
"esm": "3.2.25",
|
||||
"jsdoc": "4.0.5",
|
||||
"lorem-ipsum": "2.0.8",
|
||||
"rcedit": "5.0.2",
|
||||
"rimraf": "6.1.2",
|
||||
"tslib": "2.8.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"appdmg": "0.6.6"
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import etapi from "../support/etapi.js";
|
||||
/* TriliumNextTODO: port to Vitest
|
||||
etapi.describeEtapi("app_info", () => {
|
||||
it("get", async () => {
|
||||
const appInfo = await etapi.getEtapi("app-info");
|
||||
expect(appInfo.clipperProtocolVersion).toEqual("1.0");
|
||||
});
|
||||
});
|
||||
*/
|
||||
@@ -1,10 +0,0 @@
|
||||
import etapi from "../support/etapi.js";
|
||||
|
||||
/* TriliumNextTODO: port to Vitest
|
||||
etapi.describeEtapi("backup", () => {
|
||||
it("create", async () => {
|
||||
const response = await etapi.putEtapiContent("backup/etapi_test");
|
||||
expect(response.status).toEqual(204);
|
||||
});
|
||||
});
|
||||
*/
|
||||
@@ -1,26 +0,0 @@
|
||||
import etapi from "../support/etapi.js";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
/* TriliumNextTODO: port to Vitest
|
||||
etapi.describeEtapi("import", () => {
|
||||
// temporarily skip this test since test-export.zip is missing
|
||||
xit("import", async () => {
|
||||
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
const zipFileBuffer = fs.readFileSync(path.resolve(scriptDir, "test-export.zip"));
|
||||
|
||||
const response = await etapi.postEtapiContent("notes/root/import", zipFileBuffer);
|
||||
expect(response.status).toEqual(201);
|
||||
|
||||
const { note, branch } = await response.json();
|
||||
|
||||
expect(note.title).toEqual("test-export");
|
||||
expect(branch.parentNoteId).toEqual("root");
|
||||
|
||||
const content = await (await etapi.getEtapiContent(`notes/${note.noteId}/content`)).text();
|
||||
expect(content).toContain("test export content");
|
||||
});
|
||||
});
|
||||
*/
|
||||
@@ -1,103 +0,0 @@
|
||||
import crypto from "crypto";
|
||||
import etapi from "../support/etapi.js";
|
||||
|
||||
/* TriliumNextTODO: port to Vitest
|
||||
etapi.describeEtapi("notes", () => {
|
||||
it("create", async () => {
|
||||
const { note, branch } = await etapi.postEtapi("create-note", {
|
||||
parentNoteId: "root",
|
||||
type: "text",
|
||||
title: "Hello World!",
|
||||
content: "Content",
|
||||
prefix: "Custom prefix"
|
||||
});
|
||||
|
||||
expect(note.title).toEqual("Hello World!");
|
||||
expect(branch.parentNoteId).toEqual("root");
|
||||
expect(branch.prefix).toEqual("Custom prefix");
|
||||
|
||||
const rNote = await etapi.getEtapi(`notes/${note.noteId}`);
|
||||
expect(rNote.title).toEqual("Hello World!");
|
||||
|
||||
const rContent = await (await etapi.getEtapiContent(`notes/${note.noteId}/content`)).text();
|
||||
expect(rContent).toEqual("Content");
|
||||
|
||||
const rBranch = await etapi.getEtapi(`branches/${branch.branchId}`);
|
||||
expect(rBranch.parentNoteId).toEqual("root");
|
||||
expect(rBranch.prefix).toEqual("Custom prefix");
|
||||
});
|
||||
|
||||
it("patch", async () => {
|
||||
const { note } = await etapi.postEtapi("create-note", {
|
||||
parentNoteId: "root",
|
||||
type: "text",
|
||||
title: "Hello World!",
|
||||
content: "Content"
|
||||
});
|
||||
|
||||
await etapi.patchEtapi(`notes/${note.noteId}`, {
|
||||
title: "new title",
|
||||
type: "code",
|
||||
mime: "text/apl",
|
||||
dateCreated: "2000-01-01 12:34:56.999+0200",
|
||||
utcDateCreated: "2000-01-01 10:34:56.999Z"
|
||||
});
|
||||
|
||||
const rNote = await etapi.getEtapi(`notes/${note.noteId}`);
|
||||
expect(rNote.title).toEqual("new title");
|
||||
expect(rNote.type).toEqual("code");
|
||||
expect(rNote.mime).toEqual("text/apl");
|
||||
expect(rNote.dateCreated).toEqual("2000-01-01 12:34:56.999+0200");
|
||||
expect(rNote.utcDateCreated).toEqual("2000-01-01 10:34:56.999Z");
|
||||
});
|
||||
|
||||
it("update content", async () => {
|
||||
const { note } = await etapi.postEtapi("create-note", {
|
||||
parentNoteId: "root",
|
||||
type: "text",
|
||||
title: "Hello World!",
|
||||
content: "Content"
|
||||
});
|
||||
|
||||
await etapi.putEtapiContent(`notes/${note.noteId}/content`, "new content");
|
||||
|
||||
const rContent = await (await etapi.getEtapiContent(`notes/${note.noteId}/content`)).text();
|
||||
expect(rContent).toEqual("new content");
|
||||
});
|
||||
|
||||
it("create / update binary content", async () => {
|
||||
const { note } = await etapi.postEtapi("create-note", {
|
||||
parentNoteId: "root",
|
||||
type: "file",
|
||||
title: "Hello World!",
|
||||
content: "ZZZ"
|
||||
});
|
||||
|
||||
const updatedContent = crypto.randomBytes(16);
|
||||
|
||||
await etapi.putEtapiContent(`notes/${note.noteId}/content`, updatedContent);
|
||||
|
||||
const rContent = await (await etapi.getEtapiContent(`notes/${note.noteId}/content`)).arrayBuffer();
|
||||
expect(Buffer.from(new Uint8Array(rContent))).toEqual(updatedContent);
|
||||
});
|
||||
|
||||
it("delete note", async () => {
|
||||
const { note } = await etapi.postEtapi("create-note", {
|
||||
parentNoteId: "root",
|
||||
type: "text",
|
||||
title: "Hello World!",
|
||||
content: "Content"
|
||||
});
|
||||
|
||||
await etapi.deleteEtapi(`notes/${note.noteId}`);
|
||||
|
||||
const resp = await etapi.getEtapiResponse(`notes/${note.noteId}`);
|
||||
expect(resp.status).toEqual(404);
|
||||
|
||||
const error = await resp.json();
|
||||
expect(error.status).toEqual(404);
|
||||
expect(error.code).toEqual("NOTE_NOT_FOUND");
|
||||
expect(error.message).toEqual(`Note '${note.noteId}' not found.`);
|
||||
});
|
||||
});
|
||||
*/
|
||||
@@ -1,152 +0,0 @@
|
||||
import { describe, beforeAll, afterAll } from "vitest";
|
||||
|
||||
let etapiAuthToken: string | undefined;
|
||||
|
||||
const getEtapiAuthorizationHeader = (): string => "Basic " + Buffer.from(`etapi:${etapiAuthToken}`).toString("base64");
|
||||
|
||||
const PORT: string = "9999";
|
||||
const HOST: string = "http://localhost:" + PORT;
|
||||
|
||||
type SpecDefinitionsFunc = () => void;
|
||||
|
||||
function describeEtapi(description: string, specDefinitions: SpecDefinitionsFunc): void {
|
||||
describe(description, () => {
|
||||
beforeAll(async () => {});
|
||||
|
||||
afterAll(() => {});
|
||||
|
||||
specDefinitions();
|
||||
});
|
||||
}
|
||||
|
||||
async function getEtapiResponse(url: string): Promise<Response> {
|
||||
return await fetch(`${HOST}/etapi/${url}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: getEtapiAuthorizationHeader()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function getEtapi(url: string): Promise<any> {
|
||||
const response = await getEtapiResponse(url);
|
||||
return await processEtapiResponse(response);
|
||||
}
|
||||
|
||||
async function getEtapiContent(url: string): Promise<Response> {
|
||||
const response = await fetch(`${HOST}/etapi/${url}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: getEtapiAuthorizationHeader()
|
||||
}
|
||||
});
|
||||
|
||||
checkStatus(response);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
async function postEtapi(url: string, data: Record<string, unknown> = {}): Promise<any> {
|
||||
const response = await fetch(`${HOST}/etapi/${url}`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: getEtapiAuthorizationHeader()
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
return await processEtapiResponse(response);
|
||||
}
|
||||
|
||||
async function postEtapiContent(url: string, data: BodyInit): Promise<Response> {
|
||||
const response = await fetch(`${HOST}/etapi/${url}`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/octet-stream",
|
||||
Authorization: getEtapiAuthorizationHeader()
|
||||
},
|
||||
body: data
|
||||
});
|
||||
|
||||
checkStatus(response);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
async function putEtapi(url: string, data: Record<string, unknown> = {}): Promise<any> {
|
||||
const response = await fetch(`${HOST}/etapi/${url}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: getEtapiAuthorizationHeader()
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
return await processEtapiResponse(response);
|
||||
}
|
||||
|
||||
async function putEtapiContent(url: string, data?: BodyInit): Promise<Response> {
|
||||
const response = await fetch(`${HOST}/etapi/${url}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/octet-stream",
|
||||
Authorization: getEtapiAuthorizationHeader()
|
||||
},
|
||||
body: data
|
||||
});
|
||||
|
||||
checkStatus(response);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
async function patchEtapi(url: string, data: Record<string, unknown> = {}): Promise<any> {
|
||||
const response = await fetch(`${HOST}/etapi/${url}`, {
|
||||
method: "PATCH",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: getEtapiAuthorizationHeader()
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
return await processEtapiResponse(response);
|
||||
}
|
||||
|
||||
async function deleteEtapi(url: string): Promise<any> {
|
||||
const response = await fetch(`${HOST}/etapi/${url}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
Authorization: getEtapiAuthorizationHeader()
|
||||
}
|
||||
});
|
||||
return await processEtapiResponse(response);
|
||||
}
|
||||
|
||||
async function processEtapiResponse(response: Response): Promise<any> {
|
||||
const text = await response.text();
|
||||
|
||||
if (response.status < 200 || response.status >= 300) {
|
||||
throw new Error(`ETAPI error ${response.status}: ${text}`);
|
||||
}
|
||||
|
||||
return text?.trim() ? JSON.parse(text) : null;
|
||||
}
|
||||
|
||||
function checkStatus(response: Response): void {
|
||||
if (response.status < 200 || response.status >= 300) {
|
||||
throw new Error(`ETAPI error ${response.status}`);
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
describeEtapi,
|
||||
getEtapi,
|
||||
getEtapiResponse,
|
||||
getEtapiContent,
|
||||
postEtapi,
|
||||
postEtapiContent,
|
||||
putEtapi,
|
||||
putEtapiContent,
|
||||
patchEtapi,
|
||||
deleteEtapi
|
||||
};
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "NodeNext",
|
||||
"declaration": false,
|
||||
"sourceMap": true,
|
||||
"outDir": "./build",
|
||||
"strict": true,
|
||||
"noImplicitAny": true,
|
||||
"resolveJsonModule": true,
|
||||
"lib": ["ES2023"],
|
||||
"downlevelIteration": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowJs": true
|
||||
},
|
||||
"include": ["./src/public/app/**/*"],
|
||||
"files": [
|
||||
"./src/public/app/types.d.ts",
|
||||
"./src/public/app/types-lib.d.ts",
|
||||
"./src/types.d.ts"
|
||||
]
|
||||
}
|
||||
@@ -9,13 +9,13 @@
|
||||
"keywords": [],
|
||||
"author": "Elian Doran <contact@eliandoran.me>",
|
||||
"license": "AGPL-3.0-only",
|
||||
"packageManager": "pnpm@10.24.0",
|
||||
"packageManager": "pnpm@10.27.0",
|
||||
"devDependencies": {
|
||||
"@redocly/cli": "2.12.0",
|
||||
"@redocly/cli": "2.14.3",
|
||||
"archiver": "7.0.1",
|
||||
"fs-extra": "11.3.2",
|
||||
"react": "19.2.0",
|
||||
"react-dom": "19.2.0",
|
||||
"fs-extra": "11.3.3",
|
||||
"react": "19.2.3",
|
||||
"react-dom": "19.2.3",
|
||||
"typedoc": "0.28.15",
|
||||
"typedoc-plugin-missing-exports": "4.1.2"
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import baseConfig from "../../eslint.config.mjs";
|
||||
|
||||
export default [
|
||||
...baseConfig
|
||||
];
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@triliumnext/client",
|
||||
"version": "0.100.0",
|
||||
"version": "0.101.1",
|
||||
"description": "JQuery-based client for TriliumNext, used for both web and desktop (via Electron)",
|
||||
"private": true,
|
||||
"license": "AGPL-3.0-only",
|
||||
@@ -12,27 +12,29 @@
|
||||
"scripts": {
|
||||
"build": "cross-env NODE_OPTIONS=--max-old-space-size=4096 vite build",
|
||||
"test": "vitest",
|
||||
"coverage": "vitest --coverage",
|
||||
"circular-deps": "dpdm -T src/**/*.ts --tree=false --warning=false --skip-dynamic-imports=circular"
|
||||
},
|
||||
"dependencies": {
|
||||
"@eslint/js": "9.39.1",
|
||||
"@excalidraw/excalidraw": "0.18.0",
|
||||
"@fullcalendar/core": "6.1.19",
|
||||
"@fullcalendar/daygrid": "6.1.19",
|
||||
"@fullcalendar/interaction": "6.1.19",
|
||||
"@fullcalendar/list": "6.1.19",
|
||||
"@fullcalendar/multimonth": "6.1.19",
|
||||
"@fullcalendar/timegrid": "6.1.19",
|
||||
"@fullcalendar/core": "6.1.20",
|
||||
"@fullcalendar/daygrid": "6.1.20",
|
||||
"@fullcalendar/interaction": "6.1.20",
|
||||
"@fullcalendar/list": "6.1.20",
|
||||
"@fullcalendar/multimonth": "6.1.20",
|
||||
"@fullcalendar/timegrid": "6.1.20",
|
||||
"@maplibre/maplibre-gl-leaflet": "0.1.3",
|
||||
"@mermaid-js/layout-elk": "0.2.0",
|
||||
"@mind-elixir/node-menu": "5.0.1",
|
||||
"@popperjs/core": "2.11.8",
|
||||
"@preact/signals": "2.5.1",
|
||||
"@triliumnext/ckeditor5": "workspace:*",
|
||||
"@triliumnext/codemirror": "workspace:*",
|
||||
"@triliumnext/commons": "workspace:*",
|
||||
"@triliumnext/highlightjs": "workspace:*",
|
||||
"@triliumnext/share-theme": "workspace:*",
|
||||
"@triliumnext/split.js": "workspace:*",
|
||||
"@zumer/snapdom": "2.0.1",
|
||||
"autocomplete.js": "0.38.1",
|
||||
"bootstrap": "5.3.8",
|
||||
"boxicons": "2.1.4",
|
||||
@@ -41,24 +43,26 @@
|
||||
"debounce": "3.0.0",
|
||||
"draggabilly": "3.0.0",
|
||||
"force-graph": "1.51.0",
|
||||
"globals": "16.5.0",
|
||||
"i18next": "25.6.3",
|
||||
"globals": "17.0.0",
|
||||
"i18next": "25.7.3",
|
||||
"i18next-http-backend": "3.0.2",
|
||||
"jquery": "3.7.1",
|
||||
"jquery.fancytree": "2.38.5",
|
||||
"jsplumb": "2.15.6",
|
||||
"katex": "0.16.25",
|
||||
"katex": "0.16.27",
|
||||
"knockout": "3.5.1",
|
||||
"leaflet": "1.9.4",
|
||||
"leaflet-gpx": "2.2.0",
|
||||
"mark.js": "8.11.1",
|
||||
"marked": "17.0.1",
|
||||
"mermaid": "11.12.1",
|
||||
"mind-elixir": "5.3.7",
|
||||
"mermaid": "11.12.2",
|
||||
"mind-elixir": "5.4.0",
|
||||
"normalize.css": "8.0.1",
|
||||
"panzoom": "9.4.3",
|
||||
"preact": "10.27.2",
|
||||
"react-i18next": "16.3.5",
|
||||
"preact": "10.28.1",
|
||||
"react-i18next": "16.5.1",
|
||||
"react-window": "2.2.3",
|
||||
"react-zoom-pan-pinch": "3.7.0",
|
||||
"reveal.js": "5.2.1",
|
||||
"svg-pan-zoom": "3.6.2",
|
||||
"tabulator-tables": "6.3.1",
|
||||
@@ -72,8 +76,8 @@
|
||||
"@types/leaflet": "1.9.21",
|
||||
"@types/leaflet-gpx": "1.3.8",
|
||||
"@types/mark.js": "8.11.12",
|
||||
"@types/reveal.js": "5.2.1",
|
||||
"@types/tabulator-tables": "6.3.0",
|
||||
"@types/reveal.js": "5.2.2",
|
||||
"@types/tabulator-tables": "6.3.1",
|
||||
"copy-webpack-plugin": "13.0.1",
|
||||
"happy-dom": "20.0.11",
|
||||
"script-loader": "0.7.2",
|
||||
|
||||
@@ -1,39 +1,41 @@
|
||||
import froca from "../services/froca.js";
|
||||
import RootCommandExecutor from "./root_command_executor.js";
|
||||
import Entrypoints from "./entrypoints.js";
|
||||
import options from "../services/options.js";
|
||||
import utils, { hasTouchBar } from "../services/utils.js";
|
||||
import zoomComponent from "./zoom.js";
|
||||
import TabManager from "./tab_manager.js";
|
||||
import Component from "./component.js";
|
||||
import keyboardActionsService from "../services/keyboard_actions.js";
|
||||
import linkService, { type ViewScope } from "../services/link.js";
|
||||
import MobileScreenSwitcherExecutor, { type Screen } from "./mobile_screen_switcher.js";
|
||||
import MainTreeExecutors from "./main_tree_executors.js";
|
||||
import toast from "../services/toast.js";
|
||||
import ShortcutComponent from "./shortcut_component.js";
|
||||
import { t, initLocale } from "../services/i18n.js";
|
||||
import type { ResolveOptions } from "../widgets/dialogs/delete_notes.js";
|
||||
import type { PromptDialogOptions } from "../widgets/dialogs/prompt.js";
|
||||
import type { ConfirmWithMessageOptions, ConfirmWithTitleOptions } from "../widgets/dialogs/confirm.js";
|
||||
import type LoadResults from "../services/load_results.js";
|
||||
import type { Attribute } from "../services/attribute_parser.js";
|
||||
import type NoteTreeWidget from "../widgets/note_tree.js";
|
||||
import type { default as NoteContext, GetTextEditorCallback } from "./note_context.js";
|
||||
import type { NativeImage, TouchBar } from "electron";
|
||||
import TouchBarComponent from "./touch_bar.js";
|
||||
import type { CKTextEditor } from "@triliumnext/ckeditor5";
|
||||
import type CodeMirror from "@triliumnext/codemirror";
|
||||
import { StartupChecks } from "./startup_checks.js";
|
||||
import type { CreateNoteOpts } from "../services/note_create.js";
|
||||
import { ColumnComponent } from "tabulator-tables";
|
||||
import { ChooseNoteTypeCallback } from "../widgets/dialogs/note_type_chooser.jsx";
|
||||
import type RootContainer from "../widgets/containers/root_container.js";
|
||||
import { SqlExecuteResults } from "@triliumnext/commons";
|
||||
import { AddLinkOpts } from "../widgets/dialogs/add_link.jsx";
|
||||
import { IncludeNoteOpts } from "../widgets/dialogs/include_note.jsx";
|
||||
import type { NativeImage, TouchBar } from "electron";
|
||||
import { ColumnComponent } from "tabulator-tables";
|
||||
|
||||
import type { Attribute } from "../services/attribute_parser.js";
|
||||
import froca from "../services/froca.js";
|
||||
import { initLocale, t } from "../services/i18n.js";
|
||||
import keyboardActionsService from "../services/keyboard_actions.js";
|
||||
import linkService, { type ViewScope } from "../services/link.js";
|
||||
import type LoadResults from "../services/load_results.js";
|
||||
import type { CreateNoteOpts } from "../services/note_create.js";
|
||||
import options from "../services/options.js";
|
||||
import toast from "../services/toast.js";
|
||||
import utils, { hasTouchBar } from "../services/utils.js";
|
||||
import { ReactWrappedWidget } from "../widgets/basic_widget.js";
|
||||
import type RootContainer from "../widgets/containers/root_container.js";
|
||||
import { AddLinkOpts } from "../widgets/dialogs/add_link.jsx";
|
||||
import type { ConfirmWithMessageOptions, ConfirmWithTitleOptions } from "../widgets/dialogs/confirm.js";
|
||||
import type { ResolveOptions } from "../widgets/dialogs/delete_notes.js";
|
||||
import { IncludeNoteOpts } from "../widgets/dialogs/include_note.jsx";
|
||||
import type { InfoProps } from "../widgets/dialogs/info.jsx";
|
||||
import type { MarkdownImportOpts } from "../widgets/dialogs/markdown_import.jsx";
|
||||
import { ChooseNoteTypeCallback } from "../widgets/dialogs/note_type_chooser.jsx";
|
||||
import type { PromptDialogOptions } from "../widgets/dialogs/prompt.js";
|
||||
import type NoteTreeWidget from "../widgets/note_tree.js";
|
||||
import Component from "./component.js";
|
||||
import Entrypoints from "./entrypoints.js";
|
||||
import MainTreeExecutors from "./main_tree_executors.js";
|
||||
import MobileScreenSwitcherExecutor, { type Screen } from "./mobile_screen_switcher.js";
|
||||
import type { default as NoteContext, GetTextEditorCallback } from "./note_context.js";
|
||||
import RootCommandExecutor from "./root_command_executor.js";
|
||||
import ShortcutComponent from "./shortcut_component.js";
|
||||
import { StartupChecks } from "./startup_checks.js";
|
||||
import TabManager from "./tab_manager.js";
|
||||
import TouchBarComponent from "./touch_bar.js";
|
||||
import zoomComponent from "./zoom.js";
|
||||
|
||||
interface Layout {
|
||||
getRootWidget: (appContext: AppContext) => RootContainer;
|
||||
@@ -124,7 +126,7 @@ export type CommandMappings = {
|
||||
isNewNote?: boolean;
|
||||
};
|
||||
showPromptDialog: PromptDialogOptions;
|
||||
showInfoDialog: ConfirmWithMessageOptions;
|
||||
showInfoDialog: InfoProps;
|
||||
showConfirmDialog: ConfirmWithMessageOptions;
|
||||
showRecentChanges: CommandData & { ancestorNoteId: string };
|
||||
showImportDialog: CommandData & { noteId: string };
|
||||
@@ -264,7 +266,7 @@ export type CommandMappings = {
|
||||
|
||||
reEvaluateRightPaneVisibility: CommandData;
|
||||
runActiveNote: CommandData;
|
||||
scrollContainerToCommand: CommandData & {
|
||||
scrollContainerTo: CommandData & {
|
||||
position: number;
|
||||
};
|
||||
scrollToEnd: CommandData;
|
||||
@@ -380,7 +382,8 @@ export type CommandMappings = {
|
||||
reloadTextEditor: CommandData;
|
||||
chooseNoteType: CommandData & {
|
||||
callback: ChooseNoteTypeCallback
|
||||
}
|
||||
};
|
||||
customDownload: CommandData;
|
||||
};
|
||||
|
||||
type EventMappings = {
|
||||
@@ -446,6 +449,7 @@ type EventMappings = {
|
||||
};
|
||||
searchRefreshed: { ntxId?: string | null };
|
||||
textEditorRefreshed: { ntxId?: string | null, editor: CKTextEditor };
|
||||
contentElRefreshed: { ntxId?: string | null, contentEl: HTMLElement };
|
||||
hoistedNoteChanged: {
|
||||
noteId: string;
|
||||
ntxId: string | null;
|
||||
@@ -470,6 +474,11 @@ type EventMappings = {
|
||||
noteContextRemoved: {
|
||||
ntxIds: string[];
|
||||
};
|
||||
contextDataChanged: {
|
||||
noteContext: NoteContext;
|
||||
key: string;
|
||||
value: unknown;
|
||||
};
|
||||
exportSvg: { ntxId: string | null | undefined; };
|
||||
exportPng: { ntxId: string | null | undefined; };
|
||||
geoMapCreateChildNote: {
|
||||
@@ -694,10 +703,8 @@ $(window).on("beforeunload", () => {
|
||||
console.log(`Component ${component.componentId} is not finished saving its state.`);
|
||||
allSaved = false;
|
||||
}
|
||||
} else {
|
||||
if (!listener()) {
|
||||
allSaved = false;
|
||||
}
|
||||
} else if (!listener()) {
|
||||
allSaved = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -707,7 +714,7 @@ $(window).on("beforeunload", () => {
|
||||
}
|
||||
});
|
||||
|
||||
$(window).on("hashchange", function () {
|
||||
$(window).on("hashchange", () => {
|
||||
const { notePath, ntxId, viewScope, searchString } = linkService.parseNavigationStateFromUrl(window.location.href);
|
||||
|
||||
if (notePath || ntxId) {
|
||||
|
||||
@@ -57,6 +57,18 @@ export class TypedComponent<ChildT extends TypedComponent<ChildT>> {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a child component from this component's children array.
|
||||
* This is used for cleanup when a widget is unmounted to prevent event listener accumulation.
|
||||
*/
|
||||
removeChild(component: ChildT) {
|
||||
const index = this.children.indexOf(component);
|
||||
if (index !== -1) {
|
||||
this.children.splice(index, 1);
|
||||
component.parent = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
handleEvent<T extends EventNames>(name: T, data: EventData<T>): Promise<unknown[] | unknown> | null | undefined {
|
||||
try {
|
||||
const callMethodPromise = this.initialized ? this.initialized.then(() => this.callMethod((this as any)[`${name}Event`], data)) : this.callMethod((this as any)[`${name}Event`], data);
|
||||
@@ -65,8 +77,8 @@ export class TypedComponent<ChildT extends TypedComponent<ChildT>> {
|
||||
|
||||
// don't create promises if not needed (optimization)
|
||||
return callMethodPromise && childrenPromise ? Promise.all([callMethodPromise, childrenPromise]) : callMethodPromise || childrenPromise;
|
||||
} catch (e: any) {
|
||||
console.error(`Handling of event '${name}' failed in ${this.constructor.name} with error ${e.message} ${e.stack}`);
|
||||
} catch (e: unknown) {
|
||||
console.error(`Handling of event '${name}' failed in ${this.constructor.name} with error`, e);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
import protectedSessionHolder from "../services/protected_session_holder.js";
|
||||
import server from "../services/server.js";
|
||||
import utils from "../services/utils.js";
|
||||
import appContext, { type EventData, type EventListener } from "./app_context.js";
|
||||
import treeService from "../services/tree.js";
|
||||
import Component from "./component.js";
|
||||
import froca from "../services/froca.js";
|
||||
import hoistedNoteService from "../services/hoisted_note.js";
|
||||
import options from "../services/options.js";
|
||||
import type { ViewScope } from "../services/link.js";
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import type { CKTextEditor } from "@triliumnext/ckeditor5";
|
||||
import type CodeMirror from "@triliumnext/codemirror";
|
||||
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import { closeActiveDialog } from "../services/dialog.js";
|
||||
import froca from "../services/froca.js";
|
||||
import hoistedNoteService from "../services/hoisted_note.js";
|
||||
import type { ViewScope } from "../services/link.js";
|
||||
import options from "../services/options.js";
|
||||
import protectedSessionHolder from "../services/protected_session_holder.js";
|
||||
import server from "../services/server.js";
|
||||
import treeService from "../services/tree.js";
|
||||
import utils from "../services/utils.js";
|
||||
import { ReactWrappedWidget } from "../widgets/basic_widget.js";
|
||||
import type { HeadingContext } from "../widgets/sidebar/TableOfContents.js";
|
||||
import appContext, { type EventData, type EventListener } from "./app_context.js";
|
||||
import Component from "./component.js";
|
||||
|
||||
export interface SetNoteOpts {
|
||||
triggerSwitchEvent?: unknown;
|
||||
@@ -21,6 +23,31 @@ export interface SetNoteOpts {
|
||||
|
||||
export type GetTextEditorCallback = (editor: CKTextEditor) => void;
|
||||
|
||||
export type SaveState = "saved" | "saving" | "unsaved" | "error";
|
||||
|
||||
export interface NoteContextDataMap {
|
||||
toc: HeadingContext;
|
||||
pdfPages: {
|
||||
totalPages: number;
|
||||
currentPage: number;
|
||||
scrollToPage(page: number): void;
|
||||
requestThumbnail(page: number): void;
|
||||
};
|
||||
pdfAttachments: {
|
||||
attachments: PdfAttachment[];
|
||||
downloadAttachment(filename: string): void;
|
||||
};
|
||||
pdfLayers: {
|
||||
layers: PdfLayer[];
|
||||
toggleLayer(layerId: string, visible: boolean): void;
|
||||
};
|
||||
saveState: {
|
||||
state: SaveState;
|
||||
};
|
||||
}
|
||||
|
||||
type ContextDataKey = keyof NoteContextDataMap;
|
||||
|
||||
class NoteContext extends Component implements EventListener<"entitiesReloaded"> {
|
||||
ntxId: string | null;
|
||||
hoistedNoteId: string;
|
||||
@@ -31,6 +58,13 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
|
||||
parentNoteId?: string | null;
|
||||
viewScope?: ViewScope;
|
||||
|
||||
/**
|
||||
* Metadata storage for UI components (e.g., table of contents, PDF page list, code outline).
|
||||
* This allows type widgets to publish data that sidebar/toolbar components can consume.
|
||||
* Data is automatically cleared when navigating to a different note.
|
||||
*/
|
||||
private contextData: Map<string, unknown> = new Map();
|
||||
|
||||
constructor(ntxId: string | null = null, hoistedNoteId: string = "root", mainNtxId: string | null = null) {
|
||||
super();
|
||||
|
||||
@@ -90,6 +124,22 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
|
||||
this.viewScope = opts.viewScope;
|
||||
({ noteId: this.noteId, parentNoteId: this.parentNoteId } = treeService.getNoteIdAndParentIdFromUrl(resolvedNotePath));
|
||||
|
||||
// Clear context data when switching notes and notify subscribers
|
||||
const oldKeys = Array.from(this.contextData.keys());
|
||||
this.contextData.clear();
|
||||
if (oldKeys.length > 0) {
|
||||
// Notify subscribers asynchronously to avoid blocking navigation
|
||||
window.setTimeout(() => {
|
||||
for (const key of oldKeys) {
|
||||
this.triggerEvent("contextDataChanged", {
|
||||
noteContext: this,
|
||||
key,
|
||||
value: undefined
|
||||
});
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
|
||||
this.saveToRecentNotes(resolvedNotePath);
|
||||
|
||||
protectedSessionHolder.touchProtectedSessionIfNecessary(this.note);
|
||||
@@ -389,7 +439,7 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
|
||||
* If no content could be determined `null` is returned instead.
|
||||
*/
|
||||
async getContentElement() {
|
||||
return this.timeout<JQuery<HTMLElement>>(
|
||||
return this.timeout<JQuery<HTMLElement> | null>(
|
||||
new Promise((resolve) =>
|
||||
appContext.triggerCommand("executeWithContentElement", {
|
||||
resolve,
|
||||
@@ -442,6 +492,52 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
|
||||
|
||||
return title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set metadata for this note context (e.g., table of contents, PDF pages, code outline).
|
||||
* This data can be consumed by sidebar/toolbar components.
|
||||
*
|
||||
* @param key - Unique identifier for the data type (e.g., "toc", "pdfPages", "codeOutline")
|
||||
* @param value - The data to store (will be cleared when switching notes)
|
||||
*/
|
||||
setContextData<K extends ContextDataKey>(key: K, value: NoteContextDataMap[K]): void {
|
||||
this.contextData.set(key, value);
|
||||
// Trigger event so subscribers can react
|
||||
this.triggerEvent("contextDataChanged", {
|
||||
noteContext: this,
|
||||
key,
|
||||
value
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get metadata for this note context.
|
||||
*
|
||||
* @param key - The data key to retrieve
|
||||
* @returns The stored data, or undefined if not found
|
||||
*/
|
||||
getContextData<K extends ContextDataKey>(key: K): NoteContextDataMap[K] | undefined {
|
||||
return this.contextData.get(key) as NoteContextDataMap[K] | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if context data exists for a given key.
|
||||
*/
|
||||
hasContextData(key: ContextDataKey): boolean {
|
||||
return this.contextData.has(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear specific context data.
|
||||
*/
|
||||
clearContextData(key: ContextDataKey): void {
|
||||
this.contextData.delete(key);
|
||||
this.triggerEvent("contextDataChanged", {
|
||||
noteContext: this,
|
||||
key,
|
||||
value: undefined
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function openInCurrentNoteContext(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent | React.PointerEvent<HTMLCanvasElement> | null, notePath: string, viewScope?: ViewScope) {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import Component from "./component.js";
|
||||
import appContext, { type CommandData, type CommandListenerData } from "./app_context.js";
|
||||
import dateNoteService from "../services/date_notes.js";
|
||||
import treeService from "../services/tree.js";
|
||||
import openService from "../services/open.js";
|
||||
import protectedSessionService from "../services/protected_session.js";
|
||||
import options from "../services/options.js";
|
||||
import froca from "../services/froca.js";
|
||||
import utils from "../services/utils.js";
|
||||
import toastService from "../services/toast.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";
|
||||
import Component from "./component.js";
|
||||
|
||||
export default class RootCommandExecutor extends Component {
|
||||
editReadOnlyNoteCommand() {
|
||||
@@ -193,6 +193,19 @@ export default class RootCommandExecutor extends Component {
|
||||
appContext.triggerEvent("zenModeChanged", { isEnabled });
|
||||
}
|
||||
|
||||
async toggleRibbonTabNoteMapCommand(data: CommandListenerData<"toggleRibbonTabNoteMap">) {
|
||||
const { isExperimentalFeatureEnabled } = await import("../services/experimental_features.js");
|
||||
const isNewLayout = isExperimentalFeatureEnabled("new-layout");
|
||||
if (!isNewLayout) {
|
||||
this.triggerEvent("toggleRibbonTabNoteMap", data);
|
||||
return;
|
||||
}
|
||||
|
||||
const activeContext = appContext.tabManager.getActiveContext();
|
||||
if (!activeContext?.notePath) return;
|
||||
openInReusableSplit(activeContext.notePath, "note-map");
|
||||
}
|
||||
|
||||
firstTabCommand() {
|
||||
this.#goToTab(1);
|
||||
}
|
||||
@@ -262,7 +275,7 @@ export default class RootCommandExecutor extends Component {
|
||||
}
|
||||
catch (e) {
|
||||
console.error("Error creating AI Chat note:", e);
|
||||
toastService.showError("Failed to create AI Chat note: " + (e as Error).message);
|
||||
toastService.showError(`Failed to create AI Chat note: ${(e as Error).message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import appContext from "./components/app_context.js";
|
||||
import utils from "./services/utils.js";
|
||||
import noteTooltipService from "./services/note_tooltip.js";
|
||||
import bundleService from "./services/bundle.js";
|
||||
import toastService from "./services/toast.js";
|
||||
import noteAutocompleteService from "./services/note_autocomplete.js";
|
||||
import electronContextMenu from "./menus/electron_context_menu.js";
|
||||
import glob from "./services/glob.js";
|
||||
import { t } from "./services/i18n.js";
|
||||
import options from "./services/options.js";
|
||||
import "autocomplete.js/index_jquery.js";
|
||||
|
||||
import type ElectronRemote from "@electron/remote";
|
||||
import type Electron from "electron";
|
||||
import "boxicons/css/boxicons.min.css";
|
||||
import "autocomplete.js/index_jquery.js";
|
||||
|
||||
import appContext from "./components/app_context.js";
|
||||
import electronContextMenu from "./menus/electron_context_menu.js";
|
||||
import bundleService from "./services/bundle.js";
|
||||
import glob from "./services/glob.js";
|
||||
import { t } from "./services/i18n.js";
|
||||
import noteAutocompleteService from "./services/note_autocomplete.js";
|
||||
import noteTooltipService from "./services/note_tooltip.js";
|
||||
import options from "./services/options.js";
|
||||
import toastService from "./services/toast.js";
|
||||
import utils from "./services/utils.js";
|
||||
|
||||
await appContext.earlyInit();
|
||||
|
||||
@@ -22,6 +23,7 @@ bundleService.getWidgetBundlesByParent().then(async (widgetBundles) => {
|
||||
appContext.setLayout(new DesktopLayout(widgetBundles));
|
||||
appContext.start().catch((e) => {
|
||||
toastService.showPersistent({
|
||||
id: "critical-error",
|
||||
title: t("toast.critical-error.title"),
|
||||
icon: "alert",
|
||||
message: t("toast.critical-error.message", { message: e.message })
|
||||
@@ -63,6 +65,9 @@ function initOnElectron() {
|
||||
if (options.get("nativeTitleBarVisible") !== "true") {
|
||||
initTitleBarButtons(style, currentWindow);
|
||||
}
|
||||
|
||||
// Clear navigation history on frontend refresh.
|
||||
currentWindow.webContents.navigationHistory.clear();
|
||||
}
|
||||
|
||||
function initTitleBarButtons(style: CSSStyleDeclaration, currentWindow: Electron.BrowserWindow) {
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
import server from "../services/server.js";
|
||||
import noteAttributeCache from "../services/note_attribute_cache.js";
|
||||
import protectedSessionHolder from "../services/protected_session_holder.js";
|
||||
import { MIME_TYPES_DICT } from "@triliumnext/commons";
|
||||
|
||||
import cssClassManager from "../services/css_class_manager.js";
|
||||
import type { Froca } from "../services/froca-interface.js";
|
||||
import type FAttachment from "./fattachment.js";
|
||||
import type { default as FAttribute, AttributeType } from "./fattribute.js";
|
||||
import utils from "../services/utils.js";
|
||||
import noteAttributeCache from "../services/note_attribute_cache.js";
|
||||
import protectedSessionHolder from "../services/protected_session_holder.js";
|
||||
import search from "../services/search.js";
|
||||
import server from "../services/server.js";
|
||||
import utils from "../services/utils.js";
|
||||
import type FAttachment from "./fattachment.js";
|
||||
import type { AttributeType, default as FAttribute } from "./fattribute.js";
|
||||
|
||||
const LABEL = "label";
|
||||
const RELATION = "relation";
|
||||
|
||||
const NOTE_TYPE_ICONS = {
|
||||
export const NOTE_TYPE_ICONS = {
|
||||
file: "bx bx-file",
|
||||
image: "bx bx-image",
|
||||
code: "bx bx-code",
|
||||
@@ -268,13 +270,12 @@ export default class FNote {
|
||||
}
|
||||
}
|
||||
return results;
|
||||
} else {
|
||||
return this.children;
|
||||
}
|
||||
return this.children;
|
||||
}
|
||||
|
||||
async getSubtreeNoteIds(includeArchived = false) {
|
||||
let noteIds: (string | string[])[] = [];
|
||||
const noteIds: (string | string[])[] = [];
|
||||
for (const child of await this.getChildNotes()) {
|
||||
if (child.isArchived && !includeArchived) continue;
|
||||
|
||||
@@ -471,9 +472,8 @@ export default class FNote {
|
||||
return a.isHidden ? 1 : -1;
|
||||
} else if (a.isSearch !== b.isSearch) {
|
||||
return a.isSearch ? 1 : -1;
|
||||
} else {
|
||||
return a.notePath.length - b.notePath.length;
|
||||
}
|
||||
return a.notePath.length - b.notePath.length;
|
||||
});
|
||||
|
||||
return notePaths;
|
||||
@@ -582,6 +582,10 @@ export default class FNote {
|
||||
}
|
||||
|
||||
getIcon() {
|
||||
return `tn-icon ${this.#getIconInternal()}`;
|
||||
}
|
||||
|
||||
#getIconInternal() {
|
||||
const iconClassLabels = this.getLabels("iconClass");
|
||||
const workspaceIconClass = this.getWorkspaceIconClass();
|
||||
|
||||
@@ -597,14 +601,13 @@ export default class FNote {
|
||||
} else if (this.type === "text") {
|
||||
if (this.isFolder()) {
|
||||
return "bx bx-folder";
|
||||
} else {
|
||||
return "bx bx-note";
|
||||
}
|
||||
} else if (this.type === "code" && this.mime.startsWith("text/x-sql")) {
|
||||
return "bx bx-data";
|
||||
} else {
|
||||
return NOTE_TYPE_ICONS[this.type];
|
||||
return "bx bx-note";
|
||||
} else if (this.type === "code") {
|
||||
const correspondingMimeType = MIME_TYPES_DICT.find(m => m.mime === this.mime);
|
||||
return correspondingMimeType?.icon ?? NOTE_TYPE_ICONS.code;
|
||||
}
|
||||
return NOTE_TYPE_ICONS[this.type];
|
||||
}
|
||||
|
||||
getColorClass() {
|
||||
@@ -617,7 +620,7 @@ export default class FNote {
|
||||
}
|
||||
|
||||
getFilteredChildBranches() {
|
||||
let childBranches = this.getChildBranches();
|
||||
const childBranches = this.getChildBranches();
|
||||
|
||||
if (!childBranches) {
|
||||
console.error(`No children for '${this.noteId}'. This shouldn't happen.`);
|
||||
@@ -811,9 +814,9 @@ export default class FNote {
|
||||
return this.getLabelValue(nameWithPrefix.substring(1));
|
||||
} else if (nameWithPrefix.startsWith("~")) {
|
||||
return this.getRelationValue(nameWithPrefix.substring(1));
|
||||
} else {
|
||||
return this.getLabelValue(nameWithPrefix);
|
||||
}
|
||||
return this.getLabelValue(nameWithPrefix);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -878,10 +881,10 @@ export default class FNote {
|
||||
promotedAttrs.sort((a, b) => {
|
||||
if (a.noteId === b.noteId) {
|
||||
return a.position < b.position ? -1 : 1;
|
||||
} else {
|
||||
// inherited promoted attributes should stay grouped: https://github.com/zadam/trilium/issues/3761
|
||||
return a.noteId < b.noteId ? -1 : 1;
|
||||
}
|
||||
// inherited promoted attributes should stay grouped: https://github.com/zadam/trilium/issues/3761
|
||||
return a.noteId < b.noteId ? -1 : 1;
|
||||
|
||||
});
|
||||
|
||||
return promotedAttrs;
|
||||
@@ -993,6 +996,10 @@ export default class FNote {
|
||||
);
|
||||
}
|
||||
|
||||
isJsx() {
|
||||
return (this.type === "code" && this.mime === "text/jsx");
|
||||
}
|
||||
|
||||
/** @returns true if this note is HTML */
|
||||
isHtml() {
|
||||
return (this.type === "code" || this.type === "file" || this.type === "render") && this.mime === "text/html";
|
||||
@@ -1000,7 +1007,7 @@ export default class FNote {
|
||||
|
||||
/** @returns JS script environment - either "frontend" or "backend" */
|
||||
getScriptEnv() {
|
||||
if (this.isHtml() || (this.isJavaScript() && this.mime.endsWith("env=frontend"))) {
|
||||
if (this.isHtml() || (this.isJavaScript() && this.mime.endsWith("env=frontend")) || this.isJsx()) {
|
||||
return "frontend";
|
||||
}
|
||||
|
||||
@@ -1022,7 +1029,7 @@ export default class FNote {
|
||||
* @returns a promise that resolves when the script has been run. Additionally, for front-end notes, the promise will contain the value that is returned by the script.
|
||||
*/
|
||||
async executeScript() {
|
||||
if (!this.isJavaScript()) {
|
||||
if (!(this.isJavaScript() || this.isJsx())) {
|
||||
throw new Error(`Note ${this.noteId} is of type ${this.type} and mime ${this.mime} and thus cannot be executed`);
|
||||
}
|
||||
|
||||
|
||||
BIN
apps/client/src/fonts/boxicons.woff2
Normal file
BIN
apps/client/src/fonts/boxicons.woff2
Normal file
Binary file not shown.
@@ -1,50 +1,59 @@
|
||||
import { applyModals } from "./layout_commons.js";
|
||||
import { DESKTOP_FLOATING_BUTTONS } from "../widgets/FloatingButtonsDefinitions.jsx";
|
||||
import type { AppContext } from "../components/app_context.js";
|
||||
import type { WidgetsByParent } from "../services/bundle.js";
|
||||
import { isExperimentalFeatureEnabled } from "../services/experimental_features.js";
|
||||
import options from "../services/options.js";
|
||||
import utils from "../services/utils.js";
|
||||
import ApiLog from "../widgets/api_log.jsx";
|
||||
import ClosePaneButton from "../widgets/buttons/close_pane_button.js";
|
||||
import CloseZenModeButton from "../widgets/close_zen_button.jsx";
|
||||
import ContentHeader from "../widgets/containers/content_header.js";
|
||||
import CreatePaneButton from "../widgets/buttons/create_pane_button.js";
|
||||
import FindWidget from "../widgets/find.js";
|
||||
import FlexContainer from "../widgets/containers/flex_container.js";
|
||||
import FloatingButtons from "../widgets/FloatingButtons.jsx";
|
||||
import GlobalMenu from "../widgets/buttons/global_menu.jsx";
|
||||
import HighlightsListWidget from "../widgets/highlights_list.js";
|
||||
import LauncherContainer from "../widgets/containers/launcher_container.js";
|
||||
import LeftPaneContainer from "../widgets/containers/left_pane_container.js";
|
||||
import LeftPaneToggle from "../widgets/buttons/left_pane_toggle.js";
|
||||
import MovePaneButton from "../widgets/buttons/move_pane_button.js";
|
||||
import NoteIconWidget from "../widgets/note_icon.jsx";
|
||||
import RightPaneToggle from "../widgets/buttons/right_pane_toggle.jsx";
|
||||
import CloseZenModeButton from "../widgets/close_zen_button.jsx";
|
||||
import NoteList from "../widgets/collections/NoteList.jsx";
|
||||
import NoteTitleWidget from "../widgets/note_title.jsx";
|
||||
import NoteTreeWidget from "../widgets/note_tree.js";
|
||||
import NoteWrapperWidget from "../widgets/note_wrapper.js";
|
||||
import options from "../services/options.js";
|
||||
import PasswordNoteSetDialog from "../widgets/dialogs/password_not_set.js";
|
||||
import QuickSearchWidget from "../widgets/quick_search.js";
|
||||
import ReadOnlyNoteInfoBar from "../widgets/ReadOnlyNoteInfoBar.jsx";
|
||||
import Ribbon from "../widgets/ribbon/Ribbon.jsx";
|
||||
import ContentHeader from "../widgets/containers/content_header.js";
|
||||
import FlexContainer from "../widgets/containers/flex_container.js";
|
||||
import LeftPaneContainer from "../widgets/containers/left_pane_container.js";
|
||||
import RightPaneContainer from "../widgets/containers/right_pane_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 PasswordNoteSetDialog from "../widgets/dialogs/password_not_set.js";
|
||||
import UploadAttachmentsDialog from "../widgets/dialogs/upload_attachments.js";
|
||||
import FindWidget from "../widgets/find.js";
|
||||
import FloatingButtons from "../widgets/FloatingButtons.jsx";
|
||||
import { DESKTOP_FLOATING_BUTTONS } from "../widgets/FloatingButtonsDefinitions.jsx";
|
||||
import HighlightsListWidget from "../widgets/highlights_list.js";
|
||||
import LauncherContainer from "../widgets/launch_bar/LauncherContainer.jsx";
|
||||
import SpacerWidget from "../widgets/launch_bar/SpacerWidget.jsx";
|
||||
import InlineTitle from "../widgets/layout/InlineTitle.jsx";
|
||||
import NoteBadges from "../widgets/layout/NoteBadges.jsx";
|
||||
import NoteTitleActions from "../widgets/layout/NoteTitleActions.jsx";
|
||||
import StatusBar from "../widgets/layout/StatusBar.jsx";
|
||||
import NoteIconWidget from "../widgets/note_icon.jsx";
|
||||
import NoteTitleWidget from "../widgets/note_title.jsx";
|
||||
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 ReadOnlyNoteInfoBar from "../widgets/ReadOnlyNoteInfoBar.jsx";
|
||||
import { FixedFormattingToolbar } from "../widgets/ribbon/FormattingToolbar.jsx";
|
||||
import NoteActions from "../widgets/ribbon/NoteActions.jsx";
|
||||
import Ribbon from "../widgets/ribbon/Ribbon.jsx";
|
||||
import ScrollPadding from "../widgets/scroll_padding.js";
|
||||
import SearchResult from "../widgets/search_result.jsx";
|
||||
import SharedInfo from "../widgets/shared_info.jsx";
|
||||
import SpacerWidget from "../widgets/spacer.js";
|
||||
import SplitNoteContainer from "../widgets/containers/split_note_container.js";
|
||||
import RightPanelContainer from "../widgets/sidebar/RightPanelContainer.jsx";
|
||||
import SqlResults from "../widgets/sql_result.js";
|
||||
import SqlTableSchemas from "../widgets/sql_table_schemas.js";
|
||||
import TabRowWidget from "../widgets/tab_row.js";
|
||||
import TabHistoryNavigationButtons from "../widgets/TabHistoryNavigationButtons.jsx";
|
||||
import TitleBarButtons from "../widgets/title_bar_buttons.jsx";
|
||||
import TocWidget from "../widgets/toc.js";
|
||||
import type { AppContext } from "../components/app_context.js";
|
||||
import type { WidgetsByParent } from "../services/bundle.js";
|
||||
import UploadAttachmentsDialog from "../widgets/dialogs/upload_attachments.js";
|
||||
import utils from "../services/utils.js";
|
||||
import WatchedFileUpdateStatusWidget from "../widgets/watched_file_update_status.js";
|
||||
import NoteDetail from "../widgets/NoteDetail.jsx";
|
||||
import RightPanelWidget from "../widgets/sidebar/RightPanelWidget.jsx";
|
||||
import PromotedAttributes from "../widgets/PromotedAttributes.jsx";
|
||||
import { applyModals } from "./layout_commons.js";
|
||||
|
||||
export default class DesktopLayout {
|
||||
|
||||
@@ -70,17 +79,20 @@ export default class DesktopLayout {
|
||||
*/
|
||||
const fullWidthTabBar = launcherPaneIsHorizontal || (isElectron && !hasNativeTitleBar && isMac);
|
||||
const customTitleBarButtons = !hasNativeTitleBar && !isMac && !isWindows;
|
||||
const isNewLayout = isExperimentalFeatureEnabled("new-layout");
|
||||
|
||||
const rootContainer = new RootContainer(true)
|
||||
.setParent(appContext)
|
||||
.class((launcherPaneIsHorizontal ? "horizontal" : "vertical") + "-layout")
|
||||
.class(`${launcherPaneIsHorizontal ? "horizontal" : "vertical" }-layout`)
|
||||
.optChild(
|
||||
fullWidthTabBar,
|
||||
new FlexContainer("row")
|
||||
.class("tab-row-container")
|
||||
.child(new FlexContainer("row").id("tab-row-left-spacer"))
|
||||
.optChild(launcherPaneIsHorizontal, <LeftPaneToggle isHorizontalLayout={true} />)
|
||||
.child(<TabHistoryNavigationButtons />)
|
||||
.child(new TabRowWidget().class("full-width"))
|
||||
.optChild(isNewLayout, <RightPaneToggle />)
|
||||
.optChild(customTitleBarButtons, <TitleBarButtons />)
|
||||
.css("height", "40px")
|
||||
.css("background-color", "var(--launcher-pane-background-color)")
|
||||
@@ -102,7 +114,17 @@ export default class DesktopLayout {
|
||||
new FlexContainer("column")
|
||||
.id("rest-pane")
|
||||
.css("flex-grow", "1")
|
||||
.optChild(!fullWidthTabBar, new FlexContainer("row").child(new TabRowWidget()).optChild(customTitleBarButtons, <TitleBarButtons />).css("height", "40px"))
|
||||
.optChild(!fullWidthTabBar,
|
||||
new FlexContainer("row")
|
||||
.class("tab-row-container")
|
||||
.child(<TabHistoryNavigationButtons />)
|
||||
.child(new TabRowWidget())
|
||||
.optChild(isNewLayout, <RightPaneToggle />)
|
||||
.optChild(customTitleBarButtons, <TitleBarButtons />)
|
||||
.css("height", "40px")
|
||||
.css("align-items", "center")
|
||||
)
|
||||
.optChild(isNewLayout, <FixedFormattingToolbar />)
|
||||
.child(
|
||||
new FlexContainer("row")
|
||||
.filling()
|
||||
@@ -116,32 +138,31 @@ export default class DesktopLayout {
|
||||
.child(
|
||||
new SplitNoteContainer(() =>
|
||||
new NoteWrapperWidget()
|
||||
.child(
|
||||
new FlexContainer("row")
|
||||
.class("title-row")
|
||||
.css("height", "50px")
|
||||
.css("min-height", "50px")
|
||||
.css("align-items", "center")
|
||||
.cssBlock(".title-row > * { margin: 5px; }")
|
||||
.child(<NoteIconWidget />)
|
||||
.child(<NoteTitleWidget />)
|
||||
.child(new SpacerWidget(0, 1))
|
||||
.child(<MovePaneButton direction="left" />)
|
||||
.child(<MovePaneButton direction="right" />)
|
||||
.child(<ClosePaneButton />)
|
||||
.child(<CreatePaneButton />)
|
||||
)
|
||||
.child(<Ribbon />)
|
||||
.child(new FlexContainer("row")
|
||||
.class("title-row note-split-title")
|
||||
.cssBlock(".title-row > * { margin: 5px; }")
|
||||
.child(<NoteIconWidget />)
|
||||
.child(<NoteTitleWidget />)
|
||||
.optChild(isNewLayout, <NoteBadges />)
|
||||
.child(<SpacerWidget baseSize={0} growthFactor={1} />)
|
||||
.optChild(!isNewLayout, <MovePaneButton direction="left" />)
|
||||
.optChild(!isNewLayout, <MovePaneButton direction="right" />)
|
||||
.optChild(!isNewLayout, <ClosePaneButton />)
|
||||
.optChild(!isNewLayout, <CreatePaneButton />)
|
||||
.optChild(isNewLayout, <NoteActions />))
|
||||
.optChild(!isNewLayout, <Ribbon />)
|
||||
.child(new WatchedFileUpdateStatusWidget())
|
||||
.child(<FloatingButtons items={DESKTOP_FLOATING_BUTTONS} />)
|
||||
.optChild(!isNewLayout, <FloatingButtons items={DESKTOP_FLOATING_BUTTONS} />)
|
||||
.child(
|
||||
new ScrollingContainer()
|
||||
.filling()
|
||||
.child(new ContentHeader()
|
||||
.optChild(isNewLayout, <InlineTitle />)
|
||||
.optChild(isNewLayout, <NoteTitleActions />)
|
||||
.optChild(!isNewLayout, new ContentHeader()
|
||||
.child(<ReadOnlyNoteInfoBar />)
|
||||
.child(<SharedInfo />)
|
||||
)
|
||||
.child(<PromotedAttributes />)
|
||||
.optChild(!isNewLayout, <PromotedAttributes />)
|
||||
.child(<SqlTableSchemas />)
|
||||
.child(<NoteDetail />)
|
||||
.child(<NoteList media="screen" />)
|
||||
@@ -151,23 +172,24 @@ export default class DesktopLayout {
|
||||
)
|
||||
.child(<ApiLog />)
|
||||
.child(new FindWidget())
|
||||
.child(
|
||||
...this.customWidgets.get("node-detail-pane"), // typo, let's keep it for a while as BC
|
||||
...this.customWidgets.get("note-detail-pane")
|
||||
)
|
||||
.child(...this.customWidgets.get("note-detail-pane"))
|
||||
)
|
||||
)
|
||||
.child(...this.customWidgets.get("center-pane"))
|
||||
|
||||
)
|
||||
.child(
|
||||
.optChild(!isNewLayout,
|
||||
new RightPaneContainer()
|
||||
.child(new TocWidget())
|
||||
.child(new HighlightsListWidget())
|
||||
.child(...this.customWidgets.get("right-pane"))
|
||||
)
|
||||
.optChild(isNewLayout, <RightPanelContainer widgetsByParent={this.customWidgets} />)
|
||||
)
|
||||
.optChild(!launcherPaneIsHorizontal && isNewLayout, <StatusBar />)
|
||||
)
|
||||
)
|
||||
.optChild(launcherPaneIsHorizontal && isNewLayout, <StatusBar />)
|
||||
.child(<CloseZenModeButton />)
|
||||
|
||||
// Desktop-specific dialogs.
|
||||
@@ -185,14 +207,14 @@ export default class DesktopLayout {
|
||||
launcherPane = new FlexContainer("row")
|
||||
.css("height", "53px")
|
||||
.class("horizontal")
|
||||
.child(new LauncherContainer(true))
|
||||
.child(<LauncherContainer isHorizontalLayout={true} />)
|
||||
.child(<GlobalMenu isHorizontalLayout={true} />);
|
||||
} else {
|
||||
launcherPane = new FlexContainer("column")
|
||||
.css("width", "53px")
|
||||
.class("vertical")
|
||||
.child(<GlobalMenu isHorizontalLayout={false} />)
|
||||
.child(new LauncherContainer(false))
|
||||
.child(<LauncherContainer isHorizontalLayout={false} />)
|
||||
.child(<LeftPaneToggle isHorizontalLayout={false} />);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import InfoDialog from "../widgets/dialogs/info.js";
|
||||
import IncorrectCpuArchDialog from "../widgets/dialogs/incorrect_cpu_arch.js";
|
||||
import CallToActionDialog from "../widgets/dialogs/call_to_action.jsx";
|
||||
import PopupEditorDialog from "../widgets/dialogs/PopupEditor.jsx";
|
||||
import ToastContainer from "../widgets/Toast.jsx";
|
||||
|
||||
export function applyModals(rootContainer: RootContainer) {
|
||||
rootContainer
|
||||
@@ -50,5 +51,6 @@ export function applyModals(rootContainer: RootContainer) {
|
||||
.child(<PromptDialog />)
|
||||
.child(<IncorrectCpuArchDialog />)
|
||||
.child(<PopupEditorDialog />)
|
||||
.child(<CallToActionDialog />);
|
||||
.child(<CallToActionDialog />)
|
||||
.child(<ToastContainer />);
|
||||
}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
import { applyModals } from "./layout_commons.js";
|
||||
import { MOBILE_FLOATING_BUTTONS } from "../widgets/FloatingButtonsDefinitions.jsx";
|
||||
import { useNoteContext } from "../widgets/react/hooks.jsx";
|
||||
import CloseZenModeButton from "../widgets/close_zen_button.js";
|
||||
import FilePropertiesTab from "../widgets/ribbon/FilePropertiesTab.jsx";
|
||||
import FlexContainer from "../widgets/containers/flex_container.js";
|
||||
import FloatingButtons from "../widgets/FloatingButtons.jsx";
|
||||
import type AppContext from "../components/app_context.js";
|
||||
import GlobalMenuWidget from "../widgets/buttons/global_menu.js";
|
||||
import LauncherContainer from "../widgets/containers/launcher_container.js";
|
||||
import MobileDetailMenu from "../widgets/mobile_widgets/mobile_detail_menu.js";
|
||||
import CloseZenModeButton from "../widgets/close_zen_button.js";
|
||||
import NoteList from "../widgets/collections/NoteList.jsx";
|
||||
import NoteTitleWidget from "../widgets/note_title.js";
|
||||
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 LauncherContainer from "../widgets/launch_bar/LauncherContainer.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 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 RootContainer from "../widgets/containers/root_container.js";
|
||||
import ScreenContainer from "../widgets/mobile_widgets/screen_container.js";
|
||||
import ScrollingContainer from "../widgets/containers/scrolling_container.js";
|
||||
import StandaloneRibbonAdapter from "../widgets/ribbon/components/StandaloneRibbonAdapter.jsx";
|
||||
import FilePropertiesTab from "../widgets/ribbon/FilePropertiesTab.jsx";
|
||||
import SearchDefinitionTab from "../widgets/ribbon/SearchDefinitionTab.jsx";
|
||||
import SearchResult from "../widgets/search_result.jsx";
|
||||
import SharedInfoWidget from "../widgets/shared_info.js";
|
||||
import SidebarContainer from "../widgets/mobile_widgets/sidebar_container.js";
|
||||
import StandaloneRibbonAdapter from "../widgets/ribbon/components/StandaloneRibbonAdapter.jsx";
|
||||
import TabRowWidget from "../widgets/tab_row.js";
|
||||
import ToggleSidebarButton from "../widgets/mobile_widgets/toggle_sidebar_button.jsx";
|
||||
import type AppContext from "../components/app_context.js";
|
||||
import NoteDetail from "../widgets/NoteDetail.jsx";
|
||||
import MobileEditorToolbar from "../widgets/type_widgets/text/mobile_editor_toolbar.jsx";
|
||||
import PromotedAttributes from "../widgets/PromotedAttributes.jsx";
|
||||
import SplitNoteContainer from "../widgets/containers/split_note_container.js";
|
||||
import { applyModals } from "./layout_commons.js";
|
||||
|
||||
const MOBILE_CSS = `
|
||||
<style>
|
||||
@@ -183,7 +183,7 @@ export default class MobileLayout {
|
||||
.child(new FlexContainer("row")
|
||||
.class("horizontal")
|
||||
.css("height", "53px")
|
||||
.child(new LauncherContainer(true))
|
||||
.child(<LauncherContainer isHorizontalLayout />)
|
||||
.child(<GlobalMenuWidget isHorizontalLayout />)
|
||||
.id("launcher-pane"))
|
||||
)
|
||||
@@ -194,11 +194,11 @@ export default class MobileLayout {
|
||||
}
|
||||
|
||||
function FilePropertiesWrapper() {
|
||||
const { note } = useNoteContext();
|
||||
const { note, ntxId } = useNoteContext();
|
||||
|
||||
return (
|
||||
<div>
|
||||
{note?.type === "file" && <FilePropertiesTab note={note} />}
|
||||
{note?.type === "file" && <FilePropertiesTab note={note} ntxId={ntxId} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { t } from "../services/i18n.js";
|
||||
import contextMenu, { type ContextMenuEvent, type MenuItem } from "./context_menu.js";
|
||||
import type { LeafletMouseEvent } from "leaflet";
|
||||
|
||||
import appContext, { type CommandNames } from "../components/app_context.js";
|
||||
import { t } from "../services/i18n.js";
|
||||
import type { ViewScope } from "../services/link.js";
|
||||
import utils, { isMobile } from "../services/utils.js";
|
||||
import { getClosestNtxId } from "../widgets/widget_utils.js";
|
||||
import type { LeafletMouseEvent } from "leaflet";
|
||||
import contextMenu, { type ContextMenuEvent, type MenuItem } from "./context_menu.js";
|
||||
|
||||
function openContextMenu(notePath: string, e: ContextMenuEvent, viewScope: ViewScope = {}, hoistedNoteId: string | null = null) {
|
||||
contextMenu.show({
|
||||
@@ -34,15 +35,21 @@ function handleLinkContextMenuItem(command: string | undefined, e: ContextMenuEv
|
||||
|
||||
if (command === "openNoteInNewTab") {
|
||||
appContext.tabManager.openContextWithNote(notePath, { hoistedNoteId, viewScope });
|
||||
return true;
|
||||
} else if (command === "openNoteInNewSplit") {
|
||||
const ntxId = getNtxId(e);
|
||||
if (!ntxId) return;
|
||||
if (!ntxId) return false;
|
||||
appContext.triggerCommand("openNewNoteSplit", { ntxId, notePath, hoistedNoteId, viewScope });
|
||||
return true;
|
||||
} else if (command === "openNoteInNewWindow") {
|
||||
appContext.triggerCommand("openInWindow", { notePath, hoistedNoteId, viewScope });
|
||||
return true;
|
||||
} else if (command === "openNoteInPopup") {
|
||||
appContext.triggerCommand("openInPopup", { noteIdOrPath: notePath })
|
||||
appContext.triggerCommand("openInPopup", { noteIdOrPath: notePath });
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function getNtxId(e: ContextMenuEvent | LeafletMouseEvent) {
|
||||
@@ -52,9 +59,9 @@ function getNtxId(e: ContextMenuEvent | LeafletMouseEvent) {
|
||||
return subContexts[subContexts.length - 1].ntxId;
|
||||
} else if (e.target instanceof HTMLElement) {
|
||||
return getClosestNtxId(e.target);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import appContext from "./components/app_context.js";
|
||||
import noteAutocompleteService from "./services/note_autocomplete.js";
|
||||
import glob from "./services/glob.js";
|
||||
import "boxicons/css/boxicons.min.css";
|
||||
import "autocomplete.js/index_jquery.js";
|
||||
|
||||
import appContext from "./components/app_context.js";
|
||||
import glob from "./services/glob.js";
|
||||
import noteAutocompleteService from "./services/note_autocomplete.js";
|
||||
|
||||
glob.setupGlobs();
|
||||
|
||||
await appContext.earlyInit();
|
||||
|
||||
@@ -1,17 +1,25 @@
|
||||
import FNote from "./entities/fnote";
|
||||
import { render } from "preact";
|
||||
import { CustomNoteList, useNoteViewType } from "./widgets/collections/NoteList";
|
||||
import { useCallback, useLayoutEffect, useRef } from "preact/hooks";
|
||||
|
||||
import FNote from "./entities/fnote";
|
||||
import content_renderer from "./services/content_renderer";
|
||||
import { dynamicRequire, isElectron } from "./services/utils";
|
||||
import { applyInlineMermaid } from "./services/content_renderer_text";
|
||||
import { dynamicRequire, isElectron } from "./services/utils";
|
||||
import { CustomNoteList, useNoteViewType } from "./widgets/collections/NoteList";
|
||||
|
||||
interface RendererProps {
|
||||
note: FNote;
|
||||
onReady: () => void;
|
||||
onReady: (data: PrintReport) => void;
|
||||
onProgressChanged?: (progress: number) => void;
|
||||
}
|
||||
|
||||
export type PrintReport = {
|
||||
type: "single-note";
|
||||
} | {
|
||||
type: "collection";
|
||||
ignoredNoteIds: string[];
|
||||
};
|
||||
|
||||
async function main() {
|
||||
const notePath = window.location.hash.substring(1);
|
||||
const noteId = notePath.split("/").at(-1);
|
||||
@@ -34,15 +42,17 @@ function App({ note, noteId }: { note: FNote | null | undefined, noteId: string
|
||||
window.dispatchEvent(new CustomEvent("note-load-progress", { detail: { progress } }));
|
||||
}
|
||||
}, []);
|
||||
const onReady = useCallback(() => {
|
||||
const onReady = useCallback((printReport: PrintReport) => {
|
||||
if (sentReadyEvent.current) return;
|
||||
window.dispatchEvent(new Event("note-ready"));
|
||||
window._noteReady = true;
|
||||
window.dispatchEvent(new CustomEvent("note-ready", {
|
||||
detail: printReport
|
||||
}));
|
||||
window._noteReady = printReport;
|
||||
sentReadyEvent.current = true;
|
||||
}, []);
|
||||
const props: RendererProps | undefined | null = note && { note, onReady, onProgressChanged };
|
||||
|
||||
if (!note || !props) return <Error404 noteId={noteId} />
|
||||
if (!note || !props) return <Error404 noteId={noteId} />;
|
||||
|
||||
useLayoutEffect(() => {
|
||||
document.body.dataset.noteType = note.type;
|
||||
@@ -51,8 +61,8 @@ function App({ note, noteId }: { note: FNote | null | undefined, noteId: string
|
||||
return (
|
||||
<>
|
||||
{note.type === "book"
|
||||
? <CollectionRenderer {...props} />
|
||||
: <SingleNoteRenderer {...props} />
|
||||
? <CollectionRenderer {...props} />
|
||||
: <SingleNoteRenderer {...props} />
|
||||
}
|
||||
</>
|
||||
);
|
||||
@@ -91,7 +101,9 @@ function SingleNoteRenderer({ note, onReady }: RendererProps) {
|
||||
await loadCustomCss(note);
|
||||
}
|
||||
|
||||
load().then(() => requestAnimationFrame(onReady))
|
||||
load().then(() => requestAnimationFrame(() => onReady({
|
||||
type: "single-note"
|
||||
})));
|
||||
}, [ note ]);
|
||||
|
||||
return <>
|
||||
@@ -110,9 +122,9 @@ function CollectionRenderer({ note, onReady, onProgressChanged }: RendererProps)
|
||||
ntxId="print"
|
||||
highlightedTokens={null}
|
||||
media="print"
|
||||
onReady={async () => {
|
||||
onReady={async (data: PrintReport) => {
|
||||
await loadCustomCss(note);
|
||||
onReady();
|
||||
onReady(data);
|
||||
}}
|
||||
onProgressChanged={onProgressChanged}
|
||||
/>;
|
||||
@@ -124,12 +136,12 @@ function Error404({ noteId }: { noteId: string }) {
|
||||
<p>The note you are trying to print could not be found.</p>
|
||||
<small>{noteId}</small>
|
||||
</main>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
async function loadCustomCss(note: FNote) {
|
||||
const printCssNotes = await note.getRelationTargets("printCss");
|
||||
let loadPromises: JQueryPromise<void>[] = [];
|
||||
const loadPromises: JQueryPromise<void>[] = [];
|
||||
|
||||
for (const printCssNote of printCssNotes) {
|
||||
if (!printCssNote || (printCssNote.type !== "code" && printCssNote.mime !== "text/css")) continue;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import utils from "./utils.js";
|
||||
import server from "./server.js";
|
||||
import toastService, { type ToastOptions } from "./toast.js";
|
||||
import toastService, { type ToastOptionsWithRequiredId } from "./toast.js";
|
||||
import froca from "./froca.js";
|
||||
import hoistedNoteService from "./hoisted_note.js";
|
||||
import ws from "./ws.js";
|
||||
@@ -195,11 +195,11 @@ function filterRootNote(branchIds: string[]) {
|
||||
});
|
||||
}
|
||||
|
||||
function makeToast(id: string, message: string): ToastOptions {
|
||||
function makeToast(id: string, message: string): ToastOptionsWithRequiredId {
|
||||
return {
|
||||
id: id,
|
||||
id,
|
||||
title: t("branches.delete-status"),
|
||||
message: message,
|
||||
message,
|
||||
icon: "trash"
|
||||
};
|
||||
}
|
||||
@@ -216,7 +216,7 @@ ws.subscribeToMessages(async (message) => {
|
||||
toastService.showPersistent(makeToast(message.taskId, t("branches.delete-notes-in-progress", { count: message.progressCount })));
|
||||
} else if (message.type === "taskSucceeded") {
|
||||
const toast = makeToast(message.taskId, t("branches.delete-finished-successfully"));
|
||||
toast.closeAfter = 5000;
|
||||
toast.timeout = 5000;
|
||||
|
||||
toastService.showPersistent(toast);
|
||||
}
|
||||
@@ -234,7 +234,7 @@ ws.subscribeToMessages(async (message) => {
|
||||
toastService.showPersistent(makeToast(message.taskId, t("branches.undeleting-notes-in-progress", { count: message.progressCount })));
|
||||
} else if (message.type === "taskSucceeded") {
|
||||
const toast = makeToast(message.taskId, t("branches.undeleting-notes-finished-successfully"));
|
||||
toast.closeAfter = 5000;
|
||||
toast.timeout = 5000;
|
||||
|
||||
toastService.showPersistent(toast);
|
||||
}
|
||||
@@ -242,7 +242,7 @@ ws.subscribeToMessages(async (message) => {
|
||||
|
||||
async function cloneNoteToBranch(childNoteId: string, parentBranchId: string, prefix?: string) {
|
||||
const resp = await server.put<Response>(`notes/${childNoteId}/clone-to-branch/${parentBranchId}`, {
|
||||
prefix: prefix
|
||||
prefix
|
||||
});
|
||||
|
||||
if (!resp.success) {
|
||||
@@ -252,7 +252,7 @@ async function cloneNoteToBranch(childNoteId: string, parentBranchId: string, pr
|
||||
|
||||
async function cloneNoteToParentNote(childNoteId: string, parentNoteId: string, prefix?: string) {
|
||||
const resp = await server.put<Response>(`notes/${childNoteId}/clone-to-note/${parentNoteId}`, {
|
||||
prefix: prefix
|
||||
prefix
|
||||
});
|
||||
|
||||
if (!resp.success) {
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
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";
|
||||
import ScriptContext from "./script_context.js";
|
||||
import server from "./server.js";
|
||||
import toastService, { showError } from "./toast.js";
|
||||
import froca from "./froca.js";
|
||||
import utils from "./utils.js";
|
||||
import { t } from "./i18n.js";
|
||||
import type { Entity } from "./frontend_script_api.js";
|
||||
import toastService, { showErrorForScriptNote } from "./toast.js";
|
||||
import utils, { getErrorMessage } from "./utils.js";
|
||||
|
||||
// TODO: Deduplicate with server.
|
||||
export interface Bundle {
|
||||
@@ -14,9 +19,13 @@ export interface Bundle {
|
||||
allNoteIds: string[];
|
||||
}
|
||||
|
||||
interface Widget {
|
||||
type LegacyWidget = (BasicWidget | RightPanelWidget) & {
|
||||
parentWidget?: string;
|
||||
}
|
||||
};
|
||||
type WithNoteId<T> = T & {
|
||||
_noteId: string;
|
||||
};
|
||||
export type Widget = WithNoteId<(LegacyWidget | WidgetDefinitionWithType)>;
|
||||
|
||||
async function getAndExecuteBundle(noteId: string, originEntity = null, script = null, params = null) {
|
||||
const bundle = await server.post<Bundle>(`script/bundle/${noteId}`, {
|
||||
@@ -27,6 +36,8 @@ async function getAndExecuteBundle(noteId: string, originEntity = null, script =
|
||||
return await executeBundle(bundle, originEntity);
|
||||
}
|
||||
|
||||
export type ParentName = "left-pane" | "center-pane" | "note-detail-pane" | "right-pane";
|
||||
|
||||
export async function executeBundle(bundle: Bundle, originEntity?: Entity | null, $container?: JQuery<HTMLElement>) {
|
||||
const apiContext = await ScriptContext(bundle.noteId, bundle.allNoteIds, originEntity, $container);
|
||||
|
||||
@@ -35,17 +46,14 @@ export async function executeBundle(bundle: Bundle, originEntity?: Entity | null
|
||||
return eval(`const apiContext = this; (async function() { ${bundle.script}\r\n})()`);
|
||||
}.call(apiContext);
|
||||
} catch (e: any) {
|
||||
const note = await froca.getNote(bundle.noteId);
|
||||
|
||||
const message = `Execution of JS note "${note?.title}" with ID ${bundle.noteId} failed with error: ${e?.message}`;
|
||||
showError(message);
|
||||
logError(message);
|
||||
showErrorForScriptNote(bundle.noteId, t("toast.bundle-error.message", { message: e.message }));
|
||||
logError("Widget initialization failed: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
async function executeStartupBundles() {
|
||||
const isMobile = utils.isMobile();
|
||||
const scriptBundles = await server.get<Bundle[]>("script/startup" + (isMobile ? "?mobile=true" : ""));
|
||||
const scriptBundles = await server.get<Bundle[]>(`script/startup${ isMobile ? "?mobile=true" : ""}`);
|
||||
|
||||
for (const bundle of scriptBundles) {
|
||||
await executeBundle(bundle);
|
||||
@@ -53,67 +61,99 @@ async function executeStartupBundles() {
|
||||
}
|
||||
|
||||
export class WidgetsByParent {
|
||||
private byParent: Record<string, Widget[]>;
|
||||
private legacyWidgets: Record<string, WithNoteId<LegacyWidget>[]>;
|
||||
private preactWidgets: Record<string, WithNoteId<WidgetDefinitionWithType>[]>;
|
||||
|
||||
constructor() {
|
||||
this.byParent = {};
|
||||
this.legacyWidgets = {};
|
||||
this.preactWidgets = {};
|
||||
}
|
||||
|
||||
add(widget: Widget) {
|
||||
if (!widget.parentWidget) {
|
||||
console.log(`Custom widget does not have mandatory 'parentWidget' property defined`);
|
||||
return;
|
||||
let hasParentWidget = false;
|
||||
let isPreact = false;
|
||||
if ("type" in widget && widget.type === "preact-widget") {
|
||||
// React-based script.
|
||||
const reactWidget = widget as WithNoteId<WidgetDefinitionWithType>;
|
||||
this.preactWidgets[reactWidget.parent] = this.preactWidgets[reactWidget.parent] || [];
|
||||
this.preactWidgets[reactWidget.parent].push(reactWidget);
|
||||
isPreact = true;
|
||||
hasParentWidget = !!reactWidget.parent;
|
||||
} else if ("parentWidget" in widget && widget.parentWidget) {
|
||||
this.legacyWidgets[widget.parentWidget] = this.legacyWidgets[widget.parentWidget] || [];
|
||||
this.legacyWidgets[widget.parentWidget].push(widget);
|
||||
hasParentWidget = !!widget.parentWidget;
|
||||
}
|
||||
|
||||
this.byParent[widget.parentWidget] = this.byParent[widget.parentWidget] || [];
|
||||
this.byParent[widget.parentWidget].push(widget);
|
||||
if (!hasParentWidget) {
|
||||
showErrorForScriptNote(widget._noteId, t("toast.widget-missing-parent", {
|
||||
property: isPreact ? "parent" : "parentWidget"
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
get(parentName: string) {
|
||||
if (!this.byParent[parentName]) {
|
||||
return [];
|
||||
get(parentName: ParentName) {
|
||||
const widgets: (BasicWidget | VNode)[] = this.getLegacyWidgets(parentName);
|
||||
for (const preactWidget of this.getPreactWidgets(parentName)) {
|
||||
const el = h(preactWidget.render, {});
|
||||
const widget = new ReactWrappedWidget(el);
|
||||
widget.contentSized();
|
||||
if (preactWidget.position) {
|
||||
widget.position = preactWidget.position;
|
||||
}
|
||||
widgets.push(widget);
|
||||
}
|
||||
|
||||
return widgets;
|
||||
}
|
||||
|
||||
getLegacyWidgets(parentName: ParentName): (BasicWidget | RightPanelWidget)[] {
|
||||
if (!this.legacyWidgets[parentName]) return [];
|
||||
|
||||
return (
|
||||
this.byParent[parentName]
|
||||
this.legacyWidgets[parentName]
|
||||
// previously, custom widgets were provided as a single instance, but that has the disadvantage
|
||||
// for splits where we actually need multiple instaces and thus having a class to instantiate is better
|
||||
// https://github.com/zadam/trilium/issues/4274
|
||||
.map((w: any) => (w.prototype ? new w() : w))
|
||||
);
|
||||
}
|
||||
|
||||
getPreactWidgets(parentName: ParentName) {
|
||||
return this.preactWidgets[parentName] ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
async function getWidgetBundlesByParent() {
|
||||
const scriptBundles = await server.get<Bundle[]>("script/widgets");
|
||||
|
||||
const widgetsByParent = new WidgetsByParent();
|
||||
|
||||
for (const bundle of scriptBundles) {
|
||||
let widget;
|
||||
try {
|
||||
const scriptBundles = await server.get<Bundle[]>("script/widgets");
|
||||
|
||||
try {
|
||||
widget = await executeBundle(bundle);
|
||||
if (widget) {
|
||||
widget._noteId = bundle.noteId;
|
||||
widgetsByParent.add(widget);
|
||||
for (const bundle of scriptBundles) {
|
||||
let widget;
|
||||
|
||||
try {
|
||||
widget = await executeBundle(bundle);
|
||||
if (widget) {
|
||||
widget._noteId = bundle.noteId;
|
||||
widgetsByParent.add(widget);
|
||||
}
|
||||
} catch (e: any) {
|
||||
const noteId = bundle.noteId;
|
||||
showErrorForScriptNote(noteId, t("toast.bundle-error.message", { message: e.message }));
|
||||
|
||||
logError("Widget initialization failed: ", e);
|
||||
continue;
|
||||
}
|
||||
} catch (e: any) {
|
||||
const noteId = bundle.noteId;
|
||||
const note = await froca.getNote(noteId);
|
||||
toastService.showPersistent({
|
||||
title: t("toast.bundle-error.title"),
|
||||
icon: "alert",
|
||||
message: t("toast.bundle-error.message", {
|
||||
id: noteId,
|
||||
title: note?.title,
|
||||
message: e.message
|
||||
})
|
||||
});
|
||||
|
||||
logError("Widget initialization failed: ", e);
|
||||
continue;
|
||||
}
|
||||
} catch (e) {
|
||||
toastService.showPersistent({
|
||||
id: `custom-widget-list-failure`,
|
||||
title: t("toast.widget-list-error.title"),
|
||||
message: getErrorMessage(e),
|
||||
icon: "bx bx-error-circle"
|
||||
});
|
||||
}
|
||||
|
||||
return widgetsByParent;
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
import renderService from "./render.js";
|
||||
import { normalizeMimeTypeForCKEditor } from "@triliumnext/commons";
|
||||
import WheelZoom from 'vanilla-js-wheel-zoom';
|
||||
|
||||
import FAttachment from "../entities/fattachment.js";
|
||||
import FNote from "../entities/fnote.js";
|
||||
import imageContextMenuService from "../menus/image_context_menu.js";
|
||||
import { t } from "../services/i18n.js";
|
||||
import renderText from "./content_renderer_text.js";
|
||||
import renderDoc from "./doc_renderer.js";
|
||||
import { loadElkIfNeeded, postprocessMermaidSvg } from "./mermaid.js";
|
||||
import openService from "./open.js";
|
||||
import protectedSessionService from "./protected_session.js";
|
||||
import protectedSessionHolder from "./protected_session_holder.js";
|
||||
import openService from "./open.js";
|
||||
import utils from "./utils.js";
|
||||
import FNote from "../entities/fnote.js";
|
||||
import FAttachment from "../entities/fattachment.js";
|
||||
import imageContextMenuService from "../menus/image_context_menu.js";
|
||||
import renderService from "./render.js";
|
||||
import { applySingleBlockSyntaxHighlight } from "./syntax_highlight.js";
|
||||
import { loadElkIfNeeded, postprocessMermaidSvg } from "./mermaid.js";
|
||||
import renderDoc from "./doc_renderer.js";
|
||||
import { t } from "../services/i18n.js";
|
||||
import WheelZoom from 'vanilla-js-wheel-zoom';
|
||||
import { normalizeMimeTypeForCKEditor } from "@triliumnext/commons";
|
||||
import renderText from "./content_renderer_text.js";
|
||||
import utils from "./utils.js";
|
||||
|
||||
let idCounter = 1;
|
||||
|
||||
@@ -152,7 +153,7 @@ function renderImage(entity: FNote | FAttachment, $renderedContent: JQuery<HTMLE
|
||||
|
||||
const $img = $("<img>")
|
||||
.attr("src", url || "")
|
||||
.attr("id", "attachment-image-" + idCounter++)
|
||||
.attr("id", `attachment-image-${idCounter++}`)
|
||||
.css("max-width", "100%");
|
||||
|
||||
$renderedContent.append($img);
|
||||
@@ -193,7 +194,7 @@ function renderFile(entity: FNote | FAttachment, type: string, $renderedContent:
|
||||
|
||||
if (type === "pdf") {
|
||||
const $pdfPreview = $('<iframe class="pdf-preview" style="width: 100%; flex-grow: 100;"></iframe>');
|
||||
$pdfPreview.attr("src", openService.getUrlForDownload(`api/${entityType}/${entityId}/open`));
|
||||
$pdfPreview.attr("src", openService.getUrlForDownload(`pdfjs/web/viewer.html?file=../../api/${entityType}/${entityId}/open`));
|
||||
|
||||
$content.append($pdfPreview);
|
||||
} else if (type === "audio") {
|
||||
@@ -217,28 +218,28 @@ function renderFile(entity: FNote | FAttachment, type: string, $renderedContent:
|
||||
// in attachment list
|
||||
const $downloadButton = $(`
|
||||
<button class="file-download btn btn-primary" type="button">
|
||||
<span class="bx bx-download"></span>
|
||||
<span class="tn-icon bx bx-download"></span>
|
||||
${t("file_properties.download")}
|
||||
</button>
|
||||
`);
|
||||
|
||||
const $openButton = $(`
|
||||
<button class="file-open btn btn-primary" type="button">
|
||||
<span class="bx bx-link-external"></span>
|
||||
<span class="tn-icon bx bx-link-external"></span>
|
||||
${t("file_properties.open")}
|
||||
</button>
|
||||
`);
|
||||
|
||||
$downloadButton.on("click", (e) => {
|
||||
e.stopPropagation();
|
||||
openService.downloadFileNote(entity.noteId)
|
||||
openService.downloadFileNote(entity, null, null);
|
||||
});
|
||||
$openButton.on("click", async (e) => {
|
||||
const iconEl = $openButton.find("> .bx");
|
||||
iconEl.removeClass("bx bx-link-external");
|
||||
iconEl.addClass("bx bx-loader spin");
|
||||
e.stopPropagation();
|
||||
await openService.openNoteExternally(entity.noteId, entity.mime)
|
||||
await openService.openNoteExternally(entity.noteId, entity.mime);
|
||||
iconEl.removeClass("bx bx-loader spin");
|
||||
iconEl.addClass("bx bx-link-external");
|
||||
});
|
||||
@@ -266,7 +267,7 @@ async function renderMermaid(note: FNote | FAttachment, $renderedContent: JQuery
|
||||
|
||||
try {
|
||||
await loadElkIfNeeded(mermaid, content);
|
||||
const { svg } = await mermaid.mermaidAPI.render("in-mermaid-graph-" + idCounter++, content);
|
||||
const { svg } = await mermaid.mermaidAPI.render(`in-mermaid-graph-${idCounter++}`, content);
|
||||
|
||||
$renderedContent.append($(postprocessMermaidSvg(svg)));
|
||||
} catch (e) {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { formatCodeBlocks } from "./syntax_highlight.js";
|
||||
import { getMermaidConfig } from "./mermaid.js";
|
||||
import { renderMathInElement } from "./math.js";
|
||||
import FNote from "../entities/fnote.js";
|
||||
import FAttachment from "../entities/fattachment.js";
|
||||
import tree from "./tree.js";
|
||||
import FNote from "../entities/fnote.js";
|
||||
import { default as content_renderer, type RenderOptions } from "./content_renderer.js";
|
||||
import froca from "./froca.js";
|
||||
import link from "./link.js";
|
||||
import { renderMathInElement } from "./math.js";
|
||||
import { getMermaidConfig } from "./mermaid.js";
|
||||
import { formatCodeBlocks } from "./syntax_highlight.js";
|
||||
import tree from "./tree.js";
|
||||
import { isHtmlEmpty } from "./utils.js";
|
||||
import { default as content_renderer, type RenderOptions } from "./content_renderer.js";
|
||||
|
||||
export default async function renderText(note: FNote | FAttachment, $renderedContent: JQuery<HTMLElement>, options: RenderOptions = {}) {
|
||||
// entity must be FNote
|
||||
@@ -22,12 +22,14 @@ export default async function renderText(note: FNote | FAttachment, $renderedCon
|
||||
}
|
||||
|
||||
const getNoteIdFromLink = (el: HTMLElement) => tree.getNoteIdFromUrl($(el).attr("href") || "");
|
||||
const referenceLinks = $renderedContent.find("a.reference-link");
|
||||
const referenceLinks = $renderedContent.find<HTMLAnchorElement>("a.reference-link");
|
||||
const noteIdsToPrefetch = referenceLinks.map((i, el) => getNoteIdFromLink(el));
|
||||
await froca.getNotes(noteIdsToPrefetch);
|
||||
|
||||
for (const el of referenceLinks) {
|
||||
await link.loadReferenceLinkTitle($(el));
|
||||
const innerSpan = document.createElement("span");
|
||||
await link.loadReferenceLinkTitle($(innerSpan), el.href);
|
||||
el.replaceChildren(innerSpan);
|
||||
}
|
||||
|
||||
await rewriteMermaidDiagramsInContainer($renderedContent[0] as HTMLDivElement);
|
||||
|
||||
14
apps/client/src/services/css_class_manager.spec.ts
Normal file
14
apps/client/src/services/css_class_manager.spec.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { getReadableTextColor } from "./css_class_manager";
|
||||
|
||||
describe("getReadableTextColor", () => {
|
||||
it("doesn't crash for invalid color", () => {
|
||||
expect(getReadableTextColor("RandomColor")).toBe("#000");
|
||||
});
|
||||
|
||||
it("tolerates different casing", () => {
|
||||
expect(getReadableTextColor("Blue"))
|
||||
.toBe(getReadableTextColor("blue"));
|
||||
});
|
||||
});
|
||||
@@ -1,21 +1,22 @@
|
||||
import clsx from "clsx";
|
||||
import {readCssVar} from "../utils/css-var";
|
||||
import Color, { ColorInstance } from "color";
|
||||
|
||||
import {readCssVar} from "../utils/css-var";
|
||||
|
||||
const registeredClasses = new Set<string>();
|
||||
const colorsWithHue = new Set<string>();
|
||||
|
||||
// Read the color lightness limits defined in the theme as CSS variables
|
||||
|
||||
const lightThemeColorMaxLightness = readCssVar(
|
||||
document.documentElement,
|
||||
"tree-item-light-theme-max-color-lightness"
|
||||
).asNumber(70);
|
||||
document.documentElement,
|
||||
"tree-item-light-theme-max-color-lightness"
|
||||
).asNumber(70);
|
||||
|
||||
const darkThemeColorMinLightness = readCssVar(
|
||||
document.documentElement,
|
||||
"tree-item-dark-theme-min-color-lightness"
|
||||
).asNumber(50);
|
||||
document.documentElement,
|
||||
"tree-item-dark-theme-min-color-lightness"
|
||||
).asNumber(50);
|
||||
|
||||
function createClassForColor(colorString: string | null) {
|
||||
if (!colorString?.trim()) return "";
|
||||
@@ -27,11 +28,12 @@ function createClassForColor(colorString: string | null) {
|
||||
|
||||
if (!registeredClasses.has(className)) {
|
||||
const adjustedColor = adjustColorLightness(color, lightThemeColorMaxLightness!,
|
||||
darkThemeColorMinLightness!);
|
||||
darkThemeColorMinLightness!);
|
||||
const hue = getHue(color);
|
||||
|
||||
$("head").append(`<style>
|
||||
.${className}, span.fancytree-active.${className} {
|
||||
--original-custom-color: ${color.hex()};
|
||||
--light-theme-custom-color: ${adjustedColor.lightThemeColor};
|
||||
--dark-theme-custom-color: ${adjustedColor.darkThemeColor};
|
||||
--custom-color-hue: ${hue ?? 'unset'};
|
||||
@@ -49,7 +51,7 @@ function createClassForColor(colorString: string | null) {
|
||||
|
||||
function parseColor(color: string) {
|
||||
try {
|
||||
return Color(color);
|
||||
return Color(color.toLowerCase());
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
}
|
||||
@@ -83,8 +85,8 @@ function getHue(color: ColorInstance) {
|
||||
}
|
||||
|
||||
export function getReadableTextColor(bgColor: string) {
|
||||
const colorInstance = Color(bgColor);
|
||||
return colorInstance.isLight() ? "#000" : "#fff";
|
||||
const colorInstance = parseColor(bgColor);
|
||||
return !colorInstance || colorInstance?.isLight() ? "#000" : "#fff";
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Modal } from "bootstrap";
|
||||
import appContext from "../components/app_context.js";
|
||||
import type { ConfirmDialogOptions, ConfirmDialogResult, ConfirmWithMessageOptions } from "../widgets/dialogs/confirm.js";
|
||||
import type { ConfirmDialogOptions, ConfirmDialogResult, ConfirmWithMessageOptions, MessageType } from "../widgets/dialogs/confirm.js";
|
||||
import type { PromptDialogOptions } from "../widgets/dialogs/prompt.js";
|
||||
import { focusSavedElement, saveFocusedElement } from "./focus.js";
|
||||
import { InfoExtraProps } from "../widgets/dialogs/info.jsx";
|
||||
|
||||
export async function openDialog($dialog: JQuery<HTMLElement>, closeActDialog = true, config?: Partial<Modal.Options>) {
|
||||
if (closeActDialog) {
|
||||
@@ -37,8 +38,8 @@ export function closeActiveDialog() {
|
||||
}
|
||||
}
|
||||
|
||||
async function info(message: string) {
|
||||
return new Promise((res) => appContext.triggerCommand("showInfoDialog", { message, callback: res }));
|
||||
async function info(message: MessageType, extraProps?: InfoExtraProps) {
|
||||
return new Promise((res) => appContext.triggerCommand("showInfoDialog", { ...extraProps, message, callback: res }));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
60
apps/client/src/services/experimental_features.ts
Normal file
60
apps/client/src/services/experimental_features.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { t } from "./i18n";
|
||||
import options from "./options";
|
||||
|
||||
export interface ExperimentalFeature {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export const experimentalFeatures = [
|
||||
{
|
||||
id: "new-layout",
|
||||
name: t("experimental_features.new_layout_name"),
|
||||
description: t("experimental_features.new_layout_description"),
|
||||
}
|
||||
] as const satisfies ExperimentalFeature[];
|
||||
|
||||
export type ExperimentalFeatureId = typeof experimentalFeatures[number]["id"];
|
||||
|
||||
let enabledFeatures: Set<ExperimentalFeatureId> | null = null;
|
||||
|
||||
export function isExperimentalFeatureEnabled(featureId: ExperimentalFeatureId): boolean {
|
||||
if (featureId === "new-layout") {
|
||||
return options.is("newLayout");
|
||||
}
|
||||
|
||||
return getEnabledFeatures().has(featureId);
|
||||
}
|
||||
|
||||
export function getEnabledExperimentalFeatureIds() {
|
||||
const values = [ ...getEnabledFeatures().values() ];
|
||||
if (options.is("newLayout")) {
|
||||
values.push("new-layout");
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
export async function toggleExperimentalFeature(featureId: ExperimentalFeatureId, enable: boolean) {
|
||||
const features = new Set(getEnabledFeatures());
|
||||
if (enable) {
|
||||
features.add(featureId);
|
||||
} else {
|
||||
features.delete(featureId);
|
||||
}
|
||||
await options.save("experimentalFeatures", JSON.stringify(Array.from(features)));
|
||||
}
|
||||
|
||||
function getEnabledFeatures() {
|
||||
if (!enabledFeatures) {
|
||||
let features: ExperimentalFeatureId[] = [];
|
||||
try {
|
||||
features = JSON.parse(options.get("experimentalFeatures")) as ExperimentalFeatureId[];
|
||||
} catch (e) {
|
||||
console.warn("Failed to parse experimental features from options:", e);
|
||||
}
|
||||
enabledFeatures = new Set(features);
|
||||
enabledFeatures.delete("new-layout"); // handled separately.
|
||||
}
|
||||
return enabledFeatures;
|
||||
}
|
||||
@@ -1,26 +1,27 @@
|
||||
import server from "./server.js";
|
||||
import utils from "./utils.js";
|
||||
import toastService from "./toast.js";
|
||||
import linkService from "./link.js";
|
||||
import { dayjs, formatLogMessage } from "@triliumnext/commons";
|
||||
|
||||
import appContext from "../components/app_context.js";
|
||||
import type Component from "../components/component.js";
|
||||
import type NoteContext from "../components/note_context.js";
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import BasicWidget, { ReactWrappedWidget } from "../widgets/basic_widget.js";
|
||||
import NoteContextAwareWidget from "../widgets/note_context_aware_widget.js";
|
||||
import RightPanelWidget from "../widgets/right_panel_widget.js";
|
||||
import dateNotesService from "./date_notes.js";
|
||||
import dialogService from "./dialog.js";
|
||||
import froca from "./froca.js";
|
||||
import { preactAPI } from "./frontend_script_api_preact.js";
|
||||
import { t } from "./i18n.js";
|
||||
import linkService from "./link.js";
|
||||
import noteTooltipService from "./note_tooltip.js";
|
||||
import protectedSessionService from "./protected_session.js";
|
||||
import dateNotesService from "./date_notes.js";
|
||||
import searchService from "./search.js";
|
||||
import RightPanelWidget from "../widgets/right_panel_widget.js";
|
||||
import ws from "./ws.js";
|
||||
import appContext from "../components/app_context.js";
|
||||
import NoteContextAwareWidget from "../widgets/note_context_aware_widget.js";
|
||||
import BasicWidget, { ReactWrappedWidget } from "../widgets/basic_widget.js";
|
||||
import SpacedUpdate from "./spaced_update.js";
|
||||
import server from "./server.js";
|
||||
import shortcutService from "./shortcuts.js";
|
||||
import dialogService from "./dialog.js";
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import { t } from "./i18n.js";
|
||||
import { dayjs } from "@triliumnext/commons";
|
||||
import type NoteContext from "../components/note_context.js";
|
||||
import type Component from "../components/component.js";
|
||||
import { formatLogMessage } from "@triliumnext/commons";
|
||||
import SpacedUpdate from "./spaced_update.js";
|
||||
import toastService from "./toast.js";
|
||||
import utils from "./utils.js";
|
||||
import ws from "./ws.js";
|
||||
|
||||
/**
|
||||
* A whole number
|
||||
@@ -77,6 +78,10 @@ export interface Api {
|
||||
|
||||
/**
|
||||
* Entity whose event triggered this execution.
|
||||
*
|
||||
* <p>
|
||||
* For front-end scripts, generally there's no origin entity specified since the scripts are run by the user or automatically by the UI (widgets).
|
||||
* If there is an origin entity specified, then it's going to be a note entity.
|
||||
*/
|
||||
originEntity: unknown | null;
|
||||
|
||||
@@ -278,12 +283,16 @@ export interface Api {
|
||||
getActiveContextNote(): FNote;
|
||||
|
||||
/**
|
||||
* @returns returns active context (split)
|
||||
* Obtains the currently active/focused split in the current tab.
|
||||
*
|
||||
* Note that this method does not return the note context of the "Quick edit" panel, it will return the note context behind it.
|
||||
*/
|
||||
getActiveContext(): NoteContext;
|
||||
|
||||
/**
|
||||
* @returns returns active main context (first split in a tab, represents the tab as a whole)
|
||||
* Obtains the main context of the current tab. This is the left-most split.
|
||||
*
|
||||
* Note that this method does not return the note context of the "Quick edit" panel, it will return the note context behind it.
|
||||
*/
|
||||
getActiveMainContext(): NoteContext;
|
||||
|
||||
@@ -456,6 +465,8 @@ export interface Api {
|
||||
* Log given message to the log pane in UI
|
||||
*/
|
||||
log(message: string | object): void;
|
||||
|
||||
preact: typeof preactAPI;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -525,9 +536,8 @@ function FrontendScriptApi(this: Api, startNote: FNote, currentNote: FNote, orig
|
||||
return params.map((p) => {
|
||||
if (typeof p === "function") {
|
||||
return `!@#Function: ${p.toString()}`;
|
||||
} else {
|
||||
return p;
|
||||
}
|
||||
return p;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -554,9 +564,8 @@ function FrontendScriptApi(this: Api, startNote: FNote, currentNote: FNote, orig
|
||||
await ws.waitForMaxKnownEntityChangeId();
|
||||
|
||||
return ret.executionResult;
|
||||
} else {
|
||||
throw new Error(`server error: ${ret.error}`);
|
||||
}
|
||||
throw new Error(`server error: ${ret.error}`);
|
||||
};
|
||||
|
||||
this.runOnBackend = async (func, params = []) => {
|
||||
@@ -713,6 +722,8 @@ function FrontendScriptApi(this: Api, startNote: FNote, currentNote: FNote, orig
|
||||
this.logMessages[noteId].push(message);
|
||||
this.logSpacedUpdates[noteId].scheduleUpdate();
|
||||
};
|
||||
|
||||
this.preact = preactAPI;
|
||||
}
|
||||
|
||||
export default FrontendScriptApi as any as {
|
||||
|
||||
101
apps/client/src/services/frontend_script_api_preact.ts
Normal file
101
apps/client/src/services/frontend_script_api_preact.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import { Fragment, h, VNode } from "preact";
|
||||
import * as hooks from "preact/hooks";
|
||||
|
||||
import ActionButton from "../widgets/react/ActionButton";
|
||||
import Admonition from "../widgets/react/Admonition";
|
||||
import Button from "../widgets/react/Button";
|
||||
import CKEditor from "../widgets/react/CKEditor";
|
||||
import Collapsible from "../widgets/react/Collapsible";
|
||||
import Dropdown from "../widgets/react/Dropdown";
|
||||
import FormCheckbox from "../widgets/react/FormCheckbox";
|
||||
import FormDropdownList from "../widgets/react/FormDropdownList";
|
||||
import { FormFileUploadActionButton, FormFileUploadButton } from "../widgets/react/FormFileUpload";
|
||||
import FormGroup from "../widgets/react/FormGroup";
|
||||
import { FormDropdownDivider, FormDropdownSubmenu, FormListItem } from "../widgets/react/FormList";
|
||||
import FormRadioGroup from "../widgets/react/FormRadioGroup";
|
||||
import FormText from "../widgets/react/FormText";
|
||||
import FormTextArea from "../widgets/react/FormTextArea";
|
||||
import FormTextBox from "../widgets/react/FormTextBox";
|
||||
import FormToggle from "../widgets/react/FormToggle";
|
||||
import * as triliumHooks from "../widgets/react/hooks";
|
||||
import Icon from "../widgets/react/Icon";
|
||||
import LinkButton from "../widgets/react/LinkButton";
|
||||
import LoadingSpinner from "../widgets/react/LoadingSpinner";
|
||||
import Modal from "../widgets/react/Modal";
|
||||
import NoteAutocomplete from "../widgets/react/NoteAutocomplete";
|
||||
import NoteLink from "../widgets/react/NoteLink";
|
||||
import RawHtml from "../widgets/react/RawHtml";
|
||||
import Slider from "../widgets/react/Slider";
|
||||
import RightPanelWidget from "../widgets/sidebar/RightPanelWidget";
|
||||
|
||||
export interface WidgetDefinition {
|
||||
parent: "right-pane",
|
||||
render: () => VNode,
|
||||
position?: number,
|
||||
}
|
||||
|
||||
export interface WidgetDefinitionWithType extends WidgetDefinition {
|
||||
type: "preact-widget"
|
||||
}
|
||||
|
||||
export interface LauncherWidgetDefinitionWithType {
|
||||
type: "preact-launcher-widget"
|
||||
render: () => VNode
|
||||
}
|
||||
|
||||
export const preactAPI = Object.freeze({
|
||||
// Core
|
||||
h,
|
||||
Fragment,
|
||||
|
||||
/**
|
||||
* Method that must be run for widget scripts that run on Preact, using JSX. The method just returns the same definition, reserved for future typechecking and perhaps validation purposes.
|
||||
*
|
||||
* @param definition the widget definition.
|
||||
*/
|
||||
defineWidget(definition: WidgetDefinition) {
|
||||
return {
|
||||
type: "preact-widget",
|
||||
...definition
|
||||
};
|
||||
},
|
||||
|
||||
defineLauncherWidget(definition: Omit<LauncherWidgetDefinitionWithType, "type">) {
|
||||
return {
|
||||
type: "preact-launcher-widget",
|
||||
...definition
|
||||
};
|
||||
},
|
||||
|
||||
// Basic widgets
|
||||
ActionButton,
|
||||
Admonition,
|
||||
Button,
|
||||
CKEditor,
|
||||
Collapsible,
|
||||
Dropdown,
|
||||
FormCheckbox,
|
||||
FormDropdownList,
|
||||
FormFileUploadButton, FormFileUploadActionButton,
|
||||
FormGroup,
|
||||
FormListItem, FormDropdownDivider, FormDropdownSubmenu,
|
||||
FormRadioGroup,
|
||||
FormText,
|
||||
FormTextArea,
|
||||
FormTextBox,
|
||||
FormToggle,
|
||||
Icon,
|
||||
LinkButton,
|
||||
LoadingSpinner,
|
||||
Modal,
|
||||
NoteAutocomplete,
|
||||
NoteLink,
|
||||
RawHtml,
|
||||
Slider,
|
||||
|
||||
// Specialized widgets
|
||||
RightPanelWidget,
|
||||
|
||||
...hooks,
|
||||
...triliumHooks
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
import toastService, { type ToastOptions } from "./toast.js";
|
||||
import toastService, { type ToastOptionsWithRequiredId } from "./toast.js";
|
||||
import server from "./server.js";
|
||||
import ws from "./ws.js";
|
||||
import utils from "./utils.js";
|
||||
@@ -57,11 +57,11 @@ export async function uploadFiles(entityType: string, parentNoteId: string, file
|
||||
}
|
||||
}
|
||||
|
||||
function makeToast(id: string, message: string): ToastOptions {
|
||||
function makeToast(id: string, message: string): ToastOptionsWithRequiredId {
|
||||
return {
|
||||
id: id,
|
||||
id,
|
||||
title: t("import.import-status"),
|
||||
message: message,
|
||||
message,
|
||||
icon: "plus"
|
||||
};
|
||||
}
|
||||
@@ -78,7 +78,7 @@ ws.subscribeToMessages(async (message) => {
|
||||
toastService.showPersistent(makeToast(message.taskId, t("import.in-progress", { progress: message.progressCount })));
|
||||
} else if (message.type === "taskSucceeded") {
|
||||
const toast = makeToast(message.taskId, t("import.successful"));
|
||||
toast.closeAfter = 5000;
|
||||
toast.timeout = 5000;
|
||||
|
||||
toastService.showPersistent(toast);
|
||||
|
||||
@@ -100,7 +100,7 @@ ws.subscribeToMessages(async (message: WebSocketMessage) => {
|
||||
toastService.showPersistent(makeToast(message.taskId, t("import.in-progress", { progress: message.progressCount })));
|
||||
} else if (message.type === "taskSucceeded") {
|
||||
const toast = makeToast(message.taskId, t("import.successful"));
|
||||
toast.closeAfter = 5000;
|
||||
toast.timeout = 5000;
|
||||
|
||||
toastService.showPersistent(toast);
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import treeService from "./tree.js";
|
||||
import linkContextMenuService from "../menus/link_context_menu.js";
|
||||
import appContext, { type NoteCommandData } from "../components/app_context.js";
|
||||
import froca from "./froca.js";
|
||||
import utils from "./utils.js";
|
||||
import { ALLOWED_PROTOCOLS } from "@triliumnext/commons";
|
||||
|
||||
import appContext, { type NoteCommandData } from "../components/app_context.js";
|
||||
import { openInCurrentNoteContext } from "../components/note_context.js";
|
||||
import linkContextMenuService from "../menus/link_context_menu.js";
|
||||
import froca from "./froca.js";
|
||||
import treeService from "./tree.js";
|
||||
import utils from "./utils.js";
|
||||
|
||||
function getNotePathFromUrl(url: string) {
|
||||
const notePathMatch = /#(root[A-Za-z0-9_/]*)$/.exec(url);
|
||||
@@ -27,7 +28,7 @@ async function getLinkIcon(noteId: string, viewMode: ViewMode | undefined) {
|
||||
return icon;
|
||||
}
|
||||
|
||||
export type ViewMode = "default" | "source" | "attachments" | "contextual-help";
|
||||
export type ViewMode = "default" | "source" | "attachments" | "contextual-help" | "note-map";
|
||||
|
||||
export interface ViewScope {
|
||||
/**
|
||||
@@ -99,7 +100,7 @@ async function createLink(notePath: string | undefined, options: CreateLinkOptio
|
||||
const viewMode = viewScope.viewMode || "default";
|
||||
let linkTitle = options.title;
|
||||
|
||||
if (!linkTitle) {
|
||||
if (linkTitle === undefined) {
|
||||
if (viewMode === "attachments" && viewScope.attachmentId) {
|
||||
const attachment = await froca.getAttachment(viewScope.attachmentId);
|
||||
|
||||
@@ -122,7 +123,7 @@ async function createLink(notePath: string | undefined, options: CreateLinkOptio
|
||||
const $container = $("<span>");
|
||||
|
||||
if (showNoteIcon) {
|
||||
let icon = await getLinkIcon(noteId, viewMode);
|
||||
const icon = await getLinkIcon(noteId, viewMode);
|
||||
|
||||
if (icon) {
|
||||
$container.append($("<span>").addClass(`bx ${icon}`)).append(" ");
|
||||
@@ -131,7 +132,7 @@ async function createLink(notePath: string | undefined, options: CreateLinkOptio
|
||||
|
||||
const hash = calculateHash({
|
||||
notePath,
|
||||
viewScope: viewScope
|
||||
viewScope
|
||||
});
|
||||
|
||||
const $noteLink = $("<a>", {
|
||||
@@ -171,11 +172,11 @@ async function createLink(notePath: string | undefined, options: CreateLinkOptio
|
||||
return $container;
|
||||
}
|
||||
|
||||
function calculateHash({ notePath, ntxId, hoistedNoteId, viewScope = {} }: NoteCommandData) {
|
||||
export function calculateHash({ notePath, ntxId, hoistedNoteId, viewScope = {} }: NoteCommandData) {
|
||||
notePath = notePath || "";
|
||||
const params = [
|
||||
ntxId ? { ntxId: ntxId } : null,
|
||||
hoistedNoteId && hoistedNoteId !== "root" ? { hoistedNoteId: hoistedNoteId } : null,
|
||||
ntxId ? { ntxId } : null,
|
||||
hoistedNoteId && hoistedNoteId !== "root" ? { hoistedNoteId } : null,
|
||||
viewScope.viewMode && viewScope.viewMode !== "default" ? { viewMode: viewScope.viewMode } : null,
|
||||
viewScope.attachmentId ? { attachmentId: viewScope.attachmentId } : null
|
||||
].filter((p) => !!p);
|
||||
@@ -219,7 +220,7 @@ export function parseNavigationStateFromUrl(url: string | undefined) {
|
||||
}
|
||||
|
||||
const hash = url.substr(hashIdx + 1); // strip also the initial '#'
|
||||
let [notePath, paramString] = hash.split("?");
|
||||
const [notePath, paramString] = hash.split("?");
|
||||
|
||||
const viewScope: ViewScope = {
|
||||
viewMode: "default"
|
||||
@@ -252,7 +253,7 @@ export function parseNavigationStateFromUrl(url: string | undefined) {
|
||||
}
|
||||
|
||||
if (searchString) {
|
||||
return { searchString }
|
||||
return { searchString };
|
||||
}
|
||||
|
||||
if (!notePath.match(/^[_a-z0-9]{4,}(\/[_a-z0-9]{4,})*$/i)) {
|
||||
@@ -334,7 +335,7 @@ export function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDo
|
||||
window.open(hrefLink, "_blank");
|
||||
} else {
|
||||
// Enable protocols supported by CKEditor 5 to be clickable.
|
||||
if (ALLOWED_PROTOCOLS.some((protocol) => hrefLink.toLowerCase().startsWith(protocol + ":"))) {
|
||||
if (ALLOWED_PROTOCOLS.some((protocol) => hrefLink.toLowerCase().startsWith(`${protocol}:`))) {
|
||||
if ( utils.isElectron()) {
|
||||
const electron = utils.dynamicRequire("electron");
|
||||
electron.shell.openExternal(hrefLink);
|
||||
@@ -395,7 +396,7 @@ async function loadReferenceLinkTitle($el: JQuery<HTMLElement>, href: string | n
|
||||
|
||||
href = href || $link.attr("href");
|
||||
if (!href) {
|
||||
console.warn("Empty URL for parsing: " + $el[0].outerHTML);
|
||||
console.warn(`Empty URL for parsing: ${$el[0].outerHTML}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -438,9 +439,9 @@ async function getReferenceLinkTitle(href: string) {
|
||||
const attachment = await note.getAttachmentById(viewScope.attachmentId);
|
||||
|
||||
return attachment ? attachment.title : "[missing attachment]";
|
||||
} else {
|
||||
return note.title;
|
||||
}
|
||||
return note.title;
|
||||
|
||||
}
|
||||
|
||||
function getReferenceLinkTitleSync(href: string) {
|
||||
@@ -462,9 +463,9 @@ function getReferenceLinkTitleSync(href: string) {
|
||||
const attachment = note.attachments.find((att) => att.attachmentId === viewScope.attachmentId);
|
||||
|
||||
return attachment ? attachment.title : "[missing attachment]";
|
||||
} else {
|
||||
return note.title;
|
||||
}
|
||||
return note.title;
|
||||
|
||||
}
|
||||
|
||||
if (glob.device !== "print") {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import utils from "./utils.js";
|
||||
import Component from "../components/component.js";
|
||||
import FNote from "../entities/fnote.js";
|
||||
import options from "./options.js";
|
||||
import server from "./server.js";
|
||||
import utils from "./utils.js";
|
||||
|
||||
type ExecFunction = (command: string, cb: (err: string, stdout: string, stderror: string) => void) => void;
|
||||
|
||||
@@ -36,9 +38,14 @@ function download(url: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export function downloadFileNote(noteId: string) {
|
||||
const url = `${getFileUrl("notes", noteId)}?${Date.now()}`; // don't use cache
|
||||
export function downloadFileNote(note: FNote, parentComponent: Component | null, ntxId: string | null | undefined) {
|
||||
if (note.type === "file" && note.mime === "application/pdf" && parentComponent) {
|
||||
// Special handling, manages its own downloading process.
|
||||
parentComponent.triggerEvent("customDownload", { ntxId });
|
||||
return;
|
||||
}
|
||||
|
||||
const url = `${getFileUrl("notes", note.noteId)}?${Date.now()}`; // don't use cache
|
||||
download(url);
|
||||
}
|
||||
|
||||
@@ -97,7 +104,7 @@ async function openCustom(type: string, entityId: string, mime: string) {
|
||||
// Note that the path separator must be \ instead of /
|
||||
filePath = filePath.replace(/\//g, "\\");
|
||||
}
|
||||
const command = `rundll32.exe shell32.dll,OpenAs_RunDLL ` + filePath;
|
||||
const command = `rundll32.exe shell32.dll,OpenAs_RunDLL ${filePath}`;
|
||||
exec(command, (err, stdout, stderr) => {
|
||||
if (err) {
|
||||
console.error("Open Note custom: ", err);
|
||||
@@ -131,10 +138,10 @@ export function getUrlForDownload(url: string) {
|
||||
if (utils.isElectron()) {
|
||||
// electron needs absolute URL, so we extract current host, port, protocol
|
||||
return `${getHost()}/${url}`;
|
||||
} else {
|
||||
// web server can be deployed on subdomain, so we need to use a relative path
|
||||
return url;
|
||||
}
|
||||
// web server can be deployed on subdomain, so we need to use a relative path
|
||||
return url;
|
||||
|
||||
}
|
||||
|
||||
function canOpenInBrowser(mime: string) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import server from "./server.js";
|
||||
import protectedSessionHolder from "./protected_session_holder.js";
|
||||
import toastService from "./toast.js";
|
||||
import type { ToastOptions } from "./toast.js";
|
||||
import type { ToastOptionsWithRequiredId } from "./toast.js";
|
||||
import ws from "./ws.js";
|
||||
import appContext from "../components/app_context.js";
|
||||
import froca from "./froca.js";
|
||||
@@ -97,7 +97,7 @@ async function protectNote(noteId: string, protect: boolean, includingSubtree: b
|
||||
await server.put(`notes/${noteId}/protect/${protect ? 1 : 0}?subtree=${includingSubtree ? 1 : 0}`);
|
||||
}
|
||||
|
||||
function makeToast(message: Message, title: string, text: string): ToastOptions {
|
||||
function makeToast(message: Message, title: string, text: string): ToastOptionsWithRequiredId {
|
||||
return {
|
||||
id: message.taskId,
|
||||
title,
|
||||
@@ -124,7 +124,7 @@ ws.subscribeToMessages(async (message) => {
|
||||
} else if (message.type === "taskSucceeded") {
|
||||
const text = isProtecting ? t("protected_session.protecting-finished-successfully") : t("protected_session.unprotecting-finished-successfully");
|
||||
const toast = makeToast(message, title, text);
|
||||
toast.closeAfter = 3000;
|
||||
toast.timeout = 3000;
|
||||
|
||||
toastService.showPersistent(toast);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import server from "./server.js";
|
||||
import bundleService, { type Bundle } from "./bundle.js";
|
||||
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");
|
||||
@@ -17,12 +21,34 @@ async function render(note: FNote, $el: JQuery<HTMLElement>) {
|
||||
$scriptContainer.append(bundle.html);
|
||||
|
||||
// async so that scripts cannot block trilium execution
|
||||
bundleService.executeBundle(bundle, note, $scriptContainer);
|
||||
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
|
||||
};
|
||||
|
||||
@@ -85,13 +85,15 @@ async function remove<T>(url: string, componentId?: string) {
|
||||
return await call<T>("DELETE", url, componentId);
|
||||
}
|
||||
|
||||
async function upload(url: string, fileToUpload: File) {
|
||||
async function upload(url: string, fileToUpload: File, componentId?: string) {
|
||||
const formData = new FormData();
|
||||
formData.append("upload", fileToUpload);
|
||||
|
||||
return await $.ajax({
|
||||
url: window.glob.baseApiUrl + url,
|
||||
headers: await getHeaders(),
|
||||
headers: await getHeaders(componentId ? {
|
||||
"trilium-component-id": componentId
|
||||
} : undefined),
|
||||
data: formData,
|
||||
type: "PUT",
|
||||
timeout: 60 * 60 * 1000,
|
||||
@@ -133,11 +135,11 @@ async function call<T>(method: string, url: string, componentId?: string, option
|
||||
};
|
||||
|
||||
ipc.send("server-request", {
|
||||
requestId: requestId,
|
||||
headers: headers,
|
||||
method: method,
|
||||
requestId,
|
||||
headers,
|
||||
method,
|
||||
url: `/${window.glob.baseApiUrl}${url}`,
|
||||
data: data
|
||||
data
|
||||
});
|
||||
})) as any;
|
||||
} else {
|
||||
@@ -161,7 +163,7 @@ function ajax(url: string, method: string, data: unknown, headers: Headers, sile
|
||||
const options: JQueryAjaxSettings = {
|
||||
url: window.glob.baseApiUrl + url,
|
||||
type: method,
|
||||
headers: headers,
|
||||
headers,
|
||||
timeout: 60000,
|
||||
success: (body, textStatus, jqXhr) => {
|
||||
const respHeaders: Headers = {};
|
||||
@@ -263,7 +265,7 @@ async function reportError(method: string, url: string, statusCode: number, resp
|
||||
|
||||
const toastService = (await import("./toast.js")).default;
|
||||
|
||||
const messageStr = typeof message === "string" ? message : JSON.stringify(message);
|
||||
const messageStr = (typeof message === "string" ? message : JSON.stringify(message)) || "-";
|
||||
|
||||
if ([400, 404].includes(statusCode) && response && typeof response === "object") {
|
||||
toastService.showError(messageStr);
|
||||
@@ -274,10 +276,22 @@ async function reportError(method: string, url: string, statusCode: number, resp
|
||||
...response
|
||||
});
|
||||
} else {
|
||||
const title = `${statusCode} ${method} ${url}`;
|
||||
toastService.showErrorTitleAndMessage(title, messageStr);
|
||||
const { throwError } = await import("./ws.js");
|
||||
throwError(`${title} - ${message}`);
|
||||
const { t } = await import("./i18n.js");
|
||||
if (statusCode === 400 && (url.includes("%23") || url.includes("%2F"))) {
|
||||
toastService.showPersistent({
|
||||
id: "trafik-blocked",
|
||||
icon: "bx bx-unlink",
|
||||
title: t("server.unknown_http_error_title"),
|
||||
message: t("server.traefik_blocks_requests")
|
||||
});
|
||||
} else {
|
||||
toastService.showErrorTitleAndMessage(
|
||||
t("server.unknown_http_error_title"),
|
||||
t("server.unknown_http_error_content", { statusCode, method, url, message: messageStr }),
|
||||
15_000);
|
||||
}
|
||||
const { logError } = await import("./ws.js");
|
||||
logError(`${statusCode} ${method} ${url} - ${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import utils from "./utils.js";
|
||||
|
||||
type ElementType = HTMLElement | Document;
|
||||
type Handler = (e: KeyboardEvent) => void;
|
||||
export type Handler = (e: KeyboardEvent) => void;
|
||||
|
||||
export interface ShortcutBinding {
|
||||
element: HTMLElement | Document;
|
||||
|
||||
@@ -1,22 +1,30 @@
|
||||
import type { SaveState } from "../components/note_context";
|
||||
import { getErrorMessage } from "./utils";
|
||||
|
||||
type Callback = () => Promise<void> | void;
|
||||
|
||||
export type StateCallback = (state: SaveState) => void;
|
||||
|
||||
export default class SpacedUpdate {
|
||||
private updater: Callback;
|
||||
private lastUpdated: number;
|
||||
private changed: boolean;
|
||||
private updateInterval: number;
|
||||
private changeForbidden?: boolean;
|
||||
private stateCallback?: StateCallback;
|
||||
|
||||
constructor(updater: Callback, updateInterval = 1000) {
|
||||
constructor(updater: Callback, updateInterval = 1000, stateCallback?: StateCallback) {
|
||||
this.updater = updater;
|
||||
this.lastUpdated = Date.now();
|
||||
this.changed = false;
|
||||
this.updateInterval = updateInterval;
|
||||
this.stateCallback = stateCallback;
|
||||
}
|
||||
|
||||
scheduleUpdate() {
|
||||
if (!this.changeForbidden) {
|
||||
this.changed = true;
|
||||
this.stateCallback?.("unsaved");
|
||||
setTimeout(() => this.triggerUpdate());
|
||||
}
|
||||
}
|
||||
@@ -26,10 +34,13 @@ export default class SpacedUpdate {
|
||||
this.changed = false; // optimistic...
|
||||
|
||||
try {
|
||||
this.stateCallback?.("saving");
|
||||
await this.updater();
|
||||
this.stateCallback?.("saved");
|
||||
} catch (e) {
|
||||
this.changed = true;
|
||||
|
||||
this.stateCallback?.("error");
|
||||
logError(getErrorMessage(e));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@@ -59,15 +70,22 @@ export default class SpacedUpdate {
|
||||
this.updateInterval = interval;
|
||||
}
|
||||
|
||||
triggerUpdate() {
|
||||
async triggerUpdate() {
|
||||
if (!this.changed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Date.now() - this.lastUpdated > this.updateInterval) {
|
||||
this.updater();
|
||||
this.stateCallback?.("saving");
|
||||
try {
|
||||
await this.updater();
|
||||
this.stateCallback?.("saved");
|
||||
this.changed = false;
|
||||
} catch (e) {
|
||||
this.stateCallback?.("error");
|
||||
logError(getErrorMessage(e));
|
||||
}
|
||||
this.lastUpdated = Date.now();
|
||||
this.changed = false;
|
||||
} else {
|
||||
// update isn't triggered but changes are still pending, so we need to schedule another check
|
||||
this.scheduleUpdate();
|
||||
|
||||
@@ -1,121 +1,111 @@
|
||||
import utils from "./utils.js";
|
||||
import { signal } from "@preact/signals";
|
||||
|
||||
import appContext from "../components/app_context.js";
|
||||
import froca from "./froca.js";
|
||||
import { t } from "./i18n.js";
|
||||
import utils, { randomString } from "./utils.js";
|
||||
|
||||
export interface ToastOptions {
|
||||
id?: string;
|
||||
icon: string;
|
||||
title?: string;
|
||||
message: string;
|
||||
delay?: number;
|
||||
autohide?: boolean;
|
||||
closeAfter?: number;
|
||||
timeout?: number;
|
||||
progress?: number;
|
||||
buttons?: {
|
||||
text: string;
|
||||
onClick: (api: { dismissToast: () => void }) => void;
|
||||
}[];
|
||||
}
|
||||
|
||||
function toast({ title, icon, message, id, delay, autohide, progress }: ToastOptions) {
|
||||
const $toast = $(title
|
||||
? `\
|
||||
<div class="toast" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
<div class="toast-header">
|
||||
<strong class="me-auto">
|
||||
<span class="bx bx-${icon}"></span>
|
||||
<span class="toast-title"></span>
|
||||
</strong>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="toast-body"></div>
|
||||
<div class="toast-progress"></div>
|
||||
</div>`
|
||||
: `
|
||||
<div class="toast" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
<div class="toast-icon">
|
||||
<span class="bx bx-${icon}"></span>
|
||||
</div>
|
||||
<div class="toast-body"></div>
|
||||
<div class="toast-header">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="toast-progress"></div>
|
||||
</div>`
|
||||
);
|
||||
export type ToastOptionsWithRequiredId = Omit<ToastOptions, "id"> & Required<Pick<ToastOptions, "id">>;
|
||||
|
||||
$toast.toggleClass("no-title", !title);
|
||||
$toast.find(".toast-title").text(title ?? "");
|
||||
$toast.find(".toast-body").html(message);
|
||||
$toast.find(".toast-progress").css("width", `${(progress ?? 0) * 100}%`);
|
||||
|
||||
if (id) {
|
||||
$toast.attr("id", `toast-${id}`);
|
||||
}
|
||||
|
||||
$("#toast-container").append($toast);
|
||||
|
||||
$toast.toast({
|
||||
delay: delay || 3000,
|
||||
autohide: !!autohide
|
||||
});
|
||||
|
||||
$toast.on("hidden.bs.toast", (e) => e.target.remove());
|
||||
|
||||
$toast.toast("show");
|
||||
|
||||
return $toast;
|
||||
}
|
||||
|
||||
function showPersistent(options: ToastOptions) {
|
||||
let $toast = $(`#toast-${options.id}`);
|
||||
|
||||
if ($toast.length > 0) {
|
||||
$toast.find(".toast-body").html(options.message);
|
||||
$toast.find(".toast-progress").css("width", `${(options.progress ?? 0) * 100}%`);
|
||||
function showPersistent(options: ToastOptionsWithRequiredId) {
|
||||
const existingToast = toasts.value.find(toast => toast.id === options.id);
|
||||
if (existingToast) {
|
||||
updateToast(options.id, options);
|
||||
} else {
|
||||
options.autohide = false;
|
||||
|
||||
$toast = toast(options);
|
||||
}
|
||||
|
||||
if (options.closeAfter) {
|
||||
setTimeout(() => $toast.remove(), options.closeAfter);
|
||||
addToast(options);
|
||||
}
|
||||
}
|
||||
|
||||
function closePersistent(id: string) {
|
||||
$(`#toast-${id}`).remove();
|
||||
removeToastFromStore(id);
|
||||
}
|
||||
|
||||
function showMessage(message: string, delay = 2000, icon = "check") {
|
||||
function showMessage(message: string, timeout = 2000, icon = "bx bx-check") {
|
||||
console.debug(utils.now(), "message:", message);
|
||||
|
||||
toast({
|
||||
addToast({
|
||||
icon,
|
||||
message: message,
|
||||
autohide: true,
|
||||
delay
|
||||
message,
|
||||
timeout
|
||||
});
|
||||
}
|
||||
|
||||
export function showError(message: string, delay = 10000) {
|
||||
export function showError(message: string, timeout = 10000) {
|
||||
console.log(utils.now(), "error: ", message);
|
||||
|
||||
toast({
|
||||
icon: "alert",
|
||||
message: message,
|
||||
autohide: true,
|
||||
delay
|
||||
addToast({
|
||||
icon: "bx bx-error-circle",
|
||||
message,
|
||||
timeout
|
||||
});
|
||||
}
|
||||
|
||||
function showErrorTitleAndMessage(title: string, message: string, delay = 10000) {
|
||||
function showErrorTitleAndMessage(title: string, message: string, timeout = 10000) {
|
||||
console.log(utils.now(), "error: ", message);
|
||||
|
||||
toast({
|
||||
title: title,
|
||||
icon: "alert",
|
||||
message: message,
|
||||
autohide: true,
|
||||
delay
|
||||
addToast({
|
||||
title,
|
||||
icon: "bx bx-error-circle",
|
||||
message,
|
||||
timeout
|
||||
});
|
||||
}
|
||||
|
||||
export async function showErrorForScriptNote(noteId: string, message: string) {
|
||||
const note = await froca.getNote(noteId, true);
|
||||
|
||||
showPersistent({
|
||||
id: `custom-widget-failure-${noteId}`,
|
||||
title: t("toast.scripting-error", { title: note?.title ?? "" }),
|
||||
icon: note?.getIcon() ?? "bx bx-error-circle",
|
||||
message,
|
||||
timeout: 15_000,
|
||||
buttons: [
|
||||
{
|
||||
text: t("toast.open-script-note"),
|
||||
onClick: () => appContext.tabManager.openInNewTab(noteId, null, true)
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
//#region Toast store
|
||||
export const toasts = signal<ToastOptionsWithRequiredId[]>([]);
|
||||
|
||||
function addToast(opts: ToastOptions) {
|
||||
const id = opts.id ?? randomString();
|
||||
const toast = { ...opts, id };
|
||||
toasts.value = [ ...toasts.value, toast ];
|
||||
return id;
|
||||
}
|
||||
|
||||
function updateToast(id: string, partial: Partial<ToastOptions>) {
|
||||
toasts.value = toasts.value.map(toast => {
|
||||
if (toast.id === id) {
|
||||
return { ...toast, ...partial };
|
||||
}
|
||||
return toast;
|
||||
});
|
||||
}
|
||||
|
||||
export function removeToastFromStore(id: string) {
|
||||
toasts.value = toasts.value.filter(toast => toast.id !== id);
|
||||
}
|
||||
//#endregion
|
||||
|
||||
export default {
|
||||
showMessage,
|
||||
showError,
|
||||
|
||||
@@ -4,6 +4,8 @@ import froca from "./froca.js";
|
||||
import hoistedNoteService from "./hoisted_note.js";
|
||||
import appContext from "../components/app_context.js";
|
||||
|
||||
export const NOTE_PATH_TITLE_SEPARATOR = " › ";
|
||||
|
||||
async function resolveNotePath(notePath: string, hoistedNoteId = "root") {
|
||||
const runPath = await resolveNotePathToSegments(notePath, hoistedNoteId);
|
||||
|
||||
@@ -254,7 +256,7 @@ async function getNotePathTitle(notePath: string) {
|
||||
|
||||
const titlePath = await getNotePathTitleComponents(notePath);
|
||||
|
||||
return titlePath.join(" / ");
|
||||
return titlePath.join(NOTE_PATH_TITLE_SEPARATOR);
|
||||
}
|
||||
|
||||
async function getNoteTitleWithPathAsSuffix(notePath: string) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { dayjs } from "@triliumnext/commons";
|
||||
import type { ViewScope } from "./link.js";
|
||||
import { snapdom } from "@zumer/snapdom";
|
||||
|
||||
import FNote from "../entities/fnote";
|
||||
import type { ViewMode, ViewScope } from "./link.js";
|
||||
|
||||
const SVG_MIME = "image/svg+xml";
|
||||
|
||||
@@ -112,9 +114,8 @@ function formatDateISO(date: Date) {
|
||||
export function formatDateTime(date: Date, userSuppliedFormat?: string): string {
|
||||
if (userSuppliedFormat?.trim()) {
|
||||
return dayjs(date).format(userSuppliedFormat);
|
||||
} else {
|
||||
return `${formatDate(date)} ${formatTime(date)}`;
|
||||
}
|
||||
return `${formatDate(date)} ${formatTime(date)}`;
|
||||
}
|
||||
|
||||
function localNowDateTime() {
|
||||
@@ -150,7 +151,7 @@ export function isMac() {
|
||||
|
||||
export const hasTouchBar = (isMac() && isElectron());
|
||||
|
||||
function isCtrlKey(evt: KeyboardEvent | MouseEvent | JQuery.ClickEvent | JQuery.ContextMenuEvent | JQuery.TriggeredEvent | React.PointerEvent<HTMLCanvasElement> | JQueryEventObject) {
|
||||
export function isCtrlKey(evt: KeyboardEvent | MouseEvent | JQuery.ClickEvent | JQuery.ContextMenuEvent | JQuery.TriggeredEvent | React.PointerEvent<HTMLCanvasElement> | JQueryEventObject) {
|
||||
return (!isMac() && evt.ctrlKey) || (isMac() && evt.metaKey);
|
||||
}
|
||||
|
||||
@@ -186,13 +187,15 @@ export function formatSize(size: number | null | undefined) {
|
||||
return "";
|
||||
}
|
||||
|
||||
size = Math.max(Math.round(size / 1024), 1);
|
||||
|
||||
if (size < 1024) {
|
||||
return `${size} KiB`;
|
||||
} else {
|
||||
return `${Math.round(size / 102.4) / 10} MiB`;
|
||||
if (size === 0) {
|
||||
return "0 B";
|
||||
}
|
||||
|
||||
const k = 1024;
|
||||
const sizes = ["B", "KiB", "MiB", "GiB"];
|
||||
const i = Math.floor(Math.log(size) / Math.log(k));
|
||||
|
||||
return `${Math.round((size / Math.pow(k, i)) * 100) / 100} ${sizes[i]}`;
|
||||
}
|
||||
|
||||
function toObject<T, R>(array: T[], fn: (arg0: T) => [key: string, value: R]) {
|
||||
@@ -207,7 +210,7 @@ function toObject<T, R>(array: T[], fn: (arg0: T) => [key: string, value: R]) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
export function randomString(len: number) {
|
||||
export function randomString(len: number = 16) {
|
||||
let text = "";
|
||||
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
@@ -236,7 +239,7 @@ export function isIOS() {
|
||||
return /iPad|iPhone|iPod/.test(navigator.userAgent);
|
||||
}
|
||||
|
||||
function isDesktop() {
|
||||
export function isDesktop() {
|
||||
return (
|
||||
window.glob?.device === "desktop" ||
|
||||
// window.glob.device is not available in setup
|
||||
@@ -296,18 +299,18 @@ function formatHtml(html: string) {
|
||||
let indent = "\n";
|
||||
const tab = "\t";
|
||||
let i = 0;
|
||||
let pre: { indent: string; tag: string }[] = [];
|
||||
const pre: { indent: string; tag: string }[] = [];
|
||||
|
||||
html = html
|
||||
.replace(new RegExp("<pre>([\\s\\S]+?)?</pre>"), function (x) {
|
||||
.replace(new RegExp("<pre>([\\s\\S]+?)?</pre>"), (x) => {
|
||||
pre.push({ indent: "", tag: x });
|
||||
return "<--TEMPPRE" + i++ + "/-->";
|
||||
return `<--TEMPPRE${i++}/-->`;
|
||||
})
|
||||
.replace(new RegExp("<[^<>]+>[^<]?", "g"), function (x) {
|
||||
.replace(new RegExp("<[^<>]+>[^<]?", "g"), (x) => {
|
||||
let ret;
|
||||
const tagRegEx = /<\/?([^\s/>]+)/.exec(x);
|
||||
let tag = tagRegEx ? tagRegEx[1] : "";
|
||||
let p = new RegExp("<--TEMPPRE(\\d+)/-->").exec(x);
|
||||
const tag = tagRegEx ? tagRegEx[1] : "";
|
||||
const p = new RegExp("<--TEMPPRE(\\d+)/-->").exec(x);
|
||||
|
||||
if (p) {
|
||||
const pInd = parseInt(p[1]);
|
||||
@@ -317,24 +320,22 @@ function formatHtml(html: string) {
|
||||
if (["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "menuitem", "meta", "param", "source", "track", "wbr"].indexOf(tag) >= 0) {
|
||||
// self closing tag
|
||||
ret = indent + x;
|
||||
} else if (x.indexOf("</") < 0) {
|
||||
//open tag
|
||||
if (x.charAt(x.length - 1) !== ">") ret = indent + x.substr(0, x.length - 1) + indent + tab + x.substr(x.length - 1, x.length);
|
||||
else ret = indent + x;
|
||||
!p && (indent += tab);
|
||||
} else {
|
||||
if (x.indexOf("</") < 0) {
|
||||
//open tag
|
||||
if (x.charAt(x.length - 1) !== ">") ret = indent + x.substr(0, x.length - 1) + indent + tab + x.substr(x.length - 1, x.length);
|
||||
else ret = indent + x;
|
||||
!p && (indent += tab);
|
||||
} else {
|
||||
//close tag
|
||||
indent = indent.substr(0, indent.length - 1);
|
||||
if (x.charAt(x.length - 1) !== ">") ret = indent + x.substr(0, x.length - 1) + indent + x.substr(x.length - 1, x.length);
|
||||
else ret = indent + x;
|
||||
}
|
||||
//close tag
|
||||
indent = indent.substr(0, indent.length - 1);
|
||||
if (x.charAt(x.length - 1) !== ">") ret = indent + x.substr(0, x.length - 1) + indent + x.substr(x.length - 1, x.length);
|
||||
else ret = indent + x;
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
|
||||
for (i = pre.length; i--;) {
|
||||
html = html.replace("<--TEMPPRE" + i + "/-->", pre[i].tag.replace("<pre>", "<pre>\n").replace("</pre>", pre[i].indent + "</pre>"));
|
||||
html = html.replace(`<--TEMPPRE${i}/-->`, pre[i].tag.replace("<pre>", "<pre>\n").replace("</pre>", `${pre[i].indent}</pre>`));
|
||||
}
|
||||
|
||||
return html.charAt(0) === "\n" ? html.substr(1, html.length - 1) : html;
|
||||
@@ -363,11 +364,11 @@ type dynamicRequireMappings = {
|
||||
export function dynamicRequire<T extends keyof dynamicRequireMappings>(moduleName: T): Awaited<dynamicRequireMappings[T]>{
|
||||
if (typeof __non_webpack_require__ !== "undefined") {
|
||||
return __non_webpack_require__(moduleName);
|
||||
} else {
|
||||
// explicitly pass as string and not as expression to suppress webpack warning
|
||||
// 'Critical dependency: the request of a dependency is an expression'
|
||||
return require(`${moduleName}`);
|
||||
}
|
||||
// explicitly pass as string and not as expression to suppress webpack warning
|
||||
// 'Critical dependency: the request of a dependency is an expression'
|
||||
return require(`${moduleName}`);
|
||||
|
||||
}
|
||||
|
||||
function timeLimit<T>(promise: Promise<T>, limitMs: number, errorMessage?: string) {
|
||||
@@ -438,7 +439,20 @@ async function openInAppHelp($button: JQuery<HTMLElement>) {
|
||||
* @param inAppHelpPage the ID of the help note (excluding the `_help_` prefix).
|
||||
* @returns a promise that resolves once the help has been opened.
|
||||
*/
|
||||
export async function openInAppHelpFromUrl(inAppHelpPage: string) {
|
||||
export function openInAppHelpFromUrl(inAppHelpPage: string) {
|
||||
return openInReusableSplit(`_help_${inAppHelpPage}`, "contextual-help");
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to opening a new note in a split, but re-uses an existing split if there is already one open with the same view mode.
|
||||
*
|
||||
* @param targetNoteId the note ID to open in the split.
|
||||
* @param targetViewMode the view mode of the split to open the note in.
|
||||
* @param openOpts additional options for opening the note.
|
||||
*/
|
||||
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();
|
||||
@@ -446,23 +460,20 @@ export async function openInAppHelpFromUrl(inAppHelpPage: string) {
|
||||
return;
|
||||
}
|
||||
const subContexts = activeContext.getSubContexts();
|
||||
const targetNote = `_help_${inAppHelpPage}`;
|
||||
const helpSubcontext = subContexts.find((s) => s.viewScope?.viewMode === "contextual-help");
|
||||
const viewScope: ViewScope = {
|
||||
viewMode: "contextual-help",
|
||||
};
|
||||
if (!helpSubcontext) {
|
||||
// The help is not already open, open a new split with it.
|
||||
const existingSubcontext = subContexts.find((s) => s.viewScope?.viewMode === targetViewMode);
|
||||
const viewScope: ViewScope = { viewMode: 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", {
|
||||
ntxId,
|
||||
notePath: targetNote,
|
||||
hoistedNoteId: "_help",
|
||||
notePath: targetNoteId,
|
||||
hoistedNoteId: openOpts.hoistedNoteId,
|
||||
viewScope
|
||||
})
|
||||
});
|
||||
} else {
|
||||
// There is already a help window open, make sure it opens on the right note.
|
||||
helpSubcontext.setNote(targetNote, { viewScope });
|
||||
// There is already a target split open, make sure it opens on the right note.
|
||||
existingSubcontext.setNote(targetNoteId, { viewScope });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -498,8 +509,8 @@ export function escapeRegExp(str: string) {
|
||||
function areObjectsEqual(...args: unknown[]) {
|
||||
let i;
|
||||
let l;
|
||||
let leftChain: Object[];
|
||||
let rightChain: Object[];
|
||||
let leftChain: object[];
|
||||
let rightChain: object[];
|
||||
|
||||
function compare2Objects(x: unknown, y: unknown) {
|
||||
let p;
|
||||
@@ -628,16 +639,69 @@ export function createImageSrcUrl(note: FNote) {
|
||||
return `api/images/${note.noteId}/${encodeURIComponent(note.title)}?timestamp=${Date.now()}`;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Given a string representation of an SVG, triggers a download of the file on the client device.
|
||||
* Helper function to prepare an element for snapdom rendering.
|
||||
* Handles string parsing and temporary DOM attachment for style computation.
|
||||
*
|
||||
* @param source - Either an SVG/HTML string to be parsed, or an existing SVG/HTML element.
|
||||
* @returns An object containing the prepared element and a cleanup function.
|
||||
* The cleanup function removes temporarily attached elements from the DOM,
|
||||
* or is a no-op if the element was already in the DOM.
|
||||
*/
|
||||
function prepareElementForSnapdom(source: string | SVGElement | HTMLElement): {
|
||||
element: SVGElement | HTMLElement;
|
||||
cleanup: () => void;
|
||||
} {
|
||||
if (typeof source === 'string') {
|
||||
const parser = new DOMParser();
|
||||
|
||||
// Detect if content is SVG or HTML
|
||||
const isSvg = source.trim().startsWith('<svg');
|
||||
const mimeType = isSvg ? SVG_MIME : 'text/html';
|
||||
|
||||
const doc = parser.parseFromString(source, mimeType);
|
||||
const element = doc.documentElement;
|
||||
|
||||
// Temporarily attach to DOM for proper style computation
|
||||
element.style.position = 'absolute';
|
||||
element.style.left = '-9999px';
|
||||
element.style.top = '-9999px';
|
||||
document.body.appendChild(element);
|
||||
|
||||
return {
|
||||
element,
|
||||
cleanup: () => document.body.removeChild(element)
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
element: source,
|
||||
cleanup: () => {} // No-op for existing elements
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads an SVG using snapdom for proper rendering. Can accept either an SVG string, an SVG element, or an HTML element.
|
||||
*
|
||||
* @param nameWithoutExtension the name of the file. The .svg suffix is automatically added to it.
|
||||
* @param svgContent the content of the SVG file download.
|
||||
* @param svgSource either an SVG string, an SVGElement, or an HTMLElement to be downloaded.
|
||||
*/
|
||||
function downloadSvg(nameWithoutExtension: string, svgContent: string) {
|
||||
const filename = `${nameWithoutExtension}.svg`;
|
||||
const dataUrl = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgContent)}`;
|
||||
triggerDownload(filename, dataUrl);
|
||||
async function downloadAsSvg(nameWithoutExtension: string, svgSource: string | SVGElement | HTMLElement) {
|
||||
const { element, cleanup } = prepareElementForSnapdom(svgSource);
|
||||
|
||||
try {
|
||||
const result = await snapdom(element, {
|
||||
backgroundColor: "transparent",
|
||||
scale: 2
|
||||
});
|
||||
triggerDownload(`${nameWithoutExtension}.svg`, result.url);
|
||||
} finally {
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -658,62 +722,26 @@ function triggerDownload(fileName: string, dataUrl: string) {
|
||||
|
||||
document.body.removeChild(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string representation of an SVG, renders the SVG to PNG and triggers a download of the file on the client device.
|
||||
*
|
||||
* Note that the SVG must specify its width and height as attributes in order for it to be rendered.
|
||||
* Downloads an SVG as PNG using snapdom. Can accept either an SVG string, an SVG element, or an HTML element.
|
||||
*
|
||||
* @param nameWithoutExtension the name of the file. The .png suffix is automatically added to it.
|
||||
* @param svgContent the content of the SVG file download.
|
||||
* @returns a promise which resolves if the operation was successful, or rejects if it failed (permissions issue or some other issue).
|
||||
* @param svgSource either an SVG string, an SVGElement, or an HTMLElement to be converted to PNG.
|
||||
*/
|
||||
function downloadSvgAsPng(nameWithoutExtension: string, svgContent: string) {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
// First, we need to determine the width and the height from the input SVG.
|
||||
const result = getSizeFromSvg(svgContent);
|
||||
if (!result) {
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
async function downloadAsPng(nameWithoutExtension: string, svgSource: string | SVGElement | HTMLElement) {
|
||||
const { element, cleanup } = prepareElementForSnapdom(svgSource);
|
||||
|
||||
// Convert the image to a blob.
|
||||
const { width, height } = result;
|
||||
|
||||
// Create an image element and load the SVG.
|
||||
const imageEl = new Image();
|
||||
imageEl.width = width;
|
||||
imageEl.height = height;
|
||||
imageEl.crossOrigin = "anonymous";
|
||||
imageEl.onload = () => {
|
||||
try {
|
||||
// Draw the image with a canvas.
|
||||
const canvasEl = document.createElement("canvas");
|
||||
canvasEl.width = imageEl.width;
|
||||
canvasEl.height = imageEl.height;
|
||||
document.body.appendChild(canvasEl);
|
||||
|
||||
const ctx = canvasEl.getContext("2d");
|
||||
if (!ctx) {
|
||||
reject();
|
||||
}
|
||||
|
||||
ctx?.drawImage(imageEl, 0, 0);
|
||||
|
||||
const imgUri = canvasEl.toDataURL("image/png")
|
||||
triggerDownload(`${nameWithoutExtension}.png`, imgUri);
|
||||
document.body.removeChild(canvasEl);
|
||||
resolve();
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
reject();
|
||||
}
|
||||
};
|
||||
imageEl.onerror = (e) => reject(e);
|
||||
imageEl.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgContent)}`;
|
||||
});
|
||||
try {
|
||||
const result = await snapdom(element, {
|
||||
backgroundColor: "transparent",
|
||||
scale: 2
|
||||
});
|
||||
const pngImg = await result.toPng();
|
||||
await triggerDownload(`${nameWithoutExtension}.png`, pngImg.src);
|
||||
} finally {
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
export function getSizeFromSvg(svgContent: string) {
|
||||
const svgDocument = (new DOMParser()).parseFromString(svgContent, SVG_MIME);
|
||||
|
||||
@@ -735,11 +763,11 @@ export function getSizeFromSvg(svgContent: string) {
|
||||
return {
|
||||
width: parseFloat(width),
|
||||
height: parseFloat(height)
|
||||
}
|
||||
} else {
|
||||
console.warn("SVG export error", svgDocument.documentElement);
|
||||
return null;
|
||||
};
|
||||
}
|
||||
console.warn("SVG export error", svgDocument.documentElement);
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -868,9 +896,9 @@ export function mapToKeyValueArray<K extends string | number | symbol, V>(map: R
|
||||
export function getErrorMessage(e: unknown) {
|
||||
if (e && typeof e === "object" && "message" in e && typeof e.message === "string") {
|
||||
return e.message;
|
||||
} else {
|
||||
return "Unknown error";
|
||||
}
|
||||
return "Unknown error";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -925,8 +953,8 @@ export default {
|
||||
areObjectsEqual,
|
||||
copyHtmlToClipboard,
|
||||
createImageSrcUrl,
|
||||
downloadSvg,
|
||||
downloadSvgAsPng,
|
||||
downloadAsSvg,
|
||||
downloadAsPng,
|
||||
compareVersions,
|
||||
isUpdateAvailable,
|
||||
isLaunchBarConfig
|
||||
|
||||
498
apps/client/src/stylesheets/boxicons-compat.css
Normal file
498
apps/client/src/stylesheets/boxicons-compat.css
Normal file
@@ -0,0 +1,498 @@
|
||||
.bx-ul
|
||||
{
|
||||
margin-left: 2em;
|
||||
padding-left: 0;
|
||||
|
||||
list-style: none;
|
||||
}
|
||||
.bx-ul > li
|
||||
{
|
||||
position: relative;
|
||||
}
|
||||
.bx-ul .bx
|
||||
{
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
|
||||
position: absolute;
|
||||
left: -2em;
|
||||
|
||||
width: 2em;
|
||||
|
||||
text-align: center;
|
||||
}
|
||||
@-webkit-keyframes spin
|
||||
{
|
||||
0%
|
||||
{
|
||||
-webkit-transform: rotate(0);
|
||||
transform: rotate(0);
|
||||
}
|
||||
100%
|
||||
{
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
@keyframes spin
|
||||
{
|
||||
0%
|
||||
{
|
||||
-webkit-transform: rotate(0);
|
||||
transform: rotate(0);
|
||||
}
|
||||
100%
|
||||
{
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes burst
|
||||
{
|
||||
0%
|
||||
{
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
90%
|
||||
{
|
||||
-webkit-transform: scale(1.5);
|
||||
transform: scale(1.5);
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes burst
|
||||
{
|
||||
0%
|
||||
{
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
90%
|
||||
{
|
||||
-webkit-transform: scale(1.5);
|
||||
transform: scale(1.5);
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes flashing
|
||||
{
|
||||
0%
|
||||
{
|
||||
opacity: 1;
|
||||
}
|
||||
45%
|
||||
{
|
||||
opacity: 0;
|
||||
}
|
||||
90%
|
||||
{
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes flashing
|
||||
{
|
||||
0%
|
||||
{
|
||||
opacity: 1;
|
||||
}
|
||||
45%
|
||||
{
|
||||
opacity: 0;
|
||||
}
|
||||
90%
|
||||
{
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fade-left
|
||||
{
|
||||
0%
|
||||
{
|
||||
-webkit-transform: translateX(0);
|
||||
transform: translateX(0);
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
75%
|
||||
{
|
||||
-webkit-transform: translateX(-20px);
|
||||
transform: translateX(-20px);
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes fade-left
|
||||
{
|
||||
0%
|
||||
{
|
||||
-webkit-transform: translateX(0);
|
||||
transform: translateX(0);
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
75%
|
||||
{
|
||||
-webkit-transform: translateX(-20px);
|
||||
transform: translateX(-20px);
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fade-right
|
||||
{
|
||||
0%
|
||||
{
|
||||
-webkit-transform: translateX(0);
|
||||
transform: translateX(0);
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
75%
|
||||
{
|
||||
-webkit-transform: translateX(20px);
|
||||
transform: translateX(20px);
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes fade-right
|
||||
{
|
||||
0%
|
||||
{
|
||||
-webkit-transform: translateX(0);
|
||||
transform: translateX(0);
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
75%
|
||||
{
|
||||
-webkit-transform: translateX(20px);
|
||||
transform: translateX(20px);
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fade-up
|
||||
{
|
||||
0%
|
||||
{
|
||||
-webkit-transform: translateY(0);
|
||||
transform: translateY(0);
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
75%
|
||||
{
|
||||
-webkit-transform: translateY(-20px);
|
||||
transform: translateY(-20px);
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes fade-up
|
||||
{
|
||||
0%
|
||||
{
|
||||
-webkit-transform: translateY(0);
|
||||
transform: translateY(0);
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
75%
|
||||
{
|
||||
-webkit-transform: translateY(-20px);
|
||||
transform: translateY(-20px);
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fade-down
|
||||
{
|
||||
0%
|
||||
{
|
||||
-webkit-transform: translateY(0);
|
||||
transform: translateY(0);
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
75%
|
||||
{
|
||||
-webkit-transform: translateY(20px);
|
||||
transform: translateY(20px);
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes fade-down
|
||||
{
|
||||
0%
|
||||
{
|
||||
-webkit-transform: translateY(0);
|
||||
transform: translateY(0);
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
75%
|
||||
{
|
||||
-webkit-transform: translateY(20px);
|
||||
transform: translateY(20px);
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes tada
|
||||
{
|
||||
from
|
||||
{
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
|
||||
10%,
|
||||
20%
|
||||
{
|
||||
-webkit-transform: scale3d(.95, .95, .95) rotate3d(0, 0, 1, -10deg);
|
||||
transform: scale3d(.95, .95, .95) rotate3d(0, 0, 1, -10deg);
|
||||
}
|
||||
|
||||
30%,
|
||||
50%,
|
||||
70%,
|
||||
90%
|
||||
{
|
||||
-webkit-transform: scale3d(1, 1, 1) rotate3d(0, 0, 1, 10deg);
|
||||
transform: scale3d(1, 1, 1) rotate3d(0, 0, 1, 10deg);
|
||||
}
|
||||
|
||||
40%,
|
||||
60%,
|
||||
80%
|
||||
{
|
||||
-webkit-transform: scale3d(1, 1, 1) rotate3d(0, 0, 1, -10deg);
|
||||
transform: scale3d(1, 1, 1) rotate3d(0, 0, 1, -10deg);
|
||||
}
|
||||
|
||||
to
|
||||
{
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tada
|
||||
{
|
||||
from
|
||||
{
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
|
||||
10%,
|
||||
20%
|
||||
{
|
||||
-webkit-transform: scale3d(.95, .95, .95) rotate3d(0, 0, 1, -10deg);
|
||||
transform: scale3d(.95, .95, .95) rotate3d(0, 0, 1, -10deg);
|
||||
}
|
||||
|
||||
30%,
|
||||
50%,
|
||||
70%,
|
||||
90%
|
||||
{
|
||||
-webkit-transform: scale3d(1, 1, 1) rotate3d(0, 0, 1, 10deg);
|
||||
transform: scale3d(1, 1, 1) rotate3d(0, 0, 1, 10deg);
|
||||
}
|
||||
|
||||
40%,
|
||||
60%,
|
||||
80%
|
||||
{
|
||||
-webkit-transform: rotate3d(0, 0, 1, -10deg);
|
||||
transform: rotate3d(0, 0, 1, -10deg);
|
||||
}
|
||||
|
||||
to
|
||||
{
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
.bx-spin
|
||||
{
|
||||
-webkit-animation: spin 2s linear infinite;
|
||||
animation: spin 2s linear infinite;
|
||||
}
|
||||
.bx-spin-hover:hover
|
||||
{
|
||||
-webkit-animation: spin 2s linear infinite;
|
||||
animation: spin 2s linear infinite;
|
||||
}
|
||||
|
||||
.bx-tada
|
||||
{
|
||||
-webkit-animation: tada 1.5s ease infinite;
|
||||
animation: tada 1.5s ease infinite;
|
||||
}
|
||||
.bx-tada-hover:hover
|
||||
{
|
||||
-webkit-animation: tada 1.5s ease infinite;
|
||||
animation: tada 1.5s ease infinite;
|
||||
}
|
||||
|
||||
.bx-flashing
|
||||
{
|
||||
-webkit-animation: flashing 1.5s infinite linear;
|
||||
animation: flashing 1.5s infinite linear;
|
||||
}
|
||||
.bx-flashing-hover:hover
|
||||
{
|
||||
-webkit-animation: flashing 1.5s infinite linear;
|
||||
animation: flashing 1.5s infinite linear;
|
||||
}
|
||||
|
||||
.bx-burst
|
||||
{
|
||||
-webkit-animation: burst 1.5s infinite linear;
|
||||
animation: burst 1.5s infinite linear;
|
||||
}
|
||||
.bx-burst-hover:hover
|
||||
{
|
||||
-webkit-animation: burst 1.5s infinite linear;
|
||||
animation: burst 1.5s infinite linear;
|
||||
}
|
||||
.bx-fade-up
|
||||
{
|
||||
-webkit-animation: fade-up 1.5s infinite linear;
|
||||
animation: fade-up 1.5s infinite linear;
|
||||
}
|
||||
.bx-fade-up-hover:hover
|
||||
{
|
||||
-webkit-animation: fade-up 1.5s infinite linear;
|
||||
animation: fade-up 1.5s infinite linear;
|
||||
}
|
||||
.bx-fade-down
|
||||
{
|
||||
-webkit-animation: fade-down 1.5s infinite linear;
|
||||
animation: fade-down 1.5s infinite linear;
|
||||
}
|
||||
.bx-fade-down-hover:hover
|
||||
{
|
||||
-webkit-animation: fade-down 1.5s infinite linear;
|
||||
animation: fade-down 1.5s infinite linear;
|
||||
}
|
||||
.bx-fade-left
|
||||
{
|
||||
-webkit-animation: fade-left 1.5s infinite linear;
|
||||
animation: fade-left 1.5s infinite linear;
|
||||
}
|
||||
.bx-fade-left-hover:hover
|
||||
{
|
||||
-webkit-animation: fade-left 1.5s infinite linear;
|
||||
animation: fade-left 1.5s infinite linear;
|
||||
}
|
||||
.bx-fade-right
|
||||
{
|
||||
-webkit-animation: fade-right 1.5s infinite linear;
|
||||
animation: fade-right 1.5s infinite linear;
|
||||
}
|
||||
.bx-fade-right-hover:hover
|
||||
{
|
||||
-webkit-animation: fade-right 1.5s infinite linear;
|
||||
animation: fade-right 1.5s infinite linear;
|
||||
}
|
||||
.bx-xs
|
||||
{
|
||||
font-size: 1rem!important;
|
||||
}
|
||||
.bx-sm
|
||||
{
|
||||
font-size: 1.55rem!important;
|
||||
}
|
||||
.bx-md
|
||||
{
|
||||
font-size: 2.25rem!important;
|
||||
}
|
||||
.bx-lg
|
||||
{
|
||||
font-size: 3.0rem!important;
|
||||
}
|
||||
.bx-fw
|
||||
{
|
||||
font-size: 1.2857142857em;
|
||||
line-height: .8em;
|
||||
|
||||
width: 1.2857142857em;
|
||||
height: .8em;
|
||||
margin-top: -.2em!important;
|
||||
|
||||
vertical-align: middle;
|
||||
}
|
||||
.bx-pull-left
|
||||
{
|
||||
float: left;
|
||||
|
||||
margin-right: .3em!important;
|
||||
}
|
||||
.bx-pull-right
|
||||
{
|
||||
float: right;
|
||||
|
||||
margin-left: .3em!important;
|
||||
}
|
||||
.bx-rotate-90
|
||||
{
|
||||
transform: rotate(90deg);
|
||||
|
||||
-ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=1)';
|
||||
}
|
||||
.bx-rotate-180
|
||||
{
|
||||
transform: rotate(180deg);
|
||||
|
||||
-ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=2)';
|
||||
}
|
||||
.bx-rotate-270
|
||||
{
|
||||
transform: rotate(270deg);
|
||||
|
||||
-ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=3)';
|
||||
}
|
||||
.bx-flip-horizontal
|
||||
{
|
||||
transform: scaleX(-1);
|
||||
|
||||
-ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)';
|
||||
}
|
||||
.bx-flip-vertical
|
||||
{
|
||||
transform: scaleY(-1);
|
||||
|
||||
-ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)';
|
||||
}
|
||||
.bx-border
|
||||
{
|
||||
padding: .25em;
|
||||
|
||||
border: .07em solid rgba(0,0,0,.1);
|
||||
border-radius: .25em;
|
||||
}
|
||||
.bx-border-circle
|
||||
{
|
||||
padding: .25em;
|
||||
|
||||
border: .07em solid rgba(0,0,0,.1);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
/** Custom icon **/
|
||||
.bx-empty {
|
||||
width: 1em;
|
||||
display: inline-block;
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
@import "./boxicons-compat.css";
|
||||
|
||||
@font-face {
|
||||
font-family: Montserrat;
|
||||
src: url(../fonts/Montserrat-Light.ttf);
|
||||
@@ -24,8 +26,8 @@
|
||||
--bs-body-font-family: var(--main-font-family) !important;
|
||||
--bs-body-font-weight: var(--main-font-weight) !important;
|
||||
--bs-body-color: var(--main-text-color) !important;
|
||||
--bs-body-bg: var(--main-background-color) !important;
|
||||
--ck-mention-list-max-height: 500px;
|
||||
--bs-body-bg: var(--main-background-color) !important;
|
||||
--ck-mention-list-max-height: 500px;
|
||||
--tn-modal-max-height: 90vh;
|
||||
|
||||
--tree-item-light-theme-max-color-lightness: 50;
|
||||
@@ -423,20 +425,19 @@ body.desktop .tabulator-popup-container,
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.dropdown-menu .disabled .disabled-tooltip {
|
||||
.dropdown-menu .disabled .contextual-help {
|
||||
pointer-events: all;
|
||||
margin-inline-start: 8px;
|
||||
font-size: 0.75rem;
|
||||
color: var(--disabled-tooltip-icon-color);
|
||||
color: var(--contextual-help-icon-color);
|
||||
cursor: help;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.dropdown-menu .disabled .disabled-tooltip:hover {
|
||||
.dropdown-menu .disabled .contextual-help:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.dropdown-menu a:hover:not(.disabled),
|
||||
.dropdown-item:hover:not(.disabled, .dropdown-container-item),
|
||||
.tabulator-menu-item:hover,
|
||||
:root .excalidraw .context-menu .context-menu-item:hover {
|
||||
@@ -458,6 +459,7 @@ body.desktop .tabulator-popup-container,
|
||||
}
|
||||
|
||||
body.desktop .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 {
|
||||
display: flex;
|
||||
@@ -471,7 +473,7 @@ body.mobile .dropdown .dropdown-submenu > span {
|
||||
padding-inline-start: 12px;
|
||||
}
|
||||
|
||||
.dropdown-menu kbd {
|
||||
.dropdown-menu kbd {
|
||||
color: var(--muted-text-color);
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
@@ -487,7 +489,7 @@ body.mobile .dropdown .dropdown-submenu > span {
|
||||
border: 1px solid transparent !important;
|
||||
}
|
||||
|
||||
/* This is a workaround for Firefox not supporting break-before / break-after: avoid on columns.
|
||||
/* This is a workaround for Firefox not supporting break-before / break-after: avoid on columns.
|
||||
* It usually wraps a menu item followed by a separator / header and another menu item. */
|
||||
.dropdown-no-break {
|
||||
break-inside: avoid;
|
||||
@@ -521,9 +523,7 @@ body.mobile .dropdown .dropdown-submenu > span {
|
||||
.cm-editor {
|
||||
height: 100%;
|
||||
outline: none !important;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
margin: 4px;
|
||||
font-size: var(--monospace-font-size);
|
||||
}
|
||||
|
||||
@@ -629,6 +629,11 @@ pre:not(.hljs) {
|
||||
padding: var(--padding-size);
|
||||
}
|
||||
|
||||
pre:has(> .cm-editor) {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
pre > button.copy-button {
|
||||
position: absolute;
|
||||
top: var(--copy-button-margin-size);
|
||||
@@ -720,6 +725,10 @@ table.promoted-attributes-in-tooltip th {
|
||||
z-index: 32767 !important;
|
||||
}
|
||||
|
||||
.pre-wrap-text {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.bs-tooltip-bottom .tooltip-arrow::before {
|
||||
border-bottom-color: var(--main-border-color) !important;
|
||||
}
|
||||
@@ -1015,15 +1024,9 @@ div[data-notify="container"] {
|
||||
font-family: var(--monospace-font-family);
|
||||
}
|
||||
|
||||
svg.ck-icon {
|
||||
&.ck-icon_inherit-color path[fill="#333"] {
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
&.note-icon {
|
||||
color: var(--main-text-color);
|
||||
font-size: 20px;
|
||||
}
|
||||
svg.ck-icon.note-icon {
|
||||
color: var(--main-text-color);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.ck-content {
|
||||
@@ -1127,11 +1130,6 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
|
||||
border-color: var(--main-border-color) !important;
|
||||
}
|
||||
|
||||
.bx-empty {
|
||||
width: 1em;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 0.5rem 1rem 0.5rem 1rem !important; /* make modal header padding slightly smaller */
|
||||
}
|
||||
@@ -1141,61 +1139,6 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
|
||||
margin: 0 12px;
|
||||
}
|
||||
|
||||
#toast-container {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 20px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.toast {
|
||||
--bs-toast-bg: var(--accented-background-color);
|
||||
--bs-toast-color: var(--main-text-color);
|
||||
z-index: 9999999999 !important;
|
||||
pointer-events: all;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.toast-header {
|
||||
background-color: var(--more-accented-background-color) !important;
|
||||
color: var(--main-text-color) !important;
|
||||
}
|
||||
|
||||
.toast-body {
|
||||
white-space: preserve-breaks;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.toast.no-title {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.toast.no-title .toast-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: var(--bs-toast-padding-y) var(--bs-toast-padding-x);
|
||||
}
|
||||
|
||||
.toast.no-title .toast-body {
|
||||
padding-inline-start: 0;
|
||||
padding-inline-end: 0;
|
||||
}
|
||||
|
||||
.toast.no-title .toast-header {
|
||||
background-color: unset !important;
|
||||
}
|
||||
|
||||
.toast .toast-progress {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: 0;
|
||||
background-color: var(--toast-text-color) !important;
|
||||
height: 4px;
|
||||
transition: width 0.1s linear;
|
||||
}
|
||||
|
||||
.ck-mentions .ck-button {
|
||||
font-size: var(--detail-font-size) !important;
|
||||
padding: 5px;
|
||||
@@ -1376,12 +1319,21 @@ body.desktop li.dropdown-submenu:hover > ul.dropdown-menu {
|
||||
top: 0;
|
||||
inset-inline-start: calc(100% - 2px); /* -2px, otherwise there's a small gap between menu and submenu where the hover can disappear */
|
||||
margin-top: -10px;
|
||||
min-width: 15rem;
|
||||
/* to make submenu scrollable https://github.com/zadam/trilium/issues/3136 */
|
||||
max-height: 600px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
body.desktop .dropdown-submenu > .dropdown-menu {
|
||||
min-width: max-content;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.dropdown-submenu.dropstart > .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);
|
||||
}
|
||||
@@ -1428,6 +1380,10 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
|
||||
background-color: var(--scrollbar-background-color);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-corner {
|
||||
background-color: inherit;
|
||||
}
|
||||
@@ -1652,7 +1608,7 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: 0;
|
||||
margin: 0 !important;
|
||||
max-height: 85vh;
|
||||
max-height: 85vh;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@@ -1840,7 +1796,7 @@ button.close:hover {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.reference-link .bx {
|
||||
.reference-link .tn-icon {
|
||||
position: relative;
|
||||
top: 1px;
|
||||
margin-inline-end: 3px;
|
||||
@@ -1992,6 +1948,10 @@ body.electron.platform-darwin:not(.native-titlebar) .tab-row-container {
|
||||
padding-inline-start: 1em;
|
||||
}
|
||||
|
||||
.tab-row-widget {
|
||||
contain: inline-size;
|
||||
}
|
||||
|
||||
#tab-row-left-spacer {
|
||||
width: env(titlebar-area-x);
|
||||
-webkit-app-region: drag;
|
||||
@@ -2001,7 +1961,7 @@ body.electron.platform-darwin:not(.native-titlebar):not(.full-screen) #tab-row-l
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.tab-row-widget {
|
||||
body.electron:not(.platform-darwin) .tab-row-container {
|
||||
padding-inline-end: calc(100vw - env(titlebar-area-width, 100vw));
|
||||
}
|
||||
|
||||
@@ -2052,8 +2012,10 @@ body.zen .shared-info-widget,
|
||||
body.zen .ribbon-container:not(:has(.classic-toolbar-widget)),
|
||||
body.zen .ribbon-container:has(.classic-toolbar-widget) .ribbon-top-row,
|
||||
body.zen .ribbon-container .ribbon-body:not(:has(.classic-toolbar-widget)),
|
||||
body.zen .note-icon-widget,
|
||||
body.zen .title-row .icon-action,
|
||||
body.zen .note-badges > *:not(.read-only-badge),
|
||||
body.zen .ribbon-button-container,
|
||||
body.zen .inline-title,
|
||||
body.zen .promoted-attributes-widget,
|
||||
body.zen .floating-buttons-children > *:not(.bx-edit-alt),
|
||||
body.zen .action-button,
|
||||
@@ -2076,11 +2038,11 @@ body.zen #launcher-pane {
|
||||
}
|
||||
|
||||
body.zen .title-row {
|
||||
display: block !important;
|
||||
height: unset !important;
|
||||
-webkit-app-region: drag;
|
||||
padding-inline-start: env(titlebar-area-x);
|
||||
padding-inline-end: calc(100vw - env(titlebar-area-width, 100vw) + 2.5em);
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
body.zen .floating-buttons {
|
||||
@@ -2100,8 +2062,6 @@ body.zen .floating-buttons-children .button-widget {
|
||||
body.zen .note-title-widget,
|
||||
body.zen .note-title-widget input {
|
||||
font-size: 1rem !important;
|
||||
background: transparent !important;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
body.zen #detail-container {
|
||||
@@ -2154,65 +2114,114 @@ body.zen .note-split.type-text .scrolling-container {
|
||||
|
||||
body.zen:not(.backdrop-effects-disabled) .note-split.type-text .scrolling-container {
|
||||
--padding-top: 50px; /* Should be enough to cover the title row */
|
||||
|
||||
|
||||
padding-top: var(--padding-top);
|
||||
scroll-padding-top: var(--padding-top);
|
||||
}
|
||||
|
||||
/* Fixed formatting toolbar */
|
||||
|
||||
body.zen .note-split .ribbon-container {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 20px;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
opacity: 0; /* Hidden unless the current note split is focused */
|
||||
pointer-events: none;
|
||||
transition: opacity 100ms linear;
|
||||
}
|
||||
|
||||
body.zen .note-split:focus-within .ribbon-container {
|
||||
opacity: 1; /* Show when the note split is focused */
|
||||
}
|
||||
|
||||
body.zen .note-split .ribbon-container .ribbon-body {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
body.zen .note-split .ribbon-container .classic-toolbar-widget {
|
||||
margin: auto;
|
||||
width: fit-content;
|
||||
box-shadow: 0px 10px 20px rgba(0, 0, 0, .1);
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--main-border-color);
|
||||
padding: 4px;
|
||||
background: var(--menu-background-color);
|
||||
}
|
||||
|
||||
body.zen .note-split .ribbon-container .classic-toolbar-widget:not(:has(> .ck-toolbar)) {
|
||||
/* Hide the toolbar wrapper if the toolbar is missing */
|
||||
display: none;
|
||||
}
|
||||
|
||||
body.zen .note-split:focus-within .ribbon-container .classic-toolbar-widget {
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
@media (max-width: 1300px) {
|
||||
body.zen .note-split .ribbon-container .classic-toolbar-widget {
|
||||
/* Set the toolbar to full with */
|
||||
body.zen:not(.experimental-feature-new-layout) {
|
||||
.note-split .ribbon-container {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 20px;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
opacity: 0; /* Hidden unless the current note split is focused */
|
||||
pointer-events: none;
|
||||
transition: opacity 100ms linear;
|
||||
}
|
||||
|
||||
body.zen .classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_se,
|
||||
body.zen .classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_sw,
|
||||
body.zen .classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_smw,
|
||||
body.zen .classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_sme,
|
||||
body.zen .classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_s {
|
||||
/* Force toolbar items overflow dropdowns open upwards */
|
||||
top: auto;
|
||||
bottom: 100%;
|
||||
.note-split:focus-within .ribbon-container {
|
||||
opacity: 1; /* Show when the note split is focused */
|
||||
}
|
||||
|
||||
.note-split .ribbon-container .ribbon-body {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.note-split .ribbon-container .classic-toolbar-widget {
|
||||
margin: auto;
|
||||
width: fit-content;
|
||||
box-shadow: 0px 10px 20px rgba(0, 0, 0, .1);
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--main-border-color);
|
||||
padding: 4px;
|
||||
background: var(--menu-background-color);
|
||||
}
|
||||
|
||||
.note-split .ribbon-container .classic-toolbar-widget:not(:has(> .ck-toolbar)) {
|
||||
/* Hide the toolbar wrapper if the toolbar is missing */
|
||||
display: none;
|
||||
}
|
||||
|
||||
.note-split:focus-within .ribbon-container .classic-toolbar-widget {
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
@media (max-width: 1300px) {
|
||||
.note-split .ribbon-container .classic-toolbar-widget {
|
||||
/* Set the toolbar to full with */
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_se,
|
||||
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_sw,
|
||||
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_smw,
|
||||
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_sme,
|
||||
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_s {
|
||||
/* Force toolbar items overflow dropdowns open upwards */
|
||||
top: auto;
|
||||
bottom: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body.zen.experimental-feature-new-layout {
|
||||
.status-bar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.classic-toolbar-widget {
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
bottom: 20px;
|
||||
z-index: 1000;
|
||||
opacity: 0; /* Hidden unless the current note split is focused */
|
||||
pointer-events: none;
|
||||
transition: opacity 100ms linear;
|
||||
width: fit-content;
|
||||
box-shadow: 0px 10px 20px rgba(0, 0, 0, .1);
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--main-border-color);
|
||||
padding: 4px;
|
||||
background: var(--menu-background-color) !important;
|
||||
transform: translateX(-50%);
|
||||
backdrop-filter: blur(6px);
|
||||
}
|
||||
|
||||
#root-widget:has(.note-split.type-text:focus-within) .classic-toolbar-widget,
|
||||
.classic-toolbar-widget:focus-within {
|
||||
opacity: 1; /* Show when the note split is focused */
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
@media (max-width: 1300px) {
|
||||
.classic-toolbar-widget {
|
||||
/* Set the toolbar to full with */
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_se,
|
||||
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_sw,
|
||||
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_smw,
|
||||
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_sme,
|
||||
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_s {
|
||||
/* Force toolbar items overflow dropdowns open upwards */
|
||||
top: auto;
|
||||
bottom: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2406,7 +2415,7 @@ footer.webview-footer button {
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.right-pane-tab .tab-title .bx {
|
||||
.right-pane-tab .tab-title .tn-icon {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
@@ -2426,7 +2435,7 @@ footer.webview-footer button {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.admonition::before {
|
||||
.admonition::before {
|
||||
color: var(--accent-color);
|
||||
font-family: boxicons !important;
|
||||
position: absolute;
|
||||
@@ -2452,7 +2461,7 @@ footer.webview-footer button {
|
||||
|
||||
.ck-content ul.todo-list li:has(> span.todo-list__label input[type="checkbox"]:checked) > span.todo-list__label span.todo-list__label__description {
|
||||
text-decoration: line-through;
|
||||
opacity: 0.6;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.chat-options-container {
|
||||
@@ -2519,6 +2528,11 @@ footer.webview-footer button {
|
||||
inset-inline-start: 10px;
|
||||
}
|
||||
|
||||
.content-floating-buttons.top-right {
|
||||
top: 10px;
|
||||
inset-inline-end: 10px;
|
||||
}
|
||||
|
||||
.content-floating-buttons.bottom-left {
|
||||
bottom: 10px;
|
||||
inset-inline-start: 10px;
|
||||
@@ -2529,18 +2543,11 @@ footer.webview-footer button {
|
||||
inset-inline-end: 10px;
|
||||
}
|
||||
|
||||
.content-floating-buttons button.bx {
|
||||
.content-floating-buttons button.tn-icon {
|
||||
font-size: 130%;
|
||||
padding: 1px 10px 1px 10px;
|
||||
}
|
||||
|
||||
/* Customized icons */
|
||||
|
||||
.bx-tn-toc::before {
|
||||
content: "\ec24";
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
/* CK Editor */
|
||||
|
||||
/* Insert text snippet: limit the width of the listed items to avoid overly long names */
|
||||
@@ -2585,6 +2592,7 @@ iframe.print-iframe {
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Calendar collection */
|
||||
@@ -2599,7 +2607,7 @@ iframe.print-iframe {
|
||||
body.mobile {
|
||||
.split-note-container-widget {
|
||||
flex-direction: column !important;
|
||||
|
||||
|
||||
.note-split {
|
||||
width: 100%;
|
||||
}
|
||||
@@ -2614,4 +2622,10 @@ iframe.print-iframe {
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body.desktop .title-row {
|
||||
height: 50px;
|
||||
min-height: 50px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
--dropdown-border-color: #555;
|
||||
--dropdown-shadow-opacity: 0.4;
|
||||
--dropdown-item-icon-destructive-color: #de6e5b;
|
||||
--disabled-tooltip-icon-color: #7fd2ef;
|
||||
--contextual-help-icon-color: #7fd2ef;
|
||||
|
||||
--accented-background-color: #555;
|
||||
--more-accented-background-color: #777;
|
||||
@@ -114,4 +114,8 @@ body .todo-list input[type="checkbox"]:not(:checked):before {
|
||||
|
||||
.use-note-color {
|
||||
--custom-color: var(--dark-theme-custom-color);
|
||||
}
|
||||
}
|
||||
|
||||
span.fancytree-active {
|
||||
color: var(--dark-theme-custom-color, var(--active-item-text-color));
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ html {
|
||||
--dropdown-border-color: #ccc;
|
||||
--dropdown-shadow-opacity: 0.2;
|
||||
--dropdown-item-icon-destructive-color: #ec5138;
|
||||
--disabled-tooltip-icon-color: #004382;
|
||||
--contextual-help-icon-color: #004382;
|
||||
|
||||
--accented-background-color: #f5f5f5;
|
||||
--more-accented-background-color: #ddd;
|
||||
@@ -89,13 +89,17 @@ html {
|
||||
--custom-color: var(--light-theme-custom-color);
|
||||
}
|
||||
|
||||
:root .reference-link,
|
||||
:root .reference-link:hover,
|
||||
.ck-content a.reference-link > span,
|
||||
.board-note {
|
||||
:root .reference-link.use-note-color,
|
||||
:root .reference-link.use-note-color:hover,
|
||||
.ck-content a.reference-link.use-note-color > span,
|
||||
.board-note.use-note-color {
|
||||
color: var(--light-theme-custom-color, inherit);
|
||||
}
|
||||
|
||||
.use-note-color {
|
||||
--custom-color: var(--light-theme-custom-color);
|
||||
}
|
||||
}
|
||||
|
||||
span.fancytree-active {
|
||||
color: var(--light-theme-custom-color, var(--active-item-text-color));
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
:root {
|
||||
|
||||
/*
|
||||
/*
|
||||
* ⚠️ NOTICE: This theme is currently in the beta stage of development.
|
||||
* The names and purposes of these CSS variables are subject to frequent changes.
|
||||
*/
|
||||
@@ -21,8 +21,8 @@
|
||||
--subtle-border-color: #313131;
|
||||
--dropdown-border-color: #404040;
|
||||
--dropdown-shadow-opacity: 0.6;
|
||||
--dropdown-item-icon-destructive-color: #de6e5b;
|
||||
--disabled-tooltip-icon-color: #7fd2ef;
|
||||
--dropdown-item-icon-destructive-color: #d58477;
|
||||
--contextual-help-icon-color: #7fd2ef;
|
||||
|
||||
--accented-background-color: #555;
|
||||
|
||||
@@ -74,11 +74,13 @@
|
||||
--select-arrow-svg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='transparent' stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/></svg>");
|
||||
--select-group-heading-text-color: gray;
|
||||
|
||||
--link-hover-background: #ffffff26;
|
||||
--link-hover-color: white;
|
||||
--link-color: #95c3d9;
|
||||
--link-hover-background: #75c2e324;
|
||||
--link-hover-color: var(--link-color);
|
||||
--link-selection-outline-color: #75c2e385;
|
||||
|
||||
--hover-item-text-color: #efefef;
|
||||
--hover-item-background-color: #ffffff24;
|
||||
--hover-item-background-color: #ffffff16;
|
||||
--hover-item-border-color: transparent;
|
||||
|
||||
--active-item-text-color: var(--left-pane-text-color);
|
||||
@@ -170,6 +172,9 @@
|
||||
--protected-session-active-icon-color: #8edd8e;
|
||||
--sync-status-error-pulse-color: #f47871;
|
||||
|
||||
--classic-toolbar-vert-layout-background-color: #ffffff0d;
|
||||
--classic-toolbar-horiz-layout-background-color: var(--main-background-color);
|
||||
|
||||
--center-pane-vert-layout-background-color-bgfx: #0c0c0c69;
|
||||
--center-pane-horiz-layout-background-color-bgfx: #1e1e1ec7;
|
||||
|
||||
@@ -182,7 +187,7 @@
|
||||
|
||||
--tab-close-button-hover-background: #a45353;
|
||||
--tab-close-button-hover-color: white;
|
||||
|
||||
|
||||
--active-tab-background-color: #ffffff1c;
|
||||
--active-tab-hover-background-color: var(--active-tab-background-color);
|
||||
--active-tab-icon-color: #a9a9a9;
|
||||
@@ -199,9 +204,19 @@
|
||||
--badge-background-color: #ffffff1a;
|
||||
--badge-text-color: var(--muted-text-color);
|
||||
|
||||
--badge-temporaraily-editable-background-color: #297331;
|
||||
--badge-read-only-background-color: #af4340;
|
||||
--badge-share-background-color: #4d4d4d;
|
||||
--badge-clipped-note-background-color: #295773;
|
||||
--badge-execute-background-color: #604180;
|
||||
|
||||
--note-icon-background-color: #444444;
|
||||
--note-icon-color: #d4d4d4;
|
||||
--note-icon-hover-background-color: #555555;
|
||||
|
||||
--promoted-attribute-card-background-color: #ffffff21;
|
||||
--promoted-attribute-card-shadow: none;
|
||||
|
||||
|
||||
--floating-button-shadow-color: #00000080;
|
||||
--floating-button-background-color: #494949d2;
|
||||
--floating-button-color: var(--button-text-color);
|
||||
@@ -220,14 +235,17 @@
|
||||
--right-pane-item-hover-background: #ffffff26;
|
||||
--right-pane-item-hover-color: white;
|
||||
|
||||
--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;
|
||||
--scrollbar-border-color: unset; /* Deprecated */
|
||||
|
||||
--selection-background-color: #3399FF70;
|
||||
|
||||
--link-color: lightskyblue;
|
||||
|
||||
--mermaid-theme: dark;
|
||||
|
||||
@@ -293,10 +311,10 @@
|
||||
--custom-bg-color: hsl(var(--custom-color-hue), 20%, 33%, 0.4);
|
||||
}
|
||||
|
||||
:root .reference-link,
|
||||
:root .reference-link:hover,
|
||||
.ck-content a.reference-link > span,
|
||||
.board-note {
|
||||
:root .reference-link.use-note-color,
|
||||
:root .reference-link.use-note-color:hover,
|
||||
.ck-content a.reference-link.use-note-color > span,
|
||||
.board-note.use-note-color {
|
||||
color: var(--dark-theme-custom-color, inherit);
|
||||
}
|
||||
|
||||
@@ -320,4 +338,16 @@ body .todo-list input[type="checkbox"]:not(:checked):before {
|
||||
|
||||
.use-note-color {
|
||||
--custom-color: var(--dark-theme-custom-color);
|
||||
}
|
||||
|
||||
.note-split.with-hue,
|
||||
.quick-edit-dialog-wrapper.with-hue {
|
||||
--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%);
|
||||
}
|
||||
|
||||
.note-split.with-hue *::selection,
|
||||
.quick-edit-dialog-wrapper.with-hue *::selection {
|
||||
--selection-background-color: hsl(var(--custom-color-hue), 49.2%, 35%);
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
:root {
|
||||
|
||||
/*
|
||||
/*
|
||||
* ⚠️ NOTICE: This theme is currently in the beta stage of development.
|
||||
* The names and purposes of these CSS variables are subject to frequent changes.
|
||||
*/
|
||||
@@ -21,8 +21,8 @@
|
||||
--subtle-border-color: rgba(0, 0, 0, 0.1);
|
||||
--dropdown-border-color: #ccc;
|
||||
--dropdown-shadow-opacity: 0.2;
|
||||
--dropdown-item-icon-destructive-color: #ec5138;
|
||||
--disabled-tooltip-icon-color: #004382;
|
||||
--dropdown-item-icon-destructive-color: #de4027;
|
||||
--contextual-help-icon-color: #004382;
|
||||
|
||||
--accented-background-color: #f5f5f5;
|
||||
|
||||
@@ -74,8 +74,10 @@
|
||||
--select-arrow-svg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='transparent' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/></svg>");
|
||||
--select-group-heading-text-color: gray;
|
||||
|
||||
--link-hover-background: #00000012;
|
||||
--link-hover-color: black;
|
||||
--link-color: #0076af;
|
||||
--link-hover-background: #3c7fa017;
|
||||
--link-hover-color: var(--link-color);
|
||||
--link-selection-outline-color: #95c3d9db;
|
||||
|
||||
--hover-item-text-color: black;
|
||||
--hover-item-background-color: #0000001a;
|
||||
@@ -138,7 +140,7 @@
|
||||
/* Deprecated: now local variables in #launcher, with the values dependent on the current layout. */
|
||||
--launcher-pane-background-color: unset;
|
||||
--launcher-pane-text-color: unset;
|
||||
|
||||
|
||||
--launcher-pane-vert-background-color: #e8e8e8;
|
||||
--launcher-pane-vert-text-color: #000000bd;
|
||||
--launcher-pane-vert-button-hover-color: black;
|
||||
@@ -162,6 +164,9 @@
|
||||
--protected-session-active-icon-color: #16b516;
|
||||
--sync-status-error-pulse-color: #ff5528;
|
||||
|
||||
--classic-toolbar-vert-layout-background-color: #ffffffa1;
|
||||
--classic-toolbar-horiz-layout-background-color: var(--main-background-color);
|
||||
|
||||
--center-pane-vert-layout-background-color-bgfx: #ffffff75;
|
||||
--center-pane-horiz-layout-background-color-bgfx: #ffffffd6;
|
||||
|
||||
@@ -174,7 +179,7 @@
|
||||
|
||||
--tab-close-button-hover-background: #c95a5a;
|
||||
--tab-close-button-hover-color: white;
|
||||
|
||||
|
||||
--active-tab-background-color: white;
|
||||
--active-tab-hover-background-color: var(--active-tab-background-color);
|
||||
--active-tab-icon-color: gray;
|
||||
@@ -191,6 +196,16 @@
|
||||
--badge-background-color: #00000011;
|
||||
--badge-text-color: var(--muted-text-color);
|
||||
|
||||
--badge-temporaraily-editable-background-color: #35a64c;
|
||||
--badge-read-only-background-color: #c8302c;
|
||||
--badge-share-background-color: #6b6b6b;
|
||||
--badge-clipped-note-background-color: #2284c0;
|
||||
--badge-execute-background-color: #7b47af;
|
||||
|
||||
--note-icon-background-color: #4f4f4f;
|
||||
--note-icon-color: white;
|
||||
--note-icon-hover-background-color: #737373;
|
||||
|
||||
--promoted-attribute-card-background-color: #00000014;
|
||||
--promoted-attribute-card-shadow: none;
|
||||
|
||||
@@ -218,6 +233,11 @@
|
||||
--right-pane-item-hover-background: #00000013;
|
||||
--right-pane-item-hover-color: inherit;
|
||||
|
||||
--bottom-panel-background-color: #ffffff8c;
|
||||
--bottom-panel-title-bar-background-color: #94949414;
|
||||
|
||||
--status-bar-border-color: #0000003a;
|
||||
|
||||
--scrollbar-thumb-color: #0000005c;
|
||||
--scrollbar-thumb-hover-color: #00000066;
|
||||
--scrollbar-background-color: transparent;
|
||||
@@ -225,8 +245,6 @@
|
||||
|
||||
--selection-background-color: #3399FF70;
|
||||
|
||||
--link-color: blue;
|
||||
|
||||
--mermaid-theme: default;
|
||||
|
||||
--code-block-box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.1), 0px 0px 2px rgba(0, 0, 0, 0.2);
|
||||
@@ -291,4 +309,16 @@
|
||||
--modal-background-color: hsl(var(--custom-color-hue), 56%, 96%);
|
||||
--modal-border-color: hsl(var(--custom-color-hue), 33%, 41%);
|
||||
--promoted-attribute-card-background-color: hsl(var(--custom-color-hue), 40%, 88%);
|
||||
}
|
||||
|
||||
.note-split.with-hue,
|
||||
.quick-edit-dialog-wrapper.with-hue {
|
||||
--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%);
|
||||
}
|
||||
|
||||
.note-split.with-hue *::selection,
|
||||
.quick-edit-dialog-wrapper.with-hue *::selection {
|
||||
--selection-background-color: hsl(var(--custom-color-hue), 60%, 90%);
|
||||
}
|
||||
@@ -17,6 +17,8 @@
|
||||
*/
|
||||
|
||||
:root {
|
||||
color-scheme: var(--theme-style);
|
||||
|
||||
--main-font-family: "Inter", sans-serif;
|
||||
|
||||
--main-font-size: normal;
|
||||
@@ -50,7 +52,7 @@
|
||||
|
||||
--tab-bar-height: 50px;
|
||||
--tab-height: 36px;
|
||||
--tab-first-item-horiz-offset: 1px;
|
||||
--tab-first-item-horiz-offset: 0;
|
||||
--new-tab-button-size: 24px;
|
||||
|
||||
--center-pane-border-radius: 10px;
|
||||
@@ -89,13 +91,13 @@
|
||||
* the color is adjusted based on the current color scheme (light or dark). The lightness
|
||||
* component of the color represented in the CIELAB color space, will be
|
||||
* constrained to a certain percentage defined below.
|
||||
*
|
||||
*
|
||||
* Note: the tree background may vary when background effects are enabled, so it is recommended
|
||||
* to maintain a higher contrast margin than on the usual note tree solid background. */
|
||||
|
||||
/* The maximum perceptual lightness for the custom color in the light theme (%): */
|
||||
--tree-item-light-theme-max-color-lightness: 60;
|
||||
|
||||
|
||||
/* The minimum perceptual lightness for the custom color in the dark theme (%): */
|
||||
--tree-item-dark-theme-min-color-lightness: 65;
|
||||
}
|
||||
@@ -128,6 +130,22 @@ body.backdrop-effects-disabled {
|
||||
font-size: 0.9rem !important;
|
||||
}
|
||||
|
||||
/* Use this class for non-legacy menus */
|
||||
.dropdown-menu.tn-dropdown-menu {
|
||||
--menu-item-icon-vert-offset: 0;
|
||||
white-space-collapse: discard;
|
||||
}
|
||||
|
||||
.dropdown-menu.tn-dropdown-menu .dropdown-item .tn-icon {
|
||||
margin-inline-end: 6px;
|
||||
}
|
||||
|
||||
.dropdown-menu.tn-dropdown-menu-scrollable {
|
||||
/* Note: scrollable dropdowns does not support submenus */
|
||||
max-height: 90vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
body.desktop .dropdown-menu::before,
|
||||
:root .ck.ck-dropdown__panel::before,
|
||||
:root .excalidraw .popover::before,
|
||||
@@ -147,14 +165,14 @@ body.desktop .dropdown-menu.tn-dropdown-list {
|
||||
backdrop-filter: var(--dropdown-backdrop-filter);
|
||||
}
|
||||
|
||||
body.desktop .dropdown-menu.tn-dropdown-list::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body.desktop .dropdown-submenu .dropdown-menu::before {
|
||||
content: unset;
|
||||
}
|
||||
|
||||
body.desktop .dropdown-menu.tn-dropdown-list::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body.desktop .dropdown-submenu .dropdown-menu {
|
||||
backdrop-filter: var(--dropdown-backdrop-filter);
|
||||
background: transparent;
|
||||
@@ -165,17 +183,35 @@ body.desktop .dropdown-submenu .dropdown-menu {
|
||||
--menu-item-start-padding: 8px;
|
||||
--menu-item-end-padding: 22px;
|
||||
--menu-item-vertical-padding: 2px;
|
||||
|
||||
padding-top: var(--menu-item-vertical-padding) !important;
|
||||
padding-bottom: var(--menu-item-vertical-padding) !important;
|
||||
padding-inline-start: var(--menu-item-start-padding) !important;
|
||||
padding-inline-end: var(--menu-item-end-padding) !important;
|
||||
|
||||
/* Note: the right padding should also accommodate the submenu arrow. */
|
||||
border-radius: 6px;
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
.dropdown-item:not(.dropdown-submenu),
|
||||
body.desktop .dropdown-item.dropdown-submenu .dropdown-toggle,
|
||||
.excalidraw .context-menu .context-menu-item {
|
||||
padding-top: var(--menu-item-vertical-padding) !important;
|
||||
padding-bottom: var(--menu-item-vertical-padding) !important;
|
||||
padding-inline-start: var(--menu-item-start-padding) !important;
|
||||
padding-inline-end: var(--menu-item-end-padding) !important;
|
||||
}
|
||||
|
||||
.dropdown-item.dropdown-submenu {
|
||||
padding: 0 !important;
|
||||
|
||||
.dropdown-toggle {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
||||
body.desktop .dropdown-menu:has(> .dropdown-submenu.dropstart) > .dropdown-item:not(.dropdown-submenu),
|
||||
body.desktop .dropdown-menu:has(> .dropdown-submenu.dropstart) > .dropdown-item.dropdown-submenu .dropdown-toggle {
|
||||
padding-inline-end: var(--menu-item-start-padding) !important;
|
||||
padding-inline-start: var(--menu-item-end-padding) !important;
|
||||
}
|
||||
|
||||
:root .dropdown-item:focus-visible {
|
||||
outline: 2px solid var(--input-focus-outline-color) !important;
|
||||
background-color: transparent;
|
||||
@@ -200,6 +236,10 @@ html body .dropdown-item[disabled] {
|
||||
opacity: var(--menu-item-disabled-opacity);
|
||||
}
|
||||
|
||||
.dropdown-item:not(.disabled) .destructive-action-icon,
|
||||
.dropdown-item:not(.disabled) .bx-trash {
|
||||
--menu-item-icon-color: var(--dropdown-item-icon-destructive-color);
|
||||
}
|
||||
/* Badges */
|
||||
:root .badge {
|
||||
--bs-badge-color: var(--badge-text-color);
|
||||
@@ -211,7 +251,7 @@ html body .dropdown-item[disabled] {
|
||||
}
|
||||
|
||||
/* Menu item icon */
|
||||
.dropdown-item .bx {
|
||||
.dropdown-item .tn-icon {
|
||||
translate: 0 var(--menu-item-icon-vert-offset);
|
||||
color: var(--menu-item-icon-color) !important;
|
||||
font-size: 1.1em;
|
||||
@@ -249,7 +289,8 @@ html body .dropdown-item[disabled] {
|
||||
}
|
||||
|
||||
/* Menu item arrow */
|
||||
.dropdown-menu .dropdown-toggle::after {
|
||||
body.mobile .dropdown-submenu .dropdown-toggle::after,
|
||||
body.desktop .dropdown-submenu:not(.dropstart) .dropdown-toggle::after {
|
||||
content: "\ed3b" !important;
|
||||
position: absolute;
|
||||
display: flex !important;
|
||||
@@ -265,6 +306,26 @@ html body .dropdown-item[disabled] {
|
||||
color: var(--menu-item-arrow-color) !important;
|
||||
}
|
||||
|
||||
body.mobile .dropdown-submenu.dropstart .dropdown-toggle::before {
|
||||
content: unset;
|
||||
}
|
||||
|
||||
body.desktop .dropdown-submenu.dropstart .dropdown-toggle::before {
|
||||
content: "\ea4d" !important;
|
||||
position: absolute;
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
margin: unset !important;
|
||||
border: unset !important;
|
||||
padding: 0 4px;
|
||||
font-family: boxicons;
|
||||
font-size: 1.2em;
|
||||
color: var(--menu-item-arrow-color) !important;
|
||||
}
|
||||
|
||||
body[dir=rtl] .dropdown-menu:not([data-popper-placement="bottom-start"]) .dropdown-toggle::after {
|
||||
content: "\ea4d" !important;
|
||||
}
|
||||
@@ -339,7 +400,7 @@ body.mobile .dropdown-menu {
|
||||
font-size: 1em !important;
|
||||
backdrop-filter: var(--dropdown-backdrop-filter);
|
||||
position: relative;
|
||||
|
||||
|
||||
.dropdown-toggle::after {
|
||||
top: 0.5em;
|
||||
right: var(--dropdown-menu-padding-horizontal);
|
||||
@@ -356,7 +417,7 @@ body.mobile .dropdown-menu {
|
||||
padding: var(--dropdown-menu-padding-vertical) var(--dropdown-menu-padding-horizontal) !important;
|
||||
background: var(--card-background-color);
|
||||
border-bottom: 1px solid var(--menu-item-delimiter-color) !important;
|
||||
border-radius: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.dropdown-item:first-of-type,
|
||||
@@ -367,9 +428,9 @@ body.mobile .dropdown-menu {
|
||||
border-top-right-radius: 6px;
|
||||
}
|
||||
|
||||
.dropdown-item:last-of-type,
|
||||
.dropdown-item:last-of-type,
|
||||
.dropdown-item:has(+ .dropdown-divider),
|
||||
.dropdown-custom-item:last-of-type,
|
||||
.dropdown-custom-item:last-of-type,
|
||||
.dropdown-custom-item:has(+ .dropdown-divider) {
|
||||
border-bottom-left-radius: 6px;
|
||||
border-bottom-right-radius: 6px;
|
||||
@@ -392,10 +453,10 @@ body.mobile .dropdown-menu {
|
||||
--menu-background-color: --menu-submenu-mobile-background-color;
|
||||
--bs-dropdown-divider-margin-y: 0.25rem;
|
||||
border-radius: 0;
|
||||
max-height: 0;
|
||||
max-height: 0;
|
||||
transition: max-height 100ms ease-in;
|
||||
display: block !important;
|
||||
|
||||
display: block !important;
|
||||
|
||||
&.show {
|
||||
max-height: 1000px;
|
||||
padding: 0.5rem 0.75rem !important;
|
||||
@@ -405,7 +466,7 @@ body.mobile .dropdown-menu {
|
||||
&.submenu-open {
|
||||
.dropdown-toggle {
|
||||
padding-bottom: var(--dropdown-menu-padding-vertical);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,7 +498,7 @@ li.dropdown-item a.dropdown-item-button {
|
||||
border: unset;
|
||||
}
|
||||
|
||||
li.dropdown-item a.dropdown-item-button.bx {
|
||||
li.dropdown-item a.dropdown-item-button.tn-icon {
|
||||
color: var(--menu-text-color) !important;
|
||||
}
|
||||
|
||||
@@ -498,13 +559,13 @@ li.dropdown-item a.dropdown-item-button:focus-visible {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
#toast-container .toast:not(.no-title) .bx {
|
||||
#toast-container .toast:not(.no-title) .tn-icon {
|
||||
margin-inline-end: 0.5em;
|
||||
font-size: 1.1em;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
#toast-container .toast.no-title .bx {
|
||||
#toast-container .toast.no-title .tn-icon {
|
||||
margin-inline-end: 0;
|
||||
font-size: 1.3em;
|
||||
}
|
||||
@@ -695,7 +756,7 @@ li.dropdown-item a.dropdown-item-button:focus-visible {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .bx {
|
||||
.note-list-wrapper .note-book-card .tn-icon {
|
||||
color: var(--left-pane-icon-color) !important;
|
||||
}
|
||||
|
||||
@@ -703,11 +764,6 @@ li.dropdown-item a.dropdown-item-button:focus-visible {
|
||||
filter: contrast(105%);
|
||||
}
|
||||
|
||||
.note-list.grid-view .note-book-card img {
|
||||
object-fit: cover !important;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.note-list.grid-view .ck-content {
|
||||
line-height: 1.3;
|
||||
}
|
||||
@@ -743,4 +799,4 @@ li.dropdown-item a.dropdown-item-button:focus-visible {
|
||||
.note-detail-empty .aa-suggestions div.aa-cursor {
|
||||
background: var(--hover-item-background-color);
|
||||
color: var(--hover-item-text-color);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -423,6 +423,6 @@ div.tn-tool-dialog {
|
||||
font-size: unset;
|
||||
}
|
||||
|
||||
.note-type-chooser-dialog div.note-type-dropdown .dropdown-item span.bx {
|
||||
.note-type-chooser-dialog div.note-type-dropdown .dropdown-item span.tn-icon {
|
||||
margin-inline-end: .25em;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,15 +56,16 @@ button.btn.btn-primary:focus-visible,
|
||||
button.btn.btn-secondary:focus-visible,
|
||||
button.btn.btn-sm:not(.select-button):focus-visible,
|
||||
button.btn.btn-success:focus-visible,
|
||||
button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel, .ck-button-replaceall, .ck-button-replace).ck-button_with-text:not(.ck-disabled):focus-visible {
|
||||
button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel, .ck-button-replaceall, .ck-button-replace).ck-button_with-text:not(.ck-disabled):focus-visible,
|
||||
.tn-focusable-button:focus-visible {
|
||||
outline: 2px solid var(--input-focus-outline-color);
|
||||
}
|
||||
|
||||
/* Button's icon */
|
||||
button.btn.btn-primary span.bx,
|
||||
button.btn.btn-secondary span.bx,
|
||||
button.btn.btn-sm span.bx,
|
||||
button.btn.btn-success span.bx {
|
||||
button.btn.btn-primary span.tn-icon,
|
||||
button.btn.btn-secondary span.tn-icon,
|
||||
button.btn.btn-sm span.tn-icon,
|
||||
button.btn.btn-success span.tn-icon {
|
||||
color: var(--cmd-button-icon-color);
|
||||
padding-inline-end: 0.35em;
|
||||
font-size: 1.2em;
|
||||
@@ -154,7 +155,7 @@ button.btn.btn-success kbd {
|
||||
color: var(--button-group-active-button-text-color);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Input boxes
|
||||
*/
|
||||
|
||||
@@ -352,6 +353,11 @@ label.input-group.tn-number-unit-pair input {
|
||||
padding-inline-end: 0;
|
||||
}
|
||||
|
||||
:root .input-group > pre[aria-hidden="true"] {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Combo box-like dropdown buttons */
|
||||
|
||||
.select-button.dropdown-toggle::after {
|
||||
@@ -399,7 +405,8 @@ button.select-button.dropdown-toggle.btn:active {
|
||||
select:focus,
|
||||
select.form-select:focus,
|
||||
select.form-control:focus,
|
||||
.select-button.dropdown-toggle.btn:focus {
|
||||
.select-button.dropdown-toggle.btn:focus,
|
||||
.select-button.focus-outline:focus {
|
||||
box-shadow: unset;
|
||||
outline: 3px solid var(--input-focus-outline-color);
|
||||
outline-offset: 0;
|
||||
@@ -422,7 +429,7 @@ optgroup {
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* File input
|
||||
*
|
||||
* <label class="tn-file-input tn-input-field">
|
||||
@@ -635,8 +642,8 @@ body a.tn-link:visited,
|
||||
border-radius: 4px;
|
||||
background: var(--background);
|
||||
color: var(--link-color);
|
||||
font-weight: normal;
|
||||
text-decoration: underline;
|
||||
font-weight: 500;
|
||||
text-decoration: none;
|
||||
|
||||
transition:
|
||||
background-color 200ms ease-out,
|
||||
@@ -651,10 +658,12 @@ body a.tn-link:focus-visible,
|
||||
}
|
||||
|
||||
body a.tn-link:hover,
|
||||
.use-tn-links a:hover {
|
||||
.use-tn-links a:hover,
|
||||
.use-tn-links a.ck-widget_selected {
|
||||
box-shadow: 0 0 0 4px var(--link-hover-background);
|
||||
--background: var(--link-hover-background);
|
||||
color: var(--link-hover-color);
|
||||
text-decoration: underline;
|
||||
|
||||
transition:
|
||||
background-color 100ms ease-in,
|
||||
@@ -784,4 +793,4 @@ input[type="range"] {
|
||||
scrollbar-color: unset;
|
||||
scrollbar-width: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
--ck-color-button-on-background: transparent;
|
||||
--ck-color-button-on-hover-background: var(--hover-item-background-color);
|
||||
--ck-color-button-default-active-background: var(--hover-item-background-color);
|
||||
|
||||
|
||||
--ck-color-split-button-hover-background: var(--ck-editor-toolbar-dropdown-button-open-background);
|
||||
|
||||
--ck-focus-ring: 1px solid transparent;
|
||||
@@ -77,7 +77,7 @@
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Dropdowns
|
||||
*/
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
:root .ck.ck-dropdown__panel,
|
||||
:root .ck-balloon-panel {
|
||||
--ck-editor-popup-padding: 4px;
|
||||
|
||||
|
||||
--ck-color-panel-background: var(--menu-background-color);
|
||||
--ck-color-panel-border: var(--ck-editor-popup-border-color);
|
||||
|
||||
@@ -487,7 +487,7 @@ button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel).ck
|
||||
.ck.ck-labeled-field-view > .ck.ck-labeled-field-view__input-wrapper > label.ck.ck-label {
|
||||
/* Move the label above the text box regardless of the text box state */
|
||||
transform: translate(0, calc(-.2em - var(--ck-input-label-height))) !important;
|
||||
|
||||
|
||||
padding-inline-start: 0 !important;
|
||||
background: transparent;
|
||||
font-size: .85em;
|
||||
@@ -518,7 +518,7 @@ button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel).ck
|
||||
*/
|
||||
|
||||
/*
|
||||
* Code Blocks
|
||||
* Code Blocks
|
||||
*/
|
||||
|
||||
.attachment-content-wrapper pre,
|
||||
@@ -527,10 +527,17 @@ button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel).ck
|
||||
border: 0;
|
||||
border-radius: 6px;
|
||||
box-shadow: var(--code-block-box-shadow);
|
||||
padding: 0;
|
||||
margin-top: 2px !important;
|
||||
}
|
||||
|
||||
.attachment-content-wrapper pre {
|
||||
border-radius: var(--dropdown-border-radius);
|
||||
}
|
||||
|
||||
:root .ck-content pre:has(> code) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
:root .ck-content pre {
|
||||
--icon-button-size: 1.8em;
|
||||
--copy-button-width: var(--icon-button-size);
|
||||
@@ -539,7 +546,7 @@ button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel).ck
|
||||
* for single-line code blocks */
|
||||
|
||||
--copy-button-margin-size: calc((1em * 1.5 + var(--padding-size) * 2 - var(--icon-button-size)) / 2);
|
||||
|
||||
|
||||
/* Where: │ └ Line height
|
||||
* └───────── Font size
|
||||
*/
|
||||
@@ -627,6 +634,10 @@ html .note-detail-editable-text :not(figure, .include-note, hr):first-child {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.ck-content strong {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.ck-content hr {
|
||||
margin: 5px 0;
|
||||
height: 1px;
|
||||
@@ -663,16 +674,33 @@ html .note-detail-editable-text :not(figure, .include-note, hr):first-child {
|
||||
color: var(--main-text-color);
|
||||
}
|
||||
|
||||
/* Links */
|
||||
|
||||
.ck-content a.ck-widget {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.ck-content a.ck-widget.ck-widget_selected,
|
||||
.ck-content a.ck-link_selected {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 2px var(--link-selection-outline-color);
|
||||
background: var(--link-hover-background);
|
||||
}
|
||||
|
||||
/* Reference link */
|
||||
|
||||
.ck-content a.reference-link,
|
||||
.ck-content a.reference-link:hover {
|
||||
/* Apply underline only to the span inside the link so it can follow the
|
||||
* target note's user defined color */
|
||||
text-decoration: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.ck-content a.reference-link > span {
|
||||
.ck-content a.reference-link > span.use-note-color {
|
||||
color: var(--custom-color, inherit);
|
||||
}
|
||||
|
||||
.ck-content a.reference-link:hover > span {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@@ -687,4 +715,4 @@ html .note-detail-editable-text :not(figure, .include-note, hr):first-child {
|
||||
|
||||
.note-list-widget {
|
||||
outline: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,6 +151,11 @@
|
||||
--options-title-font-size: .75rem;
|
||||
--options-title-offset: 13px;
|
||||
}
|
||||
|
||||
.note-split.options {
|
||||
--preferred-max-content-width: var(--options-card-max-width);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
@@ -172,6 +177,10 @@
|
||||
height: 0;
|
||||
}
|
||||
|
||||
body.experimental-feature-new-layout .note-detail-content-widget-content.options {
|
||||
padding-inline: 25px;
|
||||
}
|
||||
|
||||
.options-section:not(.tn-no-card) {
|
||||
margin-bottom: calc(var(--options-title-offset) + 26px) !important;
|
||||
box-shadow: var(--card-box-shadow);
|
||||
@@ -181,10 +190,6 @@
|
||||
padding: var(--options-card-padding);
|
||||
}
|
||||
|
||||
body.prefers-centered-content .options-section:not(.tn-no-card) {
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
body.desktop .options-section:not(.tn-no-card) {
|
||||
min-width: var(--options-card-min-width);
|
||||
max-width: var(--options-card-max-width);
|
||||
|
||||
@@ -164,17 +164,11 @@ ul.editability-dropdown li.dropdown-item > div {
|
||||
background: var(--cmd-button-hover-background-color);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Note info
|
||||
*/
|
||||
|
||||
:root .note-info-widget-table button.calculate-button {
|
||||
min-width: 0;
|
||||
padding: 4px 10px !important;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
/* Narrow width layout */
|
||||
.note-info-widget {
|
||||
container: info-section / inline-size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,7 +212,8 @@ body[dir=ltr] #launcher-container {
|
||||
}
|
||||
|
||||
#launcher-pane .launcher-button,
|
||||
#launcher-pane .dropdown {
|
||||
#launcher-pane .right-dropdown-widget,
|
||||
#launcher-pane .global-menu {
|
||||
width: calc(var(--launcher-pane-size) - (var(--launcher-pane-button-margin) * 2)) !important;
|
||||
height: calc(var(--launcher-pane-size) - (var(--launcher-pane-button-margin) * 2)) !important;
|
||||
margin: var(--launcher-pane-button-gap) var(--launcher-pane-button-margin);
|
||||
@@ -496,12 +497,12 @@ div.bookmark-folder-widget .note-link:hover a {
|
||||
}
|
||||
|
||||
/* The item's icon */
|
||||
div.bookmark-folder-widget .note-link .bx {
|
||||
div.bookmark-folder-widget .note-link .tn-icon {
|
||||
color: var(--menu-item-icon-color);
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* QUICK SEARCH BOX
|
||||
*/
|
||||
|
||||
@@ -612,7 +613,7 @@ div.quick-search .dropdown-menu {
|
||||
* As a temporary workaround, the backdrop and transparency are disabled for the
|
||||
* vertical layout.
|
||||
*/
|
||||
body.layout-vertical.background-effects div.quick-search .dropdown-menu {
|
||||
body.layout-vertical.background-effects div.quick-search .dropdown-menu {
|
||||
--menu-background-color: var(--menu-background-color-no-backdrop) !important;
|
||||
}
|
||||
|
||||
@@ -766,7 +767,7 @@ body.mobile .fancytree-node > span {
|
||||
background: var(--left-pane-item-hover-background);
|
||||
}
|
||||
|
||||
#left-pane span.fancytree-node.shared .fancytree-title::after {
|
||||
#left-pane .note-indicator-icon.shared-indicator {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
@@ -944,12 +945,26 @@ body.electron.background-effects.layout-horizontal .tab-row-container .toggle-bu
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
inset-inline-start: -10px;
|
||||
inset-inline-end: -10px;
|
||||
inset-inline-end: -6px;
|
||||
top: 32px;
|
||||
height: 1px;
|
||||
border-bottom: 1px solid var(--launcher-pane-horiz-border-color);
|
||||
}
|
||||
|
||||
body.electron.background-effects.layout-horizontal .tab-row-container .tab-history-navigation-buttons {
|
||||
position: relative;
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: -7px;
|
||||
height: 1px;
|
||||
border-bottom: 1px solid var(--launcher-pane-horiz-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
body.electron.background-effects.layout-horizontal .tab-row-container .tab-scroll-button-left,
|
||||
body.electron.background-effects.layout-horizontal .tab-row-container .tab-scroll-button-right {
|
||||
position: relative;
|
||||
@@ -1014,7 +1029,7 @@ body.layout-vertical.electron.platform-darwin .tab-row-container {
|
||||
}
|
||||
|
||||
body.layout-horizontal .tab-row-container {
|
||||
padding-top: calc((var(--tab-bar-height) - var(--tab-height)));
|
||||
padding-top: calc(var(--tab-bar-height) - var(--tab-height));
|
||||
}
|
||||
|
||||
/* Define extra drag areas for Electron windows */
|
||||
@@ -1054,8 +1069,9 @@ body.desktop:not(.background-effects.platform-win32) #root-widget.horizontal-lay
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
.tab-row-widget .note-tab .note-tab-wrapper {
|
||||
:root div.tab-row-widget div.note-tab div.note-tab-wrapper {
|
||||
height: var(--tab-height) !important;
|
||||
border-radius: 8px;
|
||||
transition:
|
||||
background 75ms ease-in,
|
||||
box-shadow 75ms ease-in;
|
||||
@@ -1069,7 +1085,7 @@ body.desktop:not(.background-effects.platform-win32) #root-widget.horizontal-lay
|
||||
margin-top: calc((var(--tab-bar-height) - var(--tab-height)) * -1);
|
||||
}
|
||||
|
||||
body.layout-horizontal .tab-row-widget .note-tab .note-tab-wrapper {
|
||||
body.layout-horizontal div.tab-row-widget div.note-tab div.note-tab-wrapper {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
@@ -1206,20 +1222,53 @@ body.layout-vertical .tab-row-widget-is-sorting .note-tab.note-tab-is-dragging .
|
||||
top: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* CLASSIC FORMATTING TOOLBAR
|
||||
*/
|
||||
|
||||
#rest-pane > .classic-toolbar-widget {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
body.layout-vertical #rest-pane > .classic-toolbar-widget {
|
||||
border-start-start-radius: var(--center-pane-border-radius);
|
||||
}
|
||||
|
||||
body.layout-vertical #rest-pane > .classic-toolbar-widget {
|
||||
background: var(--classic-toolbar-vert-layout-background-color);
|
||||
}
|
||||
|
||||
body.layout-horizontal #rest-pane > .classic-toolbar-widget {
|
||||
background: var(--classic-toolbar-horiz-layout-background-color);
|
||||
}
|
||||
|
||||
.classic-toolbar-widget:not(.hidden-ext) + #vertical-main-container {
|
||||
/* Remove the center panel border radius when the toolbar is visible */
|
||||
--center-pane-border-radius: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* CENTER PANE
|
||||
*/
|
||||
|
||||
/* The first visible note split */
|
||||
.vertical-layout #center-pane .note-split:not(.visible ~ .visible) {
|
||||
border-radius: var(--center-pane-border-radius) 0 0 0;
|
||||
border-start-start-radius: var(--center-pane-border-radius);
|
||||
}
|
||||
|
||||
#center-pane .note-split {
|
||||
padding-top: 2px;
|
||||
background-color: var(--note-split-background-color, var(--main-background-color));
|
||||
transition: border-color 250ms ease-in;
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
/* The active split in a multi-split view */
|
||||
#center-pane > .split-note-container-widget:has(> .note-split.visible ~ .note-split.visible) > .note-split.active {
|
||||
border-color: var(--link-selection-outline-color);
|
||||
}
|
||||
|
||||
|
||||
body:not(.background-effects) #center-pane .note-split {
|
||||
animation: note-entrance 100ms linear;
|
||||
}
|
||||
@@ -1333,6 +1382,10 @@ body.mobile .note-title {
|
||||
border-bottom: 2px solid #0000001c !important;
|
||||
}
|
||||
|
||||
body.experimental-feature-new-layout #center-pane .note-split > div.alert {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Promoted attributes
|
||||
*/
|
||||
@@ -1568,7 +1621,7 @@ div.floating-buttons .show-floating-buttons-button {
|
||||
div.floating-buttons .show-floating-buttons-button::before {
|
||||
animation: floating-buttons-show-hide-button-animation 400ms ease-out;
|
||||
}
|
||||
|
||||
|
||||
div.floating-buttons .show-floating-buttons-button:hover,
|
||||
div.floating-buttons .show-floating-buttons-button:active {
|
||||
box-shadow: var(--floating-button-show-button-hover-shadow);
|
||||
@@ -1758,6 +1811,10 @@ div.find-replace-widget div.find-widget-found-wrapper > span {
|
||||
background: var(--right-pane-background-color);
|
||||
}
|
||||
|
||||
#right-pane > * {
|
||||
animation: fade-in 200ms ease-in;
|
||||
}
|
||||
|
||||
#right-pane div.card-header {
|
||||
align-items: center;
|
||||
border: 0;
|
||||
@@ -1830,7 +1887,7 @@ div.find-replace-widget div.find-widget-found-wrapper > span {
|
||||
|
||||
.excalidraw .dropdown-menu {
|
||||
border: unset !important;
|
||||
box-shadow: unset !important;
|
||||
box-shadow: unset !important;
|
||||
background-color: transparent !important;
|
||||
--island-bg-color: var(--menu-background-color);
|
||||
--shadow-island: 0px 10px 20px rgba(0, 0, 0, var(--dropdown-shadow-opacity));
|
||||
@@ -1849,4 +1906,4 @@ div.find-replace-widget div.find-widget-found-wrapper > span {
|
||||
|
||||
.excalidraw .dropdown-menu:before {
|
||||
content: unset !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,22 +148,26 @@ span.fancytree-node.protected > span.fancytree-custom-icon {
|
||||
filter: drop-shadow(2px 2px 2px var(--main-text-color));
|
||||
}
|
||||
|
||||
span.fancytree-node.multiple-parents.shared .fancytree-title::after {
|
||||
/* Note indicator icons (clone, shared) - real DOM elements for tooltip support */
|
||||
.note-indicator-icon {
|
||||
font-family: "boxicons" !important;
|
||||
font-size: smaller;
|
||||
content: " \eb3d \ec03";
|
||||
margin-inline-start: 4px;
|
||||
opacity: 0.8;
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
span.fancytree-node.multiple-parents .fancytree-title::after {
|
||||
font-family: "boxicons" !important;
|
||||
font-size: smaller;
|
||||
content: " \eb3d"; /* lookup code for "link-alt" in boxicons.css */
|
||||
.note-indicator-icon.clone-indicator::before {
|
||||
content: "\eb3d"; /* bx-link-alt */
|
||||
}
|
||||
|
||||
span.fancytree-node.shared .fancytree-title::after {
|
||||
font-family: "boxicons" !important;
|
||||
font-size: smaller;
|
||||
content: " \ec03"; /* lookup code for "share-alt" in boxicons.css */
|
||||
.note-indicator-icon.shared-indicator::before {
|
||||
content: "\ec03"; /* bx-share-alt */
|
||||
}
|
||||
|
||||
body.experimental-feature-new-layout .note-indicator-icon.clone-indicator::before {
|
||||
content: "\ed82";
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
span.fancytree-node.fancytree-active-clone:not(.fancytree-active) .fancytree-title {
|
||||
@@ -224,11 +228,11 @@ span.fancytree-node.archived {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.fancytree-node:hover .bx.tree-item-button {
|
||||
.fancytree-node:hover .tn-icon.tree-item-button {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.bx.tree-item-button {
|
||||
.tn-icon.tree-item-button {
|
||||
display: none;
|
||||
font-size: 120%;
|
||||
cursor: pointer;
|
||||
@@ -238,7 +242,7 @@ span.fancytree-node.archived {
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.unhoist-button.bx.tree-item-button {
|
||||
.unhoist-button.tn-icon.tree-item-button {
|
||||
margin-inline-start: 0; /* unhoist button is on the left and doesn't need more margin */
|
||||
display: block; /* keep always visible */
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import utils from "../services/utils.js";
|
||||
import { NoteType } from "@triliumnext/commons";
|
||||
|
||||
import FAttribute from "../entities/fattribute.js";
|
||||
import FBlob from "../entities/fblob.js";
|
||||
import FBranch from "../entities/fbranch.js";
|
||||
import FNote from "../entities/fnote.js";
|
||||
import froca from "../services/froca.js";
|
||||
import FAttribute from "../entities/fattribute.js";
|
||||
import noteAttributeCache from "../services/note_attribute_cache.js";
|
||||
import FBranch from "../entities/fbranch.js";
|
||||
import FBlob from "../entities/fblob.js";
|
||||
import utils from "../services/utils.js";
|
||||
|
||||
type AttributeDefinitions = { [key in `#${string}`]: string; };
|
||||
type RelationDefinitions = { [key in `~${string}`]: string; };
|
||||
@@ -12,6 +14,7 @@ type RelationDefinitions = { [key in `~${string}`]: string; };
|
||||
interface NoteDefinition extends AttributeDefinitions, RelationDefinitions {
|
||||
id?: string | undefined;
|
||||
title: string;
|
||||
type?: NoteType;
|
||||
children?: NoteDefinition[];
|
||||
content?: string;
|
||||
}
|
||||
@@ -45,7 +48,7 @@ export function buildNote(noteDef: NoteDefinition) {
|
||||
const note = new FNote(froca, {
|
||||
noteId: noteDef.id ?? utils.randomString(12),
|
||||
title: noteDef.title,
|
||||
type: "text",
|
||||
type: noteDef.type ?? "text",
|
||||
mime: "text/html",
|
||||
isProtected: false,
|
||||
blobId: ""
|
||||
|
||||
@@ -11,11 +11,25 @@
|
||||
},
|
||||
"toast": {
|
||||
"critical-error": {
|
||||
"title": "خطأ فادح"
|
||||
"title": "خطأ فادح",
|
||||
"message": "حدث خطأ حرج يمنع تشغيل تطبيق العميل:\n\n{{message}}\n\nيُرجّح أن يكون سبب هذا الخطأ هو تعطل أحد البرامج النصية بشكل غير متوقع. حاول تشغيل التطبيق في الوضع الآمن لحل المشكلة."
|
||||
},
|
||||
"widget-error": {
|
||||
"title": "فشل في البدء بعنصر الواجهة"
|
||||
}
|
||||
"title": "فشل في البدء بعنصر الواجهة",
|
||||
"message-custom": "تعذر تهيئة عنصر واجهة المستخدم المخصص من الملاحظة ذات المعرّف \"{{id}}\" والعنوان \"{{title}}\" بسبب:\n\n{{message}}",
|
||||
"message-unknown": "تعذر تهيئة عنصر واجهة المستخدم غير المعروف بسبب:\n\n{{message}}"
|
||||
},
|
||||
"bundle-error": {
|
||||
"title": "فشل تحميل البرنامج النصي المخصص",
|
||||
"message": "تعذر تنفيذ البرنامج النصي بسبب:\n\n{{message}}"
|
||||
},
|
||||
"widget-list-error": {
|
||||
"title": "فشل في الحصول على قائمة الأدوات من الخادم"
|
||||
},
|
||||
"widget-render-error": {
|
||||
"title": "فشل عرض عنصر واجهة مستخدم React مخصص"
|
||||
},
|
||||
"widget-missing-parent": "لا تحتوي الأداة المخصصة على خاصية إلزامية '{{property}}'.\n\nإذا كان من المفترض تشغيل هذا البرنامج النصي بدون عنصر واجهة مستخدم، فاستخدم '#run=frontendStartup' بدلاً من ذلك."
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "أضافة رابط",
|
||||
@@ -209,7 +223,6 @@
|
||||
"backlink_other": ""
|
||||
},
|
||||
"note_icon": {
|
||||
"category": "الفئة:",
|
||||
"search": "بحث:",
|
||||
"change_note_icon": "تغيير ايقونة الملاحظة",
|
||||
"reset-default": "اعادة تعيين الى الايقونة الافتراضية"
|
||||
@@ -471,7 +484,6 @@
|
||||
"delete_button": "حذف",
|
||||
"download_button": "تنزيل",
|
||||
"restore_button": "أستعادة",
|
||||
"preview": "معاينة:",
|
||||
"note_revisions": "مراجعات الملاحظة",
|
||||
"diff_on": "عرض الفروقات",
|
||||
"diff_off": "عرض المحتوى",
|
||||
@@ -948,7 +960,7 @@
|
||||
"move-to-available-launchers": "نقل الى المشغلات المتوفرة",
|
||||
"duplicate-launcher": "تكرار المشغل <kbd data-command=\"duplicateSubtree\">"
|
||||
},
|
||||
"editable-text": {
|
||||
"editable_text": {
|
||||
"auto-detect-language": "تم اكتشافه تلقائيا"
|
||||
},
|
||||
"classic_editor_toolbar": {
|
||||
|
||||
1
apps/client/src/translations/bg/translation.json
Normal file
1
apps/client/src/translations/bg/translation.json
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -64,8 +64,7 @@
|
||||
"restore_button": "Restaura",
|
||||
"delete_button": "Suprimeix",
|
||||
"download_button": "Descarrega",
|
||||
"mime": "MIME: ",
|
||||
"preview": "Vista prèvia:"
|
||||
"mime": "MIME: "
|
||||
},
|
||||
"sort_child_notes": {
|
||||
"title": "títol",
|
||||
@@ -146,7 +145,6 @@
|
||||
"relation": "relació"
|
||||
},
|
||||
"note_icon": {
|
||||
"category": "Categoria:",
|
||||
"search": "Cerca:"
|
||||
},
|
||||
"basic_properties": {
|
||||
|
||||
@@ -21,8 +21,17 @@
|
||||
},
|
||||
"bundle-error": {
|
||||
"title": "加载自定义脚本失败",
|
||||
"message": "来自 ID 为 \"{{id}}\"、标题为 \"{{title}}\" 的笔记的脚本因以下原因无法执行:\n\n{{message}}"
|
||||
}
|
||||
"message": "脚本因以下原因无法执行:\n\n{{message}}"
|
||||
},
|
||||
"widget-list-error": {
|
||||
"title": "无法从服务器取得小部件清单"
|
||||
},
|
||||
"widget-render-error": {
|
||||
"title": "渲染自定义 React 小部件失败"
|
||||
},
|
||||
"widget-missing-parent": "自定义小部件未定义强制性的 \"{{property}}\" 属性。\n\n如果此脚本需要在没有 UI 元素的情况下运行,请改用“#run=frontendStartup”。",
|
||||
"open-script-note": "打开脚本笔记",
|
||||
"scripting-error": "自定义脚本错误:{{title}}"
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "添加链接",
|
||||
@@ -205,7 +214,8 @@
|
||||
"info": {
|
||||
"modalTitle": "信息消息",
|
||||
"closeButton": "关闭",
|
||||
"okButton": "确定"
|
||||
"okButton": "确定",
|
||||
"copy_to_clipboard": "复制到剪切板"
|
||||
},
|
||||
"jump_to_note": {
|
||||
"search_button": "全文搜索",
|
||||
@@ -280,7 +290,6 @@
|
||||
"download_button": "下载",
|
||||
"mime": "MIME 类型: ",
|
||||
"file_size": "文件大小:",
|
||||
"preview": "预览:",
|
||||
"preview_not_available": "无法预览此类型的笔记。",
|
||||
"diff_on": "显示差异",
|
||||
"diff_off": "显示内容",
|
||||
@@ -692,7 +701,13 @@
|
||||
"convert_into_attachment_successful": "笔记 '{{title}}' 已成功转换为附件。",
|
||||
"convert_into_attachment_prompt": "确定要将笔记 '{{title}}' 转换为父笔记的附件吗?",
|
||||
"print_pdf": "导出为 PDF...",
|
||||
"open_note_on_server": "在服务器上打开笔记"
|
||||
"open_note_on_server": "在服务器上打开笔记",
|
||||
"view_revisions": "笔记修订...",
|
||||
"note_map": "笔记地图",
|
||||
"advanced": "高级",
|
||||
"export_as_image": "导出为图像",
|
||||
"export_as_image_png": "PNG(栅格)",
|
||||
"export_as_image_svg": "SVG(矢量图)"
|
||||
},
|
||||
"onclick_button": {
|
||||
"no_click_handler": "按钮组件'{{componentId}}'没有定义点击处理程序"
|
||||
@@ -748,9 +763,15 @@
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "更改笔记图标",
|
||||
"category": "类别:",
|
||||
"search": "搜索:",
|
||||
"reset-default": "重置为默认图标"
|
||||
"reset-default": "重置为默认图标",
|
||||
"search_placeholder_other": "在 {{count}} 个图标包中搜索 {{number}} 个图标",
|
||||
"search_placeholder_filtered": "在 {{name}} 中搜索 {{number}} 个图标",
|
||||
"filter": "筛选",
|
||||
"filter-none": "所有图标",
|
||||
"filter-default": "默认图标",
|
||||
"icon_tooltip": "{{name}}\n图标包:{{iconPack}}",
|
||||
"no_results": "没有找到图标。"
|
||||
},
|
||||
"basic_properties": {
|
||||
"note_type": "笔记类型",
|
||||
@@ -790,7 +811,7 @@
|
||||
"file_type": "文件类型",
|
||||
"file_size": "文件大小",
|
||||
"download": "下载",
|
||||
"open": "打开",
|
||||
"open": "用外部程序打开",
|
||||
"upload_new_revision": "上传新修订版本",
|
||||
"upload_success": "新文件修订版本已上传。",
|
||||
"upload_failed": "新文件修订版本上传失败。",
|
||||
@@ -810,7 +831,8 @@
|
||||
},
|
||||
"inherited_attribute_list": {
|
||||
"title": "继承的属性",
|
||||
"no_inherited_attributes": "没有继承的属性。"
|
||||
"no_inherited_attributes": "没有继承的属性。",
|
||||
"none": "无"
|
||||
},
|
||||
"note_info_widget": {
|
||||
"note_id": "笔记 ID",
|
||||
@@ -821,7 +843,9 @@
|
||||
"note_size_info": "笔记大小提供了该笔记存储需求的粗略估计。它考虑了笔记的内容及其笔记修订历史的内容。",
|
||||
"calculate": "计算",
|
||||
"subtree_size": "(子树大小: {{size}}, 共计 {{count}} 个笔记)",
|
||||
"title": "笔记信息"
|
||||
"title": "笔记信息",
|
||||
"show_similar_notes": "显示相似的笔记",
|
||||
"mime": "文件类型"
|
||||
},
|
||||
"note_map": {
|
||||
"open_full": "展开显示",
|
||||
@@ -884,7 +908,8 @@
|
||||
"search_parameters": "搜索参数",
|
||||
"unknown_search_option": "未知的搜索选项 {{searchOptionName}}",
|
||||
"search_note_saved": "搜索笔记已保存到 {{- notePathTitle}}",
|
||||
"actions_executed": "操作已执行。"
|
||||
"actions_executed": "操作已执行。",
|
||||
"view_options": "查看选项:"
|
||||
},
|
||||
"similar_notes": {
|
||||
"title": "相似笔记",
|
||||
@@ -986,7 +1011,14 @@
|
||||
"placeholder": "在这里输入您的代码笔记内容..."
|
||||
},
|
||||
"editable_text": {
|
||||
"placeholder": "在这里输入您的笔记内容..."
|
||||
"placeholder": "在这里输入您的笔记内容...",
|
||||
"auto-detect-language": "自动检测",
|
||||
"keeps-crashing": "编辑组件时持续崩溃。请尝试重启 Trilium。如果问题仍然存在,请考虑提交错误报告。",
|
||||
"editor_crashed_title": "文本编辑器崩溃",
|
||||
"editor_crashed_content": "您的内容已经成功恢复,但是某些最近的内容可能没有保存。",
|
||||
"editor_crashed_details_button": "浏览更多明细...",
|
||||
"editor_crashed_details_intro": "如果您多次经历此错误,考虑在Github上提交这些信息。",
|
||||
"editor_crashed_details_title": "技术信息"
|
||||
},
|
||||
"empty": {
|
||||
"open_note_instruction": "通过在下面的输入框中输入笔记标题或在树中选择笔记来打开笔记。",
|
||||
@@ -1419,7 +1451,7 @@
|
||||
"will_be_deleted_in": "此附件将在 {{time}} 后自动删除",
|
||||
"will_be_deleted_soon": "该附件在不久后将被自动删除",
|
||||
"deletion_reason": ",因为该附件未链接在笔记的内容中。为防止被删除,请将附件链接重新添加到内容中或将附件转换为笔记。",
|
||||
"role_and_size": "角色:{{role}},大小:{{size}}",
|
||||
"role_and_size": "角色:{{role}},大小:{{size}},文件类型:{{- mimeType}}",
|
||||
"link_copied": "附件链接已复制到剪贴板。",
|
||||
"unrecognized_role": "无法识别的附件角色 '{{role}}'。"
|
||||
},
|
||||
@@ -1469,7 +1501,7 @@
|
||||
"import-into-note": "导入到笔记",
|
||||
"apply-bulk-actions": "应用批量操作",
|
||||
"converted-to-attachments": "{{count}} 个笔记已被转换为附件。",
|
||||
"convert-to-attachment-confirm": "确定要将选中的笔记转换为其父笔记的附件吗?",
|
||||
"convert-to-attachment-confirm": "确定要将选中的笔记转换为其父笔记的附件吗?此操作仅适用于图像笔记,其他笔记将被跳过。",
|
||||
"duplicate": "复制",
|
||||
"open-in-popup": "快速编辑",
|
||||
"archive": "归档",
|
||||
@@ -1534,7 +1566,11 @@
|
||||
},
|
||||
"highlights_list_2": {
|
||||
"title": "高亮列表",
|
||||
"options": "选项"
|
||||
"options": "选项",
|
||||
"title_with_count_other": "{{count}} 处高亮",
|
||||
"modal_title": "配置高亮列表",
|
||||
"menu_configure": "配置高亮列表...",
|
||||
"no_highlights": "未找到高亮内容。"
|
||||
},
|
||||
"quick-search": {
|
||||
"placeholder": "快速搜索",
|
||||
@@ -1558,7 +1594,11 @@
|
||||
"create-child-note": "创建子笔记",
|
||||
"unhoist": "取消聚焦",
|
||||
"toggle-sidebar": "切换侧边栏",
|
||||
"dropping-not-allowed": "不允许移动笔记到此处。"
|
||||
"dropping-not-allowed": "不允许移动笔记到此处。",
|
||||
"shared-indicator-tooltip": "此笔记已公开分享",
|
||||
"shared-indicator-tooltip-with-url": "此笔记已公开分享至:{{- url}}",
|
||||
"clone-indicator-tooltip": "此笔记有 {{- count}} 个父级: {{- parents}}",
|
||||
"clone-indicator-tooltip-single": "此笔记已克隆(1 个额外的父级:{{- parent}})"
|
||||
},
|
||||
"title_bar_buttons": {
|
||||
"window-on-top": "保持此窗口置顶"
|
||||
@@ -1566,10 +1606,22 @@
|
||||
"note_detail": {
|
||||
"could_not_find_typewidget": "找不到类型为 '{{type}}' 的 typeWidget",
|
||||
"printing": "正在打印…",
|
||||
"printing_pdf": "正在导出为PDF…"
|
||||
"printing_pdf": "正在导出为PDF…",
|
||||
"print_report_title": "打印报告",
|
||||
"print_report_collection_content_other": "集合中的 {{count}} 篇笔记无法打印,因为它们不受支持或受到保护。",
|
||||
"print_report_collection_details_button": "查看详情",
|
||||
"print_report_collection_details_ignored_notes": "忽略的笔记"
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "请输入笔记标题..."
|
||||
"placeholder": "请输入笔记标题...",
|
||||
"created_on": "建立于 <Value />",
|
||||
"last_modified": "修改于 <Value />",
|
||||
"note_type_switcher_label": "从 {{type}} 切换到:",
|
||||
"note_type_switcher_others": "其他笔记类型",
|
||||
"note_type_switcher_templates": "模板",
|
||||
"note_type_switcher_collection": "集合",
|
||||
"edited_notes": "今天编辑过的笔记",
|
||||
"promoted_attributes": "升级属性"
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "没有找到符合搜索条件的笔记。",
|
||||
@@ -1598,7 +1650,8 @@
|
||||
},
|
||||
"toc": {
|
||||
"table_of_contents": "目录",
|
||||
"options": "选项"
|
||||
"options": "选项",
|
||||
"no_headings": "无标题。"
|
||||
},
|
||||
"watched_file_update_status": {
|
||||
"file_last_modified": "文件 <code class=\"file-path\"></code> 最后修改时间为 <span class=\"file-last-modified\"></span>。",
|
||||
@@ -1660,10 +1713,6 @@
|
||||
"move-to-available-launchers": "移动到可用启动器",
|
||||
"duplicate-launcher": "复制启动器 <kbd data-command=\"duplicateSubtree\">"
|
||||
},
|
||||
"editable-text": {
|
||||
"auto-detect-language": "自动检测",
|
||||
"keeps-crashing": "编辑组件时持续崩溃。请尝试重启 Trilium。如果问题仍然存在,请考虑提交错误报告。"
|
||||
},
|
||||
"highlighting": {
|
||||
"title": "代码块",
|
||||
"description": "控制文本笔记中代码块的语法高亮,代码笔记不会受到影响。",
|
||||
@@ -1714,7 +1763,8 @@
|
||||
"open_note_in_new_tab": "在新标签页中打开笔记",
|
||||
"open_note_in_new_split": "在新分屏中打开笔记",
|
||||
"open_note_in_new_window": "在新窗口中打开笔记",
|
||||
"open_note_in_popup": "快速编辑"
|
||||
"open_note_in_popup": "快速编辑",
|
||||
"open_note_in_other_split": "在另一个分屏中打开笔记"
|
||||
},
|
||||
"electron_integration": {
|
||||
"desktop-application": "桌面应用程序",
|
||||
@@ -1934,8 +1984,9 @@
|
||||
"unknown_widget": "未知组件:\"{{id}}\"."
|
||||
},
|
||||
"note_language": {
|
||||
"not_set": "不设置",
|
||||
"configure-languages": "设置语言..."
|
||||
"not_set": "未设置语言",
|
||||
"configure-languages": "设置语言...",
|
||||
"help-on-languages": "内容语言帮助..."
|
||||
},
|
||||
"content_language": {
|
||||
"title": "内容语言",
|
||||
@@ -1953,7 +2004,8 @@
|
||||
"button_title": "将图表导出为PNG"
|
||||
},
|
||||
"svg": {
|
||||
"export_to_png": "无法将图表导出为PNG。"
|
||||
"export_to_png": "无法将图表导出为PNG。",
|
||||
"export_to_svg": "此图像无法导出为SVG。"
|
||||
},
|
||||
"code_theme": {
|
||||
"title": "外观",
|
||||
@@ -2001,7 +2053,7 @@
|
||||
"book_properties_config": {
|
||||
"hide-weekends": "隐藏周末",
|
||||
"display-week-numbers": "显示周数",
|
||||
"map-style": "地图样式:",
|
||||
"map-style": "地图样式",
|
||||
"max-nesting-depth": "最大嵌套深度:",
|
||||
"raster": "栅格",
|
||||
"vector_light": "矢量(浅色)",
|
||||
@@ -2045,7 +2097,7 @@
|
||||
"configure_launch_bar_description": "打开启动栏配置,添加或移除项目。"
|
||||
},
|
||||
"content_renderer": {
|
||||
"open_externally": "在外部打开"
|
||||
"open_externally": "用外部程序打开"
|
||||
},
|
||||
"modal": {
|
||||
"close": "关闭",
|
||||
@@ -2058,14 +2110,20 @@
|
||||
"next_theme_title": "试用新 Trilium 主题",
|
||||
"next_theme_message": "当前使用旧版主题,要试用新主题吗?",
|
||||
"next_theme_button": "试用新主题",
|
||||
"dismiss": "关闭"
|
||||
"dismiss": "关闭",
|
||||
"new_layout_message": "我们为 Trilium 引入了现代化的布局。Ribbon 界面已被移除并无缝集成到主界面中,新的状态栏和可展开部分(例如“已提升属性”)取代了其主要功能。\n\n新布局默认启用,您可以通过“选项”→“外观”暂时禁用它。",
|
||||
"new_layout_button": "更多信息",
|
||||
"new_layout_title": "新布局"
|
||||
},
|
||||
"settings": {
|
||||
"related_settings": "相关设置"
|
||||
},
|
||||
"settings_appearance": {
|
||||
"related_code_blocks": "文本笔记中代码块的色彩方案",
|
||||
"related_code_notes": "代码笔记的色彩方案"
|
||||
"related_code_notes": "代码笔记的色彩方案",
|
||||
"ui": "用户界面",
|
||||
"ui_old_layout": "旧布局",
|
||||
"ui_new_layout": "新布局"
|
||||
},
|
||||
"units": {
|
||||
"percentage": "%"
|
||||
@@ -2080,7 +2138,7 @@
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "第 {{startIndex}} 页 - 第 {{endIndex}} 页",
|
||||
"total_notes": "{{count}} 笔记"
|
||||
"total_notes": "{{count}} 篇笔记"
|
||||
},
|
||||
"collections": {
|
||||
"rendering_error": "出现错误无法显示内容。"
|
||||
@@ -2105,5 +2163,83 @@
|
||||
},
|
||||
"popup-editor": {
|
||||
"maximize": "切换至完整编辑器"
|
||||
},
|
||||
"server": {
|
||||
"unknown_http_error_title": "与服务器通讯错误",
|
||||
"unknown_http_error_content": "状态码: {{statusCode}}\n地址: {{method}} {{url}}\n信息: {{message}}",
|
||||
"traefik_blocks_requests": "如果您使用 Traefik 反向代理,它引入了一项影响与服务器的通信重大更改。"
|
||||
},
|
||||
"experimental_features": {
|
||||
"title": "实验选项",
|
||||
"disclaimer": "这些选项处于实验阶段,可能导致系统不稳定。请谨慎使用。",
|
||||
"new_layout_name": "新布局",
|
||||
"new_layout_description": "尝试全新布局,呈现更现代的外观并提升易用性。后续版本将进行重大调整。"
|
||||
},
|
||||
"tab_history_navigation_buttons": {
|
||||
"go-back": "返回前一笔记",
|
||||
"go-forward": "前往下一笔记"
|
||||
},
|
||||
"breadcrumb_badges": {
|
||||
"read_only_explicit": "只读",
|
||||
"read_only_auto": "自动只读",
|
||||
"shared_publicly": "公开共享",
|
||||
"shared_locally": "本地共享",
|
||||
"read_only_explicit_description": "此笔记已被手动设置为只读。\n点击可临时编辑。",
|
||||
"read_only_auto_description": "出于性能原因,此笔记已被自动设置为只读模式。此自动限制可以在设置中调整。\n\n点击可临时编辑。",
|
||||
"read_only_temporarily_disabled": "临时编辑",
|
||||
"read_only_temporarily_disabled_description": "此笔记当前可编辑,但通常是只读的。一旦你切换到其他笔记,该笔记将恢复为只读模式。\n\n点击以重新启用只读模式。",
|
||||
"clipped_note": "网页剪辑",
|
||||
"clipped_note_description": "此笔记最初来自 {{url}}。\n\n点击即可跳转至源网页。",
|
||||
"execute_script": "运行脚本",
|
||||
"execute_script_description": "这是一篇脚本笔记。点击即可执行脚本。",
|
||||
"execute_sql": "运行SQL",
|
||||
"execute_sql_description": "这是一篇 SQL 笔记。点击即可执行 SQL 查询。",
|
||||
"shared_copy_to_clipboard": "复制链接到剪贴板",
|
||||
"shared_open_in_browser": "在浏览器中打开链接",
|
||||
"shared_unshare": "取消共享",
|
||||
"save_status_saved": "已保存",
|
||||
"save_status_saving": "保存中...",
|
||||
"save_status_unsaved": "未保存",
|
||||
"save_status_error": "保存失败",
|
||||
"save_status_unsaved_tooltip": "还有一些更改尚未保存。它们将稍后自动保存。",
|
||||
"save_status_error_tooltip": "保存笔记时出错。如果可以,请尝试将笔记内容复制到其他位置并重新加载应用程序。",
|
||||
"save_status_saving_tooltip": "更改正在保存。"
|
||||
},
|
||||
"status_bar": {
|
||||
"language_title": "更改内容语言",
|
||||
"note_info_title": "查看笔记信息(例如日期,笔记大小)",
|
||||
"backlinks_title_other": "查看反链",
|
||||
"attachments_title_other": "在新标签页中查看附件",
|
||||
"attributes_other": "{{count}} 个属性",
|
||||
"attributes_title": "拥有的属性和继承的属性",
|
||||
"note_paths_title": "笔记路径",
|
||||
"code_note_switcher": "更改语言模式",
|
||||
"backlinks_other": "{{count}} 个反链",
|
||||
"attachments_other": "{{count}} 个附件",
|
||||
"note_paths_other": "{{count}} 条路径"
|
||||
},
|
||||
"breadcrumb": {
|
||||
"workspace_badge": "工作空间",
|
||||
"scroll_to_top_title": "跳转到笔记开始",
|
||||
"hoisted_badge_title": "取消聚焦",
|
||||
"hoisted_badge": "聚焦",
|
||||
"create_new_note": "新建子笔记",
|
||||
"empty_hide_archived_notes": "隐藏已存档的笔记"
|
||||
},
|
||||
"right_pane": {
|
||||
"empty_button": "隐藏面板",
|
||||
"toggle": "切换右侧面板",
|
||||
"custom_widget_go_to_source": "跳转到源码",
|
||||
"empty_message": "这篇笔记没有展示内容"
|
||||
},
|
||||
"attributes_panel": {
|
||||
"title": "笔记属性"
|
||||
},
|
||||
"pdf": {
|
||||
"attachments_other": "{{count}} 个附件",
|
||||
"pages_other": "共{{count}}页",
|
||||
"pages_alt": "第{{pageNumber}}页",
|
||||
"pages_loading": "加载中...",
|
||||
"layers_other": "{{count}} 层"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,6 +108,11 @@
|
||||
"cloned_note_prefix_title": "Klonovaná poznámka se zobrazí ve stromu poznámek s danou předponou",
|
||||
"clone_to_selected_note": "Klonovat vybranou poznámku",
|
||||
"no_path_to_clone_to": "Žádná cest pro klonování.",
|
||||
"note_cloned": "Poznámka: „{{clonedTitle}}“ bylo naklonováno do „{{targetTitle}}“"
|
||||
"note_cloned": "Poznámka „{{clonedTitle}}“ bylo naklonována do „{{targetTitle}}“"
|
||||
},
|
||||
"zpetne_odkazy": {
|
||||
"backlink_one": "{{count}} zpětný odkaz",
|
||||
"backlink_few": "{{count}} zpětné odkazy",
|
||||
"backlink_other": "{{count}} zpětných odkazů"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,10 @@
|
||||
},
|
||||
"bundle-error": {
|
||||
"title": "Benutzerdefiniertes Skript konnte nicht geladen werden",
|
||||
"message": "Skript aus der Notiz \"{{title}}\" mit der ID \"{{id}}\", konnte nicht ausgeführt werden wegen:\n\n{{message}}"
|
||||
"message": "Skript konnte nicht ausgeführt werden wegen:\n\n{{message}}"
|
||||
},
|
||||
"widget-list-error": {
|
||||
"title": "Abruf der Liste von Widgets vom Server ist fehlgeschlagen"
|
||||
}
|
||||
},
|
||||
"add_link": {
|
||||
@@ -162,7 +165,8 @@
|
||||
"quickSearch": "Fokus auf schnelle Sucheingabe",
|
||||
"inPageSearch": "Auf-der-Seite-Suche",
|
||||
"newTabWithActivationNoteLink": "auf einen Notiz-Link öffnet und aktiviert die Notiz in einem neuen Tab",
|
||||
"title": "Spickzettel"
|
||||
"title": "Spickzettel",
|
||||
"editShortcuts": "Tastenkürzel bearbeiten"
|
||||
},
|
||||
"import": {
|
||||
"importIntoNote": "In Notiz importieren",
|
||||
@@ -277,7 +281,6 @@
|
||||
"download_button": "Herunterladen",
|
||||
"mime": "MIME: ",
|
||||
"file_size": "Dateigröße:",
|
||||
"preview": "Vorschau:",
|
||||
"preview_not_available": "Für diesen Notiztyp ist keine Vorschau verfügbar.",
|
||||
"restore_button": "Wiederherstellen",
|
||||
"delete_button": "Löschen",
|
||||
@@ -688,7 +691,11 @@
|
||||
"convert_into_attachment_successful": "Notiz '{{title}}' wurde als Anhang konvertiert.",
|
||||
"convert_into_attachment_prompt": "Bist du dir sicher, dass du die Notiz '{{title}}' in ein Anhang der übergeordneten Notiz konvertieren möchtest?",
|
||||
"print_pdf": "Export als PDF...",
|
||||
"open_note_on_server": "Öffne Notiz auf dem Server"
|
||||
"open_note_on_server": "Öffne Notiz auf dem Server",
|
||||
"export_as_image": "Als Bild exportieren",
|
||||
"export_as_image_png": "PNG (Raster)",
|
||||
"export_as_image_svg": "SVG (Vektor)",
|
||||
"note_map": "Notizen Karte"
|
||||
},
|
||||
"onclick_button": {
|
||||
"no_click_handler": "Das Schaltflächen-Widget „{{componentId}}“ hat keinen definierten Klick-Handler"
|
||||
@@ -745,9 +752,16 @@
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "Notiz-Icon ändern",
|
||||
"category": "Kategorie:",
|
||||
"search": "Suche:",
|
||||
"reset-default": "Standard wiederherstellen"
|
||||
"reset-default": "Standard wiederherstellen",
|
||||
"search_placeholder_one": "Suche {{number}} Icons über {{count}} Pakete",
|
||||
"search_placeholder_other": "Suche {{number}} Icons über {{count}} Pakete",
|
||||
"search_placeholder_filtered": "Suche {{number}} Icons in {{name}}",
|
||||
"filter": "Filter",
|
||||
"filter-none": "Alle Icons",
|
||||
"filter-default": "Standard Icons",
|
||||
"icon_tooltip": "{{name}}\nIcon Paket: {{iconPack}}",
|
||||
"no_results": "Keine Icons gefunden."
|
||||
},
|
||||
"basic_properties": {
|
||||
"note_type": "Notiztyp",
|
||||
@@ -807,7 +821,8 @@
|
||||
},
|
||||
"inherited_attribute_list": {
|
||||
"title": "Geerbte Attribute",
|
||||
"no_inherited_attributes": "Keine geerbten Attribute."
|
||||
"no_inherited_attributes": "Keine geerbten Attribute.",
|
||||
"none": "Keine"
|
||||
},
|
||||
"note_info_widget": {
|
||||
"note_id": "Notiz-ID",
|
||||
@@ -818,7 +833,9 @@
|
||||
"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)",
|
||||
"title": "Notizinfo"
|
||||
"title": "Notizinfo",
|
||||
"mime": "MIME Typ",
|
||||
"show_similar_notes": "Zeige ähnliche Notizen"
|
||||
},
|
||||
"note_map": {
|
||||
"open_full": "Vollständig erweitern",
|
||||
@@ -881,7 +898,8 @@
|
||||
"search_parameters": "Suchparameter",
|
||||
"unknown_search_option": "Unbekannte Suchoption {{searchOptionName}}",
|
||||
"search_note_saved": "Suchnotiz wurde in {{-notePathTitle}} gespeichert",
|
||||
"actions_executed": "Aktionen wurden ausgeführt."
|
||||
"actions_executed": "Aktionen wurden ausgeführt.",
|
||||
"view_options": "Anzeigeoptionen:"
|
||||
},
|
||||
"similar_notes": {
|
||||
"title": "Ähnliche Notizen",
|
||||
@@ -983,7 +1001,14 @@
|
||||
"placeholder": "Gebe hier den Inhalt deiner Codenotiz ein..."
|
||||
},
|
||||
"editable_text": {
|
||||
"placeholder": "Gebe hier den Inhalt deiner Notiz ein..."
|
||||
"placeholder": "Gebe hier den Inhalt deiner Notiz ein...",
|
||||
"auto-detect-language": "Automatisch erkannt",
|
||||
"keeps-crashing": "Die Bearbeitungskomponente stürzt immer wieder ab. Bitte starten Sie Trilium neu. Wenn das Problem weiterhin besteht, erstellen Sie einen Fehlerbericht.",
|
||||
"editor_crashed_title": "Der Text Editor ist abgestürzt",
|
||||
"editor_crashed_content": "Ihr Inhalt wurde erfolgreich wiederhergestellt, aber einzelne Ihrer letzten Änderungen waren möglicherweise noch nicht gespeichert.",
|
||||
"editor_crashed_details_button": "Zeige mehr Details…",
|
||||
"editor_crashed_details_intro": "Falls Sie diesen Fehler mehrmals sehen, melden Sie dies auf GitHub mit den folgenden Informationen.",
|
||||
"editor_crashed_details_title": "Technische Informationen"
|
||||
},
|
||||
"empty": {
|
||||
"open_note_instruction": "Öffne eine Notiz, indem du den Titel der Notiz in die Eingabe unten eingibst oder eine Notiz in der Baumstruktur auswählst.",
|
||||
@@ -1498,7 +1523,12 @@
|
||||
},
|
||||
"highlights_list_2": {
|
||||
"title": "Hervorhebungs-Liste",
|
||||
"options": "Optionen"
|
||||
"options": "Optionen",
|
||||
"title_with_count_one": "{{count}} Highlight",
|
||||
"title_with_count_other": "{{count}} Highlights",
|
||||
"modal_title": "Highlight Liste konfigurieren",
|
||||
"menu_configure": "Highlight Liste konfigurieren…",
|
||||
"no_highlights": "Keine Highlights gefunden."
|
||||
},
|
||||
"quick-search": {
|
||||
"placeholder": "Schnellsuche",
|
||||
@@ -1530,10 +1560,21 @@
|
||||
"note_detail": {
|
||||
"could_not_find_typewidget": "Konnte typeWidget für Typ ‚{{type}}‘ nicht finden",
|
||||
"printing": "Druckvorgang läuft…",
|
||||
"printing_pdf": "PDF-Export läuft…"
|
||||
"printing_pdf": "PDF-Export läuft…",
|
||||
"print_report_title": "Druckreport",
|
||||
"print_report_collection_details_button": "Details anzeigen",
|
||||
"print_report_collection_details_ignored_notes": "Ignorierte Notizen"
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "Titel der Notiz hier eingeben…"
|
||||
"placeholder": "Titel der Notiz hier eingeben…",
|
||||
"created_on": "Erstellt am <Value />",
|
||||
"last_modified": "Bearbeitet am <Value />",
|
||||
"note_type_switcher_label": "Ändere von {{type}} zu:",
|
||||
"note_type_switcher_others": "Andere Notizart",
|
||||
"note_type_switcher_templates": "Template",
|
||||
"note_type_switcher_collection": "Sammlung",
|
||||
"edited_notes": "Notizen, bearbeitet an diesem Tag",
|
||||
"promoted_attributes": "Hervorgehobene Attribute"
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "Es wurden keine Notizen mit den angegebenen Suchparametern gefunden.",
|
||||
@@ -1562,7 +1603,8 @@
|
||||
},
|
||||
"toc": {
|
||||
"table_of_contents": "Inhaltsverzeichnis",
|
||||
"options": "Optionen"
|
||||
"options": "Optionen",
|
||||
"no_headings": "Keine Überschriften."
|
||||
},
|
||||
"watched_file_update_status": {
|
||||
"file_last_modified": "Datei <code class=\"file-path\"></code> wurde zuletzt geändert am <span class=\"file-last-modified\"></span>.",
|
||||
@@ -1624,10 +1666,6 @@
|
||||
"move-to-available-launchers": "Zu verfügbaren Launchern verschieben",
|
||||
"duplicate-launcher": "Launcher duplizieren <kbd data-command=\"duplicateSubtree\">"
|
||||
},
|
||||
"editable-text": {
|
||||
"auto-detect-language": "Automatisch erkannt",
|
||||
"keeps-crashing": "Die Bearbeitungskomponente stürzt immer wieder ab. Bitte starten Sie Trilium neu. Wenn das Problem weiterhin besteht, erstellen Sie einen Fehlerbericht."
|
||||
},
|
||||
"highlighting": {
|
||||
"description": "Steuert die Syntaxhervorhebung für Codeblöcke in Textnotizen, Code-Notizen sind nicht betroffen.",
|
||||
"color-scheme": "Farbschema",
|
||||
@@ -2102,5 +2140,13 @@
|
||||
"clear-color": "Notizfarbe entfernen",
|
||||
"set-color": "Notizfarbe wählen",
|
||||
"set-custom-color": "Eigene Notizfarbe wählen"
|
||||
},
|
||||
"popup-editor": {
|
||||
"maximize": "Wechsele zum vollständigen Editor"
|
||||
},
|
||||
"experimental_features": {
|
||||
"title": "Experimentelle Optionen",
|
||||
"disclaimer": "Diese Optionen sind experimentell und können Instabilitäten verursachen. Achtsam zu verwenden.",
|
||||
"new_layout_name": "Neues Layout"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,17 @@
|
||||
},
|
||||
"bundle-error": {
|
||||
"title": "Failed to load a custom script",
|
||||
"message": "Script from note with ID \"{{id}}\", titled \"{{title}}\" could not be executed due to:\n\n{{message}}"
|
||||
}
|
||||
"message": "Script could not be executed due to:\n\n{{message}}"
|
||||
},
|
||||
"widget-list-error": {
|
||||
"title": "Failed to obtain the list of widgets from the server"
|
||||
},
|
||||
"widget-render-error": {
|
||||
"title": "Failed to render a custom React widget"
|
||||
},
|
||||
"widget-missing-parent": "Custom widget does not have mandatory '{{property}}' property defined.\n\nIf this script is meant to be run without a UI element, use '#run=frontendStartup' instead.",
|
||||
"open-script-note": "Open script note",
|
||||
"scripting-error": "Custom script error: {{title}}"
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "Add link",
|
||||
@@ -205,7 +214,8 @@
|
||||
"info": {
|
||||
"modalTitle": "Info message",
|
||||
"closeButton": "Close",
|
||||
"okButton": "OK"
|
||||
"okButton": "OK",
|
||||
"copy_to_clipboard": "Copy to clipboard"
|
||||
},
|
||||
"jump_to_note": {
|
||||
"search_placeholder": "Search for note by its name or type > for commands...",
|
||||
@@ -285,7 +295,6 @@
|
||||
"download_button": "Download",
|
||||
"mime": "MIME: ",
|
||||
"file_size": "File size:",
|
||||
"preview": "Preview:",
|
||||
"preview_not_available": "Preview isn't available for this note type."
|
||||
},
|
||||
"sort_child_notes": {
|
||||
@@ -688,11 +697,17 @@
|
||||
"export_note": "Export note",
|
||||
"delete_note": "Delete note",
|
||||
"print_note": "Print note",
|
||||
"view_revisions": "Note revisions...",
|
||||
"save_revision": "Save revision",
|
||||
"advanced": "Advanced",
|
||||
"convert_into_attachment_failed": "Converting note '{{title}}' failed.",
|
||||
"convert_into_attachment_successful": "Note '{{title}}' has been converted to attachment.",
|
||||
"convert_into_attachment_prompt": "Are you sure you want to convert note '{{title}}' into an attachment of the parent note?",
|
||||
"print_pdf": "Export as PDF..."
|
||||
"print_pdf": "Export as PDF...",
|
||||
"export_as_image": "Export as image",
|
||||
"export_as_image_png": "PNG (raster)",
|
||||
"export_as_image_svg": "SVG (vector)",
|
||||
"note_map": "Note map"
|
||||
},
|
||||
"onclick_button": {
|
||||
"no_click_handler": "Button widget '{{componentId}}' has no defined click handler"
|
||||
@@ -749,9 +764,16 @@
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "Change note icon",
|
||||
"category": "Category:",
|
||||
"search": "Search:",
|
||||
"reset-default": "Reset to default icon"
|
||||
"search_placeholder_one": "Search {{number}} icons across {{count}} packs",
|
||||
"search_placeholder_other": "Search {{number}} icons across {{count}} packs",
|
||||
"search_placeholder_filtered": "Search {{number}} icons in {{name}}",
|
||||
"reset-default": "Reset to default icon",
|
||||
"filter": "Filter",
|
||||
"filter-none": "All icons",
|
||||
"filter-default": "Default icons",
|
||||
"icon_tooltip": "{{name}}\nIcon pack: {{iconPack}}",
|
||||
"no_results": "No icons found."
|
||||
},
|
||||
"basic_properties": {
|
||||
"note_type": "Note type",
|
||||
@@ -791,7 +813,7 @@
|
||||
"file_type": "File type",
|
||||
"file_size": "File size",
|
||||
"download": "Download",
|
||||
"open": "Open",
|
||||
"open": "Open externally",
|
||||
"upload_new_revision": "Upload new revision",
|
||||
"upload_success": "New file revision has been uploaded.",
|
||||
"upload_failed": "Upload of a new file revision failed.",
|
||||
@@ -811,18 +833,21 @@
|
||||
},
|
||||
"inherited_attribute_list": {
|
||||
"title": "Inherited Attributes",
|
||||
"no_inherited_attributes": "No inherited attributes."
|
||||
"no_inherited_attributes": "No inherited attributes.",
|
||||
"none": "none"
|
||||
},
|
||||
"note_info_widget": {
|
||||
"note_id": "Note ID",
|
||||
"created": "Created",
|
||||
"modified": "Modified",
|
||||
"type": "Type",
|
||||
"mime": "MIME type",
|
||||
"note_size": "Note size",
|
||||
"note_size_info": "Note size provides rough estimate of storage requirements for this note. It takes into account note's content and content of its note revisions.",
|
||||
"calculate": "calculate",
|
||||
"subtree_size": "(subtree size: {{size}} in {{count}} notes)",
|
||||
"title": "Note Info"
|
||||
"title": "Note Info",
|
||||
"show_similar_notes": "Show similar notes"
|
||||
},
|
||||
"note_map": {
|
||||
"open_full": "Expand to full",
|
||||
@@ -885,7 +910,8 @@
|
||||
"search_parameters": "Search Parameters",
|
||||
"unknown_search_option": "Unknown search option {{searchOptionName}}",
|
||||
"search_note_saved": "Search note has been saved into {{- notePathTitle}}",
|
||||
"actions_executed": "Actions have been executed."
|
||||
"actions_executed": "Actions have been executed.",
|
||||
"view_options": "View options:"
|
||||
},
|
||||
"similar_notes": {
|
||||
"title": "Similar Notes",
|
||||
@@ -987,7 +1013,14 @@
|
||||
"placeholder": "Type the content of your code note here..."
|
||||
},
|
||||
"editable_text": {
|
||||
"placeholder": "Type the content of your note here..."
|
||||
"placeholder": "Type the content of your note here...",
|
||||
"editor_crashed_title": "The text editor crashed",
|
||||
"editor_crashed_content": "Your content was recovered successfully, but a few of your most recent changes may not have been saved.",
|
||||
"editor_crashed_details_button": "View more details...",
|
||||
"editor_crashed_details_intro": "If you experience this error several times, consider reporting it on GitHub by pasting the information below.",
|
||||
"editor_crashed_details_title": "Technical information",
|
||||
"auto-detect-language": "Auto-detected",
|
||||
"keeps-crashing": "Editing component keeps crashing. Please try restarting Trilium. If problem persists, consider creating a bug report."
|
||||
},
|
||||
"empty": {
|
||||
"open_note_instruction": "Open a note by typing the note's title into the input below or choose a note in the tree.",
|
||||
@@ -1088,6 +1121,12 @@
|
||||
"vacuuming_database": "Vacuuming database...",
|
||||
"database_vacuumed": "Database has been vacuumed"
|
||||
},
|
||||
"experimental_features": {
|
||||
"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."
|
||||
},
|
||||
"fonts": {
|
||||
"theme_defined": "Theme defined",
|
||||
"fonts": "Fonts",
|
||||
@@ -1580,7 +1619,7 @@
|
||||
"will_be_deleted_in": "This attachment will be automatically deleted in {{time}}",
|
||||
"will_be_deleted_soon": "This attachment will be automatically deleted soon",
|
||||
"deletion_reason": ", because the attachment is not linked in the note's content. To prevent deletion, add the attachment link back into the content or convert the attachment into note.",
|
||||
"role_and_size": "Role: {{role}}, Size: {{size}}",
|
||||
"role_and_size": "Role: {{role}}, size: {{size}}, MIME: {{- mimeType}}",
|
||||
"link_copied": "Attachment link copied to clipboard.",
|
||||
"unrecognized_role": "Unrecognized attachment role '{{role}}'."
|
||||
},
|
||||
@@ -1700,7 +1739,12 @@
|
||||
},
|
||||
"highlights_list_2": {
|
||||
"title": "Highlights List",
|
||||
"options": "Options"
|
||||
"title_with_count_one": "{{count}} highlight",
|
||||
"title_with_count_other": "{{count}} highlights",
|
||||
"options": "Options",
|
||||
"modal_title": "Configure Highlights List",
|
||||
"menu_configure": "Configure highlights list...",
|
||||
"no_highlights": "No highlights found."
|
||||
},
|
||||
"quick-search": {
|
||||
"placeholder": "Quick search",
|
||||
@@ -1724,7 +1768,11 @@
|
||||
"create-child-note": "Create child note",
|
||||
"unhoist": "Unhoist",
|
||||
"toggle-sidebar": "Toggle sidebar",
|
||||
"dropping-not-allowed": "Dropping notes into this location is not allowed."
|
||||
"dropping-not-allowed": "Dropping notes into this location is not allowed.",
|
||||
"clone-indicator-tooltip": "This note has {{- count}} parents: {{- parents}}",
|
||||
"clone-indicator-tooltip-single": "This note is cloned (1 additional parent: {{- parent}})",
|
||||
"shared-indicator-tooltip": "This note is shared publicly",
|
||||
"shared-indicator-tooltip-with-url": "This note is shared publicly at: {{- url}}"
|
||||
},
|
||||
"title_bar_buttons": {
|
||||
"window-on-top": "Keep Window on Top"
|
||||
@@ -1732,10 +1780,23 @@
|
||||
"note_detail": {
|
||||
"could_not_find_typewidget": "Could not find typeWidget for type '{{type}}'",
|
||||
"printing": "Printing in progress...",
|
||||
"printing_pdf": "Exporting to PDF in progress..."
|
||||
"printing_pdf": "Exporting to PDF in progress...",
|
||||
"print_report_title": "Print report",
|
||||
"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",
|
||||
"print_report_collection_details_ignored_notes": "Ignored notes"
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "type note's title here..."
|
||||
"placeholder": "type note's title here...",
|
||||
"created_on": "Created on <Value />",
|
||||
"last_modified": "Modified on <Value />",
|
||||
"note_type_switcher_label": "Switch from {{type}} to:",
|
||||
"note_type_switcher_others": "Other note type",
|
||||
"note_type_switcher_templates": "Template",
|
||||
"note_type_switcher_collection": "Collection",
|
||||
"edited_notes": "Notes edited on this day",
|
||||
"promoted_attributes": "Promoted attributes"
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "No notes have been found for given search parameters.",
|
||||
@@ -1764,7 +1825,8 @@
|
||||
},
|
||||
"toc": {
|
||||
"table_of_contents": "Table of Contents",
|
||||
"options": "Options"
|
||||
"options": "Options",
|
||||
"no_headings": "No headings."
|
||||
},
|
||||
"watched_file_update_status": {
|
||||
"file_last_modified": "File <code class=\"file-path\"></code> has been last modified on <span class=\"file-last-modified\"></span>.",
|
||||
@@ -1826,10 +1888,6 @@
|
||||
"move-to-available-launchers": "Move to available launchers",
|
||||
"duplicate-launcher": "Duplicate launcher <kbd data-command=\"duplicateSubtree\">"
|
||||
},
|
||||
"editable-text": {
|
||||
"auto-detect-language": "Auto-detected",
|
||||
"keeps-crashing": "Editing component keeps crashing. Please try restarting Trilium. If problem persists, consider creating a bug report."
|
||||
},
|
||||
"highlighting": {
|
||||
"title": "Code Blocks",
|
||||
"description": "Controls the syntax highlighting for code blocks inside text notes, code notes will not be affected.",
|
||||
@@ -1949,8 +2007,9 @@
|
||||
"unknown_widget": "Unknown widget for \"{{id}}\"."
|
||||
},
|
||||
"note_language": {
|
||||
"not_set": "Not set",
|
||||
"configure-languages": "Configure languages..."
|
||||
"not_set": "No language set",
|
||||
"configure-languages": "Configure languages...",
|
||||
"help-on-languages": "Help on content languages..."
|
||||
},
|
||||
"content_language": {
|
||||
"title": "Content languages",
|
||||
@@ -1968,7 +2027,8 @@
|
||||
"button_title": "Export diagram as PNG"
|
||||
},
|
||||
"svg": {
|
||||
"export_to_png": "The diagram could not be exported to PNG."
|
||||
"export_to_png": "The diagram could not be exported to PNG.",
|
||||
"export_to_svg": "The diagram could not be exported to SVG."
|
||||
},
|
||||
"code_theme": {
|
||||
"title": "Appearance",
|
||||
@@ -2016,7 +2076,7 @@
|
||||
"book_properties_config": {
|
||||
"hide-weekends": "Hide weekends",
|
||||
"display-week-numbers": "Display week numbers",
|
||||
"map-style": "Map style:",
|
||||
"map-style": "Map style",
|
||||
"max-nesting-depth": "Max nesting depth:",
|
||||
"raster": "Raster",
|
||||
"vector_light": "Vector (Light)",
|
||||
@@ -2081,6 +2141,9 @@
|
||||
"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_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.",
|
||||
"new_layout_button": "More info",
|
||||
"dismiss": "Dismiss"
|
||||
},
|
||||
"settings": {
|
||||
@@ -2088,7 +2151,10 @@
|
||||
},
|
||||
"settings_appearance": {
|
||||
"related_code_blocks": "Color scheme for code blocks in text notes",
|
||||
"related_code_notes": "Color scheme for code notes"
|
||||
"related_code_notes": "Color scheme for code notes",
|
||||
"ui": "User interface",
|
||||
"ui_old_layout": "Old layout",
|
||||
"ui_new_layout": "New layout"
|
||||
},
|
||||
"units": {
|
||||
"percentage": "%"
|
||||
@@ -2107,5 +2173,86 @@
|
||||
},
|
||||
"popup-editor": {
|
||||
"maximize": "Switch to full editor"
|
||||
},
|
||||
"server": {
|
||||
"unknown_http_error_title": "Communication error with the server",
|
||||
"unknown_http_error_content": "Status code: {{statusCode}}\nURL: {{method}} {{url}}\nMessage: {{message}}",
|
||||
"traefik_blocks_requests": "If you are using the Traefik reverse proxy, it introduced a breaking change which affects the communication with the server."
|
||||
},
|
||||
"tab_history_navigation_buttons": {
|
||||
"go-back": "Go back to previous note",
|
||||
"go-forward": "Go forward to next note"
|
||||
},
|
||||
"breadcrumb": {
|
||||
"hoisted_badge": "Hoisted",
|
||||
"hoisted_badge_title": "Unhoist",
|
||||
"workspace_badge": "Workspace",
|
||||
"scroll_to_top_title": "Jump to the beginning of the note",
|
||||
"create_new_note": "Create new child note",
|
||||
"empty_hide_archived_notes": "Hide archived notes"
|
||||
},
|
||||
"breadcrumb_badges": {
|
||||
"read_only_explicit": "Read-only",
|
||||
"read_only_explicit_description": "This note has been manually set to read-only.\nClick to edit it temporarily.",
|
||||
"read_only_auto": "Auto read-only",
|
||||
"read_only_auto_description": "This note was set automatically to read-only mode for performance reasons. This automatic limit is adjustable from settings.\n\nClick to edit it temporarily.",
|
||||
"read_only_temporarily_disabled": "Temporarily editable",
|
||||
"read_only_temporarily_disabled_description": "This note is currently editable, but it is normally read-only. The note will go back to being read-only as soon as you navigate to another note.\n\nClick to re-enable read-only mode.",
|
||||
"shared_publicly": "Shared publicly",
|
||||
"shared_locally": "Shared locally",
|
||||
"shared_copy_to_clipboard": "Copy link to clipboard",
|
||||
"shared_open_in_browser": "Open link in browser",
|
||||
"shared_unshare": "Remove share",
|
||||
"clipped_note": "Web clip",
|
||||
"clipped_note_description": "This note was originally taken from {{url}}.\n\nClick to navigate to the source webpage.",
|
||||
"execute_script": "Run script",
|
||||
"execute_script_description": "This note is a script note. Click to execute the script.",
|
||||
"execute_sql": "Run SQL",
|
||||
"execute_sql_description": "This note is a SQL note. Click to execute the SQL query.",
|
||||
"save_status_saved": "Saved",
|
||||
"save_status_saving": "Saving...",
|
||||
"save_status_unsaved": "Unsaved",
|
||||
"save_status_error": "Save failed",
|
||||
"save_status_saving_tooltip": "Changes are being saved.",
|
||||
"save_status_unsaved_tooltip": "There are unsaved changes. They will be saved automatically in a moment.",
|
||||
"save_status_error_tooltip": "An error occurred while saving the note. If possible, try copying the note content elsewhere and reloading the application."
|
||||
},
|
||||
"status_bar": {
|
||||
"language_title": "Change content language",
|
||||
"note_info_title": "View note info (e.g., dates, note size)",
|
||||
"backlinks_one": "{{count}} backlink",
|
||||
"backlinks_other": "{{count}} backlinks",
|
||||
"backlinks_title_one": "View backlink",
|
||||
"backlinks_title_other": "View backlinks",
|
||||
"attachments_one": "{{count}} attachment",
|
||||
"attachments_other": "{{count}} attachments",
|
||||
"attachments_title_one": "View attachment in a new tab",
|
||||
"attachments_title_other": "View attachments in a new tab",
|
||||
"attributes_one": "{{count}} attribute",
|
||||
"attributes_other": "{{count}} attributes",
|
||||
"attributes_title": "Owned attributes and inherited attributes",
|
||||
"note_paths_one": "{{count}} path",
|
||||
"note_paths_other": "{{count}} paths",
|
||||
"note_paths_title": "Note paths",
|
||||
"code_note_switcher": "Change language mode"
|
||||
},
|
||||
"attributes_panel": {
|
||||
"title": "Note Attributes"
|
||||
},
|
||||
"right_pane": {
|
||||
"empty_message": "Nothing to show for this note",
|
||||
"empty_button": "Hide the panel",
|
||||
"toggle": "Toggle right panel",
|
||||
"custom_widget_go_to_source": "Go to source code"
|
||||
},
|
||||
"pdf": {
|
||||
"attachments_one": "{{count}} attachment",
|
||||
"attachments_other": "{{count}} attachments",
|
||||
"layers_one": "{{count}} layer",
|
||||
"layers_other": "{{count}} layers",
|
||||
"pages_one": "{{count}} page",
|
||||
"pages_other": "{{count}} pages",
|
||||
"pages_alt": "Page {{pageNumber}}",
|
||||
"pages_loading": "Loading..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,6 @@
|
||||
"download_button": "Descargar",
|
||||
"mime": "MIME: ",
|
||||
"file_size": "Tamaño del archivo:",
|
||||
"preview": "Vista previa:",
|
||||
"preview_not_available": "La vista previa no está disponible para este tipo de notas.",
|
||||
"diff_off": "Mostrar contenido",
|
||||
"diff_on": "Mostrar diferencia",
|
||||
@@ -749,7 +748,6 @@
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "Cambiar icono de nota",
|
||||
"category": "Categoría:",
|
||||
"search": "Búsqueda:",
|
||||
"reset-default": "Restablecer a icono por defecto"
|
||||
},
|
||||
@@ -987,7 +985,8 @@
|
||||
"placeholder": "Escriba el contenido de su nota de código aquí..."
|
||||
},
|
||||
"editable_text": {
|
||||
"placeholder": "Escribe aquí el contenido de tu nota..."
|
||||
"placeholder": "Escribe aquí el contenido de tu nota...",
|
||||
"auto-detect-language": "Detectado automáticamente"
|
||||
},
|
||||
"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.",
|
||||
@@ -1812,9 +1811,6 @@
|
||||
"move-to-available-launchers": "Mover a lanzadores disponibles",
|
||||
"duplicate-launcher": "Duplicar lanzador <kbd data-command=\"duplicateSubtree\">"
|
||||
},
|
||||
"editable-text": {
|
||||
"auto-detect-language": "Detectado automáticamente"
|
||||
},
|
||||
"highlighting": {
|
||||
"title": "Bloques de código",
|
||||
"description": "Controla el resaltado de sintaxis para bloques de código dentro de las notas de texto, las notas de código no serán afectadas.",
|
||||
|
||||
@@ -22,6 +22,12 @@
|
||||
"bundle-error": {
|
||||
"title": "Echec du chargement d'un script personnalisé",
|
||||
"message": "Le script de la note avec l'ID \"{{id}}\", intitulé \"{{title}}\" n'a pas pu être exécuté à cause de\n\n{{message}}"
|
||||
},
|
||||
"widget-list-error": {
|
||||
"title": "Impossible d'obtenir la liste des widgets depuis le serveur"
|
||||
},
|
||||
"widget-render-error": {
|
||||
"title": "Rendu impossible d'un widget React custom"
|
||||
}
|
||||
},
|
||||
"add_link": {
|
||||
@@ -107,7 +113,8 @@
|
||||
"export_status": "Statut d'exportation",
|
||||
"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."
|
||||
"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."
|
||||
},
|
||||
"help": {
|
||||
"noteNavigation": "Navigation dans les notes",
|
||||
@@ -161,7 +168,8 @@
|
||||
"quickSearch": "aller à la recherche rapide",
|
||||
"inPageSearch": "recherche sur la page",
|
||||
"title": "Aide-mémoire",
|
||||
"newTabWithActivationNoteLink": "Lorsqu’on clique sur un lien de note, celle-ci s’ouvre et devient active dans un nouvel onglet"
|
||||
"newTabWithActivationNoteLink": "Lorsqu’on clique sur un lien de note, celle-ci s’ouvre et devient active dans un nouvel onglet",
|
||||
"editShortcuts": "Modifier les raccourcis clavier"
|
||||
},
|
||||
"import": {
|
||||
"importIntoNote": "Importer dans la note",
|
||||
@@ -203,7 +211,8 @@
|
||||
"info": {
|
||||
"modalTitle": "Message d'information",
|
||||
"closeButton": "Fermer",
|
||||
"okButton": "OK"
|
||||
"okButton": "OK",
|
||||
"copy_to_clipboard": "Copier dans le presse-papiers"
|
||||
},
|
||||
"jump_to_note": {
|
||||
"search_button": "Rechercher dans le texte intégral",
|
||||
@@ -276,7 +285,6 @@
|
||||
"download_button": "Télécharger",
|
||||
"mime": "MIME : ",
|
||||
"file_size": "Taille du fichier :",
|
||||
"preview": "Aperçu :",
|
||||
"preview_not_available": "L'aperçu n'est pas disponible pour ce type de note.",
|
||||
"restore_button": "Restaurer",
|
||||
"delete_button": "Supprimer",
|
||||
@@ -689,7 +697,13 @@
|
||||
"convert_into_attachment_failed": "La conversion de la note '{{title}}' a échoué.",
|
||||
"convert_into_attachment_successful": "La note '{{title}}' a été convertie en pièce jointe.",
|
||||
"convert_into_attachment_prompt": "Êtes-vous sûr de vouloir convertir la note '{{title}}' en une pièce jointe de la note parente ?",
|
||||
"print_pdf": "Exporter en PDF..."
|
||||
"print_pdf": "Exporter en PDF...",
|
||||
"open_note_on_server": "Ouvrir la note sur le serveur",
|
||||
"view_revisions": "Révisions...",
|
||||
"advanced": "Avancé",
|
||||
"export_as_image": "Exporter en tant qu'image",
|
||||
"export_as_image_png": "PNG",
|
||||
"export_as_image_svg": "SVG (vectoriel)"
|
||||
},
|
||||
"onclick_button": {
|
||||
"no_click_handler": "Le widget bouton '{{componentId}}' n'a pas de gestionnaire de clic défini"
|
||||
@@ -747,9 +761,12 @@
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "Changer l'icône de note",
|
||||
"category": "Catégorie :",
|
||||
"search": "Recherche :",
|
||||
"reset-default": "Réinitialiser l'icône par défaut"
|
||||
"reset-default": "Réinitialiser l'icône par défaut",
|
||||
"filter": "Filtre",
|
||||
"filter-none": "Toutes les icônes",
|
||||
"filter-default": "Icônes par défaut",
|
||||
"icon_tooltip": "{{name}}\nPack d'icônes : {{iconPack}}"
|
||||
},
|
||||
"basic_properties": {
|
||||
"note_type": "Type de note",
|
||||
@@ -772,7 +789,11 @@
|
||||
"geo-map": "Carte géographique",
|
||||
"board": "Tableau de bord",
|
||||
"include_archived_notes": "Afficher les notes archivées",
|
||||
"presentation": "Présentation"
|
||||
"presentation": "Présentation",
|
||||
"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"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "Aucune note modifiée ce jour-là...",
|
||||
@@ -816,7 +837,9 @@
|
||||
"note_size_info": "La taille de la note fournit une estimation approximative des besoins de stockage pour cette note. Il prend en compte le contenu de la note et de ses versions.",
|
||||
"calculate": "calculer",
|
||||
"subtree_size": "(taille du sous-arbre : {{size}} pour {{count}} notes)",
|
||||
"title": "Infos sur la Note"
|
||||
"title": "Infos sur la Note",
|
||||
"mime": "type MIME",
|
||||
"show_similar_notes": "Afficher des notes similaires"
|
||||
},
|
||||
"note_map": {
|
||||
"open_full": "Développer au maximum",
|
||||
@@ -879,7 +902,8 @@
|
||||
"search_parameters": "Paramètres de recherche",
|
||||
"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."
|
||||
"actions_executed": "Les actions ont été exécutées.",
|
||||
"view_options": "Afficher les options:"
|
||||
},
|
||||
"similar_notes": {
|
||||
"title": "Notes similaires",
|
||||
@@ -981,7 +1005,14 @@
|
||||
"placeholder": "Saisir le contenu de votre note de code ici..."
|
||||
},
|
||||
"editable_text": {
|
||||
"placeholder": "Saisir le contenu de votre note ici..."
|
||||
"placeholder": "Saisir le contenu de votre note ici...",
|
||||
"auto-detect-language": "Détecté automatiquement",
|
||||
"editor_crashed_title": "L'éditeur de texte a cessé de fonctionner",
|
||||
"editor_crashed_content": "Votre contenu a été récupéré avec succès, mais certaines de vos modifications les plus récentes n'ont peut-être pas été enregistrées.",
|
||||
"editor_crashed_details_button": "Afficher plus de détails...",
|
||||
"editor_crashed_details_intro": "Si cette erreur se produit plusieurs fois, pensez à la signaler sur GitHub en collant les informations ci-dessous.",
|
||||
"editor_crashed_details_title": "Informations techniques",
|
||||
"keeps-crashing": "Le composant d'édition cesse de fonctionner. Veuillez essayer de redémarrer Trilium. Si le problème persiste, envisager de créer un rapport de bogue."
|
||||
},
|
||||
"empty": {
|
||||
"open_note_instruction": "Ouvrez une note en tapant son titre dans la zone ci-dessous ou choisissez une note dans l'arborescence.",
|
||||
@@ -1076,9 +1107,9 @@
|
||||
"failed": "Échec de la synchronisation : {{message}}"
|
||||
},
|
||||
"vacuum_database": {
|
||||
"title": "Nettoyage la base de donnée",
|
||||
"title": "Nettoyage de la base de données",
|
||||
"description": "Cela reconstruira la base de données, ce qui générera un fichier de base de données généralement plus petit. Aucune donnée ne sera réellement modifiée.",
|
||||
"button_text": "Nettoyer de la base de donnée",
|
||||
"button_text": "Nettoyer la base de données",
|
||||
"vacuuming_database": "Nettoyage de la base de données en cours...",
|
||||
"database_vacuumed": "La base de données a été nettoyée"
|
||||
},
|
||||
@@ -1109,7 +1140,8 @@
|
||||
"title": "Largeur du contenu",
|
||||
"default_description": "Trilium limite par défaut la largeur maximale du contenu pour améliorer la lisibilité sur des écrans larges.",
|
||||
"max_width_label": "Largeur maximale du contenu en pixels",
|
||||
"max_width_unit": "Pixels"
|
||||
"max_width_unit": "Pixels",
|
||||
"centerContent": "Garder le contenu centré"
|
||||
},
|
||||
"native_title_bar": {
|
||||
"title": "Barre de titre native (nécessite le redémarrage de l'application)",
|
||||
@@ -1148,7 +1180,10 @@
|
||||
"unit": "caractères"
|
||||
},
|
||||
"code_mime_types": {
|
||||
"title": "Types MIME disponibles dans la liste déroulante"
|
||||
"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_code_note_syntax": "Notes de code"
|
||||
},
|
||||
"vim_key_bindings": {
|
||||
"use_vim_keybindings_in_code_notes": "Raccourcis clavier Vim",
|
||||
@@ -1515,7 +1550,8 @@
|
||||
"refresh-saved-search-results": "Rafraîchir les résultats de recherche enregistrée",
|
||||
"create-child-note": "Créer une note enfant",
|
||||
"unhoist": "Désactiver le focus",
|
||||
"toggle-sidebar": "Basculer la barre latérale"
|
||||
"toggle-sidebar": "Basculer la barre latérale",
|
||||
"dropping-not-allowed": "Lâcher des notes à cet endroit n'est pas autorisé"
|
||||
},
|
||||
"title_bar_buttons": {
|
||||
"window-on-top": "Épingler cette fenêtre au premier plan"
|
||||
@@ -1523,10 +1559,19 @@
|
||||
"note_detail": {
|
||||
"could_not_find_typewidget": "Impossible de trouver typeWidget pour le type '{{type}}'",
|
||||
"printing": "Impression en cours...",
|
||||
"printing_pdf": "Export au format PDF en cours..."
|
||||
"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"
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "saisir le titre de la note ici..."
|
||||
"placeholder": "saisir le titre de la note ici...",
|
||||
"created_on": "Créé le <Value />",
|
||||
"last_modified": "Modifié le <Value />",
|
||||
"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"
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "Aucune note n'a été trouvée pour les paramètres de recherche donnés.",
|
||||
@@ -1555,7 +1600,8 @@
|
||||
},
|
||||
"toc": {
|
||||
"table_of_contents": "Table des matières",
|
||||
"options": "Options"
|
||||
"options": "Options",
|
||||
"no_headings": "Pas d'en-tête."
|
||||
},
|
||||
"watched_file_update_status": {
|
||||
"file_last_modified": "Le fichier <code class=\"file-path\"></code> a été modifié pour la dernière fois le <span class=\"file-last-modified\"></span>.",
|
||||
@@ -1617,9 +1663,6 @@
|
||||
"move-to-available-launchers": "Déplacer vers les raccourcis disponibles",
|
||||
"duplicate-launcher": "Dupliquer le raccourci <kbd data-command=\"duplicateSubtree\">"
|
||||
},
|
||||
"editable-text": {
|
||||
"auto-detect-language": "Détecté automatiquement"
|
||||
},
|
||||
"highlighting": {
|
||||
"description": "Contrôle la coloration syntaxique des blocs de code à l'intérieur des notes texte, les notes de code ne seront pas affectées.",
|
||||
"color-scheme": "Jeu de couleurs",
|
||||
@@ -1659,7 +1702,8 @@
|
||||
"copy-link": "Copier le lien",
|
||||
"paste": "Coller",
|
||||
"paste-as-plain-text": "Coller comme texte brut",
|
||||
"search_online": "Rechercher «{{term}}» avec {{searchEngine}}"
|
||||
"search_online": "Rechercher «{{term}}» avec {{searchEngine}}",
|
||||
"search_in_trilium": "Rechercher \"{{term}}\" dans Trilium"
|
||||
},
|
||||
"image_context_menu": {
|
||||
"copy_reference_to_clipboard": "Copier la référence dans le presse-papiers",
|
||||
@@ -1968,7 +2012,8 @@
|
||||
"add-column": "Ajouter une colonne",
|
||||
"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"
|
||||
"edit-column-title": "Cliquez pour modifier le titre de la colonne",
|
||||
"column-already-exists": "Cette colonne existe déjà dans le tableau."
|
||||
},
|
||||
"presentation_view": {
|
||||
"edit-slide": "Modifier cette diapositive",
|
||||
@@ -2052,7 +2097,8 @@
|
||||
"button_title": "Exporter le diagramme au format PNG"
|
||||
},
|
||||
"svg": {
|
||||
"export_to_png": "Le diagramme n'a pas pu être exporté au format PNG."
|
||||
"export_to_png": "Le diagramme n'a pas pu être exporté au format PNG.",
|
||||
"export_to_svg": "Le diagramme n'a pas pu être exporté en SVG."
|
||||
},
|
||||
"code_theme": {
|
||||
"title": "Apparence",
|
||||
@@ -2076,5 +2122,19 @@
|
||||
"note_completion_description": "Si cette option est activée, des liens vers des notes peuvent être créés en tapant `@` suivi du titre d'une note.",
|
||||
"slash_commands_enabled": "Activer les commandes slash",
|
||||
"slash_commands_description": "Si cette option est activée, les commandes d'édition telles que l'insertion de sauts de ligne ou d'en-têtes peuvent être activées en tapant `/`."
|
||||
},
|
||||
"experimental_features": {
|
||||
"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."
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"calendar_view": {
|
||||
"delete_note": "Effacer la note..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,35 @@
|
||||
{
|
||||
"about": {
|
||||
"title": "ट्रिलियम नोट्स के बारें में"
|
||||
"title": "ट्रिलियम नोट्स के बारें में",
|
||||
"build_date": "निर्माण की तारीख:"
|
||||
},
|
||||
"toast": {
|
||||
"widget-error": {
|
||||
"title": "एक विजेट को इनिशियलाइज़ करने में विफल रहा"
|
||||
},
|
||||
"bundle-error": {
|
||||
"title": "एक कस्टम स्क्रिप्ट लोड करने में विफल रहा"
|
||||
},
|
||||
"widget-list-error": {
|
||||
"title": "सर्वर से विजेट्स की सूची प्राप्त करने में विफल"
|
||||
},
|
||||
"open-script-note": "स्क्रिप्ट नोट खोलें"
|
||||
},
|
||||
"update_available": {
|
||||
"update_available": "उपलब्ध अद्यतन"
|
||||
},
|
||||
"code_buttons": {
|
||||
"execute_button_title": "स्क्रिप्ट एक्सीक्यूट करें",
|
||||
"trilium_api_docs_button_title": "ट्रिलियम एपीआई डॉक्स खोलें",
|
||||
"save_to_note_button_title": "नोट में सेव करें"
|
||||
},
|
||||
"hide_floating_buttons_button": {
|
||||
"button_title": "बटन छुपाएं"
|
||||
},
|
||||
"show_floating_buttons_button": {
|
||||
"button_title": "बटन दिखाएं"
|
||||
},
|
||||
"add_link": {
|
||||
"note": "नोट"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,13 +16,22 @@
|
||||
},
|
||||
"bundle-error": {
|
||||
"title": "Non si è riusciti a caricare uno script personalizzato",
|
||||
"message": "Lo script della nota con ID \"{{id}}\", dal titolo \"{{title}}\" non è stato inizializzato a causa di:\n\n{{message}}"
|
||||
"message": "Impossibile eseguire lo script a causa di:\n\n{{message}}"
|
||||
},
|
||||
"widget-error": {
|
||||
"title": "Impossibile inizializzare un widget",
|
||||
"message-custom": "Il widget personalizzato dalla nota con ID “{{id}}”, intitolato “{{title}}”, non è stato possibile inizializzare a causa di:\n\n{{message}}",
|
||||
"message-unknown": "Un widget sconosciuto non è stato inizializzato a causa di:\n\n{{message}}"
|
||||
}
|
||||
},
|
||||
"widget-list-error": {
|
||||
"title": "Impossibile ottenere l'elenco dei widget dal server"
|
||||
},
|
||||
"widget-render-error": {
|
||||
"title": "Impossibile eseguire il rendering di un widget React personalizzato"
|
||||
},
|
||||
"widget-missing-parent": "Il widget personalizzato non ha la proprietà obbligatoria '{{property}}' definita.\n\nSe questo script deve essere eseguito senza un elemento dell'interfaccia utente, utilizzare invece '#run=frontendStartup'.",
|
||||
"open-script-note": "Apri script note",
|
||||
"scripting-error": "Errore script personalizzato: {{title}}"
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "Aggiungi un collegamento",
|
||||
@@ -94,7 +103,8 @@
|
||||
"info": {
|
||||
"okButton": "OK",
|
||||
"closeButton": "Chiudi",
|
||||
"modalTitle": "Messaggio informativo"
|
||||
"modalTitle": "Messaggio informativo",
|
||||
"copy_to_clipboard": "Copia negli appunti"
|
||||
},
|
||||
"export": {
|
||||
"close": "Chiudi",
|
||||
@@ -314,7 +324,7 @@
|
||||
"import-into-note": "Importa nella nota",
|
||||
"apply-bulk-actions": "Applica azioni in blocco",
|
||||
"converted-to-attachments": "{{count}} note sono state convertite in allegati.",
|
||||
"convert-to-attachment-confirm": "Sei sicuro di voler convertire le note selezionate in allegati delle note padre?",
|
||||
"convert-to-attachment-confirm": "Sei sicuro di voler convertire le note selezionate in allegati delle note principali? Questa operazione si applica solo alle note immagine, le altre note verranno ignorate.",
|
||||
"open-in-popup": "Modifica rapida"
|
||||
},
|
||||
"electron_context_menu": {
|
||||
@@ -408,7 +418,8 @@
|
||||
"search_parameters": "Parametri di ricerca",
|
||||
"unknown_search_option": "Opzione di ricerca sconosciuta {{searchOptionName}}",
|
||||
"search_note_saved": "La nota di ricerca è stata salvata in {{- notePathTitle}}",
|
||||
"actions_executed": "Le azioni sono state eseguite."
|
||||
"actions_executed": "Le azioni sono state eseguite.",
|
||||
"view_options": "Opzioni di visualizzazione:"
|
||||
},
|
||||
"modal": {
|
||||
"close": "Chiudi",
|
||||
@@ -521,7 +532,8 @@
|
||||
},
|
||||
"toc": {
|
||||
"table_of_contents": "Sommario",
|
||||
"options": "Opzioni"
|
||||
"options": "Opzioni",
|
||||
"no_headings": "Nessun titolo."
|
||||
},
|
||||
"table_of_contents": {
|
||||
"title": "Sommario",
|
||||
@@ -554,7 +566,13 @@
|
||||
},
|
||||
"highlights_list_2": {
|
||||
"title": "Punti salienti",
|
||||
"options": "Opzioni"
|
||||
"options": "Opzioni",
|
||||
"title_with_count_one": "{{count}} evidenza",
|
||||
"title_with_count_many": "{{count}} evidenze",
|
||||
"title_with_count_other": "{{count}} evidenze",
|
||||
"modal_title": "Configura elenco dei punti salienti",
|
||||
"menu_configure": "Configura elenco dei punti salienti...",
|
||||
"no_highlights": "Nessun punto saliente trovato."
|
||||
},
|
||||
"quick-search": {
|
||||
"placeholder": "Ricerca rapida",
|
||||
@@ -884,7 +902,6 @@
|
||||
"download_button": "Scarica",
|
||||
"mime": "MIME: ",
|
||||
"file_size": "Dimensione del file:",
|
||||
"preview": "Anteprima:",
|
||||
"preview_not_available": "L'anteprima non è disponibile per questo tipo di nota."
|
||||
},
|
||||
"sort_child_notes": {
|
||||
@@ -1260,7 +1277,13 @@
|
||||
"convert_into_attachment_successful": "Nota '{{title}}' è stato convertito in allegato.",
|
||||
"convert_into_attachment_prompt": "Sei sicuro di voler convertire la nota '{{title}}' in un allegato della nota padre?",
|
||||
"print_pdf": "Esporta come PDF...",
|
||||
"open_note_on_server": "Apri una nota sul server"
|
||||
"open_note_on_server": "Apri una nota sul server",
|
||||
"view_revisions": "Revisioni...",
|
||||
"advanced": "Avanzato",
|
||||
"export_as_image": "Esporta come immagine",
|
||||
"export_as_image_png": "PNG (raster)",
|
||||
"export_as_image_svg": "SVG (vector)",
|
||||
"note_map": "Mappa"
|
||||
},
|
||||
"onclick_button": {
|
||||
"no_click_handler": "Il widget pulsante '{{componentId}}' non ha un gestore di clic definito"
|
||||
@@ -1318,9 +1341,17 @@
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "Cambia icona nota",
|
||||
"category": "Categoria:",
|
||||
"search": "Ricerca:",
|
||||
"reset-default": "Ripristina l'icona predefinita"
|
||||
"reset-default": "Ripristina l'icona predefinita",
|
||||
"search_placeholder_one": "Cerca {{number}} icona in {{count}} pacchetto",
|
||||
"search_placeholder_many": "Cerca {{number}} icone in {{count}} pacchetti",
|
||||
"search_placeholder_other": "Cerca {{number}} icone in {{count}} pacchetti",
|
||||
"search_placeholder_filtered": "Cerca {{number}} icone in {{name}}",
|
||||
"filter": "Filtro",
|
||||
"filter-none": "Tutte le icone",
|
||||
"filter-default": "Icone predefinite",
|
||||
"icon_tooltip": "{{name}}\nPacchetto icone: {{iconPack}}",
|
||||
"no_results": "Nessuna icona trovata."
|
||||
},
|
||||
"basic_properties": {
|
||||
"note_type": "Tipo di nota",
|
||||
@@ -1360,7 +1391,7 @@
|
||||
"file_type": "Tipo di file",
|
||||
"file_size": "Dimensione del file",
|
||||
"download": "Scaricamento",
|
||||
"open": "Aprire",
|
||||
"open": "Aprire esternamente",
|
||||
"upload_new_revision": "Carica nuova revisione",
|
||||
"upload_success": "È stata caricata una nuova revisione del file.",
|
||||
"upload_failed": "Caricamento di una nuova revisione del file non riuscito.",
|
||||
@@ -1380,7 +1411,8 @@
|
||||
},
|
||||
"inherited_attribute_list": {
|
||||
"title": "Attributi ereditati",
|
||||
"no_inherited_attributes": "Nessun attributo ereditato."
|
||||
"no_inherited_attributes": "Nessun attributo ereditato.",
|
||||
"none": "nessuno"
|
||||
},
|
||||
"note_info_widget": {
|
||||
"note_id": "ID nota",
|
||||
@@ -1391,7 +1423,9 @@
|
||||
"note_size_info": "La dimensione della nota fornisce una stima approssimativa dei requisiti di archiviazione per questa nota. Tiene conto del contenuto della nota e del contenuto delle sue revisioni.",
|
||||
"calculate": "calcolare",
|
||||
"subtree_size": "(dimensione del sottoalbero: {{size}} in {{count}} note)",
|
||||
"title": "Nota informativa"
|
||||
"title": "Nota informativa",
|
||||
"show_similar_notes": "Mostra note simili",
|
||||
"mime": "Tipo MIME"
|
||||
},
|
||||
"note_map": {
|
||||
"open_full": "Espandi completamente",
|
||||
@@ -1491,7 +1525,14 @@
|
||||
"placeholder": "Digita qui il contenuto della tua nota di codice..."
|
||||
},
|
||||
"editable_text": {
|
||||
"placeholder": "Digita qui il contenuto della tua nota..."
|
||||
"placeholder": "Digita qui il contenuto della tua nota...",
|
||||
"auto-detect-language": "Rilevato automaticamente",
|
||||
"keeps-crashing": "Il componente di modifica continua a bloccarsi. Prova a riavviare Trilium. Se il problema persiste, valuta la possibilità di creare una segnalazione di bug.",
|
||||
"editor_crashed_title": "L'editor di testo si è bloccato",
|
||||
"editor_crashed_content": "I tuoi contenuti sono stati recuperati con successo, ma alcune delle modifiche più recenti potrebbero non essere state salvate.",
|
||||
"editor_crashed_details_button": "Visualizza ulteriori dettagli...",
|
||||
"editor_crashed_details_intro": "Se questo errore si verifica più volte, valuta la possibilità di segnalarlo su GitHub incollando le informazioni riportate di seguito.",
|
||||
"editor_crashed_details_title": "Informazioni tecniche"
|
||||
},
|
||||
"empty": {
|
||||
"open_note_instruction": "Apri una nota digitandone il titolo nel campo sottostante oppure scegli una nota nell'albero.",
|
||||
@@ -1768,7 +1809,7 @@
|
||||
"will_be_deleted_in": "Questo allegato verrà eliminato automaticamente tra {{time}}",
|
||||
"will_be_deleted_soon": "Questo allegato verrà eliminato automaticamente a breve",
|
||||
"deletion_reason": ", perché l'allegato non è collegato al contenuto della nota. Per impedirne l'eliminazione, aggiungi nuovamente il collegamento all'allegato nel contenuto o converti l'allegato in nota.",
|
||||
"role_and_size": "Ruolo: {{role}}, Dimensione: {{size}}",
|
||||
"role_and_size": "Ruolo: {{role}}, dimensione: {{size}}, MIME: {{- mimeType}}",
|
||||
"link_copied": "Link all'allegato copiato negli appunti.",
|
||||
"unrecognized_role": "Ruolo di allegato non riconosciuto '{{role}}'."
|
||||
},
|
||||
@@ -1862,10 +1903,24 @@
|
||||
"note_detail": {
|
||||
"could_not_find_typewidget": "Impossibile trovare typeWidget per il tipo '{{type}}'",
|
||||
"printing": "Stampa in corso...",
|
||||
"printing_pdf": "Esportazione in PDF in corso..."
|
||||
"printing_pdf": "Esportazione in PDF in corso...",
|
||||
"print_report_title": "Stampa rapporto",
|
||||
"print_report_collection_content_one": "{{count}} la note nella raccolta non può essere stampata perché non è supportata o è protetta.",
|
||||
"print_report_collection_content_many": "{{count}} le note nella raccolta non possono essere stampate perché non sono supportate o sono protette.",
|
||||
"print_report_collection_content_other": "{{count}} le note nella raccolta non possono essere stampate perché non sono supportate o sono protette.",
|
||||
"print_report_collection_details_button": "Vedi dettagli",
|
||||
"print_report_collection_details_ignored_notes": "Note ignorate"
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "scrivi qui il titolo della nota..."
|
||||
"placeholder": "scrivi qui il titolo della nota...",
|
||||
"created_on": "Creato il <Value />",
|
||||
"last_modified": "Modificato il <Value />",
|
||||
"note_type_switcher_label": "Passa da {{type}} a:",
|
||||
"note_type_switcher_others": "Altro tipo di nota",
|
||||
"note_type_switcher_templates": "Modello",
|
||||
"note_type_switcher_collection": "Collezione",
|
||||
"edited_notes": "Note modificate in questo giorno",
|
||||
"promoted_attributes": "Attributi promossi"
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "Non sono state trovate note per i parametri di ricerca specificati.",
|
||||
@@ -1937,10 +1992,6 @@
|
||||
"move-to-available-launchers": "Passa ai launcher disponibili",
|
||||
"duplicate-launcher": "Duplica il launcher <kbd data-command=\"duplicateSubtree\">"
|
||||
},
|
||||
"editable-text": {
|
||||
"auto-detect-language": "Rilevato automaticamente",
|
||||
"keeps-crashing": "Il componente di modifica continua a bloccarsi. Prova a riavviare Trilium. Se il problema persiste, valuta la possibilità di creare una segnalazione di bug."
|
||||
},
|
||||
"highlighting": {
|
||||
"title": "Blocchi di codice",
|
||||
"description": "Controlla l'evidenziazione della sintassi per i blocchi di codice all'interno delle note di testo; le note di codice non saranno interessate.",
|
||||
@@ -2005,8 +2056,9 @@
|
||||
"unknown_widget": "Widget sconosciuto per \"{{id}}\"."
|
||||
},
|
||||
"note_language": {
|
||||
"not_set": "Non impostato",
|
||||
"configure-languages": "Configura le lingue..."
|
||||
"not_set": "Nessuna lingua impostata",
|
||||
"configure-languages": "Configura le lingue...",
|
||||
"help-on-languages": "Aiuto sulle lingue dei contenuti..."
|
||||
},
|
||||
"content_language": {
|
||||
"title": "Lingue dei contenuti",
|
||||
@@ -2024,7 +2076,8 @@
|
||||
"button_title": "Esporta diagramma come PNG"
|
||||
},
|
||||
"svg": {
|
||||
"export_to_png": "Non è stato possibile esportare il diagramma in formato PNG."
|
||||
"export_to_png": "Non è stato possibile esportare il diagramma in formato PNG.",
|
||||
"export_to_svg": "Il diagramma non può essere esportato in formato SVG."
|
||||
},
|
||||
"code_theme": {
|
||||
"title": "Aspetto",
|
||||
@@ -2034,7 +2087,7 @@
|
||||
"book_properties_config": {
|
||||
"hide-weekends": "Nascondi i fine settimana",
|
||||
"display-week-numbers": "Visualizza i numeri delle settimane",
|
||||
"map-style": "Stile mappa:",
|
||||
"map-style": "Stile mappa",
|
||||
"max-nesting-depth": "Profondità massima di nidificazione:",
|
||||
"raster": "Trama",
|
||||
"vector_light": "Vettore (Luce)",
|
||||
@@ -2074,14 +2127,20 @@
|
||||
"background_effects_title": "Gli effetti di sfondo sono ora stabili",
|
||||
"background_effects_message": "Sui dispositivi Windows, gli effetti di sfondo sono ora completamente stabili. Gli effetti di sfondo aggiungono un tocco di colore all'interfaccia utente sfocando lo sfondo retrostante. Questa tecnica è utilizzata anche in altre applicazioni come Esplora risorse di Windows.",
|
||||
"background_effects_button": "Abilita gli effetti di sfondo",
|
||||
"dismiss": "Congedare"
|
||||
"dismiss": "Congedare",
|
||||
"new_layout_title": "Nuovo layout",
|
||||
"new_layout_message": "Abbiamo introdotto un layout modernizzato per Trilium. La barra multifunzione è stata rimossa e integrata perfettamente nell'interfaccia principale, con una nuova barra di stato e sezioni espandibili (come gli attributi promossi) che assumono le funzioni chiave.\n\nIl nuovo layout è abilitato di default e può essere temporaneamente disabilitato tramite Opzioni → Aspetto.",
|
||||
"new_layout_button": "Maggiori informazioni"
|
||||
},
|
||||
"settings": {
|
||||
"related_settings": "Impostazioni correlate"
|
||||
},
|
||||
"settings_appearance": {
|
||||
"related_code_blocks": "Schema di colori per i blocchi di codice nelle note di testo",
|
||||
"related_code_notes": "Schema di colori per le note del codice"
|
||||
"related_code_notes": "Schema di colori per le note del codice",
|
||||
"ui": "Interfaccia utente",
|
||||
"ui_old_layout": "Vecchio layout",
|
||||
"ui_new_layout": "Nuovo layout"
|
||||
},
|
||||
"units": {
|
||||
"percentage": "%"
|
||||
@@ -2108,5 +2167,81 @@
|
||||
},
|
||||
"popup-editor": {
|
||||
"maximize": "Passa all'editor completo"
|
||||
},
|
||||
"experimental_features": {
|
||||
"title": "Opzioni sperimentali",
|
||||
"disclaimer": "Queste opzioni sono sperimentali e potrebbero causare instabilità. Usare con cautela.",
|
||||
"new_layout_name": "Nuovo layout",
|
||||
"new_layout_description": "Prova il nuovo layout per un look più moderno e una maggiore usabilità. Soggetto a modifiche significative nelle prossime versioni."
|
||||
},
|
||||
"server": {
|
||||
"unknown_http_error_title": "Errore di comunicazione con il server",
|
||||
"unknown_http_error_content": "Codice di stato: {{statusCode}}\nURL: {{method}} {{url}}\nMessaggio: {{message}}",
|
||||
"traefik_blocks_requests": "Se si utilizza il proxy inverso Traefik, è stata introdotta una modifica sostanziale che influisce sulla comunicazione con il server."
|
||||
},
|
||||
"tab_history_navigation_buttons": {
|
||||
"go-back": "Torna alla nota precedente",
|
||||
"go-forward": "Passa alla nota successiva"
|
||||
},
|
||||
"breadcrumb_badges": {
|
||||
"read_only_explicit": "Sola lettura",
|
||||
"read_only_explicit_description": "Questa nota è stata impostata manualmente come di sola lettura.\nClicca per modificarla temporaneamente.",
|
||||
"read_only_auto": "Solo lettura automatica",
|
||||
"read_only_auto_description": "Questa nota è stata impostata automaticamente in modalità di sola lettura per motivi di prestazioni. Questo limite automatico è modificabile dalle impostazioni.\n\nClicca per modificarla temporaneamente.",
|
||||
"read_only_temporarily_disabled": "Modificabile temporaneamente",
|
||||
"read_only_temporarily_disabled_description": "Questa nota è attualmente modificabile, ma normalmente è di sola lettura. La nota tornerà ad essere di sola lettura non appena passerai a un'altra nota.\n\nClicca per riattivare la modalità di sola lettura.",
|
||||
"shared_publicly": "Condiviso pubblicamente",
|
||||
"shared_locally": "Condiviso localmente",
|
||||
"clipped_note": "Clip web",
|
||||
"clipped_note_description": "Questa nota è stata originariamente presa da {{url}}.\n\nClicca per andare alla pagina web di origine.",
|
||||
"execute_script": "Esegui script",
|
||||
"execute_script_description": "Questa nota è una nota di script. Clicca per eseguire lo script.",
|
||||
"execute_sql": "Esegui SQL",
|
||||
"execute_sql_description": "Questa nota è una nota SQL. Clicca per eseguire la query SQL.",
|
||||
"shared_copy_to_clipboard": "Copia link negli appunti",
|
||||
"shared_open_in_browser": "Apri il link nel browser",
|
||||
"shared_unshare": "Rimuovi condivisione"
|
||||
},
|
||||
"breadcrumb": {
|
||||
"workspace_badge": "Area di lavoro",
|
||||
"scroll_to_top_title": "Vai all'inizio della nota",
|
||||
"hoisted_badge": "Sollevato",
|
||||
"hoisted_badge_title": "Abbassato",
|
||||
"create_new_note": "Crea nuova nota secondaria",
|
||||
"empty_hide_archived_notes": "Nascondi note archiviate"
|
||||
},
|
||||
"status_bar": {
|
||||
"language_title": "Cambia lingua dei contenuti",
|
||||
"note_info_title": "Visualizza informazioni sulla nota (ad es. date, dimensioni della nota)",
|
||||
"backlinks_one": "{{count}} backlink",
|
||||
"backlinks_many": "{{count}} backlinks",
|
||||
"backlinks_other": "{{count}} backlinks",
|
||||
"backlinks_title_one": "Visualizza backlink",
|
||||
"backlinks_title_many": "Visualizza backlinks",
|
||||
"backlinks_title_other": "Visualizza backlinks",
|
||||
"attachments_one": "{{count}} allegato",
|
||||
"attachments_many": "{{count}} allegati",
|
||||
"attachments_other": "{{count}} allegati",
|
||||
"attachments_title_one": "Visualizza allegato in una nuova scheda",
|
||||
"attachments_title_many": "Visualizza allegati in una nuova scheda",
|
||||
"attachments_title_other": "Visualizza allegati in una nuova scheda",
|
||||
"attributes_one": "{{count}} attributo",
|
||||
"attributes_many": "{{count}} attributi",
|
||||
"attributes_other": "{{count}} attributi",
|
||||
"attributes_title": "Attributi posseduti e attributi ereditati",
|
||||
"note_paths_one": "{{count}} percorso",
|
||||
"note_paths_many": "{{count}} percorsi",
|
||||
"note_paths_other": "{{count}} percorsi",
|
||||
"note_paths_title": "Nota percorsi",
|
||||
"code_note_switcher": "Cambia modalità lingua"
|
||||
},
|
||||
"attributes_panel": {
|
||||
"title": "Attributi delle note"
|
||||
},
|
||||
"right_pane": {
|
||||
"empty_message": "Nulla da segnalare per questa nota",
|
||||
"empty_button": "Nascondi il pannello",
|
||||
"toggle": "Attiva/disattiva pannello destro",
|
||||
"custom_widget_go_to_source": "Vai al codice sorgente"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,17 @@
|
||||
},
|
||||
"bundle-error": {
|
||||
"title": "カスタムスクリプトの読み込みに失敗しました",
|
||||
"message": "ノートID”{{id}}”, ノートタイトル “{{title}}” のスクリプトを実行できませんでした。理由は以下の通りです:\n\n{{message}}"
|
||||
}
|
||||
"message": "次の理由によりスクリプトを実行できませんでした:\n\n{{message}}"
|
||||
},
|
||||
"widget-list-error": {
|
||||
"title": "サーバーからウィジェットのリストを取得できませんでした"
|
||||
},
|
||||
"widget-render-error": {
|
||||
"title": "カスタム React ウィジェットのレンダリングに失敗しました"
|
||||
},
|
||||
"widget-missing-parent": "カスタムウィジェットに必須の '{{property}}' プロパティが定義されていません。\n\nこのスクリプトを UI 要素なしで実行する場合は、代わりに '#run=frontendStartup' を使用してください。",
|
||||
"open-script-note": "スクリプトノートを開く",
|
||||
"scripting-error": "カスタムスクリプトエラー: {{title}}"
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "リンクを追加",
|
||||
@@ -143,16 +152,22 @@
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "ノートアイコンの変更",
|
||||
"category": "カテゴリー:",
|
||||
"search": "検索:",
|
||||
"reset-default": "アイコンをデフォルトに戻す"
|
||||
"reset-default": "アイコンをデフォルトに戻す",
|
||||
"search_placeholder_other": "{{count}} 個のパックから {{number}} 個のアイコンを検索",
|
||||
"search_placeholder_filtered": "{{name}} で {{number}} 個のアイコンを検索",
|
||||
"filter": "フィルター",
|
||||
"filter-none": "すべてのアイコン",
|
||||
"filter-default": "デフォルトアイコン",
|
||||
"icon_tooltip": "{{name}}\nアイコンパック: {{iconPack}}",
|
||||
"no_results": "アイコンが見つかりません。"
|
||||
},
|
||||
"basic_properties": {
|
||||
"note_type": "ノートタイプ",
|
||||
"editable": "編集可能",
|
||||
"basic_properties": "基本プロパティ",
|
||||
"language": "言語",
|
||||
"configure_code_notes": "コードノートを設定しています..."
|
||||
"configure_code_notes": "コードノートを設定..."
|
||||
},
|
||||
"i18n": {
|
||||
"title": "ローカライゼーション",
|
||||
@@ -218,7 +233,8 @@
|
||||
"unknown_search_option": "不明な検索オプション {{searchOptionName}}",
|
||||
"search_note_saved": "検索ノートが {{- notePathTitle}} に保存されました",
|
||||
"actions_executed": "アクションが実行されました。",
|
||||
"ancestor": "祖先:"
|
||||
"ancestor": "祖先:",
|
||||
"view_options": "表示オプション:"
|
||||
},
|
||||
"shortcuts": {
|
||||
"multiple_shortcuts": "同じアクションに対して複数のショートカットを設定する場合、カンマで区切ることができます。",
|
||||
@@ -258,7 +274,7 @@
|
||||
"export_in_progress": "エクスポート処理中: {{progressCount}}",
|
||||
"export_finished_successfully": "エクスポートが正常に完了しました。",
|
||||
"format_pdf": "PDF - 印刷または共有目的に。",
|
||||
"share-format": "Web 公開用の HTML - 共有ノートで使用されるのと同じテーマを使用しますが、静的 Web サイトとして公開できます。"
|
||||
"share-format": "web 公開用の HTML - 共有ノートで使用されるのと同じテーマを使用しますが、静的 web サイトとして公開できます。"
|
||||
},
|
||||
"help": {
|
||||
"title": "チートシート",
|
||||
@@ -290,7 +306,7 @@
|
||||
"pasteNotes": "ノートをサブノートとしてアクティブノートに貼り付ける(コピーされたか切り取りされたかに よって、移動またはクローンになる)",
|
||||
"deleteNotes": "ノート/サブツリーを削除",
|
||||
"editingNotes": "ノート編集",
|
||||
"editNoteTitle": "ツリーペインでEnterキーを押すと、ツリーペインからノートタイトルに切り替わります。ノートタイトルだとテキストエディタにフォーカスが切り替わります。<kbd>Ctrl+.</kbd> を押すと、エディタからツリーペインに戻ります。",
|
||||
"editNoteTitle": "ツリーペインでEnterキーを押すと、ツリーペインからノートタイトルに切り替わります。ノートタイトルだとテキストエディターにフォーカスが切り替わります。<kbd>Ctrl+.</kbd> を押すと、エディタからツリーペインに戻ります。",
|
||||
"createEditLink": "外部リンクの作成/編集",
|
||||
"createInternalLink": "内部リンクの作成",
|
||||
"followLink": "カーソル下のリンクをたどる",
|
||||
@@ -386,7 +402,7 @@
|
||||
"show_toc": "目次を表示"
|
||||
},
|
||||
"show_highlights_list_widget_button": {
|
||||
"show_highlights_list": "ハイライト一覧を表示"
|
||||
"show_highlights_list": "ハイライトリストを表示"
|
||||
},
|
||||
"relation_map_buttons": {
|
||||
"zoom_out_title": "ズームアウト",
|
||||
@@ -421,10 +437,10 @@
|
||||
"apply-bulk-actions": "一括操作の適用",
|
||||
"converted-to-attachments": "{{count}}ノートが添付ファイルに変換されました。",
|
||||
"convert-to-attachment": "添付ファイルに変換",
|
||||
"convert-to-attachment-confirm": "選択したノートを親ノートの添付ファイルに変換しますか?",
|
||||
"convert-to-attachment-confirm": "選択したノートを親ノートの添付ファイルに変換してもよろしいですか?この操作は画像ノートにのみ適用され、その他のノートはスキップされます。",
|
||||
"open-in-popup": "クイック編集",
|
||||
"hoist-note": "ホイストノート",
|
||||
"unhoist-note": "ノートをホイストしない",
|
||||
"unhoist-note": "ノートのホイストを解除",
|
||||
"edit-branch-prefix": "ブランチの接頭辞を編集",
|
||||
"archive": "アーカイブ",
|
||||
"unarchive": "アーカイブ解除"
|
||||
@@ -458,7 +474,13 @@
|
||||
"convert_into_attachment_successful": "ノート '{{title}}' は添付ファイルに変換されました。",
|
||||
"convert_into_attachment_prompt": "本当にノート '{{title}}' を親ノートの添付ファイルに変換しますか?",
|
||||
"note_attachments": "ノートの添付ファイル",
|
||||
"open_note_on_server": "サーバー上のノートを開く"
|
||||
"open_note_on_server": "サーバー上のノートを開く",
|
||||
"view_revisions": "ノートの変更履歴...",
|
||||
"note_map": "ノートマップ",
|
||||
"advanced": "高度",
|
||||
"export_as_image": "画像としてエクスポート",
|
||||
"export_as_image_png": "PNG (raster)",
|
||||
"export_as_image_svg": "SVG (vector)"
|
||||
},
|
||||
"command_palette": {
|
||||
"export_note_title": "ノートをエクスポート",
|
||||
@@ -526,7 +548,7 @@
|
||||
"button_title": "ボタンを表示"
|
||||
},
|
||||
"svg_export_button": {
|
||||
"button_title": "図をSVGとしてエクスポート"
|
||||
"button_title": "図をSVG形式でエクスポート"
|
||||
},
|
||||
"book_properties": {
|
||||
"grid": "グリッド",
|
||||
@@ -583,7 +605,7 @@
|
||||
"file_type": "ファイルタイプ",
|
||||
"file_size": "ファイルサイズ",
|
||||
"download": "ダウンロード",
|
||||
"open": "開く",
|
||||
"open": "外部で開く",
|
||||
"title": "ファイル",
|
||||
"upload_new_revision": "編集履歴をアップロード",
|
||||
"original_file_name": "元のファイル名",
|
||||
@@ -599,7 +621,9 @@
|
||||
"calculate": "計算",
|
||||
"subtree_size": "(サブツリーサイズ: {{size}}、ノード数: {{count}})",
|
||||
"title": "ノート情報",
|
||||
"note_size_info": "ノートのサイズは、このノートに必要なストレージの概算を示します。これは、ノートの内容とそのノートの編集履歴の内容を考慮したものです。"
|
||||
"note_size_info": "ノートのサイズは、このノートに必要なストレージの概算を示します。これは、ノートの内容とそのノートの編集履歴の内容を考慮したものです。",
|
||||
"show_similar_notes": "類似のノートを表示",
|
||||
"mime": "MIME タイプ"
|
||||
},
|
||||
"image_properties": {
|
||||
"file_type": "ファイルタイプ",
|
||||
@@ -630,7 +654,6 @@
|
||||
"revision_deleted": "ノートの変更履歴は削除されました。",
|
||||
"settings": "ノートの変更履歴の設定",
|
||||
"file_size": "ファイルサイズ:",
|
||||
"preview": "プレビュー:",
|
||||
"preview_not_available": "このノートタイプではプレビューは利用できません。",
|
||||
"diff_on": "差分を表示",
|
||||
"diff_off": "内容を表示",
|
||||
@@ -799,7 +822,7 @@
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "Web ビュー",
|
||||
"embed_websites": "Web ビュータイプでは、ウェブサイトをTriliumに埋め込むことができます。",
|
||||
"embed_websites": "Web ビュータイプでは、web サイトを Trilium に埋め込むことができます。",
|
||||
"create_label": "まず始めに、埋め込みたいURLアドレスのラベルを作成してください。例: #webViewSrc=\"https://www.google.com\""
|
||||
},
|
||||
"backend_log": {
|
||||
@@ -910,7 +933,7 @@
|
||||
"underline": "下線",
|
||||
"color": "カラーテキスト",
|
||||
"bg_color": "背景色付きテキスト",
|
||||
"visibility_title": "ハイライトリスト表示",
|
||||
"visibility_title": "ハイライトリストの表示",
|
||||
"visibility_description": "#hideHighlightWidget ラベルを追加することで、ノートごとにハイライトウィジェットを非表示にできます。",
|
||||
"shortcut_info": "設定 -> ショートカット(右ペイン切り替え)で、右ペイン(ハイライトを含む)を素早く切り替えるキーボードショートカットを設定できます。"
|
||||
},
|
||||
@@ -923,7 +946,8 @@
|
||||
},
|
||||
"toc": {
|
||||
"table_of_contents": "目次",
|
||||
"options": "オプション"
|
||||
"options": "オプション",
|
||||
"no_headings": "見出しはありません。"
|
||||
},
|
||||
"text_auto_read_only_size": {
|
||||
"title": "自動読み取り専用のサイズ",
|
||||
@@ -961,7 +985,7 @@
|
||||
"password": {
|
||||
"wiki": "wiki",
|
||||
"heading": "パスワード",
|
||||
"alert_message": "新しいパスワードは大切に保管してください。パスワードはウェブインターフェースへのログインや、保護されたノートの暗号化に使用されます。パスワードを忘れると、保護されたノートはすべて永久に失われます。",
|
||||
"alert_message": "新しいパスワードは大切に保管してください。パスワードは web インターフェースへのログインや、保護されたノートの暗号化に使用されます。パスワードを忘れると、保護されたノートはすべて永久に失われます。",
|
||||
"reset_link": "リセットするにはここをクリック。",
|
||||
"old_password": "旧パスワード",
|
||||
"new_password": "新パスワード",
|
||||
@@ -1011,7 +1035,8 @@
|
||||
"info": {
|
||||
"closeButton": "閉じる",
|
||||
"modalTitle": "情報メッセージ",
|
||||
"okButton": "OK"
|
||||
"okButton": "OK",
|
||||
"copy_to_clipboard": "クリップボードにコピー"
|
||||
},
|
||||
"protected_session_password": {
|
||||
"close_label": "閉じる",
|
||||
@@ -1106,7 +1131,7 @@
|
||||
"sql_console_home": "SQLコンソールノートのデフォルトの場所",
|
||||
"bookmark_folder": "このラベルの付いたノートは、ブックマークにフォルダとして表示されます(子フォルダへのアクセスを許可します)",
|
||||
"share_hidden_from_tree": "このノートは左側のナビゲーションツリーには表示されていませんが、URL からアクセスできます",
|
||||
"share_external_link": "ノートは共有ツリー内で外部ウェブサイトへのリンクとして機能します",
|
||||
"share_external_link": "ノートは共有ツリー内で外部 web サイトへのリンクとして機能します",
|
||||
"share_alias": "https://your_trilium_host/share/[your_alias] でノートを利用できるようにエイリアスを定義します",
|
||||
"share_omit_default_css": "デフォルトの共有ページのCSSは省略されます。スタイルを大幅に変更する場合に使用してください。",
|
||||
"share_root": "/share root で提供されるノートをマークする。",
|
||||
@@ -1191,7 +1216,11 @@
|
||||
},
|
||||
"highlights_list_2": {
|
||||
"title": "ハイライトリスト",
|
||||
"options": "オプション"
|
||||
"options": "オプション",
|
||||
"title_with_count_other": "{{count}} ハイライト",
|
||||
"modal_title": "ハイライトリストの設定",
|
||||
"menu_configure": "ハイライトリストの設定...",
|
||||
"no_highlights": "ハイライトが見つかりません。"
|
||||
},
|
||||
"quick-search": {
|
||||
"placeholder": "クイック検索",
|
||||
@@ -1215,7 +1244,11 @@
|
||||
"saved-search-note-refreshed": "保存した検索ノートが更新されました。",
|
||||
"refresh-saved-search-results": "保存した検索結果を更新",
|
||||
"toggle-sidebar": "サイドバーを切り替え",
|
||||
"dropping-not-allowed": "この場所にノートをドロップすることはできません。"
|
||||
"dropping-not-allowed": "この場所にノートをドロップすることはできません。",
|
||||
"clone-indicator-tooltip": "このノートには {{- count}} 個の親があります: {{- parents}}",
|
||||
"clone-indicator-tooltip-single": "このノートは複製されています (親が 1 件追加: {{- parent}})",
|
||||
"shared-indicator-tooltip": "このノートは公開されています",
|
||||
"shared-indicator-tooltip-with-url": "このノートは以下で公開されています: {{- url}}"
|
||||
},
|
||||
"bulk_actions": {
|
||||
"bulk_actions": "一括操作",
|
||||
@@ -1232,7 +1265,15 @@
|
||||
"none_yet": "アクションを上のリストからクリックして追加。"
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "ここにノートのタイトルを入力..."
|
||||
"placeholder": "ここにノートのタイトルを入力...",
|
||||
"created_on": "<Value /> に作成",
|
||||
"last_modified": "<Value /> に変更",
|
||||
"note_type_switcher_label": "{{type}} から切り替え:",
|
||||
"note_type_switcher_others": "その他のノートタイプ",
|
||||
"note_type_switcher_templates": "テンプレート",
|
||||
"note_type_switcher_collection": "コレクション",
|
||||
"edited_notes": "この日に編集されたノート",
|
||||
"promoted_attributes": "プロモート属性"
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "指定された検索パラメータに該当するノートは見つかりませんでした。",
|
||||
@@ -1268,10 +1309,6 @@
|
||||
"duplicate-launcher": "ランチャーの複製 <kbd data-command=\"duplicateSubtree\">",
|
||||
"reset_launcher_confirm": "本当に「{{title}}」をリセットしますか? このノート(およびその子ノート)のすべてのデータと設定が失われ、ランチャーは元の場所に戻ります。"
|
||||
},
|
||||
"editable-text": {
|
||||
"auto-detect-language": "自動検出",
|
||||
"keeps-crashing": "編集コンポーネントがクラッシュし続けます。Trilium を再起動してください。問題が解決しない場合は、バグレポートの作成をご検討ください。"
|
||||
},
|
||||
"highlighting": {
|
||||
"title": "コードブロック",
|
||||
"description": "テキストノート内のコードブロックのシンタックスハイライトを制御します。コードノートには影響しません。",
|
||||
@@ -1333,8 +1370,9 @@
|
||||
"minimum_input": "入力された時間値は {{minimumSeconds}} 秒以上である必要があります。"
|
||||
},
|
||||
"note_language": {
|
||||
"not_set": "未設定",
|
||||
"configure-languages": "言語を設定..."
|
||||
"not_set": "言語が設定されていません",
|
||||
"configure-languages": "言語を設定...",
|
||||
"help-on-languages": "コンテンツの言語に関するヘルプ..."
|
||||
},
|
||||
"content_language": {
|
||||
"title": "コンテンツの言語",
|
||||
@@ -1344,7 +1382,8 @@
|
||||
"button_title": "図をPNG形式でエクスポート"
|
||||
},
|
||||
"svg": {
|
||||
"export_to_png": "図をPNG形式でエクスポートできませんでした。"
|
||||
"export_to_png": "図をPNG形式でエクスポートできませんでした。",
|
||||
"export_to_svg": "図をSVG形式でエクスポートできませんでした。"
|
||||
},
|
||||
"code_theme": {
|
||||
"title": "外観",
|
||||
@@ -1601,7 +1640,8 @@
|
||||
},
|
||||
"inherited_attribute_list": {
|
||||
"title": "継承属性",
|
||||
"no_inherited_attributes": "継承属性はありません。"
|
||||
"no_inherited_attributes": "継承属性はありません。",
|
||||
"none": "なし"
|
||||
},
|
||||
"note_map": {
|
||||
"open_full": "拡大表示",
|
||||
@@ -1622,7 +1662,7 @@
|
||||
"remove_this_attribute": "この属性を削除",
|
||||
"remove_color": "このカラーラベルを削除",
|
||||
"promoted_attributes": "プロモート属性",
|
||||
"url_placeholder": "http://ウェブサイト..."
|
||||
"url_placeholder": "http://web サイト..."
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "新しいタブで開く",
|
||||
@@ -1778,7 +1818,14 @@
|
||||
"placeholder": "ここにコードノートの内容を入力..."
|
||||
},
|
||||
"editable_text": {
|
||||
"placeholder": "ここにノートの内容を入力..."
|
||||
"placeholder": "ここにノートの内容を入力...",
|
||||
"auto-detect-language": "自動検出",
|
||||
"keeps-crashing": "編集コンポーネントがクラッシュし続けます。Trilium を再起動してください。問題が解決しない場合は、バグレポートの作成をご検討ください。",
|
||||
"editor_crashed_title": "テキストエディターがクラッシュしました",
|
||||
"editor_crashed_content": "コンテンツは正常に復元されましたが、最近の変更の一部が保存されていない可能性があります。",
|
||||
"editor_crashed_details_button": "詳細を見る...",
|
||||
"editor_crashed_details_intro": "このエラーが何度も発生する場合は、以下の情報を貼り付けて GitHub に報告することを検討してください。",
|
||||
"editor_crashed_details_title": "技術情報"
|
||||
},
|
||||
"empty": {
|
||||
"open_note_instruction": "以下の入力欄にノートのタイトルを入力するか、ツリー内のノートを選択してノートを開きます。",
|
||||
@@ -1892,7 +1939,11 @@
|
||||
"note_detail": {
|
||||
"could_not_find_typewidget": "タイプ {{type}} の typeWidget が見つかりませんでした",
|
||||
"printing": "印刷中です...",
|
||||
"printing_pdf": "PDF へのエクスポート中です..."
|
||||
"printing_pdf": "PDF へのエクスポート中です...",
|
||||
"print_report_title": "レポートを印刷",
|
||||
"print_report_collection_content_other": "コレクション内の {{count}} 件のノートは、サポートされていないか保護されているため、印刷できませんでした。",
|
||||
"print_report_collection_details_button": "詳細を見る",
|
||||
"print_report_collection_details_ignored_notes": "無視されたノート"
|
||||
},
|
||||
"watched_file_update_status": {
|
||||
"ignore_this_change": "この変更を無視する",
|
||||
@@ -1969,7 +2020,7 @@
|
||||
"book_properties_config": {
|
||||
"hide-weekends": "週末を非表示",
|
||||
"display-week-numbers": "週番号を表示",
|
||||
"map-style": "マップスタイル:",
|
||||
"map-style": "マップスタイル",
|
||||
"max-nesting-depth": "最大階層の深さ:",
|
||||
"show-scale": "スケールを表示",
|
||||
"raster": "Raster",
|
||||
@@ -1983,14 +2034,20 @@
|
||||
"background_effects_title": "背景効果が安定しました",
|
||||
"background_effects_message": "Windowsデバイスでは、背景効果が完全に安定しました。背景効果は、背景をぼかすことでユーザーインターフェースに彩りを添えます。この技術は、Windowsエクスプローラーなどの他のアプリケーションでも使用されています。",
|
||||
"background_effects_button": "背景効果を有効にする",
|
||||
"dismiss": "却下"
|
||||
"dismiss": "却下",
|
||||
"new_layout_title": "新しいレイアウト",
|
||||
"new_layout_message": "Trilium のレイアウトを刷新しました。リボンは廃止され、メインインターフェースにシームレスに統合されました。主要な機能は、新しいステータスバーと展開可能なセクション(プロモート属性など)に集約されています。\n\n新しいレイアウトはデフォルトで有効になっていますが、「オプション」→「外観」から一時的に無効にすることもできます。",
|
||||
"new_layout_button": "詳細情報"
|
||||
},
|
||||
"settings": {
|
||||
"related_settings": "関連設定"
|
||||
},
|
||||
"settings_appearance": {
|
||||
"related_code_blocks": "テキストノート内のコードブロックの配色",
|
||||
"related_code_notes": "コードノートの配色"
|
||||
"related_code_notes": "コードノートの配色",
|
||||
"ui": "ユーザーインターフェース",
|
||||
"ui_old_layout": "旧レイアウト",
|
||||
"ui_new_layout": "新しいレイアウト"
|
||||
},
|
||||
"units": {
|
||||
"percentage": "%"
|
||||
@@ -2064,7 +2121,7 @@
|
||||
"recovery_keys_used": "使用日: {{date}}",
|
||||
"recovery_keys_unused": "回復コード {{index}} は未使用です",
|
||||
"oauth_title": "OAuth/OpenID",
|
||||
"oauth_description": "OpenIDは、Googleなどの他のサービスのアカウントを使用してウェブサイトにログインし、本人確認を行うための標準化された方法です。デフォルトの発行者はGoogleですが、他のOpenIDプロバイダに変更できます。詳しくは<a href=\"#root/_hidden/_help/_help_Otzi9La2YAUX/_help_WOcw2SLH6tbX/_help_7DAiwaf8Z7Rz\">こちら</a>をご覧ください。Google経由でOpenIDサービスを設定するには、<a href=\"https://developers.google.com/identity/openid-connect/openid-connect\">こちらの手順</a>に従ってください。",
|
||||
"oauth_description": "OpenIDは、Googleなどの他のサービスのアカウントを使用して web サイトにログインし、本人確認を行うための標準化された方法です。デフォルトの発行者はGoogleですが、他のOpenIDプロバイダに変更できます。詳しくは<a href=\"#root/_hidden/_help/_help_Otzi9La2YAUX/_help_WOcw2SLH6tbX/_help_7DAiwaf8Z7Rz\">こちら</a>をご覧ください。Google経由でOpenIDサービスを設定するには、<a href=\"https://developers.google.com/identity/openid-connect/openid-connect\">こちらの手順</a>に従ってください。",
|
||||
"oauth_description_warning": "OAuth/OpenIDを有効にするには、config.iniファイルにOAuth/OpenIDのベースURL、クライアントID、クライアントシークレットを設定し、アプリケーションを再起動する必要があります。環境変数から設定する場合は、TRILIUM_OAUTH_BASE_URL, TRILIUM_OAUTH_CLIENT_ID and TRILIUM_OAUTH_CLIENT_SECRET を設定してください。",
|
||||
"oauth_missing_vars": "設定がありません: {{-variables}}",
|
||||
"oauth_user_account": "ユーザーアカウント: ",
|
||||
@@ -2082,7 +2139,7 @@
|
||||
"will_be_deleted_in": "この添付ファイルは {{time}} 後に自動的に削除されます",
|
||||
"will_be_deleted_soon": "この添付ファイルはすぐに自動的に削除されます",
|
||||
"deletion_reason": "、添付ファイルがノートのコンテンツにリンクされていないためです。削除されないようにするには、添付ファイルのリンクをコンテンツに再度追加するか、添付ファイルをノートに変換してください。",
|
||||
"role_and_size": "ロール: {{role}},サイズ: {{size}}",
|
||||
"role_and_size": "ロール: {{role}},サイズ: {{size}}, MIME: {{- mimeType}}",
|
||||
"link_copied": "添付ファイルのリンクをクリップボードにコピーしました。",
|
||||
"unrecognized_role": "添付ファイルのロール「{{role}}」は認識されません。"
|
||||
},
|
||||
@@ -2106,5 +2163,83 @@
|
||||
},
|
||||
"popup-editor": {
|
||||
"maximize": "フルエディターに切り替え"
|
||||
},
|
||||
"server": {
|
||||
"unknown_http_error_title": "サーバーとの通信エラー",
|
||||
"unknown_http_error_content": "ステータスコード: {{statusCode}}\nURL: {{method}} {{url}}\nメッセージ: {{message}}",
|
||||
"traefik_blocks_requests": "Traefik リバース プロキシを使用している場合、サーバーとの通信に影響する重大な変更が導入されました。"
|
||||
},
|
||||
"tab_history_navigation_buttons": {
|
||||
"go-back": "前のノートに戻る",
|
||||
"go-forward": "次のノートに進む"
|
||||
},
|
||||
"experimental_features": {
|
||||
"title": "実験オプション",
|
||||
"disclaimer": "これらのオプションは試験的なもので、動作が不安定になる可能性があります。注意してご使用ください。",
|
||||
"new_layout_name": "新しいレイアウト",
|
||||
"new_layout_description": "よりモダンな外観と使いやすさが向上した新しいレイアウトをお試しください。今後のリリースで大幅な変更が加えられる可能性があります。"
|
||||
},
|
||||
"breadcrumb_badges": {
|
||||
"read_only_explicit": "読み取り専用",
|
||||
"read_only_auto": "自動的に読み取り専用",
|
||||
"shared_publicly": "公開で共有",
|
||||
"shared_locally": "ローカルで共有",
|
||||
"read_only_explicit_description": "このノートは手動で読み取り専用に設定されています。\nクリックすると一時的に編集できます。",
|
||||
"read_only_temporarily_disabled": "一時的に編集可能",
|
||||
"read_only_auto_description": "このノートはパフォーマンス上の理由により、自動的に読み取り専用モードに設定されました。この自動制限は設定から調整できます。\n\n一時的に編集するにはクリックしてください。",
|
||||
"read_only_temporarily_disabled_description": "このノートは現在編集可能ですが、通常は読み取り専用です。別のノートに移動すると読み取り専用に戻ります。\n\nクリックすると読み取り専用モードが再度有効になります。",
|
||||
"clipped_note": "Web クリップ",
|
||||
"clipped_note_description": "このノートは {{url}} から取得されました。\n\nクリックすると元の web ページに移動します。",
|
||||
"execute_script": "スクリプトを実行",
|
||||
"execute_script_description": "このノートはスクリプトノートです。クリックするとスクリプトが実行されます。",
|
||||
"execute_sql": "SQL を実行",
|
||||
"execute_sql_description": "このノートは SQL ノートです。クリックすると SQL クエリが実行されます。",
|
||||
"shared_copy_to_clipboard": "リンクをクリップボードにコピー",
|
||||
"shared_open_in_browser": "ブラウザでリンクを開く",
|
||||
"shared_unshare": "共有を削除",
|
||||
"save_status_saved": "保存されました",
|
||||
"save_status_saving": "保存中...",
|
||||
"save_status_unsaved": "未保存",
|
||||
"save_status_error": "保存に失敗しました",
|
||||
"save_status_saving_tooltip": "変更を保存しています。",
|
||||
"save_status_unsaved_tooltip": "未保存の変更があります。すぐに自動的に保存されます。",
|
||||
"save_status_error_tooltip": "ノートの保存中にエラーが発生しました。可能であれば、ノートの内容を別の場所にコピーして、アプリケーションを再読み込みしてください。"
|
||||
},
|
||||
"status_bar": {
|
||||
"language_title": "コンテンツの言語を変更",
|
||||
"note_info_title": "ノート情報を表示(例: 日付、ノートのサイズなど)",
|
||||
"backlinks_title_other": "バックリンクを表示",
|
||||
"attachments_title_other": "添付ファイルを新しいタブで表示",
|
||||
"attributes_other": "{{count}} 個の属性",
|
||||
"attributes_title": "所有属性と継承属性",
|
||||
"note_paths_title": "ノートパス",
|
||||
"code_note_switcher": "言語モードを変更",
|
||||
"backlinks_other": "{{count}} バックリンク",
|
||||
"attachments_other": "{{count}} 件の添付ファイル",
|
||||
"note_paths_other": "{{count}} 個のパス"
|
||||
},
|
||||
"breadcrumb": {
|
||||
"hoisted_badge": "ホイスト",
|
||||
"hoisted_badge_title": "ホイスト解除",
|
||||
"workspace_badge": "ワークスペース",
|
||||
"scroll_to_top_title": "ノートの先頭にジャンプ",
|
||||
"create_new_note": "新しい子ノートを作成",
|
||||
"empty_hide_archived_notes": "アーカイブされたノートを非表示"
|
||||
},
|
||||
"right_pane": {
|
||||
"empty_message": "このノートには何も表示されません",
|
||||
"empty_button": "パネルを非表示",
|
||||
"toggle": "右パネルを切り替え",
|
||||
"custom_widget_go_to_source": "ソースコードへ移動"
|
||||
},
|
||||
"attributes_panel": {
|
||||
"title": "ノート属性"
|
||||
},
|
||||
"pdf": {
|
||||
"attachments_other": "{{count}} 添付ファイル",
|
||||
"layers_other": "{{count}} 層",
|
||||
"pages_other": "{{count}} ページ",
|
||||
"pages_alt": "ページ {{pageNumber}}",
|
||||
"pages_loading": "読み込み中..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,12 +50,24 @@
|
||||
"available_actions": "가능한 액션들",
|
||||
"chosen_actions": "선택한 액션들",
|
||||
"execute_bulk_actions": "대량 액션들 실행",
|
||||
"bulk_actions_executed": "대량 액션들이 성공적으로 실행되었습니다."
|
||||
"bulk_actions_executed": "대량 액션들이 성공적으로 실행되었습니다.",
|
||||
"none_yet": "아직 없습니다... 위에 있는 가능한 작업 중 하나를 클릭하여 작업을 추가하세요.",
|
||||
"labels": "라벨",
|
||||
"relations": "관계",
|
||||
"notes": "노트",
|
||||
"other": "기타"
|
||||
},
|
||||
"i18n": {
|
||||
"saturday": "토요일",
|
||||
"sunday": "일요일",
|
||||
"first-week-of-the-year": "일년의 첫째 주",
|
||||
"first-week-contains-first-day": "첫 번째 주에는 올해의 첫날이 포함됩니다"
|
||||
},
|
||||
"clone_to": {
|
||||
"clone_notes_to": "~로 노트 복제",
|
||||
"help_on_links": "링크에 대한 도움말",
|
||||
"notes_to_clone": "노트 클론 생성",
|
||||
"target_parent_note": "부모 노트 타겟",
|
||||
"search_for_note_by_its_name": "이름으로 노트 검색하기"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1,22 @@
|
||||
{}
|
||||
{
|
||||
"about": {
|
||||
"title": "Om Trilium Notes",
|
||||
"app_version": "App versjon:",
|
||||
"db_version": "DB versjon:",
|
||||
"sync_version": "Synk versjon:",
|
||||
"build_date": "Byggdato:",
|
||||
"build_revision": "Bygg versjon:",
|
||||
"data_directory": "Datamappe:",
|
||||
"homepage": "Hjemmeside:"
|
||||
},
|
||||
"experimental_features": {
|
||||
"new_layout_description": "Prøv det nye grensesnittet for et mer moderne utseende og forbedret brukervenlighet. Det må påregnes betydelige endringer i kommende versjoner."
|
||||
},
|
||||
"cpu_arch_warning": {
|
||||
"recommendation": "For den beste brukeropplevelsen, vennligst last ned den tilpassede ARM64-versjonen av TriliumNext fra siden for utgivelser."
|
||||
},
|
||||
"zpetne_odkazy": {
|
||||
"backlink_one": "{{count}} Tilbakelenke",
|
||||
"backlink_other": "{{count}} Tilbakelenker"
|
||||
}
|
||||
}
|
||||
|
||||
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