use anyhow::Result;
use std::path::Path;
#[cfg(feature = "screenshots")]
pub async fn take_chart_screenshot(
html_path: &Path,
screenshot_path: &Path,
theme: &str,
) -> Result<()> {
use headless_chrome::{Browser, LaunchOptions};
use headless_chrome::protocol::cdp::Page::CaptureScreenshotFormatOption;
let browser = Browser::new(
LaunchOptions::default_builder()
.window_size(Some((1280, 2560))) .enable_logging(true) .build()
.unwrap(),
)?;
let tab = browser.new_tab()?;
let absolute_path = html_path.canonicalize()?;
let url = format!("file://{}", absolute_path.display());
tab.navigate_to(&url)?;
let mut waited = 0;
let max_wait = 15000;
let step = 300;
while waited < max_wait {
let is_defined = tab.evaluate("typeof window.prepareScreenshot === 'function'", false)?;
if is_defined.value == Some(serde_json::Value::Bool(true)) {
break;
}
std::thread::sleep(std::time::Duration::from_millis(step));
waited += step;
}
if waited >= max_wait {
anyhow::bail!(
"prepareScreenshot function not found after waiting {}ms",
max_wait
);
}
tab.evaluate(&format!("window.prepareScreenshot('{}')", theme), true)?;
std::thread::sleep(std::time::Duration::from_secs(2));
let content_height_result = tab.evaluate("Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight)", false)?;
if let Some(serde_json::Value::Number(height_num)) = content_height_result.value {
if let Some(content_height) = height_num.as_u64() {
let required_height = content_height + 100; if required_height > 2560 {
drop(tab);
drop(browser);
let browser = Browser::new(
LaunchOptions::default_builder()
.window_size(Some((1280, required_height as u32)))
.enable_logging(true)
.build()
.unwrap(),
)?;
let tab = browser.new_tab()?;
tab.navigate_to(&url)?;
std::thread::sleep(std::time::Duration::from_secs(3));
let mut waited = 0;
let max_wait = 10000; let step = 200;
while waited < max_wait {
let is_defined =
tab.evaluate("typeof window.prepareScreenshot === 'function'", false)?;
if is_defined.value == Some(serde_json::Value::Bool(true)) {
break;
}
std::thread::sleep(std::time::Duration::from_millis(step));
waited += step;
}
tab.evaluate(&format!("window.prepareScreenshot('{}')", theme), true)?;
std::thread::sleep(std::time::Duration::from_secs(2));
let png_data =
tab.capture_screenshot(CaptureScreenshotFormatOption::Png, None, None, true)?;
std::fs::write(screenshot_path, png_data)?;
return Ok(());
}
}
}
let png_data = tab.capture_screenshot(CaptureScreenshotFormatOption::Png, None, None, true)?;
std::fs::write(screenshot_path, png_data)?;
Ok(())
}
#[cfg(not(feature = "screenshots"))]
pub async fn take_chart_screenshot(
_html_path: &Path,
_screenshot_path: &Path,
_theme: &str,
) -> Result<()> {
Ok(())
}