Installation
You can simple install it by composer, require PHP 5.3 or higher:
composer require undercloud/antUsage
Setup
First step - initialize and setup engine:
require 'vendor/autoload.php';
use Ant\Ant;
//setup instance
Ant::init()
	->setup([
		/* define root directory of your templates */
	 	'view'  => '/path/to/view',
		/* define cache directory for compiled templates */
		'cache' => '/path/to/cache',
		/* define logic path, default empty */
		'logic' => '/path/to/logic',
		/* you can define your own template extension, default *.ant */
		'extension' => 'mytmpl',
		/* ignore caching, if option equal true, default false */
		'debug' => true, 
		/* if equal true - ignore rendering and always 
		   try load from cache, use in production for better performance, 
		   default false */
		'freeze' => true
	]);
Basic
Simple usage example:
require 'vendor/autoload.php';
use Ant\Ant;
echo Ant::init()
  ->get('index')
  ->assign([
    'title' => "Hello, I'm ANT",
    'features' => [
    	'simple',
    	'flexible',
    	'awesome'
    ]
  ])
  ->draw();
	Create template:
// index.ant
<html>
  <head>
    <title>{{ $title }}</title>
  </head>
  <body>
    List of features
    <ul>
    @foreach ($features as $item)
      <li>{{ $item }}</li>
    @endforeach
    </ul>
  </body>
</html>
Project Structure
We recommend use the next folders structure:
views/ ├── header.ant ├── content/ │ ├── about.ant │ ├── news.ant │ ├── products/ │ │ ├── search.ant │ │ └── list.ant │ ├── contacts.ant │ └── suport.ant ├── index.ant ├── menu.ant └── footer.ant
Use nested folders for emulating namespaces, for folders and template name use lowercase symbols a...z and dash -. Don't use a dot . because it will be transformed into invalid path.
For resolve template path ANT use dot.notation.
// will be transformed into /content/products/list.ant
Ant::init()->get('content.products.list')
Events
Here next types of events can be triggered:
- build - before template parse
 - prepare - after parse
 - exec - after rendering
 
For cancel event bubbling use preventParentEvent method.
//global events
$ant = Ant::init()->setup([/*...*/]);
$eid = $ant->bind('build', function ($s) { /*...*/ });
$eid = $ant->bind('prepare', function ($s) { /*...*/ });
$eid = $ant->bind('exec', function ($s) { /*...*/ });
//unbind event
$ant->unbind($eid);
//local events
$ant = Ant::init();
$ant->get('template');
$ant->assign($data);
$eid = $ant->on('build', function ($s) { /*...*/ });
$eid = $ant->on('prepare', function ($s) { /*...*/ });
$eid = $ant->on('exec', function ($s) { /*...*/ });
//unbind local event
$ant->off($eid);
//cancel global event
$ant->preventParentEvent($event);
$ant->draw();
Logic
Logic - special layer between model and 
	view in classic MVC pattern.
	Logic layer process variables and pass it to template. If logic path is 
	defined, use folder structure same as view:
views/ │ ├──path/ │ │ ├──to/ │ │ │ ├──... └── └── └── └──template.ant logic/ │ ├──path/ │ │ ├──to/ │ │ │ ├──... └── └── └── └──template.php
If logic file is exists, ANT include and process it.
Another way use logic - define logic path manually:
echo Ant::init()
	->get('template')
	->logic($path)
	->assign([
		'date' => '2002-05-04',
		'name' => 'john',
		'size' => 45654321
	])
	->draw();
// /logic/path/to/template.php
$date = $this->date($date, 'd/m/Y');
$name = $this->capitalize($name);
$size = $this->bytesHuman($size);
Extends
You can define your own template syntax:
Ant::init()
	...
	->rule($rx, $call)
	For example we define comments syntax like {!-- ... --!} that will be transformed into <!-- ... -->.
Ant::init()
	...
	->rule('~{!--.+?--!}/ms~', function($e) {
		return '<!-- ' . $e[0] . '-->';
	})
API
Complete list of API:
class Ant
{
	/*
	 * Create new instance
	 */
	function init();
	
	/*
	 * Return settings params, if $name = false - return all
	 *
	 * @param string $name - settings name
	 */
	function settings($name = false);
	/*
	 * Check template exists
	 *
	 * @param string $name - template name
	 */
	function has($name);
	/*
	 * Select template
	 *
	 * @param string $name - template name
	 */
	function get($name);
	
