Compare commits
23 Commits
Author | SHA1 | Date | |
---|---|---|---|
3516404a5f | |||
d96daa335f | |||
285d9da26d | |||
9ab7a72bce | |||
46dd905509 | |||
63d595c67d | |||
dc0b5f42e6 | |||
9ecbd25488 | |||
83816fbcc6 | |||
11cfbdc3ed | |||
4b7cbb3de2 | |||
b1a572072c | |||
b1071e9579 | |||
da971f8680 | |||
b596f86cc2 | |||
3bcf0832a1 | |||
565f4f23b3 | |||
ef3820a2e1 | |||
1678245750 | |||
3594b6d41f | |||
a754d42b9e | |||
c7e0234d33 | |||
11a9ff53e4 |
94
Cargo.lock
generated
94
Cargo.lock
generated
@ -92,8 +92,8 @@ version = "0.1.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4ca8ce00b267af8ccebbd647de0d61e0674b6e61185cc7a592ff88772bed655"
|
checksum = "b4ca8ce00b267af8ccebbd647de0d61e0674b6e61185cc7a592ff88772bed655"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote 1.0.7",
|
"quote 1.0.8",
|
||||||
"syn 1.0.54",
|
"syn 1.0.55",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -266,8 +266,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "ad26f77093333e0e7c6ffe54ebe3582d908a104e448723eec6d43d08b07143fb"
|
checksum = "ad26f77093333e0e7c6ffe54ebe3582d908a104e448723eec6d43d08b07143fb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.24",
|
"proc-macro2 1.0.24",
|
||||||
"quote 1.0.7",
|
"quote 1.0.8",
|
||||||
"syn 1.0.54",
|
"syn 1.0.55",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -345,8 +345,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e5444eec77a9ec2bfe4524139e09195862e981400c4358d3b760cae634e4c4ee"
|
checksum = "e5444eec77a9ec2bfe4524139e09195862e981400c4358d3b760cae634e4c4ee"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.24",
|
"proc-macro2 1.0.24",
|
||||||
"quote 1.0.7",
|
"quote 1.0.8",
|
||||||
"syn 1.0.54",
|
"syn 1.0.55",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -356,8 +356,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "8d3a45e77e34375a7923b1e8febb049bb011f064714a8e17a1a616fef01da13d"
|
checksum = "8d3a45e77e34375a7923b1e8febb049bb011f064714a8e17a1a616fef01da13d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.24",
|
"proc-macro2 1.0.24",
|
||||||
"quote 1.0.7",
|
"quote 1.0.8",
|
||||||
"syn 1.0.54",
|
"syn 1.0.55",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -561,8 +561,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c"
|
checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.24",
|
"proc-macro2 1.0.24",
|
||||||
"quote 1.0.7",
|
"quote 1.0.8",
|
||||||
"syn 1.0.54",
|
"syn 1.0.55",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -603,8 +603,8 @@ checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2 1.0.24",
|
"proc-macro2 1.0.24",
|
||||||
"quote 1.0.7",
|
"quote 1.0.8",
|
||||||
"syn 1.0.54",
|
"syn 1.0.55",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -695,8 +695,8 @@ checksum = "77408a692f1f97bcc61dc001d752e00643408fbc922e4d634c655df50d595556"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-hack",
|
"proc-macro-hack",
|
||||||
"proc-macro2 1.0.24",
|
"proc-macro2 1.0.24",
|
||||||
"quote 1.0.7",
|
"quote 1.0.8",
|
||||||
"syn 1.0.54",
|
"syn 1.0.55",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -807,9 +807,9 @@ checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.3.1"
|
version = "0.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
]
|
]
|
||||||
@ -1015,7 +1015,7 @@ checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libreddit"
|
name = "libreddit"
|
||||||
version = "0.2.0"
|
version = "0.2.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"askama",
|
"askama",
|
||||||
@ -1228,9 +1228,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot_core"
|
name = "parking_lot_core"
|
||||||
version = "0.8.1"
|
version = "0.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d7c6d9b8427445284a09c55be860a15855ab580a417ccad9da88f5a06787ced0"
|
checksum = "9ccb628cad4f84851442432c60ad8e1f607e29752d0bf072cbd0baf28aa34272"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"instant",
|
"instant",
|
||||||
@ -1271,8 +1271,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895"
|
checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.24",
|
"proc-macro2 1.0.24",
|
||||||
"quote 1.0.7",
|
"quote 1.0.8",
|
||||||
"syn 1.0.54",
|
"syn 1.0.55",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1282,8 +1282,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "f8e8d2bf0b23038a4424865103a4df472855692821aab4e4f5c3312d461d9e5f"
|
checksum = "f8e8d2bf0b23038a4424865103a4df472855692821aab4e4f5c3312d461d9e5f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.24",
|
"proc-macro2 1.0.24",
|
||||||
"quote 1.0.7",
|
"quote 1.0.8",
|
||||||
"syn 1.0.54",
|
"syn 1.0.55",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1369,9 +1369,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.7"
|
version = "1.0.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
|
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.24",
|
"proc-macro2 1.0.24",
|
||||||
]
|
]
|
||||||
@ -1583,8 +1583,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df"
|
checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.24",
|
"proc-macro2 1.0.24",
|
||||||
"quote 1.0.7",
|
"quote 1.0.8",
|
||||||
"syn 1.0.54",
|
"syn 1.0.55",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1631,9 +1631,9 @@ checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.2.2"
|
version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ce32ea0c6c56d5eacaeb814fbed9960547021d3edd010ded1425f180536b20ab"
|
checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@ -1652,9 +1652,9 @@ checksum = "ae524f056d7d770e174287294f562e95044c68e88dec909a00d2094805db9d75"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.3.18"
|
version = "0.3.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "97e0e9fd577458a4f61fb91fcb559ea2afecc54c934119421f9f5d3d5b1a1057"
|
checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"libc",
|
"libc",
|
||||||
@ -1697,10 +1697,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
|
checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.24",
|
"proc-macro2 1.0.24",
|
||||||
"quote 1.0.7",
|
"quote 1.0.8",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"syn 1.0.54",
|
"syn 1.0.55",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1711,12 +1711,12 @@ checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"base-x",
|
"base-x",
|
||||||
"proc-macro2 1.0.24",
|
"proc-macro2 1.0.24",
|
||||||
"quote 1.0.7",
|
"quote 1.0.8",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha1",
|
"sha1",
|
||||||
"syn 1.0.54",
|
"syn 1.0.55",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1738,12 +1738,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.54"
|
version = "1.0.55"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44"
|
checksum = "a571a711dddd09019ccc628e1b17fe87c59b09d513c06c026877aa708334f37a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.24",
|
"proc-macro2 1.0.24",
|
||||||
"quote 1.0.7",
|
"quote 1.0.8",
|
||||||
"unicode-xid 0.2.1",
|
"unicode-xid 0.2.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1763,8 +1763,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56"
|
checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.24",
|
"proc-macro2 1.0.24",
|
||||||
"quote 1.0.7",
|
"quote 1.0.8",
|
||||||
"syn 1.0.54",
|
"syn 1.0.55",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1829,9 +1829,9 @@ checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-hack",
|
"proc-macro-hack",
|
||||||
"proc-macro2 1.0.24",
|
"proc-macro2 1.0.24",
|
||||||
"quote 1.0.7",
|
"quote 1.0.8",
|
||||||
"standback",
|
"standback",
|
||||||
"syn 1.0.54",
|
"syn 1.0.55",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2119,8 +2119,8 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
"proc-macro2 1.0.24",
|
"proc-macro2 1.0.24",
|
||||||
"quote 1.0.7",
|
"quote 1.0.8",
|
||||||
"syn 1.0.54",
|
"syn 1.0.55",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2142,7 +2142,7 @@ version = "0.2.69"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084"
|
checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote 1.0.7",
|
"quote 1.0.8",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2153,8 +2153,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549"
|
checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.24",
|
"proc-macro2 1.0.24",
|
||||||
"quote 1.0.7",
|
"quote 1.0.8",
|
||||||
"syn 1.0.54",
|
"syn 1.0.55",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
@ -3,7 +3,7 @@ name = "libreddit"
|
|||||||
description = " Alternative private front-end to Reddit"
|
description = " Alternative private front-end to Reddit"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
repository = "https://github.com/spikecodes/libreddit"
|
repository = "https://github.com/spikecodes/libreddit"
|
||||||
version = "0.2.0"
|
version = "0.2.2"
|
||||||
authors = ["spikecodes <19519553+spikecodes@users.noreply.github.com>"]
|
authors = ["spikecodes <19519553+spikecodes@users.noreply.github.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
118
README.md
118
README.md
@ -2,19 +2,47 @@
|
|||||||
|
|
||||||
> An alternative private front-end to Reddit
|
> An alternative private front-end to Reddit
|
||||||
|
|
||||||
Libre + Reddit = Libreddit
|
Libre + Reddit = [Libreddit](https://libredd.it)
|
||||||
|
|
||||||
- 🚀 Fast: written in Rust for blazing fast speeds and safety
|
- 🚀 Fast: written in Rust for blazing fast speeds and safety
|
||||||
- ☁️ Light: no javascript, no ads, no tracking
|
- ☁️ Light: no JavaScript, no ads, no tracking
|
||||||
- 🕵 Private: all requests are proxied through the server, including media
|
- 🕵 Private: all requests are proxied through the server, including media
|
||||||
- 🔒 Safe: does not rely on Reddit OAuth or require a Reddit API Key
|
- 🔒 Safe: does not rely on Reddit OAuth or require a Reddit API Key
|
||||||
- 📱 Responsive: works great on mobile!
|
- 📱 Responsive: works great on mobile!
|
||||||
|
|
||||||
Think Invidious but for Reddit. Watch your cat videos without being watched.
|
Like [Invidious](https://github.com/iv-org/invidious) but for Reddit. Browse the coldest takes of [r/unpopularopinion](https://libredd.it/r/unpopularopinion) without being [tracked](#reddit).
|
||||||
|
|
||||||
|
## Contents
|
||||||
|
- [Screenshot](#screenshot)
|
||||||
|
- [Instances](#instances)
|
||||||
|
- [About](#about)
|
||||||
|
- [Elsewhere](#elsewhere)
|
||||||
|
- [Info](#info)
|
||||||
|
- [In Progress](#in-progress)
|
||||||
|
- [Teddit Comparison](#how-does-it-compare-to-teddit)
|
||||||
|
- [Comparison](#comparison)
|
||||||
|
- [Speed](#speed)
|
||||||
|
- [Privacy](#privacy)
|
||||||
|
- [Installation](#installation)
|
||||||
|
- [Cargo](#a-cargo)
|
||||||
|
- [Docker](#b-docker)
|
||||||
|
- [AUR](#c-aur)
|
||||||
|
- [GitHub Releases](#d-github-releases)
|
||||||
|
- [Repl.it](#e-replit)
|
||||||
|
- Developing
|
||||||
|
- [Deployment](#deployment)
|
||||||
|
- [Building](#building)
|
||||||
|
|
||||||
## Screenshot
|
## Screenshot
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
## Instances
|
||||||
|
|
||||||
|
Feel free to [open an issue](https://github.com/spikecodes/libreddit/issues/new) to have your [selfhosted instance](#deployment) listed here!
|
||||||
|
|
||||||
|
- [libredd.it](https://libredd.it) 🇺🇸 (Thank you to [YeapGuy](https://github.com/YeapGuy)!)
|
||||||
|
- [libreddit.spike.codes](https://libreddit.spike.codes) 🇺🇸
|
||||||
|
|
||||||
## About
|
## About
|
||||||
|
|
||||||
@ -26,13 +54,11 @@ Find Libreddit on...
|
|||||||
- 🦊 GitLab: [spikecodes/libreddit](https://gitlab.com/spikecodes/libreddit)
|
- 🦊 GitLab: [spikecodes/libreddit](https://gitlab.com/spikecodes/libreddit)
|
||||||
|
|
||||||
### Info
|
### Info
|
||||||
Libreddit hopes to provide an easier way to browse Reddit, without the ads, trackers and bloat. Libreddit was inspired by other alternative front-ends to popular services such as [Invidious](https://github.com/iv-org/invidious) for YouTube, [Nitter](https://github.com/zedeus/nitter) for Twitter, and [Bibliogram](https://sr.ht/~cadence/bibliogram/) for Instagram.
|
Libreddit hopes to provide an easier way to browse Reddit, without the ads, trackers, and bloat. Libreddit was inspired by other alternative front-ends to popular services such as [Invidious](https://github.com/iv-org/invidious) for YouTube, [Nitter](https://github.com/zedeus/nitter) for Twitter, and [Bibliogram](https://sr.ht/~cadence/bibliogram/) for Instagram.
|
||||||
|
|
||||||
Libreddit currently implements most of Reddit's functionalities but still lacks a few features that are being worked on below.
|
Libreddit currently implements most of Reddit's functionalities but still lacks a few features that are being worked on below.
|
||||||
|
|
||||||
### In Progress
|
### In Progress
|
||||||
- Nested comments
|
|
||||||
- User flairs
|
|
||||||
- Searching
|
- Searching
|
||||||
|
|
||||||
### How does it compare to Teddit?
|
### How does it compare to Teddit?
|
||||||
@ -41,15 +67,67 @@ Teddit is another awesome open source project designed to provide an alternative
|
|||||||
|
|
||||||
If you are looking to compare, the biggest differences I have noticed are:
|
If you are looking to compare, the biggest differences I have noticed are:
|
||||||
- Libreddit is themed around Reddit's redesign whereas Teddit appears to stick much closer to Reddit's old design. This may suit some users better as design is always subjective.
|
- Libreddit is themed around Reddit's redesign whereas Teddit appears to stick much closer to Reddit's old design. This may suit some users better as design is always subjective.
|
||||||
- Libreddit is written in Rust for speed and memory safety. It uses Actix Web, which was [benchmarked as the fastest web server for single queries](https://www.techempower.com/benchmarks/#hw=ph&test=db).
|
- Libreddit is written in [Rust](https://www.rust-lang.org) for speed and memory safety. It uses [Actix Web](https://actix.rs), which was [benchmarked as the fastest web server for single queries](https://www.techempower.com/benchmarks/#hw=ph&test=db).
|
||||||
- Unlike Teddit (at the time of writing this), Libreddit does not require a Reddit API key to host.
|
- Unlike Teddit (at the time of writing this), Libreddit does not require a Reddit API key to host.
|
||||||
|
|
||||||
## Instances
|
## Comparison
|
||||||
|
|
||||||
Feel free to [open an issue](https://github.com/spikecodes/libreddit/issues/new) to have your selfhosted instance listed here!
|
This section outlines how Libreddit compares to Reddit.
|
||||||
|
|
||||||
- [libredd.it](https://libredd.it) 🇺🇸 (Thank you to [YeapGuy](https://github.com/YeapGuy)!)
|
### Speed
|
||||||
- [libreddit.spike.codes](https://libreddit.spike.codes) 🇺🇸
|
|
||||||
|
Lasted tested December 21, 2020.
|
||||||
|
|
||||||
|
Results from Google Lighthouse ([Libreddit Report](https://lighthouse-dot-webdotdevsite.appspot.com/lh/html?url=https%3A%2F%2Flibredd.it), [Reddit Report](https://lighthouse-dot-webdotdevsite.appspot.com/lh/html?url=https%3A%2F%2Fwww.reddit.com%2F)).
|
||||||
|
|
||||||
|
| | Libreddit | Reddit |
|
||||||
|
|---------------------|---------------|-----------|
|
||||||
|
| Requests | 22 | 70 |
|
||||||
|
| Resource Size | 135 KiB | 2,222 KiB |
|
||||||
|
| Time to Interactive | **1.7 s** | **11.5 s**|
|
||||||
|
|
||||||
|
### Privacy
|
||||||
|
|
||||||
|
#### Reddit
|
||||||
|
|
||||||
|
**Logging:** According to Reddit's [privacy policy](https://www.redditinc.com/policies/privacy-policy), they "may [automatically] log information" including:
|
||||||
|
- IP address
|
||||||
|
- User-agent string
|
||||||
|
- Browser type
|
||||||
|
- Operating system
|
||||||
|
- Referral URLs
|
||||||
|
- Device information (e.g., device IDs)
|
||||||
|
- Device settings
|
||||||
|
- Pages visited
|
||||||
|
- Links clicked
|
||||||
|
- The requested URL
|
||||||
|
- Search terms
|
||||||
|
|
||||||
|
**Location:** The same privacy policy goes on to describe location data may be collected through the use of:
|
||||||
|
- GPS (consensual)
|
||||||
|
- Bluetooth (consensual)
|
||||||
|
- Content associated with a location (consensual)
|
||||||
|
- Your IP Address
|
||||||
|
|
||||||
|
**Cookies:** Reddit's [cookie notice](https://www.redditinc.com/policies/cookies) documents the array of cookies used by Reddit including/regarding:
|
||||||
|
- Authentication
|
||||||
|
- Functionality
|
||||||
|
- Analytics and Performance
|
||||||
|
- Advertising
|
||||||
|
- Third-Party Cookies
|
||||||
|
- Third-Party Site
|
||||||
|
|
||||||
|
#### Libreddit
|
||||||
|
|
||||||
|
For transparency, I hope to describe all the ways Libreddit handles user privacy.
|
||||||
|
|
||||||
|
**Logging:** In production (when running the binary, hosting with docker, or using the official instances), Libreddit logs nothing. When debugging (running from source without `--release`), Libreddit logs post IDs fetched to aid troubleshooting but nothing else.
|
||||||
|
|
||||||
|
**DNS:** Both official domains (`libredd.it` and `libreddit.spike.codes`) use Cloudflare as the DNS resolver. Though, the sites are not proxied through Cloudflare meaning Cloudflare doesn't have access to user traffic.
|
||||||
|
|
||||||
|
**Cookies:** Libreddit uses no cookies currently but eventually, I plan to add a configuration page where users can store an optional cookie to save their preferred theme, default sorting algorithm, or default layout.
|
||||||
|
|
||||||
|
**Hosting:** The official instances (`libredd.it` and `libreddit.spike.codes`) are hosted on [Repl.it](https://repl.it/) which monitors usage to prevent abuse. I can understand if this invalidates certain users' threat models and therefore, selfhosting and browsing through Tor are welcomed.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@ -85,9 +163,19 @@ yay -S libreddit-git
|
|||||||
### D) GitHub Releases
|
### D) GitHub Releases
|
||||||
|
|
||||||
If you're on Linux and none of these methods work for you, you can grab a Linux binary from [the newest release](https://github.com/spikecodes/libreddit/releases/latest).
|
If you're on Linux and none of these methods work for you, you can grab a Linux binary from [the newest release](https://github.com/spikecodes/libreddit/releases/latest).
|
||||||
Currently Libreddit does not have Windows or MacOS binaries but those will be available soon.
|
Currently, Libreddit does not have Windows or macOS binaries but those will be available soon.
|
||||||
|
|
||||||
## Deploy an Instance
|
### E) Repl.it
|
||||||
|
|
||||||
|
**Note:** Repl.it is a free option but they are *not* private and are monitor server usage to prevent abuse. If you really need a free and easy setup, this method may work best for you.
|
||||||
|
|
||||||
|
1. Create a Repl.it account (see note above)
|
||||||
|
2. Visit [the official Repl](https://repl.it/@spikethecoder/libreddit) and fork it
|
||||||
|
3. Hit the run button to download the latest Libreddit version and start it
|
||||||
|
|
||||||
|
In the web preview (defaults to top right), you should see your instance hosted where you can assign a [custom domain](https://docs.repl.it/repls/web-hosting#custom-domains).
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
Once installed, deploy Libreddit (unless you're using Docker) by running:
|
Once installed, deploy Libreddit (unless you're using Docker) by running:
|
||||||
|
|
||||||
@ -105,7 +193,7 @@ To disable the media proxy built into Libreddit, run:
|
|||||||
libreddit --no-default-features
|
libreddit --no-default-features
|
||||||
```
|
```
|
||||||
|
|
||||||
## Building from Source
|
## Building
|
||||||
|
|
||||||
```
|
```
|
||||||
git clone https://github.com/spikecodes/libreddit
|
git clone https://github.com/spikecodes/libreddit
|
||||||
|
@ -60,6 +60,7 @@ async fn main() -> std::io::Result<()> {
|
|||||||
// POST SERVICES
|
// POST SERVICES
|
||||||
.route("/{id:.{5,6}}/", web::get().to(post::short))
|
.route("/{id:.{5,6}}/", web::get().to(post::short))
|
||||||
.route("/r/{sub}/comments/{id}/{title}/", web::get().to(post::page))
|
.route("/r/{sub}/comments/{id}/{title}/", web::get().to(post::page))
|
||||||
|
.route("/r/{sub}/comments/{id}/{title}/{comment_id}/", web::get().to(post::comment))
|
||||||
})
|
})
|
||||||
.bind(address.clone())
|
.bind(address.clone())
|
||||||
.expect(format!("Cannot bind to the address: {}", address).as_str())
|
.expect(format!("Cannot bind to the address: {}", address).as_str())
|
||||||
|
@ -19,10 +19,10 @@ async fn render(sub_name: String, sort: Option<String>, ends: (Option<String>, O
|
|||||||
|
|
||||||
// Build the Reddit JSON API url
|
// Build the Reddit JSON API url
|
||||||
let url = match ends.0 {
|
let url = match ends.0 {
|
||||||
Some(val) => format!("https://www.reddit.com/r/{}/{}.json?before={}&count=25", sub_name, sorting, val),
|
Some(val) => format!("r/{}/{}.json?before={}&count=25", sub_name, sorting, val),
|
||||||
None => match ends.1 {
|
None => match ends.1 {
|
||||||
Some(val) => format!("https://www.reddit.com/r/{}/{}.json?after={}&count=25", sub_name, sorting, val),
|
Some(val) => format!("r/{}/{}.json?after={}&count=25", sub_name, sorting, val),
|
||||||
None => format!("https://www.reddit.com/r/{}/{}.json", sub_name, sorting),
|
None => format!("r/{}/{}.json", sub_name, sorting),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
39
src/post.rs
39
src/post.rs
@ -17,12 +17,19 @@ struct PostTemplate {
|
|||||||
sort: String,
|
sort: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn render(id: String, sort: String) -> Result<HttpResponse> {
|
async fn render(id: String, sort: Option<String>, comment_id: Option<String>) -> Result<HttpResponse> {
|
||||||
// Log the post ID being fetched
|
// Log the post ID being fetched in debug mode
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
dbg!(&id);
|
dbg!(&id);
|
||||||
|
|
||||||
|
// Handling sort paramater
|
||||||
|
let sorting: String = sort.unwrap_or("confidence".to_string());
|
||||||
|
|
||||||
// Build the Reddit JSON API url
|
// Build the Reddit JSON API url
|
||||||
let url: String = format!("https://reddit.com/{}.json?sort={}", id, sort);
|
let url: String = match comment_id {
|
||||||
|
None => format!("{}.json?sort={}", id, sorting),
|
||||||
|
Some(val) => format!("{}.json?sort={}&comment={}", id, sorting, val)
|
||||||
|
};
|
||||||
|
|
||||||
// Send a request to the url, receive JSON in response
|
// Send a request to the url, receive JSON in response
|
||||||
let req = request(url).await;
|
let req = request(url).await;
|
||||||
@ -48,7 +55,7 @@ async fn render(id: String, sort: String) -> Result<HttpResponse> {
|
|||||||
let s = PostTemplate {
|
let s = PostTemplate {
|
||||||
comments: comments.unwrap(),
|
comments: comments.unwrap(),
|
||||||
post: post.unwrap(),
|
post: post.unwrap(),
|
||||||
sort: sort,
|
sort: sorting,
|
||||||
}
|
}
|
||||||
.render()
|
.render()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -56,15 +63,16 @@ async fn render(id: String, sort: String) -> Result<HttpResponse> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SERVICES
|
// SERVICES
|
||||||
pub async fn short(web::Path(id): web::Path<String>) -> Result<HttpResponse> {
|
pub async fn short(web::Path(id): web::Path<String>, params: web::Query<Params>) -> Result<HttpResponse> {
|
||||||
render(id.to_string(), "confidence".to_string()).await
|
render(id, params.sort.clone(), None).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn comment(web::Path((_sub, id, _title, comment_id)): web::Path<(String, String, String, String)>, params: web::Query<Params>) -> Result<HttpResponse> {
|
||||||
|
render(id, params.sort.clone(), Some(comment_id)).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn page(web::Path((_sub, id)): web::Path<(String, String)>, params: web::Query<Params>) -> Result<HttpResponse> {
|
pub async fn page(web::Path((_sub, id)): web::Path<(String, String)>, params: web::Query<Params>) -> Result<HttpResponse> {
|
||||||
match ¶ms.sort {
|
render(id, params.sort.clone(), None).await
|
||||||
Some(sort) => render(id, sort.to_string()).await,
|
|
||||||
None => render(id, "confidence".to_string()).await,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UTILITIES
|
// UTILITIES
|
||||||
@ -115,6 +123,11 @@ async fn parse_post(json: serde_json::Value) -> Result<Post, &'static str> {
|
|||||||
community: val(post_data, "subreddit").await,
|
community: val(post_data, "subreddit").await,
|
||||||
body: markdown_to_html(post_data["data"]["selftext"].as_str().unwrap()).await,
|
body: markdown_to_html(post_data["data"]["selftext"].as_str().unwrap()).await,
|
||||||
author: val(post_data, "author").await,
|
author: val(post_data, "author").await,
|
||||||
|
author_flair: Flair(
|
||||||
|
val(post_data, "author_flair_text").await,
|
||||||
|
val(post_data, "author_flair_background_color").await,
|
||||||
|
val(post_data, "author_flair_text_color").await,
|
||||||
|
),
|
||||||
url: val(post_data, "permalink").await,
|
url: val(post_data, "permalink").await,
|
||||||
score: format_num(score),
|
score: format_num(score),
|
||||||
post_type: media.0,
|
post_type: media.0,
|
||||||
@ -159,11 +172,17 @@ async fn parse_comments(json: serde_json::Value) -> Result<Vec<Comment>, &'stati
|
|||||||
};
|
};
|
||||||
|
|
||||||
comments.push(Comment {
|
comments.push(Comment {
|
||||||
|
id: val(comment, "id").await,
|
||||||
body: body,
|
body: body,
|
||||||
author: val(comment, "author").await,
|
author: val(comment, "author").await,
|
||||||
score: format_num(score),
|
score: format_num(score),
|
||||||
time: Utc.timestamp(unix_time, 0).format("%b %e %Y %H:%M UTC").to_string(),
|
time: Utc.timestamp(unix_time, 0).format("%b %e %Y %H:%M UTC").to_string(),
|
||||||
replies: replies,
|
replies: replies,
|
||||||
|
flair: Flair(
|
||||||
|
val(comment, "author_flair_text").await,
|
||||||
|
val(comment, "author_flair_background_color").await,
|
||||||
|
val(comment, "author_flair_text_color").await,
|
||||||
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,14 +26,25 @@ pub async fn render(sub_name: String, sort: Option<String>, ends: (Option<String
|
|||||||
|
|
||||||
// Build the Reddit JSON API url
|
// Build the Reddit JSON API url
|
||||||
let url = match ends.0 {
|
let url = match ends.0 {
|
||||||
Some(val) => format!("https://www.reddit.com/r/{}/{}.json?before={}&count=25", sub_name, sorting, val),
|
Some(val) => format!("r/{}/{}.json?before={}&count=25", sub_name, sorting, val),
|
||||||
None => match ends.1 {
|
None => match ends.1 {
|
||||||
Some(val) => format!("https://www.reddit.com/r/{}/{}.json?after={}&count=25", sub_name, sorting, val),
|
Some(val) => format!("r/{}/{}.json?after={}&count=25", sub_name, sorting, val),
|
||||||
None => format!("https://www.reddit.com/r/{}/{}.json", sub_name, sorting),
|
None => format!("r/{}/{}.json", sub_name, sorting),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let sub_result = subreddit(&sub_name).await;
|
let sub_result = if !&sub_name.contains("+") {
|
||||||
|
subreddit(&sub_name).await
|
||||||
|
} else {
|
||||||
|
Ok(Subreddit {
|
||||||
|
name: String::new(),
|
||||||
|
title: String::new(),
|
||||||
|
description: String::new(),
|
||||||
|
icon: String::new(),
|
||||||
|
members: String::new(),
|
||||||
|
active: String::new(),
|
||||||
|
})
|
||||||
|
};
|
||||||
let items_result = fetch_posts(url, String::new()).await;
|
let items_result = fetch_posts(url, String::new()).await;
|
||||||
|
|
||||||
if sub_result.is_err() || items_result.is_err() {
|
if sub_result.is_err() || items_result.is_err() {
|
||||||
@ -68,7 +79,7 @@ pub async fn render(sub_name: String, sort: Option<String>, ends: (Option<String
|
|||||||
// SUBREDDIT
|
// SUBREDDIT
|
||||||
async fn subreddit(sub: &String) -> Result<Subreddit, &'static str> {
|
async fn subreddit(sub: &String) -> Result<Subreddit, &'static str> {
|
||||||
// Build the Reddit JSON API url
|
// Build the Reddit JSON API url
|
||||||
let url: String = format!("https://www.reddit.com/r/{}/about.json", sub);
|
let url: String = format!("r/{}/about.json", sub);
|
||||||
|
|
||||||
// Send a request to the url, receive JSON in response
|
// Send a request to the url, receive JSON in response
|
||||||
let req = request(url).await;
|
let req = request(url).await;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// CRATES
|
// CRATES
|
||||||
use crate::utils::{fetch_posts, nested_val, request, ErrorTemplate, Params, Post, User};
|
use crate::utils::{fetch_posts, format_url, nested_val, request, ErrorTemplate, Params, Post, User};
|
||||||
use actix_web::{http::StatusCode, web, HttpResponse, Result};
|
use actix_web::{http::StatusCode, web, HttpResponse, Result};
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ struct UserTemplate {
|
|||||||
|
|
||||||
async fn render(username: String, sort: String) -> Result<HttpResponse> {
|
async fn render(username: String, sort: String) -> Result<HttpResponse> {
|
||||||
// Build the Reddit JSON API url
|
// Build the Reddit JSON API url
|
||||||
let url: String = format!("https://www.reddit.com/user/{}/.json?sort={}", username, sort);
|
let url: String = format!("user/{}/.json?sort={}", username, sort);
|
||||||
|
|
||||||
let user = user(&username).await;
|
let user = user(&username).await;
|
||||||
let posts = fetch_posts(url, "Comment".to_string()).await;
|
let posts = fetch_posts(url, "Comment".to_string()).await;
|
||||||
@ -49,7 +49,7 @@ pub async fn page(web::Path(username): web::Path<String>, params: web::Query<Par
|
|||||||
// USER
|
// USER
|
||||||
async fn user(name: &String) -> Result<User, &'static str> {
|
async fn user(name: &String) -> Result<User, &'static str> {
|
||||||
// Build the Reddit JSON API url
|
// Build the Reddit JSON API url
|
||||||
let url: String = format!("https://www.reddit.com/user/{}/about.json", name);
|
let url: String = format!("user/{}/about.json", name);
|
||||||
|
|
||||||
// Send a request to the url, receive JSON in response
|
// Send a request to the url, receive JSON in response
|
||||||
let req = request(url).await;
|
let req = request(url).await;
|
||||||
@ -65,7 +65,7 @@ async fn user(name: &String) -> Result<User, &'static str> {
|
|||||||
// Parse the JSON output into a User struct
|
// Parse the JSON output into a User struct
|
||||||
Ok(User {
|
Ok(User {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
icon: nested_val(&res, "subreddit", "icon_img").await,
|
icon: format_url(nested_val(&res, "subreddit", "icon_img").await.as_str()).await,
|
||||||
karma: res["data"]["total_karma"].as_i64().unwrap(),
|
karma: res["data"]["total_karma"].as_i64().unwrap(),
|
||||||
banner: nested_val(&res, "subreddit", "banner_img").await,
|
banner: nested_val(&res, "subreddit", "banner_img").await,
|
||||||
description: nested_val(&res, "subreddit", "public_description").await,
|
description: nested_val(&res, "subreddit", "public_description").await,
|
||||||
|
12
src/utils.rs
12
src/utils.rs
@ -22,6 +22,7 @@ pub struct Post {
|
|||||||
pub community: String,
|
pub community: String,
|
||||||
pub body: String,
|
pub body: String,
|
||||||
pub author: String,
|
pub author: String,
|
||||||
|
pub author_flair: Flair,
|
||||||
pub url: String,
|
pub url: String,
|
||||||
pub score: String,
|
pub score: String,
|
||||||
pub post_type: String,
|
pub post_type: String,
|
||||||
@ -33,8 +34,10 @@ pub struct Post {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
// Comment with content, post, score and data/time that it was posted
|
// Comment with content, post, score and data/time that it was posted
|
||||||
pub struct Comment {
|
pub struct Comment {
|
||||||
|
pub id: String,
|
||||||
pub body: String,
|
pub body: String,
|
||||||
pub author: String,
|
pub author: String,
|
||||||
|
pub flair: Flair,
|
||||||
pub score: String,
|
pub score: String,
|
||||||
pub time: String,
|
pub time: String,
|
||||||
pub replies: Vec<Comment>,
|
pub replies: Vec<Comment>,
|
||||||
@ -147,6 +150,11 @@ pub async fn fetch_posts(url: String, fallback_title: String) -> Result<(Vec<Pos
|
|||||||
community: val(post, "subreddit").await,
|
community: val(post, "subreddit").await,
|
||||||
body: val(post, "body").await,
|
body: val(post, "body").await,
|
||||||
author: val(post, "author").await,
|
author: val(post, "author").await,
|
||||||
|
author_flair: Flair(
|
||||||
|
val(post, "author_flair_text").await,
|
||||||
|
val(post, "author_flair_background_color").await,
|
||||||
|
val(post, "author_flair_text_color").await,
|
||||||
|
),
|
||||||
score: format_num(score),
|
score: format_num(score),
|
||||||
post_type: "link".to_string(),
|
post_type: "link".to_string(),
|
||||||
media: img,
|
media: img,
|
||||||
@ -173,7 +181,9 @@ pub async fn fetch_posts(url: String, fallback_title: String) -> Result<(Vec<Pos
|
|||||||
|
|
||||||
// Make a request to a Reddit API and parse the JSON response
|
// Make a request to a Reddit API and parse the JSON response
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub async fn request(url: String) -> Result<serde_json::Value, &'static str> {
|
pub async fn request(mut url: String) -> Result<serde_json::Value, &'static str> {
|
||||||
|
url = format!("https://www.reddit.com/{}", url);
|
||||||
|
|
||||||
// --- actix-web::client ---
|
// --- actix-web::client ---
|
||||||
// let client = actix_web::client::Client::default();
|
// let client = actix_web::client::Client::default();
|
||||||
// let res = client
|
// let res = client
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
User-Agent: *
|
User-agent: *
|
||||||
Disallow: /
|
Allow: /
|
119
static/style.css
119
static/style.css
@ -1,6 +1,7 @@
|
|||||||
/* General */
|
/* General */
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
|
--accent: aqua;
|
||||||
--background: #0F0F0F;
|
--background: #0F0F0F;
|
||||||
--foreground: #222;
|
--foreground: #222;
|
||||||
--outside: #1F1F1F;
|
--outside: #1F1F1F;
|
||||||
@ -15,16 +16,18 @@
|
|||||||
color: white;
|
color: white;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
|
visibility: visible !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
nav {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
color: aqua;
|
color: var(--accent);
|
||||||
background: var(--outside);
|
background: var(--outside);
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@ -63,6 +66,7 @@ a:not(.post_right):hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#about {
|
#about {
|
||||||
|
padding-top: 20px;
|
||||||
background: #151515;
|
background: #151515;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,14 +129,27 @@ a:not(.post_right):hover {
|
|||||||
/* Sorting */
|
/* Sorting */
|
||||||
|
|
||||||
#sort {
|
#sort {
|
||||||
max-width: 750px;
|
background: var(--outside);
|
||||||
margin: 20px -10px;
|
box-shadow: var(--black-contrast);
|
||||||
display: flex;
|
border: 0px;
|
||||||
justify-content: start;
|
padding: 0px 15px;
|
||||||
padding: 0px 10px;
|
margin: 20px 0px;
|
||||||
|
height: 40px;
|
||||||
|
font-size: 15px;
|
||||||
|
border-radius: 5px 0px 0px 5px;
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sort_submit {
|
||||||
|
background: var(--highlighted);
|
||||||
|
border: 0px;
|
||||||
|
font-size: 15px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 0px 5px 5px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sort > div, footer > a {
|
#sort > div, footer > a {
|
||||||
|
box-shadow: var(--black-contrast);
|
||||||
background: var(--outside);
|
background: var(--outside);
|
||||||
color: lightgrey;
|
color: lightgrey;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
@ -143,7 +160,7 @@ a:not(.post_right):hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#sort > div.selected {
|
#sort > div.selected {
|
||||||
background: aqua;
|
background: var(--accent);
|
||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,8 +208,8 @@ a:not(.post_right):hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.post_score {
|
.post_score {
|
||||||
margin-top: 1em;
|
margin-top: 20px;
|
||||||
color: aqua;
|
color: var(--accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.post_right {
|
.post_right {
|
||||||
@ -226,16 +243,16 @@ a:not(.post_right):hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.post_body > p:not(:first-child) {
|
.post_body > p:not(:first-child) {
|
||||||
margin-top: 1.5em;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post_body a {
|
.post_body a {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
color: aqua;
|
color: var(--accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
#post_url {
|
#post_url {
|
||||||
color: aqua;
|
color: var(--accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.post_thumbnail {
|
.post_thumbnail {
|
||||||
@ -251,8 +268,8 @@ a:not(.post_right):hover {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
small {
|
.post_flair {
|
||||||
background: aqua;
|
background: var(--accent);
|
||||||
color: black;
|
color: black;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
@ -264,14 +281,10 @@ small {
|
|||||||
/* Comment */
|
/* Comment */
|
||||||
|
|
||||||
.comment {
|
.comment {
|
||||||
margin-top: 1em;
|
margin-top: 15px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
display: flex;
|
display: flex;
|
||||||
/* border: 2px solid var(--foreground); */
|
font-size: 15px;
|
||||||
}
|
|
||||||
|
|
||||||
.comment:hover {
|
|
||||||
background: var(--post);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment_left, .comment_right {
|
.comment_left, .comment_right {
|
||||||
@ -282,7 +295,7 @@ small {
|
|||||||
.comment_left {
|
.comment_left {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
min-width: 50px;
|
min-width: 50px;
|
||||||
padding: 5px;
|
padding: 5px 0px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,12 +307,19 @@ small {
|
|||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment_upvote {
|
.comment_author.op {
|
||||||
margin-top: 0.5em;
|
color: var(--accent);
|
||||||
border-radius: 5px 5px 0px 0px;
|
font-weight: bold;
|
||||||
background: var(--foreground);
|
}
|
||||||
width: 40px;
|
|
||||||
padding: 10px 0px 0px 0px;
|
.author_flair {
|
||||||
|
background: var(--highlighted);
|
||||||
|
color: white;
|
||||||
|
padding: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment_subreddit {
|
.comment_subreddit {
|
||||||
@ -307,7 +327,7 @@ small {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.comment_score {
|
.comment_score {
|
||||||
color: aqua;
|
color: var(--accent);
|
||||||
background: var(--foreground);
|
background: var(--foreground);
|
||||||
min-width: 40px;
|
min-width: 40px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
@ -341,21 +361,26 @@ small {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.comment_body > p:not(:first-child) {
|
.comment_body > p:not(:first-child) {
|
||||||
margin-top: 1.5em;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment_body a {
|
.comment_body a {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
color: aqua;
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.deeper_replies {
|
||||||
|
color: var(--accent);
|
||||||
|
margin-left: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::marker {
|
::marker {
|
||||||
color: aqua;
|
color: var(--accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.reply {
|
.replies > .comment {
|
||||||
margin-top: 0;
|
margin-left: -20px;
|
||||||
margin-left: 2em;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datetime {
|
.datetime {
|
||||||
@ -377,16 +402,31 @@ small {
|
|||||||
background: black;
|
background: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Code */
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--outside);
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-shadow: var(--black-contrast);
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Tables */
|
/* Tables */
|
||||||
|
|
||||||
table {
|
table {
|
||||||
border: 3px var(--highlighted) solid;
|
border: 3px var(--highlighted) solid;
|
||||||
border-spacing: 0rem;
|
border-spacing: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
td, th {
|
td, th {
|
||||||
border: 1px var(--highlighted) solid;
|
border: 1px var(--highlighted) solid;
|
||||||
padding: 0.5em;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mobile */
|
/* Mobile */
|
||||||
@ -412,6 +452,11 @@ td, th {
|
|||||||
max-width: initial;
|
max-width: initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.replies > .comment {
|
||||||
|
margin-left: -25px;
|
||||||
|
padding: 5px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
.datetime {
|
.datetime {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
@ -2,27 +2,21 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<title>{% block title %}{% endblock %}</title>
|
<title>{% block title %}Libreddit{% endblock %}</title>
|
||||||
|
<meta http-equiv="Referrer-Policy" content="no-referrer">
|
||||||
|
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; style-src 'self' 'unsafe-inline'; base-uri 'none'; form-action 'self';">
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
<meta name="description" content="View on Libreddit, an alternative private front-end to Reddit.">
|
<meta name="description" content="View on Libreddit, an alternative private front-end to Reddit.">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
||||||
<link rel="stylesheet" href="/style.css">
|
<link rel="stylesheet" href="/style.css">
|
||||||
{% block sortstyle %}
|
|
||||||
<style>
|
|
||||||
#sort > #sort_{{ sort }} {
|
|
||||||
background: aqua;
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
{% endblock %}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body style="visibility: hidden;">
|
||||||
{% block header %}
|
{% block navbar %}
|
||||||
<header>
|
<nav>
|
||||||
<a href="/"><span id="lib">lib</span>reddit. <span id="version">v{{ env!("CARGO_PKG_VERSION") }}</span></a>
|
<a href="/"><span id="lib">lib</span>reddit. <span id="version">v{{ env!("CARGO_PKG_VERSION") }}</span></a>
|
||||||
<a id="github" href="https://github.com/spikecodes/libreddit">GITHUB</a>
|
<a id="github" href="https://github.com/spikecodes/libreddit">GITHUB</a>
|
||||||
</header>
|
</nav>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}Libreddit{% endblock %}
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div id="sort">
|
<form>
|
||||||
<div id="sort_hot"><a href="?sort=hot">Hot</a></div>
|
<select id="sort" name="sort">
|
||||||
<div id="sort_top"><a href="?sort=top">Top</a></div>
|
<option value="confidence" {% if sort == "confidence" %}selected{% endif %}>Best</option>
|
||||||
<div id="sort_new"><a href="?sort=new">New</a></div>
|
<option value="hot" {% if sort == "hot" %}selected{% endif %}>Hot</option>
|
||||||
<div id="sort_rising"><a href="?sort=rising">Rising</a></div>
|
<option value="new" {% if sort == "new" %}selected{% endif %}>New</option>
|
||||||
</div>
|
<option value="top" {% if sort == "top" %}selected{% endif %}>Top</option>
|
||||||
|
</select><input id="sort_submit" type="submit" value="→">
|
||||||
|
</form>
|
||||||
{% for post in posts %}
|
{% for post in posts %}
|
||||||
<div class="post">
|
<div class="post">
|
||||||
<div class="post_left">
|
<div class="post_left">
|
||||||
@ -15,14 +16,15 @@
|
|||||||
<div class="post_right">
|
<div class="post_right">
|
||||||
<h4>
|
<h4>
|
||||||
<b><a class="post_subreddit" href="/r/{{ post.community }}">r/{{ post.community }}</a></b>
|
<b><a class="post_subreddit" href="/r/{{ post.community }}">r/{{ post.community }}</a></b>
|
||||||
•
|
• <a class="post_author" href="/u/{{ post.author }}">u/{{ post.author }}</a>
|
||||||
Posted by
|
{% if post.author_flair.0 != "" %}
|
||||||
<a class="post_author" href="/u/{{ post.author }}">u/{{ post.author }}</a>
|
<small class="author_flair">{{ post.author_flair.0 }}</small>
|
||||||
|
{% endif %}
|
||||||
<span class="datetime" style="float: right;">{{ post.time }}</span>
|
<span class="datetime" style="float: right;">{{ post.time }}</span>
|
||||||
</h4>
|
</h4>
|
||||||
<h3 class="post_title">
|
<h3 class="post_title">
|
||||||
{% if post.flair.0 != "" %}
|
{% if post.flair.0 != "" %}
|
||||||
<small style="color:{{ post.flair.2 }}; background:{{ post.flair.1 }}">{{ post.flair.0 }}</small>
|
<small class="post_flair" style="color:{{ post.flair.2 }}; background:{{ post.flair.1 }}">{{ post.flair.0 }}</small>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="{{ post.url }}">{{ post.title }}</a>
|
<a href="{{ post.url }}">{{ post.title }}</a>
|
||||||
</h3>
|
</h3>
|
||||||
|
@ -7,14 +7,17 @@
|
|||||||
|
|
||||||
{% macro comment(item) -%}
|
{% macro comment(item) -%}
|
||||||
|
|
||||||
<div class="comment">
|
<div id="{{ item.id }}" class="comment">
|
||||||
<div class="comment_left">
|
<div class="comment_left">
|
||||||
<h3 class="comment_score">{{ item.score }}</h3>
|
<h3 class="comment_score">{{ item.score }}</h3>
|
||||||
<div class="line"></div>
|
<div class="line"></div>
|
||||||
</div>
|
</div>
|
||||||
<details class="comment_right" open>
|
<details class="comment_right" open>
|
||||||
<summary class="comment_data">
|
<summary class="comment_data"><a class="comment_author {% if item.author == post.author %}op{% endif %}" href="/u/{{ item.author }}">u/{{ item.author }}</a>
|
||||||
<a class="comment_author" href="/u/{{ item.author }}">u/{{ item.author }}</a> • <span class="datetime">{{ item.time }}</span>
|
{% if item.flair.0 != "" %}
|
||||||
|
<small class="author_flair">{{ item.flair.0 }}</small>
|
||||||
|
{% endif %}
|
||||||
|
• <span class="datetime">{{ item.time }}</span>
|
||||||
</summary>
|
</summary>
|
||||||
<h4 class="comment_body">{{ item.body }}</h4>
|
<h4 class="comment_body">{{ item.body }}</h4>
|
||||||
|
|
||||||
@ -29,14 +32,16 @@
|
|||||||
<h4>
|
<h4>
|
||||||
<b><a class="post_subreddit" href="/r/{{ post.community }}">r/{{ post.community }}</a></b>
|
<b><a class="post_subreddit" href="/r/{{ post.community }}">r/{{ post.community }}</a></b>
|
||||||
•
|
•
|
||||||
Posted by
|
|
||||||
<a class="post_author" href="/u/{{ post.author }}">u/{{ post.author }}</a>
|
<a class="post_author" href="/u/{{ post.author }}">u/{{ post.author }}</a>
|
||||||
|
{% if post.author_flair.0 != "" %}
|
||||||
|
<small class="author_flair">{{ post.author_flair.0 }}</small>
|
||||||
|
{% endif %}
|
||||||
<span class="datetime">{{ post.time }}</span>
|
<span class="datetime">{{ post.time }}</span>
|
||||||
</h4>
|
</h4>
|
||||||
<a href="{{ post.url }}" class="post_title">
|
<a href="{{ post.url }}" class="post_title">
|
||||||
{{ post.title }}
|
{{ post.title }}
|
||||||
{% if post.flair.0 != "" %}
|
{% if post.flair.0 != "" %}
|
||||||
<small style="color:{{ post.flair.2 }}; background:{{ post.flair.1 }}">{{ post.flair.0 }}</small>
|
<small class="post_flair" style="color:{{ post.flair.2 }}; background:{{ post.flair.1 }}">{{ post.flair.0 }}</small>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</a>
|
</a>
|
||||||
{% if post.post_type == "image" %}
|
{% if post.post_type == "image" %}
|
||||||
@ -49,23 +54,34 @@
|
|||||||
<h4 class="post_body">{{ post.body }}</h4>
|
<h4 class="post_body">{{ post.body }}</h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="sort">
|
<form>
|
||||||
<div id="sort_confidence"><a href="?sort=confidence">Best</a></div>
|
<select id="sort" name="sort">
|
||||||
<div id="sort_top"><a href="?sort=top">Top</a></div>
|
<option value="confidence" {% if sort == "confidence" %}selected{% endif %}>Best</option>
|
||||||
<div id="sort_new"><a href="?sort=new">New</a></div>
|
<option value="top" {% if sort == "top" %}selected{% endif %}>Top</option>
|
||||||
<div id="sort_controversial"><a href="?sort=controversial">Controversial</a></div>
|
<option value="new" {% if sort == "new" %}selected{% endif %}>New</option>
|
||||||
<div id="sort_old"><a href="?sort=old">Old</a></div>
|
<option value="controversial" {% if sort == "controversial" %}selected{% endif %}>Controversial</option>
|
||||||
</div>
|
<option value="old" {% if sort == "old" %}selected{% endif %}>Old</option>
|
||||||
|
</select><input id="sort_submit" type="submit" value="→">
|
||||||
|
</form>
|
||||||
|
|
||||||
{% for c in comments -%}
|
{% for c in comments -%}
|
||||||
<div class="thread">
|
<div class="thread">
|
||||||
{% call comment(c) %}
|
{% call comment(c) %}
|
||||||
<div class="replies">
|
<div class="replies">
|
||||||
{% for reply in c.replies %}
|
{% for reply1 in c.replies %}
|
||||||
{% call comment(reply) %}
|
{% call comment(reply1) %}
|
||||||
<div class="replies">
|
<div class="replies">
|
||||||
{% for response in reply.replies %}
|
{% for reply2 in reply1.replies %}
|
||||||
{% call comment(response) %}</details></div>
|
{% call comment(reply2) %}
|
||||||
|
<div class="replies">
|
||||||
|
{% for reply3 in reply2.replies %}
|
||||||
|
{% call comment(reply3) %}
|
||||||
|
{% if reply3.replies.len() > 0 %}
|
||||||
|
<a class="deeper_replies" href="{{ post.url }}{{ reply3.id }}">→ More replies</a>
|
||||||
|
{% endif %}
|
||||||
|
</details></div>
|
||||||
|
{% endfor %}
|
||||||
|
</div></details></div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div></details></div>
|
</div></details></div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% if sub.name != "" %}
|
||||||
{% block title %}r/{{ sub.name }}: {{ sub.description }}{% endblock %}
|
{% block title %}r/{{ sub.name }}: {{ sub.description }}{% endblock %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
|
{% if sub.name != "" %}
|
||||||
<div id="about">
|
<div id="about">
|
||||||
<div class="subreddit">
|
<div class="subreddit">
|
||||||
<div class="subreddit_left">
|
<div class="subreddit_left">
|
||||||
@ -13,12 +18,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
<main>
|
<main>
|
||||||
<div id="sort">
|
<form>
|
||||||
<div id="sort_hot"><a href="?sort=hot">Hot</a></div>
|
<select id="sort" name="sort">
|
||||||
<div id="sort_top"><a href="?sort=top">Top</a></div>
|
<option value="hot" {% if sort == "hot" %}selected{% endif %}>Hot</option>
|
||||||
<div id="sort_new"><a href="?sort=new">New</a></div>
|
<option value="new" {% if sort == "new" %}selected{% endif %}>New</option>
|
||||||
</div>
|
<option value="top" {% if sort == "top" %}selected{% endif %}>Top</option>
|
||||||
|
</select><input id="sort_submit" type="submit" value="→">
|
||||||
|
</form>
|
||||||
{% for post in posts %}
|
{% for post in posts %}
|
||||||
<div class="post">
|
<div class="post">
|
||||||
<div class="post_left">
|
<div class="post_left">
|
||||||
@ -26,15 +34,16 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="post_right">
|
<div class="post_right">
|
||||||
<h4>
|
<h4>
|
||||||
<b><a class="post_subreddit" href="/r/{{ post.community }}">r/{{ sub.name }}</a></b>
|
<b><a class="post_subreddit" href="/r/{{ post.community }}">r/{{ post.community }}</a></b>
|
||||||
•
|
• <a class="post_author" href="/u/{{ post.author }}">u/{{ post.author }}</a>
|
||||||
Posted by
|
{% if post.author_flair.0 != "" %}
|
||||||
<a class="post_author" href="/u/{{ post.author }}">u/{{ post.author }}</a>
|
<small class="author_flair">{{ post.author_flair.0 }}</small>
|
||||||
|
{% endif %}
|
||||||
<span class="datetime">{{ post.time }}</span>
|
<span class="datetime">{{ post.time }}</span>
|
||||||
</h4>
|
</h4>
|
||||||
<h3 class="post_title">
|
<h3 class="post_title">
|
||||||
{% if post.flair.0 != "" %}
|
{% if post.flair.0 != "" %}
|
||||||
<small style="color:{{ post.flair.2 }}; background:{{ post.flair.1 }}">{{ post.flair.0 }}</small>
|
<small class="post_flair" style="color:{{ post.flair.2 }}; background:{{ post.flair.1 }}">{{ post.flair.0 }}</small>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="{{ post.url }}">{{ post.title }}</a>
|
<a href="{{ post.url }}">{{ post.title }}</a>
|
||||||
</h3>
|
</h3>
|
||||||
|
@ -13,11 +13,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<main>
|
<main>
|
||||||
<div id="sort">
|
<form>
|
||||||
<div id="sort_hot"><a href="?sort=hot">Hot</a></div>
|
<select id="sort" name="sort">
|
||||||
<div id="sort_top"><a href="?sort=top">Top</a></div>
|
<option value="hot" {% if sort == "hot" %}selected{% endif %}>Hot</option>
|
||||||
<div id="sort_new"><a href="?sort=new">New</a></div>
|
<option value="new" {% if sort == "new" %}selected{% endif %}>New</option>
|
||||||
</div>
|
<option value="top" {% if sort == "top" %}selected{% endif %}>Top</option>
|
||||||
|
</select><input id="sort_submit" type="submit" value="→">
|
||||||
|
</form>
|
||||||
{% for post in posts %}
|
{% for post in posts %}
|
||||||
{% if post.title != "Comment" %}
|
{% if post.title != "Comment" %}
|
||||||
<div class='post'>
|
<div class='post'>
|
||||||
@ -27,16 +29,17 @@
|
|||||||
<div class="post_right">
|
<div class="post_right">
|
||||||
<h4>
|
<h4>
|
||||||
<b><a class="post_subreddit" href="/r/{{ post.community }}">r/{{ post.community }}</a></b>
|
<b><a class="post_subreddit" href="/r/{{ post.community }}">r/{{ post.community }}</a></b>
|
||||||
•
|
• <a class="post_author" href="/u/{{ post.author }}">u/{{ post.author }}</a>
|
||||||
Posted by
|
{% if post.author_flair.0 != "" %}
|
||||||
<a class="post_author" href="/u/{{ post.author }}">u/{{ post.author }}</a>
|
<small class="author_flair">{{ post.author_flair.0 }}</small>
|
||||||
|
{% endif %}
|
||||||
<span class="datetime" style="float: right;">{{ post.time }}</span>
|
<span class="datetime" style="float: right;">{{ post.time }}</span>
|
||||||
</h4>
|
</h4>
|
||||||
<h3 class="post_title">
|
<h3 class="post_title">
|
||||||
{% if post.flair.0 == "Comment" %}
|
{% if post.flair.0 == "Comment" %}
|
||||||
{% else if post.flair.0 == "" %}
|
{% else if post.flair.0 == "" %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<small style="color:{{ post.flair.2 }}; background:{{ post.flair.1 }}">{{ post.flair.0 }}</small>
|
<small class="post_flair" style="color:{{ post.flair.2 }}; background:{{ post.flair.1 }}">{{ post.flair.0 }}</small>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="{{ post.url }}">{{ post.title }}</a>
|
<a href="{{ post.url }}">{{ post.title }}</a>
|
||||||
</h3>
|
</h3>
|
||||||
|
Reference in New Issue
Block a user