Compare commits
1074 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 | |||
| e40e47df7d | |||
| 2146e5c8a8 | |||
| c9cb1959b3 | |||
| cab3fe1bf4 | |||
| 53057f4e18 | |||
| 57b12ffcc3 | |||
| 4c88c1bc54 | |||
| a7b8e50159 | |||
| 2c8e86297f | |||
| 6a0c5914e9 | |||
| 38925ea4ca | |||
| b123e8eba5 | |||
| f093d65729 | |||
| 4a95e001bb | |||
| 6662115d10 | |||
| 58423bfc21 | |||
| fe3088acfc | |||
| dd11cfab40 | |||
| effbb3a047 | |||
| c667c77582 | |||
| ae50611acc | |||
| f6feb7a7e7 | |||
| 0a67da2c76 | |||
| defe6ef1e5 | |||
| f00df02b21 | |||
| 5275866f09 | |||
| 1937a83531 | |||
| a2dc64142d | |||
| 1a0dd6fefe | |||
| bcc10b0186 | |||
| ca1127a988 | |||
| 43da32a91c | |||
| c5dd94f3e3 | |||
| 2d37b8104e | |||
| 523503a100 | |||
| 072053f794 | |||
| 35e2e743d9 | |||
| af2fa55d9b | |||
| 852fff588d | |||
| 6f981e1a29 | |||
| d1949d8eb4 | |||
| aa79741e8e | |||
| bac4306e78 | |||
| 9d89621cfd | |||
| b2bbe2b4f3 | |||
| d8d2b0072c | |||
| cd29ee4e21 | |||
| 08d9409d2c | |||
| 1f1f50a615 | |||
| 81f031a2ca | |||
| 0b09ef16b2 | |||
| 59d8e66921 | |||
| 624e0e3619 | |||
| 9836c2f281 | |||
| cd4bd2a796 | |||
| b56e5a0e05 | |||
| ab50b625d4 | |||
| 957241043e | |||
| 5c41c952b6 | |||
| cada1fd80f | |||
| ae638eec94 | |||
| d63d61878d | |||
| 8b007072fe | |||
| 98c1224598 | |||
| 1e194cc837 | |||
| 6e0bb8e312 | |||
| ec5cca71b9 | |||
| ce09227951 | |||
| 40f7862fe1 | |||
| 44a0137818 | |||
| d8458607a2 | |||
| df0ad86d28 | |||
| fb8f825d42 | |||
| 967846ec3a | |||
| 5f3cba6037 | |||
| 5fd66417b9 | |||
| cb55af1fa7 | |||
| 79223a8140 | |||
| 5188c4bd9c | |||
| 1fb520ff57 | |||
| ff85036367 | |||
| a42baf5600 | |||
| b078905889 | |||
| d70aec5daa |
@@ -0,0 +1,2 @@
|
||||
# All PRs must be approved by one of the main v2 developers
|
||||
* @Frooodle @Sf298 @LaserKaspar @sbplat
|
||||
@@ -0,0 +1,7 @@
|
||||
node_modules/
|
||||
*.code-workspace
|
||||
.idea/
|
||||
dist/
|
||||
android/
|
||||
ios/
|
||||
releases/
|
||||
@@ -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,20 +1,223 @@
|
||||
## Usage
|
||||
|
||||
[Helm](https://helm.sh) must be installed to use the charts. Please refer to
|
||||
Helm's [documentation](https://helm.sh/docs) to get started.
|
||||
|
||||
Once Helm has been set up correctly, add the repo as follows:
|
||||
|
||||
`helm repo add <alias> https://docs.stirlingpdf.com/Stirling-PDF`
|
||||
|
||||
If you had already added this repo earlier, run `helm repo update` to retrieve
|
||||
the latest versions of the packages. You can then run `helm search repo <alias>` to see the charts.
|
||||
|
||||
To install the <chart-name> chart:
|
||||
|
||||
helm install <chart-name> <alias>/<chart-name>
|
||||
|
||||
To uninstall the chart:
|
||||
|
||||
helm delete <chart-name>
|
||||
|
||||
# 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.
|
||||
|
||||
## Try the new API!
|
||||
|
||||
[](https://documenter.getpostman.com/view/30633786/2s9YRB1Wto)
|
||||
|
||||
## 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
|
||||
|
||||
### Rewrite Roadmap
|
||||
|
||||
* [x] Client side PDF-Manipulation
|
||||
* [x] Workflows
|
||||
* [ ] Feature equivalent with S-PDF v1
|
||||
* [ ] Stateful UI
|
||||
* [ ] Node based editing of Workflows
|
||||
* [ ] Propper auth using passportjs
|
||||
|
||||
### Functions
|
||||
|
||||
Current functions of spdf and their progress in this repo.
|
||||
|
||||
#### 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 | |
|
||||
|
||||
|
||||
#### 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 | |
|
||||
|
||||
#### Security
|
||||
| Status | Feature | Description |
|
||||
| ------ | --------------------- | ----------- |
|
||||
| ❌ | Add Password | |
|
||||
| ❌ | Remove Password | |
|
||||
| ❌ | Change Permissions | |
|
||||
| ❌ | Add Watermark | |
|
||||
| ❌ | Sign with Certificate | |
|
||||
| ❌ | Sanitize | |
|
||||
| ❌ | Auto Redact | |
|
||||
|
||||
#### 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 | |
|
||||
|
||||
|
||||
|
||||
|
||||
✔️: 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
|
||||
*/
|
||||
@@ -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;
|
||||
@@ -0,0 +1,10 @@
|
||||
import { defineConfig } from "cypress";
|
||||
|
||||
export default defineConfig({
|
||||
e2e: {
|
||||
baseUrl: "http://localhost:5173",
|
||||
setupNodeEvents(on, config) {
|
||||
// implement node event listeners here
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
describe('My First Test', () => {
|
||||
it('Visits the app root url', () => {
|
||||
cy.visit('/')
|
||||
cy.contains('#container', 'Ready to create an app?')
|
||||
})
|
||||
})
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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>
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -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')
|
||||
@@ -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>
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "StirlingPDF",
|
||||
"integrations": {
|
||||
"capacitor": {}
|
||||
},
|
||||
"type": "react-vite"
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 930 B |
@@ -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"
|
||||
}
|
||||
@@ -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();
|
||||
});
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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>
|
||||
);
|
||||
@@ -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;
|
||||
@@ -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() {}
|
||||
};
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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() */
|
||||
}));
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
@@ -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" }]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
@@ -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',
|
||||
}
|
||||
})
|
||||
@@ -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?
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["tauri-apps.tauri-vscode", "rust-lang.rust-analyzer"]
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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>
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 132 KiB |
@@ -0,0 +1,298 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="99.537987mm"
|
||||
height="95.209366mm"
|
||||
viewBox="0 0 99.537987 95.209366"
|
||||
version="1.1"
|
||||
id="svg745"
|
||||
xml:space="preserve"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
sodipodi:docname="stirling-transparent.svg"
|
||||
inkscape:export-filename="stirling.png"
|
||||
inkscape:export-xdpi="80"
|
||||
inkscape:export-ydpi="80"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview747"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.914906"
|
||||
inkscape:cx="175.42786"
|
||||
inkscape:cy="510.43495"
|
||||
inkscape:window-width="2256"
|
||||
inkscape:window-height="1428"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="40"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg745" /><defs
|
||||
id="defs742"><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient72198"><stop
|
||||
style="stop-color:#ccd6d7;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop72194" /><stop
|
||||
style="stop-color:#0f3a3f;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop72196" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient71928"><stop
|
||||
style="stop-color:#4b0005;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop71924" /><stop
|
||||
style="stop-color:#8f000c;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop71926" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient71920"><stop
|
||||
style="stop-color:#4b0005;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop71916" /><stop
|
||||
style="stop-color:#8f000c;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop71918" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient69598"><stop
|
||||
style="stop-color:#6a0007;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop69594" /><stop
|
||||
style="stop-color:#b8000f;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop69596" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient46361"><stop
|
||||
style="stop-color:#f7f6f8;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop46359" /><stop
|
||||
style="stop-color:#b7b7b5;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop46357" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient40554"><stop
|
||||
style="stop-color:#f4f2f4;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop40550" /><stop
|
||||
style="stop-color:#57767b;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop40552" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient39095"><stop
|
||||
style="stop-color:#285459;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop39093" /><stop
|
||||
style="stop-color:#a6b6af;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop39091" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient36672"><stop
|
||||
style="stop-color:#da453f;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop36668" /><stop
|
||||
style="stop-color:#a60008;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop36670" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient19524"><stop
|
||||
style="stop-color:#3a4b4f;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop19522" /><stop
|
||||
style="stop-color:#617979;stop-opacity:0.97461927;"
|
||||
offset="1"
|
||||
id="stop19520" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient17996"><stop
|
||||
style="stop-color:#401016;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop17994" /><stop
|
||||
style="stop-color:#761f19;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop17992" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient15569"><stop
|
||||
style="stop-color:#8ea8ad;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop15565" /><stop
|
||||
style="stop-color:#e9e7eb;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop15567" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient15557"><stop
|
||||
style="stop-color:#9b0e11;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop15553" /><stop
|
||||
style="stop-color:#370707;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop15555" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient15557"
|
||||
id="linearGradient15559"
|
||||
x1="120.06672"
|
||||
y1="63.25761"
|
||||
x2="135.16347"
|
||||
y2="78.078682"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient15569"
|
||||
id="linearGradient15571"
|
||||
x1="127.97037"
|
||||
y1="101.66144"
|
||||
x2="133.88971"
|
||||
y2="104.77026"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient17996"
|
||||
id="linearGradient17998"
|
||||
x1="117.9284"
|
||||
y1="86.055084"
|
||||
x2="130.67392"
|
||||
y2="76.945541"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient19524"
|
||||
id="linearGradient19528"
|
||||
x1="130.98172"
|
||||
y1="82.402977"
|
||||
x2="135.72115"
|
||||
y2="86.45166"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient36672"
|
||||
id="linearGradient36674"
|
||||
x1="63.797714"
|
||||
y1="74.81752"
|
||||
x2="96.636673"
|
||||
y2="120.29293"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient39095"
|
||||
id="linearGradient39097"
|
||||
x1="120.54506"
|
||||
y1="124.76902"
|
||||
x2="128.04152"
|
||||
y2="126.0704"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient40554"
|
||||
id="linearGradient40556"
|
||||
x1="113.84585"
|
||||
y1="114.04285"
|
||||
x2="119.65858"
|
||||
y2="128.50244"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient46361"
|
||||
id="linearGradient46363"
|
||||
x1="73.993439"
|
||||
y1="114.13906"
|
||||
x2="94.845322"
|
||||
y2="71.247383"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient69598"
|
||||
id="linearGradient69600"
|
||||
x1="95.854446"
|
||||
y1="114.66749"
|
||||
x2="103.77842"
|
||||
y2="120.1887"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient71920"
|
||||
id="linearGradient71922"
|
||||
x1="98.580376"
|
||||
y1="87.186958"
|
||||
x2="118.09738"
|
||||
y2="101.19449"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient71928"
|
||||
id="linearGradient71930"
|
||||
x1="78.278267"
|
||||
y1="97.433273"
|
||||
x2="92.313202"
|
||||
y2="104.33479"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient72198"
|
||||
id="linearGradient72200"
|
||||
x1="125.76636"
|
||||
y1="138.46817"
|
||||
x2="123.3327"
|
||||
y2="126.03291"
|
||||
gradientUnits="userSpaceOnUse" /></defs><g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer5"
|
||||
inkscape:label="shadow"
|
||||
style="display:inline"
|
||||
sodipodi:insensitive="true"
|
||||
transform="translate(-51.420144,-44.470286)"><path
|
||||
style="display:inline;fill:url(#linearGradient72200);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 84.146049,134.73858 c 0,0 11.721038,2.48294 17.938661,2.91673 6.21763,0.43378 14.75251,0.59994 22.41237,-0.43379 8.01008,-1.081 13.19907,-2.22733 14.50043,-2.66112 1.30136,-0.43379 4.00784,-1.24297 4.15244,-2.25514 0.1446,-1.01217 -3.4703,-2.74733 -6.21763,-3.32571 -2.74732,-0.57838 -12.72444,-1.44596 -14.89337,-1.44596 -2.16894,0 -37.892901,7.20499 -37.892901,7.20499 z"
|
||||
id="path72192"
|
||||
sodipodi:nodetypes="cssssssc" /></g><g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="Origami"
|
||||
style="display:inline"
|
||||
sodipodi:insensitive="true"
|
||||
transform="translate(-51.420144,-44.470286)"><path
|
||||
style="display:inline;fill:url(#linearGradient40556);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 84.460552,134.86721 35.165798,-6.85679 16.15467,-42.7383 z"
|
||||
id="path960"
|
||||
sodipodi:nodetypes="cccc" /><path
|
||||
style="fill:url(#linearGradient15571);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 135.71493,85.428056 0.3984,45.049024 -9.66213,-20.46173 z"
|
||||
id="path964"
|
||||
sodipodi:nodetypes="cccc" /><path
|
||||
style="display:inline;fill:url(#linearGradient39097);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 119.60518,128.00293 16.5337,2.48693 -9.68769,-20.5512 z"
|
||||
id="path966"
|
||||
sodipodi:nodetypes="cccc" /><path
|
||||
style="display:inline;fill:url(#linearGradient15559);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 118.42209,57.022622 12.70423,-2.766809 -0.0785,25.087175 -12.43878,-13.376518 z"
|
||||
id="path968"
|
||||
sodipodi:nodetypes="ccccc" /><path
|
||||
style="display:inline;fill:url(#linearGradient19528);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 135.72114,85.386768 -4.84219,-6.459493 0.0305,11.126604 z"
|
||||
id="path970"
|
||||
sodipodi:nodetypes="cccc" /><path
|
||||
style="display:inline;fill:url(#linearGradient17998);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 119.10273,65.682415 11.96883,13.44935 -0.0899,10.819868 -11.88577,11.430427 z"
|
||||
id="path972"
|
||||
sodipodi:nodetypes="ccccc" /><path
|
||||
style="display:inline;fill:url(#linearGradient36674);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 62.145635,130.15618 62.043392,65.435258 c 0,0 0.179321,-2.778132 1.89516,-4.036097 1.874923,-1.374597 4.341768,-1.894096 4.341768,-1.894096 l 50.91788,-11.349167 -0.0113,53.144272 -34.733274,33.56547 z"
|
||||
id="path958"
|
||||
sodipodi:nodetypes="ccsccccc" /></g><g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer3"
|
||||
inkscape:label="Letter"
|
||||
style="display:inline"
|
||||
sodipodi:insensitive="true"
|
||||
transform="translate(-51.420144,-44.470286)"><path
|
||||
style="display:inline;fill:url(#linearGradient69600);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 94.780881,91.406803 16.870379,17.074877 -23.723345,23.00249 -18.122131,-17.99816 5.497473,-2.80607 18.404054,-0.0511 2.35163,-8.23071 z"
|
||||
id="path54894"
|
||||
sodipodi:nodetypes="cccccccc" /><path
|
||||
style="display:inline;fill:url(#linearGradient71930);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 72.440405,92.224764 16.15467,15.745686 4.089788,-6.79927 z"
|
||||
id="path54892" /><path
|
||||
style="display:inline;fill:url(#linearGradient71922);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 95.138739,84.965385 1.124691,-14.109776 22.92453,22.286787 0.008,8.164604 -3.28863,3.16649 z"
|
||||
id="path54890"
|
||||
sodipodi:nodetypes="cccccc"
|
||||
inkscape:label="path54890" /><path
|
||||
style="display:inline;fill:url(#linearGradient46363);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 95.138739,84.965385 h 1.226936 l -0.05112,-14.109776 c 0,0 -5.776827,-3.220709 -12.167126,-2.40275 -6.390296,0.817957 -8.151582,2.1248 -10.58233,4.396523 -1.90229,1.777838 -2.913974,3.527446 -3.987546,7.157132 -0.512646,1.733226 -0.281963,5.988892 0.613471,8.537436 0.664591,1.891528 2.453873,4.294281 4.958868,6.134686 2.662335,1.956002 8.281825,3.527443 8.281825,3.527443 0,0 5.134614,1.887351 5.572338,4.294281 0.308137,1.69437 -0.102243,3.22071 -1.635914,4.95887 -1.258314,1.42609 -3.62969,1.99377 -6.288054,1.07357 -2.658364,-0.92021 -6.139514,-3.85065 -7.106009,-4.90775 -0.817958,-0.89464 -2.820665,-3.06173 -2.890231,-4.294021 -0.01209,-0.214205 -1.229505,-0.0963 -1.229505,-0.0963 l -0.0723,14.256941 5.879073,2.24938 c 0,0 5.214483,1.78929 8.946415,1.43143 3.731934,-0.35786 7.617235,-0.51122 11.604778,-5.16336 3.987542,-4.65213 3.680812,-12.831715 2.147141,-15.899056 -1.533673,-3.067344 -3.561212,-6.138812 -10.480087,-8.281826 -5.776829,-1.789283 -7.872846,-3.01622 -8.128458,-4.396524 -0.255611,-1.380305 0.0091,-4.253646 2.760607,-5.214481 3.220711,-1.124693 5.623462,-0.05112 7.05489,1.12469 1.431425,1.175817 5.572339,5.623462 5.572339,5.623462 z"
|
||||
id="path46355"
|
||||
sodipodi:nodetypes="cccssssscssssscccssssssscc" /></g></svg>
|
||||
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,4 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
|
||||
@@ -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"]
|
||||
@@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
tauri_build::build()
|
||||
}
|
||||
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 6.8 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 87 KiB |
@@ -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");
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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 |
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
function About() {
|
||||
return (
|
||||
<div>
|
||||
<h2>About</h2>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default About;
|
||||
@@ -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;
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
function Home() {
|
||||
return (
|
||||
<div>
|
||||
<h2>Home</h2>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Home;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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(".");
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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}`)
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
@@ -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" }]
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
@@ -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_"],
|
||||
}));
|
||||
@@ -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}`);
|
||||
});
|
||||
@@ -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() */
|
||||
}));
|
||||
@@ -0,0 +1,165 @@
|
||||
// JSON Representation of this Node Tree:
|
||||
// https://discord.com/channels/1068636748814483718/1099390571493195898/1118192754103693483
|
||||
// https://cdn.discordapp.com/attachments/1099390571493195898/1118192753759764520/image.png?ex=6537dba7&is=652566a7&hm=dc46820ef7c34bc37424794966c5f66f93ba0e15a740742c364d47d31ea119a9&
|
||||
export const discordWorkflow = {
|
||||
outputOptions: {
|
||||
zip: false
|
||||
},
|
||||
operations: [
|
||||
{
|
||||
type: "extract",
|
||||
values: { "index": "1" },
|
||||
operations: [
|
||||
{
|
||||
type: "removeObjects",
|
||||
values: { "objectNames": "photo, josh" },
|
||||
operations: [
|
||||
{
|
||||
type: "wait",
|
||||
values: { "id": 1 }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "extract",
|
||||
values: { "index": "2-5" },
|
||||
operations: [
|
||||
{
|
||||
type: "fillField",
|
||||
values: { "objectName": "name", "inputValue": "Josh" },
|
||||
operations: [
|
||||
{
|
||||
type: "wait",
|
||||
values: { "id": 1 }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "done", // This gets called when the other merge-ops with the same id finish.
|
||||
values: { "id": 1 },
|
||||
operations: [
|
||||
{
|
||||
type: "merge",
|
||||
values: {},
|
||||
operations: []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "extractImages",
|
||||
values: {},
|
||||
operations: []
|
||||
},
|
||||
{
|
||||
type: "merge",
|
||||
values: {},
|
||||
operations: [
|
||||
{
|
||||
type: "transform",
|
||||
values: { "scale": "2x", "rotation": "90deg" },
|
||||
operations: []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
// This will merge all input files into one giant document
|
||||
export const mergeOnly = {
|
||||
outputOptions: {
|
||||
zip: false
|
||||
},
|
||||
operations: [
|
||||
{
|
||||
type: "merge",
|
||||
values: {},
|
||||
operations: []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
// Extract Pages and store them in a new document
|
||||
export const extractOnly = {
|
||||
outputOptions: {
|
||||
zip: false
|
||||
},
|
||||
operations: [
|
||||
{
|
||||
type: "extract",
|
||||
values: { "pageIndexes": [0, 2] },
|
||||
operations: []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
// Split a document up into multiple documents
|
||||
export const splitOnly = {
|
||||
outputOptions: {
|
||||
zip: false
|
||||
},
|
||||
operations: [
|
||||
{
|
||||
type: "split",
|
||||
values: { "splitAfterPageArray": [2, 10] },
|
||||
operations: []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export const rotateOnly = {
|
||||
outputOptions: {
|
||||
zip: false
|
||||
},
|
||||
operations: [
|
||||
{
|
||||
type: "rotate",
|
||||
values: { "rotation": -90 },
|
||||
operations: []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export const imposeOnly = {
|
||||
outputOptions: {
|
||||
zip: false
|
||||
},
|
||||
operations: [
|
||||
{
|
||||
type: "impose",
|
||||
values: { "nup": 2, "format": "A4L" },
|
||||
operations: []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export const removeBlankPagesOnly = {
|
||||
outputOptions: {
|
||||
zip: false
|
||||
},
|
||||
operations: [
|
||||
{
|
||||
type: "removeBlankPages",
|
||||
values: { "whiteThreashold": 10 },
|
||||
operations: []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export const splitOnQR = {
|
||||
outputOptions: {
|
||||
zip: false
|
||||
},
|
||||
operations: [
|
||||
{
|
||||
type: "splitOn",
|
||||
values: {
|
||||
type: "QR_CODE"
|
||||
},
|
||||
operations: []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// PDFLib gets imported via index.html script-tag
|
||||
// PDFJS as pdfjsLib via index.html script-tag
|
||||
// jsQR via index.html script-tag
|
||||
|
||||
import * as pdfcpuWraopper from "./wasm/pdfcpu/pdfcpu-wrapper-browser.js";
|
||||
|
||||
const OpenCV = { cv: cv } // OPENCV gets importet as cv via index.html script-tag
|
||||
|
||||
import { extractPages as dependantExtractPages } from "./functions/extractPages.js";
|
||||
import { impose as dependantImpose } from './functions/impose.js';
|
||||
import { mergePDFs as dependantMergePDFs } from './functions/mergePDFs.js';
|
||||
import { rotatePages as dependantRotatePages } from './functions/rotatePages.js';
|
||||
import { scaleContent as dependantScaleContent} from './functions/scaleContent.js';
|
||||
import { scalePage as dependantScalePage } from './functions/scalePage.js';
|
||||
import { splitPDF as dependantSplitPDF } from './functions/splitPDF.js';
|
||||
import { editMetadata as dependantEditMetadata} from "./functions/editMetadata.js";
|
||||
import { sortPagesWithPreset as dependantSortPagesWithPreset} from "./functions/organizePages.js";
|
||||
import { removeBlankPages as dependantRemoveBlankPages} from "./functions/removeBlankPages.js";
|
||||
import { splitOn as dependantSplitOn } from "./functions/splitOn.js";
|
||||
|
||||
// TODO: Dynamic loading & undloading of libraries.
|
||||
|
||||
export async function extractPages(snapshot, pageIndexes) {
|
||||
return dependantExtractPages(snapshot, pageIndexes, PDFLib);
|
||||
}
|
||||
|
||||
export async function impose(snapshot, nup, format) {
|
||||
return dependantImpose(snapshot, nup, format, pdfcpuWraopper);
|
||||
}
|
||||
|
||||
export async function mergePDFs(snapshots) {
|
||||
return dependantMergePDFs(snapshots, PDFLib);
|
||||
}
|
||||
|
||||
export async function rotatePages(snapshot, rotation) {
|
||||
return dependantRotatePages(snapshot, rotation, PDFLib);
|
||||
}
|
||||
|
||||
export async function scaleContent(snapshot, scaleFactor) {
|
||||
return dependantScaleContent(snapshot, scaleFactor, PDFLib);
|
||||
}
|
||||
|
||||
export async function scalePage(snapshot, pageSize) {
|
||||
return dependantScalePage(snapshot, pageSize, PDFLib);
|
||||
}
|
||||
|
||||
export async function splitPDF(snapshot, splitAfterPageArray) {
|
||||
return dependantSplitPDF(snapshot, splitAfterPageArray, PDFLib);
|
||||
}
|
||||
|
||||
export async function editMetadata(snapshot, metadata) {
|
||||
return dependantEditMetadata(snapshot, metadata, PDFLib);
|
||||
}
|
||||
|
||||
export async function sortPagesWithPreset(snapshot, operation) {
|
||||
return dependantSortPagesWithPreset(snapshot, operation, PDFLib);
|
||||
}
|
||||
|
||||
export async function removeBlankPages(snapshot, whiteThreashold) {
|
||||
return dependantRemoveBlankPages(snapshot, whiteThreashold, pdfjsLib, OpenCV, PDFLib);
|
||||
}
|
||||
|
||||
export async function splitOn(snapshot, type, whiteThreashold) {
|
||||
return dependantSplitOn(snapshot, type, whiteThreashold, pdfjsLib, OpenCV, PDFLib, jsQR);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
|
||||
<script src="/dep/pdf-lib.min.js"></script>
|
||||
<script src="/dep/downloadjs_1.4.7.js"></script>
|
||||
<script src="/dep/pdf.min.js"></script>
|
||||
<script src="/dep/jsQR.js"></script>
|
||||
|
||||
<script src="/wasm/browserfs.min.js"></script>
|
||||
<script src="/wasm/opencv/opencv_3_4_custom_O3.js"></script>
|
||||
|
||||
<script src="index.js" type="module"></script>
|
||||
</head>
|
||||
<body>
|
||||
<input type="file" id="pdfFile" accept=".pdf" multiple>
|
||||
<br>
|
||||
|
||||
<br>
|
||||
<textarea name="workflow" id="workflow" cols="120" rows="20"></textarea>
|
||||
<br>
|
||||
<select id="pdfOptions">
|
||||
</select>
|
||||
<button id="loadButton">Load</button>
|
||||
<br>
|
||||
|
||||
<br>
|
||||
<button id="doneButton">Done</button>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,65 @@
|
||||
import { scaleContent } from "./functions/scaleContent.js";
|
||||
import { scalePage, PageSize } from "./functions/scalePage.js";
|
||||
import * as exampleWorkflows from "./exampleWorkflows.js";
|
||||
import { traverseOperations } from "./traverseOperations.js";
|
||||
import * as Functions from "./functions.js";
|
||||
|
||||
(async () => {
|
||||
const workflowField = document.getElementById("workflow");
|
||||
|
||||
const dropdown = document.getElementById("pdfOptions");
|
||||
// Clear existing options (if any)
|
||||
dropdown.innerHTML = '';
|
||||
|
||||
// Iterate over the keys of the object and create an option for each key
|
||||
for (const key in exampleWorkflows) {
|
||||
const option = document.createElement('option');
|
||||
option.value = key;
|
||||
option.text = key;
|
||||
dropdown.appendChild(option);
|
||||
}
|
||||
|
||||
const loadButton = document.getElementById("loadButton");
|
||||
loadButton.addEventListener("click", (e) => {
|
||||
workflowField.value = JSON.stringify(exampleWorkflows[dropdown.value], null, 2);
|
||||
});
|
||||
loadButton.click();
|
||||
|
||||
const pdfFileInput = document.getElementById('pdfFile');
|
||||
const doneButton = document.getElementById("doneButton");
|
||||
|
||||
doneButton.addEventListener('click', async (e) => {
|
||||
console.log("Starting...");
|
||||
|
||||
const files = Array.from(pdfFileInput.files);
|
||||
const inputs = await Promise.all(files.map(async file => {
|
||||
return {
|
||||
originalFileName: file.name.replace(/\.[^/.]+$/, ""),
|
||||
fileName: file.name.replace(/\.[^/.]+$/, ""),
|
||||
buffer: new Uint8Array(await file.arrayBuffer())
|
||||
}
|
||||
}));
|
||||
console.log(inputs);
|
||||
|
||||
const workflow = JSON.parse(workflowField.value);
|
||||
console.log(workflow);
|
||||
const traverse = traverseOperations(workflow.operations, inputs, Functions);
|
||||
|
||||
let pdfResults;
|
||||
let iteration;
|
||||
while (true) {
|
||||
iteration = await traverse.next();
|
||||
if (iteration.done) {
|
||||
pdfResults = iteration.value;
|
||||
console.log(`data: processing done\n\n`);
|
||||
break;
|
||||
}
|
||||
console.log(`data: ${iteration.value}\n\n`);
|
||||
}
|
||||
|
||||
// TODO: Zip if wanted
|
||||
pdfResults.forEach(result => {
|
||||
download(result.buffer, result.fileName, "application/pdf");
|
||||
});
|
||||
});
|
||||
})();
|
||||
@@ -1,24 +0,0 @@
|
||||
apiVersion: v1
|
||||
entries:
|
||||
stirling-pdf-chart:
|
||||
- apiVersion: v2
|
||||
appVersion: 0.31.1
|
||||
created: "2024-11-04T20:13:48.298110043Z"
|
||||
description: locally hosted web application that allows you to perform various
|
||||
operations on PDF files
|
||||
digest: 49a6e968f0203e7390094ae7fa20bc3fb0542ebdf426501c170641e98d2a45e2
|
||||
home: https://github.com/Stirling-Tools/Stirling-PDF
|
||||
keywords:
|
||||
- stirling-pdf
|
||||
- helm
|
||||
- charts repo
|
||||
maintainers:
|
||||
- name: Stirling-Tools
|
||||
url: https://github.com/Stirling-Tools/Stirling-PDF
|
||||
name: stirling-pdf-chart
|
||||
sources:
|
||||
- https://github.com/Stirling-Tools/Stirling-PDF
|
||||
urls:
|
||||
- https://github.com/Stirling-Tools/Stirling-PDF/releases/download/stirling-pdf-chart-1.0.1/stirling-pdf-chart-1.0.1.tgz
|
||||
version: 1.0.1
|
||||
generated: "2024-11-04T20:13:48.29811941Z"
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "stirling-pdf",
|
||||
"private": "true",
|
||||
"workspaces": [
|
||||
"client-ionic",
|
||||
"client-tauri",
|
||||
"server-node",
|
||||
"shared-operations"
|
||||
],
|
||||
"scripts": {
|
||||
"dev": "concurrently --names \"node,ionic\" -c \"red.bold,cyan.bold\" --kill-others \"npm run -w server-node dev\" \"npm run -w client-ionic dev\""
|
||||
},
|
||||
"devDependencies": {
|
||||
"concurrently": "^8.2.2"
|
||||
},
|
||||
"engines" : {
|
||||
"npm" : ">=7.24.2"
|
||||
},
|
||||
"engineStrict" : true
|
||||
}
|
||||