post pathing

This commit is contained in:
2026-01-25 16:09:07 -05:00
parent f9d58cbd7c
commit 552cad6b4a
19 changed files with 2834 additions and 61 deletions

2625
Cargo.lock generated
View File

File diff suppressed because it is too large Load Diff

View File

@@ -12,3 +12,6 @@ tower-http = { version = "0.5", features = ["fs"] }
askama = "0.14.0"
serde_json = "1.0.149"
serde = "1.0.228"
typst = "0.14.2"
typst-html = "0.14.2"
regex = "1.12.2"

View File

@@ -12,6 +12,7 @@ in
# Replace llvmPackages with llvmPackages_X, where X is the latest LLVM version (at the time of writing, 16)
llvmPackages.bintools
rustup
typst
];
RUSTC_VERSION = overrides.toolchain.channel;

View File

@@ -1,12 +1,75 @@
use axum::{
Router, response::Html, routing::get
Router, extract::Path, response::Html, routing::get
};
use tower_http::services::ServeDir;
use askama::Template;
use markdown::to_html;
use std::fs;
// use typst::model;
// use typst_html;
use std::{collections::HashMap, fs, io::{Error, Write}, process::{Command, Stdio}};
use regex::Regex;
fn load_posts() -> Result<HashMap<String, Post>, Error> {
let dirs = fs::read_dir("static/posts")?;
let re_title = Regex::new(r#"#let\s+post_title\s*=\s*"([^"]*)""#).unwrap();
let re_summary = Regex::new(r#"#let\s+post_summary\s*=\s*"([^"]*)""#).unwrap();
let mut posts: HashMap<String, Post> = HashMap::new();
for dir in dirs {
let typst_path = dir?.path().join("post.typ");
let typst = fs::read_to_string(typst_path).expect("Failed reading post");
let title = re_title.captures(&typst)
.expect("Post title not found")
.get(1).unwrap().as_str().trim().to_string();
let summary = re_summary.captures(&typst)
.expect("Post summary not found")
.get(1).unwrap().as_str().trim().to_string();
let slug = title.clone().replace(" ", "-").to_lowercase();
posts.insert(
slug.clone(),
Post {
title: title.clone(),
slug: slug,
preview_image: "NA".to_string(),
summary: summary,
render: Html(PostTemplate {
title: title,
content: typst_to_html(typst),
}.render().expect("Failed rendering post")),
}
);
}
Ok(posts)
}
#[derive(Template)]
#[template(path = "post.html")]
struct PostTemplate {
title: String,
content: String,
}
#[derive(Clone)]
#[derive(Debug)]
struct Post {
title: String,
preview_image: String,
summary: String,
slug: String,
render: Html<String>
}
#[derive(Debug)]
#[derive(Template)]
#[template(path = "posts.html")]
struct PostsTemplate {
posts: Vec<Post>
}
// Template for home
#[derive(Template)]
#[template(path = "home.html", ext = "html")]
@@ -14,21 +77,58 @@ struct HomeTemplate {
content: String
}
fn typst_to_html(typst: String) -> String {
let mut child = Command::new("typst")
.args(["compile", "-", "-", "--format", "html", "--features", "html" ])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.expect("Failed running typst");
let mut stdin = child.stdin.take().expect("Failed opening STDIN");
stdin.write_all(typst.as_bytes()).expect("Failed writing to STDIN");
drop(stdin);
let output = child.wait_with_output().expect("Failed reading output");
String::from_utf8_lossy(&output.stdout).to_string()
}
// , posts: &Vec<Post>
async fn get_post(
Path(slug): Path<String>,
posts: HashMap<String, Post>
) -> Html<String> {
if posts.contains_key(&slug) {
return posts[&slug].render.clone()
}
else {
return Html("404".to_string());
}
}
#[tokio::main]
async fn main() {
let home_html = Html(
HomeTemplate {
content: to_html(&fs::read_to_string(
"static/strings/home.md"
content: typst_to_html(fs::read_to_string(
"static/home.typ"
).expect("Couldnt read file"))
}.render().unwrap()
}.render().expect("Failed rendering home template")
);
let posts: HashMap<String, Post> = load_posts().expect("Failed loading posts");
let posts_html = Html(
PostsTemplate{
posts: posts.values().cloned().collect::<Vec<Post>>()
}.render().expect("Failed rendering posts")
);
let site: Router = Router::new()
.route("/", get(home_html))
.nest_service("/static", ServeDir::new("static"));
.route("/posts", get(posts_html))
.route("/posts/{title}", get(|title| get_post(title, posts)))
.nest_service("/static", ServeDir::new("static"))
// .with_state(posts)
;

26
static/home.typ Normal file
View File

@@ -0,0 +1,26 @@
= About me
Hey! I'm someone that likes to know my tools well.
I also beleive in fairness and doing what is right. I'm frequently
= Skills
= Hobbies
My free time is split into working on projects and touching grass.
= What I want to do
What I've found most interesting has to be the oppurtunities I get
// Software engineering is a passion of mine, and people tend to reflect the things they do.
// My desktop and homelab run NixOS. I wrote this site in Rust, and add posts using Typst files. The whole thing is hosted on my gitea, and runs in a container defined by Nix.
// I wrote this myself. While AI communicates ideas better than I do, I want to ensure that my and only my thoughts are written.

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -1,16 +1,22 @@
#let post_title = "Game Dev"
#let post_summary = "Creating an open world multiplayer terrain destruction game in Godot and Rust"
I am currently developing an underground-submarine openworld multiplayer
physics inspired game. As a gamer and enjoyer of large, rich maps and
depth to gameplay, I would really like to say thats what I started out
trying to create. Instead, the story goes that I had this random idea
for terrain manipulation. Games like Minecraft and Terraria use squares
and cubes, which just feels boring in my opinion. I thought I could do
something much more <i>visceral</i> As a sort of tech-demo/proof of
something much more precise. As a sort of tech-demo/proof of
concept I programmed a shape that could be modified by boolean geometry
operations, mainly union and subtract with a second polygon. This led to
a very interesting, but quickly boring "game" to hop around in. However,
since I could drill through and place prettymuch any shape I wanted to,
it felt like I could "fly" through the land, much like a submarine
"flies" through water.<br /><br />I implemented some modularly built
"flies" through water.
I implemented some modularly built
vehicles with use of graphs theory and object oriented programming, and
terrain generation using cellular noise. The reason I used cellular
noise is because if you look at the lines between cells, they form a
@@ -18,13 +24,17 @@ network without dead ends. Then by applying an algorithm using a density
function on depth I am able to fine tune the width and density of the
caves without impacting their interconnectedness. By using this method
chunks can generate completely independent of their neighbor, which is
optimal.<br /><br />"Multiplayer is the hardest part of game dev, maybe
optimal.
"Multiplayer is the hardest part of game dev, maybe
release that later" I have been told by a lot of people. However, as a
hobby-server configurer and network security nerd, I thought I could
take it on. I was right, however as a network security nerd I have more
layers of firewalls than I do braincells. Every single time I have an
issue with networking, its a firewall. Once I found which ports were
blocked, yes multiplayer was easy.<br /><br />The result? I could fly
blocked, yes multiplayer was easy.
The result? I could fly
drilling vehicles through terrain, pop out of the ground or into random
caves, mine materials, play hide and seek with friends, and even orbit
the planet. One of the things important to me in this game was accurate
@@ -32,17 +42,21 @@ physics: thrust, torque, gravity, mass, all the fun stuff. While I am a
physics minor, I am more importantly a heavy player of physics and
rocket science games such as Kerbal Space Program. I was able to glide
through AP physics simply because it
<i>just part of the games world</i>, it included everything we would
_just part of the games world_, it included everything we would
learn in the classroom. Realistic physics also added to the depth of
gameplay I was looking for.<br /><br /> After some formal computer
gameplay I was looking for.
After some formal computer
science education, I discovered new ways to more efficiently implement
many of the algorithms I had initially generated and rewrote them
...multiple times. Currently everything runs <i>buttery smooth</i> and
...multiple times. Currently everything runs _buttery smooth_ and
framerates are high due to efficient caching of unloaded chunks,
multithreaded chunk generation, gpu accelerated compute shaders to
modify chunk density, enhanced use of object oriented programing and
graph algorithms to build massive modular vehicles, authoritative server
networking to disable hackers, and other performance tweaks.<br /><br />
networking to disable hackers, and other performance tweaks.
So this sounds amazing, where's the game? Well, a game needs graphics, audio,
a sound track. As much as I'd love to release it now, its unplayable for
these reasons along with a few minor implementations left such as NPC's and

View File

@@ -1,5 +0,0 @@
# About me
I'm a fungi
_markdown in html :0_

View File

@@ -58,5 +58,6 @@ nav ul {
}
body {
background-image: linear-gradient(315deg, #111, #222);
min-height: 100vh;
background-image: linear-gradient(330deg, #222, #040404);
}

21
templates/base.html Normal file
View File

@@ -0,0 +1,21 @@
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="/static/style.css"
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<header>
<nav>
<ul>
<li>Posts</li>
<li>Contact</li>
</ul>
</nav>
</header>
<div style="padding: auto">
{% block body %}{% endblock %}
</div>
</body>
</html>

View File

@@ -1,27 +1,10 @@
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="/static/style.css"
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<header>
<nav>
<ul>
<li>Posts</li>
<li>Contact</li>
</ul>
</nav>
</header>
<div style="padding: auto">
<div>
{% extends "base.html" %}
{% block body %}
<p id="name">Jeremy Janella</p>
</div>
<div>
{{ content|safe }}
</div>
</div>
</body>
</html>
{% endblock %}

View File

@@ -0,0 +1,4 @@
<div>
<h2>{{ post.title }}</h2>
{{ post.summary }}
</div>

9
templates/post.html Normal file
View File

@@ -0,0 +1,9 @@
{% extends "base.html" %}
{% block body %}
{{ title|safe }}
{{ content|safe }}
{% endblock %}

13
templates/posts.html Normal file
View File

@@ -0,0 +1,13 @@
{% extends "base.html" %}
{% block body %}
<div id="posts-grid">
{% for post in posts %}
{% include "post-preview.html" %}
{% endfor %}
</div>
{% endblock %}