mirror of
https://github.com/zadam/trilium.git
synced 2026-01-18 13:22:14 +01:00
Compare commits
871 Commits
v0.101.0
...
feature/sq
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
197fa90176 | ||
|
|
0844914e11 | ||
|
|
c376b0bbe2 | ||
|
|
4491086c55 | ||
|
|
791697369d | ||
|
|
28d0bfd229 | ||
|
|
8182a04eae | ||
|
|
711828d6b4 | ||
|
|
69e88c1d9f | ||
|
|
748b87da9a | ||
|
|
94dca4cd87 | ||
|
|
7179701e0f | ||
|
|
af5061646c | ||
|
|
9c4163ad3a | ||
|
|
46c3f5296a | ||
|
|
ebadcfd844 | ||
|
|
b7d4947462 | ||
|
|
a599526dea | ||
|
|
c4f166fe12 | ||
|
|
a8ae91aa3b | ||
|
|
82b3692acb | ||
|
|
432c054b68 | ||
|
|
dcd8bfa255 | ||
|
|
c287a2ae97 | ||
|
|
3fce4fc66c | ||
|
|
d83d7ed106 | ||
|
|
1b812f1886 | ||
|
|
56fcc7adcc | ||
|
|
fb0c7359f1 | ||
|
|
4c4e5b85e9 | ||
|
|
476247beb5 | ||
|
|
2c87f609f3 | ||
|
|
bc79ff6845 | ||
|
|
f10373d54f | ||
|
|
630d16b722 | ||
|
|
769f3db21c | ||
|
|
c6896a4b33 | ||
|
|
7c18025098 | ||
|
|
6ae74b3181 | ||
|
|
2ecfbbf284 | ||
|
|
781de9a1fb | ||
|
|
6972a4b901 | ||
|
|
52ed1750ac | ||
|
|
9010e0b1ce | ||
|
|
5053e74447 | ||
|
|
f294276849 | ||
|
|
0740788cc8 | ||
|
|
9bac07ce62 | ||
|
|
3d8289d394 | ||
|
|
5a60fdad8a | ||
|
|
62cca5a96b | ||
|
|
74548d638e | ||
|
|
e0ccf30f4f | ||
|
|
d2c6081537 | ||
|
|
bd933f2c4c | ||
|
|
1d898d618e | ||
|
|
11c8e5b3b2 | ||
|
|
fe4c3ffecb | ||
|
|
334a96186e | ||
|
|
34b2df705b | ||
|
|
5a7fc1c8b6 | ||
|
|
fabab6abb1 | ||
|
|
0c9c20c0c5 | ||
|
|
67cc1113b1 | ||
|
|
3aacd255f4 | ||
|
|
ccfda21413 | ||
|
|
46c88506cc | ||
|
|
51157e1979 | ||
|
|
bfb6d975ff | ||
|
|
aa01bc1457 | ||
|
|
5600f1b7b1 | ||
|
|
a169db807c | ||
|
|
f40348daff | ||
|
|
f63042ef87 | ||
|
|
d148c9d1c6 | ||
|
|
f72929ca13 | ||
|
|
cc3e3ca4d4 | ||
|
|
8fad664a6d | ||
|
|
f1946c1386 | ||
|
|
ea8bd0136f | ||
|
|
4a3f72ae50 | ||
|
|
c944762ef6 | ||
|
|
f6924d7fda | ||
|
|
3a0880fcd6 | ||
|
|
df62dc87b2 | ||
|
|
d42679315e | ||
|
|
2a19be5ab6 | ||
|
|
33bbe994d7 | ||
|
|
04c598caea | ||
|
|
3577688bf9 | ||
|
|
e0439655df | ||
|
|
84f944f78a | ||
|
|
022b6df959 | ||
|
|
9e3e92669f | ||
|
|
35b96a71fc | ||
|
|
4b78de6726 | ||
|
|
4771e02909 | ||
|
|
03dffdb65f | ||
|
|
859a3948cd | ||
|
|
161aa625e6 | ||
|
|
28fd945e80 | ||
|
|
748fb0bf05 | ||
|
|
98e1d0afd9 | ||
|
|
9c61ce1835 | ||
|
|
c3a5705be0 | ||
|
|
9d0fa9f7ca | ||
|
|
cc4ceb975e | ||
|
|
8a6495a0bd | ||
|
|
1d95392d22 | ||
|
|
93dd08d629 | ||
|
|
f466367c4d | ||
|
|
924d495d2e | ||
|
|
0b5c1b648b | ||
|
|
03ec39f52a | ||
|
|
f3ae1bf12c | ||
|
|
6d61cf41d9 | ||
|
|
333679523b | ||
|
|
1cd3a361f6 | ||
|
|
7405627663 | ||
|
|
2c4fb6c0d0 | ||
|
|
3e284208ef | ||
|
|
42b7f4c795 | ||
|
|
d445209eeb | ||
|
|
ed1bf17add | ||
|
|
4800f2a172 | ||
|
|
e7ff364c01 | ||
|
|
79ca299726 | ||
|
|
9d7ba48a6a | ||
|
|
9329665919 | ||
|
|
f6821bce03 | ||
|
|
a7aedf93ab | ||
|
|
4ffcf01452 | ||
|
|
618459d353 | ||
|
|
6436c16449 | ||
|
|
1bec457004 | ||
|
|
3e541e37fe | ||
|
|
a41b78d36f | ||
|
|
79c50f3b4c | ||
|
|
0f54b01cdd | ||
|
|
41f2b03711 | ||
|
|
0be76f982c | ||
|
|
5deb277672 | ||
|
|
3d15c9e94c | ||
|
|
1363f94621 | ||
|
|
abdcd6cc0c | ||
|
|
dc8abed2f3 | ||
|
|
892c2cd838 | ||
|
|
2796b29138 | ||
|
|
05620a129f | ||
|
|
cb11955a44 | ||
|
|
c3623a15fb | ||
|
|
0273c64bbf | ||
|
|
5b37140ffa | ||
|
|
fb4d63b049 | ||
|
|
015e41e792 | ||
|
|
8e47f33329 | ||
|
|
ad4a8ec5f4 | ||
|
|
56356f9c61 | ||
|
|
abda0f9111 | ||
|
|
c2a9d21198 | ||
|
|
59ffa1fa93 | ||
|
|
d056185368 | ||
|
|
251c1f6471 | ||
|
|
9efca9827e | ||
|
|
f5e2129ad4 | ||
|
|
6c8e6f2429 | ||
|
|
9b4b1a393e | ||
|
|
028334407c | ||
|
|
b93540b40d | ||
|
|
9e7eba5eab | ||
|
|
fcfa64ae52 | ||
|
|
62f5b800b6 | ||
|
|
5b910cce56 | ||
|
|
a5e8c8f573 | ||
|
|
2c8edb413e | ||
|
|
644cc27fa7 | ||
|
|
71d3eb4fde | ||
|
|
7c2340d60e | ||
|
|
24013ef020 | ||
|
|
72d9e846b7 | ||
|
|
b572ea0954 | ||
|
|
060257fa06 | ||
|
|
1c6bb0a20e | ||
|
|
1479109582 | ||
|
|
13f4e38f48 | ||
|
|
5cbde8d32a | ||
|
|
f3e3ef2f7d | ||
|
|
0a58f8108a | ||
|
|
768213438a | ||
|
|
00e0eb6f8a | ||
|
|
3abea13d79 | ||
|
|
67ab7f0c1e | ||
|
|
b38e8e27b2 | ||
|
|
a70c103b93 | ||
|
|
b83c3090f7 | ||
|
|
59ee38e7a6 | ||
|
|
890fe5929b | ||
|
|
56cc312565 | ||
|
|
9dfd015a27 | ||
|
|
04618dcdab | ||
|
|
f408e15c32 | ||
|
|
00e60c147c | ||
|
|
ad6fd64226 | ||
|
|
6595fd9c10 | ||
|
|
a268507b80 | ||
|
|
9e847f67f2 | ||
|
|
df4992122b | ||
|
|
a325ba7b8f | ||
|
|
26e64ae7d0 | ||
|
|
d793774f51 | ||
|
|
c5f2b5c177 | ||
|
|
b2f782f2a3 | ||
|
|
b65b31ca4d | ||
|
|
64827dcdcf | ||
|
|
96d5d07087 | ||
|
|
ffd0f4727a | ||
|
|
e33cd86d30 | ||
|
|
fc85c23a67 | ||
|
|
a55c8fb210 | ||
|
|
19b865a5b4 | ||
|
|
61d90dda36 | ||
|
|
a4b1f06475 | ||
|
|
49704ea928 | ||
|
|
a73df362d5 | ||
|
|
f42010e22a | ||
|
|
0b85e0fe2d | ||
|
|
c7f0720237 | ||
|
|
cc3031eaad | ||
|
|
2850c7808c | ||
|
|
30bbcd866f | ||
|
|
55b6f322ac | ||
|
|
4518c9bb99 | ||
|
|
c551c863f4 | ||
|
|
3c25f8b4f3 | ||
|
|
d3c37556c3 | ||
|
|
cf60fcd6c1 | ||
|
|
97075ff91b | ||
|
|
ce57a43d90 | ||
|
|
33485369c3 | ||
|
|
7fcd93a61b | ||
|
|
3d4b84c7c4 | ||
|
|
61eb4017dd | ||
|
|
b4df4aaf0d | ||
|
|
244294f699 | ||
|
|
d609ee028e | ||
|
|
8dc8b046fb | ||
|
|
349203e300 | ||
|
|
83a8f07998 | ||
|
|
94d4a307cf | ||
|
|
2e35e0a830 | ||
|
|
ecdb819067 | ||
|
|
e2cf0c6e3e | ||
|
|
5dd600a291 | ||
|
|
df1beb1ffb | ||
|
|
7773059ac0 | ||
|
|
a238fc16b2 | ||
|
|
e298f5ea6f | ||
|
|
a5512267c1 | ||
|
|
f503c4ca6c | ||
|
|
c834c01c8e | ||
|
|
1f72ab9593 | ||
|
|
c7d446f4aa | ||
|
|
fb1530423d | ||
|
|
545464efee | ||
|
|
29d0223fd1 | ||
|
|
00852277f2 | ||
|
|
edfe23d88c | ||
|
|
2b8a7a28d9 | ||
|
|
7f29480237 | ||
|
|
61ac482946 | ||
|
|
de6a6cbb07 | ||
|
|
2dcb003909 | ||
|
|
d5c934a518 | ||
|
|
779909837c | ||
|
|
a4cb375a0f | ||
|
|
e2da8c28ca | ||
|
|
7808848f05 | ||
|
|
7c05109645 | ||
|
|
8f9e89b73b | ||
|
|
861a61a4d8 | ||
|
|
52d4083814 | ||
|
|
0272189b22 | ||
|
|
ddba0e823c | ||
|
|
be81acb9e7 | ||
|
|
3bb97385c9 | ||
|
|
a72cec0494 | ||
|
|
cb02198c6f | ||
|
|
298d438230 | ||
|
|
cb2f7932dd | ||
|
|
3354bd669f | ||
|
|
8ad779be66 | ||
|
|
f462034868 | ||
|
|
26c25cd4cd | ||
|
|
6398830c2d | ||
|
|
0b065063f2 | ||
|
|
a3a9de6fdd | ||
|
|
d77d30f29e | ||
|
|
5cabc6379d | ||
|
|
af537e6a48 | ||
|
|
faf3797663 | ||
|
|
db57f3ff62 | ||
|
|
0f77caad69 | ||
|
|
751b91e1b8 | ||
|
|
968a17fbfb | ||
|
|
712e87b39f | ||
|
|
0b40b42315 | ||
|
|
62996b1162 | ||
|
|
b67ccc6091 | ||
|
|
211d2dcf99 | ||
|
|
ee52e16a75 | ||
|
|
0c27bd25fa | ||
|
|
b6a6e78d01 | ||
|
|
92e6a29e70 | ||
|
|
acc8cee7cd | ||
|
|
afefbe154b | ||
|
|
83fa55b7d9 | ||
|
|
4f6c10d995 | ||
|
|
ed972d2601 | ||
|
|
6b57ee5654 | ||
|
|
e469af1ca5 | ||
|
|
6d41f076c2 | ||
|
|
8cff591746 | ||
|
|
b3ccf89094 | ||
|
|
d31c6b1627 | ||
|
|
1481356d1f | ||
|
|
a54661fd0a | ||
|
|
ae4a3f10ae | ||
|
|
fe3160e7a1 | ||
|
|
66659d4786 | ||
|
|
0b25b09040 | ||
|
|
0d41cc2660 | ||
|
|
f5e8822718 | ||
|
|
bdc220ec12 | ||
|
|
3eb68e5271 | ||
|
|
521952ebcc | ||
|
|
034091a696 | ||
|
|
ae881101d8 | ||
|
|
b11a30c49c | ||
|
|
4625efda7f | ||
|
|
3c168d750d | ||
|
|
5cc7b259ce | ||
|
|
f7ae046b20 | ||
|
|
02f43d6239 | ||
|
|
53e1fa1047 | ||
|
|
b1dc0e234f | ||
|
|
9d380dd828 | ||
|
|
1f77540dbb | ||
|
|
455edbfb5d | ||
|
|
7288b66d27 | ||
|
|
3d72ec80bb | ||
|
|
f2a74df511 | ||
|
|
68c6052d10 | ||
|
|
c4edb56bd4 | ||
|
|
b6a3fe7cfb | ||
|
|
7a088c5b7d | ||
|
|
2e845a9faa | ||
|
|
ac3ae0dbbe | ||
|
|
a3fc13de3a | ||
|
|
ee6cbc710c | ||
|
|
18d701525e | ||
|
|
e47c848ec8 | ||
|
|
cd64548299 | ||
|
|
8645d053de | ||
|
|
91f2dabed7 | ||
|
|
716612680d | ||
|
|
3800fb85eb | ||
|
|
d807984be4 | ||
|
|
2c92ae8898 | ||
|
|
3d8cbc81c4 | ||
|
|
d747c94450 | ||
|
|
a627d1f96e | ||
|
|
869db5e478 | ||
|
|
73e94d385e | ||
|
|
8f4ebeb335 | ||
|
|
263ee864be | ||
|
|
f078732624 | ||
|
|
fac1f6b16c | ||
|
|
a5841c1423 | ||
|
|
aaca18003d | ||
|
|
5ec521b024 | ||
|
|
b3c0be7559 | ||
|
|
d52b735b99 | ||
|
|
639b1f2863 | ||
|
|
aff4f7e010 | ||
|
|
dec4dafba6 | ||
|
|
d0cdcfc32c | ||
|
|
0867b81c7a | ||
|
|
bde6068f2d | ||
|
|
47fd2affa4 | ||
|
|
2dd541e1d0 | ||
|
|
7f2cc885fe | ||
|
|
19a365a370 | ||
|
|
9a50da328e | ||
|
|
181e36a7c1 | ||
|
|
178508d245 | ||
|
|
8157ef5e74 | ||
|
|
d132d084cf | ||
|
|
494b55d685 | ||
|
|
0185dd0d18 | ||
|
|
142ed42d90 | ||
|
|
51513d3779 | ||
|
|
5b95b9875b | ||
|
|
688d197472 | ||
|
|
b745fb476e | ||
|
|
047b5a85d2 | ||
|
|
370a0c6a05 | ||
|
|
0d4558fee1 | ||
|
|
76526e0a96 | ||
|
|
70093e0a7d | ||
|
|
458398f2ca | ||
|
|
7a6cc4f51e | ||
|
|
f4ccce7de5 | ||
|
|
f8b5417d6c | ||
|
|
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 | ||
|
|
87ab41c80c | ||
|
|
d2391f94c0 | ||
|
|
050ddb8c55 | ||
|
|
bc23e0984a | ||
|
|
07de353207 | ||
|
|
c02491d2e6 | ||
|
|
a6ede8f905 | ||
|
|
22941a9ce0 | ||
|
|
633a09d414 | ||
|
|
29f0881c5a | ||
|
|
60debca37b | ||
|
|
30ea81d0fb | ||
|
|
b1d92c4fe6 | ||
|
|
70f46de2d8 | ||
|
|
f1b2d0b870 | ||
|
|
8a385972fc | ||
|
|
28dd85c1d1 | ||
|
|
827c8e0e72 | ||
|
|
162c076a14 | ||
|
|
9386465de7 | ||
|
|
acca22f3a1 | ||
|
|
a1c0314334 | ||
|
|
3ecdcd9ea0 | ||
|
|
f8d84814e0 | ||
|
|
c46cf41842 | ||
|
|
64ab1c4116 | ||
|
|
a6de1041c7 | ||
|
|
c8d34e65ea | ||
|
|
51db729546 | ||
|
|
d2052ad236 | ||
|
|
9c4301467f | ||
|
|
e7355dc0e4 | ||
|
|
4110fec94f | ||
|
|
d5e601eae9 | ||
|
|
4f044c4a57 | ||
|
|
5821c350e1 | ||
|
|
edba8188fe | ||
|
|
1471a72633 | ||
|
|
56834cb88a | ||
|
|
a0f16f9184 | ||
|
|
de80eb4806 | ||
|
|
48a4b81fbe | ||
|
|
e225794f72 | ||
|
|
4eef30f8b5 | ||
|
|
569b09609d | ||
|
|
39838c25c2 | ||
|
|
49e90c08a9 | ||
|
|
e777b06fb8 | ||
|
|
497ec2ac74 | ||
|
|
c5d282d203 |
30
.github/workflows/i18n.yml
vendored
Normal file
30
.github/workflows/i18n.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: Internationalization
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "weblate:*"
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths:
|
||||
- "apps/client/src/translations/**"
|
||||
- ".github/workflows/i18n.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
i18n-check:
|
||||
name: Check i18n translations
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
cache: 'pnpm'
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Check translations
|
||||
run: pnpm tsx scripts/translation/check-translation-coverage.ts
|
||||
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
@@ -11,6 +11,14 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
sanity-check:
|
||||
name: Sanity Check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Check version consistency
|
||||
run: pnpm tsx ${{ github.workspace }}/scripts/check-version-consistency.ts ${{ github.ref_name }}
|
||||
make-electron:
|
||||
name: Make Electron
|
||||
strategy:
|
||||
|
||||
2
.github/workflows/website.yml
vendored
2
.github/workflows/website.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
cache: "pnpm"
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --filter website --frozen-lockfile
|
||||
run: pnpm install --filter website --frozen-lockfile --ignore-scripts
|
||||
|
||||
- name: Build the website
|
||||
run: pnpm website:build
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -51,3 +51,4 @@ upload
|
||||
# docs
|
||||
site/
|
||||
apps/*/coverage
|
||||
scripts/translation/.language*.json
|
||||
|
||||
11
README.md
11
README.md
@@ -165,6 +165,17 @@ pnpm install
|
||||
pnpm edit-docs:edit-docs
|
||||
```
|
||||
|
||||
Alternatively, if you have Nix installed:
|
||||
```shell
|
||||
# Run directly
|
||||
nix run .#edit-docs
|
||||
|
||||
# Or install to your profile
|
||||
nix profile install .#edit-docs
|
||||
trilium-edit-docs
|
||||
```
|
||||
|
||||
|
||||
### Building the Executable
|
||||
Download the repository, install dependencies using `pnpm` and then build the desktop app for Windows:
|
||||
```shell
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
"keywords": [],
|
||||
"author": "Elian Doran <contact@eliandoran.me>",
|
||||
"license": "AGPL-3.0-only",
|
||||
"packageManager": "pnpm@10.26.2",
|
||||
"packageManager": "pnpm@10.28.0",
|
||||
"devDependencies": {
|
||||
"@redocly/cli": "2.14.1",
|
||||
"@redocly/cli": "2.14.5",
|
||||
"archiver": "7.0.1",
|
||||
"fs-extra": "11.3.3",
|
||||
"react": "19.2.3",
|
||||
"react-dom": "19.2.3",
|
||||
"typedoc": "0.28.15",
|
||||
"typedoc": "0.28.16",
|
||||
"typedoc-plugin-missing-exports": "4.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@triliumnext/client",
|
||||
"version": "0.101.0",
|
||||
"version": "0.101.3",
|
||||
"description": "JQuery-based client for TriliumNext, used for both web and desktop (via Electron)",
|
||||
"private": true,
|
||||
"license": "AGPL-3.0-only",
|
||||
@@ -43,8 +43,8 @@
|
||||
"debounce": "3.0.0",
|
||||
"draggabilly": "3.0.0",
|
||||
"force-graph": "1.51.0",
|
||||
"globals": "16.5.0",
|
||||
"i18next": "25.7.3",
|
||||
"globals": "17.0.0",
|
||||
"i18next": "25.7.4",
|
||||
"i18next-http-backend": "3.0.2",
|
||||
"jquery": "3.7.1",
|
||||
"jquery.fancytree": "2.38.5",
|
||||
@@ -56,11 +56,12 @@
|
||||
"mark.js": "8.11.1",
|
||||
"marked": "17.0.1",
|
||||
"mermaid": "11.12.2",
|
||||
"mind-elixir": "5.3.8",
|
||||
"mind-elixir": "5.6.1",
|
||||
"normalize.css": "8.0.1",
|
||||
"panzoom": "9.4.3",
|
||||
"preact": "10.28.1",
|
||||
"react-i18next": "16.5.0",
|
||||
"preact": "10.28.2",
|
||||
"react-i18next": "16.5.3",
|
||||
"react-window": "2.2.5",
|
||||
"reveal.js": "5.2.1",
|
||||
"svg-pan-zoom": "3.6.2",
|
||||
"tabulator-tables": "6.3.1",
|
||||
@@ -68,7 +69,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ckeditor/ckeditor5-inspector": "5.0.0",
|
||||
"@preact/preset-vite": "2.10.2",
|
||||
"@prefresh/vite": "2.4.11",
|
||||
"@types/bootstrap": "5.2.10",
|
||||
"@types/jquery": "3.5.33",
|
||||
"@types/leaflet": "1.9.21",
|
||||
@@ -77,7 +78,8 @@
|
||||
"@types/reveal.js": "5.2.2",
|
||||
"@types/tabulator-tables": "6.3.1",
|
||||
"copy-webpack-plugin": "13.0.1",
|
||||
"happy-dom": "20.0.11",
|
||||
"happy-dom": "20.3.1",
|
||||
"lightningcss": "1.30.2",
|
||||
"script-loader": "0.7.2",
|
||||
"vite-plugin-static-copy": "3.1.4"
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import type { CKTextEditor } from "@triliumnext/ckeditor5";
|
||||
import type CodeMirror from "@triliumnext/codemirror";
|
||||
import { SqlExecuteResults } from "@triliumnext/commons";
|
||||
import { SqlExecuteResponse } from "@triliumnext/commons";
|
||||
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 { 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";
|
||||
@@ -154,6 +154,7 @@ export type CommandMappings = {
|
||||
};
|
||||
openInTab: ContextMenuCommandData;
|
||||
openNoteInSplit: ContextMenuCommandData;
|
||||
openNoteInWindow: ContextMenuCommandData;
|
||||
openNoteInPopup: ContextMenuCommandData;
|
||||
toggleNoteHoisting: ContextMenuCommandData;
|
||||
insertNoteAfter: ContextMenuCommandData;
|
||||
@@ -382,7 +383,8 @@ export type CommandMappings = {
|
||||
reloadTextEditor: CommandData;
|
||||
chooseNoteType: CommandData & {
|
||||
callback: ChooseNoteTypeCallback
|
||||
}
|
||||
};
|
||||
customDownload: CommandData;
|
||||
};
|
||||
|
||||
type EventMappings = {
|
||||
@@ -408,7 +410,7 @@ type EventMappings = {
|
||||
addNewLabel: CommandData;
|
||||
addNewRelation: CommandData;
|
||||
sqlQueryResults: CommandData & {
|
||||
results: SqlExecuteResults;
|
||||
response: SqlExecuteResponse;
|
||||
};
|
||||
readOnlyTemporarilyDisabled: {
|
||||
noteContext: NoteContext;
|
||||
@@ -473,6 +475,11 @@ type EventMappings = {
|
||||
noteContextRemoved: {
|
||||
ntxIds: string[];
|
||||
};
|
||||
contextDataChanged: {
|
||||
noteContext: NoteContext;
|
||||
key: string;
|
||||
value: unknown;
|
||||
};
|
||||
exportSvg: { ntxId: string | null | undefined; };
|
||||
exportPng: { ntxId: string | null | undefined; };
|
||||
geoMapCreateChildNote: {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import utils from "../services/utils.js";
|
||||
import { CreateChildrenResponse, SqlExecuteResponse } from "@triliumnext/commons";
|
||||
|
||||
import bundleService from "../services/bundle.js";
|
||||
import dateNoteService from "../services/date_notes.js";
|
||||
import froca from "../services/froca.js";
|
||||
import { t } from "../services/i18n.js";
|
||||
import linkService from "../services/link.js";
|
||||
import protectedSessionHolder from "../services/protected_session_holder.js";
|
||||
import server from "../services/server.js";
|
||||
import toastService from "../services/toast.js";
|
||||
import utils from "../services/utils.js";
|
||||
import ws from "../services/ws.js";
|
||||
import appContext, { type NoteCommandData } from "./app_context.js";
|
||||
import Component from "./component.js";
|
||||
import toastService from "../services/toast.js";
|
||||
import ws from "../services/ws.js";
|
||||
import bundleService from "../services/bundle.js";
|
||||
import froca from "../services/froca.js";
|
||||
import linkService from "../services/link.js";
|
||||
import { t } from "../services/i18n.js";
|
||||
import { CreateChildrenResponse, SqlExecuteResponse } from "@triliumnext/commons";
|
||||
|
||||
export default class Entrypoints extends Component {
|
||||
constructor() {
|
||||
@@ -187,13 +188,8 @@ export default class Entrypoints extends Component {
|
||||
} else if (note.mime.endsWith("env=backend")) {
|
||||
await server.post(`script/run/${note.noteId}`);
|
||||
} else if (note.mime === "text/x-sqlite;schema=trilium") {
|
||||
const resp = await server.post<SqlExecuteResponse>(`sql/execute/${note.noteId}`);
|
||||
|
||||
if (!resp.success) {
|
||||
toastService.showError(t("entrypoints.sql-error", { message: resp.error }));
|
||||
}
|
||||
|
||||
await appContext.triggerEvent("sqlQueryResults", { ntxId: ntxId, results: resp.results });
|
||||
const response = await server.post<SqlExecuteResponse>(`sql/execute/${note.noteId}`);
|
||||
await appContext.triggerEvent("sqlQueryResults", { ntxId, response });
|
||||
}
|
||||
|
||||
toastService.showMessage(t("entrypoints.note-executed"));
|
||||
|
||||
@@ -12,6 +12,7 @@ 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";
|
||||
|
||||
@@ -22,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;
|
||||
@@ -32,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();
|
||||
|
||||
@@ -91,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);
|
||||
@@ -443,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,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();
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MIME_TYPES_DICT } from "@triliumnext/commons";
|
||||
import { getNoteIcon } from "@triliumnext/commons";
|
||||
|
||||
import cssClassManager from "../services/css_class_manager.js";
|
||||
import type { Froca } from "../services/froca-interface.js";
|
||||
@@ -8,30 +8,11 @@ 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";
|
||||
import type { AttributeType, default as FAttribute } from "./fattribute.js";
|
||||
|
||||
const LABEL = "label";
|
||||
const RELATION = "relation";
|
||||
|
||||
export const NOTE_TYPE_ICONS = {
|
||||
file: "bx bx-file",
|
||||
image: "bx bx-image",
|
||||
code: "bx bx-code",
|
||||
render: "bx bx-extension",
|
||||
search: "bx bx-file-find",
|
||||
relationMap: "bx bxs-network-chart",
|
||||
book: "bx bx-book",
|
||||
noteMap: "bx bxs-network-chart",
|
||||
mermaid: "bx bx-selection",
|
||||
canvas: "bx bx-pen",
|
||||
webView: "bx bx-globe-alt",
|
||||
launcher: "bx bx-link",
|
||||
doc: "bx bxs-file-doc",
|
||||
contentWidget: "bx bxs-widget",
|
||||
mindMap: "bx bx-sitemap",
|
||||
aiChat: "bx bx-bot"
|
||||
};
|
||||
|
||||
/**
|
||||
* There are many different Note types, some of which are entirely opaque to the
|
||||
* end user. Those types should be used only for checking against, they are
|
||||
@@ -585,25 +566,15 @@ export default class FNote {
|
||||
const iconClassLabels = this.getLabels("iconClass");
|
||||
const workspaceIconClass = this.getWorkspaceIconClass();
|
||||
|
||||
if (iconClassLabels && iconClassLabels.length > 0) {
|
||||
return iconClassLabels[0].value;
|
||||
} else if (workspaceIconClass) {
|
||||
return workspaceIconClass;
|
||||
} else if (this.noteId === "root") {
|
||||
return "bx bx-home-alt-2";
|
||||
}
|
||||
if (this.noteId === "_share") {
|
||||
return "bx bx-share-alt";
|
||||
} else if (this.type === "text") {
|
||||
if (this.isFolder()) {
|
||||
return "bx bx-folder";
|
||||
}
|
||||
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];
|
||||
const icon = getNoteIcon({
|
||||
noteId: this.noteId,
|
||||
type: this.type,
|
||||
mime: this.mime,
|
||||
iconClass: iconClassLabels.length > 0 ? iconClassLabels[0].value : undefined,
|
||||
workspaceIconClass,
|
||||
isFolder: this.isFolder.bind(this)
|
||||
});
|
||||
return `tn-icon ${icon}`;
|
||||
}
|
||||
|
||||
getColorClass() {
|
||||
@@ -612,7 +583,9 @@ export default class FNote {
|
||||
}
|
||||
|
||||
isFolder() {
|
||||
return this.type === "search" || this.getFilteredChildBranches().length > 0;
|
||||
if (this.isLabelTruthy("subtreeHidden")) return false;
|
||||
if (this.type === "search") return true;
|
||||
return this.getFilteredChildBranches().length > 0;
|
||||
}
|
||||
|
||||
getFilteredChildBranches() {
|
||||
|
||||
BIN
apps/client/src/fonts/boxicons.woff2
Normal file
BIN
apps/client/src/fonts/boxicons.woff2
Normal file
Binary file not shown.
29
apps/client/src/index.html
Normal file
29
apps/client/src/index.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="shortcut icon" href="favicon.ico">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover, interactive-widget=resizes-content" />
|
||||
<link rel="manifest" crossorigin="use-credentials" href="manifest.webmanifest">
|
||||
<title>Trilium Notes</title>
|
||||
</head>
|
||||
|
||||
<body id="trilium-app">
|
||||
<noscript>Trilium requires JavaScript to be enabled.</noscript>
|
||||
|
||||
<div class="dropdown-menu dropdown-menu-sm" id="context-menu-container" style="display: none"></div>
|
||||
|
||||
<!-- Required to match the PWA's top bar color with the theme -->
|
||||
<!-- This works even when the user directly changes --root-background in CSS -->
|
||||
<div id="background-color-tracker" style="position: absolute; visibility: hidden; color: var(--root-background); transition: color 1ms;"></div>
|
||||
|
||||
<script src="./index.ts" type="module"></script>
|
||||
|
||||
<!-- Required for correct loading of scripts in Electron -->
|
||||
<script>
|
||||
if (typeof module === 'object') {window.module = module; module = undefined;}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,110 @@
|
||||
async function bootstrap() {
|
||||
showSplash();
|
||||
await setupGlob();
|
||||
await Promise.all([
|
||||
initJQuery(),
|
||||
loadBootstrapCss()
|
||||
]);
|
||||
loadStylesheets();
|
||||
loadIcons();
|
||||
setBodyAttributes();
|
||||
await loadScripts();
|
||||
hideSplash();
|
||||
}
|
||||
|
||||
async function initJQuery() {
|
||||
const $ = (await import("jquery")).default;
|
||||
window.$ = $;
|
||||
window.jQuery = $;
|
||||
}
|
||||
|
||||
async function setupGlob() {
|
||||
const response = await fetch(`/bootstrap${window.location.search}`);
|
||||
const json = await response.json();
|
||||
|
||||
window.global = globalThis; /* fixes https://github.com/webpack/webpack/issues/10035 */
|
||||
window.glob = {
|
||||
...json,
|
||||
activeDialog: null
|
||||
};
|
||||
}
|
||||
|
||||
async function loadBootstrapCss() {
|
||||
// We have to selectively import Bootstrap CSS based on text direction.
|
||||
if (glob.isRtl) {
|
||||
await import("bootstrap/dist/css/bootstrap.rtl.min.css");
|
||||
} else {
|
||||
await import("bootstrap/dist/css/bootstrap.min.css");
|
||||
}
|
||||
}
|
||||
|
||||
function loadStylesheets() {
|
||||
const { assetPath, themeCssUrl, themeUseNextAsBase } = window.glob;
|
||||
const cssToLoad: string[] = [];
|
||||
cssToLoad.push(`${assetPath}/stylesheets/ckeditor-theme.css`);
|
||||
cssToLoad.push(`api/fonts`);
|
||||
cssToLoad.push(`${assetPath}/stylesheets/theme-light.css`);
|
||||
if (themeCssUrl) {
|
||||
cssToLoad.push(themeCssUrl);
|
||||
}
|
||||
if (themeUseNextAsBase === "next") {
|
||||
cssToLoad.push(`${assetPath}/stylesheets/theme-next.css`);
|
||||
} else if (themeUseNextAsBase === "next-dark") {
|
||||
cssToLoad.push(`${assetPath}/stylesheets/theme-next-dark.css`);
|
||||
} else if (themeUseNextAsBase === "next-light") {
|
||||
cssToLoad.push(`${assetPath}/stylesheets/theme-next-light.css`);
|
||||
}
|
||||
cssToLoad.push(`${assetPath}/stylesheets/style.css`);
|
||||
|
||||
for (const href of cssToLoad) {
|
||||
const linkEl = document.createElement("link");
|
||||
linkEl.href = href;
|
||||
linkEl.rel = "stylesheet";
|
||||
document.head.appendChild(linkEl);
|
||||
}
|
||||
}
|
||||
|
||||
function loadIcons() {
|
||||
const styleEl = document.createElement("style");
|
||||
styleEl.innerText = window.glob.iconPackCss;
|
||||
document.head.appendChild(styleEl);
|
||||
}
|
||||
|
||||
function setBodyAttributes() {
|
||||
const { device, headingStyle, layoutOrientation, platform, isElectron, hasNativeTitleBar, hasBackgroundEffects, currentLocale } = window.glob;
|
||||
const classesToSet = [
|
||||
device,
|
||||
`heading-style-${headingStyle}`,
|
||||
`layout-${layoutOrientation}`,
|
||||
`platform-${platform}`,
|
||||
isElectron && "electron",
|
||||
hasNativeTitleBar && "native-titlebar",
|
||||
hasBackgroundEffects && "background-effects"
|
||||
].filter(Boolean) as string[];
|
||||
|
||||
for (const classToSet of classesToSet) {
|
||||
document.body.classList.add(classToSet);
|
||||
}
|
||||
|
||||
document.body.lang = currentLocale.id;
|
||||
document.body.dir = currentLocale.rtl ? "rtl" : "ltr";
|
||||
}
|
||||
|
||||
async function loadScripts() {
|
||||
if (glob.device === "mobile") {
|
||||
await import("./mobile.js");
|
||||
} else {
|
||||
await import("./desktop.js");
|
||||
}
|
||||
}
|
||||
|
||||
function showSplash() {
|
||||
// hide body to reduce flickering on the startup. This is done through JS and not CSS to not hide <noscript>
|
||||
document.body.style.display = "none";
|
||||
}
|
||||
|
||||
function hideSplash() {
|
||||
document.body.style.display = "block";
|
||||
}
|
||||
|
||||
bootstrap();
|
||||
|
||||
@@ -46,8 +46,6 @@ import ScrollPadding from "../widgets/scroll_padding.js";
|
||||
import SearchResult from "../widgets/search_result.jsx";
|
||||
import SharedInfo from "../widgets/shared_info.jsx";
|
||||
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";
|
||||
@@ -92,7 +90,7 @@ export default class DesktopLayout {
|
||||
.optChild(launcherPaneIsHorizontal, <LeftPaneToggle isHorizontalLayout={true} />)
|
||||
.child(<TabHistoryNavigationButtons />)
|
||||
.child(new TabRowWidget().class("full-width"))
|
||||
.optChild(launcherPaneIsHorizontal && isNewLayout, <RightPaneToggle />)
|
||||
.optChild(isNewLayout, <RightPaneToggle />)
|
||||
.optChild(customTitleBarButtons, <TitleBarButtons />)
|
||||
.css("height", "40px")
|
||||
.css("background-color", "var(--launcher-pane-background-color)")
|
||||
@@ -163,11 +161,9 @@ export default class DesktopLayout {
|
||||
.child(<SharedInfo />)
|
||||
)
|
||||
.optChild(!isNewLayout, <PromotedAttributes />)
|
||||
.child(<SqlTableSchemas />)
|
||||
.child(<NoteDetail />)
|
||||
.child(<NoteList media="screen" />)
|
||||
.child(<SearchResult />)
|
||||
.child(<SqlResults />)
|
||||
.child(<ScrollPadding />)
|
||||
)
|
||||
.child(<ApiLog />)
|
||||
|
||||
@@ -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 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 LauncherContainer from "../widgets/launch_bar/LauncherContainer.jsx";
|
||||
import { applyModals } from "./layout_commons.js";
|
||||
|
||||
const MOBILE_CSS = `
|
||||
<style>
|
||||
@@ -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,21 +1,21 @@
|
||||
import NoteColorPicker from "./custom-items/NoteColorPicker.jsx";
|
||||
import treeService from "../services/tree.js";
|
||||
import froca from "../services/froca.js";
|
||||
import clipboard from "../services/clipboard.js";
|
||||
import noteCreateService from "../services/note_create.js";
|
||||
import contextMenu, { type MenuCommandItem, type MenuItem } from "./context_menu.js";
|
||||
import appContext, { type ContextMenuCommandData, type FilteredCommandNames } from "../components/app_context.js";
|
||||
import type { SelectMenuItemEventListener } from "../components/events.js";
|
||||
import type FAttachment from "../entities/fattachment.js";
|
||||
import attributes from "../services/attributes.js";
|
||||
import { executeBulkActions } from "../services/bulk_action.js";
|
||||
import clipboard from "../services/clipboard.js";
|
||||
import dialogService from "../services/dialog.js";
|
||||
import froca from "../services/froca.js";
|
||||
import { t } from "../services/i18n.js";
|
||||
import noteCreateService from "../services/note_create.js";
|
||||
import noteTypesService from "../services/note_types.js";
|
||||
import server from "../services/server.js";
|
||||
import toastService from "../services/toast.js";
|
||||
import dialogService from "../services/dialog.js";
|
||||
import { t } from "../services/i18n.js";
|
||||
import type NoteTreeWidget from "../widgets/note_tree.js";
|
||||
import type FAttachment from "../entities/fattachment.js";
|
||||
import type { SelectMenuItemEventListener } from "../components/events.js";
|
||||
import treeService from "../services/tree.js";
|
||||
import utils from "../services/utils.js";
|
||||
import attributes from "../services/attributes.js";
|
||||
import { executeBulkActions } from "../services/bulk_action.js";
|
||||
import type NoteTreeWidget from "../widgets/note_tree.js";
|
||||
import contextMenu, { type MenuCommandItem, type MenuItem } from "./context_menu.js";
|
||||
import NoteColorPicker from "./custom-items/NoteColorPicker.jsx";
|
||||
|
||||
// TODO: Deduplicate once client/server is well split.
|
||||
interface ConvertToAttachmentResponse {
|
||||
@@ -72,6 +72,8 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
|
||||
const noSelectedNotes = selNodes.length === 0 || (selNodes.length === 1 && selNodes[0] === this.node);
|
||||
|
||||
const notSearch = note?.type !== "search";
|
||||
const hasSubtreeHidden = note?.isLabelTruthy("subtreeHidden") ?? false;
|
||||
const isSpotlighted = this.node.extraClasses.includes("spotlighted-node");
|
||||
const notOptionsOrHelp = !note?.noteId.startsWith("_options") && !note?.noteId.startsWith("_help");
|
||||
const parentNotSearch = !parentNote || parentNote.type !== "search";
|
||||
const insertNoteAfterEnabled = isNotRoot && !isHoisted && parentNotSearch;
|
||||
@@ -79,17 +81,18 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
|
||||
const items: (MenuItem<TreeCommandNames> | null)[] = [
|
||||
{ title: t("tree-context-menu.open-in-a-new-tab"), command: "openInTab", shortcut: "Ctrl+Click", uiIcon: "bx bx-link-external", enabled: noSelectedNotes },
|
||||
{ title: t("tree-context-menu.open-in-a-new-split"), command: "openNoteInSplit", uiIcon: "bx bx-dock-right", enabled: noSelectedNotes },
|
||||
{ title: t("tree-context-menu.open-in-a-new-window"), command: "openNoteInWindow", uiIcon: "bx bx-window-open", enabled: noSelectedNotes },
|
||||
{ title: t("tree-context-menu.open-in-popup"), command: "openNoteInPopup", uiIcon: "bx bx-edit", enabled: noSelectedNotes },
|
||||
|
||||
isHoisted
|
||||
? null
|
||||
: {
|
||||
title: `${t("tree-context-menu.hoist-note")}`,
|
||||
command: "toggleNoteHoisting",
|
||||
keyboardShortcut: "toggleNoteHoisting",
|
||||
uiIcon: "bx bxs-chevrons-up",
|
||||
enabled: noSelectedNotes && notSearch
|
||||
},
|
||||
title: `${t("tree-context-menu.hoist-note")}`,
|
||||
command: "toggleNoteHoisting",
|
||||
keyboardShortcut: "toggleNoteHoisting",
|
||||
uiIcon: "bx bxs-chevrons-up",
|
||||
enabled: noSelectedNotes && notSearch
|
||||
},
|
||||
!isHoisted || !isNotRoot
|
||||
? null
|
||||
: { title: t("tree-context-menu.unhoist-note"), command: "toggleNoteHoisting", keyboardShortcut: "toggleNoteHoisting", uiIcon: "bx bx-door-open" },
|
||||
@@ -112,7 +115,7 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
|
||||
keyboardShortcut: "createNoteInto",
|
||||
uiIcon: "bx bx-plus",
|
||||
items: notSearch ? await noteTypesService.getNoteTypeItems("insertChildNote") : null,
|
||||
enabled: notSearch && noSelectedNotes && notOptionsOrHelp,
|
||||
enabled: notSearch && noSelectedNotes && notOptionsOrHelp && !hasSubtreeHidden && !isSpotlighted,
|
||||
columns: 2
|
||||
},
|
||||
|
||||
@@ -150,8 +153,17 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
|
||||
|
||||
{ kind: "separator" },
|
||||
|
||||
{ title: t("tree-context-menu.expand-subtree"), command: "expandSubtree", keyboardShortcut: "expandSubtree", uiIcon: "bx bx-expand", enabled: noSelectedNotes },
|
||||
{ title: t("tree-context-menu.collapse-subtree"), command: "collapseSubtree", keyboardShortcut: "collapseSubtree", uiIcon: "bx bx-collapse", enabled: noSelectedNotes },
|
||||
!hasSubtreeHidden && { title: t("tree-context-menu.expand-subtree"), command: "expandSubtree", keyboardShortcut: "expandSubtree", uiIcon: "bx bx-expand", enabled: noSelectedNotes },
|
||||
!hasSubtreeHidden && { title: t("tree-context-menu.collapse-subtree"), command: "collapseSubtree", keyboardShortcut: "collapseSubtree", uiIcon: "bx bx-collapse", enabled: noSelectedNotes },
|
||||
{
|
||||
title: hasSubtreeHidden ? t("tree-context-menu.show-subtree") : t("tree-context-menu.hide-subtree"),
|
||||
uiIcon: "bx bx-show",
|
||||
handler: async () => {
|
||||
const note = await froca.getNote(this.node.data.noteId);
|
||||
if (!note) return;
|
||||
attributes.setBooleanWithInheritance(note, "subtreeHidden", !hasSubtreeHidden);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: t("tree-context-menu.sort-by"),
|
||||
command: "sortChildNotes",
|
||||
@@ -164,7 +176,7 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
|
||||
|
||||
{ title: t("tree-context-menu.copy-note-path-to-clipboard"), command: "copyNotePathToClipboard", uiIcon: "bx bx-directions", enabled: true },
|
||||
{ title: t("tree-context-menu.recent-changes-in-subtree"), command: "recentChangesInSubtree", uiIcon: "bx bx-history", enabled: noSelectedNotes && notOptionsOrHelp }
|
||||
]
|
||||
].filter(Boolean) as MenuItem<TreeCommandNames>[]
|
||||
},
|
||||
|
||||
{ kind: "separator" },
|
||||
@@ -292,25 +304,30 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
|
||||
noteCreateService.createNote(parentNotePath, {
|
||||
target: "after",
|
||||
targetBranchId: this.node.data.branchId,
|
||||
type: type,
|
||||
isProtected: isProtected,
|
||||
templateNoteId: templateNoteId
|
||||
type,
|
||||
isProtected,
|
||||
templateNoteId
|
||||
});
|
||||
} else if (command === "insertChildNote") {
|
||||
const parentNotePath = treeService.getNotePath(this.node);
|
||||
|
||||
noteCreateService.createNote(parentNotePath, {
|
||||
type: type,
|
||||
type,
|
||||
isProtected: this.node.data.isProtected,
|
||||
templateNoteId: templateNoteId
|
||||
templateNoteId
|
||||
});
|
||||
} else if (command === "openNoteInSplit") {
|
||||
const subContexts = appContext.tabManager.getActiveContext()?.getSubContexts();
|
||||
const { ntxId } = subContexts?.[subContexts.length - 1] ?? {};
|
||||
|
||||
this.treeWidget.triggerCommand("openNewNoteSplit", { ntxId, notePath });
|
||||
} else if (command === "openNoteInWindow") {
|
||||
appContext.triggerCommand("openInWindow", {
|
||||
notePath,
|
||||
hoistedNoteId: appContext.tabManager.getActiveContext()?.hoistedNoteId
|
||||
});
|
||||
} else if (command === "openNoteInPopup") {
|
||||
appContext.triggerCommand("openInPopup", { noteIdOrPath: notePath })
|
||||
appContext.triggerCommand("openInPopup", { noteIdOrPath: notePath });
|
||||
} else if (command === "convertNoteToAttachment") {
|
||||
if (!(await dialogService.confirm(t("tree-context-menu.convert-to-attachment-confirm")))) {
|
||||
return;
|
||||
@@ -332,11 +349,11 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
|
||||
|
||||
toastService.showMessage(t("tree-context-menu.converted-to-attachments", { count: converted }));
|
||||
} else if (command === "copyNotePathToClipboard") {
|
||||
navigator.clipboard.writeText("#" + notePath);
|
||||
navigator.clipboard.writeText(`#${ notePath}`);
|
||||
} else if (command) {
|
||||
this.treeWidget.triggerCommand<TreeCommandNames>(command, {
|
||||
node: this.node,
|
||||
notePath: notePath,
|
||||
notePath,
|
||||
noteId: this.node.data.noteId,
|
||||
selectedOrActiveBranchIds: this.treeWidget.getSelectedOrActiveBranchIds(this.node),
|
||||
selectedOrActiveNoteIds: this.treeWidget.getSelectedOrActiveNoteIds(this.node)
|
||||
|
||||
@@ -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();
|
||||
|
||||
139
apps/client/src/services/attributes.spec.ts
Normal file
139
apps/client/src/services/attributes.spec.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { buildNote } from "../test/easy-froca";
|
||||
import { setBooleanWithInheritance } from "./attributes";
|
||||
import froca from "./froca";
|
||||
import server from "./server.js";
|
||||
|
||||
// Spy on server methods to track calls
|
||||
// @ts-expect-error the generic typing is causing issues here
|
||||
server.put = vi.fn(async <T> (url: string, data?: T) => ({} as T));
|
||||
// @ts-expect-error the generic typing is causing issues here
|
||||
server.remove = vi.fn(async <T> (url: string) => ({} as T));
|
||||
|
||||
describe("Set boolean with inheritance", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it("doesn't call server if value matches directly", async () => {
|
||||
const noteWithLabel = buildNote({
|
||||
title: "New note",
|
||||
"#foo": ""
|
||||
});
|
||||
const noteWithoutLabel = buildNote({
|
||||
title: "New note"
|
||||
});
|
||||
|
||||
await setBooleanWithInheritance(noteWithLabel, "foo", true);
|
||||
await setBooleanWithInheritance(noteWithoutLabel, "foo", false);
|
||||
expect(server.put).not.toHaveBeenCalled();
|
||||
expect(server.remove).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("sets boolean normally without inheritance", async () => {
|
||||
const standaloneNote = buildNote({
|
||||
title: "New note"
|
||||
});
|
||||
|
||||
await setBooleanWithInheritance(standaloneNote, "foo", true);
|
||||
expect(server.put).toHaveBeenCalledWith(`notes/${standaloneNote.noteId}/set-attribute`, {
|
||||
type: "label",
|
||||
name: "foo",
|
||||
value: "",
|
||||
isInheritable: false
|
||||
});
|
||||
});
|
||||
|
||||
it("removes boolean normally without inheritance", async () => {
|
||||
const standaloneNote = buildNote({
|
||||
title: "New note",
|
||||
"#foo": ""
|
||||
});
|
||||
|
||||
const attributeId = standaloneNote.getLabel("foo")!.attributeId;
|
||||
await setBooleanWithInheritance(standaloneNote, "foo", false);
|
||||
expect(server.remove).toHaveBeenCalledWith(`notes/${standaloneNote.noteId}/attributes/${attributeId}`);
|
||||
});
|
||||
|
||||
it("doesn't call server if value matches inherited", async () => {
|
||||
const parentNote = buildNote({
|
||||
title: "Parent note",
|
||||
"#foo(inheritable)": "",
|
||||
"children": [
|
||||
{
|
||||
title: "Child note"
|
||||
}
|
||||
]
|
||||
});
|
||||
const childNote = froca.getNoteFromCache(parentNote.children[0])!;
|
||||
expect(childNote.isLabelTruthy("foo")).toBe(true);
|
||||
await setBooleanWithInheritance(childNote, "foo", true);
|
||||
expect(server.put).not.toHaveBeenCalled();
|
||||
expect(server.remove).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("overrides boolean with inheritance", async () => {
|
||||
const parentNote = buildNote({
|
||||
title: "Parent note",
|
||||
"#foo(inheritable)": "",
|
||||
"children": [
|
||||
{
|
||||
title: "Child note"
|
||||
}
|
||||
]
|
||||
});
|
||||
const childNote = froca.getNoteFromCache(parentNote.children[0])!;
|
||||
expect(childNote.isLabelTruthy("foo")).toBe(true);
|
||||
await setBooleanWithInheritance(childNote, "foo", false);
|
||||
expect(server.put).toHaveBeenCalledWith(`notes/${childNote.noteId}/set-attribute`, {
|
||||
type: "label",
|
||||
name: "foo",
|
||||
value: "false",
|
||||
isInheritable: false
|
||||
});
|
||||
});
|
||||
|
||||
it("overrides boolean with inherited false", async () => {
|
||||
const parentNote = buildNote({
|
||||
title: "Parent note",
|
||||
"#foo(inheritable)": "false",
|
||||
"children": [
|
||||
{
|
||||
title: "Child note"
|
||||
}
|
||||
]
|
||||
});
|
||||
const childNote = froca.getNoteFromCache(parentNote.children[0])!;
|
||||
expect(childNote.isLabelTruthy("foo")).toBe(false);
|
||||
await setBooleanWithInheritance(childNote, "foo", true);
|
||||
expect(server.put).toHaveBeenCalledWith(`notes/${childNote.noteId}/set-attribute`, {
|
||||
type: "label",
|
||||
name: "foo",
|
||||
value: "",
|
||||
isInheritable: false
|
||||
});
|
||||
});
|
||||
|
||||
it("deletes override boolean with inherited false with already existing value", async () => {
|
||||
const parentNote = buildNote({
|
||||
title: "Parent note",
|
||||
"#foo(inheritable)": "false",
|
||||
"children": [
|
||||
{
|
||||
title: "Child note",
|
||||
"#foo": "false",
|
||||
}
|
||||
]
|
||||
});
|
||||
const childNote = froca.getNoteFromCache(parentNote.children[0])!;
|
||||
expect(childNote.isLabelTruthy("foo")).toBe(false);
|
||||
await setBooleanWithInheritance(childNote, "foo", true);
|
||||
expect(server.put).toBeCalledWith(`notes/${childNote.noteId}/set-attribute`, {
|
||||
type: "label",
|
||||
name: "foo",
|
||||
value: "",
|
||||
isInheritable: false
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,14 +1,15 @@
|
||||
import server from "./server.js";
|
||||
import froca from "./froca.js";
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import type { AttributeRow } from "./load_results.js";
|
||||
import { AttributeType } from "@triliumnext/commons";
|
||||
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import froca from "./froca.js";
|
||||
import type { AttributeRow } from "./load_results.js";
|
||||
import server from "./server.js";
|
||||
|
||||
async function addLabel(noteId: string, name: string, value: string = "", isInheritable = false) {
|
||||
await server.put(`notes/${noteId}/attribute`, {
|
||||
type: "label",
|
||||
name: name,
|
||||
value: value,
|
||||
name,
|
||||
value,
|
||||
isInheritable
|
||||
});
|
||||
}
|
||||
@@ -16,8 +17,8 @@ async function addLabel(noteId: string, name: string, value: string = "", isInhe
|
||||
export async function setLabel(noteId: string, name: string, value: string = "", isInheritable = false) {
|
||||
await server.put(`notes/${noteId}/set-attribute`, {
|
||||
type: "label",
|
||||
name: name,
|
||||
value: value,
|
||||
name,
|
||||
value,
|
||||
isInheritable
|
||||
});
|
||||
}
|
||||
@@ -25,12 +26,42 @@ export async function setLabel(noteId: string, name: string, value: string = "",
|
||||
export async function setRelation(noteId: string, name: string, value: string = "", isInheritable = false) {
|
||||
await server.put(`notes/${noteId}/set-attribute`, {
|
||||
type: "relation",
|
||||
name: name,
|
||||
value: value,
|
||||
name,
|
||||
value,
|
||||
isInheritable
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a boolean label on the given note, taking inheritance into account. If the desired value matches the inherited
|
||||
* value, any owned label will be removed to allow the inherited value to take effect. If the desired value differs
|
||||
* from the inherited value, an owned label will be created or updated to reflect the desired value.
|
||||
*
|
||||
* When checking if the boolean value is set, don't use `note.hasLabel`; instead use `note.isLabelTruthy`.
|
||||
*
|
||||
* @param note the note on which to set the boolean label.
|
||||
* @param labelName the name of the label to set.
|
||||
* @param value the boolean value to set for the label.
|
||||
*/
|
||||
export async function setBooleanWithInheritance(note: FNote, labelName: string, value: boolean) {
|
||||
const actualValue = note.isLabelTruthy(labelName);
|
||||
if (actualValue === value) return;
|
||||
const hasInheritedValue = !note.hasOwnedLabel(labelName) && note.hasLabel(labelName);
|
||||
|
||||
if (hasInheritedValue) {
|
||||
if (value) {
|
||||
setLabel(note.noteId, labelName, "");
|
||||
} else {
|
||||
// Label is inherited - override to false.
|
||||
setLabel(note.noteId, labelName, "false");
|
||||
}
|
||||
} else if (value) {
|
||||
setLabel(note.noteId, labelName, "");
|
||||
} else {
|
||||
removeOwnedLabelByName(note, labelName);
|
||||
}
|
||||
}
|
||||
|
||||
async function removeAttributeById(noteId: string, attributeId: string) {
|
||||
await server.remove(`notes/${noteId}/attributes/${attributeId}`);
|
||||
}
|
||||
@@ -142,6 +173,7 @@ export default {
|
||||
setLabel,
|
||||
setRelation,
|
||||
setAttribute,
|
||||
setBooleanWithInheritance,
|
||||
removeAttributeById,
|
||||
removeOwnedLabelByName,
|
||||
removeOwnedRelationByName,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import utils from "./utils.js";
|
||||
import server from "./server.js";
|
||||
import toastService, { type ToastOptionsWithRequiredId } from "./toast.js";
|
||||
import appContext from "../components/app_context.js";
|
||||
import type { ResolveOptions } from "../widgets/dialogs/delete_notes.js";
|
||||
import froca from "./froca.js";
|
||||
import hoistedNoteService from "./hoisted_note.js";
|
||||
import ws from "./ws.js";
|
||||
import appContext from "../components/app_context.js";
|
||||
import { t } from "./i18n.js";
|
||||
import type { ResolveOptions } from "../widgets/dialogs/delete_notes.js";
|
||||
import server from "./server.js";
|
||||
import toastService, { type ToastOptionsWithRequiredId } from "./toast.js";
|
||||
import utils from "./utils.js";
|
||||
import ws from "./ws.js";
|
||||
|
||||
// TODO: Deduplicate type with server
|
||||
interface Response {
|
||||
@@ -66,7 +66,7 @@ async function moveAfterBranch(branchIdsToMove: string[], afterBranchId: string)
|
||||
}
|
||||
}
|
||||
|
||||
async function moveToParentNote(branchIdsToMove: string[], newParentBranchId: string) {
|
||||
async function moveToParentNote(branchIdsToMove: string[], newParentBranchId: string, componentId?: string) {
|
||||
const newParentBranch = froca.getBranch(newParentBranchId);
|
||||
if (!newParentBranch) {
|
||||
return;
|
||||
@@ -86,7 +86,7 @@ async function moveToParentNote(branchIdsToMove: string[], newParentBranchId: st
|
||||
continue;
|
||||
}
|
||||
|
||||
const resp = await server.put<Response>(`branches/${branchIdToMove}/move-to/${newParentBranchId}`);
|
||||
const resp = await server.put<Response>(`branches/${branchIdToMove}/move-to/${newParentBranchId}`, undefined, componentId);
|
||||
|
||||
if (!resp.success) {
|
||||
toastService.showError(resp.message);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -22,6 +23,12 @@ export interface RenderOptions {
|
||||
imageHasZoom?: boolean;
|
||||
/** If enabled, it will prevent the default behavior in which an empty note would display a list of children. */
|
||||
noChildrenList?: boolean;
|
||||
/** If enabled, it will prevent rendering of included notes. */
|
||||
noIncludedNotes?: boolean;
|
||||
/** If enabled, it will include archived notes when rendering children list. */
|
||||
includeArchivedNotes?: boolean;
|
||||
/** Set of note IDs that have already been seen during rendering to prevent infinite recursion. */
|
||||
seenNoteIds?: Set<string>;
|
||||
}
|
||||
|
||||
const CODE_MIME_TYPES = new Set(["application/json"]);
|
||||
@@ -152,7 +159,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 +200,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 +224,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 +273,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) {
|
||||
|
||||
132
apps/client/src/services/content_renderer_text.spec.ts
Normal file
132
apps/client/src/services/content_renderer_text.spec.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import { trimIndentation } from "@triliumnext/commons";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { buildNote } from "../test/easy-froca";
|
||||
import renderText from "./content_renderer_text";
|
||||
|
||||
describe("Text content renderer", () => {
|
||||
it("renders included note", async () => {
|
||||
const contentEl = document.createElement("div");
|
||||
const includedNote = buildNote({
|
||||
title: "Included note",
|
||||
content: "<p>This is the included note.</p>"
|
||||
});
|
||||
const note = buildNote({
|
||||
title: "New note",
|
||||
content: trimIndentation`
|
||||
<p>
|
||||
Hi there
|
||||
</p>
|
||||
<section class="include-note" data-note-id="${includedNote.noteId}" data-box-size="medium">
|
||||
|
||||
</section>
|
||||
`
|
||||
});
|
||||
await renderText(note, $(contentEl));
|
||||
expect(contentEl.querySelectorAll("section.include-note").length).toBe(1);
|
||||
expect(contentEl.querySelectorAll("section.include-note p").length).toBe(1);
|
||||
});
|
||||
|
||||
it("skips rendering included note", async () => {
|
||||
const contentEl = document.createElement("div");
|
||||
const includedNote = buildNote({
|
||||
title: "Included note",
|
||||
content: "<p>This is the included note.</p>"
|
||||
});
|
||||
const note = buildNote({
|
||||
title: "New note",
|
||||
content: trimIndentation`
|
||||
<p>
|
||||
Hi there
|
||||
</p>
|
||||
<section class="include-note" data-note-id="${includedNote.noteId}" data-box-size="medium">
|
||||
|
||||
</section>
|
||||
`
|
||||
});
|
||||
await renderText(note, $(contentEl), { noIncludedNotes: true });
|
||||
expect(contentEl.querySelectorAll("section.include-note").length).toBe(0);
|
||||
});
|
||||
|
||||
it("doesn't enter infinite loop on direct recursion", async () => {
|
||||
const contentEl = document.createElement("div");
|
||||
const note = buildNote({
|
||||
title: "New note",
|
||||
id: "Y7mBwmRjQyb4",
|
||||
content: trimIndentation`
|
||||
<p>
|
||||
Hi there
|
||||
</p>
|
||||
<section class="include-note" data-note-id="Y7mBwmRjQyb4" data-box-size="medium">
|
||||
|
||||
</section>
|
||||
<section class="include-note" data-note-id="Y7mBwmRjQyb4" data-box-size="medium">
|
||||
|
||||
</section>
|
||||
`
|
||||
});
|
||||
await renderText(note, $(contentEl));
|
||||
expect(contentEl.querySelectorAll("section.include-note").length).toBe(0);
|
||||
});
|
||||
|
||||
it("doesn't enter infinite loop on indirect recursion", async () => {
|
||||
const contentEl = document.createElement("div");
|
||||
buildNote({
|
||||
id: "first",
|
||||
title: "Included note",
|
||||
content: trimIndentation`\
|
||||
<p>This is the included note.</p>
|
||||
<section class="include-note" data-note-id="second" data-box-size="medium">
|
||||
|
||||
</section>
|
||||
`
|
||||
});
|
||||
const note = buildNote({
|
||||
id: "second",
|
||||
title: "New note",
|
||||
content: trimIndentation`
|
||||
<p>
|
||||
Hi there
|
||||
</p>
|
||||
<section class="include-note" data-note-id="first" data-box-size="medium">
|
||||
|
||||
</section>
|
||||
`
|
||||
});
|
||||
await renderText(note, $(contentEl));
|
||||
expect(contentEl.querySelectorAll("section.include-note").length).toBe(1);
|
||||
});
|
||||
|
||||
it("renders children list when note is empty", async () => {
|
||||
const contentEl = document.createElement("div");
|
||||
const parentNote = buildNote({
|
||||
title: "Parent note",
|
||||
children: [
|
||||
{ title: "Child note 1" },
|
||||
{ title: "Child note 2" }
|
||||
]
|
||||
});
|
||||
await renderText(parentNote, $(contentEl));
|
||||
const items = contentEl.querySelectorAll("a");
|
||||
expect(items.length).toBe(2);
|
||||
expect(items[0].textContent).toBe("Child note 1");
|
||||
expect(items[1].textContent).toBe("Child note 2");
|
||||
});
|
||||
|
||||
it("skips archived notes in children list", async () => {
|
||||
const contentEl = document.createElement("div");
|
||||
const parentNote = buildNote({
|
||||
title: "Parent note",
|
||||
children: [
|
||||
{ title: "Child note 1" },
|
||||
{ title: "Child note 2", "#archived": "" },
|
||||
{ title: "Child note 3" }
|
||||
]
|
||||
});
|
||||
await renderText(parentNote, $(contentEl));
|
||||
const items = contentEl.querySelectorAll("a");
|
||||
expect(items.length).toBe(2);
|
||||
expect(items[0].textContent).toBe("Child note 1");
|
||||
expect(items[1].textContent).toBe("Child note 3");
|
||||
});
|
||||
});
|
||||
@@ -15,7 +15,14 @@ export default async function renderText(note: FNote | FAttachment, $renderedCon
|
||||
|
||||
if (blob && !isHtmlEmpty(blob.content)) {
|
||||
$renderedContent.append($('<div class="ck-content">').html(blob.content));
|
||||
await renderIncludedNotes($renderedContent[0]);
|
||||
|
||||
const seenNoteIds = options.seenNoteIds ?? new Set<string>();
|
||||
seenNoteIds.add("noteId" in note ? note.noteId : note.attachmentId);
|
||||
if (!options.noIncludedNotes) {
|
||||
await renderIncludedNotes($renderedContent[0], seenNoteIds);
|
||||
} else {
|
||||
$renderedContent.find("section.include-note").remove();
|
||||
}
|
||||
|
||||
if ($renderedContent.find("span.math-tex").length > 0) {
|
||||
renderMathInElement($renderedContent[0], { trust: true });
|
||||
@@ -35,11 +42,11 @@ export default async function renderText(note: FNote | FAttachment, $renderedCon
|
||||
await rewriteMermaidDiagramsInContainer($renderedContent[0] as HTMLDivElement);
|
||||
await formatCodeBlocks($renderedContent);
|
||||
} else if (note instanceof FNote && !options.noChildrenList) {
|
||||
await renderChildrenList($renderedContent, note);
|
||||
await renderChildrenList($renderedContent, note, options.includeArchivedNotes ?? false);
|
||||
}
|
||||
}
|
||||
|
||||
async function renderIncludedNotes(contentEl: HTMLElement) {
|
||||
async function renderIncludedNotes(contentEl: HTMLElement, seenNoteIds: Set<string>) {
|
||||
// TODO: Consider duplicating with server's share/content_renderer.ts.
|
||||
const includeNoteEls = contentEl.querySelectorAll("section.include-note");
|
||||
|
||||
@@ -66,7 +73,15 @@ async function renderIncludedNotes(contentEl: HTMLElement) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const renderedContent = (await content_renderer.getRenderedContent(note)).$renderedContent;
|
||||
if (seenNoteIds.has(noteId)) {
|
||||
console.warn(`Skipping inclusion of ${noteId} to avoid circular reference.`);
|
||||
includeNoteEl.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
const renderedContent = (await content_renderer.getRenderedContent(note, {
|
||||
seenNoteIds
|
||||
})).$renderedContent;
|
||||
includeNoteEl.replaceChildren(...renderedContent);
|
||||
}
|
||||
}
|
||||
@@ -98,7 +113,7 @@ export async function applyInlineMermaid(container: HTMLDivElement) {
|
||||
}
|
||||
}
|
||||
|
||||
async function renderChildrenList($renderedContent: JQuery<HTMLElement>, note: FNote) {
|
||||
async function renderChildrenList($renderedContent: JQuery<HTMLElement>, note: FNote, includeArchivedNotes: boolean) {
|
||||
let childNoteIds = note.getChildNoteIds();
|
||||
|
||||
if (!childNoteIds.length) {
|
||||
@@ -108,14 +123,16 @@ async function renderChildrenList($renderedContent: JQuery<HTMLElement>, note: F
|
||||
$renderedContent.css("padding", "10px");
|
||||
$renderedContent.addClass("text-with-ellipsis");
|
||||
|
||||
// just load the first 10 child notes
|
||||
if (childNoteIds.length > 10) {
|
||||
childNoteIds = childNoteIds.slice(0, 10);
|
||||
}
|
||||
|
||||
// just load the first 10 child notes
|
||||
const childNotes = await froca.getNotes(childNoteIds);
|
||||
|
||||
for (const childNote of childNotes) {
|
||||
if (childNote.isArchived && !includeArchivedNotes) continue;
|
||||
|
||||
$renderedContent.append(
|
||||
await link.createLink(`${note.noteId}/${childNote.noteId}`, {
|
||||
showTooltip: false,
|
||||
|
||||
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,7 +28,7 @@ function createClassForColor(colorString: string | null) {
|
||||
|
||||
if (!registeredClasses.has(className)) {
|
||||
const adjustedColor = adjustColorLightness(color, lightThemeColorMaxLightness!,
|
||||
darkThemeColorMinLightness!);
|
||||
darkThemeColorMinLightness!);
|
||||
const hue = getHue(color);
|
||||
|
||||
$("head").append(`<style>
|
||||
@@ -50,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);
|
||||
}
|
||||
@@ -84,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,4 +1,5 @@
|
||||
import type { AttachmentRow, EtapiTokenRow, NoteType, OptionNames } from "@triliumnext/commons";
|
||||
|
||||
import type { AttributeType } from "../entities/fattribute.js";
|
||||
import type { EntityChange } from "../server_types.js";
|
||||
|
||||
@@ -135,7 +136,14 @@ export default class LoadResults {
|
||||
}
|
||||
|
||||
getBranchRows() {
|
||||
return this.branchRows.map((row) => this.getEntityRow("branches", row.branchId)).filter((branch) => !!branch);
|
||||
return this.branchRows.map((row) => {
|
||||
const branch = this.getEntityRow("branches", row.branchId);
|
||||
if (branch) {
|
||||
// Merge the componentId from the tracked row with the entity data
|
||||
return { ...branch, componentId: row.componentId };
|
||||
}
|
||||
return null;
|
||||
}).filter((branch) => !!branch) as BranchRow[];
|
||||
}
|
||||
|
||||
addNoteReordering(parentNoteId: string, componentId: string) {
|
||||
@@ -153,7 +161,14 @@ export default class LoadResults {
|
||||
getAttributeRows(componentId = "none"): AttributeRow[] {
|
||||
return this.attributeRows
|
||||
.filter((row) => row.componentId !== componentId)
|
||||
.map((row) => this.getEntityRow("attributes", row.attributeId))
|
||||
.map((row) => {
|
||||
const attr = this.getEntityRow("attributes", row.attributeId);
|
||||
if (attr) {
|
||||
// Merge the componentId from the tracked row with the entity data
|
||||
return { ...attr, componentId: row.componentId };
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter((attr) => !!attr) as AttributeRow[];
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -100,6 +100,20 @@ describe("shortcuts", () => {
|
||||
expect(consoleSpy).toHaveBeenCalled();
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
|
||||
it("should match letter keys using code when key is a special character (macOS Alt behavior)", () => {
|
||||
// On macOS, pressing Option/Alt + A produces 'å' as the key, but code is still 'KeyA'
|
||||
const macOSAltAEvent = createKeyboardEvent("å", "KeyA");
|
||||
expect(keyMatches(macOSAltAEvent, "a")).toBe(true);
|
||||
|
||||
// Option + H produces '˙'
|
||||
const macOSAltHEvent = createKeyboardEvent("˙", "KeyH");
|
||||
expect(keyMatches(macOSAltHEvent, "h")).toBe(true);
|
||||
|
||||
// Option + S produces 'ß'
|
||||
const macOSAltSEvent = createKeyboardEvent("ß", "KeyS");
|
||||
expect(keyMatches(macOSAltSEvent, "s")).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("matchesShortcut", () => {
|
||||
@@ -200,6 +214,33 @@ describe("shortcuts", () => {
|
||||
expect(consoleSpy).toHaveBeenCalled();
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
|
||||
it("should match Alt+letter shortcuts on macOS where key is a special character", () => {
|
||||
// On macOS, pressing Option/Alt + A produces 'å' but code remains 'KeyA'
|
||||
const macOSAltAEvent = createKeyboardEvent({
|
||||
key: "å",
|
||||
code: "KeyA",
|
||||
altKey: true
|
||||
});
|
||||
expect(matchesShortcut(macOSAltAEvent, "alt+a")).toBe(true);
|
||||
|
||||
// Option/Alt + H produces '˙'
|
||||
const macOSAltHEvent = createKeyboardEvent({
|
||||
key: "˙",
|
||||
code: "KeyH",
|
||||
altKey: true
|
||||
});
|
||||
expect(matchesShortcut(macOSAltHEvent, "alt+h")).toBe(true);
|
||||
|
||||
// Combined with Ctrl: Ctrl+Alt+S where Alt produces 'ß'
|
||||
const macOSCtrlAltSEvent = createKeyboardEvent({
|
||||
key: "ß",
|
||||
code: "KeyS",
|
||||
ctrlKey: true,
|
||||
altKey: true
|
||||
});
|
||||
expect(matchesShortcut(macOSCtrlAltSEvent, "ctrl+alt+s")).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("bindGlobalShortcut", () => {
|
||||
|
||||
@@ -110,8 +110,9 @@ function bindElShortcut($el: JQuery<ElementType | Element>, keyboardShortcut: st
|
||||
}
|
||||
};
|
||||
|
||||
// Add the event listener
|
||||
element.addEventListener('keydown', listener);
|
||||
// Add the event listener in capture phase to intercept events before they reach
|
||||
// child elements like CodeMirror
|
||||
element.addEventListener('keydown', listener, true);
|
||||
|
||||
// Store the binding for later cleanup
|
||||
const binding: ShortcutBinding = {
|
||||
@@ -138,15 +139,16 @@ export function removeIndividualBinding(binding: ShortcutBinding) {
|
||||
if (activeBindingsInNamespace) {
|
||||
activeBindings.set(key, activeBindingsInNamespace.filter(aBinding => aBinding.handler === binding.handler));
|
||||
}
|
||||
binding.element.removeEventListener("keydown", binding.listener);
|
||||
// Remove listener with capture phase to match how it was added
|
||||
binding.element.removeEventListener("keydown", binding.listener, true);
|
||||
}
|
||||
|
||||
function removeNamespaceBindings(namespace: string) {
|
||||
const bindings = activeBindings.get(namespace);
|
||||
if (bindings) {
|
||||
// Remove all event listeners for this namespace
|
||||
bindings.forEach(binding => {
|
||||
binding.element.removeEventListener('keydown', binding.listener);
|
||||
// Remove listener with capture phase to match how it was added
|
||||
binding.element.removeEventListener('keydown', binding.listener, true);
|
||||
});
|
||||
activeBindings.delete(namespace);
|
||||
}
|
||||
@@ -213,8 +215,11 @@ export function keyMatches(e: KeyboardEvent, key: string): boolean {
|
||||
}
|
||||
|
||||
// For letter keys, use the physical key code for consistency
|
||||
// On macOS, Option/Alt key produces special characters, so we must use e.code
|
||||
if (key.length === 1 && key >= 'a' && key <= 'z') {
|
||||
return e.key.toLowerCase() === key.toLowerCase();
|
||||
// e.code is like "KeyA", "KeyB", etc.
|
||||
const expectedCode = `Key${key.toUpperCase()}`;
|
||||
return e.code === expectedCode || e.key.toLowerCase() === key.toLowerCase();
|
||||
}
|
||||
|
||||
// For regular keys, check both key and code as fallback
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -3,7 +3,7 @@ import { signal } from "@preact/signals";
|
||||
import appContext from "../components/app_context.js";
|
||||
import froca from "./froca.js";
|
||||
import { t } from "./i18n.js";
|
||||
import utils from "./utils.js";
|
||||
import utils, { randomString } from "./utils.js";
|
||||
|
||||
export interface ToastOptions {
|
||||
id?: string;
|
||||
@@ -86,7 +86,7 @@ export async function showErrorForScriptNote(noteId: string, message: string) {
|
||||
export const toasts = signal<ToastOptionsWithRequiredId[]>([]);
|
||||
|
||||
function addToast(opts: ToastOptions) {
|
||||
const id = opts.id ?? crypto.randomUUID();
|
||||
const id = opts.id ?? randomString();
|
||||
const toast = { ...opts, id };
|
||||
toasts.value = [ ...toasts.value, toast ];
|
||||
return id;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { dayjs } from "@triliumnext/commons";
|
||||
import type { ViewMode, ViewScope } from "./link.js";
|
||||
import FNote from "../entities/fnote";
|
||||
import { snapdom } from "@zumer/snapdom";
|
||||
|
||||
import FNote from "../entities/fnote";
|
||||
import type { ViewMode, ViewScope } from "./link.js";
|
||||
|
||||
const SVG_MIME = "image/svg+xml";
|
||||
|
||||
export const isShare = !window.glob;
|
||||
@@ -113,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() {
|
||||
@@ -187,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]) {
|
||||
@@ -208,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";
|
||||
|
||||
@@ -297,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]);
|
||||
@@ -318,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;
|
||||
@@ -364,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) {
|
||||
@@ -509,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;
|
||||
@@ -695,9 +695,9 @@ async function downloadAsSvg(nameWithoutExtension: string, svgSource: string | S
|
||||
|
||||
try {
|
||||
const result = await snapdom(element, {
|
||||
backgroundColor: "transparent",
|
||||
scale: 2
|
||||
});
|
||||
backgroundColor: "transparent",
|
||||
scale: 2
|
||||
});
|
||||
triggerDownload(`${nameWithoutExtension}.svg`, result.url);
|
||||
} finally {
|
||||
cleanup();
|
||||
@@ -733,9 +733,9 @@ async function downloadAsPng(nameWithoutExtension: string, svgSource: string | S
|
||||
|
||||
try {
|
||||
const result = await snapdom(element, {
|
||||
backgroundColor: "transparent",
|
||||
scale: 2
|
||||
});
|
||||
backgroundColor: "transparent",
|
||||
scale: 2
|
||||
});
|
||||
const pngImg = await result.toPng();
|
||||
await triggerDownload(`${nameWithoutExtension}.png`, pngImg.src);
|
||||
} finally {
|
||||
@@ -763,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;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -896,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";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
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);
|
||||
@@ -436,7 +438,6 @@ body.desktop .tabulator-popup-container,
|
||||
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 {
|
||||
@@ -1129,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 */
|
||||
}
|
||||
@@ -1800,7 +1796,7 @@ button.close:hover {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.reference-link .bx {
|
||||
.reference-link .tn-icon {
|
||||
position: relative;
|
||||
top: 1px;
|
||||
margin-inline-end: 3px;
|
||||
@@ -1952,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;
|
||||
@@ -1961,7 +1961,7 @@ body.electron.platform-darwin:not(.native-titlebar):not(.full-screen) #tab-row-l
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.tab-row-container {
|
||||
body.electron:not(.platform-darwin) .tab-row-container {
|
||||
padding-inline-end: calc(100vw - env(titlebar-area-width, 100vw));
|
||||
}
|
||||
|
||||
@@ -2415,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;
|
||||
}
|
||||
|
||||
@@ -2543,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 */
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
--row-moving-background-color: var(--accented-background-color);
|
||||
--row-text-color: var(--main-text-color);
|
||||
--row-delimiter-color: var(--more-accented-background-color);
|
||||
|
||||
|
||||
--cell-horiz-padding-size: 8px;
|
||||
--cell-vert-padding-size: 8px;
|
||||
|
||||
|
||||
--cell-editable-hover-outline-color: var(--main-border-color);
|
||||
--cell-read-only-text-color: var(--muted-text-color);
|
||||
|
||||
|
||||
--cell-editing-border-color: var(--main-border-color);
|
||||
--cell-editing-border-width: 2px;
|
||||
--cell-editing-background-color: var(--ck-color-selector-focused-cell-background);
|
||||
@@ -40,10 +40,42 @@
|
||||
border-bottom: var(--col-header-bottom-border);
|
||||
background: var(--col-header-background-color);
|
||||
color: var(--col-header-text-color);
|
||||
}
|
||||
font-weight: normal;
|
||||
|
||||
.tabulator .tabulator-col-content {
|
||||
padding: 8px 4px !important;
|
||||
.tabulator-col.tabulator-range-highlight {
|
||||
background: inherit;
|
||||
color: inherit;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tabulator-col-content {
|
||||
padding: 0 !important;
|
||||
|
||||
.tabulator-col-title-holder {
|
||||
padding: 8px 4px;
|
||||
}
|
||||
|
||||
&:has(.tabulator-header-filter) {
|
||||
.tabulator-col-title-holder {
|
||||
padding: 4px;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.tabulator-header-filter {
|
||||
background: var(--main-background-color);
|
||||
padding: 2px 1px;
|
||||
|
||||
input {
|
||||
background: var(--main-background-color);
|
||||
color: var(--main-text-color);
|
||||
border: 1px solid var(--button-border-color);
|
||||
border-radius: 3px;
|
||||
outline: none;
|
||||
padding: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (hover: hover) and (pointer: fine) {
|
||||
@@ -80,7 +112,6 @@
|
||||
|
||||
.tabulator-tableholder {
|
||||
padding-top: 10px;
|
||||
height: unset !important; /* Don't extend on the full height */
|
||||
}
|
||||
|
||||
/* Rows */
|
||||
@@ -99,6 +130,14 @@
|
||||
border-top: none;
|
||||
border-bottom: 1px solid var(--row-delimiter-color);
|
||||
color: var(--row-text-color);
|
||||
|
||||
&:last-of-type {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&.tabulator-range-highlight > .tabulator-cell.tabulator-frozen {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.tabulator-row.tabulator-row-odd {
|
||||
@@ -120,11 +159,14 @@
|
||||
margin-inline-end: var(--cell-editing-border-width);
|
||||
}
|
||||
|
||||
.tabulator-row .tabulator-cell.tabulator-frozen.tabulator-frozen-left,
|
||||
.tabulator-row .tabulator-cell {
|
||||
border-inline-end-color: transparent;
|
||||
}
|
||||
|
||||
.tabulator-row .tabulator-cell.tabulator-frozen.tabulator-frozen-left {
|
||||
border-inline-end-color: var(--main-border-color);
|
||||
}
|
||||
|
||||
.tabulator-row .tabulator-cell:not(.tabulator-editable) {
|
||||
color: var(--cell-read-only-text-color);
|
||||
}
|
||||
@@ -174,10 +216,6 @@
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tabulator .tabulator-footer {
|
||||
color: var(--main-text-color);
|
||||
}
|
||||
|
||||
/* Context menus */
|
||||
|
||||
.tabulator-popup-container {
|
||||
@@ -192,8 +230,27 @@
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
|
||||
:root .tabulator .tabulator-footer {
|
||||
border-top: unset;
|
||||
background: transparent;
|
||||
color: var(--main-text-color);
|
||||
border-top: 1px solid var(--main-border-color);
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.tabulator-page {
|
||||
background: var(--button-background-color);
|
||||
color: var(--button-text-color);
|
||||
border: 1px solid var(--button-border-color);
|
||||
border-radius: var(--button-border-radius);
|
||||
|
||||
&:hover {
|
||||
border-color: var(--hover-item-border-color);
|
||||
color: var(--button-text-color);
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
background: var(--button-background-color);
|
||||
color: var(--input-text-color);
|
||||
border: 1px solid var(--button-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,5 +349,5 @@ body .todo-list input[type="checkbox"]:not(:checked):before {
|
||||
|
||||
.note-split.with-hue *::selection,
|
||||
.quick-edit-dialog-wrapper.with-hue *::selection {
|
||||
background: hsl(var(--custom-color-hue), 49.2%, 35%);
|
||||
--selection-background-color: hsl(var(--custom-color-hue), 49.2%, 35%);
|
||||
}
|
||||
@@ -320,5 +320,5 @@
|
||||
|
||||
.note-split.with-hue *::selection,
|
||||
.quick-edit-dialog-wrapper.with-hue *::selection {
|
||||
background: hsl(var(--custom-color-hue), 60%, 90%);
|
||||
--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;
|
||||
@@ -134,7 +136,7 @@ body.backdrop-effects-disabled {
|
||||
white-space-collapse: discard;
|
||||
}
|
||||
|
||||
.dropdown-menu.tn-dropdown-menu .bx {
|
||||
.dropdown-menu.tn-dropdown-menu .dropdown-item .tn-icon {
|
||||
margin-inline-end: 6px;
|
||||
}
|
||||
|
||||
@@ -249,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;
|
||||
@@ -496,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;
|
||||
}
|
||||
|
||||
@@ -557,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;
|
||||
}
|
||||
@@ -754,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,10 +62,10 @@ button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel, .c
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
@@ -634,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;
|
||||
|
||||
@@ -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);
|
||||
@@ -185,10 +190,6 @@ body.experimental-feature-new-layout .note-detail-content-widget-content.options
|
||||
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);
|
||||
|
||||
@@ -497,7 +497,7 @@ 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;
|
||||
}
|
||||
@@ -767,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;
|
||||
}
|
||||
|
||||
@@ -1259,8 +1259,16 @@ body.layout-horizontal #rest-pane > .classic-toolbar-widget {
|
||||
#center-pane .note-split {
|
||||
padding-top: 2px;
|
||||
background-color: var(--note-split-background-color, var(--main-background-color));
|
||||
transition: border-color 250ms ease-in;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -148,29 +148,28 @@ 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 */
|
||||
}
|
||||
|
||||
body.experimental-feature-new-layout span.fancytree-node.multiple-parents .fancytree-title::after {
|
||||
content: " \ed82";
|
||||
.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.shared .fancytree-title::after {
|
||||
font-family: "boxicons" !important;
|
||||
font-size: smaller;
|
||||
content: " \ec03"; /* lookup code for "share-alt" in boxicons.css */
|
||||
}
|
||||
|
||||
span.fancytree-node.fancytree-active-clone:not(.fancytree-active) .fancytree-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -229,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;
|
||||
@@ -243,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 */
|
||||
}
|
||||
|
||||
@@ -69,24 +69,6 @@ export function buildNote(noteDef: NoteDefinition) {
|
||||
});
|
||||
note.getBlob = async () => blob;
|
||||
|
||||
// Manage children.
|
||||
if (noteDef.children) {
|
||||
for (const childDef of noteDef.children) {
|
||||
const childNote = buildNote(childDef);
|
||||
const branchId = `${note.noteId}_${childNote.noteId}`;
|
||||
const branch = new FBranch(froca, {
|
||||
branchId,
|
||||
noteId: childNote.noteId,
|
||||
parentNoteId: note.noteId,
|
||||
notePosition: childNotePosition,
|
||||
fromSearchNote: false
|
||||
});
|
||||
froca.branches[branchId] = branch;
|
||||
note.addChild(childNote.noteId, branchId, false);
|
||||
childNotePosition += 10;
|
||||
}
|
||||
}
|
||||
|
||||
let position = 0;
|
||||
for (const [ key, value ] of Object.entries(noteDef)) {
|
||||
const attributeId = utils.randomString(12);
|
||||
@@ -136,5 +118,25 @@ export function buildNote(noteDef: NoteDefinition) {
|
||||
}
|
||||
noteAttributeCache.attributes[note.noteId].push(attribute);
|
||||
}
|
||||
|
||||
// Manage children.
|
||||
if (noteDef.children) {
|
||||
for (const childDef of noteDef.children) {
|
||||
const childNote = buildNote(childDef);
|
||||
const branchId = `${note.noteId}_${childNote.noteId}`;
|
||||
const branch = new FBranch(froca, {
|
||||
branchId,
|
||||
noteId: childNote.noteId,
|
||||
parentNoteId: note.noteId,
|
||||
notePosition: childNotePosition,
|
||||
fromSearchNote: false
|
||||
});
|
||||
froca.branches[branchId] = branch;
|
||||
note.addChild(childNote.noteId, branchId, false);
|
||||
childNote.addParent(note.noteId, branchId, false);
|
||||
childNotePosition += 10;
|
||||
}
|
||||
}
|
||||
|
||||
return note;
|
||||
}
|
||||
|
||||
@@ -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": "عرض المحتوى",
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"widget-render-error": {
|
||||
"title": "渲染自定义 React 小部件失败"
|
||||
},
|
||||
"widget-missing-parent": "自定义小部件未定义强制性的 \"{{property}}\" 属性。",
|
||||
"widget-missing-parent": "自定义小部件未定义强制性的 \"{{property}}\" 属性。\n\n如果此脚本需要在没有 UI 元素的情况下运行,请改用“#run=frontendStartup”。",
|
||||
"open-script-note": "打开脚本笔记",
|
||||
"scripting-error": "自定义脚本错误:{{title}}"
|
||||
},
|
||||
@@ -290,7 +290,6 @@
|
||||
"download_button": "下载",
|
||||
"mime": "MIME 类型: ",
|
||||
"file_size": "文件大小:",
|
||||
"preview": "预览:",
|
||||
"preview_not_available": "无法预览此类型的笔记。",
|
||||
"diff_on": "显示差异",
|
||||
"diff_off": "显示内容",
|
||||
@@ -764,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": "笔记类型",
|
||||
@@ -793,7 +798,8 @@
|
||||
"expand_tooltip": "展开此集合的直接子代(单层深度)。点击右方箭头以查看更多选项。",
|
||||
"expand_first_level": "展开直接子代",
|
||||
"expand_nth_level": "展开 {{depth}} 层",
|
||||
"expand_all_levels": "展开所有层级"
|
||||
"expand_all_levels": "展开所有层级",
|
||||
"hide_child_notes": "隐藏树中的子笔记"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "今天还没有编辑过的笔记...",
|
||||
@@ -1446,7 +1452,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}}'。"
|
||||
},
|
||||
@@ -1500,7 +1506,10 @@
|
||||
"duplicate": "复制",
|
||||
"open-in-popup": "快速编辑",
|
||||
"archive": "归档",
|
||||
"unarchive": "解压"
|
||||
"unarchive": "解压",
|
||||
"open-in-a-new-window": "在新窗口中打开",
|
||||
"hide-subtree": "隐藏子树",
|
||||
"show-subtree": "显示子树"
|
||||
},
|
||||
"shared_info": {
|
||||
"help_link": "访问 <a href=\"https://triliumnext.github.io/Docs/Wiki/sharing.html\">wiki</a> 获取帮助。",
|
||||
@@ -1589,7 +1598,15 @@
|
||||
"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}})",
|
||||
"subtree-hidden-tooltip_other": "从树中隐藏的 {{count}} 篇子笔记",
|
||||
"subtree-hidden-moved-title": "已添加到 {{title}}",
|
||||
"subtree-hidden-moved-description-collection": "此集合隐藏其树中的子笔记。",
|
||||
"subtree-hidden-moved-description-other": "子笔记隐藏于此笔记的树中。"
|
||||
},
|
||||
"title_bar_buttons": {
|
||||
"window-on-top": "保持此窗口置顶"
|
||||
@@ -1597,7 +1614,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": "忽略的笔记"
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "请输入笔记标题...",
|
||||
@@ -2183,7 +2204,14 @@
|
||||
"execute_sql_description": "这是一篇 SQL 笔记。点击即可执行 SQL 查询。",
|
||||
"shared_copy_to_clipboard": "复制链接到剪贴板",
|
||||
"shared_open_in_browser": "在浏览器中打开链接",
|
||||
"shared_unshare": "取消共享"
|
||||
"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": "更改内容语言",
|
||||
@@ -2214,5 +2242,12 @@
|
||||
},
|
||||
"attributes_panel": {
|
||||
"title": "笔记属性"
|
||||
},
|
||||
"pdf": {
|
||||
"attachments_other": "{{count}} 个附件",
|
||||
"pages_other": "共{{count}}页",
|
||||
"pages_alt": "第{{pageNumber}}页",
|
||||
"pages_loading": "加载中...",
|
||||
"layers_other": "{{count}} 层"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"about": {
|
||||
"title": "Über Trilium Notes",
|
||||
"title": "Über Trilium Notizen",
|
||||
"homepage": "Startseite:",
|
||||
"app_version": "App-Version:",
|
||||
"db_version": "DB-Version:",
|
||||
@@ -21,8 +21,17 @@
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"open-script-note": "Script-Notiz öffnen",
|
||||
"widget-render-error": {
|
||||
"title": "Eine externe React Integration konnte nicht dargestellt werden"
|
||||
},
|
||||
"widget-missing-parent": "Der externen Integration fehlt die erforderliche Eigenschaft '{{property}}'\n\nFalls dieses Skript ohne UI-Element ausgeführt werden soll, benutze stattdessen '#run=frontendStartup'.",
|
||||
"scripting-error": "Benutzerdefinierter Skriptfehler: {{title}}"
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "Link hinzufügen",
|
||||
@@ -205,7 +214,8 @@
|
||||
"info": {
|
||||
"modalTitle": "Infonachricht",
|
||||
"closeButton": "Schließen",
|
||||
"okButton": "OK"
|
||||
"okButton": "OK",
|
||||
"copy_to_clipboard": "In Zwischenablage kopieren"
|
||||
},
|
||||
"jump_to_note": {
|
||||
"search_button": "Suche im Volltext",
|
||||
@@ -278,7 +288,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",
|
||||
@@ -689,7 +698,13 @@
|
||||
"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",
|
||||
"view_revisions": "Änderungshistorie...",
|
||||
"advanced": "Fortgeschritten"
|
||||
},
|
||||
"onclick_button": {
|
||||
"no_click_handler": "Das Schaltflächen-Widget „{{componentId}}“ hat keinen definierten Klick-Handler"
|
||||
@@ -746,9 +761,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",
|
||||
@@ -775,7 +797,8 @@
|
||||
"expand_all_levels": "Alle Ebenen erweitern",
|
||||
"expand_tooltip": "Erweitert die direkten Unterelemente dieser Sammlung (eine Ebene tiefer). Für weitere Optionen auf den Pfeil rechts klicken.",
|
||||
"expand_first_level": "Direkte Unterelemente erweitern",
|
||||
"expand_nth_level": "{{depth}} Ebenen erweitern"
|
||||
"expand_nth_level": "{{depth}} Ebenen erweitern",
|
||||
"hide_child_notes": "Unterknoten im Baum ausblenden"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "An diesem Tag wurden noch keine Notizen bearbeitet...",
|
||||
@@ -788,7 +811,7 @@
|
||||
"file_type": "Dateityp",
|
||||
"file_size": "Dateigröße",
|
||||
"download": "Herunterladen",
|
||||
"open": "Offen",
|
||||
"open": "Extern öffnen",
|
||||
"upload_new_revision": "Neue Revision hochladen",
|
||||
"upload_success": "Neue Dateirevision wurde hochgeladen.",
|
||||
"upload_failed": "Das Hochladen einer neuen Dateirevision ist fehlgeschlagen.",
|
||||
@@ -808,7 +831,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",
|
||||
@@ -819,7 +843,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",
|
||||
@@ -882,7 +908,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": "Optionen anzeigen:"
|
||||
},
|
||||
"similar_notes": {
|
||||
"title": "Ähnliche Notizen",
|
||||
@@ -986,7 +1013,12 @@
|
||||
"editable_text": {
|
||||
"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."
|
||||
"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 kürzlich gemachte Änderungen wurden unter Umständen nicht gespeichert.",
|
||||
"editor_crashed_details_button": "Mehr Details anzeigen...",
|
||||
"editor_crashed_details_intro": "Falls dieser Fehler häufiger auftritt, ziehen Sie in Betracht uns diesen über GitHub zu melden, indem Sie die folgenden Informationen bereitstellen.",
|
||||
"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.",
|
||||
@@ -1386,7 +1418,7 @@
|
||||
"will_be_deleted_in": "Dieser Anhang wird in {{time}} automatisch gelöscht",
|
||||
"will_be_deleted_soon": "Dieser Anhang wird bald automatisch gelöscht",
|
||||
"deletion_reason": ", da der Anhang nicht im Inhalt der Notiz verlinkt ist. Um das Löschen zu verhindern, füge den Anhangslink wieder in den Inhalt ein oder wandel den Anhang in eine Notiz um.",
|
||||
"role_and_size": "Rolle: {{role}}, Größe: {{size}}",
|
||||
"role_and_size": "Rolle: {{role}}, Größe: {{size}}, MIME: {{- mimeType}}",
|
||||
"link_copied": "Anhangslink in die Zwischenablage kopiert.",
|
||||
"unrecognized_role": "Unbekannte Anhangsrolle „{{role}}“."
|
||||
},
|
||||
@@ -1437,10 +1469,13 @@
|
||||
"import-into-note": "In Notiz importieren",
|
||||
"apply-bulk-actions": "Massenaktionen anwenden",
|
||||
"converted-to-attachments": "{{count}} Notizen wurden als Anhang konvertiert.",
|
||||
"convert-to-attachment-confirm": "Bist du sicher, dass du die ausgewählten Notizen in Anhänge ihrer übergeordneten Notizen umwandeln möchtest?",
|
||||
"convert-to-attachment-confirm": "Bist du sicher, dass du die ausgewählten Notizen in Anhänge ihrer übergeordneten Notizen umwandeln möchtest? Diese Operation wird nur auf Bildnotizes angewandt. Andere Notizen werden übersprungen.",
|
||||
"open-in-popup": "Schnellbearbeitung",
|
||||
"archive": "Archiviere",
|
||||
"unarchive": "Entarchivieren"
|
||||
"unarchive": "Entarchivieren",
|
||||
"open-in-a-new-window": "In neuem Fenster öffnen",
|
||||
"hide-subtree": "Teilbaum ausblenden",
|
||||
"show-subtree": "Teilbaum anzeigen"
|
||||
},
|
||||
"shared_info": {
|
||||
"shared_publicly": "Diese Notiz ist öffentlich geteilt auf {{- link}}.",
|
||||
@@ -1501,7 +1536,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",
|
||||
@@ -1525,7 +1565,16 @@
|
||||
"create-child-note": "Unternotiz anlegen",
|
||||
"unhoist": "Fokus verlassen",
|
||||
"toggle-sidebar": "Seitenleiste ein-/ausblenden",
|
||||
"dropping-not-allowed": "Ablegen von Notizen an dieser Stelle ist nicht zulässig."
|
||||
"dropping-not-allowed": "Ablegen von Notizen an dieser Stelle ist nicht zulässig.",
|
||||
"clone-indicator-tooltip": "Diese Notiz hat {{- count}} Elterknoten: {{- parents}}",
|
||||
"clone-indicator-tooltip-single": "Diese Notiz ist geklont (1 weiterer Elternknoten: {{- parent}})",
|
||||
"shared-indicator-tooltip": "Diese Notiz ist öffentlich einsehbar",
|
||||
"shared-indicator-tooltip-with-url": "Diese Notiz ist unter {{- url}} öffentlich einsehbar",
|
||||
"subtree-hidden-tooltip_one": "{{count}} Unterknoten, der im Baum ausgeblendet ist",
|
||||
"subtree-hidden-tooltip_other": "{{count}} Unterknoten, die im Baum ausgeblendet sind",
|
||||
"subtree-hidden-moved-title": "Zu {{title}} hinzugefügt",
|
||||
"subtree-hidden-moved-description-collection": "Diese Sammlung blendet ihre Unternotizem im Baum aus.",
|
||||
"subtree-hidden-moved-description-other": "Diese Sammlung blendet ihre Unterknoten im Baum aus."
|
||||
},
|
||||
"title_bar_buttons": {
|
||||
"window-on-top": "Dieses Fenster immer oben halten"
|
||||
@@ -1533,10 +1582,23 @@
|
||||
"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",
|
||||
"print_report_collection_content_one": "{{count}} Notiz in der Sammlung konnte nicht gedruckt werden, weil sie nicht unterstützt ist oder geschützt ist.",
|
||||
"print_report_collection_content_other": "{{count}} Notizen in der Sammlung konnten nicht gedruckt werden, weil sie nicht unterstützt sind oder geschützt sind."
|
||||
},
|
||||
"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.",
|
||||
@@ -1565,7 +1627,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>.",
|
||||
@@ -1677,7 +1740,8 @@
|
||||
"open_note_in_new_tab": "Notiz in neuen Tab öffnen",
|
||||
"open_note_in_new_split": "Notiz in neuen geteilten Tab öffnen",
|
||||
"open_note_in_new_window": "Notiz in neuen Fenster öffnen",
|
||||
"open_note_in_popup": "Schnellbearbeitung"
|
||||
"open_note_in_popup": "Schnellbearbeitung",
|
||||
"open_note_in_other_split": "Notiz in neuer Spalte öffnen"
|
||||
},
|
||||
"electron_integration": {
|
||||
"desktop-application": "Desktop Anwendung",
|
||||
@@ -1945,8 +2009,9 @@
|
||||
"unknown_widget": "Unbekanntes Widget für '{{id}}'."
|
||||
},
|
||||
"note_language": {
|
||||
"not_set": "Nicht gesetzt",
|
||||
"configure-languages": "Konfiguriere Sprachen..."
|
||||
"not_set": "Keine Sprache ausgewählt",
|
||||
"configure-languages": "Konfiguriere Sprachen...",
|
||||
"help-on-languages": "Zu Übersetzungen beitragen..."
|
||||
},
|
||||
"content_language": {
|
||||
"title": "Inhaltssprachen",
|
||||
@@ -1964,7 +2029,8 @@
|
||||
"button_title": "Exportiere Diagramm als PNG"
|
||||
},
|
||||
"svg": {
|
||||
"export_to_png": "Das Diagramm konnte als PNG nicht exportiert werden."
|
||||
"export_to_png": "Das Diagramm konnte als PNG nicht exportiert werden.",
|
||||
"export_to_svg": "Das Diagramm konnte nicht als SVG exportiert werden."
|
||||
},
|
||||
"code_theme": {
|
||||
"title": "Aussehen",
|
||||
@@ -2012,7 +2078,7 @@
|
||||
"book_properties_config": {
|
||||
"hide-weekends": "Wochenenden ausblenden",
|
||||
"display-week-numbers": "Zeige Kalenderwoche",
|
||||
"map-style": "Kartenstil:",
|
||||
"map-style": "Kartenstil",
|
||||
"max-nesting-depth": "Maximale Verschachtelungstiefe:",
|
||||
"raster": "Raster",
|
||||
"vector_light": "Vektor (Hell)",
|
||||
@@ -2065,14 +2131,20 @@
|
||||
"background_effects_title": "Hintergrundeffekte sind jetzt zuverlässig nutzbar",
|
||||
"background_effects_message": "Auf Windows-Geräten sind die Hintergrundeffekte nun vollständig stabil. Die Hintergrundeffekte verleihen der Benutzeroberfläche einen Farbakzent, indem der Hintergrund dahinter weichgezeichnet wird. Diese Technik wird auch in anderen Anwendungen wie dem Windows-Explorer eingesetzt.",
|
||||
"background_effects_button": "Aktiviere Hintergrundeffekte",
|
||||
"dismiss": "Ablehnen"
|
||||
"dismiss": "Ablehnen",
|
||||
"new_layout_title": "Neues Layout",
|
||||
"new_layout_message": "Wir haben ein modernisiertes Layout für Trilium eingeführt. Die Multifunktionsleiste wurde entfernt und als neue Statusanzeige und ausklappbaren Sektionen (wie hervorgehobenen Attributen), welche Schlüsselfunktionen übernehmen, nahtlos in das Hauptinterface integriert.\n\nDas neue Layout ist standardmäßig aktiviert und kann temporär in Optionen → Anzeige deaktiviert werden.",
|
||||
"new_layout_button": "Mehr Informationen"
|
||||
},
|
||||
"settings": {
|
||||
"related_settings": "Ähnliche Einstellungen"
|
||||
},
|
||||
"settings_appearance": {
|
||||
"related_code_blocks": "Farbschema für Code-Blöcke in Textnotizen",
|
||||
"related_code_notes": "Farbschema für Code-Notizen"
|
||||
"related_code_notes": "Farbschema für Code-Notizen",
|
||||
"ui": "Benutzeroberfläche",
|
||||
"ui_old_layout": "Altes Layout",
|
||||
"ui_new_layout": "Neues Layout"
|
||||
},
|
||||
"units": {
|
||||
"percentage": "%"
|
||||
@@ -2104,5 +2176,92 @@
|
||||
},
|
||||
"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",
|
||||
"new_layout_description": "Probiere das neue Layout für eine modernere Darstellung und verbesserte Benutzbarkeit aus. Kann sich in Zukunft stark ändern."
|
||||
},
|
||||
"server": {
|
||||
"unknown_http_error_title": "Bei der Kommunikation mit dem Server ist ein Fehler aufgetreten",
|
||||
"unknown_http_error_content": "Statuscode: {{statusCode}}\nURL: {{method}} {{url}}\nNachricht: {{message}}",
|
||||
"traefik_blocks_requests": "Der Traefik Reverse-Proxy hat ein fatales Update bekommen, welche die Kommunikation mit dem Server stört."
|
||||
},
|
||||
"tab_history_navigation_buttons": {
|
||||
"go-back": "Zur vorherigen Notiz zurück kehren",
|
||||
"go-forward": "Zur nächsten Notiz"
|
||||
},
|
||||
"breadcrumb": {
|
||||
"hoisted_badge": "Gehoben",
|
||||
"hoisted_badge_title": "Abgesenkt",
|
||||
"workspace_badge": "Arbeitsfläche",
|
||||
"scroll_to_top_title": "Zum Anfang der Notiz springen",
|
||||
"create_new_note": "Neue Unternotiz erstellen",
|
||||
"empty_hide_archived_notes": "Archivierte Notizen ausblenden"
|
||||
},
|
||||
"breadcrumb_badges": {
|
||||
"read_only_explicit": "Nicht Änderbar",
|
||||
"read_only_explicit_description": "Diese Notiz wurde händisch als nicht änderbar markiert.\nKlicke hier um sie temporär zu bearbeiten.",
|
||||
"read_only_auto": "Automatisch nicht änderbar",
|
||||
"read_only_auto_description": "Diese Notiz wurde automatisch aus Leistungsgründen als nicht änderbar markiert. Dieses automatische Limit kann in den Einstellungen angepasst werden.\n\nKlicke hier, um sie temporär zu bearbeiten.",
|
||||
"read_only_temporarily_disabled": "Temporär bearbeitbar",
|
||||
"read_only_temporarily_disabled_description": "Diese Notiz ist aktuell bearbeitbar, ist aber normalerweise nicht änderbar. Sobald du zu einer anderen Notiz navigierst, kehrt diese Notiz in ihren Normalzustand zurück.\n\nKlicke hier, um die Notiz wieder nicht änderbar zu machen.",
|
||||
"shared_publicly": "Öffentlich geteilt",
|
||||
"shared_locally": "Lokal geteilt",
|
||||
"shared_copy_to_clipboard": "Link in die Zwischenablage kopieren",
|
||||
"shared_open_in_browser": "Link öffnen",
|
||||
"shared_unshare": "Teilen aufheben",
|
||||
"clipped_note": "Internetschnellverweis",
|
||||
"clipped_note_description": "Diese Notiz wurde von {{url}} übernommen.\n\nKlicke hier, um zum Ursprung zu gehen.",
|
||||
"execute_script": "Skript ausführen",
|
||||
"execute_script_description": "Diese Notiz ist eine Skriptnotiz. Klicke hier, um das Skript auszuführen.",
|
||||
"execute_sql": "SQL ausführen",
|
||||
"execute_sql_description": "Diese Notiz ist eine SQL-Notiz. Klicke hier, um die SQL-Abfrage auszuführen.",
|
||||
"save_status_saved": "Gespeichert",
|
||||
"save_status_saving": "Speichern...",
|
||||
"save_status_unsaved": "Nicht gespeichert",
|
||||
"save_status_error": "Speichern fehlgeschlagen",
|
||||
"save_status_saving_tooltip": "Änderungen werden gespeichert.",
|
||||
"save_status_unsaved_tooltip": "Es gibt ungespeicherte Änderungen, welche gleich automatisch gespeichert werden.",
|
||||
"save_status_error_tooltip": "Beim speichern der Notiz ist ein Fehler aufgetreten. Wenn möglich, versuche die Notiz woandershin zu kopieren und die Applikation neu zu laden."
|
||||
},
|
||||
"status_bar": {
|
||||
"language_title": "Inhaltssprache ändern",
|
||||
"note_info_title": "Notizinfo anzeigen (z.B.: Datum, Notizgröße)",
|
||||
"backlinks_one": "{{count}} Rücklink",
|
||||
"backlinks_other": "{{count}} Rücklinks",
|
||||
"backlinks_title_one": "Rücklink anzeigen",
|
||||
"backlinks_title_other": "Rücklinks anzeigen",
|
||||
"attachments_one": "{{count}} Anhang",
|
||||
"attachments_other": "{{count}} Anhänge",
|
||||
"attachments_title_one": "Anhang in einem neuen Tab öffnen",
|
||||
"attachments_title_other": "Anhänge in einem neuen Tab öffnen",
|
||||
"attributes_one": "{{count}} Eigenschaft",
|
||||
"attributes_other": "{{count}} Eigenschaften",
|
||||
"attributes_title": "Eigene und gererbte Eigenschaften",
|
||||
"note_paths_one": "{{count}} Pfad",
|
||||
"note_paths_other": "{{count}} Pfade",
|
||||
"note_paths_title": "Notizpfade",
|
||||
"code_note_switcher": "Sprachmodus ändern"
|
||||
},
|
||||
"attributes_panel": {
|
||||
"title": "Notizeigenschaften"
|
||||
},
|
||||
"right_pane": {
|
||||
"empty_message": "Für diese Notiz gibt es nichts anzuzeigen",
|
||||
"empty_button": "Anzeige ausblenden",
|
||||
"toggle": "Rechte Anzeige umschalten",
|
||||
"custom_widget_go_to_source": "Zum Ursprungscode"
|
||||
},
|
||||
"pdf": {
|
||||
"attachments_one": "{{count}} Anhang",
|
||||
"attachments_other": "{{count}} Anhänge",
|
||||
"layers_one": "{{count}} Ebene",
|
||||
"layers_other": "{{count}} Ebenen",
|
||||
"pages_one": "{{count}} Seite",
|
||||
"pages_other": "{{count}} Seiten",
|
||||
"pages_alt": "Seite {{pageNumber}}",
|
||||
"pages_loading": "Laden..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,5 +69,8 @@
|
||||
"clear-color": "Clear note colour",
|
||||
"set-color": "Set note colour",
|
||||
"set-custom-color": "Set custom note colour"
|
||||
},
|
||||
"about": {
|
||||
"title": "About Trilium Notes"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,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": {
|
||||
@@ -765,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",
|
||||
@@ -794,7 +800,8 @@
|
||||
"geo-map": "Geo Map",
|
||||
"board": "Board",
|
||||
"presentation": "Presentation",
|
||||
"include_archived_notes": "Show archived notes"
|
||||
"include_archived_notes": "Show archived notes",
|
||||
"hide_child_notes": "Hide child notes in tree"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "No edited notes on this day yet...",
|
||||
@@ -1613,7 +1620,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}}'."
|
||||
},
|
||||
@@ -1637,6 +1644,7 @@
|
||||
"tree-context-menu": {
|
||||
"open-in-a-new-tab": "Open in a new tab",
|
||||
"open-in-a-new-split": "Open in a new split",
|
||||
"open-in-a-new-window": "Open in a new window",
|
||||
"insert-note-after": "Insert note after",
|
||||
"insert-child-note": "Insert child note",
|
||||
"archive": "Archive",
|
||||
@@ -1649,6 +1657,8 @@
|
||||
"advanced": "Advanced",
|
||||
"expand-subtree": "Expand subtree",
|
||||
"collapse-subtree": "Collapse subtree",
|
||||
"hide-subtree": "Hide subtree",
|
||||
"show-subtree": "Show subtree",
|
||||
"sort-by": "Sort by...",
|
||||
"recent-changes-in-subtree": "Recent changes in subtree",
|
||||
"convert-to-attachment": "Convert to attachment",
|
||||
@@ -1762,7 +1772,16 @@
|
||||
"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}}",
|
||||
"subtree-hidden-tooltip_one": "{{count}} child note that is hidden from the tree",
|
||||
"subtree-hidden-tooltip_other": "{{count}} child notes that are hidden from the tree",
|
||||
"subtree-hidden-moved-title": "Added to {{title}}",
|
||||
"subtree-hidden-moved-description-collection": "This collection hides its child notes in the tree.",
|
||||
"subtree-hidden-moved-description-other": "Child notes are hidden in the tree for this note."
|
||||
},
|
||||
"title_bar_buttons": {
|
||||
"window-on-top": "Keep Window on Top"
|
||||
@@ -1796,7 +1815,11 @@
|
||||
"configure_launchbar": "Configure Launchbar"
|
||||
},
|
||||
"sql_result": {
|
||||
"no_rows": "No rows have been returned for this query"
|
||||
"not_executed": "The query has not been executed yet.",
|
||||
"no_rows": "No rows have been returned for this query",
|
||||
"failed": "SQL query execution has failed",
|
||||
"statement_result": "Statement result",
|
||||
"execute_now": "Execute now"
|
||||
},
|
||||
"sql_table_schemas": {
|
||||
"tables": "Tables"
|
||||
@@ -2198,7 +2221,14 @@
|
||||
"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."
|
||||
"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",
|
||||
@@ -2227,5 +2257,15 @@
|
||||
"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..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,13 @@
|
||||
},
|
||||
"bundle-error": {
|
||||
"title": "Hubo un fallo al cargar un script personalizado",
|
||||
"message": "El script de la nota con ID \"{{id}}\", titulado \"{{title}}\" no pudo ser ejecutado debido a:\n\n{{message}}"
|
||||
"message": "El script no pudo ser ejecutado debido a:\n\n{{message}}"
|
||||
},
|
||||
"widget-list-error": {
|
||||
"title": "Hubo un fallo al obtener la lista de widgets del servidor"
|
||||
},
|
||||
"widget-render-error": {
|
||||
"title": "Hubo un fallo al renderizar un widget personalizado de React"
|
||||
}
|
||||
},
|
||||
"add_link": {
|
||||
@@ -162,7 +168,8 @@
|
||||
"other": "Otro",
|
||||
"quickSearch": "centrarse en la entrada de búsqueda rápida",
|
||||
"inPageSearch": "búsqueda en la página",
|
||||
"title": "Hoja de ayuda"
|
||||
"title": "Hoja de ayuda",
|
||||
"editShortcuts": "Editar atajos de teclado"
|
||||
},
|
||||
"import": {
|
||||
"importIntoNote": "Importar a nota",
|
||||
@@ -279,7 +286,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",
|
||||
@@ -691,7 +697,7 @@
|
||||
"convert_into_attachment_successful": "La nota '{{title}}' ha sido convertida a un archivo adjunto.",
|
||||
"convert_into_attachment_prompt": "¿Está seguro que desea convertir la nota '{{title}}' en un archivo adjunto de la nota padre?",
|
||||
"print_pdf": "Exportar como PDF...",
|
||||
"open_note_on_server": "Abrir nota en el servidor"
|
||||
"open_note_on_server": "Abrir nota en servidor"
|
||||
},
|
||||
"onclick_button": {
|
||||
"no_click_handler": "El widget de botón '{{componentId}}' no tiene un controlador de clics definido"
|
||||
@@ -737,7 +743,7 @@
|
||||
"zpetne_odkazy": {
|
||||
"relation": "relación",
|
||||
"backlink_one": "{{count}} Vínculo de retroceso",
|
||||
"backlink_many": "",
|
||||
"backlink_many": "{{count}} Vínculos de retroceso",
|
||||
"backlink_other": "{{count}} vínculos de retroceso"
|
||||
},
|
||||
"mobile_detail_menu": {
|
||||
@@ -749,9 +755,11 @@
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "Cambiar icono de nota",
|
||||
"category": "Categoría:",
|
||||
"search": "Búsqueda:",
|
||||
"reset-default": "Restablecer a icono por defecto"
|
||||
"reset-default": "Restablecer a icono por defecto",
|
||||
"search_placeholder_one": "Buscar {{number}} icono a través de {{count}} paquetes",
|
||||
"search_placeholder_many": "Buscar {{number}} iconos a través de {{count}} paquetes",
|
||||
"search_placeholder_other": "Buscar {{number}} iconos a través de {{count}} paquetes"
|
||||
},
|
||||
"basic_properties": {
|
||||
"note_type": "Tipo de nota",
|
||||
@@ -791,7 +799,7 @@
|
||||
"file_type": "Tipo de archivo",
|
||||
"file_size": "Tamaño del archivo",
|
||||
"download": "Descargar",
|
||||
"open": "Abrir",
|
||||
"open": "Abrir externamente",
|
||||
"upload_new_revision": "Subir nueva revisión",
|
||||
"upload_success": "Se ha subido una nueva revisión de archivo.",
|
||||
"upload_failed": "Error al cargar una nueva revisión de archivo.",
|
||||
@@ -1304,11 +1312,11 @@
|
||||
"code_mime_types": {
|
||||
"title": "Tipos MIME disponibles en el menú desplegable",
|
||||
"tooltip_syntax_highlighting": "Resaltado de sintaxis",
|
||||
"tooltip_code_block_syntax": "Bloques de código en notas de texto",
|
||||
"tooltip_code_note_syntax": "Notas de código"
|
||||
"tooltip_code_block_syntax": "Bloques de Código en notas de Texto",
|
||||
"tooltip_code_note_syntax": "Notas de Código"
|
||||
},
|
||||
"vim_key_bindings": {
|
||||
"use_vim_keybindings_in_code_notes": "Atajos de teclas de Vim",
|
||||
"use_vim_keybindings_in_code_notes": "Combinaciones de teclas Vim",
|
||||
"enable_vim_keybindings": "Habilitar los atajos de teclas de Vim en la notas de código (no es modo ex)"
|
||||
},
|
||||
"wrap_lines": {
|
||||
@@ -1573,7 +1581,7 @@
|
||||
"will_be_deleted_in": "Este archivo adjunto se eliminará automáticamente en {{time}}",
|
||||
"will_be_deleted_soon": "Este archivo adjunto se eliminará automáticamente pronto",
|
||||
"deletion_reason": ", porque el archivo adjunto no está vinculado en el contenido de la nota. Para evitar la eliminación, vuelva a agregar el enlace del archivo adjunto al contenido o convierta el archivo adjunto en una nota.",
|
||||
"role_and_size": "Rol: {{role}}, Tamaño: {{size}}",
|
||||
"role_and_size": "Rol: {{role}}, tamaño: {{size}}, MIME: {{- mimeType}}",
|
||||
"link_copied": "Enlace del archivo adjunto copiado al portapapeles.",
|
||||
"unrecognized_role": "Rol de archivo adjunto no reconocido '{{role}}'."
|
||||
},
|
||||
@@ -1624,7 +1632,7 @@
|
||||
"import-into-note": "Importar a nota",
|
||||
"apply-bulk-actions": "Aplicar acciones en lote",
|
||||
"converted-to-attachments": "{{count}} notas han sido convertidas en archivos adjuntos.",
|
||||
"convert-to-attachment-confirm": "¿Está seguro que desea convertir las notas seleccionadas en archivos adjuntos de sus notas padres?",
|
||||
"convert-to-attachment-confirm": "¿Está seguro que desea convertir las notas seleccionadas en archivos adjuntos de sus notas padres? Esta operación solo aplica a notas de Imagen, otras notas serán omitidas.",
|
||||
"open-in-popup": "Edición rápida",
|
||||
"archive": "Archivar",
|
||||
"unarchive": "Desarchivar"
|
||||
@@ -1719,7 +1727,10 @@
|
||||
"note_detail": {
|
||||
"could_not_find_typewidget": "No se pudo encontrar typeWidget para el tipo '{{type}}'",
|
||||
"printing": "Impresión en curso...",
|
||||
"printing_pdf": "Exportando a PDF en curso.."
|
||||
"printing_pdf": "Exportando a PDF en curso..",
|
||||
"print_report_collection_content_one": "{{count}} nota en la colección no se puede imprimir porque no son compatibles o está protegida.",
|
||||
"print_report_collection_content_many": "{{count}} notas en la colección no se pueden imprimir porque no son compatibles o están protegidas.",
|
||||
"print_report_collection_content_other": "{{count}} notas en la colección no se pueden imprimir porque no son compatibles o están protegidas."
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "escriba el título de la nota aquí..."
|
||||
@@ -1931,7 +1942,7 @@
|
||||
"unknown_widget": "Widget desconocido para \"{{id}}\"."
|
||||
},
|
||||
"note_language": {
|
||||
"not_set": "No establecido",
|
||||
"not_set": "Idioma no establecido",
|
||||
"configure-languages": "Configurar idiomas..."
|
||||
},
|
||||
"content_language": {
|
||||
@@ -1970,7 +1981,7 @@
|
||||
"hide-weekends": "Ocultar fines de semana",
|
||||
"show-scale": "Mostrar escala",
|
||||
"display-week-numbers": "Mostrar números de semana",
|
||||
"map-style": "Estilo de mapa:",
|
||||
"map-style": "Estilo de mapa",
|
||||
"max-nesting-depth": "Máxima profundidad de anidamiento:",
|
||||
"vector_light": "Vector (claro)",
|
||||
"vector_dark": "Vector (oscuro)",
|
||||
@@ -2099,5 +2110,36 @@
|
||||
"clear-color": "Borrar color de nota",
|
||||
"set-color": "Asignar color de nota",
|
||||
"set-custom-color": "Asignar color de nota personalizado"
|
||||
},
|
||||
"status_bar": {
|
||||
"backlinks_one": "{{count}} vínculo de retroceso",
|
||||
"backlinks_many": "{{count}} vínculos de retroceso",
|
||||
"backlinks_other": "{{count}} vínculos de retroceso",
|
||||
"backlinks_title_one": "Ver vínculo de retroceso",
|
||||
"backlinks_title_many": "Ver vínculos de retroceso",
|
||||
"backlinks_title_other": "Ver vínculos de retroceso",
|
||||
"attachments_one": "{{count}} adjunto",
|
||||
"attachments_many": "{{count}} adjuntos",
|
||||
"attachments_other": "{{count}} adjuntos",
|
||||
"attachments_title_one": "Ver adjunto en una nueva pestaña",
|
||||
"attachments_title_many": "Ver adjuntos en una nueva pestaña",
|
||||
"attachments_title_other": "Ver adjuntos en una nueva pestaña",
|
||||
"attributes_one": "{{count}} atributo",
|
||||
"attributes_many": "{{count}} atributos",
|
||||
"attributes_other": "{{count}} atributos",
|
||||
"note_paths_one": "{{count}} ruta",
|
||||
"note_paths_many": "{{count}} rutas",
|
||||
"note_paths_other": "{{count}} rutas"
|
||||
},
|
||||
"pdf": {
|
||||
"attachments_one": "{{count}} adjunto",
|
||||
"attachments_many": "{{count}} adjuntos",
|
||||
"attachments_other": "{{count}} adjuntos",
|
||||
"layers_one": "{{count}} capa",
|
||||
"layers_many": "{{count}} capas",
|
||||
"layers_other": "{{count}} capas",
|
||||
"pages_one": "{{count}} página",
|
||||
"pages_many": "{{count}} páginas",
|
||||
"pages_other": "{{count}} páginas"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,13 @@
|
||||
},
|
||||
"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}}"
|
||||
"message": "Le script 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": {
|
||||
@@ -279,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",
|
||||
@@ -756,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",
|
||||
@@ -1542,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"
|
||||
@@ -1550,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.",
|
||||
@@ -1582,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>.",
|
||||
@@ -1683,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",
|
||||
@@ -1992,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",
|
||||
@@ -2076,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",
|
||||
@@ -2109,6 +2131,10 @@
|
||||
},
|
||||
"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."
|
||||
"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,50 @@
|
||||
{
|
||||
"about": {
|
||||
"title": "ट्रिलियम नोट्स के बारें में"
|
||||
"title": "ट्रिलियम नोट्स के बारें में",
|
||||
"build_date": "निर्माण की तारीख:",
|
||||
"app_version": "ऐप वर्ज़न:",
|
||||
"db_version": "DB वर्ज़न:",
|
||||
"build_revision": "बिल्ड रिविज़न:"
|
||||
},
|
||||
"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": "नोट"
|
||||
},
|
||||
"bulk_actions": {
|
||||
"other": "अन्य"
|
||||
},
|
||||
"clone_to": {
|
||||
"search_for_note_by_its_name": "नोट क नाम से नोट खोजें"
|
||||
},
|
||||
"confirm": {
|
||||
"also_delete_note": "नोट भी डिलीट करें"
|
||||
},
|
||||
"delete_notes": {
|
||||
"delete_notes_preview": "नोट्स प्रिव्यू डिलीट करें"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,13 @@
|
||||
},
|
||||
"bundle-error": {
|
||||
"title": "Nem sikerült betölteni az egyéni szkriptet",
|
||||
"message": "A(z) \"{{id}}\" azonosítójú, \"{{title}}\" című jegyzetből származó szkript nem hajtható végre a következő ok miatt:\n\n{{message}}"
|
||||
"message": "A skript nem hajtható végre a következő ok miatt:\n\n{{message}}"
|
||||
},
|
||||
"widget-list-error": {
|
||||
"title": "A Widget-ek letöltése sikertelen volt"
|
||||
},
|
||||
"widget-render-error": {
|
||||
"title": "Nem sikerült renderelni a React widget-et"
|
||||
}
|
||||
},
|
||||
"add_link": {
|
||||
|
||||
@@ -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",
|
||||
@@ -893,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": {
|
||||
@@ -1333,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",
|
||||
@@ -1793,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}}'."
|
||||
},
|
||||
@@ -1879,7 +1895,11 @@
|
||||
"create-child-note": "Crea nota figlio",
|
||||
"unhoist": "Sganciare",
|
||||
"toggle-sidebar": "Attiva/disattiva la barra laterale",
|
||||
"dropping-not-allowed": "Non è consentito lasciare appunti in questa posizione."
|
||||
"dropping-not-allowed": "Non è consentito lasciare appunti in questa posizione.",
|
||||
"clone-indicator-tooltip": "Questa nota ha {{- count}} genitori: {{- parents}}",
|
||||
"clone-indicator-tooltip-single": "Questa nota è stata clonata (1 genitore aggiuntivo: {{- parent}})",
|
||||
"shared-indicator-tooltip": "Questa nota è condivisa pubblicamente",
|
||||
"shared-indicator-tooltip-with-url": "Questa nota è condivisa pubblicamente all'indirizzo: {{- url}}"
|
||||
},
|
||||
"title_bar_buttons": {
|
||||
"window-on-top": "Mantieni la finestra in primo piano"
|
||||
@@ -1887,7 +1907,13 @@
|
||||
"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...",
|
||||
@@ -1897,7 +1923,8 @@
|
||||
"note_type_switcher_others": "Altro tipo di nota",
|
||||
"note_type_switcher_templates": "Modello",
|
||||
"note_type_switcher_collection": "Collezione",
|
||||
"edited_notes": "Note modificate"
|
||||
"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.",
|
||||
@@ -2177,7 +2204,14 @@
|
||||
"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"
|
||||
"shared_unshare": "Rimuovi condivisione",
|
||||
"save_status_saved": "Salvato",
|
||||
"save_status_saving": "Salvataggio in corso...",
|
||||
"save_status_unsaved": "Non salvato",
|
||||
"save_status_error": "Salvataggio non riuscito",
|
||||
"save_status_saving_tooltip": "Le modifiche sono state salvate.",
|
||||
"save_status_unsaved_tooltip": "Ci sono modifiche non salvate. Verranno salvate automaticamente tra un attimo.",
|
||||
"save_status_error_tooltip": "Si è verificato un errore durante il salvataggio della nota. Se possibile, prova a copiare il contenuto della nota altrove e a ricaricare l'applicazione."
|
||||
},
|
||||
"breadcrumb": {
|
||||
"workspace_badge": "Area di lavoro",
|
||||
@@ -2220,5 +2254,18 @@
|
||||
"empty_button": "Nascondi il pannello",
|
||||
"toggle": "Attiva/disattiva pannello destro",
|
||||
"custom_widget_go_to_source": "Vai al codice sorgente"
|
||||
},
|
||||
"pdf": {
|
||||
"attachments_one": "{{count}} allegato",
|
||||
"attachments_many": "{{count}} allegati",
|
||||
"attachments_other": "{{count}} allegati",
|
||||
"layers_one": "{{count}} livello",
|
||||
"layers_many": "{{count}} livelli",
|
||||
"layers_other": "{{count}} livelli",
|
||||
"pages_one": "{{count}} pagina",
|
||||
"pages_many": "{{count}} pagine",
|
||||
"pages_other": "{{count}} pagine",
|
||||
"pages_alt": "Pagina {{pageNumber}}",
|
||||
"pages_loading": "Caricamento in corso..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"widget-render-error": {
|
||||
"title": "カスタム React ウィジェットのレンダリングに失敗しました"
|
||||
},
|
||||
"widget-missing-parent": "カスタムウィジェットに必須の '{{property}}' プロパティが定義されていません。",
|
||||
"widget-missing-parent": "カスタムウィジェットに必須の '{{property}}' プロパティが定義されていません。\n\nこのスクリプトを UI 要素なしで実行する場合は、代わりに '#run=frontendStartup' を使用してください。",
|
||||
"open-script-note": "スクリプトノートを開く",
|
||||
"scripting-error": "カスタムスクリプトエラー: {{title}}"
|
||||
},
|
||||
@@ -152,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": "ローカライゼーション",
|
||||
@@ -437,7 +443,10 @@
|
||||
"unhoist-note": "ノートのホイストを解除",
|
||||
"edit-branch-prefix": "ブランチの接頭辞を編集",
|
||||
"archive": "アーカイブ",
|
||||
"unarchive": "アーカイブ解除"
|
||||
"unarchive": "アーカイブ解除",
|
||||
"open-in-a-new-window": "新しいウィンドウで開く",
|
||||
"hide-subtree": "サブツリーを非表示",
|
||||
"show-subtree": "サブツリーを表示"
|
||||
},
|
||||
"zen_mode": {
|
||||
"button_exit": "禅モードを退出"
|
||||
@@ -562,7 +571,8 @@
|
||||
"expand_tooltip": "このコレクションの直下の子(1階層下)を展開します。その他のオプションについては、右側の矢印を押してください。",
|
||||
"expand_first_level": "直下の子を展開",
|
||||
"expand_nth_level": "{{depth}} 階層下まで展開",
|
||||
"expand_all_levels": "すべての階層を展開"
|
||||
"expand_all_levels": "すべての階層を展開",
|
||||
"hide_child_notes": "ツリー内の子ノートを非表示"
|
||||
},
|
||||
"note_types": {
|
||||
"geo-map": "ジオマップ",
|
||||
@@ -648,7 +658,6 @@
|
||||
"revision_deleted": "ノートの変更履歴は削除されました。",
|
||||
"settings": "ノートの変更履歴の設定",
|
||||
"file_size": "ファイルサイズ:",
|
||||
"preview": "プレビュー:",
|
||||
"preview_not_available": "このノートタイプではプレビューは利用できません。",
|
||||
"diff_on": "差分を表示",
|
||||
"diff_off": "内容を表示",
|
||||
@@ -1239,7 +1248,15 @@
|
||||
"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}}",
|
||||
"subtree-hidden-tooltip_other": "{{count}} 個の子ノートがツリーで非表示になっています",
|
||||
"subtree-hidden-moved-title": "{{title}} に追加されました",
|
||||
"subtree-hidden-moved-description-collection": "このコレクションはツリー内の子ノートを非表示にします。",
|
||||
"subtree-hidden-moved-description-other": "このノートのツリーでは子ノートは非表示になっています。"
|
||||
},
|
||||
"bulk_actions": {
|
||||
"bulk_actions": "一括操作",
|
||||
@@ -1930,7 +1947,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": "この変更を無視する",
|
||||
@@ -2126,7 +2147,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}}」は認識されません。"
|
||||
},
|
||||
@@ -2183,7 +2204,14 @@
|
||||
"execute_sql_description": "このノートは SQL ノートです。クリックすると SQL クエリが実行されます。",
|
||||
"shared_copy_to_clipboard": "リンクをクリップボードにコピー",
|
||||
"shared_open_in_browser": "ブラウザでリンクを開く",
|
||||
"shared_unshare": "共有を削除"
|
||||
"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": "コンテンツの言語を変更",
|
||||
@@ -2214,5 +2242,12 @@
|
||||
},
|
||||
"attributes_panel": {
|
||||
"title": "ノート属性"
|
||||
},
|
||||
"pdf": {
|
||||
"attachments_other": "{{count}} 添付ファイル",
|
||||
"layers_other": "{{count}} 層",
|
||||
"pages_other": "{{count}} ページ",
|
||||
"pages_alt": "ページ {{pageNumber}}",
|
||||
"pages_loading": "読み込み中..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1,82 @@
|
||||
{}
|
||||
{
|
||||
"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"
|
||||
},
|
||||
"add_link": {
|
||||
"note": "Notat"
|
||||
},
|
||||
"branch_prefix": {
|
||||
"prefix": "Prefiks : ",
|
||||
"save": "Lagre"
|
||||
},
|
||||
"bulk_actions": {
|
||||
"labels": "Etiketter",
|
||||
"relations": "Relasjoner",
|
||||
"notes": "Notater",
|
||||
"other": "Andre"
|
||||
},
|
||||
"confirm": {
|
||||
"confirmation": "Bekreftelse",
|
||||
"cancel": "Avbryt",
|
||||
"ok": "OK"
|
||||
},
|
||||
"delete_notes": {
|
||||
"close": "Lukk",
|
||||
"cancel": "Avbryt",
|
||||
"ok": "OK"
|
||||
},
|
||||
"export": {
|
||||
"close": "Lukk",
|
||||
"export": "Eksporter"
|
||||
},
|
||||
"note_type_chooser": {
|
||||
"templates": "Maler"
|
||||
},
|
||||
"help": {
|
||||
"title": "Hurtigveiledning",
|
||||
"troubleshooting": "Feilsøking",
|
||||
"other": "Andre"
|
||||
},
|
||||
"import": {
|
||||
"options": "Alternativer",
|
||||
"import": "Importer"
|
||||
},
|
||||
"include_note": {
|
||||
"label_note": "Notat"
|
||||
},
|
||||
"prompt": {
|
||||
"title": "Ledetekst",
|
||||
"ok": "OK",
|
||||
"defaultTitle": "Ledetekst"
|
||||
},
|
||||
"info": {
|
||||
"closeButton": "Lukk",
|
||||
"okButton": "OK"
|
||||
},
|
||||
"markdown_import": {
|
||||
"import_button": "Importer"
|
||||
},
|
||||
"protected_session_password": {
|
||||
"close_label": "Lukk"
|
||||
},
|
||||
"recent_changes": {
|
||||
"undelete_link": "gjenopprett"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"toast": {
|
||||
"critical-error": {
|
||||
"title": "Kritische Error",
|
||||
"message": "Een kritieke fout heeft plaatsgevonden waardoor de cliënt zich aanmeldt vanaf het begin:\n\n84X\n\nDit is waarschijnlijk veroorzaakt door een script dat op een onverwachte manier faalt. Probeer de sollicitatie in veilige modus te starten en de kwestie aan te spreken."
|
||||
"message": "Een kritieke fout heeft plaatsgevonden waardoor de applicatie niet kon opstarten:\n\n{{message}}\n\nDit is waarschijnlijk veroorzaakt door een onverwachte fout in een script. Probeer de applicatie op te starten in veilige modus en het probleem op te lossen."
|
||||
},
|
||||
"widget-error": {
|
||||
"title": "Starten widget mislukt",
|
||||
@@ -22,7 +22,16 @@
|
||||
"bundle-error": {
|
||||
"title": "Custom script laden mislukt",
|
||||
"message": "Script van notitie met ID \"{{id}}\", getiteld \"{{title}}\" kon niet worden uitgevoerd vanwege:\n\n{{message}}"
|
||||
}
|
||||
},
|
||||
"scripting-error": "Error met script: {{title}}",
|
||||
"widget-list-error": {
|
||||
"title": "Kon geen lijst met widgets ophalen van de server"
|
||||
},
|
||||
"widget-render-error": {
|
||||
"title": "React-widget kon niet geladen worden"
|
||||
},
|
||||
"widget-missing-parent": "Widget heeft niet het verplichte '{{property}}'-veld gedefinieerd.\n\nAls dit script is bedoeld om zonder interface te draaien, gebruik dan in plaats daarvan '#run=frontendStartup'.",
|
||||
"open-script-note": "Open scriptnotitie"
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "Voeg link toe",
|
||||
@@ -41,7 +50,8 @@
|
||||
"help_on_tree_prefix": "Help bij boomvoorvoegsel",
|
||||
"prefix": "Voorvoegsel: ",
|
||||
"edit_branch_prefix_multiple": "Bewerk zijtakvoorvoegsel voor {{count}} zijtakken",
|
||||
"branch_prefix_saved_multiple": "Vertakkingsvoorvoegsel opgeslagen voor {{count}} vertakkingen."
|
||||
"branch_prefix_saved_multiple": "Vertakkingsvoorvoegsel opgeslagen voor {{count}} vertakkingen.",
|
||||
"affected_branches": "Aangetaste takken ({{count}}):"
|
||||
},
|
||||
"bulk_actions": {
|
||||
"bulk_actions": "Bulk acties",
|
||||
@@ -54,7 +64,8 @@
|
||||
"labels": "Labels",
|
||||
"relations": "Relaties",
|
||||
"notes": "Notities",
|
||||
"other": "Andere"
|
||||
"other": "Andere",
|
||||
"include_descendants": "Tel afstammelingen van de geselecteerde notities mee"
|
||||
},
|
||||
"calendar": {
|
||||
"april": "April",
|
||||
@@ -78,5 +89,35 @@
|
||||
},
|
||||
"show_toc_widget_button": {
|
||||
"show_toc": "Laat Inhoudsopgave zien"
|
||||
},
|
||||
"status_bar": {
|
||||
"note_paths_one": "{{count}} pad",
|
||||
"note_paths_other": "{{count}} paden",
|
||||
"note_paths_title": "Notitiepaden",
|
||||
"code_note_switcher": "Verander de taalmodus"
|
||||
},
|
||||
"attributes_panel": {
|
||||
"title": "Notitie-attributen"
|
||||
},
|
||||
"right_pane": {
|
||||
"empty_message": "Geen informatie voor deze notitie",
|
||||
"empty_button": "Verberg dit paneel",
|
||||
"toggle": "Schakel rechterpaneel in/uit",
|
||||
"custom_widget_go_to_source": "Go naar de broncode"
|
||||
},
|
||||
"pdf": {
|
||||
"attachments_one": "{{count}} bijlage",
|
||||
"attachments_other": "{{count}} bijlagen",
|
||||
"layers_one": "{{count}} laag",
|
||||
"layers_other": "{{count}} lagen",
|
||||
"pages_one": "{{count}} pagina",
|
||||
"pages_other": "{{count}} pagina's",
|
||||
"pages_alt": "Pagina {{pageNumber}}",
|
||||
"pages_loading": "Laden..."
|
||||
},
|
||||
"clone_to": {
|
||||
"clone_notes_to": "Kloon de notities naar...",
|
||||
"help_on_links": "Hulp op links",
|
||||
"notes_to_clone": "Notities om te klonen"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -959,7 +959,6 @@
|
||||
"download_button": "Pobierz",
|
||||
"mime": "MIME: ",
|
||||
"file_size": "Rozmiar pliku:",
|
||||
"preview": "Podgląd:",
|
||||
"preview_not_available": "Podgląd nie jest dostępny dla tego typu notatki."
|
||||
},
|
||||
"sort_child_notes": {
|
||||
@@ -1286,7 +1285,6 @@
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "Zmień ikonę notatki",
|
||||
"category": "Kategoria:",
|
||||
"search": "Szukaj:",
|
||||
"reset-default": "Przywróć domyślną ikonę"
|
||||
},
|
||||
|
||||
@@ -22,7 +22,16 @@
|
||||
"bundle-error": {
|
||||
"title": "Falha para carregar o script customizado",
|
||||
"message": "O script da nota com ID \"{{id}}\", intitulada \"{{title}}\", não pôde ser executado devido a:\n\n{{message}}"
|
||||
}
|
||||
},
|
||||
"widget-list-error": {
|
||||
"title": "Falha ao obter a lista de widgets do servidor"
|
||||
},
|
||||
"scripting-error": "Erro do script específicado: {{title}}",
|
||||
"open-script-note": "Abrir script da nota",
|
||||
"widget-render-error": {
|
||||
"title": "Falha do renderizar um widget React personalizado"
|
||||
},
|
||||
"widget-missing-parent": "Widget adaptado não tem a propriedade '{{property}}' mandatória definida.\n\nSe este script é para ser executado sem um element de UI, usar '#run=frontendStartup'."
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "Adicionar ligação",
|
||||
@@ -39,7 +48,10 @@
|
||||
"help_on_tree_prefix": "Ajuda sobre o prefixo da árvore de notas",
|
||||
"prefix": "Prefixo: ",
|
||||
"save": "Gravar",
|
||||
"branch_prefix_saved": "O prefixo de ramificação foi gravado."
|
||||
"branch_prefix_saved": "O prefixo de ramificação foi gravado.",
|
||||
"edit_branch_prefix_multiple": "Editar prefixo para {{count}} branches",
|
||||
"branch_prefix_saved_multiple": "Prefixo dos branches foi editado para {{count}} branches.",
|
||||
"affected_branches": "Alterados ({{count}}) branches:"
|
||||
},
|
||||
"bulk_actions": {
|
||||
"bulk_actions": "Ações em massa",
|
||||
@@ -104,7 +116,8 @@
|
||||
"export_status": "Estado da exportação",
|
||||
"export_in_progress": "Exportação em andamento: {{progressCount}}",
|
||||
"export_finished_successfully": "Exportação concluída com sucesso.",
|
||||
"format_pdf": "PDF – para impressão ou compartilhamento."
|
||||
"format_pdf": "PDF – para impressão ou compartilhamento.",
|
||||
"share-format": "HTML para publicação web - usa o mesmo tema que é usado para notas partilhadas, mas pode ser publicado como um site estatico."
|
||||
},
|
||||
"help": {
|
||||
"title": "Folha de Dicas",
|
||||
@@ -158,7 +171,8 @@
|
||||
"showSQLConsole": "mostrar console SQL",
|
||||
"other": "Outros",
|
||||
"quickSearch": "focar no campo de pesquisa rápida",
|
||||
"inPageSearch": "pesquisa na página"
|
||||
"inPageSearch": "pesquisa na página",
|
||||
"editShortcuts": "Editar atalhos do teclado"
|
||||
},
|
||||
"import": {
|
||||
"importIntoNote": "Importar para a nota",
|
||||
@@ -184,7 +198,8 @@
|
||||
},
|
||||
"import-status": "Estado da importação",
|
||||
"in-progress": "Importação em andamento: {{progress}}",
|
||||
"successful": "Importação concluída com sucesso."
|
||||
"successful": "Importação concluída com sucesso.",
|
||||
"importZipRecommendation": "Quando a importar ficheiro ZIP, a hierarquia de notas vai reflectir a estrutura da sub directoria dentro do ficheiro."
|
||||
},
|
||||
"include_note": {
|
||||
"dialog_title": "Incluir nota",
|
||||
@@ -199,7 +214,8 @@
|
||||
"info": {
|
||||
"modalTitle": "Mensagem informativa",
|
||||
"closeButton": "Fechar",
|
||||
"okButton": "OK"
|
||||
"okButton": "OK",
|
||||
"copy_to_clipboard": "Copiar para a área de transferência"
|
||||
},
|
||||
"jump_to_note": {
|
||||
"search_placeholder": "Pesquise uma nota pelo nome ou digite > para comandos...",
|
||||
@@ -274,8 +290,12 @@
|
||||
"download_button": "Descarregar",
|
||||
"mime": "MIME: ",
|
||||
"file_size": "Tamanho do ficheiro:",
|
||||
"preview": "Visualizar:",
|
||||
"preview_not_available": "A visualização não está disponível para este tipo de nota."
|
||||
"preview_not_available": "A visualização não está disponível para este tipo de nota.",
|
||||
"diff_on": "Mostrar diferenças",
|
||||
"diff_off": "Mostrar conteúdos",
|
||||
"diff_on_hint": "Carregar para mostrar diferenças da fonte da nota",
|
||||
"diff_off_hint": "Carregar para mostrar conteúdos da nota",
|
||||
"diff_not_available": "Diferenças não disponível."
|
||||
},
|
||||
"sort_child_notes": {
|
||||
"sort_children_by": "Ordenar notas filhas por...",
|
||||
@@ -586,7 +606,18 @@
|
||||
"september": "Setembro",
|
||||
"october": "Outubro",
|
||||
"november": "Novembro",
|
||||
"december": "Dezembro"
|
||||
"december": "Dezembro",
|
||||
"week": "Semana",
|
||||
"week_previous": "Semana anterior",
|
||||
"week_next": "Próxima semana",
|
||||
"month": "Mês",
|
||||
"month_previous": "Mês anterior",
|
||||
"month_next": "Próximo mês",
|
||||
"year": "Ano",
|
||||
"year_previous": "Ano anterior",
|
||||
"year_next": "Próximo ano",
|
||||
"list": "Lista",
|
||||
"today": "Hoje"
|
||||
},
|
||||
"close_pane_button": {
|
||||
"close_this_pane": "Fechar este painel"
|
||||
@@ -629,7 +660,9 @@
|
||||
"about": "Sobre o Trilium Notes",
|
||||
"logout": "Sair",
|
||||
"show-cheatsheet": "Exibir Cheatsheet",
|
||||
"toggle-zen-mode": "Modo Zen"
|
||||
"toggle-zen-mode": "Modo Zen",
|
||||
"new-version-available": "Nova actualização disponível",
|
||||
"download-update": "Obter versão {{latestVersion}}"
|
||||
},
|
||||
"zen_mode": {
|
||||
"button_exit": "Sair do Modo Zen"
|
||||
@@ -667,7 +700,14 @@
|
||||
"convert_into_attachment_failed": "A conversão da nota '{{title}}' falhou.",
|
||||
"convert_into_attachment_successful": "A nota '{{title}}' foi convertida para anexo.",
|
||||
"convert_into_attachment_prompt": "Tem certeza que quer converter a nota '{{title}}' num anexo da nota pai?",
|
||||
"print_pdf": "Exportar como PDF…"
|
||||
"print_pdf": "Exportar como PDF…",
|
||||
"open_note_on_server": "Abrir nota no servidor",
|
||||
"export_as_image": "Exportar como imagem",
|
||||
"note_map": "Mapa de notas",
|
||||
"advanced": "Avançadas",
|
||||
"view_revisions": "Revisões da nota...",
|
||||
"export_as_image_svg": "SVG (vectorial)",
|
||||
"export_as_image_png": "PNG (matricial)"
|
||||
},
|
||||
"onclick_button": {
|
||||
"no_click_handler": "Componente de botão '{{componentId}}' não possui manipulador de clique definido"
|
||||
@@ -713,20 +753,29 @@
|
||||
"zpetne_odkazy": {
|
||||
"relation": "relação",
|
||||
"backlink_one": "{{count}} Ligação Reversa",
|
||||
"backlink_many": "",
|
||||
"backlink_many": "{{count}} Ligações Reversas",
|
||||
"backlink_other": "{{count}} Ligações Reversas"
|
||||
},
|
||||
"mobile_detail_menu": {
|
||||
"insert_child_note": "Inserir nota filha",
|
||||
"delete_this_note": "Apagar esta nota",
|
||||
"error_cannot_get_branch_id": "Não foi possível obter o branchId para o notePath '{{notePath}} '",
|
||||
"error_unrecognized_command": "Comando não reconhecido {{command}}"
|
||||
"error_unrecognized_command": "Comando não reconhecido {{command}}",
|
||||
"note_revisions": "Revisões da nota"
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "Alterar ícone da nota",
|
||||
"category": "Categoria:",
|
||||
"search": "Pesquisa:",
|
||||
"reset-default": "Redefinir para o ícone padrão"
|
||||
"reset-default": "Redefinir para o ícone padrão",
|
||||
"filter": "Filtrar",
|
||||
"filter-none": "Todos os icons",
|
||||
"filter-default": "Icons default",
|
||||
"no_results": "Não foram encontrados icons.",
|
||||
"search_placeholder_filtered": "Procurar {{number}} icons no {{name}}",
|
||||
"icon_tooltip": "{{name}}\nPacote de icons: {{iconPack}}",
|
||||
"search_placeholder_one": "Procurar {{number}} icon nos {{count}} pacotes",
|
||||
"search_placeholder_many": "Procurar {{number}} icons em {{count}} pacotes",
|
||||
"search_placeholder_other": "Procurar {{number}} icons nos {{count}} pacotes"
|
||||
},
|
||||
"basic_properties": {
|
||||
"note_type": "Tipo da nota",
|
||||
@@ -747,7 +796,14 @@
|
||||
"calendar": "Calendário",
|
||||
"table": "Tabela",
|
||||
"geo-map": "Mapa geográfico",
|
||||
"board": "Quadro"
|
||||
"board": "Quadro",
|
||||
"expand_first_level": "Expandir descendentes directos",
|
||||
"presentation": "Apresentação",
|
||||
"expand_nth_level": "Expandir {{depth}} níveis",
|
||||
"expand_all_levels": "Expandir todos os níveis",
|
||||
"include_archived_notes": "Mostrar notas arquivadas",
|
||||
"expand_tooltip": "Expande a direcção dos descendentes desta colecção (um nível). Para mais opções, carregar na seta à direita.",
|
||||
"hide_child_notes": "Esconder notas descendentes na árvore"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "Ainda não há nenhuma nota editada neste dia…",
|
||||
@@ -780,7 +836,8 @@
|
||||
},
|
||||
"inherited_attribute_list": {
|
||||
"title": "Atributos Herdados",
|
||||
"no_inherited_attributes": "Nenhum atributo herdado."
|
||||
"no_inherited_attributes": "Nenhum atributo herdado.",
|
||||
"none": "Nenhum"
|
||||
},
|
||||
"note_info_widget": {
|
||||
"note_id": "ID da Nota",
|
||||
@@ -791,7 +848,9 @@
|
||||
"note_size_info": "O tamanho da nota fornece uma estimativa aproximada dos requisitos de armazenamento para esta nota. Leva em conta o conteúdo e o conteúdo das suas revisões de nota.",
|
||||
"calculate": "calcular",
|
||||
"subtree_size": "(tamanho da subárvore: {{size}} em {{count}} notas)",
|
||||
"title": "Informações da nota"
|
||||
"title": "Informações da nota",
|
||||
"mime": "Tipo MIME",
|
||||
"show_similar_notes": "Mostrar notas semelhantes"
|
||||
},
|
||||
"note_map": {
|
||||
"open_full": "Expandir completamente",
|
||||
@@ -854,7 +913,8 @@
|
||||
"search_parameters": "Parâmetros de Pesquisa",
|
||||
"unknown_search_option": "Opção de pesquisa desconhecida {{searchOptionName}}",
|
||||
"search_note_saved": "Nota de pesquisa foi gravada em {{- notePathTitle}}",
|
||||
"actions_executed": "As ações foram executadas."
|
||||
"actions_executed": "As ações foram executadas.",
|
||||
"view_options": "Ver opções:"
|
||||
},
|
||||
"similar_notes": {
|
||||
"title": "Notas Similares",
|
||||
@@ -948,14 +1008,22 @@
|
||||
"no_attachments": "Esta nota não possuí anexos."
|
||||
},
|
||||
"book": {
|
||||
"no_children_help": "Esta coleção não possui nenhum nota filha, então não há nada para exibir. Veja <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> para pormenores."
|
||||
"no_children_help": "Esta coleção não possui nenhum nota filha, então não há nada para exibir. Veja <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> para pormenores.",
|
||||
"drag_locked_title": "Bloqueado para edição",
|
||||
"drag_locked_message": "Arrastar não permitida pois a coleção está bloqueada para edição."
|
||||
},
|
||||
"editable_code": {
|
||||
"placeholder": "Digite o conteúdo da sua nota de código aqui…"
|
||||
},
|
||||
"editable_text": {
|
||||
"placeholder": "Digite o conteúdo da sua nota aqui…",
|
||||
"auto-detect-language": "Detetado automaticamente"
|
||||
"auto-detect-language": "Detetado automaticamente",
|
||||
"editor_crashed_title": "O editor de texto quebrou",
|
||||
"editor_crashed_details_button": "Ver mais detalhes...",
|
||||
"editor_crashed_details_title": "Informação técnica",
|
||||
"editor_crashed_details_intro": "Se teve este erro várias vezes, considerer reportar no GitHub disponibilizando a informação abaixo.",
|
||||
"editor_crashed_content": "O seu conteudo foi recuperado com sucesso, mas alguns das alterações mais recentes podem não ter sido gravadas.",
|
||||
"keeps-crashing": "Componente de edição a rebentar continuamente. Por favor tentar reiniciar Trilium. Se o problema persistir, considere abrir um bug report."
|
||||
},
|
||||
"empty": {
|
||||
"open_note_instruction": "Abra uma nota a digitar o título da nota no campo abaixo ou escolha uma nota na árvore.",
|
||||
@@ -1083,7 +1151,8 @@
|
||||
"title": "Largura do Conteúdo",
|
||||
"default_description": "Por padrão, o Trilium limita a largura máxima do conteúdo para melhorar a legibilidade em janelas maximizadas em ecrãs largos.",
|
||||
"max_width_label": "Largura máxima do conteúdo",
|
||||
"max_width_unit": "pixels"
|
||||
"max_width_unit": "pixels",
|
||||
"centerContent": "Manter conteúdo centrado"
|
||||
},
|
||||
"native_title_bar": {
|
||||
"title": "Barra de Título Nativa (requer recarregar a app)",
|
||||
@@ -1115,7 +1184,9 @@
|
||||
"title": "Desempenho",
|
||||
"enable-motion": "Ativar transições e animações",
|
||||
"enable-shadows": "Ativar sombras",
|
||||
"enable-backdrop-effects": "Ativar efeitos de fundo para menus, popups e painéis"
|
||||
"enable-backdrop-effects": "Ativar efeitos de fundo para menus, popups e painéis",
|
||||
"enable-smooth-scroll": "Activar deslocamento suave",
|
||||
"app-restart-required": "(é necessário reiniciar a aplicação para aplicar as alterações)"
|
||||
},
|
||||
"ai_llm": {
|
||||
"not_started": "Não iniciado",
|
||||
@@ -1274,7 +1345,10 @@
|
||||
"title": "Editor"
|
||||
},
|
||||
"code_mime_types": {
|
||||
"title": "Tipos MIME disponíveis no dropdown"
|
||||
"title": "Tipos MIME disponíveis no dropdown",
|
||||
"tooltip_syntax_highlighting": "Destaque de sintaxe",
|
||||
"tooltip_code_block_syntax": "Blocos de código nas notas de texto",
|
||||
"tooltip_code_note_syntax": "Notas de código"
|
||||
},
|
||||
"vim_key_bindings": {
|
||||
"use_vim_keybindings_in_code_notes": "Atribuições de teclas do Vim",
|
||||
@@ -1394,7 +1468,13 @@
|
||||
"min-days-in-first-week": "Mínimo de dias da primeira semana",
|
||||
"first-week-info": "Primeira semana que contenha a primeira Quinta-feira do ano é baseado na <a href=\"https://en.wikipedia.org/wiki/ISO_week_date#First_week\">ISO 8601</a>.",
|
||||
"first-week-warning": "Alterar as opções de primeira semana pode causar duplicidade nas Notas Semanais existentes e estas Notas não serão atualizadas de acordo.",
|
||||
"formatting-locale": "Formato de data e número"
|
||||
"formatting-locale": "Formato de data e número",
|
||||
"tuesday": "Terça-feira",
|
||||
"wednesday": "Quarta-feira",
|
||||
"thursday": "Quinta-feira",
|
||||
"friday": "Sexta-feira",
|
||||
"saturday": "Sábado",
|
||||
"formatting-locale-auto": "Baseado na linguagem da aplicação"
|
||||
},
|
||||
"backup": {
|
||||
"automatic_backup": "Backup automático",
|
||||
@@ -1487,7 +1567,8 @@
|
||||
"oauth_description_warning": "Para ativar o OAuth/OpenID, precisa definir a URL base do OAuth/OpenID, o client ID e o client secret no ficheiro config.ini e reiniciar a aplicação. Se quiser configurar via variáveis de ambiente, defina TRILIUM_OAUTH_BASE_URL, TRILIUM_OAUTH_CLIENT_ID e TRILIUM_OAUTH_CLIENT_SECRET.",
|
||||
"oauth_user_account": "Conta do Utilizador: ",
|
||||
"oauth_user_email": "E-mail do Utilizador: ",
|
||||
"oauth_user_not_logged_in": "Não está logado!"
|
||||
"oauth_user_not_logged_in": "Não está logado!",
|
||||
"oauth_missing_vars": "Configurações em falta: {{-variables}}"
|
||||
},
|
||||
"shortcuts": {
|
||||
"keyboard_shortcuts": "Atalhos de Teclado",
|
||||
@@ -1587,7 +1668,12 @@
|
||||
"apply-bulk-actions": "Aplicar ações em massa",
|
||||
"converted-to-attachments": "{{count}} notas foram convertidas em anexos.",
|
||||
"convert-to-attachment-confirm": "Tem certeza que deseja converter as notas selecionadas em anexos das suas notas-pai?",
|
||||
"open-in-popup": "Edição rápida"
|
||||
"open-in-popup": "Edição rápida",
|
||||
"open-in-a-new-window": "Abrir numa nova janela",
|
||||
"archive": "Arquivar",
|
||||
"unarchive": "Retirar do arquivo",
|
||||
"hide-subtree": "Esconder sub-árvore",
|
||||
"show-subtree": "Mostrar sub-árvore"
|
||||
},
|
||||
"shared_info": {
|
||||
"shared_publicly": "Esta nota é partilhada publicamente em {{- link}}.",
|
||||
@@ -1648,7 +1734,13 @@
|
||||
},
|
||||
"highlights_list_2": {
|
||||
"title": "Lista de Destaques",
|
||||
"options": "Opções"
|
||||
"options": "Opções",
|
||||
"no_highlights": "Sem destaques encontrados.",
|
||||
"menu_configure": "Configurar lista de destaques...",
|
||||
"modal_title": "Configurar list de destaques",
|
||||
"title_with_count_one": "{{count}} destaque",
|
||||
"title_with_count_many": "{{count}} destaques",
|
||||
"title_with_count_other": "{{count}} destaques"
|
||||
},
|
||||
"quick-search": {
|
||||
"placeholder": "Pesquisa rápida",
|
||||
@@ -1671,16 +1763,43 @@
|
||||
"refresh-saved-search-results": "Atualizar resultados de pesquisa gravados",
|
||||
"create-child-note": "Criar nota filha",
|
||||
"unhoist": "Desafixar",
|
||||
"toggle-sidebar": "Alternar barra lateral"
|
||||
"toggle-sidebar": "Alternar barra lateral",
|
||||
"dropping-not-allowed": "Largar notas nesta localização não é permitida",
|
||||
"clone-indicator-tooltip": "Esta nota tem {{- count}} ascendentes: {{- parents}}",
|
||||
"shared-indicator-tooltip": "Esta nota está partilhada publicamente",
|
||||
"shared-indicator-tooltip-with-url": "Esta nota está partilhada publicamente em: {{- url}}",
|
||||
"subtree-hidden-moved-title": "Adicionar ao {{title}}",
|
||||
"subtree-hidden-moved-description-collection": "Esta colecção esconde as notas descendentes na árvore.",
|
||||
"subtree-hidden-moved-description-other": "Notas descendentes estão escondidades na árvore para esta nota.",
|
||||
"subtree-hidden-tooltip_one": "{{count}} nota descendentes escondidas da árvore",
|
||||
"subtree-hidden-tooltip_many": "{{count}} notas descendentes escondidas da árvore",
|
||||
"subtree-hidden-tooltip_other": "{{count}} notas descendentes escondidas da árvore",
|
||||
"clone-indicator-tooltip-single": "Esta nota está clonada (1 additional parent: {{- parent}})"
|
||||
},
|
||||
"title_bar_buttons": {
|
||||
"window-on-top": "Manter Janela no Topo"
|
||||
},
|
||||
"note_detail": {
|
||||
"could_not_find_typewidget": "Não foi possível encontrar typeWidget para o tipo '{{type}}'"
|
||||
"could_not_find_typewidget": "Não foi possível encontrar typeWidget para o tipo '{{type}}'",
|
||||
"print_report_collection_details_button": "Ver detalhes",
|
||||
"printing": "Impressão em progresso...",
|
||||
"printing_pdf": "Exportação PDF em progresso...",
|
||||
"print_report_title": "Imprimir relatório",
|
||||
"print_report_collection_details_ignored_notes": "Ignorar notas",
|
||||
"print_report_collection_content_one": "{{count}} nota na colecção não pode ser impressa porque não é suportado ou está protegida.",
|
||||
"print_report_collection_content_many": "{{count}} notas na colecção não podem ser impressas porque não é suportado ou estão protegidas.",
|
||||
"print_report_collection_content_other": "{{count}} notas na colecção não podem ser impressas porque não é suportado ou estão protegidas."
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "digite o título da nota aqui..."
|
||||
"placeholder": "digite o título da nota aqui...",
|
||||
"promoted_attributes": "Atributos destacados",
|
||||
"created_on": "Criado em <Value />",
|
||||
"last_modified": "Modificado em <Value />",
|
||||
"note_type_switcher_label": "Alterar de {{type}} para:",
|
||||
"note_type_switcher_others": "Outro tipo de nota",
|
||||
"note_type_switcher_templates": "Template",
|
||||
"note_type_switcher_collection": "Colecção",
|
||||
"edited_notes": "Notas editadas neste dia"
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "Nenhuma nota encontrada para os parâmetros de pesquisa digitados.",
|
||||
@@ -1709,7 +1828,8 @@
|
||||
},
|
||||
"toc": {
|
||||
"table_of_contents": "Tabela de Conteúdos",
|
||||
"options": "Opções"
|
||||
"options": "Opções",
|
||||
"no_headings": "Sem cabeçalhos."
|
||||
},
|
||||
"watched_file_update_status": {
|
||||
"file_last_modified": "O ficheiro <code class=\"file-path\"></code> foi modificado pela última vez em <span class=\"file-last-modified\"></span>.",
|
||||
@@ -1752,7 +1872,9 @@
|
||||
"ws": {
|
||||
"sync-check-failed": "A verificação de sincronização falhou!",
|
||||
"consistency-checks-failed": "A verificação de consistência falhou! Veja os logs para pormenores.",
|
||||
"encountered-error": "Encontrado o erro \"{{message}}\", verifique o console."
|
||||
"encountered-error": "Encontrado o erro \"{{message}}\", verifique o console.",
|
||||
"lost-websocket-connection-title": "Perdida conexão com o servidor",
|
||||
"lost-websocket-connection-message": "Verifique a configuração da proxy inversa (e.g. nginx ou Apache) para assegurar conexões WebSocket estão permitidas e não bloqueadas."
|
||||
},
|
||||
"hoisted_note": {
|
||||
"confirm_unhoisting": "A nota solicitada '{{requestedNote}}' está fora da árvore da nota fixada '{{hoistedNote}}' e precisa desafixar para aceder a nota. Quer prosseguir e desafixar?"
|
||||
@@ -1808,7 +1930,8 @@
|
||||
"copy-link": "Copiar ligação",
|
||||
"paste": "Colar",
|
||||
"paste-as-plain-text": "Colar como texto sem formatação",
|
||||
"search_online": "Pesquisar por \"{{term}}\" com {{searchEngine}}"
|
||||
"search_online": "Pesquisar por \"{{term}}\" com {{searchEngine}}",
|
||||
"search_in_trilium": "A procurar \"{{term}}\" no Trilium"
|
||||
},
|
||||
"image_context_menu": {
|
||||
"copy_reference_to_clipboard": "Copiar referência para a área de transferência",
|
||||
@@ -1818,7 +1941,8 @@
|
||||
"open_note_in_new_tab": "Abrir nota em nova guia",
|
||||
"open_note_in_new_split": "Abrir nota em nova divisão",
|
||||
"open_note_in_new_window": "Abrir nota em nova janela",
|
||||
"open_note_in_popup": "Edição rápida"
|
||||
"open_note_in_popup": "Edição rápida",
|
||||
"open_note_in_other_split": "Abrir nota noutro separador"
|
||||
},
|
||||
"electron_integration": {
|
||||
"desktop-application": "Aplicação Desktop",
|
||||
@@ -1826,7 +1950,8 @@
|
||||
"native-title-bar-description": "Para Windows e macOS, manter a barra de título nativa desativada faz a aplicação parecer mais compacta. No Linux, manter a barra de título nativa ativada faz a aplicação se integrar melhor com o restante do sistema.",
|
||||
"background-effects": "Ativar efeitos de fundo (apenas Windows 11)",
|
||||
"restart-app-button": "Reiniciar a aplicação para ver as alterações",
|
||||
"zoom-factor": "Fator de Zoom"
|
||||
"zoom-factor": "Fator de Zoom",
|
||||
"background-effects-description": "O Mica adiciona um desfoque, fundo estiloso as janelas da aplicação, criando uma profundidade e aspecto moderno. \"Barra de titulo nativa\" deve estar inactiva."
|
||||
},
|
||||
"note_autocomplete": {
|
||||
"search-for": "Pesquisar por \"{{term}}\"",
|
||||
@@ -1886,7 +2011,8 @@
|
||||
},
|
||||
"note_language": {
|
||||
"not_set": "Não atribuído",
|
||||
"configure-languages": "Configurar idiomas..."
|
||||
"configure-languages": "Configurar idiomas...",
|
||||
"help-on-languages": "Ajuda nas linguagens de conteúdos..."
|
||||
},
|
||||
"content_language": {
|
||||
"title": "Idiomas do conteúdo",
|
||||
@@ -1904,7 +2030,8 @@
|
||||
"button_title": "Exportar diagrama como PNG"
|
||||
},
|
||||
"svg": {
|
||||
"export_to_png": "O diagrama não pôde ser exportado como PNG."
|
||||
"export_to_png": "O diagrama não pôde ser exportado como PNG.",
|
||||
"export_to_svg": "O diagrama não pode ser exportado para SVG."
|
||||
},
|
||||
"code_theme": {
|
||||
"title": "Aparência",
|
||||
@@ -1923,7 +2050,11 @@
|
||||
"editorfeatures": {
|
||||
"title": "Recursos",
|
||||
"emoji_completion_enabled": "Ativar auto-completar de Emoji",
|
||||
"note_completion_enabled": "Ativar auto-completar de notas"
|
||||
"note_completion_enabled": "Ativar auto-completar de notas",
|
||||
"emoji_completion_description": "Se activo, emojis podem ser facilmente inseridos em texto ao pressionar `:`, seguido do nome de um emoji.",
|
||||
"note_completion_description": "Se activo, links para notas podem ser criadas ao escrever `@` seguido do titulo de uma nota.",
|
||||
"slash_commands_enabled": "Activar comentários simples",
|
||||
"slash_commands_description": "Se activo, editar comandos como inserir quebras de linha ou cabeçalhos podem ser activado/inactivado ao escrever `/`."
|
||||
},
|
||||
"table_view": {
|
||||
"new-row": "Nova linha",
|
||||
@@ -1965,7 +2096,16 @@
|
||||
"delete-column": "Apagar coluna",
|
||||
"delete-column-confirmation": "Tem certeza que deseja apagar esta coluna? O atributo correspondente também será apagado de todas as notas abaixo desta coluna.",
|
||||
"new-item": "Novo elemento",
|
||||
"add-column": "Adicionar Coluna"
|
||||
"add-column": "Adicionar Coluna",
|
||||
"delete-note": "Apagar nota...",
|
||||
"remove-from-board": "Remover do quadro",
|
||||
"archive-note": "Arquivar nota",
|
||||
"new-item-placeholder": "Inserir titulo da nota...",
|
||||
"add-column-placeholder": "Inserir nome da coluna...",
|
||||
"edit-note-title": "Clicar para editar o titulo da nota",
|
||||
"unarchive-note": "Remover nota do arquivo",
|
||||
"edit-column-title": "Click para editar titulo da coluna",
|
||||
"column-already-exists": "Esta coluna já existe no quadro."
|
||||
},
|
||||
"command_palette": {
|
||||
"tree-action-name": "Árvore: {{name}}",
|
||||
@@ -1996,16 +2136,146 @@
|
||||
"background_effects_title": "Efeitos de fundo estão estáveis agora",
|
||||
"background_effects_message": "Em dispositivos Windows, efeitos de fundo estão estáveis agora. Os efeitos de fundo adicionam um toque de cor à interface do utilizador borrando o plano de fundo atrás dela. Esta técnica também é usada noutras aplicações como o Windows Explorer.",
|
||||
"background_effects_button": "Ativar os efeitos de fundo",
|
||||
"dismiss": "Dispensar"
|
||||
"dismiss": "Dispensar",
|
||||
"new_layout_title": "Novo titulo do layout",
|
||||
"new_layout_button": "Mais informação",
|
||||
"new_layout_message": "Estamos a introduzir um layout modernizado para o Trilium. A faixa foi removida e está integrada na interface principal, com uma nota barra de estado e secções expansíveis (como as propriedades próprias) a tomar papéis principais.\n\nO novo layout está activo por defeito, e pode ser temporáriamente disabilidade em Opções → Aparência."
|
||||
},
|
||||
"settings": {
|
||||
"related_settings": "Configurações relacionadas"
|
||||
},
|
||||
"settings_appearance": {
|
||||
"related_code_blocks": "Esquema de cores para blocos de código em notas de texto",
|
||||
"related_code_notes": "Esquema de cores para notas de código"
|
||||
"related_code_notes": "Esquema de cores para notas de código",
|
||||
"ui": "Interface do utilizador",
|
||||
"ui_old_layout": "Layout antigo",
|
||||
"ui_new_layout": "Nova aparência"
|
||||
},
|
||||
"units": {
|
||||
"percentage": "%"
|
||||
},
|
||||
"experimental_features": {
|
||||
"title": "Opções experimentais",
|
||||
"new_layout_name": "Novo layout",
|
||||
"new_layout_description": "Experimente o novo layout para um aspecto moderno e melhor estabilidade. Sujeito a grandes alterações nas próximas publicações.",
|
||||
"disclaimer": "Estas opções são experimentais e podem causar instabilidade. Usar com cuidado."
|
||||
},
|
||||
"read-only-info": {
|
||||
"read-only-note": "Actualmente a ver em modo de leitura.",
|
||||
"edit-note": "Editar nota",
|
||||
"auto-read-only-note": "Esta nota está a ser mostrada em modo de leitura para um carregamento mais rápido."
|
||||
},
|
||||
"presentation_view": {
|
||||
"edit-slide": "Editar este slide",
|
||||
"start-presentation": "Iniciar apresentação",
|
||||
"slide-overview": "Alternar visão geral dos slides"
|
||||
},
|
||||
"calendar_view": {
|
||||
"delete_note": "Apagar nota..."
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "Página {{startIndex}} - {{endIndex}}",
|
||||
"total_notes": "{{count}} notas"
|
||||
},
|
||||
"collections": {
|
||||
"rendering_error": "Sem possíbilidade de mostrar conteúdos devido a um erro."
|
||||
},
|
||||
"note-color": {
|
||||
"clear-color": "Remover cor da nota",
|
||||
"set-color": "Atribuir cor da nota",
|
||||
"set-custom-color": "Afectar cor personalizada da nota"
|
||||
},
|
||||
"popup-editor": {
|
||||
"maximize": "Alterar para editor completo"
|
||||
},
|
||||
"server": {
|
||||
"unknown_http_error_title": "Erro na comunicação com servidor",
|
||||
"unknown_http_error_content": "Código de estado: {{statusCode}}\nURL: {{method}} {{url}}\nMessagem: {{message}}",
|
||||
"traefik_blocks_requests": "Se está a usar o Traefik, este introduz uma alteração que afecta a comunicação com o servidor."
|
||||
},
|
||||
"tab_history_navigation_buttons": {
|
||||
"go-back": "Ir para a nota anterior",
|
||||
"go-forward": "Ir para nota seguinte"
|
||||
},
|
||||
"breadcrumb": {
|
||||
"hoisted_badge": "Içado",
|
||||
"workspace_badge": "Área de trabalho",
|
||||
"scroll_to_top_title": "Saltar para o início da nota",
|
||||
"create_new_note": "Criar nova nota descendente",
|
||||
"empty_hide_archived_notes": "Esconder notas arquivadas",
|
||||
"hoisted_badge_title": "Retirar de içado"
|
||||
},
|
||||
"breadcrumb_badges": {
|
||||
"read_only_explicit": "Modo de leitura",
|
||||
"read_only_auto": "Modo de leitura automático",
|
||||
"read_only_temporarily_disabled": "Editável temporáriamente",
|
||||
"read_only_auto_description": "Esta nota foi automaticamente colocada em modo de leitura por razões de performance. Este limite automatico é ajustável nas configurações.\n\nClicar para editar temporáriamente.",
|
||||
"read_only_temporarily_disabled_description": "Esta nota está editável, mas normalmente está em modo de leitura. A nova vai regressar para mode de leitura assim que navegar para outra nota.\n\nClicar para reactivar o modo de leitura.",
|
||||
"read_only_explicit_description": "Esta nota foi manualmente colocada em modo de leitura.\nClicar para editar temporáriamente.",
|
||||
"shared_publicly": "Partilhado publicamente",
|
||||
"shared_locally": "Partilhado localmente",
|
||||
"shared_copy_to_clipboard": "Copiar link para a área de transferência",
|
||||
"shared_open_in_browser": "Abrir link no browser",
|
||||
"shared_unshare": "Remover partilha",
|
||||
"clipped_note_description": "Esta nota foi retirar do {{url}}.\n\nClicar para navegar no código fonte da página.",
|
||||
"clipped_note": "Web clipe",
|
||||
"execute_script": "Correr script",
|
||||
"execute_script_description": "Esta nota é uma nota de script. Clicar para executar o script.",
|
||||
"execute_sql": "Correr SQL",
|
||||
"execute_sql_description": "Esta nota é uma nota de SQL. Clicar para executar script SQL.",
|
||||
"save_status_saved": "Guardar",
|
||||
"save_status_saving": "A guardar...",
|
||||
"save_status_unsaved": "Não gravado",
|
||||
"save_status_error": "Gravar falhou",
|
||||
"save_status_saving_tooltip": "Alterações estão a ser guardadas",
|
||||
"save_status_unsaved_tooltip": "Existem alterações não guardadas. Serão guardadas automaticamente em breve.",
|
||||
"save_status_error_tooltip": "Ocorreu um erro ao guardar a nota. Se possível, tente copiar os conteúdos da nota para outro local e reiniciar a aplicação."
|
||||
},
|
||||
"status_bar": {
|
||||
"language_title": "Alterar lingua do conteúdo",
|
||||
"note_info_title": "Ver informação da nota (e.g., datas, tamanho da nota)",
|
||||
"backlinks_one": "{{count}} backlink",
|
||||
"backlinks_many": "{{count}} backlinks",
|
||||
"backlinks_other": "{{count}} backlinks",
|
||||
"backlinks_title_one": "Ver backlink",
|
||||
"backlinks_title_many": "Ver backlinks",
|
||||
"backlinks_title_other": "Ver backlinks",
|
||||
"attachments_one": "{{count}} anexo",
|
||||
"attachments_many": "{{count}} anexos",
|
||||
"attachments_other": "{{count}} anexos",
|
||||
"attachments_title_one": "Ver anexo num novo separador",
|
||||
"attachments_title_many": "Ver anexos num novo separador",
|
||||
"attachments_title_other": "Ver anexos num novo separador",
|
||||
"attributes_one": "{{count}} atributo",
|
||||
"attributes_many": "{{count}} atributos",
|
||||
"attributes_other": "{{count}} atributos",
|
||||
"attributes_title": "Atributos próprios e herdados",
|
||||
"note_paths_one": "{{count}} caminho",
|
||||
"note_paths_many": "{{count}} caminhos",
|
||||
"note_paths_other": "{{count}} caminhos",
|
||||
"note_paths_title": "Caminhos da nota",
|
||||
"code_note_switcher": "Alterar modo de linguagem"
|
||||
},
|
||||
"attributes_panel": {
|
||||
"title": "Atributos da nota"
|
||||
},
|
||||
"right_pane": {
|
||||
"empty_message": "Nada para mostrar nesta nota",
|
||||
"empty_button": "Esconder painél",
|
||||
"toggle": "Alterar painel direito",
|
||||
"custom_widget_go_to_source": "Ir para código fonte"
|
||||
},
|
||||
"pdf": {
|
||||
"attachments_one": "{{count}} anexo pdf",
|
||||
"attachments_many": "{{count}} anexos pdf",
|
||||
"attachments_other": "{{count}} anexos pdf",
|
||||
"layers_one": "{{count}} camada",
|
||||
"layers_many": "{{count}} camadas",
|
||||
"layers_other": "{{count}} camadas",
|
||||
"pages_one": "{{count}} página",
|
||||
"pages_many": "{{count}} páginas",
|
||||
"pages_other": "{{count}} páginas",
|
||||
"pages_alt": "Página {{pageNumber}}",
|
||||
"pages_loading": "A carregar..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -439,7 +439,6 @@
|
||||
"download_button": "Download",
|
||||
"mime": "MIME: ",
|
||||
"file_size": "Tamanho do arquivo:",
|
||||
"preview": "Visualizar:",
|
||||
"preview_not_available": "A visualização não está disponível para este tipo de nota.",
|
||||
"diff_on": "Exibir diferença",
|
||||
"diff_off": "Exibir conteúdo",
|
||||
@@ -1008,7 +1007,6 @@
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "Alterar ícone da nota",
|
||||
"category": "Categoria:",
|
||||
"search": "Busca:",
|
||||
"reset-default": "Redefinir para o ícone padrão"
|
||||
},
|
||||
|
||||
@@ -1103,7 +1103,6 @@
|
||||
"mime": "MIME: ",
|
||||
"no_revisions": "Nu există încă nicio revizie pentru această notiță...",
|
||||
"note_revisions": "Revizii ale notiței",
|
||||
"preview": "Previzualizare:",
|
||||
"preview_not_available": "Nu este disponibilă o previzualizare pentru acest tip de notiță.",
|
||||
"restore_button": "Restaurează",
|
||||
"revision_deleted": "Revizia notiței a fost ștearsă.",
|
||||
@@ -1483,7 +1482,6 @@
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "Schimbă iconița notiței",
|
||||
"category": "Categorie:",
|
||||
"reset-default": "Resetează la iconița implicită",
|
||||
"search": "Căutare:"
|
||||
},
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"widget-render-error": {
|
||||
"title": "Не удалось отобразить пользовательский React виджет"
|
||||
},
|
||||
"widget-missing-parent": "В пользовательском виджете не определено обязательное свойство '{{property}}'.",
|
||||
"widget-missing-parent": "В пользовательском виджете не определено обязательное свойство '{{property}}'.\n\nЕсли этот скрипт предназначен для запуска без элемента пользовательского интерфейса, используйте '#run=frontendStartup'.",
|
||||
"open-script-note": "Открыть заметку со скриптом",
|
||||
"scripting-error": "Ошибка пользовательского скрипта: {{title}}"
|
||||
},
|
||||
@@ -387,7 +387,6 @@
|
||||
"revision_deleted": "Версия заметки была удалена.",
|
||||
"download_button": "Скачать",
|
||||
"file_size": "Размер файла:",
|
||||
"preview": "Предпросмотр:",
|
||||
"preview_not_available": "Предпосмотр недоступен для заметки этого типа.",
|
||||
"mime": "MIME: ",
|
||||
"settings": "Настройка версионирования заметок",
|
||||
@@ -1010,10 +1009,18 @@
|
||||
"backlink_many": "{{count}} обратных ссылок"
|
||||
},
|
||||
"note_icon": {
|
||||
"category": "Категория:",
|
||||
"search": "Поиск:",
|
||||
"change_note_icon": "Изменить иконку заметки",
|
||||
"reset-default": "Сбросить к значку по умолчанию"
|
||||
"reset-default": "Сбросить к значку по умолчанию",
|
||||
"no_results": "Иконки не найдены.",
|
||||
"icon_tooltip": "{{name}}\nНабор иконок: {{iconPack}}",
|
||||
"filter-default": "Иконки по-умолчанию",
|
||||
"filter-none": "Все иконки",
|
||||
"filter": "Фильтр",
|
||||
"search_placeholder_filtered": "Поиск {{number}} иконок в {{name}}",
|
||||
"search_placeholder_one": "Поиск {{number}} иконки среди {{count}} наборов",
|
||||
"search_placeholder_few": "Поиск {{number}} иконок среди {{count}} наборов",
|
||||
"search_placeholder_many": "Поиск {{number}} иконок среди {{count}} наборов"
|
||||
},
|
||||
"basic_properties": {
|
||||
"editable": "Изменяемое",
|
||||
@@ -2026,7 +2033,7 @@
|
||||
"lost-websocket-connection-message": "Проверьте конфигурацию обратного прокси (например, nginx или Apache), чтобы убедиться, что соединения WebSocket должным образом разрешены и не заблокированы."
|
||||
},
|
||||
"attachment_detail_2": {
|
||||
"role_and_size": "Роль: {{role}}, Размер: {{size}}",
|
||||
"role_and_size": "Роль: {{role}}, размер: {{size}}, MIME: {{- mimeType}}",
|
||||
"unrecognized_role": "Нераспознанная роль вложения '{{role}}'.",
|
||||
"link_copied": "Ссылка на вложение скопирована в буфер обмена.",
|
||||
"will_be_deleted_soon": "Это вложение скоро будет автоматически удалено",
|
||||
@@ -2112,7 +2119,13 @@
|
||||
"note_detail": {
|
||||
"could_not_find_typewidget": "Не удалось найти typeWidget для типа '{{type}}'",
|
||||
"printing_pdf": "Выполняется экспорт PDF...",
|
||||
"printing": "Выполняется печать..."
|
||||
"printing": "Выполняется печать...",
|
||||
"print_report_title": "Отчет по печати",
|
||||
"print_report_collection_content_one": "{{count}} заметка в коллекции не удалось распечатать, поскольку она не поддерживается или защищена.",
|
||||
"print_report_collection_content_few": "{{count}} заметки в коллекции не удалось распечатать, поскольку они не поддерживаются или защищены.",
|
||||
"print_report_collection_content_many": "{{count}} заметок в коллекции не удалось распечатать, поскольку они не поддерживаются или защищены.",
|
||||
"print_report_collection_details_button": "Подробнее",
|
||||
"print_report_collection_details_ignored_notes": "Пропущенные заметки"
|
||||
},
|
||||
"book": {
|
||||
"no_children_help": "В этой коллекции нет дочерних заметок, поэтому отображать нечего. Подробности см. в <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a>.",
|
||||
|
||||
@@ -271,7 +271,6 @@
|
||||
"download_button": "Preuzmi",
|
||||
"mime": "MIME: ",
|
||||
"file_size": "Veličina datoteke:",
|
||||
"preview": "Pregled:",
|
||||
"preview_not_available": "Pregled nije dostupan za ovaj tip beleške."
|
||||
},
|
||||
"sort_child_notes": {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
},
|
||||
"bundle-error": {
|
||||
"title": "載入自訂腳本失敗",
|
||||
"message": "來自 ID 為 \"{{id}}\"、標題為 \"{{title}}\" 的筆記的腳本因以下原因無法執行:\n\n{{message}}"
|
||||
"message": "腳本因以下原因無法執行:\n\n{{message}}"
|
||||
},
|
||||
"widget-list-error": {
|
||||
"title": "無法從伺服器取得元件清單"
|
||||
@@ -29,8 +29,9 @@
|
||||
"widget-render-error": {
|
||||
"title": "無法渲染自訂 React 元件"
|
||||
},
|
||||
"widget-missing-parent": "自訂元件未定義強制性的 \"{{property}}\" 屬性。",
|
||||
"open-script-note": "打開腳本筆記"
|
||||
"widget-missing-parent": "自訂元件未定義強制性的 \"{{property}}\" 屬性。\n\n若此腳本需在無 UI 的情況下執行,請改用 \"#run=frontendStartup\"。",
|
||||
"open-script-note": "打開腳本筆記",
|
||||
"scripting-error": "自訂腳本錯誤:{{title}}"
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "新增連結",
|
||||
@@ -287,7 +288,6 @@
|
||||
"download_button": "下載",
|
||||
"mime": "MIME類型: ",
|
||||
"file_size": "檔案大小:",
|
||||
"preview": "預覽:",
|
||||
"preview_not_available": "無法預覽此類型的筆記。",
|
||||
"restore_button": "還原",
|
||||
"delete_button": "刪除",
|
||||
@@ -761,9 +761,16 @@
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "更改筆記圖標",
|
||||
"category": "類別:",
|
||||
"search": "搜尋:",
|
||||
"reset-default": "重置為預設圖標"
|
||||
"reset-default": "重置為預設圖標",
|
||||
"search_placeholder_one": "在 {{count}} 個圖示包中搜尋 {{number}} 個圖示",
|
||||
"search_placeholder_other": "",
|
||||
"search_placeholder_filtered": "在 {{name}} 中搜尋 {{number}} 個圖示",
|
||||
"filter": "篩選",
|
||||
"filter-none": "所有圖示",
|
||||
"filter-default": "預設圖示",
|
||||
"icon_tooltip": "{{name}}\n圖示包:{{iconPack}}",
|
||||
"no_results": "找不到圖示。"
|
||||
},
|
||||
"basic_properties": {
|
||||
"note_type": "筆記類型",
|
||||
@@ -790,7 +797,8 @@
|
||||
"expand_tooltip": "展開此集合的直接子級(單層深度)。按下右側箭頭以查看更多選項。",
|
||||
"expand_first_level": "展開直接子級",
|
||||
"expand_nth_level": "展開 {{depth}} 層",
|
||||
"expand_all_levels": "展開所有層級"
|
||||
"expand_all_levels": "展開所有層級",
|
||||
"hide_child_notes": "隱藏樹中的子筆記"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "今天還沒有編輯過的筆記...",
|
||||
@@ -1405,7 +1413,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}}'。"
|
||||
},
|
||||
@@ -1459,7 +1467,10 @@
|
||||
"duplicate": "複製副本",
|
||||
"open-in-popup": "快速編輯",
|
||||
"archive": "封存",
|
||||
"unarchive": "解除封存"
|
||||
"unarchive": "解除封存",
|
||||
"open-in-a-new-window": "在新視窗打開",
|
||||
"hide-subtree": "隱藏子階層",
|
||||
"show-subtree": "顯示子階層"
|
||||
},
|
||||
"shared_info": {
|
||||
"help_link": "如需幫助,請訪問 <a href=\"https://triliumnext.github.io/Docs/Wiki/sharing.html\">wiki</a>。",
|
||||
@@ -1549,7 +1560,15 @@
|
||||
"create-child-note": "建立子筆記",
|
||||
"unhoist": "取消聚焦",
|
||||
"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}}",
|
||||
"subtree-hidden-tooltip_one": "從樹中隱藏的 {{count}} 篇子筆記",
|
||||
"subtree-hidden-moved-title": "已新增至 {{title}}",
|
||||
"subtree-hidden-moved-description-collection": "此集合隱藏其樹中的子筆記。",
|
||||
"subtree-hidden-moved-description-other": "子筆記隱藏於此筆記的樹中。"
|
||||
},
|
||||
"title_bar_buttons": {
|
||||
"window-on-top": "保持此視窗置頂"
|
||||
@@ -1557,7 +1576,12 @@
|
||||
"note_detail": {
|
||||
"could_not_find_typewidget": "找不到類型為 '{{type}}' 的 typeWidget",
|
||||
"printing": "正在列印…",
|
||||
"printing_pdf": "正在匯出為 PDF…"
|
||||
"printing_pdf": "正在匯出為 PDF…",
|
||||
"print_report_title": "列印報告",
|
||||
"print_report_collection_content_one": "集合中的 {{count}} 篇筆記無法列印,因為它們不被支援或受到保護。",
|
||||
"print_report_collection_content_other": "",
|
||||
"print_report_collection_details_button": "查看詳情",
|
||||
"print_report_collection_details_ignored_notes": "忽略的筆記"
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "請輸入筆記標題...",
|
||||
@@ -1567,7 +1591,8 @@
|
||||
"note_type_switcher_others": "其他筆記類型",
|
||||
"note_type_switcher_templates": "模板",
|
||||
"note_type_switcher_collection": "集合",
|
||||
"edited_notes": "編輯過的筆記"
|
||||
"edited_notes": "今天編輯過的筆記",
|
||||
"promoted_attributes": "升級屬性"
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "沒有找到符合搜尋條件的筆記。",
|
||||
@@ -2183,7 +2208,14 @@
|
||||
"read_only_temporarily_disabled_description": "此筆記目前可編輯,但通常為唯讀狀態。當您切換至其他筆記時,本筆記將立即恢復為唯讀模式。\n\n點擊此處重新啟用唯讀模式。",
|
||||
"clipped_note_description": "本筆記原始來源為 {{url}}。\n\n點擊此處前往原網頁。",
|
||||
"execute_script_description": "此筆記為腳本筆記。點擊以執行腳本。",
|
||||
"execute_sql_description": "此筆記為 SQL 筆記。點擊以執行 SQL 查詢。"
|
||||
"execute_sql_description": "此筆記為 SQL 筆記。點擊以執行 SQL 查詢。",
|
||||
"save_status_saved": "已儲存",
|
||||
"save_status_saving": "正在儲存…",
|
||||
"save_status_unsaved": "未儲存",
|
||||
"save_status_error": "儲存失敗",
|
||||
"save_status_saving_tooltip": "正在儲存更動。",
|
||||
"save_status_unsaved_tooltip": "仍有更動尚未儲存。它們將在稍後自動儲存。",
|
||||
"save_status_error_tooltip": "在儲存筆記時發生錯誤。如果可以,請嘗試將筆記內容複製至他處並重新載入應用程式。"
|
||||
},
|
||||
"breadcrumb": {
|
||||
"hoisted_badge": "聚焦",
|
||||
@@ -2220,5 +2252,15 @@
|
||||
},
|
||||
"attributes_panel": {
|
||||
"title": "筆記屬性"
|
||||
},
|
||||
"pdf": {
|
||||
"attachments_one": "{{count}} 個附件",
|
||||
"attachments_other": "",
|
||||
"layers_one": "{{count}} 層",
|
||||
"layers_other": "",
|
||||
"pages_one": "共 {{count}} 頁",
|
||||
"pages_other": "",
|
||||
"pages_alt": "第 {{pageNumber}} 頁",
|
||||
"pages_loading": "正在載入…"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,7 +321,6 @@
|
||||
"download_button": "Завантажити",
|
||||
"mime": "МІМЕ: ",
|
||||
"file_size": "Розмір файлу:",
|
||||
"preview": "Попередній перегляд:",
|
||||
"preview_not_available": "Попередній перегляд недоступний для цього типу нотатки.",
|
||||
"diff_on": "Показати різницю",
|
||||
"diff_off": "Показати вміст",
|
||||
@@ -849,7 +848,6 @@
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "Змінити значок нотатки",
|
||||
"category": "Категорія:",
|
||||
"search": "Пошук:",
|
||||
"reset-default": "Скинути значок до стандартного значення"
|
||||
},
|
||||
|
||||
2
apps/client/src/types-assets.d.ts
vendored
2
apps/client/src/types-assets.d.ts
vendored
@@ -17,5 +17,3 @@ declare module "*?raw" {
|
||||
var content: string;
|
||||
export default content;
|
||||
}
|
||||
|
||||
declare module "boxicons/css/boxicons.min.css" { }
|
||||
|
||||
21
apps/client/src/types-fancytree.d.ts
vendored
21
apps/client/src/types-fancytree.d.ts
vendored
@@ -69,7 +69,7 @@ declare namespace Fancytree {
|
||||
debug(msg: any): void;
|
||||
|
||||
/** Expand (or collapse) all parent nodes. */
|
||||
expandAll(flag?: boolean, options?: Object): void;
|
||||
expandAll(flag?: boolean, options?: object): void;
|
||||
|
||||
/** [ext-filter] Dimm or hide whole branches.
|
||||
* @returns {integer} count
|
||||
@@ -221,6 +221,7 @@ declare namespace Fancytree {
|
||||
branchId: string;
|
||||
isProtected: boolean;
|
||||
noteType: NoteType;
|
||||
subtreeHidden: boolean;
|
||||
}
|
||||
|
||||
interface FancytreeNewNode extends FancytreeNodeData {
|
||||
@@ -369,7 +370,7 @@ declare namespace Fancytree {
|
||||
* @param mode 'before', 'after', or 'child' (default='child')
|
||||
* @param init NodeData (or simple title string)
|
||||
*/
|
||||
editCreateNode(mode?: string, init?: Object): void;
|
||||
editCreateNode(mode?: string, init?: object): void;
|
||||
|
||||
/** [ext-edit] Stop inline editing.
|
||||
*
|
||||
@@ -526,7 +527,7 @@ declare namespace Fancytree {
|
||||
*
|
||||
* @param opts passed to `setExpanded()`. Defaults to {noAnimation: false, noEvents: false, scrollIntoView: true}
|
||||
*/
|
||||
makeVisible(opts?: Object): JQueryPromise<any>;
|
||||
makeVisible(opts?: object): JQueryPromise<any>;
|
||||
|
||||
/** Move this node to targetNode.
|
||||
*
|
||||
@@ -589,25 +590,25 @@ declare namespace Fancytree {
|
||||
* @param effects animation options.
|
||||
* @param options {topNode: null, effects: ..., parent: ...} this node will remain visible in any case, even if `this` is outside the scroll pane.
|
||||
*/
|
||||
scrollIntoView(effects?: boolean, options?: Object): JQueryPromise<any>;
|
||||
scrollIntoView(effects?: boolean, options?: object): JQueryPromise<any>;
|
||||
|
||||
/**
|
||||
* @param effects animation options.
|
||||
* @param options {topNode: null, effects: ..., parent: ...} this node will remain visible in any case, even if `this` is outside the scroll pane.
|
||||
*/
|
||||
scrollIntoView(effects?: Object, options?: Object): JQueryPromise<any>;
|
||||
scrollIntoView(effects?: object, options?: object): JQueryPromise<any>;
|
||||
|
||||
/**
|
||||
* @param flag pass false to deactivate
|
||||
* @param opts additional options. Defaults to {noEvents: false}
|
||||
*/
|
||||
setActive(flag?: boolean, opts?: Object): JQueryPromise<any>;
|
||||
setActive(flag?: boolean, opts?: object): JQueryPromise<any>;
|
||||
|
||||
/**
|
||||
* @param flag pass false to collapse.
|
||||
* @param opts additional options. Defaults to {noAnimation:false, noEvents:false}
|
||||
*/
|
||||
setExpanded(flag?: boolean, opts?: Object): JQueryPromise<any>;
|
||||
setExpanded(flag?: boolean, opts?: object): JQueryPromise<any>;
|
||||
|
||||
/**
|
||||
* Set keyboard focus to this node.
|
||||
@@ -1109,7 +1110,7 @@ declare namespace Fancytree {
|
||||
/** class names added to the node markup (separate with space) */
|
||||
extraClasses?: string | undefined;
|
||||
/** all properties from will be copied to `node.data` */
|
||||
data?: Object | undefined;
|
||||
data?: object | undefined;
|
||||
|
||||
/** Will be added as title attribute of the node's icon span,thus enabling a tooltip. */
|
||||
iconTooltip?: string | undefined;
|
||||
@@ -1160,7 +1161,7 @@ declare namespace Fancytree {
|
||||
|
||||
escapeHtml(s: string): string;
|
||||
|
||||
getEventTarget(event: Event): Object;
|
||||
getEventTarget(event: Event): object;
|
||||
|
||||
getEventTargetType(event: Event): string;
|
||||
|
||||
@@ -1179,7 +1180,7 @@ declare namespace Fancytree {
|
||||
parseHtml($ul: JQuery): NodeData[];
|
||||
|
||||
/** Add Fancytree extension definition to the list of globally available extensions. */
|
||||
registerExtension(definition: Object): void;
|
||||
registerExtension(definition: object): void;
|
||||
|
||||
unescapeHtml(s: string): string;
|
||||
|
||||
|
||||
121
apps/client/src/types-pdfjs.d.ts
vendored
Normal file
121
apps/client/src/types-pdfjs.d.ts
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
type HistoryData = {
|
||||
files: {
|
||||
fingerprint: string;
|
||||
page: number;
|
||||
zoom: string;
|
||||
scrollLeft: number;
|
||||
scrollTop: number;
|
||||
rotation: number;
|
||||
sidebarView: number;
|
||||
}[];
|
||||
};
|
||||
|
||||
interface Window {
|
||||
/**
|
||||
* By default, pdf.js will try to store information about the opened PDFs such as zoom and scroll position in local storage.
|
||||
* The Trilium alternative is to use attachments stored at note level.
|
||||
* This variable represents the direct content used by the pdf.js viewer in its local storage key, but in plain JS object format.
|
||||
* The variable must be set early at startup, before pdf.js fully initializes.
|
||||
*/
|
||||
TRILIUM_VIEW_HISTORY_STORE?: HistoryData;
|
||||
|
||||
/**
|
||||
* If set to true, hides the pdf.js viewer default sidebar containing the outline, page navigation, etc.
|
||||
* This needs to be set early in the main method.
|
||||
*/
|
||||
TRILIUM_HIDE_SIDEBAR?: boolean;
|
||||
|
||||
TRILIUM_NOTE_ID: string;
|
||||
|
||||
TRILIUM_NTX_ID: string | null | undefined;
|
||||
}
|
||||
|
||||
interface PdfOutlineItem {
|
||||
title: string;
|
||||
level: number;
|
||||
dest: unknown;
|
||||
id: string;
|
||||
items: PdfOutlineItem[];
|
||||
}
|
||||
|
||||
interface WithContext {
|
||||
ntxId: string;
|
||||
noteId: string | null | undefined;
|
||||
}
|
||||
|
||||
interface PdfDocumentModifiedMessage extends WithContext {
|
||||
type: "pdfjs-viewer-document-modified";
|
||||
}
|
||||
|
||||
interface PdfDocumentBlobResultMessage extends WithContext {
|
||||
type: "pdfjs-viewer-blob";
|
||||
data: Uint8Array<ArrayBufferLike>;
|
||||
}
|
||||
|
||||
interface PdfSaveViewHistoryMessage extends WithContext {
|
||||
type: "pdfjs-viewer-save-view-history";
|
||||
data: string;
|
||||
}
|
||||
|
||||
interface PdfViewerTocMessage {
|
||||
type: "pdfjs-viewer-toc";
|
||||
data: PdfOutlineItem[];
|
||||
}
|
||||
|
||||
interface PdfViewerActiveHeadingMessage {
|
||||
type: "pdfjs-viewer-active-heading";
|
||||
headingId: string;
|
||||
}
|
||||
|
||||
interface PdfViewerPageInfoMessage {
|
||||
type: "pdfjs-viewer-page-info";
|
||||
totalPages: number;
|
||||
currentPage: number;
|
||||
}
|
||||
|
||||
interface PdfViewerCurrentPageMessage {
|
||||
type: "pdfjs-viewer-current-page";
|
||||
currentPage: number;
|
||||
}
|
||||
|
||||
interface PdfViewerThumbnailMessage {
|
||||
type: "pdfjs-viewer-thumbnail";
|
||||
pageNumber: number;
|
||||
dataUrl: string;
|
||||
}
|
||||
|
||||
interface PdfAttachment {
|
||||
filename: string;
|
||||
size: number;
|
||||
}
|
||||
|
||||
interface PdfViewerAttachmentsMessage {
|
||||
type: "pdfjs-viewer-attachments";
|
||||
attachments: PdfAttachment[];
|
||||
downloadAttachment?: (fileName: string) => void;
|
||||
}
|
||||
|
||||
interface PdfLayer {
|
||||
id: string;
|
||||
name: string;
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
interface PdfViewerLayersMessage {
|
||||
type: "pdfjs-viewer-layers";
|
||||
layers: PdfLayer[];
|
||||
toggleLayer?: (layerId: string, visible: boolean) => void;
|
||||
}
|
||||
|
||||
type PdfMessageEvent = MessageEvent<
|
||||
PdfDocumentModifiedMessage
|
||||
| PdfSaveViewHistoryMessage
|
||||
| PdfViewerTocMessage
|
||||
| PdfViewerActiveHeadingMessage
|
||||
| PdfViewerPageInfoMessage
|
||||
| PdfViewerCurrentPageMessage
|
||||
| PdfViewerThumbnailMessage
|
||||
| PdfViewerAttachmentsMessage
|
||||
| PdfViewerLayersMessage
|
||||
| PdfDocumentBlobResultMessage
|
||||
>;
|
||||
14
apps/client/src/types.d.ts
vendored
14
apps/client/src/types.d.ts
vendored
@@ -1,3 +1,5 @@
|
||||
import { IconRegistry, Locale } from "@triliumnext/commons";
|
||||
|
||||
import appContext, { AppContext } from "./components/app_context";
|
||||
import type FNote from "./entities/fnote";
|
||||
import type { PrintReport } from "./print";
|
||||
@@ -45,13 +47,25 @@ interface CustomGlobals {
|
||||
platform?: typeof process.platform;
|
||||
linter: typeof lint;
|
||||
hasNativeTitleBar: boolean;
|
||||
hasBackgroundEffects: boolean;
|
||||
isElectron: boolean;
|
||||
isRtl: boolean;
|
||||
iconRegistry: IconRegistry;
|
||||
themeCssUrl: string;
|
||||
themeUseNextAsBase?: "next" | "next-light" | "next-dark";
|
||||
iconPackCss: string;
|
||||
headingStyle: "plain" | "underline" | "markdown";
|
||||
layoutOrientation: "vertical" | "horizontal";
|
||||
currentLocale: Locale;
|
||||
}
|
||||
|
||||
type RequireMethod = (moduleName: string) => any;
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
$: JQueryStatic;
|
||||
jQuery: JQueryStatic;
|
||||
|
||||
logError(message: string);
|
||||
logInfo(message: string);
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ function ShowTocWidgetButton({ note, noteContext, isDefaultViewMode }: FloatingB
|
||||
|
||||
return isEnabled && <FloatingButton
|
||||
text={t("show_toc_widget_button.show_toc")}
|
||||
icon="bx bx-tn-toc"
|
||||
icon="bx bx-spreadsheet bx-rotate-180"
|
||||
onClick={() => {
|
||||
if (noteContext?.viewScope && noteContext.noteId) {
|
||||
noteContext.viewScope.tocTemporarilyHidden = false;
|
||||
|
||||
@@ -215,7 +215,7 @@ export default function NoteDetail() {
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
class={`note-detail ${isFullHeight ? "full-height" : ""}`}
|
||||
class={`component note-detail ${isFullHeight ? "full-height" : ""}`}
|
||||
>
|
||||
{Object.entries(noteTypesToRender).map(([ itemType, Element ]) => {
|
||||
return <NoteDetailWrapper
|
||||
@@ -265,9 +265,13 @@ function useNoteInfo() {
|
||||
const [ note, setNote ] = useState<FNote | null | undefined>();
|
||||
const [ type, setType ] = useState<ExtendedNoteType>();
|
||||
const [ mime, setMime ] = useState<string>();
|
||||
const refreshIdRef = useRef(0);
|
||||
|
||||
function refresh() {
|
||||
const refreshId = ++refreshIdRef.current;
|
||||
|
||||
getExtendedWidgetType(actualNote, noteContext).then(type => {
|
||||
if (refreshId !== refreshIdRef.current) return;
|
||||
setNote(actualNote);
|
||||
setType(type);
|
||||
setMime(actualNote?.mime);
|
||||
@@ -318,6 +322,8 @@ export async function getExtendedWidgetType(note: FNote | null | undefined, note
|
||||
resultingType = "noteMap";
|
||||
} else if (type === "text" && (await noteContext?.isReadOnly())) {
|
||||
resultingType = "readOnlyText";
|
||||
} else if (note.isTriliumSqlite()) {
|
||||
resultingType = "sqlConsole";
|
||||
} else if ((type === "code" || type === "mermaid") && (await noteContext?.isReadOnly())) {
|
||||
resultingType = "readOnlyCode";
|
||||
} else if (type === "text") {
|
||||
@@ -342,9 +348,8 @@ export function checkFullHeight(noteContext: NoteContext | undefined, type: Exte
|
||||
|
||||
// https://github.com/zadam/trilium/issues/2522
|
||||
const isBackendNote = noteContext?.noteId === "_backendLog";
|
||||
const isSqlNote = noteContext.note?.mime === "text/x-sqlite;schema=trilium";
|
||||
const isFullHeightNoteType = type && TYPE_MAPPINGS[type].isFullHeight;
|
||||
return (!noteContext?.hasNoteList() && isFullHeightNoteType && !isSqlNote)
|
||||
return (!noteContext?.hasNoteList() && isFullHeightNoteType)
|
||||
|| noteContext?.viewScope?.viewMode === "attachments"
|
||||
|| isBackendNote;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import debounce from "../services/debounce";
|
||||
import { t } from "../services/i18n";
|
||||
import { DefinitionObject, extractAttributeDefinitionTypeAndName, LabelType } from "../services/promoted_attribute_definition_parser";
|
||||
import server from "../services/server";
|
||||
import { randomString } from "../services/utils";
|
||||
import ws from "../services/ws";
|
||||
import { useNoteContext, useNoteLabel, useTriliumEvent, useUniqueName } from "./react/hooks";
|
||||
import NoteAutocomplete from "./react/NoteAutocomplete";
|
||||
@@ -116,7 +117,7 @@ export function usePromotedAttributeData(note: FNote | null | undefined, compone
|
||||
valueAttr.attributeId = "";
|
||||
}
|
||||
|
||||
const uniqueId = crypto.randomUUID();
|
||||
const uniqueId = randomString();
|
||||
cells.push({ definitionAttr, definition, valueAttr, valueName, uniqueId });
|
||||
}
|
||||
}
|
||||
@@ -319,7 +320,7 @@ function MultiplicityCell({ cell, cells, setCells, setCellToFocus, note, compone
|
||||
const index = cells.indexOf(cell);
|
||||
const newCell: Cell = {
|
||||
...cell,
|
||||
uniqueId: crypto.randomUUID(),
|
||||
uniqueId: randomString(),
|
||||
valueAttr: {
|
||||
attributeId: "",
|
||||
type: cell.valueAttr.type,
|
||||
|
||||
@@ -4,6 +4,7 @@ import Component, { TypedComponent } from "../components/component.js";
|
||||
import froca from "../services/froca.js";
|
||||
import { t } from "../services/i18n.js";
|
||||
import toastService, { showErrorForScriptNote } from "../services/toast.js";
|
||||
import { randomString } from "../services/utils.js";
|
||||
import { renderReactWidget } from "./react/react_utils.jsx";
|
||||
|
||||
export class TypedBasicWidget<T extends TypedComponent<any>> extends TypedComponent<T> {
|
||||
@@ -180,7 +181,7 @@ export class TypedBasicWidget<T extends TypedComponent<any>> extends TypedCompon
|
||||
});
|
||||
} else {
|
||||
toastService.showPersistent({
|
||||
id: `custom-widget-failure-unknown-${crypto.randomUUID()}`,
|
||||
id: `custom-widget-failure-unknown-${randomString()}`,
|
||||
title: t("toast.widget-error.title"),
|
||||
icon: "bx bx-error-circle",
|
||||
message: t("toast.widget-error.message-unknown", {
|
||||
|
||||
@@ -108,14 +108,6 @@ button.global-menu-button {
|
||||
margin-inline-end: 5px;
|
||||
}
|
||||
|
||||
.global-menu .dropdown-item .bx {
|
||||
position: relative;
|
||||
top: 3px;
|
||||
font-size: 120%;
|
||||
margin-inline-end: 6px;
|
||||
}
|
||||
|
||||
|
||||
.global-menu-button-wrapper:hover .global-menu-button-update-available-button {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
import clsx from "clsx";
|
||||
|
||||
import { t } from "../../services/i18n";
|
||||
import options from "../../services/options";
|
||||
import ActionButton from "../react/ActionButton";
|
||||
import { useTriliumOptionBool } from "../react/hooks";
|
||||
import { useState, useCallback } from "preact/hooks";
|
||||
import { useTriliumEvent } from "../react/hooks";
|
||||
|
||||
export default function RightPaneToggle() {
|
||||
const [ rightPaneVisible, setRightPaneVisible ] = useTriliumOptionBool("rightPaneVisible");
|
||||
const [ rightPaneVisible, setRightPaneVisible ] = useState(options.is("rightPaneVisible"));
|
||||
|
||||
useTriliumEvent("toggleRightPane", useCallback(() => {
|
||||
setRightPaneVisible(current => !current);
|
||||
}, []));
|
||||
|
||||
return (
|
||||
<ActionButton
|
||||
@@ -15,7 +21,7 @@ export default function RightPaneToggle() {
|
||||
)}
|
||||
text={t("right_pane.toggle")}
|
||||
icon="bx bx-sidebar"
|
||||
onClick={() => setRightPaneVisible(!rightPaneVisible)}
|
||||
triggerCommand="toggleRightPane"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ body.prefers-centered-content .note-list-widget:not(.full-height) {
|
||||
}
|
||||
|
||||
.note-list-widget .note-list {
|
||||
padding: 10px;
|
||||
padding-block: 10px;
|
||||
}
|
||||
|
||||
.note-list-widget.full-height,
|
||||
|
||||
@@ -11,7 +11,8 @@ import froca from "../../services/froca";
|
||||
import { subscribeToMessages, unsubscribeToMessage as unsubscribeFromMessage } from "../../services/ws";
|
||||
import { useNoteContext, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumEvent } from "../react/hooks";
|
||||
import { allViewTypes, ViewModeMedia, ViewModeProps, ViewTypeOptions } from "./interface";
|
||||
import ViewModeStorage from "./view_mode_storage";
|
||||
import ViewModeStorage, { type ViewModeStorageType } from "./view_mode_storage";
|
||||
|
||||
interface NoteListProps {
|
||||
note: FNote | null | undefined;
|
||||
notePath: string | null | undefined;
|
||||
@@ -215,7 +216,7 @@ export function useNoteIds(note: FNote | null | undefined, viewType: ViewTypeOpt
|
||||
return noteIds;
|
||||
}
|
||||
|
||||
export function useViewModeConfig<T extends object>(note: FNote | null | undefined, viewType: ViewTypeOptions | undefined) {
|
||||
export function useViewModeConfig<T extends object>(note: FNote | null | undefined, viewType: ViewModeStorageType | undefined) {
|
||||
const [ viewConfig, setViewConfig ] = useState<{
|
||||
config: T | undefined;
|
||||
storeFn: (data: T) => void;
|
||||
|
||||
@@ -1,27 +1,29 @@
|
||||
import { DateSelectArg, EventChangeArg, EventMountArg, EventSourceFuncArg, LocaleInput, PluginDef } from "@fullcalendar/core/index.js";
|
||||
import { ViewModeProps } from "../interface";
|
||||
import Calendar from "./calendar";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "preact/hooks";
|
||||
import "./index.css";
|
||||
import { useNoteLabel, useNoteLabelBoolean, useResizeObserver, useSpacedUpdate, useTriliumEvent, useTriliumOption, useTriliumOptionInt } from "../../react/hooks";
|
||||
import { DISPLAYABLE_LOCALE_IDS } from "@triliumnext/commons";
|
||||
|
||||
import { Calendar as FullCalendar } from "@fullcalendar/core";
|
||||
import { parseStartEndDateFromEvent, parseStartEndTimeFromEvent } from "./utils";
|
||||
import dialog from "../../../services/dialog";
|
||||
import { t } from "../../../services/i18n";
|
||||
import { buildEvents, buildEventsForCalendar } from "./event_builder";
|
||||
import { changeEvent, newEvent } from "./api";
|
||||
import froca from "../../../services/froca";
|
||||
import date_notes from "../../../services/date_notes";
|
||||
import appContext from "../../../components/app_context";
|
||||
import { DateSelectArg, EventChangeArg, EventMountArg, EventSourceFuncArg, LocaleInput, PluginDef } from "@fullcalendar/core/index.js";
|
||||
import { DateClickArg } from "@fullcalendar/interaction";
|
||||
import FNote from "../../../entities/fnote";
|
||||
import Button, { ButtonGroup } from "../../react/Button";
|
||||
import ActionButton from "../../react/ActionButton";
|
||||
import { DISPLAYABLE_LOCALE_IDS } from "@triliumnext/commons";
|
||||
import { RefObject } from "preact";
|
||||
import TouchBar, { TouchBarButton, TouchBarLabel, TouchBarSegmentedControl, TouchBarSpacer } from "../../react/TouchBar";
|
||||
import { openCalendarContextMenu } from "./context_menu";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "preact/hooks";
|
||||
|
||||
import appContext from "../../../components/app_context";
|
||||
import FNote from "../../../entities/fnote";
|
||||
import date_notes from "../../../services/date_notes";
|
||||
import dialog from "../../../services/dialog";
|
||||
import froca from "../../../services/froca";
|
||||
import { t } from "../../../services/i18n";
|
||||
import { isMobile } from "../../../services/utils";
|
||||
import ActionButton from "../../react/ActionButton";
|
||||
import Button, { ButtonGroup } from "../../react/Button";
|
||||
import { useNoteLabel, useNoteLabelBoolean, useResizeObserver, useSpacedUpdate, useTriliumEvent, useTriliumOption, useTriliumOptionInt } from "../../react/hooks";
|
||||
import TouchBar, { TouchBarButton, TouchBarLabel, TouchBarSegmentedControl, TouchBarSpacer } from "../../react/TouchBar";
|
||||
import { ViewModeProps } from "../interface";
|
||||
import { changeEvent, newEvent } from "./api";
|
||||
import Calendar from "./calendar";
|
||||
import { openCalendarContextMenu } from "./context_menu";
|
||||
import { buildEvents, buildEventsForCalendar } from "./event_builder";
|
||||
import { parseStartEndDateFromEvent, parseStartEndTimeFromEvent } from "./utils";
|
||||
|
||||
interface CalendarViewData {
|
||||
|
||||
@@ -59,7 +61,7 @@ const CALENDAR_VIEWS = [
|
||||
previousText: t("calendar.month_previous"),
|
||||
nextText: t("calendar.month_next")
|
||||
}
|
||||
]
|
||||
];
|
||||
|
||||
const SUPPORTED_CALENDAR_VIEW_TYPE = CALENDAR_VIEWS.map(v => v.type);
|
||||
|
||||
@@ -75,6 +77,7 @@ export const LOCALE_MAPPINGS: Record<DISPLAYABLE_LOCALE_IDS, (() => Promise<{ de
|
||||
ru: () => import("@fullcalendar/core/locales/ru"),
|
||||
ja: () => import("@fullcalendar/core/locales/ja"),
|
||||
pt: () => import("@fullcalendar/core/locales/pt"),
|
||||
pl: () => import("@fullcalendar/core/locales/pl"),
|
||||
"pt_br": () => import("@fullcalendar/core/locales/pt-br"),
|
||||
uk: () => import("@fullcalendar/core/locales/uk"),
|
||||
en: null,
|
||||
@@ -102,9 +105,9 @@ export default function CalendarView({ note, noteIds }: ViewModeProps<CalendarVi
|
||||
const eventBuilder = useMemo(() => {
|
||||
if (!isCalendarRoot) {
|
||||
return async () => await buildEvents(noteIds);
|
||||
} else {
|
||||
return async (e: EventSourceFuncArg) => await buildEventsForCalendar(note, e);
|
||||
}
|
||||
}
|
||||
return async (e: EventSourceFuncArg) => await buildEventsForCalendar(note, e);
|
||||
|
||||
}, [isCalendarRoot, noteIds]);
|
||||
|
||||
const plugins = usePlugins(isEditable, isCalendarRoot);
|
||||
@@ -178,7 +181,7 @@ function CalendarHeader({ calendarRef }: { calendarRef: RefObject<FullCalendar>
|
||||
<ActionButton icon="bx bx-chevron-right" text={currentViewData?.nextText ?? ""} frame onClick={() => calendarRef.current?.next()} />
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function usePlugins(isEditable: boolean, isCalendarRoot: boolean) {
|
||||
@@ -293,7 +296,7 @@ function useEventDisplayCustomization(parentNote: FNote) {
|
||||
if (promotedAttributes) {
|
||||
let promotedAttributesHtml = "";
|
||||
for (const [name, value] of promotedAttributes) {
|
||||
promotedAttributesHtml = promotedAttributesHtml + /*html*/`\
|
||||
promotedAttributesHtml = `${promotedAttributesHtml /*html*/}\
|
||||
<div class="promoted-attribute">
|
||||
<span class="promoted-attribute-name">${name}</span>: <span class="promoted-attribute-value">${value}</span>
|
||||
</div>`;
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.geo-map-container .leaflet-div-icon .bx {
|
||||
.geo-map-container .leaflet-div-icon .tn-icon {
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
inset-inline-start: 2px;
|
||||
|
||||
@@ -142,4 +142,10 @@
|
||||
border: 1px solid var(--main-border-color);
|
||||
background: var(--more-accented-background-color);
|
||||
}
|
||||
|
||||
.note-list.grid-view .note-path {
|
||||
margin-left: 0.5em;
|
||||
vertical-align: middle;
|
||||
opacity: 0.5;
|
||||
}
|
||||
/* #endregion */
|
||||
|
||||
@@ -7,7 +7,6 @@ import attribute_renderer from "../../../services/attribute_renderer";
|
||||
import content_renderer from "../../../services/content_renderer";
|
||||
import { t } from "../../../services/i18n";
|
||||
import link from "../../../services/link";
|
||||
import tree from "../../../services/tree";
|
||||
import { useImperativeSearchHighlighlighting, useNoteLabel, useNoteLabelBoolean } from "../../react/hooks";
|
||||
import Icon from "../../react/Icon";
|
||||
import NoteLink from "../../react/NoteLink";
|
||||
@@ -45,6 +44,7 @@ export function ListView({ note, noteIds: unfilteredNoteIds, highlightedTokens }
|
||||
export function GridView({ note, noteIds: unfilteredNoteIds, highlightedTokens }: ViewModeProps<{}>) {
|
||||
const noteIds = useFilteredNoteIds(note, unfilteredNoteIds);
|
||||
const { pageNotes, ...pagination } = usePagination(note, noteIds);
|
||||
const [ includeArchived ] = useNoteLabelBoolean(note, "includeArchived");
|
||||
|
||||
return (
|
||||
<div class="note-list grid-view">
|
||||
@@ -53,7 +53,7 @@ export function GridView({ note, noteIds: unfilteredNoteIds, highlightedTokens }
|
||||
|
||||
<div class="note-list-container use-tn-links">
|
||||
{pageNotes?.map(childNote => (
|
||||
<GridNoteCard note={childNote} parentNote={note} highlightedTokens={highlightedTokens} />
|
||||
<GridNoteCard note={childNote} parentNote={note} highlightedTokens={highlightedTokens} includeArchived={includeArchived} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -95,24 +95,17 @@ function ListNoteCard({ note, parentNote, highlightedTokens, currentLevel, expan
|
||||
</h5>
|
||||
|
||||
{isExpanded && <>
|
||||
<NoteContent note={note} highlightedTokens={highlightedTokens} noChildrenList />
|
||||
<NoteContent note={note} highlightedTokens={highlightedTokens} noChildrenList includeArchivedNotes={includeArchived} />
|
||||
<NoteChildren note={note} parentNote={parentNote} highlightedTokens={highlightedTokens} currentLevel={currentLevel} expandDepth={expandDepth} includeArchived={includeArchived} />
|
||||
</>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function GridNoteCard({ note, parentNote, highlightedTokens }: { note: FNote, parentNote: FNote, highlightedTokens: string[] | null | undefined }) {
|
||||
function GridNoteCard({ note, parentNote, highlightedTokens, includeArchived }: { note: FNote, parentNote: FNote, highlightedTokens: string[] | null | undefined, includeArchived: boolean }) {
|
||||
const titleRef = useRef<HTMLSpanElement>(null);
|
||||
const [ noteTitle, setNoteTitle ] = useState<string>();
|
||||
const notePath = getNotePath(parentNote, note);
|
||||
const highlightSearch = useImperativeSearchHighlighlighting(highlightedTokens);
|
||||
|
||||
useEffect(() => {
|
||||
tree.getNoteTitle(note.noteId, parentNote.noteId).then(setNoteTitle);
|
||||
}, [ note ]);
|
||||
|
||||
useEffect(() => highlightSearch(titleRef.current), [ noteTitle, highlightedTokens ]);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -123,13 +116,14 @@ function GridNoteCard({ note, parentNote, highlightedTokens }: { note: FNote, pa
|
||||
>
|
||||
<h5 className="note-book-header">
|
||||
<Icon className="note-icon" icon={note.getIcon()} />
|
||||
<span ref={titleRef} className="note-book-title">{noteTitle}</span>
|
||||
<NoteLink className="note-book-title" notePath={notePath} noPreview showNotePath={parentNote.type === "search"} highlightedTokens={highlightedTokens} />
|
||||
<NoteAttributes note={note} />
|
||||
</h5>
|
||||
<NoteContent
|
||||
note={note}
|
||||
trim
|
||||
highlightedTokens={highlightedTokens}
|
||||
includeArchivedNotes={includeArchived}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@@ -146,14 +140,22 @@ function NoteAttributes({ note }: { note: FNote }) {
|
||||
return <span className="note-list-attributes" ref={ref} />;
|
||||
}
|
||||
|
||||
function NoteContent({ note, trim, noChildrenList, highlightedTokens }: { note: FNote, trim?: boolean, noChildrenList?: boolean, highlightedTokens: string[] | null | undefined }) {
|
||||
function NoteContent({ note, trim, noChildrenList, highlightedTokens, includeArchivedNotes }: {
|
||||
note: FNote;
|
||||
trim?: boolean;
|
||||
noChildrenList?: boolean;
|
||||
highlightedTokens: string[] | null | undefined;
|
||||
includeArchivedNotes: boolean;
|
||||
}) {
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
const highlightSearch = useImperativeSearchHighlighlighting(highlightedTokens);
|
||||
|
||||
useEffect(() => {
|
||||
content_renderer.getRenderedContent(note, {
|
||||
trim,
|
||||
noChildrenList
|
||||
noChildrenList,
|
||||
noIncludedNotes: true,
|
||||
includeArchivedNotes
|
||||
})
|
||||
.then(({ $renderedContent, type }) => {
|
||||
if (!contentRef.current) return;
|
||||
|
||||
@@ -74,11 +74,11 @@ describe("Presentation model", () => {
|
||||
});
|
||||
|
||||
it("rewrites links to other slides", () => {
|
||||
expect(data.slides[1].content.__html).toStrictEqual(`<div class="ck-content"><p>Go to <a class="reference-link" href="#/slide-slide1"><span><span class="bx bx-folder"></span>First slide</span></a>.</p></div>`);
|
||||
expect(data.slides[1].verticalSlides![0].content.__html).toStrictEqual(`<div class="ck-content"><p>Go to <a class="reference-link" href="#/slide-slide2"><span><span class="bx bx-note"></span>First-sub</span></a>.</p></div>`);
|
||||
expect(data.slides[1].content.__html).toStrictEqual(`<div class="ck-content"><p>Go to <a class="reference-link" href="#/slide-slide1"><span><span class="tn-icon bx bx-folder"></span>First slide</span></a>.</p></div>`);
|
||||
expect(data.slides[1].verticalSlides![0].content.__html).toStrictEqual(`<div class="ck-content"><p>Go to <a class="reference-link" href="#/slide-slide2"><span><span class="tn-icon bx bx-note"></span>First-sub</span></a>.</p></div>`);
|
||||
});
|
||||
|
||||
it("rewrites links even if they are not part of the slideshow", () => {
|
||||
expect(data.slides[0].verticalSlides![0].content.__html).toStrictEqual(`<div class="ck-content"><p>Go to <a class="reference-link" href="#/slide-other"><span><span class="bx bx-note"></span>Other note</span></a>.</p></div>`);
|
||||
expect(data.slides[0].verticalSlides![0].content.__html).toStrictEqual(`<div class="ck-content"><p>Go to <a class="reference-link" href="#/slide-other"><span><span class="tn-icon bx bx-note"></span>Other note</span></a>.</p></div>`);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
height: 100%;
|
||||
user-select: none;
|
||||
padding: 0 5px 0 10px;
|
||||
|
||||
.tabulator-tableholder {
|
||||
height: unset !important;
|
||||
}
|
||||
}
|
||||
|
||||
.table-view-container {
|
||||
@@ -68,4 +72,4 @@
|
||||
inset-inline-start: 0;
|
||||
font-size: 1.5em;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
import { useContext, useEffect, useLayoutEffect, useRef } from "preact/hooks";
|
||||
import { EventCallBackMethods, Module, Options, Tabulator as VanillaTabulator } from "tabulator-tables";
|
||||
import "tabulator-tables/dist/css/tabulator.css";
|
||||
import "../../../../src/stylesheets/table.css";
|
||||
import { ParentComponent, renderReactWidget } from "../../react/react_utils";
|
||||
import { JSX } from "preact/jsx-runtime";
|
||||
|
||||
import { isValidElement, RefObject } from "preact";
|
||||
import { useContext, useEffect, useLayoutEffect, useRef } from "preact/hooks";
|
||||
import { JSX } from "preact/jsx-runtime";
|
||||
import { EventCallBackMethods, Module, Options, Tabulator as VanillaTabulator } from "tabulator-tables";
|
||||
|
||||
import { ParentComponent, renderReactWidget } from "../../react/react_utils";
|
||||
|
||||
interface TableProps<T> extends Omit<Options, "data" | "footerElement" | "index"> {
|
||||
tabulatorRef: RefObject<VanillaTabulator>;
|
||||
tabulatorRef?: RefObject<VanillaTabulator>;
|
||||
className?: string;
|
||||
data?: T[];
|
||||
modules?: (new (table: VanillaTabulator) => Module)[];
|
||||
events?: Partial<EventCallBackMethods>;
|
||||
index: keyof T;
|
||||
index?: keyof T;
|
||||
footerElement?: string | HTMLElement | JSX.Element;
|
||||
onReady?: () => void;
|
||||
}
|
||||
@@ -43,7 +45,9 @@ export default function Tabulator<T>({ className, columns, data, modules, tabula
|
||||
|
||||
tabulator.on("tableBuilt", () => {
|
||||
tabulatorRef.current = tabulator;
|
||||
externalTabulatorRef.current = tabulator;
|
||||
if (externalTabulatorRef) {
|
||||
externalTabulatorRef.current = tabulator;
|
||||
}
|
||||
onReady?.();
|
||||
});
|
||||
|
||||
@@ -62,12 +66,12 @@ export default function Tabulator<T>({ className, columns, data, modules, tabula
|
||||
for (const [ eventName, handler ] of Object.entries(events)) {
|
||||
tabulator.off(eventName as keyof EventCallBackMethods, handler);
|
||||
}
|
||||
}
|
||||
};
|
||||
}, Object.values(events ?? {}));
|
||||
|
||||
// Change in data.
|
||||
useEffect(() => { tabulatorRef.current?.setData(data) }, [ data ]);
|
||||
useEffect(() => { columns && tabulatorRef.current?.setColumns(columns)}, [ data]);
|
||||
useEffect(() => { tabulatorRef.current?.setData(data); }, [ data ]);
|
||||
useEffect(() => { columns && tabulatorRef.current?.setColumns(columns); }, [ data ]);
|
||||
|
||||
return (
|
||||
<div ref={containerRef} className={className} />
|
||||
|
||||
@@ -4,14 +4,16 @@ import { ViewTypeOptions } from "../collections/interface";
|
||||
|
||||
const ATTACHMENT_ROLE = "viewConfig";
|
||||
|
||||
export type ViewModeStorageType = ViewTypeOptions | "pdfHistory";
|
||||
|
||||
export default class ViewModeStorage<T extends object> {
|
||||
|
||||
private note: FNote;
|
||||
private attachmentName: string;
|
||||
|
||||
constructor(note: FNote, viewType: ViewTypeOptions) {
|
||||
constructor(note: FNote, viewType: ViewModeStorageType) {
|
||||
this.note = note;
|
||||
this.attachmentName = viewType + ".json";
|
||||
this.attachmentName = `${viewType}.json`;
|
||||
}
|
||||
|
||||
async store(data: T) {
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
overflow: auto;
|
||||
scroll-behavior: smooth;
|
||||
position: relative;
|
||||
|
||||
> .inline-title,
|
||||
> .note-detail > .note-detail-editable-text,
|
||||
> .note-list-widget:not(.full-height) {
|
||||
padding-inline: 24px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.note-split.type-code:not(.mime-text-x-sqlite) {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import FlexContainer from "./flex_container.js";
|
||||
import appContext, { type CommandData, type CommandListenerData, type EventData, type EventNames, type NoteSwitchedContext } from "../../components/app_context.js";
|
||||
import type BasicWidget from "../basic_widget.js";
|
||||
import Component from "../../components/component.js";
|
||||
import NoteContext from "../../components/note_context.js";
|
||||
import splitService from "../../services/resizer.js";
|
||||
import { isMobile } from "../../services/utils.js";
|
||||
import NoteContext from "../../components/note_context.js";
|
||||
import type BasicWidget from "../basic_widget.js";
|
||||
import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
||||
import FlexContainer from "./flex_container.js";
|
||||
|
||||
interface SplitNoteWidget extends BasicWidget {
|
||||
hasBeenAlreadyShown?: boolean;
|
||||
@@ -74,7 +75,7 @@ export default class SplitNoteContainer extends FlexContainer<SplitNoteWidget> {
|
||||
|
||||
|
||||
const subContexts = activeContext.getSubContexts();
|
||||
let noteContext: NoteContext | undefined = undefined;
|
||||
let noteContext: NoteContext | undefined;
|
||||
if (isMobile() && subContexts.length > 1) {
|
||||
noteContext = subContexts.find(s => s.ntxId !== ntxId);
|
||||
}
|
||||
@@ -201,6 +202,11 @@ export default class SplitNoteContainer extends FlexContainer<SplitNoteWidget> {
|
||||
|
||||
async refresh() {
|
||||
this.toggleExt(true);
|
||||
|
||||
// Mark the active note context.
|
||||
for (const child of this.children as NoteContextAwareWidget[]) {
|
||||
child.$widget.toggleClass("active", !!child.noteContext?.isActive());
|
||||
}
|
||||
}
|
||||
|
||||
toggleInt(show: boolean) {} // not needed
|
||||
@@ -239,16 +245,16 @@ export default class SplitNoteContainer extends FlexContainer<SplitNoteWidget> {
|
||||
widget.hasBeenAlreadyShown = true;
|
||||
|
||||
return [widget.handleEvent("noteSwitched", noteSwitchedContext), this.refreshNotShown(noteSwitchedContext)];
|
||||
} else {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.resolve();
|
||||
|
||||
}
|
||||
|
||||
if (name === "activeContextChanged") {
|
||||
return this.refreshNotShown(data as EventData<"activeContextChanged">);
|
||||
} else {
|
||||
return super.handleEventInChildren(name, data);
|
||||
}
|
||||
return super.handleEventInChildren(name, data);
|
||||
|
||||
}
|
||||
|
||||
refreshNotShown(data: NoteSwitchedContext | EventData<"activeContextChanged">) {
|
||||
|
||||
@@ -88,6 +88,7 @@ export default function PopupEditor() {
|
||||
onHidden={() => setShown(false)}
|
||||
keepInDom // needed for faster loading
|
||||
noFocus // automatic focus breaks block popup
|
||||
stackable
|
||||
>
|
||||
{!isNewLayout && <ReadOnlyNoteInfoBar />}
|
||||
<PromotedAttributes />
|
||||
|
||||
@@ -14,7 +14,7 @@ body.mobile .revisions-dialog {
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.modal-body {
|
||||
height: fit-content !important;
|
||||
flex-direction: column;
|
||||
@@ -24,7 +24,7 @@ body.mobile .revisions-dialog {
|
||||
.modal-footer {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
|
||||
.revision-list {
|
||||
height: fit-content !important;
|
||||
max-height: 20vh;
|
||||
@@ -32,7 +32,7 @@ body.mobile .revisions-dialog {
|
||||
padding: 0 1em;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
|
||||
.modal-body > .revision-content-wrapper {
|
||||
flex-grow: 1;
|
||||
max-width: unset !important;
|
||||
@@ -40,24 +40,68 @@ body.mobile .revisions-dialog {
|
||||
margin: 0;
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
|
||||
.modal-body > .revision-content-wrapper > div:first-of-type {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
.revision-title {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
|
||||
.revision-title-buttons {
|
||||
text-align: center;
|
||||
display: flex;
|
||||
gap: 0.25em;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
|
||||
.revision-content {
|
||||
padding: 0.5em;
|
||||
height: fit-content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.revisions-dialog {
|
||||
.revision-title-buttons {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.revision-list {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.revision-content.type-file {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
flex-grow: 1;
|
||||
|
||||
.file-preview-table {
|
||||
th,
|
||||
td {
|
||||
padding: 0.25em 0;
|
||||
}
|
||||
}
|
||||
|
||||
.revision-file-preview {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.revision-file-preview-content {
|
||||
flex-grow: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> * {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,26 +1,31 @@
|
||||
import type { RevisionPojo, RevisionItem } from "@triliumnext/commons";
|
||||
import "./revisions.css";
|
||||
|
||||
import type { RevisionItem, RevisionPojo } from "@triliumnext/commons";
|
||||
import clsx from "clsx";
|
||||
import { diffWords } from "diff";
|
||||
import type { CSSProperties } from "preact/compat";
|
||||
import { Dispatch, StateUpdater, useEffect, useRef, useState } from "preact/hooks";
|
||||
|
||||
import appContext from "../../components/app_context";
|
||||
import FNote from "../../entities/fnote";
|
||||
import dialog from "../../services/dialog";
|
||||
import froca from "../../services/froca";
|
||||
import { t } from "../../services/i18n";
|
||||
import { renderMathInElement } from "../../services/math";
|
||||
import open from "../../services/open";
|
||||
import options from "../../services/options";
|
||||
import protected_session_holder from "../../services/protected_session_holder";
|
||||
import server from "../../services/server";
|
||||
import toast from "../../services/toast";
|
||||
import Button from "../react/Button";
|
||||
import FormToggle from "../react/FormToggle";
|
||||
import Modal from "../react/Modal";
|
||||
import FormList, { FormListItem } from "../react/FormList";
|
||||
import utils from "../../services/utils";
|
||||
import { Dispatch, StateUpdater, useEffect, useRef, useState } from "preact/hooks";
|
||||
import protected_session_holder from "../../services/protected_session_holder";
|
||||
import { renderMathInElement } from "../../services/math";
|
||||
import type { CSSProperties } from "preact/compat";
|
||||
import open from "../../services/open";
|
||||
import ActionButton from "../react/ActionButton";
|
||||
import options from "../../services/options";
|
||||
import Button from "../react/Button";
|
||||
import FormList, { FormListItem } from "../react/FormList";
|
||||
import FormToggle from "../react/FormToggle";
|
||||
import { useTriliumEvent } from "../react/hooks";
|
||||
import { diffWords } from "diff";
|
||||
import "./revisions.css";
|
||||
import Modal from "../react/Modal";
|
||||
import { RawHtmlBlock } from "../react/RawHtml";
|
||||
import PdfViewer from "../type_widgets/file/PdfViewer";
|
||||
|
||||
export default function RevisionsDialog() {
|
||||
const [ note, setNote ] = useState<FNote>();
|
||||
@@ -47,7 +52,7 @@ export default function RevisionsDialog() {
|
||||
setRevisions(undefined);
|
||||
setNoteContent(undefined);
|
||||
}
|
||||
}, [ note?.noteId, refreshCounter ]);
|
||||
}, [ note, refreshCounter ]);
|
||||
|
||||
if (revisions?.length && !currentRevision) {
|
||||
setCurrentRevision(revisions[0]);
|
||||
@@ -102,38 +107,38 @@ export default function RevisionsDialog() {
|
||||
setRevisions(undefined);
|
||||
}}
|
||||
show={shown}
|
||||
>
|
||||
<RevisionsList
|
||||
revisions={revisions ?? []}
|
||||
onSelect={(revisionId) => {
|
||||
const correspondingRevision = (revisions ?? []).find((r) => r.revisionId === revisionId);
|
||||
if (correspondingRevision) {
|
||||
setCurrentRevision(correspondingRevision);
|
||||
}
|
||||
}}
|
||||
currentRevision={currentRevision}
|
||||
/>
|
||||
>
|
||||
<RevisionsList
|
||||
revisions={revisions ?? []}
|
||||
onSelect={(revisionId) => {
|
||||
const correspondingRevision = (revisions ?? []).find((r) => r.revisionId === revisionId);
|
||||
if (correspondingRevision) {
|
||||
setCurrentRevision(correspondingRevision);
|
||||
}
|
||||
}}
|
||||
currentRevision={currentRevision}
|
||||
/>
|
||||
|
||||
<div className="revision-content-wrapper" style={{
|
||||
flexGrow: "1",
|
||||
marginInlineStart: "20px",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
maxWidth: "calc(100% - 150px)",
|
||||
minWidth: 0
|
||||
}}>
|
||||
<RevisionPreview
|
||||
noteContent={noteContent}
|
||||
revisionItem={currentRevision}
|
||||
showDiff={showDiff}
|
||||
setShown={setShown}
|
||||
onRevisionDeleted={() => {
|
||||
setRefreshCounter(c => c + 1);
|
||||
setCurrentRevision(undefined);
|
||||
}} />
|
||||
</div>
|
||||
<div className="revision-content-wrapper" style={{
|
||||
flexGrow: "1",
|
||||
marginInlineStart: "20px",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
maxWidth: "calc(100% - 150px)",
|
||||
minWidth: 0
|
||||
}}>
|
||||
<RevisionPreview
|
||||
noteContent={noteContent}
|
||||
revisionItem={currentRevision}
|
||||
showDiff={showDiff}
|
||||
setShown={setShown}
|
||||
onRevisionDeleted={() => {
|
||||
setRefreshCounter(c => c + 1);
|
||||
setCurrentRevision(undefined);
|
||||
}} />
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function RevisionsList({ revisions, onSelect, currentRevision }: { revisions: RevisionItem[], onSelect: (val: string) => void, currentRevision?: RevisionItem }) {
|
||||
@@ -141,6 +146,7 @@ function RevisionsList({ revisions, onSelect, currentRevision }: { revisions: Re
|
||||
<FormList onSelect={onSelect} fullHeight wrapperClassName="revision-list">
|
||||
{revisions.map((item) =>
|
||||
<FormListItem
|
||||
key={item.revisionId}
|
||||
value={item.revisionId}
|
||||
active={currentRevision && item.revisionId === currentRevision.revisionId}
|
||||
>
|
||||
@@ -202,14 +208,17 @@ function RevisionPreview({noteContent, revisionItem, showDiff, setShown, onRevis
|
||||
text={t("revisions.download_button")}
|
||||
onClick={() => {
|
||||
if (revisionItem.revisionId) {
|
||||
open.downloadRevision(revisionItem.noteId, revisionItem.revisionId)}
|
||||
}
|
||||
open.downloadRevision(revisionItem.noteId, revisionItem.revisionId);}
|
||||
}
|
||||
}/>
|
||||
</>
|
||||
}
|
||||
</div>)}
|
||||
</div>
|
||||
<div className="revision-content use-tn-links selectable-text" style={{ overflow: "auto", wordBreak: "break-word" }}>
|
||||
<div
|
||||
className={clsx("revision-content use-tn-links selectable-text", `type-${revisionItem?.type}`)}
|
||||
style={{ overflow: "auto", wordBreak: "break-word" }}
|
||||
>
|
||||
<RevisionContent noteContent={noteContent} revisionItem={revisionItem} fullRevision={fullRevision} showDiff={showDiff}/>
|
||||
</div>
|
||||
</>
|
||||
@@ -230,16 +239,16 @@ const CODE_STYLE: CSSProperties = {
|
||||
|
||||
function RevisionContent({ noteContent, revisionItem, fullRevision, showDiff }: { noteContent?:string, revisionItem?: RevisionItem, fullRevision?: RevisionPojo, showDiff: boolean}) {
|
||||
const content = fullRevision?.content;
|
||||
if (!revisionItem || !content) {
|
||||
if (!revisionItem || !fullRevision) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
if (showDiff) {
|
||||
return <RevisionContentDiff noteContent={noteContent} itemContent={content} itemType={revisionItem.type}/>
|
||||
return <RevisionContentDiff noteContent={noteContent} itemContent={content} itemType={revisionItem.type}/>;
|
||||
}
|
||||
switch (revisionItem.type) {
|
||||
case "text":
|
||||
return <RevisionContentText content={content} />
|
||||
return <RevisionContentText content={content} />;
|
||||
case "code":
|
||||
return <pre style={CODE_STYLE}>{content}</pre>;
|
||||
case "image":
|
||||
@@ -256,28 +265,11 @@ function RevisionContent({ noteContent, revisionItem, fullRevision, showDiff }:
|
||||
// as a URL to be used in a note. Instead, if they copy and paste it into a note, it will be uploaded as a new note
|
||||
return <img
|
||||
src={`data:${fullRevision.mime};base64,${fullRevision.content}`}
|
||||
style={IMAGE_STYLE} />
|
||||
style={IMAGE_STYLE} />;
|
||||
}
|
||||
}
|
||||
case "file":
|
||||
return <table cellPadding="10">
|
||||
<tr>
|
||||
<th>{t("revisions.mime")}</th>
|
||||
<td>{revisionItem.mime}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{t("revisions.file_size")}</th>
|
||||
<td>{revisionItem.contentLength && utils.formatSize(revisionItem.contentLength)}</td>
|
||||
</tr>
|
||||
{fullRevision.content &&
|
||||
<tr>
|
||||
<td colspan={2}>
|
||||
<strong>{t("revisions.preview")}</strong>
|
||||
<pre className="file-preview-content" style={CODE_STYLE}>{fullRevision.content}</pre>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</table>;
|
||||
return <FilePreview fullRevision={fullRevision} revisionItem={revisionItem} />;
|
||||
case "canvas":
|
||||
case "mindMap":
|
||||
case "mermaid": {
|
||||
@@ -287,7 +279,7 @@ function RevisionContent({ noteContent, revisionItem, fullRevision, showDiff }:
|
||||
style={IMAGE_STYLE} />;
|
||||
}
|
||||
default:
|
||||
return <>{t("revisions.preview_not_available")}</>
|
||||
return <>{t("revisions.preview_not_available")}</>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,7 +290,7 @@ function RevisionContentText({ content }: { content: string | Buffer<ArrayBuffer
|
||||
renderMathInElement(contentRef.current, { trust: true });
|
||||
}
|
||||
}, [content]);
|
||||
return <div ref={contentRef} className="ck-content" dangerouslySetInnerHTML={{ __html: content as string }}></div>
|
||||
return <RawHtmlBlock containerRef={contentRef} className="ck-content" html={content as string} />;
|
||||
}
|
||||
|
||||
function RevisionContentDiff({ noteContent, itemContent, itemType }: {
|
||||
@@ -330,9 +322,9 @@ function RevisionContentDiff({ noteContent, itemContent, itemType }: {
|
||||
return `<span class="revision-diff-added">${utils.escapeHtml(part.value)}</span>`;
|
||||
} else if (part.removed) {
|
||||
return `<span class="revision-diff-removed">${utils.escapeHtml(part.value)}</span>`;
|
||||
} else {
|
||||
return utils.escapeHtml(part.value);
|
||||
}
|
||||
return utils.escapeHtml(part.value);
|
||||
|
||||
}).join("");
|
||||
|
||||
if (contentRef.current) {
|
||||
@@ -340,7 +332,7 @@ function RevisionContentDiff({ noteContent, itemContent, itemType }: {
|
||||
}
|
||||
}, [noteContent, itemContent, itemType]);
|
||||
|
||||
return <div ref={contentRef} className="ck-content" style={{ whiteSpace: "pre-wrap" }}></div>;
|
||||
return <div ref={contentRef} className="ck-content" style={{ whiteSpace: "pre-wrap" }} />;
|
||||
}
|
||||
|
||||
function RevisionFooter({ note }: { note?: FNote }) {
|
||||
@@ -348,7 +340,7 @@ function RevisionFooter({ note }: { note?: FNote }) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
let revisionsNumberLimit: number | string = parseInt(note?.getLabelValue("versioningLimit") ?? "");
|
||||
let revisionsNumberLimit: number | string = parseInt(note?.getLabelValue("versioningLimit") ?? "", 10);
|
||||
if (!Number.isInteger(revisionsNumberLimit)) {
|
||||
revisionsNumberLimit = options.getInt("revisionSnapshotNumberLimit") ?? 0;
|
||||
}
|
||||
@@ -370,10 +362,67 @@ function RevisionFooter({ note }: { note?: FNote }) {
|
||||
</>;
|
||||
}
|
||||
|
||||
function FilePreview({ revisionItem, fullRevision }: { revisionItem: RevisionItem, fullRevision: RevisionPojo }) {
|
||||
return (
|
||||
<div className="revision-file-preview">
|
||||
<table className="file-preview-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{t("revisions.mime")}</th>
|
||||
<td>{revisionItem.mime}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{t("revisions.file_size")}</th>
|
||||
<td>{revisionItem.contentLength && utils.formatSize(revisionItem.contentLength)}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="revision-file-preview-content">
|
||||
<FilePreviewInner revisionItem={revisionItem} fullRevision={fullRevision} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function FilePreviewInner({ revisionItem, fullRevision }: { revisionItem: RevisionItem, fullRevision: RevisionPojo }) {
|
||||
if (revisionItem.mime.startsWith("audio/")) {
|
||||
return (
|
||||
<audio
|
||||
src={`api/revisions/${revisionItem.revisionId}/download`}
|
||||
controls
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (revisionItem.mime.startsWith("video/")) {
|
||||
return (
|
||||
<video
|
||||
src={`api/revisions/${revisionItem.revisionId}/download`}
|
||||
controls
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (revisionItem.mime === "application/pdf") {
|
||||
return (
|
||||
<PdfViewer
|
||||
pdfUrl={`../../api/revisions/${revisionItem.revisionId}/download`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (fullRevision.content) {
|
||||
return <pre className="file-preview-content" style={CODE_STYLE}>{fullRevision.content}</pre>;
|
||||
}
|
||||
|
||||
return t("revisions.preview_not_available");
|
||||
}
|
||||
|
||||
async function getNote(noteId?: string | null) {
|
||||
if (noteId) {
|
||||
return await froca.getNote(noteId);
|
||||
} else {
|
||||
return appContext.tabManager.getActiveContextNote();
|
||||
}
|
||||
return appContext.tabManager.getActiveContextNote();
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -30,7 +30,7 @@ export function CustomNoteLauncher({ launcherNote, getTargetNoteId, getHoistedNo
|
||||
const activate = !!evt.shiftKey;
|
||||
await appContext.tabManager.openInNewTab(targetNoteId, hoistedNoteIdWithDefault, activate);
|
||||
} else {
|
||||
await appContext.tabManager.openInSameTab(targetNoteId);
|
||||
await appContext.tabManager.openInSameTab(targetNoteId, hoistedNoteIdWithDefault);
|
||||
}
|
||||
}, [ launcherNote, getTargetNoteId, getHoistedNoteId ]);
|
||||
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { useCallback, useLayoutEffect, useState } from "preact/hooks";
|
||||
|
||||
import FNote from "../../entities/fnote";
|
||||
import froca from "../../services/froca";
|
||||
import { isDesktop, isMobile } from "../../services/utils";
|
||||
import CalendarWidget from "./CalendarWidget";
|
||||
import SpacerWidget from "./SpacerWidget";
|
||||
import BookmarkButtons from "./BookmarkButtons";
|
||||
import ProtectedSessionStatusWidget from "./ProtectedSessionStatusWidget";
|
||||
import SyncStatus from "./SyncStatus";
|
||||
import HistoryNavigationButton from "./HistoryNavigation";
|
||||
import { AiChatButton, CommandButton, CustomWidget, NoteLauncher, QuickSearchLauncherWidget, ScriptLauncher, TodayLauncher } from "./LauncherDefinitions";
|
||||
import { useTriliumEvent } from "../react/hooks";
|
||||
import { onWheelHorizontalScroll } from "../widget_utils";
|
||||
import BookmarkButtons from "./BookmarkButtons";
|
||||
import CalendarWidget from "./CalendarWidget";
|
||||
import HistoryNavigationButton from "./HistoryNavigation";
|
||||
import { LaunchBarContext } from "./launch_bar_widgets";
|
||||
import { AiChatButton, CommandButton, CustomWidget, NoteLauncher, QuickSearchLauncherWidget, ScriptLauncher, TodayLauncher } from "./LauncherDefinitions";
|
||||
import ProtectedSessionStatusWidget from "./ProtectedSessionStatusWidget";
|
||||
import SpacerWidget from "./SpacerWidget";
|
||||
import SyncStatus from "./SyncStatus";
|
||||
|
||||
export default function LauncherContainer({ isHorizontalLayout }: { isHorizontalLayout: boolean }) {
|
||||
const childNotes = useLauncherChildNotes();
|
||||
@@ -34,18 +35,19 @@ export default function LauncherContainer({ isHorizontalLayout }: { isHorizontal
|
||||
}}>
|
||||
{childNotes?.map(childNote => {
|
||||
if (childNote.type !== "launcher") {
|
||||
throw new Error(`Note '${childNote.noteId}' '${childNote.title}' is not a launcher even though it's in the launcher subtree`);
|
||||
console.warn(`Note '${childNote.noteId}' '${childNote.title}' is not a launcher even though it's in the launcher subtree`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isDesktop() && childNote.isLabelTruthy("desktopOnly")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return <Launcher key={childNote.noteId} note={childNote} isHorizontalLayout={isHorizontalLayout} />
|
||||
return <Launcher key={childNote.noteId} note={childNote} isHorizontalLayout={isHorizontalLayout} />;
|
||||
})}
|
||||
</LaunchBarContext.Provider>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function Launcher({ note, isHorizontalLayout }: { note: FNote, isHorizontalLayout: boolean }) {
|
||||
@@ -72,7 +74,7 @@ function initBuiltinWidget(note: FNote, isHorizontalLayout: boolean) {
|
||||
const builtinWidget = note.getLabelValue("builtinWidget");
|
||||
switch (builtinWidget) {
|
||||
case "calendar":
|
||||
return <CalendarWidget launcherNote={note} />
|
||||
return <CalendarWidget launcherNote={note} />;
|
||||
case "spacer":
|
||||
// || has to be inside since 0 is a valid value
|
||||
const baseSize = parseInt(note.getLabelValue("baseSize") || "40");
|
||||
@@ -86,15 +88,15 @@ function initBuiltinWidget(note: FNote, isHorizontalLayout: boolean) {
|
||||
case "syncStatus":
|
||||
return <SyncStatus />;
|
||||
case "backInHistoryButton":
|
||||
return <HistoryNavigationButton launcherNote={note} command="backInNoteHistory" />
|
||||
return <HistoryNavigationButton launcherNote={note} command="backInNoteHistory" />;
|
||||
case "forwardInHistoryButton":
|
||||
return <HistoryNavigationButton launcherNote={note} command="forwardInNoteHistory" />
|
||||
return <HistoryNavigationButton launcherNote={note} command="forwardInNoteHistory" />;
|
||||
case "todayInJournal":
|
||||
return <TodayLauncher launcherNote={note} />
|
||||
return <TodayLauncher launcherNote={note} />;
|
||||
case "quickSearch":
|
||||
return <QuickSearchLauncherWidget />
|
||||
return <QuickSearchLauncherWidget />;
|
||||
case "aiChatLauncher":
|
||||
return <AiChatButton launcherNote={note} />
|
||||
return <AiChatButton launcherNote={note} />;
|
||||
default:
|
||||
throw new Error(`Unrecognized builtin widget ${builtinWidget} for launcher ${note.noteId} "${note.title}"`);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user