From efa0d033157a0a5ce01bda6daa899b63ec01f19e Mon Sep 17 00:00:00 2001 From: Zoey Date: Fri, 9 Jun 2023 21:55:04 -0700 Subject: [PATCH] many many changes --- site/blog/estradiol-delivery-methods.md | 29 +++++++ site/blog/so-now-i-have-a-blog.md | 23 +++++ site/config.yaml | 1 + site/images/{amogus.yml => amogus.md} | 4 + site/images/{boxtop.yml => boxtop.md} | 2 + site/images/{cat.yml => cat.md} | 2 + site/images/{cat2.yml => cat2.md} | 2 + site/images/makeup-first-lol.md | 13 +++ site/images/makeup-first-lol.yml | 9 -- .../{trans-comfy.yml => trans-comfy.md} | 5 +- site/sass/index.scss | 74 +++++++++++++++- site/templates/base.hbs | 1 + site/templates/blog-list.hbs | 23 +++++ site/templates/blog-post.hbs | 22 +++++ site/templates/image.hbs | 4 +- site/templates/rss/blog-post.hbs | 1 + src/blog.rs | 86 +++++++++++++++++++ src/builder.rs | 7 +- src/images.rs | 12 +-- src/lib.rs | 11 +++ src/resource.rs | 67 +++++++++++---- src/serving.rs | 7 ++ 22 files changed, 360 insertions(+), 45 deletions(-) create mode 100644 site/blog/estradiol-delivery-methods.md create mode 100644 site/blog/so-now-i-have-a-blog.md rename site/images/{amogus.yml => amogus.md} (93%) rename site/images/{boxtop.yml => boxtop.md} (96%) rename site/images/{cat.yml => cat.md} (94%) rename site/images/{cat2.yml => cat2.md} (95%) create mode 100644 site/images/makeup-first-lol.md delete mode 100644 site/images/makeup-first-lol.yml rename site/images/{trans-comfy.yml => trans-comfy.md} (78%) create mode 100644 site/templates/blog-list.hbs create mode 100644 site/templates/blog-post.hbs create mode 100644 site/templates/rss/blog-post.hbs create mode 100644 src/blog.rs diff --git a/site/blog/estradiol-delivery-methods.md b/site/blog/estradiol-delivery-methods.md new file mode 100644 index 0000000..a79c399 --- /dev/null +++ b/site/blog/estradiol-delivery-methods.md @@ -0,0 +1,29 @@ +--- +title: Estradiol Delivery Methods +timestamp: 2023-05-28T16:00:00.00Z +tags: [trans, hrt] +desc: A comparison of the various ways I've taken estradiol since starting HRT. +header_image_file: cat.jpeg # TODO: placeholder image +header_image_alt: placeholder +draft: true +--- + +I thought it might be useful to write out my experiences with the four methods of taking estradiol I've tried. + +- patches + - wouldn't consistently stay on me + - could feel the effects wearing off 3-4 days after application + - insurance sucks +- sublingual pills + - worked alright, except: + - could feel them wearing off ~5-6 hours after taking a dose + - apparently hard to measure levels? had one test at ~200 mg/ml and another at 400+ mg/ml at same dosage +- swallowed pills + - could not get ideal levels with a reasonable number of pills, but: + - couldn't actually feel them wearing off even at 12 hours between doses +- injections + - holy shit these are great + - was kinda nervous the first few times I injected myself, but I got used to it + - cannot feel it wearing off between doses + - levels are actually good?? + - insurance sucks pt. 2 diff --git a/site/blog/so-now-i-have-a-blog.md b/site/blog/so-now-i-have-a-blog.md new file mode 100644 index 0000000..190a775 --- /dev/null +++ b/site/blog/so-now-i-have-a-blog.md @@ -0,0 +1,23 @@ +--- +title: so now i have a blog +timestamp: 2023-06-09T16:00:00.00Z +tags: [meta, technical] +desc: I added a blog to my site. +header_image_file: cat.jpeg # TODO: placeholder image +header_image_alt: placeholder +draft: true +--- + +So now I have a blog on my site. I don't really have any plans to post here regularly, but idk maybe that'll change in the future. + +That's pretty much it as far as the non-technical side of things goes. + +## The Technical Side of Things + +I haven't really written anything about how my site works before, so this is also going to contain some general information about the site as a whole. + +`zyl.gay` is a static website built with a custom static site builder I built for it. It started by taking Markdown pages and rendering them on top of the appropriate template. + +When I added the [images section](/images/) to the site I added the first abstraction on top of this: YAML files with the relevant metadata for the image (including a short but unstyled description) which then get rendered not only into pages for the individual pages, but also a paginated display for all the images _and_ a method to view images by tag. + +To get blogs working I modified the image page code to be generic over provided resource types, so really the images and the blog posts are rendered the same way, just with different configurations. diff --git a/site/config.yaml b/site/config.yaml index 5f6ce0a..9bdc53f 100644 --- a/site/config.yaml +++ b/site/config.yaml @@ -3,5 +3,6 @@ title: Zyllian description: "Zoey's website." sass_styles: [index.scss] images_per_page: 10 +blog_posts_per_page: 20 cdn_url: "https://i.zyl.gay" s3_prefix: # no longer prefixed diff --git a/site/images/amogus.yml b/site/images/amogus.md similarity index 93% rename from site/images/amogus.yml rename to site/images/amogus.md index 87321d4..b58294b 100644 --- a/site/images/amogus.yml +++ b/site/images/amogus.md @@ -1,6 +1,10 @@ +--- title: among us 😱 timestamp: 2022-12-14T00:00:00.00Z alt: Screenshot of Pokémon White on an evolution screen. Text reads "Congratulations! Your amogus evolved into Amoonguss!" desc: aaahhhh file: amogus.png tags: [pokémon, sussy] +--- + +aaahhhh diff --git a/site/images/boxtop.yml b/site/images/boxtop.md similarity index 96% rename from site/images/boxtop.yml rename to site/images/boxtop.md index 7d62b03..d21bc72 100644 --- a/site/images/boxtop.yml +++ b/site/images/boxtop.md @@ -1,5 +1,7 @@ +--- title: cat 3 timestamp: 2022-12-14T00:00:00.00Z alt: Picture of my cat sleeping in a box barely large enough for them. Their head is resting on one edge of the box. file: boxtop.jpeg tags: [cat] +--- diff --git a/site/images/cat.yml b/site/images/cat.md similarity index 94% rename from site/images/cat.yml rename to site/images/cat.md index 89b402b..f1f6ebc 100644 --- a/site/images/cat.yml +++ b/site/images/cat.md @@ -1,5 +1,7 @@ +--- title: cat timestamp: 2022-12-14T00:00:00.00Z alt: Picture of my cat sleeping curled up on top of some pillows. file: cat.jpeg tags: [cat] +--- diff --git a/site/images/cat2.yml b/site/images/cat2.md similarity index 95% rename from site/images/cat2.yml rename to site/images/cat2.md index 8bd0359..16dbcc6 100644 --- a/site/images/cat2.yml +++ b/site/images/cat2.md @@ -1,5 +1,7 @@ +--- title: cat 2 timestamp: 2022-12-14T00:00:00.00Z alt: Close up picture of my cat laying on a shelf while staring not quite at the camera. file: cat2.jpeg tags: [cat] +--- diff --git a/site/images/makeup-first-lol.md b/site/images/makeup-first-lol.md new file mode 100644 index 0000000..004c831 --- /dev/null +++ b/site/images/makeup-first-lol.md @@ -0,0 +1,13 @@ +--- +title: first time applying makeup +timestamp: 2023-02-10T21:40:00.00Z +alt: Bathroom mirror selfie of me in a cap, dark-rimmed glasses, and a flannel button-up over a mesh shirt wearing some light red lipstick, light and slightly orange blush around the nose, and poorly applied eyeliner. +file: makeup-first-lol.jpeg +tags: [me, selfie] +--- + +had the house to myself to try out some outfits and makeup without any external pressure + +this picture's of my first time applying any makeup where despite thinking it all looked like shit individually, I think all the parts came together well + +I'm wearing only lipstick, a little blush, and eyeliner. the foundation in the kit I was given wouldn't stay on 🤷 diff --git a/site/images/makeup-first-lol.yml b/site/images/makeup-first-lol.yml deleted file mode 100644 index 359e8b7..0000000 --- a/site/images/makeup-first-lol.yml +++ /dev/null @@ -1,9 +0,0 @@ -title: first time applying makeup -timestamp: 2023-02-10T21:40:00.00Z -alt: Bathroom mirror selfie of me in a cap, dark-rimmed glasses, and a flannel button-up over a mesh shirt wearing some light red lipstick, light and slightly orange blush around the nose, and poorly applied eyeliner. -desc: > -

