Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions tera/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,16 +207,20 @@ impl<'k, T: ArgFromValue<'k, Output = T>> ArgFromValue<'k> for Vec<T> {
}
}

/// The keyword arguments of a filter/function
#[derive(Debug, Clone, Default)]
pub struct Kwargs {
values: Arc<Map>,
}

impl Kwargs {
/// Creates a new Kwargs struct from a Map. The Map is Arc<_> since internally
/// that's what we have.
pub fn new(map: Arc<Map>) -> Self {
Self { values: map }
}

/// Deserialize the kwargs into something that impl Deserialize
pub fn deserialize<'a, T: Deserialize<'a>>(&'a self) -> TeraResult<T> {
T::deserialize(&Value {
inner: ValueInner::Map(self.values.clone()),
Expand Down
8 changes: 8 additions & 0 deletions tera/src/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,24 @@ use crate::value::Value;
/// The type of component arguments.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ComponentArgType {
#[allow(missing_docs)]
String,
#[allow(missing_docs)]
Bool,
#[allow(missing_docs)]
Integer,
#[allow(missing_docs)]
Float,
#[allow(missing_docs)]
Number,
#[allow(missing_docs)]
Array,
#[allow(missing_docs)]
Map,
}

impl ComponentArgType {
/// Returns the name of this argument type
pub fn as_str(&self) -> &'static str {
match self {
ComponentArgType::String => "string",
Expand Down
17 changes: 15 additions & 2 deletions tera/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! The Tera error type, with optional nice terminal error reporting.
use std::error::Error as StdError;
use std::fmt::{self};

use crate::reporting::generate_report;
use std::error::Error as StdError;

use crate::utils::Span;

Expand All @@ -13,6 +13,7 @@ pub(crate) struct Note {
pub(crate) span: Span,
}

/// An error that knows how to present itself nicely, with the right spans/notes etc.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ReportError {
pub(crate) message: String,
Expand Down Expand Up @@ -82,6 +83,8 @@ impl ReportError {
}
}

/// All the kind of errors Tera can produce.
/// Non-exhaustive so we can add more if needed without a breaking change.
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum ErrorKind {
Expand Down Expand Up @@ -135,11 +138,16 @@ pub enum ErrorKind {
ComponentNotFound(String),
/// A filter/test main value was not the expected type
InvalidArgument {
#[allow(missing_docs)]
expected_type: String,
#[allow(missing_docs)]
actual_type: String,
},
/// A function/test/filter was expecting an argument but it wasn't found
MissingArgument { arg_name: String },
MissingArgument {
#[allow(missing_docs)]
arg_name: String,
},
/// An IO error occurred
Io(std::io::ErrorKind),
/// UTF-8 conversion error when converting output to UTF-8
Expand Down Expand Up @@ -208,6 +216,7 @@ impl fmt::Display for ErrorKind {
}
}

/// The Error struct for Tera.
#[derive(Debug)]
pub struct Error {
pub(crate) kind: ErrorKind,
Expand All @@ -222,10 +231,12 @@ impl fmt::Display for Error {
}

impl Error {
/// Creates a new error of the given kind.
pub fn new(kind: ErrorKind) -> Self {
Self { kind, source: None }
}

/// Returns the kind of error
pub fn kind(&self) -> &ErrorKind {
&self.kind
}
Expand All @@ -238,6 +249,7 @@ impl Error {
}
}

/// Creates generic error with a message and no source.
pub fn message(message: impl ToString) -> Self {
Self {
kind: ErrorKind::Msg(message.to_string()),
Expand Down Expand Up @@ -351,6 +363,7 @@ impl From<std::string::FromUtf8Error> for Error {
}
}

/// A custom Result type for this library
pub type TeraResult<T> = Result<T, Error>;

#[cfg(test)]
Expand Down
3 changes: 2 additions & 1 deletion tera/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
//! [Jinja2]: http://jinja.pocoo.org/
//! [Django]: https://docs.djangoproject.com/en/3.1/topics/templates/

//#![deny(missing_docs)]
#![deny(missing_docs)]

mod args;
mod components;
Expand All @@ -72,6 +72,7 @@ mod template;
mod tera;
mod tests;
mod utils;
/// The value type used by Tera and supporting types (`Key`, `Map`, `Number`, `ValueKind`).
pub mod value;
pub(crate) mod vm;

Expand Down
60 changes: 58 additions & 2 deletions tera/src/tera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,41 @@ const ONE_OFF_TEMPLATE_NAME: &str = "__tera_one_off";
/// The escape function type definition
pub type EscapeFn = fn(&[u8], &mut dyn Write) -> std::io::Result<()>;

/// Main point of interaction in this library.
///
/// The [`Tera`] struct is the primary interface for working with the Tera template engine. It contains parsed templates, registered filters (which can filter
/// data), functions, and testers. It also contains some configuration options, such as a list of
/// suffixes for files that have autoescaping turned on.
///
/// It is responsible for:
///
/// - Loading and managing templates from files or strings
/// - Parsing templates and checking for syntax errors
/// - Maintaining a cache of compiled templates for efficient rendering
/// - Providing an interface for rendering templates with given contexts
/// - Managing template inheritance and includes
/// - Handling custom filters and functions
/// - Overriding settings, such as autoescape rules
///
/// # Example
///
/// Basic usage:
///
/// ```
/// use tera::Tera;
///
/// let mut tera = Tera::default();
/// tera.load_from_glob("examples/basic/templates/**/*").unwrap();
/// tera.add_raw_template("hello", "Hello, {{ name }}!").unwrap();
///
/// // Prepare the context with some data
/// let mut context = tera::Context::new();
/// context.insert("name", "World");
///
/// // Render the template with the given context
/// let rendered = tera.render("hello", &context).unwrap();
/// assert_eq!(rendered, "Hello, World!");
/// ```
#[derive(Clone)]
pub struct Tera {
/// The glob used to load templates if there was one.
Expand All @@ -53,10 +88,31 @@ pub struct Tera {
}

impl Tera {
/// Create a new instance of Tera. Equivalent of `Tera::default()`.
pub fn new() -> Self {
Self::default()
}

/// Loads all the parsed templates found in the `dir` glob.
///
/// A glob is a pattern for matching multiple file paths, employing special characters such as
/// the single asterisk (`*`) to match any sequence of characters within a single directory
/// level, and the double asterisk (`**`) to match any sequence of characters across multiple
/// directory levels, thereby providing a flexible and concise way to select files based on
/// their names, extensions, or hierarchical relationships. For example, the glob pattern
/// `templates/*.html` will match all files with the `.html` extension located directly inside
/// the `templates` folder, while the glob pattern `templates/**/*.html` will match all files
/// with the `.html` extension directly inside or in a subdirectory of `templates`.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # use tera::Tera;
/// let mut tera = Tera::default();
/// tera.load_from_glob("examples/basic/templates/**/*").unwrap();
/// ```
#[cfg(feature = "glob_fs")]
pub fn load_from_glob(&mut self, glob: &str) -> TeraResult<()> {
self.glob = Some(glob.to_string());
Expand Down Expand Up @@ -182,9 +238,9 @@ impl Tera {
///
/// // Override escape function to escape the capital letter A, why not
/// tera.set_escape_fn(|input: &[u8], output: &mut dyn Write| {
/// for &byte in input {
/// for &byte in input {<
/// match byte {
/// b'A' => output.write_all(b"")?,
/// b'A' => output.write_all(b"\xc6\x90")?,
/// _ => output.write_all(&[byte])?,
/// }
/// }
Expand Down
1 change: 1 addition & 0 deletions tera/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ impl TestResult for bool {

/// The test function type definition
pub trait Test<Arg, Res>: Sync + Send + 'static {
/// The test function type definition
fn call(&self, value: Arg, kwargs: Kwargs, state: &State) -> Res;
}

Expand Down
9 changes: 9 additions & 0 deletions tera/src/value/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,24 @@ use std::sync::Arc;
/// The key of anything looking like a hashmap (struct/hashmaps)
#[derive(Debug, Clone)]
pub enum Key<'a> {
#[allow(missing_docs)]
Bool(bool),
#[allow(missing_docs)]
U64(u64),
#[allow(missing_docs)]
I64(i64),
#[allow(missing_docs)]
U128(u128),
#[allow(missing_docs)]
I128(i128),
#[allow(missing_docs)]
String(Arc<str>),
#[allow(missing_docs)]
Str(&'a str),
}

impl<'a> Key<'a> {
/// Returns the content if the key is a string
pub fn as_str(&self) -> Option<&str> {
match self {
Key::String(s) => Some(s),
Expand All @@ -28,6 +36,7 @@ impl<'a> Key<'a> {
}
}

#[allow(missing_docs)]
pub fn as_value(&self) -> Value {
match self {
Key::Bool(b) => Value::from(*b),
Expand Down
Loading