#![cfg_attr(coverage_nightly, coverage(off))]
use crate::scaffold::errors::{Result, ScaffoldError};
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct Template {
content: String,
name: String,
}
impl Template {
pub fn from_string(content: impl Into<String>) -> Result<Self> {
Ok(Self {
content: content.into(),
name: String::new(),
})
}
pub fn new(name: impl Into<String>, content: impl Into<String>) -> Result<Self> {
Ok(Self {
content: content.into(),
name: name.into(),
})
}
pub fn render(&self, vars: &HashMap<String, String>) -> Result<String> {
let mut result = self.content.clone();
for (key, value) in vars {
let placeholder = format!("{{{{{}}}}}", key);
result = result.replace(&placeholder, value);
}
if result.contains("{{") && result.contains("}}") {
if let Some(start) = result.find("{{") {
if let Some(end) = result.get(start..).unwrap_or_default().find("}}") {
let var_name = result.get(start + 2..start + end).unwrap_or_default();
return Err(ScaffoldError::InvalidProjectName(format!(
"Unreplaced template variable: {}",
var_name
)));
}
}
}
Ok(result)
}
pub fn name(&self) -> &str {
&self.name
}
pub fn pforge_yaml() -> Self {
Self::new("pforge.yaml", include_str!("templates/pforge.yaml.tmpl"))
.expect("pforge.yaml template should be valid")
}
pub fn cargo_toml() -> Self {
Self::new("Cargo.toml", include_str!("templates/Cargo.toml.tmpl"))
.expect("Cargo.toml template should be valid")
}
pub fn handler_rs() -> Self {
Self::new("handler.rs", include_str!("templates/handler.rs.tmpl"))
.expect("handler.rs template should be valid")
}
pub fn readme_md() -> Self {
Self::new("README.md", include_str!("templates/README.md.tmpl"))
.expect("README.md template should be valid")
}
pub fn wasm_cargo_toml() -> Self {
Self::new("Cargo.toml", include_str!("templates/wasm_Cargo.toml.tmpl"))
.expect("wasm Cargo.toml template should be valid")
}
pub fn wasm_makefile() -> Self {
Self::new("Makefile", include_str!("templates/wasm_Makefile.tmpl"))
.expect("wasm Makefile template should be valid")
}
pub fn wasm_lib_rs() -> Self {
Self::new("lib.rs", include_str!("templates/wasm_lib.rs.tmpl"))
.expect("wasm lib.rs template should be valid")
}
pub fn wasm_vfs_rs() -> Self {
Self::new("vfs.rs", include_str!("templates/wasm_vfs.rs.tmpl"))
.expect("wasm vfs.rs template should be valid")
}
}
#[derive(Debug)]
pub struct TemplateRegistry {
templates: HashMap<String, Template>,
}
impl TemplateRegistry {
pub fn new() -> Self {
Self {
templates: HashMap::new(),
}
}
pub fn register(&mut self, name: String, template: Template) {
self.templates.insert(name, template);
}
pub fn get(&self, name: &str) -> Result<&Template> {
self.templates.get(name).ok_or_else(|| {
ScaffoldError::InvalidProjectName(format!("Template not found: {}", name))
})
}
pub fn list(&self) -> Vec<String> {
self.templates.keys().cloned().collect()
}
pub fn with_pforge_templates() -> Self {
let mut registry = Self::new();
registry.register("pforge.yaml".into(), Template::pforge_yaml());
registry.register("Cargo.toml".into(), Template::cargo_toml());
registry.register("handler.rs".into(), Template::handler_rs());
registry.register("README.md".into(), Template::readme_md());
registry
}
pub fn with_wasm_templates() -> Self {
let mut registry = Self::new();
registry.register("Cargo.toml".into(), Template::wasm_cargo_toml());
registry.register("Makefile".into(), Template::wasm_makefile());
registry.register("lib.rs".into(), Template::wasm_lib_rs());
registry.register("vfs.rs".into(), Template::wasm_vfs_rs());
registry
}
}
impl Default for TemplateRegistry {
fn default() -> Self {
Self::new()
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests;
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod property_tests;