diff --git a/README.md b/README.md
index c060c54..2839411 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,8 @@
Fenom - Template Engine for PHP
===============================
-> Composer package: `{"fenom/fenom": "2.*"}`. See on [Packagist.org](https://packagist.org/packages/fenom/fenom)
+> Composer [package](https://packagist.org/packages/fenom/fenom): `{"fenom/fenom": "2.*"}`.
+> For old version: `{"fenom/fenom": "1.*"}`. List of incompatibilities between 1.* and 2.* versions.
[![Latest Stable Version](https://poser.pugx.org/fenom/fenom/v/stable.png)](https://packagist.org/packages/fenom/fenom)
[![Build Status](https://travis-ci.org/bzick/fenom.svg?branch=develop)](https://travis-ci.org/bzick/fenom)
@@ -9,6 +10,10 @@ Fenom - Template Engine for PHP
[![Total Downloads](https://poser.pugx.org/fenom/fenom/downloads.png)](https://packagist.org/packages/fenom/fenom)
## [Usage](./docs/usage.md) :: [Documentation](./docs/readme.md) :: [Benchmark](./docs/benchmark.md) :: [Articles](./docs/articles.md)
+## What is it
+
+*Fenom* (from "fenomenal") — шаблонизатор на PHP с большими возможностями и синтаксисом Smarty.
+
* Simple [syntax](./docs/syntax.md)
* [Fast](./docs/benchmark.md)
* [Secure](./docs/settings.md)
diff --git a/docs/start.md b/docs/start.md
new file mode 100644
index 0000000..a53e07c
--- /dev/null
+++ b/docs/start.md
@@ -0,0 +1,71 @@
+Basic usage
+===========
+
+## Install Fenom
+
+### Composer
+
+Add package Fenom in your require-list in `composer.json`:
+```json
+{
+ "require": {
+ "fenom/fenom": "2.*"
+ }
+}
+```
+and update project's dependencies: `composer update`.
+
+### Custom loader
+
+Clone Fenom to any directory: `git clone https://github.com/bzick/fenom.git`. Recommended use latest tag.
+Fenom use [psr-0](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md#autoloading-standard) autoloading standard. Therefore you can
+* use `psr-0` format in your project loader for loading Fenom's classes
+* or register Fenom's autoloader: ```php
+Fenom::registerAutoload();
+```
+For loading itself.
+
+Also you can use this autoloader for loading any library with `psr-0` file naming:
+```php
+Fenom::registerAutoload(PROJECT_DIR."/src");
+```
+
+## Setup Fenom
+
+Create an object via factory method
+```php
+$fenom = Fenom::factory('/path/to/templates', '/path/to/compiled/template', $options);
+```
+
+Create an object via `new` operator
+```php
+$fenom = new Fenom(new Provider('/path/to/templates'));
+$fenom->setCompileDir('/path/to/template/cache');
+$fenom->setOptions($options);
+```
+
+* `/path/to/templates` — directory, where stores your templates.
+* `/path/to/template/cache` — directory, where stores compiled templates in PHP files.
+* `$options` - bit-mask or array of [Fenom settings](./docs/settings.md).
+
+### Use Fenom
+
+Output template
+```php
+$fenom->display("template/name.tpl", $vars);
+```
+
+Get the result of rendering the template
+```php
+$result = $fenom->fetch("template/name.tpl", $vars);
+```
+
+Create the pipeline of rendering into callback
+```php
+$fenom->pipe(
+ "template/sitemap.tpl",
+ $vars,
+ $callback = [new SplFileObject("/tmp/sitemap.xml", "w"), "fwrite"], // pipe to file /tmp/sitemap.xml
+ $chunk_size = 1e6 // chunk size for callback
+);
+```
diff --git a/docs/syntax.md b/docs/syntax.md
index ef3332e..0063d1a 100644
--- a/docs/syntax.md
+++ b/docs/syntax.md
@@ -1,11 +1,61 @@
-Syntax [RU]
-===========
+Syntax
+======
-Fenom implement [Smarty](http://www.smarty.net/) syntax with some improvements
+Fenom implements [Smarty](http://www.smarty.net/) syntax with some improvements.
+All Fenom tags enclosed in the delimiters `{` and `}`, for example `{var $five = 5}`.
+If you wanna leave delimiters as is in the template use [special statements or tags](#ignoring-delimiters).
+
+*Note*
+Fenom implements [Smarty](http://www.smarty.net/) syntax but not implements Smarty tags, however, some tags very similar.
+But not so bad, Fenom has the [extras](https://github.com/bzick/fenom-extra) that make Fenom like Smarty.
## Variable
-### Use variables
+Variables in Fenom can be either displayed directly or used as arguments for functions, attributes and modifiers,
+inside conditional expressions, etc.
+
+### Example variables
+
+Next example uses simple variables `$user_id` ans `$user_name`
+```smarty
+
+```
+
+Example outputs next HTML code:
+```html
+
+```
+
+Переменные могут быть массивом. В этом случае обращение по ключу происходит через опертор `.` или, как в PHP, через операторы `[` и `]`
+```smarty
+
+```
+
+`{$user.id}` and `{$user['id']}` are same.
+
+```smarty
+
+```
+
+```smarty
+
+```
+
+*Note*
+Be careful, Fenom do not checks existence of the method before invoke.
+To avoid the problem class of the object have to define method `__call`, which throws an exception etc.
+Also you may disable invoke method in [settings](./docs/settings.md).
+
+Multidimensional value support
+
+```smarty
+{$foo.bar.baz}
+{$foo.$bar.$baz}
+{$foo[4].baz}
+{$foo[4].$baz}
+{$foo.bar.baz[4]}
+{$foo[ $bar.baz ]}
+```
```smarty
{$foo}
@@ -25,7 +75,7 @@ Fenom implement [Smarty](http://www.smarty.net/) syntax with some improvements
### System variable
-Unnamed system variable starts with `$.` and allow access to global variables and system info (fix doc):
+Unnamed system variable starts with `$.` and allows access to global variables and system info (fix doc):
* `$.get` is `$_GET`.
* `$.post` is `$_POST`.
@@ -47,17 +97,6 @@ Unnamed system variable starts with `$.` and allow access to global variables an
{/if}
```
-### Multidimensional value support
-
-```smarty
-{$foo.bar.baz}
-{$foo.$bar.$baz}
-{$foo[4].baz}
-{$foo[4].$baz}
-{$foo.bar.baz[4]}
-{$foo[ $bar.baz ]}
-```
-
### Math operations
```smarty
diff --git a/docs/usage.md b/docs/usage.md
deleted file mode 100644
index e008084..0000000
--- a/docs/usage.md
+++ /dev/null
@@ -1,38 +0,0 @@
-Basic usage
-===========
-
-### Initialize Fenom
-
-Creating an object via factory method
-```php
-$fenom = Fenom::factory('/path/to/templates', '/path/to/compiled/template', $options);
-```
-
-Creating an object via `new` operator
-```php
-$fenom = new Fenom(new Provider('/path/to/templates'));
-$fenom->setCompileDir('/path/to/template/cache');
-$fenom->setOptions($options);
-```
-
-### Rendering template
-
-Output template
-```php
-$fenom->display("template/name.tpl", $vars);
-```
-
-Get the result of rendering the template
-```php
-$result = $fenom->fetch("template/name.tpl", $vars);
-```
-
-Create the pipeline of rendering into callback
-```php
-$fenom->pipe(
- "template/sitemap.tpl",
- $vars,
- $callback = [new SplFileObject("/tmp/sitemap.xml", "w"), "fwrite"], // pipe to file /tmp/sitemap.xml
- $chunk_size = 1e6 // chunk size for callback
-);
-```
diff --git a/src/Fenom.php b/src/Fenom.php
index 6c5929d..5f3b78a 100644
--- a/src/Fenom.php
+++ b/src/Fenom.php
@@ -35,11 +35,8 @@ class Fenom
const DISABLE_CACHE = 0x400;
const FORCE_VERIFY = 0x800;
const AUTO_TRIM = 0x1000; // reserved
- const DENY_STATICS = 0x2000;
- const AUTO_STRIP = 0x4000;
-
- /* @deprecated */
- const DENY_INLINE_FUNCS = 0x20;
+ const DENY_STATICS = 0x2000;
+ const AUTO_STRIP = 0x4000;
/* Default parsers */
const DEFAULT_CLOSE_COMPILER = 'Fenom\Compiler::stdClose';
@@ -66,6 +63,7 @@ class Fenom
"force_verify" => self::FORCE_VERIFY,
"auto_trim" => self::AUTO_TRIM,
"disable_statics" => self::DENY_STATICS,
+ "strip" => self::AUTO_STRIP,
);
/**
@@ -265,10 +263,20 @@ class Fenom
'type' => self::INLINE_COMPILER,
'parser' => 'Fenom\Compiler::tagRaw'
),
- 'autoescape' => array(
+ 'autoescape' => array( // deprecated
'type' => self::BLOCK_COMPILER,
- 'open' => 'Fenom\Compiler::autoescapeOpen',
- 'close' => 'Fenom\Compiler::autoescapeClose'
+ 'open' => 'Fenom\Compiler::escapeOpen',
+ 'close' => 'Fenom\Compiler::nope'
+ ),
+ 'escape' => array(
+ 'type' => self::BLOCK_COMPILER,
+ 'open' => 'Fenom\Compiler::escapeOpen',
+ 'close' => 'Fenom\Compiler::nope'
+ ),
+ 'strip' => array(
+ 'type' => self::BLOCK_COMPILER,
+ 'open' => 'Fenom\Compiler::stripOpen',
+ 'close' => 'Fenom\Compiler::nope'
)
);
@@ -988,7 +996,7 @@ class Fenom
}
/**
- * Register PSR-0 autoload for Fenom
+ * Register PSR-0 autoload
* @param string $dir custom directory for autoloading, if NULL — autoload itself
* @return bool
*/
diff --git a/src/Fenom/Compiler.php b/src/Fenom/Compiler.php
index 2c5486c..91c987a 100644
--- a/src/Fenom/Compiler.php
+++ b/src/Fenom/Compiler.php
@@ -962,7 +962,7 @@ class Compiler
* @param Tokenizer $tokens
* @param Tag $tag
*/
- public static function autoescapeOpen(Tokenizer $tokens, Tag $tag)
+ public static function escapeOpen(Tokenizer $tokens, Tag $tag)
{
$expected = ($tokens->get(T_STRING) == "true" ? true : false);
$tokens->next();
@@ -970,11 +970,20 @@ class Compiler
}
/**
- * @param Tokenizer $tokens
- * @param Tag $tag
+ * Do nothing
*/
- public static function autoescapeClose(Tokenizer $tokens, Tag $tag)
+ public static function nope()
{
}
+ /**
+ * @param Tokenizer $tokens
+ * @param Tag $tag
+ */
+ public static function stripOpen(Tokenizer $tokens, Tag $tag)
+ {
+ $expected = ($tokens->get(T_STRING) == "true" ? true : false);
+ $tokens->next();
+ $tag->setOption(\Fenom::AUTO_STRIP, $expected);
+ }
}
diff --git a/src/Fenom/Modifier.php b/src/Fenom/Modifier.php
index 4646ba3..22f326a 100644
--- a/src/Fenom/Modifier.php
+++ b/src/Fenom/Modifier.php
@@ -140,7 +140,7 @@ class Modifier
{
$str = trim($str);
if ($to_line) {
- return preg_replace('#[\s]+#ms', ' ', $str);
+ return preg_replace('#\s+#ms', ' ', $str);
} else {
return preg_replace('#[ \t]{2,}#', ' ', $str);
}
@@ -158,7 +158,7 @@ class Modifier
} elseif (is_array($item)) {
return count($item);
} elseif ($item instanceof \Countable) {
- return count($item);
+ return $item->count();
} else {
return 0;
}
diff --git a/src/Fenom/Tag.php b/src/Fenom/Tag.php
index 5bdde33..e71ffdd 100644
--- a/src/Fenom/Tag.php
+++ b/src/Fenom/Tag.php
@@ -263,13 +263,27 @@ class Tag extends \ArrayObject
return $this->tpl->out($code, $this->escape);
}
+ /**
+ * Enable escape option for the tag
+ */
public function optEscape()
{
$this->escape = true;
}
+ /**
+ * Disable escape option for the tag
+ */
public function optRaw()
{
$this->escape = false;
}
+
+ /**
+ * Enable strip spaces option for the tag
+ */
+ public function optStrip()
+ {
+ $this->setOption(\Fenom::AUTO_STRIP, true);
+ }
}
\ No newline at end of file
diff --git a/src/Fenom/Template.php b/src/Fenom/Template.php
index b76dd57..ed6d805 100644
--- a/src/Fenom/Template.php
+++ b/src/Fenom/Template.php
@@ -344,7 +344,6 @@ class Template extends Render
foreach ($this->_filters as $filter) {
$text = call_user_func($filter, $this, $text);
}
- $this->_body .= $text;
} else {
$fragments = explode("", $text);
foreach ($fragments as &$fragment) {
@@ -354,11 +353,16 @@ class Template extends Render
}
}
}
- $this->_body .= implode('', $fragments);
+ $text = implode('', $fragments);
}
} else {
- $this->_body .= str_replace("", '' . PHP_EOL, $text);
+ $text = str_replace("", '' . PHP_EOL, $text);
}
+ if($this->_options & Fenom::AUTO_STRIP) {
+ $text = preg_replace('/\s+/uS', ' ', $text);
+ $text = preg_replace('/\s*([\pP\pS]+)\s*/uS', '$1', $text);
+ }
+ $this->_body .= $text;
}
/**
diff --git a/tests/TestCase.php b/tests/TestCase.php
index a7f86f7..da390e7 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -11,18 +11,7 @@ class TestCase extends \PHPUnit_Framework_TestCase
*/
public $fenom;
- public $values = array(
- "zero" => 0,
- "one" => 1,
- "two" => 2,
- "three" => 3,
- "float" => 4.5,
- "bool" => true,
- 0 => "empty value",
- 1 => "one value",
- 2 => "two value",
- 3 => "three value",
- );
+ public $values;
public static function getVars()
{
@@ -40,6 +29,12 @@ class TestCase extends \PHPUnit_Framework_TestCase
"b" => 2,
"two" => 2
),
+ "num" => array(
+ 1 => "one",
+ 2 => "two",
+ 3 => "three",
+ 4 => "four"
+ ),
0 => "empty value",
1 => "one value",
2 => "two value",
@@ -62,6 +57,7 @@ class TestCase extends \PHPUnit_Framework_TestCase
$this->fenom->addModifier('append', __CLASS__ . '::append');
$this->fenom->addFunction('test_function', __CLASS__ . '::inlineFunction');
$this->fenom->addBlockFunction('test_block_function', __CLASS__ . '::blockFunction');
+ $this->values = $this->getVars();
}
public static function dots($value)
diff --git a/tests/cases/Fenom/TemplateTest.php b/tests/cases/Fenom/TemplateTest.php
index 8391480..86da05f 100644
--- a/tests/cases/Fenom/TemplateTest.php
+++ b/tests/cases/Fenom/TemplateTest.php
@@ -185,7 +185,7 @@ class TemplateTest extends TestCase
'Mod: {$lorem|str_rot13}!',
'Fenom\Error\CompileException',
"Modifier str_rot13 not found",
- Fenom::DENY_INLINE_FUNCS
+ Fenom::DENY_NATIVE_FUNCS
),
array('Mod: {$lorem|my_encode}!', 'Fenom\Error\CompileException', "Modifier my_encode not found"),
array('Mod: {$lorem|truncate:}!', 'Fenom\Error\CompileException', "Unexpected end of expression"),
diff --git a/tests/cases/FenomTest.php b/tests/cases/FenomTest.php
index 351bed9..e3aac2f 100644
--- a/tests/cases/FenomTest.php
+++ b/tests/cases/FenomTest.php
@@ -13,7 +13,8 @@ class FenomTest extends \Fenom\TestCase
array("auto_reload", Fenom::AUTO_RELOAD),
array("force_include", Fenom::FORCE_INCLUDE),
array("auto_escape", Fenom::AUTO_ESCAPE),
- array("force_verify", Fenom::FORCE_VERIFY)
+ array("force_verify", Fenom::FORCE_VERIFY),
+ array("strip", Fenom::AUTO_STRIP),
);
}
@@ -289,6 +290,19 @@ class FenomTest extends \Fenom\TestCase
);
$this->assertSame(3, $iteration);
}
+
+ /**
+ * @group strip
+ */
+ public function testStrip() {
+ $this->fenom->setOptions(Fenom::AUTO_STRIP);
+ $tpl = <<
+ number {\$num.1}
+
+TPL;
+ $this->assertRender($tpl, '');
+ }
}