You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-08-24 20:19:10 +02:00
Compare commits
819 Commits
android-v0
...
android-v1
Author | SHA1 | Date | |
---|---|---|---|
|
c6466a780e | ||
|
43774ad3fb | ||
|
b3ba5b7747 | ||
|
599f4ccef4 | ||
|
a67600d264 | ||
|
ebf4c89ef0 | ||
|
aa7da784fc | ||
|
617ed42d8c | ||
|
5848e7d90d | ||
|
54d06646aa | ||
|
81da46035a | ||
|
74d0f75802 | ||
|
f25a352dcb | ||
|
21ef8da45f | ||
|
1f3a1c49df | ||
|
a8b58aaec3 | ||
|
44f9b35d93 | ||
|
711af9beed | ||
|
971339ca9a | ||
|
f5a72ffbaf | ||
|
cf4331c5af | ||
|
553b086ba2 | ||
|
ff89537899 | ||
|
f20792889a | ||
|
ee22a7ff73 | ||
|
4fc4353859 | ||
|
f4f9e25e6b | ||
|
e54f9934b5 | ||
|
f599ae065a | ||
|
5bd9bf6a4e | ||
|
cb9e8d4f76 | ||
|
f64596672e | ||
|
961150b2d3 | ||
|
0cd8e1cbc0 | ||
|
b503aff5e9 | ||
|
54bde47c67 | ||
|
d345f8dc13 | ||
|
979b0c0e78 | ||
|
13525f3327 | ||
|
5d9c2c0904 | ||
|
c748281d86 | ||
|
fa619eba7c | ||
|
17a75f7cf5 | ||
|
a74cfbfb25 | ||
|
af01fed950 | ||
|
218b446915 | ||
|
a68df18cd5 | ||
|
f79326b2d5 | ||
|
b08dcdfd90 | ||
|
ced14e578f | ||
|
0528c6e970 | ||
|
df9c1e0aeb | ||
|
b6619b41df | ||
|
ab9675544c | ||
|
0d9f703c75 | ||
|
f6ee5dd0e7 | ||
|
423d880b92 | ||
|
41017b9ab8 | ||
|
e3314c859f | ||
|
8f794fdbc6 | ||
|
80b0773618 | ||
|
ac848241b9 | ||
|
b4432e2efc | ||
|
52f60a2cf6 | ||
|
03c8438050 | ||
|
0e1c36ccf1 | ||
|
1b2b68c485 | ||
|
5c36f3e78a | ||
|
d4ec8ae823 | ||
|
449a70d840 | ||
|
8375030135 | ||
|
e9f938b0fb | ||
|
b0e57a5990 | ||
|
f47610e6fd | ||
|
c131cb9bb8 | ||
|
023f775bd2 | ||
|
1127eb6e09 | ||
|
0d7437c7d2 | ||
|
6dbc691973 | ||
|
fe53200a3a | ||
|
c7f61271a0 | ||
|
b826e2d97b | ||
|
d8ad42b04a | ||
|
b3ca30b8b6 | ||
|
bdd9da3d22 | ||
|
eb43ddc701 | ||
|
f9c65a148f | ||
|
bd0b9dff51 | ||
|
3822309657 | ||
|
ac2ec65c81 | ||
|
c0943f1776 | ||
|
5a2ab5fae7 | ||
|
281e36fde7 | ||
|
1af1c445c6 | ||
|
e6d2e028ad | ||
|
8d25b8075d | ||
|
58201fd6c3 | ||
|
2b624a9aed | ||
|
792fd7c50d | ||
|
90d37a15bd | ||
|
ef57ee803f | ||
|
e2bfb74895 | ||
|
89b486a3ee | ||
|
d6c6ef20d4 | ||
|
6cb6e9541f | ||
|
a8acecb703 | ||
|
0938297250 | ||
|
a2da2f681c | ||
|
32477e901d | ||
|
1841c4dc11 | ||
|
f81dce3321 | ||
|
e15f84716a | ||
|
d11ecd8fac | ||
|
012e70d668 | ||
|
264ee4f319 | ||
|
4640d6d6e3 | ||
|
9db9d98419 | ||
|
f79d7b9626 | ||
|
a8da469523 | ||
|
3c5eb99c59 | ||
|
8dc14516d6 | ||
|
84efc6a04e | ||
|
86e3038cfe | ||
|
6898b9ca4c | ||
|
9eb62920f7 | ||
|
7cf267254f | ||
|
5a0e3cbbf2 | ||
|
4b376ec5c2 | ||
|
92b71d3eb2 | ||
|
c32d7de7c4 | ||
|
c83a61d45d | ||
|
429f2d5aab | ||
|
ed70cf571c | ||
|
fd77671575 | ||
|
9d915a916e | ||
|
acb90935c7 | ||
|
6301ba0a12 | ||
|
44e1245416 | ||
|
6527d9db83 | ||
|
2bcaf62a2f | ||
|
2db3998f11 | ||
|
04724c58d1 | ||
|
7ed9c2770c | ||
|
48883bfa13 | ||
|
b6d9e695d1 | ||
|
43bab3c1bd | ||
|
dd67602b87 | ||
|
c96a416c2c | ||
|
c4ca9cde32 | ||
|
6c5d208893 | ||
|
795fd8b58c | ||
|
c226940792 | ||
|
bdd0a6106f | ||
|
d1ea7ad3ea | ||
|
a2b1181f7c | ||
|
8cce2f17d5 | ||
|
658b911513 | ||
|
3c95979d94 | ||
|
2e32211a28 | ||
|
ba2874173d | ||
|
ba9598682c | ||
|
30bfd82683 | ||
|
10c6774c28 | ||
|
c4ad9019aa | ||
|
7c99ab9947 | ||
|
feb7778fe4 | ||
|
b45185780f | ||
|
4e032c0c55 | ||
|
2e2b35dfeb | ||
|
526ef7e1d2 | ||
|
a37005446a | ||
|
e012b927dc | ||
|
359b8d5545 | ||
|
23c592b322 | ||
|
9aeddf86f4 | ||
|
0e1887988e | ||
|
394f2df664 | ||
|
2a04378a0d | ||
|
bac68f2c42 | ||
|
0f0ff86ffa | ||
|
8b38752cbf | ||
|
3c24589450 | ||
|
65065a62d8 | ||
|
482e9340bc | ||
|
69d490996e | ||
|
3494937e34 | ||
|
41ba1043be | ||
|
cc57de60c0 | ||
|
60a2b9e5c6 | ||
|
8e1fb666a5 | ||
|
f4ad777bbf | ||
|
2eacf6146a | ||
|
fe2ba34cb4 | ||
|
84daa0db61 | ||
|
b9118a90be | ||
|
ef2ffd4e52 | ||
|
5e3063abe0 | ||
|
f460b2497a | ||
|
c080d7054f | ||
|
61dd4cefbc | ||
|
63d99b2d70 | ||
|
55332d7671 | ||
|
16635defcd | ||
|
595cf3fcad | ||
|
c9b9f82130 | ||
|
f5bca733d7 | ||
|
494e235e18 | ||
|
85219a6004 | ||
|
e4a7851e57 | ||
|
b7529b40b5 | ||
|
74827e5324 | ||
|
2e16cc5433 | ||
|
7f41bc5703 | ||
|
a2380fb752 | ||
|
f6a902809d | ||
|
33a853397d | ||
|
4f02481899 | ||
|
b18076565f | ||
|
853ddc5840 | ||
|
7930ab66c6 | ||
|
c7716c0d59 | ||
|
49cbb254d0 | ||
|
cf9246796d | ||
|
e1dee546dc | ||
|
da6fdad2de | ||
|
567596643c | ||
|
cb617e1b14 | ||
|
facf8afa8b | ||
|
f0dd61a711 | ||
|
e958211a13 | ||
|
0ed170b5bc | ||
|
473d3453a2 | ||
|
fa9d7b0408 | ||
|
d4a28f48c9 | ||
|
ead6fff861 | ||
|
c7d06b35cd | ||
|
fa939e5c76 | ||
|
1bf2601f4f | ||
|
feb0c02c9a | ||
|
40a34a7c05 | ||
|
c62dcd96b0 | ||
|
1364d6786d | ||
|
9f2666aef9 | ||
|
a6a351e68d | ||
|
1db38a9699 | ||
|
c57db1834f | ||
|
3aeb49b469 | ||
|
80b467eead | ||
|
61572f287a | ||
|
f136664c11 | ||
|
0e545baf10 | ||
|
e65e647359 | ||
|
238268884e | ||
|
4c210d0956 | ||
|
5f32c6466a | ||
|
71bd39a8a3 | ||
|
ffb660f0f4 | ||
|
dde23632c1 | ||
|
9d26f13db0 | ||
|
2a4c9c4427 | ||
|
3bfde26b74 | ||
|
a419bc7253 | ||
|
89e0dad88b | ||
|
ff1ee1249b | ||
|
ba9cfd8041 | ||
|
80a51e02a4 | ||
|
a2e2a9a2f5 | ||
|
49e4c37cac | ||
|
11d323d8b7 | ||
|
784ba45f1f | ||
|
e534414874 | ||
|
01f4faf8f1 | ||
|
b33d30ca47 | ||
|
1ba3fae101 | ||
|
9550347e04 | ||
|
398946d39a | ||
|
05faf55e8d | ||
|
4cf5525e20 | ||
|
62e91c44d7 | ||
|
e4ec4ae92b | ||
|
c1f5dfd9cc | ||
|
0c0efeac1f | ||
|
5e0f2642e3 | ||
|
93966b0fa1 | ||
|
e90abf3517 | ||
|
d3fa0dce96 | ||
|
58a7c2fa94 | ||
|
962a8700c2 | ||
|
b5c704e2bb | ||
|
e7b52b19d7 | ||
|
903c2e6d92 | ||
|
abcb1ac760 | ||
|
b6bf76cc4c | ||
|
2bf87655da | ||
|
d4b19f19a1 | ||
|
d8ccc38d5b | ||
|
c8c9f80cc5 | ||
|
577bef5704 | ||
|
4e3b8a06ea | ||
|
363632ffa7 | ||
|
994c99f47f | ||
|
96571baadc | ||
|
4ce2b2c948 | ||
|
5d69f7a0a7 | ||
|
69ddcc6e30 | ||
|
bcb1f36ad8 | ||
|
34c65a686c | ||
|
0b32741a12 | ||
|
dbb321a3cc | ||
|
a6e4f47adf | ||
|
fb6dee32ac | ||
|
984dd6f2c0 | ||
|
02bde2c6e9 | ||
|
782d24cc04 | ||
|
4d0af575e5 | ||
|
be8bda8e73 | ||
|
1242de532e | ||
|
7d7ec7f15e | ||
|
ca112ec5d3 | ||
|
5deb8cf76d | ||
|
a2c9737c17 | ||
|
d3fca3d6cc | ||
|
16554b22c7 | ||
|
d5574098f0 | ||
|
f5a683f25c | ||
|
5f04adb392 | ||
|
edd0f7e255 | ||
|
67145d9104 | ||
|
003e2afff7 | ||
|
6e9d70c5cb | ||
|
4821b4cdf2 | ||
|
734d4db431 | ||
|
317aaed0ac | ||
|
9778098d6c | ||
|
5b1755f988 | ||
|
2a772895dd | ||
|
5fbb01cf2f | ||
|
f9e0870b4e | ||
|
a58f1e9b4b | ||
|
6fc0d89b30 | ||
|
2dcadab7d2 | ||
|
bb3307e156 | ||
|
ecd07f1209 | ||
|
266cb1174f | ||
|
bfb9b77b6e | ||
|
01b1361dcb | ||
|
3a921720d6 | ||
|
cdfd3d9c31 | ||
|
9961fb64bb | ||
|
3137c355cf | ||
|
16abaf60d2 | ||
|
9004b710ea | ||
|
6ebac21c2b | ||
|
99f79faf83 | ||
|
613fa20806 | ||
|
1b5f812278 | ||
|
3a9643c1ea | ||
|
aee7f5a8ac | ||
|
d3cd378922 | ||
|
4f5e7367d0 | ||
|
2280fb5c43 | ||
|
96fb7c2087 | ||
|
6e994fd8b9 | ||
|
a7cde1e269 | ||
|
f8310ba0d5 | ||
|
b239c3faba | ||
|
3c2281dbf9 | ||
|
ac07bf784d | ||
|
067455542f | ||
|
5bfeaa357b | ||
|
fe27a64331 | ||
|
ed638612aa | ||
|
1d7ec83510 | ||
|
75c710232d | ||
|
5af52afadb | ||
|
0f4324c2f8 | ||
|
b48e1dac94 | ||
|
f0ca8e1e31 | ||
|
74b83eb71e | ||
|
28dce0fbb5 | ||
|
c12d402c7e | ||
|
014f5b123c | ||
|
58601dfc04 | ||
|
9fe7f0adae | ||
|
ea1374371f | ||
|
bce4294529 | ||
|
de409b632a | ||
|
a677b2e844 | ||
|
c63bb19cb6 | ||
|
72fd77812e | ||
|
40f3e72bd1 | ||
|
d6d86f2aff | ||
|
c71809438b | ||
|
3e6e1a0a36 | ||
|
f590ce4a34 | ||
|
67608e29c8 | ||
|
d5c2982093 | ||
|
90fad2a3ab | ||
|
bc7c82e3da | ||
|
cb824f7dd7 | ||
|
32c47a96f1 | ||
|
4e3f8893f7 | ||
|
ca3946689a | ||
|
e2ad2dfcaa | ||
|
d6f7893c56 | ||
|
8c65a7cc31 | ||
|
aabb9be7de | ||
|
544f93bf22 | ||
|
f81dbf4a4c | ||
|
fbec8263a3 | ||
|
68d77a69e6 | ||
|
f2ef2446c6 | ||
|
875cb5387a | ||
|
ae9ecdad40 | ||
|
86a0e34975 | ||
|
1141074745 | ||
|
efc46d9989 | ||
|
2b45f745b6 | ||
|
37fb81e9b2 | ||
|
255a4fac93 | ||
|
3e3fb88de8 | ||
|
e4cf03ae46 | ||
|
554a3eb10d | ||
|
61881b528a | ||
|
c2507cbc4e | ||
|
ed0f6d165c | ||
|
8e22d38eb3 | ||
|
2599c425c3 | ||
|
0e15821a81 | ||
|
c1bb51c12b | ||
|
1532b6d159 | ||
|
945018b698 | ||
|
df7b981e5e | ||
|
4fe495675b | ||
|
7828eef2ad | ||
|
694f81b75f | ||
|
8364b6e08d | ||
|
3f4328ce9d | ||
|
9e0bf1acb2 | ||
|
c9e130a771 | ||
|
26331f61e1 | ||
|
694672859a | ||
|
858ead40b9 | ||
|
b07fe5cc34 | ||
|
0317171097 | ||
|
9741a3a53d | ||
|
7937fab5ff | ||
|
f595be07d4 | ||
|
eef106c99b | ||
|
dbe1833f92 | ||
|
520dc0ae21 | ||
|
c9be287f4a | ||
|
711f5dcaba | ||
|
ebc0aa9809 | ||
|
dcaaf50a5a | ||
|
3370b57134 | ||
|
55c5ddedf4 | ||
|
5e8b09f5af | ||
|
1acffce62d | ||
|
8555ecce87 | ||
|
4df5f668dc | ||
|
cceebeebef | ||
|
c4f19465a6 | ||
|
e868102c98 | ||
|
0d4a1837f5 | ||
|
d6a4436313 | ||
|
03b5c6aa5e | ||
|
250cd47e02 | ||
|
943fef32e7 | ||
|
408634671c | ||
|
570b5856ba | ||
|
d114d14e87 | ||
|
32791f502e | ||
|
083ab0c788 | ||
|
003c4c4e26 | ||
|
f08f89ebd4 | ||
|
3c973144c4 | ||
|
82e99ca658 | ||
|
b04d750cec | ||
|
c804e9f541 | ||
|
7753f3f842 | ||
|
c985b7c682 | ||
|
4509919c22 | ||
|
89b164c7ca | ||
|
e52d17b39a | ||
|
5014914dc9 | ||
|
122ab83a84 | ||
|
7a985c2c8a | ||
|
b11ad30a31 | ||
|
5914fc97df | ||
|
e41ae1832d | ||
|
89b50909ed | ||
|
edccd7412f | ||
|
c76beae057 | ||
|
23c5934a7d | ||
|
a078947d6d | ||
|
0faaf660b4 | ||
|
5ba98b4200 | ||
|
c36513b99d | ||
|
97814531fa | ||
|
fd3e335a02 | ||
|
e676fa2b57 | ||
|
122cbbf673 | ||
|
271793b324 | ||
|
134b31933b | ||
|
0ec5518a62 | ||
|
76931370d7 | ||
|
8cf0e4517a | ||
|
e75c62bf0f | ||
|
058285e0b9 | ||
|
795568d8c2 | ||
|
df4933fddd | ||
|
4046a51472 | ||
|
45845f645d | ||
|
d7fd8944f7 | ||
|
3cee671f25 | ||
|
8f2e5faff3 | ||
|
39ddd934f6 | ||
|
9f8a46b9d9 | ||
|
c6698eaea6 | ||
|
8a96cf3434 | ||
|
74d255c056 | ||
|
71aa841265 | ||
|
14a93a9f26 | ||
|
e1fd9c6922 | ||
|
b9db747b5c | ||
|
4a56c76901 | ||
|
6bb3184a72 | ||
|
7fb8fbd450 | ||
|
9d5bba472e | ||
|
e6d821a45f | ||
|
72f0027e21 | ||
|
29a13a9943 | ||
|
3691ae4d13 | ||
|
4dda397c29 | ||
|
b4b058998d | ||
|
10919e415e | ||
|
4966d74864 | ||
|
c70ecb30a5 | ||
|
acc0d17e0f | ||
|
b509b878bf | ||
|
322ec2efa1 | ||
|
1232661b1e | ||
|
c46d123503 | ||
|
8f4060999f | ||
|
0addd86069 | ||
|
760086307b | ||
|
fc6558a64c | ||
|
eca500880d | ||
|
90bcd7c977 | ||
|
cca0c6eaf3 | ||
|
b0736002be | ||
|
51fc2d8e51 | ||
|
d87c192ff1 | ||
|
52ccf398a6 | ||
|
344d0e2687 | ||
|
1bc4d6b423 | ||
|
baa9ca7ea3 | ||
|
e4d477fb4c | ||
|
71319eee28 | ||
|
68b31526f8 | ||
|
0b2b7324d9 | ||
|
43512cf27b | ||
|
4218b65969 | ||
|
7244e12b78 | ||
|
a796ef5c66 | ||
|
9474a05aaa | ||
|
41df355a7e | ||
|
4f3ab87914 | ||
|
5d1a08707c | ||
|
4f822df80e | ||
|
951be5cbf6 | ||
|
b6c2341542 | ||
|
a6e6b49a9d | ||
|
3a4bbd571e | ||
|
feccc6150e | ||
|
a37b599a6b | ||
|
9347683fe3 | ||
|
3551c26e28 | ||
|
cfca0107eb | ||
|
dfbe37fdaf | ||
|
81bc975193 | ||
|
7908fda451 | ||
|
cdbb7c4b0d | ||
|
414e57ec55 | ||
|
1871123066 | ||
|
87bc08bef5 | ||
|
214a39c3d3 | ||
|
ef0cc5e33e | ||
|
3a1fa583ab | ||
|
c1161ae017 | ||
|
1023ec6206 | ||
|
7841421c0d | ||
|
995d8c35dd | ||
|
b179471eff | ||
|
19a126ebfe | ||
|
7e56e5b587 | ||
|
acf0c79341 | ||
|
9fe7e23ffe | ||
|
c94cc93971 | ||
|
b26094eba8 | ||
|
89a5ccdf93 | ||
|
ce2da0e6dc | ||
|
f49d644b6a | ||
|
02ac0b8593 | ||
|
78e5eaf1e2 | ||
|
fc0d227396 | ||
|
f91c52cdf7 | ||
|
3f14878d0f | ||
|
69fd32e7c6 | ||
|
80801cedf0 | ||
|
480e4fa94b | ||
|
717c789836 | ||
|
f099376446 | ||
|
41fa9d093e | ||
|
e2f3f81eb6 | ||
|
5cab7aeb55 | ||
|
fa5f418c22 | ||
|
a25fcacace | ||
|
727ba7300e | ||
|
d25d9b3f44 | ||
|
9d762a4319 | ||
|
18d94c7585 | ||
|
af82345eb8 | ||
|
1e94a22986 | ||
|
e19a8a99ff | ||
|
f975009e24 | ||
|
90640fafc7 | ||
|
42e0e1e5a5 | ||
|
61f64fa933 | ||
|
0d0ffd6d27 | ||
|
023ccffd2e | ||
|
bc26098c7d | ||
|
7257a71a18 | ||
|
8ad8b73585 | ||
|
9a06815db9 | ||
|
66947d4954 | ||
|
3ec22185d5 | ||
|
0f05c23e26 | ||
|
74493fece0 | ||
|
557a96e814 | ||
|
4b23b419a4 | ||
|
8b7f5b1151 | ||
|
29e9ccf216 | ||
|
2c04f5c8bc | ||
|
5430a747e9 | ||
|
13bc185829 | ||
|
ed87581a8a | ||
|
2645ec96a8 | ||
|
d278d830f0 | ||
|
b4dce0ed46 | ||
|
e8416042d4 | ||
|
70adbe5e76 | ||
|
f66be08d1d | ||
|
fad96f5266 | ||
|
c33a7f5f47 | ||
|
28afbcde02 | ||
|
691292d2b3 | ||
|
30ff81064f | ||
|
f9f398ad98 | ||
|
537884bdcd | ||
|
d54400a7cb | ||
|
37e7ea0b52 | ||
|
42c78264fb | ||
|
c52da82447 | ||
|
cca43624e4 | ||
|
dac1cd7668 | ||
|
b4c00db0e3 | ||
|
3ce393a8b2 | ||
|
2b627fe4ab | ||
|
fcf8a1649d | ||
|
8d3b050831 | ||
|
43297ef0a3 | ||
|
551fabdfc9 | ||
|
d6de56b2db | ||
|
9e979804f3 | ||
|
b8e0f182cc | ||
|
9a41b9e192 | ||
|
9b8f520b9f | ||
|
5b6019805c | ||
|
a4106436c4 | ||
|
f6b4eb511e | ||
|
eb67ac17a0 | ||
|
7b760d03ef | ||
|
2805ae2acf | ||
|
5cb5ccc781 | ||
|
0dba2821b6 | ||
|
1db7825b22 | ||
|
8a92d6ad70 | ||
|
138ad9fcad | ||
|
08cb518c25 | ||
|
6d04eab200 | ||
|
8a8cb51e1b | ||
|
5c66042a2d | ||
|
ae75181b02 | ||
|
9dc3238182 | ||
|
0a68749373 | ||
|
1519116291 | ||
|
d023d841e2 | ||
|
d7a1465d8e | ||
|
15848fc696 | ||
|
837ae2c9f2 | ||
|
6789b98ead | ||
|
29f6e74ee3 | ||
|
2780c38c45 | ||
|
4531838217 | ||
|
7bccf7f65d | ||
|
c62a24a9cb | ||
|
c6830499f7 | ||
|
d9f00a2539 | ||
|
def83c9119 | ||
|
b6cb0056c7 | ||
|
1669b5258a | ||
|
5a9e0bfc26 | ||
|
8f3fdb3afe | ||
|
7ab135c099 | ||
|
1cc27f2509 | ||
|
ef700b421c | ||
|
b9af5ac052 | ||
|
173f2d421d | ||
|
9f82c069c9 | ||
|
6ade09c228 | ||
|
5393a1399c | ||
|
fd29f20b2e | ||
|
c011b53d1f | ||
|
26e3a7b68c | ||
|
e70a291698 | ||
|
511bd57726 | ||
|
c6de8598dc | ||
|
7bee25599d | ||
|
773a1ad829 | ||
|
1a1e264fa4 | ||
|
5b99ecefca | ||
|
1bfeed377a | ||
|
86eee376bb | ||
|
6a7d368184 | ||
|
1da19ae98d | ||
|
f52c117b09 | ||
|
2551f96149 | ||
|
c984c19fee | ||
|
ac8e91e82e | ||
|
af50d80541 | ||
|
e355f4e49b | ||
|
738ef2b0fa | ||
|
9746a3964b | ||
|
9efbf74b6f | ||
|
c16ea6b237 | ||
|
b06a3b588f | ||
|
6ff67e0995 | ||
|
1a5c8d126d | ||
|
f632580eed | ||
|
1d73f0cdee | ||
|
99c7111f8c | ||
|
ae9806561a | ||
|
fffdf5b5b7 | ||
|
3de19c3db7 | ||
|
56e074b4ef | ||
|
1a79253780 | ||
|
b67908df11 | ||
|
6a5089f71d | ||
|
f710463b67 | ||
|
6ae0c3aba0 | ||
|
07c6347014 | ||
|
b10999e83e | ||
|
961b5bfd25 | ||
|
d1f1d1068a | ||
|
faade0afe2 | ||
|
a442a49e2f | ||
|
7d3fbbcaba | ||
|
d9bb7c3271 | ||
|
4d1dd17fa2 | ||
|
c5c6c777be | ||
|
1fd1a73fda | ||
|
feeb498a79 | ||
|
1d7f30d441 | ||
|
53da63e371 | ||
|
424443a2d8 | ||
|
08b58f0e4c | ||
|
c2a0d8600f | ||
|
ede3c2ce2f | ||
|
0b93515711 | ||
|
2f13e689b9 | ||
|
ea135a0d28 | ||
|
f67e4a03e4 | ||
|
e9268edeff | ||
|
a8576a55d6 | ||
|
eb500cdf9e | ||
|
7b9dc66121 | ||
|
bba2c68c6f | ||
|
c70d8bea78 | ||
|
176bda66ad | ||
|
78ce10ddf0 | ||
|
29f14681a8 | ||
|
aaf617e41c | ||
|
b99146ed7f | ||
|
d136161650 | ||
|
39051a27a1 | ||
|
30bc9dd551 | ||
|
cc2f665313 | ||
|
37c989ed28 | ||
|
adc5885980 | ||
|
8de5b4219d | ||
|
e096ddebd4 | ||
|
83398dd0bc | ||
|
ddc78ebb41 | ||
|
70b69eb31e | ||
|
3fa891e136 | ||
|
6f7a9f3295 | ||
|
44bf518244 | ||
|
63cb9b4968 | ||
|
a6cecc103c | ||
|
8e8793943b | ||
|
83d9faf2fe | ||
|
f45a4fff8b | ||
|
1e02aa3120 | ||
|
77fec75f23 | ||
|
277ad90f72 | ||
|
f2e3bedde6 | ||
|
98c0f2315a |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -35,4 +35,9 @@ _vieux/
|
||||
_mydocs
|
||||
.DS_Store
|
||||
Assets/DownloadBadges*.psd
|
||||
node_modules
|
||||
node_modules
|
||||
Tools/github_oauth_token.txt
|
||||
_releases
|
||||
ReactNativeClient/lib/csstojs/
|
||||
ElectronClient/app/gui/note-viewer/fonts/
|
||||
Tools/commit_hook.txt
|
18
.travis.yml
18
.travis.yml
@@ -1,5 +1,16 @@
|
||||
# Only build tags (Doesn't work - doesn't build anything)
|
||||
if: tag IS present
|
||||
|
||||
rvm: 2.3.3
|
||||
|
||||
# It's important to only build production branches otherwise Electron Builder
|
||||
# might take assets from dev branches and overwrite those of production.
|
||||
# https://docs.travis-ci.com/user/customizing-the-build/#Building-Specific-Branches
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: osx
|
||||
@@ -43,7 +54,8 @@ before_install:
|
||||
|
||||
script:
|
||||
- |
|
||||
cd ElectronClient/app
|
||||
rsync -aP --delete ../../ReactNativeClient/lib/ lib/
|
||||
cd Tools
|
||||
npm install
|
||||
yarn dist
|
||||
cd ../ElectronClient/app
|
||||
rsync -aP --delete ../../ReactNativeClient/lib/ lib/
|
||||
npm install && yarn dist
|
||||
|
62
Assets/JoplinLetter.svg
Normal file
62
Assets/JoplinLetter.svg
Normal file
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="116.54575mm"
|
||||
height="131.19589mm"
|
||||
viewBox="0 0 116.54575 131.19589"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
|
||||
sodipodi:docname="JoplinLetter.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.49497475"
|
||||
inkscape:cx="152.11122"
|
||||
inkscape:cy="-26.090631"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-2.7903623,-2.175533)">
|
||||
<path
|
||||
style="fill:#000000;stroke-width:0.26458332"
|
||||
d="m 43.790458,133.13317 c -8.32317,-1.11843 -12.937,-2.40956 -18.46857,-5.16822 -10.21924,-5.09644 -18.1023498,-13.95338 -21.1745998,-23.79038 -1.22214,-3.91319 -1.3607,-4.872332 -1.35685,-9.392712 0.003,-3.72804 0.0907,-4.66941 0.59927,-6.44569 1.0664,-3.7246 2.49409,-6.1704 5.19529,-8.90014 3.2574198,-3.29184 6.6565798,-4.77332 11.3929598,-4.96548 4.53189,-0.18388 7.54661,0.59927 10.40386,2.70266 1.82035,1.34007 3.67693,3.96421 4.71565,6.66525 0.65839,1.71204 0.70959,2.1839 0.90042,8.29756 0.19973,6.39855 0.36372,7.6318 1.39223,10.469902 1.40468,3.87611 3.78939,6.56189 7.33039,8.25588 3.20047,1.53108 5.63801,2.00183 9.60817,1.8556 2.58182,-0.0951 3.60332,-0.25442 5.15337,-0.80371 4.61358,-1.63493 8.46322,-5.31381 10.31326,-9.85579 1.91154,-4.693002 1.90785,-4.609372 1.90213,-43.127082 -0.005,-33.78395 -0.0106,-34.14337 -0.54484,-35.32188 -1.30698,-2.882895 -2.68223,-3.398165 -9.66971,-3.622945 l -5.12472,-0.16486 V 10.998334 2.175533 l 31.41927,0.06723 31.419272,0.06723 0.0697,8.755726 0.0697,8.755724 -5.09675,0.1793 c -2.82759,0.0995 -5.60596,0.33101 -6.24051,0.52006 -1.72896,0.5151 -2.82899,1.538795 -3.52569,3.281045 l -0.61059,1.5269 -0.16762,34.7927 c -0.16988,35.26321 -0.19381,36.08914 -1.18496,40.914372 -1.81292,8.82581 -8.301582,17.89221 -16.959672,23.69719 -6.95182,4.66099 -14.48972,7.21214 -24.82645,8.40235 -2.7431,0.31585 -14.57797,0.31433 -16.93333,-0.002 z"
|
||||
id="path21"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.1 KiB |
26
BUILD.md
26
BUILD.md
@@ -8,7 +8,7 @@
|
||||
brew install yarn node
|
||||
echo 'export PATH="/usr/local/opt/gettext/bin:$PATH"' >> ~/.bash_profile
|
||||
source ~/.bash_profile
|
||||
|
||||
|
||||
If you get a node-gyp related error you might need to manually install it: `npm install -g node-gyp`
|
||||
|
||||
## Linux and Windows (WSL) dependencies
|
||||
@@ -17,6 +17,15 @@ If you get a node-gyp related error you might need to manually install it: `npm
|
||||
- Install node v8.x (check with `node --version`) - https://nodejs.org/en/
|
||||
- If you get a node-gyp related error you might need to manually install it: `npm install -g node-gyp`
|
||||
|
||||
# Building the tools
|
||||
|
||||
Before building any of the applications, you need to build the tools:
|
||||
|
||||
```
|
||||
cd Tools
|
||||
npm install
|
||||
```
|
||||
|
||||
# Building the Electron application
|
||||
|
||||
```
|
||||
@@ -32,6 +41,21 @@ That will create the executable file in the `dist` directory.
|
||||
|
||||
From `/ElectronClient` you can also run `run.sh` to run the app for testing.
|
||||
|
||||
## Building Electron application on Windows
|
||||
|
||||
```
|
||||
cd Tools
|
||||
npm install
|
||||
cd ..\ElectronClient\app
|
||||
xcopy /C /I /H /R /Y /S ..\..\ReactNativeClient\lib lib
|
||||
npm install
|
||||
yarn dist
|
||||
```
|
||||
|
||||
If node-gyp does not works (MSBUILD: error MSB3428: Could not load the Visual C++ component "VCBuild.exe"), you might need to install the `windows-build-tools` using `npm install --global windows-build-tools`.
|
||||
|
||||
If `yarn dist` fails, it may need administrative rights.
|
||||
|
||||
# Building the Mobile application
|
||||
|
||||
First you need to setup React Native to build projects with native code. For this, follow the instructions on the [Get Started](https://facebook.github.io/react-native/docs/getting-started.html) tutorial, in the "Building Projects with Native Code" tab.
|
||||
|
@@ -1,6 +1,19 @@
|
||||
# Adding new features
|
||||
If you want to add a new feature, consider asking about it before implementing it to make sure it is within the scope of the project. Of course you are free to create the pull request directly but it is not guaranteed it is going to be accepted.
|
||||
# User support
|
||||
|
||||
# Style
|
||||
- Only use tabs for indentation, not spaces.
|
||||
- Do not remove or add optional characters from other lines (such as colons or new line characters) as it can make the commit needlessly big, and create conflicts with other changes.
|
||||
For general discussion about Joplin, user support, software development questions, and to discuss new features, please go to the [Joplin Forum](https://discourse.joplin.cozic.net/). It is possible to login with your GitHub account.
|
||||
|
||||
# Reporting a bug
|
||||
|
||||
Please check first that it [has not already been reported](https://github.com/laurent22/joplin/issues?utf8=%E2%9C%93&q=is%3Aissue). Also consider [enabling debug mode](https://github.com/laurent22/joplin/blob/master/readme/debugging.md) before reporting the issue so that you can provide as much details as possible to help fix it.
|
||||
|
||||
If possible, **please provide a screenshot**. A screenshot showing the problem is often more useful than a paragraph describing it as it can make it immediately clear what the issue is.
|
||||
|
||||
# Feature requests
|
||||
|
||||
Again, please check that it has not already been requested. If it has, simply **up-vote the issue** - the ones with the most up-votes are likely to be implemented. "+1" comments are not tracked.
|
||||
|
||||
# Adding new features
|
||||
|
||||
If you want to add a new feature, consider asking about it before implementing it or checking existing discussions to make sure it is within the scope of the project. Of course you are free to create the pull request directly but it is not guaranteed it is going to be accepted.
|
||||
|
||||
Building the apps is relatively easy - please [see the build instructions](https://github.com/laurent22/joplin/blob/master/BUILD.md) for more details.
|
||||
|
3
CliClient/.gitignore
vendored
3
CliClient/.gitignore
vendored
@@ -18,4 +18,5 @@ tests/cli-integration/
|
||||
tests/sync
|
||||
out.txt
|
||||
linkToLocal.sh
|
||||
yarn-error.log
|
||||
yarn-error.log
|
||||
tests/support/dropbox-auth.txt
|
@@ -1,5 +1,6 @@
|
||||
const { Logger } = require('lib/logger.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const BaseItem = require('lib/models/BaseItem.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
@@ -9,6 +10,8 @@ const { reducer, defaultState } = require('lib/reducer.js');
|
||||
const { splitCommandString } = require('lib/string-utils.js');
|
||||
const { reg } = require('lib/registry.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const Entities = require('html-entities').AllHtmlEntities;
|
||||
const htmlentities = (new Entities()).encode;
|
||||
|
||||
const chalk = require('chalk');
|
||||
const tk = require('terminal-kit');
|
||||
@@ -35,38 +38,55 @@ const ConsoleWidget = require('./gui/ConsoleWidget.js');
|
||||
|
||||
class AppGui {
|
||||
|
||||
constructor(app, store) {
|
||||
this.app_ = app;
|
||||
this.store_ = store;
|
||||
constructor(app, store, keymap) {
|
||||
try {
|
||||
this.app_ = app;
|
||||
this.store_ = store;
|
||||
|
||||
BaseWidget.setLogger(app.logger());
|
||||
BaseWidget.setLogger(app.logger());
|
||||
|
||||
this.term_ = new TermWrapper(tk.terminal);
|
||||
this.term_ = new TermWrapper(tk.terminal);
|
||||
|
||||
this.renderer_ = null;
|
||||
this.logger_ = new Logger();
|
||||
this.buildUi();
|
||||
// Some keys are directly handled by the tkwidget framework
|
||||
// so they need to be remapped in a different way.
|
||||
this.tkWidgetKeys_ = {
|
||||
'focus_next': 'TAB',
|
||||
'focus_previous': 'SHIFT_TAB',
|
||||
'move_up': 'UP',
|
||||
'move_down': 'DOWN',
|
||||
'page_down': 'PAGE_DOWN',
|
||||
'page_up': 'PAGE_UP',
|
||||
};
|
||||
|
||||
this.renderer_ = new Renderer(this.term(), this.rootWidget_);
|
||||
this.renderer_ = null;
|
||||
this.logger_ = new Logger();
|
||||
this.buildUi();
|
||||
|
||||
this.app_.on('modelAction', async (event) => {
|
||||
await this.handleModelAction(event.action);
|
||||
});
|
||||
this.renderer_ = new Renderer(this.term(), this.rootWidget_);
|
||||
|
||||
this.shortcuts_ = this.setupShortcuts();
|
||||
this.app_.on('modelAction', async (event) => {
|
||||
await this.handleModelAction(event.action);
|
||||
});
|
||||
|
||||
this.inputMode_ = AppGui.INPUT_MODE_NORMAL;
|
||||
this.keymap_ = this.setupKeymap(keymap);
|
||||
|
||||
this.commandCancelCalled_ = false;
|
||||
this.inputMode_ = AppGui.INPUT_MODE_NORMAL;
|
||||
|
||||
this.currentShortcutKeys_ = [];
|
||||
this.lastShortcutKeyTime_ = 0;
|
||||
this.commandCancelCalled_ = false;
|
||||
|
||||
// Recurrent sync is setup only when the GUI is started. In
|
||||
// a regular command it's not necessary since the process
|
||||
// exits right away.
|
||||
reg.setupRecurrentSync();
|
||||
DecryptionWorker.instance().scheduleStart();
|
||||
this.currentShortcutKeys_ = [];
|
||||
this.lastShortcutKeyTime_ = 0;
|
||||
|
||||
// Recurrent sync is setup only when the GUI is started. In
|
||||
// a regular command it's not necessary since the process
|
||||
// exits right away.
|
||||
reg.setupRecurrentSync();
|
||||
DecryptionWorker.instance().scheduleStart();
|
||||
} catch (error) {
|
||||
this.fullScreen(false);
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
store() {
|
||||
@@ -105,6 +125,7 @@ class AppGui {
|
||||
buildUi() {
|
||||
this.rootWidget_ = new ReduxRootWidget(this.store_);
|
||||
this.rootWidget_.name = 'root';
|
||||
this.rootWidget_.autoShortcutsEnabled = false;
|
||||
|
||||
const folderList = new FolderListWidget();
|
||||
folderList.style = {
|
||||
@@ -269,155 +290,31 @@ class AppGui {
|
||||
|
||||
addCommandToConsole(cmd) {
|
||||
if (!cmd) return;
|
||||
const isConfigPassword = cmd.indexOf('config ') >= 0 && cmd.indexOf('password') >= 0;
|
||||
if (isConfigPassword) return;
|
||||
this.stdout(chalk.cyan.bold('> ' + cmd));
|
||||
}
|
||||
|
||||
setupShortcuts() {
|
||||
const shortcuts = {};
|
||||
setupKeymap(keymap) {
|
||||
const output = [];
|
||||
|
||||
shortcuts['TAB'] = {
|
||||
friendlyName: 'Tab',
|
||||
description: () => _('Give focus to next pane'),
|
||||
isDocOnly: true,
|
||||
}
|
||||
for (let i = 0; i < keymap.length; i++) {
|
||||
const item = Object.assign({}, keymap[i]);
|
||||
|
||||
shortcuts['SHIFT_TAB'] = {
|
||||
friendlyName: 'Shift+Tab',
|
||||
description: () => _('Give focus to previous pane'),
|
||||
isDocOnly: true,
|
||||
}
|
||||
if (!item.command) throw new Error('Missing command for keymap item: ' + JSON.stringify(item));
|
||||
|
||||
shortcuts[':'] = {
|
||||
description: () => _('Enter command line mode'),
|
||||
action: async () => {
|
||||
const cmd = await this.widget('statusBar').prompt();
|
||||
if (!cmd) return;
|
||||
this.addCommandToConsole(cmd);
|
||||
await this.processCommand(cmd);
|
||||
},
|
||||
};
|
||||
if (!('type' in item)) item.type = 'exec';
|
||||
|
||||
shortcuts['ESC'] = { // Built into terminal-kit inputField
|
||||
description: () => _('Exit command line mode'),
|
||||
isDocOnly: true,
|
||||
};
|
||||
|
||||
shortcuts['ENTER'] = {
|
||||
description: () => _('Edit the selected note'),
|
||||
action: () => {
|
||||
const w = this.widget('mainWindow').focusedWidget;
|
||||
if (w.name === 'folderList') {
|
||||
this.widget('noteList').focus();
|
||||
} else if (w.name === 'noteList' || w.name === 'noteText') {
|
||||
this.processCommand('edit $n');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
shortcuts['CTRL_C'] = {
|
||||
description: () => _('Cancel the current command.'),
|
||||
friendlyName: 'Ctrl+C',
|
||||
isDocOnly: true,
|
||||
}
|
||||
|
||||
shortcuts['CTRL_D'] = {
|
||||
description: () => _('Exit the application.'),
|
||||
friendlyName: 'Ctrl+D',
|
||||
isDocOnly: true,
|
||||
}
|
||||
|
||||
shortcuts['DELETE'] = {
|
||||
description: () => _('Delete the currently selected note or notebook.'),
|
||||
action: async () => {
|
||||
if (this.widget('folderList').hasFocus) {
|
||||
const item = this.widget('folderList').selectedJoplinItem;
|
||||
|
||||
if (!item) return;
|
||||
|
||||
if (item.type_ === BaseModel.TYPE_FOLDER) {
|
||||
await this.processCommand('rmbook ' + item.id);
|
||||
} else if (item.type_ === BaseModel.TYPE_TAG) {
|
||||
this.stdout(_('To delete a tag, untag the associated notes.'));
|
||||
} else if (item.type_ === BaseModel.TYPE_SEARCH) {
|
||||
this.store().dispatch({
|
||||
type: 'SEARCH_DELETE',
|
||||
id: item.id,
|
||||
});
|
||||
}
|
||||
} else if (this.widget('noteList').hasFocus) {
|
||||
await this.processCommand('rmnote $n');
|
||||
} else {
|
||||
this.stdout(_('Please select the note or notebook to be deleted first.'));
|
||||
}
|
||||
if (item.command in this.tkWidgetKeys_) {
|
||||
item.type = 'tkwidgets';
|
||||
}
|
||||
};
|
||||
|
||||
shortcuts['BACKSPACE'] = {
|
||||
alias: 'DELETE',
|
||||
};
|
||||
item.canRunAlongOtherCommands = item.type === 'function' && ['toggle_metadata', 'toggle_console'].indexOf(item.command) >= 0;
|
||||
|
||||
shortcuts[' '] = {
|
||||
friendlyName: 'SPACE',
|
||||
description: () => _('Set a to-do as completed / not completed'),
|
||||
action: 'todo toggle $n',
|
||||
output.push(item);
|
||||
}
|
||||
|
||||
shortcuts['tc'] = {
|
||||
description: () => _('[t]oggle [c]onsole between maximized/minimized/hidden/visible.'),
|
||||
action: () => {
|
||||
if (!this.consoleIsShown()) {
|
||||
this.showConsole();
|
||||
this.minimizeConsole();
|
||||
} else {
|
||||
if (this.consoleIsMaximized()) {
|
||||
this.hideConsole();
|
||||
} else {
|
||||
this.maximizeConsole();
|
||||
}
|
||||
}
|
||||
},
|
||||
canRunAlongOtherCommands: true,
|
||||
}
|
||||
|
||||
shortcuts['/'] = {
|
||||
description: () => _('Search'),
|
||||
action: { type: 'prompt', initialText: 'search ""', cursorPosition: -2 },
|
||||
};
|
||||
|
||||
shortcuts['tm'] = {
|
||||
description: () => _('[t]oggle note [m]etadata.'),
|
||||
action: () => {
|
||||
this.toggleNoteMetadata();
|
||||
},
|
||||
canRunAlongOtherCommands: true,
|
||||
}
|
||||
|
||||
shortcuts['mn'] = {
|
||||
description: () => _('[M]ake a new [n]ote'),
|
||||
action: { type: 'prompt', initialText: 'mknote ""', cursorPosition: -2 },
|
||||
}
|
||||
|
||||
shortcuts['mt'] = {
|
||||
description: () => _('[M]ake a new [t]odo'),
|
||||
action: { type: 'prompt', initialText: 'mktodo ""', cursorPosition: -2 },
|
||||
}
|
||||
|
||||
shortcuts['mb'] = {
|
||||
description: () => _('[M]ake a new note[b]ook'),
|
||||
action: { type: 'prompt', initialText: 'mkbook ""', cursorPosition: -2 },
|
||||
}
|
||||
|
||||
shortcuts['yn'] = {
|
||||
description: () => _('Copy ([Y]ank) the [n]ote to a notebook.'),
|
||||
action: { type: 'prompt', initialText: 'cp $n ""', cursorPosition: -2 },
|
||||
}
|
||||
|
||||
shortcuts['dn'] = {
|
||||
description: () => _('Move the note to a notebook.'),
|
||||
action: { type: 'prompt', initialText: 'mv $n ""', cursorPosition: -2 },
|
||||
}
|
||||
|
||||
return shortcuts;
|
||||
return output;
|
||||
}
|
||||
|
||||
toggleConsole() {
|
||||
@@ -492,8 +389,16 @@ class AppGui {
|
||||
return this.logger_;
|
||||
}
|
||||
|
||||
shortcuts() {
|
||||
return this.shortcuts_;
|
||||
keymap() {
|
||||
return this.keymap_;
|
||||
}
|
||||
|
||||
keymapItemByKey(key) {
|
||||
for (let i = 0; i < this.keymap_.length; i++) {
|
||||
const item = this.keymap_[i];
|
||||
if (item.keys.indexOf(key) >= 0) return item;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
term() {
|
||||
@@ -524,17 +429,77 @@ class AppGui {
|
||||
}
|
||||
}
|
||||
|
||||
async processCommand(cmd) {
|
||||
async processFunctionCommand(cmd) {
|
||||
|
||||
if (cmd === 'activate') {
|
||||
|
||||
const w = this.widget('mainWindow').focusedWidget;
|
||||
if (w.name === 'folderList') {
|
||||
this.widget('noteList').focus();
|
||||
} else if (w.name === 'noteList' || w.name === 'noteText') {
|
||||
this.processPromptCommand('edit $n');
|
||||
}
|
||||
|
||||
} else if (cmd === 'delete') {
|
||||
|
||||
if (this.widget('folderList').hasFocus) {
|
||||
const item = this.widget('folderList').selectedJoplinItem;
|
||||
|
||||
if (!item) return;
|
||||
|
||||
if (item.type_ === BaseModel.TYPE_FOLDER) {
|
||||
await this.processPromptCommand('rmbook ' + item.id);
|
||||
} else if (item.type_ === BaseModel.TYPE_TAG) {
|
||||
this.stdout(_('To delete a tag, untag the associated notes.'));
|
||||
} else if (item.type_ === BaseModel.TYPE_SEARCH) {
|
||||
this.store().dispatch({
|
||||
type: 'SEARCH_DELETE',
|
||||
id: item.id,
|
||||
});
|
||||
}
|
||||
} else if (this.widget('noteList').hasFocus) {
|
||||
await this.processPromptCommand('rmnote $n');
|
||||
} else {
|
||||
this.stdout(_('Please select the note or notebook to be deleted first.'));
|
||||
}
|
||||
|
||||
} else if (cmd === 'toggle_console') {
|
||||
|
||||
if (!this.consoleIsShown()) {
|
||||
this.showConsole();
|
||||
this.minimizeConsole();
|
||||
} else {
|
||||
if (this.consoleIsMaximized()) {
|
||||
this.hideConsole();
|
||||
} else {
|
||||
this.maximizeConsole();
|
||||
}
|
||||
}
|
||||
|
||||
} else if (cmd === 'toggle_metadata') {
|
||||
|
||||
this.toggleNoteMetadata();
|
||||
|
||||
} else if (cmd === 'enter_command_line_mode') {
|
||||
|
||||
const cmd = await this.widget('statusBar').prompt();
|
||||
if (!cmd) return;
|
||||
this.addCommandToConsole(cmd);
|
||||
await this.processPromptCommand(cmd);
|
||||
|
||||
} else {
|
||||
|
||||
throw new Error('Unknown command: ' + cmd);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
async processPromptCommand(cmd) {
|
||||
if (!cmd) return;
|
||||
cmd = cmd.trim();
|
||||
if (!cmd.length) return;
|
||||
|
||||
this.logger().info('Got command: ' + cmd);
|
||||
|
||||
if (cmd === 'q' || cmd === 'wq' || cmd === 'qa') { // Vim bonus
|
||||
await this.app().exit();
|
||||
return;
|
||||
}
|
||||
// this.logger().debug('Got command: ' + cmd);
|
||||
|
||||
try {
|
||||
let note = this.widget('noteList').currentItem;
|
||||
@@ -676,12 +641,27 @@ class AppGui {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (link.type === 'resource') {
|
||||
const resourceId = link.id;
|
||||
let resource = await Resource.load(resourceId);
|
||||
if (!resource) throw new Error('No resource with ID ' + resourceId); // Should be nearly impossible
|
||||
if (resource.mime) response.setHeader('Content-Type', resource.mime);
|
||||
response.write(await Resource.content(resource));
|
||||
if (link.type === 'item') {
|
||||
const itemId = link.id;
|
||||
let item = await BaseItem.loadItemById(itemId);
|
||||
if (!item) throw new Error('No item with ID ' + itemId); // Should be nearly impossible
|
||||
|
||||
if (item.type_ === BaseModel.TYPE_RESOURCE) {
|
||||
if (item.mime) response.setHeader('Content-Type', item.mime);
|
||||
response.write(await Resource.content(item));
|
||||
} else if (item.type_ === BaseModel.TYPE_NOTE) {
|
||||
const html = [`
|
||||
<!DOCTYPE html>
|
||||
<html class="client-nojs" lang="en" dir="ltr">
|
||||
<head><meta charset="UTF-8"/></head><body>
|
||||
`];
|
||||
html.push('<pre>' + htmlentities(item.title) + '\n\n' + htmlentities(item.body) + '</pre>');
|
||||
html.push('</body></html>');
|
||||
response.write(html.join(''));
|
||||
} else {
|
||||
throw new Error('Unsupported item type: ' + item.type_);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -697,7 +677,7 @@ class AppGui {
|
||||
|
||||
if (resourceIdRegex.test(url)) {
|
||||
noteLinks[index] = {
|
||||
type: 'resource',
|
||||
type: 'item',
|
||||
id: url.substr(2),
|
||||
};
|
||||
} else if (hasProtocol(url, ['http', 'https', 'file', 'ftp'])) {
|
||||
@@ -786,35 +766,34 @@ class AppGui {
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
const shortcutKey = this.currentShortcutKeys_.join('');
|
||||
let cmd = shortcutKey in this.shortcuts_ ? this.shortcuts_[shortcutKey] : null;
|
||||
let keymapItem = this.keymapItemByKey(shortcutKey);
|
||||
|
||||
// If this command is an alias to another command, resolve to the actual command
|
||||
if (cmd && cmd.alias) cmd = this.shortcuts_[cmd.alias];
|
||||
|
||||
let processShortcutKeys = !this.app().currentCommand() && cmd;
|
||||
if (cmd && cmd.canRunAlongOtherCommands) processShortcutKeys = true;
|
||||
let processShortcutKeys = !this.app().currentCommand() && keymapItem;
|
||||
if (keymapItem && keymapItem.canRunAlongOtherCommands) processShortcutKeys = true;
|
||||
if (statusBar.promptActive) processShortcutKeys = false;
|
||||
if (cmd && cmd.isDocOnly) processShortcutKeys = false;
|
||||
|
||||
if (processShortcutKeys) {
|
||||
this.logger().info('Shortcut:', shortcutKey, cmd.description());
|
||||
this.logger().debug('Shortcut:', shortcutKey, keymapItem);
|
||||
|
||||
this.currentShortcutKeys_ = [];
|
||||
if (typeof cmd.action === 'function') {
|
||||
await cmd.action();
|
||||
} else if (typeof cmd.action === 'object') {
|
||||
if (cmd.action.type === 'prompt') {
|
||||
let promptOptions = {};
|
||||
if ('cursorPosition' in cmd.action) promptOptions.cursorPosition = cmd.action.cursorPosition;
|
||||
const commandString = await statusBar.prompt(cmd.action.initialText ? cmd.action.initialText : '', null, promptOptions);
|
||||
this.addCommandToConsole(commandString);
|
||||
await this.processCommand(commandString);
|
||||
} else {
|
||||
throw new Error('Unknown command: ' + JSON.stringify(cmd.action));
|
||||
}
|
||||
} else { // String
|
||||
this.stdout(cmd.action);
|
||||
await this.processCommand(cmd.action);
|
||||
|
||||
if (keymapItem.type === 'function') {
|
||||
this.processFunctionCommand(keymapItem.command);
|
||||
} else if (keymapItem.type === 'prompt') {
|
||||
let promptOptions = {};
|
||||
if ('cursorPosition' in keymapItem) promptOptions.cursorPosition = keymapItem.cursorPosition;
|
||||
const commandString = await statusBar.prompt(keymapItem.command ? keymapItem.command : '', null, promptOptions);
|
||||
this.addCommandToConsole(commandString);
|
||||
await this.processPromptCommand(commandString);
|
||||
} else if (keymapItem.type === 'exec') {
|
||||
this.stdout(keymapItem.command);
|
||||
await this.processPromptCommand(keymapItem.command);
|
||||
} else if (keymapItem.type === 'tkwidgets') {
|
||||
this.widget('root').handleKey(this.tkWidgetKeys_[keymapItem.command]);
|
||||
} else {
|
||||
throw new Error('Unknown command type: ' + JSON.stringify(keymapItem));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -5,6 +5,7 @@ const { JoplinDatabase } = require('lib/joplin-database.js');
|
||||
const { Database } = require('lib/database.js');
|
||||
const { FoldersScreenUtils } = require('lib/folders-screen-utils.js');
|
||||
const { DatabaseDriverNode } = require('lib/database-driver-node.js');
|
||||
const ResourceService = require('lib/services/ResourceService');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const BaseItem = require('lib/models/BaseItem.js');
|
||||
@@ -21,6 +22,7 @@ const os = require('os');
|
||||
const fs = require('fs-extra');
|
||||
const { cliUtils } = require('./cli-utils.js');
|
||||
const EventEmitter = require('events');
|
||||
const Cache = require('lib/Cache');
|
||||
|
||||
class Application extends BaseApplication {
|
||||
|
||||
@@ -34,6 +36,7 @@ class Application extends BaseApplication {
|
||||
this.allCommandsLoaded_ = false;
|
||||
this.showStackTraces_ = false;
|
||||
this.gui_ = null;
|
||||
this.cache_ = new Cache();
|
||||
}
|
||||
|
||||
gui() {
|
||||
@@ -223,12 +226,8 @@ class Application extends BaseApplication {
|
||||
async commandMetadata() {
|
||||
if (this.commandMetadata_) return this.commandMetadata_;
|
||||
|
||||
const osTmpdir = require('os-tmpdir');
|
||||
const storage = require('node-persist');
|
||||
await storage.init({ dir: osTmpdir() + '/commandMetadata', ttl: 1000 * 60 * 60 * 24 });
|
||||
|
||||
let output = await storage.getItem('metadata');
|
||||
if (Setting.value('env') != 'dev' && output) {
|
||||
let output = await this.cache_.getItem('metadata');
|
||||
if (output) {
|
||||
this.commandMetadata_ = output;
|
||||
return Object.assign({}, this.commandMetadata_);
|
||||
}
|
||||
@@ -242,7 +241,7 @@ class Application extends BaseApplication {
|
||||
output[n] = cmd.metadata();
|
||||
}
|
||||
|
||||
await storage.setItem('metadata', output);
|
||||
await this.cache_.setItem('metadata', output, 1000 * 60 * 60 * 24);
|
||||
|
||||
this.commandMetadata_ = output;
|
||||
return Object.assign({}, this.commandMetadata_);
|
||||
@@ -285,7 +284,7 @@ class Application extends BaseApplication {
|
||||
exit: () => {},
|
||||
showModalOverlay: (text) => {},
|
||||
hideModalOverlay: () => {},
|
||||
stdoutMaxWidth: () => { return 78; },
|
||||
stdoutMaxWidth: () => { return 100; },
|
||||
forceRender: () => {},
|
||||
termSaveState: () => {},
|
||||
termRestoreState: (state) => {},
|
||||
@@ -294,7 +293,7 @@ class Application extends BaseApplication {
|
||||
|
||||
async execCommand(argv) {
|
||||
if (!argv.length) return this.execCommand(['help']);
|
||||
reg.logger().info('execCommand()', argv);
|
||||
// reg.logger().debug('execCommand()', argv);
|
||||
const commandName = argv[0];
|
||||
this.activeCommand_ = this.findCommandByName(commandName);
|
||||
|
||||
@@ -314,6 +313,63 @@ class Application extends BaseApplication {
|
||||
return this.activeCommand_;
|
||||
}
|
||||
|
||||
async loadKeymaps() {
|
||||
const defaultKeyMap = [
|
||||
{ "keys": [":"], "type": "function", "command": "enter_command_line_mode" },
|
||||
{ "keys": ["TAB"], "type": "function", "command": "focus_next" },
|
||||
{ "keys": ["SHIFT_TAB"], "type": "function", "command": "focus_previous" },
|
||||
{ "keys": ["UP"], "type": "function", "command": "move_up" },
|
||||
{ "keys": ["DOWN"], "type": "function", "command": "move_down" },
|
||||
{ "keys": ["PAGE_UP"], "type": "function", "command": "page_up" },
|
||||
{ "keys": ["PAGE_DOWN"], "type": "function", "command": "page_down" },
|
||||
{ "keys": ["ENTER"], "type": "function", "command": "activate" },
|
||||
{ "keys": ["DELETE", "BACKSPACE"], "type": "function", "command": "delete" },
|
||||
{ "keys": [" "], "command": "todo toggle $n" },
|
||||
{ "keys": ["tc"], "type": "function", "command": "toggle_console" },
|
||||
{ "keys": ["tm"], "type": "function", "command": "toggle_metadata" },
|
||||
{ "keys": ["/"], "type": "prompt", "command": "search \"\"", "cursorPosition": -2 },
|
||||
{ "keys": ["mn"], "type": "prompt", "command": "mknote \"\"", "cursorPosition": -2 },
|
||||
{ "keys": ["mt"], "type": "prompt", "command": "mktodo \"\"", "cursorPosition": -2 },
|
||||
{ "keys": ["mb"], "type": "prompt", "command": "mkbook \"\"", "cursorPosition": -2 },
|
||||
{ "keys": ["yn"], "type": "prompt", "command": "cp $n \"\"", "cursorPosition": -2 },
|
||||
{ "keys": ["dn"], "type": "prompt", "command": "mv $n \"\"", "cursorPosition": -2 }
|
||||
];
|
||||
|
||||
// Filter the keymap item by command so that items in keymap.json can override
|
||||
// the default ones.
|
||||
const itemsByCommand = {};
|
||||
|
||||
for (let i = 0; i < defaultKeyMap.length; i++) {
|
||||
itemsByCommand[defaultKeyMap[i].command] = defaultKeyMap[i]
|
||||
}
|
||||
|
||||
const filePath = Setting.value('profileDir') + '/keymap.json';
|
||||
if (await fs.pathExists(filePath)) {
|
||||
try {
|
||||
let configString = await fs.readFile(filePath, 'utf-8');
|
||||
configString = configString.replace(/^\s*\/\/.*/, ''); // Strip off comments
|
||||
const keymap = JSON.parse(configString);
|
||||
for (let keymapIndex = 0; keymapIndex < keymap.length; keymapIndex++) {
|
||||
const item = keymap[keymapIndex];
|
||||
itemsByCommand[item.command] = item;
|
||||
}
|
||||
} catch (error) {
|
||||
let msg = error.message ? error.message : '';
|
||||
msg = 'Could not load keymap ' + filePath + '\n' + msg;
|
||||
error.message = msg;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
const output = [];
|
||||
for (let n in itemsByCommand) {
|
||||
if (!itemsByCommand.hasOwnProperty(n)) continue;
|
||||
output.push(itemsByCommand[n]);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
async start(argv) {
|
||||
argv = await super.start(argv);
|
||||
|
||||
@@ -332,16 +388,19 @@ class Application extends BaseApplication {
|
||||
await this.execCommand(argv);
|
||||
} catch (error) {
|
||||
if (this.showStackTraces_) {
|
||||
console.info(error);
|
||||
console.error(error);
|
||||
} else {
|
||||
console.info(error.message);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
} else { // Otherwise open the GUI
|
||||
this.initRedux();
|
||||
|
||||
const keymap = await this.loadKeymaps();
|
||||
|
||||
const AppGui = require('./app-gui.js');
|
||||
this.gui_ = new AppGui(this, this.store());
|
||||
this.gui_ = new AppGui(this, this.store(), keymap);
|
||||
this.gui_.setLogger(this.logger_);
|
||||
await this.gui_.start();
|
||||
|
||||
@@ -354,6 +413,8 @@ class Application extends BaseApplication {
|
||||
|
||||
const tags = await Tag.allWithNotes();
|
||||
|
||||
ResourceService.runInBackground();
|
||||
|
||||
this.dispatch({
|
||||
type: 'TAG_UPDATE_ALL',
|
||||
items: tags,
|
||||
|
@@ -4,6 +4,7 @@ var Folder = require('lib/models/Folder.js');
|
||||
var Tag = require('lib/models/Tag.js');
|
||||
var { cliUtils } = require('./cli-utils.js');
|
||||
var yargParser = require('yargs-parser');
|
||||
var fs = require('fs-extra');
|
||||
|
||||
async function handleAutocompletionPromise(line) {
|
||||
// Auto-complete the command name
|
||||
@@ -35,7 +36,7 @@ async function handleAutocompletionPromise(line) {
|
||||
if (next[0] === '-') {
|
||||
for (let i = 0; i<metadata.options.length; i++) {
|
||||
const options = metadata.options[i][0].split(' ');
|
||||
//if there are multiple options then they will be seperated by comma and
|
||||
//if there are multiple options then they will be separated by comma and
|
||||
//space. The comma should be removed
|
||||
if (options[0][options[0].length - 1] === ',') {
|
||||
options[0] = options[0].slice(0, -1);
|
||||
@@ -48,7 +49,7 @@ async function handleAutocompletionPromise(line) {
|
||||
if (options.length > 1 && options[1].indexOf(next) === 0) {
|
||||
l.push(options[1]);
|
||||
} else if (options[0].indexOf(next) === 0) {
|
||||
l.push(options[2]);
|
||||
l.push(options[0]);
|
||||
}
|
||||
}
|
||||
if (l.length === 0) {
|
||||
@@ -71,8 +72,10 @@ async function handleAutocompletionPromise(line) {
|
||||
let argName = cmdUsage[positionalArgs - 1];
|
||||
argName = cliUtils.parseCommandArg(argName).name;
|
||||
|
||||
if (argName == 'note' || argName == 'note-pattern' && app().currentFolder()) {
|
||||
const notes = await Note.previews(app().currentFolder().id, { titlePattern: next + '*' });
|
||||
const currentFolder = app().currentFolder();
|
||||
|
||||
if (argName == 'note' || argName == 'note-pattern') {
|
||||
const notes = currentFolder ? await Note.previews(currentFolder.id, { titlePattern: next + '*' }) : [];
|
||||
l.push(...notes.map((n) => n.title));
|
||||
}
|
||||
|
||||
@@ -81,11 +84,22 @@ async function handleAutocompletionPromise(line) {
|
||||
l.push(...folders.map((n) => n.title));
|
||||
}
|
||||
|
||||
if (argName == 'item') {
|
||||
const notes = currentFolder ? await Note.previews(currentFolder.id, { titlePattern: next + '*' }) : [];
|
||||
const folders = await Folder.search({ titlePattern: next + '*' });
|
||||
l.push(...notes.map((n) => n.title), folders.map((n) => n.title));
|
||||
}
|
||||
|
||||
if (argName == 'tag') {
|
||||
let tags = await Tag.search({ titlePattern: next + '*' });
|
||||
l.push(...tags.map((n) => n.title));
|
||||
}
|
||||
|
||||
if (argName == 'file') {
|
||||
let files = await fs.readdir('.');
|
||||
l.push(...files);
|
||||
}
|
||||
|
||||
if (argName == 'tag-command') {
|
||||
let c = filterList(['add', 'remove', 'list'], next);
|
||||
l.push(...c);
|
||||
|
@@ -32,10 +32,6 @@ class BaseCommand {
|
||||
return this.compatibleUis().indexOf(ui) >= 0;
|
||||
}
|
||||
|
||||
aliases() {
|
||||
return [];
|
||||
}
|
||||
|
||||
options() {
|
||||
return [];
|
||||
}
|
||||
|
@@ -102,7 +102,7 @@ function getFooter() {
|
||||
|
||||
output.push('WEBSITE');
|
||||
output.push('');
|
||||
output.push(INDENT + 'http://joplin.cozic.net');
|
||||
output.push(INDENT + 'https://joplin.cozic.net');
|
||||
|
||||
output.push('');
|
||||
|
||||
|
@@ -23,7 +23,11 @@ class Command extends BaseCommand {
|
||||
const verbose = args.options.verbose;
|
||||
|
||||
const renderKeyValue = (name) => {
|
||||
const value = Setting.value(name);
|
||||
const md = Setting.settingMetadata(name);
|
||||
let value = Setting.value(name);
|
||||
if (typeof value === 'object' || Array.isArray(value)) value = JSON.stringify(value);
|
||||
if (md.secure) value = '********';
|
||||
|
||||
if (Setting.isEnum(name)) {
|
||||
return _('%s = %s (%s)', name, value, Setting.enumOptionsDoc(name));
|
||||
} else {
|
||||
|
@@ -131,7 +131,6 @@ class Command extends BaseCommand {
|
||||
} else if (stat.isDirectory()) {
|
||||
continue;
|
||||
} else {
|
||||
itemCount++;
|
||||
const content = await fs.readFile(fullPath, 'utf8');
|
||||
const item = await BaseItem.unserialize(content);
|
||||
const ItemClass = BaseItem.itemClass(item);
|
||||
@@ -141,6 +140,8 @@ class Command extends BaseCommand {
|
||||
continue;
|
||||
}
|
||||
|
||||
itemCount++;
|
||||
|
||||
const isEncrypted = await EncryptionService.instance().itemIsEncrypted(item);
|
||||
|
||||
if (isEncrypted) {
|
||||
|
@@ -81,7 +81,9 @@ class Command extends BaseCommand {
|
||||
const termState = app().gui().termSaveState();
|
||||
|
||||
const spawnSync = require('child_process').spawnSync;
|
||||
spawnSync(editorPath, editorArgs, { stdio: 'inherit' });
|
||||
const result = spawnSync(editorPath, editorArgs, { stdio: 'inherit' });
|
||||
|
||||
if (result.error) this.stdout(_('Error opening note in editor: %s', result.error.message));
|
||||
|
||||
app().gui().termRestoreState(termState);
|
||||
app().gui().hideModalOverlay();
|
||||
|
@@ -1,5 +1,5 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { Exporter } = require('lib/services/exporter.js');
|
||||
const InteropService = require('lib/services/InteropService.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const { reg } = require('lib/registry.js');
|
||||
@@ -10,15 +10,21 @@ const fs = require('fs-extra');
|
||||
class Command extends BaseCommand {
|
||||
|
||||
usage() {
|
||||
return 'export <directory>';
|
||||
return 'export <path>';
|
||||
}
|
||||
|
||||
description() {
|
||||
return _('Exports Joplin data to the given directory. By default, it will export the complete database including notebooks, notes, tags and resources.');
|
||||
return _('Exports Joplin data to the given path. By default, it will export the complete database including notebooks, notes, tags and resources.');
|
||||
}
|
||||
|
||||
options() {
|
||||
const service = new InteropService();
|
||||
const formats = service.modules()
|
||||
.filter(m => m.type === 'exporter')
|
||||
.map(m => m.format + (m.description ? ' (' + m.description + ')' : ''));
|
||||
|
||||
return [
|
||||
['--format <format>', _('Destination format: %s', formats.join(', '))],
|
||||
['--note <note>', _('Exports only the given note.')],
|
||||
['--notebook <notebook>', _('Exports only the given notebook.')],
|
||||
];
|
||||
@@ -26,13 +32,9 @@ class Command extends BaseCommand {
|
||||
|
||||
async action(args) {
|
||||
let exportOptions = {};
|
||||
exportOptions.destDir = args.directory;
|
||||
exportOptions.writeFile = (filePath, data) => {
|
||||
return fs.writeFile(filePath, data);
|
||||
};
|
||||
exportOptions.copyFile = (source, dest) => {
|
||||
return fs.copy(source, dest, { overwrite: true });
|
||||
};
|
||||
exportOptions.path = args.path;
|
||||
|
||||
exportOptions.format = args.options.format ? args.options.format : 'jex';
|
||||
|
||||
if (args.options.note) {
|
||||
|
||||
@@ -48,10 +50,10 @@ class Command extends BaseCommand {
|
||||
|
||||
}
|
||||
|
||||
const exporter = new Exporter();
|
||||
const result = await exporter.export(exportOptions);
|
||||
const service = new InteropService();
|
||||
const result = await service.export(exportOptions);
|
||||
|
||||
reg.logger().info('Export result: ', result);
|
||||
result.warnings.map((w) => this.stdout(w));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -36,21 +36,22 @@ class Command extends BaseCommand {
|
||||
async action(args) {
|
||||
const stdoutWidth = app().commandStdoutMaxWidth();
|
||||
|
||||
if (args.command === 'shortcuts') {
|
||||
if (args.command === 'shortcuts' || args.command === 'keymap') {
|
||||
this.stdout(_('For information on how to customise the shortcuts please visit %s', 'https://joplin.cozic.net/terminal/#shortcuts'));
|
||||
this.stdout('');
|
||||
|
||||
if (app().gui().isDummy()) {
|
||||
throw new Error(_('Shortcuts are not available in CLI mode.'));
|
||||
}
|
||||
|
||||
const shortcuts = app().gui().shortcuts();
|
||||
const keymap = app().gui().keymap();
|
||||
|
||||
let rows = [];
|
||||
|
||||
for (let n in shortcuts) {
|
||||
if (!shortcuts.hasOwnProperty(n)) continue;
|
||||
const shortcut = shortcuts[n];
|
||||
if (!shortcut.description) continue;
|
||||
n = shortcut.friendlyName ? shortcut.friendlyName : n;
|
||||
rows.push([n, shortcut.description()]);
|
||||
for (let i = 0; i < keymap.length; i++) {
|
||||
const item = keymap[i];
|
||||
const keys = item.keys.map((k) => k === ' ' ? '(SPACE)' : k);
|
||||
rows.push([keys.join(', '), item.command]);
|
||||
}
|
||||
|
||||
cliUtils.printArray(this.stdout.bind(this), rows);
|
||||
@@ -71,14 +72,14 @@ class Command extends BaseCommand {
|
||||
this.stdout('');
|
||||
this.stdout(commandNames.join(', '));
|
||||
this.stdout('');
|
||||
this.stdout(_('In any command, a note or notebook can be refered to by title or ID, or using the shortcuts `$n` or `$b` for, respectively, the currently selected note or notebook. `$c` can be used to refer to the currently selected item.'));
|
||||
this.stdout(_('In any command, a note or notebook can be referred to by title or ID, or using the shortcuts `$n` or `$b` for, respectively, the currently selected note or notebook. `$c` can be used to refer to the currently selected item.'));
|
||||
this.stdout('');
|
||||
this.stdout(_('To move from one pane to another, press Tab or Shift+Tab.'));
|
||||
this.stdout(_('Use the arrows and page up/down to scroll the lists and text areas (including this console).'));
|
||||
this.stdout(_('To maximise/minimise the console, press "TC".'));
|
||||
this.stdout(_('To maximise/minimise the console, press "tc".'));
|
||||
this.stdout(_('To enter command line mode, press ":"'));
|
||||
this.stdout(_('To exit command line mode, press ESCAPE'));
|
||||
this.stdout(_('For the complete list of available keyboard shortcuts, type `help shortcuts`'));
|
||||
this.stdout(_('For the list of keyboard shortcuts and config options, type `help keymap`'));
|
||||
}
|
||||
|
||||
app().gui().showConsole();
|
||||
|
@@ -1,68 +0,0 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const { importEnex } = require('lib/import-enex');
|
||||
const { filename, basename } = require('lib/path-utils.js');
|
||||
const { cliUtils } = require('./cli-utils.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
|
||||
usage() {
|
||||
return 'import-enex <file> [notebook]';
|
||||
}
|
||||
|
||||
description() {
|
||||
return _('Imports an Evernote notebook file (.enex file).');
|
||||
}
|
||||
|
||||
options() {
|
||||
return [
|
||||
['-f, --force', _('Do not ask for confirmation.')],
|
||||
];
|
||||
}
|
||||
|
||||
async action(args) {
|
||||
let filePath = args.file;
|
||||
let folder = null;
|
||||
let folderTitle = args['notebook'];
|
||||
let force = args.options.force === true;
|
||||
|
||||
if (!folderTitle) folderTitle = filename(filePath);
|
||||
folder = await Folder.loadByField('title', folderTitle);
|
||||
const msg = folder ? _('File "%s" will be imported into existing notebook "%s". Continue?', basename(filePath), folderTitle) : _('New notebook "%s" will be created and file "%s" will be imported into it. Continue?', folderTitle, basename(filePath));
|
||||
const ok = force ? true : await this.prompt(msg);
|
||||
if (!ok) return;
|
||||
|
||||
let lastProgress = '';
|
||||
|
||||
let options = {
|
||||
onProgress: (progressState) => {
|
||||
let line = [];
|
||||
line.push(_('Found: %d.', progressState.loaded));
|
||||
line.push(_('Created: %d.', progressState.created));
|
||||
if (progressState.updated) line.push(_('Updated: %d.', progressState.updated));
|
||||
if (progressState.skipped) line.push(_('Skipped: %d.', progressState.skipped));
|
||||
if (progressState.resourcesCreated) line.push(_('Resources: %d.', progressState.resourcesCreated));
|
||||
if (progressState.notesTagged) line.push(_('Tagged: %d.', progressState.notesTagged));
|
||||
lastProgress = line.join(' ');
|
||||
cliUtils.redraw(lastProgress);
|
||||
},
|
||||
onError: (error) => {
|
||||
let s = error.trace ? error.trace : error.toString();
|
||||
this.stdout(s);
|
||||
},
|
||||
}
|
||||
|
||||
folder = !folder ? await Folder.save({ title: folderTitle }) : folder;
|
||||
|
||||
app().gui().showConsole();
|
||||
this.stdout(_('Importing notes...'));
|
||||
await importEnex(folder.id, filePath, options);
|
||||
cliUtils.redrawDone();
|
||||
this.stdout(_('The notes have been imported: %s', lastProgress));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = Command;
|
75
CliClient/app/command-import.js
Normal file
75
CliClient/app/command-import.js
Normal file
@@ -0,0 +1,75 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const InteropService = require('lib/services/InteropService.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const { filename, basename, fileExtension } = require('lib/path-utils.js');
|
||||
const { importEnex } = require('lib/import-enex');
|
||||
const { cliUtils } = require('./cli-utils.js');
|
||||
const { reg } = require('lib/registry.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const fs = require('fs-extra');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
|
||||
usage() {
|
||||
return 'import <path> [notebook]';
|
||||
}
|
||||
|
||||
description() {
|
||||
return _('Imports data into Joplin.');
|
||||
}
|
||||
|
||||
options() {
|
||||
const service = new InteropService();
|
||||
const formats = service.modules().filter(m => m.type === 'importer').map(m => m.format);
|
||||
|
||||
return [
|
||||
['--format <format>', _('Source format: %s', (['auto'].concat(formats)).join(', '))],
|
||||
['-f, --force', _('Do not ask for confirmation.')],
|
||||
];
|
||||
}
|
||||
|
||||
async action(args) {
|
||||
let folder = await app().loadItem(BaseModel.TYPE_FOLDER, args.notebook);
|
||||
|
||||
if (args.notebook && !folder) throw new Error(_('Cannot find "%s".', args.notebook));
|
||||
|
||||
const importOptions = {};
|
||||
importOptions.path = args.path;
|
||||
importOptions.format = args.options.format ? args.options.format : 'auto';
|
||||
importOptions.destinationFolderId = folder ? folder.id : null;
|
||||
|
||||
let lastProgress = '';
|
||||
|
||||
// onProgress/onError supported by Enex import only
|
||||
|
||||
importOptions.onProgress = (progressState) => {
|
||||
let line = [];
|
||||
line.push(_('Found: %d.', progressState.loaded));
|
||||
line.push(_('Created: %d.', progressState.created));
|
||||
if (progressState.updated) line.push(_('Updated: %d.', progressState.updated));
|
||||
if (progressState.skipped) line.push(_('Skipped: %d.', progressState.skipped));
|
||||
if (progressState.resourcesCreated) line.push(_('Resources: %d.', progressState.resourcesCreated));
|
||||
if (progressState.notesTagged) line.push(_('Tagged: %d.', progressState.notesTagged));
|
||||
lastProgress = line.join(' ');
|
||||
cliUtils.redraw(lastProgress);
|
||||
};
|
||||
|
||||
importOptions.onError = (error) => {
|
||||
let s = error.trace ? error.trace : error.toString();
|
||||
this.stdout(s);
|
||||
};
|
||||
|
||||
app().gui().showConsole();
|
||||
this.stdout(_('Importing notes...'));
|
||||
const service = new InteropService();
|
||||
const result = await service.import(importOptions);
|
||||
result.warnings.map((w) => this.stdout(w));
|
||||
cliUtils.redrawDone();
|
||||
if (lastProgress) this.stdout(_('The notes have been imported: %s', lastProgress));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = Command;
|
@@ -14,10 +14,6 @@ class Command extends BaseCommand {
|
||||
return _('Creates a new notebook.');
|
||||
}
|
||||
|
||||
aliases() {
|
||||
return ['mkdir'];
|
||||
}
|
||||
|
||||
async action(args) {
|
||||
let folder = await Folder.save({ title: args['new-notebook'] }, { userSideValidation: true });
|
||||
app().switchCurrentFolder(folder);
|
||||
|
@@ -29,7 +29,7 @@ class Command extends BaseCommand {
|
||||
|
||||
const folder = await app().loadItem(BaseModel.TYPE_FOLDER, pattern);
|
||||
if (!folder) throw new Error(_('Cannot find "%s".', pattern));
|
||||
const ok = force ? true : await this.prompt(_('Delete notebook? All notes within this notebook will also be deleted.'), { booleanAnswerDefault: 'n' });
|
||||
const ok = force ? true : await this.prompt(_('Delete notebook? All notes and sub-notebooks within this notebook will also be deleted.'), { booleanAnswerDefault: 'n' });
|
||||
if (!ok) return;
|
||||
|
||||
await Folder.delete(folder.id);
|
||||
|
@@ -10,7 +10,7 @@ const { cliUtils } = require('./cli-utils.js');
|
||||
const md5 = require('md5');
|
||||
const locker = require('proper-lockfile');
|
||||
const fs = require('fs-extra');
|
||||
const osTmpdir = require('os-tmpdir');
|
||||
const SyncTargetRegistry = require('lib/SyncTargetRegistry');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
|
||||
@@ -61,14 +61,44 @@ class Command extends BaseCommand {
|
||||
});
|
||||
}
|
||||
|
||||
async doAuth(syncTargetId) {
|
||||
async doAuth() {
|
||||
const syncTarget = reg.syncTarget(this.syncTargetId_);
|
||||
this.oneDriveApiUtils_ = new OneDriveApiNodeUtils(syncTarget.api());
|
||||
const auth = await this.oneDriveApiUtils_.oauthDance({
|
||||
log: (...s) => { return this.stdout(...s); }
|
||||
});
|
||||
this.oneDriveApiUtils_ = null;
|
||||
return auth;
|
||||
const syncTargetMd = SyncTargetRegistry.idToMetadata(this.syncTargetId_);
|
||||
|
||||
if (this.syncTargetId_ === 3 || this.syncTargetId_ === 4) { // OneDrive
|
||||
this.oneDriveApiUtils_ = new OneDriveApiNodeUtils(syncTarget.api());
|
||||
const auth = await this.oneDriveApiUtils_.oauthDance({
|
||||
log: (...s) => { return this.stdout(...s); }
|
||||
});
|
||||
this.oneDriveApiUtils_ = null;
|
||||
|
||||
Setting.setValue('sync.' + this.syncTargetId_ + '.auth', auth ? JSON.stringify(auth) : null);
|
||||
if (!auth) {
|
||||
this.stdout(_('Authentication was not completed (did not receive an authentication token).'));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} else if (syncTargetMd.name === 'dropbox') { // Dropbox
|
||||
const api = await syncTarget.api();
|
||||
const loginUrl = api.loginUrl();
|
||||
this.stdout(_('To allow Joplin to synchronise with Dropbox, please follow the steps below:'));
|
||||
this.stdout(_('Step 1: Open this URL in your browser to authorise the application:'));
|
||||
this.stdout(loginUrl);
|
||||
const authCode = await this.prompt(_('Step 2: Enter the code provided by Dropbox:'), { type: 'string' });
|
||||
if (!authCode) {
|
||||
this.stdout(_('Authentication was not completed (did not receive an authentication token).'));
|
||||
return false;
|
||||
}
|
||||
|
||||
const response = await api.execAuthToken(authCode);
|
||||
Setting.setValue('sync.' + this.syncTargetId_ + '.auth', response.access_token);
|
||||
api.setAuthToken(response.access_token);
|
||||
return true;
|
||||
}
|
||||
|
||||
this.stdout(_('Not authentified with %s. Please provide any missing credentials.', syncTargetMd.label));
|
||||
return false;
|
||||
}
|
||||
|
||||
cancelAuth() {
|
||||
@@ -86,7 +116,8 @@ class Command extends BaseCommand {
|
||||
this.releaseLockFn_ = null;
|
||||
|
||||
// Lock is unique per profile/database
|
||||
const lockFilePath = osTmpdir() + '/synclock_' + md5(Setting.value('profileDir'));
|
||||
// TODO: use SQLite database to do lock?
|
||||
const lockFilePath = require('os').tmpdir() + '/synclock_' + md5(escape(Setting.value('profileDir'))); // https://github.com/pvorb/node-md5/issues/41
|
||||
if (!await fs.pathExists(lockFilePath)) await fs.writeFile(lockFilePath, 'synclock');
|
||||
|
||||
try {
|
||||
@@ -116,16 +147,12 @@ class Command extends BaseCommand {
|
||||
|
||||
const syncTarget = reg.syncTarget(this.syncTargetId_);
|
||||
|
||||
if (!syncTarget.isAuthenticated()) {
|
||||
if (!await syncTarget.isAuthenticated()) {
|
||||
app().gui().showConsole();
|
||||
app().gui().maximizeConsole();
|
||||
|
||||
const auth = await this.doAuth(this.syncTargetId_);
|
||||
Setting.setValue('sync.' + this.syncTargetId_ + '.auth', auth ? JSON.stringify(auth) : null);
|
||||
if (!auth) {
|
||||
this.stdout(_('Authentication was not completed (did not receive an authentication token).'));
|
||||
return cleanUp();
|
||||
}
|
||||
const authDone = await this.doAuth();
|
||||
if (!authDone) return cleanUp();
|
||||
}
|
||||
|
||||
const sync = await syncTarget.synchronizer();
|
||||
@@ -187,7 +214,7 @@ class Command extends BaseCommand {
|
||||
|
||||
const syncTarget = reg.syncTarget(syncTargetId);
|
||||
|
||||
if (syncTarget.isAuthenticated()) {
|
||||
if (await syncTarget.isAuthenticated()) {
|
||||
const sync = await syncTarget.synchronizer();
|
||||
if (sync) await sync.cancel();
|
||||
} else {
|
||||
|
@@ -18,19 +18,20 @@ class FolderListWidget extends ListWidget {
|
||||
this.notesParentType_ = 'Folder';
|
||||
this.updateIndexFromSelectedFolderId_ = false;
|
||||
this.updateItems_ = false;
|
||||
this.trimItemTitle = false;
|
||||
|
||||
this.itemRenderer = (item) => {
|
||||
let output = [];
|
||||
if (item === '-') {
|
||||
output.push('-'.repeat(this.innerWidth));
|
||||
} else if (item.type_ === Folder.modelType()) {
|
||||
output.push(Folder.displayTitle(item));
|
||||
output.push(' '.repeat(this.folderDepth(this.folders, item.id)) + Folder.displayTitle(item));
|
||||
} else if (item.type_ === Tag.modelType()) {
|
||||
output.push('[' + Folder.displayTitle(item) + ']');
|
||||
} else if (item.type_ === BaseModel.TYPE_SEARCH) {
|
||||
output.push(_('Search:'));
|
||||
output.push(item.title);
|
||||
}
|
||||
}
|
||||
|
||||
// if (item && item.id) output.push(item.id.substr(0, 5));
|
||||
|
||||
@@ -38,6 +39,17 @@ class FolderListWidget extends ListWidget {
|
||||
};
|
||||
}
|
||||
|
||||
folderDepth(folders, folderId) {
|
||||
let output = 0;
|
||||
while (true) {
|
||||
const folder = BaseModel.byId(folders, folderId);
|
||||
if (!folder.parent_id) return output;
|
||||
output++;
|
||||
folderId = folder.parent_id;
|
||||
}
|
||||
throw new Error('unreachable');
|
||||
}
|
||||
|
||||
get selectedFolderId() {
|
||||
return this.selectedFolderId_;
|
||||
}
|
||||
|
@@ -133,7 +133,8 @@ class StatusBarWidget extends BaseWidget {
|
||||
resolveResult = input ? input.trim() : input;
|
||||
// Add the command to history but only if it's longer than one character.
|
||||
// Below that it's usually an answer like "y"/"n", etc.
|
||||
if (!isSecurePrompt && input && input.length > 1) this.history_.push(input);
|
||||
const isConfigPassword = input.indexOf('config ') >= 0 && input.indexOf('password') >= 0;
|
||||
if (!isSecurePrompt && input && input.length > 1 && !isConfigPassword) this.history_.push(input);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -53,9 +53,8 @@ function renderCommandHelp(cmd, width = null) {
|
||||
desc.push(label);
|
||||
}
|
||||
|
||||
if (md.description) {
|
||||
desc.push(md.description());
|
||||
}
|
||||
const description = Setting.keyDescription(md.key, 'cli');
|
||||
if (description) desc.push(description);
|
||||
|
||||
desc.push(_('Type: %s.', md.isEnum ? _('Enum') : Setting.typeToString(md.type)));
|
||||
if (md.isEnum) desc.push(_('Possible values: %s.', Setting.enumOptionsDoc(md.key, '%s (%s)')));
|
||||
|
@@ -3,6 +3,13 @@
|
||||
// Make it possible to require("/lib/...") without specifying full path
|
||||
require('app-module-path').addPath(__dirname);
|
||||
|
||||
const compareVersion = require('compare-version');
|
||||
const nodeVersion = process && process.versions && process.versions.node ? process.versions.node : '0.0.0';
|
||||
if (compareVersion(nodeVersion, '8.0.0') < 0) {
|
||||
console.error('Joplin requires Node 8+. Detected version ' + nodeVersion);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const { app } = require('./app.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Resource = require('lib/models/Resource.js');
|
||||
@@ -16,12 +23,14 @@ const { Logger } = require('lib/logger.js');
|
||||
const { FsDriverNode } = require('lib/fs-driver-node.js');
|
||||
const { shimInit } = require('lib/shim-init-node.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { FileApiDriverLocal } = require('lib/file-api-driver-local.js');
|
||||
const EncryptionService = require('lib/services/EncryptionService');
|
||||
|
||||
const fsDriver = new FsDriverNode();
|
||||
Logger.fsDriver_ = fsDriver;
|
||||
Resource.fsDriver_ = fsDriver;
|
||||
EncryptionService.fsDriver_ = fsDriver;
|
||||
FileApiDriverLocal.fsDriver_ = fsDriver;
|
||||
|
||||
// That's not good, but it's to avoid circular dependency issues
|
||||
// in the BaseItem class.
|
||||
@@ -58,6 +67,13 @@ process.stdout.on('error', function( err ) {
|
||||
});
|
||||
|
||||
application.start(process.argv).catch((error) => {
|
||||
console.error(_('Fatal error:'));
|
||||
console.error(error);
|
||||
if (error.code == 'flagError') {
|
||||
console.error(error.message);
|
||||
console.error(_('Type `joplin help` for usage information.'));
|
||||
} else {
|
||||
console.error(_('Fatal error:'));
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
process.exit(1);
|
||||
});
|
1635
CliClient/locales/ca.po
Normal file
1635
CliClient/locales/ca.po
Normal file
File diff suppressed because it is too large
Load Diff
1606
CliClient/locales/cs_CZ.po
Normal file
1606
CliClient/locales/cs_CZ.po
Normal file
File diff suppressed because it is too large
Load Diff
1622
CliClient/locales/da_DK.po
Normal file
1622
CliClient/locales/da_DK.po
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -15,63 +15,12 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
msgid "Give focus to next pane"
|
||||
msgstr ""
|
||||
|
||||
msgid "Give focus to previous pane"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enter command line mode"
|
||||
msgstr ""
|
||||
|
||||
msgid "Exit command line mode"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit the selected note"
|
||||
msgstr ""
|
||||
|
||||
msgid "Cancel the current command."
|
||||
msgstr ""
|
||||
|
||||
msgid "Exit the application."
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete the currently selected note or notebook."
|
||||
msgstr ""
|
||||
|
||||
msgid "To delete a tag, untag the associated notes."
|
||||
msgstr ""
|
||||
|
||||
msgid "Please select the note or notebook to be deleted first."
|
||||
msgstr ""
|
||||
|
||||
msgid "Set a to-do as completed / not completed"
|
||||
msgstr ""
|
||||
|
||||
msgid "[t]oggle [c]onsole between maximized/minimized/hidden/visible."
|
||||
msgstr ""
|
||||
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
|
||||
msgid "[t]oggle note [m]etadata."
|
||||
msgstr ""
|
||||
|
||||
msgid "[M]ake a new [n]ote"
|
||||
msgstr ""
|
||||
|
||||
msgid "[M]ake a new [t]odo"
|
||||
msgstr ""
|
||||
|
||||
msgid "[M]ake a new note[b]ook"
|
||||
msgstr ""
|
||||
|
||||
msgid "Copy ([Y]ank) the [n]ote to a notebook."
|
||||
msgstr ""
|
||||
|
||||
msgid "Move the note to a notebook."
|
||||
msgstr ""
|
||||
|
||||
msgid "Press Ctrl+D or type \"exit\" to exit the application"
|
||||
msgstr ""
|
||||
|
||||
@@ -108,6 +57,9 @@ msgstr ""
|
||||
msgid "The command \"%s\" is only available in GUI mode"
|
||||
msgstr ""
|
||||
|
||||
msgid "Cannot change encrypted item"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Missing required argument: %s"
|
||||
msgstr ""
|
||||
@@ -165,6 +117,35 @@ msgstr ""
|
||||
msgid "Note is not a to-do: \"%s\""
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Manages E2EE configuration. Commands are `enable`, `disable`, `decrypt`, "
|
||||
"`status` and `target-status`."
|
||||
msgstr ""
|
||||
|
||||
msgid "Enter master password:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Operation cancelled"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Starting decryption... Please wait as it may take several minutes depending "
|
||||
"on how much there is to decrypt."
|
||||
msgstr ""
|
||||
|
||||
msgid "Completed decryption."
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Encryption is: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit note."
|
||||
msgstr ""
|
||||
|
||||
@@ -182,6 +163,10 @@ msgstr ""
|
||||
msgid "Starting to edit note. Close the editor to get back to the prompt."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Error opening note in editor: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note has been saved."
|
||||
msgstr ""
|
||||
|
||||
@@ -189,10 +174,14 @@ msgid "Exits the application."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Exports Joplin data to the given directory. By default, it will export the "
|
||||
"Exports Joplin data to the given path. By default, it will export the "
|
||||
"complete database including notebooks, notes, tags and resources."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Destination format: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Exports only the given note."
|
||||
msgstr ""
|
||||
|
||||
@@ -205,6 +194,10 @@ msgstr ""
|
||||
msgid "Displays usage information."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "For information on how to customise the shortcuts please visit %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Shortcuts are not available in CLI mode."
|
||||
msgstr ""
|
||||
|
||||
@@ -217,7 +210,7 @@ msgid "The possible commands are:"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"In any command, a note or notebook can be refered to by title or ID, or "
|
||||
"In any command, a note or notebook can be referred to by title or ID, or "
|
||||
"using the shortcuts `$n` or `$b` for, respectively, the currently selected "
|
||||
"note or notebook. `$c` can be used to refer to the currently selected item."
|
||||
msgstr ""
|
||||
@@ -230,7 +223,7 @@ msgid ""
|
||||
"(including this console)."
|
||||
msgstr ""
|
||||
|
||||
msgid "To maximise/minimise the console, press \"TC\"."
|
||||
msgid "To maximise/minimise the console, press \"tc\"."
|
||||
msgstr ""
|
||||
|
||||
msgid "To enter command line mode, press \":\""
|
||||
@@ -240,25 +233,19 @@ msgid "To exit command line mode, press ESCAPE"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"For the complete list of available keyboard shortcuts, type `help shortcuts`"
|
||||
"For the list of keyboard shortcuts and config options, type `help keymap`"
|
||||
msgstr ""
|
||||
|
||||
msgid "Imports an Evernote notebook file (.enex file)."
|
||||
msgid "Imports data into Joplin."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Source format: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Do not ask for confirmation."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "File \"%s\" will be imported into existing notebook \"%s\". Continue?"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"New notebook \"%s\" will be created and file \"%s\" will be imported into "
|
||||
"it. Continue?"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Found: %d."
|
||||
msgstr ""
|
||||
@@ -345,7 +332,9 @@ msgstr ""
|
||||
msgid "Deletes the notebook without asking for confirmation."
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete notebook? All notes within this notebook will also be deleted."
|
||||
msgid ""
|
||||
"Delete notebook? All notes and sub-notebooks within this notebook will also "
|
||||
"be deleted."
|
||||
msgstr ""
|
||||
|
||||
msgid "Deletes the notes matching <note-pattern>."
|
||||
@@ -381,6 +370,24 @@ msgstr ""
|
||||
msgid "Sync to provided target (defaults to sync.target config value)"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Authentication was not completed (did not receive an authentication token)."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"To allow Joplin to synchronise with Dropbox, please follow the steps below:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Step 1: Open this URL in your browser to authorise the application:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Step 2: Enter the code provided by Dropbox:"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Not authentified with %s. Please provide any missing credentials."
|
||||
msgstr ""
|
||||
|
||||
msgid "Synchronisation is already in progress."
|
||||
msgstr ""
|
||||
|
||||
@@ -391,10 +398,6 @@ msgid ""
|
||||
"operation."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Authentication was not completed (did not receive an authentication token)."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Synchronisation target: %s (%s)"
|
||||
msgstr ""
|
||||
@@ -458,6 +461,9 @@ msgstr ""
|
||||
msgid "Possible keys/values:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Type `joplin help` for usage information."
|
||||
msgstr ""
|
||||
|
||||
msgid "Fatal error:"
|
||||
msgstr ""
|
||||
|
||||
@@ -488,6 +494,24 @@ msgid ""
|
||||
"For example, to create a notebook press `mb`; to create a note press `mn`."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"One or more items are currently encrypted and you may need to supply a "
|
||||
"master password. To do so please type `e2ee decrypt`. If you have already "
|
||||
"supplied the password, the encrypted items are being decrypted in the "
|
||||
"background and will be available soon."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
msgid "PDF File"
|
||||
msgstr ""
|
||||
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
@@ -500,10 +524,17 @@ msgstr ""
|
||||
msgid "New notebook"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import Evernote notes"
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
msgid "Evernote Export Files"
|
||||
msgid "Export"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Hide %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Quit"
|
||||
@@ -521,16 +552,40 @@ msgstr ""
|
||||
msgid "Paste"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bold"
|
||||
msgstr ""
|
||||
|
||||
msgid "Italic"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit in external editor"
|
||||
msgstr ""
|
||||
|
||||
msgid "Search in all the notes"
|
||||
msgstr ""
|
||||
|
||||
msgid "View"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle editor layout"
|
||||
msgstr ""
|
||||
|
||||
msgid "Tools"
|
||||
msgstr ""
|
||||
|
||||
msgid "Synchronisation status"
|
||||
msgstr ""
|
||||
|
||||
msgid "Options"
|
||||
msgid "Web clipper options"
|
||||
msgstr ""
|
||||
|
||||
msgid "Encryption options"
|
||||
msgstr ""
|
||||
|
||||
msgid "General Options"
|
||||
msgstr ""
|
||||
|
||||
msgid "Help"
|
||||
@@ -539,6 +594,12 @@ msgstr ""
|
||||
msgid "Website and documentation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Make a donation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Check for updates..."
|
||||
msgstr ""
|
||||
|
||||
msgid "About Joplin"
|
||||
msgstr ""
|
||||
|
||||
@@ -546,12 +607,77 @@ msgstr ""
|
||||
msgid "%s %s (%s, %s)"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Open %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Exit"
|
||||
msgstr ""
|
||||
|
||||
msgid "OK"
|
||||
msgstr ""
|
||||
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr ""
|
||||
|
||||
msgid "An update is available, do you want to download it now?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
|
||||
msgid "No"
|
||||
msgstr ""
|
||||
|
||||
msgid "The web clipper service is enabled and set to auto-start."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Status: Started on port %d"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Status: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disable Web Clipper Service"
|
||||
msgstr ""
|
||||
|
||||
msgid "The web clipper service is not enabled."
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable Web Clipper Service"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Joplin Web Clipper allows saving web pages and screenshots from your browser "
|
||||
"to Joplin."
|
||||
msgstr ""
|
||||
|
||||
msgid "In order to use the web clipper, you need to do the following:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Step 1: Enable the clipper service"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"This service allows the browser extension to communicate with Joplin. When "
|
||||
"enabling it your firewall may ask you to give permission to Joplin to listen "
|
||||
"to a particular port."
|
||||
msgstr ""
|
||||
|
||||
msgid "Step 2: Install the extension"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download and install the relevant extension for your browser:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr ""
|
||||
@@ -559,6 +685,9 @@ msgstr ""
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
|
||||
msgid "Submit"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Disabling encryption means *all* your notes and attachments are going to be "
|
||||
"re-synchronised and sent unencrypted to the sync target. Do you wish to "
|
||||
@@ -608,18 +737,26 @@ msgid ""
|
||||
"how the notes or notebooks were originally encrypted."
|
||||
msgstr ""
|
||||
|
||||
msgid "Missing Master Keys"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"The master keys with these IDs are used to encrypt some of your items, "
|
||||
"however the application does not currently have access to them. It is likely "
|
||||
"they will eventually be downloaded via synchronisation."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"For more information about End-To-End Encryption (E2EE) and advices on how "
|
||||
"to enable it please check the documentation:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
msgid "Encryption is:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
|
||||
msgid "Back"
|
||||
msgstr ""
|
||||
|
||||
@@ -631,15 +768,9 @@ msgstr ""
|
||||
msgid "Please create a notebook first."
|
||||
msgstr ""
|
||||
|
||||
msgid "Note title:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Please create a notebook first"
|
||||
msgstr ""
|
||||
|
||||
msgid "To-do title:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Notebook title:"
|
||||
msgstr ""
|
||||
|
||||
@@ -652,12 +783,18 @@ msgstr ""
|
||||
msgid "Rename notebook:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Rename tag:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Set alarm:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Layout"
|
||||
msgstr ""
|
||||
|
||||
msgid "Search..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Some items cannot be synchronised."
|
||||
msgstr ""
|
||||
|
||||
@@ -676,6 +813,9 @@ msgstr ""
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr ""
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
@@ -689,16 +829,91 @@ msgid ""
|
||||
"There is currently no notebook. Create one by clicking on \"New notebook\"."
|
||||
msgstr ""
|
||||
|
||||
msgid "Open..."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "This file could not be opened: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Save as..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Copy path to clipboard"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Unsupported link or message: %s"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"This note has no content. Click on \"%s\" to toggle the editor and edit the "
|
||||
"note."
|
||||
msgstr ""
|
||||
|
||||
msgid "strong text"
|
||||
msgstr ""
|
||||
|
||||
msgid "emphasized text"
|
||||
msgstr ""
|
||||
|
||||
msgid "List item"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Hyperlink"
|
||||
msgstr ""
|
||||
|
||||
msgid "Attach file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Tags"
|
||||
msgstr ""
|
||||
|
||||
msgid "Set alarm"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "In: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Hyperlink"
|
||||
msgstr ""
|
||||
|
||||
msgid "Code"
|
||||
msgstr ""
|
||||
|
||||
msgid "Numbered List"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bulleted List"
|
||||
msgstr ""
|
||||
|
||||
msgid "Checkbox"
|
||||
msgstr ""
|
||||
|
||||
msgid "Heading"
|
||||
msgstr ""
|
||||
|
||||
msgid "Horizontal Rule"
|
||||
msgstr ""
|
||||
|
||||
msgid "Click to stop external editing"
|
||||
msgstr ""
|
||||
|
||||
msgid "Watching..."
|
||||
msgstr ""
|
||||
|
||||
msgid "to-do"
|
||||
msgstr ""
|
||||
|
||||
msgid "note"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Creating new %s..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Refresh"
|
||||
msgstr ""
|
||||
|
||||
@@ -708,7 +923,10 @@ msgstr ""
|
||||
msgid "OneDrive Login"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import"
|
||||
msgid "Dropbox Login"
|
||||
msgstr ""
|
||||
|
||||
msgid "Options"
|
||||
msgstr ""
|
||||
|
||||
msgid "Synchronisation Status"
|
||||
@@ -717,6 +935,9 @@ msgstr ""
|
||||
msgid "Encryption Options"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clipper Options"
|
||||
msgstr ""
|
||||
|
||||
msgid "Remove this tag from all the notes?"
|
||||
msgstr ""
|
||||
|
||||
@@ -732,12 +953,6 @@ msgstr ""
|
||||
msgid "Notebooks"
|
||||
msgstr ""
|
||||
|
||||
msgid "Tags"
|
||||
msgstr ""
|
||||
|
||||
msgid "Searches"
|
||||
msgstr ""
|
||||
|
||||
msgid "Please select where the sync status should be exported to"
|
||||
msgstr ""
|
||||
|
||||
@@ -749,15 +964,24 @@ msgstr ""
|
||||
msgid "Unknown flag: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Dropbox"
|
||||
msgstr ""
|
||||
|
||||
msgid "File system"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nextcloud"
|
||||
msgstr ""
|
||||
|
||||
msgid "OneDrive"
|
||||
msgstr ""
|
||||
|
||||
msgid "OneDrive Dev (For testing only)"
|
||||
msgstr ""
|
||||
|
||||
msgid "WebDAV"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Unknown log level: %s"
|
||||
msgstr ""
|
||||
@@ -809,7 +1033,11 @@ msgid "Deleted remote items: %d."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "State: \"%s\"."
|
||||
msgid "Fetched items: %d/%d."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "State: %s."
|
||||
msgstr ""
|
||||
|
||||
msgid "Cancelling..."
|
||||
@@ -819,13 +1047,32 @@ msgstr ""
|
||||
msgid "Completed: %s"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Last error: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Idle"
|
||||
msgstr ""
|
||||
|
||||
msgid "In progress"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Synchronisation is already in progress. State: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Encrypted"
|
||||
msgstr ""
|
||||
|
||||
msgid "Encrypted items cannot be modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "Conflicts"
|
||||
msgstr ""
|
||||
|
||||
msgid "Cannot move notebook to this location"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "A notebook with this title already exists: \"%s\""
|
||||
msgstr ""
|
||||
@@ -834,6 +1081,15 @@ msgstr ""
|
||||
msgid "Notebooks cannot be named \"%s\", which is a reserved title."
|
||||
msgstr ""
|
||||
|
||||
msgid "title"
|
||||
msgstr ""
|
||||
|
||||
msgid "updated date"
|
||||
msgstr ""
|
||||
|
||||
msgid "created date"
|
||||
msgstr ""
|
||||
|
||||
msgid "Untitled"
|
||||
msgstr ""
|
||||
|
||||
@@ -874,12 +1130,53 @@ msgstr ""
|
||||
msgid "Dark"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show uncompleted todos on top of the lists"
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show completed to-dos"
|
||||
msgstr ""
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr ""
|
||||
|
||||
msgid "Reverse sort order"
|
||||
msgstr ""
|
||||
|
||||
msgid "Save geo-location with notes"
|
||||
msgstr ""
|
||||
|
||||
msgid "When creating a new to-do:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Focus title"
|
||||
msgstr ""
|
||||
|
||||
msgid "Focus body"
|
||||
msgstr ""
|
||||
|
||||
msgid "When creating a new note:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show tray icon"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note: Does not work in all desktop environments."
|
||||
msgstr ""
|
||||
|
||||
msgid "Global zoom percentage"
|
||||
msgstr ""
|
||||
|
||||
msgid "Editor font family"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"This must be *monospace* font or it will not work properly. If the font is "
|
||||
"incorrect or empty, it will default to a generic monospace font."
|
||||
msgstr ""
|
||||
|
||||
msgid "Automatically update the application"
|
||||
msgstr ""
|
||||
|
||||
msgid "Synchronisation interval"
|
||||
msgstr ""
|
||||
|
||||
@@ -895,9 +1192,6 @@ msgstr ""
|
||||
msgid "%d hours"
|
||||
msgstr ""
|
||||
|
||||
msgid "Automatically update the application"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show advanced options"
|
||||
msgstr ""
|
||||
|
||||
@@ -905,8 +1199,8 @@ msgid "Synchronisation target"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"The target to synchonise to. If synchronising with the file system, set "
|
||||
"`sync.2.path` to specify the target directory."
|
||||
"The target to synchonise to. Each sync target may have additional parameters "
|
||||
"which are named as `sync.NUM.NAME` (all documented below)."
|
||||
msgstr ""
|
||||
|
||||
msgid "Directory to synchronise with (absolute path)"
|
||||
@@ -917,15 +1211,86 @@ msgid ""
|
||||
"See `sync.target`."
|
||||
msgstr ""
|
||||
|
||||
msgid "Nextcloud WebDAV URL"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nextcloud username"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nextcloud password"
|
||||
msgstr ""
|
||||
|
||||
msgid "WebDAV URL"
|
||||
msgstr ""
|
||||
|
||||
msgid "WebDAV username"
|
||||
msgstr ""
|
||||
|
||||
msgid "WebDAV password"
|
||||
msgstr ""
|
||||
|
||||
msgid "Custom TLS certificates"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Comma-separated list of paths to directories to load the certificates from, "
|
||||
"or path to individual cert files. For example: /my/cert_dir, /other/custom."
|
||||
"pem"
|
||||
msgstr ""
|
||||
|
||||
msgid "Ignore TLS certificate errors"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr ""
|
||||
|
||||
msgid "Joplin Export File"
|
||||
msgstr ""
|
||||
|
||||
msgid "Markdown"
|
||||
msgstr ""
|
||||
|
||||
msgid "Joplin Export Directory"
|
||||
msgstr ""
|
||||
|
||||
msgid "Evernote Export File"
|
||||
msgstr ""
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Cannot load \"%s\" module for format \"%s\""
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Please specify import format for %s"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"This item is currently encrypted: %s \"%s\". Please wait for all items to be "
|
||||
"decrypted and try again."
|
||||
msgstr ""
|
||||
|
||||
msgid "There is no data to export."
|
||||
msgstr ""
|
||||
|
||||
msgid "Please specify the notebook where the notes should be imported to."
|
||||
msgstr ""
|
||||
|
||||
msgid "Items that cannot be synchronised"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "\"%s\": \"%s\""
|
||||
msgid "%s (%s): %s"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"These items will remain on the device but will not be uploaded to the sync "
|
||||
"target. In order to find these items, either search for the title or the ID "
|
||||
"(which is displayed in brackets above)."
|
||||
msgstr ""
|
||||
|
||||
msgid "Sync status (synced items / total items)"
|
||||
@@ -973,6 +1338,9 @@ msgstr ""
|
||||
msgid "Export Debug Report"
|
||||
msgstr ""
|
||||
|
||||
msgid "Encryption Config"
|
||||
msgstr ""
|
||||
|
||||
msgid "Configuration"
|
||||
msgstr ""
|
||||
|
||||
@@ -983,6 +1351,12 @@ msgstr ""
|
||||
msgid "Move %d notes to notebook \"%s\"?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Press to set the decryption password."
|
||||
msgstr ""
|
||||
|
||||
msgid "Save alarm"
|
||||
msgstr ""
|
||||
|
||||
msgid "Select date"
|
||||
msgstr ""
|
||||
|
||||
@@ -992,6 +1366,55 @@ msgstr ""
|
||||
msgid "Cancel synchronisation"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Decrypting items: %d/%d"
|
||||
msgstr ""
|
||||
|
||||
msgid "New tags:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Type new tags or select from list"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"To work correctly, the app needs the following permissions. Please enable "
|
||||
"them in your phone settings, in Apps > Joplin > Permissions"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"- Storage: to allow attaching files to notes and to enable filesystem "
|
||||
"synchronisation."
|
||||
msgstr ""
|
||||
|
||||
msgid "- Camera: to allow taking a picture and attaching it to a note."
|
||||
msgstr ""
|
||||
|
||||
msgid "- Location: to allow attaching geo-location information to a note."
|
||||
msgstr ""
|
||||
|
||||
msgid "Joplin website"
|
||||
msgstr ""
|
||||
|
||||
msgid "Login with Dropbox"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Master Key %s"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Created: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Password:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Password cannot be empty"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "The notebook could not be saved: %s"
|
||||
msgstr ""
|
||||
@@ -999,6 +1422,12 @@ msgstr ""
|
||||
msgid "Edit notebook"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show all"
|
||||
msgstr ""
|
||||
|
||||
msgid "Errors only"
|
||||
msgstr ""
|
||||
|
||||
msgid "This note has been modified:"
|
||||
msgstr ""
|
||||
|
||||
@@ -1008,6 +1437,14 @@ msgstr ""
|
||||
msgid "Discard changes"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "No item with ID %s"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "The Joplin mobile app does not currently support this type of link: %s"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Unsupported image type: %s"
|
||||
msgstr ""
|
||||
@@ -1018,6 +1455,9 @@ msgstr ""
|
||||
msgid "Attach any file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Share"
|
||||
msgstr ""
|
||||
|
||||
msgid "Convert to note"
|
||||
msgstr ""
|
||||
|
||||
@@ -1039,6 +1479,9 @@ msgstr ""
|
||||
msgid "Login with OneDrive"
|
||||
msgstr ""
|
||||
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Click on the (+) button to create a new note or notebook. Click on the side "
|
||||
"menu to access your existing notebooks."
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1711
CliClient/locales/eu.po
Normal file
1711
CliClient/locales/eu.po
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1611
CliClient/locales/gl_ES.po
Normal file
1611
CliClient/locales/gl_ES.po
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -15,63 +15,12 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
msgid "Give focus to next pane"
|
||||
msgstr ""
|
||||
|
||||
msgid "Give focus to previous pane"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enter command line mode"
|
||||
msgstr ""
|
||||
|
||||
msgid "Exit command line mode"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit the selected note"
|
||||
msgstr ""
|
||||
|
||||
msgid "Cancel the current command."
|
||||
msgstr ""
|
||||
|
||||
msgid "Exit the application."
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete the currently selected note or notebook."
|
||||
msgstr ""
|
||||
|
||||
msgid "To delete a tag, untag the associated notes."
|
||||
msgstr ""
|
||||
|
||||
msgid "Please select the note or notebook to be deleted first."
|
||||
msgstr ""
|
||||
|
||||
msgid "Set a to-do as completed / not completed"
|
||||
msgstr ""
|
||||
|
||||
msgid "[t]oggle [c]onsole between maximized/minimized/hidden/visible."
|
||||
msgstr ""
|
||||
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
|
||||
msgid "[t]oggle note [m]etadata."
|
||||
msgstr ""
|
||||
|
||||
msgid "[M]ake a new [n]ote"
|
||||
msgstr ""
|
||||
|
||||
msgid "[M]ake a new [t]odo"
|
||||
msgstr ""
|
||||
|
||||
msgid "[M]ake a new note[b]ook"
|
||||
msgstr ""
|
||||
|
||||
msgid "Copy ([Y]ank) the [n]ote to a notebook."
|
||||
msgstr ""
|
||||
|
||||
msgid "Move the note to a notebook."
|
||||
msgstr ""
|
||||
|
||||
msgid "Press Ctrl+D or type \"exit\" to exit the application"
|
||||
msgstr ""
|
||||
|
||||
@@ -108,6 +57,9 @@ msgstr ""
|
||||
msgid "The command \"%s\" is only available in GUI mode"
|
||||
msgstr ""
|
||||
|
||||
msgid "Cannot change encrypted item"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Missing required argument: %s"
|
||||
msgstr ""
|
||||
@@ -165,6 +117,35 @@ msgstr ""
|
||||
msgid "Note is not a to-do: \"%s\""
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Manages E2EE configuration. Commands are `enable`, `disable`, `decrypt`, "
|
||||
"`status` and `target-status`."
|
||||
msgstr ""
|
||||
|
||||
msgid "Enter master password:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Operation cancelled"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Starting decryption... Please wait as it may take several minutes depending "
|
||||
"on how much there is to decrypt."
|
||||
msgstr ""
|
||||
|
||||
msgid "Completed decryption."
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Encryption is: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit note."
|
||||
msgstr ""
|
||||
|
||||
@@ -182,6 +163,10 @@ msgstr ""
|
||||
msgid "Starting to edit note. Close the editor to get back to the prompt."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Error opening note in editor: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note has been saved."
|
||||
msgstr ""
|
||||
|
||||
@@ -189,10 +174,14 @@ msgid "Exits the application."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Exports Joplin data to the given directory. By default, it will export the "
|
||||
"Exports Joplin data to the given path. By default, it will export the "
|
||||
"complete database including notebooks, notes, tags and resources."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Destination format: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Exports only the given note."
|
||||
msgstr ""
|
||||
|
||||
@@ -205,6 +194,10 @@ msgstr ""
|
||||
msgid "Displays usage information."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "For information on how to customise the shortcuts please visit %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Shortcuts are not available in CLI mode."
|
||||
msgstr ""
|
||||
|
||||
@@ -217,7 +210,7 @@ msgid "The possible commands are:"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"In any command, a note or notebook can be refered to by title or ID, or "
|
||||
"In any command, a note or notebook can be referred to by title or ID, or "
|
||||
"using the shortcuts `$n` or `$b` for, respectively, the currently selected "
|
||||
"note or notebook. `$c` can be used to refer to the currently selected item."
|
||||
msgstr ""
|
||||
@@ -230,7 +223,7 @@ msgid ""
|
||||
"(including this console)."
|
||||
msgstr ""
|
||||
|
||||
msgid "To maximise/minimise the console, press \"TC\"."
|
||||
msgid "To maximise/minimise the console, press \"tc\"."
|
||||
msgstr ""
|
||||
|
||||
msgid "To enter command line mode, press \":\""
|
||||
@@ -240,25 +233,19 @@ msgid "To exit command line mode, press ESCAPE"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"For the complete list of available keyboard shortcuts, type `help shortcuts`"
|
||||
"For the list of keyboard shortcuts and config options, type `help keymap`"
|
||||
msgstr ""
|
||||
|
||||
msgid "Imports an Evernote notebook file (.enex file)."
|
||||
msgid "Imports data into Joplin."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Source format: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Do not ask for confirmation."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "File \"%s\" will be imported into existing notebook \"%s\". Continue?"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"New notebook \"%s\" will be created and file \"%s\" will be imported into "
|
||||
"it. Continue?"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Found: %d."
|
||||
msgstr ""
|
||||
@@ -345,7 +332,9 @@ msgstr ""
|
||||
msgid "Deletes the notebook without asking for confirmation."
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete notebook? All notes within this notebook will also be deleted."
|
||||
msgid ""
|
||||
"Delete notebook? All notes and sub-notebooks within this notebook will also "
|
||||
"be deleted."
|
||||
msgstr ""
|
||||
|
||||
msgid "Deletes the notes matching <note-pattern>."
|
||||
@@ -381,6 +370,24 @@ msgstr ""
|
||||
msgid "Sync to provided target (defaults to sync.target config value)"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Authentication was not completed (did not receive an authentication token)."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"To allow Joplin to synchronise with Dropbox, please follow the steps below:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Step 1: Open this URL in your browser to authorise the application:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Step 2: Enter the code provided by Dropbox:"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Not authentified with %s. Please provide any missing credentials."
|
||||
msgstr ""
|
||||
|
||||
msgid "Synchronisation is already in progress."
|
||||
msgstr ""
|
||||
|
||||
@@ -391,10 +398,6 @@ msgid ""
|
||||
"operation."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Authentication was not completed (did not receive an authentication token)."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Synchronisation target: %s (%s)"
|
||||
msgstr ""
|
||||
@@ -458,6 +461,9 @@ msgstr ""
|
||||
msgid "Possible keys/values:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Type `joplin help` for usage information."
|
||||
msgstr ""
|
||||
|
||||
msgid "Fatal error:"
|
||||
msgstr ""
|
||||
|
||||
@@ -488,6 +494,24 @@ msgid ""
|
||||
"For example, to create a notebook press `mb`; to create a note press `mn`."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"One or more items are currently encrypted and you may need to supply a "
|
||||
"master password. To do so please type `e2ee decrypt`. If you have already "
|
||||
"supplied the password, the encrypted items are being decrypted in the "
|
||||
"background and will be available soon."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
msgid "PDF File"
|
||||
msgstr ""
|
||||
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
@@ -500,10 +524,17 @@ msgstr ""
|
||||
msgid "New notebook"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import Evernote notes"
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
msgid "Evernote Export Files"
|
||||
msgid "Export"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Hide %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Quit"
|
||||
@@ -521,16 +552,40 @@ msgstr ""
|
||||
msgid "Paste"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bold"
|
||||
msgstr ""
|
||||
|
||||
msgid "Italic"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit in external editor"
|
||||
msgstr ""
|
||||
|
||||
msgid "Search in all the notes"
|
||||
msgstr ""
|
||||
|
||||
msgid "View"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle editor layout"
|
||||
msgstr ""
|
||||
|
||||
msgid "Tools"
|
||||
msgstr ""
|
||||
|
||||
msgid "Synchronisation status"
|
||||
msgstr ""
|
||||
|
||||
msgid "Options"
|
||||
msgid "Web clipper options"
|
||||
msgstr ""
|
||||
|
||||
msgid "Encryption options"
|
||||
msgstr ""
|
||||
|
||||
msgid "General Options"
|
||||
msgstr ""
|
||||
|
||||
msgid "Help"
|
||||
@@ -539,6 +594,12 @@ msgstr ""
|
||||
msgid "Website and documentation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Make a donation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Check for updates..."
|
||||
msgstr ""
|
||||
|
||||
msgid "About Joplin"
|
||||
msgstr ""
|
||||
|
||||
@@ -546,12 +607,77 @@ msgstr ""
|
||||
msgid "%s %s (%s, %s)"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Open %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Exit"
|
||||
msgstr ""
|
||||
|
||||
msgid "OK"
|
||||
msgstr ""
|
||||
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr ""
|
||||
|
||||
msgid "An update is available, do you want to download it now?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
|
||||
msgid "No"
|
||||
msgstr ""
|
||||
|
||||
msgid "The web clipper service is enabled and set to auto-start."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Status: Started on port %d"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Status: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disable Web Clipper Service"
|
||||
msgstr ""
|
||||
|
||||
msgid "The web clipper service is not enabled."
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable Web Clipper Service"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Joplin Web Clipper allows saving web pages and screenshots from your browser "
|
||||
"to Joplin."
|
||||
msgstr ""
|
||||
|
||||
msgid "In order to use the web clipper, you need to do the following:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Step 1: Enable the clipper service"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"This service allows the browser extension to communicate with Joplin. When "
|
||||
"enabling it your firewall may ask you to give permission to Joplin to listen "
|
||||
"to a particular port."
|
||||
msgstr ""
|
||||
|
||||
msgid "Step 2: Install the extension"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download and install the relevant extension for your browser:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr ""
|
||||
@@ -559,6 +685,9 @@ msgstr ""
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
|
||||
msgid "Submit"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Disabling encryption means *all* your notes and attachments are going to be "
|
||||
"re-synchronised and sent unencrypted to the sync target. Do you wish to "
|
||||
@@ -608,18 +737,26 @@ msgid ""
|
||||
"how the notes or notebooks were originally encrypted."
|
||||
msgstr ""
|
||||
|
||||
msgid "Missing Master Keys"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"The master keys with these IDs are used to encrypt some of your items, "
|
||||
"however the application does not currently have access to them. It is likely "
|
||||
"they will eventually be downloaded via synchronisation."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"For more information about End-To-End Encryption (E2EE) and advices on how "
|
||||
"to enable it please check the documentation:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
msgid "Encryption is:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
|
||||
msgid "Back"
|
||||
msgstr ""
|
||||
|
||||
@@ -631,15 +768,9 @@ msgstr ""
|
||||
msgid "Please create a notebook first."
|
||||
msgstr ""
|
||||
|
||||
msgid "Note title:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Please create a notebook first"
|
||||
msgstr ""
|
||||
|
||||
msgid "To-do title:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Notebook title:"
|
||||
msgstr ""
|
||||
|
||||
@@ -652,12 +783,18 @@ msgstr ""
|
||||
msgid "Rename notebook:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Rename tag:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Set alarm:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Layout"
|
||||
msgstr ""
|
||||
|
||||
msgid "Search..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Some items cannot be synchronised."
|
||||
msgstr ""
|
||||
|
||||
@@ -676,6 +813,9 @@ msgstr ""
|
||||
msgid "Switch between note and to-do type"
|
||||
msgstr ""
|
||||
|
||||
msgid "Copy Markdown link"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
@@ -689,16 +829,91 @@ msgid ""
|
||||
"There is currently no notebook. Create one by clicking on \"New notebook\"."
|
||||
msgstr ""
|
||||
|
||||
msgid "Open..."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "This file could not be opened: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Save as..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Copy path to clipboard"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Unsupported link or message: %s"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"This note has no content. Click on \"%s\" to toggle the editor and edit the "
|
||||
"note."
|
||||
msgstr ""
|
||||
|
||||
msgid "strong text"
|
||||
msgstr ""
|
||||
|
||||
msgid "emphasized text"
|
||||
msgstr ""
|
||||
|
||||
msgid "List item"
|
||||
msgstr ""
|
||||
|
||||
msgid "Insert Hyperlink"
|
||||
msgstr ""
|
||||
|
||||
msgid "Attach file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Tags"
|
||||
msgstr ""
|
||||
|
||||
msgid "Set alarm"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "In: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Hyperlink"
|
||||
msgstr ""
|
||||
|
||||
msgid "Code"
|
||||
msgstr ""
|
||||
|
||||
msgid "Numbered List"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bulleted List"
|
||||
msgstr ""
|
||||
|
||||
msgid "Checkbox"
|
||||
msgstr ""
|
||||
|
||||
msgid "Heading"
|
||||
msgstr ""
|
||||
|
||||
msgid "Horizontal Rule"
|
||||
msgstr ""
|
||||
|
||||
msgid "Click to stop external editing"
|
||||
msgstr ""
|
||||
|
||||
msgid "Watching..."
|
||||
msgstr ""
|
||||
|
||||
msgid "to-do"
|
||||
msgstr ""
|
||||
|
||||
msgid "note"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Creating new %s..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Refresh"
|
||||
msgstr ""
|
||||
|
||||
@@ -708,7 +923,10 @@ msgstr ""
|
||||
msgid "OneDrive Login"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import"
|
||||
msgid "Dropbox Login"
|
||||
msgstr ""
|
||||
|
||||
msgid "Options"
|
||||
msgstr ""
|
||||
|
||||
msgid "Synchronisation Status"
|
||||
@@ -717,6 +935,9 @@ msgstr ""
|
||||
msgid "Encryption Options"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clipper Options"
|
||||
msgstr ""
|
||||
|
||||
msgid "Remove this tag from all the notes?"
|
||||
msgstr ""
|
||||
|
||||
@@ -732,12 +953,6 @@ msgstr ""
|
||||
msgid "Notebooks"
|
||||
msgstr ""
|
||||
|
||||
msgid "Tags"
|
||||
msgstr ""
|
||||
|
||||
msgid "Searches"
|
||||
msgstr ""
|
||||
|
||||
msgid "Please select where the sync status should be exported to"
|
||||
msgstr ""
|
||||
|
||||
@@ -749,15 +964,24 @@ msgstr ""
|
||||
msgid "Unknown flag: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Dropbox"
|
||||
msgstr ""
|
||||
|
||||
msgid "File system"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nextcloud"
|
||||
msgstr ""
|
||||
|
||||
msgid "OneDrive"
|
||||
msgstr ""
|
||||
|
||||
msgid "OneDrive Dev (For testing only)"
|
||||
msgstr ""
|
||||
|
||||
msgid "WebDAV"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Unknown log level: %s"
|
||||
msgstr ""
|
||||
@@ -809,7 +1033,11 @@ msgid "Deleted remote items: %d."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "State: \"%s\"."
|
||||
msgid "Fetched items: %d/%d."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "State: %s."
|
||||
msgstr ""
|
||||
|
||||
msgid "Cancelling..."
|
||||
@@ -819,13 +1047,32 @@ msgstr ""
|
||||
msgid "Completed: %s"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Last error: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Idle"
|
||||
msgstr ""
|
||||
|
||||
msgid "In progress"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Synchronisation is already in progress. State: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Encrypted"
|
||||
msgstr ""
|
||||
|
||||
msgid "Encrypted items cannot be modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "Conflicts"
|
||||
msgstr ""
|
||||
|
||||
msgid "Cannot move notebook to this location"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "A notebook with this title already exists: \"%s\""
|
||||
msgstr ""
|
||||
@@ -834,6 +1081,15 @@ msgstr ""
|
||||
msgid "Notebooks cannot be named \"%s\", which is a reserved title."
|
||||
msgstr ""
|
||||
|
||||
msgid "title"
|
||||
msgstr ""
|
||||
|
||||
msgid "updated date"
|
||||
msgstr ""
|
||||
|
||||
msgid "created date"
|
||||
msgstr ""
|
||||
|
||||
msgid "Untitled"
|
||||
msgstr ""
|
||||
|
||||
@@ -874,12 +1130,53 @@ msgstr ""
|
||||
msgid "Dark"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show uncompleted todos on top of the lists"
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show completed to-dos"
|
||||
msgstr ""
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr ""
|
||||
|
||||
msgid "Reverse sort order"
|
||||
msgstr ""
|
||||
|
||||
msgid "Save geo-location with notes"
|
||||
msgstr ""
|
||||
|
||||
msgid "When creating a new to-do:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Focus title"
|
||||
msgstr ""
|
||||
|
||||
msgid "Focus body"
|
||||
msgstr ""
|
||||
|
||||
msgid "When creating a new note:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show tray icon"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note: Does not work in all desktop environments."
|
||||
msgstr ""
|
||||
|
||||
msgid "Global zoom percentage"
|
||||
msgstr ""
|
||||
|
||||
msgid "Editor font family"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"This must be *monospace* font or it will not work properly. If the font is "
|
||||
"incorrect or empty, it will default to a generic monospace font."
|
||||
msgstr ""
|
||||
|
||||
msgid "Automatically update the application"
|
||||
msgstr ""
|
||||
|
||||
msgid "Synchronisation interval"
|
||||
msgstr ""
|
||||
|
||||
@@ -895,9 +1192,6 @@ msgstr ""
|
||||
msgid "%d hours"
|
||||
msgstr ""
|
||||
|
||||
msgid "Automatically update the application"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show advanced options"
|
||||
msgstr ""
|
||||
|
||||
@@ -905,8 +1199,8 @@ msgid "Synchronisation target"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"The target to synchonise to. If synchronising with the file system, set "
|
||||
"`sync.2.path` to specify the target directory."
|
||||
"The target to synchonise to. Each sync target may have additional parameters "
|
||||
"which are named as `sync.NUM.NAME` (all documented below)."
|
||||
msgstr ""
|
||||
|
||||
msgid "Directory to synchronise with (absolute path)"
|
||||
@@ -917,15 +1211,86 @@ msgid ""
|
||||
"See `sync.target`."
|
||||
msgstr ""
|
||||
|
||||
msgid "Nextcloud WebDAV URL"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nextcloud username"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nextcloud password"
|
||||
msgstr ""
|
||||
|
||||
msgid "WebDAV URL"
|
||||
msgstr ""
|
||||
|
||||
msgid "WebDAV username"
|
||||
msgstr ""
|
||||
|
||||
msgid "WebDAV password"
|
||||
msgstr ""
|
||||
|
||||
msgid "Custom TLS certificates"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Comma-separated list of paths to directories to load the certificates from, "
|
||||
"or path to individual cert files. For example: /my/cert_dir, /other/custom."
|
||||
"pem"
|
||||
msgstr ""
|
||||
|
||||
msgid "Ignore TLS certificate errors"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr ""
|
||||
|
||||
msgid "Joplin Export File"
|
||||
msgstr ""
|
||||
|
||||
msgid "Markdown"
|
||||
msgstr ""
|
||||
|
||||
msgid "Joplin Export Directory"
|
||||
msgstr ""
|
||||
|
||||
msgid "Evernote Export File"
|
||||
msgstr ""
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Cannot load \"%s\" module for format \"%s\""
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Please specify import format for %s"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"This item is currently encrypted: %s \"%s\". Please wait for all items to be "
|
||||
"decrypted and try again."
|
||||
msgstr ""
|
||||
|
||||
msgid "There is no data to export."
|
||||
msgstr ""
|
||||
|
||||
msgid "Please specify the notebook where the notes should be imported to."
|
||||
msgstr ""
|
||||
|
||||
msgid "Items that cannot be synchronised"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "\"%s\": \"%s\""
|
||||
msgid "%s (%s): %s"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"These items will remain on the device but will not be uploaded to the sync "
|
||||
"target. In order to find these items, either search for the title or the ID "
|
||||
"(which is displayed in brackets above)."
|
||||
msgstr ""
|
||||
|
||||
msgid "Sync status (synced items / total items)"
|
||||
@@ -973,6 +1338,9 @@ msgstr ""
|
||||
msgid "Export Debug Report"
|
||||
msgstr ""
|
||||
|
||||
msgid "Encryption Config"
|
||||
msgstr ""
|
||||
|
||||
msgid "Configuration"
|
||||
msgstr ""
|
||||
|
||||
@@ -983,6 +1351,12 @@ msgstr ""
|
||||
msgid "Move %d notes to notebook \"%s\"?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Press to set the decryption password."
|
||||
msgstr ""
|
||||
|
||||
msgid "Save alarm"
|
||||
msgstr ""
|
||||
|
||||
msgid "Select date"
|
||||
msgstr ""
|
||||
|
||||
@@ -992,6 +1366,55 @@ msgstr ""
|
||||
msgid "Cancel synchronisation"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Decrypting items: %d/%d"
|
||||
msgstr ""
|
||||
|
||||
msgid "New tags:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Type new tags or select from list"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"To work correctly, the app needs the following permissions. Please enable "
|
||||
"them in your phone settings, in Apps > Joplin > Permissions"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"- Storage: to allow attaching files to notes and to enable filesystem "
|
||||
"synchronisation."
|
||||
msgstr ""
|
||||
|
||||
msgid "- Camera: to allow taking a picture and attaching it to a note."
|
||||
msgstr ""
|
||||
|
||||
msgid "- Location: to allow attaching geo-location information to a note."
|
||||
msgstr ""
|
||||
|
||||
msgid "Joplin website"
|
||||
msgstr ""
|
||||
|
||||
msgid "Login with Dropbox"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Master Key %s"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Created: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Password:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Password cannot be empty"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "The notebook could not be saved: %s"
|
||||
msgstr ""
|
||||
@@ -999,6 +1422,12 @@ msgstr ""
|
||||
msgid "Edit notebook"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show all"
|
||||
msgstr ""
|
||||
|
||||
msgid "Errors only"
|
||||
msgstr ""
|
||||
|
||||
msgid "This note has been modified:"
|
||||
msgstr ""
|
||||
|
||||
@@ -1008,6 +1437,14 @@ msgstr ""
|
||||
msgid "Discard changes"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "No item with ID %s"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "The Joplin mobile app does not currently support this type of link: %s"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Unsupported image type: %s"
|
||||
msgstr ""
|
||||
@@ -1018,6 +1455,9 @@ msgstr ""
|
||||
msgid "Attach any file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Share"
|
||||
msgstr ""
|
||||
|
||||
msgid "Convert to note"
|
||||
msgstr ""
|
||||
|
||||
@@ -1039,6 +1479,9 @@ msgstr ""
|
||||
msgid "Login with OneDrive"
|
||||
msgstr ""
|
||||
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Click on the (+) button to create a new note or notebook. Click on the side "
|
||||
"menu to access your existing notebooks."
|
||||
|
1724
CliClient/locales/nl_BE.po
Normal file
1724
CliClient/locales/nl_BE.po
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1628
CliClient/locales/sl_SI.po
Normal file
1628
CliClient/locales/sl_SI.po
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1515
CliClient/locales/zh_TW.po
Normal file
1515
CliClient/locales/zh_TW.po
Normal file
File diff suppressed because it is too large
Load Diff
1336
CliClient/package-lock.json
generated
1336
CliClient/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -19,7 +19,7 @@
|
||||
],
|
||||
"owner": "Laurent Cozic"
|
||||
},
|
||||
"version": "0.10.85",
|
||||
"version": "1.0.108",
|
||||
"bin": {
|
||||
"joplin": "./main.js"
|
||||
},
|
||||
@@ -28,10 +28,18 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"app-module-path": "^2.2.0",
|
||||
"async-mutex": "^0.1.3",
|
||||
"base-64": "^0.1.0",
|
||||
"compare-version": "^0.1.2",
|
||||
"es6-promise-pool": "^2.5.0",
|
||||
"follow-redirects": "^1.2.4",
|
||||
"form-data": "^2.1.4",
|
||||
"fs-extra": "^5.0.0",
|
||||
"html-entities": "^1.2.1",
|
||||
"html-minifier": "^3.5.15",
|
||||
"image-type": "^3.0.0",
|
||||
"joplin-turndown": "^4.0.3",
|
||||
"joplin-turndown-plugin-gfm": "^1.0.2",
|
||||
"jssha": "^2.3.0",
|
||||
"levenshtein": "^1.0.5",
|
||||
"lodash": "^4.17.4",
|
||||
@@ -41,10 +49,10 @@
|
||||
"node-emoji": "^1.8.1",
|
||||
"node-fetch": "^1.7.1",
|
||||
"node-persist": "^2.1.0",
|
||||
"os-tmpdir": "^1.0.2",
|
||||
"promise": "^7.1.1",
|
||||
"proper-lockfile": "^2.0.1",
|
||||
"query-string": "4.3.4",
|
||||
"read-chunk": "^2.1.0",
|
||||
"redux": "^3.7.2",
|
||||
"sax": "^1.2.2",
|
||||
"server-destroy": "^1.0.1",
|
||||
@@ -54,10 +62,14 @@
|
||||
"string-padding": "^1.0.2",
|
||||
"string-to-stream": "^1.1.0",
|
||||
"strip-ansi": "^4.0.0",
|
||||
"tar": "^4.4.0",
|
||||
"tcp-port-used": "^0.1.2",
|
||||
"tkwidgets": "^0.5.20",
|
||||
"tkwidgets": "^0.5.26",
|
||||
"url-parse": "^1.2.0",
|
||||
"uuid": "^3.0.1",
|
||||
"valid-url": "^1.0.9",
|
||||
"word-wrap": "^1.2.3",
|
||||
"xml2js": "^0.4.19",
|
||||
"yargs-parser": "^7.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@@ -9,4 +9,10 @@ bash $SCRIPT_DIR/build.sh
|
||||
cp "$SCRIPT_DIR/package.json" build/
|
||||
cp "$SCRIPT_DIR/../README.md" build/
|
||||
cd "$SCRIPT_DIR/build"
|
||||
npm publish
|
||||
npm publish
|
||||
|
||||
NEW_VERSION=$(cat package.json | jq -r .version)
|
||||
git add -A
|
||||
git commit -m "CLI v$NEW_VERSION"
|
||||
git tag "cli-v$NEW_VERSION"
|
||||
git push && git push --tags
|
@@ -1,4 +1,5 @@
|
||||
#!/bin/bash
|
||||
START_DIR="$(pwd)"
|
||||
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
BUILD_DIR="$ROOT_DIR/tests-build"
|
||||
TEST_FILE="$1"
|
||||
@@ -8,10 +9,27 @@ rsync -a "$ROOT_DIR/../ReactNativeClient/lib/" "$BUILD_DIR/lib/"
|
||||
rsync -a "$ROOT_DIR/build/locales/" "$BUILD_DIR/locales/"
|
||||
mkdir -p "$BUILD_DIR/data"
|
||||
|
||||
if [[ $TEST_FILE == "" ]]; then
|
||||
(cd "$ROOT_DIR" && npm test tests-build/synchronizer.js)
|
||||
(cd "$ROOT_DIR" && npm test tests-build/encryption.js)
|
||||
(cd "$ROOT_DIR" && npm test tests-build/ArrayUtils.js)
|
||||
else
|
||||
if [[ $TEST_FILE != "" ]]; then
|
||||
(cd "$ROOT_DIR" && npm test tests-build/$TEST_FILE.js)
|
||||
fi
|
||||
exit
|
||||
fi
|
||||
|
||||
function finish {
|
||||
cd "$START_DIR"
|
||||
}
|
||||
|
||||
trap finish EXIT
|
||||
|
||||
cd "$ROOT_DIR"
|
||||
npm test tests-build/ArrayUtils.js
|
||||
npm test tests-build/encryption.js
|
||||
npm test tests-build/EnexToMd.js
|
||||
npm test tests-build/HtmlToMd.js
|
||||
npm test tests-build/markdownUtils.js
|
||||
npm test tests-build/models_Folder.js
|
||||
npm test tests-build/models_Note.js
|
||||
npm test tests-build/models_Setting.js
|
||||
npm test tests-build/services_InteropService.js
|
||||
npm test tests-build/services_ResourceService.js
|
||||
npm test tests-build/synchronizer.js
|
||||
npm test tests-build/urlUtils.js
|
@@ -8,7 +8,7 @@ process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
describe('Encryption', function() {
|
||||
describe('ArrayUtils', function() {
|
||||
|
||||
beforeEach(async (done) => {
|
||||
done();
|
||||
@@ -29,4 +29,28 @@ describe('Encryption', function() {
|
||||
done();
|
||||
});
|
||||
|
||||
it('should find items using binary search', async (done) => {
|
||||
let items = ['aaa', 'ccc', 'bbb'];
|
||||
expect(ArrayUtils.binarySearch(items, 'bbb')).toBe(-1); // Array not sorted!
|
||||
items.sort();
|
||||
expect(ArrayUtils.binarySearch(items, 'bbb')).toBe(1);
|
||||
expect(ArrayUtils.binarySearch(items, 'ccc')).toBe(2);
|
||||
expect(ArrayUtils.binarySearch(items, 'oops')).toBe(-1);
|
||||
expect(ArrayUtils.binarySearch(items, 'aaa')).toBe(0);
|
||||
|
||||
items = [];
|
||||
expect(ArrayUtils.binarySearch(items, 'aaa')).toBe(-1);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it('should compare arrays', async (done) => {
|
||||
expect(ArrayUtils.contentEquals([], [])).toBe(true);
|
||||
expect(ArrayUtils.contentEquals(['a'], ['a'])).toBe(true);
|
||||
expect(ArrayUtils.contentEquals(['b', 'a'], ['a', 'b'])).toBe(true);
|
||||
expect(ArrayUtils.contentEquals(['b'], ['a', 'b'])).toBe(false);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
62
CliClient/tests/EnexToMd.js
Normal file
62
CliClient/tests/EnexToMd.js
Normal file
@@ -0,0 +1,62 @@
|
||||
require('app-module-path').addPath(__dirname);
|
||||
|
||||
const { time } = require('lib/time-utils.js');
|
||||
const { filename } = require('lib/path-utils.js');
|
||||
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const { enexXmlToMd } = require('lib/import-enex-md-gen.js');
|
||||
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 60 * 60 * 1000; // Can run for a while since everything is in the same test unit
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
describe('EnexToMd', function() {
|
||||
|
||||
beforeEach(async (done) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
await switchClient(1);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should convert from Enex to Markdown', asyncTest(async () => {
|
||||
const basePath = __dirname + '/enex_to_md';
|
||||
const files = await shim.fsDriver().readDirStats(basePath);
|
||||
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const htmlFilename = files[i].path;
|
||||
if (htmlFilename.indexOf('.html') < 0) continue;
|
||||
|
||||
const htmlPath = basePath + '/' + htmlFilename;
|
||||
const mdPath = basePath + '/' + filename(htmlFilename) + '.md';
|
||||
|
||||
// if (htmlFilename !== 'text2.html') continue;
|
||||
|
||||
const html = await shim.fsDriver().readFile(htmlPath);
|
||||
const expectedMd = await shim.fsDriver().readFile(mdPath);
|
||||
|
||||
const actualMd = await enexXmlToMd('<div>' + html + '</div>', []);
|
||||
|
||||
if (actualMd !== expectedMd) {
|
||||
console.info('');
|
||||
console.info('Error converting file: ' + htmlFilename);
|
||||
console.info('--------------------------------- Got:');
|
||||
console.info(actualMd.split('\n'));
|
||||
console.info('--------------------------------- Expected:');
|
||||
console.info(expectedMd.split('\n'));
|
||||
console.info('--------------------------------------------');
|
||||
console.info('');
|
||||
|
||||
expect(false).toBe(true);
|
||||
// return;
|
||||
} else {
|
||||
expect(true).toBe(true)
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
});
|
66
CliClient/tests/HtmlToMd.js
Normal file
66
CliClient/tests/HtmlToMd.js
Normal file
@@ -0,0 +1,66 @@
|
||||
require('app-module-path').addPath(__dirname);
|
||||
|
||||
const { time } = require('lib/time-utils.js');
|
||||
const { filename } = require('lib/path-utils.js');
|
||||
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const HtmlToMd = require('lib/HtmlToMd');
|
||||
const { enexXmlToMd } = require('lib/import-enex-md-gen.js');
|
||||
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 60 * 60 * 1000; // Can run for a while since everything is in the same test unit
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
describe('HtmlToMd', function() {
|
||||
|
||||
beforeEach(async (done) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
await switchClient(1);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should convert from Html to Markdown', asyncTest(async () => {
|
||||
const basePath = __dirname + '/html_to_md';
|
||||
const files = await shim.fsDriver().readDirStats(basePath);
|
||||
const htmlToMd = new HtmlToMd();
|
||||
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const htmlFilename = files[i].path;
|
||||
if (htmlFilename.indexOf('.html') < 0) continue;
|
||||
|
||||
const htmlPath = basePath + '/' + htmlFilename;
|
||||
const mdPath = basePath + '/' + filename(htmlFilename) + '.md';
|
||||
|
||||
// if (htmlFilename !== 'code_1.html') continue;
|
||||
|
||||
const html = await shim.fsDriver().readFile(htmlPath);
|
||||
const expectedMd = await shim.fsDriver().readFile(mdPath);
|
||||
|
||||
const actualMd = await htmlToMd.parse('<div>' + html + '</div>', []);
|
||||
|
||||
if (actualMd !== expectedMd) {
|
||||
console.info('');
|
||||
console.info('Error converting file: ' + htmlFilename);
|
||||
console.info('--------------------------------- Got:');
|
||||
console.info(actualMd);
|
||||
console.info('--------------------------------- Raw:');
|
||||
console.info(actualMd.split('\n'));
|
||||
console.info('--------------------------------- Expected:');
|
||||
console.info(expectedMd.split('\n'));
|
||||
console.info('--------------------------------------------');
|
||||
console.info('');
|
||||
|
||||
expect(false).toBe(true);
|
||||
// return;
|
||||
} else {
|
||||
expect(true).toBe(true)
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
});
|
16
CliClient/tests/enex_to_md/code1.html
Normal file
16
CliClient/tests/enex_to_md/code1.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<div>
|
||||
<p>For example, consider a web page like this:</p>
|
||||
|
||||
<pre class="brush: html line-numbers language-html"><code class=" language-html"><span class="token doctype"><!DOCTYPE html></span>
|
||||
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>html</span><span class="token punctuation">></span></span>
|
||||
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>head</span><span class="token punctuation">></span></span>
|
||||
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">http-equiv</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>content-type<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>text/html; charset<span class="token punctuation">=</span>utf-8<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
|
||||
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>head</span><span class="token punctuation">></span></span>
|
||||
|
||||
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>body</span><span class="token punctuation">></span></span>
|
||||
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>page-scripts/page-script.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script language-javascript"></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span>
|
||||
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span>
|
||||
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>html</span><span class="token punctuation">></span></span><span class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
|
||||
|
||||
<p>The script "page-script.js" does this:</p>
|
||||
</div>
|
14
CliClient/tests/enex_to_md/code1.md
Normal file
14
CliClient/tests/enex_to_md/code1.md
Normal file
@@ -0,0 +1,14 @@
|
||||
For example, consider a web page like this:
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script src="page-scripts/page-script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
The script "page-script.js" does this:
|
7
CliClient/tests/enex_to_md/code2.html
Normal file
7
CliClient/tests/enex_to_md/code2.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<p>Subshell:</p>
|
||||
<pre><code>(
|
||||
set -e
|
||||
false
|
||||
echo Unreachable
|
||||
) && echo Great success
|
||||
</code></pre>
|
7
CliClient/tests/enex_to_md/code2.md
Normal file
7
CliClient/tests/enex_to_md/code2.md
Normal file
@@ -0,0 +1,7 @@
|
||||
Subshell:
|
||||
|
||||
(
|
||||
set -e
|
||||
false
|
||||
echo Unreachable
|
||||
) && echo Great success
|
9
CliClient/tests/enex_to_md/heading.html
Normal file
9
CliClient/tests/enex_to_md/heading.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<div>
|
||||
<div class="note">
|
||||
<p>Values added to the global scope of a content script with</p>
|
||||
</div>
|
||||
|
||||
<h2 id="Loading_content_scripts">Loading content scripts</h2>
|
||||
|
||||
<p>You can load a content script into a web page in one of three ways:</p>
|
||||
</div>
|
5
CliClient/tests/enex_to_md/heading.md
Normal file
5
CliClient/tests/enex_to_md/heading.md
Normal file
@@ -0,0 +1,5 @@
|
||||
Values added to the global scope of a content script with
|
||||
|
||||
## Loading content scripts
|
||||
|
||||
You can load a content script into a web page in one of three ways:
|
3
CliClient/tests/enex_to_md/inlineCode.html
Normal file
3
CliClient/tests/enex_to_md/inlineCode.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<div>
|
||||
<p>Similarly, I need another regex to match double newlines (<code>\n\n</code>) that are not part of a longer run of newline characters like <code>\n\n\n</code> or <code>\n\n\n\n\n\n</code> etc.</p>
|
||||
</div>
|
1
CliClient/tests/enex_to_md/inlineCode.md
Normal file
1
CliClient/tests/enex_to_md/inlineCode.md
Normal file
@@ -0,0 +1 @@
|
||||
Similarly, I need another regex to match double newlines (`\n\n`) that are not part of a longer run of newline characters like `\n\n\n` or `\n\n\n\n\n\n` etc.
|
3
CliClient/tests/enex_to_md/inlineCodeWithLink.html
Normal file
3
CliClient/tests/enex_to_md/inlineCodeWithLink.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<div>
|
||||
<p>the <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onConnect">runtime.onConnect</a></code> listener gets passed its own <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/Port">runtime.Port</a></code> object.</p>
|
||||
</div>
|
1
CliClient/tests/enex_to_md/inlineCodeWithLink.md
Normal file
1
CliClient/tests/enex_to_md/inlineCodeWithLink.md
Normal file
@@ -0,0 +1 @@
|
||||
the `[runtime.onConnect](/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onConnect)` listener gets passed its own `[runtime.Port](/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/Port)` object.
|
4
CliClient/tests/enex_to_md/link1.html
Normal file
4
CliClient/tests/enex_to_md/link1.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<a href="https://arstechnica.com/civis/ucp.php?mode=login&return_to=%2Ftech-policy%2F2018%2F05%2Fjails-are-replacing-in-person-visits-with-video-calling-services-theyre-awful%2F" class="dropdown-toggle">
|
||||
Sign in
|
||||
<span class="icon dropdown-indicator icon-drop-indicator"></span>
|
||||
</a>
|
1
CliClient/tests/enex_to_md/link1.md
Normal file
1
CliClient/tests/enex_to_md/link1.md
Normal file
@@ -0,0 +1 @@
|
||||
[Sign in](https://arstechnica.com/civis/ucp.php?mode=login&return_to=%2Ftech-policy%2F2018%2F05%2Fjails-are-replacing-in-person-visits-with-video-calling-services-theyre-awful%2F)
|
17
CliClient/tests/enex_to_md/list.html
Normal file
17
CliClient/tests/enex_to_md/list.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<div>
|
||||
<p>Liste de courses</p>
|
||||
|
||||
<div>
|
||||
<div><en-todo checked="true"/>Pizzas</div>
|
||||
<div><en-todo checked="true"/>Pain</div>
|
||||
<div><en-todo checked="true"/>Jambon</div>
|
||||
</div>
|
||||
|
||||
<div><br/></div>
|
||||
|
||||
<div>
|
||||
<div><en-todo checked="true"/>On its own</div>
|
||||
</div>
|
||||
|
||||
<p>End</p>
|
||||
</div>
|
9
CliClient/tests/enex_to_md/list.md
Normal file
9
CliClient/tests/enex_to_md/list.md
Normal file
@@ -0,0 +1,9 @@
|
||||
Liste de courses
|
||||
|
||||
- [X] Pizzas
|
||||
- [X] Pain
|
||||
- [X] Jambon
|
||||
|
||||
- [X] On its own
|
||||
|
||||
End
|
1
CliClient/tests/enex_to_md/list2.html
Normal file
1
CliClient/tests/enex_to_md/list2.html
Normal file
@@ -0,0 +1 @@
|
||||
<ul class="find-me-on"><li><a href="https://github.com/zetter">Github</a></li><li><a href="https://twitter.com/czetter">Twitter</a></li><li><a href="http://lanyrd.com/profile/czetter/">Lanyrd</a></li></ul>
|
3
CliClient/tests/enex_to_md/list2.md
Normal file
3
CliClient/tests/enex_to_md/list2.md
Normal file
@@ -0,0 +1,3 @@
|
||||
- [Github](https://github.com/zetter)
|
||||
- [Twitter](https://twitter.com/czetter)
|
||||
- [Lanyrd](http://lanyrd.com/profile/czetter/)
|
1
CliClient/tests/enex_to_md/list3.html
Normal file
1
CliClient/tests/enex_to_md/list3.html
Normal file
@@ -0,0 +1 @@
|
||||
<ul class="find-me-on"><li>Github</li><li>Twitter</li></ul>
|
2
CliClient/tests/enex_to_md/list3.md
Normal file
2
CliClient/tests/enex_to_md/list3.md
Normal file
@@ -0,0 +1,2 @@
|
||||
- Github
|
||||
- Twitter
|
11
CliClient/tests/enex_to_md/paragraph.html
Normal file
11
CliClient/tests/enex_to_md/paragraph.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<div>
|
||||
<p>Short paragraphs are merged together:</p>
|
||||
<p>Something something</p>
|
||||
<p>Blablbla blabla lbla</p>
|
||||
<p>Last line</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p>Longer ones are separated by new lines. In 1894 Joplin arrived in Sedalia, Missouri. At first, Joplin stayed with the family of Arthur Marshall, at the time a 13-year-old boy but later one of Joplin's students and a rag-time composer in his own right.[26] There is no record of Joplin having a permanent residence in the town until 1904, as Joplin was making a living as a touring musician.</p>
|
||||
<p>There is little precise evidence known about Joplin's activities at this time, although he performed as a solo musician at dances and at the major black clubs in Sedalia, the Black 400 club and the Maple Leaf Club. He performed in the Queen City Cornet Band, and his own six-piece dance orchestra.</p>
|
||||
</div>
|
8
CliClient/tests/enex_to_md/paragraph.md
Normal file
8
CliClient/tests/enex_to_md/paragraph.md
Normal file
@@ -0,0 +1,8 @@
|
||||
Short paragraphs are merged together:
|
||||
Something something
|
||||
Blablbla blabla lbla
|
||||
Last line
|
||||
|
||||
Longer ones are separated by new lines. In 1894 Joplin arrived in Sedalia, Missouri. At first, Joplin stayed with the family of Arthur Marshall, at the time a 13-year-old boy but later one of Joplin's students and a rag-time composer in his own right.[26] There is no record of Joplin having a permanent residence in the town until 1904, as Joplin was making a living as a touring musician.
|
||||
|
||||
There is little precise evidence known about Joplin's activities at this time, although he performed as a solo musician at dances and at the major black clubs in Sedalia, the Black 400 club and the Maple Leaf Club. He performed in the Queen City Cornet Band, and his own six-piece dance orchestra.
|
12
CliClient/tests/enex_to_md/table1.html
Normal file
12
CliClient/tests/enex_to_md/table1.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div>$ sudo ethtool --set-priv-flags p2p1 mlx4_rss_xor_hash_function on</div>
|
||||
<div># Three empty lines follow</div>
|
||||
<div><br/></div>
|
||||
<div><br/></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Some text
|
5
CliClient/tests/enex_to_md/table1.md
Normal file
5
CliClient/tests/enex_to_md/table1.md
Normal file
@@ -0,0 +1,5 @@
|
||||
| |
|
||||
| --- |
|
||||
| $ sudo ethtool --set-priv-flags p2p1 mlx4_rss_xor_hash_function on<br># Three empty lines follow |
|
||||
|
||||
Some text
|
3
CliClient/tests/enex_to_md/tableWithNewLines.html
Normal file
3
CliClient/tests/enex_to_md/tableWithNewLines.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<div>
|
||||
<table style="-evernote-table:true;border-collapse:collapse;width:100%;table-layout:fixed;margin-left:0px;"><tr><td style="border-style:solid;border-width:1px;border-color:rgb(211,211,211);padding:10px;margin:0px;width:50%;"><div>line 1</div><div>line 2</div></td><td style="border-style:solid;border-width:1px;border-color:rgb(211,211,211);padding:10px;margin:0px;width:50%;"><div><br/></div></td></tr><tr><td style="border-style:solid;border-width:1px;border-color:rgb(211,211,211);padding:10px;margin:0px;width:50%;"><div>aaaaaa</div></td><td style="border-style:solid;border-width:1px;border-color:rgb(211,211,211);padding:10px;margin:0px;width:50%;"><div>line 3</div><div>line 4</div></td></tr></table>
|
||||
</div>
|
4
CliClient/tests/enex_to_md/tableWithNewLines.md
Normal file
4
CliClient/tests/enex_to_md/tableWithNewLines.md
Normal file
@@ -0,0 +1,4 @@
|
||||
| | |
|
||||
| --- | --- |
|
||||
| line 1<br>line 2 | |
|
||||
| aaaaaa | line 3<br>line 4 |
|
1
CliClient/tests/html_to_md/anchor_with_inner_tags.html
Normal file
1
CliClient/tests/html_to_md/anchor_with_inner_tags.html
Normal file
@@ -0,0 +1 @@
|
||||
<a href="https://joplin.cozic.net"><h1 id="joplin"><img class="title-icon" src="https://joplin.cozic.net/images/Icon512.png">oplin</h1></a>
|
1
CliClient/tests/html_to_md/anchor_with_inner_tags.md
Normal file
1
CliClient/tests/html_to_md/anchor_with_inner_tags.md
Normal file
@@ -0,0 +1 @@
|
||||
[# oplin](https://joplin.cozic.net)
|
1
CliClient/tests/html_to_md/anchor_with_js.html
Normal file
1
CliClient/tests/html_to_md/anchor_with_js.html
Normal file
@@ -0,0 +1 @@
|
||||
<a href="javascript:alert('js')">Some text</a>
|
1
CliClient/tests/html_to_md/anchor_with_js.md
Normal file
1
CliClient/tests/html_to_md/anchor_with_js.md
Normal file
@@ -0,0 +1 @@
|
||||
[Some text]()
|
1
CliClient/tests/html_to_md/anchor_with_newlines.html
Normal file
1
CliClient/tests/html_to_md/anchor_with_newlines.html
Normal file
@@ -0,0 +1 @@
|
||||
<a href="http://example.com"><p>That</p><p>Shouldn't be allowed</p></a>
|
1
CliClient/tests/html_to_md/anchor_with_newlines.md
Normal file
1
CliClient/tests/html_to_md/anchor_with_newlines.md
Normal file
@@ -0,0 +1 @@
|
||||
[That<br>Shouldn't be allowed](http://example.com)
|
8
CliClient/tests/html_to_md/code_1.html
Normal file
8
CliClient/tests/html_to_md/code_1.html
Normal file
@@ -0,0 +1,8 @@
|
||||
<div>
|
||||
<table><tbody><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> ma_fonction<span style="color: black;">(</span><span style="color: black;">)</span>:
|
||||
<span style="color: #483d8b;">"""
|
||||
C'est une super fonction
|
||||
"""</span>
|
||||
<span style="color: #ff7700;font-weight:bold;">pass</span></pre></td></tr></tbody></table>
|
||||
|
||||
</div>
|
5
CliClient/tests/html_to_md/code_1.md
Normal file
5
CliClient/tests/html_to_md/code_1.md
Normal file
@@ -0,0 +1,5 @@
|
||||
def ma_fonction():
|
||||
"""
|
||||
C'est une super fonction
|
||||
"""
|
||||
pass
|
13
CliClient/tests/html_to_md/list_with_many_items.html
Normal file
13
CliClient/tests/html_to_md/list_with_many_items.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!-- Make sure in particular that indentation is correct after the 9th item -->
|
||||
<ol>
|
||||
<li><p>One</p><p>Two</p></li>
|
||||
<li><p>One</p><p>Two</p></li>
|
||||
<li><p>One</p><p>Two</p></li>
|
||||
<li><p>One</p><p>Two</p></li>
|
||||
<li><p>One</p><p>Two</p></li>
|
||||
<li><p>One</p><p>Two</p></li>
|
||||
<li><p>One</p><p>Two</p></li>
|
||||
<li><p>One</p><p>Two</p></li>
|
||||
<li><p>One</p><p>Two</p></li>
|
||||
<li><p>One</p><p>Two</p></li>
|
||||
</ol>
|
39
CliClient/tests/html_to_md/list_with_many_items.md
Normal file
39
CliClient/tests/html_to_md/list_with_many_items.md
Normal file
@@ -0,0 +1,39 @@
|
||||
1. One
|
||||
|
||||
Two
|
||||
|
||||
2. One
|
||||
|
||||
Two
|
||||
|
||||
3. One
|
||||
|
||||
Two
|
||||
|
||||
4. One
|
||||
|
||||
Two
|
||||
|
||||
5. One
|
||||
|
||||
Two
|
||||
|
||||
6. One
|
||||
|
||||
Two
|
||||
|
||||
7. One
|
||||
|
||||
Two
|
||||
|
||||
8. One
|
||||
|
||||
Two
|
||||
|
||||
9. One
|
||||
|
||||
Two
|
||||
|
||||
10. One
|
||||
|
||||
Two
|
1
CliClient/tests/html_to_md/skip_script.html
Normal file
1
CliClient/tests/html_to_md/skip_script.html
Normal file
@@ -0,0 +1 @@
|
||||
<script id="appnexus-adload" data-reactid="7">window.apntag=window.apntag||{};window.apntag.anq=window.apntag.anq||[];</script>
|
0
CliClient/tests/html_to_md/skip_script.md
Normal file
0
CliClient/tests/html_to_md/skip_script.md
Normal file
6
CliClient/tests/html_to_md/skip_style.html
Normal file
6
CliClient/tests/html_to_md/skip_style.html
Normal file
File diff suppressed because one or more lines are too long
0
CliClient/tests/html_to_md/skip_style.md
Normal file
0
CliClient/tests/html_to_md/skip_style.md
Normal file
4
CliClient/tests/html_to_md/table_no_header.html
Normal file
4
CliClient/tests/html_to_md/table_no_header.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<table>
|
||||
<tr><td>No</td><td>header</td></tr>
|
||||
<tr><td>And no</td><td>suprises</td></tr>
|
||||
</table>
|
4
CliClient/tests/html_to_md/table_no_header.md
Normal file
4
CliClient/tests/html_to_md/table_no_header.md
Normal file
@@ -0,0 +1,4 @@
|
||||
| | |
|
||||
| --- | --- |
|
||||
| No | header |
|
||||
| And no | suprises |
|
15
CliClient/tests/html_to_md/table_with_colspan.html
Normal file
15
CliClient/tests/html_to_md/table_with_colspan.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<table>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
Something that was originally spanning two columns
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
One
|
||||
</td>
|
||||
<td>
|
||||
Two
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
4
CliClient/tests/html_to_md/table_with_colspan.md
Normal file
4
CliClient/tests/html_to_md/table_with_colspan.md
Normal file
@@ -0,0 +1,4 @@
|
||||
| | |
|
||||
| --- | --- |
|
||||
| Something that was originally spanning two columns | |
|
||||
| One | Two |
|
10
CliClient/tests/html_to_md/table_with_empty_cells.html
Normal file
10
CliClient/tests/html_to_md/table_with_empty_cells.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<table>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Previous is empty</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Next is empty</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
4
CliClient/tests/html_to_md/table_with_empty_cells.md
Normal file
4
CliClient/tests/html_to_md/table_with_empty_cells.md
Normal file
@@ -0,0 +1,4 @@
|
||||
| | |
|
||||
| --- | --- |
|
||||
| | Previous is empty |
|
||||
| Next is empty | |
|
13
CliClient/tests/html_to_md/table_with_empty_row.html
Normal file
13
CliClient/tests/html_to_md/table_with_empty_row.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<table>
|
||||
<tr>
|
||||
<td>One</td><td>Two</td>
|
||||
</tr>
|
||||
<tr></tr>
|
||||
<tr>
|
||||
<td>One</td><td>Two</td>
|
||||
</tr>
|
||||
<tr></tr>
|
||||
<tr>
|
||||
<td>One</td><td>Two</td>
|
||||
</tr>
|
||||
</table>
|
5
CliClient/tests/html_to_md/table_with_empty_row.md
Normal file
5
CliClient/tests/html_to_md/table_with_empty_row.md
Normal file
@@ -0,0 +1,5 @@
|
||||
| | |
|
||||
| --- | --- |
|
||||
| One | Two |
|
||||
| One | Two |
|
||||
| One | Two |
|
6
CliClient/tests/html_to_md/table_with_newlines.html
Normal file
6
CliClient/tests/html_to_md/table_with_newlines.html
Normal file
@@ -0,0 +1,6 @@
|
||||
<table>
|
||||
<tr>
|
||||
<td><p>Some paragraph</p><p>inside a table cell</p></td>
|
||||
<td>Second column</td>
|
||||
</tr>
|
||||
</table>
|
3
CliClient/tests/html_to_md/table_with_newlines.md
Normal file
3
CliClient/tests/html_to_md/table_with_newlines.md
Normal file
@@ -0,0 +1,3 @@
|
||||
| | |
|
||||
| --- | --- |
|
||||
| Some paragraph<br><br>inside a table cell | Second column |
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user