Crate rs_web

Crate rs_web 

Source
Expand description

§rs-web - Static Site Generator

A fast, opinionated static site generator built in Rust with support for:

  • Markdown processing with syntax highlighting, external link handling
  • Content encryption via Lua (rs.crypt module)
  • Link graph with backlinks and visualization (Obsidian-style)
  • RSS feed generation with section filtering
  • Parallel processing for fast builds
  • Live reload with automatic browser refresh during watch mode
  • Asset minification for CSS, JS (with dead code elimination), and HTML

§Quick Start

# Build the site
rs-web build

# Build to custom output directory
rs-web build --output public

# Watch for changes and rebuild incrementally with live reload
rs-web build --watch

# Watch mode with custom port
rs-web build --watch --port 8080

# Enable debug logging
rs-web --debug build

# Set specific log level (trace, debug, info, warning, error)
rs-web --log-level trace build

# Or use environment variable
RS_WEB_LOG_LEVEL=debug rs-web build

§Configuration

Configure via config.lua:

return {
  site = {
    title = "My Site",
    description = "Site description",
    base_url = "https://example.com",
    author = "Your Name",
  },

  build = {
    output_dir = "dist",
  },

  -- Generate pages via Lua
  pages = function()
    return {
      { path = "/", template = "home.html", title = "Home" },
      { path = "/about/", template = "page.html", title = "About", minify = true },
    }
  end,

  -- Build hooks
  hooks = {
    before_build = function() print("Starting...") end,
    after_build = function() print("Done!") end,
  },
}

§Configuration Sections

  • site - Required: title, description, base_url, author
  • seo - twitter_handle, default_og_image
  • build - output_dir
  • paths - templates

§Lua Sandbox

By default, file operations are sandboxed to the project directory. To disable (use with caution):

return {
  lua = { sandbox = false },
  site = { ... },
}

§Lua API Functions

File Operations:

  • read_file(path) - Read file contents
  • write_file(path, content) - Write content to file
  • copy_file(src, dest) - Copy file (binary-safe)
  • file_exists(path) - Check if file exists
  • list_files(path, pattern?) - List files matching pattern
  • list_dirs(path) - List subdirectories
  • load_json(path) - Load and parse JSON file
  • load_yaml(path) - Load and parse YAML file
  • load_toml(path) - Load and parse TOML file
  • read_frontmatter(path) - Extract frontmatter and content from markdown

Content Processing:

  • html_to_text(html) - Convert HTML to plain text

Date & Time (rs.date):

  • now() - Get current Unix timestamp
  • from_timestamp(ts) - Convert Unix timestamp to DateTime table
  • to_timestamp(date) - Convert date to Unix timestamp
  • format(date, format) - Format date using strftime
  • parse(str, format?) - Parse date string (auto-detects or custom format)
  • rss_format(date) - Format for RSS (RFC 2822)
  • iso_format(date) - Format as ISO 8601
  • add(date, delta) - Add time to date
  • diff(date1, date2) - Difference in seconds

Markdown (rs.markdown):

  • render(content, opts?) - Render markdown to HTML with optional plugins
  • plugins(...) - Combine/flatten plugins
  • plugins.default(opts?) - Get default plugins (lazy_images, heading_anchors, external_links)
  • plugins.lazy_images(opts?) - Plugin: add loading=“lazy” decoding=“async” to images
  • plugins.heading_anchors(opts?) - Plugin: add id=“slug” to headings
  • plugins.external_links(opts?) - Plugin: add target=“_blank” rel=“noopener” to external links

Image Processing:

  • image_dimensions(path) - Get image width and height
  • image_resize(input, output, options) - Resize image
  • image_convert(input, output, options?) - Convert image format
  • image_optimize(input, output, options?) - Optimize/compress image

Fonts (rs.fonts):

  • download_google_font(family, options) - Download Google Font with optional CSS minification (async)

JS Module (rs.js):

  • concat(paths, output, options?) - Concatenate JS files with optional minification (async)
  • bundle(entry, output, options?) - Bundle JS with imports via Rolldown (async)
  • bundle_many(entries, output_dir, options?) - Bundle multiple JS entries to separate files (async)

CSS Module (rs.css):

  • concat(paths, output, options?) - Concatenate CSS files with optional minification (async)
  • bundle(paths, output, options?) - Bundle CSS with @import resolution via LightningCSS (async)
  • bundle_many(paths, output_dir, options?) - Bundle multiple CSS entries to separate files (async)
  • purge(css_path, options?) - Remove unused CSS rules based on HTML/JS output (async, call in after_build)
  • critical(html, css_path, options?) - Extract critical CSS for a specific HTML page (async)
  • inline_critical(html_path, css_path, options?) - Inline critical CSS into HTML with async loading (async)

Asset Hashing (rs.assets):

  • hash(content, length?) - Compute SHA256 hash of content (async)
  • hash_sync(content, length?) - Compute hash synchronously
  • write_hashed(content, path, options?) - Write file with hashed filename (async)
  • register(original, hashed) - Register asset path mapping
  • get_path(path) - Get hashed path for original
  • manifest() - Get all path mappings
  • clear() - Clear the manifest

PWA (rs.pwa):

  • manifest(options) - Generate web app manifest.json (async)
  • service_worker(options) - Generate service worker sw.js (async)

SEO (rs.seo):

  • sitemap(options) - Generate XML sitemap (async)
  • robots(options) - Generate robots.txt (async)

