mini-docs 0.3.6

A minimal, secure build-time Markdown to HTML generator for the mini-* family.
Documentation
use std::fs;

use mini_docs::Builder;
use serde_json::{json, Value};

/// Builds a `data.json` index alongside the HTML output: full frontmatter on one
/// page, none on another (defaults kick in), and a `draft: true` page excluded from
/// both the index and the HTML build entirely.
#[test]
fn data_json_includes_non_draft_pages_with_frontmatter_defaults() {
    let input = tempfile::tempdir().expect("create input tempdir");
    let templates = tempfile::tempdir().expect("create templates tempdir");
    let output = tempfile::tempdir().expect("create output tempdir");

    fs::write(
        input.path().join("design-review-sync.md"),
        "---\ndate: 2026-07-14\ntags: [meetings, design]\npinned: true\nsummary: \"Notes from sync.\"\n---\n# Design review sync\n",
    )
    .expect("write design-review-sync.md");

    fs::write(
        input.path().join("weekly-eng-report.md"),
        "# Weekly eng report\n",
    )
    .expect("write weekly-eng-report.md");

    fs::write(
        input.path().join("unfinished-draft.md"),
        "---\ndraft: true\n---\n# Unfinished draft\n",
    )
    .expect("write unfinished-draft.md");

    fs::write(
        templates.path().join("page.html"),
        "{{ page.content | safe }}",
    )
    .expect("write page.html");

    Builder::new(input.path())
        .templates(templates.path())
        .output(output.path())
        .default_template("page.html")
        .link_base("/")
        .data_json("data.json")
        .build()
        .expect("build should succeed");

    // The draft page must not exist in the HTML output at all.
    assert!(!output.path().join("unfinished-draft.html").is_file());
    assert!(output.path().join("design-review-sync.html").is_file());
    assert!(output.path().join("weekly-eng-report.html").is_file());

    let raw = fs::read_to_string(output.path().join("data.json")).expect("read data.json");
    let entries: Vec<Value> = serde_json::from_str(&raw).expect("data.json must be valid JSON");

    assert_eq!(
        entries.len(),
        2,
        "draft page must be excluded: {entries:#?}"
    );

    let design_review = entries
        .iter()
        .find(|e| e["id"] == "design-review-sync")
        .expect("design-review-sync entry present");
    assert_eq!(
        *design_review,
        json!({
            "id": "design-review-sync",
            "title": "Design review sync",
            "date": "2026-07-14",
            "updated": "",
            "version": "",
            "url": "/design-review-sync",
            "summary": "Notes from sync.",
            "tags": ["meetings", "design"],
            "pinned": true,
        })
    );

    let weekly_report = entries
        .iter()
        .find(|e| e["id"] == "weekly-eng-report")
        .expect("weekly-eng-report entry present");
    assert_eq!(
        *weekly_report,
        json!({
            "id": "weekly-eng-report",
            "title": "Weekly eng report",
            "date": "",
            "updated": "",
            "version": "",
            "url": "/weekly-eng-report",
            "summary": "",
            "tags": [],
            "pinned": false,
        })
    );
}

/// Without `.data_json(...)`, no such file is written at all — explicit over implicit.
#[test]
fn no_data_json_written_when_not_configured() {
    let input = tempfile::tempdir().expect("create input tempdir");
    let templates = tempfile::tempdir().expect("create templates tempdir");
    let output = tempfile::tempdir().expect("create output tempdir");

    fs::write(input.path().join("page.md"), "# Page\n").expect("write page.md");
    fs::write(
        templates.path().join("page.html"),
        "{{ page.content | safe }}",
    )
    .expect("write page.html");

    Builder::new(input.path())
        .templates(templates.path())
        .output(output.path())
        .default_template("page.html")
        .build()
        .expect("build should succeed");

    assert!(!output.path().join("data.json").exists());
}