{{title}}
published {{timestamp}} - + {{{content}}} - +tags
{{#each tags}}
diff --git a/site/templates/images.hbs b/site/templates/images.hbs
index fd421c4..062121a 100644
--- a/site/templates/images.hbs
+++ b/site/templates/images.hbs
@@ -16,7 +16,7 @@
{{#each resources}}
-
+
{{title}}
{{/each}}
diff --git a/src/blog.rs b/src/blog.rs
deleted file mode 100644
index 34ea2ab..0000000
--- a/src/blog.rs
+++ /dev/null
@@ -1,98 +0,0 @@
-use serde::{Deserialize, Serialize};
-
-use crate::{
- resource::{EmbedMetadata, ResourceBuilderConfig, ResourceMetadata, ResourceMethods},
- Site, SiteConfig,
-};
-
-pub const BLOG_PATH: &str = "blog";
-
-/// Gets the blog's resource configuration.
-pub fn get_blog_resource_config(site: &Site) -> ResourceBuilderConfig {
- ResourceBuilderConfig {
- source_path: BLOG_PATH.to_string(),
- output_path_short: BLOG_PATH.to_string(),
- output_path_long: BLOG_PATH.to_string(),
- resource_template: "blog-post".to_string(),
- resource_list_template: "blog-list".to_string(),
- rss_template: "rss/blog-post".to_string(),
- rss_title: "zyl's blog".to_string(),
- rss_description: "Feed of recent blog posts on zyl's website.".to_string(),
- list_title: "blog".to_string(),
- tag_list_title: "blog tags".to_string(),
- resource_name_plural: "blog posts".to_string(),
- resources_per_page: site.config.blog_posts_per_page,
- }
-}
-
-/// Metadata for a blog post.
-#[derive(Debug, Serialize, Deserialize)]
-pub struct BlogPostMetadata {
- /// A short description about the post.
- pub desc: String,
- /// Path to the post's header image.
- pub header_image_file: String,
- /// Alt text for the post's header image.
- pub header_image_alt: String,
- /// Optional custom object fit value.
- pub image_fit: Option,
- /// Optional custom object position value.
- pub image_center: Option,
-}
-
-impl BlogPostMetadata {
- /// Helper to get the CDN URL to the blog post's header image.
- fn get_header_image(&self, site_config: &SiteConfig) -> eyre::Result {
- Ok(site_config.cdn_url(&self.header_image_file)?.to_string())
- }
-}
-
-/// Template data for a blog post.
-#[derive(Debug, Serialize)]
-pub struct BlogPostTemplateData {
- /// CDN path to the post's header image.
- pub header_image: String,
- /// Custom object fit value.
- pub object_fit: String,
- /// Custom object position value.
- pub object_position: String,
-}
-
-impl ResourceMethods for ResourceMetadata {
- fn get_short_desc(&self) -> String {
- self.inner.desc.clone()
- }
-
- fn get_extra_resource_template_data(
- &self,
- site_config: &SiteConfig,
- ) -> eyre::Result {
- // TODO: render markdown
- Ok(BlogPostTemplateData {
- header_image: self.inner.get_header_image(site_config)?,
- object_fit: self
- .inner
- .image_fit
- .clone()
- .unwrap_or_else(|| "cover".to_string()),
- object_position: self
- .inner
- .image_center
- .clone()
- .unwrap_or_else(|| "50% 50%".to_string()),
- })
- }
-
- fn get_head_data(&self, site_config: &SiteConfig) -> eyre::Result {
- Ok(EmbedMetadata {
- title: self.title.clone(),
- site_name: site_config.title.clone(),
- description: Some(self.inner.desc.clone()),
- image: Some(self.inner.get_header_image(site_config)?),
- url: None,
- theme_color: EmbedMetadata::default_theme_color(),
- large_image: true,
- }
- .build())
- }
-}
diff --git a/src/builder.rs b/src/builder.rs
index 8d29625..bede56e 100644
--- a/src/builder.rs
+++ b/src/builder.rs
@@ -1,6 +1,6 @@
//! Module containing the site builder.
-use std::path::PathBuf;
+use std::{collections::HashMap, path::PathBuf};
use eyre::{eyre, Context, OptionExt};
use gray_matter::{engine::YAML, Matter};
@@ -43,12 +43,8 @@ pub struct SiteBuilder<'a> {
/// Whether the site is going to be served locally with the dev server.
serving: bool,
- /// Resource builder for the site's images section.
- pub images_builder:
- ResourceBuilder,
- /// Resource builder for the site's blog section.
- pub blog_builder:
- ResourceBuilder,
+ /// The resource builders available to the builder.
+ pub resource_builders: HashMap,
}
impl<'a> SiteBuilder<'a> {
@@ -65,8 +61,7 @@ impl<'a> SiteBuilder<'a> {
Self {
matter: Matter::new(),
reg: Handlebars::new(),
- images_builder: ResourceBuilder::new(crate::images::get_images_resource_config(&site)),
- blog_builder: ResourceBuilder::new(crate::blog::get_blog_resource_config(&site)),
+ resource_builders: HashMap::new(),
site,
build_path,
serving,
@@ -112,34 +107,35 @@ impl<'a> SiteBuilder<'a> {
}
}
- let images_path = self.build_path.join(crate::images::IMAGES_OUT_PATH);
- if !images_path.exists() {
- std::fs::create_dir(images_path).wrap_err("Failed to create images path")?;
- }
-
- self.reload_images_builder()?;
- self.reload_blog_builder()?;
+ self.reload()?;
Ok(self)
}
- /// Reloads the images builder's metadata.
- pub fn reload_images_builder(&mut self) -> eyre::Result<()> {
- let mut images_builder = std::mem::take(&mut self.images_builder);
- images_builder
- .load_all(self)
- .wrap_err("Failed to load images metadata")?;
- self.images_builder = images_builder;
+ /// Performs actions that need to be done when the config changes while serving.
+ pub fn reload(&mut self) -> eyre::Result<()> {
+ self.resource_builders.clear();
+ for (prefix, config) in &self.site.config.resources {
+ self.resource_builders
+ .insert(prefix.to_owned(), ResourceBuilder::new(config.clone()));
+ }
+
+ for prefix in self.resource_builders.keys().cloned().collect::>() {
+ self.reload_resource_builder(&prefix)?;
+ }
+
Ok(())
}
- /// Reloads the blog builder's metadata.
- pub fn reload_blog_builder(&mut self) -> eyre::Result<()> {
- let mut blog_builder = std::mem::take(&mut self.blog_builder);
- blog_builder
- .load_all(self)
- .wrap_err("Failed to load blog metadata")?;
- self.blog_builder = blog_builder;
+ /// Reloads a particular resource builder's metadata.
+ pub fn reload_resource_builder(&mut self, builder: &str) -> eyre::Result<()> {
+ let mut resource_builder = self
+ .resource_builders
+ .remove(builder)
+ .ok_or_else(|| eyre!("missing resource builder: {builder}"))?;
+ resource_builder.load_all(self)?;
+ self.resource_builders
+ .insert(builder.to_string(), resource_builder);
Ok(())
}
@@ -384,13 +380,19 @@ impl<'a> SiteBuilder<'a> {
Ok(())
}
- /// Builds the site's various image pages.
- pub fn build_images(&self) -> eyre::Result<()> {
- self.images_builder.build_all(self)
+ /// Builds all resource types.
+ pub fn build_all_resources(&self) -> eyre::Result<()> {
+ for builder in self.resource_builders.values() {
+ builder.build_all(self)?;
+ }
+ Ok(())
}
- /// Builds the site's blog.
- pub fn build_blog(&self) -> eyre::Result<()> {
- self.blog_builder.build_all(self)
+ /// Builds a resource type from the site.
+ pub fn build_resources(&self, resource: &str) -> eyre::Result<()> {
+ self.resource_builders
+ .get(resource)
+ .ok_or_else(|| eyre!("missing resource: {resource}"))?
+ .build_all(self)
}
}
diff --git a/src/extras.rs b/src/extras.rs
index 9525585..54ceb5d 100644
--- a/src/extras.rs
+++ b/src/extras.rs
@@ -1,7 +1,7 @@
use lol_html::{element, RewriteStrSettings};
use serde::Serialize;
-use crate::{blog::BlogPostMetadata, builder::SiteBuilder, resource::ResourceTemplateData};
+use crate::{builder::SiteBuilder, resource::ResourceTemplateData};
#[derive(Debug)]
pub enum Extra {
@@ -31,6 +31,7 @@ pub fn get_extra(extra: &str) -> Option {
}
}
+/// Extra to append a tempalte to the page.
fn append_to(page: &str, content: &str, selector: &str) -> eyre::Result {
Ok(lol_html::rewrite_str(
page,
@@ -48,22 +49,22 @@ fn append_to(page: &str, content: &str, selector: &str) -> eyre::Result
fn index(page: String, builder: &SiteBuilder) -> eyre::Result {
#[derive(Debug, Serialize)]
struct SidebarTemplateData<'r> {
- // resources: Vec<&'r ResourceMetadata>,
- resources: Vec>,
+ resources: Vec>,
}
let sidebar = builder.reg.render(
"extras/index-injection",
&SidebarTemplateData {
resources: builder
- .blog_builder
+ .resource_builders
+ .get("blog")
+ .expect("missing blog builder")
.loaded_metadata
.iter()
.take(3)
.map(|(id, v)| ResourceTemplateData {
resource: v,
id: id.clone(),
- extra: (),
timestamp: v.timestamp,
})
.collect(),
diff --git a/src/images.rs b/src/images.rs
deleted file mode 100644
index 720c624..0000000
--- a/src/images.rs
+++ /dev/null
@@ -1,80 +0,0 @@
-use serde::{Deserialize, Serialize};
-
-use crate::{
- resource::{EmbedMetadata, ResourceBuilderConfig, ResourceMetadata, ResourceMethods},
- Site, SiteConfig,
-};
-
-pub(crate) const IMAGES_PATH: &str = "images";
-pub(crate) const IMAGES_OUT_PATH: &str = "i";
-
-/// Gets the resource configuration for images.
-pub fn get_images_resource_config(site: &Site) -> ResourceBuilderConfig {
- ResourceBuilderConfig {
- source_path: IMAGES_PATH.to_string(),
- output_path_short: IMAGES_OUT_PATH.to_string(),
- output_path_long: "images".to_string(),
- resource_template: "image".to_string(),
- resource_list_template: "images".to_string(),
- rss_template: "rss/image".to_string(),
- rss_title: "zyl's images".to_string(),
- rss_description: "feed of newly uploaded images from zyl's website.".to_string(),
- list_title: "images".to_string(),
- tag_list_title: "image tags".to_string(),
- resource_name_plural: "images".to_string(),
- resources_per_page: site.config.images_per_page,
- }
-}
-
-/// Definition for a remote image.
-#[derive(Debug, Deserialize, Serialize)]
-pub struct ImageMetadata {
- /// The image's alt text.
- pub alt: String,
- /// The image's extra description, if any.
- pub desc: Option,
- /// The image's file path.
- pub file: String,
-}
-
-impl ImageMetadata {
- fn get_image_url(&self, site_config: &SiteConfig) -> eyre::Result {
- Ok(site_config.cdn_url(&self.file)?.to_string())
- }
-}
-
-/// Template data for a specific image.
-#[derive(Debug, Serialize)]
-pub struct ImageTemplateData {
- /// Direct URL to the image's CDN location.
- /// TODO: link to smaller versions on list pages
- src: String,
-}
-
-impl ResourceMethods for ResourceMetadata {
- fn get_short_desc(&self) -> String {
- self.inner.desc.clone().unwrap_or_default()
- }
-
- fn get_extra_resource_template_data(
- &self,
- site_config: &SiteConfig,
- ) -> eyre::Result {
- Ok(ImageTemplateData {
- src: self.inner.get_image_url(site_config)?,
- })
- }
-
- fn get_head_data(&self, site_config: &SiteConfig) -> eyre::Result {
- Ok(EmbedMetadata {
- title: self.title.clone(),
- site_name: site_config.title.clone(),
- description: self.inner.desc.clone(),
- image: Some(self.inner.get_image_url(site_config)?),
- url: None,
- theme_color: EmbedMetadata::default_theme_color(),
- large_image: true,
- }
- .build())
- }
-}
diff --git a/src/lib.rs b/src/lib.rs
index 531d244..cb72b23 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,7 +1,5 @@
-mod blog;
mod builder;
mod extras;
-mod images;
mod link_list;
mod resource;
#[cfg(feature = "serve")]
@@ -15,7 +13,7 @@ use std::{
use eyre::Context;
use rayon::prelude::*;
-use resource::EmbedMetadata;
+use resource::{EmbedMetadata, ResourceBuilderConfig};
use serde::Deserialize;
use url::Url;
use util::get_name;
@@ -41,20 +39,16 @@ pub struct SiteConfig {
pub build: Option,
/// A list of Sass stylesheets that will be built.
pub sass_styles: Vec,
- /// The number of images to display on a single page of an image list.
- pub images_per_page: usize,
- /// The number of blog posts to display on a single page of a post list.
- pub blog_posts_per_page: usize,
/// URL to the CDN used for the site's images.
pub cdn_url: Url,
- /// Prefix applied to all files uploaded to the site's S3 space.
- pub s3_prefix: String,
+ /// List of resources the site should build.
+ pub resources: HashMap,
}
impl SiteConfig {
/// Gets a CDN url from the given file name.
pub fn cdn_url(&self, file: &str) -> eyre::Result {
- Ok(self.cdn_url.join(&self.s3_prefix)?.join(file)?)
+ Ok(self.cdn_url.join(file)?)
}
}
@@ -155,8 +149,12 @@ impl Site {
builder.site.build_all_pages(&builder)?;
builder.build_sass()?;
- builder.build_images()?;
- builder.build_blog()?;
+
+ for (_source_path, config) in builder.site.config.resources.iter() {
+ let mut res_builder = resource::ResourceBuilder::new(config.clone());
+ res_builder.load_all(&builder)?;
+ res_builder.build_all(&builder)?;
+ }
Ok(())
}
diff --git a/src/resource.rs b/src/resource.rs
index eb87085..f80839f 100644
--- a/src/resource.rs
+++ b/src/resource.rs
@@ -1,6 +1,5 @@
use std::{
collections::BTreeMap,
- marker::PhantomData,
path::{Path, PathBuf},
};
@@ -8,14 +7,17 @@ use eyre::Context;
use itertools::Itertools;
use pulldown_cmark::{Options, Parser};
use rss::{validation::Validate, ChannelBuilder, ItemBuilder};
-use serde::{de::DeserializeOwned, Deserialize, Serialize, Serializer};
+use serde::{Deserialize, Serialize, Serializer};
use time::{format_description::well_known::Rfc2822, OffsetDateTime};
-use crate::{builder::SiteBuilder, link_list::Link, PageMetadata, SiteConfig};
+use crate::{builder::SiteBuilder, link_list::Link, PageMetadata};
+
+/// Source base path for resources.
+pub const RESOURCES_PATH: &str = "resources";
/// Metadata for resources.
#[derive(Debug, Deserialize, Serialize)]
-pub struct ResourceMetadata {
+pub struct ResourceMetadata {
/// The resource's title.
pub title: String,
/// The resource's timestamp.
@@ -23,9 +25,13 @@ pub struct ResourceMetadata {
pub timestamp: OffsetDateTime,
/// The resource's tags.
pub tags: Vec,
+ /// Special field that gets transformed to the full CDN URL for the given path.
+ pub cdn_file: Option,
+ /// The resource's description, if any.
+ pub desc: Option,
/// Extra resource data not included.
#[serde(flatten)]
- pub inner: T,
+ pub inner: serde_yml::Value,
/// Whether the resource is a draft. Drafts can be committed without being published to the live site.
#[serde(default)]
pub draft: bool,
@@ -35,21 +41,18 @@ pub struct ResourceMetadata {
}
#[derive(Debug, Serialize)]
-pub struct ResourceTemplateData<'r, M, E> {
+pub struct ResourceTemplateData<'r> {
/// The resource's metadata.
#[serde(flatten)]
- pub resource: &'r ResourceMetadata,
+ pub resource: &'r ResourceMetadata,
/// The resource's ID.
pub id: String,
- /// Extra data to be passed to the template.
- #[serde(flatten)]
- pub extra: E,
/// The resource's timestamp. Duplicated to change serialization method.
- #[serde(serialize_with = "ResourceTemplateData::::timestamp_formatter")]
+ #[serde(serialize_with = "ResourceTemplateData::timestamp_formatter")]
pub timestamp: OffsetDateTime,
}
-impl<'r, M, E> ResourceTemplateData<'r, M, E> {
+impl<'r> ResourceTemplateData<'r> {
fn timestamp_formatter(timestamp: &OffsetDateTime, serializer: S) -> Result
where
S: Serializer,
@@ -64,20 +67,6 @@ impl<'r, M, E> ResourceTemplateData<'r, M, E> {
}
}
-/// Trait for getting extra template data from resource metadata.
-pub trait ResourceMethods
-where
- E: Serialize,
-{
- fn get_short_desc(&self) -> String;
-
- fn get_extra_resource_template_data(&self, site_config: &SiteConfig) -> eyre::Result;
-
- fn get_head_data(&self, _site_config: &SiteConfig) -> eyre::Result {
- Ok(String::new())
- }
-}
-
/// struct for adding custom meta content embeds
#[derive(Debug, Deserialize)]
pub struct EmbedMetadata {
@@ -130,8 +119,8 @@ impl EmbedMetadata {
}
#[derive(Debug, Serialize)]
-struct ResourceListTemplateData<'r, M, E> {
- resources: Vec<&'r ResourceTemplateData<'r, M, E>>,
+struct ResourceListTemplateData<'r> {
+ resources: Vec<&'r ResourceTemplateData<'r>>,
tag: Option<&'r str>,
page: usize,
page_max: usize,
@@ -145,7 +134,7 @@ struct ExtraResourceRenderData {
}
/// Config for the resource builder.
-#[derive(Debug, Default)]
+#[derive(Debug, Clone, Default, Deserialize)]
pub struct ResourceBuilderConfig {
/// Path to where the resources should be loaded from.
pub source_path: String,
@@ -174,27 +163,20 @@ pub struct ResourceBuilderConfig {
}
/// Helper to genericize resource building.
-#[derive(Debug)]
-pub struct ResourceBuilder {
+#[derive(Debug, Default)]
+pub struct ResourceBuilder {
/// The builder's config.
pub config: ResourceBuilderConfig,
/// The currently loaded resource metadata.
- pub loaded_metadata: Vec<(String, ResourceMetadata)>,
- _extra: PhantomData,
+ pub loaded_metadata: Vec<(String, ResourceMetadata)>,
}
-impl ResourceBuilder
-where
- M: Serialize + DeserializeOwned,
- E: Serialize,
- ResourceMetadata: ResourceMethods,
-{
+impl ResourceBuilder {
/// Creates a new resource builder.
pub fn new(config: ResourceBuilderConfig) -> Self {
Self {
config,
loaded_metadata: Default::default(),
- _extra: Default::default(),
}
}
@@ -208,13 +190,13 @@ where
}
/// Loads resource metadata from the given path.
- fn load(builder: &SiteBuilder, path: &Path) -> eyre::Result<(String, ResourceMetadata)> {
+ fn load(builder: &SiteBuilder, path: &Path) -> eyre::Result<(String, ResourceMetadata)> {
let id = Self::get_id(path);
let input = std::fs::read_to_string(path)?;
let mut page = builder
.matter
- .parse_with_struct::>(&input)
+ .parse_with_struct::(&input)
.ok_or_else(|| eyre::anyhow!("Failed to parse resource front matter"))?;
let parser = Parser::new_ext(&page.content, Options::all());
@@ -222,6 +204,9 @@ where
pulldown_cmark::html::push_html(&mut html, parser);
page.data.content = html;
+ if let Some(cdn_file) = page.data.cdn_file {
+ page.data.cdn_file = Some(builder.site.config.cdn_url(&cdn_file)?.to_string());
+ }
Ok((id, page.data))
}
@@ -233,6 +218,7 @@ where
for e in builder
.site
.site_path
+ .join(RESOURCES_PATH)
.join(&self.config.source_path)
.read_dir()?
{
@@ -262,13 +248,12 @@ where
&self,
builder: &SiteBuilder,
id: String,
- resource: &ResourceMetadata,
+ resource: &ResourceMetadata,
) -> eyre::Result<()> {
let out_path = self.build_path(&builder.build_path, &id);
let out = {
let data = ResourceTemplateData {
resource,
- extra: resource.get_extra_resource_template_data(&builder.site.config)?,
id,
timestamp: resource.timestamp,
};
@@ -282,7 +267,20 @@ where
},
&out,
ExtraResourceRenderData {
- head: resource.get_head_data(&builder.site.config)?,
+ head: EmbedMetadata {
+ title: resource.title.clone(),
+ site_name: builder.site.config.title.clone(),
+ description: resource.desc.clone(),
+ image: if let Some(cdn_file) = &resource.cdn_file {
+ Some(builder.site.config.cdn_url(cdn_file)?.to_string())
+ } else {
+ None
+ },
+ url: None,
+ theme_color: EmbedMetadata::default_theme_color(),
+ large_image: true,
+ }
+ .build(),
},
)?;
std::fs::write(out_path, out)?;
@@ -309,28 +307,22 @@ where
let mut data = Vec::with_capacity(lmd.len());
for (id, resource) in lmd.iter() {
- let extra = resource.get_extra_resource_template_data(&builder.site.config)?;
data.push(ResourceTemplateData {
resource,
- extra,
id: id.clone(),
timestamp: resource.timestamp,
});
}
- fn build_list(
+ fn build_list(
builder: &SiteBuilder,
config: &ResourceBuilderConfig,
- list: Vec<&ResourceTemplateData>,
+ list: Vec<&ResourceTemplateData>,
title: &str,
tag: Option<&str>,
out_path: &Path,
items_per_page: usize,
- ) -> eyre::Result<()>
- where
- M: Serialize,
- E: Serialize,
- {
+ ) -> eyre::Result<()> {
if !out_path.exists() {
std::fs::create_dir_all(out_path)?;
}
@@ -381,7 +373,7 @@ where
)?;
// Build resource lists by tag
- let mut tags: BTreeMap>> = BTreeMap::new();
+ let mut tags: BTreeMap> = BTreeMap::new();
for resource in &data {
for tag in resource.resource.tags.iter().cloned() {
tags.entry(tag).or_default().push(resource);
@@ -442,7 +434,7 @@ where
))?
.to_string(),
))
- .description(Some(resource.resource.get_short_desc()))
+ .description(resource.resource.desc.clone())
.pub_date(Some(resource.timestamp.format(&Rfc2822)?))
.content(Some(
builder.reg.render(&self.config.rss_template, &resource)?,
@@ -472,13 +464,3 @@ where
Ok(())
}
}
-
-impl Default for ResourceBuilder {
- fn default() -> Self {
- Self {
- config: Default::default(),
- loaded_metadata: Default::default(),
- _extra: Default::default(),
- }
- }
-}
diff --git a/src/serving.rs b/src/serving.rs
index ef44df6..c19796d 100644
--- a/src/serving.rs
+++ b/src/serving.rs
@@ -18,7 +18,10 @@ use warp::{
Filter,
};
-use crate::{util::get_name, Site, SiteBuilder, PAGES_PATH, ROOT_PATH, SASS_PATH, TEMPLATES_PATH};
+use crate::{
+ resource::RESOURCES_PATH, util::get_name, Site, SiteBuilder, PAGES_PATH, ROOT_PATH, SASS_PATH,
+ TEMPLATES_PATH,
+};
fn with_build_path(
build_path: PathBuf,
@@ -31,6 +34,30 @@ fn rel(path: &Path, prefix: &Path) -> Result eyre::Result<()> {
+ let paths: Vec<_> = builder
+ .resource_builders
+ .values()
+ .map(|b| {
+ (
+ b.config.source_path.clone(),
+ path.strip_prefix(&b.config.source_path),
+ )
+ })
+ .filter_map(|(p, v)| v.ok().map(|v| (p, v)))
+ .collect();
+ if paths.len() > 1 {
+ todo!("handle more than one possible match");
+ }
+ if let Some((prefix, _path)) = paths.first() {
+ // HACK: this could get very inefficient with a larger number of resources. should definitely optimize
+ builder.reload_resource_builder(prefix)?;
+ builder.build_resources(prefix)?;
+ }
+ Ok(())
+}
+
/// Creates or updates a resource.
fn create(
builder: &mut SiteBuilder,
@@ -57,12 +84,12 @@ fn create(
builder.refresh_template(&template_name_str, path)?;
if build {
builder.site.build_all_pages(builder)?;
- builder.build_images()?;
- builder.build_blog()?;
+ builder.build_all_resources()?;
}
} else if relative_path.display().to_string() == "config.yaml" {
let new_config = serde_yml::from_str(&std::fs::read_to_string(path)?)?;
builder.site.config = new_config;
+ builder.reload()?;
builder.site.build_all_pages(builder)?;
} else if let Ok(_sass_path) = relative_path.strip_prefix(SASS_PATH) {
if build {
@@ -70,14 +97,8 @@ fn create(
}
} else if let Ok(root_path) = relative_path.strip_prefix(ROOT_PATH) {
std::fs::copy(path, builder.build_path.join(root_path))?;
- } else if let Ok(_image_path) = relative_path.strip_prefix(crate::images::IMAGES_PATH) {
- // HACK: this could get very inefficient with a larger number of images. should definitely optimize
- builder.reload_images_builder()?;
- builder.build_images()?;
- } else if let Ok(_blog_path) = relative_path.strip_prefix(crate::blog::BLOG_PATH) {
- // HACK: same as above
- builder.reload_blog_builder()?;
- builder.build_blog()?;
+ } else if let Ok(resources_path) = relative_path.strip_prefix(RESOURCES_PATH) {
+ build_resources(builder, resources_path)?;
}
Ok(())
@@ -106,14 +127,8 @@ fn remove(builder: &mut SiteBuilder, path: &Path, relative_path: &Path) -> eyre:
builder.build_sass().wrap_err("Failed to rebuild Sass")?;
} else if let Ok(root_path) = relative_path.strip_prefix(ROOT_PATH) {
std::fs::remove_file(builder.build_path.join(root_path))?;
- } else if let Ok(_image_path) = relative_path.strip_prefix(crate::images::IMAGES_PATH) {
- // HACK: same as in `create`
- builder.reload_images_builder()?;
- builder.build_images()?;
- } else if let Ok(_blog_path) = relative_path.strip_prefix(crate::blog::BLOG_PATH) {
- // HACK: same as above
- builder.reload_blog_builder()?;
- builder.build_blog()?;
+ } else if let Ok(resources_path) = relative_path.strip_prefix(RESOURCES_PATH) {
+ build_resources(builder, resources_path)?;
}
Ok(())
@@ -141,9 +156,8 @@ impl Site {
}
builder.build_sass().wrap_err("Failed to build Sass")?;
builder
- .build_images()
- .wrap_err("Failed to build image pages")?;
- builder.build_blog().wrap_err("Failed to build blog")?;
+ .build_all_resources()
+ .wrap_err("Failed to build resources")?;
// Map of websocket connections
let peers: Arc>> =