diff options
Diffstat (limited to 'src/theming')
-rw-r--r-- | src/theming/hbs.rs | 4 | ||||
-rw-r--r-- | src/theming/lua-lib/expect.lua | 6 | ||||
-rw-r--r-- | src/theming/lua-lib/html.lua | 14 | ||||
-rw-r--r-- | src/theming/lua.rs | 39 |
4 files changed, 42 insertions, 21 deletions
diff --git a/src/theming/hbs.rs b/src/theming/hbs.rs index e5da0cd..67a2ae4 100644 --- a/src/theming/hbs.rs +++ b/src/theming/hbs.rs @@ -15,13 +15,13 @@ static HANDLEBARS: LazyLock<Handlebars> = LazyLock::new(|| { hb.register_helper("url-encode", Box::new(url_encode)); for (key, fulltext) in INTERNAL_THEMES { - log::info!("Registering internal theme `{key}`"); + log::info!("Registering internal handlebars theme `{key}`"); hb.register_template_string(key, fulltext).unwrap(); } hb.set_dev_mode(CONFIG.theme_debug); if let Some(themes_dir) = CONFIG.theme_dir.as_ref() { - log::info!("Registering theme dir `{themes_dir}`"); + log::info!("Registering handlebars theme dir `{themes_dir}` with extension `{}`.", CONFIG.theme_ext_hbs); hb.register_templates_directory(&CONFIG.theme_ext_hbs, themes_dir.as_ref()).unwrap(); } diff --git a/src/theming/lua-lib/expect.lua b/src/theming/lua-lib/expect.lua index 9afbb49..20772b2 100644 --- a/src/theming/lua-lib/expect.lua +++ b/src/theming/lua-lib/expect.lua @@ -50,7 +50,7 @@ local function get_display_type(value, t) -- Cobalt and only read the metatable for tables/userdata. if t ~= "table" and t ~= "userdata" then return t end - local metatable = debug.getmetatable(value) + local metatable = getmetatable(value) if not metatable then return t end local name = rawget(metatable, "__name") @@ -72,8 +72,8 @@ local function expect(index, value, ...) -- If we can determine the function name with a high level of confidence, try to include it. local name - local ok, info = pcall(debug.getinfo, 3, "nS") - if ok and info.name and info.name ~= "" and info.what ~= "C" then name = info.name end + -- local ok, info = pcall(debug.getinfo, 3, "nS") + -- if ok and info.name and info.name ~= "" and info.what ~= "C" then name = info.name end t = get_display_type(value, t) diff --git a/src/theming/lua-lib/html.lua b/src/theming/lua-lib/html.lua index 386618b..6786f96 100644 --- a/src/theming/lua-lib/html.lua +++ b/src/theming/lua-lib/html.lua @@ -16,8 +16,8 @@ local function html(el, tbl) expect(1, el, "string") expect(2, tbl, "table") - innerHtml = "" - attributes = "" + local innerHtml = "" + local attributes = "" for k, v in pairs(tbl) do if type(k) == "string" then @@ -39,6 +39,12 @@ local function root(tbl) end return setmetatable( - { root = root }, + {}, { __call = html, - __index = function (idx) return function(tbl) html(idx, tbl) end end }) + __index = function (_, idx) + if idx == "root" then + return root + else + return function(tbl) return html(idx, tbl) end + end + end }) diff --git a/src/theming/lua.rs b/src/theming/lua.rs index c9168cb..6bd6989 100644 --- a/src/theming/lua.rs +++ b/src/theming/lua.rs @@ -1,10 +1,10 @@ // SPDX-License-Identifier: AGPL-3.0-only use std::sync::LazyLock; -use std::ops::Deref; use std::path::Path; +use std::fs; -use tokio::sync::Mutex; -use mlua::{Lua, Compiler, StdLib, Value, LuaOptions}; +use std::sync::Mutex; +use mlua::{Lua, LuaSerdeExt, Compiler, StdLib, Value, LuaOptions, Table}; use http::StatusCode; use crate::CONFIG; @@ -37,16 +37,19 @@ static LUA: LazyLock<Mutex<Lua>> = LazyLock::new(|| { let themes = lua.create_table().expect("creating themes table"); for (k, v) in INTERNAL_THEMES { + log::info!("Registering compiled lua theme `{k}`."); let _ = themes.set(*k, lua.load(*v).into_function().expect("loading internal theme")); } if let Some(theme_dir) = CONFIG.theme_dir.as_ref() { + log::info!("Registering lua theme dir `{theme_dir}` with extension `{}`.", CONFIG.theme_ext_lua); for (k, v) in walk_dir(theme_dir.as_ref().as_ref()).expect("walking theme dir") { - let _ = themes.set(k, lua.load(v).into_function().expect("loading internal theme")); + log::info!("Registering runtime lua theme `{k}`."); + let _ = themes.set(k, lua.load(v).eval::<Value>().expect("loading internal theme")); } } - let _ = lua.globals().set("__themes", themes).unwrap(); + lua.globals().set("__themes", themes).unwrap(); lua.globals().set_readonly(true); @@ -54,7 +57,7 @@ static LUA: LazyLock<Mutex<Lua>> = LazyLock::new(|| { }); fn walk_dir(path: &Path) -> std::io::Result<Vec<(String, String)>> { - use std::fs; + let ext = CONFIG.theme_ext_lua.as_ref(); let mut path_bits = vec![]; let mut dir_readers = vec![fs::read_dir(path)?]; @@ -67,7 +70,7 @@ fn walk_dir(path: &Path) -> std::io::Result<Vec<(String, String)>> { let name = ent.file_name().into_string().expect("why do you have such FUCKED UP FILE PATHS"); let ty = ent.file_type()?; if ty.is_file() && name.ends_with(CONFIG.theme_ext_lua.as_ref()) { - ret.push((path_bits.join("") + &name, fs::read_to_string(ent.path())?)); + ret.push((path_bits.join("") + &name[..name.len() - ext.len()], fs::read_to_string(ent.path())?)); } else if ty.is_dir() { path_bits.push(name); @@ -82,10 +85,22 @@ fn walk_dir(path: &Path) -> std::io::Result<Vec<(String, String)>> { Ok(ret) } -pub fn touch() { - let _ = LUA.deref(); -} - pub fn render_theme(name: &str, ctx: &crate::ctx::Ctx) -> Option<Result<String, StatusCode>> { - return None + LUA.clear_poison(); + let lua = LUA.lock().expect("FIXME: Mutex poisoning race condition."); + let themes: Table = lua.globals().get("__themes").unwrap(); + let Ok(Value::Function(theme)) = themes.get(name) + else { + return None; + }; + + let ctx = match lua.to_value(ctx) { + Ok(ok) => ok, + Err(e) => { + log::error!("Lua context serialization error: {e}"); + return Some(Err(StatusCode::INTERNAL_SERVER_ERROR)) + } + }; + + Some(theme.call((ctx,)).map_err(|e| { log::error!("Lua theme execution error: {e}"); StatusCode::INTERNAL_SERVER_ERROR })) } |