summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock65
-rw-r--r--Cargo.toml4
-rw-r--r--blog/fall-semester-status.md50
-rw-r--r--src/blog/mod.rs25
-rw-r--r--src/blog/post.rs18
-rw-r--r--src/main.rs18
-rw-r--r--src/misc/mod.rs10
-rw-r--r--statics/custom.css41
-rw-r--r--statics/gruvbox.css74
-rw-r--r--templates/bloglist.rs.html19
-rw-r--r--templates/footer.rs.html6
-rw-r--r--templates/header.rs.html11
-rw-r--r--templates/index.rs.html43
-rw-r--r--templates/post.rs.html10
14 files changed, 379 insertions, 15 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f71d922..e0965c3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -376,6 +376,21 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -392,6 +407,36 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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",
]
@@ -1030,6 +1081,18 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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<SiteState>) -> Result<impl Reply, Rejection> {
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<impl Reply, Rejection> {
- Ok("Post test")
+ pub async fn post(name: String, state: Arc<SiteState>) -> Result<impl Reply, Rejection> {
+ let mut want: Option<Post> = 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<FixedOffset>,
+ pub link: String,
}
impl Ord for Post {
@@ -46,6 +47,7 @@ async fn read_post(dir: &str, fname: PathBuf) -> Result<Post> {
Ok(Post {
front_matter,
body_html,
+ link,
date
} )
}
@@ -55,7 +57,19 @@ pub async fn load(dir: &str) -> Result<Vec<Post>> {
.filter_map(Result::ok)
.map(|fname| read_post(dir, fname));
- Ok(Vec::new())
+ let mut result: Vec<Post> = 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<SiteState>) -> impl Filter<Extract = (Arc<SiteState>,), 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<impl Reply, Rejection> {
+ 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<Post>)
+
+@:header_html(Some("Posts"), None)
+
+<h1>Posts</h1>
+
+<p>
+<ul>
+ @for post in posts {
+ <li>@post.date.format("%B %d %Y") -
+ <a href="/@post.link">@post.front_matter.title</a></li>
+ }
+</ul>
+</p>
+
+@: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 @@
@()
-</div>
-<hr />
-<footer>
+
+<footer class="footer">
<blockquote>Content copyright Cara Salter 2021, based on <a
href="https://github.com/Xe/site">Xe/site</a>
under the Zlib license</blockquote>
<p>This server runs version @env!("GIT_SHA"), located on my <a
href='https://git.carathe.dev/~muirrum/site/commit/@env!("GIT_SHA")'>sourcehut</a>
</footer>
+</div>
</body>
</html>
diff --git a/templates/header.rs.html b/templates/header.rs.html
index afcf445..c93566c 100644
--- a/templates/header.rs.html
+++ b/templates/header.rs.html
@@ -1,4 +1,4 @@
-@use chrono::{DateLike, Utc};
+@use chrono::{Datelike, Utc};
@(title: Option<&str>, styles: Option<&str>)
@@ -10,7 +10,16 @@
} else {
<title>cara salter</title>
}
+ <link rel="stylesheet" href="/static/gruvbox.css">
+ <link rel="stylesheet" href="/static/custom.css">
+ <meta name="viewport" content="width=device-width,
+ initial-scale=1.0">
</head>
<body>
<div class="container">
+ <ul class="navbar">
+ <li class="navbar-item"><a href="/">Home</a></li>
+ <li class="navbar-item"><a
+ href="/blog">Posts</a></li>
+ </ul>
diff --git a/templates/index.rs.html b/templates/index.rs.html
index 6e35935..d4158a1 100644
--- a/templates/index.rs.html
+++ b/templates/index.rs.html
@@ -1,9 +1,48 @@
-@use super::{header_html}
+@use super::{header_html, footer_html};
@()
@:header_html(None, None)
<link rel="canonical" href="https://devcara.com">
-Test
+
+<div class="two-column">
+
+ <div class="inner-column">
+ <h3>About me</h3>
+ I am a:
+ <ul>
+ <li>Trans woman (she/her/hers)</li>
+ <li>Eagle Scout</li>
+ <li>Software Engineer</li>
+ </ul>
+
+ My interests include:
+ <ul>
+ <li>Radio</li>
+ <li>Event production</li>
+ <li>Software tinkering</li>
+ <li>Linux</li>
+ </ul>
+ Among other things.
+
+ </div>
+ <div class="inner-column">
+ <h3>Skills</h3>
+ <h4>Web Development</h4>
+ <ul>
+ <li>Rust (Warp)</li>
+ <li>Go (Gin-gonic)</li>
+ <li>Python (Django/Flask)</li>
+ </ul>
+ <h4>Systems Administration</h4>
+ <ul>
+ <li>Prometheus Monitoring/Alerts</li>
+ <li>Ansible</li>
+ <li>Shell scripting</li>
+ <li>Nginx</li>
+ </ul>
+ </div>
</div>
+
+@:footer_html()
diff --git a/templates/post.rs.html b/templates/post.rs.html
new file mode 100644
index 0000000..c638bfb
--- /dev/null
+++ b/templates/post.rs.html
@@ -0,0 +1,10 @@
+@use super::{header_html, footer_html};
+@use crate::blog::post::Post;
+
+@(post: Post, body: impl ToHtml)
+
+@:header_html(Some(&post.front_matter.title.clone()), None))
+
+@body
+
+@:footer_html()