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.markdown.render(content)
7//! ```
8
9mod assets;
10mod async_io;
11mod coro;
12mod crypt;
13mod css;
14mod data;
15mod date;
16mod env;
17mod fonts;
18mod fs;
19mod git;
20mod hash;
21mod helpers;
22mod highlight;
23mod html;
24mod image;
25mod js;
26mod log;
27mod markdown;
28mod ops;
29mod parallel;
30mod path;
31mod portable;
32mod pwa;
33mod seo;
34mod text;
35mod types;
36
37pub use assets::{AssetManifest, create_manifest};
38pub use helpers::{is_path_within_root, parse_frontmatter_content, resolve_path};
39pub use highlight::highlight_code_sync;
40pub use types::{LuaClass, LuaField, LuaFunction, LuaParam, generate_emmylua, generate_markdown};
41
42use crate::tracker::SharedTracker;
43use mlua::{Lua, Result, Table};
44use std::path::Path;
45
46/// Register all Lua functions as a require-able module
47///
48/// This function registers the rs-web module so it can be used with:
49/// ```lua
50/// local rs = require("rs-web")
51/// ```
52///
53/// The module provides:
54/// - File operations: rs.read_file, rs.write_file, rs.load_json, etc.
55/// - Search: rs.glob, rs.scan
56/// - Collections: rs.filter, rs.sort, rs.map
57/// - Text: rs.slugify, rs.word_count, rs.reading_time
58/// - Environment: rs.env, rs.print, rs.is_gitignored
59/// - Git: rs.git_info
60/// - Content: rs.rss_date, rs.html_to_text, etc.
61/// - Markdown: rs.markdown.render, rs.markdown.plugins
62/// - Images: rs.image_dimensions, rs.image_resize, rs.image_convert, rs.image_optimize
63/// - JS: rs.js.concat, rs.js.bundle
64/// - CSS: rs.css.concat, rs.css.bundle
65/// - Fonts: rs.fonts.download_google_font
66/// - Assets: rs.assets.hash, rs.assets.write_hashed, rs.assets.get_path
67/// - PWA: rs.pwa.manifest, rs.pwa.service_worker
68/// - SEO: rs.seo.sitemap, rs.seo.robots
69/// - Coroutines: rs.coro.task, rs.coro.await, rs.coro.yield, etc.
70/// - Parallel (rayon): rs.parallel.load_json, rs.parallel.read_files, etc.
71/// - Async I/O (tokio): rs.async.fetch, rs.async.read_file, rs.async.write_file, etc.
72/// - Encryption: rs.crypt.encrypt, rs.crypt.decrypt, rs.crypt.encrypt_html
73pub fn register(
74    lua: &Lua,
75    project_root: &Path,
76    sandbox: bool,
77    tracker: SharedTracker,
78    global_password: Option<String>,
79    asset_manifest: AssetManifest,
80) -> Result<()> {
81    let root = project_root.to_path_buf();
82
83    // Create the main module table
84    let rs_module = lua.create_table()?;
85
86    // Store metadata
87    rs_module.set("_VERSION", env!("CARGO_PKG_VERSION"))?;
88    rs_module.set("_SANDBOX", sandbox)?;
89    rs_module.set("_PROJECT_ROOT", project_root.to_string_lossy().to_string())?;
90
91    let ops_module = ops::create_module(lua)?;
92    rs_module.set("ops", ops_module)?;
93
94    let fs_module = fs::create_module(lua, &root, sandbox, tracker.clone())?;
95    rs_module.set("fs", fs_module)?;
96
97    let data_module = data::create_module(lua, &root, sandbox, tracker.clone())?;
98    rs_module.set("data", data_module)?;
99
100    let image_module = image::create_module(lua, &root, tracker.clone())?;
101    rs_module.set("image", image_module)?;
102
103    let text_module = text::create_module(lua)?;
104    rs_module.set("text", text_module)?;
105
106    let date_module = date::create_module(lua)?;
107    rs_module.set("date", date_module)?;
108
109    let path_module = path::create_module(lua)?;
110    rs_module.set("path", path_module)?;
111
112    let hash_module = hash::create_module(lua)?;
113    rs_module.set("hash", hash_module)?;
114
115    let git_module = git::create_module(lua, &root, sandbox)?;
116    rs_module.set("git", git_module)?;
117
118    let html_module = html::create_module(lua, tracker.clone())?;
119    rs_module.set("html", html_module)?;
120
121    let log_module = log::create_module(lua)?;
122    rs_module.set("log", log_module)?;
123
124    let env_module = env::create_module(lua)?;
125    rs_module.set("env", env_module)?;
126
127    let js_module = js::create_module(lua, &root, tracker.clone())?;
128    rs_module.set("js", js_module)?;
129
130    let css_module = css::create_module(lua, &root, tracker.clone())?;
131    rs_module.set("css", css_module)?;
132
133    let fonts_module = fonts::create_module(lua, &root, tracker.clone())?;
134    rs_module.set("fonts", fonts_module)?;
135
136    // Register coro and parallel as submodules
137    let coro_module = coro::create_module(lua)?;
138    rs_module.set("coro", coro_module)?;
139
140    let parallel_module = parallel::create_module(lua, &root, sandbox, tracker.clone())?;
141    rs_module.set("parallel", parallel_module)?;
142
143    let async_module = async_io::create_module(lua, &root, sandbox, tracker.clone())?;
144    // Use raw_set to avoid "async" being a reserved word in some contexts
145    rs_module.raw_set("async", async_module)?;
146
147    let crypt_module = crypt::create_module(lua, global_password)?;
148    rs_module.set("crypt", crypt_module)?;
149
150    let highlight_module = highlight::create_module(lua)?;
151    rs_module.set("highlight", highlight_module)?;
152
153    let assets_module = assets::create_module(lua, &root, asset_manifest, tracker.clone())?;
154    rs_module.set("assets", assets_module)?;
155
156    let pwa_module = pwa::create_module(lua, &root, tracker.clone())?;
157    rs_module.set("pwa", pwa_module)?;
158
159    let seo_module = seo::create_module(lua, &root, tracker.clone())?;
160    rs_module.set("seo", seo_module)?;
161
162    // Register markdown module (rs.markdown.render, rs.markdown.plugins)
163    markdown::register(lua, &rs_module, tracker)?;
164
165    // Register as a preloaded module so require("rs-web") works
166    let preload: Table = lua
167        .globals()
168        .get::<Table>("package")?
169        .get::<Table>("preload")?;
170
171    let loader = lua.create_function(move |_, _: ()| Ok(rs_module.clone()))?;
172    preload.set("rs-web", loader)?;
173
174    Ok(())
175}