summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCara Salter <cara@devcara.com>2021-12-22 01:06:39 -0500
committerCara Salter <cara@devcara.com>2021-12-22 01:06:39 -0500
commit3d7cd8a7addd86b7a97a50821eb348345e0d427a (patch)
tree875aecda597c8161359005c33a147097fa36c807
parentc4d7f8f50d53057005d6bb28ac487f69ea45bd5e (diff)
downloadsite-3d7cd8a7addd86b7a97a50821eb348345e0d427a.tar.gz
site-3d7cd8a7addd86b7a97a50821eb348345e0d427a.zip
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.
-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()