post pathing
This commit is contained in:
2625
Cargo.lock
generated
2625
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -12,3 +12,6 @@ tower-http = { version = "0.5", features = ["fs"] }
|
|||||||
askama = "0.14.0"
|
askama = "0.14.0"
|
||||||
serde_json = "1.0.149"
|
serde_json = "1.0.149"
|
||||||
serde = "1.0.228"
|
serde = "1.0.228"
|
||||||
|
typst = "0.14.2"
|
||||||
|
typst-html = "0.14.2"
|
||||||
|
regex = "1.12.2"
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ in
|
|||||||
# Replace llvmPackages with llvmPackages_X, where X is the latest LLVM version (at the time of writing, 16)
|
# Replace llvmPackages with llvmPackages_X, where X is the latest LLVM version (at the time of writing, 16)
|
||||||
llvmPackages.bintools
|
llvmPackages.bintools
|
||||||
rustup
|
rustup
|
||||||
|
typst
|
||||||
];
|
];
|
||||||
|
|
||||||
RUSTC_VERSION = overrides.toolchain.channel;
|
RUSTC_VERSION = overrides.toolchain.channel;
|
||||||
|
|||||||
114
src/main.rs
114
src/main.rs
@@ -1,12 +1,75 @@
|
|||||||
use axum::{
|
use axum::{
|
||||||
Router, response::Html, routing::get
|
Router, extract::Path, response::Html, routing::get
|
||||||
};
|
};
|
||||||
use tower_http::services::ServeDir;
|
use tower_http::services::ServeDir;
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
use markdown::to_html;
|
// use typst::model;
|
||||||
use std::fs;
|
// 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
|
// Template for home
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
#[template(path = "home.html", ext = "html")]
|
#[template(path = "home.html", ext = "html")]
|
||||||
@@ -14,21 +77,58 @@ struct HomeTemplate {
|
|||||||
content: String
|
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]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
|
||||||
let home_html = Html(
|
let home_html = Html(
|
||||||
HomeTemplate {
|
HomeTemplate {
|
||||||
content: to_html(&fs::read_to_string(
|
content: typst_to_html(fs::read_to_string(
|
||||||
"static/strings/home.md"
|
"static/home.typ"
|
||||||
).expect("Couldnt read file"))
|
).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()
|
let site: Router = Router::new()
|
||||||
.route("/", get(home_html))
|
.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
26
static/home.typ
Normal 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.
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
@@ -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
|
I am currently developing an underground-submarine openworld multiplayer
|
||||||
physics inspired game. As a gamer and enjoyer of large, rich maps and
|
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
|
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
|
trying to create. Instead, the story goes that I had this random idea
|
||||||
for terrain manipulation. Games like Minecraft and Terraria use squares
|
for terrain manipulation. Games like Minecraft and Terraria use squares
|
||||||
and cubes, which just feels boring in my opinion. I thought I could do
|
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
|
concept I programmed a shape that could be modified by boolean geometry
|
||||||
operations, mainly union and subtract with a second polygon. This led to
|
operations, mainly union and subtract with a second polygon. This led to
|
||||||
a very interesting, but quickly boring "game" to hop around in. However,
|
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,
|
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
|
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
|
vehicles with use of graphs theory and object oriented programming, and
|
||||||
terrain generation using cellular noise. The reason I used cellular
|
terrain generation using cellular noise. The reason I used cellular
|
||||||
noise is because if you look at the lines between cells, they form a
|
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
|
function on depth I am able to fine tune the width and density of the
|
||||||
caves without impacting their interconnectedness. By using this method
|
caves without impacting their interconnectedness. By using this method
|
||||||
chunks can generate completely independent of their neighbor, which is
|
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
|
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
|
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
|
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
|
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
|
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
|
drilling vehicles through terrain, pop out of the ground or into random
|
||||||
caves, mine materials, play hide and seek with friends, and even orbit
|
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
|
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
|
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
|
rocket science games such as Kerbal Space Program. I was able to glide
|
||||||
through AP physics simply because it
|
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
|
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
|
science education, I discovered new ways to more efficiently implement
|
||||||
many of the algorithms I had initially generated and rewrote them
|
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,
|
framerates are high due to efficient caching of unloaded chunks,
|
||||||
multithreaded chunk generation, gpu accelerated compute shaders to
|
multithreaded chunk generation, gpu accelerated compute shaders to
|
||||||
modify chunk density, enhanced use of object oriented programing and
|
modify chunk density, enhanced use of object oriented programing and
|
||||||
graph algorithms to build massive modular vehicles, authoritative server
|
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,
|
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
|
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
|
these reasons along with a few minor implementations left such as NPC's and
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
|
|
||||||
# About me
|
|
||||||
I'm a fungi
|
|
||||||
|
|
||||||
_markdown in html :0_
|
|
||||||
@@ -58,5 +58,6 @@ nav ul {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background-image: linear-gradient(315deg, #111, #222);
|
min-height: 100vh;
|
||||||
|
background-image: linear-gradient(330deg, #222, #040404);
|
||||||
}
|
}
|
||||||
|
|||||||
21
templates/base.html
Normal file
21
templates/base.html
Normal 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>
|
||||||
@@ -1,27 +1,10 @@
|
|||||||
<!doctype html>
|
{% extends "base.html" %}
|
||||||
<html lang="en">
|
|
||||||
<head>
|
{% block body %}
|
||||||
<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>
|
|
||||||
<p id="name">Jeremy Janella</p>
|
<p id="name">Jeremy Janella</p>
|
||||||
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{{ content|safe }}
|
{{ content|safe }}
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
{% endblock %}
|
||||||
</html>
|
|
||||||
|
|||||||
4
templates/post-preview.html
Normal file
4
templates/post-preview.html
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<div>
|
||||||
|
<h2>{{ post.title }}</h2>
|
||||||
|
{{ post.summary }}
|
||||||
|
</div>
|
||||||
9
templates/post.html
Normal file
9
templates/post.html
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
|
||||||
|
{{ title|safe }}
|
||||||
|
|
||||||
|
{{ content|safe }}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
13
templates/posts.html
Normal file
13
templates/posts.html
Normal 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 %}
|
||||||
Reference in New Issue
Block a user