#Lavender
Lavender is a templating language for php loosely based on jade.
##installation
via composer:
first get yourself some composer. next you need to make yourself a composer.json
, here's an example.
{
"require": {
"lavender/lavender": "*"
}
}
then run php composer.phar install
or composer install
depending on how you installed composer. once composer has finished it will generate an autoloader in vendor/autoload.php
which you can require()
from your application's bootstrap process.
via git:
add the lavender submodule with git submodule add git@github.com:golavender/lavender.git <folder to clone to>
and include it with require "<where you put lavender>/src/Lavender/lavender.php"
##usage
once you have installed and included lavender the only required configuration is to tell lavender where the views directory is.
Lavender::config(array(
/*
* required - path to views directory
*/
'view_dir' => String,
/*
* optional - cache view files, if this is true
* the cache folder needs to be emptied
* every time view files are changed
*/
//'caching' => FALSE,
/*
* optional - defaults to something random in your tmp directory
*/
//'cache_dir' => NULL,
/*
* optional - defaults to "lavender"
*/
//'file_extension' => String,
/*
* optional - defaults to TRUE
*
* renders a debugging error page instead of throwing an exception.
* in production you should disable this and use a 500 page.
*/
//'handle_errors' => Boolean,
));
rendering a template is as easy as
$output = Lavender::view('some_template')->compile();
// or if you need to pass data into the template (probably the case)
$output = Lavender::view('some_template')->compile(array(
'data' => 'some data that the template will use',
'more_data' => "moar data",
));
##language reference
html:
section#some_id.foo.bar(attribute1='foo',attribute2='bar')
becomes
<section id="some_id" class="foo bar" attribute1="foo" attribute2="bar"></section>
child nodes are indented below their parent
section.foo
div(data-something='foo')
div(data-something='bar')
becomes
<section class="foo">
<div data-something="foo"></div>
<div data-something="bar"></div>
</section>
there is a shortcut if you just want a div, you can skip right to class or id definitions
.foobar text text
#foobar text text
becomes
<div class="foobar">text text</div>
<div id="foobar">text text</div>
text can be added to nodes in two ways
section.foo
div(data-something='foo') this is some text
div(data-something='bar')
| this is also some text
Lavender knows not to put a closing tag on certain nodes. (we got the list from here)
input(type="text",value="fooooobar")
becomes
<input type="text" value="fooooobar">
doctype:
do you always forget the syntax for doctype? Lavender exists to solve your first world problems. just throw a !!!
at the top of your layout and you get yourself a nice html doctype. doctypes supported are html
, transitional
, strict
, frameset
, 1.1
, basic
and mobile
. here are some pretty examples.
!!!
defaults to html but you can also specify
!!! html
the word doctype
works too
doctype html
doctype strict
comments
comments are a thing
// this is an html comment. it will be rendered to the page
//- this is a lavender comment. it will not be rendered
conditional comments
the IE
shorthand can be used to generate conditional comments for Internet Explorer. check out this if you're not farmiliar with conditional comments.
IE
script(src="some script to make IE work")
IE lt 7
script(src="some script to make super old IE work")
becomes
<!--[if IE]>
<script src="some script to make IE work"></script>
<![endif]-->
<!--[if lt IE 7]>
<script src="some script to make super old IE work"></script>
<![endif]-->
variables:
lavender views can be passed variables from the parent php application or they can be defined right in the template.
this just assigns a variable without outputting anything to the page
- some_variable = "this is stored in a variable"
note the -
symbol, which evaluates an expression without outputting. the content of the variable can then later be output using the =
symbol
- some_variable = "this is stored in a variable"
span.foo= some_variable
span.bar
= some_variable
becomes
<span class="foo">this is stored in a variable</div>
<span class="bar">this is stored in a variable</div>
arrays too
- some_array = ['foo', 'bar', 'baz']
and associative arrays
- some_array = {key1: 'foo', key2: 'bar', key3: 'baz'}
conditionals:
markup can be conditionally rendered using the if
keyword. Lavender supports all the conditional operations you know and love !
, &&
, ||
, <
. >
, <=
, >=
, ==
, !=
and does a truthy check against the result.
- some_variable = "this is stored in a variable"
if some_variable
span.foo= some_variable
if some_variable_that_doesnt_exist
span.foo this won't be rendered
if FALSE
div this isn't rendered
elseif FALSE
div still not rendered
elseif TRUE
div wooooooooo
else
div sadface
becomes
<span class="foo">this is stored in a variable</div>
<div>wooooooooo</div>
TRUE
and FALSE
(and true
and false
) are keywords in Lavender, they can be assinged to variables or used in conditionals directly (but if you actually do that then wat)
- my_variable = TRUE
if my_variable
div this will show up
if false
div this will not
loops:
Lavender supports iterating over arrays and associative arrays with the each
keyword
ul
each value in some_random_array
li= value
ul
each value, key in some_random_array
li(data-key=key)= value
you may have noticed how i snuck in using variables for your html attributes there, yea you can do that too.
else:
the else keyword can be used after loops or conditionals
if FALSE
div will not show up
else
div will show up
- empty_array = []
each value in empty_array
div nothing to see here
else
div empty array!
math:
math. you can do it. supported operators are %
, +
, -
, *
, /
, (
, )
div
| 1 + 1 =
= 1 + 1
div
| 2 - 3 =
= 2 - 3
div
| 2 * 3 =
= 2 * 3
div
| 10 / 5 =
= 10 / 5
ul
each value, key in some_random_array
if key % 2 == 0
li(data-key=key)= value
include:
partials are a thing
span stuff and things
div.content
include /path/relative/to/view/directory/somefile
div.content
include /path/relative/to/view/directory/somefile with {stuff: "Asdfasdf"}
extends:
Lavender supports block style layout extension. this means that in the parent template you define blocks using the block
keyword. then in the child template you only have blocks which override the blocks in the parent template
so if this was layout.lavender
h1 this is a pretty cool web page
block header
| you can put some default content in here
| it will be displayed if no child template
| overrides it
div.content
block content
and this is the child template
extends layout
block header
div
span
| foo bar baz
block content
| content
| more content
| moar content
and you were to render the child temlate, you would get
<h1>this is a pretty cool web page</h1>
<div>
<span>foo bar baz</span>
</div>
<div class="content">
content
more content
moar content
</div>
a special case has been added to allow definining variables at the top of your child templates, these variables can be referenced from the layout to do cool things like specifying a list of javascript files necessary for a template to work or setting the page title.
###whitespace
newlines are added automatically after every html element, if you don't want the newline you can add a -
to the
node definition like so.
p
a(href="/some/place")- click here for some cool stuff
|.
automagic whitespace management is hard and subject to change.
###filters
programatic expressions in Lavender are a little limited, none of your favorite php functions are available for modifying the template data. this is by design, we don't think there should be a ton of logic in templates when that logic could be in controllers or models. however since you have to be able to do some templating logic we added filters. it's super easy to add your own filters to Lavender and there are (or will be) plenty in place out of the box. here's how they work.
- myvariable = "some really cool text"
div
span
| i'm gonna filter some stuff. it's gonna be cool.
= myvariable | upper
becomes
<div>
<span>im gonna filter some stuff. it's gonna be cool. SOME REALLY COOL TEXT</span>
</div>
profound right? not that we invented this, we copied the idea from twig. the filters Lavender comes with are:
upper:
="string"|upper
becomes STRING
trim:
=" string "|trim
becomes string
title:
="this is a title"|title
becomes This Is A Title
split:
"these are some words"|split(' ')
becomes the array ['these', 'are', 'some', 'words']
sort:
"these are some words"|split(' ')|sort
becomes the array ['are', 'some', 'these', 'words']
capitalize:
= "these are some words"|capitalize
becomes These are some words
date:
= "1396372567"|date
becomes 4/1/2014
= "1396372567"|date('Y')
becomes 2014
default:
= []|default('foobar')
becomes foobar
first:
= ['asdf','qwer']|first
becomes asdf
join:
= ['asdf','qwer']|join
becomes asdf qwer
= ['asdf','qwer']|join('-')
becomes asdf-qwer
last:
= ['asdf','qwer']|last
becomes qwer
= ['asdf','qwer', 'zxcv']|last(2)|join('-')
becomes qwer-zxcv
keys:
{'asdf': 'foo','qwer': 'bar'}|keys
becomes the array ['asdf', 'qwer']
length:
= ['asdf','qwer']|length
becomes 2
lower:
= "FOO BAR"|lower
becomes foo bar
nl2br:
= "new\nline"|nl2br
becomes new<br>line
round:
= 12345.123|round(2)
becomes 12345.12
merge:
['foo', 'bar']|merge(['baz'])
becomes the array ['foo', 'bar', 'baz']
replace:
= "foo bar"|replace(' ', '-')
becomes foo-bar
reverse:
['asdf', 'qwer']|reverse
becomes the array ['qwer', 'asdf']
slice:
['foo', 'bar', 'baz']|slice(1, 1)
becomes the array ['bar']
number_format:
= 10000000000.12345|number_format()
becomes 10,000,000,000
= 10000000000.12345|number_format(2, ',', '.')
becomes 10.000.000.000,12
ceil:
= 10000000000.12345|ceil
becomes 10000000001
floor:
= 10000000000.12345|floor
becomes 10000000000
relative:
if you had a timestamp
variable timestamp|relative
would return things like 'just now' or 'in 3 days' or 6 minutes ago
contains:
= ['asdf', 'qwer']|contains('asdf')
returns TRUE
is:
= ['asdf', 'qwer']|is('list')
returns TRUE
= {asdf: 'qwer'}|is('object')
returns TRUE
= 8|is('number')
returns TRUE
= myVariable|is('My_Class_Name')
also works
json:
= ['asdf', 'qwer']|json
returns "['asdf','qwer']"
url_encode:
= user@email.com|url_encode
becomes user%40email.com