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` (recommended) or `config.toml`:
36//!
37//! ### Lua Configuration (config.lua)
38//!
39//! Lua configuration provides computed data, dynamic pages, and build hooks:
40//!
41//! ```lua
42//! return {
43//! site = {
44//! title = "My Site",
45//! description = "Site description",
46//! base_url = "https://example.com",
47//! author = "Your Name",
48//! },
49//!
50//! -- Computed data available in templates as {{ computed.tags }}
51//! computed = {
52//! tags = function(sections) return {...} end,
53//! },
54//!
55//! -- Generate dynamic pages
56//! computed_pages = function(sections)
57//! return {{ path = "/tags/array/", template = "tag.html", title = "Array", data = {...} }}
58//! end,
59//!
60//! -- Custom Tera filters: {{ value | my_filter }}
61//! filters = {
62//! shout = function(s) return s:upper() .. "!" end,
63//! },
64//!
65//! -- Build hooks
66//! hooks = {
67//! before_build = function() print("Starting...") end,
68//! after_build = function() print("Done!") end,
69//! },
70//! }
71//! ```
72//!
73//! #### Lua Sandbox
74//!
75//! By default, file operations are sandboxed to the project directory.
76//! To disable (use with caution):
77//!
78//! ```lua
79//! return {
80//! lua = { sandbox = false },
81//! site = { ... },
82//! }
83//! ```
84//!
85//! #### Lua API Functions
86//!
87//! - `read_file(path)` - Read file contents
88//! - `write_file(path, content)` - Write content to file
89//! - `file_exists(path)` - Check if file exists
90//! - `list_files(path, pattern?)` - List files matching pattern
91//! - `list_dirs(path)` - List subdirectories
92//! - `load_json(path)` - Load and parse JSON file
93//! - `env(name)` - Get environment variable
94//! - `print(...)` - Log output to build log
95//!
96//! All file operations respect the sandbox setting.
97//!
98//! ### TOML Configuration (config.toml)
99//!
100//! ### Required Settings
101//!
102//! ```toml
103//! [site]
104//! title = "My Site" # Site title
105//! description = "Site description" # Site description
106//! base_url = "https://example.com" # Base URL (no trailing slash)
107//! author = "Your Name" # Author name
108//!
109//! [seo]
110//! twitter_handle = "@username" # Optional: Twitter handle
111//! default_og_image = "/static/og.png" # Optional: Default OG image
112//!
113//! [build]
114//! output_dir = "dist" # Output directory
115//! minify_css = true # Default: true
116//!
117//! [images]
118//! quality = 85.0 # WebP quality (default: 85.0)
119//! scale_factor = 1.0 # Image scale (default: 1.0)
120//! ```
121//!
122//! ### Optional Settings (have defaults)
123//!
124//! ```toml
125//! [paths]
126//! content = "content" # Content directory (default: "content")
127//! styles = "styles" # Styles directory (default: "styles")
128//! static_files = "static" # Static files (default: "static")
129//! templates = "templates" # Templates (default: "templates")
130//! home = "index.md" # Home page file (default: "index.md")
131//! exclude = ["drafts", "^temp.*"] # Regex patterns to exclude files/dirs (default: [])
132//! exclude_defaults = true # Exclude README.md, LICENSE.md, etc. (default: true)
133//!
134//! [highlight]
135//! names = ["John Doe", "Jane Doe"] # Names to highlight (default: [])
136//! class = "me" # CSS class for highlights (default: "me")
137//!
138//! [templates]
139//! blog = "post.html" # Section -> template mapping
140//! projects = "project.html" # (default: uses {section}.html or post.html)
141//!
142//! [permalinks]
143//! blog = "/:year/:month/:slug/" # Section -> URL pattern
144//! projects = "/:slug/" # Placeholders: :year :month :day :slug :title :section
145//!
146//! [encryption]
147//! password_command = "pass show site" # Command to get password (optional)
148//! password = "secret" # Raw password (optional, less secure)
149//! # Priority: SITE_PASSWORD env > command > password
150//!
151//! [graph]
152//! enabled = true # Enable graph generation (default: true)
153//! template = "graph.html" # Graph page template (default: "graph.html")
154//! path = "graph" # URL path (default: "graph" -> /graph/)
155//!
156//! [rss]
157//! enabled = true # Enable RSS generation (default: true)
158//! filename = "rss.xml" # Output filename (default: "rss.xml")
159//! sections = ["blog"] # Sections to include (default: [] = all)
160//! limit = 20 # Max items (default: 20)
161//! exclude_encrypted_blocks = false # Exclude posts with :::encrypted (default: false)
162//!
163//! [text]
164//! enabled = false # Enable plain text generation (default: false)
165//! sections = ["blog"] # Sections to include (default: [] = all)
166//! exclude_encrypted = false # Exclude encrypted posts (default: false)
167//! include_home = true # Include home page as index.txt (default: true)
168//! ```
169//!
170//! ## Root Pages
171//!
172//! Markdown files at the content root (besides the home page) are processed as
173//! standalone pages. For example, `404.md` becomes `404.html`:
174//!
175//! ```yaml
176//! ---
177//! title: "404 - Page Not Found"
178//! template: "error.html"
179//! ---
180//!
181//! # Page Not Found
182//! The page you're looking for doesn't exist.
183//! ```
184//!
185//! Default excluded files (disable with `exclude_defaults = false`):
186//! - README.md, LICENSE.md, CHANGELOG.md, CONTRIBUTING.md, CODE_OF_CONDUCT.md
187//! - Hidden files (starting with `.`)
188//!
189//! ## Frontmatter
190//!
191//! Post frontmatter options (YAML or TOML):
192//!
193//! ```yaml
194//! ---
195//! title: "Post Title" # Required
196//! description: "Description" # Optional
197//! date: 2024-01-15 # Optional (YAML date or string)
198//! tags: ["tag1", "tag2"] # Optional
199//! draft: false # Optional (default: false, excluded from build)
200//! image: "/static/post.png" # Optional: OG image
201//! template: "custom.html" # Optional: Override template
202//! slug: "custom-slug" # Optional: Override URL slug
203//! permalink: "/custom/url/" # Optional: Full URL override
204//! encrypted: false # Optional: Encrypt entire post
205//! password: "post-secret" # Optional: Post-specific password
206//! ---
207//! ```
208//!
209//! ## Partial Encryption
210//!
211//! Use `:::encrypted` blocks for partial content encryption:
212//!
213//! ```markdown
214//! Public content here.
215//!
216//! :::encrypted
217//! This content is encrypted with the global/post password.
218//! :::
219//!
220//! :::encrypted password="custom"
221//! This block has its own password.
222//! :::
223//! ```
224//!
225//! ## Template Variables
226//!
227//! ### Home Template (`home.html`)
228//! - `site` - Site config (title, description, base_url, author)
229//! - `page` - Page info (title, description, url, image)
230//! - `sections` - All sections with posts (`sections.blog.posts`)
231//! - `content` - Rendered markdown content
232//!
233//! ### Post Template (`post.html`)
234//! - `site` - Site config
235//! - `post` - Post info (title, url, date, tags, reading_time, etc.)
236//! - `page` - Page info for head.html compatibility
237//! - `content` - Rendered markdown content
238//! - `backlinks` - Posts linking to this post (url, title, section)
239//! - `graph` - Local graph data (nodes, edges) for visualization
240//!
241//! ### Graph Template (`graph.html`)
242//! - `site` - Site config
243//! - `page` - Page info
244//! - `graph` - Full graph data (nodes, edges)
245//!
246//! ## Modules
247//!
248//! - [`config`] - Configuration loading and structures
249//! - [`content`] - Content discovery and post/page models
250//! - [`markdown`] - Markdown processing pipeline
251//! - [`templates`] - Tera template rendering
252//! - [`encryption`] - AES-GCM encryption for protected content
253//! - [`links`] - Link graph and backlink generation
254//! - [`rss`] - RSS feed generation
255//! - [`text`] - Plain text output for curl-friendly access
256//! - [`assets`] - CSS building and image optimization
257//! - [`build`] - Main build orchestrator
258
259pub mod assets;
260pub mod build;
261pub mod config;
262pub mod content;
263pub mod data;
264pub mod encryption;
265pub mod git;
266pub mod links;
267pub mod lua_config;
268pub mod markdown;
269pub mod rss;
270pub mod templates;
271pub mod text;
272pub mod watch;