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}