Text Processing:

  • slugify(text) - Convert text to URL-friendly slug
  • word_count(text) - Count words in text
  • reading_time(text, wpm?) - Calculate reading time in minutes
  • truncate(text, len, suffix?) - Truncate text with optional suffix
  • strip_tags(html) - Remove HTML tags
  • hash(content) - Hash content (xxHash64)
  • hash_file(path) - Hash file contents
  • url_encode(str) - URL encode a string
  • url_decode(str) - URL decode a string

Path Utilities:

  • join_path(...) - Join path segments
  • basename(path) - Get file name from path
  • dirname(path) - Get directory from path
  • extension(path) - Get file extension

Collections:

  • filter(items, fn) - Filter items where fn returns true
  • sort(items, fn) - Sort items using comparator
  • map(items, fn) - Transform each item
  • find(items, fn) - Find first item where fn returns true
  • group_by(items, key_fn) - Group items by key
  • unique(items) - Remove duplicates
  • reverse(items) - Reverse array order
  • take(items, n) - Take first n items
  • skip(items, n) - Skip first n items
  • keys(table) - Get all keys from a table
  • values(table) - Get all values from a table

Environment:

  • env(name, default?) - Get environment variable with optional default
  • print(...) - Log output to build log
  • git_info(path?) - Get git info (hash, branch, author, timestamp, dirty)

Parallel (rs.parallel): Rayon-backed true parallel operations

  • load_json(paths) / load_yaml(paths) - Load multiple files in parallel
  • read_files(paths) / read_frontmatter(paths) - Read multiple files
  • create_dirs(paths) / copy_files(sources, dests) - Parallel file operations
  • image_convert(sources, dests, opts?) - Convert images in parallel
  • map(items, fn, ctx?) / filter(items, fn, ctx?) - Parallel map/filter with explicit context
  • map_seq(items, fn) / filter_seq(items, fn) - Sequential fallbacks for non-serializable items

Async I/O (rs.async): All return handles, await with rs.async.await(task) or rs.async.await_all(tasks)

  • fetch(url, opts?) / fetch_bytes(url, opts?) - HTTP fetch (text/binary)
  • fetch_sync(url, opts?) - Blocking fetch (returns response directly)
  • write_file(path, content) / write(path, bytes) - Write text/binary
  • copy_file(src, dst) / create_dir(path) - File/dir operations
  • exists(path) / read_file(path) - Check existence / read file

Encryption (rs.crypt):

  • encrypt(content, password?) - Encrypt content (AES-256-GCM)
  • decrypt(data, password?) - Decrypt content
  • encrypt_html(content, options?) - Generate encrypted HTML block for browser decryption

All file operations respect the sandbox setting and are tracked for incremental builds. Encryption uses SITE_PASSWORD environment variable if password is not provided.

§Frontmatter

Post frontmatter options (YAML or TOML):

---
title: "Post Title"           # Required
description: "Description"    # Optional
date: 2024-01-15              # Optional (YAML date or string)
tags: ["tag1", "tag2"]        # Optional
draft: false                  # Optional (default: false, excluded from build)
image: "/static/post.png"     # Optional: OG image
template: "custom.html"       # Optional: Override template
slug: "custom-slug"           # Optional: Override URL slug
permalink: "/custom/url/"     # Optional: Full URL override
---

§Encryption

Encryption is handled via the rs.crypt module in Lua. Use SITE_PASSWORD environment variable or pass password explicitly:

-- Encrypt content
local encrypted = rs.crypt.encrypt("secret content")
-- Returns: { ciphertext, salt, nonce }

-- Generate encrypted HTML block for browser decryption
local html = rs.crypt.encrypt_html("secret content", {
  slug = "post-slug",
  block_id = "secret-1",
})

-- Decrypt content
local plaintext = rs.crypt.decrypt(encrypted)

§Template Variables

§Home Template (home.html)

  • site - Site config (title, description, base_url, author)
  • page - Page info (title, description, url, image)
  • sections - All sections with posts (sections.blog.posts)
  • content - Rendered markdown content

§Post Template (post.html)

  • site - Site config
  • post - Post info (title, url, date, tags, reading_time, etc.)
  • page - Page info for head.html compatibility
  • content - Rendered markdown content
  • backlinks - Posts linking to this post (url, title, section)
  • graph - Local graph data (nodes, edges) for visualization

§Graph Template (graph.html)

  • site - Site config
  • page - Page info
  • graph - Full graph data (nodes, edges)

§Modules

  • config - Configuration loading and structures
  • lua - Lua API including rs.markdown for markdown processing
  • templates - Tera template rendering
  • encryption - AES-256-GCM encryption utilities (used by rs.crypt Lua module)
  • build - Main build orchestrator

Modules§

assets
Asset processing (CSS bundling, image optimization)
build
Build orchestrator for static site generation
config
Configuration loader for rs-web
data
Tera template functions for data loading and content rendering
encryption
AES-256-GCM encryption with Argon2id key derivation
git
Git integration for commit info and file history
lua
Lua API for rs-web Usage in Lua:
server
Development server with WebSocket live reload
templates
Tera template engine wrapper with page rendering
text
Plain text generation from HTML content
tracker
Build dependency tracker for incremental builds
watch
File watcher for incremental rebuilds

Macros§

rs_print
Print output at info level (always shown regardless of log level)