use deno_core::{v8, JsRuntime};
pub fn render_html(
url: &str,
data: Option<&str>,
render_function: &str,
js_runtime: &mut JsRuntime,
) -> Result<String, String> {
let data = data.unwrap_or("{}");
let safe_data: serde_json::Value = serde_json::from_str(data)
.map_err(|e| format!("Invalid JSON data: {}", e))?;
let escaped_url = url.replace('\\', "\\\\").replace('"', "\\\"");
let render_code = format!(
r#"
(async function() {{
try {{
if (typeof globalThis.{fn} !== 'function') {{
throw new Error('Render function globalThis.{fn} not found');
}}
return await globalThis.{fn}("{url}", {data});
}} catch (error) {{
console.error("Render error:", error);
return `<html><body><h1>SSR Error</h1><pre>${{error.stack || error.message}}</pre></body></html>`;
}}
}})()
"#,
fn = render_function,
url = escaped_url,
data = safe_data
);
let global = js_runtime
.execute_script("<render>", render_code)
.map_err(|e| format!("JS execute error: {}", e))?;
#[allow(deprecated)]
let resolved = futures::executor::block_on(js_runtime.resolve_value(global))
.map_err(|e| format!("Promise resolution error: {}", e))?;
let scope = &mut js_runtime.handle_scope();
let local = v8::Local::new(scope, resolved);
serde_v8::from_v8::<String>(scope, local)
.map_err(|e| format!("Result deserialization error: {}", e))
}