feat: implement cohesive site structure
Add content type handling and multi-page generation: - content.rs: Add ContentKind enum (Post, Page, Section, Project) and extend Frontmatter with weight/link_to fields - templates.rs: Add render_page, render_homepage, render_blog_index, render_projects_index templates - main.rs: Process all content types with dedicated handlers Output structure: - /index.html (homepage from _index.md) - /blog/index.html (post listing, sorted by date) - /blog/<slug>/index.html (individual posts) - /about/index.html, /collab/index.html (standalone pages) - /projects/index.html (project cards with external links)
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
//! HTML templates using maud.
|
||||
|
||||
use crate::content::Frontmatter;
|
||||
use maud::{html, Markup, DOCTYPE};
|
||||
use crate::content::{Content, Frontmatter};
|
||||
use maud::{DOCTYPE, Markup, PreEscaped, html};
|
||||
|
||||
/// Render a blog post with the base layout.
|
||||
pub fn render_post(frontmatter: &Frontmatter, content_html: &str) -> Markup {
|
||||
@@ -26,7 +26,94 @@ pub fn render_post(frontmatter: &Frontmatter, content_html: &str) -> Markup {
|
||||
}
|
||||
}
|
||||
section.content {
|
||||
(maud::PreEscaped(content_html))
|
||||
(PreEscaped(content_html))
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Render a standalone page (about, collab, etc.)
|
||||
pub fn render_page(frontmatter: &Frontmatter, content_html: &str) -> Markup {
|
||||
base_layout(
|
||||
&frontmatter.title,
|
||||
html! {
|
||||
article.page {
|
||||
h1 { (frontmatter.title) }
|
||||
section.content {
|
||||
(PreEscaped(content_html))
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Render the homepage.
|
||||
pub fn render_homepage(frontmatter: &Frontmatter, content_html: &str) -> Markup {
|
||||
base_layout(
|
||||
&frontmatter.title,
|
||||
html! {
|
||||
section.hero {
|
||||
h1 { (frontmatter.title) }
|
||||
@if let Some(ref desc) = frontmatter.description {
|
||||
p.tagline { (desc) }
|
||||
}
|
||||
}
|
||||
section.content {
|
||||
(PreEscaped(content_html))
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Render the blog listing page.
|
||||
pub fn render_blog_index(title: &str, posts: &[Content]) -> Markup {
|
||||
base_layout(
|
||||
title,
|
||||
html! {
|
||||
h1 { (title) }
|
||||
ul.post-list {
|
||||
@for post in posts {
|
||||
li {
|
||||
a href=(format!("/blog/{}/", post.slug)) {
|
||||
span.title { (post.frontmatter.title) }
|
||||
@if let Some(ref date) = post.frontmatter.date {
|
||||
time.date { (date) }
|
||||
}
|
||||
}
|
||||
@if let Some(ref desc) = post.frontmatter.description {
|
||||
p.description { (desc) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Render the projects page with cards.
|
||||
pub fn render_projects_index(title: &str, projects: &[Content]) -> Markup {
|
||||
base_layout(
|
||||
title,
|
||||
html! {
|
||||
h1 { (title) }
|
||||
ul.project-cards {
|
||||
@for project in projects {
|
||||
li.card {
|
||||
@if let Some(ref link) = project.frontmatter.link_to {
|
||||
a href=(link) target="_blank" rel="noopener" {
|
||||
h2 { (project.frontmatter.title) }
|
||||
@if let Some(ref desc) = project.frontmatter.description {
|
||||
p { (desc) }
|
||||
}
|
||||
}
|
||||
} @else {
|
||||
h2 { (project.frontmatter.title) }
|
||||
@if let Some(ref desc) = project.frontmatter.description {
|
||||
p { (desc) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user