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;