Compare commits
No commits in common. "586fd8a066701ac81208c404d5ea437cd2bd70ad" and "a510d0809f8e97d62a8c9e3d534c6a119049f722" have entirely different histories.
586fd8a066
...
a510d0809f
20
Cargo.lock
generated
20
Cargo.lock
generated
@ -216,25 +216,6 @@ version = "0.3.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
|
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "include_dir"
|
|
||||||
version = "0.7.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "18762faeff7122e89e0857b02f7ce6fcc0d101d5e9ad2ad7846cc01d61b7f19e"
|
|
||||||
dependencies = [
|
|
||||||
"include_dir_macros",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "include_dir_macros"
|
|
||||||
version = "0.7.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.0.2"
|
version = "2.0.2"
|
||||||
@ -643,7 +624,6 @@ version = "0.0.1"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"duster",
|
"duster",
|
||||||
"include_dir",
|
|
||||||
"organic",
|
"organic",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -6,12 +6,14 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
# error-context, suggestions, usage | env
|
||||||
clap = { version = "4.4.6", default-features = false, features = ["std", "color", "help", "derive"] }
|
clap = { version = "4.4.6", default-features = false, features = ["std", "color", "help", "derive"] }
|
||||||
duster = { git = "https://code.fizz.buzz/talexander/duster.git", branch = "master" }
|
duster = { git = "https://code.fizz.buzz/talexander/duster.git", branch = "master" }
|
||||||
include_dir = "0.7.3"
|
|
||||||
organic = "0.1.12"
|
organic = "0.1.12"
|
||||||
|
# | alloc, rc, serde_derive, unstable
|
||||||
serde = { version = "1.0.189", default-features = false, features = ["std", "derive"] }
|
serde = { version = "1.0.189", default-features = false, features = ["std", "derive"] }
|
||||||
serde_json = "1.0.107"
|
serde_json = "1.0.107"
|
||||||
tokio = { version = "1.30.0", default-features = false, features = ["rt", "rt-multi-thread", "fs", "io-util"] }
|
tokio = { version = "1.30.0", default-features = false, features = ["rt", "rt-multi-thread", "fs", "io-util"] }
|
||||||
|
# display, parse | indexmap, preserve_order
|
||||||
toml = "0.8.2"
|
toml = "0.8.2"
|
||||||
walkdir = "2.4.0"
|
walkdir = "2.4.0"
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p>Hello world!</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,8 +0,0 @@
|
|||||||
use super::render_context::RenderBlogPost;
|
|
||||||
use super::BlogPost;
|
|
||||||
|
|
||||||
pub(crate) fn convert_blog_post_to_render_context(post: &BlogPost) -> RenderBlogPost {
|
|
||||||
RenderBlogPost {
|
|
||||||
id: post.id.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,7 +8,7 @@ use crate::error::CustomError;
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct BlogPost {
|
pub(crate) struct BlogPost {
|
||||||
pub(crate) id: String,
|
id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BlogPost {
|
impl BlogPost {
|
||||||
|
@ -1,5 +1,2 @@
|
|||||||
mod convert;
|
|
||||||
mod definition;
|
mod definition;
|
||||||
mod render_context;
|
|
||||||
pub(crate) use convert::convert_blog_post_to_render_context;
|
|
||||||
pub(crate) use definition::BlogPost;
|
pub(crate) use definition::BlogPost;
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
use serde::Serialize;
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
|
||||||
#[serde(tag = "type")]
|
|
||||||
#[serde(rename = "blog_post")]
|
|
||||||
pub(crate) struct RenderBlogPost {
|
|
||||||
pub(crate) id: String,
|
|
||||||
}
|
|
@ -1,4 +1,3 @@
|
|||||||
mod render;
|
|
||||||
mod runner;
|
mod runner;
|
||||||
|
|
||||||
pub(crate) use runner::build_site;
|
pub(crate) use runner::build_site;
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
use std::ffi::OsStr;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use include_dir::include_dir;
|
|
||||||
use include_dir::Dir;
|
|
||||||
|
|
||||||
use crate::blog_post::convert_blog_post_to_render_context;
|
|
||||||
use crate::blog_post::BlogPost;
|
|
||||||
use crate::error::CustomError;
|
|
||||||
use crate::render::DusterRenderer;
|
|
||||||
use crate::render::RendererIntegration;
|
|
||||||
|
|
||||||
static MAIN_TEMPLATES: Dir = include_dir!("$CARGO_MANIFEST_DIR/default_environment/templates/html");
|
|
||||||
|
|
||||||
pub(crate) struct SiteRenderer {
|
|
||||||
output_directory: PathBuf,
|
|
||||||
blog_posts: Vec<BlogPost>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SiteRenderer {
|
|
||||||
pub(crate) fn new<P: Into<PathBuf>>(
|
|
||||||
output_directory: P,
|
|
||||||
blog_posts: Vec<BlogPost>,
|
|
||||||
) -> SiteRenderer {
|
|
||||||
SiteRenderer {
|
|
||||||
output_directory: output_directory.into(),
|
|
||||||
blog_posts,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub(crate) async fn render_blog_posts(&self) -> Result<(), CustomError> {
|
|
||||||
let mut renderer_integration = DusterRenderer::new();
|
|
||||||
|
|
||||||
let (main_template, other_templates): (Vec<_>, Vec<_>) = MAIN_TEMPLATES
|
|
||||||
.files()
|
|
||||||
.filter(|f| f.path().extension() == Some(OsStr::new("dust")))
|
|
||||||
.partition(|f| f.path().file_stem() == Some(OsStr::new("main")));
|
|
||||||
if main_template.len() != 1 {
|
|
||||||
return Err("Expect exactly 1 main.dust template file.".into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let decoded_templates = {
|
|
||||||
let mut decoded_templates =
|
|
||||||
Vec::with_capacity(main_template.len() + other_templates.len());
|
|
||||||
for entry in main_template {
|
|
||||||
decoded_templates.push(build_name_contents_pairs(entry)?);
|
|
||||||
}
|
|
||||||
for entry in other_templates {
|
|
||||||
decoded_templates.push(build_name_contents_pairs(entry)?);
|
|
||||||
}
|
|
||||||
decoded_templates
|
|
||||||
};
|
|
||||||
|
|
||||||
for (name, contents) in decoded_templates {
|
|
||||||
renderer_integration.load_template(name, contents)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
for blog_post in &self.blog_posts {
|
|
||||||
let render_context = convert_blog_post_to_render_context(blog_post);
|
|
||||||
let rendered_output = renderer_integration.render(render_context)?;
|
|
||||||
println!("Rendered: {}", rendered_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_name_contents_pairs<'a>(
|
|
||||||
entry: &'a include_dir::File<'_>,
|
|
||||||
) -> Result<(&'a str, &'a str), CustomError> {
|
|
||||||
let path = entry.path();
|
|
||||||
let name = path
|
|
||||||
.file_stem()
|
|
||||||
.ok_or("All templates should have a stem.")?
|
|
||||||
.to_str()
|
|
||||||
.ok_or("All template filenames should be valid utf-8.")?;
|
|
||||||
let contents = std::str::from_utf8(entry.contents())?;
|
|
||||||
Ok((name, contents))
|
|
||||||
}
|
|
@ -2,16 +2,22 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
use crate::blog_post::BlogPost;
|
use crate::blog_post::BlogPost;
|
||||||
use crate::cli::parameters::BuildArgs;
|
use crate::cli::parameters::BuildArgs;
|
||||||
use crate::command::build::render::SiteRenderer;
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::error::CustomError;
|
use crate::error::CustomError;
|
||||||
|
|
||||||
pub(crate) async fn build_site(args: BuildArgs) -> Result<(), CustomError> {
|
pub(crate) async fn build_site(args: BuildArgs) -> Result<(), CustomError> {
|
||||||
let config = Config::load_from_file(args.config).await?;
|
let config = Config::load_from_file(args.config).await?;
|
||||||
let blog_posts = load_blog_posts(&config).await?;
|
let root_directory = config.get_root_directory().to_owned();
|
||||||
let renderer = SiteRenderer::new(get_output_directory(&config).await?, blog_posts);
|
let output_directory = get_output_directory(&config).await?;
|
||||||
renderer.render_blog_posts().await?;
|
let post_directories = get_post_directories(&config).await?;
|
||||||
|
let load_jobs = post_directories
|
||||||
|
.into_iter()
|
||||||
|
.map(|path| tokio::spawn(BlogPost::load_blog_post(root_directory.clone(), path)));
|
||||||
|
let mut blog_posts = Vec::new();
|
||||||
|
for job in load_jobs {
|
||||||
|
blog_posts.push(job.await??);
|
||||||
|
}
|
||||||
|
println!("{:?}", blog_posts);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,16 +51,3 @@ async fn get_post_directories(config: &Config) -> Result<Vec<PathBuf>, CustomErr
|
|||||||
}
|
}
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn load_blog_posts(config: &Config) -> Result<Vec<BlogPost>, CustomError> {
|
|
||||||
let root_directory = config.get_root_directory().to_owned();
|
|
||||||
let post_directories = get_post_directories(&config).await?;
|
|
||||||
let load_jobs = post_directories
|
|
||||||
.into_iter()
|
|
||||||
.map(|path| tokio::spawn(BlogPost::load_blog_post(root_directory.clone(), path)));
|
|
||||||
let mut blog_posts = Vec::new();
|
|
||||||
for job in load_jobs {
|
|
||||||
blog_posts.push(job.await??);
|
|
||||||
}
|
|
||||||
Ok(blog_posts)
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
use std::str::Utf8Error;
|
|
||||||
use std::string::FromUtf8Error;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) enum CustomError {
|
pub(crate) enum CustomError {
|
||||||
Static(&'static str),
|
Static(&'static str),
|
||||||
@ -9,11 +6,6 @@ pub(crate) enum CustomError {
|
|||||||
TomlDeserialize(toml::de::Error),
|
TomlDeserialize(toml::de::Error),
|
||||||
WalkDir(walkdir::Error),
|
WalkDir(walkdir::Error),
|
||||||
Tokio(tokio::task::JoinError),
|
Tokio(tokio::task::JoinError),
|
||||||
Serde(serde_json::Error),
|
|
||||||
Utf8(Utf8Error),
|
|
||||||
FromUtf8(FromUtf8Error),
|
|
||||||
DusterCompile(duster::renderer::CompileError),
|
|
||||||
DusterRender(duster::renderer::RenderError),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<std::io::Error> for CustomError {
|
impl From<std::io::Error> for CustomError {
|
||||||
@ -51,33 +43,3 @@ impl From<tokio::task::JoinError> for CustomError {
|
|||||||
CustomError::Tokio(value)
|
CustomError::Tokio(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<serde_json::Error> for CustomError {
|
|
||||||
fn from(value: serde_json::Error) -> Self {
|
|
||||||
CustomError::Serde(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Utf8Error> for CustomError {
|
|
||||||
fn from(value: Utf8Error) -> Self {
|
|
||||||
CustomError::Utf8(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<FromUtf8Error> for CustomError {
|
|
||||||
fn from(value: FromUtf8Error) -> Self {
|
|
||||||
CustomError::FromUtf8(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<duster::renderer::CompileError> for CustomError {
|
|
||||||
fn from(value: duster::renderer::CompileError) -> Self {
|
|
||||||
CustomError::DusterCompile(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<duster::renderer::RenderError> for CustomError {
|
|
||||||
fn from(value: duster::renderer::RenderError) -> Self {
|
|
||||||
CustomError::DusterRender(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -12,7 +12,6 @@ mod cli;
|
|||||||
mod command;
|
mod command;
|
||||||
mod config;
|
mod config;
|
||||||
mod error;
|
mod error;
|
||||||
mod render;
|
|
||||||
|
|
||||||
fn main() -> Result<ExitCode, CustomError> {
|
fn main() -> Result<ExitCode, CustomError> {
|
||||||
let rt = tokio::runtime::Runtime::new()?;
|
let rt = tokio::runtime::Runtime::new()?;
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use crate::error::CustomError;
|
|
||||||
|
|
||||||
use super::renderer_integration::RendererIntegration;
|
|
||||||
use serde::Serialize;
|
|
||||||
|
|
||||||
pub(crate) struct DusterRenderer<'a> {
|
|
||||||
templates: HashMap<&'a str, duster::parser::Template<'a>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> DusterRenderer<'a> {
|
|
||||||
pub(crate) fn new() -> DusterRenderer<'a> {
|
|
||||||
DusterRenderer {
|
|
||||||
templates: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> RendererIntegration<'a> for DusterRenderer<'a> {
|
|
||||||
fn load_template(&mut self, name: &'a str, contents: &'a str) -> Result<(), CustomError> {
|
|
||||||
let compiled_template = duster::renderer::compile_template(contents.as_ref())?;
|
|
||||||
self.templates.insert(name, compiled_template);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render<C>(&self, context: C) -> Result<String, CustomError>
|
|
||||||
where
|
|
||||||
C: Serialize,
|
|
||||||
{
|
|
||||||
let mut dust_renderer = duster::renderer::DustRenderer::new();
|
|
||||||
for (name, compiled_template) in self.templates.iter() {
|
|
||||||
dust_renderer.load_source(compiled_template, (*name).to_owned());
|
|
||||||
}
|
|
||||||
// TODO: This is horribly inefficient. I am converting from a serialize type to json and back again so I can use the existing implementation of IntoContextElement. Honestly, I probably need to rework a lot of duster now that I've improved in rust over the years.
|
|
||||||
let json_context = serde_json::to_string(&context)?;
|
|
||||||
println!("Context: {}", json_context);
|
|
||||||
let parsed_context: serde_json::Value = serde_json::from_str(json_context.as_str())?;
|
|
||||||
let rendered_output = dust_renderer.render("main", Some(&parsed_context))?;
|
|
||||||
Ok(rendered_output)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
mod duster_renderer;
|
|
||||||
mod renderer_integration;
|
|
||||||
pub(crate) use duster_renderer::DusterRenderer;
|
|
||||||
pub(crate) use renderer_integration::RendererIntegration;
|
|
@ -1,11 +0,0 @@
|
|||||||
use serde::Serialize;
|
|
||||||
|
|
||||||
use crate::error::CustomError;
|
|
||||||
|
|
||||||
pub(crate) trait RendererIntegration<'a> {
|
|
||||||
fn load_template(&mut self, name: &'a str, contents: &'a str) -> Result<(), CustomError>;
|
|
||||||
|
|
||||||
fn render<C>(&self, context: C) -> Result<String, CustomError>
|
|
||||||
where
|
|
||||||
C: Serialize;
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user