Compare commits
990 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6e43d3de7 | ||
|
|
a7545b017f | ||
|
|
facf1553ec | ||
|
|
7503d70377 | ||
|
|
698c8f6215 | ||
|
|
9bca4848f3 | ||
|
|
c060b2a4e0 | ||
|
|
8a63ebe6cf | ||
|
|
432342415e | ||
|
|
3496a5d658 | ||
|
|
26cb467156 | ||
|
|
a93c575b05 | ||
|
|
4c8a85726d | ||
|
|
b4251b56fe | ||
|
|
fa36d5d296 | ||
|
|
544a080db4 | ||
|
|
53bf6ef4bc | ||
|
|
57db105b7e | ||
|
|
921a8c431c | ||
|
|
abf9278b90 | ||
|
|
8f1f64f6c0 | ||
|
|
ae99ba0fab | ||
|
|
373c5e4c26 | ||
|
|
576b0e02f6 | ||
|
|
667583984f | ||
|
|
57415bea85 | ||
|
|
5f23491189 | ||
|
|
ed4c7d9400 | ||
|
|
997f0f349d | ||
|
|
063acc6bbf | ||
|
|
85d61fddf0 | ||
|
|
d7feec32dd | ||
|
|
7bf100daff | ||
|
|
02957f7757 | ||
|
|
01bc1b0303 | ||
|
|
35e2668f07 | ||
|
|
bbcbc8be50 | ||
|
|
9956367384 | ||
|
|
b3c73247d3 | ||
|
|
185cd1c0a7 | ||
|
|
89e8c3b0ba | ||
|
|
77274e6117 | ||
|
|
4a832942f2 | ||
|
|
eab9607f8a | ||
|
|
e625a415fd | ||
|
|
d2a7ef921b | ||
|
|
5ae8cb77ac | ||
|
|
57142381ca | ||
|
|
c7dd18695d | ||
|
|
8018947353 | ||
|
|
0d915fcc33 | ||
|
|
3fad22c4fe | ||
|
|
1b0a881ad6 | ||
|
|
fd6b0740fd | ||
|
|
2cb2116940 | ||
|
|
458e9ed75b | ||
|
|
7b702734f3 | ||
|
|
55f55afed2 | ||
|
|
97e4eab7bb | ||
|
|
0f35c77074 | ||
|
|
0a43660e55 | ||
|
|
f80297fbcc | ||
|
|
55bab60e89 | ||
|
|
48f0c24886 | ||
|
|
608b1cbe4d | ||
|
|
47e0092378 | ||
|
|
7186c6c3e0 | ||
|
|
de2c1fd3e2 | ||
|
|
c404754e26 | ||
|
|
0d2d1726f8 | ||
|
|
35c5a457b7 | ||
|
|
98a19e56a4 | ||
|
|
fcf53c3923 | ||
|
|
5a2d8e9f07 | ||
|
|
f73c570bd3 | ||
|
|
f87a921ad1 | ||
|
|
261cbe64f2 | ||
|
|
3006478e9c | ||
|
|
cac8f856fa | ||
|
|
a006937e6e | ||
|
|
877386cdd3 | ||
|
|
f7e5fd3aef | ||
|
|
e25c3a4110 | ||
|
|
ad62137a28 | ||
|
|
88550e13dd | ||
|
|
cfbfbf34d7 | ||
|
|
013a3f7e1b | ||
|
|
dd14b3a773 | ||
|
|
4f500f2257 | ||
|
|
29a8107ae0 | ||
|
|
99ca6b6a26 | ||
|
|
29b633d7b4 | ||
|
|
6d505715e0 | ||
|
|
13c4f664c2 | ||
|
|
4e8d8e3d53 | ||
|
|
02f98fb378 | ||
|
|
19f4f7febb | ||
|
|
989a5e02b9 | ||
|
|
f78a64d545 | ||
|
|
50a1bd8082 | ||
|
|
9eb3ff4bb3 | ||
|
|
1588ae4948 | ||
|
|
5579892aa7 | ||
|
|
8d032a2cf2 | ||
|
|
0320d76f05 | ||
|
|
368d742d41 | ||
|
|
4fe725f7b5 | ||
|
|
27842a43d2 | ||
|
|
31b746eb4b | ||
|
|
db1c558a2b | ||
|
|
19589c6468 | ||
|
|
9ab4d9f585 | ||
|
|
256a2b61fb | ||
|
|
7f68a580f0 | ||
|
|
2dfb90d0e5 | ||
|
|
f6b4479200 | ||
|
|
26cdb1d04f | ||
|
|
b5ba2b25cd | ||
|
|
6248aa6a32 | ||
|
|
f402a36042 | ||
|
|
2bc618d66b | ||
|
|
0bf8c520aa | ||
|
|
3fd8833457 | ||
|
|
8193d5044a | ||
|
|
be336f09de | ||
|
|
5203fc3605 | ||
|
|
c60de02e14 | ||
|
|
21e0385a31 | ||
|
|
fddbec2408 | ||
|
|
8e8c4596bf | ||
|
|
96bac91fa1 | ||
|
|
76e37354e1 | ||
|
|
542d74b9cc | ||
|
|
3be12c8988 | ||
|
|
89345c8d60 | ||
|
|
49f1f4e7c7 | ||
|
|
d0ce7db9ee | ||
|
|
53a0291cc2 | ||
|
|
9a3bc839dd | ||
|
|
e519840bd6 | ||
|
|
ed32a3ca33 | ||
|
|
369ac99a16 | ||
|
|
39ac823b05 | ||
|
|
548ae4dba3 | ||
|
|
f69d593649 | ||
|
|
423af5f077 | ||
|
|
76e5e1ad00 | ||
|
|
420caa4d8d | ||
|
|
fdeeb68a6d | ||
|
|
9fe803a0b1 | ||
|
|
dd9ba90a03 | ||
|
|
2bc739316a | ||
|
|
74da8c340d | ||
|
|
766cb4410b | ||
|
|
78fe6d6ea8 | ||
|
|
6b99decb56 | ||
|
|
323745e61f | ||
|
|
22c19670e9 | ||
|
|
a1b7aaddb8 | ||
|
|
cfba9681c4 | ||
|
|
a019b8b5ca | ||
|
|
bd9b267562 | ||
|
|
b0f8f56650 | ||
|
|
a71e813e82 | ||
|
|
75e7665d6e | ||
|
|
12293f5297 | ||
|
|
4899ee0bee | ||
|
|
563c17c84e | ||
|
|
d94eca4ee7 | ||
|
|
f4a01884bd | ||
|
|
105d7f12ac | ||
|
|
30c115a7de | ||
|
|
88a90f22a3 | ||
|
|
c72c712c1b | ||
|
|
7205801e76 | ||
|
|
64f4f54b9d | ||
|
|
0287d88895 | ||
|
|
cdc075b27c | ||
|
|
604d9827c5 | ||
|
|
bdeb6bf188 | ||
|
|
19e122be99 | ||
|
|
f3ddf18a23 | ||
|
|
51f863e1e4 | ||
|
|
0a9381d538 | ||
|
|
a9514b54eb | ||
|
|
d647cb196f | ||
|
|
b69973f614 | ||
|
|
fb9c42f4a1 | ||
|
|
b873e3cdf8 | ||
|
|
e9fc024332 | ||
|
|
d4956fad8c | ||
|
|
9d1dfe742e | ||
|
|
e32c092af8 | ||
|
|
18a2664b54 | ||
|
|
954e46c5ec | ||
|
|
e0f306d3f7 | ||
|
|
09db6618d6 | ||
|
|
c5ea254945 | ||
|
|
1fc1ecbaa6 | ||
|
|
bc4640c3f0 | ||
|
|
1e2eb9b07a | ||
|
|
ece00956d9 | ||
|
|
af5bbd8838 | ||
|
|
3a8f2495ea | ||
|
|
993f5e5097 | ||
|
|
1f99c26e78 | ||
|
|
05ebf3a6b4 | ||
|
|
1be3046d26 | ||
|
|
5b3858ba29 | ||
|
|
a1f388e524 | ||
|
|
cf14ff1540 | ||
|
|
a0ac2bc02a | ||
|
|
ed82c492ab | ||
|
|
fc2d71d120 | ||
|
|
e5a7a0631b | ||
|
|
315cba07f0 | ||
|
|
cd5bd92a41 | ||
|
|
10126ce979 | ||
|
|
f6c4f08254 | ||
|
|
fc4feb2096 | ||
|
|
82b641458f | ||
|
|
2c0fb33548 | ||
|
|
24e665bfd5 | ||
|
|
1404e33386 | ||
|
|
0b1fd61188 | ||
|
|
80b4c67e35 | ||
|
|
1f4aae9249 | ||
|
|
145e8006f0 | ||
|
|
872f562aad | ||
|
|
db70d67180 | ||
|
|
b1fd798a5c | ||
|
|
42907ade21 | ||
|
|
b3bc0b4e5a | ||
|
|
12e24f3ec1 | ||
|
|
fefa8347da | ||
|
|
cd7ca09a3f | ||
|
|
3960b2d6f9 | ||
|
|
264969e80c | ||
|
|
4e2911f648 | ||
|
|
42610b2645 | ||
|
|
7b07a706e1 | ||
|
|
8fef9dc8a8 | ||
|
|
83936bf4c8 | ||
|
|
65f89e283e | ||
|
|
1aa65bd3d1 | ||
|
|
0547ec3c49 | ||
|
|
7e1cbe572d | ||
|
|
7a98f30d05 | ||
|
|
c565bd4400 | ||
|
|
d039c8e62e | ||
|
|
da7f0561cb | ||
|
|
00210b75c7 | ||
|
|
3fe8973ae6 | ||
|
|
87c4b42683 | ||
|
|
0901eaac45 | ||
|
|
c7c81a7243 | ||
|
|
ac019ac196 | ||
|
|
b12c1305ea | ||
|
|
1876c2afae | ||
|
|
4575375ea9 | ||
|
|
aac7836dce | ||
|
|
df5de2d60d | ||
|
|
b026283ef2 | ||
|
|
548e5d108c | ||
|
|
4d31152a02 | ||
|
|
fd08513212 | ||
|
|
3175ac16d1 | ||
|
|
0cb5a6c7ad | ||
|
|
0bb2df135b | ||
|
|
adadf7428c | ||
|
|
146dd3c00b | ||
|
|
78bfa84afd | ||
|
|
07512c7e2c | ||
|
|
9fe96bec40 | ||
|
|
18172aa33a | ||
|
|
9ece6dacbd | ||
|
|
ef07963d79 | ||
|
|
862086eae5 | ||
|
|
277aa0c7e1 | ||
|
|
fc52741435 | ||
|
|
a7cd6bfd2e | ||
|
|
648df7b3d3 | ||
|
|
01f7f1f59c | ||
|
|
ff7f089f69 | ||
|
|
4e06e8c0c0 | ||
|
|
ca5ce905c7 | ||
|
|
0fc29de02c | ||
|
|
8509a16d6e | ||
|
|
0ed021357b | ||
|
|
58ad7a1e8a | ||
|
|
622ee29dd8 | ||
|
|
5cbb4c6223 | ||
|
|
5299859385 | ||
|
|
c57b308909 | ||
|
|
6409274f83 | ||
|
|
bc534c12a5 | ||
|
|
b58fd2022a | ||
|
|
d850d026ed | ||
|
|
83627686d4 | ||
|
|
4e7d01c72c | ||
|
|
0f8ab20db7 | ||
|
|
88cc90786d | ||
|
|
fb66717b43 | ||
|
|
1d60433fcf | ||
|
|
0f3df6e92b | ||
|
|
ca7c63c7d7 | ||
|
|
135f9611df | ||
|
|
cfaaeebd4a | ||
|
|
09a0779180 | ||
|
|
7f7d09bc85 | ||
|
|
0c454a08dc | ||
|
|
d749b63549 | ||
|
|
2053a6950d | ||
|
|
41bd801e0d | ||
|
|
cd0e1a3962 | ||
|
|
7c2f482b3b | ||
|
|
7741d60afd | ||
|
|
8aac0c0327 | ||
|
|
7c26c56210 | ||
|
|
e88a780efe | ||
|
|
363fb5dc02 | ||
|
|
39a187b6da | ||
|
|
b4cc34a522 | ||
|
|
af94ef3d49 | ||
|
|
505855a53c | ||
|
|
87ac245341 | ||
|
|
1670a09d04 | ||
|
|
620b954336 | ||
|
|
cfd51e9b84 | ||
|
|
6c797f8216 | ||
|
|
40e208152a | ||
|
|
cf7bfa62ef | ||
|
|
a1086b9a04 | ||
|
|
9bc4bbd2c8 | ||
|
|
73156012e9 | ||
|
|
91cc3d77d4 | ||
|
|
3fc55a9e9f | ||
|
|
b666aa3f26 | ||
|
|
53e7dbe12f | ||
|
|
9d8ff6856b | ||
|
|
3fb38376b0 | ||
|
|
15c73d9dd3 | ||
|
|
86f71ffb93 | ||
|
|
eb928d3369 | ||
|
|
d7307665b3 | ||
|
|
2836f0ab5a | ||
|
|
91b7f3980c | ||
|
|
5053432c2d | ||
|
|
563c612395 | ||
|
|
95dced6455 | ||
|
|
989f0bbbfb | ||
|
|
e5eec28bfd | ||
|
|
bfc402f307 | ||
|
|
35a998b934 | ||
|
|
cadc8e499d | ||
|
|
7f7ea6da9f | ||
|
|
ab9a22d8e7 | ||
|
|
cd2728105e | ||
|
|
d75e84bdff | ||
|
|
e791fee38b | ||
|
|
ad5f057733 | ||
|
|
6f325b5fdb | ||
|
|
b73aeee18d | ||
|
|
8a54035a9f | ||
|
|
af28e30e4c | ||
|
|
492513306c | ||
|
|
bc554ff4a7 | ||
|
|
b7a0d1ece8 | ||
|
|
ca384218dc | ||
|
|
e9550fd6b2 | ||
|
|
232a305d51 | ||
|
|
a6ab448eeb | ||
|
|
f9aa157c6c | ||
|
|
b7df24acaa | ||
|
|
ad4ca1b2d7 | ||
|
|
c562d197e7 | ||
|
|
83ba1899b7 | ||
|
|
3420adc7c9 | ||
|
|
fd39f28e46 | ||
|
|
710125852a | ||
|
|
e8ec208390 | ||
|
|
4584562607 | ||
|
|
2c1412a088 | ||
|
|
0a65382979 | ||
|
|
4f404f66e5 | ||
|
|
89505ada00 | ||
|
|
374a30ac5a | ||
|
|
cee4ee4128 | ||
|
|
58fc5e2ffa | ||
|
|
951ea43f8b | ||
|
|
ca16ecef24 | ||
|
|
bb025dc2a1 | ||
|
|
d797169bd0 | ||
|
|
891f9e2252 | ||
|
|
4a579c00ce | ||
|
|
9cb4d8e088 | ||
|
|
5d3ee7755a | ||
|
|
c047c46587 | ||
|
|
54f53be5b5 | ||
|
|
8bb9e5b22f | ||
|
|
379791a326 | ||
|
|
38ec68b303 | ||
|
|
a5095b04ad | ||
|
|
a27ddb40be | ||
|
|
bc36be8a5e | ||
|
|
1e35556034 | ||
|
|
882cd41d4b | ||
|
|
724fb4bf8f | ||
|
|
b07437dbfa | ||
|
|
96f05cd518 | ||
|
|
77411e94a4 | ||
|
|
0da9c62ef8 | ||
|
|
52a7885f3c | ||
|
|
f98f089d63 | ||
|
|
6b618f3abe | ||
|
|
0732ffa76e | ||
|
|
b5b4636e56 | ||
|
|
ca12d040e1 | ||
|
|
3388b9fafa | ||
|
|
954b36e14c | ||
|
|
4d43814220 | ||
|
|
f6262c82e1 | ||
|
|
7ead12922f | ||
|
|
33a6a7869c | ||
|
|
bf995f989c | ||
|
|
21de6c6520 | ||
|
|
c14aa6851e | ||
|
|
8260eced2d | ||
|
|
d028465dc5 | ||
|
|
29dab5e47d | ||
|
|
9e655631b4 | ||
|
|
179c7b80bb | ||
|
|
349bf29122 | ||
|
|
295357f12b | ||
|
|
940f8d999e | ||
|
|
5605d53a5f | ||
|
|
116d103119 | ||
|
|
2fd8c643af | ||
|
|
4367ae7934 | ||
|
|
749461334d | ||
|
|
e83a027023 | ||
|
|
1883b477a3 | ||
|
|
37e2cd40da | ||
|
|
81a9329975 | ||
|
|
0eb019fc3c | ||
|
|
4129c75475 | ||
|
|
3d66f03f58 | ||
|
|
7b83104fd6 | ||
|
|
794aede27f | ||
|
|
08eb39b206 | ||
|
|
2566c7f3d7 | ||
|
|
a8522bb3b5 | ||
|
|
92b9142902 | ||
|
|
d07e3e6522 | ||
|
|
29aabdfba8 | ||
|
|
9af1b0cfdc | ||
|
|
6e32c7fe85 | ||
|
|
ddf5915c6a | ||
|
|
cdbf1fa73a | ||
|
|
5d926b022b | ||
|
|
50bcca10e2 | ||
|
|
a5528c06ee | ||
|
|
94526de04b | ||
|
|
1ddf7abe6f | ||
|
|
a742c1b034 | ||
|
|
6e726ac2a6 | ||
|
|
5877b40be5 | ||
|
|
a3c7f5aa46 | ||
|
|
4e28bf03bd | ||
|
|
f92482d89e | ||
|
|
3c54429fe0 | ||
|
|
4c4c22e861 | ||
|
|
00e27d9327 | ||
|
|
f082278041 | ||
|
|
09dde64c57 | ||
|
|
b52a6357f6 | ||
|
|
f14a566d06 | ||
|
|
b352ec6888 | ||
|
|
4ec1bad03d | ||
|
|
f20bbc119d | ||
|
|
8555c3d422 | ||
|
|
71f9d03b19 | ||
|
|
0b31379078 | ||
|
|
29c204b2c2 | ||
|
|
657e881963 | ||
|
|
ef6bdc70a4 | ||
|
|
e4a36115a2 | ||
|
|
325f86832c | ||
|
|
e3dbdd6b09 | ||
|
|
919041e879 | ||
|
|
182231a183 | ||
|
|
46d4ae8fc5 | ||
|
|
73ab1936a3 | ||
|
|
59c72527b5 | ||
|
|
5ea3bcc1dd | ||
|
|
c140052822 | ||
|
|
f7832774d9 | ||
|
|
279d25c03a | ||
|
|
f1984047a8 | ||
|
|
eae7c1bd60 | ||
|
|
d7f592ebda | ||
|
|
1798ce002a | ||
|
|
57a0cca595 | ||
|
|
b26fbd7693 | ||
|
|
43b0e25bdb | ||
|
|
3377af1305 | ||
|
|
c81c1006b7 | ||
|
|
f313857f96 | ||
|
|
d5fbe02149 | ||
|
|
159cee0b39 | ||
|
|
5da4dd6cca | ||
|
|
e9daf05f16 | ||
|
|
a12643194a | ||
|
|
25d8fc08f7 | ||
|
|
a72378dd4d | ||
|
|
9aed70408b | ||
|
|
5ae2c71c3a | ||
|
|
4edce515b8 | ||
|
|
67ff664eb8 | ||
|
|
71c1a4f102 | ||
|
|
ba4ba1b9fc | ||
|
|
59f10f06ca | ||
|
|
f7953cbc37 | ||
|
|
9a74e81754 | ||
|
|
420e4b6766 | ||
|
|
aed48ffc93 | ||
|
|
0cebe69ff8 | ||
|
|
e5990dba81 | ||
|
|
c9b0d01250 | ||
|
|
4918ed3f3c | ||
|
|
b176ce4251 | ||
|
|
518ff5409e | ||
|
|
803bd3c5b2 | ||
|
|
03d4e73304 | ||
|
|
55a820b09f | ||
|
|
f2a65dc360 | ||
|
|
7b4a889ea7 | ||
|
|
f627d251c3 | ||
|
|
d5b7125415 | ||
|
|
67dd3cf0e3 | ||
|
|
b8b62bb5af | ||
|
|
b4a9d1ac18 | ||
|
|
8aae651c2c | ||
|
|
fc9465b324 | ||
|
|
579a50be2c | ||
|
|
9c5b967e4c | ||
|
|
d41deb729b | ||
|
|
a93a89f3f0 | ||
|
|
11d642a25f | ||
|
|
67448498ea | ||
|
|
489b8da713 | ||
|
|
728d4d0fa8 | ||
|
|
e70f4ff3a6 | ||
|
|
04032c0dfe | ||
|
|
ecba6461df | ||
|
|
433ba6c250 | ||
|
|
ff6c55d1d0 | ||
|
|
d9f8facf2e | ||
|
|
6bd3e5cc8f | ||
|
|
936fb5ae45 | ||
|
|
8e661e1260 | ||
|
|
987d9b0502 | ||
|
|
f6a9169446 | ||
|
|
d5c1c43eb1 | ||
|
|
20c74dac60 | ||
|
|
30161275a3 | ||
|
|
7e9479806e | ||
|
|
39b9ea9f1d | ||
|
|
5a9165d7c6 | ||
|
|
4f851156b7 | ||
|
|
b8fa278173 | ||
|
|
2cfb344e13 | ||
|
|
1d2bf92abe | ||
|
|
cefcda9f40 | ||
|
|
a4bc67ff8e | ||
|
|
48b3dea256 | ||
|
|
1f5231d905 | ||
|
|
c526e18992 | ||
|
|
4594765cbd | ||
|
|
e2a787e519 | ||
|
|
45b3e0aa6a | ||
|
|
7bdb2615d4 | ||
|
|
019a502490 | ||
|
|
6793fd5bc7 | ||
|
|
8ac5cf759e | ||
|
|
19880567ba | ||
|
|
5c5a3fefc1 | ||
|
|
90057828a5 | ||
|
|
7cfc3a09a2 | ||
|
|
b8bbee27f8 | ||
|
|
8e5c665e49 | ||
|
|
7b1e6fb953 | ||
|
|
79936e69c5 | ||
|
|
a19cd327f3 | ||
|
|
5c831c156b | ||
|
|
602df08df5 | ||
|
|
3b8d06a9e3 | ||
|
|
5fd43b50e0 | ||
|
|
15d39413f3 | ||
|
|
5e01946981 | ||
|
|
576d11f09a | ||
|
|
a43c296eef | ||
|
|
6015591e34 | ||
|
|
6f5f031b24 | ||
|
|
1499e78795 | ||
|
|
1b45ab7222 | ||
|
|
005b158ad3 | ||
|
|
26d003e840 | ||
|
|
192fb39302 | ||
|
|
1650dfcc29 | ||
|
|
fda83c4c1d | ||
|
|
1a6ebbb8e5 | ||
|
|
ea1f8912b8 | ||
|
|
a5885d2628 | ||
|
|
716d4c6f28 | ||
|
|
b3a36c82bb | ||
|
|
75fff1d52f | ||
|
|
2d88987cb3 | ||
|
|
8bbbdbd359 | ||
|
|
8a2aa44de8 | ||
|
|
3715c555d3 | ||
|
|
5e4de6cc5f | ||
|
|
4cadfc64f6 | ||
|
|
a3f0d47cad | ||
|
|
bc55b5fdda | ||
|
|
43474712eb | ||
|
|
bf48cbb89c | ||
|
|
c50d8e216a | ||
|
|
8c160bcddf | ||
|
|
6fd6aa2733 | ||
|
|
d7431c459d | ||
|
|
464a11cd69 | ||
|
|
154535a7b1 | ||
|
|
f379a759bb | ||
|
|
8cbd7eafb8 | ||
|
|
6fb304d010 | ||
|
|
089b2290bd | ||
|
|
c4e5bfdabb | ||
|
|
9d5cb104c3 | ||
|
|
d577b8b34e | ||
|
|
6219cd1d86 | ||
|
|
dfd1ac7e99 | ||
|
|
e3838b291f | ||
|
|
04a073c7cf | ||
|
|
04d5c60957 | ||
|
|
2be6cad7e1 | ||
|
|
b44e036be3 | ||
|
|
7ac6e9d37b | ||
|
|
6854e96fb8 | ||
|
|
2df3a386ad | ||
|
|
187b47eddd | ||
|
|
763aeb5fae | ||
|
|
3cad43006a | ||
|
|
8e4cdb78a0 | ||
|
|
9d80458250 | ||
|
|
d601c2ae64 | ||
|
|
87cd6dfb54 | ||
|
|
3dea1b3d7c | ||
|
|
f882c166cd | ||
|
|
9be0acd75b | ||
|
|
0901683880 | ||
|
|
216f3045db | ||
|
|
ce544adb62 | ||
|
|
107d299822 | ||
|
|
d577a34135 | ||
|
|
394c3412e5 | ||
|
|
e3aa726f12 | ||
|
|
e46b7aaf35 | ||
|
|
68947de06a | ||
|
|
1739de95a6 | ||
|
|
759f184d36 | ||
|
|
8a8d3437a6 | ||
|
|
87f0d6930e | ||
|
|
e659f11f05 | ||
|
|
b53920ddc5 | ||
|
|
21c2bb281f | ||
|
|
b0232eb917 | ||
|
|
f8c855eab1 | ||
|
|
8a277aebd7 | ||
|
|
d4c25476d2 | ||
|
|
8fa35da2d1 | ||
|
|
dcf5852432 | ||
|
|
e2aa342539 | ||
|
|
e28e5230d7 | ||
|
|
cbe5b15abd | ||
|
|
566546748d | ||
|
|
320f56e473 | ||
|
|
54e7998bf7 | ||
|
|
479dcb18b3 | ||
|
|
1a9329d1df | ||
|
|
7fda51a0c9 | ||
|
|
28368cd6c0 | ||
|
|
5d6b1280a8 | ||
|
|
8fddb4d6bf | ||
|
|
81a9b65559 | ||
|
|
d20533e048 | ||
|
|
6eb32b06af | ||
|
|
9c9970d6fb | ||
|
|
887d634fde | ||
|
|
9c334fb021 | ||
|
|
8c9880145e | ||
|
|
6fa6f3d1dc | ||
|
|
fe0c9fe57a | ||
|
|
3ab820763b | ||
|
|
31a6f6af93 | ||
|
|
32f4245024 | ||
|
|
92a8aba69c | ||
|
|
c2fec0a030 | ||
|
|
e0ef53431a | ||
|
|
093dcba4ba | ||
|
|
1cffb64344 | ||
|
|
caffe7b455 | ||
|
|
2e87db99c2 | ||
|
|
220ef5ae1a | ||
|
|
395f7272c3 | ||
|
|
fd427c3931 | ||
|
|
2ea07688be | ||
|
|
b1f8324c21 | ||
|
|
e920fb16d4 | ||
|
|
802ae3643c | ||
|
|
42cc031200 | ||
|
|
d6cf4648a2 | ||
|
|
d6deb52731 | ||
|
|
a4c8221fc4 | ||
|
|
50b921f318 | ||
|
|
e0526b9584 | ||
|
|
f822f6d931 | ||
|
|
0a25d75682 | ||
|
|
0eea2c672f | ||
|
|
e4e7b8f449 | ||
|
|
54a5c621c4 | ||
|
|
03e1d9a863 | ||
|
|
098fc340ca | ||
|
|
27c8a03c16 | ||
|
|
1ddf829a6d | ||
|
|
6952a8b72a | ||
|
|
2ee720760d | ||
|
|
ccee0eecb5 | ||
|
|
2b7e97a09f | ||
|
|
a2926b8fe9 | ||
|
|
9009317f83 | ||
|
|
67772e7221 | ||
|
|
cc02da47d7 | ||
|
|
af540183a6 | ||
|
|
6581bb4ab4 | ||
|
|
53e5edcb75 | ||
|
|
ae22066bad | ||
|
|
6ee5daf884 | ||
|
|
93edc56f1d | ||
|
|
41970348cd | ||
|
|
815a823104 | ||
|
|
c27f99ab58 | ||
|
|
ed35a878a5 | ||
|
|
bd1ab5e80b | ||
|
|
a1fae66800 | ||
|
|
c4d1761687 | ||
|
|
a647347e10 | ||
|
|
2d42ae9a36 | ||
|
|
8ce900acca | ||
|
|
60ee55b602 | ||
|
|
75cd62b7c2 | ||
|
|
55fe47d4f3 | ||
|
|
440d5072b7 | ||
|
|
80968ee6c4 | ||
|
|
99254c964b | ||
|
|
d2a4cf74e8 | ||
|
|
fd918ef15f | ||
|
|
e16ed5ca1a | ||
|
|
25e5470c5e | ||
|
|
59320e6828 | ||
|
|
f9aacb4c66 | ||
|
|
28faf3888c | ||
|
|
a9e22947ef | ||
|
|
7585fc80b4 | ||
|
|
5139af9f48 | ||
|
|
f2521717ae | ||
|
|
0f935b92cb | ||
|
|
5e3a2b456e | ||
|
|
632f29d1d6 | ||
|
|
7353d69f1a | ||
|
|
0b1cdf6a68 | ||
|
|
e0350b2837 | ||
|
|
1a521505a6 | ||
|
|
12d457e3ee | ||
|
|
d58933ea8d | ||
|
|
5bbfd15f38 | ||
|
|
acf4662d2f | ||
|
|
1d55ee7f93 | ||
|
|
b86afd7fc9 | ||
|
|
a5164dc0b6 | ||
|
|
cc919ea614 | ||
|
|
42d0d49682 | ||
|
|
07e81a117b | ||
|
|
a56bcb09b0 | ||
|
|
28b3272cd0 | ||
|
|
5c7221d0d7 | ||
|
|
0aa79d28f8 | ||
|
|
4b4cdb85ff | ||
|
|
654f7742e4 | ||
|
|
f082bca6c9 | ||
|
|
f7ace9d92a | ||
|
|
9759b44cbb | ||
|
|
5dfe8a83cd | ||
|
|
3c47f21337 | ||
|
|
b75360bdb1 | ||
|
|
32bace863c | ||
|
|
acda1e4dd8 | ||
|
|
a342def43f | ||
|
|
b100435d9c | ||
|
|
b2a29e2b13 | ||
|
|
fc0af56136 | ||
|
|
fd246aac93 | ||
|
|
7d90ecf91f | ||
|
|
d2aa72d873 | ||
|
|
d0b57c0419 | ||
|
|
5bee714437 | ||
|
|
9af537c985 | ||
|
|
30c56a0ec9 | ||
|
|
563a72ad95 | ||
|
|
2d4aff3b08 | ||
|
|
e0783cad60 | ||
|
|
feaad367df | ||
|
|
6b5b58ea94 | ||
|
|
60d1d336d6 | ||
|
|
2b93407e64 | ||
|
|
d5dec31b39 | ||
|
|
2608aa4c97 | ||
|
|
c174ca1c7e | ||
|
|
80c26a9550 | ||
|
|
f4ad6b963f | ||
|
|
b470cdf60c | ||
|
|
585bf4ccb4 | ||
|
|
6b0fedfabf | ||
|
|
9a1510a4f1 | ||
|
|
bcb4594afa | ||
|
|
0ebec74bed | ||
|
|
d10f5734fb | ||
|
|
91171727e4 | ||
|
|
e8a91d2631 | ||
|
|
cd020e536b | ||
|
|
c05605a286 | ||
|
|
63a698b679 | ||
|
|
3d3ef6f37b | ||
|
|
9e839e130e | ||
|
|
3e2ca2fd5f | ||
|
|
ee26262b6e | ||
|
|
4327af5133 | ||
|
|
6cce2ee70a | ||
|
|
70d07433d5 | ||
|
|
8109c63250 | ||
|
|
32ba7361ac | ||
|
|
a9da1b648f | ||
|
|
1fcd64a1ab | ||
|
|
f8362b6bfa | ||
|
|
fb0541fddf | ||
|
|
61b645c51c | ||
|
|
84b5a69074 | ||
|
|
374f445953 | ||
|
|
bf78db9b75 | ||
|
|
e3882b78db | ||
|
|
5389d4fc13 | ||
|
|
01529cc981 | ||
|
|
93fb571725 | ||
|
|
ab4aea315a | ||
|
|
90ca50ae7a | ||
|
|
3cb36d36bf | ||
|
|
8f51f025d0 | ||
|
|
e048fc6653 | ||
|
|
a44fc62fee | ||
|
|
9da29bf99a | ||
|
|
1edb669583 | ||
|
|
8e4e2469b0 | ||
|
|
f91953f67a | ||
|
|
0bb61149e8 | ||
|
|
e5f7d1077d | ||
|
|
7c91a77442 | ||
|
|
fb24398b01 | ||
|
|
43107965a9 | ||
|
|
67b7435624 | ||
|
|
78d3fd3768 | ||
|
|
243e4889b9 | ||
|
|
42564e683b | ||
|
|
96097d1cd3 | ||
|
|
4f35a8d79f | ||
|
|
3b8bed5b0a | ||
|
|
5897f0e3ed | ||
|
|
2aba80d0ca | ||
|
|
af6cd2e38b | ||
|
|
5ab2664c70 | ||
|
|
39c31ef5d9 | ||
|
|
bd1c7a35e2 | ||
|
|
0eed041986 | ||
|
|
1958c34bcb | ||
|
|
f5ceede3cd | ||
|
|
d98473f5e3 | ||
|
|
19d7027361 | ||
|
|
a34c2863bd | ||
|
|
4521dce1a9 | ||
|
|
3564c1a45c | ||
|
|
b6e2d25462 | ||
|
|
256ce50c49 | ||
|
|
fb0ad73035 | ||
|
|
71636c3413 | ||
|
|
5ef28bab9a | ||
|
|
757433629a | ||
|
|
050ae2a512 | ||
|
|
4c81eac8fb | ||
|
|
a4544d7943 | ||
|
|
9d65537317 | ||
|
|
b6a284e2bc | ||
|
|
f4e5690841 | ||
|
|
fa84479254 | ||
|
|
6ef1ca0a0b | ||
|
|
927a1481a9 | ||
|
|
7f9f45c720 | ||
|
|
7ddc607fd2 | ||
|
|
4e1b0c6abe | ||
|
|
e4d7b53112 | ||
|
|
f9ff57a26e | ||
|
|
2af9f19c3a | ||
|
|
dbb8e2b245 | ||
|
|
689ad18c71 | ||
|
|
4422787d4e | ||
|
|
8d1057477b | ||
|
|
b3dff3a520 | ||
|
|
6141be7310 | ||
|
|
2762459acf | ||
|
|
53d8d4dbb4 | ||
|
|
5ae72f3e6f | ||
|
|
872b36124f | ||
|
|
f762ab6aa7 | ||
|
|
c311f9a4ed | ||
|
|
0a7517ecdd | ||
|
|
03febd9484 | ||
|
|
655b97bfd5 | ||
|
|
fdbc7f4621 | ||
|
|
f9fe303671 | ||
|
|
d4459eb6d6 | ||
|
|
9087a3ebbd | ||
|
|
56669f4247 | ||
|
|
22be1a1104 | ||
|
|
a80c585086 | ||
|
|
6d5dbd9729 | ||
|
|
0b4e3de455 | ||
|
|
8faef235a6 | ||
|
|
559bc7c731 | ||
|
|
3d7fdd0f35 | ||
|
|
726fcf861c | ||
|
|
839105f41d | ||
|
|
a2a27e2216 | ||
|
|
f866c8a61f | ||
|
|
472082cb03 | ||
|
|
b5a59ddb6a | ||
|
|
82da3c0027 | ||
|
|
908e75de39 | ||
|
|
a9145fe84c | ||
|
|
54abb53842 | ||
|
|
c2aa7b27ce | ||
|
|
a90e69366b | ||
|
|
74b94230fd | ||
|
|
e3ab333a59 | ||
|
|
ac9ed63f97 | ||
|
|
3bb7b1343a | ||
|
|
8db58dae2c | ||
|
|
d2aa1c2e39 | ||
|
|
8176eb1372 | ||
|
|
37c37f22d5 | ||
|
|
d2aa442b4a | ||
|
|
3547f3fab9 | ||
|
|
a338ad21cd | ||
|
|
d276e581a1 | ||
|
|
51fe6970ef | ||
|
|
c613164003 | ||
|
|
67345d083e | ||
|
|
6135d08154 | ||
|
|
340cbb9acf | ||
|
|
57b67fdeb1 | ||
|
|
b40d324e04 | ||
|
|
54e1ced26a | ||
|
|
c739c9dd2b | ||
|
|
aa9f8329d5 | ||
|
|
9b3aac4a8a | ||
|
|
75d841083c | ||
|
|
a01ad71414 | ||
|
|
9e6771d0f8 | ||
|
|
c83c57a37e | ||
|
|
90ef6deca8 | ||
|
|
83bd2d5915 | ||
|
|
879f558b44 | ||
|
|
f7d320ac32 |
2
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# All PRs must be approved by one of the main v2 developers
|
||||
* @Frooodle @Sf298 @LaserKaspar @sbplat
|
||||
13
.github/FUNDING.yml
vendored
@@ -1,13 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
custom: ['https://paypal.me/froodleplex?country.x=GB&locale.x=en_GB'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
11
.github/dependabot.yml
vendored
@@ -1,11 +0,0 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "gradle" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
56
.github/workflows/codeql.yml
vendored
@@ -1,56 +0,0 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ "main" ]
|
||||
schedule:
|
||||
- cron: '15 12 * * 1'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: java
|
||||
|
||||
- uses: gradle/gradle-build-action@v2.3.3
|
||||
with:
|
||||
gradle-version: 7.6
|
||||
arguments: assemble --no-build-cache
|
||||
|
||||
- name: Perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
73
.github/workflows/push-docker.yml
vendored
@@ -1,73 +0,0 @@
|
||||
name: Push Docker Image with VersionNumber
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- testGit
|
||||
- main
|
||||
jobs:
|
||||
push:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
|
||||
|
||||
- uses: gradle/gradle-build-action@v2.3.3
|
||||
with:
|
||||
gradle-version: 7.6
|
||||
arguments: clean build
|
||||
|
||||
- name: Make Gradle wrapper executable
|
||||
run: chmod +x gradlew
|
||||
|
||||
- name: Get version number
|
||||
id: versionNumber
|
||||
run: echo "::set-output name=versionNumber::$(./gradlew printVersion --quiet | tail -1)"
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2.1.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_API }}
|
||||
|
||||
- name: Check if tag exists
|
||||
id: checkIdExists
|
||||
continue-on-error: true
|
||||
run: |
|
||||
response=$(curl -s https://hub.docker.com/v2/repositories/frooodle/s-pdf/tags/?name=${{ steps.versionNumber.outputs.versionNumber }})
|
||||
result=$(echo $response | jq ".results")
|
||||
if [ "$result" == "[]" ]; then
|
||||
echo "Tag ${{ steps.versionNumber.outputs.versionNumber }} doesnt exist. Continuing with build and push."
|
||||
else
|
||||
echo "Tag ${{ steps.versionNumber.outputs.versionNumber }} already exists. Skipping build and push."
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
|
||||
|
||||
- name: Setup buildx
|
||||
run: |
|
||||
docker buildx create --name mybuilder
|
||||
docker buildx use mybuilder
|
||||
|
||||
- name: Build and push versioned amd64 and v8
|
||||
if: github.ref == 'refs/heads/main' && steps.checkIdExists.outcome != 'failure'
|
||||
run: |
|
||||
docker buildx build --platform="linux/amd64,linux/arm64/v8" --push --tag "frooodle/s-pdf:${{ steps.versionNumber.outputs.versionNumber }}" .
|
||||
|
||||
|
||||
- name: Build and push latest amd64 and v8
|
||||
if: github.ref == 'refs/heads/master'
|
||||
run: |
|
||||
docker buildx build --platform="linux/amd64,linux/arm64/v8" --push --tag "frooodle/s-pdf:latest" .
|
||||
|
||||
|
||||
117
.gitignore
vendored
@@ -1,110 +1,7 @@
|
||||
|
||||
|
||||
### Eclipse ###
|
||||
.metadata
|
||||
bin/
|
||||
tmp/
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~.nib
|
||||
local.properties
|
||||
.settings/
|
||||
.loadpath
|
||||
.recommenders
|
||||
.classpath
|
||||
.project
|
||||
|
||||
# Gradle
|
||||
.gradle
|
||||
.lock
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# PyDev specific (Python IDE for Eclipse)
|
||||
*.pydevproject
|
||||
|
||||
# CDT-specific (C/C++ Development Tooling)
|
||||
.cproject
|
||||
|
||||
# CDT- autotools
|
||||
.autotools
|
||||
|
||||
# Java annotation processor (APT)
|
||||
.factorypath
|
||||
|
||||
# PDT-specific (PHP Development Tools)
|
||||
.buildpath
|
||||
|
||||
# sbteclipse plugin
|
||||
.target
|
||||
|
||||
# Tern plugin
|
||||
.tern-project
|
||||
|
||||
# TeXlipse plugin
|
||||
.texlipse
|
||||
|
||||
# STS (Spring Tool Suite)
|
||||
.springBeans
|
||||
|
||||
# Code Recommenders
|
||||
.recommenders/
|
||||
|
||||
# Annotation Processing
|
||||
.apt_generated/
|
||||
.apt_generated_test/
|
||||
|
||||
# Scala IDE specific (Scala & Java development for Eclipse)
|
||||
.cache-main
|
||||
.scala_dependencies
|
||||
.worksheet
|
||||
|
||||
# Uncomment this line if you wish to ignore the project description file.
|
||||
# Typically, this file would be tracked if it contains build/dependency configurations:
|
||||
#.project
|
||||
|
||||
### Eclipse Patch ###
|
||||
# Spring Boot Tooling
|
||||
.sts4-cache/
|
||||
|
||||
### Git ###
|
||||
# Created by git for backups. To disable backups in Git:
|
||||
# $ git config --global mergetool.keepBackup false
|
||||
*.orig
|
||||
|
||||
# Created by git when using merge tools for conflicts
|
||||
*.BACKUP.*
|
||||
*.BASE.*
|
||||
*.LOCAL.*
|
||||
*.REMOTE.*
|
||||
*_BACKUP_*.txt
|
||||
*_BASE_*.txt
|
||||
*_LOCAL_*.txt
|
||||
*_REMOTE_*.txt
|
||||
|
||||
### Java ###
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
node_modules/
|
||||
*.code-workspace
|
||||
.idea/
|
||||
dist/
|
||||
android/
|
||||
ios/
|
||||
releases/
|
||||
26
CONTRIBUTE.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Contribute
|
||||
|
||||
This file should introduce you with the concepts and tools used in this project.
|
||||
|
||||
## PDF Library Docs
|
||||
- [pdf-lib](https://pdf-lib.js.org) - js
|
||||
- [pdfcpu](https://pdfcpu.io) - go-wasm
|
||||
- [opencv-wasm](https://www.npmjs.com/package/opencv-wasm) - ?-wasm
|
||||
- [pdfjs](https://www.npmjs.com/package/pdfjs-dist) - js
|
||||
|
||||
## Adding a PDF Operation
|
||||
StirlingPDF aims to support as many types of operations as possible, including some that cannot be executed in the client. Because of this, we have decided to move some of the shared functionality into it's own node module so that it can be shared by both client and server.
|
||||
|
||||
### Adding a shared (server + client) operation
|
||||
1. Add the code for the operation to a new file in the [functions folder](/shared-operations/functions/).
|
||||
|
||||
> **NOTE:** many of the functions in these files use **dependency injection** (see impose for an example).
|
||||
>
|
||||
> **Explanation:** Because some libraries need to be imported in different ways. We import the library as needed in the ```pdf-operations.js``` files, then pass the required library objects into the operation function as a parameter.
|
||||
|
||||
2. Now that we have the function code, we need to tell the other modules that it exists. Edit the [server operations](/server-node/src/pdf-operations.js) and the [client operations](/client-ionic/src/utils/pdf-operations.ts) files to add your new operation! (Try to follow existing patterns where possible, keep the added operations in alphabetical order in the files).
|
||||
|
||||
3. If you added a wrapper function to the [client operations](/client-ionic/src/utils/pdf-operations.ts) file, you will also need to add the TypeScript declarations to the [declaration](/client-ionic/declarations/shared-operations.d.ts) file. See the other module declarations for examples.
|
||||
|
||||
### Adding a server only operation
|
||||
> WIP
|
||||
@@ -1,5 +0,0 @@
|
||||
FROM openjdk:17-jdk-slim
|
||||
COPY build/libs/*.jar app.jar
|
||||
EXPOSE 8080
|
||||
ENV LOG_LEVEL=INFO
|
||||
ENTRYPOINT ["java","-jar","/app.jar","-Dlogging.level=${LOG_LEVEL}"]
|
||||
@@ -1,31 +0,0 @@
|
||||
<p align="center"><img src="https://raw.githubusercontent.com/Frooodle/Stirling-PDF/main/docs/stirling.png" width="80" ><br><h1 align="center">Stirling-PDF</h1>
|
||||
</p>
|
||||
|
||||
|
||||
# How to add new languages to Stirling-PDF
|
||||
|
||||
Fork Stirling-PDF and make a new branch out of Main
|
||||
|
||||
Then add reference to the language in the navbar by adding a new language entry to the dropdown
|
||||
|
||||
https://github.com/Frooodle/Stirling-PDF/blob/main/src/main/resources/templates/fragments/navbar.html#L80
|
||||
|
||||
For example to add Polish you would add
|
||||
```
|
||||
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="pl_PL">Polish</a>
|
||||
```
|
||||
The data-language-code is the code used to reference the file in the next step.
|
||||
|
||||
Start by copying the existing english property file
|
||||
|
||||
[https://github.com/Frooodle/Stirling-PDF/tree/langSetup/src/main/resources/messages_en_GB.properties](https://github.com/Frooodle/Stirling-PDF/blob/main/src/main/resources/messages_en_US.properties)
|
||||
|
||||
Copy and rename it to messages_{your data-language-code here}.properties, in the polish example you would set the name to messages_pl_PL.properties
|
||||
|
||||
|
||||
Then simply translate all property entries within that file and make a PR into main for others to use!
|
||||
|
||||
If you do not have a java IDE i am happy to verify the changes worked once you raise PR (but wont be able to verify the translations themselves)
|
||||
|
||||
|
||||
|
||||
33
Jenkinsfile
vendored
@@ -1,33 +0,0 @@
|
||||
pipeline {
|
||||
agent any
|
||||
stages {
|
||||
stage('Build') {
|
||||
steps {
|
||||
sh 'chmod 755 gradlew'
|
||||
sh './gradlew build'
|
||||
}
|
||||
}
|
||||
stage('Docker Build') {
|
||||
steps {
|
||||
script {
|
||||
def appVersion = sh(returnStdout: true, script: './gradlew printVersion -q').trim()
|
||||
def image = "frooodle/s-pdf:$appVersion"
|
||||
sh "docker build -t $image ."
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Docker Push') {
|
||||
steps {
|
||||
script {
|
||||
def appVersion = sh(returnStdout: true, script: './gradlew printVersion -q').trim()
|
||||
def image = "frooodle/s-pdf:$appVersion"
|
||||
withCredentials([string(credentialsId: 'docker_hub_access_token', variable: 'DOCKER_HUB_ACCESS_TOKEN')]) {
|
||||
sh "docker login --username frooodle --password $DOCKER_HUB_ACCESS_TOKEN"
|
||||
sh "docker push $image"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
201
LICENSE
@@ -1,201 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
256
README.md
@@ -1,71 +1,223 @@
|
||||
<p align="center"><img src="https://raw.githubusercontent.com/Frooodle/Stirling-PDF/main/docs/stirling.png" width="80" ><br><h1 align="center">Stirling-PDF</h1>
|
||||
</p>
|
||||
# StirlingPDF rewrite
|
||||
|
||||
This is the development repository for the new StirlingPDF backend. With the power of JS, WASM & GO this will provide almost all functionality SPDF can do currently directly on the client. For automation purposes this will still provide an API to automate your workflows.
|
||||
|
||||
This is a locally hosted web application that allows you to perform various operations on PDF files, such as splitting and adding images.
|
||||
## Try the new API!
|
||||
|
||||
Started off as a 100% ChatGPT made application, slowly moving away from that as more features are added
|
||||
[](https://documenter.getpostman.com/view/30633786/2s9YRB1Wto)
|
||||
|
||||
I will support and fix/add things to this if there is a demand [Discord](https://discord.gg/Cn8pWhQRxZ)
|
||||
## Understanding Workflows
|
||||
|
||||
Workflows define how to apply operations to a PDF, including their order and relations with eachother.
|
||||
|
||||

|
||||
Workflows can be created via the web-ui and then exported or, if you want to brag a bit, you can create the JSON object yourself.
|
||||
|
||||
### Basics
|
||||
|
||||
To create your own, you have to understand a few key features first. You can also look at more examples our github repository.
|
||||
|
||||
```json
|
||||
{
|
||||
"outputOptions": {
|
||||
"zip": false
|
||||
},
|
||||
"operations": [
|
||||
{
|
||||
"type": "extract",
|
||||
"values": {
|
||||
"pageIndexes": [0, 2]
|
||||
},
|
||||
"operations": []
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The workflow above will extract the first (p\[0\]) and third (p\[2\]) page of the document.
|
||||
|
||||
You can also nest workflows like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"outputOptions": {
|
||||
"zip": false
|
||||
},
|
||||
"operations": [
|
||||
{
|
||||
"type": "extract",
|
||||
"values": {
|
||||
"pageIndexes": [0, 2]
|
||||
},
|
||||
"operations": [
|
||||
{
|
||||
"type": "impose",
|
||||
"values": {
|
||||
"nup": 2, // 2 pages of the input document will be put on one page of the output document.
|
||||
"format": "A4L" // A4L -> The page size of the Ouput will be an A4 in Landscape. You can also use other paper formats and "P" for portrait output.
|
||||
},
|
||||
"operations": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
If you look at it closely, you will see that the extract operation has another nested operation of the type impose. This workflow will produce a PDF with the 1st and 2nd page of the input on one single page.
|
||||
|
||||
### Advanced
|
||||
|
||||
If that is not enought for you usecase, there is also the possibility to connect operations with eachother.
|
||||
|
||||
You can also do different operations to produce two different output PDFs from one input.
|
||||
|
||||
If you are interested in learning about this, take a look at the Example workflows provided in the repository, ask on the discord, or wait for me to finish this documentation.
|
||||
|
||||
## Features
|
||||
|
||||
- Split PDFs into multiple files at specified page numbers or extract all pages as individual files.
|
||||
- Merge multiple PDFs together into a single resultant file
|
||||
- Convert PDFs to and from images
|
||||
- Reorganize PDF pages into different orders.
|
||||
- Add images to PDFs at specified locations.
|
||||
- Rotating PDFs in 90 degree increments.
|
||||
- Compressing PDFs to decrease their filesize.
|
||||
- Add and remove passwords
|
||||
- Set PDF Permissions
|
||||
- Add watermark(s)
|
||||
- Dark mode support.
|
||||
### Rewrite Roadmap
|
||||
|
||||
## Technologies used
|
||||
- Spring Boot + Thymeleaf
|
||||
- PDFBox
|
||||
- e-iceblue spire.pdf.free (for PDF compression untill i find a nicer way)
|
||||
- HTML, CSS, JavaScript
|
||||
- Docker
|
||||
* [x] Client side PDF-Manipulation
|
||||
* [x] Workflows
|
||||
* [ ] Feature equivalent with S-PDF v1
|
||||
* [ ] Stateful UI
|
||||
* [ ] Node based editing of Workflows
|
||||
* [ ] Propper auth using passportjs
|
||||
|
||||
## How to use
|
||||
### Functions
|
||||
|
||||
### Locally
|
||||
Current functions of spdf and their progress in this repo.
|
||||
|
||||
Prerequisites
|
||||
- Java 17 or later
|
||||
- Gradle 7.0 or later
|
||||
|
||||
1. Clone or download the repository.
|
||||
2. Build the project using Gradle by running `./gradlew build`
|
||||
3. Start the application by running `./gradlew bootRun` or by calling the build jar in build/libs with java -jar jarName.jar
|
||||
#### Page Operations
|
||||
| Status | Feature | Description |
|
||||
| ------ | ------------------------ | ----------- |
|
||||
| 🚧A | Merge | |
|
||||
| 🚧A | Split | |
|
||||
| 🚧A | Organize | |
|
||||
| 🚧S | Rotate | |
|
||||
| 🚧A | Remove Pages | |
|
||||
| 🚧A | Multi-Page Layout | |
|
||||
| ❌ | Adjust page size/scale | |
|
||||
| 🚧A | Auto Split Pages | |
|
||||
| ❌ | Adjust Colours/Contrast | |
|
||||
| ❌ | Crop | |
|
||||
| 🚧A | Extract Pages | |
|
||||
| ❌ | PDF to Single large Page | |
|
||||
|
||||
|
||||
### Docker
|
||||
https://hub.docker.com/r/frooodle/s-pdf
|
||||
#### Convert
|
||||
| Status | Feature | Description |
|
||||
| ------ | ------------------- | ----------- |
|
||||
| ❌ | Image to PDF | |
|
||||
| 🚧S | Convert file to PDF | |
|
||||
| ❌ | URL to PDF | |
|
||||
| ❌ | HTML to PDF | |
|
||||
| ❌ | Markdown to PDF | |
|
||||
| ❌ | PDF to Image | |
|
||||
| ❌ | PDF to Word | |
|
||||
| ❌ | PDF to Presentation | |
|
||||
| ❌ | PDF to Text/RTF | |
|
||||
| ❌ | PDF to HTML | |
|
||||
| ❌ | PDF to PDF/A | |
|
||||
|
||||
Docker Run
|
||||
```
|
||||
docker run -p 8080:8080 frooodle/s-pdf
|
||||
```
|
||||
Docker Compose
|
||||
```
|
||||
version: '3.3'
|
||||
services:
|
||||
s-pdf:
|
||||
ports:
|
||||
- '8080:8080'
|
||||
image: frooodle/s-pdf
|
||||
```
|
||||
#### Security
|
||||
| Status | Feature | Description |
|
||||
| ------ | --------------------- | ----------- |
|
||||
| ❌ | Add Password | |
|
||||
| ❌ | Remove Password | |
|
||||
| ❌ | Change Permissions | |
|
||||
| ❌ | Add Watermark | |
|
||||
| ❌ | Sign with Certificate | |
|
||||
| ❌ | Sanitize | |
|
||||
| ❌ | Auto Redact | |
|
||||
|
||||
## How to View
|
||||
1. Open a web browser and navigate to `http://localhost:8080/`
|
||||
2. Use the application by following the instructions on the website.
|
||||
#### Miscellaneous
|
||||
| Status | Feature | Description |
|
||||
| ------ | --------------------------- | ----------- |
|
||||
| ❌ | OCR | |
|
||||
| ❌ | Add image | |
|
||||
| ❌ | Compress | |
|
||||
| ❌ | Extract Images | |
|
||||
| 🚧S | Change Metadata | |
|
||||
| 🚧A | Detect/Split Scanned photos | |
|
||||
| ❌ | Sign | |
|
||||
| ❌ | Flatten | |
|
||||
| ❌ | Repair | |
|
||||
| 🚧A | Remove Blank Pages | |
|
||||
| ❌ | Compare/Diff | |
|
||||
| ❌ | Add Page Numbers | |
|
||||
| ❌ | Auto Rename | |
|
||||
| ❌ | Get info | |
|
||||
| ❌ | Show JS | |
|
||||
|
||||
## Note
|
||||
The application is currently not thread-safe
|
||||
|
||||
|
||||
|
||||
✔️: Done, 🚧: Started Developement, ❌: Planned Feature
|
||||
A: Available in the internal API, S: Available on the node server, C: Available in the client
|
||||
|
||||
## Contribute
|
||||
|
||||
For initial instructions look at [CONTRIBUTE.md](./CONTRIBUTE.md)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
///// CONVERT 2 pdf
|
||||
file2pdf
|
||||
url2pdf
|
||||
html2pdf
|
||||
md2pdf
|
||||
image2pdf
|
||||
|
||||
///// CONVERT from pdf
|
||||
pdf2image
|
||||
flatten
|
||||
pdf2pdf/a
|
||||
pdf2word
|
||||
pdf2presentation
|
||||
pdf2rtf
|
||||
pdf2html
|
||||
pdf2xml
|
||||
|
||||
///// SINGLE
|
||||
merge
|
||||
rotate
|
||||
crop
|
||||
pageNumbers
|
||||
colours/contrast
|
||||
addPassword
|
||||
removePassword
|
||||
compress
|
||||
changeMetadata
|
||||
change Permissions
|
||||
OCR
|
||||
sanitise
|
||||
repair
|
||||
compare
|
||||
extract images
|
||||
signWith certificate
|
||||
impose
|
||||
adjust page size/scale
|
||||
auto rename
|
||||
getAllInfo
|
||||
showJS
|
||||
redact
|
||||
pdf2singleLargePage
|
||||
|
||||
///// SPLITTING
|
||||
split
|
||||
auto split
|
||||
detect/split scanned
|
||||
|
||||
///// REARRANGE
|
||||
- organise pages (remove/re-arrange)
|
||||
- removePages
|
||||
- removeBlank
|
||||
- extractPages
|
||||
|
||||
///// ADD OBJECTS
|
||||
add image
|
||||
add watermark
|
||||
sign
|
||||
*/
|
||||
39
build.gradle
@@ -1,39 +0,0 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'org.springframework.boot' version '3.0.2'
|
||||
id 'io.spring.dependency-management' version '1.1.0'
|
||||
}
|
||||
|
||||
group = 'stirling.software'
|
||||
version = '0.3.2'
|
||||
sourceCompatibility = '17'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url "https://repo.e-iceblue.com/nexus/content/groups/public/"
|
||||
name "com.e-iceblue"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
implementation 'org.apache.pdfbox:pdfbox:2.0.27'
|
||||
implementation 'org.apache.logging.log4j:log4j-core:2.19.0'
|
||||
implementation 'e-iceblue:spire.pdf.free:5.1.0'
|
||||
}
|
||||
|
||||
jar {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
tasks.named('test') {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
task printVersion {
|
||||
println project.version
|
||||
}
|
||||
|
||||
12
client-ionic/capacitor.config.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { CapacitorConfig } from '@capacitor/cli';
|
||||
|
||||
const config: CapacitorConfig = {
|
||||
appId: 'com.stirlingtools.pdf',
|
||||
appName: 'StirlingPDF',
|
||||
webDir: 'dist',
|
||||
server: {
|
||||
androidScheme: 'https'
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
10
client-ionic/cypress.config.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { defineConfig } from "cypress";
|
||||
|
||||
export default defineConfig({
|
||||
e2e: {
|
||||
baseUrl: "http://localhost:5173",
|
||||
setupNodeEvents(on, config) {
|
||||
// implement node event listeners here
|
||||
},
|
||||
},
|
||||
});
|
||||
6
client-ionic/cypress/e2e/test.cy.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
describe('My First Test', () => {
|
||||
it('Visits the app root url', () => {
|
||||
cy.visit('/')
|
||||
cy.contains('#container', 'Ready to create an app?')
|
||||
})
|
||||
})
|
||||
5
client-ionic/cypress/fixtures/example.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
||||
37
client-ionic/cypress/support/commands.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
/// <reference types="cypress" />
|
||||
// ***********************************************
|
||||
// This example commands.ts shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add('login', (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||
//
|
||||
// declare global {
|
||||
// namespace Cypress {
|
||||
// interface Chainable {
|
||||
// login(email: string, password: string): Chainable<void>
|
||||
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
|
||||
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
|
||||
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
20
client-ionic/cypress/support/e2e.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
// ***********************************************************
|
||||
// This example support/e2e.ts is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
33
client-ionic/index.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Ionic App</title>
|
||||
|
||||
<base href="/" />
|
||||
|
||||
<meta name="color-scheme" content="light dark" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||||
/>
|
||||
<meta name="format-detection" content="telephone=no" />
|
||||
<meta name="msapplication-tap-highlight" content="no" />
|
||||
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
|
||||
<link rel="shortcut icon" type="image/png" href="/favicon.png" />
|
||||
|
||||
<!-- add to homescreen for ios -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-title" content="Ionic App" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||
|
||||
<!-- TODO: I have no idea if this will build: -->
|
||||
<script src="/src/utils/browserfs.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
7
client-ionic/ionic.config.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "StirlingPDF",
|
||||
"integrations": {
|
||||
"capacitor": {}
|
||||
},
|
||||
"type": "react-vite"
|
||||
}
|
||||
12
client-ionic/ionic.starter.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "Blank Starter",
|
||||
"baseref": "main",
|
||||
"tarignore": [
|
||||
"node_modules",
|
||||
"package-lock.json",
|
||||
"www"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "npm run build && npm run test.unit -- --watch=false && npm i --no-save concurrently && ./node_modules/.bin/concurrently \"npm run dev\" \"npm run test.e2e\" --kill-others --success first"
|
||||
}
|
||||
}
|
||||
6316
client-ionic/package-lock.json
generated
Normal file
58
client-ionic/package.json
Normal file
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"name": "@stirling-pdf/client-ionic",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "ionic serve",
|
||||
"dev-android": "ionic build && ionic cap run android -l --external --open",
|
||||
"linux_build-release-android": "ionic cap build android --no-open --prod && cd android && ./gradlew assembleDebug && mkdir -p ../releases && mv app/build/outputs/apk/debug/app-debug.apk ../releases/StirlingPDF.apk && echo \"Done packaging APK!!!\"",
|
||||
"linux_build-release-pwa": "ionic build && mkdir -p releases && zip -r releases/pwa.zip dist/ && echo \"Done packaging PWA!!!\"",
|
||||
"build-vite": "tsc && vite build",
|
||||
"preview": "vite preview",
|
||||
"test.e2e": "cypress run",
|
||||
"test.unit": "vitest",
|
||||
"lint": "eslint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@capacitor/android": "5.5.1",
|
||||
"@capacitor/app": "5.0.6",
|
||||
"@capacitor/core": "5.5.1",
|
||||
"@capacitor/haptics": "5.0.6",
|
||||
"@capacitor/ios": "^5.5.1",
|
||||
"@capacitor/keyboard": "5.0.6",
|
||||
"@capacitor/status-bar": "5.0.6",
|
||||
"@capawesome/capacitor-file-picker": "^5.1.1",
|
||||
"@ionic/react": "^7.0.0",
|
||||
"@ionic/react-router": "^7.0.0",
|
||||
"@stirling-pdf/shared-operations": "*",
|
||||
"@types/react-router": "^5.1.20",
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
"downloadjs": "^1.4.7",
|
||||
"ionicons": "^7.0.0",
|
||||
"pdf-lib": "^1.17.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router": "^5.3.4",
|
||||
"react-router-dom": "^5.3.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@capacitor/cli": "5.5.1",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^14.0.0",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
"@types/downloadjs": "^1.4.5",
|
||||
"@types/react": "^18.0.27",
|
||||
"@types/react-dom": "^18.0.10",
|
||||
"@vitejs/plugin-legacy": "^4.0.2",
|
||||
"@vitejs/plugin-react": "^4.0.1",
|
||||
"cypress": "^13.3.2",
|
||||
"eslint": "^8.35.0",
|
||||
"eslint-plugin-react": "^7.32.2",
|
||||
"jsdom": "^22.1.0",
|
||||
"typescript": "^5.1.6",
|
||||
"vite": "4.5.0",
|
||||
"vite-plugin-pwa": "^0.16.6",
|
||||
"vitest": "^0.32.2"
|
||||
}
|
||||
}
|
||||
BIN
client-ionic/public/favicon.png
Normal file
|
After Width: | Height: | Size: 930 B |
21
client-ionic/public/manifest.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"short_name": "StirlingPDF",
|
||||
"name": "StirlingPDF",
|
||||
"icons": [
|
||||
{
|
||||
"src": "assets/icon/favicon.png",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "assets/icon/icon.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#ffffff",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
8
client-ionic/src/App.test.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import App from './App';
|
||||
|
||||
test('renders without crashing', () => {
|
||||
const { baseElement } = render(<App />);
|
||||
expect(baseElement).toBeDefined();
|
||||
});
|
||||
42
client-ionic/src/App.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import { Redirect, Route } from 'react-router-dom';
|
||||
import { IonApp, IonRouterOutlet, setupIonicReact } from '@ionic/react';
|
||||
import { IonReactRouter } from '@ionic/react-router';
|
||||
import Home from './pages/Home';
|
||||
|
||||
/* Core CSS required for Ionic components to work properly */
|
||||
import '@ionic/react/css/core.css';
|
||||
|
||||
/* Basic CSS for apps built with Ionic */
|
||||
import '@ionic/react/css/normalize.css';
|
||||
import '@ionic/react/css/structure.css';
|
||||
import '@ionic/react/css/typography.css';
|
||||
|
||||
/* Optional CSS utils that can be commented out */
|
||||
import '@ionic/react/css/padding.css';
|
||||
import '@ionic/react/css/float-elements.css';
|
||||
import '@ionic/react/css/text-alignment.css';
|
||||
import '@ionic/react/css/text-transformation.css';
|
||||
import '@ionic/react/css/flex-utils.css';
|
||||
import '@ionic/react/css/display.css';
|
||||
|
||||
/* Theme variables */
|
||||
import './theme/variables.css';
|
||||
|
||||
setupIonicReact();
|
||||
|
||||
const App: React.FC = () => (
|
||||
<IonApp>
|
||||
<IonReactRouter>
|
||||
<IonRouterOutlet>
|
||||
<Route exact path="/home">
|
||||
<Home />
|
||||
</Route>
|
||||
<Route exact path="/">
|
||||
<Redirect to="/home" />
|
||||
</Route>
|
||||
</IonRouterOutlet>
|
||||
</IonReactRouter>
|
||||
</IonApp>
|
||||
);
|
||||
|
||||
export default App;
|
||||
24
client-ionic/src/components/ExploreContainer.css
Normal file
@@ -0,0 +1,24 @@
|
||||
#container {
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
#container strong {
|
||||
font-size: 20px;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
#container p {
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
color: #8c8c8c;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#container a {
|
||||
text-decoration: none;
|
||||
}
|
||||
14
client-ionic/src/components/ExploreContainer.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import './ExploreContainer.css';
|
||||
|
||||
interface ContainerProps { }
|
||||
|
||||
const ExploreContainer: React.FC<ContainerProps> = () => {
|
||||
return (
|
||||
<div id="container">
|
||||
<strong>Ready to create an app?</strong>
|
||||
<p>Start with Ionic <a target="_blank" rel="noopener noreferrer" href="https://ionicframework.com/docs/components">UI Components</a></p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExploreContainer;
|
||||
11
client-ionic/src/main.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import App from './App';
|
||||
|
||||
const container = document.getElementById('root');
|
||||
const root = createRoot(container!);
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>
|
||||
);
|
||||
48
client-ionic/src/pages/Home.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonButton } from '@ionic/react';
|
||||
import './Home.css';
|
||||
import { rotatePages } from '../utils/pdf-operations.js';
|
||||
|
||||
import { FilePicker } from '@capawesome/capacitor-file-picker';
|
||||
|
||||
import download from 'downloadjs';
|
||||
|
||||
console.log(rotatePages);
|
||||
async function rotate90() {
|
||||
console.log("Test rotate 90 with Button Click");
|
||||
|
||||
const pickedFiles = await FilePicker.pickFiles({
|
||||
types: ['application/pdf'],
|
||||
multiple: false,
|
||||
});
|
||||
const file = pickedFiles.files[0];
|
||||
|
||||
const buffer = await file.blob?.arrayBuffer();
|
||||
if (!buffer) return;
|
||||
|
||||
const rotated = await rotatePages(buffer, 90)
|
||||
|
||||
download(rotated, "Rotated.pdf", "application/pdf");
|
||||
}
|
||||
|
||||
|
||||
const Home: React.FC = () => {
|
||||
return (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Blank</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent fullscreen>
|
||||
<IonHeader collapse="condense">
|
||||
<IonToolbar>
|
||||
<IonTitle size="large">Blank</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonButton onClick={rotate90}>Rotate 90</IonButton>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default Home;
|
||||
14
client-ionic/src/setupTests.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||
// allows you to do things like:
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import '@testing-library/jest-dom/extend-expect';
|
||||
|
||||
// Mock matchmedia
|
||||
window.matchMedia = window.matchMedia || function() {
|
||||
return {
|
||||
matches: false,
|
||||
addListener: function() {},
|
||||
removeListener: function() {}
|
||||
};
|
||||
};
|
||||
242
client-ionic/src/theme/variables.css
Normal file
@@ -0,0 +1,242 @@
|
||||
/* Ionic Variables and Theming. For more info, please see:
|
||||
http://ionicframework.com/docs/theming/ */
|
||||
|
||||
/** Ionic CSS Variables **/
|
||||
:root {
|
||||
/** primary **/
|
||||
--ion-color-primary: #3880ff;
|
||||
--ion-color-primary-rgb: 56, 128, 255;
|
||||
--ion-color-primary-contrast: #ffffff;
|
||||
--ion-color-primary-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-primary-shade: #3171e0;
|
||||
--ion-color-primary-tint: #4c8dff;
|
||||
|
||||
/** secondary **/
|
||||
--ion-color-secondary: #3dc2ff;
|
||||
--ion-color-secondary-rgb: 61, 194, 255;
|
||||
--ion-color-secondary-contrast: #ffffff;
|
||||
--ion-color-secondary-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-secondary-shade: #36abe0;
|
||||
--ion-color-secondary-tint: #50c8ff;
|
||||
|
||||
/** tertiary **/
|
||||
--ion-color-tertiary: #5260ff;
|
||||
--ion-color-tertiary-rgb: 82, 96, 255;
|
||||
--ion-color-tertiary-contrast: #ffffff;
|
||||
--ion-color-tertiary-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-tertiary-shade: #4854e0;
|
||||
--ion-color-tertiary-tint: #6370ff;
|
||||
|
||||
/** success **/
|
||||
--ion-color-success: #2dd36f;
|
||||
--ion-color-success-rgb: 45, 211, 111;
|
||||
--ion-color-success-contrast: #ffffff;
|
||||
--ion-color-success-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-success-shade: #28ba62;
|
||||
--ion-color-success-tint: #42d77d;
|
||||
|
||||
/** warning **/
|
||||
--ion-color-warning: #ffc409;
|
||||
--ion-color-warning-rgb: 255, 196, 9;
|
||||
--ion-color-warning-contrast: #000000;
|
||||
--ion-color-warning-contrast-rgb: 0, 0, 0;
|
||||
--ion-color-warning-shade: #e0ac08;
|
||||
--ion-color-warning-tint: #ffca22;
|
||||
|
||||
/** danger **/
|
||||
--ion-color-danger: #eb445a;
|
||||
--ion-color-danger-rgb: 235, 68, 90;
|
||||
--ion-color-danger-contrast: #ffffff;
|
||||
--ion-color-danger-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-danger-shade: #cf3c4f;
|
||||
--ion-color-danger-tint: #ed576b;
|
||||
|
||||
/** dark **/
|
||||
--ion-color-dark: #222428;
|
||||
--ion-color-dark-rgb: 34, 36, 40;
|
||||
--ion-color-dark-contrast: #ffffff;
|
||||
--ion-color-dark-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-dark-shade: #1e2023;
|
||||
--ion-color-dark-tint: #383a3e;
|
||||
|
||||
/** medium **/
|
||||
--ion-color-medium: #92949c;
|
||||
--ion-color-medium-rgb: 146, 148, 156;
|
||||
--ion-color-medium-contrast: #ffffff;
|
||||
--ion-color-medium-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-medium-shade: #808289;
|
||||
--ion-color-medium-tint: #9d9fa6;
|
||||
|
||||
/** light **/
|
||||
--ion-color-light: #f4f5f8;
|
||||
--ion-color-light-rgb: 244, 245, 248;
|
||||
--ion-color-light-contrast: #000000;
|
||||
--ion-color-light-contrast-rgb: 0, 0, 0;
|
||||
--ion-color-light-shade: #d7d8da;
|
||||
--ion-color-light-tint: #f5f6f9;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
/*
|
||||
* Dark Colors
|
||||
* -------------------------------------------
|
||||
*/
|
||||
|
||||
body {
|
||||
--ion-color-primary: #428cff;
|
||||
--ion-color-primary-rgb: 66,140,255;
|
||||
--ion-color-primary-contrast: #ffffff;
|
||||
--ion-color-primary-contrast-rgb: 255,255,255;
|
||||
--ion-color-primary-shade: #3a7be0;
|
||||
--ion-color-primary-tint: #5598ff;
|
||||
|
||||
--ion-color-secondary: #50c8ff;
|
||||
--ion-color-secondary-rgb: 80,200,255;
|
||||
--ion-color-secondary-contrast: #ffffff;
|
||||
--ion-color-secondary-contrast-rgb: 255,255,255;
|
||||
--ion-color-secondary-shade: #46b0e0;
|
||||
--ion-color-secondary-tint: #62ceff;
|
||||
|
||||
--ion-color-tertiary: #6a64ff;
|
||||
--ion-color-tertiary-rgb: 106,100,255;
|
||||
--ion-color-tertiary-contrast: #ffffff;
|
||||
--ion-color-tertiary-contrast-rgb: 255,255,255;
|
||||
--ion-color-tertiary-shade: #5d58e0;
|
||||
--ion-color-tertiary-tint: #7974ff;
|
||||
|
||||
--ion-color-success: #2fdf75;
|
||||
--ion-color-success-rgb: 47,223,117;
|
||||
--ion-color-success-contrast: #000000;
|
||||
--ion-color-success-contrast-rgb: 0,0,0;
|
||||
--ion-color-success-shade: #29c467;
|
||||
--ion-color-success-tint: #44e283;
|
||||
|
||||
--ion-color-warning: #ffd534;
|
||||
--ion-color-warning-rgb: 255,213,52;
|
||||
--ion-color-warning-contrast: #000000;
|
||||
--ion-color-warning-contrast-rgb: 0,0,0;
|
||||
--ion-color-warning-shade: #e0bb2e;
|
||||
--ion-color-warning-tint: #ffd948;
|
||||
|
||||
--ion-color-danger: #ff4961;
|
||||
--ion-color-danger-rgb: 255,73,97;
|
||||
--ion-color-danger-contrast: #ffffff;
|
||||
--ion-color-danger-contrast-rgb: 255,255,255;
|
||||
--ion-color-danger-shade: #e04055;
|
||||
--ion-color-danger-tint: #ff5b71;
|
||||
|
||||
--ion-color-dark: #f4f5f8;
|
||||
--ion-color-dark-rgb: 244,245,248;
|
||||
--ion-color-dark-contrast: #000000;
|
||||
--ion-color-dark-contrast-rgb: 0,0,0;
|
||||
--ion-color-dark-shade: #d7d8da;
|
||||
--ion-color-dark-tint: #f5f6f9;
|
||||
|
||||
--ion-color-medium: #989aa2;
|
||||
--ion-color-medium-rgb: 152,154,162;
|
||||
--ion-color-medium-contrast: #000000;
|
||||
--ion-color-medium-contrast-rgb: 0,0,0;
|
||||
--ion-color-medium-shade: #86888f;
|
||||
--ion-color-medium-tint: #a2a4ab;
|
||||
|
||||
--ion-color-light: #222428;
|
||||
--ion-color-light-rgb: 34,36,40;
|
||||
--ion-color-light-contrast: #ffffff;
|
||||
--ion-color-light-contrast-rgb: 255,255,255;
|
||||
--ion-color-light-shade: #1e2023;
|
||||
--ion-color-light-tint: #383a3e;
|
||||
}
|
||||
|
||||
/*
|
||||
* iOS Dark Theme
|
||||
* -------------------------------------------
|
||||
*/
|
||||
|
||||
.ios body {
|
||||
--ion-background-color: #000000;
|
||||
--ion-background-color-rgb: 0,0,0;
|
||||
|
||||
--ion-text-color: #ffffff;
|
||||
--ion-text-color-rgb: 255,255,255;
|
||||
|
||||
--ion-color-step-50: #0d0d0d;
|
||||
--ion-color-step-100: #1a1a1a;
|
||||
--ion-color-step-150: #262626;
|
||||
--ion-color-step-200: #333333;
|
||||
--ion-color-step-250: #404040;
|
||||
--ion-color-step-300: #4d4d4d;
|
||||
--ion-color-step-350: #595959;
|
||||
--ion-color-step-400: #666666;
|
||||
--ion-color-step-450: #737373;
|
||||
--ion-color-step-500: #808080;
|
||||
--ion-color-step-550: #8c8c8c;
|
||||
--ion-color-step-600: #999999;
|
||||
--ion-color-step-650: #a6a6a6;
|
||||
--ion-color-step-700: #b3b3b3;
|
||||
--ion-color-step-750: #bfbfbf;
|
||||
--ion-color-step-800: #cccccc;
|
||||
--ion-color-step-850: #d9d9d9;
|
||||
--ion-color-step-900: #e6e6e6;
|
||||
--ion-color-step-950: #f2f2f2;
|
||||
|
||||
--ion-item-background: #000000;
|
||||
|
||||
--ion-card-background: #1c1c1d;
|
||||
}
|
||||
|
||||
.ios ion-modal {
|
||||
--ion-background-color: var(--ion-color-step-100);
|
||||
--ion-toolbar-background: var(--ion-color-step-150);
|
||||
--ion-toolbar-border-color: var(--ion-color-step-250);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Material Design Dark Theme
|
||||
* -------------------------------------------
|
||||
*/
|
||||
|
||||
.md body {
|
||||
--ion-background-color: #121212;
|
||||
--ion-background-color-rgb: 18,18,18;
|
||||
|
||||
--ion-text-color: #ffffff;
|
||||
--ion-text-color-rgb: 255,255,255;
|
||||
|
||||
--ion-border-color: #222222;
|
||||
|
||||
--ion-color-step-50: #1e1e1e;
|
||||
--ion-color-step-100: #2a2a2a;
|
||||
--ion-color-step-150: #363636;
|
||||
--ion-color-step-200: #414141;
|
||||
--ion-color-step-250: #4d4d4d;
|
||||
--ion-color-step-300: #595959;
|
||||
--ion-color-step-350: #656565;
|
||||
--ion-color-step-400: #717171;
|
||||
--ion-color-step-450: #7d7d7d;
|
||||
--ion-color-step-500: #898989;
|
||||
--ion-color-step-550: #949494;
|
||||
--ion-color-step-600: #a0a0a0;
|
||||
--ion-color-step-650: #acacac;
|
||||
--ion-color-step-700: #b8b8b8;
|
||||
--ion-color-step-750: #c4c4c4;
|
||||
--ion-color-step-800: #d0d0d0;
|
||||
--ion-color-step-850: #dbdbdb;
|
||||
--ion-color-step-900: #e7e7e7;
|
||||
--ion-color-step-950: #f3f3f3;
|
||||
|
||||
--ion-item-background: #1e1e1e;
|
||||
|
||||
--ion-toolbar-background: #1f1f1f;
|
||||
|
||||
--ion-tab-bar-background: #1f1f1f;
|
||||
|
||||
--ion-card-background: #1e1e1e;
|
||||
}
|
||||
}
|
||||
|
||||
html {
|
||||
/* For more information on dynamic font scaling, visit the documentation:
|
||||
https://ionicframework.com/docs/layout/dynamic-font-scaling */
|
||||
--ion-dynamic-font: var(--ion-default-dynamic-font);
|
||||
}
|
||||
167
client-ionic/src/utils/downloadjs.js
Normal file
@@ -0,0 +1,167 @@
|
||||
//download.js v4.2, by dandavis; 2008-2016. [MIT] see http://danml.com/download.html for tests/usage
|
||||
// v1 landed a FF+Chrome compat way of downloading strings to local un-named files, upgraded to use a hidden frame and optional mime
|
||||
// v2 added named files via a[download], msSaveBlob, IE (10+) support, and window.URL support for larger+faster saves than dataURLs
|
||||
// v3 added dataURL and Blob Input, bind-toggle arity, and legacy dataURL fallback was improved with force-download mime and base64 support. 3.1 improved safari handling.
|
||||
// v4 adds AMD/UMD, commonJS, and plain browser support
|
||||
// v4.1 adds url download capability via solo URL argument (same domain/CORS only)
|
||||
// v4.2 adds semantic variable names, long (over 2MB) dataURL support, and hidden by default temp anchors
|
||||
// https://github.com/rndme/download
|
||||
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define([], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node. Does not work with strict CommonJS, but
|
||||
// only CommonJS-like environments that support module.exports,
|
||||
// like Node.
|
||||
module.exports = factory();
|
||||
} else {
|
||||
// Browser globals (root is window)
|
||||
root.download = factory();
|
||||
}
|
||||
}(this, function () {
|
||||
|
||||
return function download(data, strFileName, strMimeType) {
|
||||
|
||||
var self = window, // this script is only for browsers anyway...
|
||||
defaultMime = "application/octet-stream", // this default mime also triggers iframe downloads
|
||||
mimeType = strMimeType || defaultMime,
|
||||
payload = data,
|
||||
url = !strFileName && !strMimeType && payload,
|
||||
anchor = document.createElement("a"),
|
||||
toString = function(a){return String(a);},
|
||||
myBlob = (self.Blob || self.MozBlob || self.WebKitBlob || toString),
|
||||
fileName = strFileName || "download",
|
||||
blob,
|
||||
reader;
|
||||
myBlob= myBlob.call ? myBlob.bind(self) : Blob ;
|
||||
|
||||
if(String(this)==="true"){ //reverse arguments, allowing download.bind(true, "text/xml", "export.xml") to act as a callback
|
||||
payload=[payload, mimeType];
|
||||
mimeType=payload[0];
|
||||
payload=payload[1];
|
||||
}
|
||||
|
||||
|
||||
if(url && url.length< 2048){ // if no filename and no mime, assume a url was passed as the only argument
|
||||
fileName = url.split("/").pop().split("?")[0];
|
||||
anchor.href = url; // assign href prop to temp anchor
|
||||
if(anchor.href.indexOf(url) !== -1){ // if the browser determines that it's a potentially valid url path:
|
||||
var ajax=new XMLHttpRequest();
|
||||
ajax.open( "GET", url, true);
|
||||
ajax.responseType = 'blob';
|
||||
ajax.onload= function(e){
|
||||
download(e.target.response, fileName, defaultMime);
|
||||
};
|
||||
setTimeout(function(){ ajax.send();}, 0); // allows setting custom ajax headers using the return:
|
||||
return ajax;
|
||||
} // end if valid url?
|
||||
} // end if url?
|
||||
|
||||
|
||||
//go ahead and download dataURLs right away
|
||||
if(/^data:([\w+-]+\/[\w+.-]+)?[,;]/.test(payload)){
|
||||
|
||||
if(payload.length > (1024*1024*1.999) && myBlob !== toString ){
|
||||
payload=dataUrlToBlob(payload);
|
||||
mimeType=payload.type || defaultMime;
|
||||
}else{
|
||||
return navigator.msSaveBlob ? // IE10 can't do a[download], only Blobs:
|
||||
navigator.msSaveBlob(dataUrlToBlob(payload), fileName) :
|
||||
saver(payload) ; // everyone else can save dataURLs un-processed
|
||||
}
|
||||
|
||||
}else{//not data url, is it a string with special needs?
|
||||
if(/([\x80-\xff])/.test(payload)){
|
||||
var i=0, tempUiArr= new Uint8Array(payload.length), mx=tempUiArr.length;
|
||||
for(i;i<mx;++i) tempUiArr[i]= payload.charCodeAt(i);
|
||||
payload=new myBlob([tempUiArr], {type: mimeType});
|
||||
}
|
||||
}
|
||||
blob = payload instanceof myBlob ?
|
||||
payload :
|
||||
new myBlob([payload], {type: mimeType}) ;
|
||||
|
||||
|
||||
function dataUrlToBlob(strUrl) {
|
||||
var parts= strUrl.split(/[:;,]/),
|
||||
type= parts[1],
|
||||
decoder= parts[2] == "base64" ? atob : decodeURIComponent,
|
||||
binData= decoder( parts.pop() ),
|
||||
mx= binData.length,
|
||||
i= 0,
|
||||
uiArr= new Uint8Array(mx);
|
||||
|
||||
for(i;i<mx;++i) uiArr[i]= binData.charCodeAt(i);
|
||||
|
||||
return new myBlob([uiArr], {type: type});
|
||||
}
|
||||
|
||||
function saver(url, winMode){
|
||||
|
||||
if ('download' in anchor) { //html5 A[download]
|
||||
anchor.href = url;
|
||||
anchor.setAttribute("download", fileName);
|
||||
anchor.className = "download-js-link";
|
||||
anchor.innerHTML = "downloading...";
|
||||
anchor.style.display = "none";
|
||||
document.body.appendChild(anchor);
|
||||
setTimeout(function() {
|
||||
anchor.click();
|
||||
document.body.removeChild(anchor);
|
||||
if(winMode===true){setTimeout(function(){ self.URL.revokeObjectURL(anchor.href);}, 250 );}
|
||||
}, 66);
|
||||
return true;
|
||||
}
|
||||
|
||||
// handle non-a[download] safari as best we can:
|
||||
if(/(Version)\/(\d+)\.(\d+)(?:\.(\d+))?.*Safari\//.test(navigator.userAgent)) {
|
||||
if(/^data:/.test(url)) url="data:"+url.replace(/^data:([\w\/\-\+]+)/, defaultMime);
|
||||
if(!window.open(url)){ // popup blocked, offer direct download:
|
||||
if(confirm("Displaying New Document\n\nUse Save As... to download, then click back to return to this page.")){ location.href=url; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//do iframe dataURL download (old ch+FF):
|
||||
var f = document.createElement("iframe");
|
||||
document.body.appendChild(f);
|
||||
|
||||
if(!winMode && /^data:/.test(url)){ // force a mime that will download:
|
||||
url="data:"+url.replace(/^data:([\w\/\-\+]+)/, defaultMime);
|
||||
}
|
||||
f.src=url;
|
||||
setTimeout(function(){ document.body.removeChild(f); }, 333);
|
||||
|
||||
}//end saver
|
||||
|
||||
|
||||
|
||||
|
||||
if (navigator.msSaveBlob) { // IE10+ : (has Blob, but not a[download] or URL)
|
||||
return navigator.msSaveBlob(blob, fileName);
|
||||
}
|
||||
|
||||
if(self.URL){ // simple fast and modern way using Blob and URL:
|
||||
saver(self.URL.createObjectURL(blob), true);
|
||||
}else{
|
||||
// handle non-Blob()+non-URL browsers:
|
||||
if(typeof blob === "string" || blob.constructor===toString ){
|
||||
try{
|
||||
return saver( "data:" + mimeType + ";base64," + self.btoa(blob) );
|
||||
}catch(y){
|
||||
return saver( "data:" + mimeType + "," + encodeURIComponent(blob) );
|
||||
}
|
||||
}
|
||||
|
||||
// Blob but not URL support:
|
||||
reader=new FileReader();
|
||||
reader.onload=function(e){
|
||||
saver(this.result);
|
||||
};
|
||||
reader.readAsDataURL(blob);
|
||||
}
|
||||
return true;
|
||||
}; /* end download() */
|
||||
}));
|
||||
38
client-ionic/src/utils/pdf-operations.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
// Import injected libraries here!
|
||||
|
||||
import { Metadata, editMetadata as dependantEditMetadata} from "@stirling-pdf/shared-operations/functions/editMetadata";
|
||||
import { extractPages as dependantExtractPages } from "@stirling-pdf/shared-operations/functions/extractPages";
|
||||
import { mergePDFs as dependantMergePDFs } from '@stirling-pdf/shared-operations/functions/mergePDFs';
|
||||
import { rotatePages as dependantRotatePages } from '@stirling-pdf/shared-operations/functions/rotatePages';
|
||||
import { scaleContent as dependantScaleContent} from '@stirling-pdf/shared-operations/functions/scaleContent';
|
||||
import { scalePage as dependantScalePage } from '@stirling-pdf/shared-operations/functions/scalePage';
|
||||
import { splitPDF as dependantSplitPDF } from '@stirling-pdf/shared-operations/functions/splitPDF';
|
||||
|
||||
export async function editMetadata(snapshot: string | Uint8Array | ArrayBuffer, metadata: Metadata) {
|
||||
return dependantEditMetadata(snapshot, metadata);
|
||||
}
|
||||
|
||||
export async function extractPages(snapshot: string | Uint8Array | ArrayBuffer, pageIndexes: number[]) {
|
||||
return dependantExtractPages(snapshot, pageIndexes);
|
||||
}
|
||||
|
||||
export async function mergePDFs(snapshots: (string | Uint8Array | ArrayBuffer)[]) {
|
||||
return dependantMergePDFs(snapshots);
|
||||
}
|
||||
|
||||
export async function rotatePages(snapshot: string | Uint8Array | ArrayBuffer, rotation: number) {
|
||||
return dependantRotatePages(snapshot, rotation);
|
||||
}
|
||||
|
||||
export async function scaleContent(snapshot: string | Uint8Array | ArrayBuffer, scaleFactor: number) {
|
||||
return dependantScaleContent(snapshot, scaleFactor);
|
||||
}
|
||||
|
||||
export async function scalePage(snapshot: string | Uint8Array | ArrayBuffer, pageSize: { width: number; height: number; }) {
|
||||
return dependantScalePage(snapshot, pageSize);
|
||||
}
|
||||
|
||||
export async function splitPDF(snapshot: string | Uint8Array | ArrayBuffer, splitAfterPageArray: number[]) {
|
||||
return dependantSplitPDF(snapshot, splitAfterPageArray);
|
||||
}
|
||||
1
client-ionic/src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
24
client-ionic/tsconfig.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
"allowJs": false,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": [
|
||||
"src",
|
||||
"declarations/*.d.ts"
|
||||
],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
9
client-ionic/tsconfig.node.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
18
client-ionic/vite.config.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import legacy from '@vitejs/plugin-legacy'
|
||||
import react from '@vitejs/plugin-react'
|
||||
import { defineConfig } from 'vite'
|
||||
import { VitePWA } from 'vite-plugin-pwa'; // https://ionicframework.com/docs/react/pwa
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
react(),
|
||||
VitePWA({ registerType: 'autoUpdate' }),
|
||||
legacy()
|
||||
],
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
setupFiles: './src/setupTests.ts',
|
||||
}
|
||||
})
|
||||
24
client-tauri/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
3
client-tauri/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["tauri-apps.tauri-vscode", "rust-lang.rust-analyzer"]
|
||||
}
|
||||
7
client-tauri/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Tauri + React + Typescript
|
||||
|
||||
This template should help get you started developing with Tauri, React and Typescript in Vite.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
- [VS Code](https://code.visualstudio.com/) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer)
|
||||
14
client-tauri/index.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/stirling-pdf-logo.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Tauri + React + TS</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
40
client-tauri/package.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "@stirling-pdf/client-tauri",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"preview": "vite preview",
|
||||
"tauri": "tauri"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stirling-pdf/shared-operations": "^0.0.0",
|
||||
"@tauri-apps/api": "^1.5.1",
|
||||
"archiver": "^6.0.1",
|
||||
"bootstrap": "^5.3.2",
|
||||
"i18next": "^23.6.0",
|
||||
"i18next-browser-languagedetector": "^7.1.0",
|
||||
"path-browserify": "^1.0.1",
|
||||
"pdfjs-dist": "^4.0.189",
|
||||
"react": "^18.2.0",
|
||||
"react-bootstrap": "^2.9.1",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-i18next": "^13.3.1",
|
||||
"react-icons": "^4.11.0",
|
||||
"react-router-bootstrap": "^0.26.2",
|
||||
"react-router-dom": "^6.18.0",
|
||||
"vite-plugin-top-level-await": "^1.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^1.5.0",
|
||||
"@types/archiver": "^5.3.4",
|
||||
"@types/react": "^18.2.15",
|
||||
"@types/react-dom": "^18.2.7",
|
||||
"@types/react-router-bootstrap": "^0.26.5",
|
||||
"@vitejs/plugin-react": "^4.0.3",
|
||||
"typescript": "^5.0.2",
|
||||
"vite": "^4.4.4"
|
||||
}
|
||||
}
|
||||
BIN
client-tauri/public/stirling-pdf-logo.png
Normal file
|
After Width: | Height: | Size: 132 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
4
client-tauri/src-tauri/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
|
||||
3801
client-tauri/src-tauri/Cargo.lock
generated
Normal file
23
client-tauri/src-tauri/Cargo.toml
Normal file
@@ -0,0 +1,23 @@
|
||||
[package]
|
||||
name = "stirling_pdf"
|
||||
version = "0.0.0"
|
||||
description = "A Tauri App"
|
||||
authors = ["you"]
|
||||
license = ""
|
||||
repository = ""
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "1.5", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "1.5", features = [ "fs-remove-dir", "fs-create-dir", "shell-all", "fs-write-file", "fs-read-file", "dialog-save", "dialog-open"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
||||
[features]
|
||||
# this feature is used for production builds or when `devPath` points to the filesystem
|
||||
# DO NOT REMOVE!!
|
||||
custom-protocol = ["tauri/custom-protocol"]
|
||||
3
client-tauri/src-tauri/build.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
tauri_build::build()
|
||||
}
|
||||
BIN
client-tauri/src-tauri/icons/128x128.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
client-tauri/src-tauri/icons/128x128@2x.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
client-tauri/src-tauri/icons/32x32.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
client-tauri/src-tauri/icons/Square107x107Logo.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
client-tauri/src-tauri/icons/Square142x142Logo.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
client-tauri/src-tauri/icons/Square150x150Logo.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
client-tauri/src-tauri/icons/Square284x284Logo.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
client-tauri/src-tauri/icons/Square30x30Logo.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
client-tauri/src-tauri/icons/Square310x310Logo.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
client-tauri/src-tauri/icons/Square44x44Logo.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
client-tauri/src-tauri/icons/Square71x71Logo.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
client-tauri/src-tauri/icons/Square89x89Logo.png
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
BIN
client-tauri/src-tauri/icons/StoreLogo.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
client-tauri/src-tauri/icons/icon.icns
Normal file
BIN
client-tauri/src-tauri/icons/icon.ico
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
client-tauri/src-tauri/icons/icon.png
Normal file
|
After Width: | Height: | Size: 87 KiB |
15
client-tauri/src-tauri/src/main.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
|
||||
#[tauri::command]
|
||||
fn greet(name: &str) -> String {
|
||||
format!("Hello, {}! You've been greeted from Rust!", name)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.invoke_handler(tauri::generate_handler![greet])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
78
client-tauri/src-tauri/tauri.conf.json
Normal file
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"build": {
|
||||
"beforeDevCommand": "npm run dev",
|
||||
"beforeBuildCommand": "npm run build",
|
||||
"devPath": "http://localhost:1420",
|
||||
"distDir": "../dist",
|
||||
"withGlobalTauri": false
|
||||
},
|
||||
"package": {
|
||||
"productName": "StirlingPDF",
|
||||
"version": "0.0.0"
|
||||
},
|
||||
"tauri": {
|
||||
"allowlist": {
|
||||
"all": false,
|
||||
"shell": {
|
||||
"all": true,
|
||||
"open": true,
|
||||
"scope": [
|
||||
{
|
||||
"name": "libreoffice-version",
|
||||
"cmd": "libreoffice",
|
||||
"args": ["--version"]
|
||||
},{
|
||||
"name": "libreoffice-convert",
|
||||
"cmd": "libreoffice",
|
||||
"args": ["--headless","--convert-to",{ "validator": "\\S+" },{ "validator": "\\S+" },"--outdir",{ "validator": "\\S+" }]
|
||||
}
|
||||
]
|
||||
},
|
||||
"dialog": {
|
||||
"all": false,
|
||||
"ask": false,
|
||||
"confirm": false,
|
||||
"message": false,
|
||||
"open": true,
|
||||
"save": true
|
||||
},
|
||||
"fs": {
|
||||
"all": false,
|
||||
"readFile": true,
|
||||
"writeFile": true,
|
||||
"readDir": false,
|
||||
"copyFile": false,
|
||||
"createDir": true,
|
||||
"removeDir": true,
|
||||
"removeFile": false,
|
||||
"renameFile": false,
|
||||
"exists": false
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"identifier": "com.stirlingtools.pdf",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
],
|
||||
"category": "Business"
|
||||
},
|
||||
"security": {
|
||||
"csp": null
|
||||
},
|
||||
"windows": [
|
||||
{
|
||||
"fullscreen": false,
|
||||
"resizable": true,
|
||||
"title": "StirlingPDF",
|
||||
"width": 800,
|
||||
"height": 600
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
72
client-tauri/src/App.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import { Suspense } from 'react';
|
||||
|
||||
import { Routes, Route, Outlet } from "react-router-dom";
|
||||
import Home from "./pages/Home";
|
||||
import About from "./pages/About";
|
||||
import Dashboard from "./pages/Dashboard";
|
||||
import ToPdf from "./pages/convert/ToPdf"
|
||||
import NoMatch from "./pages/NoMatch";
|
||||
import NavBar from "./components/NavBar";
|
||||
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
import { Container } from "react-bootstrap";
|
||||
|
||||
import i18n from "i18next";
|
||||
import { useTranslation, initReactI18next } from "react-i18next";
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
import ar from './locales/ar.json';
|
||||
import en from './locales/en.json';
|
||||
|
||||
import './general.css'
|
||||
|
||||
i18n
|
||||
.use(LanguageDetector)
|
||||
.use(initReactI18next) // passes i18n down to react-i18next
|
||||
.init({
|
||||
fallbackLng: "en",
|
||||
resources: { ar,en },
|
||||
});
|
||||
|
||||
export default function App() {
|
||||
|
||||
return (
|
||||
<Suspense fallback="loading">
|
||||
{/* Routes nest inside one another. Nested route paths build upon
|
||||
parent route paths, and nested route elements render inside
|
||||
parent route elements. See the note about <Outlet> below. */}
|
||||
<Routes>
|
||||
<Route path="/" element={<Layout />}>
|
||||
<Route index element={<Home />} />
|
||||
<Route path="about" element={<About />} />
|
||||
<Route path="dashboard" element={<Dashboard />} />
|
||||
<Route path="to-pdf" element={<ToPdf />} />
|
||||
|
||||
{/* Using path="*"" means "match anything", so this route
|
||||
acts like a catch-all for URLs that we don't have explicit
|
||||
routes for. */}
|
||||
<Route path="*" element={<NoMatch />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
function Layout() {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<div lang-direction={t('language.direction')}>
|
||||
<NavBar/>
|
||||
|
||||
{/* An <Outlet> renders whatever child route is currently active,
|
||||
so you can think about this <Outlet> as a placeholder for
|
||||
the child routes we defined above. */}
|
||||
<Container fluid="sm" className="">
|
||||
<div className="row justify-content-center">
|
||||
<div className="col-md-6">
|
||||
<Outlet/>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
1
client-tauri/src/assets/react.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
138
client-tauri/src/components/NavBar.css
Normal file
@@ -0,0 +1,138 @@
|
||||
#search-icon i {
|
||||
font-size: 24px; /* Adjust this to your desired size */
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
#search-icon:hover i {
|
||||
color: #666; /* Adjust this to your hover color */
|
||||
}
|
||||
|
||||
#navbarSearch {
|
||||
transition: all 0.3s;
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
|
||||
}
|
||||
|
||||
#navbarSearch.show {
|
||||
max-height: 300px; /* Adjust this to your desired max height */
|
||||
}
|
||||
|
||||
.search-input {
|
||||
transition: border 0.3s, box-shadow 0.3s;
|
||||
|
||||
}
|
||||
|
||||
.search-input:focus {
|
||||
border-color: #666; /* Adjust this to your focus color */
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); /* Adjust this to your desired shadow */
|
||||
}
|
||||
|
||||
#searchResults {
|
||||
max-width: 300px; /* Adjust to your preferred width */
|
||||
transition: height 0.3s ease; /* Smooth height transition */
|
||||
}
|
||||
|
||||
/* Set a fixed height and styling for each search result item */
|
||||
.search-results a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px; /* space between icon and text */
|
||||
height: 40px; /* Adjust based on your design */
|
||||
overflow: hidden; /* Prevent content from overflowing */
|
||||
white-space: nowrap; /* Prevent text from wrapping to next line */
|
||||
text-overflow: ellipsis; /* Truncate text if it's too long */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#navbarSearch {
|
||||
top: 100%;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#searchForm {
|
||||
width: 200px; /* Adjust this value as needed */
|
||||
}
|
||||
|
||||
/* Style the search results to match the navbar */
|
||||
#searchResults {
|
||||
max-height: 200px; /* Adjust this value as needed */
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#searchResults .dropdown-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
height: 50px; /* Fixed height */
|
||||
overflow: hidden; /* Hide overflow */
|
||||
}
|
||||
|
||||
#searchResults .icon {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
#searchResults .icon-text {
|
||||
display: inline;
|
||||
overflow: hidden; /* Hide overflow */
|
||||
text-overflow: ellipsis; /* Add ellipsis for long text */
|
||||
}
|
||||
|
||||
|
||||
|
||||
.main-icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
vertical-align: middle;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.nav-icon svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
vertical-align: middle;
|
||||
transform: translateY(-2px);
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
/*
|
||||
.icon+.icon {
|
||||
margin-left: -4px;
|
||||
}
|
||||
*/
|
||||
.nav-icon span {
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.nav-item-separator {
|
||||
position: relative;
|
||||
margin: 0 4px; /* Adjust the margin as needed */
|
||||
}
|
||||
|
||||
.nav-item-separator::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 10%; /* Adjust the top and bottom margins as needed */
|
||||
bottom: 10%;
|
||||
width: 1px;
|
||||
background-color: #ccc; /* Adjust the color as needed */
|
||||
}
|
||||
|
||||
.navbar-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
173
client-tauri/src/components/NavBar.tsx
Normal file
@@ -0,0 +1,173 @@
|
||||
|
||||
import { AiOutlineMergeCells, AiOutlineSplitCells } from "react-icons/ai";
|
||||
import { BiCrop, BiSprayCan } from "react-icons/bi";
|
||||
import {
|
||||
BsTools, BsSortNumericDown, BsArrowClockwise, BsFileEarmarkX, BsLayoutSplit, BsPalette, BsArrowUpSquare, Bs1Square, BsFileEarmarkPdf,
|
||||
BsArrowLeftRight, BsFileEarmarkImage, BsFileEarmark, BsFiletypeHtml, BsLink, BsFiletypeMd, BsFileEarmarkWord, BsFiletypePpt, BsFiletypeTxt,
|
||||
BsFiletypeXml, BsLock, BsUnlock, BsShieldLock, BsDroplet, BsAward, BsEraserFill, BsCardList, BsClipboardData, BsFile, BsFileEarmarkRichtext,
|
||||
BsFileZip, BsFiletypeJs, BsFonts, BsImages, BsInfoCircle, BsSearch, BsShieldCheck, BsVectorPen, BsWrench, BsArrowsCollapse, BsGrid, Bs123,
|
||||
BsArrowsFullscreen
|
||||
} from "react-icons/bs";
|
||||
import { MdOutlineScanner, MdOutlineBalance } from "react-icons/md";
|
||||
import { IconType } from "react-icons";
|
||||
|
||||
import Container from 'react-bootstrap/Container';
|
||||
import Nav from 'react-bootstrap/Nav';
|
||||
import Navbar from 'react-bootstrap/Navbar';
|
||||
import NavDropdown from 'react-bootstrap/NavDropdown';
|
||||
import { LinkContainer } from 'react-router-bootstrap';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import LanguagePicker from "./toolbar/LanguagePicker";
|
||||
import Logo from '../../public/stirling-pdf-logo.svg'
|
||||
import './NavBar.css';
|
||||
|
||||
interface NavInfoItem {
|
||||
displayText: string;
|
||||
icon: any;
|
||||
dest: string;
|
||||
tooltip?: string;
|
||||
}
|
||||
interface NavInfoSublist {
|
||||
displayText: string;
|
||||
icon: IconType;
|
||||
sublist: Array<NavInfoItem>;
|
||||
}
|
||||
|
||||
function convertToNavLink(item: NavInfoItem, index: number) {
|
||||
return <LinkContainer key={"nav-link-"+index} to={item.dest}><Nav.Link className="nav-icon" title={item.tooltip}><item.icon/><span>{item.displayText}</span></Nav.Link></LinkContainer>;
|
||||
}
|
||||
function convertToNavDropdownItem(item: NavInfoItem | null, index: number) {
|
||||
if (item == null)
|
||||
return <NavDropdown.Divider key={"nav-dropdown-divider-"+index}/>;
|
||||
|
||||
return (
|
||||
<LinkContainer to={item.dest} key={"nav-dropdown-item-"+index}>
|
||||
<NavDropdown.Item className="nav-icon" title={item.tooltip}>
|
||||
<item.icon/>
|
||||
<span>{item.displayText}</span>
|
||||
</NavDropdown.Item>
|
||||
</LinkContainer>
|
||||
);
|
||||
}
|
||||
function convertToNavDropdown(sublist: NavInfoSublist, index: number) {
|
||||
var myTitle = <>
|
||||
<span className="nav-icon">
|
||||
<sublist.icon/>
|
||||
<span>{sublist.displayText}</span>
|
||||
</span>
|
||||
</>;
|
||||
|
||||
return (
|
||||
<NavDropdown title={myTitle} id="basic-nav-dropdown" key={"nav-dropdown-"+index}>
|
||||
{sublist.sublist.map((item, i) => convertToNavDropdownItem(item, i))}
|
||||
</NavDropdown>
|
||||
);
|
||||
}
|
||||
|
||||
function NavBar() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const navInfo = [
|
||||
{displayText: t('multiTool.title'), icon: BsTools, dest: "/home", tooltip: t('home.multiTool.desc')},
|
||||
{displayText: t('navbar.pageOps'), icon: BsFileEarmarkPdf, sublist: [
|
||||
{ displayText: t('home.merge.title'), icon: AiOutlineMergeCells, dest: "/dashboard", tooltip: t('home.merge.desc') },
|
||||
{ displayText: t('home.split.title'), icon: AiOutlineSplitCells, dest: "/about", tooltip: t('home.split.desc') },
|
||||
{ displayText: t('home.pdfOrganiser.title'), icon: BsSortNumericDown, dest: "/nothing-here", tooltip: t('home.pdfOrganiser.desc') },
|
||||
{ displayText: t('home.rotate.title'), icon: BsArrowClockwise, dest: "/nothing-here", tooltip: t('home.rotate.desc') },
|
||||
{ displayText: t('home.removePages.title'), icon: BsFileEarmarkX, dest: "/nothing-here", tooltip: t('home.removePages.desc') },
|
||||
{ displayText: t('home.pageLayout.title'), icon: BsGrid, dest: "/nothing-here", tooltip: t('home.pageLayout.desc') },
|
||||
{ displayText: t('home.scalePages.title'), icon: BsArrowsFullscreen, dest: "/nothing-here", tooltip: t('home.scalePages.desc') },
|
||||
{ displayText: t('home.autoSplitPDF.title'), icon: BsLayoutSplit, dest: "/nothing-here", tooltip: t('home.autoSplitPDF.desc') },
|
||||
{ displayText: t('home.adjust-contrast.title'), icon: BsPalette, dest: "/nothing-here", tooltip: t('home.adjust-contrast.desc') },
|
||||
{ displayText: t('home.crop.title'), icon: BiCrop, dest: "/nothing-here", tooltip: t('home.crop.desc') },
|
||||
{ displayText: t('home.extractPage.title'), icon: BsArrowUpSquare, dest: "/nothing-here", tooltip: t('home.extractPage.desc') },
|
||||
{ displayText: t('home.PdfToSinglePage.title'), icon: Bs1Square, dest: "/nothing-here", tooltip: t('home.PdfToSinglePage.desc') },
|
||||
]},
|
||||
{displayText: t('navbar.convert'), icon: BsArrowLeftRight, sublist: [
|
||||
{ displayText: t('home.imageToPdf.title'), icon: BsFileEarmarkImage, dest: "/dashboard", tooltip: t('home.imageToPdf.desc') },
|
||||
{ displayText: t('home.fileToPDF.title'), icon: BsFileEarmark, dest: "/to-pdf", tooltip: t('home.fileToPDF.desc') },
|
||||
{ displayText: t('home.HTMLToPDF.title'), icon: BsFiletypeHtml, dest: "/nothing-here", tooltip: t('home.HTMLToPDF.desc') },
|
||||
{ displayText: t('home.URLToPDF.title'), icon: BsLink, dest: "/nothing-here", tooltip: t('home.URLToPDF.desc') },
|
||||
{ displayText: t('home.MarkdownToPDF.title'), icon: BsFiletypeMd, dest: "/nothing-here", tooltip: t('home.MarkdownToPDF.desc') },
|
||||
null,
|
||||
{ displayText: t('home.pdfToImage.title'), icon: BsFileEarmarkImage, dest: "/nothing-here", tooltip: t('home.pdfToImage.desc') },
|
||||
{ displayText: t('home.PDFToWord.title'), icon: BsFileEarmarkWord, dest: "/nothing-here", tooltip: t('home.PDFToWord.desc') },
|
||||
{ displayText: t('home.PDFToPresentation.title'), icon: BsFiletypePpt, dest: "/nothing-here", tooltip: t('home.PDFToPresentation.desc') },
|
||||
{ displayText: t('home.PDFToText.title'), icon: BsFiletypeTxt, dest: "/nothing-here", tooltip: t('home.PDFToText.desc') },
|
||||
{ displayText: t('home.PDFToHTML.title'), icon: BsFiletypeHtml, dest: "/nothing-here", tooltip: t('home.PDFToHTML.desc') },
|
||||
{ displayText: t('home.PDFToXML.title'), icon: BsFiletypeXml, dest: "/nothing-here", tooltip: t('home.PDFToXML.desc') },
|
||||
{ displayText: t('home.pdfToPDFA.title'), icon: BsFileEarmarkPdf, dest: "/nothing-here", tooltip: t('home.pdfToPDFA.desc') },
|
||||
]},
|
||||
{displayText: t('navbar.security'), icon: BsShieldCheck, sublist: [
|
||||
{ displayText: t('home.addPassword.title'), icon: BsLock, dest: "/dashboard", tooltip: t('home.addPassword.desc') },
|
||||
{ displayText: t('home.removePassword.title'), icon: BsUnlock, dest: "/nothing-here", tooltip: t('home.removePassword.desc') },
|
||||
{ displayText: t('home.permissions.title'), icon: BsShieldLock, dest: "/nothing-here", tooltip: t('home.permissions.desc') },
|
||||
{ displayText: t('home.watermark.title'), icon: BsDroplet, dest: "/nothing-here", tooltip: t('home.watermark.desc') },
|
||||
{ displayText: t('home.certSign.title'), icon: BsAward, dest: "/nothing-here", tooltip: t('home.certSign.desc') },
|
||||
{ displayText: t('home.sanitizePdf.title'), icon: BiSprayCan, dest: "/nothing-here", tooltip: t('home.sanitizePdf.desc') },
|
||||
{ displayText: t('home.autoRedact.title'), icon: BsEraserFill, dest: "/nothing-here", tooltip: t('home.autoRedact.desc') },
|
||||
]},
|
||||
{displayText: t('navbar.other'), icon: BsCardList, sublist: [
|
||||
{ displayText: t('home.ocr.title'), icon: BsSearch, dest: "/dashboard", tooltip: t('home.ocr.desc') },
|
||||
{ displayText: t('home.addImage.title'), icon: BsFileEarmarkRichtext, dest: "/nothing-here", tooltip: t('home.addImage.desc') },
|
||||
{ displayText: t('home.compressPdfs.title'), icon: BsFileZip, dest: "/nothing-here", tooltip: t('home.compressPdfs.desc') },
|
||||
{ displayText: t('home.extractImages.title'), icon: BsImages, dest: "/nothing-here", tooltip: t('home.extractImages.desc') },
|
||||
{ displayText: t('home.changeMetadata.title'), icon: BsClipboardData, dest: "/nothing-here", tooltip: t('home.changeMetadata.desc') },
|
||||
{ displayText: t('home.ScannerImageSplit.title'), icon: MdOutlineScanner, dest: "/nothing-here", tooltip: t('home.ScannerImageSplit.desc') },
|
||||
{ displayText: t('home.sign.title'), icon: BsVectorPen, dest: "/nothing-here", tooltip: t('home.sign.desc') },
|
||||
{ displayText: t('home.flatten.title'), icon: BsArrowsCollapse, dest: "/nothing-here", tooltip: t('home.flatten.desc') },
|
||||
{ displayText: t('home.repair.title'), icon: BsWrench, dest: "/nothing-here", tooltip: t('home.repair.desc') },
|
||||
{ displayText: t('home.removeBlanks.title'), icon: BsFile, dest: "/nothing-here", tooltip: t('home.removeBlanks.desc') },
|
||||
{ displayText: t('home.compare.title'), icon: MdOutlineBalance, dest: "/nothing-here", tooltip: t('home.compare.desc') },
|
||||
{ displayText: t('home.add-page-numbers.title'), icon: Bs123, dest: "/nothing-here", tooltip: t('home.add-page-numbers.desc') },
|
||||
{ displayText: t('home.auto-rename.title'), icon: BsFonts, dest: "/nothing-here", tooltip: t('home.auto-rename.desc') },
|
||||
{ displayText: t('home.getPdfInfo.title'), icon: BsInfoCircle, dest: "/nothing-here", tooltip: t('home.getPdfInfo.desc') },
|
||||
{ displayText: t('home.showJS.title'), icon: BsFiletypeJs, dest: "/nothing-here", tooltip: t('home.showJS.desc') },
|
||||
]},
|
||||
] as Array<NavInfoItem | NavInfoSublist>;
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<Navbar expand="lg" className="bg-light">
|
||||
<Container>
|
||||
<LinkContainer to="/home">
|
||||
<Navbar.Brand className="nav-icon">
|
||||
<img src={Logo} alt="Image" className="main-icon" />
|
||||
<span className="icon-text">Stirling PDF</span>
|
||||
</Navbar.Brand>
|
||||
</LinkContainer>
|
||||
<Navbar.Toggle aria-controls="basic-navbar-nav"/>
|
||||
<Navbar.Collapse id="basic-navbar-nav">
|
||||
|
||||
<Nav>
|
||||
{navInfo.map((ni, idx) => {
|
||||
var element;
|
||||
if ('dest' in ni) {
|
||||
element = convertToNavLink(ni, idx);
|
||||
} else {
|
||||
element = convertToNavDropdown(ni, idx);
|
||||
}
|
||||
const out: JSX.Element[] = [];
|
||||
if (idx >= 1 ) {
|
||||
out.push( <div className="nav-item nav-item-separator" key={"nav-item-separator-"+idx}></div> );
|
||||
}
|
||||
out.push(element);
|
||||
return out;
|
||||
})}
|
||||
</Nav>
|
||||
|
||||
<div className="flex-fill-remaining-space"></div>
|
||||
|
||||
<Nav>
|
||||
<LanguagePicker />
|
||||
</Nav>
|
||||
|
||||
</Navbar.Collapse>
|
||||
</Container>
|
||||
</Navbar>
|
||||
);
|
||||
}
|
||||
|
||||
export default NavBar;
|
||||
29
client-tauri/src/components/toolbar/LanguagePicker.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
import NavDropdown from 'react-bootstrap/NavDropdown';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { BsGlobe2 } from 'react-icons/bs';
|
||||
|
||||
function generateSublist() {
|
||||
const { i18n } = useTranslation();
|
||||
const out: JSX.Element[] = [];
|
||||
const languages = i18n.options.resources;
|
||||
for (var key in languages) {
|
||||
const lang: any = languages[key].translation;
|
||||
const staticKey = key;
|
||||
out.push((
|
||||
<NavDropdown.Item key={"language-"+key} className="nav-icon" onClick={()=>i18n.changeLanguage(staticKey)}>
|
||||
<span>{lang.language?.flag}</span>
|
||||
<span>{lang.language?.name}</span>
|
||||
</NavDropdown.Item>
|
||||
));
|
||||
}
|
||||
return <>{out}</>;
|
||||
}
|
||||
|
||||
export default function LanguagePicker() {
|
||||
return (
|
||||
<NavDropdown id="languages-dropdown" title={<><span className="nav-icon"><BsGlobe2/></span></>}>
|
||||
{generateSublist()}
|
||||
</NavDropdown>
|
||||
);
|
||||
}
|
||||
4
client-tauri/src/declarations/shared-operations.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
declare module '@stirling-pdf/shared-operations/wasm/pdfcpu/pdfcpu-wrapper-browser.js' {
|
||||
export async function oneToOne(wasmArray: any, snapshot: any): Promise<Uint8Array>;
|
||||
}
|
||||
16
client-tauri/src/general.css
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
div[lang-direction=ltr] * {
|
||||
direction: ltr;
|
||||
}
|
||||
div[lang-direction=rtl] * {
|
||||
direction: rtl;
|
||||
text-align: right;
|
||||
}
|
||||
.ignore-rtl {
|
||||
direction: ltr !important;
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
.flex-fill-remaining-space {
|
||||
flex-grow: 10000000;
|
||||
}
|
||||
110
client-tauri/src/index.css
Normal file
@@ -0,0 +1,110 @@
|
||||
/*:root {
|
||||
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
font-weight: 400;
|
||||
|
||||
color: #0f0f0f;
|
||||
background-color: #f6f6f6;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin: 0;
|
||||
padding-top: 10vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 6em;
|
||||
padding: 1.5em;
|
||||
will-change: filter;
|
||||
transition: 0.75s;
|
||||
}
|
||||
|
||||
.logo.tauri:hover {
|
||||
filter: drop-shadow(0 0 2em #24c8db);
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
color: #0f0f0f;
|
||||
background-color: #ffffff;
|
||||
transition: border-color 0.25s;
|
||||
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
border-color: #396cd8;
|
||||
}
|
||||
button:active {
|
||||
border-color: #396cd8;
|
||||
background-color: #e8e8e8;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#greet-input {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
color: #f6f6f6;
|
||||
background-color: #2f2f2f;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #24c8db;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
color: #ffffff;
|
||||
background-color: #0f0f0f98;
|
||||
}
|
||||
button:active {
|
||||
background-color: #0f0f0f69;
|
||||
}
|
||||
}
|
||||
*/
|
||||
853
client-tauri/src/locales/ar.json
Normal file
@@ -0,0 +1,853 @@
|
||||
{
|
||||
"translation": {
|
||||
"language": {
|
||||
"name":"العربية",
|
||||
"flag": "🇸🇦",
|
||||
"direction": "rtl"
|
||||
},
|
||||
"pdfPrompt": "اختر PDF",
|
||||
"multiPdfPrompt": "اختر ملفات PDF (2+)",
|
||||
"multiPdfDropPrompt": "حدد (أو اسحب وأفلت) جميع ملفات PDF التي تحتاجها",
|
||||
"imgPrompt": "اختر صورة",
|
||||
"genericSubmit": "إرسال",
|
||||
"processTimeWarning": "تحذير: يمكن أن تستغرق هذه العملية ما يصل إلى دقيقة حسب حجم الملف",
|
||||
"pageOrderPrompt": "ترتيب الصفحات (أدخل قائمة بأرقام الصفحات مفصولة بفواصل):",
|
||||
"goToPage": "اذهب",
|
||||
"true": "\u0635\u062D\u064A\u062D",
|
||||
"false": "\u062E\u0637\u0623",
|
||||
"unknown": "\u063A\u064A\u0631 \u0645\u0639\u0631\u0648\u0641",
|
||||
"save": "\u062D\u0641\u0638",
|
||||
"close": "\u0625\u063A\u0644\u0627\u0642",
|
||||
"filesSelected": "الملفات المحددة",
|
||||
"noFavourites": "لم تتم إضافة أي مفضلات",
|
||||
"bored": "الانتظار بالملل؟",
|
||||
"alphabet": "\u0627\u0644\u0623\u0628\u062C\u062F\u064A\u0629",
|
||||
"downloadPdf": "تنزيل PDF",
|
||||
"text": "نص",
|
||||
"font": "الخط",
|
||||
"selectFillter": "- حدد -",
|
||||
"pageNum": "رقم الصفحة",
|
||||
"sizes": {
|
||||
"small": "Small",
|
||||
"medium": "Medium",
|
||||
"large": "Large",
|
||||
"x-large": "X-Large"
|
||||
},
|
||||
"error": {
|
||||
"pdfPassword": "The PDF Document is passworded and either the password was not provided or was incorrect"
|
||||
},
|
||||
"delete": "Delete",
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"welcome": "Welcome",
|
||||
"property": "Property",
|
||||
"black": "Black",
|
||||
"white": "White",
|
||||
"red": "Red",
|
||||
"green": "Green",
|
||||
"blue": "Blue",
|
||||
"custom": "Custom...",
|
||||
"changedCredsMessage": "Credentials changed!",
|
||||
"notAuthenticatedMessage": "User not authenticated.",
|
||||
"userNotFoundMessage": "User not found.",
|
||||
"incorrectPasswordMessage": "Current password is incorrect.",
|
||||
"usernameExistsMessage": "New Username already exists.",
|
||||
"navbar": {
|
||||
"convert": "تحويل",
|
||||
"security": "الأمان",
|
||||
"other": "أخرى",
|
||||
"darkmode": "الوضع الداكن",
|
||||
"pageOps": "عمليات الصفحة",
|
||||
"settings": "\u0625\u0639\u062F\u0627\u062F\u0627\u062A"
|
||||
},
|
||||
"settings": {
|
||||
"title": "\u0627\u0644\u0625\u0639\u062F\u0627\u062F\u0627\u062A",
|
||||
"update": "\u0627\u0644\u062A\u062D\u062F\u064A\u062B \u0645\u062A\u0627\u062D",
|
||||
"appVersion": "\u0625\u0635\u062F\u0627\u0631 \u0627\u0644\u062A\u0637\u0628\u064A\u0642:",
|
||||
"downloadOption": {
|
||||
"1": "\u0641\u062A\u062D \u0641\u064A \u0646\u0641\u0633 \u0627\u0644\u0646\u0627\u0641\u0630\u0629",
|
||||
"2": "\u0641\u062A\u062D \u0641\u064A \u0646\u0627\u0641\u0630\u0629 \u062C\u062F\u064A\u062F\u0629",
|
||||
"3": "\u062A\u0646\u0632\u064A\u0644 \u0627\u0644\u0645\u0644\u0641",
|
||||
"title": "\u062A\u062D\u062F\u064A\u062F \u062E\u064A\u0627\u0631 \u0627\u0644\u062A\u0646\u0632\u064A\u0644 (\u0644\u0644\u062A\u0646\u0632\u064A\u0644\u0627\u062A \u0630\u0627\u062A \u0627\u0644\u0645\u0644\u0641 \u0627\u0644\u0648\u0627\u062D\u062F \u063A\u064A\u0631 \u0627\u0644\u0645\u0636\u063A\u0648\u0637):"
|
||||
},
|
||||
"zipThreshold": "\u0645\u0644\u0641\u0627\u062A \u0645\u0636\u063A\u0648\u0637\u0629 \u0639\u0646\u062F \u062A\u062C\u0627\u0648\u0632 \u0639\u062F\u062F \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0627\u0644\u062A\u064A \u062A\u0645 \u062A\u0646\u0632\u064A\u0644\u0647\u0627",
|
||||
"signOut": "Sign Out",
|
||||
"accountSettings": "Account Settings"
|
||||
},
|
||||
"changeCreds": {
|
||||
"title": "Change Credentials",
|
||||
"header": "Update Your Account Details",
|
||||
"changeUserAndPassword": "You are using default login credentials. Please enter a new password (and username if wanted)",
|
||||
"newUsername": "New Username",
|
||||
"oldPassword": "Current Password",
|
||||
"newPassword": "New Password",
|
||||
"confirmNewPassword": "Confirm New Password",
|
||||
"submit": "Submit Changes"
|
||||
},
|
||||
"account": {
|
||||
"title": "Account Settings",
|
||||
"accountSettings": "Account Settings",
|
||||
"adminSettings": "Admin Settings - View and Add Users",
|
||||
"userControlSettings": "User Control Settings",
|
||||
"changeUsername": "Change Username",
|
||||
"password": "Confirmation Password",
|
||||
"oldPassword": "Old password",
|
||||
"newPassword": "New Password",
|
||||
"changePassword": "Change Password",
|
||||
"confirmNewPassword": "Confirm New Password",
|
||||
"signOut": "Sign Out",
|
||||
"yourApiKey": "Your API Key",
|
||||
"syncTitle": "Sync browser settings with Account",
|
||||
"settingsCompare": "Settings Comparison:",
|
||||
"property": "Property",
|
||||
"webBrowserSettings": "Web Browser Setting",
|
||||
"syncToBrowser": "Sync Account -> Browser",
|
||||
"syncToAccount": "Sync Account <- Browser"
|
||||
},
|
||||
"adminUserSettings": {
|
||||
"title": "User Control Settings",
|
||||
"header": "Admin User Control Settings",
|
||||
"admin": "Admin",
|
||||
"user": "User",
|
||||
"addUser": "Add New User",
|
||||
"roles": "Roles",
|
||||
"role": "Role",
|
||||
"actions": "Actions",
|
||||
"apiUser": "Limited API User",
|
||||
"webOnlyUser": "Web Only User",
|
||||
"forceChange": "Force user to change username/password on login",
|
||||
"submit": "Save User"
|
||||
},
|
||||
"home": {
|
||||
"desc": "متجرك الشامل المستضاف محليًا لجميع احتياجات PDF الخاصة بك.",
|
||||
"searchBar": "Search for features...",
|
||||
"viewPdf": {
|
||||
"title": "View PDF",
|
||||
"desc": "View, annotate, add text or images"
|
||||
},
|
||||
"multiTool": {
|
||||
"title": "أداة متعددة PDF",
|
||||
"desc": "دمج الصفحات وتدويرها وإعادة ترتيبها وإزالتها"
|
||||
},
|
||||
"merge": {
|
||||
"title": "دمج ملفات",
|
||||
"desc": "دمج ملفات PDF متعددة في ملف واحد بسهولة."
|
||||
},
|
||||
"split": {
|
||||
"title": "انقسام ملفات",
|
||||
"desc": "تقسيم ملفات PDF إلى مستندات متعددة"
|
||||
},
|
||||
"rotate": {
|
||||
"title": "تدوير ملفات",
|
||||
"desc": "قم بتدوير ملفات PDF الخاصة بك بسهولة."
|
||||
},
|
||||
"imageToPdf": {
|
||||
"title": "صورة إلى PDF",
|
||||
"desc": "تحويل الصور (PNG ، JPEG ، GIF) إلى PDF."
|
||||
},
|
||||
"pdfToImage": {
|
||||
"title": "تحويل PDF إلى صورة",
|
||||
"desc": "تحويل ملف PDF إلى صورة. (PNG ، JPEG ، GIF)"
|
||||
},
|
||||
"pdfOrganiser": {
|
||||
"title": "منظم",
|
||||
"desc": "إزالة / إعادة ترتيب الصفحات بأي ترتيب"
|
||||
},
|
||||
"addImage": {
|
||||
"title": "إضافة صورة إلى ملف PDF",
|
||||
"desc": "إضافة صورة إلى موقع معين في PDF (العمل قيد التقدم)"
|
||||
},
|
||||
"watermark": {
|
||||
"title": "إضافة علامة مائية",
|
||||
"desc": "أضف علامة مائية مخصصة إلى مستند PDF الخاص بك."
|
||||
},
|
||||
"permissions": {
|
||||
"title": "تغيير الأذونات",
|
||||
"desc": "قم بتغيير أذونات مستند PDF الخاص بك"
|
||||
},
|
||||
"removePages": {
|
||||
"title": "إزالة الصفحات",
|
||||
"desc": "حذف الصفحات غير المرغوب فيها من مستند PDF الخاص بك."
|
||||
},
|
||||
"addPassword": {
|
||||
"title": "إضافة كلمة مرور",
|
||||
"desc": "تشفير مستند PDF الخاص بك بكلمة مرور."
|
||||
},
|
||||
"removePassword": {
|
||||
"title": "إزالة كلمة المرور",
|
||||
"desc": "إزالة الحماية بكلمة مرور من مستند PDF الخاص بك."
|
||||
},
|
||||
"compressPdfs": {
|
||||
"title": "ضغط ملفات",
|
||||
"desc": "ضغط ملفات PDF لتقليل حجم الملف."
|
||||
},
|
||||
"changeMetadata": {
|
||||
"title": "\u062A\u063A\u064A\u064A\u0631 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0648\u0635\u0641\u064A\u0629",
|
||||
"desc": "\u062A\u063A\u064A\u064A\u0631 / \u0625\u0632\u0627\u0644\u0629 / \u0625\u0636\u0627\u0641\u0629 \u0628\u064A\u0627\u0646\u0627\u062A \u0623\u0648\u0644\u064A\u0629 \u0645\u0646 \u0645\u0633\u062A\u0646\u062F PDF"
|
||||
},
|
||||
"fileToPDF": {
|
||||
"title": "\u062A\u062D\u0648\u064A\u0644 \u0627\u0644\u0645\u0644\u0641 \u0625\u0644\u0649 PDF",
|
||||
"desc": "\u062A\u062D\u0648\u064A\u0644 \u0623\u064A \u0645\u0644\u0641 \u062A\u0642\u0631\u064A\u0628\u0627 \u0625\u0644\u0649 PDF (DOCX \u0648PNG \u0648XLS \u0648PPT \u0648TXT \u0648\u0627\u0644\u0645\u0632\u064A\u062F)"
|
||||
},
|
||||
"ocr": {
|
||||
"title": "\u062A\u0634\u063A\u064A\u0644 OCR \u0639\u0644\u0649 PDF \u0648 / \u0623\u0648 \u0645\u0633\u062D \u0636\u0648\u0626\u064A",
|
||||
"desc": "\u064A\u0642\u0648\u0645 \u0628\u0631\u0646\u0627\u0645\u062C \u0627\u0644\u062A\u0646\u0638\u064A\u0641 \u0628\u0645\u0633\u062D \u0648\u0627\u0643\u062A\u0634\u0627\u0641 \u0627\u0644\u0646\u0635 \u0645\u0646 \u0627\u0644\u0635\u0648\u0631 \u062F\u0627\u062E\u0644 \u0645\u0644\u0641 PDF \u0648\u064A\u0639\u064A\u062F \u0625\u0636\u0627\u0641\u062A\u0647 \u0643\u0646\u0635"
|
||||
},
|
||||
"extractImages": {
|
||||
"title": "\u0627\u0633\u062A\u062E\u0631\u0627\u062C \u0627\u0644\u0635\u0648\u0631",
|
||||
"desc": "\u064A\u0633\u062A\u062E\u0631\u062C \u062C\u0645\u064A\u0639 \u0627\u0644\u0635\u0648\u0631 \u0645\u0646 \u0645\u0644\u0641 PDF \u0648\u064A\u062D\u0641\u0638\u0647\u0627 \u0641\u064A \u0627\u0644\u0631\u0645\u0632 \u0627\u0644\u0628\u0631\u064A\u062F\u064A"
|
||||
},
|
||||
"pdfToPDFA": {
|
||||
"title": "\u062A\u062D\u0648\u064A\u0644 \u0645\u0644\u0641\u0627\u062A PDF \u0625\u0644\u0649 PDF / A",
|
||||
"desc": "\u062A\u062D\u0648\u064A\u0644 PDF \u0625\u0644\u0649 PDF / A \u0644\u0644\u062A\u062E\u0632\u064A\u0646 \u0637\u0648\u064A\u0644 \u0627\u0644\u0645\u062F\u0649"
|
||||
},
|
||||
"PDFToWord": {
|
||||
"title": "تحويل PDF إلى Word",
|
||||
"desc": "تحويل PDF إلى تنسيقات Word (DOC و DOCX و ODT)"
|
||||
},
|
||||
"PDFToPresentation": {
|
||||
"title": "PDF للعرض التقديمي",
|
||||
"desc": "تحويل PDF إلى تنسيقات عرض تقديمي (PPT و PPTX و ODP)"
|
||||
},
|
||||
"PDFToText": {
|
||||
"title": "تحويل PDF إلى نص / RTF",
|
||||
"desc": "تحويل PDF إلى تنسيق نص أو RTF"
|
||||
},
|
||||
"PDFToHTML": {
|
||||
"title": "تحويل PDF إلى HTML",
|
||||
"desc": "تحويل PDF إلى تنسيق HTML"
|
||||
},
|
||||
"PDFToXML": {
|
||||
"title": "تحويل PDF إلى XML",
|
||||
"desc": "تحويل PDF إلى تنسيق XML"
|
||||
},
|
||||
"ScannerImageSplit": {
|
||||
"title": "كشف / انقسام الصور الممسوحة ضوئيًا",
|
||||
"desc": "تقسيم عدة صور من داخل صورة / ملف PDF"
|
||||
},
|
||||
"sign": {
|
||||
"title": "تسجيل الدخول",
|
||||
"desc": "إضافة التوقيع إلى PDF عن طريق الرسم أو النص أو الصورة"
|
||||
},
|
||||
"flatten": {
|
||||
"title": "تسطيح",
|
||||
"desc": "قم بإزالة كافة العناصر والنماذج التفاعلية من ملف PDF"
|
||||
},
|
||||
"repair": {
|
||||
"title": "إصلاح",
|
||||
"desc": "يحاول إصلاح ملف PDF تالف / معطل"
|
||||
},
|
||||
"removeBlanks": {
|
||||
"title": "إزالة الصفحات الفارغة",
|
||||
"desc": "يكتشف ويزيل الصفحات الفارغة من المستند"
|
||||
},
|
||||
"compare": {
|
||||
"title": "قارن",
|
||||
"desc": "يقارن ويظهر الاختلافات بين 2 من مستندات PDF"
|
||||
},
|
||||
"certSign": {
|
||||
"title": "Sign with Certificate",
|
||||
"desc": "Signs a PDF with a Certificate/Key (PEM/P12)"
|
||||
},
|
||||
"pageLayout": {
|
||||
"title": "Multi-Page Layout",
|
||||
"desc": "Merge multiple pages of a PDF document into a single page"
|
||||
},
|
||||
"scalePages": {
|
||||
"title": "Adjust page size/scale",
|
||||
"desc": "Change the size/scale of page and/or its contents."
|
||||
},
|
||||
"pipeline": {
|
||||
"title": "Pipeline (Advanced)",
|
||||
"desc": "Run multiple actions on PDFs by defining pipeline scripts"
|
||||
},
|
||||
"add-page-numbers": {
|
||||
"title": "Add Page Numbers",
|
||||
"desc": "Add Page numbers throughout a document in a set location"
|
||||
},
|
||||
"auto-rename": {
|
||||
"title": "Auto Rename PDF File",
|
||||
"desc": "Auto renames a PDF file based on its detected header"
|
||||
},
|
||||
"adjust-contrast": {
|
||||
"title": "Adjust Colors/Contrast",
|
||||
"desc": "Adjust Contrast, Saturation and Brightness of a PDF"
|
||||
},
|
||||
"crop": {
|
||||
"title": "Crop PDF",
|
||||
"desc": "Crop a PDF to reduce its size (maintains text!)"
|
||||
},
|
||||
"autoSplitPDF": {
|
||||
"title": "Auto Split Pages",
|
||||
"desc": "Auto Split Scanned PDF with physical scanned page splitter QR Code"
|
||||
},
|
||||
"sanitizePdf": {
|
||||
"title": "Sanitize",
|
||||
"desc": "Remove scripts and other elements from PDF files"
|
||||
},
|
||||
"URLToPDF": {
|
||||
"title": "URL/Website To PDF",
|
||||
"desc": "Converts any http(s)URL to PDF"
|
||||
},
|
||||
"HTMLToPDF": {
|
||||
"title": "HTML to PDF",
|
||||
"desc": "Converts any HTML file or zip to PDF"
|
||||
},
|
||||
"MarkdownToPDF": {
|
||||
"title": "Markdown to PDF",
|
||||
"desc": "Converts any Markdown file to PDF"
|
||||
},
|
||||
"getPdfInfo": {
|
||||
"title": "Get ALL Info on PDF",
|
||||
"desc": "Grabs any and all information possible on PDFs"
|
||||
},
|
||||
"extractPage": {
|
||||
"title": "Extract page(s)",
|
||||
"desc": "Extracts select pages from PDF"
|
||||
},
|
||||
"PdfToSinglePage": {
|
||||
"title": "PDF to Single Large Page",
|
||||
"desc": "Merges all PDF pages into one large single page"
|
||||
},
|
||||
"showJS": {
|
||||
"title": "Show Javascript",
|
||||
"desc": "Searches and displays any JS injected into a PDF"
|
||||
},
|
||||
"autoRedact": {
|
||||
"title": "Auto Redact",
|
||||
"desc": "Auto Redacts(Blacks out) text in a PDF based on input text"
|
||||
}
|
||||
},
|
||||
"viewPdf": {
|
||||
"tags": "view,read,annotate,text,image",
|
||||
"title": "View PDF",
|
||||
"header": "View PDF"
|
||||
},
|
||||
"multiTool": {
|
||||
"tags": "Multi Tool,Multi operation,UI,click drag,front end,client side",
|
||||
"title": "أداة متعددة PDF",
|
||||
"header": "أداة متعددة PDF"
|
||||
},
|
||||
"merge": {
|
||||
"tags": "merge,Page operations,Back end,server side",
|
||||
"title": "دمج",
|
||||
"header": "دمج ملفات PDF متعددة (2+)",
|
||||
"sortByName": "Sort by name",
|
||||
"sortByDate": "Sort by date",
|
||||
"submit": "دمج"
|
||||
},
|
||||
"split": {
|
||||
"tags": "Page operations,divide,Multi Page,cut,server side",
|
||||
"title": "انقسام PDF",
|
||||
"header": "تقسيم PDF",
|
||||
"desc": {
|
||||
"1": "الأرقام التي تحددها هي رقم الصفحة التي تريد تقسيمها",
|
||||
"2": "على هذا النحو ، سيؤدي تحديد 1،3،7-8 إلى تقسيم مستند من 10 صفحات إلى 6 PDFS منفصلة مع:",
|
||||
"3": "المستند رقم 1: الصفحة 1",
|
||||
"4": "المستند رقم 2: الصفحتان 2 و 3",
|
||||
"5": "المستند رقم 3: الصفحة 4 و 5 و 6",
|
||||
"6": "المستند رقم 4: الصفحة 7",
|
||||
"7": "المستند رقم 5: الصفحة 8",
|
||||
"8": "المستند رقم 6: الصفحتان 9 و 10"
|
||||
},
|
||||
"splitPages": "أدخل الصفحات المراد تقسيمها:",
|
||||
"submit": "Split"
|
||||
},
|
||||
"rotate": {
|
||||
"tags": "server side",
|
||||
"title": "تدوير PDF",
|
||||
"header": "تدوير PDF",
|
||||
"selectAngle": "حدد زاوية الدوران (بمضاعفات 90 درجة):",
|
||||
"submit": "استدارة"
|
||||
},
|
||||
"imageToPdf": {
|
||||
"tags": "conversion,img,jpg,picture,photo"
|
||||
},
|
||||
"pdfToImage": {
|
||||
"tags": "conversion,img,jpg,picture,photo",
|
||||
"title": "تحويل PDF إلى صورة",
|
||||
"header": "تحويل PDF إلى صورة",
|
||||
"selectText": "تنسيق الصورة",
|
||||
"singleOrMultiple": "\u0646\u0648\u0639 \u0646\u062A\u064A\u062C\u0629 \u0627\u0644\u0635\u0648\u0631\u0629",
|
||||
"single": "\u0635\u0648\u0631\u0629 \u0648\u0627\u062D\u062F\u0629 \u0643\u0628\u064A\u0631\u0629",
|
||||
"multi": "\u0635\u0648\u0631 \u0645\u062A\u0639\u062F\u062F\u0629",
|
||||
"colorType": "\u0646\u0648\u0639 \u0627\u0644\u0644\u0648\u0646",
|
||||
"color": "\u0627\u0644\u0644\u0648\u0646",
|
||||
"grey": "\u062A\u062F\u0631\u062C \u0627\u0644\u0631\u0645\u0627\u062F\u064A",
|
||||
"blackwhite": "\u0623\u0628\u064A\u0636 \u0648\u0623\u0633\u0648\u062F (\u0642\u062F \u064A\u0641\u0642\u062F \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A!)",
|
||||
"submit": "تحول"
|
||||
},
|
||||
"pdfOrganiser": {
|
||||
"tags": "duplex,even,odd,sort,move",
|
||||
"title": "منظم الصفحة",
|
||||
"header": "منظم صفحات PDF",
|
||||
"submit": "إعادة ترتيب الصفحات"
|
||||
},
|
||||
"addImage": {
|
||||
"tags": "img,jpg,picture,photo",
|
||||
"title": "إضافة صورة",
|
||||
"header": "إضافة صورة إلى PDF",
|
||||
"everyPage": "كل صفحة؟",
|
||||
"upload": "إضافة صورة",
|
||||
"submit": "إضافة صورة"
|
||||
},
|
||||
"watermark": {
|
||||
"tags": "Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo",
|
||||
"title": "إضافة علامة مائية",
|
||||
"header": "إضافة علامة مائية",
|
||||
"selectText": {
|
||||
"1": "حدد PDF لإضافة العلامة المائية إلى:",
|
||||
"2": "نص العلامة المائية:",
|
||||
"3": "حجم الخط:",
|
||||
"4": "دوران (0-360):",
|
||||
"5": "widthSpacer (مسافة بين كل علامة مائية أفقيًا):",
|
||||
"6": "heightSpacer (مسافة بين كل علامة مائية عموديًا):",
|
||||
"7": "\u0627\u0644\u062A\u0639\u062A\u064A\u0645 (0\u066A - 100\u066A):",
|
||||
"8": "Watermark Type:",
|
||||
"9": "Watermark Image:"
|
||||
},
|
||||
"submit": "إضافة علامة مائية"
|
||||
},
|
||||
"permissions": {
|
||||
"tags": "read,write,edit,print",
|
||||
"title": "تغيير الأذونات",
|
||||
"header": "تغيير الأذونات",
|
||||
"warning": "تحذير من أن تكون هذه الأذونات غير قابلة للتغيير ، يوصى بتعيينها بكلمة مرور عبر صفحة إضافة كلمة المرور",
|
||||
"selectText": {
|
||||
"1": "حدد ملف PDF لتغيير الأذونات",
|
||||
"2": "أذونات لتعيينها",
|
||||
"3": "منع تجميع المستند",
|
||||
"4": "منع استخراج المحتوى",
|
||||
"5": "منع الاستخراج للوصول",
|
||||
"6": "منع ملء النموذج",
|
||||
"7": "منع التعديل",
|
||||
"8": "منع تعديل التعليق التوضيحي",
|
||||
"9": "منع الطباعة",
|
||||
"10": "منع طباعة التنسيقات المختلفة"
|
||||
},
|
||||
"submit": "تغيير"
|
||||
},
|
||||
"removePages": {
|
||||
"tags": "Remove pages,delete pages"
|
||||
},
|
||||
"addPassword": {
|
||||
"tags": "secure,security",
|
||||
"title": "إضافة كلمة مرور",
|
||||
"header": "إضافة كلمة مرور (تشفير)",
|
||||
"selectText": {
|
||||
"1": "حدد ملف PDF للتشفير",
|
||||
"2": "كلمة المرور",
|
||||
"3": "طول مفتاح التشفير",
|
||||
"4": "القيم الأعلى تكون أقوى ، لكن القيم الأقل لها توافق أفضل.",
|
||||
"5": "أذونات للتعيين",
|
||||
"6": "منع تجميع المستند",
|
||||
"7": "منع استخراج المحتوى",
|
||||
"8": "منع الاستخراج للوصول",
|
||||
"9": "منع ملء النموذج",
|
||||
"10": "منع التعديل",
|
||||
"11": "منع تعديل التعليقات التوضيحية",
|
||||
"12": "منع الطباعة",
|
||||
"13": "منع طباعة تنسيقات مختلفة",
|
||||
"14": "Owner Password",
|
||||
"15": "Restricts what can be done with the document once it is opened (Not supported by all readers)",
|
||||
"16": "Restricts the opening of the document itself"
|
||||
},
|
||||
"submit": "تشفير"
|
||||
},
|
||||
"removePassword": {
|
||||
"tags": "secure,Decrypt,security,unpassword,delete password",
|
||||
"title": "إزالة كلمة المرور",
|
||||
"header": "إزالة كلمة المرور (فك التشفير)",
|
||||
"selectText": {
|
||||
"1": "حدد PDF لفك التشفير",
|
||||
"2": "كلمة المرور"
|
||||
},
|
||||
"submit": "إزالة"
|
||||
},
|
||||
"compressPdfs": {
|
||||
"tags": "squish,small,tiny"
|
||||
},
|
||||
"fileToPDF": {
|
||||
"tags": "transformation,format,document,picture,slide,text,conversion,office,docs,word,excel,powerpoint",
|
||||
"title": "\u0645\u0644\u0641 \u0625\u0644\u0649 PDF",
|
||||
"header": "\u062A\u062D\u0648\u064A\u0644 \u0623\u064A \u0645\u0644\u0641 \u0625\u0644\u0649 PDF",
|
||||
"credit": "\u062A\u0633\u062A\u062E\u062F\u0645 \u0647\u0630\u0647 \u0627\u0644\u062E\u062F\u0645\u0629 \u0644\u064A\u0628\u0631 \u0623\u0648\u0641\u064A\u0633 \u0648\u0623\u0648\u0646\u0648\u0643\u0648\u0646\u0641 \u0644\u062A\u062D\u0648\u064A\u0644 \u0627\u0644\u0645\u0644\u0641\u0627\u062A.",
|
||||
"supportedFileTypes": "\u064A\u062C\u0628 \u0623\u0646 \u062A\u062A\u0636\u0645\u0646 \u0623\u0646\u0648\u0627\u0639 \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0627\u0644\u0645\u062F\u0639\u0648\u0645\u0629 \u0645\u0627 \u064A\u0644\u064A \u0648\u0644\u0643\u0646 \u0644\u0644\u062D\u0635\u0648\u0644 \u0639\u0644\u0649 \u0642\u0627\u0626\u0645\u0629 \u0645\u062D\u062F\u062B\u0629 \u0643\u0627\u0645\u0644\u0629 \u0628\u0627\u0644\u062A\u0646\u0633\u064A\u0642\u0627\u062A \u0627\u0644\u0645\u062F\u0639\u0648\u0645\u0629 \u060C \u064A\u0631\u062C\u0649 \u0627\u0644\u0631\u062C\u0648\u0639 \u0625\u0644\u0649 \u0648\u062B\u0627\u0626\u0642 LibreOffice",
|
||||
"submit": "\u062A\u062D\u0648\u064A\u0644 \u0625\u0644\u0649 PDF"
|
||||
},
|
||||
"ocr": {
|
||||
"tags": "recognition,text,image,scan,read,identify,detection,editable",
|
||||
"title": "\u0627\u0644\u062A\u0639\u0631\u0641 \u0627\u0644\u0636\u0648\u0626\u064A \u0639\u0644\u0649 \u0627\u0644\u062D\u0631\u0648\u0641 / \u062A\u0646\u0638\u064A\u0641 \u0627\u0644\u0645\u0633\u062D \u0627\u0644\u0636\u0648\u0626\u064A",
|
||||
"header": "\u0645\u0633\u062D \u0627\u0644\u0645\u0633\u062D \u0627\u0644\u0636\u0648\u0626\u064A / \u0627\u0644\u062A\u0639\u0631\u0641 \u0627\u0644\u0636\u0648\u0626\u064A \u0639\u0644\u0649 \u0627\u0644\u062D\u0631\u0648\u0641 (\u0627\u0644\u062A\u0639\u0631\u0641 \u0627\u0644\u0636\u0648\u0626\u064A \u0639\u0644\u0649 \u0627\u0644\u062D\u0631\u0648\u0641)",
|
||||
"selectText": {
|
||||
"1": "\u062D\u062F\u062F \u0627\u0644\u0644\u063A\u0627\u062A \u0627\u0644\u062A\u064A \u0633\u064A\u062A\u0645 \u0627\u0643\u062A\u0634\u0627\u0641\u0647\u0627 \u062F\u0627\u062E\u0644 \u0645\u0644\u0641 PDF (\u0627\u0644\u0644\u063A\u0627\u062A \u0627\u0644\u0645\u062F\u0631\u062C\u0629 \u0647\u064A \u062A\u0644\u0643 \u0627\u0644\u062A\u064A \u062A\u0645 \u0627\u0643\u062A\u0634\u0627\u0641\u0647\u0627 \u062D\u0627\u0644\u064A\u064B\u0627):",
|
||||
"2": "\u0625\u0646\u062A\u0627\u062C \u0645\u0644\u0641 \u0646\u0635\u064A \u064A\u062D\u062A\u0648\u064A \u0639\u0644\u0649 \u0646\u0635 OCR \u0628\u062C\u0627\u0646\u0628 \u0645\u0644\u0641 PDF \u0627\u0644\u0630\u064A \u062A\u0645 \u0625\u0639\u062F\u0627\u062F\u0647 \u0628\u0648\u0627\u0633\u0637\u0629 OCR",
|
||||
"3": "\u062A\u0645 \u0645\u0633\u062D \u0627\u0644\u0635\u0641\u062D\u0627\u062A \u0627\u0644\u0635\u062D\u064A\u062D\u0629 \u0636\u0648\u0626\u064A\u064B\u0627 \u0628\u0632\u0627\u0648\u064A\u0629 \u0645\u0646\u062D\u0631\u0641\u0629 \u0639\u0646 \u0637\u0631\u064A\u0642 \u062A\u062F\u0648\u064A\u0631\u0647\u0627 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649 \u0641\u064A \u0645\u0643\u0627\u0646\u0647\u0627",
|
||||
"4": "\u0635\u0641\u062D\u0629 \u0646\u0638\u064A\u0641\u0629 \u0644\u0630\u0644\u0643 \u0645\u0646 \u063A\u064A\u0631 \u0627\u0644\u0645\u062D\u062A\u0645\u0644 \u0623\u0646 \u064A\u062C\u062F OCR \u0646\u0635\u064B\u0627 \u0641\u064A \u0636\u0648\u0636\u0627\u0621 \u0627\u0644\u062E\u0644\u0641\u064A\u0629. (\u0644\u0627 \u064A\u0648\u062C\u062F \u062A\u063A\u064A\u064A\u0631 \u0641\u064A \u0627\u0644\u0625\u062E\u0631\u0627\u062C)",
|
||||
"5": "\u0635\u0641\u062D\u0629 \u0646\u0638\u064A\u0641\u0629 \u060C \u0644\u0630\u0644\u0643 \u0645\u0646 \u063A\u064A\u0631 \u0627\u0644\u0645\u062D\u062A\u0645\u0644 \u0623\u0646 \u064A\u062C\u062F OCR \u0646\u0635\u064B\u0627 \u0641\u064A \u0636\u0648\u0636\u0627\u0621 \u0627\u0644\u062E\u0644\u0641\u064A\u0629 \u060C \u0648\u064A\u062D\u0627\u0641\u0638 \u0639\u0644\u0649 \u0627\u0644\u062A\u0646\u0638\u064A\u0641 \u0641\u064A \u0627\u0644\u0625\u062E\u0631\u0627\u062C.",
|
||||
"6": "\u064A\u062A\u062C\u0627\u0647\u0644 \u0627\u0644\u0635\u0641\u062D\u0627\u062A \u0627\u0644\u062A\u064A \u062A\u062D\u062A\u0648\u064A \u0639\u0644\u0649 \u0646\u0635 \u062A\u0641\u0627\u0639\u0644\u064A \u060C \u0641\u0642\u0637 \u0635\u0641\u062D\u0627\u062A OCRs \u0627\u0644\u062A\u064A \u0647\u064A \u0635\u0648\u0631",
|
||||
"7": "\u0641\u0631\u0636 \u0627\u0644\u062A\u0639\u0631\u0641 \u0627\u0644\u0636\u0648\u0626\u064A \u0639\u0644\u0649 \u0627\u0644\u062D\u0631\u0648\u0641 \u060C \u0633\u064A\u0624\u062F\u064A \u0627\u0644\u062A\u0639\u0631\u0641 \u0627\u0644\u0636\u0648\u0626\u064A \u0639\u0644\u0649 \u0627\u0644\u062D\u0631\u0648\u0641 \u0639\u0644\u0649 \u0643\u0644 \u0635\u0641\u062D\u0629 \u0625\u0644\u0649 \u0625\u0632\u0627\u0644\u0629 \u062C\u0645\u064A\u0639 \u0639\u0646\u0627\u0635\u0631 \u0627\u0644\u0646\u0635 \u0627\u0644\u0623\u0635\u0644\u064A",
|
||||
"8": "\u0639\u0627\u062F\u064A (\u062E\u0637\u0623 \u0625\u0630\u0627 \u0643\u0627\u0646 PDF \u064A\u062D\u062A\u0648\u064A \u0639\u0644\u0649 \u0646\u0635)",
|
||||
"9": "\u0625\u0639\u062F\u0627\u062F\u0627\u062A \u0625\u0636\u0627\u0641\u064A\u0629",
|
||||
"10": "\u0648\u0636\u0639 \u0627\u0644\u062A\u0639\u0631\u0641 \u0627\u0644\u0636\u0648\u0626\u064A \u0639\u0644\u0649 \u0627\u0644\u062D\u0631\u0648\u0641",
|
||||
"11": "إزالة الصور بعد التعرف الضوئي على الحروف (يزيل كل الصور ، يكون مفيدًا فقط إذا كان جزءًا من خطوة التحويل)",
|
||||
"12": "نوع العرض (متقدم)"
|
||||
},
|
||||
"help": "\u064A\u0631\u062C\u0649 \u0642\u0631\u0627\u0621\u0629 \u0647\u0630\u0647 \u0627\u0644\u0648\u062B\u0627\u0626\u0642 \u062D\u0648\u0644 \u0643\u064A\u0641\u064A\u0629 \u0627\u0633\u062A\u062E\u062F\u0627\u0645 \u0647\u0630\u0627 \u0644\u0644\u063A\u0627\u062A \u0623\u062E\u0631\u0649 \u0648 / \u0623\u0648 \u0627\u0644\u0627\u0633\u062A\u062E\u062F\u0627\u0645 \u0644\u064A\u0633 \u0641\u064A \u0639\u0627\u0645\u0644 \u0627\u0644\u0625\u0631\u0633\u0627\u0621",
|
||||
"credit": "\u062A\u0633\u062A\u062E\u062F\u0645 \u0647\u0630\u0647 \u0627\u0644\u062E\u062F\u0645\u0629 OCRmyPDF \u0648 Tesseract \u0644 OCR.",
|
||||
"submit": "\u0645\u0639\u0627\u0644\u062C\u0629 PDF \u0628\u0627\u0633\u062A\u062E\u062F\u0627\u0645 OCR"
|
||||
},
|
||||
"extractImages": {
|
||||
"tags": "picture,photo,save,archive,zip,capture,grab",
|
||||
"title": "\u0627\u0633\u062A\u062E\u0631\u0627\u062C \u0627\u0644\u0635\u0648\u0631",
|
||||
"header": "\u0627\u0633\u062A\u062E\u0631\u0627\u062C \u0627\u0644\u0635\u0648\u0631",
|
||||
"selectText": "\u062D\u062F\u062F \u062A\u0646\u0633\u064A\u0642 \u0627\u0644\u0635\u0648\u0631\u0629 \u0644\u062A\u062D\u0648\u064A\u0644 \u0627\u0644\u0635\u0648\u0631 \u0627\u0644\u0645\u0633\u062A\u062E\u0631\u062C\u0629 \u0625\u0644\u0649",
|
||||
"submit": "\u0627\u0633\u062A\u062E\u0631\u0627\u062C"
|
||||
},
|
||||
"pdfToPDFA": {
|
||||
"tags": "archive,long-term,standard,conversion,storage,preservation",
|
||||
"title": "PDF \u0625\u0644\u0649 PDF / A",
|
||||
"header": "PDF \u0625\u0644\u0649 PDF / A",
|
||||
"credit": "\u062A\u0633\u062A\u062E\u062F\u0645 \u0647\u0630\u0647 \u0627\u0644\u062E\u062F\u0645\u0629 OCRmyPDF \u0644\u062A\u062D\u0648\u064A\u0644 PDF / A.",
|
||||
"submit": "\u062A\u062D\u0648\u064A\u0644"
|
||||
},
|
||||
"PDFToWord": {
|
||||
"tags": "doc,docx,odt,word,transformation,format,conversion,office,microsoft,docfile",
|
||||
"title": "تحويل PDF إلى Word",
|
||||
"header": "تحويل PDF إلى Word",
|
||||
"selectText": {
|
||||
"1": "تنسيق ملف الإخراج"
|
||||
},
|
||||
"credit": "تستخدم هذه الخدمة LibreOffice لتحويل الملفات.",
|
||||
"submit": "تحويل"
|
||||
},
|
||||
"PDFToPresentation": {
|
||||
"tags": "slides,show,office,microsoft",
|
||||
"title": "PDF للعرض التقديمي",
|
||||
"header": "PDF للعرض التقديمي",
|
||||
"selectText": {
|
||||
"1": "تنسيق ملف الإخراج"
|
||||
},
|
||||
"credit": "تستخدم هذه الخدمة LibreOffice لتحويل الملف.",
|
||||
"submit": "تحويل"
|
||||
},
|
||||
"PDFToText": {
|
||||
"tags": "richformat,richtextformat,rich text format",
|
||||
"title": "تحويل PDF إلى نص / RTF",
|
||||
"header": "تحويل PDF إلى نص / RTF",
|
||||
"selectText": {
|
||||
"1": "تنسيق ملف الإخراج"
|
||||
},
|
||||
"credit": "تستخدم هذه الخدمة LibreOffice لتحويل الملفات.",
|
||||
"submit": "تحويل"
|
||||
},
|
||||
"PDFToHTML": {
|
||||
"tags": "web content,browser friendly",
|
||||
"title": "PDF إلى HTML",
|
||||
"header": "PDF إلى HTML",
|
||||
"credit": "تستخدم هذه الخدمة LibreOffice لتحويل الملفات.",
|
||||
"submit": "تحويل"
|
||||
},
|
||||
"PDFToXML": {
|
||||
"tags": "data-extraction,structured-content,interop,transformation,convert",
|
||||
"title": "تحويل PDF إلى XML",
|
||||
"header": "تحويل PDF إلى XML",
|
||||
"credit": "تستخدم هذه الخدمة LibreOffice لتحويل الملفات.",
|
||||
"submit": "تحويل"
|
||||
},
|
||||
"ScannerImageSplit": {
|
||||
"tags": "separate,auto-detect,scans,multi-photo,organize",
|
||||
"selectText": {
|
||||
"1": "عتبة الزاوية:",
|
||||
"2": "تعيين الحد الأدنى للزاوية المطلقة المطلوبة لتدوير الصورة (افتراضي: 10).",
|
||||
"3": "التسامح:",
|
||||
"4": "يحدد نطاق تباين اللون حول لون الخلفية المقدر (الافتراضي: 30).",
|
||||
"5": "أدنى مساحة:",
|
||||
"6": "تعيين الحد الأدنى لمنطقة الصورة (الافتراضي: 10000).",
|
||||
"7": "الحد الأدنى لمنطقة المحيط:",
|
||||
"8": "تعيين الحد الأدنى لمنطقة المحيط للصورة",
|
||||
"9": "حجم الحدود:",
|
||||
"10": "يضبط حجم الحدود المضافة والمزالة لمنع الحدود البيضاء في الإخراج (الافتراضي: 1)."
|
||||
}
|
||||
},
|
||||
"sign": {
|
||||
"tags": "authorize,initials,drawn-signature,text-sign,image-signature",
|
||||
"title": "تسجيل الدخول",
|
||||
"header": "توقيع ملفات PDF",
|
||||
"upload": "تحميل الصورة",
|
||||
"draw": "رسم التوقيع",
|
||||
"text": "Text Input",
|
||||
"clear": "واضح",
|
||||
"add": "إضافة"
|
||||
},
|
||||
"flatten": {
|
||||
"tags": "static,deactivate,non-interactive,streamline",
|
||||
"title": "تسطيح",
|
||||
"header": "تسوية ملفات PDF",
|
||||
"submit": "تسطيح"
|
||||
},
|
||||
"repair": {
|
||||
"tags": "fix,restore,correction,recover",
|
||||
"title": "إصلاح",
|
||||
"header": "إصلاح ملفات PDF",
|
||||
"submit": "الإصلاح"
|
||||
},
|
||||
"removeBlanks": {
|
||||
"tags": "cleanup,streamline,non-content,organize",
|
||||
"title": "إزالة الفراغات",
|
||||
"header": "إزالة الصفحات الفارغة",
|
||||
"threshold": "العتبة:",
|
||||
"thresholdDesc": "الحد الفاصل لتحديد مدى بياض البكسل الأبيض",
|
||||
"whitePercent": "نسبة الأبيض (٪):",
|
||||
"whitePercentDesc": "النسبة المئوية للصفحة التي يجب أن تكون بيضاء لتتم إزالتها",
|
||||
"submit": "إزالة الفراغات"
|
||||
},
|
||||
"compare": {
|
||||
"tags": "differentiate,contrast,changes,analysis",
|
||||
"title": "يقارن",
|
||||
"header": "قارن ملفات PDF",
|
||||
"document": {
|
||||
"1": "المستند 1",
|
||||
"2": "المستند 2"
|
||||
},
|
||||
"submit": "يقارن"
|
||||
},
|
||||
"certSign": {
|
||||
"tags": "authenticate,PEM,P12,official,encrypt",
|
||||
"title": "توقيع الشهادة",
|
||||
"header": "قم بتوقيع ملف PDF بشهادتك (العمل قيد التقدم)",
|
||||
"selectPDF": "حدد ملف PDF للتوقيع:",
|
||||
"selectKey": "حدد ملف المفتاح الخاص (تنسيق PKCS ",
|
||||
"selectCert": "حدد ملف الشهادة الخاص بك (تنسيق X.509 ، يمكن أن يكون .pem أو .der):",
|
||||
"selectP12": "حدد ملف تخزين المفاتيح PKCS ",
|
||||
"certType": "نوع الشهادة",
|
||||
"password": "أدخل ملف تخزين المفاتيح أو كلمة المرور الخاصة (إن وجدت):",
|
||||
"showSig": "إظهار التوقيع",
|
||||
"reason": "السبب",
|
||||
"location": "الموقع",
|
||||
"name": "الاسم",
|
||||
"submit": "تسجيل PDF"
|
||||
},
|
||||
"pageLayout": {
|
||||
"tags": "merge,composite,single-view,organize",
|
||||
"title": "Multi Page Layout",
|
||||
"header": "Multi Page Layout",
|
||||
"pagesPerSheet": "Pages per sheet:",
|
||||
"addBorder": "Add Borders",
|
||||
"submit": "Submit"
|
||||
},
|
||||
"scalePages": {
|
||||
"tags": "resize,modify,dimension,adapt",
|
||||
"title": "Adjust page-scale",
|
||||
"header": "Adjust page-scale",
|
||||
"pageSize": "Size of a page of the document.",
|
||||
"scaleFactor": "Zoom level (crop) of a page.",
|
||||
"submit": "Submit"
|
||||
},
|
||||
"pipeline": {
|
||||
"tags": "automate,sequence,scripted,batch-process",
|
||||
"title": "Pipeline"
|
||||
},
|
||||
"add-page-numbers": {
|
||||
"tags": "paginate,label,organize,index"
|
||||
},
|
||||
"auto-rename": {
|
||||
"tags": "auto-detect,header-based,organize,relabel",
|
||||
"title": "Auto Rename",
|
||||
"header": "Auto Rename PDF",
|
||||
"submit": "Auto Rename"
|
||||
},
|
||||
"adjust-contrast": {
|
||||
"tags": "color-correction,tune,modify,enhance"
|
||||
},
|
||||
"crop": {
|
||||
"tags": "trim,shrink,edit,shape",
|
||||
"title": "Crop",
|
||||
"header": "Crop Image",
|
||||
"submit": "Submit"
|
||||
},
|
||||
"autoSplitPDF": {
|
||||
"tags": "QR-based,separate,scan-segment,organize",
|
||||
"title": "Auto Split PDF",
|
||||
"header": "Auto Split PDF",
|
||||
"description": "Print, Insert, Scan, upload, and let us auto-separate your documents. No manual work sorting needed.",
|
||||
"selectText": {
|
||||
"1": "Print out some divider sheets from below (Black and white is fine).",
|
||||
"2": "Scan all your documents at once by inserting the divider sheet between them.",
|
||||
"3": "Upload the single large scanned PDF file and let Stirling PDF handle the rest.",
|
||||
"4": "Divider pages are automatically detected and removed, guaranteeing a neat final document."
|
||||
},
|
||||
"formPrompt": "Submit PDF containing Stirling-PDF Page dividers:",
|
||||
"duplexMode": "Duplex Mode (Front and back scanning)",
|
||||
"dividerDownload1": "Download 'Auto Splitter Divider (minimal).pdf'",
|
||||
"dividerDownload2": "Download 'Auto Splitter Divider (with instructions).pdf'",
|
||||
"submit": "Submit"
|
||||
},
|
||||
"sanitizePdf": {
|
||||
"tags": "clean,secure,safe,remove-threats"
|
||||
},
|
||||
"URLToPDF": {
|
||||
"tags": "web-capture,save-page,web-to-doc,archive",
|
||||
"title": "URL To PDF",
|
||||
"header": "URL To PDF",
|
||||
"submit": "Convert",
|
||||
"credit": "Uses WeasyPrint"
|
||||
},
|
||||
"HTMLToPDF": {
|
||||
"tags": "markup,web-content,transformation,convert",
|
||||
"title": "HTML To PDF",
|
||||
"header": "HTML To PDF",
|
||||
"help": "Accepts HTML files and ZIPs containing html/css/images etc required",
|
||||
"submit": "Convert",
|
||||
"credit": "Uses WeasyPrint"
|
||||
},
|
||||
"MarkdownToPDF": {
|
||||
"tags": "markup,web-content,transformation,convert",
|
||||
"title": "Markdown To PDF",
|
||||
"header": "Markdown To PDF",
|
||||
"submit": "Convert",
|
||||
"help": "Work in progress",
|
||||
"credit": "Uses WeasyPrint"
|
||||
},
|
||||
"getPdfInfo": {
|
||||
"tags": "infomation,data,stats,statistics",
|
||||
"title": "Get Info on PDF",
|
||||
"header": "Get Info on PDF",
|
||||
"submit": "Get Info",
|
||||
"downloadJson": "Download JSON"
|
||||
},
|
||||
"extractPage": {
|
||||
"tags": "extract"
|
||||
},
|
||||
"PdfToSinglePage": {
|
||||
"tags": "single page"
|
||||
},
|
||||
"showJS": {
|
||||
"tags": "JS",
|
||||
"title": "Show Javascript",
|
||||
"header": "Show Javascript",
|
||||
"downloadJS": "Download Javascript",
|
||||
"submit": "Show"
|
||||
},
|
||||
"login": {
|
||||
"title": "Sign in",
|
||||
"signin": "Sign in",
|
||||
"rememberme": "Remember me",
|
||||
"invalid": "Invalid username or password.",
|
||||
"locked": "Your account has been locked.",
|
||||
"signinTitle": "Please sign in"
|
||||
},
|
||||
"autoRedact": {
|
||||
"title": "Auto Redact",
|
||||
"header": "Auto Redact",
|
||||
"colorLabel": "Colour",
|
||||
"textsToRedactLabel": "Text to Redact (line-separated)",
|
||||
"textsToRedactPlaceholder": "e.g. \\nConfidential \\nTop-Secret",
|
||||
"useRegexLabel": "Use Regex",
|
||||
"wholeWordSearchLabel": "Whole Word Search",
|
||||
"customPaddingLabel": "Custom Extra Padding",
|
||||
"convertPDFToImageLabel": "Convert PDF to PDF-Image (Used to remove text behind the box)",
|
||||
"submitButton": "Submit"
|
||||
},
|
||||
"pdfToSinglePage": {
|
||||
"title": "PDF To Single Page",
|
||||
"header": "PDF To Single Page",
|
||||
"submit": "Convert To Single Page"
|
||||
},
|
||||
"pageExtracter": {
|
||||
"title": "Extract Pages",
|
||||
"header": "Extract Pages",
|
||||
"submit": "Extract"
|
||||
},
|
||||
"sanitizePDF": {
|
||||
"title": "Sanitize PDF",
|
||||
"header": "Sanitize a PDF file",
|
||||
"selectText": {
|
||||
"1": "Remove JavaScript actions",
|
||||
"2": "Remove embedded files",
|
||||
"3": "Remove metadata",
|
||||
"4": "Remove links",
|
||||
"5": "Remove fonts"
|
||||
},
|
||||
"submit": "Sanitize PDF"
|
||||
},
|
||||
"addPageNumbers": {
|
||||
"title": "Add Page Numbers",
|
||||
"header": "Add Page Numbers",
|
||||
"selectText": {
|
||||
"1": "Select PDF file:",
|
||||
"2": "Margin Size",
|
||||
"3": "Position",
|
||||
"4": "Starting Number",
|
||||
"5": "Pages to Number",
|
||||
"6": "Custom Text"
|
||||
},
|
||||
"customTextDesc": "Custom Text",
|
||||
"numberPagesDesc": "Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc",
|
||||
"customNumberDesc": "Defaults to {n}, also accepts 'Page {n} of {total}', 'Text-{n}', '{filename}-{n}",
|
||||
"submit": "Add Page Numbers"
|
||||
},
|
||||
"adjustContrast": {
|
||||
"title": "Adjust Contrast",
|
||||
"header": "Adjust Contrast",
|
||||
"contrast": "Contrast:",
|
||||
"brightness": "Brightness:",
|
||||
"saturation": "Saturation:",
|
||||
"download": "Download"
|
||||
},
|
||||
"compress": {
|
||||
"title": "ضغط",
|
||||
"header": "ضغط ملف PDF",
|
||||
"credit": "تستخدم هذه الخدمة OCRmyPDF لضغط / تحسين PDF.",
|
||||
"selectText": {
|
||||
"1": "الوضع اليدوي - من 1 إلى 4",
|
||||
"2": "مستوى التحسين:",
|
||||
"3": "4 (رهيب للصور النصية)",
|
||||
"4": "الوضع التلقائي - يضبط الجودة تلقائيًا للحصول على ملف PDF بالحجم المحدد",
|
||||
"5": "حجم PDF المتوقع (على سبيل المثال 25 ميجا بايت ، 10.8 ميجا بايت ، 25 كيلو بايت)"
|
||||
},
|
||||
"submit": "ضغطضغط"
|
||||
},
|
||||
"pageRemover": {
|
||||
"title": "مزيل الصفحة",
|
||||
"header": "مزيل صفحة PDF",
|
||||
"pagesToDelete": "الصفحات المراد حذفها (أدخل قائمة بأرقام الصفحات مفصولة بفواصل):",
|
||||
"submit": "حذف الصفحات"
|
||||
},
|
||||
"imageToPDF": {
|
||||
"title": "صورة إلى PDF",
|
||||
"header": "صورة إلى PDF",
|
||||
"submit": "تحول",
|
||||
"selectLabel": "Image Fit Options",
|
||||
"fillPage": "Fill Page",
|
||||
"fitDocumentToImage": "Fit Page to Image",
|
||||
"maintainAspectRatio": "Maintain Aspect Ratios",
|
||||
"selectText": {
|
||||
"2": "\u062F\u0648\u0631\u0627\u0646 PDF \u062A\u0644\u0642\u0627\u0626\u064A\u064B\u0627",
|
||||
"3": "\u0627\u0644\u0645\u0646\u0637\u0642 \u0627\u0644\u0645\u062A\u0639\u062F\u062F \u0644\u0644\u0645\u0644\u0641\u0627\u062A (\u0645\u0641\u0639\u0651\u0644 \u0641\u0642\u0637 \u0625\u0630\u0627 \u0643\u0646\u062A \u062A\u0639\u0645\u0644 \u0645\u0639 \u0635\u0648\u0631 \u0645\u062A\u0639\u062F\u062F\u0629)",
|
||||
"4": "\u062F\u0645\u062C \u0641\u064A \u0645\u0644\u0641 PDF \u0648\u0627\u062D\u062F",
|
||||
"5": "\u062A\u062D\u0648\u064A\u0644 \u0625\u0644\u0649 \u0645\u0644\u0641\u0627\u062A PDF \u0645\u0646\u0641\u0635\u0644\u0629"
|
||||
}
|
||||
},
|
||||
"changeMetadata": {
|
||||
"title": "\u0627\u0644\u0639\u0646\u0648\u0627\u0646:",
|
||||
"header": "\u062A\u063A\u064A\u064A\u0631 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0648\u0635\u0641\u064A\u0629",
|
||||
"selectText": {
|
||||
"1": "\u064A\u0631\u062C\u0649 \u062A\u0639\u062F\u064A\u0644 \u0627\u0644\u0645\u062A\u063A\u064A\u0631\u0627\u062A \u0627\u0644\u062A\u064A \u062A\u0631\u063A\u0628 \u0641\u064A \u062A\u063A\u064A\u064A\u0631\u0647\u0627",
|
||||
"2": "\u062D\u0630\u0641 \u0643\u0644 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0623\u0648\u0644\u064A\u0629",
|
||||
"3": "\u0625\u0638\u0647\u0627\u0631 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0623\u0648\u0644\u064A\u0629 \u0627\u0644\u0645\u062E\u0635\u0635\u0629:",
|
||||
"4": "\u0628\u064A\u0627\u0646\u0627\u062A \u0648\u0635\u0641\u064A\u0629 \u0623\u062E\u0631\u0649:",
|
||||
"5": "\u0625\u0636\u0627\u0641\u0629 \u0625\u062F\u062E\u0627\u0644 \u0628\u064A\u0627\u0646\u0627\u062A \u0623\u0648\u0644\u064A\u0629 \u0645\u062E\u0635\u0635"
|
||||
},
|
||||
"author": "\u0627\u0644\u0645\u0624\u0644\u0641:",
|
||||
"creationDate": "\u062A\u0627\u0631\u064A\u062E \u0627\u0644\u0625\u0646\u0634\u0627\u0621 (yyyy / MM / dd HH: mm: ss):",
|
||||
"creator": "\u0627\u0644\u0645\u0646\u0634\u0626:",
|
||||
"keywords": "\u0627\u0644\u0643\u0644\u0645\u0627\u062A \u0627\u0644\u0631\u0626\u064A\u0633\u064A\u0629:",
|
||||
"modDate": "\u062A\u0627\u0631\u064A\u062E \u0627\u0644\u062A\u0639\u062F\u064A\u0644 (yyyy / MM / dd HH: mm: ss):",
|
||||
"producer": "\u0627\u0644\u0645\u0646\u062A\u062C:",
|
||||
"subject": "\u0627\u0644\u0645\u0648\u0636\u0648\u0639:",
|
||||
"trapped": "\u0645\u062D\u0627\u0635\u0631:",
|
||||
"submit": "\u062A\u063A\u064A\u064A\u0631"
|
||||
}
|
||||
}
|
||||
}
|
||||
854
client-tauri/src/locales/en.json
Normal file
@@ -0,0 +1,854 @@
|
||||
{
|
||||
"translation": {
|
||||
"language": {
|
||||
"name":"English (UK)",
|
||||
"flag": "🇬🇧",
|
||||
"direction": "ltr"
|
||||
},
|
||||
"pdfPrompt": "Select PDF(s)",
|
||||
"multiPdfPrompt": "Select PDFs (2+)",
|
||||
"multiPdfDropPrompt": "Select (or drag & drop) all PDFs you require",
|
||||
"imgPrompt": "Select Image(s)",
|
||||
"genericSubmit": "Submit",
|
||||
"processTimeWarning": "Warning: This process can take up to a minute depending on file-size",
|
||||
"pageOrderPrompt": "Custom Page Order (Enter a comma-separated list of page numbers or Functions like 2n+1) :",
|
||||
"goToPage": "Go",
|
||||
"true": "True",
|
||||
"false": "False",
|
||||
"unknown": "Unknown",
|
||||
"save": "Save",
|
||||
"close": "Close",
|
||||
"filesSelected": "files selected",
|
||||
"noFavourites": "No favourites added",
|
||||
"bored": "Bored Waiting?",
|
||||
"alphabet": "Alphabet",
|
||||
"downloadPdf": "Download PDF",
|
||||
"text": "Text",
|
||||
"font": "Font",
|
||||
"selectFillter": "-- Select --",
|
||||
"pageNum": "Page Number ",
|
||||
"sizes": {
|
||||
"small": "Small",
|
||||
"medium": "Medium",
|
||||
"large": "Large",
|
||||
"x-large": "X-Large"
|
||||
},
|
||||
"error": {
|
||||
"pdfPassword": "The PDF Document is passworded and either the password was not provided or was incorrect"
|
||||
},
|
||||
"delete": "Delete",
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"welcome": "Welcome",
|
||||
"property": "Property",
|
||||
"black": "Black",
|
||||
"white": "White",
|
||||
"red": "Red",
|
||||
"green": "Green",
|
||||
"blue": "Blue",
|
||||
"custom": "Custom...",
|
||||
"changedCredsMessage": "Credentials changed!",
|
||||
"notAuthenticatedMessage": "User not authenticated.",
|
||||
"userNotFoundMessage": "User not found.",
|
||||
"incorrectPasswordMessage": "Current password is incorrect.",
|
||||
"usernameExistsMessage": "New Username already exists.",
|
||||
"navbar": {
|
||||
"convert": "Convert",
|
||||
"security": "Security",
|
||||
"other": "Miscellaneous",
|
||||
"darkmode": "Dark Mode",
|
||||
"pageOps": "Page Operations",
|
||||
"settings": "Settings"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Settings",
|
||||
"update": "Update available",
|
||||
"appVersion": "App Version:",
|
||||
"downloadOption": {
|
||||
"1": "Open in same window",
|
||||
"2": "Open in new window",
|
||||
"3": "Download file",
|
||||
"title": "Choose download option (For single file non zip downloads):"
|
||||
},
|
||||
"zipThreshold": "Zip files when the number of downloaded files exceeds",
|
||||
"signOut": "Sign Out",
|
||||
"accountSettings": "Account Settings"
|
||||
},
|
||||
"changeCreds": {
|
||||
"title": "Change Credentials",
|
||||
"header": "Update Your Account Details",
|
||||
"changeUserAndPassword": "You are using default login credentials. Please enter a new password (and username if wanted)",
|
||||
"newUsername": "New Username",
|
||||
"oldPassword": "Current Password",
|
||||
"newPassword": "New Password",
|
||||
"confirmNewPassword": "Confirm New Password",
|
||||
"submit": "Submit Changes"
|
||||
},
|
||||
"account": {
|
||||
"title": "Account Settings",
|
||||
"accountSettings": "Account Settings",
|
||||
"adminSettings": "Admin Settings - View and Add Users",
|
||||
"userControlSettings": "User Control Settings",
|
||||
"changeUsername": "Change Username",
|
||||
"password": "Confirmation Password",
|
||||
"oldPassword": "Old password",
|
||||
"newPassword": "New Password",
|
||||
"changePassword": "Change Password",
|
||||
"confirmNewPassword": "Confirm New Password",
|
||||
"signOut": "Sign Out",
|
||||
"yourApiKey": "Your API Key",
|
||||
"syncTitle": "Sync browser settings with Account",
|
||||
"settingsCompare": "Settings Comparison:",
|
||||
"property": "Property",
|
||||
"webBrowserSettings": "Web Browser Setting",
|
||||
"syncToBrowser": "Sync Account -> Browser",
|
||||
"syncToAccount": "Sync Account <- Browser"
|
||||
},
|
||||
"adminUserSettings": {
|
||||
"title": "User Control Settings",
|
||||
"header": "Admin User Control Settings",
|
||||
"admin": "Admin",
|
||||
"user": "User",
|
||||
"addUser": "Add New User",
|
||||
"roles": "Roles",
|
||||
"role": "Role",
|
||||
"actions": "Actions",
|
||||
"apiUser": "Limited API User",
|
||||
"webOnlyUser": "Web Only User",
|
||||
"forceChange": "Force user to change username/password on login",
|
||||
"submit": "Save User"
|
||||
},
|
||||
"home": {
|
||||
"desc": "Your locally hosted one-stop-shop for all your PDF needs.",
|
||||
"searchBar": "Search for features...",
|
||||
"viewPdf": {
|
||||
"title": "View PDF",
|
||||
"desc": "View, annotate, add text or images"
|
||||
},
|
||||
"multiTool": {
|
||||
"title": "PDF Multi Tool",
|
||||
"desc": "Merge, Rotate, Rearrange, and Remove pages"
|
||||
},
|
||||
"merge": {
|
||||
"title": "Merge",
|
||||
"desc": "Easily merge multiple PDFs into one."
|
||||
},
|
||||
"split": {
|
||||
"title": "Split",
|
||||
"desc": "Split PDFs into multiple documents"
|
||||
},
|
||||
"rotate": {
|
||||
"title": "Rotate",
|
||||
"desc": "Easily rotate your PDFs."
|
||||
},
|
||||
"imageToPdf": {
|
||||
"title": "Image to PDF",
|
||||
"desc": "Convert a image (PNG, JPEG, GIF) to PDF."
|
||||
},
|
||||
"pdfToImage": {
|
||||
"title": "PDF to Image",
|
||||
"desc": "Convert a PDF to a image. (PNG, JPEG, GIF)"
|
||||
},
|
||||
"pdfOrganiser": {
|
||||
"title": "Organise",
|
||||
"desc": "Remove/Rearrange pages in any order"
|
||||
},
|
||||
"addImage": {
|
||||
"title": "Add image",
|
||||
"desc": "Adds a image onto a set location on the PDF"
|
||||
},
|
||||
"watermark": {
|
||||
"title": "Add Watermark",
|
||||
"desc": "Add a custom watermark to your PDF document."
|
||||
},
|
||||
"permissions": {
|
||||
"title": "Change Permissions",
|
||||
"desc": "Change the permissions of your PDF document"
|
||||
},
|
||||
"removePages": {
|
||||
"title": "Remove",
|
||||
"desc": "Delete unwanted pages from your PDF document."
|
||||
},
|
||||
"addPassword": {
|
||||
"title": "Add Password",
|
||||
"desc": "Encrypt your PDF document with a password."
|
||||
},
|
||||
"removePassword": {
|
||||
"title": "Remove Password",
|
||||
"desc": "Remove password protection from your PDF document."
|
||||
},
|
||||
"compressPdfs": {
|
||||
"title": "Compress",
|
||||
"desc": "Compress PDFs to reduce their file size."
|
||||
},
|
||||
"changeMetadata": {
|
||||
"title": "Change Metadata",
|
||||
"desc": "Change/Remove/Add metadata from a PDF document"
|
||||
},
|
||||
"fileToPDF": {
|
||||
"title": "Convert file to PDF",
|
||||
"desc": "Convert nearly any file to PDF (DOCX, PNG, XLS, PPT, TXT and more)"
|
||||
},
|
||||
"ocr": {
|
||||
"title": "OCR / Cleanup scans",
|
||||
"desc": "Cleanup scans and detects text from images within a PDF and re-adds it as text."
|
||||
},
|
||||
"extractImages": {
|
||||
"title": "Extract Images",
|
||||
"desc": "Extracts all images from a PDF and saves them to zip"
|
||||
},
|
||||
"pdfToPDFA": {
|
||||
"title": "PDF to PDF/A",
|
||||
"desc": "Convert PDF to PDF/A for long-term storage"
|
||||
},
|
||||
"PDFToWord": {
|
||||
"title": "PDF to Word",
|
||||
"desc": "Convert PDF to Word formats (DOC, DOCX and ODT)"
|
||||
},
|
||||
"PDFToPresentation": {
|
||||
"title": "PDF to Presentation",
|
||||
"desc": "Convert PDF to Presentation formats (PPT, PPTX and ODP)"
|
||||
},
|
||||
"PDFToText": {
|
||||
"title": "PDF to RTF (Text)",
|
||||
"desc": "Convert PDF to Text or RTF format"
|
||||
},
|
||||
"PDFToHTML": {
|
||||
"title": "PDF to HTML",
|
||||
"desc": "Convert PDF to HTML format"
|
||||
},
|
||||
"PDFToXML": {
|
||||
"title": "PDF to XML",
|
||||
"desc": "Convert PDF to XML format"
|
||||
},
|
||||
"ScannerImageSplit": {
|
||||
"title": "Detect/Split Scanned photos",
|
||||
"desc": "Splits multiple photos from within a photo/PDF"
|
||||
},
|
||||
"sign": {
|
||||
"title": "Sign",
|
||||
"desc": "Adds signature to PDF by drawing, text or image"
|
||||
},
|
||||
"flatten": {
|
||||
"title": "Flatten",
|
||||
"desc": "Remove all interactive elements and forms from a PDF"
|
||||
},
|
||||
"repair": {
|
||||
"title": "Repair",
|
||||
"desc": "Tries to repair a corrupt/broken PDF"
|
||||
},
|
||||
"removeBlanks": {
|
||||
"title": "Remove Blank pages",
|
||||
"desc": "Detects and removes blank pages from a document"
|
||||
},
|
||||
"compare": {
|
||||
"title": "Compare",
|
||||
"desc": "Compares and shows the differences between 2 PDF Documents"
|
||||
},
|
||||
"certSign": {
|
||||
"title": "Sign with Certificate",
|
||||
"desc": "Signs a PDF with a Certificate/Key (PEM/P12)"
|
||||
},
|
||||
"pageLayout": {
|
||||
"title": "Multi-Page Layout",
|
||||
"desc": "Merge multiple pages of a PDF document into a single page"
|
||||
},
|
||||
"scalePages": {
|
||||
"title": "Adjust page size/scale",
|
||||
"desc": "Change the size/scale of a page and/or its contents."
|
||||
},
|
||||
"pipeline": {
|
||||
"title": "Pipeline (Advanced)",
|
||||
"desc": "Run multiple actions on PDFs by defining pipeline scripts"
|
||||
},
|
||||
"add-page-numbers": {
|
||||
"title": "Add Page Numbers",
|
||||
"desc": "Add Page numbers throughout a document in a set location"
|
||||
},
|
||||
"auto-rename": {
|
||||
"title": "Auto Rename PDF File",
|
||||
"desc": "Auto renames a PDF file based on its detected header "
|
||||
},
|
||||
"adjust-contrast": {
|
||||
"title": "Adjust Colors/Contrast",
|
||||
"desc": "Adjust Contrast, Saturation and Brightness of a PDF"
|
||||
},
|
||||
"crop": {
|
||||
"title": "Crop PDF",
|
||||
"desc": "Crop a PDF to reduce its size (maintains text!)"
|
||||
},
|
||||
"autoSplitPDF": {
|
||||
"title": "Auto Split Pages",
|
||||
"desc": "Auto Split Scanned PDF with physical scanned page splitter QR Code"
|
||||
},
|
||||
"sanitizePdf": {
|
||||
"title": "Sanitize",
|
||||
"desc": "Remove scripts and other elements from PDF files"
|
||||
},
|
||||
"URLToPDF": {
|
||||
"title": "URL/Website To PDF",
|
||||
"desc": "Converts any http(s)URL to PDF"
|
||||
},
|
||||
"HTMLToPDF": {
|
||||
"title": "HTML to PDF",
|
||||
"desc": "Converts any HTML file or zip to PDF"
|
||||
},
|
||||
"MarkdownToPDF": {
|
||||
"title": "Markdown to PDF",
|
||||
"desc": "Converts any Markdown file to PDF"
|
||||
},
|
||||
"getPdfInfo": {
|
||||
"title": "Get ALL Info on PDF",
|
||||
"desc": "Grabs any and all information possible on PDFs"
|
||||
},
|
||||
"extractPage": {
|
||||
"title": "Extract page(s)",
|
||||
"desc": "Extracts select pages from PDF"
|
||||
},
|
||||
"PdfToSinglePage": {
|
||||
"title": "PDF to Single Large Page",
|
||||
"desc": "Merges all PDF pages into one large single page"
|
||||
},
|
||||
"showJS": {
|
||||
"title": "Show Javascript",
|
||||
"desc": "Searches and displays any JS injected into a PDF"
|
||||
},
|
||||
"autoRedact": {
|
||||
"title": "Auto Redact",
|
||||
"desc": "Auto Redacts(Blacks out) text in a PDF based on input text"
|
||||
}
|
||||
},
|
||||
"viewPdf": {
|
||||
"tags": "view,read,annotate,text,image",
|
||||
"title": "View PDF",
|
||||
"header": "View PDF"
|
||||
},
|
||||
"multiTool": {
|
||||
"tags": "Multi Tool,Multi operation,UI,click drag,front end,client side,interactive,intractable,move",
|
||||
"title": "PDF Multi Tool",
|
||||
"header": "PDF Multi Tool"
|
||||
},
|
||||
"merge": {
|
||||
"tags": "merge,Page operations,Back end,server side",
|
||||
"title": "Merge",
|
||||
"header": "Merge multiple PDFs (2+)",
|
||||
"sortByName": "Sort by name",
|
||||
"sortByDate": "Sort by date",
|
||||
"submit": "Merge"
|
||||
},
|
||||
"split": {
|
||||
"tags": "Page operations,divide,Multi Page,cut,server side ",
|
||||
"title": "Split PDF",
|
||||
"header": "Split PDF",
|
||||
"desc": {
|
||||
"1": "The numbers you select are the page number you wish to do a split on",
|
||||
"2": "As such selecting 1,3,7-8 would split a 10 page document into 6 separate PDFS with:",
|
||||
"3": "Document ",
|
||||
"4": "Document ",
|
||||
"5": "Document ",
|
||||
"6": "Document ",
|
||||
"7": "Document ",
|
||||
"8": "Document "
|
||||
},
|
||||
"splitPages": "Enter pages to split on:",
|
||||
"submit": "Split"
|
||||
},
|
||||
"rotate": {
|
||||
"tags": "server side",
|
||||
"title": "Rotate PDF",
|
||||
"header": "Rotate PDF",
|
||||
"selectAngle": "Select rotation angle (in multiples of 90 degrees):",
|
||||
"submit": "Rotate"
|
||||
},
|
||||
"imageToPdf": {
|
||||
"tags": "conversion,img,jpg,picture,photo"
|
||||
},
|
||||
"pdfToImage": {
|
||||
"tags": "conversion,img,jpg,picture,photo",
|
||||
"title": "PDF to Image",
|
||||
"header": "PDF to Image",
|
||||
"selectText": "Image Format",
|
||||
"singleOrMultiple": "Page to Image result type",
|
||||
"single": "Single Big Image Combing all pages",
|
||||
"multi": "Multiple Images, one image per page",
|
||||
"colorType": "Colour type",
|
||||
"color": "Colour",
|
||||
"grey": "Greyscale",
|
||||
"blackwhite": "Black and White (May lose data!)",
|
||||
"submit": "Convert"
|
||||
},
|
||||
"pdfOrganiser": {
|
||||
"tags": "duplex,even,odd,sort,move",
|
||||
"title": "Page Organiser",
|
||||
"header": "PDF Page Organiser",
|
||||
"submit": "Rearrange Pages"
|
||||
},
|
||||
"addImage": {
|
||||
"tags": "img,jpg,picture,photo",
|
||||
"title": "Add Image",
|
||||
"header": "Add image to PDF",
|
||||
"everyPage": "Every Page?",
|
||||
"upload": "Add image",
|
||||
"submit": "Add image"
|
||||
},
|
||||
"watermark": {
|
||||
"tags": "Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo",
|
||||
"title": "Add Watermark",
|
||||
"header": "Add Watermark",
|
||||
"selectText": {
|
||||
"1": "Select PDF to add watermark to:",
|
||||
"2": "Watermark Text:",
|
||||
"3": "Font Size:",
|
||||
"4": "Rotation (0-360):",
|
||||
"5": "widthSpacer (Space between each watermark horizontally):",
|
||||
"6": "heightSpacer (Space between each watermark vertically):",
|
||||
"7": "Opacity (0% - 100%):",
|
||||
"8": "Watermark Type:",
|
||||
"9": "Watermark Image:"
|
||||
},
|
||||
"submit": "Add Watermark"
|
||||
},
|
||||
"permissions": {
|
||||
"tags": "read,write,edit,print",
|
||||
"title": "Change Permissions",
|
||||
"header": "Change Permissions",
|
||||
"warning": "Warning to have these permissions be unchangeable it is recommended to set them with a password via the add-password page",
|
||||
"selectText": {
|
||||
"1": "Select PDF to change permissions",
|
||||
"2": "Permissions to set",
|
||||
"3": "Prevent assembly of document",
|
||||
"4": "Prevent content extraction",
|
||||
"5": "Prevent extraction for accessibility",
|
||||
"6": "Prevent filling in form",
|
||||
"7": "Prevent modification",
|
||||
"8": "Prevent annotation modification",
|
||||
"9": "Prevent printing",
|
||||
"10": "Prevent printing different formats"
|
||||
},
|
||||
"submit": "Change"
|
||||
},
|
||||
"removePages": {
|
||||
"tags": "Remove pages,delete pages"
|
||||
},
|
||||
"addPassword": {
|
||||
"tags": "secure,security",
|
||||
"title": "Add Password",
|
||||
"header": "Add password (Encrypt)",
|
||||
"selectText": {
|
||||
"1": "Select PDF to encrypt",
|
||||
"2": "User Password",
|
||||
"3": "Encryption Key Length",
|
||||
"4": "Higher values are stronger, but lower values have better compatibility.",
|
||||
"5": "Permissions to set (Recommended to be used along with Owner password)",
|
||||
"6": "Prevent assembly of document",
|
||||
"7": "Prevent content extraction",
|
||||
"8": "Prevent extraction for accessibility",
|
||||
"9": "Prevent filling in form",
|
||||
"10": "Prevent modification",
|
||||
"11": "Prevent annotation modification",
|
||||
"12": "Prevent printing",
|
||||
"13": "Prevent printing different formats",
|
||||
"14": "Owner Password",
|
||||
"15": "Restricts what can be done with the document once it is opened (Not supported by all readers)",
|
||||
"16": "Restricts the opening of the document itself"
|
||||
},
|
||||
"submit": "Encrypt"
|
||||
},
|
||||
"removePassword": {
|
||||
"tags": "secure,Decrypt,security,unpassword,delete password",
|
||||
"title": "Remove password",
|
||||
"header": "Remove password (Decrypt)",
|
||||
"selectText": {
|
||||
"1": "Select PDF to Decrypt",
|
||||
"2": "Password"
|
||||
},
|
||||
"submit": "Remove"
|
||||
},
|
||||
"compressPdfs": {
|
||||
"tags": "squish,small,tiny"
|
||||
},
|
||||
"fileToPDF": {
|
||||
"tags": "transformation,format,document,picture,slide,text,conversion,office,docs,word,excel,powerpoint",
|
||||
"title": "File to PDF",
|
||||
"header": "Convert any file to PDF",
|
||||
"credit": "This service uses LibreOffice and Unoconv for file conversion.",
|
||||
"supportedFileTypes": "Supported file types should include the below however for a full updated list of supported formats, please refer to the LibreOffice documentation",
|
||||
"submit": "Convert to PDF"
|
||||
},
|
||||
"ocr": {
|
||||
"tags": "recognition,text,image,scan,read,identify,detection,editable",
|
||||
"title": "OCR / Scan Cleanup",
|
||||
"header": "Cleanup Scans / OCR (Optical Character Recognition)",
|
||||
"selectText": {
|
||||
"1": "Select languages that are to be detected within the PDF (Ones listed are the ones currently detected):",
|
||||
"2": "Produce text file containing OCR text alongside the OCR'ed PDF",
|
||||
"3": "Correct pages were scanned at a skewed angle by rotating them back into place",
|
||||
"4": "Clean page so its less likely that OCR will find text in background noise. (No output change)",
|
||||
"5": "Clean page so its less likely that OCR will find text in background noise, maintains cleanup in output.",
|
||||
"6": "Ignores pages that have interactive text on them, only OCRs pages that are images",
|
||||
"7": "Force OCR, will OCR Every page removing all original text elements",
|
||||
"8": "Normal (Will error if PDF contains text)",
|
||||
"9": "Additional Settings",
|
||||
"10": "OCR Mode",
|
||||
"11": "Remove images after OCR (Removes ALL images, only useful if part of conversion step)",
|
||||
"12": "Render Type (Advanced)"
|
||||
},
|
||||
"help": "Please read this documentation on how to use this for other languages and/or use not in docker",
|
||||
"credit": "This service uses OCRmyPDF and Tesseract for OCR.",
|
||||
"submit": "Process PDF with OCR"
|
||||
},
|
||||
"extractImages": {
|
||||
"tags": "picture,photo,save,archive,zip,capture,grab",
|
||||
"title": "Extract Images",
|
||||
"header": "Extract Images",
|
||||
"selectText": "Select image format to convert extracted images to",
|
||||
"submit": "Extract"
|
||||
},
|
||||
"pdfToPDFA": {
|
||||
"tags": "archive,long-term,standard,conversion,storage,preservation",
|
||||
"title": "PDF To PDF/A",
|
||||
"header": "PDF To PDF/A",
|
||||
"credit": "This service uses OCRmyPDF for PDF/A conversion",
|
||||
"submit": "Convert"
|
||||
},
|
||||
"PDFToWord": {
|
||||
"tags": "doc,docx,odt,word,transformation,format,conversion,office,microsoft,docfile",
|
||||
"title": "PDF to Word",
|
||||
"header": "PDF to Word",
|
||||
"selectText": {
|
||||
"1": "Output file format"
|
||||
},
|
||||
"credit": "This service uses LibreOffice for file conversion.",
|
||||
"submit": "Convert"
|
||||
},
|
||||
"PDFToPresentation": {
|
||||
"tags": "slides,show,office,microsoft",
|
||||
"title": "PDF to Presentation",
|
||||
"header": "PDF to Presentation",
|
||||
"selectText": {
|
||||
"1": "Output file format"
|
||||
},
|
||||
"credit": "This service uses LibreOffice for file conversion.",
|
||||
"submit": "Convert"
|
||||
},
|
||||
"PDFToText": {
|
||||
"tags": "richformat,richtextformat,rich text format",
|
||||
"title": "PDF to RTF (Text)",
|
||||
"header": "PDF to RTF (Text)",
|
||||
"selectText": {
|
||||
"1": "Output file format"
|
||||
},
|
||||
"credit": "This service uses LibreOffice for file conversion.",
|
||||
"submit": "Convert"
|
||||
},
|
||||
"PDFToHTML": {
|
||||
"tags": "web content,browser friendly",
|
||||
"title": "PDF to HTML",
|
||||
"header": "PDF to HTML",
|
||||
"credit": "This service uses LibreOffice for file conversion.",
|
||||
"submit": "Convert"
|
||||
},
|
||||
"PDFToXML": {
|
||||
"tags": "data-extraction,structured-content,interop,transformation,convert",
|
||||
"title": "PDF to XML",
|
||||
"header": "PDF to XML",
|
||||
"credit": "This service uses LibreOffice for file conversion.",
|
||||
"submit": "Convert"
|
||||
},
|
||||
"ScannerImageSplit": {
|
||||
"tags": "separate,auto-detect,scans,multi-photo,organize",
|
||||
"selectText": {
|
||||
"1": "Angle Threshold:",
|
||||
"2": "Sets the minimum absolute angle required for the image to be rotated (default: 10).",
|
||||
"3": "Tolerance:",
|
||||
"4": "Determines the range of color variation around the estimated background color (default: 30).",
|
||||
"5": "Minimum Area:",
|
||||
"6": "Sets the minimum area threshold for a photo (default: 10000).",
|
||||
"7": "Minimum Contour Area:",
|
||||
"8": "Sets the minimum contour area threshold for a photo",
|
||||
"9": "Border Size:",
|
||||
"10": "Sets the size of the border added and removed to prevent white borders in the output (default: 1)."
|
||||
}
|
||||
},
|
||||
"sign": {
|
||||
"tags": "authorize,initials,drawn-signature,text-sign,image-signature",
|
||||
"title": "Sign",
|
||||
"header": "Sign PDFs",
|
||||
"upload": "Upload Image",
|
||||
"draw": "Draw Signature",
|
||||
"text": "Text Input",
|
||||
"clear": "Clear",
|
||||
"add": "Add"
|
||||
},
|
||||
"flatten": {
|
||||
"tags": "static,deactivate,non-interactive,streamline",
|
||||
"title": "Flatten",
|
||||
"header": "Flatten PDFs",
|
||||
"submit": "Flatten"
|
||||
},
|
||||
"repair": {
|
||||
"tags": "fix,restore,correction,recover",
|
||||
"title": "Repair",
|
||||
"header": "Repair PDFs",
|
||||
"submit": "Repair"
|
||||
},
|
||||
"removeBlanks": {
|
||||
"tags": "cleanup,streamline,non-content,organize",
|
||||
"title": "Remove Blanks",
|
||||
"header": "Remove Blank Pages",
|
||||
"threshold": "Pixel Whiteness Threshold:",
|
||||
"thresholdDesc": "Threshold for determining how white a white pixel must be to be classed as 'White'. 0 ",
|
||||
"whitePercent": "White Percent (%):",
|
||||
"whitePercentDesc": "Percent of page that must be 'white' pixels to be removed",
|
||||
"submit": "Remove Blanks"
|
||||
},
|
||||
"compare": {
|
||||
"tags": "differentiate,contrast,changes,analysis",
|
||||
"title": "Compare",
|
||||
"header": "Compare PDFs",
|
||||
"document": {
|
||||
"1": "Document 1",
|
||||
"2": "Document 2"
|
||||
},
|
||||
"submit": "Compare"
|
||||
},
|
||||
"certSign": {
|
||||
"tags": "authenticate,PEM,P12,official,encrypt",
|
||||
"title": "Certificate Signing",
|
||||
"header": "Sign a PDF with your certificate (Work in progress)",
|
||||
"selectPDF": "Select a PDF File for Signing: ",
|
||||
"selectKey": "Select Your Private Key File (PKCS",
|
||||
"selectCert": "Select Your Certificate File (X.509 format, could be .pem or .der): ",
|
||||
"selectP12": "Select Your PKCS",
|
||||
"certType": "Certificate Type",
|
||||
"password": "Enter Your Keystore or Private Key Password (If Any): ",
|
||||
"showSig": "Show Signature",
|
||||
"reason": "Reason",
|
||||
"location": "Location",
|
||||
"name": "Name ",
|
||||
"submit": "Sign PDF"
|
||||
},
|
||||
"pageLayout": {
|
||||
"tags": "merge,composite,single-view,organize",
|
||||
"title": "Multi Page Layout",
|
||||
"header": "Multi Page Layout",
|
||||
"pagesPerSheet": "Pages per sheet:",
|
||||
"addBorder": "Add Borders",
|
||||
"submit": "Submit"
|
||||
},
|
||||
"scalePages": {
|
||||
"tags": "resize,modify,dimension,adapt",
|
||||
"title": "Adjust page-scale",
|
||||
"header": "Adjust page-scale",
|
||||
"pageSize": "Size of a page of the document.",
|
||||
"scaleFactor": "Zoom level (crop) of a page.",
|
||||
"submit": "Submit"
|
||||
},
|
||||
"pipeline": {
|
||||
"tags": "automate,sequence,scripted,batch-process",
|
||||
"title": "Pipeline"
|
||||
},
|
||||
"add-page-numbers": {
|
||||
"tags": "paginate,label,organize,index"
|
||||
},
|
||||
"auto-rename": {
|
||||
"tags": "auto-detect,header-based,organize,relabel",
|
||||
"title": "Auto Rename",
|
||||
"header": "Auto Rename PDF",
|
||||
"submit": "Auto Rename"
|
||||
},
|
||||
"adjust-contrast": {
|
||||
"tags": "color-correction,tune,modify,enhance"
|
||||
},
|
||||
"crop": {
|
||||
"tags": "trim,shrink,edit,shape",
|
||||
"title": "Crop",
|
||||
"header": "Crop Image",
|
||||
"submit": "Submit"
|
||||
},
|
||||
"autoSplitPDF": {
|
||||
"tags": "QR-based,separate,scan-segment,organize",
|
||||
"title": "Auto Split PDF",
|
||||
"header": "Auto Split PDF",
|
||||
"description": "Print, Insert, Scan, upload, and let us auto-separate your documents. No manual work sorting needed.",
|
||||
"selectText": {
|
||||
"1": "Print out some divider sheets from below (Black and white is fine).",
|
||||
"2": "Scan all your documents at once by inserting the divider sheet between them.",
|
||||
"3": "Upload the single large scanned PDF file and let Stirling PDF handle the rest.",
|
||||
"4": "Divider pages are automatically detected and removed, guaranteeing a neat final document."
|
||||
},
|
||||
"formPrompt": "Submit PDF containing Stirling-PDF Page dividers:",
|
||||
"duplexMode": "Duplex Mode (Front and back scanning)",
|
||||
"dividerDownload1": "Download 'Auto Splitter Divider (minimal).pdf'",
|
||||
"dividerDownload2": "Download 'Auto Splitter Divider (with instructions).pdf'",
|
||||
"submit": "Submit"
|
||||
},
|
||||
"sanitizePdf": {
|
||||
"tags": "clean,secure,safe,remove-threats"
|
||||
},
|
||||
"URLToPDF": {
|
||||
"tags": "web-capture,save-page,web-to-doc,archive",
|
||||
"title": "URL To PDF",
|
||||
"header": "URL To PDF",
|
||||
"submit": "Convert",
|
||||
"credit": "Uses WeasyPrint"
|
||||
},
|
||||
"HTMLToPDF": {
|
||||
"tags": "markup,web-content,transformation,convert",
|
||||
"title": "HTML To PDF",
|
||||
"header": "HTML To PDF",
|
||||
"help": "Accepts HTML files and ZIPs containing html/css/images etc required",
|
||||
"submit": "Convert",
|
||||
"credit": "Uses WeasyPrint"
|
||||
},
|
||||
"MarkdownToPDF": {
|
||||
"tags": "markup,web-content,transformation,convert",
|
||||
"title": "Markdown To PDF",
|
||||
"header": "Markdown To PDF",
|
||||
"submit": "Convert",
|
||||
"help": "Work in progress",
|
||||
"credit": "Uses WeasyPrint"
|
||||
},
|
||||
"getPdfInfo": {
|
||||
"tags": "infomation,data,stats,statistics",
|
||||
"title": "Get Info on PDF",
|
||||
"header": "Get Info on PDF",
|
||||
"submit": "Get Info",
|
||||
"downloadJson": "Download JSON"
|
||||
},
|
||||
"extractPage": {
|
||||
"tags": "extract"
|
||||
},
|
||||
"PdfToSinglePage": {
|
||||
"tags": "single page"
|
||||
},
|
||||
"showJS": {
|
||||
"tags": "Redact,Hide,black out,black,marker,hidden",
|
||||
"title": "Show Javascript",
|
||||
"header": "Show Javascript",
|
||||
"downloadJS": "Download Javascript",
|
||||
"submit": "Show"
|
||||
},
|
||||
"login": {
|
||||
"title": "Sign in",
|
||||
"signin": "Sign in",
|
||||
"rememberme": "Remember me",
|
||||
"invalid": "Invalid username or password.",
|
||||
"locked": "Your account has been locked.",
|
||||
"signinTitle": "Please sign in"
|
||||
},
|
||||
"autoRedact": {
|
||||
"title": "Auto Redact",
|
||||
"header": "Auto Redact",
|
||||
"colorLabel": "Colour",
|
||||
"textsToRedactLabel": "Text to Redact (line-separated)",
|
||||
"textsToRedactPlaceholder": "e.g. \\nConfidential \\nTop-Secret",
|
||||
"useRegexLabel": "Use Regex",
|
||||
"wholeWordSearchLabel": "Whole Word Search",
|
||||
"customPaddingLabel": "Custom Extra Padding",
|
||||
"convertPDFToImageLabel": "Convert PDF to PDF-Image (Used to remove text behind the box)",
|
||||
"submitButton": "Submit"
|
||||
},
|
||||
"pdfToSinglePage": {
|
||||
"title": "PDF To Single Page",
|
||||
"header": "PDF To Single Page",
|
||||
"submit": "Convert To Single Page"
|
||||
},
|
||||
"pageExtracter": {
|
||||
"title": "Extract Pages",
|
||||
"header": "Extract Pages",
|
||||
"submit": "Extract"
|
||||
},
|
||||
"sanitizePDF": {
|
||||
"title": "Sanitize PDF",
|
||||
"header": "Sanitize a PDF file",
|
||||
"selectText": {
|
||||
"1": "Remove JavaScript actions",
|
||||
"2": "Remove embedded files",
|
||||
"3": "Remove metadata",
|
||||
"4": "Remove links",
|
||||
"5": "Remove fonts"
|
||||
},
|
||||
"submit": "Sanitize PDF"
|
||||
},
|
||||
"addPageNumbers": {
|
||||
"title": "Add Page Numbers",
|
||||
"header": "Add Page Numbers",
|
||||
"selectText": {
|
||||
"1": "Select PDF file:",
|
||||
"2": "Margin Size",
|
||||
"3": "Position",
|
||||
"4": "Starting Number",
|
||||
"5": "Pages to Number",
|
||||
"6": "Custom Text"
|
||||
},
|
||||
"customTextDesc": "Custom Text",
|
||||
"numberPagesDesc": "Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc",
|
||||
"customNumberDesc": "Defaults to {n}, also accepts 'Page {n} of {total}', 'Text-{n}', '{filename}-{n}",
|
||||
"submit": "Add Page Numbers"
|
||||
},
|
||||
"adjustContrast": {
|
||||
"title": "Adjust Contrast",
|
||||
"header": "Adjust Contrast",
|
||||
"contrast": "Contrast:",
|
||||
"brightness": "Brightness:",
|
||||
"saturation": "Saturation:",
|
||||
"download": "Download"
|
||||
},
|
||||
"compress": {
|
||||
"title": "Compress",
|
||||
"header": "Compress PDF",
|
||||
"credit": "This service uses Ghostscript for PDF Compress/Optimisation.",
|
||||
"selectText": {
|
||||
"1": "Manual Mode - From 1 to 4",
|
||||
"2": "Optimization level:",
|
||||
"3": "4 (Terrible for text images)",
|
||||
"4": "Auto mode - Auto adjusts quality to get PDF to exact size",
|
||||
"5": "Expected PDF Size (e.g. 25MB, 10.8MB, 25KB) "
|
||||
},
|
||||
"submit": "Compress"
|
||||
},
|
||||
"pageRemover": {
|
||||
"title": "Page Remover",
|
||||
"header": "PDF Page remover",
|
||||
"pagesToDelete": "Pages to delete (Enter a comma-separated list of page numbers) :",
|
||||
"submit": "Delete Pages"
|
||||
},
|
||||
"imageToPDF": {
|
||||
"title": "Image to PDF",
|
||||
"header": "Image to PDF",
|
||||
"submit": "Convert",
|
||||
"selectLabel": "Image Fit Options",
|
||||
"fillPage": "Fill Page",
|
||||
"fitDocumentToImage": "Fit Page to Image",
|
||||
"maintainAspectRatio": "Maintain Aspect Ratios",
|
||||
"selectText": {
|
||||
"2": "Auto rotate PDF",
|
||||
"3": "Multi file logic (Only enabled if working with multiple images)",
|
||||
"4": "Merge into single PDF",
|
||||
"5": "Convert to separate PDFs"
|
||||
}
|
||||
},
|
||||
"changeMetadata": {
|
||||
"title": "Title:",
|
||||
"header": "Change Metadata",
|
||||
"selectText": {
|
||||
"1": "Please edit the variables you wish to change",
|
||||
"2": "Delete all metadata",
|
||||
"3": "Show Custom Metadata:",
|
||||
"4": "Other Metadata:",
|
||||
"5": "Add Custom Metadata Entry"
|
||||
},
|
||||
"author": "Author:",
|
||||
"creationDate": "Creation Date (yyyy/MM/dd HH:mm:ss):",
|
||||
"creator": "Creator:",
|
||||
"keywords": "Keywords:",
|
||||
"modDate": "Modification Date (yyyy/MM/dd HH:mm:ss):",
|
||||
"producer": "Producer:",
|
||||
"subject": "Subject:",
|
||||
"trapped": "Trapped:",
|
||||
"submit": "Change"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
14
client-tauri/src/main.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
|
||||
import App from "./App";
|
||||
import "./index.css";
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
<React.StrictMode>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
</React.StrictMode>
|
||||
);
|
||||
10
client-tauri/src/pages/About.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
function About() {
|
||||
return (
|
||||
<div>
|
||||
<h2>About</h2>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default About;
|
||||
49
client-tauri/src/pages/Dashboard.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
|
||||
function Dashboard() {
|
||||
return (
|
||||
<div>
|
||||
<h2>Dashboard</h2>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis aliquet felis in ornare molestie. Quisque et dolor gravida, vulputate libero ultricies, suscipit diam. Pellentesque semper eget purus et rutrum. Duis fringilla elementum tellus, ut egestas nisi ultrices sed. Fusce id elit ipsum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nulla facilisi. Duis varius, orci vel tempor cursus, elit tellus interdum sem, at vulputate lorem ex et dolor. Vestibulum purus mauris, consequat viverra gravida eget, fermentum a lacus. Phasellus eu varius dolor. Etiam a vulputate sapien. Etiam pulvinar, neque eu elementum imperdiet, nibh ex lobortis magna, ut varius lectus ante tristique massa.
|
||||
|
||||
Nullam quis porttitor sapien. Suspendisse dictum enim vitae tristique aliquet. Nunc imperdiet pellentesque quam, sit amet luctus dui dignissim non. Vivamus eleifend sagittis mauris, at imperdiet nisl. Morbi rutrum magna ut tortor euismod efficitur. Pellentesque quis tortor consectetur, lobortis turpis eget, tincidunt turpis. Nulla consectetur massa ex. Donec lectus purus, interdum sit amet sapien eu, maximus dapibus diam. Suspendisse potenti. In lacinia augue massa, et vulputate eros convallis id. Suspendisse bibendum sagittis posuere. Integer ullamcorper odio eget risus venenatis, non mollis arcu lacinia. Vestibulum feugiat arcu elit, eu varius enim fermentum vitae.
|
||||
|
||||
Morbi rutrum metus magna, ac tempor enim posuere sit amet. Vivamus laoreet, ligula a maximus mattis, eros justo ultrices libero, eget congue enim mi vel massa. Nunc finibus tempor lacus, ac condimentum neque vehicula sit amet. Maecenas vestibulum, eros ut fringilla interdum, nisi metus vestibulum libero, efficitur lacinia massa risus et orci. Nulla orci magna, efficitur a iaculis nec, consequat eu lorem. Maecenas faucibus, diam ut vehicula tincidunt, nulla ipsum dictum magna, quis lobortis felis lacus ac felis. Suspendisse a luctus nunc. Aliquam eget nisi non libero gravida gravida. Etiam massa metus, posuere vel dui eu, malesuada aliquam purus. Maecenas sed sagittis sapien. Integer vel posuere nunc, sit amet venenatis mi.
|
||||
|
||||
Donec vitae ipsum ut velit bibendum ultricies et ut est. Maecenas ac felis commodo, hendrerit sapien ut, molestie sapien. Sed rhoncus dui ut porta volutpat. Fusce in arcu id leo dignissim dignissim. Aenean pharetra ullamcorper tristique. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris convallis ultrices ante pellentesque pellentesque. Proin sed efficitur neque, ut sollicitudin neque. Sed sollicitudin dui diam, vitae fringilla eros bibendum vitae. Duis in augue nec enim pharetra lacinia nec quis nisi. Suspendisse pellentesque et quam a volutpat. Integer consectetur, tellus non feugiat sollicitudin, nibh nisl fringilla felis, at imperdiet turpis orci ut ex. Nam malesuada diam turpis. Phasellus blandit sodales suscipit. Sed condimentum placerat mi blandit ultrices. Integer egestas eleifend blandit.
|
||||
|
||||
Morbi massa sem, efficitur dapibus sapien quis, mollis auctor lorem. Maecenas eget fringilla sem, vitae scelerisque tellus. Nulla orci ante, consequat interdum ornare sit amet, finibus sed lorem. Nunc vulputate ante placerat, porttitor dui sit amet, elementum libero. Maecenas hendrerit, neque et iaculis tristique, arcu felis porta libero, et luctus est enim a arcu. In blandit magna turpis, lobortis accumsan sem pellentesque a. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Ut dui urna, finibus eu tincidunt a, dignissim a metus.
|
||||
|
||||
Ut condimentum eros eu hendrerit aliquam. Vestibulum faucibus, ipsum et posuere tempor, ante sem cursus ante, non facilisis libero arcu ac nisi. Sed porttitor non mi nec tristique. Donec et ligula tincidunt, congue felis et, vehicula ipsum. Integer eget nunc in lectus volutpat ultrices. Praesent malesuada velit vel enim egestas, eu auctor mauris maximus. Proin pretium odio lacus, ac fermentum erat fermentum id.
|
||||
|
||||
Integer congue odio sit amet efficitur scelerisque. Nunc elit arcu, pulvinar vitae aliquam id, aliquet eget tortor. Donec ullamcorper condimentum libero, vel iaculis elit. Maecenas vestibulum fermentum tellus, auctor vestibulum leo volutpat et. Quisque ac mauris tristique, placerat augue et, cursus nunc. Sed nec lacinia lacus. Nam congue quam non nisl fermentum, nec lobortis nulla lobortis. Donec id neque a nibh tempus interdum in eget metus.
|
||||
|
||||
Sed sed ligula sapien. Phasellus non tempor mauris, ac tempor velit. Suspendisse potenti. Nullam tempus enim purus, ac hendrerit odio lobortis vitae. Curabitur sit amet facilisis nisi. In tristique porttitor sem et sollicitudin. Etiam ut tortor hendrerit tortor blandit porttitor. In pretium ex nec arcu scelerisque, id cursus tortor ultrices. Suspendisse potenti.
|
||||
|
||||
Ut dictum velit felis, vitae efficitur arcu varius lobortis. Etiam aliquet quam vel elementum pulvinar. Morbi ultricies nulla sit amet neque mattis, eget viverra elit laoreet. Vivamus elementum eros ipsum, vitae laoreet lacus accumsan at. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed vel turpis in arcu condimentum porta vel et eros. Maecenas luctus euismod mauris ac tincidunt. Nulla rutrum efficitur sollicitudin. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec et venenatis lorem. Sed malesuada tincidunt consequat. Phasellus vitae ex magna. Quisque ac hendrerit tellus, sed convallis velit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Ut imperdiet tempor dui, et sodales leo malesuada eget. Curabitur at finibus neque, vel efficitur ante.
|
||||
|
||||
Suspendisse a pellentesque arcu. Mauris tempus posuere dui, vitae consectetur neque tristique ut. Duis imperdiet pulvinar lacus, ac porttitor diam. Praesent congue justo ut ex tincidunt, non pellentesque justo hendrerit. Etiam volutpat neque ut neque lacinia, quis dapibus tortor pulvinar. Etiam vestibulum tincidunt augue id lacinia. Nullam et fermentum ligula.
|
||||
|
||||
Donec aliquet egestas elementum. Proin volutpat massa eu libero cursus, ut tincidunt enim convallis. Fusce ut magna nec odio feugiat auctor. Donec id libero eget quam finibus vestibulum et nec lectus. Duis et mattis arcu. Nam sit amet dolor eget est consequat euismod sed egestas enim. Fusce scelerisque ligula ut imperdiet mollis.
|
||||
|
||||
Sed fermentum tellus feugiat, pretium tellus et, ullamcorper libero. Curabitur et justo quis odio efficitur euismod. Vivamus elementum sagittis odio euismod lobortis. Curabitur nec nunc eget ipsum malesuada gravida. Maecenas dignissim mauris sapien, quis malesuada ante condimentum in. In suscipit blandit turpis vitae congue. Aenean dignissim tempus finibus.
|
||||
|
||||
Donec lacinia sapien risus, quis efficitur sapien vestibulum eget. Ut vehicula est in scelerisque pretium. Maecenas feugiat tempor urna a lobortis. Duis ac libero quis massa sodales rutrum. Suspendisse fermentum pellentesque nibh, pulvinar rutrum purus tempus consectetur. Donec non elementum diam. Aliquam et justo vitae quam tincidunt molestie. Mauris nec arcu erat. Mauris a justo ipsum. Maecenas consectetur nunc nec lobortis lacinia. Integer quis enim risus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Aliquam consequat, sem quis gravida semper, mauris est pretium nunc, a malesuada erat dolor eget metus. Ut pretium consectetur consequat. Quisque non mollis purus, in facilisis eros.
|
||||
|
||||
Sed aliquam nunc id lorem gravida, non sagittis ligula ultrices. Ut vel risus congue, aliquet lacus eget, ullamcorper arcu. Morbi ullamcorper scelerisque risus eu molestie. Curabitur non dapibus risus. In in libero massa. Etiam sed mi ultrices, lacinia justo nec, gravida est. Sed vehicula sollicitudin ullamcorper. Suspendisse potenti. Etiam non metus malesuada, dictum risus venenatis, fringilla nunc.
|
||||
|
||||
Ut vel ante volutpat justo luctus sollicitudin. Quisque sit amet sagittis velit, quis ultrices elit. Nam euismod, enim vel suscipit pharetra, nisl quam porta nisi, ac mollis eros ante ut lectus. Ut sagittis ex eget diam efficitur commodo. Suspendisse mattis eros ligula, eu facilisis ipsum cursus ac. Nullam imperdiet id diam vel ultrices. Nullam nunc purus, aliquet ac ornare at, posuere id lacus. Sed ex leo, sollicitudin ac velit id, pulvinar lacinia nunc. Nullam molestie faucibus lectus, sed molestie sem vehicula et. Sed justo eros, ullamcorper eu hendrerit ac, vehicula at est. Morbi ut sem iaculis, ultricies lacus eu, tincidunt metus.
|
||||
|
||||
Nullam hendrerit consectetur pulvinar. Praesent id orci feugiat, congue libero sit amet, ultricies neque. Suspendisse magna elit, mattis in mauris eu, porta sollicitudin enim. Cras sagittis lacinia nunc, sed aliquet augue condimentum quis. Proin eu dui at libero pharetra finibus et ac sem. Aliquam euismod, enim eget elementum mattis, lorem tellus maximus nibh, vel malesuada felis nulla nec mi. Aliquam a neque ut ex dapibus accumsan. Donec vitae bibendum mi. Donec blandit ante at dui condimentum, et congue leo luctus. Sed sapien est, accumsan et tellus in, tincidunt vehicula sapien. Curabitur iaculis pharetra urna ac molestie. Proin in enim orci. Vestibulum scelerisque, risus ut tincidunt mollis, dolor mi pretium dui, in fermentum est sapien et lacus. Fusce tincidunt orci nulla, sed gravida massa facilisis sit amet. Proin eget finibus diam. Nunc vitae diam interdum, rhoncus nulla eu, pulvinar ex.
|
||||
|
||||
Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vivamus ultrices pharetra magna eget malesuada. Ut vel mauris nibh. Integer maximus purus vitae ante elementum congue. Nam fringilla consectetur condimentum. Nunc pulvinar lobortis sem, sit amet egestas sem vulputate in. Curabitur eleifend mi vitae ipsum aliquam congue. Nullam lobortis aliquet euismod. Praesent augue lacus, dapibus sit amet venenatis sed, hendrerit dictum felis. Donec tristique, lectus nec cursus tincidunt, sem justo condimentum ligula, vel feugiat felis leo ut tortor. Donec sed est ac tortor pharetra pulvinar. Pellentesque scelerisque augue quis commodo congue. Etiam eget tempus sapien. Nullam ex ligula, venenatis sed felis vel, scelerisque fermentum nibh. In felis quam, vulputate ac dignissim ut, scelerisque et quam.
|
||||
|
||||
Proin faucibus efficitur sollicitudin. Curabitur pharetra lectus ut metus molestie, eget rutrum velit laoreet. Duis sit amet tellus sem. In pretium egestas massa eu pharetra. Vestibulum suscipit, nibh sit amet tincidunt feugiat, quam mauris scelerisque lorem, quis commodo ex libero in tellus. Donec tellus erat, tempor id fringilla sed, vehicula ac nibh. Curabitur nisi lacus, maximus id lorem vitae, faucibus faucibus massa. Nulla dictum molestie dolor, finibus commodo est lobortis id. Ut nec dapibus purus. Curabitur quis ligula tincidunt, hendrerit risus eu, tristique ipsum. Morbi neque est, pharetra ut pharetra non, semper id justo. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Pellentesque tempor erat elit, non viverra tortor malesuada eget. Aliquam et efficitur lorem, ac euismod dui.
|
||||
|
||||
Aenean tincidunt scelerisque ante non vestibulum. Curabitur eleifend ipsum sem, elementum ornare enim ornare eu. In molestie sodales mattis. Morbi ac posuere lorem. Aliquam in nisi ac ipsum euismod bibendum eget id urna. Quisque suscipit lectus non magna varius venenatis sed sit amet lectus. Nam leo nisl, imperdiet at lorem fringilla, lacinia bibendum lacus. Nunc auctor mauris at orci condimentum venenatis at non augue. Donec iaculis aliquam risus. Suspendisse vel massa leo.
|
||||
|
||||
Mauris sed est turpis. Nullam ut magna eu elit vehicula tempus. Sed mollis ultrices eleifend. Curabitur metus felis, sodales a turpis accumsan, ultricies feugiat arcu. Donec sit amet dui commodo, lacinia sem facilisis, lobortis urna. Donec cursus arcu ex, ac imperdiet lorem rutrum at. Curabitur faucibus erat in dolor placerat, vel blandit ligula eleifend. Morbi blandit nisl ut arcu semper consequat. Nulla malesuada convallis lectus a egestas. Sed volutpat metus vitae libero pulvinar, ut pretium magna malesuada.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Dashboard;
|
||||
10
client-tauri/src/pages/Home.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
function Home() {
|
||||
return (
|
||||
<div>
|
||||
<h2>Home</h2>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Home;
|
||||
14
client-tauri/src/pages/NoMatch.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
function NoMatch() {
|
||||
return (
|
||||
<div>
|
||||
<h2>Nothing to see here!</h2>
|
||||
<p>
|
||||
<Link to="/">Go to the home page 3</Link>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default NoMatch;
|
||||
16
client-tauri/src/pages/convert/ToPdf.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
import { isLibreOfficeInstalled } from "../../utils/libre-office-utils";
|
||||
|
||||
const hasLibreOffice = await isLibreOfficeInstalled();
|
||||
console.log(hasLibreOffice)
|
||||
|
||||
function About() {
|
||||
return (
|
||||
<div>
|
||||
<h2>Convert to PDF</h2>
|
||||
{"hasLibreOffice: "+hasLibreOffice}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default About;
|
||||
9
client-tauri/src/utils/file-utils.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
|
||||
export function appendToFilename(inputPath: string, toAppend: string) {
|
||||
const parts = inputPath.split('.');
|
||||
if (parts.length > 1) {
|
||||
parts[parts.length-2] = parts[parts.length-2] + toAppend;
|
||||
}
|
||||
return parts.join(".");
|
||||
}
|
||||
46
client-tauri/src/utils/libre-office-utils.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
import { readBinaryFile, writeBinaryFile, removeDir, BaseDirectory } from '@tauri-apps/api/fs';
|
||||
import { PdfFile,RepresentationType } from '@stirling-pdf/shared-operations/src/wrappers/PdfFile'
|
||||
import { runShell } from './tauri-wrapper';
|
||||
|
||||
export async function fileToPdf(byteArray: Uint8Array, filename: string): Promise<PdfFile> {
|
||||
const randUuid = crypto.randomUUID();
|
||||
const tempDir = "StirlingPDF/"+randUuid;
|
||||
const srcFile = tempDir+"/"+filename;
|
||||
|
||||
await writeBinaryFile(srcFile, byteArray);
|
||||
await writeBinaryFile(srcFile, new Uint8Array([]), { dir: BaseDirectory.Temp });
|
||||
|
||||
const messageList: string[] = [];
|
||||
await runShell("libreoffice-convert", ["--headless","--convert-to","pdf",srcFile,"--outdir",tempDir], (message, stream) => {
|
||||
if (stream === "stdout") {
|
||||
messageList.push(message);
|
||||
}
|
||||
console.debug(`${stream}, ${randUuid}: ${message}`);
|
||||
});
|
||||
const lastMessage = messageList[messageList.length-1]
|
||||
const outputFilePath = lastMessage.split(" -> ")[1].split(".pdf")[0]+".pdf";
|
||||
const outputFilePathSplit = outputFilePath.toString().split("[\\/]")
|
||||
const outputFileName = outputFilePathSplit[outputFilePathSplit.length-1];
|
||||
const outputBytes = await readBinaryFile(outputFilePath);
|
||||
|
||||
await removeDir(tempDir);
|
||||
|
||||
return new PdfFile(outputFileName, outputBytes, RepresentationType.Uint8Array);
|
||||
}
|
||||
|
||||
export async function isLibreOfficeInstalled() {
|
||||
const messageList: string[] = [];
|
||||
try {
|
||||
await runShell("libreoffice-version", ["--version"], (message, stream) => {
|
||||
if (stream === "stdout") {
|
||||
messageList.push(message);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
console.log("messageList", messageList)
|
||||
const result = messageList[0].match("LibreOffice ([0-9]+\.){4}.*");
|
||||
return result ? true : false;
|
||||
}
|
||||
17
client-tauri/src/utils/pdf-operations.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
import SharedOperations, { OperationsType } from '@stirling-pdf/shared-operations/src'
|
||||
import { ImposeParamsType } from '@stirling-pdf/shared-operations/src/functions/impose'
|
||||
import { PdfFile } from "@stirling-pdf/shared-operations/src/wrappers/PdfFile"
|
||||
|
||||
// Import injected libraries here!
|
||||
import * as pdfcpuWrapper from "@stirling-pdf/shared-operations/wasm/pdfcpu/pdfcpu-wrapper-browser.js";
|
||||
|
||||
async function impose(params: ImposeParamsType): Promise<PdfFile> {
|
||||
return SharedOperations.impose(params, pdfcpuWrapper);
|
||||
}
|
||||
|
||||
const toExport: OperationsType = {
|
||||
...SharedOperations,
|
||||
impose,
|
||||
}
|
||||
export default toExport;
|
||||
169
client-tauri/src/utils/tauri-wrapper.ts
Normal file
@@ -0,0 +1,169 @@
|
||||
|
||||
import { open, save } from '@tauri-apps/api/dialog';
|
||||
import { readBinaryFile, writeBinaryFile } from '@tauri-apps/api/fs';
|
||||
import { Command } from '@tauri-apps/api/shell'
|
||||
|
||||
export type TauriBrowserFile = {
|
||||
name: string,
|
||||
relativePath?: string,
|
||||
data: Uint8Array,
|
||||
getPath: ()=>string
|
||||
}
|
||||
function byteArrayToFile(byteArray: Uint8Array, filePath: string): TauriBrowserFile | null {
|
||||
const separator = filePath.includes("\\") ? "\\" : "/";
|
||||
|
||||
const split = filePath.split(separator);
|
||||
const fileName = split.pop();
|
||||
const path = split.join(separator);
|
||||
if (!fileName) return null;
|
||||
return {
|
||||
name: fileName,
|
||||
data: byteArray,
|
||||
relativePath: path?path:undefined,
|
||||
getPath: ()=> (path?path:undefined) + separator + fileName,
|
||||
};
|
||||
}
|
||||
|
||||
export function isTauriAvailable() {
|
||||
return (window as any).__TAURI_IPC__ ? true : false;
|
||||
}
|
||||
|
||||
// [*] = Not available in browser
|
||||
type SelectFilesDialogOptions = {
|
||||
defaultPath?: string, // [*] the default path to open the dialog on
|
||||
directory?: boolean, // should the dialog be a directory dialog
|
||||
filters?: Array<{ // list of file type filters
|
||||
name: string, // category name eg. 'Images'
|
||||
extensions: string[] // list of extensions eg ['png', 'jpeg', 'jpg']
|
||||
}>,
|
||||
multiple?: boolean, // allow multiple selections
|
||||
recursive?: boolean, // [*] If directory is true, indicates that it will be read recursively later. Defines whether subdirectories will be allowed on the scope or not.
|
||||
title?: string // [*] the title of the dialog
|
||||
}
|
||||
export function openFiles(options: SelectFilesDialogOptions): Promise<TauriBrowserFile[] | null> {
|
||||
return new Promise(async (resolve) => {
|
||||
if (isTauriAvailable()) {
|
||||
var selected = await open(options);
|
||||
if (!selected) {
|
||||
resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Array.isArray(selected)) {
|
||||
selected = [selected];
|
||||
}
|
||||
|
||||
const files: TauriBrowserFile[] = [];
|
||||
for (const s of selected) {
|
||||
const contents = await readBinaryFile(s);
|
||||
const res = byteArrayToFile(contents, s);
|
||||
if (res) {
|
||||
files.push(res);
|
||||
}
|
||||
}
|
||||
|
||||
resolve(files);
|
||||
return;
|
||||
} else {
|
||||
var input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
if (options.directory) input.setAttribute("webkitdirectory", "");
|
||||
if (options.filters) input.setAttribute("accept", options.filters.flatMap(f => f.extensions).map(ext => "."+ext).join(", "));
|
||||
if (options.multiple) input.setAttribute("multiple", "");
|
||||
|
||||
input.onchange = async () => {
|
||||
if (input.files && input.files.length) {
|
||||
console.log("input.files", input.files)
|
||||
const files: TauriBrowserFile[] = [];
|
||||
for (const f of input.files) {
|
||||
const contents = new Uint8Array(await f.arrayBuffer());
|
||||
const res = byteArrayToFile(contents, f.name);
|
||||
if (res) {
|
||||
files.push(res);
|
||||
}
|
||||
}
|
||||
|
||||
resolve(files);
|
||||
}
|
||||
input.onchange = null;
|
||||
document.body.onfocus = null;
|
||||
};
|
||||
|
||||
// detect the user clicking cancel
|
||||
document.body.onfocus = () => {
|
||||
setTimeout(()=>resolve(null), 200); // the timeout is needed because 'document.body.onfocus' is called before 'input.onchange'
|
||||
}
|
||||
|
||||
input.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// [*] = Not available in browser
|
||||
type DownloadFilesDialogOptions = {
|
||||
defaultPath?: string, // the default path to open the dialog on
|
||||
filters?: Array<{ // [*] list of file type filters
|
||||
name: string, // category name eg. 'Images'
|
||||
extensions: string[] // list of extensions eg ['png', 'jpeg', 'jpg']
|
||||
}>,
|
||||
title?: string // [*] the title of the dialog
|
||||
}
|
||||
export async function downloadFile(fileData: Uint8Array, options: DownloadFilesDialogOptions): Promise<undefined> {
|
||||
if (isTauriAvailable()) {
|
||||
const pathToSave = await save(options);
|
||||
console.log("pathToSave", pathToSave)
|
||||
if (pathToSave) {
|
||||
await writeBinaryFile(pathToSave, fileData);
|
||||
}
|
||||
} else {
|
||||
const pdfBlob = new Blob([fileData], { type: 'application/pdf' });
|
||||
const url = URL.createObjectURL(pdfBlob);
|
||||
const downloadOption = localStorage.getItem('downloadOption');
|
||||
|
||||
// ensure filename is not a path
|
||||
const separator = options.defaultPath?.includes("\\") ? "\\" : "/";
|
||||
const filename = options.defaultPath?.split(separator).pop();
|
||||
const filenameToUse = filename ? filename : 'edited.pdf';
|
||||
|
||||
if (downloadOption === 'sameWindow') {
|
||||
// Open the file in the same window
|
||||
window.location.href = url;
|
||||
} else if (downloadOption === 'newWindow') {
|
||||
// Open the file in a new window
|
||||
window.open(url, '_blank');
|
||||
} else {
|
||||
// Download the file
|
||||
const downloadLink = document.createElement('a');
|
||||
downloadLink.href = url;
|
||||
downloadLink.download = filenameToUse;
|
||||
downloadLink.click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dont forget to whitelist the Command in src-tauri/tauri.conf.json! (tauri.allowlist.shell.scope)
|
||||
* @param commandName The name of the command to run. Must be defined in tauri.allowlist.shell.scope[].name
|
||||
* @param args The args to pass into the command
|
||||
* @param callback A callback function that is called when output is logged
|
||||
* @returns A log of all the outputs logged
|
||||
*/
|
||||
export function runShell(commandName: string, args: string[], callback: (message: any, stream:"stdout"|"stderr"|"error") => void): Promise<void> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
|
||||
const comm = new Command(commandName, args);
|
||||
comm.on('close', data => {
|
||||
if (data.code === 0) {
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error(`Command failed with exit code ${data.code} and signal ${data.signal}`));
|
||||
}
|
||||
});
|
||||
comm.on('error', error => callback(error, "error"));
|
||||
comm.stdout.on('data', line => callback(line, "stdout"));
|
||||
comm.stderr.on('data', line => callback(line, "stderr"));
|
||||
|
||||
const child = await comm.spawn();
|
||||
console.debug(`Started child process with pid: ${child.pid}`)
|
||||
});
|
||||
}
|
||||
1
client-tauri/src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
28
client-tauri/tsconfig.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": [
|
||||
"src",
|
||||
"declarations/*.d.ts"
|
||||
],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
10
client-tauri/tsconfig.node.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
29
client-tauri/vite.config.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { defineConfig } from "vite";
|
||||
import react from "@vitejs/plugin-react";
|
||||
import topLevelAwait from "vite-plugin-top-level-await";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(async () => ({
|
||||
plugins: [
|
||||
react(),
|
||||
topLevelAwait({
|
||||
// The export name of top-level await promise for each chunk module
|
||||
promiseExportName: "__tla",
|
||||
// The function to generate import names of top-level await promise in each chunk module
|
||||
promiseImportName: i => `__tla_${i}`
|
||||
}),
|
||||
],
|
||||
|
||||
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
|
||||
//
|
||||
// 1. prevent vite from obscuring rust errors
|
||||
clearScreen: false,
|
||||
// 2. tauri expects a fixed port, fail if that port is not available
|
||||
server: {
|
||||
port: 1420,
|
||||
strictPort: true,
|
||||
},
|
||||
// 3. to make use of `TAURI_DEBUG` and other env variables
|
||||
// https://tauri.app/v1/api/config#buildconfig.beforedevcommand
|
||||
envPrefix: ["VITE_"],
|
||||
}));
|
||||
13
client-vanilla/index.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import express from 'express';
|
||||
const app = express();
|
||||
const PORT = 80;
|
||||
|
||||
// Server Frontend TODO: Make this typescript compatible
|
||||
app.use(express.static('../client-vanilla/public'));
|
||||
app.use(express.static('../shared-operations'));
|
||||
|
||||
// serve
|
||||
app.listen(PORT, function (err) {
|
||||
if (err) console.log(err);
|
||||
console.log(`http://localhost:${PORT}`);
|
||||
});
|
||||
167
client-vanilla/public/dep/downloadjs_1.4.7.js
Normal file
@@ -0,0 +1,167 @@
|
||||
//download.js v4.2, by dandavis; 2008-2016. [MIT] see http://danml.com/download.html for tests/usage
|
||||
// v1 landed a FF+Chrome compat way of downloading strings to local un-named files, upgraded to use a hidden frame and optional mime
|
||||
// v2 added named files via a[download], msSaveBlob, IE (10+) support, and window.URL support for larger+faster saves than dataURLs
|
||||
// v3 added dataURL and Blob Input, bind-toggle arity, and legacy dataURL fallback was improved with force-download mime and base64 support. 3.1 improved safari handling.
|
||||
// v4 adds AMD/UMD, commonJS, and plain browser support
|
||||
// v4.1 adds url download capability via solo URL argument (same domain/CORS only)
|
||||
// v4.2 adds semantic variable names, long (over 2MB) dataURL support, and hidden by default temp anchors
|
||||
// https://github.com/rndme/download
|
||||
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define([], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node. Does not work with strict CommonJS, but
|
||||
// only CommonJS-like environments that support module.exports,
|
||||
// like Node.
|
||||
module.exports = factory();
|
||||
} else {
|
||||
// Browser globals (root is window)
|
||||
root.download = factory();
|
||||
}
|
||||
}(this, function () {
|
||||
|
||||
return function download(data, strFileName, strMimeType) {
|
||||
|
||||
var self = window, // this script is only for browsers anyway...
|
||||
defaultMime = "application/octet-stream", // this default mime also triggers iframe downloads
|
||||
mimeType = strMimeType || defaultMime,
|
||||
payload = data,
|
||||
url = !strFileName && !strMimeType && payload,
|
||||
anchor = document.createElement("a"),
|
||||
toString = function(a){return String(a);},
|
||||
myBlob = (self.Blob || self.MozBlob || self.WebKitBlob || toString),
|
||||
fileName = strFileName || "download",
|
||||
blob,
|
||||
reader;
|
||||
myBlob= myBlob.call ? myBlob.bind(self) : Blob ;
|
||||
|
||||
if(String(this)==="true"){ //reverse arguments, allowing download.bind(true, "text/xml", "export.xml") to act as a callback
|
||||
payload=[payload, mimeType];
|
||||
mimeType=payload[0];
|
||||
payload=payload[1];
|
||||
}
|
||||
|
||||
|
||||
if(url && url.length< 2048){ // if no filename and no mime, assume a url was passed as the only argument
|
||||
fileName = url.split("/").pop().split("?")[0];
|
||||
anchor.href = url; // assign href prop to temp anchor
|
||||
if(anchor.href.indexOf(url) !== -1){ // if the browser determines that it's a potentially valid url path:
|
||||
var ajax=new XMLHttpRequest();
|
||||
ajax.open( "GET", url, true);
|
||||
ajax.responseType = 'blob';
|
||||
ajax.onload= function(e){
|
||||
download(e.target.response, fileName, defaultMime);
|
||||
};
|
||||
setTimeout(function(){ ajax.send();}, 0); // allows setting custom ajax headers using the return:
|
||||
return ajax;
|
||||
} // end if valid url?
|
||||
} // end if url?
|
||||
|
||||
|
||||
//go ahead and download dataURLs right away
|
||||
if(/^data:([\w+-]+\/[\w+.-]+)?[,;]/.test(payload)){
|
||||
|
||||
if(payload.length > (1024*1024*1.999) && myBlob !== toString ){
|
||||
payload=dataUrlToBlob(payload);
|
||||
mimeType=payload.type || defaultMime;
|
||||
}else{
|
||||
return navigator.msSaveBlob ? // IE10 can't do a[download], only Blobs:
|
||||
navigator.msSaveBlob(dataUrlToBlob(payload), fileName) :
|
||||
saver(payload) ; // everyone else can save dataURLs un-processed
|
||||
}
|
||||
|
||||
}else{//not data url, is it a string with special needs?
|
||||
if(/([\x80-\xff])/.test(payload)){
|
||||
var i=0, tempUiArr= new Uint8Array(payload.length), mx=tempUiArr.length;
|
||||
for(i;i<mx;++i) tempUiArr[i]= payload.charCodeAt(i);
|
||||
payload=new myBlob([tempUiArr], {type: mimeType});
|
||||
}
|
||||
}
|
||||
blob = payload instanceof myBlob ?
|
||||
payload :
|
||||
new myBlob([payload], {type: mimeType}) ;
|
||||
|
||||
|
||||
function dataUrlToBlob(strUrl) {
|
||||
var parts= strUrl.split(/[:;,]/),
|
||||
type= parts[1],
|
||||
decoder= parts[2] == "base64" ? atob : decodeURIComponent,
|
||||
binData= decoder( parts.pop() ),
|
||||
mx= binData.length,
|
||||
i= 0,
|
||||
uiArr= new Uint8Array(mx);
|
||||
|
||||
for(i;i<mx;++i) uiArr[i]= binData.charCodeAt(i);
|
||||
|
||||
return new myBlob([uiArr], {type: type});
|
||||
}
|
||||
|
||||
function saver(url, winMode){
|
||||
|
||||
if ('download' in anchor) { //html5 A[download]
|
||||
anchor.href = url;
|
||||
anchor.setAttribute("download", fileName);
|
||||
anchor.className = "download-js-link";
|
||||
anchor.innerHTML = "downloading...";
|
||||
anchor.style.display = "none";
|
||||
document.body.appendChild(anchor);
|
||||
setTimeout(function() {
|
||||
anchor.click();
|
||||
document.body.removeChild(anchor);
|
||||
if(winMode===true){setTimeout(function(){ self.URL.revokeObjectURL(anchor.href);}, 250 );}
|
||||
}, 66);
|
||||
return true;
|
||||
}
|
||||
|
||||
// handle non-a[download] safari as best we can:
|
||||
if(/(Version)\/(\d+)\.(\d+)(?:\.(\d+))?.*Safari\//.test(navigator.userAgent)) {
|
||||
if(/^data:/.test(url)) url="data:"+url.replace(/^data:([\w\/\-\+]+)/, defaultMime);
|
||||
if(!window.open(url)){ // popup blocked, offer direct download:
|
||||
if(confirm("Displaying New Document\n\nUse Save As... to download, then click back to return to this page.")){ location.href=url; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//do iframe dataURL download (old ch+FF):
|
||||
var f = document.createElement("iframe");
|
||||
document.body.appendChild(f);
|
||||
|
||||
if(!winMode && /^data:/.test(url)){ // force a mime that will download:
|
||||
url="data:"+url.replace(/^data:([\w\/\-\+]+)/, defaultMime);
|
||||
}
|
||||
f.src=url;
|
||||
setTimeout(function(){ document.body.removeChild(f); }, 333);
|
||||
|
||||
}//end saver
|
||||
|
||||
|
||||
|
||||
|
||||
if (navigator.msSaveBlob) { // IE10+ : (has Blob, but not a[download] or URL)
|
||||
return navigator.msSaveBlob(blob, fileName);
|
||||
}
|
||||
|
||||
if(self.URL){ // simple fast and modern way using Blob and URL:
|
||||
saver(self.URL.createObjectURL(blob), true);
|
||||
}else{
|
||||
// handle non-Blob()+non-URL browsers:
|
||||
if(typeof blob === "string" || blob.constructor===toString ){
|
||||
try{
|
||||
return saver( "data:" + mimeType + ";base64," + self.btoa(blob) );
|
||||
}catch(y){
|
||||
return saver( "data:" + mimeType + "," + encodeURIComponent(blob) );
|
||||
}
|
||||
}
|
||||
|
||||
// Blob but not URL support:
|
||||
reader=new FileReader();
|
||||
reader.onload=function(e){
|
||||
saver(this.result);
|
||||
};
|
||||
reader.readAsDataURL(blob);
|
||||
}
|
||||
return true;
|
||||
}; /* end download() */
|
||||
}));
|
||||