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
This commit is contained in:
slhx agent
2026-05-26 00:23:38 +02:00
parent 93c68b6d87
commit 4803d681d2
2 changed files with 49 additions and 9 deletions
+3 -1
View File
@@ -1 +1,3 @@
fn main() { slhx_build::app().run().unwrap(); }
fn main() {
slhx_build::app().global_exports(true).run().unwrap();
}
+46 -8
View File
@@ -13,6 +13,7 @@ use std::sync::Arc;
pub struct AppBuilder {
out_dir: Option<PathBuf>,
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#"<button data-slhx-handle="create">Create</button><div data-slhx-slot="todos"></div>"#,
)
.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#"<form data-slhx-handle="create"><input name="title"></form><li data-slhx-slot="row" data-slhx-key="7"></li>"#);
let html = todo::lower_html(r#"<form data-slhx-handle="create"><input name="title"></form><li data-slhx-slot="row" data-slhx-key="7"></li>"#);
assert!(html.contains(r#"data-hid="#));
assert!(html.contains(r#"name="__h""#));
assert!(html.contains(r#"data-key="7""#));