diff --git a/README.md b/README.md index c40a22d..893310d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # clj-jtwig [Twig](http://twig.sensiolabs.org/) templates in Clojure, provided by [Jtwig](http://jtwig.org). clj-jtwig is a simple -Clojure wrapper around Jtwig to make using it in Clojure applications simple. It also provides some extra functions on top of what Jtwig provides already. As well, it adds a simple template caching layer that works out-of-the-box when rendering templates from files. +Clojure wrapper around Jtwig to make using it in Clojure applications simple. It also provides some extra functions on +top of the standard library that Jtwig provides. As well, it adds a simple template caching layer that works +out-of-the-box when rendering templates from files. For more information on Twig templates, you can refer to the [Twig documentation](http://twig.sensiolabs.org/documentation) and the [Jtwig documentation](http://jtwig.org/documentation). Please note that Jtwig is not yet a full implementation @@ -31,18 +33,12 @@ only being maintained by me *purely* for use with clj-jtwig. *It is not supporte Getting up and running with clj-jtwig is easy: ```clojure -(ns yourapp.core - (:require [clj-jtwig.core :refer [render]])) +(use 'clj-jtwig.core) -(defn say-hello [name] - (render "Hello {{name}}!" {:name name}) - -(say-hello "Gered") ; returns "Hello Gered!" +(render "Hello {{name}}!" {:name "Gered"}) ; returns "Hello Gered! ``` -You can also render from files by providing a full path and filename to `clj-jtwig.core/render-file`. Most of the time -you'll want to render from a resource file that is bundled along with your app, in which case you can provide a path -and filename relative to the classpath to `clj-jtwig.core/render-resource`. +You can also render templates from files: ```clojure (render-file "/Users/gered/say-hello.twig" {:name "Gered"}) @@ -51,34 +47,38 @@ and filename relative to the classpath to `clj-jtwig.core/render-resource`. (render-resource "say-hello.twig" {:name "Gered"}) ``` -From these examples we can see that the second argument to `render`, `render-file` and `render-resource` is a map of -variables that can be referred to in the template (basically it is the template 'model'). You can nest data and refer -to it using 'dot' syntax like in Java. +As we can see above, there are 3 main template rendering functions, `render`, `render-file` and `render-resource`. +`render-resource` is probably what you will use most often. The file path you provide to this function is relative +to the classpath, and so is ideal for rendering templates bundled with your application. -```jinja -City of residence: {{address.city}} +All three "render" functions take a second parameter which is a map that contains the values to pass to the template +which can then be referred to in the template by name. This map is also referred to as the "model map." + +Nested variables can be referred to using "dot" syntax like in Java: + +```clojure +(render "Hello {{person.name}}!" {:person {:name "Gered"}}) ; returns "Hello Gered! ``` -If a variable's name has any special characters (such as a `-` character), you can access it using 'subscript' syntax -instead. +You can only use "dot" syntax like in the above example when your variable names do not include any special characters +in them. For Clojure programmers, this also includes the use of hyphens in variable names. To get around this you can +use "subscript" syntax instead: -```jinja -Customer name: {{customer['full-name']}} +```clojure +(render "Hello {{person['first-name']}}!" {:person {:first-name "Gered"}}) ; returns "Hello Gered! ``` -If a "root" variable has special characters in it's name, you can also access it using the same syntax, but you will -need to access it off of the `model` variable which all variables set in the template are bound to. +If your root-level variables in the model map contain special characters, you can still access them by using the +same "subscript" syntax off of the automatically added `model` variable that is passed to all templates: -```jinja -Order number: {{model['customer-order'].orderNumber}} +```clojure +(render "Hello {{model['first-name']}}!" {:first-name "Gered"}) ; returns "Hello Gered! ``` -Otherwise, you normally don't need to include `model`, it is implicit. - - ### Web Apps -For web apps built on [Ring](https://github.com/ring-clojure/ring) and [Compojure](https://github.com/weavejester/compojure), you can do something like: +For web apps built on [Ring](https://github.com/ring-clojure/ring) and [Compojure](https://github.com/weavejester/compojure), +you can do something like: ```clojure (ns yourwebapp.views @@ -114,26 +114,31 @@ And then in your routes: (GET "/" [] (home-page))) ``` -You will also probably want to add `clj-jtwig.web.middleware/wrap-servlet-context-path` to your [Ring middleware](https://github.com/ring-clojure/ring/wiki/Concepts#middleware) so that template functions such as `path`, `javascript` and `stylesheet` can automatically prepend the servlet context path to urls you provide to your web app's resources. +You will also probably want to add `clj-jtwig.web.middleware/wrap-servlet-context-path` to your +[Ring middleware](https://github.com/ring-clojure/ring/wiki/Concepts#middleware) so that template functions such as +`path`, `javascript` and `stylesheet` can automatically prepend the servlet context path to urls you provide to your +web app's resources. -If you need to output the servlet context path in one of your templates (e.g. for use with Javascript code that performs AJAX requests), then you can either update the `render` function example provided above to `assoc` the value of `clj-jtwig.web.middleware/*servlet-context-path*` to the `params` map. Then you can refer to this value in your templates the same way as any other value you pass in. Or you can do something like this in one of your templates: +If you need to output the servlet context path in one of your templates (e.g. for use with Javascript code that +performs AJAX requests), then you can either update the `render` function example provided above to `assoc` the value +of `clj-jtwig.web.middleware/*servlet-context-path*` to the `params` map. Then you can refer to this value in your +templates the same way as any other value you pass in. Or you can do something like this in one of your templates: ```html ``` -Which will make a global variable `context` available to your Javascript code which will have the value of the servlet context path. +Which will make a global variable `context` available to your Javascript code which will have the value of the servlet +context path. ### Functions Adding custom functions is easy: ```clojure -(ns yourapp.core - (:require [clj-jtwig.core :refer [render]] - [clj-jtwig.functions :refer [deftwigfn]])) +(use 'clj-jtwig.functions) (deftwigfn "sayHello" [name] (str "Hello " name "!")) @@ -155,17 +160,10 @@ Then your functions can be used in your templates: For convenience, you can also define one or more aliases for functions: ```clojure -(ns yourapp.core - (:require [clj-jtwig.core :refer [render]] - [clj-jtwig.functions :refer [defaliasedtwigfn]])) - (defaliasedtwigfn "sayHello" [name] ["sayHi"] (str "Hello " name "!")) - -; elsewhere in your app's code ... - (render "{{ sayHello(name) }}" {:name "Gered"}) ; "Hello Gered!" (render "{{ sayHi(name) }}" {:name "Gered"}) ; "Hello Gered!" ``` @@ -176,7 +174,8 @@ in a 'defn'-style syntax. #### Standard Library Functions -A number of functions are provided out of the box by Jtwig. A few more are provided to fill in some gaps by clj-jtwig. The following is a list of all the functions available with clj-jtwig. +A number of functions are provided out of the box by Jtwig. A few more are provided by clj-jtwig to fill in some gaps. +The following is a list of all the functions available with clj-jtwig. | Function | Description |----------|------------ @@ -187,19 +186,23 @@ A number of functions are provided out of the box by Jtwig. A few more are provi | capitalize | `capitalize(string)`
Capitalizes a value. The first character will be uppercase, all others lowercase. | center | `center(string, max_width)`
`center(string, max_width, padding_string)`
Pads a string with whitespace on the left and right as necessary to 'center' the given value. If the padding_string argument is provided, that string will be used to pad instead of whitespace. | concat | `concat(values, ...)`
Concatenates any number of values together as strings. +| contains | `contains(map, key)`
`contains(collection, value)`
`contains(string, substring)`
If a map is specified, checks if it contains the given key. If a collection or string is specified, checks if the value/substring is present. Returns true if found. | convert_encoding | `convert_encoding(string, output_charset, input_charset)`
Converts a string from one encoding to another. The first argument is the expected output charset and the second one is the input charset. | date_format | `date_format(date)`
`date_format(date, format)`
Formats a date to a given format. The format specifier is the same as supported by `SimpleDateFormat`. If the format argument is not specified, the format used will be `yyyy-MM-dd HH:mm:ss`. The date argument should be an instance of `java.util.Date`. | date_modify | `date_modify(date, modifier)`
Modifies a date with a given modifier string. The modifier string can be things like "+1 day" or "+30 minutes". Recognized modifiers are 'seconds', 'minutes', 'hours', 'days', 'months' or 'years'. The date argument should be an instance of `java.util.Date`. A new instance of `java.util.Date` is returned. | default | `default(value, default_value)`
Returns the passed default value if the value is undefined or empty, otherwise the value of the variable. | dump | `dump(value)`
Uses `clojure.pprint/pprint` to dump the entire value of a variable to a string and returns that string. +| dump_table | `dump_table(collection_of_maps)`
Uses `clojure.pprint/print-table` to dump the entire value of a collection of maps to a string and returns that string. | escape | `escape(string)`
`escape(string, strategy)`
Escapes a string for safe insertion into the final output. The optional strategy parameter specifies the escape strategy: 'html' (default), 'js' or 'xml'. | first | `first(collection)`
`first(string)`
`first(values, ...)`
Returns the first "element" of a collection, series of values, or a string (in which case the first character is returned). | format | `format(format_string, values, ...)`
Formats a given string by replacing the placeholders (placeholders follow the `String.format` notation). The values provided will be used in order for each placeholder in the string. +| index_of | `index_of(collection, value)`
`index_of(string, substring)`
Returns the first index of a value in a collection or the start of a substring in a string. Returns -1 if not found. | javascript | `javascript(url)`
Returns a `