Skip to main content

simple_gal/
types.rs

1//! Shared types used across all pipeline stages.
2//!
3//! These types are serialized to JSON between stages (scan → process → generate)
4//! and must be identical across all three modules.
5
6use serde::{Deserialize, Serialize};
7
8/// A page generated from a markdown file in the content root.
9///
10/// Pages follow the same numbering convention as albums:
11/// - Numbered files (`NNN-name.md`) appear in navigation, sorted by number
12/// - Unnumbered files are generated but hidden from navigation
13///
14/// If the file content is just a URL, the page becomes an external link in nav.
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct Page {
17    /// Title from first `# heading` in markdown, or link_title as fallback
18    pub title: String,
19    /// Display label in nav (filename with number stripped and dashes → spaces)
20    pub link_title: String,
21    /// URL slug (filename stem with number prefix stripped)
22    pub slug: String,
23    /// Raw markdown content (or URL for link pages)
24    pub body: String,
25    /// Whether this page appears in navigation (has number prefix)
26    pub in_nav: bool,
27    /// Sort key from number prefix (for ordering)
28    pub sort_key: u32,
29    /// If true, body is a URL and this page is an external link
30    pub is_link: bool,
31}
32
33/// Navigation tree item (only numbered directories).
34///
35/// Leaf items (no children) correspond to albums. Items with children are
36/// container directories (groups) that generate gallery-list pages. Container
37/// items can carry an optional `description` read from `description.md`/`.txt`
38/// in the container directory.
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct NavItem {
41    pub title: String,
42    pub path: String,
43    #[serde(default, skip_serializing_if = "String::is_empty")]
44    pub source_dir: String,
45    /// Optional description for container directories, rendered on their gallery-list page.
46    #[serde(default, skip_serializing_if = "Option::is_none")]
47    pub description: Option<String>,
48    #[serde(default, skip_serializing_if = "Vec::is_empty")]
49    pub children: Vec<NavItem>,
50}