mustache.java

repository·main·Indexed 23 days ago

https://github.com/spullara/mustache.java

A high-performance Java implementation of the Mustache templating system. It supports template inheritance, concurrent evaluation via Callables and ExecutorService, and data access through non-private fields, methods, or maps. The library includes SafeMustacheFactory for handling untrusted templates and ScalaObjectHandler for integration with Scala 2.10, 2.11, 2.12, and 2.13, providing specialized handling for Scala collections, Options, and truthiness logic.

Tokens
2.7K
Snippets
4
Records
10
Agent score
82%

What's inside mustache.java

  1. Secure Mustache.java with SafeMustacheFactory

    main
    By default, Mustache.java is UNSAFE if untrusted parties provide templates. To prevent security vulnerabilities, do not use the default factory when handling untrusted input. Instead, use SafeMustacheFactory and whitelist all allowed templates and partials.
  2. How Mustache.java differs from Mustache.js

    main

    While Mustache.java is a derivative of mustache.js, it has several key differences:

    • Concurrent Evaluation: Supports optional concurrent evaluation if Callable objects are used with an ExecutorService.
    • Functions/Lambdas: Implemented using Java 8 Function (post-substitution). Use TemplateFunction if you want the library to reparse the results of your function (pre-substitution).
    • Template Inheritance: Supports template inheritance (e.g., {{<super}}{{$content}}...{{/content}}{{/super}}).
    • Data Access: Data is accessed via non-private fields, methods, or maps in an array of scopes.
  3. Enable concurrent template evaluation with Callables

    main

    By default, template evaluation is serial. If a data method contains blocking code, the system pauses. To enable concurrent/asynchronous evaluation, return a Callable from your data methods and provide an ExecutorService when creating your MustacheFactory.

    // Instead of a blocking method:
    String description() throws InterruptedException {
      Thread.sleep(1000);
      return description;
    }
    
    // Use a Callable for concurrent execution:
    Callable<String> description() throws InterruptedException {
      return new Callable<String>() {
        @Override
        public String call() throws Exception {
          Thread.sleep(1000);
          return description;
        }
      };
    }
  4. Install Mustache.java via Maven

    main

    To use Mustache.java in your project, add the compiler module as a dependency in your pom.xml. Choose the version based on your Java runtime:

    • For Java 8+, use version 0.9.10.
    • For Java 6/7, use version 0.8.18.
    <!-- Java 8+ -->
    <dependency>
      <groupId>com.github.spullara.mustache.java</groupId>
      <artifactId>compiler</artifactId>
      <version>0.9.10</version>
    </dependency>
    
    <!-- Java 6/7 -->
    <dependency>
      <groupId>com.github.spullara.mustache.java</groupId>
      <artifactId>compiler</artifactId>
      <version>0.8.18</version>
    </dependency>
  5. Execute a Mustache template with an object scope

    main

    You can provide data to a template using Java objects. Mustache.java accesses data via non-private fields, methods, or maps. Any Iterable can be used for list-like behaviors.

    import com.github.mustachejava.DefaultMustacheFactory;
    import com.github.mustachejava.Mustache;
    import com.github.mustachejava.MustacheFactory;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Arrays;
    import java.util.List;
    
    public class Example {
    
      List<Item> items() {
        return Arrays.asList(
          new Item("Item 1", "$19.99", Arrays.asList(new Feature("New!"), new Feature("Awesome!"))),
          new Item("Item 2", "$29.99", Arrays.asList(new Feature("Old."), new Feature("Ugly.")))
        );
      }
    
      static class Item {
        Item(String name, String price, List<Feature> features) {
          this.name = name;
          this.price = price;
          this.features = features;
        }
        String name, price;
        List<Feature> features;
      }
    
      static class Feature {
        Feature(String description) {
           this.description = description;
        }
        String description;
      }
    
      public static void main(String[] args) throws IOException {
        MustacheFactory mf = new DefaultMustacheFactory();
        Mustache mustache = mf.compile("template.mustache");
        mustache.execute(new PrintWriter(System.out), new Example()).flush();
      }
    }
  6. Execute a Mustache template with a Map scope

    main

    Alternatively, you can provide data using a Map<String, Object> instead of a dedicated context object.

    import com.github.mustachejava.DefaultMustacheFactory;
    import com.github.mustachejava.Mustache;
    import com.github.mustachejava.MustacheFactory;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    import java.io.StringReader;
    import java.io.Writer;
    import java.util.HashMap;
    
    public class MapExample {
      public static void main(String[] args) throws IOException {
        HashMap<String, Object> scopes = new HashMap<String, Object>();
        scopes.put("name", "Mustache");
        scopes.put("feature", new Feature("Perfect!"));
    
        Writer writer = new OutputStreamWriter(System.out);
        MustacheFactory mf = new DefaultMustacheFactory();
        Mustache mustache = mf.compile(new StringReader("{{name}}, {{feature.description}}!"), "example");
        mustache.execute(writer, scopes);
        writer.flush();
      }
    
      static class Feature {
        Feature(String description) { this.description = description; }
        String description;
      }
    }
  7. Use ScalaObjectHandler for Scala 2.12 Mustache templates

    main

    The ScalaObjectHandler is a specialized implementation of ReflectionObjectHandler designed for Scala 2.12 environments. It bridges the gap between Scala's collection types and Mustache.java's expectations by providing custom coercion and iteration logic.

    Key behaviors include:

    • Scala Collection Support: Automatically converts Scala Map types to Java Maps.
    • Option/Some Handling: Unwraps Scala Some(value) to the underlying value and converts None to null.
    • Truthy/Falsey Logic:
      • Scala collections are considered 'falsey' if they are empty.
      • Numbers are considered 'falsey' if their integer value is 0.
    • Unit Handling: Converts Scala BoxedUnit to null.
    • Iteration: Supports iterating over Scala Traversable collections.
  8. Use ScalaObjectHandler for Scala 2.11 Mustache templates

    main

    The ScalaObjectHandler is a specialized implementation of ReflectionObjectHandler designed for Scala 2.11 environments. It allows Mustache.java to correctly interpret Scala-specific types and collections when rendering templates.

    Key behaviors include:

    • Scala Collection Support: Automatically converts Scala Map objects to Java Maps.
    • Option Handling: Unwraps Scala Some(value) to the underlying value and treats None as null.
    • Truthiness/Falsey Logic:
      • Scala Traversable collections are considered 'falsey' if they are empty.
      • Numbers with a value of 0 are treated as 'falsey'.
    • Unit Handling: Converts BoxedUnit to null.

    To use this, you should provide an instance of ScalaObjectHandler to your Mustache compiler or engine configuration to ensure Scala data structures are correctly resolved during template execution.

  9. Use ScalaObjectHandler for Scala 2.10 Mustache templates

    main

    The ScalaObjectHandler is a specialized implementation of ReflectionObjectHandler designed to bridge Scala 2.10 data structures with Mustache.java templates. It allows Mustache to natively understand Scala-specific types like Option, Some, None, and Scala collections.

    Key Behaviors:

    • Option Handling: Some(value) is automatically unwrapped to its underlying value, while None is treated as null.
    • Collection Handling: Scala Map objects are converted to Java Maps. Scala Traversable collections are iterated over during template execution.
    • Truthiness/Falsey Logic:
      • An empty Scala collection is considered "falsey" (it will trigger the {{#section}}...{{/section}} else block or skip the section).
      • A Scala Number with a value of 0 is considered "falsey".
    • BoxedUnit: BoxedUnit values are treated as null.
  10. Use ScalaObjectHandler for Scala 2.13 Mustache templates

    main

    The ScalaObjectHandler is a specialized ReflectionObjectHandler designed for use with Mustache.java in Scala 2.13 environments. It provides seamless integration between Scala types and Mustache templates by handling Scala-specific constructs that the standard Java reflection handler might not recognize.

    Key behaviors include:

    • Scala Collection Support: Automatically converts Scala Map types to Java Maps using asJava so they can be accessed in templates.
    • Option Handling: Unwraps Scala Some(value) to the underlying value and treats None as null.
    • Unit Handling: Converts Scala BoxedUnit to null.
    • Truthy/Falsey Logic:
      • An empty Scala Iterable is treated as falsey.
      • A Scala Number with a value of 0 is treated as falsey.
    • Unrestricted Access: Overrides checkMethod and checkField to allow access to any method or field without restriction.