wproot 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/Rakefile +2 -0
- data/bin/wproot +7 -0
- data/lib/wproot.rb +11 -0
- data/lib/wproot/cli.rb +35 -0
- data/lib/wproot/compass.rb +15 -0
- data/lib/wproot/haml.rb +15 -0
- data/lib/wproot/version.rb +3 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/wproot_spec.rb +59 -0
- data/vendor/HamlPHP.php +7 -0
- data/vendor/HamlPHP/.gitignore +6 -0
- data/vendor/HamlPHP/MIT-LICENSE +22 -0
- data/vendor/HamlPHP/README.mkd +39 -0
- data/vendor/HamlPHP/src/HamlPHP/CommentNode.php +92 -0
- data/vendor/HamlPHP/src/HamlPHP/Compiler.php +109 -0
- data/vendor/HamlPHP/src/HamlPHP/ContentEvaluator/ContentEvaluator.php +16 -0
- data/vendor/HamlPHP/src/HamlPHP/ContentEvaluator/DefaultContentEvaluator.php +22 -0
- data/vendor/HamlPHP/src/HamlPHP/DoctypeNode.php +47 -0
- data/vendor/HamlPHP/src/HamlPHP/Element.php +618 -0
- data/vendor/HamlPHP/src/HamlPHP/ElementNode.php +222 -0
- data/vendor/HamlPHP/src/HamlPHP/Filter/CssFilter.php +31 -0
- data/vendor/HamlPHP/src/HamlPHP/Filter/Filter.php +18 -0
- data/vendor/HamlPHP/src/HamlPHP/Filter/FilterContainer.php +34 -0
- data/vendor/HamlPHP/src/HamlPHP/Filter/JavascriptFilter.php +29 -0
- data/vendor/HamlPHP/src/HamlPHP/Filter/PhpFilter.php +24 -0
- data/vendor/HamlPHP/src/HamlPHP/Filter/PlainFilter.php +46 -0
- data/vendor/HamlPHP/src/HamlPHP/FilterNode.php +29 -0
- data/vendor/HamlPHP/src/HamlPHP/HamlNode.php +75 -0
- data/vendor/HamlPHP/src/HamlPHP/HamlPHP.php +191 -0
- data/vendor/HamlPHP/src/HamlPHP/Helpers.php +136 -0
- data/vendor/HamlPHP/src/HamlPHP/Interpolation.php +71 -0
- data/vendor/HamlPHP/src/HamlPHP/NodeFactory.php +80 -0
- data/vendor/HamlPHP/src/HamlPHP/RootNode.php +133 -0
- data/vendor/HamlPHP/src/HamlPHP/Storage/DontEvaluateStorage.php +68 -0
- data/vendor/HamlPHP/src/HamlPHP/Storage/FileStorage.php +74 -0
- data/vendor/HamlPHP/src/HamlPHP/Storage/Storage.php +24 -0
- data/vendor/HamlPHP/src/HamlPHP/TagNode.php +125 -0
- data/vendor/HamlPHP/src/HamlPHP/Util/BaseException.php +340 -0
- data/vendor/HamlPHP/src/HamlPHP/Util/BaseObject.php +94 -0
- data/vendor/HamlPHP/src/HamlPHP/Util/StringScanner.php +989 -0
- data/wproot.gemspec +21 -0
- metadata +126 -0
@@ -0,0 +1,191 @@
|
|
1
|
+
<?php
|
2
|
+
|
3
|
+
require_once 'Storage/Storage.php';
|
4
|
+
require_once 'Compiler.php';
|
5
|
+
require_once 'ContentEvaluator/DefaultContentEvaluator.php';
|
6
|
+
|
7
|
+
class HamlPHP
|
8
|
+
{
|
9
|
+
private $_compiler = null;
|
10
|
+
private $_storage = null;
|
11
|
+
private $_contentEvaluator = null;
|
12
|
+
private $_nodeFactory = null;
|
13
|
+
private $_filterContainer = null;
|
14
|
+
private $_cacheEnabled = true;
|
15
|
+
|
16
|
+
// Placeholder until config gets properly implemented
|
17
|
+
public static $Config = array(
|
18
|
+
'escape_html' => false
|
19
|
+
);
|
20
|
+
|
21
|
+
public function __construct(Storage $storage)
|
22
|
+
{
|
23
|
+
$this->_compiler = $this->getCompiler();
|
24
|
+
$this->_storage = $storage;
|
25
|
+
|
26
|
+
if ($this->_storage instanceof ContentEvaluator) {
|
27
|
+
$this->setContentEvaluator($this->_storage);
|
28
|
+
} else {
|
29
|
+
$this->setContentEvaluator(new DefaultContentEvaluator());
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
/**
|
34
|
+
* Sets a content evaluator.
|
35
|
+
*
|
36
|
+
* @param ContentEvaluator $contentEvaluator
|
37
|
+
*/
|
38
|
+
public function setContentEvaluator(ContentEvaluator $contentEvaluator)
|
39
|
+
{
|
40
|
+
$this->_contentEvaluator = $contentEvaluator;
|
41
|
+
}
|
42
|
+
|
43
|
+
/**
|
44
|
+
* Sets a filter container and updates the node factory to use it.
|
45
|
+
*
|
46
|
+
* @param FilterContainer $container
|
47
|
+
*/
|
48
|
+
public function setFilterContainer(FilterContainer $container)
|
49
|
+
{
|
50
|
+
$this->_filterContainer = $container;
|
51
|
+
$this->getNodeFactory()->setFilterContainer($this->getFilterContainer());
|
52
|
+
}
|
53
|
+
|
54
|
+
/**
|
55
|
+
* Returns a filter container object. Initializes the filter container with
|
56
|
+
* default filters if it's null.
|
57
|
+
*
|
58
|
+
* @return FilterContainer
|
59
|
+
*/
|
60
|
+
public function getFilterContainer()
|
61
|
+
{
|
62
|
+
if ($this->_filterContainer === null) {
|
63
|
+
$filterContainer = new FilterContainer();
|
64
|
+
$filterContainer->addFilter(new CssFilter());
|
65
|
+
$filterContainer->addFilter(new PlainFilter());
|
66
|
+
$filterContainer->addFilter(new JavascriptFilter());
|
67
|
+
$filterContainer->addFilter(new PhpFilter());
|
68
|
+
|
69
|
+
$this->_filterContainer = $filterContainer;
|
70
|
+
}
|
71
|
+
|
72
|
+
return $this->_filterContainer;
|
73
|
+
}
|
74
|
+
|
75
|
+
/**
|
76
|
+
* Sets a node factory.
|
77
|
+
*
|
78
|
+
* @param NodeFactory $factory
|
79
|
+
*/
|
80
|
+
public function setNodeFactory(NodeFactory $factory)
|
81
|
+
{
|
82
|
+
$this->_nodeFactory = $factory;
|
83
|
+
$this->getNodeFactory()->setFilterContainer($this->getFilterContainer());
|
84
|
+
}
|
85
|
+
|
86
|
+
/**
|
87
|
+
* Returns a node factory object.
|
88
|
+
*
|
89
|
+
* @return NodeFactory
|
90
|
+
*/
|
91
|
+
public function getNodeFactory()
|
92
|
+
{
|
93
|
+
if ($this->_nodeFactory === null) {
|
94
|
+
$this->setNodeFactory(new NodeFactory());
|
95
|
+
}
|
96
|
+
|
97
|
+
return $this->_nodeFactory;
|
98
|
+
}
|
99
|
+
|
100
|
+
/**
|
101
|
+
* Sets a compiler.
|
102
|
+
*
|
103
|
+
* @param Compiler $compiler
|
104
|
+
*/
|
105
|
+
public function setCompiler(Compiler $compiler)
|
106
|
+
{
|
107
|
+
$this->_compiler = $compiler;
|
108
|
+
}
|
109
|
+
|
110
|
+
/**
|
111
|
+
* Returns a compiler object.
|
112
|
+
*
|
113
|
+
* @return Compiler
|
114
|
+
*/
|
115
|
+
public function getCompiler()
|
116
|
+
{
|
117
|
+
if ($this->_compiler === null) {
|
118
|
+
$this->_compiler = new Compiler($this);
|
119
|
+
}
|
120
|
+
|
121
|
+
return $this->_compiler;
|
122
|
+
}
|
123
|
+
|
124
|
+
/**
|
125
|
+
* Enables caching.
|
126
|
+
*/
|
127
|
+
public function enableCache()
|
128
|
+
{
|
129
|
+
$this->_cacheEnabled = true;
|
130
|
+
}
|
131
|
+
|
132
|
+
/**
|
133
|
+
* Disables caching.
|
134
|
+
*/
|
135
|
+
public function disableCache()
|
136
|
+
{
|
137
|
+
$this->_cacheEnabled = false;
|
138
|
+
}
|
139
|
+
|
140
|
+
/**
|
141
|
+
* Returns true if caching is enabled.
|
142
|
+
*
|
143
|
+
* @return bool
|
144
|
+
*/
|
145
|
+
public function isCacheEnabled()
|
146
|
+
{
|
147
|
+
return $this->_cacheEnabled;
|
148
|
+
}
|
149
|
+
|
150
|
+
/**
|
151
|
+
* Parses a haml file and returns a cached path to the file.
|
152
|
+
*
|
153
|
+
* @param string $fileName
|
154
|
+
*/
|
155
|
+
public function parseFile($fileName, array $templateVars = array())
|
156
|
+
{
|
157
|
+
$content = $this->getContentFromStorage($fileName);
|
158
|
+
|
159
|
+
return $this->_contentEvaluator->evaluate(
|
160
|
+
$content, $templateVars, $this->generateFileId($fileName));
|
161
|
+
}
|
162
|
+
|
163
|
+
/**
|
164
|
+
* Returns content from a storage
|
165
|
+
*
|
166
|
+
* @param string $fileName
|
167
|
+
* @return string
|
168
|
+
*/
|
169
|
+
public function getContentFromStorage($fileName)
|
170
|
+
{
|
171
|
+
$fileId = $this->generateFileId($fileName);
|
172
|
+
|
173
|
+
if ($this->_storage === null) {
|
174
|
+
throw new Exception('Storage not set');
|
175
|
+
}
|
176
|
+
|
177
|
+
if ($this->isCacheEnabled()
|
178
|
+
&& $this->_storage->isFresh($fileId)) {
|
179
|
+
return $this->_storage->fetch($fileId);
|
180
|
+
}
|
181
|
+
|
182
|
+
// file is not fresh, so compile and cache it
|
183
|
+
$this->_storage->cache($fileId, $this->_compiler->parseFile($fileName));
|
184
|
+
return $this->_storage->fetch($fileId);
|
185
|
+
}
|
186
|
+
|
187
|
+
private function generateFileId($filename)
|
188
|
+
{
|
189
|
+
return str_replace(array(':','/','\\'), '_', ltrim($filename, '/\\'));
|
190
|
+
}
|
191
|
+
}
|
@@ -0,0 +1,136 @@
|
|
1
|
+
<?php
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Returns a double or single quoted string. whatever works without changing the content of the string.
|
5
|
+
* Example:
|
6
|
+
* @code
|
7
|
+
* quote("McDonald's") # -> "\"McDonad's\""
|
8
|
+
* quote("You \"win\", looser") # -> "'You \"win\", looser'"
|
9
|
+
* @endcode
|
10
|
+
*
|
11
|
+
* If it can't be done. It will return false.
|
12
|
+
*
|
13
|
+
* @param $str
|
14
|
+
* @return mixed The quoted string or false
|
15
|
+
*/
|
16
|
+
function quote($str)
|
17
|
+
{
|
18
|
+
if(strpos($str, '"') === false)
|
19
|
+
return "\"$str\"";
|
20
|
+
|
21
|
+
if(strpos($str, "'") === false)
|
22
|
+
return "'$str'";
|
23
|
+
|
24
|
+
return false;
|
25
|
+
}
|
26
|
+
|
27
|
+
/**
|
28
|
+
* Prints a list of attributes specified by an array of (att_name => att_value)
|
29
|
+
*
|
30
|
+
* @param array $atts
|
31
|
+
* @param bool $echo [optional] Wheter to echo the result or not (default: true)
|
32
|
+
*
|
33
|
+
* @return string The list of attributes
|
34
|
+
*/
|
35
|
+
function atts($atts, $echo=true)
|
36
|
+
{
|
37
|
+
$str = '';
|
38
|
+
$flatten = array();
|
39
|
+
|
40
|
+
foreach ($atts as $name => $value)
|
41
|
+
{
|
42
|
+
if((string)$name != 'id' && (string)$name != 'class' && is_array($value))
|
43
|
+
{
|
44
|
+
foreach($value as $k => $v)
|
45
|
+
{
|
46
|
+
// TODO: if we found an Id or a Class attribute here. What should we do? For now, it will replace the original ones instead of append
|
47
|
+
$flatten[$k] = $v;
|
48
|
+
}
|
49
|
+
unset($atts[$name]);
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
$atts = array_merge($atts, $flatten);
|
54
|
+
|
55
|
+
foreach ($atts as $name => $value)
|
56
|
+
{
|
57
|
+
if($value === false)
|
58
|
+
continue;
|
59
|
+
|
60
|
+
if($value === true)
|
61
|
+
{
|
62
|
+
$str .= " $name=\"$name\"";
|
63
|
+
}
|
64
|
+
else
|
65
|
+
{
|
66
|
+
if('id' == (string)$name && is_array($value))
|
67
|
+
{
|
68
|
+
$str .= ' id="'.join('_', $value);
|
69
|
+
}
|
70
|
+
elseif ('class' == (string)$name && is_array($value))
|
71
|
+
$str .= ' class="'.join(' ', $value);
|
72
|
+
else
|
73
|
+
$str .= " $name=".quote($value);
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
if($echo)
|
78
|
+
echo $str;
|
79
|
+
|
80
|
+
return $str;
|
81
|
+
}
|
82
|
+
|
83
|
+
/**
|
84
|
+
* Returns an id generated by joining the class of $obj and the id of $obj, joined by a underscore (_), and prefixing it with $prefix.
|
85
|
+
* To get the class, this method will call the class_for() helper.
|
86
|
+
* To get the id, this method first check if the \c $id variable is set, if not, it checks for a \c getId()
|
87
|
+
* method. If none of them is found, it will use an internal, class specific, object counter.
|
88
|
+
*
|
89
|
+
* @param object $obj
|
90
|
+
* @param string $prefix [Optional]
|
91
|
+
*/
|
92
|
+
function id_for($obj, $prefix = '')
|
93
|
+
{
|
94
|
+
static $counter = array();
|
95
|
+
|
96
|
+
if(!empty($prefix))
|
97
|
+
$prefix .= '_';
|
98
|
+
|
99
|
+
$klass = class_for($obj).'_';
|
100
|
+
|
101
|
+
if(isset($obj->id))
|
102
|
+
return $prefix.$klass.$obj->id;
|
103
|
+
|
104
|
+
if(method_exists($obj, 'getId'))
|
105
|
+
return $prefix.$klass.$obj->getId();
|
106
|
+
|
107
|
+
if(!isset($counter[$klass]))
|
108
|
+
$counter[$klass] = 0;
|
109
|
+
|
110
|
+
$counter[$klass]++;
|
111
|
+
|
112
|
+
return $prefix.$klass.$counter[$klass];
|
113
|
+
}
|
114
|
+
|
115
|
+
/**
|
116
|
+
* Returns the class name of an object to be used in the class attribute.
|
117
|
+
* This behaviour can be overloaded by implement a haml_obj_ref (or hamlObjRef) method.
|
118
|
+
* Which MUST return a string. If such method isn't present, it will use php's get_class() function.
|
119
|
+
* If prefix is not empty, both, the object's class and the prefix, will be returned separated by one space.
|
120
|
+
*
|
121
|
+
* @param object $obj
|
122
|
+
* @param string $prefix [Optional]
|
123
|
+
*/
|
124
|
+
function class_for($obj, $prefix = '')
|
125
|
+
{
|
126
|
+
if(!empty($prefix))
|
127
|
+
$prefix .= ' ';
|
128
|
+
|
129
|
+
if(method_exists($obj, 'haml_obj_ref'))
|
130
|
+
return $prefix.$obj->haml_obj_ref();
|
131
|
+
|
132
|
+
if(method_exists($obj, 'hamlObjRef'))
|
133
|
+
return $prefix.$obj->hamlObjRef();
|
134
|
+
|
135
|
+
return $prefix.get_class($obj);
|
136
|
+
}
|
@@ -0,0 +1,71 @@
|
|
1
|
+
<?php
|
2
|
+
|
3
|
+
class Interpolation
|
4
|
+
{
|
5
|
+
const REGEXP = '/(?:\#\{([^\}]+)\})+/';
|
6
|
+
const REPLACEMENT = '<?php echo $1; ?>';
|
7
|
+
|
8
|
+
private $_text = null;
|
9
|
+
|
10
|
+
public function __construct($text)
|
11
|
+
{
|
12
|
+
$this->_text = $text;
|
13
|
+
}
|
14
|
+
|
15
|
+
/**
|
16
|
+
* @todo Refactor!
|
17
|
+
* @throws LogicException
|
18
|
+
*/
|
19
|
+
public function render()
|
20
|
+
{
|
21
|
+
$interpolationStarted = false;
|
22
|
+
$content = "";
|
23
|
+
$interpolationContent = "";
|
24
|
+
$len = strlen($this->_text);
|
25
|
+
$i = 0;
|
26
|
+
|
27
|
+
while ($i < $len) {
|
28
|
+
$currentChar = $this->_text[$i];
|
29
|
+
$nextChar = ($i + 1 <= $len - 1) ? $this->_text[$i + 1] : null;
|
30
|
+
|
31
|
+
if ($interpolationStarted) {
|
32
|
+
if ($currentChar === '}') {
|
33
|
+
$interpolationStarted = false;
|
34
|
+
|
35
|
+
if (empty($interpolationContent)) {
|
36
|
+
throw new LogicException("Empty interpolation: " . $this->_text);
|
37
|
+
}
|
38
|
+
|
39
|
+
$content .= "<?php echo " . $interpolationContent . "; ?>";
|
40
|
+
$interpolationContent = '';
|
41
|
+
$i++;
|
42
|
+
continue;
|
43
|
+
}
|
44
|
+
|
45
|
+
if (null !== $nextChar && '#{' === $currentChar . $nextChar) {
|
46
|
+
throw new LogicException(
|
47
|
+
"Nested interpolation not allowed: " . $this->_text);
|
48
|
+
}
|
49
|
+
|
50
|
+
$interpolationContent .= $currentChar;
|
51
|
+
$i++;
|
52
|
+
continue;
|
53
|
+
}
|
54
|
+
|
55
|
+
if (null !== $nextChar && '#{' === $currentChar . $nextChar) {
|
56
|
+
$interpolationStarted = true;
|
57
|
+
$i += 2;
|
58
|
+
continue;
|
59
|
+
}
|
60
|
+
|
61
|
+
$content .= $currentChar;
|
62
|
+
$i++;
|
63
|
+
}
|
64
|
+
|
65
|
+
if ($interpolationStarted) {
|
66
|
+
throw new LogicException("Unclosed interpolation: " . $this->_text);
|
67
|
+
}
|
68
|
+
|
69
|
+
return $content;
|
70
|
+
}
|
71
|
+
}
|
@@ -0,0 +1,80 @@
|
|
1
|
+
<?php
|
2
|
+
|
3
|
+
require_once 'ElementNode.php';
|
4
|
+
require_once 'HamlNode.php';
|
5
|
+
require_once 'DoctypeNode.php';
|
6
|
+
require_once 'TagNode.php';
|
7
|
+
require_once 'CommentNode.php';
|
8
|
+
require_once 'FilterNode.php';
|
9
|
+
|
10
|
+
class NodeFactory
|
11
|
+
{
|
12
|
+
const ELEMENT = '%';
|
13
|
+
const ID = '#';
|
14
|
+
const KLASS = '.';
|
15
|
+
|
16
|
+
const HTML_COMMENT = '/';
|
17
|
+
const HAML_COMMENT = '-#';
|
18
|
+
const DOCTYPE = '!!!';
|
19
|
+
|
20
|
+
const VARIABLE = '=';
|
21
|
+
const TAG = '-';
|
22
|
+
const FILTER = ':';
|
23
|
+
const LOUD_SCRIPT = '=';
|
24
|
+
|
25
|
+
private $_filterContainer = null;
|
26
|
+
|
27
|
+
public function setFilterContainer(FilterContainer $container)
|
28
|
+
{
|
29
|
+
$this->_filterContainer = $container;
|
30
|
+
}
|
31
|
+
|
32
|
+
protected function getNodeObject($line, Compiler $compiler) {
|
33
|
+
$strippedLine = trim($line);
|
34
|
+
|
35
|
+
if($strippedLine == '')
|
36
|
+
return null;
|
37
|
+
|
38
|
+
if (strpos($strippedLine, self::FILTER, 0) === 0) {
|
39
|
+
return new FilterNode($line, $this->_filterContainer);
|
40
|
+
}
|
41
|
+
|
42
|
+
if (strpos($strippedLine, NodeFactory::DOCTYPE, 0) !== false) {
|
43
|
+
return new DoctypeNode($line);
|
44
|
+
}
|
45
|
+
|
46
|
+
if (substr($strippedLine, 0, 1) === NodeFactory::HTML_COMMENT
|
47
|
+
|| substr($strippedLine, 0, 2) === NodeFactory::HAML_COMMENT) {
|
48
|
+
return new CommentNode($line);
|
49
|
+
}
|
50
|
+
|
51
|
+
$elements = array(
|
52
|
+
NodeFactory::ELEMENT,
|
53
|
+
NodeFactory::ID,
|
54
|
+
NodeFactory::KLASS,
|
55
|
+
);
|
56
|
+
|
57
|
+
if (in_array($strippedLine[0], $elements)) {
|
58
|
+
return new ElementNode($line, $compiler);
|
59
|
+
}
|
60
|
+
|
61
|
+
if ($strippedLine[0] === NodeFactory::TAG
|
62
|
+
||$strippedLine[0] === NodeFactory::LOUD_SCRIPT) {
|
63
|
+
return new TagNode($line);
|
64
|
+
}
|
65
|
+
|
66
|
+
return new HamlNode($line);
|
67
|
+
}
|
68
|
+
|
69
|
+
public function createNode($line, $lineNumber, Compiler $compiler)
|
70
|
+
{
|
71
|
+
$node = $this->getNodeObject($line, $compiler);
|
72
|
+
|
73
|
+
if ($node !== null) {
|
74
|
+
$node->setLineNumber($lineNumber);
|
75
|
+
$node->setCompiler($compiler);
|
76
|
+
}
|
77
|
+
|
78
|
+
return $node;
|
79
|
+
}
|
80
|
+
}
|