basic generic post loading
This commit is contained in:
parent
02031f9062
commit
92c9daeb82
|
@ -187,6 +187,17 @@ version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chrono"
|
||||||
|
version = "0.4.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c74d84029116787153e02106bf53e66828452a4b325cc8652b788b5967c0a0b6"
|
||||||
|
dependencies = [
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
"time",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "2.33.1"
|
version = "2.33.1"
|
||||||
|
@ -524,6 +535,12 @@ dependencies = [
|
||||||
"wasi",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glob"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "h2"
|
||||||
version = "0.2.5"
|
version = "0.2.5"
|
||||||
|
@ -759,6 +776,12 @@ version = "0.2.72"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a9f8082297d534141b30c8d39e9b1773713ab50fdbe4ff30f750d063b3bfd701"
|
checksum = "a9f8082297d534141b30c8d39e9b1773713ab50fdbe4ff30f750d063b3bfd701"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linked-hash-map"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
@ -938,6 +961,25 @@ dependencies = [
|
||||||
"version_check 0.9.2",
|
"version_check 0.9.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.43"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 1.0.0",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 1.0.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_cpus"
|
name = "num_cpus"
|
||||||
version = "1.13.0"
|
version = "1.13.0"
|
||||||
|
@ -1604,6 +1646,18 @@ dependencies = [
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_yaml"
|
||||||
|
version = "0.8.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae3e2dd40a7cdc18ca80db804b7f461a39bb721160a85c9a1fa30134bf3c02a5"
|
||||||
|
dependencies = [
|
||||||
|
"dtoa",
|
||||||
|
"linked-hash-map",
|
||||||
|
"serde",
|
||||||
|
"yaml-rust",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha-1"
|
name = "sha-1"
|
||||||
version = "0.8.2"
|
version = "0.8.2"
|
||||||
|
@ -1713,6 +1767,26 @@ dependencies = [
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "thread_local"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -2184,8 +2258,10 @@ name = "xesite"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"chrono",
|
||||||
"comrak",
|
"comrak",
|
||||||
"envy",
|
"envy",
|
||||||
|
"glob",
|
||||||
"log 0.4.8",
|
"log 0.4.8",
|
||||||
"mime 0.3.16",
|
"mime 0.3.16",
|
||||||
"pretty_env_logger",
|
"pretty_env_logger",
|
||||||
|
@ -2193,6 +2269,17 @@ dependencies = [
|
||||||
"ructe",
|
"ructe",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_dhall",
|
"serde_dhall",
|
||||||
|
"serde_yaml",
|
||||||
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"warp",
|
"warp",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yaml-rust"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d"
|
||||||
|
dependencies = [
|
||||||
|
"linked-hash-map",
|
||||||
|
]
|
||||||
|
|
|
@ -9,17 +9,21 @@ build = "src/build.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
|
chrono = "0.4"
|
||||||
comrak = "0.8"
|
comrak = "0.8"
|
||||||
envy = "0.4"
|
envy = "0.4"
|
||||||
|
glob = "0.3"
|
||||||
log = "0"
|
log = "0"
|
||||||
mime = "0.3.0"
|
mime = "0.3.0"
|
||||||
pretty_env_logger = "0"
|
pretty_env_logger = "0"
|
||||||
rand = "0"
|
rand = "0"
|
||||||
ructe = "0.11"
|
ructe = "0.11"
|
||||||
serde_dhall = "0.5.3"
|
serde_dhall = "0.5.3"
|
||||||
|
serde_yaml = "0.8"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
tokio = { version = "0.2", features = ["macros"] }
|
tokio = { version = "0.2", features = ["macros"] }
|
||||||
warp = "0.2"
|
warp = "0.2"
|
||||||
|
thiserror = "1"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
ructe = { version = "0.11", features = ["warp02"] }
|
ructe = { version = "0.11", features = ["warp02"] }
|
||||||
|
|
|
@ -4,6 +4,7 @@ use warp::{path, Filter};
|
||||||
|
|
||||||
pub mod app;
|
pub mod app;
|
||||||
pub mod handlers;
|
pub mod handlers;
|
||||||
|
pub mod post;
|
||||||
pub mod signalboost;
|
pub mod signalboost;
|
||||||
|
|
||||||
use app::State;
|
use app::State;
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
/// This code was borrowed from @fasterthanlime.
|
||||||
|
|
||||||
|
use anyhow::{Result};
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Deserialize, Default, Debug, Serialize, Clone)]
|
||||||
|
pub struct Data {
|
||||||
|
pub title: String,
|
||||||
|
pub date: String,
|
||||||
|
pub series: Option<String>,
|
||||||
|
pub tags: Option<Vec<String>>,
|
||||||
|
pub slides_link: Option<String>,
|
||||||
|
pub image: Option<String>,
|
||||||
|
pub thumb: Option<String>,
|
||||||
|
pub show: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum State {
|
||||||
|
SearchForStart,
|
||||||
|
ReadingMarker { count: usize, end: bool },
|
||||||
|
ReadingFrontMatter { buf: String, line_start: bool },
|
||||||
|
SkipNewline { end: bool },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
enum Error {
|
||||||
|
#[error("EOF while parsing frontmatter")]
|
||||||
|
EOF,
|
||||||
|
#[error("Error parsing yaml: {0:?}")]
|
||||||
|
Yaml(#[from] serde_yaml::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Data {
|
||||||
|
pub fn parse(input: &str) -> Result<(Data, usize)> {
|
||||||
|
let mut state = State::SearchForStart;
|
||||||
|
|
||||||
|
let mut payload = None;
|
||||||
|
let offset;
|
||||||
|
|
||||||
|
let mut chars = input.char_indices();
|
||||||
|
'parse: loop {
|
||||||
|
let (idx, ch) = match chars.next() {
|
||||||
|
Some(x) => x,
|
||||||
|
None => return Err(Error::EOF)?,
|
||||||
|
};
|
||||||
|
match &mut state {
|
||||||
|
State::SearchForStart => match ch {
|
||||||
|
'-' => {
|
||||||
|
state = State::ReadingMarker {
|
||||||
|
count: 1,
|
||||||
|
end: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
'\n' | '\t' | ' ' => {
|
||||||
|
// ignore whitespace
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
panic!("Start of frontmatter not found");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State::ReadingMarker { count, end } => match ch {
|
||||||
|
'-' => {
|
||||||
|
*count += 1;
|
||||||
|
if *count == 3 {
|
||||||
|
state = State::SkipNewline { end: *end };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
panic!("Malformed frontmatter marker");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State::SkipNewline { end } => match ch {
|
||||||
|
'\n' => {
|
||||||
|
if *end {
|
||||||
|
offset = idx + 1;
|
||||||
|
break 'parse;
|
||||||
|
} else {
|
||||||
|
state = State::ReadingFrontMatter {
|
||||||
|
buf: String::new(),
|
||||||
|
line_start: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => panic!("Expected newline, got {:?}",),
|
||||||
|
},
|
||||||
|
State::ReadingFrontMatter { buf, line_start } => match ch {
|
||||||
|
'-' if *line_start => {
|
||||||
|
let mut state_temp = State::ReadingMarker {
|
||||||
|
count: 1,
|
||||||
|
end: true,
|
||||||
|
};
|
||||||
|
std::mem::swap(&mut state, &mut state_temp);
|
||||||
|
if let State::ReadingFrontMatter { buf, .. } = state_temp {
|
||||||
|
payload = Some(buf);
|
||||||
|
} else {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ch => {
|
||||||
|
buf.push(ch);
|
||||||
|
*line_start = ch == '\n';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unwrap justification: option set in state machine, Rust can't statically analyze it
|
||||||
|
let payload = payload.unwrap();
|
||||||
|
|
||||||
|
let fm: Self = serde_yaml::from_str(&payload)?;
|
||||||
|
|
||||||
|
Ok((fm, offset))
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
use anyhow::{anyhow, Result};
|
||||||
|
use chrono::prelude::*;
|
||||||
|
use glob::glob;
|
||||||
|
use std::{cmp::Ordering, fs};
|
||||||
|
|
||||||
|
pub mod frontmatter;
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Debug)]
|
||||||
|
pub struct Post {
|
||||||
|
pub front_matter: frontmatter::Data,
|
||||||
|
pub link: String,
|
||||||
|
pub body: String,
|
||||||
|
pub body_html: String,
|
||||||
|
pub date: NaiveDate,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for Post {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
self.partial_cmp(&other).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Post {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(self.date.cmp(&other.date))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load(dir: &str) -> Result<Vec<Post>> {
|
||||||
|
let mut result: Vec<Post> = vec![];
|
||||||
|
|
||||||
|
for path in glob(&format!("{}/*.markdown", dir))?.filter_map(Result::ok) {
|
||||||
|
let body = fs::read_to_string(path.clone())?;
|
||||||
|
let (fm, content_offset) = frontmatter::Data::parse(body.clone().as_str())?;
|
||||||
|
let markup = &body[content_offset..];
|
||||||
|
let date = NaiveDate::parse_from_str(&fm.clone().date, "%Y-%m-%d")?;
|
||||||
|
|
||||||
|
result.push(Post {
|
||||||
|
front_matter: fm,
|
||||||
|
link: format!("{}/{}", dir, path.file_stem().unwrap().to_str().unwrap()),
|
||||||
|
body: markup.to_string(),
|
||||||
|
body_html: crate::app::markdown(&markup),
|
||||||
|
date: date,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if result.len() == 0 {
|
||||||
|
Err(anyhow!("no posts loaded"))
|
||||||
|
} else {
|
||||||
|
result.sort();
|
||||||
|
result.reverse();
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn blog() -> Result<()> {
|
||||||
|
load("./blog")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue