wproot 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ ?>