Liking cljdoc? Tell your friends :D

Pogonos

Clojars Project build codecov

Pogonos is another Clojure(Script) implementation of the Mustache templating language.

Features

  • Completely compliant to the Mustache spec, including lambdas
  • Fast, but clean implementation
  • User-friendly error messages for parsing errors
  • Supports all of Clojure, ClojureScript and self-hosted ClojureScript

Project status

Pogonos is still in beta. The public API provided in the pogonos.core namespace is almost fixed while any other interfaces, including various extension points (such as readers, outputs, AST nodes), are all subject to change.

Table of Contents

Installation

Add the following to your project's :dependencies:

Clojars Project

Usage

We will show you how to use Pogonos in this section, but if you're not too familiar with the Mustache language itself, you might want to read its documentation first.

Fundamentals

The easiest way to use the library is to just call render-string:

(require '[pogonos.core :as pg])

(pg/render-string "Hello, {{name}}!" {:name "Rich"})
;=> "Hello, Rich!"

render-string takes two arguments; a string that represents a Mustache template, and a map of the values passed to the template. The keys of the map must be keywords.

The function, then, will render the template and return the resulting string. If you'd rather write out the rendering result to somewhere, instead of generating a string, you can use outputs to specify where to output the result. See Outputs for the details.

render-string has look-alike cousins named render-file and render-resource. The only difference between render-string and those functions is that render-string directly takes a template string as an argument whereas render-file and render-resource load a template stored in a text file on the file system or a resource file placed somewhere on the classpath.

Let's say you have a template file located at resources/sample.mustache whose content looks like the following:

$ cat resources/sample.mustache
Hello, {{name}}!

Then, you can render the template using render-file:

;; loads a template from a text file on the file system
(pg/render-file "resources/sample.mustache" {:name "Rich"})

Or if you have the template file on your classpath, you can also render it with render-resource (Here we assume the resources directory is included in the classpath):

;; loads a template from a resource file on the classpath
(pg/render-resource "sample.mustache" {:name "Rich"})

All the render functions mentioned above are more suitable for one-shot rendering. But if you want to render the same template with different contexts over and over again, it would be more efficient to prepare a parsed template prior to rendering.

To prepare a parsed template, use parse-string (or parse-file / parse-resource accordingly):

(def template (pg/parse-string "Hello, {{name}}!"))

template
;=> #pogonos.nodes.Root{:body ["Hello, " #pogonos.nodes.Variable{:keys (:name), :unescaped? false} "!"]}

And then, you can render the parsed template using the render function:

(pg/render template {:name "Rich"})
;=> "Hello, Rich!"

(pg/render template {:name "Alex"})
;=> "Hello, Alex!"

At the time, Pogonos does NOT have an internal mechanism to implicitly cache parsing results for templates you've ever rendered, for better performance of rendering. So, if you're trying to use Pogonos where the rendering performance matters much, you may have to cache parsed templates on your own.

Outputs

An output is the way to specify where to output the rendering result. By default, Pogonos' render functions output the result as a string. You can emulate this behavior by specifying (pogonos.output/to-string) to them as the output like the following:

(require '[pogonos.output :as output])

(pg/render-string "Hello, {{name}}!" {:name "Clojure"}
                  {:output (output/to-string)})
;=> "Hello, Clojure!"

You can also write out the rendering result to a file or the stdout via output:

;; writes the rendering result to a file
(pg/render-string "Hello, {{name}}!" {:name "Clojure"}
                  {:output (output/to-file "hello.txt")})

;; writes the rendering result to the stdout
(pg/render-string "Hello, {{name}}!" {:name "Clojure"}
                  {:output (output/to-stdout)})

In general, it's more efficient to write out the rendering result directly to a file than to generate a resulting string, and then write it out to the file.

Partials

The Mustache spec provides a feature named partials. Partials can be used to include contents from other templates.

Let's say you have a partial resources/user.mustache that looks like:

$ cat resources/user.mustache
<strong>{{name}}</strong>

You can render a template that has a partial in it using the render functions out of the box:

(pg/render-string "<h2>Users</h2>{{#users}}{{>user}}{{/users}}"
                  {:users [{:name "Rich"} {:name "Alex"}]})
;=> "<h2>Users</h2><strong>Rich</strong><strong>Alex</strong>"

By default, render-string and render-resource try to find partials on the classpath, and render-file on the file system.

To specify where to find partials explicitly, use the :partials option:

(require '[pogonos.partials :as partials])

(pg/render-string "<h2>Users</h2>{{#users}}{{>user}}{{/users}}"
                  {:users [{:name "Rich"} {:name "Alex"}]}
                  {:partials (partials/file-partials "resources")})

(pg/render-string "<h2>Users</h2>{{#users}}{{>user}}{{/users}}"
                  {:users [{:name "Rich"} {:name "Alex"}]}
                  {:partials (partials/resource-partials)})

You can even specify a map to utilize inline partials:

(pg/render-string "<h2>Users</h2>{{#users}}{{>user}}{{/users}}"
                  {:users [{:name "Rich"} {:name "Alex"}]}
                  {:partials {:user "<strong>{{name}}</strong>"}}

Error messages

Pogonos aims to provide user-friendly error messages for parse errors as one of its features, so that users can easily find where and why the error occurred.

For example, if you miss the closing delimiter of a Mustache tag, you'll see a detailed error message, like the following:

(pg/render-string "Hello, {{name" {:name "Clojure"})

;; Execution error (ExceptionInfo) at pogonos.error/error (error.cljc:52).
;; Missing closing delimiter "}}" (1:14):
;;
;;   1| Hello, {{name
;;                   ^^

You can suppress these somewhat "verbose" error messages if you want, by specifying the option {:suppress-verbose-errors true}:

(pg/render-string "Hello, {{name" {:name "Clojure"}
                  {:suppress-verbose-errors true})

;; Execution error (ExceptionInfo) at pogonos.error/error (error.cljc:52).
;; Missing closing delimiter "}}" (1:14)

Even while disabling verbose error messages, you can get them back by calling perr explicitly:

(pg/perr *e)
;; Missing closing delimiter "}}" (1:14):
;;
;;   1| Hello, {{name
;;                   ^^

License

Copyright © 2020 Shogo Ohta

This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0.

This Source Code may also be made available under the following Secondary Licenses when the conditions for such availability set forth in the Eclipse Public License, v. 2.0 are satisfied: GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version, with the GNU Classpath Exception which is available at https://www.gnu.org/software/classpath/license.html.

Can you improve this documentation? These fine people already did:
Shogo Ohta & Ohta Shogo
Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close