Work on modularizing - things were getting messy
This commit is contained in:
parent
7b79205148
commit
1843f9fac3
11 changed files with 177 additions and 105 deletions
11
Cargo.lock
generated
11
Cargo.lock
generated
|
@ -757,7 +757,9 @@ dependencies = [
|
||||||
"futures",
|
"futures",
|
||||||
"minijinja",
|
"minijinja",
|
||||||
"notify",
|
"notify",
|
||||||
|
"pathdiff",
|
||||||
"redact",
|
"redact",
|
||||||
|
"serde",
|
||||||
"sled",
|
"sled",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower",
|
"tower",
|
||||||
|
@ -765,6 +767,7 @@ dependencies = [
|
||||||
"tower-livereload",
|
"tower-livereload",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1232,18 +1235,18 @@ checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.200"
|
version = "1.0.201"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f"
|
checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.200"
|
version = "1.0.201"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb"
|
checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
|
@ -12,7 +12,9 @@ config = "0.14.0"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
minijinja = { version = "2.0.1", features = ["loader"] }
|
minijinja = { version = "2.0.1", features = ["loader"] }
|
||||||
notify = "6.1.1"
|
notify = "6.1.1"
|
||||||
|
pathdiff = "0.2.1"
|
||||||
redact = { version = "0.1.9", features = ["serde"] }
|
redact = { version = "0.1.9", features = ["serde"] }
|
||||||
|
serde = "1.0.201"
|
||||||
sled = "0.34.7"
|
sled = "0.34.7"
|
||||||
tokio = { version = "1.37.0", features = ["full"] }
|
tokio = { version = "1.37.0", features = ["full"] }
|
||||||
tower = "0.4.13"
|
tower = "0.4.13"
|
||||||
|
@ -20,3 +22,4 @@ tower-http = { version = "0.5.2", features = ["fs"] }
|
||||||
tower-livereload = "0.9.2"
|
tower-livereload = "0.9.2"
|
||||||
tracing = "0.1.40"
|
tracing = "0.1.40"
|
||||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||||
|
walkdir = "2.5.0"
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
pkg-config
|
pkg-config
|
||||||
inotify-tools
|
inotify-tools
|
||||||
tailwindcss
|
tailwindcss
|
||||||
|
nodePackages.typescript-language-server
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
{% extends "page.html.jinja" %}
|
|
||||||
{% block body %}
|
|
||||||
<h1>Index</h1>
|
|
||||||
<p class="important">
|
|
||||||
Welcome to my awesome homepage.
|
|
||||||
</p>
|
|
||||||
{% endblock %}
|
|
80
src/main.rs
80
src/main.rs
|
@ -2,14 +2,11 @@ use axum::extract::State;
|
||||||
use axum::response::IntoResponse;
|
use axum::response::IntoResponse;
|
||||||
use axum::routing::get;
|
use axum::routing::get;
|
||||||
use axum::{http::StatusCode, response::Html, serve, Router};
|
use axum::{http::StatusCode, response::Html, serve, Router};
|
||||||
use minijinja::{context, Environment};
|
use minijinja::context;
|
||||||
use notify::{Config, RecommendedWatcher, RecursiveMode, Watcher};
|
use notify::{Config, RecommendedWatcher, RecursiveMode, Watcher};
|
||||||
use std::process::Stdio;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::{path::PathBuf, str::FromStr, sync::OnceLock};
|
use std::{path::PathBuf, str::FromStr, sync::OnceLock};
|
||||||
use tokio::io::{AsyncBufReadExt, BufReader};
|
use templates::Templates;
|
||||||
use tokio::sync::mpsc::channel;
|
use tokio::sync::mpsc::channel;
|
||||||
use tokio::sync::Mutex;
|
|
||||||
use tower_http::services::ServeDir;
|
use tower_http::services::ServeDir;
|
||||||
use tower_livereload::{LiveReloadLayer, Reloader};
|
use tower_livereload::{LiveReloadLayer, Reloader};
|
||||||
pub use tracing::{debug, error, event, info, span, warn, Level};
|
pub use tracing::{debug, error, event, info, span, warn, Level};
|
||||||
|
@ -18,19 +15,9 @@ pub use tracing::{debug, error, event, info, span, warn, Level};
|
||||||
struct Berr(Box<dyn std::error::Error>);
|
struct Berr(Box<dyn std::error::Error>);
|
||||||
type Besult<T> = std::result::Result<T, Berr>;
|
type Besult<T> = std::result::Result<T, Berr>;
|
||||||
|
|
||||||
mod observe {
|
mod observe;
|
||||||
pub fn setup_logging() {
|
mod tailwind;
|
||||||
color_eyre::install().expect("Failed to install color_eyre");
|
mod templates;
|
||||||
|
|
||||||
let filter = tracing_subscriber::EnvFilter::builder()
|
|
||||||
.with_default_directive(<tracing_subscriber::filter::Directive>::from(
|
|
||||||
tracing::level_filters::LevelFilter::TRACE,
|
|
||||||
))
|
|
||||||
.parse_lossy("info,lyrs=trace");
|
|
||||||
|
|
||||||
tracing_subscriber::fmt().with_env_filter(filter).init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn static_file_dir() -> &'static PathBuf {
|
fn static_file_dir() -> &'static PathBuf {
|
||||||
static STATIC_FILE_DIR: OnceLock<PathBuf> = OnceLock::new();
|
static STATIC_FILE_DIR: OnceLock<PathBuf> = OnceLock::new();
|
||||||
|
@ -39,53 +26,22 @@ fn static_file_dir() -> &'static PathBuf {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct AppState {
|
struct AppState {
|
||||||
templates: Arc<Mutex<Environment<'static>>>,
|
templates: Templates,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Besult<()> {
|
async fn main() -> Besult<()> {
|
||||||
// load configuration?
|
// load configuration?
|
||||||
observe::setup_logging();
|
let _setup_logging = observe::setup_logging();
|
||||||
|
|
||||||
|
// TODO: reload templates when they change? separate watcher?
|
||||||
|
let templates = Templates::try_load().await?;
|
||||||
|
let mut tt = templates.clone();
|
||||||
|
let templates_watcher = tt.start_watcher();
|
||||||
|
|
||||||
// TODO: only start tailwind if in dev mode?
|
// TODO: only start tailwind if in dev mode?
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async { tailwind::start_watcher() });
|
||||||
info!("Starting tailwind...");
|
tokio::spawn(async move { templates_watcher.await });
|
||||||
match tokio::process::Command::new("tailwindcss")
|
|
||||||
.args(["-i", "src/style.css", "-o", "static/style.css", "--watch"])
|
|
||||||
.stdout(Stdio::piped())
|
|
||||||
.stderr(Stdio::piped())
|
|
||||||
.spawn()
|
|
||||||
{
|
|
||||||
Ok(mut tw) => {
|
|
||||||
info!("Tailwind spawned!");
|
|
||||||
let mut stdout_reader = BufReader::new(tw.stdout.take().unwrap()).lines();
|
|
||||||
tokio::spawn(async move {
|
|
||||||
while let Ok(Some(l)) = stdout_reader.next_line().await {
|
|
||||||
if l.trim().len() > 0 {
|
|
||||||
event!(target: "tailwind::stdout", Level::INFO, "{l}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let mut stderr_reader = BufReader::new(tw.stderr.take().unwrap()).lines();
|
|
||||||
tokio::spawn(async move {
|
|
||||||
while let Ok(Some(l)) = stderr_reader.next_line().await {
|
|
||||||
if l.trim().len() > 0 {
|
|
||||||
event!(target: "tailwind::stderr", Level::INFO, "{l}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Err(e) => error!("Failed to spawn Tailwind: {e}"),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let templates = Arc::new(Mutex::new(Environment::new()));
|
|
||||||
while let Some(d) = tokio::fs::read_dir("templates").await?.next_entry().await? {
|
|
||||||
templates.clone().lock().await.add_template_owned(
|
|
||||||
d.file_name().into_string().unwrap(),
|
|
||||||
std::fs::read_to_string(d.path())?,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// pulling the watcher into main's scope lets it live until the program dies
|
// pulling the watcher into main's scope lets it live until the program dies
|
||||||
let (rl_layer, _watcher) = live_reload_layer()?;
|
let (rl_layer, _watcher) = live_reload_layer()?;
|
||||||
|
@ -105,10 +61,8 @@ async fn index(State(state): State<AppState>) -> Besult<Html<String>> {
|
||||||
Ok(Html(
|
Ok(Html(
|
||||||
state
|
state
|
||||||
.templates
|
.templates
|
||||||
.lock()
|
.render("pages/index.html.jinja", context!())
|
||||||
.await
|
.await?,
|
||||||
.get_template("page.html")?
|
|
||||||
.render(context!())?,
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,9 +96,7 @@ fn static_file_watcher(
|
||||||
watcher.watch(static_file_dir(), RecursiveMode::Recursive)?;
|
watcher.watch(static_file_dir(), RecursiveMode::Recursive)?;
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
info!("Recieving...");
|
|
||||||
while let Some(res) = rx.recv().await {
|
while let Some(res) = rx.recv().await {
|
||||||
info!("Recieved! {res:#?}");
|
|
||||||
match res {
|
match res {
|
||||||
Ok(event) => {
|
Ok(event) => {
|
||||||
info!("fs event: {event:#?}");
|
info!("fs event: {event:#?}");
|
||||||
|
|
11
src/observe.rs
Normal file
11
src/observe.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
pub fn setup_logging() {
|
||||||
|
color_eyre::install().expect("Failed to install color_eyre");
|
||||||
|
|
||||||
|
let filter = tracing_subscriber::EnvFilter::builder()
|
||||||
|
.with_default_directive(<tracing_subscriber::filter::Directive>::from(
|
||||||
|
tracing::level_filters::LevelFilter::TRACE,
|
||||||
|
))
|
||||||
|
.parse_lossy("info,lyrs=trace");
|
||||||
|
|
||||||
|
tracing_subscriber::fmt().with_env_filter(filter).init();
|
||||||
|
}
|
37
src/tailwind.rs
Normal file
37
src/tailwind.rs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
use std::process::Stdio;
|
||||||
|
use tokio::{
|
||||||
|
io::{AsyncBufReadExt, BufReader},
|
||||||
|
process::Command,
|
||||||
|
};
|
||||||
|
use tracing::{error, event, info, Level};
|
||||||
|
|
||||||
|
pub fn start_watcher() {
|
||||||
|
info!("Starting tailwind...");
|
||||||
|
match Command::new("tailwindcss")
|
||||||
|
.args(["-i", "src/style.css", "-o", "static/style.css", "--watch"])
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.stderr(Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
{
|
||||||
|
Ok(mut tw) => {
|
||||||
|
info!("Tailwind spawned!");
|
||||||
|
let mut stdout_reader = BufReader::new(tw.stdout.take().unwrap()).lines();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
while let Ok(Some(l)) = stdout_reader.next_line().await {
|
||||||
|
if l.trim().len() > 0 {
|
||||||
|
event!(target: "tailwind::stdout", Level::INFO, "{l}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let mut stderr_reader = BufReader::new(tw.stderr.take().unwrap()).lines();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
while let Ok(Some(l)) = stderr_reader.next_line().await {
|
||||||
|
if l.trim().len() > 0 {
|
||||||
|
event!(target: "tailwind::stderr", Level::INFO, "{l}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Err(e) => error!("Failed to spawn Tailwind: {e}"),
|
||||||
|
}
|
||||||
|
}
|
68
src/templates.rs
Normal file
68
src/templates.rs
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use minijinja::Environment;
|
||||||
|
use pathdiff::diff_paths;
|
||||||
|
use tokio::sync::Mutex;
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Templates {
|
||||||
|
env: Arc<Mutex<Environment<'static>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Error = Box<dyn std::error::Error>;
|
||||||
|
|
||||||
|
impl Templates {
|
||||||
|
pub fn empty() -> Self {
|
||||||
|
let env = Arc::new(Mutex::new(Environment::new()));
|
||||||
|
Self { env }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn try_load() -> Result<Self, Error> {
|
||||||
|
let mut result = Self::empty();
|
||||||
|
result.load_env().await?;
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn start_watcher(&mut self) {
|
||||||
|
info!("TODO: Implement template watcher");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn load_env(&mut self) -> Result<(), Error> {
|
||||||
|
info!("Loading templates...");
|
||||||
|
for d in walkdir::WalkDir::new("src/templates") {
|
||||||
|
match d {
|
||||||
|
Ok(d) => {
|
||||||
|
if d.file_type().is_dir() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let filename: String = diff_paths(d.path(), "src/templates")
|
||||||
|
.unwrap()
|
||||||
|
.to_string_lossy()
|
||||||
|
.into_owned();
|
||||||
|
info!("Loading template {filename:#?} ({d:#?})");
|
||||||
|
self.env
|
||||||
|
.clone()
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.add_template_owned(filename, std::fs::read_to_string(d.path())?)?;
|
||||||
|
}
|
||||||
|
Err(_) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
info!("Done loading templates!");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn render<S: serde::ser::Serialize>(
|
||||||
|
&self,
|
||||||
|
template_name: &str,
|
||||||
|
context: S,
|
||||||
|
) -> Result<String, minijinja::Error> {
|
||||||
|
self.env
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.get_template(template_name)?
|
||||||
|
.render(context)
|
||||||
|
}
|
||||||
|
}
|
7
src/templates/pages/index.html.jinja
Normal file
7
src/templates/pages/index.html.jinja
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "page.html.jinja" %}
|
||||||
|
{% block body %}
|
||||||
|
<h1>Index</h1>
|
||||||
|
<p class="important">
|
||||||
|
Welcome to my awesome homepage!
|
||||||
|
</p>
|
||||||
|
{% endblock %}
|
|
@ -1,8 +1,7 @@
|
||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: ["./src/**/*.rs","./static/**/*.{html,js}"], theme: {
|
content: ["./src/**/*"], theme: {
|
||||||
colors: {
|
colors: {
|
||||||
|
|
||||||
rosewater: "var(--Rosewater)",
|
rosewater: "var(--Rosewater)",
|
||||||
flamingo: "var(--Flamingo)",
|
flamingo: "var(--Flamingo)",
|
||||||
pink: "var(--Pink)",
|
pink: "var(--Pink)",
|
||||||
|
@ -29,10 +28,8 @@ module.exports = {
|
||||||
base: "var(--Base)",
|
base: "var(--Base)",
|
||||||
mantle: "var(--Mantle)",
|
mantle: "var(--Mantle)",
|
||||||
crust: "var(--Crust)",
|
crust: "var(--Crust)",
|
||||||
|
|
||||||
},
|
},
|
||||||
extend: {
|
extend: {
|
||||||
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [],
|
||||||
|
|
Loading…
Reference in a new issue