forked from Maurice/pastabble
Pastabble frontend
This commit is contained in:
parent
293a0af9c5
commit
a1b5c513ea
5
.containerignore
Normal file
5
.containerignore
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
*/node_modules
|
||||||
|
*/dist
|
||||||
|
*/target
|
||||||
|
data
|
||||||
|
config
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
/target
|
/target
|
||||||
/data
|
/data
|
||||||
pastabble.tar
|
pastabble.tar
|
||||||
|
.vscode/
|
195
Cargo.lock
generated
195
Cargo.lock
generated
@ -23,6 +23,12 @@ dependencies = [
|
|||||||
"alloc-no-stdlib",
|
"alloc-no-stdlib",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android-tzdata"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "android_system_properties"
|
name = "android_system_properties"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
@ -56,15 +62,6 @@ version = "1.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "block-buffer"
|
|
||||||
version = "0.10.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
|
|
||||||
dependencies = [
|
|
||||||
"generic-array",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "brotli"
|
name = "brotli"
|
||||||
version = "3.3.4"
|
version = "3.3.4"
|
||||||
@ -122,18 +119,17 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chrono"
|
name = "chrono"
|
||||||
version = "0.4.22"
|
version = "0.4.33"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1"
|
checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"android-tzdata",
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"num-integer",
|
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"serde",
|
"serde",
|
||||||
"time 0.1.44",
|
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"winapi",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -158,15 +154,6 @@ version = "0.8.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cpufeatures"
|
|
||||||
version = "0.2.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
@ -198,16 +185,6 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crypto-common"
|
|
||||||
version = "0.1.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
|
||||||
dependencies = [
|
|
||||||
"generic-array",
|
|
||||||
"typenum",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cxx"
|
name = "cxx"
|
||||||
version = "1.0.80"
|
version = "1.0.80"
|
||||||
@ -262,16 +239,6 @@ dependencies = [
|
|||||||
"gzip-header",
|
"gzip-header",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "digest"
|
|
||||||
version = "0.10.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c"
|
|
||||||
dependencies = [
|
|
||||||
"block-buffer",
|
|
||||||
"crypto-common",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "1.8.0"
|
version = "1.8.0"
|
||||||
@ -321,16 +288,6 @@ dependencies = [
|
|||||||
"byteorder",
|
"byteorder",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "generic-array"
|
|
||||||
version = "0.14.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
|
|
||||||
dependencies = [
|
|
||||||
"typenum",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
@ -339,7 +296,7 @@ checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -527,16 +484,6 @@ dependencies = [
|
|||||||
"twoway",
|
"twoway",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-integer"
|
|
||||||
version = "0.1.45"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.15"
|
version = "0.2.15"
|
||||||
@ -598,7 +545,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pastabble"
|
name = "pastabble"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"kv",
|
"kv",
|
||||||
@ -700,9 +647,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rouille"
|
name = "rouille"
|
||||||
version = "3.6.1"
|
version = "3.6.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4f86e4c51a773f953f02bbab5fd049f004bfd384341d62da2a079aff812ab176"
|
checksum = "3716fbf57fc1084d7a706adf4e445298d123e4a44294c4e8213caf1b85fcc921"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"brotli",
|
"brotli",
|
||||||
@ -710,15 +657,14 @@ dependencies = [
|
|||||||
"deflate",
|
"deflate",
|
||||||
"filetime",
|
"filetime",
|
||||||
"multipart",
|
"multipart",
|
||||||
"num_cpus",
|
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"rand",
|
"rand",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha1",
|
"sha1_smol",
|
||||||
"threadpool",
|
"threadpool",
|
||||||
"time 0.3.16",
|
"time",
|
||||||
"tiny_http",
|
"tiny_http",
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
@ -779,21 +725,16 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha1"
|
name = "sha1_smol"
|
||||||
version = "0.10.5"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
|
checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"cpufeatures",
|
|
||||||
"digest",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook"
|
name = "signal-hook"
|
||||||
version = "0.3.14"
|
version = "0.3.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d"
|
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
@ -893,17 +834,6 @@ dependencies = [
|
|||||||
"num_cpus",
|
"num_cpus",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "time"
|
|
||||||
version = "0.1.44"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"wasi 0.10.0+wasi-snapshot-preview1",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.3.16"
|
version = "0.3.16"
|
||||||
@ -967,12 +897,6 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "typenum"
|
|
||||||
version = "1.15.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicase"
|
name = "unicase"
|
||||||
version = "2.6.0"
|
version = "2.6.0"
|
||||||
@ -1026,12 +950,6 @@ version = "0.9.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasi"
|
|
||||||
version = "0.10.0+wasi-snapshot-preview1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
@ -1129,13 +1047,28 @@ version = "0.42.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows_aarch64_gnullvm",
|
"windows_aarch64_gnullvm 0.42.0",
|
||||||
"windows_aarch64_msvc",
|
"windows_aarch64_msvc 0.42.0",
|
||||||
"windows_i686_gnu",
|
"windows_i686_gnu 0.42.0",
|
||||||
"windows_i686_msvc",
|
"windows_i686_msvc 0.42.0",
|
||||||
"windows_x86_64_gnu",
|
"windows_x86_64_gnu 0.42.0",
|
||||||
"windows_x86_64_gnullvm",
|
"windows_x86_64_gnullvm 0.42.0",
|
||||||
"windows_x86_64_msvc",
|
"windows_x86_64_msvc 0.42.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.52.0",
|
||||||
|
"windows_aarch64_msvc 0.52.0",
|
||||||
|
"windows_i686_gnu 0.52.0",
|
||||||
|
"windows_i686_msvc 0.52.0",
|
||||||
|
"windows_x86_64_gnu 0.52.0",
|
||||||
|
"windows_x86_64_gnullvm 0.52.0",
|
||||||
|
"windows_x86_64_msvc 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1144,38 +1077,80 @@ version = "0.42.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
|
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.42.0"
|
version = "0.42.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
|
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.42.0"
|
version = "0.42.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
|
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.42.0"
|
version = "0.42.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
|
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.42.0"
|
version = "0.42.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
|
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.42.0"
|
version = "0.42.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
|
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.42.0"
|
version = "0.42.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
|
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "pastabble"
|
name = "pastabble"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
@ -8,7 +8,7 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
kv = { version = "0.24.0", features = ["json-value"] }
|
kv = { version = "0.24.0", features = ["json-value"] }
|
||||||
serde = { version = "1.0.147", features = ["derive"] }
|
serde = { version = "1.0.147", features = ["derive"] }
|
||||||
chrono = { version = "0.4.22", features = ["serde"] }
|
chrono = { version = "0.4.33", features = ["serde"] }
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
rouille = "3.6.1"
|
rouille = "3.6.2"
|
||||||
signal-hook = "0.3.14"
|
signal-hook = "0.3.17"
|
@ -1,4 +1,11 @@
|
|||||||
FROM rust:alpine3.18 AS builder
|
FROM node:21-alpine3.19 AS frontend-builder
|
||||||
|
WORKDIR /build
|
||||||
|
|
||||||
|
RUN corepack enable
|
||||||
|
COPY pastabble-frontend/ .
|
||||||
|
RUN pnpm i && pnpm build
|
||||||
|
|
||||||
|
FROM rust:alpine3.19 AS builder
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
|
|
||||||
RUN apk add --no-cache musl-dev
|
RUN apk add --no-cache musl-dev
|
||||||
@ -13,9 +20,13 @@ RUN case "$(apk --print-arch)" in \
|
|||||||
|
|
||||||
FROM alpine:edge
|
FROM alpine:edge
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
RUN mkdir /app/wwwroot
|
||||||
|
|
||||||
|
# /* removes directory structure
|
||||||
COPY --from=builder /release/* /app
|
COPY --from=builder /release/* /app
|
||||||
COPY ./about.html /app/about.html
|
COPY ./about.html /app/about.html
|
||||||
|
COPY --from=frontend-builder /build/dist /app/wwwroot
|
||||||
|
|
||||||
|
ENV WWW_DIR /app/wwwroot
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
CMD [ "./pastabble" ]
|
CMD [ "./pastabble" ]
|
24
pastabble-frontend/.gitignore
vendored
Normal file
24
pastabble-frontend/.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
47
pastabble-frontend/README.md
Normal file
47
pastabble-frontend/README.md
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# Svelte + TS + Vite
|
||||||
|
|
||||||
|
This template should help get you started developing with Svelte and TypeScript in Vite.
|
||||||
|
|
||||||
|
## Recommended IDE Setup
|
||||||
|
|
||||||
|
[VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode).
|
||||||
|
|
||||||
|
## Need an official Svelte framework?
|
||||||
|
|
||||||
|
Check out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more.
|
||||||
|
|
||||||
|
## Technical considerations
|
||||||
|
|
||||||
|
**Why use this over SvelteKit?**
|
||||||
|
|
||||||
|
- It brings its own routing solution which might not be preferable for some users.
|
||||||
|
- It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app.
|
||||||
|
|
||||||
|
This template contains as little as possible to get started with Vite + TypeScript + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project.
|
||||||
|
|
||||||
|
Should you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate.
|
||||||
|
|
||||||
|
**Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?**
|
||||||
|
|
||||||
|
Setting `compilerOptions.types` shuts out all other types not explicitly listed in the configuration. Using triple-slash references keeps the default TypeScript setting of accepting type information from the entire workspace, while also adding `svelte` and `vite/client` type information.
|
||||||
|
|
||||||
|
**Why include `.vscode/extensions.json`?**
|
||||||
|
|
||||||
|
Other templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project.
|
||||||
|
|
||||||
|
**Why enable `allowJs` in the TS template?**
|
||||||
|
|
||||||
|
While `allowJs: false` would indeed prevent the use of `.js` files in the project, it does not prevent the use of JavaScript syntax in `.svelte` files. In addition, it would force `checkJs: false`, bringing the worst of both worlds: not being able to guarantee the entire codebase is TypeScript, and also having worse typechecking for the existing JavaScript. In addition, there are valid use cases in which a mixed codebase may be relevant.
|
||||||
|
|
||||||
|
**Why is HMR not preserving my local component state?**
|
||||||
|
|
||||||
|
HMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/rixo/svelte-hmr#svelte-hmr).
|
||||||
|
|
||||||
|
If you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// store.ts
|
||||||
|
// An extremely simple external store
|
||||||
|
import { writable } from 'svelte/store'
|
||||||
|
export default writable(0)
|
||||||
|
```
|
4
pastabble-frontend/data/conf
Normal file
4
pastabble-frontend/data/conf
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
segment_size: 524288
|
||||||
|
use_compression: false
|
||||||
|
version: 0.34
|
||||||
|
vQÁ
|
BIN
pastabble-frontend/data/db
Normal file
BIN
pastabble-frontend/data/db
Normal file
Binary file not shown.
13
pastabble-frontend/index.html
Normal file
13
pastabble-frontend/index.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Pastabble</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/src/main.ts"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
29
pastabble-frontend/package.json
Normal file
29
pastabble-frontend/package.json
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"name": "pastabble-frontend",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"check": "svelte-check --tsconfig ./tsconfig.json"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@sveltejs/vite-plugin-svelte": "^3.0.1",
|
||||||
|
"@tsconfig/svelte": "^5.0.2",
|
||||||
|
"autoprefixer": "^10.4.17",
|
||||||
|
"daisyui": "^4.6.1",
|
||||||
|
"postcss": "^8.4.33",
|
||||||
|
"svelte": "^4.2.8",
|
||||||
|
"svelte-check": "^3.6.2",
|
||||||
|
"tailwindcss": "^3.4.1",
|
||||||
|
"tslib": "^2.6.2",
|
||||||
|
"typescript": "^5.2.2",
|
||||||
|
"vite": "^5.0.8"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"highlight.js": "^11.9.0",
|
||||||
|
"svelte-spa-router": "^4.0.1"
|
||||||
|
}
|
||||||
|
}
|
1717
pastabble-frontend/pnpm-lock.yaml
generated
Normal file
1717
pastabble-frontend/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
6
pastabble-frontend/postcss.config.js
Normal file
6
pastabble-frontend/postcss.config.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export default {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
22
pastabble-frontend/src/App.svelte
Normal file
22
pastabble-frontend/src/App.svelte
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import ThemeSwitcher from "./lib/components/ThemeSwitcher.svelte";
|
||||||
|
import Router from 'svelte-spa-router'
|
||||||
|
import Home from './lib/pages/Home.svelte';
|
||||||
|
import Viewer from "./lib/pages/Viewer.svelte";
|
||||||
|
|
||||||
|
const routes = {
|
||||||
|
'/:id': Viewer,
|
||||||
|
'*': Home
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="float-right p-5">
|
||||||
|
<ThemeSwitcher />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<main class="p-10">
|
||||||
|
<a href="/#/" class="text-3xl font-bold">Pastabble</a><br/>
|
||||||
|
<i>Fast and free pastebin alternative brought to you by the Plabble team</i>
|
||||||
|
|
||||||
|
<Router {routes} />
|
||||||
|
</main>
|
3
pastabble-frontend/src/app.css
Normal file
3
pastabble-frontend/src/app.css
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
67
pastabble-frontend/src/lib/components/CodeBlock.svelte
Normal file
67
pastabble-frontend/src/lib/components/CodeBlock.svelte
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import hljs from 'highlight.js';
|
||||||
|
import LanguageSelector from './LanguageSelector.svelte';
|
||||||
|
|
||||||
|
export let code: string | undefined;
|
||||||
|
export let language: string | undefined;
|
||||||
|
|
||||||
|
let displayCode: string | undefined;
|
||||||
|
let showAlert = false;
|
||||||
|
let initial = true;
|
||||||
|
|
||||||
|
$: if(code) {
|
||||||
|
highlight();
|
||||||
|
initial = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$: if(language) {
|
||||||
|
if(initial || !code) {
|
||||||
|
highlight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function highlight() {
|
||||||
|
if(language) {
|
||||||
|
const res = hljs.highlight(language!, code!);
|
||||||
|
if(!res.errorRaised) {
|
||||||
|
displayCode = res.value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const res = hljs.highlightAuto(code!);
|
||||||
|
if(!res.errorRaised) {
|
||||||
|
displayCode = res.value;
|
||||||
|
language = res.language;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function copy() {
|
||||||
|
await navigator.clipboard.writeText(code!);
|
||||||
|
showAlert = true;
|
||||||
|
setTimeout(() => showAlert = false, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function share() {
|
||||||
|
await navigator.clipboard.writeText(window.location.href);
|
||||||
|
showAlert = true;
|
||||||
|
setTimeout(() => showAlert = false, 3000);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex flex-col m-3 gap-5">
|
||||||
|
<div role="alert" class="alert alert-success transition-opacity ease-in-out duration-500 {showAlert ? 'opacity-100' : 'opacity-0'}">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
|
||||||
|
<span>Copied to your clipboard!</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col md:flex-row gap-5">
|
||||||
|
<div class="mockup-code flex-1">
|
||||||
|
<pre class="p-5"><code>{@html displayCode}</code></pre>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col gap-3">
|
||||||
|
<LanguageSelector bind:language />
|
||||||
|
<button on:click={copy} class="btn btn-outline btn-primary">Copy</button>
|
||||||
|
<button on:click={share} class="btn btn-outline btn-primary">Share link</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,13 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import hljs from 'highlight.js';
|
||||||
|
const languages = hljs.listLanguages();
|
||||||
|
|
||||||
|
export let language: string | undefined = undefined;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<select bind:value={language} class="select select-primary select-bordered w-full max-w-xs">
|
||||||
|
<option value="{undefined}" disabled selected>Choose programming language</option>
|
||||||
|
{#each languages as lang}
|
||||||
|
<option value="{lang}">{lang}</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
28
pastabble-frontend/src/lib/components/ThemeSwitcher.svelte
Normal file
28
pastabble-frontend/src/lib/components/ThemeSwitcher.svelte
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
|
||||||
|
let darkTheme: boolean;
|
||||||
|
let mounted = false;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
mounted = true;
|
||||||
|
darkTheme = localStorage['theme'] ? localStorage['theme'] === 'dark' : isDarkMode();
|
||||||
|
});
|
||||||
|
|
||||||
|
$: if(darkTheme) {
|
||||||
|
localStorage.setItem('theme', 'dark');
|
||||||
|
document.documentElement.setAttribute('data-theme', 'dark');
|
||||||
|
} else if(mounted) {
|
||||||
|
localStorage.setItem('theme', 'light');
|
||||||
|
document.documentElement.setAttribute('data-theme', 'light');
|
||||||
|
}
|
||||||
|
|
||||||
|
const isDarkMode = () =>
|
||||||
|
window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<label class="flex cursor-pointer gap-2 items-center">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"/><path d="M12 1v2M12 21v2M4.2 4.2l1.4 1.4M18.4 18.4l1.4 1.4M1 12h2M21 12h2M4.2 19.8l1.4-1.4M18.4 5.6l1.4-1.4"/></svg>
|
||||||
|
<input bind:checked={darkTheme} type="checkbox" class="toggle theme-controller"/>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>
|
||||||
|
</label>
|
5
pastabble-frontend/src/lib/models/note_details.ts
Normal file
5
pastabble-frontend/src/lib/models/note_details.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export default interface NoteDetails {
|
||||||
|
content: string;
|
||||||
|
language?: string;
|
||||||
|
created: string;
|
||||||
|
}
|
176
pastabble-frontend/src/lib/pages/Home.svelte
Normal file
176
pastabble-frontend/src/lib/pages/Home.svelte
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { push } from "svelte-spa-router";
|
||||||
|
import LanguageSelector from "../components/LanguageSelector.svelte";
|
||||||
|
|
||||||
|
let language: string | undefined;
|
||||||
|
|
||||||
|
let lookupNoteId: string = '';
|
||||||
|
let enteredUrl: string = '';
|
||||||
|
let createdUrl: string = '';
|
||||||
|
let newNoteId: string = '';
|
||||||
|
let newNoteCode: string = '';
|
||||||
|
|
||||||
|
let urlError = false;
|
||||||
|
let lookupNoteIdError = false;
|
||||||
|
|
||||||
|
let creatingNote = false;
|
||||||
|
let creatingUrl = false;
|
||||||
|
|
||||||
|
let copied = false;
|
||||||
|
let showAlert = false;
|
||||||
|
|
||||||
|
$: if(copied) {
|
||||||
|
setTimeout(() => {
|
||||||
|
copied = false;
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
$: if(showAlert) {
|
||||||
|
window.scrollTo({
|
||||||
|
top: 0,
|
||||||
|
behavior: 'smooth'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createNote() {
|
||||||
|
creatingNote = true;
|
||||||
|
|
||||||
|
const res = await fetch(language ? `/${newNoteId}?lang=${language}` : `/${newNoteId}`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: newNoteCode
|
||||||
|
});
|
||||||
|
|
||||||
|
if(res.ok) {
|
||||||
|
const id = await res.text();
|
||||||
|
push(`/${id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function lookupNote() {
|
||||||
|
if(lookupNoteId.length === 0) {
|
||||||
|
lookupNoteIdError = true;
|
||||||
|
}
|
||||||
|
push(`/${lookupNoteId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function copyUrl() {
|
||||||
|
await navigator.clipboard.writeText(createdUrl);
|
||||||
|
copied = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function shortenUrl() {
|
||||||
|
if(!isValidUrl(enteredUrl)) {
|
||||||
|
urlError = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
creatingUrl = true;
|
||||||
|
const res = await fetch('/to', {
|
||||||
|
method: 'POST',
|
||||||
|
body: enteredUrl
|
||||||
|
});
|
||||||
|
|
||||||
|
if(res.status === 200) {
|
||||||
|
const id = await res.text();
|
||||||
|
createdUrl = `${location.origin}/to/${id}`;
|
||||||
|
enteredUrl = '';
|
||||||
|
showAlert = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
creatingUrl = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isValidUrl = (url: string) => {
|
||||||
|
var urlPattern = new RegExp('^(https?:\\/\\/)?'+ // validate protocol
|
||||||
|
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // validate domain name
|
||||||
|
'((\\d{1,3}\\.){3}\\d{1,3}))'+ // validate OR ip (v4) address
|
||||||
|
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // validate port and path
|
||||||
|
'(\\?[;&a-z\\d%_.~+=-]*)?'+ // validate query string
|
||||||
|
'(\\#[-a-z\\d_]*)?$','i'); // validate fragment locator
|
||||||
|
return !!urlPattern.test(url);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div role="alert" class="alert transition-opacity ease-in-out duration-500 my-5 {showAlert ? 'opacity-100' : 'opacity-0'}">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-6 h-6"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
|
||||||
|
<div class="flex flex-col md:flex-row gap-3 items-center w-full">
|
||||||
|
<span>Link created: </span>
|
||||||
|
<a href={createdUrl} class="font-medium text-blue-600 dark:text-blue-500 hover:underline">{createdUrl}</a>
|
||||||
|
<button on:click={copyUrl} class="btn btn-info ml-auto">
|
||||||
|
{copied ? 'Copied' : 'Copy'}
|
||||||
|
<svg class:hidden={!copied} xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col md:flex-row gap-5 justify-around">
|
||||||
|
<div class="mt-10">
|
||||||
|
<div>
|
||||||
|
<h2 class="text-2xl font-bold mb-3">Lookup existing note</h2>
|
||||||
|
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<input
|
||||||
|
on:keydown={(e) => {
|
||||||
|
lookupNoteIdError = false;
|
||||||
|
e.key === 'Enter' && lookupNote();
|
||||||
|
}}
|
||||||
|
bind:value={lookupNoteId}
|
||||||
|
type="text"
|
||||||
|
placeholder="Note ID"
|
||||||
|
class:input-error={lookupNoteIdError}
|
||||||
|
class:input-primary={!lookupNoteIdError}
|
||||||
|
class="input input-bordered w-full max-w-xs"
|
||||||
|
/>
|
||||||
|
<button on:click={lookupNote} class="btn btn-primary">Find</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-10">
|
||||||
|
<h2 class="text-2xl font-bold mb-3">URL shortener</h2>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<input
|
||||||
|
bind:value={enteredUrl}
|
||||||
|
on:keydown={(e) => {
|
||||||
|
lookupNoteIdError = false;
|
||||||
|
e.key === 'Enter' && shortenUrl();
|
||||||
|
}}
|
||||||
|
type="text"
|
||||||
|
placeholder="Enter your long URL"
|
||||||
|
class:input-error={urlError}
|
||||||
|
class="input input-bordered w-full max-w-xs"
|
||||||
|
/>
|
||||||
|
<button disabled={creatingUrl} on:click={shortenUrl} class="btn btn-outline btn-primary">
|
||||||
|
Shorten
|
||||||
|
<span class:hidden={!creatingUrl} class="loading loading-spinner"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-10">
|
||||||
|
<h2 class="text-2xl font-bold mb-3">Or create a new one</h2>
|
||||||
|
|
||||||
|
<div class="flex flex-col md:flex-row gap-3">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Note ID (empty for random)"
|
||||||
|
class="input input-bordered w-full max-w-xs"
|
||||||
|
bind:value={newNoteId}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<LanguageSelector bind:language />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<textarea
|
||||||
|
class="textarea textarea-bordered mt-5 w-full h-32"
|
||||||
|
placeholder="Paste your code here..."
|
||||||
|
bind:value={newNoteCode}
|
||||||
|
></textarea>
|
||||||
|
|
||||||
|
<button disabled={creatingNote} on:click={createNote} class="btn btn-outline btn-primary w-full mt-3">
|
||||||
|
Save your paste
|
||||||
|
<span class:hidden={!creatingNote} class="loading loading-spinner"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
46
pastabble-frontend/src/lib/pages/Viewer.svelte
Normal file
46
pastabble-frontend/src/lib/pages/Viewer.svelte
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { push } from "svelte-spa-router";
|
||||||
|
import CodeBlock from "../components/CodeBlock.svelte";
|
||||||
|
import type NoteDetails from "../models/note_details";
|
||||||
|
|
||||||
|
export let params: any;
|
||||||
|
let paste: NoteDetails | undefined;
|
||||||
|
let code: string | undefined;
|
||||||
|
let language: string | undefined;
|
||||||
|
let noteDoesNotExist = false;
|
||||||
|
let noteId: string;
|
||||||
|
|
||||||
|
if(params.id) {
|
||||||
|
noteId = params.id;
|
||||||
|
lookup();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function lookup() {
|
||||||
|
const res = await fetch(`/${noteId}?details=y`);
|
||||||
|
if(res.ok) {
|
||||||
|
paste = await res.json();
|
||||||
|
code = paste?.content;
|
||||||
|
language = paste?.language;
|
||||||
|
} else {
|
||||||
|
if(res.status === 404) {
|
||||||
|
noteDoesNotExist = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function home() {
|
||||||
|
push('/');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{#if noteDoesNotExist}
|
||||||
|
<div role="alert" class="alert alert-warning mt-10">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" /></svg>
|
||||||
|
<span>Note with id <b>#{noteId}</b> not found!</span>
|
||||||
|
</div>
|
||||||
|
<button on:click={home} class="btn btn-outline btn-primary mt-5">Back home</button>
|
||||||
|
{:else if code}
|
||||||
|
<CodeBlock {language} {code} />
|
||||||
|
{/if}
|
||||||
|
</div>
|
9
pastabble-frontend/src/main.ts
Normal file
9
pastabble-frontend/src/main.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import './app.css'
|
||||||
|
import 'highlight.js/styles/github-dark.min.css';
|
||||||
|
import App from './App.svelte'
|
||||||
|
|
||||||
|
const app = new App({
|
||||||
|
target: document.getElementById('app'),
|
||||||
|
})
|
||||||
|
|
||||||
|
export default app
|
2
pastabble-frontend/src/vite-env.d.ts
vendored
Normal file
2
pastabble-frontend/src/vite-env.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/// <reference types="svelte" />
|
||||||
|
/// <reference types="vite/client" />
|
7
pastabble-frontend/svelte.config.js
Normal file
7
pastabble-frontend/svelte.config.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// Consult https://svelte.dev/docs#compile-time-svelte-preprocess
|
||||||
|
// for more information about preprocessors
|
||||||
|
preprocess: vitePreprocess(),
|
||||||
|
}
|
9
pastabble-frontend/tailwind.config.js
Normal file
9
pastabble-frontend/tailwind.config.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
export default {
|
||||||
|
content: ['./src/**/*.{html,svelte,js,ts}'],
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [require('daisyui')],
|
||||||
|
}
|
||||||
|
|
20
pastabble-frontend/tsconfig.json
Normal file
20
pastabble-frontend/tsconfig.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"extends": "@tsconfig/svelte/tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
/**
|
||||||
|
* Typecheck JS in `.svelte` and `.js` files by default.
|
||||||
|
* Disable checkJs if you'd like to use dynamic types in JS.
|
||||||
|
* Note that setting allowJs false does not prevent the use
|
||||||
|
* of JS in `.svelte` files.
|
||||||
|
*/
|
||||||
|
"allowJs": true,
|
||||||
|
"checkJs": true,
|
||||||
|
"isolatedModules": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
|
||||||
|
"references": [{ "path": "./tsconfig.node.json" }]
|
||||||
|
}
|
9
pastabble-frontend/tsconfig.node.json
Normal file
9
pastabble-frontend/tsconfig.node.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "bundler"
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
7
pastabble-frontend/vite.config.ts
Normal file
7
pastabble-frontend/vite.config.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [svelte()]
|
||||||
|
})
|
44
src/main.rs
44
src/main.rs
@ -1,4 +1,4 @@
|
|||||||
use std::{env, fs, thread};
|
use std::{env, fs::{self, File}, thread};
|
||||||
|
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use kv::{Config, Store, Json, Bucket, Value};
|
use kv::{Config, Store, Json, Bucket, Value};
|
||||||
@ -30,10 +30,20 @@ fn generate_key<T : Value>(key: Option<String>, store: &Bucket<String, T>) -> St
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_query(req: &Request, name: &str) -> Option<String> {
|
||||||
|
let params: Vec<&str> = req.raw_query_string().split('&').collect();
|
||||||
|
let param = params.iter().find(|p|p.starts_with(&format!("{}=", name)));
|
||||||
|
match param {
|
||||||
|
Some(q) => q.split('=').last(),
|
||||||
|
None => None,
|
||||||
|
}.map(|d|d.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Get settings
|
// Get settings
|
||||||
let port: u16 = env::var("PORT").unwrap_or(String::from("8080")).parse().expect("Failed to parse PORT variable");
|
let port: u16 = env::var("PORT").unwrap_or(String::from("8080")).parse().expect("Failed to parse PORT variable");
|
||||||
let data_dir: String = env::var("DATA_DIR").unwrap_or(String::from("./data"));
|
let data_dir: String = env::var("DATA_DIR").unwrap_or(String::from("./data"));
|
||||||
|
let source_dir: String = env::var("WWW_DIR").unwrap_or(String::from("./wwwroot"));
|
||||||
let prefix: Option<String> = env::var("PREFIX").ok();
|
let prefix: Option<String> = env::var("PREFIX").ok();
|
||||||
|
|
||||||
let config = Config::new(data_dir);
|
let config = Config::new(data_dir);
|
||||||
@ -47,12 +57,27 @@ fn main() {
|
|||||||
// Get links bucket
|
// Get links bucket
|
||||||
let links = store.bucket::<String, String>(Some("links"))
|
let links = store.bucket::<String, String>(Some("links"))
|
||||||
.expect("Failed to open links bucket");
|
.expect("Failed to open links bucket");
|
||||||
|
|
||||||
|
|
||||||
// Create server
|
// Create server
|
||||||
let server = Server::new(format!("0.0.0.0:{}", port), move |req| {
|
let server = Server::new(format!("0.0.0.0:{}", port), move |req| {
|
||||||
|
if req.url().ends_with(".html") || req.url().ends_with(".css") || req.url().ends_with(".js") {
|
||||||
|
let asset_response = rouille::match_assets(req, &source_dir);
|
||||||
|
if asset_response.is_success() {
|
||||||
|
return asset_response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
router!(req,
|
router!(req,
|
||||||
(GET) (/) => {
|
(GET) (/) => {
|
||||||
Response::html(&about)
|
match File::open(format!("{}/index.html", &source_dir)) {
|
||||||
|
Ok(file) => {
|
||||||
|
Response::from_file("text/html", file)
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
Response::html(&about)
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
(GET) (/to/{id: String}) => {
|
(GET) (/to/{id: String}) => {
|
||||||
match links.get(&id).expect("Failed to access links DB") {
|
match links.get(&id).expect("Failed to access links DB") {
|
||||||
@ -71,7 +96,13 @@ fn main() {
|
|||||||
// Get note from database, if exists
|
// Get note from database, if exists
|
||||||
match pastes.get(&id).expect("Failed to access pastes DB") {
|
match pastes.get(&id).expect("Failed to access pastes DB") {
|
||||||
Some(paste) => {
|
Some(paste) => {
|
||||||
Response::text(paste.0.content)
|
// If details, return JSON. Else, return text
|
||||||
|
if get_query(req, "details").is_some() {
|
||||||
|
Response::json(&paste.0)
|
||||||
|
} else {
|
||||||
|
Response::text(paste.0.content)
|
||||||
|
.with_additional_header("Access-Control-Allow-Origin", "*")
|
||||||
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
Response::text(format!("Note with ID '{}' not found", &id))
|
Response::text(format!("Note with ID '{}' not found", &id))
|
||||||
@ -110,7 +141,7 @@ fn main() {
|
|||||||
|
|
||||||
// Register paste handler
|
// Register paste handler
|
||||||
fn register_paste(pastes: &Bucket<String, Json<Paste>>, req: &Request, id: Option<String>, prefix: Option<String>) -> Response {
|
fn register_paste(pastes: &Bucket<String, Json<Paste>>, req: &Request, id: Option<String>, prefix: Option<String>) -> Response {
|
||||||
|
|
||||||
// Try read body from form data, and if not present from request body
|
// Try read body from form data, and if not present from request body
|
||||||
let body = match post_input!(req, {
|
let body = match post_input!(req, {
|
||||||
content: String
|
content: String
|
||||||
@ -123,11 +154,14 @@ fn register_paste(pastes: &Bucket<String, Json<Paste>>, req: &Request, id: Optio
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// If lang param is present in query, extract it
|
||||||
|
let language = get_query(req, "lang");
|
||||||
|
|
||||||
// Create and save new note
|
// Create and save new note
|
||||||
let paste = Json(Paste {
|
let paste = Json(Paste {
|
||||||
content: body,
|
content: body,
|
||||||
expires: None,
|
expires: None,
|
||||||
language: None,
|
language,
|
||||||
created: Utc::now()
|
created: Utc::now()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user