rs_web/lua/
mod.rs

1//! Lua API functions for rs-web
2//!
3//! This module provides all Lua functions available in config.lua,
4//! organized by category for maintainability.
5//!
6//! Usage in Lua:
7//! ```lua
8//! local rs = require("rs-web")
9//! local content = rs.read_file("path/to/file.md")
10//! local html = rs.render_markdown(content)
11//! ```
12
13mod assets;
14mod async_io;
15mod collections;
16mod content;
17mod coro;
18mod crypt;
19mod env;
20mod file_ops;
21mod git;
22mod helpers;
23mod images;
24mod markdown_context;
25mod parallel;
26mod search;
27mod text;
28pub mod tracker;
29mod types;
30
31pub use helpers::{is_path_within_root, parse_frontmatter_content, resolve_path};
32pub use tracker::{BuildTracker, CachedDeps, SharedTracker};
33pub use types::{LuaClass, LuaField, LuaFunction, LuaParam, generate_emmylua, generate_markdown};
34
35use mlua::{Lua, Result, Table};
36use std::path::Path;
37
38/// Register all Lua functions as a require-able module
39///
40/// This function registers the rs-web module so it can be used with:
41/// ```lua
42/// local rs = require("rs-web")
43/// ```
44///
45/// The module provides:
46/// - File operations: rs.read_file, rs.write_file, rs.load_json, etc.
47/// - Search: rs.glob, rs.scan
48/// - Collections: rs.filter, rs.sort, rs.map
49/// - Text: rs.slugify, rs.word_count, rs.reading_time
50/// - Environment: rs.env, rs.print, rs.is_gitignored
51/// - Git: rs.git_info
52/// - Content: rs.render_markdown, rs.rss_date, rs.html_to_text, etc.
53/// - Images: rs.image_dimensions, rs.image_resize, rs.image_convert, rs.image_optimize
54/// - Assets: rs.build_css
55/// - Coroutines: rs.coro.task, rs.coro.await, rs.coro.yield, etc.
56/// - Parallel (rayon): rs.parallel.load_json, rs.parallel.read_files, etc.
57/// - Async I/O (tokio): rs.async.fetch, rs.async.read_file, rs.async.write_file, etc.
58/// - Encryption: rs.crypt.encrypt, rs.crypt.decrypt, rs.crypt.encrypt_html
59pub fn register(
60    lua: &Lua,
61    project_root: &Path,
62    sandbox: bool,
63    tracker: SharedTracker,
64    global_password: Option<String>,
65) -> Result<()> {
66    let root = project_root.to_path_buf();
67
68    // Create the main module table
69    let rs_module = lua.create_table()?;
70
71    // Store metadata
72    rs_module.set("_VERSION", env!("CARGO_PKG_VERSION"))?;
73    rs_module.set("_SANDBOX", sandbox)?;
74    rs_module.set("_PROJECT_ROOT", project_root.to_string_lossy().to_string())?;
75
76    // Register all function categories on the module
77    file_ops::register(lua, &rs_module, &root, sandbox, tracker.clone())?;
78    search::register(lua, &rs_module, &root, sandbox)?;
79    collections::register(lua, &rs_module)?;
80    text::register(lua, &rs_module)?;
81    env::register(lua, &rs_module, &root)?;
82    git::register(lua, &rs_module, &root, sandbox)?;
83    content::register(lua, &rs_module, tracker.clone())?;
84    images::register(lua, &rs_module, &root, tracker.clone())?;
85    assets::register(lua, &rs_module, &root, tracker.clone())?;
86
87    // Register coro and parallel as submodules
88    let coro_module = coro::create_module(lua)?;
89    rs_module.set("coro", coro_module)?;
90
91    let parallel_module = parallel::create_module(lua, &root, sandbox, tracker.clone())?;
92    rs_module.set("parallel", parallel_module)?;
93
94    let async_module = async_io::create_module(lua, &root, sandbox)?;
95    // Use raw_set to avoid "async" being a reserved word in some contexts
96    rs_module.raw_set("async", async_module)?;
97
98    let crypt_module = crypt::create_module(lua, global_password)?;
99    rs_module.set("crypt", crypt_module)?;
100
101    // Register as a preloaded module so require("rs-web") works
102    let preload: Table = lua
103        .globals()
104        .get::<Table>("package")?
105        .get::<Table>("preload")?;
106
107    let rs_module_clone = rs_module.clone();
108    let loader = lua.create_function(move |_, _: ()| Ok(rs_module_clone.clone()))?;
109    preload.set("rs-web", loader)?;
110    lua.globals().set("rs", rs_module)?;
111
112    Ok(())
113}