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::{
|
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
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 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"
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
body {
|
body {
|
||||||
width: 800px;
|
max-width: 800px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
padding: 8px;
|
||||||
}
|
}
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in a new issue