Skip to content

Commit

Permalink
Merge pull request #22 from Talesoft/dev-master
Browse files Browse the repository at this point in the history
New features, more tests, minor bugfixes
  • Loading branch information
TorbenKoehn committed Nov 6, 2015
2 parents df6f206 + a3c93a2 commit 5533809
Showing 25 changed files with 454 additions and 110 deletions.
174 changes: 157 additions & 17 deletions Compiler.php
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@
* @author Talesoft <[email protected]>
* @copyright Copyright (c) 2015 Talesoft (http://talesoft.io)
* @license http://licenses.talesoft.io/2015/MIT.txt MIT License
* @version 1.1.1
* @version 1.2
* @link http://jade.talesoft.io/docs/files/Compiler.html
* @since File available since Release 1.0
*/
@@ -74,7 +74,7 @@
* //Make sure the variables are accessible by the included template
* extract($variables);
*
* //Compiler needs an $__args variable to pass arguments on to mixins
* //Compiler needs an $__args variables to pass arguments on to mixins
* $__args = $variables;
*
* //Include the rendered PHTML directly
@@ -91,7 +91,7 @@
* @author Talesoft <[email protected]>
* @copyright Copyright (c) 2015 Talesoft (http://talesoft.io)
* @license http://licenses.talesoft.io/2015/MIT.txt MIT License
* @version 1.1.1
* @version 1.2
* @link http://jade.talesoft.io/docs/classes/Tale.Jade.Compiler.html
* @since File available since Release 1.0
*/
@@ -396,7 +396,7 @@ public function addFilter($name, $callback)
*
* Look at Renderer to get this done for you
*
* Before evaluating you should set a $__args variable
* Before evaluating you should set a $__args variables
* that will be passed through mixins.
* It like a global scope.
*
@@ -489,7 +489,7 @@ public function compileFile($path)
}

/**
* Checks if a variable is scalar (or "not an expression").
* Checks if a variables is scalar (or "not an expression").
*
* These values don't get much special handling, they are mostly
* simple attributes values like `type="button"` or `method='post'`
@@ -528,9 +528,9 @@ protected function compileScalar($value, $attribute = false)
}

/**
* Checks if a value is a variable.
* Checks if a value is a variables.
*
* A variable needs to start with $.
* A variables needs to start with $.
* After that only a-z, A-Z and _ can follow
* After that you can use any character of
* a-z, A-Z, 0-9, _, [, ], -, >, ' and "
@@ -558,7 +558,7 @@ protected function isVariable($value)
*
* Interpolation is initialized with # (escaped) or ! (not escaped)
*
* After that use either {} brackets for variable expressions
* After that use either {} brackets for variables expressions
* or [] for Jade-expressions
*
* e.g.
@@ -1098,7 +1098,7 @@ protected function handleMixin(Node $node)
* Compiles found mixins under each other into a single PHTML block.
*
* Mixins will be anonymous functions inside a $__mixins array
* The mixins also pass the global $__args variable on (so that it _is_ global)
* The mixins also pass the global $__args variables on (so that it _is_ global)
*
* @return string The compile PHTML
*/
@@ -1144,7 +1144,7 @@ protected function compileMixins()

$phtml .= $this->createCode(
'$__mixins[\''.$name.'\'] = function(array $__arguments) use($__args, $__mixins) {
static $__defaults = '.var_export($args, true).';
static $__defaults = '.$this->exportArray($args).';
$__arguments = array_replace($__defaults, $__arguments);
$__args = array_replace($__args, $__arguments);
extract($__args); '.$variadic.'
@@ -1443,7 +1443,7 @@ protected function compileWhen(Node $node)
/**
* Compiles a each-instruction into a foreach-loop PHTML block.
*
* the $ in the variable names are optional
* the $ in the variables names are optional
*
* @param Node $node the each-node to compile
*
@@ -1460,8 +1460,9 @@ protected function compileEach(Node $node)
$subject = "isset({$subject}) ? {$subject} : []";

$as = "\${$node->itemName}";

if ($node->keyName)
$as .= " => \${$node->keyName}";
$as = "\${$node->keyName} => ".$as;

$var = '$__iterator'.($id++);
$phtml = $this->createCode("$var = {$subject};").$this->newLine();
@@ -1479,8 +1480,6 @@ protected function compileEach(Node $node)
* Notice that if it has no children, we assume it's a do/while loop
* and don't print brackets
*
* @todo Check for do-instruction via $node->prev()
*
* @param Node $node the while-node to compile
*
* @return string The compiled PHTML
@@ -1494,7 +1493,22 @@ protected function compileWhile(Node $node)
$subject = "isset({$subject}) ? {$subject} : null";

$hasChildren = count($node->children) > 0;
$phtml = $this->createCode("while ({$subject})".($hasChildren ? ' {' : '')).$this->newLine();
$isDoWhile = $node->prev() && $node->prev()->type === 'do';

if (!$hasChildren && !$isDoWhile)
$this->throwException(
'A while-loop without children you loop through is not valid if'
.' there\'s no do-statement before it.',
$node
);
else if ($isDoWhile && $hasChildren)
$this->throwException(
'In a do-while statement the while-part shouldn\'t have any children',
$node
);

$phtml = $this->createCode("while ({$subject})".($hasChildren ? ' {' : ''), $isDoWhile ? ' ' : '<?php ').$this->newLine();

if ($hasChildren) {

$phtml .= $this->compileChildren($node->children).$this->newLine();
@@ -1504,6 +1518,24 @@ protected function compileWhile(Node $node)
return $phtml;
}

/**
* Compiles a for-loop into PHTML.
*
* @param Node $node the while-node to compile
*
* @return string The compiled PHTML
*/
protected function compileFor(Node $node)
{

$subject = $node->subject;
$phtml = $this->createCode("for ({$subject}) {").$this->newLine();
$phtml .= $this->compileChildren($node->children).$this->newLine();
$phtml .= $this->indent().$this->createCode('}').$this->newLine();

return $phtml;
}

/**
* Compiles a do-instruction into PHTML.
*
@@ -1530,15 +1562,91 @@ protected function compileDo(Node $node)
"A do-statement needs a while-statement following immediately"
);

//Notice that the } wont have closing ? >, php needs this.
//Check compileWhile to see the combination of both
$phtml = $this->createCode("do {").$this->newLine();
$phtml .= $this->compileChildren($node->children).$this->newLine();
$phtml .= $this->indent().$this->createCode('}').$this->newLine();
$phtml .= $this->indent().$this->createCode('}', '<?php ', '').$this->newLine();

return $phtml;
}

/**
* Compiles a filter-node intp PHTML.
* Compiles a variable-node into PHTML.
*
* @param Node $node the variable node to compile
*
* @return string The compiled PHTML
* @throws Exception
*/
protected function compileVariable(Node $node)
{

//Attribute-style assignment
//$variable(a=b, c=d)
if (count($node->attributes)) {

if (count($node->children))
$this->throwException(
'A variable node with attributes cant have any children',
$node
);

//Attribute-based assignment
$array = [];
foreach ($node->attributes as $attr) {

$name = $attr->name;
$value = trim($attr->value, '"\'');

if (!$name)
$array[] = $value;
else {

if (isset($array[$name])) {

if (is_array($array[$name]))
$array[$name][] = $value;
else
$array[$name] = [$array[$name], $value];
} else
$array[$name] = $value;
}
}

//In $array we have the final array to assign on the variable, sadly
//we can't just use var_export, since we might have variables inside
//the array that shouldn't be converted to strings.
//We convert it ourself

return $this->createCode(
"\$__value = ".$this->exportArray($array)."; "
."\${$node->name} = isset(\${$node->name}) ? array_replace_recursive(\${$node->name}, \$__value) : \$__value; "
."unset(\$__value);"
);
}

if (!count($node->children)) {

//No children, this is simple variable output (Escaped!)
return $this->createShortCode(
"htmlentities(\${$node->name}, \\ENT_QUOTES, '".$this->_options['escapeCharset']."')"
);
}

if ($node->children[0]->type !== 'expression') {

$this->throwException(
'Variable nodes can only have expression children',
$node
);
}

return $this->createCode("\${$node->name} = ".$node->children[0]->value);
}

/**
* Compiles a filter-node into PHTML.
*
* The filters are drawn from the filters-option
*
@@ -1893,6 +2001,38 @@ protected function compileComment(Node $node)
return $node->rendered ? $this->createMarkupComment($content) : $this->createPhpComment($content);
}

/**
* Exports an array to a string.
*
* This works similar to var_export in PHP, with the difference
* that it won't try to convert variable-style strings to
* quote-enclosed strings
*
* @param array $array the array to export
*
* @return string the exported array
*/
protected function exportArray(array $array)
{

$pairs = [];
foreach ($array as $key => $val) {

$pair = var_export($key, true).' => ';

if (is_array($val))
$pair .= $this->exportArray($val);
else if ($this->isVariable($val))
$pair .= $val;
else
$pair .= var_export($val, true);

$pairs[] = $pair;
}

return '['.implode(', ', $pairs).']';
}

/**
* Compiles a simple error helper in a string to be prepended to the final PHTML.
*
4 changes: 2 additions & 2 deletions Compiler/Exception.php
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@
* @author Talesoft <[email protected]>
* @copyright Copyright (c) 2015 Talesoft (http://talesoft.io)
* @license http://licenses.talesoft.io/2015/MIT.txt MIT License
* @version 1.1.1
* @version 1.2
* @link http://jade.talesoft.io/docs/files/Compiler.Exception.html
* @since File available since Release 1.0
*/
@@ -35,7 +35,7 @@
* @author Talesoft <[email protected]>
* @copyright Copyright (c) 2015 Talesoft (http://talesoft.io)
* @license http://licenses.talesoft.io/2015/MIT.txt MIT License
* @version 1.1.1
* @version 1.2
* @link http://jade.talesoft.io/docs/classes/Tale.Jade.Compiler.Exception.html
* @since File available since Release 1.0
*/
4 changes: 2 additions & 2 deletions Filter.php
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@
* @author Talesoft <[email protected]>
* @copyright Copyright (c) 2015 Talesoft (http://talesoft.io)
* @license http://licenses.talesoft.io/2015/MIT.txt MIT License
* @version 1.1.1
* @version 1.2
* @link http://jade.talesoft.io/docs/files/Filter.html
* @since File available since Release 1.0
*/
@@ -48,7 +48,7 @@
* @author Talesoft <[email protected]>
* @copyright Copyright (c) 2015 Talesoft (http://talesoft.io)
* @license http://licenses.talesoft.io/2015/MIT.txt MIT License
* @version 1.1.1
* @version 1.2
* @link http://jade.talesoft.io/docs/classes/Tale.Jade.Filter.html
* @since File available since Release 1.0
*/
Loading

0 comments on commit 5533809

Please sign in to comment.