rs_web/lua/
mod.rs

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