#![allow(clippy::unwrap_used, clippy::expect_used)]
use anyhow::Result;
use http_handle::Server;
use ssg::plugin::{PluginContext, PluginManager};
use ssg::search::SearchPlugin;
use staticdatagen::compiler::service::compile;
use std::time::Instant;
use std::{fs, path::Path};
fn main() -> Result<()> {
let build_dir = Path::new("./examples/basic/build");
let site_dir = Path::new("./examples/basic/public");
let content_dir = Path::new("./examples/basic/content");
let template_dir = Path::new("./examples/templates");
fs::create_dir_all(build_dir)?;
fs::create_dir_all(site_dir)?;
let start = Instant::now();
match compile(build_dir, content_dir, site_dir, template_dir) {
Ok(()) => println!(" ✅ Successfully compiled static site"),
Err(e) => {
println!(" ❌ Error compiling site: {e:?}");
return Err(e);
}
}
let mut plugins = PluginManager::new();
plugins.register(ssg::postprocess::HtmlFixPlugin);
plugins.register(ssg::postprocess::ManifestFixPlugin);
plugins.register(SearchPlugin);
let ctx =
PluginContext::new(content_dir, build_dir, site_dir, template_dir);
plugins.run_after_compile(&ctx)?;
plugins.run_fused_transforms(&ctx)?;
println!(" 🔍 Search index generated");
println!(" 🧹 Browser-compat cleanups applied");
let elapsed = start.elapsed();
println!(" ⚡ Built in {elapsed:.0?}");
let gfm_sample = ssg::markdown_ext::expand_gfm("**bold** and ~~strike~~");
println!(" \u{1f4dd} GFM: {} chars processed", gfm_sample.len());
apply_template_trim(site_dir)?;
println!(" 🌐 Template trimmed for single-page studio layout");
let example_root: String = site_dir.to_str().unwrap().to_string();
let server = Server::builder()
.address("127.0.0.1:3001")
.document_root(example_root.as_str())
.custom_header("Permissions-Policy", "browsing-topics=()")
.build()
.map_err(|e| anyhow::anyhow!("{e}"))?;
server.start().map_err(|e| anyhow::anyhow!("{e}"))?;
Ok(())
}
fn apply_template_trim(site_dir: &Path) -> Result<()> {
const MARKER: &str = "/* ssg-basic: trim */";
const STYLE: &str = "<style>/* ssg-basic: trim */\
.lang-btn,.lang-dropdown,.mobile-lang{display:none!important}\
.footer-cols .footer-col:nth-child(2){display:none!important}\
.hero-actions{display:none!important}\
.nav-item:has(a[href*=\"/posts/\"]),\
.nav-item:has(a[href*=\"/tags/\"]){display:none!important}\
</style>";
fn walk(dir: &Path, marker: &str, style: &str) -> Result<()> {
for entry in fs::read_dir(dir)? {
let entry = entry?;
let path = entry.path();
if path.is_dir() {
walk(&path, marker, style)?;
} else if path.extension().is_some_and(|e| e == "html") {
let html = fs::read_to_string(&path)?;
if html.contains(marker) {
continue;
}
if let Some(pos) = html.find("</head>") {
let new_html =
format!("{}{}{}", &html[..pos], style, &html[pos..]);
fs::write(&path, new_html)?;
}
}
}
Ok(())
}
walk(site_dir, MARKER, STYLE)
}