Manual Display and Error trait implementations replace derive macro.
Preserves source() chaining for all io::Error and tera::Error variants.
One less dependency, same behavior.
Two issues fixed:
1. Language-less code blocks (``` without lang) were not accumulating
text content. The guard `code_block_lang.is_some()` was false for
them, so content fell through to regular text rendering.
Fix: Add `in_code_block` flag to track code block state separately
from language presence.
2. Single quotes in code blocks were being HTML-escaped as ',
breaking CSP headers like 'self' in documentation.
Fix: Create code_escape/code_escape_into in escape.rs that only
escapes <, >, & (required to prevent HTML tag injection) but
preserves quotes (safe inside <pre><code> content).
Rationale for code_escape:
- < and > MUST be escaped to prevent browser interpreting code as HTML
- & MUST be escaped to prevent HTML entity interpretation
- Quotes are safe inside element content (no attribute context)
Also:
- Add test for unlabeled code block quote preservation
All 71 tests pass.
Apply html_escape to:
- Link href and title attributes (start_tag_to_html)
- Image src attribute (Event::End TagEnd::Image handler)
Add test cases for:
- Quote-breaking URL attacks
- Link title escaping
- Image src escaping
Addresses HIGH severity finding from security audit.
All 70 tests pass.
Add '\'' → ''' case to html_escape_into for complete XSS
protection in HTML attribute contexts. Update documentation
and add test case.
Addresses LOW severity finding from security audit.
- Fix module count: 12 → 13 (add escape.rs)
- Add escape.rs to module responsibilities table
- Update code example from old HighlightConfiguration API
to current tree-house LanguageConfig pattern
Reflects tree-house migration and API coherence audit findings.
- content: DEFAULT_WEIGHT, DEFAULT_WEIGHT_HIGH → pub(crate)
- sitemap: SitemapEntry → pub(crate)
These items are implementation details not exposed to consumers.
- 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.
- Add 6 syntax highlighting themes (dracula, gruvbox, nord, github)
- Rewrite css.rs to use lightningcss bundler for @import resolution
- Theme CSS is inlined at build time, producing single bundled output
Replace tree-sitter-highlight dep with tree-house crate from Helix
editor. Add ropey dependency required by tree-house.
Reorganize query files from Helix's runtime/queries/ for all 14
supported languages:
- bash, c, css, go, html, javascript, json, markdown, nix, python,
rust, toml, typescript, yaml
- Include ecma, _javascript, _typescript base dirs for JS/TS inheritance
- Copy highlights.scm, injections.scm, locals.scm where available
This commit establishes the foundation; highlight.rs implementation
will follow in subsequent commits.
Use CSS Overflow Level 5 properties (scroll-target-group, :target-current)
to highlight the current section in the sidebar TOC as the user scrolls.
Progressive enhancement: gracefully degrades in unsupported browsers
(Firefox, Safari) — they retain existing hover/click behavior.
Browser support: Chrome 140+, Edge 140+, Opera 124+ (~65% global).
Document that sukr prioritizes output quality over minimal build-time
weight. Acknowledges KaTeX and mermaid-rs are heavier than alternatives,
leaving door open for future evaluation without committing to redesign.
Rename "Zero JS Output" to "JS-Free Rich Content" with footnote
explaining that all generators can produce JS-free basic HTML—sukr's
distinction is built-in build-time math and diagram rendering.
Override mermaid's default white backgrounds to blend with dark theme:
- Transparent SVG background
- Node fills use --bg-sidebar
- Labels use --fg color
- Edges use --fg-muted
Add scrollable container rules for .mermaid-diagram in mobile
media query. SVG diagrams now scroll horizontally within their
container instead of extending the page width and obscuring
the hamburger menu.
- Highlight heading with accent border-left when targeted via URL hash
- Show pilcrow anchor visibly on targeted headings
- Add scroll-margin-top for better scroll positioning
- Add pilcrow (¶) anchor link after heading text for deep-linking
- CSS: hidden by default, visible on heading hover, user-overridable
- Add strip_parens Tera filter for cleaner nav anchor labels
- Update test expectations for new heading format
- 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
- 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
- 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
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.
Add responsive table rules: horizontal scroll within container,
word-break for inline code, and constrained max-width. Fixes
hamburger menu being pushed off-screen on pages with wide tables.
Implement pure CSS mobile navigation with the following features:
- Collapsible sidebar nav hidden behind hamburger toggle on mobile
- Animated hamburger → X icon morph using CSS transforms
- Smooth slide-down transition for nav reveal (max-height/opacity)
- Hamburger positioned on right side of header via absolute positioning
- Uses :has() selector to detect checkbox state without JavaScript
- Overflow fixes to prevent horizontal scroll on mobile devices
The implementation follows suckless principles with zero JavaScript.
pulldown-cmark emits alt text as Text events between Image start/end
tags. Previously, images were rendered immediately on the Start event
with empty alt text, losing the user-provided description.
Refactored to accumulate alt text using the same pattern as code block
handling: state variables track image attributes and alt content, then
the full <img> tag is rendered on the End event.
Also omits the title attribute entirely when no title is provided,
producing cleaner HTML output.
Fixes Lighthouse "Image elements have [alt] attributes" audit issue.
Add docs/content/features/sitemap.md documenting the automatic
XML sitemap generation feature:
- Output location and contents
- Auto-generation behavior
- lastmod date handling
- Linking and validation tips
Follows established pattern from feeds.md.
Eliminate redundant Content::from_path call by using the pre-discovered
manifest.homepage content. Also uses manifest.nav directly.
- Removes dead_code warning on SiteManifest.homepage field
- Reduces I/O by reusing discovered content
- Simplifies function signature (4 args vs 5)
Replace separate discover_nav + discover_sections calls with single
SiteManifest::discover() in run() pipeline:
- Update generate_feed() to accept &SiteManifest
- Update generate_sitemap_file() to accept &SiteManifest
- Simplify process_pages() to return Result<()>
- Remove redundant all_posts collection (now in manifest.posts)
- Remove unused discover_nav and discover_sections imports
All 49 tests pass, site builds identically.
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.