Progress
This commit is contained in:
parent
b98031de94
commit
e0237555cd
9 changed files with 90 additions and 51 deletions
BIN
posts/foldertest/FbHSmoeUUAA2x-m.png
Normal file
BIN
posts/foldertest/FbHSmoeUUAA2x-m.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 343 KiB |
7
posts/foldertest/index.md
Normal file
7
posts/foldertest/index.md
Normal 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)
|
|
@ -5,12 +5,15 @@ use tracing::log::*;
|
|||
use axum::{
|
||||
extract::Path,
|
||||
response::{Html, IntoResponse, Response},
|
||||
http::{StatusCode, Uri},
|
||||
Extension,
|
||||
};
|
||||
use pulldown_cmark::{html, Options, Parser};
|
||||
|
||||
use crate::State;
|
||||
|
||||
pub mod posts;
|
||||
|
||||
pub enum Error {
|
||||
NotFound,
|
||||
}
|
||||
|
@ -31,45 +34,6 @@ pub async fn index(Extension(state): Extension<Arc<State>>) -> Result {
|
|||
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 {
|
||||
fn into_response(self) -> Response {
|
||||
let result: Vec<u8> = "not found".into();
|
||||
|
|
47
src/handlers/posts.rs
Normal file
47
src/handlers/posts.rs
Normal 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()))
|
||||
}
|
37
src/main.rs
37
src/main.rs
|
@ -1,6 +1,6 @@
|
|||
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 glob::glob;
|
||||
use serde_derive::Serialize;
|
||||
|
@ -17,7 +17,7 @@ pub struct State {
|
|||
|
||||
#[derive(Serialize)]
|
||||
pub struct Post {
|
||||
pub name: String,
|
||||
pub slug: String,
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
|
@ -31,15 +31,24 @@ async fn main() -> Result<()> {
|
|||
let posts = glob("posts/**/*.md")?
|
||||
.map(|p| {
|
||||
let path = p.unwrap();
|
||||
let name = path
|
||||
|
||||
let filename = path
|
||||
.file_name()
|
||||
.unwrap()
|
||||
.to_string_lossy()
|
||||
.strip_suffix(".md")
|
||||
.unwrap()
|
||||
.to_owned();
|
||||
.to_string_lossy();
|
||||
|
||||
let (filename, _) = filename.rsplit_once('.')
|
||||
.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 {
|
||||
name,
|
||||
slug,
|
||||
content: std::fs::read_to_string(&path).unwrap(),
|
||||
}
|
||||
})
|
||||
|
@ -53,8 +62,12 @@ async fn main() -> Result<()> {
|
|||
|
||||
let app = Router::new()
|
||||
.route("/", get(handlers::index))
|
||||
.route("/posts", get(handlers::post_index))
|
||||
.route("/posts/:name", get(handlers::post_view))
|
||||
.route("/posts/", get(handlers::posts::index))
|
||||
.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);
|
||||
|
||||
info!("Now listening at http://localhost:8180");
|
||||
|
@ -65,3 +78,7 @@ async fn main() -> Result<()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn healthcheck() -> &'static str {
|
||||
"OK"
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
body {
|
||||
width: 800px;
|
||||
max-width: 800px;
|
||||
margin: auto;
|
||||
padding: 8px;
|
||||
}
|
|
@ -2,5 +2,6 @@
|
|||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/static/site.css">
|
||||
<title>Document</title>
|
||||
</head>
|
|
@ -1,3 +1,3 @@
|
|||
<nav>
|
||||
<a href="/">tollyx</a> - <a href="/posts">posts</a>
|
||||
<a href="/">tollyx</a> - <a href="/posts/">posts</a>
|
||||
</nav>
|
|
@ -1,6 +1,8 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block main %}
|
||||
<h1>posts</h1>
|
||||
<p>i occasionally write some stuff i guess</p>
|
||||
<ul>
|
||||
{% for post in posts %}
|
||||
<li><a href="/posts/{{post.name}}">{{post.name}}</a></li>
|
||||
|
|
Loading…
Reference in a new issue