feat(nav): add anchor TOC in sidebar for toc-enabled pages
- Pass extracted anchors through template context - Render anchor links under active page when page.toc is true - Hierarchical indentation by heading level (h2-h6) - CSS styling: smaller font, muted color, border-left indicator - Add toc: true to templates.md as example
This commit is contained in:
20
src/main.rs
20
src/main.rs
@@ -142,10 +142,16 @@ fn run(config_path: &Path) -> Result<()> {
|
||||
// Render individual content pages for all sections
|
||||
for item in &items {
|
||||
eprintln!(" processing: {}", item.slug);
|
||||
let (html_body, _anchors) = render::markdown_to_html(&item.body);
|
||||
let (html_body, anchors) = render::markdown_to_html(&item.body);
|
||||
let page_path = format!("/{}", item.output_path(&content_dir).display());
|
||||
let html =
|
||||
engine.render_content(item, &html_body, &page_path, &config, &manifest.nav)?;
|
||||
let html = engine.render_content(
|
||||
item,
|
||||
&html_body,
|
||||
&page_path,
|
||||
&config,
|
||||
&manifest.nav,
|
||||
&anchors,
|
||||
)?;
|
||||
write_output(&output_dir, &content_dir, item, html)?;
|
||||
}
|
||||
|
||||
@@ -259,9 +265,10 @@ fn process_pages(
|
||||
eprintln!("processing: {}", path.display());
|
||||
|
||||
let content = Content::from_path(&path, ContentKind::Page)?;
|
||||
let (html_body, _anchors) = render::markdown_to_html(&content.body);
|
||||
let (html_body, anchors) = render::markdown_to_html(&content.body);
|
||||
let page_path = format!("/{}", content.output_path(content_dir).display());
|
||||
let html = engine.render_page(&content, &html_body, &page_path, config, nav)?;
|
||||
let html =
|
||||
engine.render_page(&content, &html_body, &page_path, config, nav, &anchors)?;
|
||||
|
||||
write_output(output_dir, content_dir, &content, html)?;
|
||||
}
|
||||
@@ -278,13 +285,14 @@ fn generate_homepage(
|
||||
) -> Result<()> {
|
||||
eprintln!("generating: homepage");
|
||||
|
||||
let (html_body, _anchors) = render::markdown_to_html(&manifest.homepage.body);
|
||||
let (html_body, anchors) = render::markdown_to_html(&manifest.homepage.body);
|
||||
let html = engine.render_page(
|
||||
&manifest.homepage,
|
||||
&html_body,
|
||||
"/index.html",
|
||||
config,
|
||||
&manifest.nav,
|
||||
&anchors,
|
||||
)?;
|
||||
|
||||
let out_path = output_dir.join("index.html");
|
||||
|
||||
@@ -8,6 +8,7 @@ use tera::{Context, Tera};
|
||||
use crate::config::SiteConfig;
|
||||
use crate::content::{Content, NavItem};
|
||||
use crate::error::{Error, Result};
|
||||
use crate::render::Anchor;
|
||||
|
||||
/// Runtime template engine wrapping Tera.
|
||||
pub struct TemplateEngine {
|
||||
@@ -40,11 +41,13 @@ impl TemplateEngine {
|
||||
page_path: &str,
|
||||
config: &SiteConfig,
|
||||
nav: &[NavItem],
|
||||
anchors: &[Anchor],
|
||||
) -> Result<String> {
|
||||
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("content", html_body);
|
||||
ctx.insert("anchors", anchors);
|
||||
self.render("page.html", &ctx)
|
||||
}
|
||||
|
||||
@@ -56,6 +59,7 @@ impl TemplateEngine {
|
||||
page_path: &str,
|
||||
config: &SiteConfig,
|
||||
nav: &[NavItem],
|
||||
anchors: &[Anchor],
|
||||
) -> Result<String> {
|
||||
let template = content
|
||||
.frontmatter
|
||||
@@ -66,6 +70,7 @@ impl TemplateEngine {
|
||||
ctx.insert("title", &content.frontmatter.title);
|
||||
ctx.insert("page", &FrontmatterContext::from(&content.frontmatter));
|
||||
ctx.insert("content", html_body);
|
||||
ctx.insert("anchors", anchors);
|
||||
self.render(template, &ctx)
|
||||
}
|
||||
|
||||
@@ -145,6 +150,8 @@ pub struct FrontmatterContext {
|
||||
pub tags: Vec<String>,
|
||||
pub weight: Option<i64>,
|
||||
pub link_to: Option<String>,
|
||||
/// Enable table of contents (anchor nav in sidebar)
|
||||
pub toc: bool,
|
||||
}
|
||||
|
||||
impl From<&crate::content::Frontmatter> for FrontmatterContext {
|
||||
@@ -156,6 +163,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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user