	/*
	 * Load template from string
	 *
	 * @param string $s - template string
	 */
	function fromString($s);
	/*
	 * Load template from file
	 *
	 * @param string $path - path to template file
	 */
	function fromFile($path);
	/**
	 * Accept template variables
	 *
	 * @param array $data - variables
	 */
	function assign(array $data = array());
	/**
	 * Render template
	*/
	function draw();
	/*
	 * Helper wrapper for Ant::init()->get()->assign()->draw()
	 *
	 *	@param string $path - template name
	 */
	function view($name);
	/*
	 * @param string $path - path to template
	 * @param array $assign - variables
	 */
	function view($name, array $assign);
	/*
	 * @param string $path - path to template
	 * @param string $logic - path to logic file
	 */
	function view($name, $logic);
	/*
	 * @param string $path - path to template
	 * @param array $assign - variables
	 * @param string $logic - path to logic file
	 */
	function view($name, array $assign, $logic);
}
Variables
Define template variable by double curly brackets, by default ANT escape all variables:
{{ $name }}
	If you don't wanna escape value, use 3 curly brackets syntax:
{{{ $name }}}
	Handle empty values:
{{ $name or 'Default' }}
	Array values can be accessed by dot notation syntax:
{{ $array.dot.notation }}
	Object values can be accessed by arrows:
{{ $objects->arrow->notaion }}
	Simple access to global variables:
// $_GET['name']
{{ $.get.name }}
// $_SERVER['DOCUMENT_ROOT']
{{ $.server.DOCUMENT_ROOT }}
// $GLOBALS['foo']
{{ $.globals.foo }}
// shortcut helper
{{ $.ant }}
	$.scope - special variable that contains all defined variables in scope:
@each('view.path', $comments, 'com', $.scope)
@import('view.path', $.scope)
	Easy plugin access:
$.plugin->youtube('6v2L2UGZJAM')
	Comment syntax:
{{-- comments never output --}}
	For skipping variable parsing use single backslash, now you can safely use Angular variables:
<div>
	<label>Name:</label>
	<input type="text" ng-model="yourName" placeholder="Enter a name here">
	<hr>
	<h1>Hello \{{yourName}}!</h1>
</div>
Control
@if
@if ($condition)
	<div>Block One</div>
@elseif ($alter)
	<div>Block Two</div>
@else
	<div>Block Three</div>
@endif
@unless
@unless ($is_mobile)
	<div>You use desktop version</div>
@endunless
@switch
@switch ($fruit)
	@case ('apple')
		<img src="apple.png" />
	@break
	@case ('pear')
		<img src="pear.png" />
	@break
	@default
		<img src="no-image.png" />
	@break
@endswitch
@for
<ul>
@for ($i = 0; $i < 10; $i++)
	<li>{{ $i }}</li>
@endfor
</ul>
@while
@while ($condition)
	...
@endwhile
@foreach
@foreach ($comments as $com)
	<div class="comment-item">
		<div class="comment-date">{{ $com.date }}</div>
		<div class="comment-text">{{ $com.text }}</div>
	</div>
@endforeach
	Inside @foreach and @forelse loops you can get iterator state, ANT wrap collection by Ant\StateIterator and restore value after loop is end.
@foreach ($collection as $item)
	// check first iteration
	@if ($collection->isFirst())
		...
	// check last iteration
	@if ($collection->isLast())
		...
	// is between first and last
	@if ($collection->isMiddle())
		...
	// is iteration number is odd
	@if ($collection->isOdd())
		...
	// is iteration number is even
	@if ($collection->isEven())
		...
	// is iteration number divisible by number
	@if ($collection->isDivisible($by))
		...
@endforeach
@forelse
@forelse ($comments as $com)
	...
