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.
- 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 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 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
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.
Intercept 'mermaid' code blocks in render.rs and call
mermaid::render_diagram() to convert to inline SVG.
- Use catch_unwind to handle upstream dagre_rust panics gracefully
- Graceful fallback: show raw code with mermaid-error class on failure
- Flowcharts render correctly; some diagram types hit upstream bugs
Add src/mermaid.rs with render_diagram() wrapper around
mermaid-rs-renderer for build-time Mermaid-to-SVG conversion.
- Use mermaid-rs-renderer git dependency (SVG-only, no PNG)
- Configure with RenderOptions::modern() theme
- Include unit tests for flowchart and sequence diagrams
Enable ENABLE_MATH in pulldown-cmark options and implement
InlineMath/DisplayMath event handlers in the render pipeline.
- Inline math ($...$) renders via render_math(_, false)
- Display math ($$...$$) wrapped in <div class="math-display">
- Graceful degradation: errors logged to stderr, raw LaTeX shown
with class="math-error" for styling
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.