Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Racket implementation of Mustache templates

License

NotificationsYou must be signed in to change notification settings

rcherrueau/rastache

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Racket implementation ofMustache templates.

Rastache is compliant with theMustache spec v1.1+λ

Get It

Rastache can be installed as a collection within Racket with package manager:

$ raco pkg install"git://github.com/rcherrueau/rastache.git?path=rastache"

Or manually:

$ git clone git://github.com/rcherrueau/rastache.git$cd rastache/rastache$ raco link.$ raco setup

Usage

Once installed, here is the simplest way to use Rastache:

#lang racket/base(require rastache); rast-compile/render: input-port hash -> output-port(rast-compile/render (open-input-string"{{foo}}")                     #hash{ (foo ."bar") }                     (current-output-port))

The functionrast-compile/render takes three parameters, the template as an input port, the context as a hash table and an output port in which Rastache displays the rendered template.

The functionrast-compile/render is the composition of two auxiliary functions,rast-compile andrast-render. Using those two separately enables the compilation of a template and its memoization for later uses.

#lang racket/base(require rastache)(let* ([template (open-input-file"huge-template.mustache")]       [compiled-template (rast-compile template)])  (define ctx1 #hash{#|context 1|#})  (define ctx2 #hash{#|context 2|#})  (define ctx3 #hash{#|context 3|#})  (for ([ctx (list ctx1 ctx2 ctx3)])    (rast-render compiled-template ctx (current-output-port))    (newline)))

Rastache also offers facilities for reading strings and files.

; rast-compile/open-string: string -> (listof token)(rast-compile/open-string"{{foo}}"); rast-compile/open-file: path -> (listof token)(rast-compile/open-file"path/to/file.mustache")

Seeexamples directory for more usage examples.

Running Tests

At the moment the project is under development but passes allMustache spec tests. If you want to run the tests yourself, do the following:

$ git clone git://github.com/rcherrueau/rastache.git$cd rastache/rastache/tests/$ racotest tests.rkt

Supported Functionality

Variables

The most basic tag type is the variable. A{{name}} tag in a basic template will try to find thename key in the current context.

All variables are HTML escaped by default. If you want to return unescaped HTML, use the triple mustache{{{name}}} or&.

Template:

*{{name}}*{{age}}*{{company}}*{{{company}}}*{{& company}}

Context:

#hash{ (name ."Chris")       (company ."<b>GitHub</b>") }

Output:

* Chris** &lt;b&gt;GitHub&lt;/b&gt;*<b>GitHub</b>*<b>GitHub</b>

Dot notation

Dot notation may be used to access nested keys.

Template:

*{{type}}*{{delorean.name}}:{{delorean.speed}}

Context:

#hash{ (type ."Time Machine")       (delorean . #hash{ (name ."DeLorean")                          (speed ."88 mph") }) }

Output:

* Time Machine* DeLorean: 88 mph

Lambdas

If the value of a key is a lambda, it is called with the current context as its first argument. The second argument is a rendering function that uses the current context as its context argument.

Template:

Hello,{{lambda}}!

Context:

`#hash{ (planet ."world")        (lambda . ,(λ (_ render) (render"{{planet}}"))) }

Output:

Hello, world!

Sections

Sections render blocks of text one or more times, depending on the value of the key in the current context.

A section begins with a pound and ends with a slash. That is,{{#person}} begins a “person” section while{{/person}} ends it.

The behavior of the section is determined by the value of the key.

False Values of Empty Lists

Template:

Shown.{{#person}}  Never shown!{{/person}}

Context:

#hash{ (person .#f) }

Output:

Shown.

Non-Empty Lists

If theperson key exists and has a non-false value, the HTML between the pound and slash will be rendered and displayed one or more times.

When the value is a non-empty list, the text in the block will be displayed once for each item in the list. The context of the block will be set to the current item for each iteration. In this way we can loop over collections.

Template:

Death List Five:{{#death}}<b>{{name}}</b>{{/death}}

Context:

#hash{ (death . [#hash{ (name ."O-Ren Ishii") }                 #hash{ (name ."Vernita Green") }                 #hash{ (name ."Budd") }                 #hash{ (name ."Elle Driver") }                 #hash{ (name ."Bill") }]) }

Output:

Death List Five:<b>O-Ren Ishii</b><b>Vernita Green</b><b>Budd</b><b>Elle Driver</b><b>Bill</b>

When looping over an array of strings, a. can be used to refer to the current item in the list.

Template:

{{#tmnt}}*{{.}}{{/tmnt}}

Context:

#hash{ (tmnt . ["Leonardo""Michelangelo""Donatello""Raphael"]) }

Output:

* Leonardo* Michelangelo* Donatello* Raphael

Lambdas

If the value of a section key is a lambda, it is called with the section’s literal block of text, un-rendered, as its first argument. The second argument is a special rendering function that uses the current context as its context argument.

Template:

<{{#lambda}}-{{/lambda}}>

Context:

`#hash{ (planet ."Earth")        (lambda . ,(λ (text render)                     (render (string-append text"{{planet}}"                                            text)))) }

Output:

<-Earth->

Inverted Sections

An inverted section begins with a caret (hat) and ends with a slash. That is{{^person}} begins a “person” inverted section while{{/person}} ends it.

Template:

{{#repo}}<b>{{name}}</b>{{/repo}}{{^repo}}No repos :{{{/repo}}

Context:

#hash{ (repo . []) }

Output:

No repos :{

Comments

Comments begin with a bang and are ignored. The following template:

<h1>Today{{! ignore me}}.</h1>

Will render as follows:

<h1>Today.</h1>

Comments may contain newlines.

Partials

Partials allow you to include other templates. It begins with a greater than sign, like{{> partialkey}}.

Thepartialkey can be a simple string, thus Rastache interpretspartialkey as a file path.

Template:

Hello{{>partials/names}}

Context:

#hash{ (people . [ #hash{ (name ."Marty") }                   #hash{ (name ."Emmet") }                   #hash{ (name ."Einstein") } ]) }

Partial file `partials/names’:

{{#people}},{{name}}{{/people}}

Output:

Hello, Marty, Emmet, Einstein

Thepartialkey can also be an URIs, as specified inRFC 2396. Thus Rastache uses`get-pure-port’ with redirection parameter set to1 to get the resource.

Template:

Hello{{>https://github.com/rcherrueau/rastache/raw/master/rastache/tests/partials/names}}

Context:

#hash{ (people . [ #hash{ (name ."Marty") }                   #hash{ (name ."Emmet") }                   #hash{ (name ."Einstein") } ]) }

Output:

Hello, Marty, Emmet, Einstein

Set Delimiter

Set Delimiter tags start with an equal sign and change the tag delimiters from{{ and}} to custom strings.

Consider the following contrived example:

*{{default_tags}}{{=<%%>=}}* <% erb_style_tags %><%={{}}=%>*{{ default_tags_again}}

Here we have a list with three items. The first item uses the default tag style, the second uses erb style as defined by the Set Delimiter tag, and the third returns to the default style after yet another Set Delimiter declaration.

Why?

I’ve given myself a project as I learn Racket. I’m particularly interested in Racket facilities for defining expander and reader and for packaging those two into a conveniently named language. For all these reasons, mustache implementation seems a good project.

License

Copyright (C) 2014 Ronan-Alexandre Cherrueau

This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

About

Racket implementation of Mustache templates

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp