From 3d2b68b0b19f3ab284147d5d85003ee2463e902a Mon Sep 17 00:00:00 2001 From: Adrien Burgun Date: Wed, 27 Jul 2022 12:55:22 +0200 Subject: [PATCH] :sparkles: Use a generic method for handling partials This fixes a few issues: - https://github.com/nickel-org/rust-mustache/issues/67 - https://github.com/nickel-org/rust-mustache/issues/62 (by implementing a custom PartialLoader without the set_extension) But it also adds a lot of complexity and breaks previous code. --- Cargo.toml | 5 +- README.md | 2 +- src/compiler.rs | 67 ++++++++++-------------- src/context.rs | 128 +++++++++++++++++++++++++++++++++++----------- src/lib.rs | 13 ++--- src/template.rs | 18 +++---- tests/template.rs | 8 +-- 7 files changed, 147 insertions(+), 94 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4586cea..8d6d94d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,9 +3,10 @@ name = "mustache" description = "Rust implementation of Mustache" repository = "https://github.com/nickel-org/rust-mustache" documentation = "http://nickel-org.github.io/rust-mustache" -version = "0.9.0" -authors = ["erick.tryzelaar@gmail.com"] +version = "0.10.0" +authors = ["erick.tryzelaar@gmail.com", "Shad Amethyst "] license = "MIT/Apache-2.0" +autotests = false [features] unstable = [] diff --git a/README.md b/README.md index 89755a3..50ccca0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Mustache [![Ohloh statistics](http://www.ohloh.net/p/rust-mustache/widgets/project_thin_badge.gif)](https://www.ohloh.net/p/rust-mustache) [![Build Status](http://travis-ci.org/nickel-org/rust-mustache.png?branch=master)](https://travis-ci.org/nickel-org/rust-mustache) [![](http://meritbadge.herokuapp.com/mustache)](https://crates.io/crates/mustache) +Mustache (customization fork) ======== Inspired by [ctemplate][1] and [et][2], [Mustache][3] is a framework-agnostic way diff --git a/src/compiler.rs b/src/compiler.rs index b40e558..9acdc5a 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -4,24 +4,24 @@ use std::io::Read; use std::fs::File; use parser::{Parser, Token}; -use super::Context; +use super::{Context, PartialLoader}; use Result; pub type PartialsMap = HashMap>; /// `Compiler` is a object that compiles a string into a `Vec`. -pub struct Compiler { - ctx: Context, +pub struct Compiler { + ctx: Context

, reader: T, partials: PartialsMap, otag: String, ctag: String, } -impl> Compiler { +impl, P: PartialLoader> Compiler { /// Construct a default compiler. - pub fn new(ctx: Context, reader: T) -> Compiler { + pub fn new(ctx: Context

, reader: T) -> Compiler { Compiler { ctx: ctx, reader: reader, @@ -32,12 +32,13 @@ impl> Compiler { } /// Construct a default compiler. - pub fn new_with(ctx: Context, - reader: T, - partials: PartialsMap, - otag: String, - ctag: String) - -> Compiler { + pub fn new_with( + ctx: Context

, + reader: T, + partials: PartialsMap, + otag: String, + ctag: String + ) -> Compiler { Compiler { ctx: ctx, reader: reader, @@ -56,38 +57,26 @@ impl> Compiler { // Compile the partials if we haven't done so already. for name in partials.into_iter() { - let path = - self.ctx.template_path.join(&(name.clone() + "." + &self.ctx.template_extension)); - if !self.partials.contains_key(&name) { // Insert a placeholder so we don't recurse off to infinity. self.partials.insert(name.to_string(), Vec::new()); - match File::open(&path) { - Ok(mut file) => { - let mut string = String::new(); - file.read_to_string(&mut string)?; - - let compiler = Compiler { - ctx: self.ctx.clone(), - reader: string.chars(), - partials: self.partials.clone(), - otag: "{{".to_string(), - ctag: "}}".to_string(), - }; - - let (tokens, subpartials) = compiler.compile()?; - - // Include subpartials - self.partials.extend(subpartials.into_iter()); - - // Set final compiled tokens for *this* partial - self.partials.insert(name, tokens); - } - // Ignore missing files. - Err(ref e) if e.kind() == NotFound => {}, - Err(e) => return Err(e.into()), - } + let string = self.ctx.partial_loader.load(&name)?; + let compiler = Compiler { + ctx: self.ctx.clone(), + reader: string.chars(), + partials: self.partials.clone(), + otag: "{{".to_string(), + ctag: "}}".to_string(), + }; + + let (tokens, subpartials) = compiler.compile()?; + + // Include subpartials + self.partials.extend(subpartials.into_iter()); + + // Set final compiled tokens for *this* partial + self.partials.insert(name, tokens); } } diff --git a/src/context.rs b/src/context.rs index 16ef0db..307d021 100644 --- a/src/context.rs +++ b/src/context.rs @@ -10,32 +10,39 @@ use std::path::{Path, PathBuf}; /// Represents the shared metadata needed to compile and render a mustache /// template. -#[derive(Clone)] -pub struct Context { - pub template_path: PathBuf, - pub template_extension: String, +#[derive(Debug, Clone)] +pub struct Context { + pub partial_loader: P, } -impl fmt::Debug for Context { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, - "Context {{ template_path: {:?}, template_extension: {} }}", - &*self.template_path, - self.template_extension) +impl Context { + /// Configures a mustache context the specified path to the templates. + pub fn new(path: PathBuf) -> Self { + Context { + // template_path: path.clone(), + // template_extension: "mustache".to_string(), + partial_loader: DefaultLoader::new(path, "mustache".to_string()), + } } -} -impl Context { - /// Configures a mustache context the specified path to the templates. - pub fn new(path: PathBuf) -> Context { + /// Configures a mustache context the specified path and extension to the templates. + pub fn with_extension(path: PathBuf, extension: String) -> Self { Context { - template_path: path, - template_extension: "mustache".to_string(), + partial_loader: DefaultLoader::new(path, extension), + } + } +} + +impl Context

{ + /// Configures a mustache context to use a custom loader + pub fn with_loader(loader: P) -> Self { + Self { + partial_loader: loader } } /// Compiles a template from a string - pub fn compile>(&self, reader: IT) -> Result