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.
Files changed (44) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +4 -0
  3. data/Rakefile +2 -0
  4. data/bin/wproot +7 -0
  5. data/lib/wproot.rb +11 -0
  6. data/lib/wproot/cli.rb +35 -0
  7. data/lib/wproot/compass.rb +15 -0
  8. data/lib/wproot/haml.rb +15 -0
  9. data/lib/wproot/version.rb +3 -0
  10. data/spec/spec_helper.rb +7 -0
  11. data/spec/wproot_spec.rb +59 -0
  12. data/vendor/HamlPHP.php +7 -0
  13. data/vendor/HamlPHP/.gitignore +6 -0
  14. data/vendor/HamlPHP/MIT-LICENSE +22 -0
  15. data/vendor/HamlPHP/README.mkd +39 -0
  16. data/vendor/HamlPHP/src/HamlPHP/CommentNode.php +92 -0
  17. data/vendor/HamlPHP/src/HamlPHP/Compiler.php +109 -0
  18. data/vendor/HamlPHP/src/HamlPHP/ContentEvaluator/ContentEvaluator.php +16 -0
  19. data/vendor/HamlPHP/src/HamlPHP/ContentEvaluator/DefaultContentEvaluator.php +22 -0
  20. data/vendor/HamlPHP/src/HamlPHP/DoctypeNode.php +47 -0
  21. data/vendor/HamlPHP/src/HamlPHP/Element.php +618 -0
  22. data/vendor/HamlPHP/src/HamlPHP/ElementNode.php +222 -0
  23. data/vendor/HamlPHP/src/HamlPHP/Filter/CssFilter.php +31 -0
  24. data/vendor/HamlPHP/src/HamlPHP/Filter/Filter.php +18 -0
  25. data/vendor/HamlPHP/src/HamlPHP/Filter/FilterContainer.php +34 -0
  26. data/vendor/HamlPHP/src/HamlPHP/Filter/JavascriptFilter.php +29 -0
  27. data/vendor/HamlPHP/src/HamlPHP/Filter/PhpFilter.php +24 -0
  28. data/vendor/HamlPHP/src/HamlPHP/Filter/PlainFilter.php +46 -0
  29. data/vendor/HamlPHP/src/HamlPHP/FilterNode.php +29 -0
  30. data/vendor/HamlPHP/src/HamlPHP/HamlNode.php +75 -0
  31. data/vendor/HamlPHP/src/HamlPHP/HamlPHP.php +191 -0
  32. data/vendor/HamlPHP/src/HamlPHP/Helpers.php +136 -0
  33. data/vendor/HamlPHP/src/HamlPHP/Interpolation.php +71 -0
  34. data/vendor/HamlPHP/src/HamlPHP/NodeFactory.php +80 -0
  35. data/vendor/HamlPHP/src/HamlPHP/RootNode.php +133 -0
  36. data/vendor/HamlPHP/src/HamlPHP/Storage/DontEvaluateStorage.php +68 -0
  37. data/vendor/HamlPHP/src/HamlPHP/Storage/FileStorage.php +74 -0
  38. data/vendor/HamlPHP/src/HamlPHP/Storage/Storage.php +24 -0
  39. data/vendor/HamlPHP/src/HamlPHP/TagNode.php +125 -0
  40. data/vendor/HamlPHP/src/HamlPHP/Util/BaseException.php +340 -0
  41. data/vendor/HamlPHP/src/HamlPHP/Util/BaseObject.php +94 -0
  42. data/vendor/HamlPHP/src/HamlPHP/Util/StringScanner.php +989 -0
  43. data/wproot.gemspec +21 -0
  44. metadata +126 -0