had the house to myself to try out some outfits and makeup without any external pressure

-

this picture's of my first time applying any makeup where despite thinking it all looked like shit individually, I think all the parts came together well

-

I'm wearing only lipstick, a little blush, and eyeliner. the foundation in the kit I was given wouldn't stay on 🤷

-file: makeup-first-lol.jpeg -tags: [me, selfie] diff --git a/site/images/trans-comfy.yml b/site/images/trans-comfy.md similarity index 78% rename from site/images/trans-comfy.yml rename to site/images/trans-comfy.md index f8d398f..798b5b1 100644 --- a/site/images/trans-comfy.yml +++ b/site/images/trans-comfy.md @@ -1,6 +1,9 @@ +--- title: shorts to dresses timestamp: 2022-12-14T00:00:00.00Z alt: Screenshot from Pokémon Black 2 of an NPC saying "This dress is comfy and easy to wear..." -desc: yooo they're turning the comfy shorts kid trans file: trans-comfy.png tags: [pokémon, trans] +--- + +yooo they're turning the comfy shorts kid trans diff --git a/site/sass/index.scss b/site/sass/index.scss index 12c554b..e4f238f 100644 --- a/site/sass/index.scss +++ b/site/sass/index.scss @@ -9,11 +9,15 @@ body { --text-color: black; --accent-color: #b520e7; --accent-text-color: var(--bg-color); + --accent-color-neutral: #aaa; + --accent-text-color-neutral: #eee; @media (prefers-color-scheme: dark) { --bg-color: #333; --text-color: #ccc; --accent-text-color: black; + --accent-color-neutral: #555; + --accent-text-color-neutral: #bbb; } } @@ -55,7 +59,7 @@ abbr { .images-list { display: flex; flex-wrap: wrap; - + .image { position: relative; padding: 4px; @@ -81,7 +85,8 @@ abbr { } .image-full { - .title, .tags-title { + .title, + .tags-title { margin-bottom: 0; } @@ -92,3 +97,68 @@ abbr { background-color: rgba(0, 0, 0, 0.3); } } + +.blog-post-list { + .post { + p { + margin: 0; + } + + .title { + font-size: 1.2rem; + } + + .short-desc { + font-size: 0.9rem; + font-style: italic; + + &:before { + content: "└ "; + } + } + } +} + +.blog-post { + margin-left: auto; + margin-right: auto; + max-width: max(1000px, 40%); + + .title, + .tags-title { + margin: 0; + } + + .header-image-wrapper { + color: var(--accent-text-color-neutral); + background-color: var(--accent-color-neutral); + font-style: italic; + font-size: 1.2rem; + margin-bottom: 8px; + + .short-desc { + margin: 0; + padding: 8px; + } + + .header-image { + width: 100%; + max-height: 60vh; + object-fit: cover; + object-position: 50% 50%; + } + } + + .content { + text-indent: 1rem; + + h1, + h2, + h3, + h4, + h5, + h6 { + text-indent: 0; + } + } +} diff --git a/site/templates/base.hbs b/site/templates/base.hbs index 36d0b01..c4a1e8f 100644 --- a/site/templates/base.hbs +++ b/site/templates/base.hbs @@ -13,6 +13,7 @@ she/they + {{!-- Blog | --}} Images | Source diff --git a/site/templates/blog-list.hbs b/site/templates/blog-list.hbs new file mode 100644 index 0000000..32bbf60 --- /dev/null +++ b/site/templates/blog-list.hbs @@ -0,0 +1,23 @@ +{{#if tag}} +

Blog posts tagged {{tag}}

+

View all blog posts

+{{else}} +

Blog Posts

+

View blog tags

+

RSS Feed

+{{/if}} +

Page {{page}}/{{page_max}}

+{{#if previous}} +Previous page +{{/if}} +{{#if next}} +Next page +{{/if}} +
+ {{#each resources}} +
+

{{title}}

+

{{desc}}

+
+ {{/each}} +
diff --git a/site/templates/blog-post.hbs b/site/templates/blog-post.hbs new file mode 100644 index 0000000..59d31e7 --- /dev/null +++ b/site/templates/blog-post.hbs @@ -0,0 +1,22 @@ +
+

{{title}}

+ Published {{timestamp}} + {{#if draft}} +

DRAFT

+ {{/if}} +
+

{{desc}}

+ {{header_image_alt}} +
+
+ {{{content}}} +
+
+

Tags

+ +
diff --git a/site/templates/image.hbs b/site/templates/image.hbs index b61fbf8..599ee3d 100644 --- a/site/templates/image.hbs +++ b/site/templates/image.hbs @@ -2,9 +2,7 @@

{{title}}

Published {{timestamp}} {{alt}} - {{#if desc}} -

{{{desc}}}

- {{/if}} + {{{content}}}

View full size image

Tags

diff --git a/site/templates/rss/blog-post.hbs b/site/templates/rss/blog-post.hbs new file mode 100644 index 0000000..ee20e88 --- /dev/null +++ b/site/templates/rss/blog-post.hbs @@ -0,0 +1 @@ +
{{{source}}}
diff --git a/src/blog.rs b/src/blog.rs new file mode 100644 index 0000000..a0c6ec6 --- /dev/null +++ b/src/blog.rs @@ -0,0 +1,86 @@ +use serde::{Deserialize, Serialize}; + +use crate::{ + builder::SiteBuilder, + resource::{ResourceBuilder, ResourceBuilderConfig, ResourceMetadata, ResourceMethods}, +}; + +pub const BLOG_PATH: &str = "blog"; + +/// Builds the blog. +pub fn build_blog(site_builder: &SiteBuilder) -> anyhow::Result<()> { + let config = 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: "Zyllian's blog".to_string(), + rss_description: "Feed of recent blog posts on Zyllian'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_builder.site.config.blog_posts_per_page, + }; + + let mut builder = ResourceBuilder::::new(config); + builder.load_all(site_builder)?; + builder.build_all(site_builder)?; + + Ok(()) +} + +/// 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, +} + +/// 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: &crate::SiteConfig, + ) -> anyhow::Result { + // TODO: render markdown + Ok(BlogPostTemplateData { + header_image: site_config + .cdn_url(&self.inner.header_image_file)? + .to_string(), + 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()), + }) + } +} diff --git a/src/builder.rs b/src/builder.rs index 9c1b4e3..e84aa24 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -25,7 +25,7 @@ struct TemplateData<'a> { /// Struct used to build the site. pub struct SiteBuilder<'a> { /// The matter instance used to extract front matter. - matter: Matter, + pub(crate) matter: Matter, /// The Handlebars registry used to render templates. pub(crate) reg: Handlebars<'a>, /// The site info used to build the site. @@ -242,4 +242,9 @@ impl<'a> SiteBuilder<'a> { pub fn build_images(&self) -> anyhow::Result<()> { crate::images::build_images(self) } + + /// Builds the site's blog. + pub fn build_blog(&self) -> anyhow::Result<()> { + crate::blog::build_blog(self) + } } diff --git a/src/images.rs b/src/images.rs index 4a50749..2d451b3 100644 --- a/src/images.rs +++ b/src/images.rs @@ -1,5 +1,4 @@ use serde::{Deserialize, Serialize}; -use url::Url; use crate::{ builder::SiteBuilder, @@ -28,7 +27,7 @@ pub fn build_images(site_builder: &SiteBuilder) -> anyhow::Result<()> { }; let mut builder = ResourceBuilder::::new(config); - builder.load_all(&site_builder.site.site_path)?; + builder.load_all(site_builder)?; builder.build_all(site_builder)?; Ok(()) @@ -45,13 +44,6 @@ pub struct ImageMetadata { pub file: String, } -impl ImageMetadata { - /// Gets an image's CDN url. - pub fn cdn_url(&self, config: &SiteConfig) -> anyhow::Result { - Ok(config.cdn_url.join(&config.s3_prefix)?.join(&self.file)?) - } -} - /// Template data for a specific image. #[derive(Debug, Serialize)] struct ImageTemplateData { @@ -70,7 +62,7 @@ impl ResourceMethods for ResourceMetadata { site_config: &SiteConfig, ) -> anyhow::Result { Ok(ImageTemplateData { - src: self.inner.cdn_url(site_config)?.to_string(), + src: site_config.cdn_url(&self.inner.file)?.to_string(), }) } } diff --git a/src/lib.rs b/src/lib.rs index 1ba085c..1c30343 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +mod blog; mod builder; mod images; mod link_list; @@ -38,12 +39,21 @@ pub struct SiteConfig { 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, } +impl SiteConfig { + /// Gets a CDN url from the given file name. + pub fn cdn_url(&self, file: &str) -> anyhow::Result { + Ok(self.cdn_url.join(&self.s3_prefix)?.join(file)?) + } +} + /// Struct for the front matter in templates. (nothing here yet) #[derive(Debug, Default, Deserialize)] pub struct TemplateMetadata {} @@ -134,6 +144,7 @@ impl Site { builder.site.build_all_pages(&builder)?; builder.build_sass()?; builder.build_images()?; + builder.build_blog()?; Ok(()) } diff --git a/src/resource.rs b/src/resource.rs index 75d81a3..028e0a6 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -6,6 +6,7 @@ use std::{ use anyhow::Context; use itertools::Itertools; +use pulldown_cmark::{Options, Parser}; use rss::{validation::Validate, ChannelBuilder, ItemBuilder}; use serde::{de::DeserializeOwned, Deserialize, Serialize, Serializer}; use time::{format_description::well_known::Rfc2822, OffsetDateTime}; @@ -25,6 +26,12 @@ pub struct ResourceMetadata { /// Extra resource data not included. #[serde(flatten)] pub inner: T, + /// Whether the resource is a draft. Drafts can be committed without being published to the live site. + #[serde(default)] + pub draft: bool, + /// The resource's content. Defaults to nothing until loaded in another step. + #[serde(default)] + pub content: String, } #[derive(Debug, Serialize)] @@ -141,19 +148,39 @@ where } /// Loads resource metadata from the given path. - fn load(path: &Path) -> anyhow::Result<(String, ResourceMetadata)> { + fn load(builder: &SiteBuilder, path: &Path) -> anyhow::Result<(String, ResourceMetadata)> { let id = Self::get_id(path); - let metadata = serde_yaml::from_str(&std::fs::read_to_string(path)?)?; - Ok((id, metadata)) + + let input = std::fs::read_to_string(path)?; + let mut page = builder + .matter + .parse_with_struct::>(&input) + .ok_or_else(|| anyhow::anyhow!("Failed to parse resource front matter"))?; + + let parser = Parser::new_ext(&page.content, Options::all()); + let mut html = String::new(); + pulldown_cmark::html::push_html(&mut html, parser); + + page.data.content = html; + + Ok((id, page.data)) } /// Loads all resource metadata from the given config. - pub fn load_all(&mut self, site_path: &Path) -> anyhow::Result<()> { + pub fn load_all(&mut self, builder: &SiteBuilder) -> anyhow::Result<()> { self.loaded_metadata.clear(); - for e in site_path.join(&self.config.source_path).read_dir()? { + for e in builder + .site + .site_path + .join(&self.config.source_path) + .read_dir()? + { let p = e?.path(); - if let Some("yml") = p.extension().and_then(|e| e.to_str()) { - let (id, metadata) = Self::load(&p)?; + if let Some("md") = p.extension().and_then(|e| e.to_str()) { + let (id, metadata) = Self::load(builder, &p)?; + if cfg!(not(debug_assertions)) && metadata.draft { + continue; + } self.loaded_metadata.push((id, metadata)); } } @@ -201,6 +228,16 @@ where } pub fn build_all(&self, builder: &SiteBuilder) -> anyhow::Result<()> { + let out_short = builder.build_path.join(&self.config.output_path_short); + let out_long = builder.build_path.join(&self.config.output_path_long); + + if !out_short.exists() { + std::fs::create_dir_all(&out_short)?; + } + if !out_long.exists() { + std::fs::create_dir_all(&out_long)?; + } + for (id, resource) in &self.loaded_metadata { self.build(builder, id.clone(), resource)?; } @@ -267,8 +304,6 @@ where Ok(()) } - let out_path = builder.build_path.join(&self.config.output_path_short); - // Build main list of resources build_list( builder, @@ -276,7 +311,7 @@ where data.iter().collect(), &self.config.list_title, None, - &builder.build_path.join(&self.config.output_path_long), + &out_long, self.config.resources_per_page, )?; @@ -310,7 +345,7 @@ where links, &self.config.tag_list_title, )?; - std::fs::write(out_path.join("tags.html"), out)?; + std::fs::write(out_short.join("tags.html"), out)?; } for (tag, data) in tags { @@ -320,7 +355,7 @@ where data, &format!("{} tagged {tag}", self.config.resource_name_plural), Some(tag.as_str()), - &out_path.join("tag").join(&tag), + &out_short.join("tag").join(&tag), self.config.resources_per_page, )?; } @@ -367,13 +402,7 @@ where .build(); channel.validate().context("Failed to validate RSS feed")?; let out = channel.to_string(); - std::fs::write( - builder - .build_path - .join(&self.config.output_path_long) - .join("rss.xml"), - out, - )?; + std::fs::write(out_long.join("rss.xml"), out)?; Ok(()) } diff --git a/src/serving.rs b/src/serving.rs index 1f913cd..c7df754 100644 --- a/src/serving.rs +++ b/src/serving.rs @@ -64,6 +64,7 @@ fn create( if build { builder.site.build_all_pages(builder)?; builder.build_images()?; + builder.build_blog()?; } } else if relative_path.display().to_string() == "config.yaml" { let new_config = serde_yaml::from_str(&std::fs::read_to_string(path)?)?; @@ -78,6 +79,9 @@ fn create( } 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.build_images()?; + } else if let Ok(_blog_path) = relative_path.strip_prefix(crate::blog::BLOG_PATH) { + // HACK: same as above + builder.build_blog()?; } Ok(()) @@ -109,6 +113,8 @@ fn remove(builder: &mut SiteBuilder, path: &Path, relative_path: &Path) -> anyho } else if let Ok(_image_path) = relative_path.strip_prefix(crate::images::IMAGES_PATH) { // HACK: same as in `create` builder.build_images()?; + } else if let Ok(_blog_path) = relative_path.strip_prefix(crate::blog::BLOG_PATH) { + // HACK: same as above } Ok(()) @@ -138,6 +144,7 @@ impl Site { builder .build_images() .context("Failed to build image pages")?; + builder.build_blog().context("Failed to build blog")?; // Map of websocket connections let peers: Arc>> =