tmpltool/context.rs
1/// Global context for template rendering
2///
3/// This context provides information about the template execution environment,
4/// such as the base directory for resolving relative file paths.
5use std::path::{Path, PathBuf};
6use std::sync::Arc;
7
8/// Global context shared across all template functions
9///
10/// This struct is thread-safe and can be cloned cheaply (uses Arc internally)
11#[derive(Clone, Debug)]
12pub struct TemplateContext {
13 /// Base directory for resolving relative file paths
14 /// - If template is from a file: directory containing the template file
15 /// - If template is from stdin: current working directory
16 base_dir: Arc<PathBuf>,
17
18 /// Trust mode: if true, disables filesystem security restrictions
19 trust_mode: bool,
20}
21
22impl TemplateContext {
23 /// Create a new context with the given base directory and trust mode
24 pub fn new(base_dir: PathBuf, trust_mode: bool) -> Self {
25 Self {
26 base_dir: Arc::new(base_dir),
27 trust_mode,
28 }
29 }
30
31 /// Create context from a template file path
32 ///
33 /// The base directory will be the directory containing the template file
34 pub fn from_template_file(template_path: &str, trust_mode: bool) -> std::io::Result<Self> {
35 let path = Path::new(template_path);
36 let base_dir = path
37 .parent()
38 .map(|p| p.to_path_buf())
39 .unwrap_or_else(|| PathBuf::from("."));
40
41 // Canonicalize to get absolute path
42 let canonical = std::fs::canonicalize(&base_dir)?;
43 Ok(Self::new(canonical, trust_mode))
44 }
45
46 /// Create context for stdin (uses current working directory)
47 pub fn from_stdin(trust_mode: bool) -> std::io::Result<Self> {
48 let cwd = std::env::current_dir()?;
49 Ok(Self::new(cwd, trust_mode))
50 }
51
52 /// Get the base directory for file operations
53 pub fn base_dir(&self) -> &Path {
54 &self.base_dir
55 }
56
57 /// Check if trust mode is enabled
58 pub fn is_trust_mode(&self) -> bool {
59 self.trust_mode
60 }
61
62 /// Resolve a relative path against the base directory
63 ///
64 /// # Arguments
65 ///
66 /// * `path` - The path to resolve (can be relative or absolute)
67 ///
68 /// # Returns
69 ///
70 /// The resolved absolute path
71 pub fn resolve_path(&self, path: &str) -> PathBuf {
72 let path_obj = Path::new(path);
73
74 // If path is absolute, return as-is
75 if path_obj.is_absolute() {
76 path_obj.to_path_buf()
77 } else {
78 // Resolve relative to base directory
79 self.base_dir.join(path)
80 }
81 }
82}