Commit Graph

17 Commits

Author SHA1 Message Date
Timothy DeHerrera
16fed12273 feat!: replace YAML frontmatter with TOML
Replace hand-rolled YAML parser (70 lines) with serde-backed
toml::from_str<Frontmatter> (6 lines). Frontmatter delimiter
changes from --- to +++ (Hugo TOML convention).

New Frontmatter fields:
- draft: bool (#[serde(default)]) for draft filtering
- aliases: Vec<String> (#[serde(default)]) for URL redirects

Date field upgraded from Option<String> to Option<NaiveDate>
with custom deserializer for TOML native dates. Parse, don't
validate: invalid dates now fail at deserialization time.

Add chrono dependency with serde feature. Update cascade in
sitemap.rs (NaiveDate→String at boundary), template_engine.rs
(FrontmatterContext gains draft/aliases), and all 14 tests.

BREAKING CHANGE: Content files must use +++ TOML frontmatter
instead of --- YAML frontmatter.
2026-02-14 06:50:35 -07:00
Timothy DeHerrera
8e1f8cbb95 refactor(content): remove gray_matter, manual frontmatter
Implement extract_frontmatter (--- delimiters) and parse_frontmatter
(simple YAML key:value pairs). Handles taxonomies.tags for blog posts.
~70 lines replaces external dependency.
2026-02-05 23:59:53 -07:00
Timothy DeHerrera
f1e3add292 chore: add .rustfmt.toml 2026-02-05 23:48:08 -07:00
Timothy DeHerrera
c60c7851a8 refactor(api): restrict visibility of internal items
- content: DEFAULT_WEIGHT, DEFAULT_WEIGHT_HIGH → pub(crate)
- sitemap: SitemapEntry → pub(crate)

These items are implementation details not exposed to consumers.
2026-02-05 15:03:52 -07:00
Timothy DeHerrera
16f04eb95b refactor: consolidate escape functions and extract weight constants
- Create escape.rs with shared html_escape, html_escape_into, xml_escape
- Remove duplicate implementations from render.rs, highlight.rs, feed.rs, sitemap.rs
- Add DEFAULT_WEIGHT (50) and DEFAULT_WEIGHT_HIGH (99) constants to content.rs
- Replace all magic number weight defaults with named constants

No functional changes; all 67 tests pass.
2026-02-05 14:35:24 -07:00
Timothy DeHerrera
3f218ed49c chore: address clippy lints 2026-02-05 12:26:22 -07:00
Timothy DeHerrera
a59b8ff2ab feat(render): add anchor extraction during markdown rendering
- Add Anchor struct with id, label, level fields
- markdown_to_html() now returns (String, Vec<Anchor>) tuple
- Headings h2-h6 are extracted with slugified IDs
- Add toc: bool frontmatter field for per-page TOC opt-in
- All heading tags now include id attributes for anchor links
2026-02-01 09:31:54 -07:00
Timothy DeHerrera
b3a540651a feat(content): add nested children to NavItem for hierarchical nav
Extend NavItem struct with children field to support nested navigation.
discover_nav() now populates children for section items by collecting
section pages via Section::collect_items() and mapping them to child
NavItem entries. Children are sorted by weight then alphabetically.
2026-02-01 09:00:04 -07:00
Timothy DeHerrera
96aa60d9e4 refactor(content): add SiteManifest for unified content discovery
Introduce SiteManifest struct that aggregates all site content from a
single discovery pass:

- homepage: content/_index.md
- sections: directories with _index.md
- pages: top-level standalone .md files
- posts: blog section items (sorted by date for feed)
- nav: navigation menu items

Add discover_pages() helper and 5 unit tests covering homepage,
sections, pages, posts, and nav discovery.

Not yet integrated into main.rs pipeline.
2026-01-31 22:08:49 -07:00
Timothy DeHerrera
e200e94583 feat(templates): complete Tera migration, remove maud
Fully migrate from compile-time maud templates to runtime Tera:
- Rewrote main.rs to use TemplateEngine and discover_sections()
- Replaced hardcoded blog/projects with generic section loop
- Added Clone derive to Frontmatter and Content
- Fixed section_type dispatch via Section struct
- Deleted src/templates.rs, removed maud dependency

Users can now add sections without code changes.
2026-01-31 15:10:39 -07:00
Timothy DeHerrera
244b0ce85b feat(content): add Section struct and discover_sections()
Enable generic section processing by adding:
- Section struct with index, name, section_type, path
- Section::collect_items() to gather content in a section
- discover_sections() to find all directories with _index.md

Section type is determined from frontmatter `section_type` field,
falling back to directory name. Includes 5 unit tests.
2026-01-31 15:02:20 -07:00
Timothy DeHerrera
3df7fda26a feat(templates): add Tera runtime template engine
Lay groundwork for user-editable templates by adding Tera as a
runtime template engine alongside the existing maud templates.

Changes:
- Add tera dependency
- Create TemplateEngine struct with render methods
- Add TemplateLoad/TemplateRender error variants
- Add section_type/template fields to Frontmatter
- Create templates/ directory with base, page, section, and content templates

Dead code warnings are expected; TemplateEngine will be wired
in to replace maud in subsequent commits.
2026-01-31 14:59:49 -07:00
Timothy DeHerrera
b978edf4f2 feat(content): add filesystem-driven nav discovery
Add NavItem struct and discover_nav() function to scan content
directory and automatically build navigation from:
- Top-level .md files (pages)
- Directories with _index.md (sections)

Navigation is sorted by frontmatter weight, then alphabetically.
Custom nav_label field allows overriding title in nav menu.

Includes 5 unit tests covering page/section discovery, weight
ordering, and nav_label support.
2026-01-31 13:52:21 -07:00
Timothy DeHerrera
71d5ac1e37 refactor: switch to flat .html output (suckless style)
- src/content.rs: output_path() now returns slug.html instead of
  slug/index.html for regular content.

- src/templates.rs: All hrefs use explicit .html extension.
  Nav links point to index.html, blog.index.html, about.html.
  Blog post links use ./slug.html format.

- src/main.rs: Adjust depth values (root=0, blog posts=1).

No more directory-per-page overhead. file:// navigation works
without directory listings. True suckless structure.
2026-01-24 21:36:58 -07:00
Timothy DeHerrera
5317da94c4 feat: add minimal base CSS with dark mode support
- static/style.css: CSS variable-based theming with:
  - Typography (system fonts, monospace for code)
  - Layout (centered content, nav/main/footer structure)
  - Dark mode via prefers-color-scheme
  - Component styles (posts, cards, tags, hero)

- src/main.rs: Add copy_static_assets() to copy static/
  directory to public/ during build

Phase 1 complete. Ready for syntax highlighting.
2026-01-24 20:27:22 -07:00
Timothy DeHerrera
06b7e0df64 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)
2026-01-24 19:19:53 -07:00
Timothy DeHerrera
e07a9e87e6 feat: implement core markdown rendering pipeline
Add minimal e2e pipeline to transform content → HTML:

- src/error.rs: Custom error types with thiserror
- src/content.rs: YAML frontmatter parsing via gray_matter
- src/render.rs: Markdown → HTML via pulldown-cmark
- src/templates.rs: Maud templates for base layout and posts
- src/main.rs: Pipeline orchestrator

All 15 blog posts successfully rendered to public/blog/*/index.html.
Added thiserror and walkdir dependencies.
Added public/ and DepMap fragment to .gitignore and AGENTS.md.
2026-01-24 19:01:30 -07:00