1
0
Fork 0
This commit is contained in:
Adrian Hedqvist 2022-09-05 00:02:58 +02:00
parent b98031de94
commit e0237555cd
9 changed files with 90 additions and 51 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 KiB

View file

@ -0,0 +1,7 @@
# Testing post as index within folder
hope it works yay
here have a squid miku to test relative paths:
![Squid kid miku](FbHSmoeUUAA2x-m.png)

View file

@ -5,12 +5,15 @@ use tracing::log::*;
use axum::{ use axum::{
extract::Path, extract::Path,
response::{Html, IntoResponse, Response}, response::{Html, IntoResponse, Response},
http::{StatusCode, Uri},
Extension, Extension,
}; };
use pulldown_cmark::{html, Options, Parser}; use pulldown_cmark::{html, Options, Parser};
use crate::State; use crate::State;
pub mod posts;
pub enum Error { pub enum Error {
NotFound, NotFound,
} }
@ -31,45 +34,6 @@ pub async fn index(Extension(state): Extension<Arc<State>>) -> Result {
Ok(Html(res.into())) Ok(Html(res.into()))
} }
pub async fn post_view(
Path(name): Path<String>,
Extension(state): Extension<Arc<State>>,
) -> Result {
info!("Requested post: {}", name);
let state = state.clone();
let post = state
.posts
.iter()
.find(|p| p.name == name)
.ok_or(Error::NotFound)?;
let options = Options::all();
let parser = Parser::new_ext(&post.content, options);
let mut out = String::new();
html::push_html(&mut out, parser);
let ctx =
tera::Context::from_serialize(PageContext { content: out }).map_err(|_| Error::NotFound)?;
let res = state.tera.render("post.html", &ctx).map_err(|e| {
error!("Failed rendering post: {}", e);
Error::NotFound
})?;
Ok(Html(res.into()))
}
pub async fn post_index(Extension(state): Extension<Arc<State>>) -> Result {
let mut ctx = tera::Context::new();
ctx.insert("posts", &state.posts);
let res = state.tera.render("postsindex.html", &ctx).map_err(|e| {
error!("Failed rendering posts index: {}", e);
Error::NotFound
})?;
Ok(Html(res.into()))
}
impl IntoResponse for Error { impl IntoResponse for Error {
fn into_response(self) -> Response { fn into_response(self) -> Response {
let result: Vec<u8> = "not found".into(); let result: Vec<u8> = "not found".into();

47
src/handlers/posts.rs Normal file
View file

@ -0,0 +1,47 @@
use std::sync::Arc;
use axum::{extract::Path, Extension, response::Html};
use pulldown_cmark::{Options, Parser, html};
use tracing::log::*;
use crate::{State, handlers::PageContext};
use super::{Result, Error};
pub async fn view(
Path(slug): Path<String>,
Extension(state): Extension<Arc<State>>,
) -> Result {
let post = state
.posts
.iter()
.find(|p| p.slug == slug)
.ok_or(Error::NotFound)?;
info!("Requested post: {}", slug);
let options = Options::all();
let parser = Parser::new_ext(&post.content, options);
let mut out = String::new();
html::push_html(&mut out, parser);
let ctx =
tera::Context::from_serialize(PageContext { content: out }).map_err(|_| Error::NotFound)?;
let res = state.tera.render("post.html", &ctx).map_err(|e| {
error!("Failed rendering post: {}", e);
Error::NotFound
})?;
Ok(Html(res.into()))
}
pub async fn index(Extension(state): Extension<Arc<State>>) -> Result {
let mut ctx = tera::Context::new();
ctx.insert("posts", &state.posts);
let res = state.tera.render("postsindex.html", &ctx).map_err(|e| {
error!("Failed rendering posts index: {}", e);
Error::NotFound
})?;
Ok(Html(res.into()))
}

View file

@ -1,6 +1,6 @@
use std::{path::PathBuf, sync::Arc}; use std::{path::PathBuf, sync::Arc};
use axum::{routing::get, Extension, Router}; use axum::{routing::{get, get_service}, Extension, Router, handler::Handler, http::StatusCode};
use color_eyre::eyre::Result; use color_eyre::eyre::Result;
use glob::glob; use glob::glob;
use serde_derive::Serialize; use serde_derive::Serialize;
@ -17,7 +17,7 @@ pub struct State {
#[derive(Serialize)] #[derive(Serialize)]
pub struct Post { pub struct Post {
pub name: String, pub slug: String,
pub content: String, pub content: String,
} }
@ -31,15 +31,24 @@ async fn main() -> Result<()> {
let posts = glob("posts/**/*.md")? let posts = glob("posts/**/*.md")?
.map(|p| { .map(|p| {
let path = p.unwrap(); let path = p.unwrap();
let name = path
let filename = path
.file_name() .file_name()
.unwrap() .unwrap()
.to_string_lossy() .to_string_lossy();
.strip_suffix(".md")
.unwrap() let (filename, _) = filename.rsplit_once('.')
.to_owned(); .unwrap();
let slug = if filename.eq_ignore_ascii_case("index") {
path.parent().unwrap().file_name().unwrap().to_string_lossy().into_owned()
}
else {
filename.to_owned()
};
Post { Post {
name, slug,
content: std::fs::read_to_string(&path).unwrap(), content: std::fs::read_to_string(&path).unwrap(),
} }
}) })
@ -53,8 +62,12 @@ async fn main() -> Result<()> {
let app = Router::new() let app = Router::new()
.route("/", get(handlers::index)) .route("/", get(handlers::index))
.route("/posts", get(handlers::post_index)) .route("/posts/", get(handlers::posts::index))
.route("/posts/:name", get(handlers::post_view)) .route("/posts/:slug/", get(handlers::posts::view))
.nest("/static", get_service(tower_http::services::ServeDir::new("./static")).handle_error(|e| async {
(StatusCode::NOT_FOUND, "not found")
}))
.fallback((|| async { (StatusCode::NOT_FOUND, "not found") }).into_service())
.layer(middleware); .layer(middleware);
info!("Now listening at http://localhost:8180"); info!("Now listening at http://localhost:8180");
@ -65,3 +78,7 @@ async fn main() -> Result<()> {
Ok(()) Ok(())
} }
async fn healthcheck() -> &'static str {
"OK"
}

View file

@ -1,4 +1,5 @@
body { body {
width: 800px; max-width: 800px;
margin: auto; margin: auto;
padding: 8px;
} }

View file

@ -2,5 +2,6 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/static/site.css">
<title>Document</title> <title>Document</title>
</head> </head>

View file

@ -1,3 +1,3 @@
<nav> <nav>
<a href="/">tollyx</a> - <a href="/posts">posts</a> <a href="/">tollyx</a> - <a href="/posts/">posts</a>
</nav> </nav>

View file

@ -1,6 +1,8 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block main %} {% block main %}
<h1>posts</h1>
<p>i occasionally write some stuff i guess</p>
<ul> <ul>
{% for post in posts %} {% for post in posts %}
<li><a href="/posts/{{post.name}}">{{post.name}}</a></li> <li><a href="/posts/{{post.name}}">{{post.name}}</a></li>