From 4803d681d260f974bea504f1b15fe92a5e5000e3 Mon Sep 17 00:00:00 2001 From: slhx agent Date: Tue, 26 May 2026 00:23:38 +0200 Subject: [PATCH] feat(build): make global exports opt in Default generated APIs to component-scoped modules and require global_exports(true) for legacy/global slot, handle, class, event, and lowering exports. req: component/003 req: build/001 --- examples/v0/build.rs | 4 +++- slhx-build/src/lib.rs | 54 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/examples/v0/build.rs b/examples/v0/build.rs index dadfeed..f507d87 100644 --- a/examples/v0/build.rs +++ b/examples/v0/build.rs @@ -1 +1,3 @@ -fn main() { slhx_build::app().run().unwrap(); } +fn main() { + slhx_build::app().global_exports(true).run().unwrap(); +} diff --git a/slhx-build/src/lib.rs b/slhx-build/src/lib.rs index aa90bf9..fe8c3f9 100644 --- a/slhx-build/src/lib.rs +++ b/slhx-build/src/lib.rs @@ -13,6 +13,7 @@ use std::sync::Arc; pub struct AppBuilder { out_dir: Option, template_dir: PathBuf, + global_exports: bool, } impl AppBuilder { @@ -26,6 +27,11 @@ impl AppBuilder { self } + pub fn global_exports(mut self, enabled: bool) -> Self { + self.global_exports = enabled; + self + } + pub fn run(self) -> io::Result<()> { println!("cargo:rerun-if-changed={}", self.template_dir.display()); @@ -54,7 +60,10 @@ impl AppBuilder { resources.add_stylesheet(&self.template_dir, &path, &source)?; } - std::fs::write(out_dir.join("slhx.generated.rs"), resources.generated_rs())?; + std::fs::write( + out_dir.join("slhx.generated.rs"), + resources.generated_rs(self.global_exports), + )?; std::fs::write(out_dir.join("slhx.syms"), resources.syms())?; Ok(()) } @@ -64,6 +73,7 @@ pub fn app() -> AppBuilder { AppBuilder { out_dir: None, template_dir: PathBuf::from("templates"), + global_exports: false, } } @@ -306,7 +316,7 @@ impl Resources { Ok(()) } - fn generated_rs(&self) -> String { + fn generated_rs(&self, global_exports: bool) -> String { let mut out = String::new(); out.push_str("// @generated by slhx-build. Do not edit.\n"); out.push_str(&format!( @@ -318,9 +328,11 @@ impl Resources { .join(", ") )); - // req: build/001 - self.push_resource_modules(&mut out, None, 0); - self.push_lowering_api(&mut out, None, 0); + // req: build/001 req: component/003 + if global_exports { + self.push_resource_modules(&mut out, None, 0); + self.push_lowering_api(&mut out, None, 0); + } for component in self.component_names() { out.push_str("\n#[allow(non_upper_case_globals)]\n"); @@ -1020,7 +1032,7 @@ mod tests { ) .unwrap(); - app().template_dir(&templates).out_dir(&out).run().unwrap(); + app().template_dir(&templates).out_dir(&out).global_exports(true).run().unwrap(); let generated = std::fs::read_to_string(out.join("slhx.generated.rs")).unwrap(); assert!(generated.contains("pub mod slots")); @@ -1055,6 +1067,32 @@ mod tests { let _ = std::fs::remove_dir_all(&base); } + #[test] + fn global_resource_exports_are_explicit_opt_in() { + // req: component/003 + let base = test_dir("slhx-build-no-global-exports-test"); + let templates = base.join("templates"); + let out = base.join("out"); + let _ = std::fs::remove_dir_all(&base); + std::fs::create_dir_all(&templates).unwrap(); + std::fs::write( + templates.join("todo.heml"), + r#"
"#, + ) + .unwrap(); + + app().template_dir(&templates).out_dir(&out).run().unwrap(); + + let generated = std::fs::read_to_string(out.join("slhx.generated.rs")).unwrap(); + assert!(!generated.contains("\n#[allow(non_upper_case_globals)]\npub mod slots")); + assert!(!generated.contains("\npub fn lower_html")); + assert!(generated.contains("pub mod todo")); + assert!(generated.contains(" pub mod slots")); + assert!(generated.contains(" pub fn lower_html")); + + let _ = std::fs::remove_dir_all(&base); + } + #[test] fn emits_form_contract_metadata_from_surface_controls() { // req: codegen/004 req: form/001 @@ -1129,7 +1167,7 @@ mod tests { ) .unwrap(); - app().template_dir(&templates).out_dir(&out).run().unwrap(); + app().template_dir(&templates).out_dir(&out).global_exports(true).run().unwrap(); let generated = std::fs::read_to_string(out.join("slhx.generated.rs")).unwrap(); assert!(generated.contains("pub mod classes")); @@ -1260,7 +1298,7 @@ mod slhx {{ }} {generated} fn main() {{ - let html = lower_html(r#"
  • "#); + let html = todo::lower_html(r#"
  • "#); assert!(html.contains(r#"data-hid="#)); assert!(html.contains(r#"name="__h""#)); assert!(html.contains(r#"data-key="7""#));