diff options
| author | Adam T. Carpenter <atc@53hor.net> | 2024-09-07 21:18:54 -0400 | 
|---|---|---|
| committer | Adam T. Carpenter <atc@53hor.net> | 2024-09-07 21:18:54 -0400 | 
| commit | ae00627e7c99fd21ce4ad8ec0692445f00a349b2 (patch) | |
| tree | 9af9c980db9075fbc0e520443201d684a0a03832 /src | |
| parent | 4ae354f108acaef8c78b778124d4638904bd7c69 (diff) | |
| download | carpentertutoring-ae00627e7c99fd21ce4ad8ec0692445f00a349b2.tar.xz carpentertutoring-ae00627e7c99fd21ce4ad8ec0692445f00a349b2.zip  | |
feat: basic markdown post to html page loading
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 136 | 
1 files changed, 136 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..43b6fa6 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,136 @@ +use axum::response::Html; +use axum::extract::State; +use std::sync::Arc; +use askama_axum::Template; +use axum::{routing::get, Router}; +use std::borrow::Cow; +use std::ffi::OsString; +use std::fmt; +use std::fs; +use std::io::*; +use std::path::Path; +use std::path::PathBuf; + +trait Post<'a>: fmt::Debug { +    fn dump(&self); +    fn display_name(&'a self) -> &'a str; +    fn get_content(&self) -> Cow<str>; +} + +#[derive(Debug)] +struct MockPost; + +impl<'a> Post<'a> for MockPost { +    fn dump(&self) { +        println!("Post content goes here."); +    } + +    fn display_name(&'a self) -> &'a str { +        "" +    } + +    fn get_content(&self) -> Cow<str> { +        Cow::Borrowed("") +    } +} + +struct MdFilePost { +    path: PathBuf, +    name: OsString, +} + +impl MdFilePost { +    fn new(path: &Path) -> Self { +        Self { +            path: path.to_path_buf(), +            name: path.file_stem().unwrap_or_default().to_owned(), +        } +    } +} + +impl<'a> Post<'a> for MdFilePost { +    fn dump(&self) { +        println!("{}: {}", &self.display_name(), &self.get_content()); +    } + +    fn display_name(&'a self) -> &'a str { +        self.name.to_str().unwrap() +    } + +    fn get_content(&self) -> Cow<str> { +        let mut file = std::fs::File::open(&self.path).unwrap(); +        let mut markdown = String::new(); +        file.read_to_string(&mut markdown).unwrap(); +        Cow::Owned(markdown) +    } +} + +impl fmt::Debug for MdFilePost { +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +        write!(f, "MdFilePost '{}'", self.display_name()) +    } +} + +trait Posts { +    fn get_posts(&self) -> impl Iterator<Item = impl Post>; +} + +struct FsDirPosts { +    path: PathBuf, +} + +impl FsDirPosts { +    fn new(path: &str) -> Self { +        Self { +            path: PathBuf::from(path), +        } +    } +} + +impl Posts for FsDirPosts { +    fn get_posts(&self) -> impl Iterator<Item = impl Post> { +        let dirs = fs::read_dir(&self.path).unwrap(); +        dirs.flatten().map(|d| MdFilePost::new(&d.path())) +    } +} + +trait Page<'a>: Template { +    fn from_post(post: &impl Post<'a>) -> Self; +} + +#[derive(Template)] +#[template(path = "post.html")] +struct MdPage { +    article: String, +} + +impl<'a> Page<'a> for MdPage { +    fn from_post(post: &impl Post<'a>) -> Self { +        Self { +            article: post.get_content().into_owned(), +        } +    } +} + +fn test_get_posts(posts: &impl Posts) { +    for post in posts.get_posts() { +        let page = MdPage::from_post(&post); +        println!("{}", page.render().unwrap()); +    } +} + +async fn handler(State(posts): State<Arc<impl Posts>>) -> Html<String> { +    let post = posts.get_posts().next().unwrap(); +    let page = MdPage::from_post(&post); +    Html(page.render().unwrap()) +} + +#[tokio::main] +async fn main() { +    let repo = Arc::new(FsDirPosts::new(&format!("/data/ct/{}", "blog"))); + +    let app = Router::new().route("/posts", get(handler)).with_state(repo); + +    let listener = tokio::net::TcpListener::bind("0.0.0.0:8000").await.unwrap(); +    axum::serve(listener, app).await.unwrap(); +}  |