rs_web/
lib.rs

1//! # rs-web - Static Site Generator
2//!
3//! A fast, opinionated static site generator built in Rust with support for:
4//!
5//! - **Markdown processing** with syntax highlighting, external link handling
6//! - **Content encryption** (full post or partial `:::encrypted` blocks)
7//! - **Link graph** with backlinks and visualization (Obsidian-style)
8//! - **RSS feed** generation with section filtering
9//! - **Parallel processing** for fast builds
10//!
11//! ## Quick Start
12//!
13//! ```bash
14//! # Build the site
15//! rs-web build
16//!
17//! # Build to custom output directory
18//! rs-web build --output public
19//!
20//! # Watch for changes and rebuild incrementally
21//! rs-web build --watch
22//!
23//! # Enable debug logging
24//! rs-web --debug build
25//!
26//! # Set specific log level (trace, debug, info, warning, error)
27//! rs-web --log-level trace build
28//!
29//! # Or use environment variable
30//! RS_WEB_LOG_LEVEL=debug rs-web build
31//! ```
32//!
33//! ## Configuration
34//!
35//! Configure via `config.lua`:
36//!
37//! ```lua
38//! return {
39//!   site = {
40//!     title = "My Site",
41//!     description = "Site description",
42//!     base_url = "https://example.com",
43//!     author = "Your Name",
44//!   },
45//!
46//!   build = {
47//!     output_dir = "dist",
48//!     minify_css = true,
49//!   },
50//!
51//!   -- Section configuration with custom sort
52//!   sections = {
53//!     blog = {
54//!       iterate = "files",
55//!       sort_by = function(a, b)
56//!         -- C-style comparator: return -1, 0, or 1
57//!         if a.date < b.date then return -1
58//!         elseif a.date > b.date then return 1
59//!         else return 0 end
60//!       end,
61//!     },
62//!   },
63//!
64//!   -- Computed data available in templates as {{ computed.tags }}
65//!   computed = {
66//!     tags = function(sections) return {...} end,
67//!   },
68//!
69//!   -- Generate dynamic pages
70//!   computed_pages = function(sections)
71//!     return {{ path = "/tags/array/", template = "tag.html", title = "Array", data = {...} }}
72//!   end,
73//!
74//!   -- Custom Tera filters: {{ value | my_filter }}
75//!   filters = {
76//!     shout = function(s) return s:upper() .. "!" end,
77//!   },
78//!
79//!   -- Build hooks
80//!   hooks = {
81//!     before_build = function() print("Starting...") end,
82//!     after_build = function() print("Done!") end,
83//!   },
84//! }
85//! ```
86//!
87//! ### Configuration Sections
88//!
89//! - `site` - Required: title, description, base_url, author
90//! - `build` - output_dir, minify_css (default: true)
91//! - `images` - quality (default: 85.0), scale_factor (default: 1.0)
92//! - `paths` - content, styles, static_files, templates, home, exclude
93//! - `sections` - Per-section config with iterate ("files"/"directories") and sort_by function
94//! - `templates` - Section -> template file mapping
95//! - `permalinks` - Section -> URL pattern (`:year`, `:month`, `:slug`, `:title`, `:section`)
96//! - `encryption` - password_command or password (SITE_PASSWORD env takes priority)
97//! - `graph` - enabled, template, path
98//! - `rss` - enabled, filename, sections, limit
99//! - `text` - enabled, sections, exclude_encrypted, include_home
100//!
101//! ### Lua Sandbox
102//!
103//! By default, file operations are sandboxed to the project directory.
104//! To disable (use with caution):
105//!
106//! ```lua
107//! return {
108//!   lua = { sandbox = false },
109//!   site = { ... },
110//! }
111//! ```
112//!
113//! ### Lua API Functions
114//!
115//! - `read_file(path)` - Read file contents
116//! - `write_file(path, content)` - Write content to file
117//! - `file_exists(path)` - Check if file exists
118//! - `list_files(path, pattern?)` - List files matching pattern
119//! - `list_dirs(path)` - List subdirectories
120//! - `load_json(path)` - Load and parse JSON file
121//! - `env(name)` - Get environment variable
122//! - `print(...)` - Log output to build log
123//!
124//! All file operations respect the sandbox setting.
125//!
126//! ## Root Pages
127//!
128//! Markdown files at the content root (besides the home page) are processed as
129//! standalone pages. For example, `404.md` becomes `404.html`:
130//!
131//! ```yaml
132//! ---
133//! title: "404 - Page Not Found"
134//! template: "error.html"
135//! ---
136//!
137//! # Page Not Found
138//! The page you're looking for doesn't exist.
139//! ```
140//!
141//! Default excluded files (disable with `exclude_defaults = false`):
142//! - README.md, LICENSE.md, CHANGELOG.md, CONTRIBUTING.md, CODE_OF_CONDUCT.md
143//! - Hidden files (starting with `.`)
144//!
145//! ## Frontmatter
146//!
147//! Post frontmatter options (YAML or TOML):
148//!
149//! ```yaml
150//! ---
151//! title: "Post Title"           # Required
152//! description: "Description"    # Optional
153//! date: 2024-01-15              # Optional (YAML date or string)
154//! tags: ["tag1", "tag2"]        # Optional
155//! draft: false                  # Optional (default: false, excluded from build)
156//! image: "/static/post.png"     # Optional: OG image
157//! template: "custom.html"       # Optional: Override template
158//! slug: "custom-slug"           # Optional: Override URL slug
159//! permalink: "/custom/url/"     # Optional: Full URL override
160//! encrypted: false              # Optional: Encrypt entire post
161//! password: "post-secret"       # Optional: Post-specific password
162//! ---
163//! ```
164//!
165//! ## Partial Encryption
166//!
167//! Use `:::encrypted` blocks for partial content encryption:
168//!
169//! ```markdown
170//! Public content here.
171//!
172//! :::encrypted
173//! This content is encrypted with the global/post password.
174//! :::
175//!
176//! :::encrypted password="custom"
177//! This block has its own password.
178//! :::
179//! ```
180//!
181//! ## Template Variables
182//!
183//! ### Home Template (`home.html`)
184//! - `site` - Site config (title, description, base_url, author)
185//! - `page` - Page info (title, description, url, image)
186//! - `sections` - All sections with posts (`sections.blog.posts`)
187//! - `content` - Rendered markdown content
188//!
189//! ### Post Template (`post.html`)
190//! - `site` - Site config
191//! - `post` - Post info (title, url, date, tags, reading_time, etc.)
192//! - `page` - Page info for head.html compatibility
193//! - `content` - Rendered markdown content
194//! - `backlinks` - Posts linking to this post (url, title, section)
195//! - `graph` - Local graph data (nodes, edges) for visualization
196//!
197//! ### Graph Template (`graph.html`)
198//! - `site` - Site config
199//! - `page` - Page info
200//! - `graph` - Full graph data (nodes, edges)
201//!
202//! ## Modules
203//!
204//! - [`config`] - Configuration loading and structures
205//! - [`content`] - Content discovery and post/page models
206//! - [`markdown`] - Markdown processing pipeline
207//! - [`templates`] - Tera template rendering
208//! - [`encryption`] - AES-GCM encryption for protected content
209//! - [`links`] - Link graph and backlink generation
210//! - [`rss`] - RSS feed generation
211//! - [`text`] - Plain text output for curl-friendly access
212//! - [`assets`] - CSS building and image optimization
213//! - [`build`] - Main build orchestrator
214
215pub mod assets;
216pub mod build;
217pub mod config;
218pub mod content;
219pub mod data;
220pub mod encryption;
221pub mod git;
222pub mod links;
223pub mod markdown;
224pub mod rss;
225pub mod templates;
226pub mod text;
227pub mod watch;