All Projects → Flamefork → Fleet

Flamefork / Fleet

Licence: mit
Templating System for Clojure

Programming Languages

clojure
4091 projects

Projects that are alternatives of or similar to Fleet

escapevelocity
A subset reimplementation of Apache Velocity with a much simpler API.
Stars: ✭ 28 (-81.08%)
Mutual labels:  template-language
hyperviews
Template language that produces `h` output
Stars: ✭ 26 (-82.43%)
Mutual labels:  template-language
Jinjasql
Template Language for SQL with Automatic Bind Parameter Extraction
Stars: ✭ 529 (+257.43%)
Mutual labels:  template-language
strgen
A Python module for a template language that generates randomized data
Stars: ✭ 34 (-77.03%)
Mutual labels:  template-language
khufu
A template language for incremental-dom or DSL for javascript views
Stars: ✭ 19 (-87.16%)
Mutual labels:  template-language
Rascal
The implementation of the Rascal meta-programming language (including interpreter, type checker, parser generator, compiler and JVM based run-time system)
Stars: ✭ 284 (+91.89%)
Mutual labels:  template-language
Liquid Rust
Liquid templating for Rust
Stars: ✭ 229 (+54.73%)
Mutual labels:  template-language
Awesome Twig
A curated list of amazingly awesome Twig extensions, snippets and tutorials
Stars: ✭ 63 (-57.43%)
Mutual labels:  template-language
closet
The Web Framework for Flashcards
Stars: ✭ 45 (-69.59%)
Mutual labels:  template-language
Twirl
Twirl is Play's default template engine
Stars: ✭ 498 (+236.49%)
Mutual labels:  template-language
Splain
small parser to create more interesting language/sentences
Stars: ✭ 15 (-89.86%)
Mutual labels:  template-language
sourcery-templates
Building Vapor projects using meta programming with Sourcery ✨
Stars: ✭ 24 (-83.78%)
Mutual labels:  template-language
Leaf
🍃 An expressive, performant, and extensible templating language built for Swift.
Stars: ✭ 310 (+109.46%)
Mutual labels:  template-language
gender-render
Template-system and proof-of-concept for rendering gender-neutral text-, email- and RPG-text-templates with the correct pronouns of all people involved.
Stars: ✭ 21 (-85.81%)
Mutual labels:  template-language
Bars
Bars is a lightweight high performance HTML aware templating engine. Bars emits DOM rather than DOM-strings, this means the DOM state is preserved even if data updates happen.
Stars: ✭ 5 (-96.62%)
Mutual labels:  template-language
Superviews.js
Template engine targeting incremental-dom
Stars: ✭ 242 (+63.51%)
Mutual labels:  template-language
bart
A compile time templating language for Rust inspired by Mustache
Stars: ✭ 29 (-80.41%)
Mutual labels:  template-language
Tuxedo
Tuxedo is a template language for Swift.
Stars: ✭ 80 (-45.95%)
Mutual labels:  template-language
Srml
String Resource Markup Language. Style your localized strings for Android.
Stars: ✭ 49 (-66.89%)
Mutual labels:  template-language
Ego
An ERB-style templating language for Go.
Stars: ✭ 477 (+222.3%)
Mutual labels:  template-language

Fleet

Build Status

Clojars Project

Templating System for Clojure

Gist

  1. Template is function of its arguments.
  2. HTML is better for HTML than some host language DSL (just cause HTML is DSL).
  3. DOM manipulation tools and XSLT are good for transforming, not for templating (yes, opinionated).
  4. Clojure is good :)
  5. HTML isn't the only language that needs templating.

Brief

Write

<p><(post :body)></p>

instead of

<p><%= (escape-html (post :body)) %></p>

Read on for more goodness.

Template Language

Main Fleet construction is Spaceship <()>.

...just because (star)fleet consists of many spaceships.

<()> is almost equivalent to Clojure's (), so <h1><(body)></h1> in Fleet is nearly the same as (str "<h1>" (body) "</h1>") in Clojure.

The only difference is that (body) output gets escaped (e.g. html-encoded to prevent XSS).
Use raw function to prevent escaping: <(raw "<br/>")>.
Use str function to place value <(str posts-count)> instead of calling a function.

This is almost all we need, with one issue: writing something like

<(raw (for [p posts]
  (str "<li class=\"post\">" (p :title) "</li>")))>

is too ugly, and defining <li class="post"><(p :title)></li> as separate template can be overkill in many cases. So there should be the good way of embedding strings and anonymous templates.

Slipway construction "><" is for embedding strings.

