From 3d7cd8a7addd86b7a97a50821eb348345e0d427a Mon Sep 17 00:00:00 2001
From: Cara Salter
Date: Wed, 22 Dec 2021 01:06:39 -0500
Subject: Work for the day
Post parsing, index page, navbar, CSS, blog listings
There's something weird with the path matching that's making it miss the
post view page in favor of the list view page.
---
Cargo.lock | 65 ++++++++++++++++++++++++++++++++++++++
Cargo.toml | 4 +++
blog/fall-semester-status.md | 50 ++++++++++++++++++++++++++++++
src/blog/mod.rs | 25 +++++++++++++--
src/blog/post.rs | 18 +++++++++--
src/main.rs | 18 ++++++++---
src/misc/mod.rs | 10 ++++++
statics/custom.css | 41 ++++++++++++++++++++++++
statics/gruvbox.css | 74 ++++++++++++++++++++++++++++++++++++++++++++
templates/bloglist.rs.html | 19 ++++++++++++
templates/footer.rs.html | 6 ++--
templates/header.rs.html | 11 ++++++-
templates/index.rs.html | 43 +++++++++++++++++++++++--
templates/post.rs.html | 10 ++++++
14 files changed, 379 insertions(+), 15 deletions(-)
create mode 100644 blog/fall-semester-status.md
create mode 100644 src/misc/mod.rs
create mode 100644 statics/custom.css
create mode 100644 statics/gruvbox.css
create mode 100644 templates/bloglist.rs.html
create mode 100644 templates/post.rs.html
diff --git a/Cargo.lock b/Cargo.lock
index f71d922..e0965c3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -375,6 +375,21 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
+[[package]]
+name = "futures"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
[[package]]
name = "futures-channel"
version = "0.3.17"
@@ -391,6 +406,36 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d"
+[[package]]
+name = "futures-executor"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-io"
+version = "0.3.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb"
+dependencies = [
+ "autocfg",
+ "proc-macro-hack",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "futures-sink"
version = "0.3.17"
@@ -410,11 +455,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481"
dependencies = [
"autocfg",
+ "futures-channel",
"futures-core",
+ "futures-io",
+ "futures-macro",
"futures-sink",
"futures-task",
+ "memchr",
"pin-project-lite",
"pin-utils",
+ "proc-macro-hack",
+ "proc-macro-nested",
"slab",
]
@@ -1029,6 +1080,18 @@ version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba"
+[[package]]
+name = "proc-macro-hack"
+version = "0.5.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
+
+[[package]]
+name = "proc-macro-nested"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
+
[[package]]
name = "proc-macro2"
version = "1.0.34"
@@ -1308,8 +1371,10 @@ dependencies = [
"chrono",
"color-eyre",
"comrak",
+ "futures",
"glob",
"kankyo",
+ "mime",
"ructe",
"serde",
"serde_yaml",
diff --git a/Cargo.toml b/Cargo.toml
index ae5ffa0..5c15097 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,6 +17,10 @@ thiserror = "1"
serde_yaml = "0.8"
glob = "0.3"
+mime = "0.3"
+
+futures = "0.3"
+
[build-dependencies]
ructe = { version = "0.13", features = ["warp03"] }
diff --git a/blog/fall-semester-status.md b/blog/fall-semester-status.md
new file mode 100644
index 0000000..c3bf41e
--- /dev/null
+++ b/blog/fall-semester-status.md
@@ -0,0 +1,50 @@
+---
+title: Status Update - Fall Semester
+date: 2021-12-17
+series:
+ - status
+---
+
+## Preface
+Hello all! Welcome back to another status update! I realized recently that I
+haven't been all that good about making monthly status updates, so I think for
+at least the rest of this academic year I'll be making termly status updates,
+so one every 7 weeks. Hopefully this will lead to longer status updates with
+more content.
+
+Now, on to the Fall Semester status update!
+
+## Status update
+As I write this, it's a day after my last final exams, and I'm sitting in the
+campus library on my service desk shift. Much of my open source contributions
+this semester have been to the [LNLDB](https://github.com/WPI-LNL/lnldb), which
+handles events, membership, and a whole bunch of other stuff for WPI Lens and
+Lights. That's a Django codebase, and I've contributed a few features:
+
+- Pronoun Support
+ - Allowed members to provide their personal pronouns on their profile pages
+- Email resources for new Crew Chiefs
+ - When a member is assigned as a Crew Chief for the first time, send some
+ extra resources in the email
+
+I also have some pull requests pending review:
+
+- Position postings
+ - Lets executive board members post leadership roles to the active members
+- Cropping Officer photos
+ - Officer photos are currently inconsistently cropped, this lets them resize
+ as needed
+
+With the transition to college, among other things, I haven't had the time to
+do much else. I started to work on adding a tag for GPG-signed commits to
+git.sr.ht, but that hasn't gone anywhere.
+
+Speaking of git.sr.ht...
+
+## New code location
+I've deployed a production [sourcehut](https://sourcehut.org) instance to a new
+server, available at https://git.carathe.dev. I'm waiting on WPI ITS to unblock
+that domain, but it shouldn't be too long. I've already thrown things up there,
+and that's where I'll put personal projects.
+
+That's all for this semester! Happy holidays, and see you in the new year :)
diff --git a/src/blog/mod.rs b/src/blog/mod.rs
index 3640bcd..c227f22 100644
--- a/src/blog/mod.rs
+++ b/src/blog/mod.rs
@@ -2,6 +2,7 @@ pub mod post;
pub mod handlers {
use std::sync::Arc;
+use color_eyre::eyre::eyre;
use warp::{Reply, Rejection};
use warp::http::Response;
@@ -9,13 +10,31 @@ use crate::templates::{self, Html, RenderRucte};
use crate::internal::SiteState;
+use super::post::Post;
+
pub async fn list(state: Arc) -> Result {
let state = state.clone();
Response::builder()
- .html(|o| templates::index_html(o))
+ .html(|o| templates::bloglist_html(o, state.blog.clone()))
}
- pub async fn post(name: String) -> Result {
- Ok("Post test")
+ pub async fn post(name: String, state: Arc) -> Result {
+ let mut want: Option = None;
+
+ for post in &state.blog {
+ if post.link == format!("blog/{}", name) {
+ want = Some(post.clone());
+ break;
+ }
+ }
+
+ match want {
+ Some(post) => {
+ let body = Html(post.body_html.clone());
+ Response::builder()
+ .html(|o| templates::post_html(o, post, body))
+ },
+ None => panic!("No post found"),
+ }
}
}
diff --git a/src/blog/post.rs b/src/blog/post.rs
index abe57aa..3c27690 100644
--- a/src/blog/post.rs
+++ b/src/blog/post.rs
@@ -1,7 +1,7 @@
use std::{cmp::Ordering, path::PathBuf};
use glob::glob;
use color_eyre::eyre::{Result, Context, eyre};
-use tokio::fs;
+use tokio::{fs};
use chrono::prelude::*;
@@ -11,6 +11,7 @@ pub struct Post {
pub front_matter: frontmatter::Data,
pub body_html: String,
pub date: DateTime,
+ pub link: String,
}
impl Ord for Post {
@@ -46,6 +47,7 @@ async fn read_post(dir: &str, fname: PathBuf) -> Result {
Ok(Post {
front_matter,
body_html,
+ link,
date
} )
}
@@ -55,7 +57,19 @@ pub async fn load(dir: &str) -> Result> {
.filter_map(Result::ok)
.map(|fname| read_post(dir, fname));
- Ok(Vec::new())
+ let mut result: Vec = futures::future::join_all(futs)
+ .await
+ .into_iter()
+ .map(Result::unwrap)
+ .collect();
+
+ if result.len() == 0 {
+ Err(eyre!("No posts found"))
+ } else {
+ result.sort();
+ result.reverse();
+ Ok(result)
+ }
}
mod frontmatter {
diff --git a/src/main.rs b/src/main.rs
index 04ab18e..e247211 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,11 +3,12 @@ extern crate tracing;
use color_eyre::eyre::Result;
use std::{net::IpAddr, sync::Arc};
-use warp::Filter;
+use warp::{Filter, path};
use std::str::FromStr;
pub mod blog;
+pub mod misc;
mod internal;
use internal::SiteState;
@@ -24,15 +25,22 @@ async fn main() -> Result<()> {
let state = Arc::new(internal::init().await?);
+ let index = warp::get().and(path::end().and_then(misc::handlers::index));
+
let blog_base = warp::path!("blog" / ..);
let blog_list = blog_base.and(give_site_state(state.clone())).and_then(blog::handlers::list);
let blog_post = blog_base.and(
warp::path!(String)
- .and(warp::get()).and_then(blog::handlers::post));
+ .and(give_site_state(state.clone()))
+ .and_then(blog::handlers::post),
+ );
- let blog = blog_list.or(blog_post);
+ let static_files = warp::path("static")
+ .and(warp::fs::dir("./statics"));
+ let site = index
+ .or(blog_list.or(blog_post))
+ .or(static_files).with(warp::log("site"));
- let site = blog.with(warp::log("site"));
let server = warp::serve(site);
@@ -51,3 +59,5 @@ async fn main() -> Result<()> {
fn give_site_state(sitestate: Arc) -> impl Filter,), Error=std::convert::Infallible> + Clone {
warp::any().map(move || sitestate.clone())
}
+
+include!(concat!(env!("OUT_DIR"), "/templates.rs"));
diff --git a/src/misc/mod.rs b/src/misc/mod.rs
new file mode 100644
index 0000000..5942b8c
--- /dev/null
+++ b/src/misc/mod.rs
@@ -0,0 +1,10 @@
+pub mod handlers {
+ use color_eyre::Result;
+ use warp::{Reply, Rejection, http::Response};
+ use crate::templates::{self, Html, RenderRucte};
+
+ pub async fn index() -> Result {
+ Response::builder()
+ .html(|o| templates::index_html(o))
+ }
+}
diff --git a/statics/custom.css b/statics/custom.css
new file mode 100644
index 0000000..827bd23
--- /dev/null
+++ b/statics/custom.css
@@ -0,0 +1,41 @@
+/* Element styles */
+body {
+ font-family: sans-serif;
+}
+
+/* Base container */
+.container {
+ margin: auto; /* centered */
+ width: 80%; /* looks nice */
+}
+
+/* Navbar */
+.navbar {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+ border-bottom: 1px solid;
+ margin-bottom: 2rem;
+ text-align: center;
+ padding-bottom: 0.4rem;
+}
+
+.navbar-item {
+ display: inline;
+ margin-right: 1rem;
+}
+
+.footer {
+ border-top: 1px solid;
+ margin-top: 2rem;
+ padding-top: 0.4rem;
+}
+
+.two-column {
+ display: flex;
+ justify-content: center;
+}
+
+.inner-column {
+ flex: 50%;
+}
diff --git a/statics/gruvbox.css b/statics/gruvbox.css
new file mode 100644
index 0000000..618eb3b
--- /dev/null
+++ b/statics/gruvbox.css
@@ -0,0 +1,74 @@
+main {
+ font-family: monospace, monospace;
+ max-width: 38rem;
+ padding: 2rem;
+ margin: auto;
+}
+
+@media only screen and (max-device-width: 736px) {
+ main {
+ padding: 0rem;
+ }
+}
+
+::selection {
+ background: #d3869b;
+}
+
+body {
+ background: #282828;
+ color: #ebdbb2;
+}
+
+pre {
+ background-color: #3c3836;
+ padding: 1em;
+ border: 0;
+}
+
+a, a:active, a:visited {
+ color: #b16286;
+ background-color: #1d2021;
+}
+
+h1, h2, h3, h4, h5 {
+ margin-bottom: .1rem;
+}
+
+blockquote {
+ border-left: 1px solid #bdae93;
+ margin: 0.5em 10px;
+ padding: 0.5em 10px;
+}
+
+footer {
+ align: center;
+}
+
+@media (prefers-color-scheme: light) {
+ body {
+ background: #fbf1c7;
+ color: #3c3836;
+ }
+
+ pre {
+ background-color: #ebdbb2;
+ padding: 1em;
+ border: 0;
+ }
+
+ a, a:active, a:visited {
+ color: #b16286;
+ background-color: #f9f5d7;
+ }
+
+ h1, h2, h3, h4, h5 {
+ margin-bottom: .1rem;
+ }
+
+ blockquote {
+ border-left: 1px solid #655c54;
+ margin: 0.5em 10px;
+ padding: 0.5em 10px;
+ }
+}
diff --git a/templates/bloglist.rs.html b/templates/bloglist.rs.html
new file mode 100644
index 0000000..98cd171
--- /dev/null
+++ b/templates/bloglist.rs.html
@@ -0,0 +1,19 @@
+@use crate::blog::post::Post;
+@use super::{header_html, footer_html};
+
+@(posts: Vec)
+
+@:header_html(Some("Posts"), None)
+
+Posts
+
+
+
+
+
+@:footer_html()
diff --git a/templates/footer.rs.html b/templates/footer.rs.html
index 5029544..1574a50 100644
--- a/templates/footer.rs.html
+++ b/templates/footer.rs.html
@@ -1,12 +1,12 @@
@()
-
-
-