@@ -0,0 +1,16 @@
1
+ <?php
2
+
3
+ require_once dirname(__FILE__) . '/../Helpers.php';
4
+
5
+ interface ContentEvaluator
6
+ {
7
+ /**
8
+ * Evaluates a string. Content contains HTML and PHP code.
9
+ *
10
+ * @param $content A string
11
+ * @param $contentVariables an array of variables
12
+ * @param $id An identifier of the content. Could be a filename.
13
+ * @return string
14
+ */
15
+ public function evaluate($content, array $contentVariables = array(), $id = null);
16
+ }
@@ -0,0 +1,22 @@
1
+ <?php
2
+
3
+ require_once 'ContentEvaluator.php';
4
+
5
+ class DefaultContentEvaluator implements ContentEvaluator
6
+ {
7
+ public function evaluate($content, array $contentVariables = array(), $id = null)
8
+ {
9
+ $tempFileName = tempnam("/tmp", "foo");
10
+ $fp = fopen($tempFileName, "w");
11
+ fwrite($fp, $content);
12
+
13
+ ob_start();
14
+ extract($contentVariables);
15
+ require $tempFileName;
16
+ $result = ob_get_clean();
17
+
18
+ fclose($fp);
19
+ unlink($tempFileName);
20
+ return $result;
21
+ }
22
+ }
@@ -0,0 +1,47 @@
1
+ <?php
2
+
3
+ require_once 'Interpolation.php';
4
+
5
+ class DoctypeNode extends HamlNode
6
+ {
7
+ const XHTML10_T = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
8
+ const XHTML10_S = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
9
+ const XHTML10_F = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">';
10
+ const HTML5 = '<!DOCTYPE html>';
11
+
12
+ private $_type;
13
+
14
+ public function __construct($line)
15
+ {
16
+ parent::__construct($line);
17
+ $parts = explode(' ', trim($line));
18
+ $this->_type = isset($parts[1]) ? $parts[1] : '!!!';
19
+ }
20
+
21
+ public function render()
22
+ {
23
+ $interpolation = new Interpolation($this->renderDoctype() . "\n");
24
+ return $interpolation->render();
25
+ }
26
+
27
+ private function renderDoctype()
28
+ {
29
+ if ($this->_type === '!!!') {
30
+ return DoctypeNode::XHTML10_T;
31
+ }
32
+
33
+ if ($this->_type === 'Strict') {
34
+ return DoctypeNode::XHTML10_S;
35
+ }
36
+
37
+ if ($this->_type === 'Frameset') {
38
+ return DoctypeNode::XHTML10_F;
39
+ }
40
+
41
+ if ($this->_type === '5') {
42
+ return DoctypeNode::HTML5;
43
+ }
44
+
45
+ return '';
46
+ }
47
+ }
@@ -0,0 +1,618 @@
1
+ <?php
2
+
3
+ require_once 'HamlPHP.php';
4
+ require_once 'Util/StringScanner.php';
5
+
6
+ class SyntaxErrorException extends Exception
7
+ {}
8
+
9
+ class Element
10
+ {
11
+ //const HAML_REGEXP = '/^(?P<tag>%\w+)?(?P<id>#\w*)?(?P<classes>\.[\w\.\-]*)*(?P<attributes>\((?P<html_attrs>.+)\)|\{(?P<hash_attrs>.*)\})?(?P<php>=)?(?P<inline>[^\w\.#\{].*)?$/';
12
+
13
+
14
+ const ELEMENT = '%';
15
+ const ID = '#';
16
+ const KLASS = '.';
17
+
18
+ private $_haml = null;
19
+ private $_tag = null;
20
+ private $_id = null;
21
+ private $_classes = null;
22
+ private $_inlineContent = null;
23
+ private $_php = false;
24
+ private $_attributes = null;
25
+ private $_scanner;
26
+ private $_nukeOuterWhitespace;
27
+ private $_nukeInnerWhitespace;
28
+
29
+ private $_selfClosing = false;
30
+ private $_preserveWhitespace = false;
31
+ private $_useAttsHelper;
32
+
33
+ /**
34
+ * @var Compiler
35
+ */
36
+ private $_compiler;
37
+
38
+ public function __construct($line, Compiler $compiler)
39
+ {
40
+ $this->_haml = $line;
41
+ $this->_scanner = new StringScanner($this->_haml);
42
+ $this->_compiler = $compiler;
43
+ $this->parseHaml();
44
+ $this->_compiler = null;
45
+ }
46
+
47
+ private function parseHaml()
48
+ {
49
+ $scanner = $this->_scanner;
50
+
51
+ if (! $scanner->check('/(?:%(?P<tag>[\\-:\\w]+))?(?P<attrs>[\\#\\.\\-:\\w]*)?(?P<rest>.*)/'))
52
+ throw new SyntaxErrorException("Invalid tag: \"${$this->haml}\".");
53
+
54
+ if (preg_match('/[\.#](\.|#|\z)/', $scanner['attrs']))
55
+ throw new SyntaxErrorException("Illegal element: classes and ids must have values.");
56
+
57
+ if (!empty($scanner['tag']))
58
+ $this->_tag = $scanner['tag'];
59
+ else
60
+ $this->_tag = 'div';
61
+
62
+ $classAndIdAtts = $this->_parseClassAndId($scanner['attrs']);
63
+
64
+ $scanner->string = $scanner['rest'];
65
+
66
+ $hashAtts = $htmlAtts = $objRef = false;
67
+ $merge_order = array(
68
+ $classAndIdAtts
69
+ );
70
+
71
+ while ($scanner->rest)
72
+ {
73
+ switch ($scanner->rest[0])
74
+ {
75
+ case '{':
76
+ if ($hashAtts)
77
+ break;
78
+ $hashAtts = $this->_parseHashAttrs($scanner);
79
+ $merge_order[] = $hashAtts;
80
+ break;
81
+ case '(':
82
+ if ($htmlAtts)
83
+ break;
84
+ $htmlAtts = $this->_parseHtmlAttrs($scanner);
85
+ $merge_order[] = $htmlAtts;
86
+ break;
87
+ case '[':
88
+ if ($objRef)
89
+ break;
90
+ $objRef = $this->_parseObjRef($scanner);
91
+ $merge_order[] = $objRef;
92
+ break;
93
+ default:
94
+ break 2;
95
+ }
96
+ }
97
+
98
+ $this->_attributes = $this->_mergeAttributes($merge_order);
99
+
100
+ if (! $this->_attributes)
101
+ $this->_attributes = array();
102
+
103
+ $this->_useAttsHelper = $this->_containsPhpAttribute($this->_attributes);
104
+
105
+ if ($scanner->rest)
106
+ {
107
+ $scanner->scan('/(<>|><|[><])?([=\/\~&!])?(.*)?/');
108
+ $nuke_whitespace = trim($scanner[1]);
109
+ $action = $scanner[2];
110
+ $value = $scanner[3];
111
+
112
+ $this->_nukeOuterWhitespace = (mb_strpos($nuke_whitespace, '>') !== false);
113
+ $this->_nukeInnerWhitespace = (mb_strpos($nuke_whitespace, '<') !== false);
114
+
115
+ $escape_html = ($action == '&' || ($action != '!' && HamlPHP::$Config['escape_html']));
116
+
117
+ switch ($action)
118
+ {
119
+ case '/':
120
+ $this->_selfClosing = true;
121
+ $value = trim($value);
122
+ if(!empty($value))
123
+ throw new SyntaxErrorException("Self closing tags can't have content.");
124
+ break;
125
+
126
+ case '~': // whitespace preservation
127
+ throw new Exception("Whitespace preservation (~) is not implemented yet.");
128
+ $parse = $this->_preserveWhitespace = true;
129
+ break;
130
+
131
+ case '=': //
132
+ $this->_php = true;
133
+ $this->_inlineContent = $this->_interpolate(mb_substr($value, 1));
134
+ break;
135
+
136
+ case '&': // escape html
137
+ case '!': // unescape html
138
+ throw new Exception("Escape (&) and unescape (!) html features are not implemented yet.");
139
+ if ($value[0] == '=' || $value[0] == '~')
140
+ {
141
+ $parse = true;
142
+ $this->_preserveWhitespace = ($value[0] == '~');
143
+ if ($value[1] == '=')
144
+ {
145
+ $value = $this->_interpolate(mb_substr($value, 2, - 1), $escape_html);
146
+ $escape_html = false;
147
+ }
148
+ else
149
+ $value = mb_substr($value, 1, - 1);
150
+ }
151
+ else
152
+ $this->_interpolate($value, $escape_html);
153
+
154
+ break;
155
+
156
+ default:
157
+ $value = trim($value);
158
+ if(!empty($value))
159
+ $this->_inlineContent = $this->_interpolate($value, $escape_html);
160
+ }
161
+
162
+ }
163
+
164
+ /*
165
+ raise SyntaxError.new("Illegal nesting: nesting within a self-closing tag is illegal.", @next_line.index) if block_opened? && self_closing
166
+ raise SyntaxError.new("There's no Ruby code for #{action} to evaluate.", last_line - 1) if parse && value.empty?
167
+ raise SyntaxError.new("Self-closing tags can't have content.", last_line - 1) if self_closing && !value.empty?
168
+
169
+ if block_opened? && !value.empty? && !is_ruby_multiline?(value)
170
+ raise SyntaxError.new("Illegal nesting: content can't be both given on the same line as %#{tag_name} and nested within it.", @next_line.index)
171
+ end
172
+
173
+ self_closing ||= !!(!block_opened? && value.empty? && @options[:autoclose].any? {|t| t === tag_name})
174
+ value = nil if value.empty? && (block_opened? || self_closing)
175
+ value = handle_ruby_multiline(value) if parse
176
+ */
177
+ }
178
+
179
+ private function _containsPhpAttribute(array $att_arr)
180
+ {
181
+ foreach ($att_arr as $att)
182
+ {
183
+ if (isset($att['t']) && ($att['t'] == 'php' || $att['t'] == 'function'))
184
+ return true;
185
+ }
186
+
187
+ return false;
188
+ }
189
+
190
+ private function _mergeAttributes($att_arrays)
191
+ {
192
+ $merged = array();
193
+
194
+ $count = count($att_arrays);
195
+
196
+ if ($count == 1)
197
+ return $att_arrays[0];
198
+
199
+ for ($i = 0; $i < $count; $i ++)
200
+ {
201
+ foreach ($att_arrays[$i] as $k => $v)
202
+ {
203
+ if(is_array($v))
204
+ $att = $v;
205
+ else
206
+ $att = array($v);
207
+
208
+ for ($j = $i + 1; $j < $count; $j ++)
209
+ {
210
+ if (isset($att_arrays[$j][$k]))
211
+ {
212
+ if(is_array($att_arrays[$j][$k]) && is_array($v))
213
+ $att = array_merge($att, $att_arrays[$j][$k]);
214
+ else
215
+ $att[] = $att_arrays[$j][$k];
216
+
217
+ unset($att_arrays[$j][$k]);
218
+ }
219
+ }
220
+
221
+ if (count($att) == 1 && !is_array($v))
222
+ $merged[$k] = $v;
223
+ else
224
+ $merged[$k] = $att;
225
+ }
226
+ }
227
+
228
+ return $merged;
229
+ }
230
+
231
+ private function _parseObjRef($scanner)
232
+ {
233
+ $scanner->scan('/\\[*\s*/');
234
+
235
+ $obj = $scanner->scan('/[^,\\]]+/');
236
+ $scanner->scan('/\s*,\s*/');
237
+ $prefix = $scanner->scan('/[^\\]]*/');
238
+ if (! $prefix)
239
+ $prefix = '';
240
+ $end = trim($scanner->scan('/\s*\\]/'));
241
+
242
+ if ($end != ']')
243
+ throw new SyntaxErrorException("Invalid object reference.");
244
+
245
+ return array(
246
+ 'id' => array(array(
247
+ 't' => 'php' , 'v' => "id_for($obj, '$prefix')"
248
+ )),
249
+ 'class' => array(array(
250
+ 't' => 'php' , 'v' => "class_for($obj, '$prefix')"
251
+ ))
252
+ );
253
+ }
254
+
255
+ private function _parseClassAndId($list)
256
+ {
257
+ $list = new StringScanner($list);
258
+ $attributes = array();
259
+
260
+ while ($list->scan('/([#.])([-:_a-zA-Z0-9]+)/'))
261
+ {
262
+ $type = $list[1];
263
+ $prop = $list[2];
264
+
265
+ switch ($type)
266
+ {
267
+ case '.':
268
+ $attributes['class'][] = array('t' => 'str', 'v' => $prop);
269
+ break;
270
+ case '#':
271
+ $attributes['id'][] = array('t' => 'str', 'v' => $prop);
272
+ break;
273
+ }
274
+ }
275
+
276
+ return $attributes;
277
+ }
278
+
279
+ private function _parseHtmlAttrs(StringScanner $scanner)
280
+ {
281
+ $atts = array(
282
+ 'class' => array(),
283
+ 'id' => array()
284
+ );
285
+
286
+ $scanner->scan('/\(\s*/');
287
+ while (! $scanner->scan('/\\s*\\)/'))
288
+ {
289
+ $scanner->scan('/\s*/');
290
+
291
+ if (! $name = $scanner->scan('/[-:\w]+/'))
292
+ throw new SyntaxErrorException("Invalid attribute list: {$scanner->string}");
293
+
294
+ $scanner->scan('/\s*/');
295
+
296
+ // If a equal sign doesn't follow, the value is true
297
+ if (! $scanner->scan('/=/'))
298
+ $atts[$name] = array(
299
+ 't' => 'static' , 'v' => true
300
+ );
301
+ else
302
+ {
303
+ $scanner->scan('/\s*/');
304
+
305
+ // if we don't find a quote, it's a php value
306
+ if (! ($quote = $scanner->scan('/["\\\']/')))
307
+ {
308
+ if (! $var = $scanner->scan('/\$\w+/')) // in this mode only variables are accepted
309
+ throw new SyntaxErrorException("Invalid attribute list: {$scanner->string}");
310
+
311
+ if($name == 'class' || $name == 'id')
312
+ $atts[$name][] = array(
313
+ 't' => 'php' , 'v' => $var
314
+ );
315
+ else
316
+ $atts[$name] = array(
317
+ 't' => 'php' , 'v' => $var
318
+ );
319
+ }
320
+ elseif ($scanner->scan('/true|false/i'))
321
+ {
322
+ if ($scanner[0] == 'true')
323
+ $atts[$name] = array(
324
+ 't' => 'static' , 'v' => true
325
+ );
326
+ else
327
+ $atts[$name] = array(
328
+ 't' => 'static' , 'v' => false
329
+ );
330
+ }
331
+ else
332
+ {
333
+ // we've found a quote, let's scan until the ending quote
334
+ $scanner->scan("/([^\\\\]*?)$quote/");
335
+ $content = $scanner[1];
336
+
337
+ if($name == 'class' || $name == 'id')
338
+ $atts[$name][] = array(
339
+ 't' => 'str' , 'v' => $content
340
+ );
341
+ else
342
+ $atts[$name] = array(
343
+ 't' => 'str' , 'v' => $quote . $content . $quote
344
+ );
345
+ }
346
+ }
347
+
348
+ $scanner->scan('/\s*/');
349
+ if ($scanner->eos)
350
+ {
351
+ $next_line = ' ' . trim($this->_compiler->getNextLine());
352
+ $scanner->concat($next_line);
353
+ }
354
+ }
355
+
356
+ if(count($atts['id']) == 0)
357
+ unset($atts['id']);
358
+
359
+ if(count($atts['class']) == 0)
360
+ unset($atts['class']);
361
+
362
+ return $atts;
363
+ }
364
+
365
+ /**
366
+ * @param StringScanner $scanner
367
+ * @return array an array with the parsed elements
368
+ */
369
+ private function _parseHashAttrs(StringScanner $scanner)
370
+ {
371
+ $atts = array(
372
+ 'class' => array(),
373
+ 'id' => array()
374
+ );
375
+ $litRe = '/(["\\\']).*?\\1(?=[\\s|=])|:?[\\-\\w:]*/';
376
+
377
+ $scanner->scan('/\\s*\\{?\\s*/');
378
+
379
+ while (! $scanner->scan('/}/'))
380
+ {
381
+ $scanner->scan('/\\s*/');
382
+
383
+ $name = trim($scanner->scan($litRe), ':"\'');
384
+ if (! $name)
385
+ throw new SyntaxErrorException("Invalid attribute list. Expecting an attribute name");
386
+
387
+ if (! $scanner->scan('/\s*=>\s*/'))
388
+ {
389
+ // it's an attribute function
390
+ if(!($scanner->rest[0] == '('))
391
+ throw new SyntaxErrorException("Invalid attribute list. Either missing attribute function parameters or attribute value");
392
+
393
+ list ($balanced, $value, $rest, $count) = $this->balance($scanner, '(', ')', 0);
394
+
395
+ if(!$balanced)
396
+ throw new SyntaxErrorException("Unbalanced brackets in attribute function");
397
+
398
+ $value = $name.$value;
399
+ $name = 'fn_'.count($atts);
400
+ $atts[$name] = array(
401
+ 't' => 'function' , 'v' => $value
402
+ );
403
+ $scanner->scan('/\\s*,\\s*/');
404
+ continue;
405
+ }
406
+
407
+ switch ($scanner->rest[0])
408
+ {
409
+ case '"':
410
+ case "'":
411
+ $quote = $scanner->scan('/["\']/');
412
+ $value = $scanner->scan("/(.*?[^\\\\])$quote/");
413
+
414
+ if($name == 'class' || $name == 'id')
415
+ $atts[$name][] = array(
416
+ 't' => 'str' , 'v' => $scanner[1]
417
+ );
418
+ else
419
+ {
420
+ $value = $this->_interpolate($quote . $value);
421
+ $atts[$name] = array(
422
+ 't' => 'str' , 'v' => $value
423
+ );
424
+ }
425
+ break;
426
+
427
+ case '[':
428
+ $value = $scanner->scanUntil('/\]/');
429
+ $items = mb_substr($value, 1, - 1);
430
+
431
+ if($name == 'class' || $name == 'id')
432
+ $atts[$name][] = array(
433
+ 't' => 'php' , 'v' => "array($items)"
434
+ );
435
+ else
436
+ $atts[$name] = array(
437
+ 't' => 'php' , 'v' => "array($items)"
438
+ );
439
+ break;
440
+
441
+ case '{':
442
+ list ($balanced, $value, $rest, $count) = $this->balance($scanner, '{', '}', 0);
443
+ $value = mb_substr($value, 1, - 1);
444
+
445
+ if($name == 'class' || $name == 'id')
446
+ $atts[$name][] = array(
447
+ 't' => 'php' , 'v' => $value
448
+ );
449
+ else
450
+ $atts[$name] = array(
451
+ 't' => 'php' , 'v' => $value
452
+ );
453
+ break;
454
+
455
+ default:
456
+ if ($scanner->scan('/true|false/i'))
457
+ {
458
+ if ($scanner[0] == 'true')
459
+ $atts[$name] = array(
460
+ 't' => 'static' , 'v' => true
461
+ );
462
+ else
463
+ $atts[$name] = array(
464
+ 't' => 'static' , 'v' => false
465
+ );
466
+ }
467
+ else
468
+ {
469
+ $value = trim($scanner->scanUntil('/.(?=,)|.(?=\\})/'));
470
+
471
+ if($name == 'class' || $name == 'id')
472
+ $atts[$name][] = array(
473
+ 't' => 'php' , 'v' => $value
474
+ );
475
+ else
476
+ $atts[$name] = array(
477
+ 't' => 'php' , 'v' => $value
478
+ );
479
+ }
480
+ }
481
+
482
+ $scanner->scan('/\s*(,)\s*/');
483
+ if ($scanner->eos)
484
+ {
485
+ $next_line = ' ' . trim($this->_compiler->getNextLine());
486
+ $scanner->concat($next_line);
487
+ }
488
+ }
489
+
490
+ if(count($atts['id']) == 0)
491
+ unset($atts['id']);
492
+
493
+ if(count($atts['class']) == 0)
494
+ unset($atts['class']);
495
+
496
+ return $atts;
497
+ }
498
+
499
+ /**
500
+ * Checks if the string has a balanced amount of $start_char and $finish_char pairs
501
+ * If you pass a scanner, the pointer of the scanner will be altered!
502
+ *
503
+ * @param $scanner_or_line The line or a scanner to balance
504
+ * @param $start_char The balancing start char
505
+ * @param $finish_char The balancing end char
506
+ * @param $count [Optional] The current balance count
507
+ * @return array [$balanced, $balanced_str, $rest, $count]
508
+ */
509
+ private function balance($scanner_or_line, $start_char, $finish_char, $count = 0)
510
+ {
511
+ $str = '';
512
+ $regexp = "/(.*?)[\\$start_char\\$finish_char]/";
513
+
514
+ if (! ($scanner_or_line instanceof StringScanner))
515
+ $scanner = new StringScanner($scanner_or_line);
516
+ else
517
+ $scanner = $scanner_or_line;
518
+
519
+ while ($scanner->scan($regexp))
520
+ {
521
+ $str .= $scanner->matched;
522
+ if (mb_substr($scanner->matched, - 1, 1) == $start_char)
523
+ $count ++;
524
+ if (mb_substr($scanner->matched, - 1, 1) == $finish_char)
525
+ $count --;
526
+
527
+ if ($count == 0)
528
+ return array(
529
+ true , trim($str) , $scanner->rest , $count
530
+ );
531
+ }
532
+
533
+ return array(
534
+ false , trim($str) , $scanner->rest , $count
535
+ );
536
+ }
537
+
538
+ private function _interpolate($str)
539
+ {
540
+ if (! preg_match('/(?<!\\\\)\\#\\{/', $str))
541
+ return $str;
542
+
543
+ if ($str[0] != '"' && $str[0] != "'")
544
+ {
545
+ $int = new Interpolation($str);
546
+ return $int->render();
547
+ }
548
+
549
+ $nStr = '';
550
+ $s = new StringScanner($str);
551
+
552
+ $quote = $s->scan('/["\']/');
553
+
554
+ while (! $s->eos)
555
+ {
556
+ $part = $s->scan('/([^\\\\]*)\\#\\{/');
557
+
558
+ if (! $part)
559
+ break;
560
+
561
+ $nStr = $s[1] . $quote . '.(';
562
+
563
+ $part = $s->scan('/([^\\\\]*)\\}/');
564
+
565
+ if (! $part)
566
+ throw new SyntaxErrorException("Unclosed interpolation");
567
+
568
+ $nStr .= $s[1] . ').' . $quote;
569
+ }
570
+
571
+ if ($s->rest == $quote)
572
+ return $quote . trim($nStr, ". {$quote}");
573
+
574
+ return $quote . $nStr . $s->rest;
575
+ }
576
+
577
+ public function getTag()
578
+ {
579
+ return $this->_tag;
580
+ }
581
+
582
+ public function getId()
583
+ {
584
+ if(isset($this->_attributes['id']))
585
+ return $this->_attributes['id'];
586
+
587
+ return null;
588
+ }
589
+
590
+ public function isPhpVariable()
591
+ {
592
+ return $this->_php;
593
+ }
594
+
595
+ public function getClasses()
596
+ {
597
+ if(isset($this->_attributes['class']))
598
+ return $this->_attributes['class'];
599
+
600
+ }
601
+
602
+ public function getAttributes()
603
+ {
604
+ return $this->_attributes;
605
+ }
606
+
607
+ public function getInlineContent()
608
+ {
609
+ return $this->_inlineContent;
610
+ }
611
+
612
+ public function useAttsHelper()
613
+ {
614
+ return $this->_useAttsHelper;
615
+ }
616
+ }
617
+
618
+ ?>