The previous example could be rewritten using Slipway as

    <(for [p posts] ">
      <li class="post"><(p :title)></li>
    <")>

This example has two points worth mentioning. Result of "><" construction processing is an expression of String type. Strings in Slipway considered raw by default.

Next case is something like this:

    <(raw (map (fn [post]
      (str "<li class=\"post\">" (post :title) "</li>")) posts))>

With Slipway it can be replaced with

    <(map (fn [post] ">
      <li class="post"><(post :title)></li>
    <") posts)>

Need to mention that all this supports lexical scoping and other Clojure features just like reference (previous) expression.

Functions

Single anonymous template: fleet

(fleet [& args] template-str options)

Creates anonymous function from template-str using provided options map. Intended to use just like (fn construct.

Example:

(def footer (fleet "<p>&copy; <(year (now))> Your Company</p>"))
(println (footer))

(def header (fleet [title] "<head><title><(str title)></title></head>"))
(println (header "Main Page"))

Main option is :escaping. It can be function of one String argument or keyword specifying one of predefined functions:
:bypass — default, no escaping;
:xml — XML (or HTML) rules;
:str — Java-compatible string escaping;
:clj-str — Clojure string escaping (\n is allowed);
:regex — Escaping of Regex special symbols.

Options :file-name and :file-path (both String) are in place for better stack traces.

Template namespace: fleet-ns

(fleet-ns root-ns root-path filters)

Treats root-path as root of template directory tree, maps it to namespace with prefix root-ns., creates template functions for each file in it with name and samespace according to relative path.

Example:

(fleet-ns view "path/to/view_dir" [:fleet :xml])

Template functions are created by the following rules:

— Several equal functions will be created for each file. E.g. file posts.html.fleet will produce 3 functions: posts, posts-html and posts-html-fleet.

This is useful for cases where you have posts.html.fleet and posts.json.fleet, so you may access distinct templates as posts-html and posts-json, while and if you have only one posts.html.fleet you could call it posts conviniently.

— Template function will take one or two arguments: first named same as shortest function name for file (posts in previous example) and second named data.

When it's called with one arguments both symbols (fn-name and data) are bound to same value of this argument.
When it's called with no arguments both symbols (fn-name and data) are bound to nil.
This is also for convinience: you could use name appropriate to usage: e.g. if your template renders post, you could use post param name, and if template renders some complex data you could use data. Also you can mix&match, for example post as main rendered entity and data as some render options.

Filters argument is vector of file-filter escaping-fn pairs used to filter which files to process and with which escaping function. File filters could be defined as function, string, regex, :fleet or :all.
— Function should have Boolean type and one File argument.
— String filter definition treated as *.string.fleet mask, e.g. "js" mask will match update.js.fleet.
— Regex filter matches whole filename, e.g. #".*.html" will match posts.html.
:fleet filter is treated as "others". If it is set all *.fleet files will be processed.
:all means, literally, all.

More on escaping

If you need to insert Fleet constructions into text you can escape them using backslash.
You only need escaping to remove ambiguity, so use \<( and \<" only outside embedded clojure code, \"> and \)> only inside embedded clojure code.

Examples

This is not intended to work out-of-box, only to show some bits of a language / system.

Language

Template file (post_dedicated.fleet):

<head>
  <title><(post :title)></title>

  <(stylesheet :main)>
  <(raw "<script>alert('Hello!')</script>")>
</head>
<body>

<p><(str notice)></p>

<p>Spaceship \<()> is landing.</p>

<(
; Begin of post
)>
<(inside-frame (let [p post] ">
  Author: <(p :author)><br/>
  Date: <(p :date)><br/>
<"))>

<p><(post :body)></p>
<ul>
  <(for [tag (post :tags] ">
    <li><(str tag)></li>
  <")>
</ul>
<(
; End of post
)>

<(footer)>
</body>
</html>

Clojure:

(def post-page (fleet [post] (slurp "post_dedicated.fleet")))

(post-page p)

(footer)

API

Low-level:

(def footer (fleet "<p>&copy; <(year (now))> Flamefork</p>"))

High-level:

Directory tree

root_dir/
  first_subdir/
    file_a.html.fleet
    file_b.html.fleet
  second_subdir/
    file_c.html.fleet

will be treated and processed by (fleet-ns templates "path/to/root_dir" [:fleet :xml]) as functions

templates.first-subdir/file-a
templates.first-subdir/file-b
templates.second-subdir/file-c

and (for example) first function will be like

(defn file-a
  ([file-a data] ...)
  ([file-a] (recur file-a file-a)))
  ([] (recur nil nil)))

Compatibility

Use 0.9.x for Clojure 1.2, 1.3
Use 0.10.x for Clojure 1.4+

Roadmap

  • update Fleet with latest Clojure goodness [in progress]
  • support ClojureScript

License

Copyright (c) 2010 Ilia Ablamonov, released under the MIT license.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].