From c8c2506e16318366d148e2738a560a29becf6c35 Mon Sep 17 00:00:00 2001 From: Timothy DeHerrera Date: Sun, 1 Feb 2026 09:42:00 -0700 Subject: [PATCH] feat(config): add global nav.toc setting with frontmatter override - Add toc: bool to [nav] config section (default: false) - Frontmatter toc: true/false overrides global config - If frontmatter toc is not specified, falls back to config.nav.toc - Enable nav.toc = true in docs/site.toml for global TOC --- docs/content/features/templates.md | 1 - docs/site.toml | 1 + src/config.rs | 3 +++ src/main.rs | 2 +- src/template_engine.rs | 26 ++++++++++++++++++-------- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/docs/content/features/templates.md b/docs/content/features/templates.md index b36c88c..153ed90 100644 --- a/docs/content/features/templates.md +++ b/docs/content/features/templates.md @@ -2,7 +2,6 @@ title: Tera Templates description: Customizable templates without recompilation weight: 1 -toc: true --- sukr uses [Tera](https://tera.netlify.app/), a Jinja2-like templating engine. Templates are loaded at runtime, so you can modify them without recompiling sukr. diff --git a/docs/site.toml b/docs/site.toml index a675928..d12efa4 100644 --- a/docs/site.toml +++ b/docs/site.toml @@ -10,3 +10,4 @@ templates = "templates" [nav] nested = true +toc = true diff --git a/src/config.rs b/src/config.rs index a896069..bdeb1ce 100644 --- a/src/config.rs +++ b/src/config.rs @@ -28,6 +28,9 @@ pub struct SiteConfig { pub struct NavConfig { /// Whether to display nested navigation (default: false). pub nested: bool, + /// Enable table of contents (anchor nav) globally (default: false). + /// Can be overridden per-page via frontmatter toc field. + pub toc: bool, } /// Path configuration with sensible defaults. diff --git a/src/main.rs b/src/main.rs index e2664ce..888b1bb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -159,7 +159,7 @@ fn run(config_path: &Path) -> Result<()> { let page_path = format!("/{}/index.html", section.name); let item_contexts: Vec<_> = items .iter() - .map(|c| ContentContext::from_content(c, &content_dir)) + .map(|c| ContentContext::from_content(c, &content_dir, &config)) .collect(); let html = engine.render_section( §ion.index, diff --git a/src/template_engine.rs b/src/template_engine.rs index f5e02fb..a08ea02 100644 --- a/src/template_engine.rs +++ b/src/template_engine.rs @@ -45,7 +45,10 @@ impl TemplateEngine { ) -> Result { let mut ctx = self.base_context(page_path, config, nav); ctx.insert("title", &content.frontmatter.title); - ctx.insert("page", &FrontmatterContext::from(&content.frontmatter)); + ctx.insert( + "page", + &FrontmatterContext::new(&content.frontmatter, config), + ); ctx.insert("content", html_body); ctx.insert("anchors", anchors); self.render("page.html", &ctx) @@ -68,7 +71,10 @@ impl TemplateEngine { .unwrap_or("content/default.html"); let mut ctx = self.base_context(page_path, config, nav); ctx.insert("title", &content.frontmatter.title); - ctx.insert("page", &FrontmatterContext::from(&content.frontmatter)); + ctx.insert( + "page", + &FrontmatterContext::new(&content.frontmatter, config), + ); ctx.insert("content", html_body); ctx.insert("anchors", anchors); self.render(template, &ctx) @@ -88,7 +94,10 @@ impl TemplateEngine { let mut ctx = self.base_context(page_path, config, nav); ctx.insert("title", §ion.frontmatter.title); - ctx.insert("section", &FrontmatterContext::from(§ion.frontmatter)); + ctx.insert( + "section", + &FrontmatterContext::new(§ion.frontmatter, config), + ); ctx.insert("items", items); self.render(&template, &ctx) } @@ -154,8 +163,9 @@ pub struct FrontmatterContext { pub toc: bool, } -impl From<&crate::content::Frontmatter> for FrontmatterContext { - fn from(fm: &crate::content::Frontmatter) -> Self { +impl FrontmatterContext { + /// Create context from frontmatter with config fallback for toc. + pub fn new(fm: &crate::content::Frontmatter, config: &SiteConfig) -> Self { Self { title: fm.title.clone(), description: fm.description.clone(), @@ -163,7 +173,7 @@ impl From<&crate::content::Frontmatter> for FrontmatterContext { tags: fm.tags.clone(), weight: fm.weight, link_to: fm.link_to.clone(), - toc: fm.toc.unwrap_or(false), + toc: fm.toc.unwrap_or(config.nav.toc), } } } @@ -178,9 +188,9 @@ pub struct ContentContext { } impl ContentContext { - pub fn from_content(content: &Content, content_dir: &Path) -> Self { + pub fn from_content(content: &Content, content_dir: &Path, config: &SiteConfig) -> Self { Self { - frontmatter: FrontmatterContext::from(&content.frontmatter), + frontmatter: FrontmatterContext::new(&content.frontmatter, config), body: content.body.clone(), slug: content.slug.clone(), path: format!("/{}", content.output_path(content_dir).display()),