@empty
	<div>No comments yet :(</div>
@endforelse
@each
@each ('view.path', $comments, 'com')
...
//view.path
<div class="comment-item">
	<div class="comment-date">{{ $com.date }}</div>
	<div class="comment-text">{{ $com.text }}</div>
</div>
	@each($view, $collection[,$item[,$scope]])
- $view - template name
 - $collection - data
 - $item - variable name, default item
 - $scope - additional data
 
@import
Shortcut to Ant::view.
<!DOCTYPE html>
<html>
<head>
	<title>Include Blocks</title>
</head>
<body>
	@import ('header')
	...
	@import ('content')
	...
	@import ('footer')
</body>
</html>
@widget
Equivalent to @import.
@skip
For ignore parsing use @skip tag.
@skip
  {{ $vaiable }}
@endskip
@php
@php
  // multiline php code
  ...
@endphp
Inheritance
Define base layout:
// layout.ant
<!DOCTYPE html>
<html>
<head>
	<title>Inheritance Example</title>
	@block('scripts')
		@js('/path/to/script.js')
	@endblock
	@block('styles')
		@css('/path/to/style.css')
	@endblock
</head>
<body>
	@block('contents')
		<main>Content will be replaced</main>
	@endblock
</body>
</html>
	Extends:
// inject.ant
@extends('layout')
@inject('scripts')
	@js('/path/to/another.js')
@append
@inject('styles')
	@css('/path/to/another.css')
@prepend
@inject('contents')
	<main>Contents</main>
@rewrite
	Final page:
<!DOCTYPE html>
<html>
<head>
	<title>Inheritance Example</title>
	<script type="text/javascript" src="/path/to/script.js"></script>
	<script type="text/javascript" src="/path/to/another.js"></script>
	<link type="text/css" rel="stylesheet" href="/path/to/another.css" />
	<link type="text/css" rel="stylesheet" href="/path/to/style.css" />
</head>
<body>
	<main>Contents</main>
</body>
Functions
For calling defined functions use next syntax:
//short syntax
{{ ::functionName($param) }}
//long syntax
{{ $this->ant->functionName($param) }}
	For creating new function use Ant::share.
//define function
Ant::share('pow', function($n) {
	return $n * $n;
});
//check function exists
Ant::isShared('pow')
//call
{{ ::pow(5) }}
doctype
doctype($type = 'HTML5')
	Description
Return DOCTYPE declaration
Parameters
- $type
 - One of values
				
- HTML5
 - XHTML11
 - XHTML1_STRICT
 - XHTML1_TRANSITIONAL
 - XHTML1_FRAMESET
 - XHTML_liASIC1
 - HTML4_STRICT
 - HTML4_LOOSE
 - HTML4_FRAMESET
 
 
js
js($src, $defer = "")
// or you can use shortcut
@js($src, $defer = "")
	Description
Embed script
Parameters
- $src
 - Path to script
 - $defer
 - Additional attributes: defer or async
 
css
css($href, $media = "")
//or you can use shortcut
@css($href, $media = "")
	Description
Embed style
Parameters
- $href
 - Path to stylesheet
 - $media
 - Media values
 
escape
escape($string, $double = false)
	Description
Escape string
Parameters
- $string
 - The input string
 - $double
 - Process escaped entity, default false
 
decode
decode($string)
	Description
Unescape string
Parameters
- $string
 - The input string
 
upper
//hello => HELLO
upper($string)
	Description
Make a string uppercase
Parameters
- $string
 - The input string
 
lower
// HELLO => hello
lower($string)
	Description
Make a string lowercase
Parameters
- $string
 - The input string
 
isBlank
isBlank($what)
	Description
Return true if variable is null, false, empty string, string with whitespaces only, or empty array
Parameters
- $what
 - Variable for check
 
isEmpty
isEmpty($what)
	Description
Return true if variable is 0, null, false, empty string, string with whitespaces only, or empty array
Parameters
- $what
 - Variable for check
 
date
date($date, $format = 'Y-m-d H:i:s', $tz = null)
	Description
Print date in given format
Parameters
- $date
 - Date value accepted by DateTime
 - $format
 - Output format
 - $tz
 - Timezone name
 
capitalize
// hello => Hello
capitalize($string)
	Description
Capitalize string
Parameters
- $string
 - The input string
 
capitalizeAll
// hello world => Hello World
capitalizeAll($string)
	Description
Capitalize all words in string
Parameters
- $string
 - The input string
 
whitespace
// H  el  lo => H el lo
whitespace($string)
	Description
Replaces all white-space characters sequence, with single white-space
Parameters
- $string
 - The input string
 
limit
// Lorem ipsum dolor sit amet, cons... 
limit($string, $limit = 250, $postfix = '...')
	Description
Limit string length
Parameters
- $string
 - The input string
 - $limit
 - Number of characters
 - $postfix
 - String decorator
 
limitWords
// Lorem ipsum dolor sit amet, consectetuer...
limitWords($string, $limit = 250, $postfix = '...')
	Description
Limit string length, non word breaking
Parameters
- $string
 - The input string
 - $limit
 - Number of characters
 - $postfix
 - String decorator
 
limitMiddle
// Lorem ipsum dolor...te feugait nulla facilisi.
limitMiddle($string, $limit = 250, $postfix = '...')
	Description
Limit string length, by middle
Parameters
- $string
 - The input string
 - $limit
 - Number of characters
 - $postfix
 - String decorator
 
lorem
// Lorem ipsum dolor sit amet, consectetuer
lorem($limit = 544)
	Description
Fake text generator
Parameters
- $limit
 - Fake text length
 
number
// 3548791 => 3 548 791
number($num, $precision = 0)
	Description
Format number
Parameters
- $num
 - Number
 - $precision
 - Precision
 
bytesHuman
// 4637467 => 4.42 MB
bytesHuman($size, $precision = 2)
	Description
Human readable in bytes
Parameters
- $size
 - Size in bytes
 - $precision
 - Precision
 
roundHuman
// 637467 => 637.47 K
roundHuman($size, $precision = 2)
	Description
Format number
Parameters
- $size
 - Number
 - $precision
 - Precision
 
ordinal
// 25 => 25th
ordinal($num)
	Description
Create ordinal number
Parameters
- $num
 - Number
 
unicode
// I \u2665 HTML => I ♥ HTML
unicode($string)
	Description
Conver unicode sequence to html entity
Parameters
- $string
 - Sequence
 
url
// ['foo' => 'bar', 'baz' => 'quux'] => foo=bar&baz=quux
url(array $params)
	Description
Build url string
Parameters
- $params
 - Params
 
iterable
iterable($instance)
	Description
Check if variable can be used in loops
Parameters
- $instance
 - Variable to check
 
count
count($instance)	
	Description
Count collection items
Parameters
- $instance
 - Variable to check
 
template
template($tmpl, $params...)
//ANT is simple, flexible and awesome
template('ANT is {1}, {2} and {3}', 'simple', 'flexible', 'awesome')
	Description
Build template with placeholders
Parameters
- $tmpl
 - Template string
 - $params
 - Params list
 
Plugins
ANT provide access for dozen build-in plugins. For activate it use next example:
use Ant\Ant;
// activate plugin
$ant = Ant::init()
	->setup([
		...
	])
	->activate($pluginOne)
	->activate($pluginTwo)
	->activate($pluginThree);
// check is plugin activated
$ant->isActivated($plugin)
// deactivate plugin
$ant->deactivate($plugin)
	You can simple define your own plugin like this:
// plugin definition
class MyPlugin
{
	public function __construct(array $options)
	{
		/*...*/
	}
	public function __invoke($param)
	{
		/*...*/
	}
	public function methodName($param)
	{
		/*...*/
	}
}
// global init
Ant::init()
	->setup([
		...
	])
	->register('myplugin', new MyPlugin($options));
// call __invoke
{{ $.plugin->myplugin($param) }}
// call methodName
{{ $.plugin->myplugin->methodName($param) }}
Asset
Append file modification time to given path, useful for cache manage. If plugin activated, automatically process path in ::js and ::css functions.
$ant->activate('Asset')
// /path/to/script.js?1463545199
{{ $.plugin->asset($path) }}
// <script src="/path/to/script.js?1463545199"></script>
@js($path)
Compressor
Compress HTML code.
$ant->activate('Compressor')
Faker
		Wrapper for https://github.com/fzaninotto/Faker.
		You need install it by composer require fzaninotto/faker.
	
$ant->activate('Faker', ['locale' => 'en_US'])
// 'Lucy Cechtelar'
{{ $.plugin->faker->name  }}
Google Analytics
Embed Google Analytics script https://www.google.com/analytics.
$ant->activate('GoogleAnalytics')
{{{ $.plugins->ga($code, $domain = '') }}}
Haml
Haml parser. You need install it by composer require hamlphp/hamlphp.
$ant->activate('Haml')
InlineCSS
Wrapper for InlineCss. You need install it by composer require undercloud/inlinecss.
$ant->activate('InlineCSS')
{{ $.plugin->css(['color' => 'red', 'font-weight' => 'bold']) }}
Jade
Jade parser. You need install it by composer require undercloud/picojade.
$ant->activate('Jade')
Lang
Wrapper for Lang. You need install it by composer require undercloud/lang.
$ant->activate('Lang'[,$options])
// you can use $.lang shortcut helper
{{ $.lang('message.name') }}
Leaf
Wrapper for Leaf. You need install it by composer require undercloud/leaf.
$ant->activate('Leaf')
Markdown
Markdown parser. Port for parsedown. You need install it by composer require erusev/parsedown.
$ant->activate('Markdown')
Validator
HTML validator and linter.
// basic validator, check DOM tree only
$ant->activate('Validator')
// strict, check deprecated tags and attrs, non standard tags, required attrs etc...
$ant->activate('Validator', ['strict' => true])
YouTube
Embed Youtube video.
$ant->activate('YouTube')
// extended setup
$ant->activate('YouTube', ['params' => [...], 'attrs' => [...]])
// embed video
{{{ $.plugin->youtube($video_id[,$options]) }}}
// get preview image url, $size - one of values: hq, mq, sd, maxres or empty for default
{{ $.plugin->youtube->preview($video_id[,$size]) }}