feat(build): accept precomputed surface facts
Allow slhx-build callers to feed hemplate SurfaceDocument facts directly, preserving the existing .heml parse fallback while covering the build-from-surface path. req: surface/008 req: build/001
This commit is contained in:
+49
-8
@@ -14,6 +14,7 @@ pub struct AppBuilder {
|
|||||||
out_dir: Option<PathBuf>,
|
out_dir: Option<PathBuf>,
|
||||||
template_dir: PathBuf,
|
template_dir: PathBuf,
|
||||||
global_exports: bool,
|
global_exports: bool,
|
||||||
|
surfaces: Vec<(PathBuf, SurfaceDocument)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppBuilder {
|
impl AppBuilder {
|
||||||
@@ -32,6 +33,11 @@ impl AppBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn surface(mut self, path: impl Into<PathBuf>, surface: SurfaceDocument) -> Self {
|
||||||
|
self.surfaces.push((path.into(), surface));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn run(self) -> io::Result<()> {
|
pub fn run(self) -> io::Result<()> {
|
||||||
println!("cargo:rerun-if-changed={}", self.template_dir.display());
|
println!("cargo:rerun-if-changed={}", self.template_dir.display());
|
||||||
|
|
||||||
@@ -46,14 +52,21 @@ impl AppBuilder {
|
|||||||
std::fs::create_dir_all(&out_dir)?;
|
std::fs::create_dir_all(&out_dir)?;
|
||||||
|
|
||||||
let mut resources = Resources::default();
|
let mut resources = Resources::default();
|
||||||
for path in collect_heml(&self.template_dir)? {
|
if self.surfaces.is_empty() {
|
||||||
let source = std::fs::read_to_string(&path)?;
|
for path in collect_heml(&self.template_dir)? {
|
||||||
let doc = build_ast(Arc::new(source)).map_err(|err| parse_error(&path, err))?;
|
let source = std::fs::read_to_string(&path)?;
|
||||||
let Some(doc) = doc else {
|
let doc = build_ast(Arc::new(source)).map_err(|err| parse_error(&path, err))?;
|
||||||
continue;
|
let Some(doc) = doc else {
|
||||||
};
|
continue;
|
||||||
let surface = extract_surface(&doc);
|
};
|
||||||
resources.add_surface(&self.template_dir, &path, &surface)?;
|
let surface = extract_surface(&doc);
|
||||||
|
resources.add_surface(&self.template_dir, &path, &surface)?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// req: surface/008
|
||||||
|
for (path, surface) in &self.surfaces {
|
||||||
|
resources.add_surface(&self.template_dir, path, surface)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for path in collect_stylesheets(&self.template_dir)? {
|
for path in collect_stylesheets(&self.template_dir)? {
|
||||||
let source = std::fs::read_to_string(&path)?;
|
let source = std::fs::read_to_string(&path)?;
|
||||||
@@ -74,6 +87,7 @@ pub fn app() -> AppBuilder {
|
|||||||
out_dir: None,
|
out_dir: None,
|
||||||
template_dir: PathBuf::from("templates"),
|
template_dir: PathBuf::from("templates"),
|
||||||
global_exports: false,
|
global_exports: false,
|
||||||
|
surfaces: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1090,6 +1104,33 @@ mod tests {
|
|||||||
let _ = std::fs::remove_dir_all(&base);
|
let _ = std::fs::remove_dir_all(&base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn app_can_consume_precomputed_surface_facts() {
|
||||||
|
// req: surface/008 req: build/001
|
||||||
|
let base = test_dir("slhx-build-precomputed-surface-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();
|
||||||
|
let path = templates.join("todo.heml");
|
||||||
|
let source = Arc::new(
|
||||||
|
r#"<button data-slhx-handle="create" data-slhx-on="click">Create</button><div data-slhx-slot="todos"></div>"#
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
|
let ast = build_ast(source).unwrap().unwrap();
|
||||||
|
let surface = extract_surface(&ast);
|
||||||
|
|
||||||
|
app().template_dir(&templates).out_dir(&out).surface(&path, surface).run().unwrap();
|
||||||
|
|
||||||
|
let generated = std::fs::read_to_string(out.join("slhx.generated.rs")).unwrap();
|
||||||
|
assert!(generated.contains("pub mod todo"));
|
||||||
|
assert!(generated.contains("pub const create: ::slhx::Handle<()> = ::slhx::Handle::new("));
|
||||||
|
assert!(generated.contains("pub const todos: ::slhx::Slot<::std::string::String> = ::slhx::Slot::new("));
|
||||||
|
assert!(generated.contains("pub const click: ::slhx::EventName = ::slhx::EventName::new(\"click\")"));
|
||||||
|
|
||||||
|
let _ = std::fs::remove_dir_all(&base);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn global_resource_exports_are_explicit_opt_in() {
|
fn global_resource_exports_are_explicit_opt_in() {
|
||||||
// req: component/003
|
// req: component/003
|
||||||
|
|||||||
Reference in New Issue
Block a user