frontsau 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (280) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +21 -0
  5. data/README.md +30 -0
  6. data/Rakefile +2 -0
  7. data/bin/frontsau +15 -0
  8. data/bin/frontsau-phaml-compiler +35 -0
  9. data/example/.frontsau +12 -0
  10. data/example/assets/head.jpg +0 -0
  11. data/example/assets/script.js +4 -0
  12. data/example/assets/style.css +6 -0
  13. data/example/css/includes.sass +2 -0
  14. data/example/css/style.sass +6 -0
  15. data/example/image/head.jpg +0 -0
  16. data/example/index.html +0 -0
  17. data/example/js/script.coffee +1 -0
  18. data/frontsau.gemspec +41 -0
  19. data/lib/Phamlp/Phamlp.php +72 -0
  20. data/lib/Phamlp/PhamlpException.php +31 -0
  21. data/lib/Phamlp/haml/HamlException.php +29 -0
  22. data/lib/Phamlp/haml/HamlHelpers.php +199 -0
  23. data/lib/Phamlp/haml/HamlParser.php +1250 -0
  24. data/lib/Phamlp/haml/filters/HamlBaseFilter.php +30 -0
  25. data/lib/Phamlp/haml/filters/HamlCdataFilter.php +29 -0
  26. data/lib/Phamlp/haml/filters/HamlCssFilter.php +30 -0
  27. data/lib/Phamlp/haml/filters/HamlEscapedFilter.php +32 -0
  28. data/lib/Phamlp/haml/filters/HamlJavascriptFilter.php +31 -0
  29. data/lib/Phamlp/haml/filters/HamlPhpFilter.php +27 -0
  30. data/lib/Phamlp/haml/filters/HamlPlainFilter.php +28 -0
  31. data/lib/Phamlp/haml/filters/HamlPreserveFilter.php +29 -0
  32. data/lib/Phamlp/haml/filters/HamlSassFilter.php +37 -0
  33. data/lib/Phamlp/haml/filters/HamlScssFilter.php +37 -0
  34. data/lib/Phamlp/haml/filters/_HamlMarkdownFilter.php +50 -0
  35. data/lib/Phamlp/haml/filters/_HamlTextileFilter.php +50 -0
  36. data/lib/Phamlp/haml/messages/_i18n.php +32 -0
  37. data/lib/Phamlp/haml/messages/de.php +32 -0
  38. data/lib/Phamlp/haml/messages/fr.php +32 -0
  39. data/lib/Phamlp/haml/renderers/HamlCompactRenderer.php +32 -0
  40. data/lib/Phamlp/haml/renderers/HamlCompressedRenderer.php +48 -0
  41. data/lib/Phamlp/haml/renderers/HamlExpandedRenderer.php +58 -0
  42. data/lib/Phamlp/haml/renderers/HamlNestedRenderer.php +77 -0
  43. data/lib/Phamlp/haml/renderers/HamlRenderer.php +137 -0
  44. data/lib/Phamlp/haml/tree/HamlCodeBlockNode.php +58 -0
  45. data/lib/Phamlp/haml/tree/HamlCommentNode.php +41 -0
  46. data/lib/Phamlp/haml/tree/HamlDoctypeNode.php +27 -0
  47. data/lib/Phamlp/haml/tree/HamlElementNode.php +52 -0
  48. data/lib/Phamlp/haml/tree/HamlFilterNode.php +50 -0
  49. data/lib/Phamlp/haml/tree/HamlHelperNode.php +73 -0
  50. data/lib/Phamlp/haml/tree/HamlNode.php +253 -0
  51. data/lib/Phamlp/haml/tree/HamlNodeExceptions.php +19 -0
  52. data/lib/Phamlp/haml/tree/HamlRootNode.php +58 -0
  53. data/lib/Phamlp/sass/SassException.php +29 -0
  54. data/lib/Phamlp/sass/SassFile.php +164 -0
  55. data/lib/Phamlp/sass/SassParser.php +848 -0
  56. data/lib/Phamlp/sass/extensions/compass/config.php +65 -0
  57. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/stylesheets/_blueprint.scss +47 -0
  58. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/stylesheets/blueprint/_buttons.scss +101 -0
  59. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/stylesheets/blueprint/_colors.scss +32 -0
  60. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/stylesheets/blueprint/_debug.scss +11 -0
  61. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/stylesheets/blueprint/_fancy-type.scss +86 -0
  62. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/stylesheets/blueprint/_form.scss +68 -0
  63. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/stylesheets/blueprint/_grid.scss +249 -0
  64. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/stylesheets/blueprint/_ie.scss +109 -0
  65. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/stylesheets/blueprint/_interaction.scss +57 -0
  66. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/stylesheets/blueprint/_link-icons.scss +37 -0
  67. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/stylesheets/blueprint/_liquid.scss +147 -0
  68. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/stylesheets/blueprint/_print.scss +93 -0
  69. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/stylesheets/blueprint/_reset.scss +3 -0
  70. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/stylesheets/blueprint/_rtl.scss +133 -0
  71. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/stylesheets/blueprint/_scaffolding.scss +54 -0
  72. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/stylesheets/blueprint/_typography.scss +104 -0
  73. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/stylesheets/blueprint/_utilities.scss +37 -0
  74. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/stylesheets/blueprint/reset/_utilities.scss +58 -0
  75. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/basic/grid.png +0 -0
  76. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/basic/ie.sass +4 -0
  77. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/basic/manifest.rb +30 -0
  78. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/basic/partials/_base.sass +10 -0
  79. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/basic/print.sass +4 -0
  80. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/basic/screen.sass +12 -0
  81. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/buttons/buttons/cross.png +0 -0
  82. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/buttons/buttons/key.png +0 -0
  83. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/buttons/buttons/tick.png +0 -0
  84. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/buttons/buttons.sass +49 -0
  85. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/buttons/manifest.rb +17 -0
  86. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/link_icons/link_icons/doc.png +0 -0
  87. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/link_icons/link_icons/email.png +0 -0
  88. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/link_icons/link_icons/external.png +0 -0
  89. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/link_icons/link_icons/feed.png +0 -0
  90. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/link_icons/link_icons/im.png +0 -0
  91. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/link_icons/link_icons/pdf.png +0 -0
  92. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/link_icons/link_icons/visited.png +0 -0
  93. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/link_icons/link_icons/xls.png +0 -0
  94. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/link_icons/link_icons.sass +13 -0
  95. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/link_icons/manifest.rb +23 -0
  96. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/project/grid.png +0 -0
  97. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/project/ie.sass +16 -0
  98. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/project/manifest.rb +30 -0
  99. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/project/partials/_base.sass +11 -0
  100. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/project/print.sass +8 -0
  101. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/project/screen.sass +45 -0
  102. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/semantic/grid.png +0 -0
  103. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/semantic/ie.sass +16 -0
  104. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/semantic/manifest.rb +33 -0
  105. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/semantic/partials/_base.sass +10 -0
  106. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/semantic/partials/_form.sass +6 -0
  107. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/semantic/partials/_page.sass +18 -0
  108. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/semantic/partials/_two_col.sass +38 -0
  109. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/semantic/print.sass +5 -0
  110. data/lib/Phamlp/sass/extensions/compass/frameworks/blueprint/templates/semantic/screen.sass +14 -0
  111. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/_compass.scss +2 -0
  112. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/_css3.scss +15 -0
  113. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/_layout.scss +1 -0
  114. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/_reset.scss +3 -0
  115. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/_utilities.scss +6 -0
  116. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/css3/_background-clip.scss +43 -0
  117. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/css3/_background-origin.scss +42 -0
  118. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/css3/_background-size.scss +14 -0
  119. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/css3/_border-radius.scss +135 -0
  120. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/css3/_box-shadow.scss +50 -0
  121. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/css3/_box-sizing.scss +13 -0
  122. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/css3/_box.scss +112 -0
  123. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/css3/_columns.scss +55 -0
  124. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/css3/_font-face.scss +33 -0
  125. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/css3/_gradient.scss +82 -0
  126. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/css3/_inline-block.scss +12 -0
  127. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/css3/_opacity.scss +27 -0
  128. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/css3/_shared.scss +47 -0
  129. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/css3/_text-shadow.scss +25 -0
  130. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/css3/_transform.scss +85 -0
  131. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/css3/_transition.scss +85 -0
  132. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/layout/_sticky-footer.scss +23 -0
  133. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/reset/_utilities.scss +133 -0
  134. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/_general.scss +6 -0
  135. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/_links.scss +3 -0
  136. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/_lists.scss +4 -0
  137. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/_print.scss +17 -0
  138. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/_sprites.scss +1 -0
  139. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/_tables.scss +3 -0
  140. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/_text.scss +3 -0
  141. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/general/_clearfix.scss +31 -0
  142. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/general/_float.scss +15 -0
  143. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/general/_hacks.scss +35 -0
  144. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/general/_min.scss +16 -0
  145. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/general/_reset.scss +2 -0
  146. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/general/_tabs.scss +1 -0
  147. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/general/_tag-cloud.scss +18 -0
  148. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/links/_hover-link.scss +5 -0
  149. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/links/_link-colors.scss +28 -0
  150. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/links/_unstyled-link.scss +7 -0
  151. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/lists/_bullets.scss +34 -0
  152. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/lists/_horizontal-list.scss +52 -0
  153. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/lists/_inline-block-list.scss +47 -0
  154. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/lists/_inline-list.scss +29 -0
  155. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/sprites/_sprite-img.scss +56 -0
  156. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/tables/_alternating-rows-and-columns.scss +20 -0
  157. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/tables/_borders.scss +27 -0
  158. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/tables/_scaffolding.scss +9 -0
  159. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/text/_ellipsis.scss +25 -0
  160. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/text/_nowrap.scss +2 -0
  161. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/stylesheets/compass/utilities/text/_replacement.scss +34 -0
  162. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/templates/ellipsis/ellipsis.sass +9 -0
  163. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/templates/ellipsis/manifest.rb +27 -0
  164. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/templates/ellipsis/xml/ellipsis.xml +14 -0
  165. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/templates/extension/manifest.rb +20 -0
  166. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/templates/extension/stylesheets/main.sass +1 -0
  167. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/templates/extension/templates/project/manifest.rb +2 -0
  168. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/templates/extension/templates/project/screen.sass +2 -0
  169. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/templates/project/USAGE.markdown +32 -0
  170. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/templates/project/ie.sass +6 -0
  171. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/templates/project/manifest.rb +4 -0
  172. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/templates/project/print.sass +6 -0
  173. data/lib/Phamlp/sass/extensions/compass/frameworks/compass/templates/project/screen.sass +7 -0
  174. data/lib/Phamlp/sass/extensions/compass/functions/colourStops.php +268 -0
  175. data/lib/Phamlp/sass/extensions/compass/functions/constants.php +44 -0
  176. data/lib/Phamlp/sass/extensions/compass/functions/fontFiles.php +30 -0
  177. data/lib/Phamlp/sass/extensions/compass/functions/imageSize.php +39 -0
  178. data/lib/Phamlp/sass/extensions/compass/functions/inlineData.php +84 -0
  179. data/lib/Phamlp/sass/extensions/compass/functions/lists.php +47 -0
  180. data/lib/Phamlp/sass/extensions/compass/functions/selectors.php +128 -0
  181. data/lib/Phamlp/sass/extensions/compass/functions/urls.php +143 -0
  182. data/lib/Phamlp/sass/extensions/compass/stylesheets/_compass.scss +2 -0
  183. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/_css3.scss +15 -0
  184. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/_layout.scss +1 -0
  185. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/_reset.scss +3 -0
  186. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/_utilities.scss +6 -0
  187. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/css3/_background-clip.scss +43 -0
  188. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/css3/_background-origin.scss +42 -0
  189. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/css3/_background-size.scss +14 -0
  190. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/css3/_border-radius.scss +135 -0
  191. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/css3/_box-shadow.scss +50 -0
  192. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/css3/_box-sizing.scss +13 -0
  193. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/css3/_box.scss +112 -0
  194. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/css3/_columns.scss +55 -0
  195. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/css3/_font-face.scss +33 -0
  196. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/css3/_gradient.scss +96 -0
  197. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/css3/_inline-block.scss +12 -0
  198. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/css3/_opacity.scss +27 -0
  199. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/css3/_shared.scss +47 -0
  200. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/css3/_text-shadow.scss +25 -0
  201. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/css3/_transform.scss +85 -0
  202. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/css3/_transition.scss +85 -0
  203. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/layout/_sticky-footer.scss +23 -0
  204. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/reset/_utilities.scss +133 -0
  205. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/_general.scss +6 -0
  206. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/_links.scss +3 -0
  207. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/_lists.scss +4 -0
  208. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/_print.scss +17 -0
  209. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/_sprites.scss +1 -0
  210. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/_tables.scss +3 -0
  211. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/_text.scss +3 -0
  212. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/general/_clearfix.scss +31 -0
  213. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/general/_float.scss +15 -0
  214. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/general/_hacks.scss +35 -0
  215. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/general/_min.scss +16 -0
  216. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/general/_reset.scss +2 -0
  217. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/general/_tabs.scss +1 -0
  218. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/general/_tag-cloud.scss +18 -0
  219. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/links/_hover-link.scss +5 -0
  220. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/links/_link-colors.scss +28 -0
  221. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/links/_unstyled-link.scss +7 -0
  222. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/lists/_bullets.scss +34 -0
  223. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/lists/_horizontal-list.scss +52 -0
  224. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/lists/_inline-block-list.scss +47 -0
  225. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/lists/_inline-list.scss +29 -0
  226. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/sprites/_sprite-img.scss +56 -0
  227. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/tables/_alternating-rows-and-columns.scss +20 -0
  228. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/tables/_borders.scss +27 -0
  229. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/tables/_scaffolding.scss +9 -0
  230. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/text/_ellipsis.scss +25 -0
  231. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/text/_nowrap.scss +2 -0
  232. data/lib/Phamlp/sass/extensions/compass/stylesheets/compass/utilities/text/_replacement.scss +34 -0
  233. data/lib/Phamlp/sass/messages/_i18n.php +122 -0
  234. data/lib/Phamlp/sass/messages/de.php +70 -0
  235. data/lib/Phamlp/sass/messages/fr.php +70 -0
  236. data/lib/Phamlp/sass/renderers/SassCompactRenderer.php +130 -0
  237. data/lib/Phamlp/sass/renderers/SassCompressedRenderer.php +102 -0
  238. data/lib/Phamlp/sass/renderers/SassExpandedRenderer.php +62 -0
  239. data/lib/Phamlp/sass/renderers/SassNestedRenderer.php +61 -0
  240. data/lib/Phamlp/sass/renderers/SassRenderer.php +51 -0
  241. data/lib/Phamlp/sass/script/SassScriptFunction.php +169 -0
  242. data/lib/Phamlp/sass/script/SassScriptFunctions.php +751 -0
  243. data/lib/Phamlp/sass/script/SassScriptLexer.php +114 -0
  244. data/lib/Phamlp/sass/script/SassScriptOperation.php +151 -0
  245. data/lib/Phamlp/sass/script/SassScriptParser.php +192 -0
  246. data/lib/Phamlp/sass/script/SassScriptParserExceptions.php +40 -0
  247. data/lib/Phamlp/sass/script/SassScriptVariable.php +57 -0
  248. data/lib/Phamlp/sass/script/literals/SassBoolean.php +67 -0
  249. data/lib/Phamlp/sass/script/literals/SassColour.php +886 -0
  250. data/lib/Phamlp/sass/script/literals/SassLiteral.php +359 -0
  251. data/lib/Phamlp/sass/script/literals/SassLiteralExceptions.php +47 -0
  252. data/lib/Phamlp/sass/script/literals/SassNumber.php +503 -0
  253. data/lib/Phamlp/sass/script/literals/SassString.php +106 -0
  254. data/lib/Phamlp/sass/tree/SassCommentNode.php +64 -0
  255. data/lib/Phamlp/sass/tree/SassContext.php +120 -0
  256. data/lib/Phamlp/sass/tree/SassDebugNode.php +84 -0
  257. data/lib/Phamlp/sass/tree/SassDirectiveNode.php +76 -0
  258. data/lib/Phamlp/sass/tree/SassElseNode.php +28 -0
  259. data/lib/Phamlp/sass/tree/SassExtendNode.php +47 -0
  260. data/lib/Phamlp/sass/tree/SassForNode.php +99 -0
  261. data/lib/Phamlp/sass/tree/SassIfNode.php +95 -0
  262. data/lib/Phamlp/sass/tree/SassImportNode.php +69 -0
  263. data/lib/Phamlp/sass/tree/SassMixinDefinitionNode.php +88 -0
  264. data/lib/Phamlp/sass/tree/SassMixinNode.php +91 -0
  265. data/lib/Phamlp/sass/tree/SassNode.php +342 -0
  266. data/lib/Phamlp/sass/tree/SassNodeExceptions.php +117 -0
  267. data/lib/Phamlp/sass/tree/SassPropertyNode.php +239 -0
  268. data/lib/Phamlp/sass/tree/SassRootNode.php +100 -0
  269. data/lib/Phamlp/sass/tree/SassRuleNode.php +337 -0
  270. data/lib/Phamlp/sass/tree/SassVariableNode.php +90 -0
  271. data/lib/Phamlp/sass/tree/SassWhileNode.php +64 -0
  272. data/lib/frontsau/assets/rack.rb +12 -0
  273. data/lib/frontsau/assets/sprockets.rb +59 -0
  274. data/lib/frontsau/assets/static_assets_compiler.rb +50 -0
  275. data/lib/frontsau/assets/url_rewriter.rb +22 -0
  276. data/lib/frontsau/assets/watcher.rb +60 -0
  277. data/lib/frontsau/thor_app.rb +118 -0
  278. data/lib/frontsau/version.rb +3 -0
  279. data/lib/frontsau.rb +64 -0
  280. metadata +578 -0
@@ -0,0 +1,1250 @@
1
+ <?php
2
+ /* SVN FILE: $Id: HamlParser.php 117 2010-09-21 09:41:58Z chris.l.yates@gmail.com $ */
3
+ /**
4
+ * HamlParser class file.
5
+ * HamlParser allows you to write view files in
6
+ * {@link http://haml-lang.com/ Haml}.
7
+ *
8
+ * Please see the {@link http://haml-lang.com/docs/yardoc/file.Haml_REFERENCE.html#plain_text Haml documentation} for the syntax.
9
+ *
10
+ * Credits:
11
+ * This is a port of Haml to PHP. All the genius comes from the people that
12
+ * invented and develop Haml; in particular:
13
+ * + {@link http://hamptoncatlin.com/ Hampton Catlin},
14
+ * + {@link http://nex-3.com/ Nathan Weizenbaum},
15
+ * + {@link http://chriseppstein.github.com/ Chris Eppstein}
16
+ *
17
+ * The bugs are mine. Please report any found at {@link http://code.google.com/p/phamlp/issues/list}
18
+ *
19
+ * Notes
20
+ * <ul>
21
+ * <li>Debug (addition)<ul>
22
+ * <li>Source debug - adds comments to the output showing each source line above
23
+ * the result - ?#s+ to turn on, ?#s- to turn off, ?#s! to toggle</li>
24
+ * <li>Output debug - shows the output directly in the browser - ?#o+ to turn on, ?#o- to turn off, ?#o! to toggle</li>
25
+ * <li>Control both at once - ?#so+ to turn on, ?#so- to turn off, ?#so! to toggle</li>
26
+ * <li>Ugly mode can be controlled by the template</li>
27
+ * <liUugly mode strips comments in the output by default</li>
28
+ * <li>Ugly mode is turned off when in debug</li></ul></li>
29
+ * <li>"-" command (notes)<ul>
30
+ * <li>PHP does not require ending ";"</li>
31
+ * <li>PHP control blocks are automatically bracketed</li>
32
+ * <li>Switch Case statements do not end with ":"
33
+ * <li>do-while control blocks are written as "do (expression)"</li></ul></li>
34
+ * </ul>
35
+ * Comes with filters that run "out of the box":
36
+ * + <b>plain</b>: useful for large chunks of text to ensure Haml doesn't do anything.
37
+ * + <b>escaped</b>: like plain but the output is (x)html escaped.
38
+ * + <b>preserve</b>: like plain but preserves the whitespace.
39
+ * + <b>cdata</b>: wraps the content in CDATA tags.
40
+ * + <b>javascript</b>: wraps the content in <script> and CDATA tags. Useful for adding inline JavaScript.
41
+ * + <b>css</b>: wraps the content in <style> and CDATA tags. Useful for adding inline CSS.
42
+ * + <b>php</b>: wraps the content in <?php tags. The content is PHP code.
43
+ * There are two filters that require external classes to work. See {@link http://code.google.com/p/phamlp/wiki/PredefinedFilters PredefinedFilters on the PHamlP wiki} for details of how to use them.
44
+ * + <b>markdown</b>: Parses the filtered text with Markdown.
45
+ * + <b>textile</b>: Parses the filtered text with Textile.
46
+ * PHP can be used in all the filters (except php) by wrapping expressions in #().
47
+ *
48
+ * @author Chris Yates <chris.l.yates@gmail.com>
49
+ * @copyright Copyright (c) 2010 PBM Web Development
50
+ * @license http://phamlp.googlecode.com/files/license.txt
51
+ * @package PHamlP
52
+ * @subpackage Haml
53
+ */
54
+
55
+ require_once('tree/HamlNode.php');
56
+ require_once('HamlHelpers.php');
57
+ require_once('HamlException.php');
58
+
59
+ /**
60
+ * HamlParser class.
61
+ * Parses {@link http://haml-lang.com/ Haml} view files.
62
+ * @package PHamlP
63
+ * @subpackage Haml
64
+ */
65
+ class HamlParser {
66
+ /**#@+
67
+ * Debug modes
68
+ */
69
+ const DEBUG_NONE = 0;
70
+ const DEBUG_SHOW_SOURCE = 1;
71
+ const DEBUG_SHOW_OUTPUT = 2;
72
+ const DEBUG_SHOW_ALL = 3;
73
+ /**#@-*/
74
+
75
+ /**#@+
76
+ * Regexes used to parse the document
77
+ */
78
+ const REGEX_HAML = '/(?m)^([ \x09]*)((?::(\w*))?(?:%([\w:-]*))?(?:\.((?:(?:[-_:a-zA-Z]|#\{.+?\})+(?:[-:\w]|#\{.+?\})*(?:\.?))*))?(?:#((?:[_:a-zA-Z]|#\{.+?\})+(?:[-:\w]|#\{.+?\})*))?(?:\[(.+)\])?(?:(\()((?:(?:html_attrs\(.*?\)|data[\t ]*=[\t ]*\{.+?\}|(?:[_:a-zA-Z]+[-:\w]*)[\t ]*=[\t ]*.+)[\t ]*)+\)))?(?:(\{)((?::(?:html_attrs\(.*?\)|data[\t ]*=>[\t ]*\{.+?\}|(?:[_:a-zA-Z]+[-:\w]*)[\t ]*=>?[\t ]*.+)(?:,?[\t ]*)?)+\}))?(\|?>?\|?<?) *((?:\?#)|!!!|\/\/|\/|-#|!=|&=|!|&|=|-|~|\\\\\\\\)? *(.*?)(?:\s(\|)?)?)$/'; // Haml line
79
+ const REGEX_ATTRIBUTES = '/:?(?:(data)\s*=>?\s*([({].*?[})]))|(\w+(?:[-:]\w*)*)\s*=>?\s*(?(?=\[)(?:\[(.+?)\])|(?(?=([\'"]))(?:[\'"](.*?)\5)|([^\s,]+)))/';
80
+ const REGEX_ATTRIBUTE_FUNCTION = '/^\$?[_a-zA-Z]\w*(?(?=->)(->[_a-zA-Z]\w*)+|(::[_a-zA-Z]\w*)?)\(.+\)$/'; // Matches functions and instantiated and static object methods
81
+ const REGEX_WHITESPACE_REMOVAL = '/(.*?)\s+$/s';
82
+ const REGEX_WHITESPACE_REMOVAL_DEBUG = '%(.*?)(?:<br />\s)$%s'; // whitespace control when showing output
83
+ //const REGEX_CODE_INTERPOLATION = '/(?:(?<!\\\\)#{(.+?(?:\(.*?\).*?)*)})/';
84
+ /**#@-*/
85
+ const MATCH_INTERPOLATION = '/(?<!\\\\)#\{(.*?)\}/';
86
+ const INTERPOLATE = '<?php echo \1; ?>';
87
+ const HTML_ATTRS = '/html_attrs\(\s*((?(?=\')(?:.*?)\'|(?:.*?)"))(?:\s*,\s*(.*?))?\)/';
88
+
89
+
90
+ /**#@+
91
+ * Haml regex match positions
92
+ */
93
+ const HAML_HAML = 0;
94
+ const HAML_INDENT = 1;
95
+ const HAML_SOURCE = 2;
96
+ const HAML_FILTER = 3;
97
+ const HAML_TAG = 4;
98
+ const HAML_CLASS = 5;
99
+ const HAML_ID = 6;
100
+ const HAML_OBJECT_REFERENCE = 7;
101
+ const HAML_OPEN_XML_ATTRIBUTES = 8;
102
+ const HAML_XML_ATTRIBUTES = 9;
103
+ const HAML_OPEN_RUBY_ATTRIBUTES = 10;
104
+ const HAML_RUBY_ATTRIBUTES = 11;
105
+ const HAML_WHITESPACE_REMOVAL = 12;
106
+ const HAML_TOKEN = 13;
107
+ const HAML_CONTENT = 14;
108
+ const HAML_MULTILINE = 15;
109
+ /**#@-*/
110
+
111
+ /**#@+
112
+ * Haml tokens
113
+ */
114
+ const DOCTYPE = '!!!';
115
+ const HAML_COMMENT = '!(-#|//)!';
116
+ const XML_COMMENT = '/';
117
+ const SELF_CLOSE_TAG = '/';
118
+ const ESCAPE_XML = '&=';
119
+ const UNESCAPE_XML = '!=';
120
+ const INSERT_CODE = '=';
121
+ const INSERT_CODE_PRESERVE_WHITESPACE = '~';
122
+ const RUN_CODE = '-';
123
+ const INNER_WHITESPACE_REMOVAL = '<';
124
+ const OUTER_WHITESPACE_REMOVAL = '>';
125
+ const BLOCK_LEFT_OUTER_WHITESPACE_REMOVAL = '|>';
126
+ const BLOCK_RIGHT_OUTER_WHITESPACE_REMOVAL = '>|';
127
+ /**#@-*/
128
+
129
+ const MULTILINE= ' |';
130
+
131
+ /**#@+
132
+ * Attribute tokens
133
+ */
134
+ const OPEN_XML_ATTRIBUTES = '(';
135
+ const CLOSE_XML_ATTRIBUTES = ')';
136
+ const OPEN_RUBY_ATTRIBUTES = '{';
137
+ const CLOSE_RUBY_ATTRIBUTES = '}';
138
+ /**#@-*/
139
+
140
+ /**#@+
141
+ * Directives
142
+ */
143
+ const DIRECTIVE = '?#';
144
+ const SOURCE_DEBUG = 's';
145
+ const OUTPUT_DEBUG = 'o';
146
+ /**#@-*/
147
+
148
+ const IS_XML_PROLOG = 'XML';
149
+ const XML_PROLOG = "<?php echo \"<?xml version='1.0' encoding='{encoding}' ?>\n\"; ?>";
150
+ const DEFAULT_XML_ENCODING = 'utf-8';
151
+ const XML_ENCODING = '{encoding}';
152
+
153
+ /**
154
+ * @var string Doctype format. Determines how the Haml Doctype declaration is
155
+ * rendered.
156
+ * @see doctypes
157
+ */
158
+ private $format = 'xhtml';
159
+ /**
160
+ * @var string Custom Doctype. If not null and the Doctype declaration in the
161
+ * Haml Document is not a built in Doctype this will be used as the Doctype.
162
+ * This allows Haml to be used for non-(X)HTML documents that are XML compliant.
163
+ * @see doctypes
164
+ * @see emptyTags
165
+ * @see inlineTags
166
+ * @see minimizedAttributes
167
+ */
168
+ private $doctype;
169
+ /**
170
+ * @var boolean whether or not to escape X(HT)ML-sensitive characters in script.
171
+ * If this is true, = behaves like &=; otherwise, it behaves like !=.
172
+ * Note that if this is set, != should be used for yielding to subtemplates
173
+ * and rendering partials. Defaults to false.
174
+ */
175
+ private $escapeHtml = false;
176
+ /**
177
+ * @var boolean Whether or not attribute hashes and scripts designated by
178
+ * = or ~ should be evaluated. If true, the scripts are rendered as empty strings.
179
+ * Defaults to false.
180
+ */
181
+ private $suppressEval = false;
182
+ /**
183
+ * @var string The character that should wrap element attributes. Characters
184
+ * of this type within attributes will be escaped (e.g. by replacing them with
185
+ * &apos;) if the character is an apostrophe or a quotation mark.
186
+ * Defaults to " (an quotation mark).
187
+ */
188
+ private $attrWrapper = '"';
189
+ /**
190
+ * @var array available output styles:
191
+ * nested: output is nested according to the indent level in the source
192
+ * expanded: block tags have their own lines as does content which is indented
193
+ * compact: block tags and their content go on one line
194
+ * compressed: all unneccessary whitepaces is removed. If ugly is true this style is used.
195
+ */
196
+ private $styles = array('nested', 'expanded', 'compact', 'compressed');
197
+ /**
198
+ * @var string output style. Note: ugly must be false to allow style.
199
+ */
200
+ private $style = 'nested';
201
+ /**
202
+ * @var boolean if true no attempt is made to properly indent or format
203
+ * the output. Reduces size of output file but is not very readable;
204
+ * equivalent of style == compressed. Note: ugly must be false to allow style.
205
+ * Defaults to true.
206
+ * @see style
207
+ */
208
+ private $ugly = true;
209
+ /**
210
+ * @var boolean if true comments are preserved in ugly mode. If not in
211
+ * ugly mode comments are always output. Defaults to false.
212
+ */
213
+ private $preserveComments = false;
214
+ /**
215
+ * @var integer Initial debug setting:
216
+ * no debug, show source, show output, or show all.
217
+ * Debug settings can be controlled in the template
218
+ * Defaults to DEBUG_NONE.
219
+ */
220
+ private $debug = self::DEBUG_NONE;
221
+ /**
222
+ * @var string Path to the directory containing user defined filters. If
223
+ * specified this dirctory will be searched before PHamlP looks for the filter
224
+ * in it's collection. This allows the default filters to be overridden and
225
+ * new filters to be installed. Note: No trailing directory separator.
226
+ */
227
+ private $filterDir;
228
+ /**
229
+ * @var string Path to the file containing user defined Haml helpers.
230
+ */
231
+ private $helperFile;
232
+ /**
233
+ * @var string Haml helper class. This must be an instance of HamlHelpers.
234
+ */
235
+ private $helperClass = 'HamlHelpers';
236
+
237
+ /**
238
+ * @var array built in Doctypes
239
+ * @see format
240
+ * @see doctype
241
+ */
242
+ private $doctypes = array (
243
+ 'html4' => array (
244
+ '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">', //HTML 4.01 Transitional
245
+ 'Strict' => '<!DOCTYPE html PUBLIC "-//W3C//DTD 4.01 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">', //HTML 4.01 Strict
246
+ 'Frameset' => '<!DOCTYPE html PUBLIC "-//W3C//DTD 4.01 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">', //HTML 4.01 Frameset
247
+ ),
248
+ 'html5' => array (
249
+ '<!DOCTYPE html>', // XHTML 5
250
+ ),
251
+ 'xhtml' => array (
252
+ '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">', //XHTML 1.0 Transitional
253
+ 'Strict' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">', //XHTML 1.0 Strict
254
+ 'Frameset' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">', //XHTML 1.0 Frameset
255
+ '5' => '<!DOCTYPE html>', // XHTML 5
256
+ '1.1' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">', // XHTML 1.1
257
+ 'Basic' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">', //XHTML Basic 1.1
258
+ 'Mobile' => '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">', //XHTML Mobile 1.2
259
+ )
260
+ );
261
+ /**
262
+ * @var array A list of tag names that should be automatically self-closed
263
+ * if they have no content.
264
+ */
265
+ private $emptyTags = array('meta', 'img', 'link', 'br', 'hr', 'input', 'area', 'param', 'col', 'base');
266
+ /**
267
+ * @var array A list of inline tags.
268
+ */
269
+ private $inlineTags = array('a', 'abbr', 'accronym', 'b', 'big', 'cite', 'code', 'dfn', 'em', 'i', 'kbd', 'q', 'samp', 'small', 'span', 'strike', 'strong', 'tt', 'u', 'var');
270
+ /**
271
+ * @var array attributes that are minimised
272
+ */
273
+ private $minimizedAttributes = array('compact', 'checked', 'declare', 'readonly', 'disabled', 'selected', 'defer', 'ismap', 'nohref', 'noshade', 'nowrap', 'multiple', 'noresize');
274
+ /**
275
+ * @var array A list of tag names that should automatically have their newlines preserved.
276
+ */
277
+ private $preserve = array('pre', 'textarea');
278
+ /**#@-*/
279
+
280
+ /**
281
+ * @var string the character used for indenting. Space or tab.
282
+ * @see indentSpaces
283
+ */
284
+ private $indentChar;
285
+ /**
286
+ * @var array allowable characters for indenting
287
+ */
288
+ private $indentChars = array(' ', "\t");
289
+ /**
290
+ * @var integer number of spaces for indentation.
291
+ * Used on source if {@link indentChar} is space.
292
+ * Used on output if {@link ugly} is false.
293
+ */
294
+ private $indentSpaces;
295
+ /**
296
+ * @var array loaded filters
297
+ */
298
+ private $filters = array();
299
+ /**
300
+ * @var boolean whether line is in a filter
301
+ */
302
+ private $inFilter = false;
303
+ /**
304
+ * @var boolean whether to show the output in the browser for debug
305
+ */
306
+ private $showOutput;
307
+ /**
308
+ * @var boolean whether to show the source in the browser for debug
309
+ */
310
+ private $showSource;
311
+ /**
312
+ * @var integer line number of source being parsed
313
+ */
314
+ private $line;
315
+ /**
316
+ * @var string name of file being parsed
317
+ */
318
+ private $filename;
319
+ /**
320
+ * @var mixed source
321
+ */
322
+ private $source;
323
+
324
+ /**
325
+ * HamlParser constructor.
326
+ * @param array options
327
+ * @return HamlParser
328
+ */
329
+ public function __construct($options = array()) {
330
+ if (isset($options['language'])) {
331
+ Phamlp::$language = $options['language'];
332
+ unset($options['language']);
333
+ }
334
+ foreach ($options as $name => $value) {
335
+ $this->$name = $value;
336
+ } // foreach
337
+
338
+ if ($this->ugly) {
339
+ $this->style = 'compressed';
340
+ }
341
+
342
+ $this->format = strtolower($this->format);
343
+ if (is_null($this->doctype) &&
344
+ !array_key_exists($this->format, $this->doctypes)) {
345
+ throw new HamlException('Invalid {what} ({value}). Must be one of "{options}"', array('{what}'=>'format', '{value}'=>$this->format, '{options}'=>join(', ', array_keys($this->doctypes))), $this);
346
+ }
347
+
348
+ $this->showSource = $this->debug & HamlParser::DEBUG_SHOW_SOURCE;
349
+ $this->showOutput = $this->debug & HamlParser::DEBUG_SHOW_OUTPUT;
350
+
351
+ require_once dirname(__FILE__).DIRECTORY_SEPARATOR.'HamlHelpers.php';
352
+ if (isset($this->helperFile)) {
353
+ require_once $this->helperFile;
354
+ $this->helperClass = basename($this->helperFile, ".php");
355
+ if (!is_subclass_of($this->helperClass, 'HamlHelpers')) {
356
+ throw new HamlException('{what} must extend {base} class', array('{what}'=>$this->helperClass, '{base}'=>'HamlHelpers'), $this);
357
+ }
358
+ }
359
+ }
360
+
361
+ /**
362
+ * Getter.
363
+ * @param string name of property to get
364
+ * @return mixed return value of getter function
365
+ */
366
+ public function __get($name) {
367
+ $getter = 'get' . ucfirst($name);
368
+ if (method_exists($this, $getter)) {
369
+ return $this->$getter();
370
+ }
371
+ throw new HamlException('No getter function for {what}', array('{what}'=>$name));
372
+ }
373
+
374
+ public function getFilename() {
375
+ return $this->filename;
376
+ }
377
+
378
+ public function getLine() {
379
+ return $this->line;
380
+ }
381
+
382
+ public function getSource() {
383
+ return $this->source;
384
+ }
385
+
386
+ /**
387
+ * Parses a Haml file.
388
+ * If an output directory is given the resulting PHP is cached.
389
+ * @param string path to file to parse
390
+ * @param mixed boolean: true to use the default cache directory, false to use
391
+ * the source file directory. string: path to the cache directory.
392
+ * null: disable caching
393
+ * @param string output file extension
394
+ * @param integer permission for the output directory and file
395
+ * @return mixed string: the resulting PHP if no output directory is specified
396
+ * or the output filename if the output directory is specified.
397
+ * boolean: false if the output file could not be written.
398
+ */
399
+ public function parse($sourceFile, $cacheDir=null, $permission=0755, $sourceExtension='.haml', $outputExtension='.php') {
400
+ if (is_string($cacheDir) || is_bool($cacheDir)) {
401
+ if (is_bool($cacheDir)) {
402
+ $cacheDir =
403
+ ($cacheDir ? dirname(__FILE__).DIRECTORY_SEPARATOR.'haml-cache' :
404
+ dirname($sourceFile));
405
+ }
406
+ $outputFile = $cacheDir.DIRECTORY_SEPARATOR.
407
+ basename($sourceFile, $sourceExtension).$outputExtension;
408
+ if (@filemtime($sourceFile) > @filemtime($outputFile)) {
409
+ if (!is_dir($cacheDir)) {
410
+ @mkdir($cacheDir, $permission);
411
+ }
412
+ $return = (file_put_contents($outputFile, $this->haml2PHP($sourceFile))
413
+ === false ? false : $outputFile);
414
+ if ($return !== false) {
415
+ @chmod($outputFile, $permission);
416
+ }
417
+ }
418
+ else {
419
+ $return = $outputFile;
420
+ }
421
+ }
422
+ else {
423
+ $return = $this->haml2PHP($sourceFile);
424
+ }
425
+ return $return;
426
+ }
427
+
428
+ /**
429
+ * Parses a Haml file into PHP.
430
+ * @param string path to file to parse
431
+ * @return string the resulting PHP
432
+ */
433
+ public function haml2PHP($sourceFile) {
434
+ $this->line = 0;
435
+ $this->filename = $sourceFile;
436
+ $helpers = "<?php ";
437
+ //"<?php\nrequire_once '".dirname(__FILE__).DIRECTORY_SEPARATOR."HamlHelpers.php';\n";
438
+ if (isset($this->helperFile)) {
439
+ $helpers .= "require_once '{$this->helperFile}';\n";
440
+ }
441
+ $helpers .= "?>";
442
+ return $helpers . $this->toTree(file_get_contents($sourceFile))->render();
443
+ }
444
+
445
+ /**
446
+ * Parse Haml source into a document tree.
447
+ * @param string Haml source
448
+ * @return HamlRootNode the root of this document tree
449
+ */
450
+ private function toTree($source) {
451
+ $this->source = explode("\n", $source);
452
+ $this->setIndentChar();
453
+
454
+ preg_match_all(self::REGEX_HAML, $source, $this->source, PREG_SET_ORDER);
455
+ unset($source);
456
+ $root = new HamlRootNode(array(
457
+ 'format' => $this->format,
458
+ 'style' => $this->style,
459
+ 'attrWrapper' => $this->attrWrapper,
460
+ 'minimizedAttributes' => $this->minimizedAttributes
461
+ ));
462
+ $this->buildTree($root);
463
+ return $root;
464
+ }
465
+
466
+ /**
467
+ * Builds a parse tree under the parent node.
468
+ * @param HamlNode the parent node
469
+ */
470
+ private function buildTree($parent) {
471
+ while (!empty($this->source) && $this->isChildOf($parent, $this->source[0])) {
472
+ $line = $this->getNextLine();
473
+ if (!empty($line)) {
474
+ $node = ($this->inFilter ?
475
+ new HamlNode($line[self::HAML_SOURCE], $parent) :
476
+ $this->parseLine($line, $parent));
477
+
478
+ if (!empty($node)) {
479
+ $node->token = $line;
480
+ $node->showOutput = $this->showOutput;
481
+ $node->showSource = $this->showSource;
482
+ $this->addChildren($node, $line);
483
+ }
484
+ }
485
+ }
486
+ }
487
+
488
+ /**
489
+ * Adds children to a node if the current line has children.
490
+ * @param HamlNode the node to add children to
491
+ * @param array line to test
492
+ */
493
+ private function addChildren($node, $line) {
494
+ if ($node instanceof HamlFilterNode) {
495
+ $this->inFilter = true;
496
+ }
497
+ if ($this->hasChild($line, $this->inFilter)) {
498
+ $this->buildTree($node);
499
+ if ($node instanceof HamlFilterNode) {
500
+ $this->inFilter = false;
501
+ }
502
+ }
503
+ }
504
+
505
+ /**
506
+ * Returns a value indicating if the next line is a child of the parent line
507
+ * @param array parent line
508
+ * @param boolean whether to all greater than the current indent
509
+ * Used if the source line is a comment or a filter.
510
+ * If true all indented lines are regarded as children; if not the child line
511
+ * must only be indented by 1 or blank. Defaults to false.
512
+ * @return boolean true if the next line is a child of the parent line
513
+ * @throws Exception if the indent is invalid
514
+ */
515
+ private function hasChild($line, $allowGreater = false) {
516
+ if (!empty($this->source)) {
517
+ $i = 0;
518
+ $c = count($this->source);
519
+ while (empty($nextLine[self::HAML_SOURCE]) && $i <= $c) {
520
+ $nextLine = $this->source[$i++];
521
+ }
522
+
523
+ $level = $this->getLevel($nextLine, $line['line'] + $i);
524
+
525
+ if (($level == $line['level'] + 1) ||
526
+ ($allowGreater && $level > $line['level'])) {
527
+ return true;
528
+ }
529
+ elseif ($level <= $line['level']) {
530
+ return false;
531
+ }
532
+ else {
533
+ throw new HamlException('Illegal indentation level ({level}); indentation level can only increase by one', array('{level}'=>$level), $this);
534
+ }
535
+ }
536
+ else {
537
+ return false;
538
+ }
539
+ }
540
+
541
+ /**
542
+ * Returns a value indicating if $line is a child of a node.
543
+ * A blank line is a child of a node.
544
+ * @param HamlNode the node
545
+ * @param array the line to check
546
+ * @return boolean true if the line is a child of the node, false if not
547
+ */
548
+ private function isChildOf($node, $line) {
549
+ $haml = trim($line[self::HAML_HAML]);
550
+ return empty($haml) || $this->getLevel($line, $this->line) >
551
+ $node->level;
552
+ }
553
+
554
+ /**
555
+ * Determine the indent character and indent spaces.
556
+ * The first character of the first indented line determines the character.
557
+ * If this is a space the number of spaces determines the indentSpaces; this
558
+ * is always 1 if the indent character is a tab.
559
+ * @throws HamlException if the indent is mixed
560
+ */
561
+ private function setIndentChar() {
562
+ foreach ($this->source as $l=>$source) {
563
+ if (!empty($source) && in_array($source[0], $this->indentChars)) {
564
+ $this->indentChar = $source[0];
565
+ for ($i = 0, $len = strlen($source); $i < $len && $source[$i] == $this->indentChar; $i++);
566
+ if ($i < $len && in_array($source[$i], $this->indentChars)) {
567
+ $this->line = ++$l;
568
+ $this->source = $source;
569
+ throw new HamlException('Mixed indentation not allowed', array(), $this);
570
+ }
571
+ $this->indentSpaces = ($this->indentChar == ' ' ? $i : 1);
572
+ return;
573
+ }
574
+ } // foreach
575
+ $this->indentChar = ' ';
576
+ $this->indentSpaces = 2;
577
+ }
578
+
579
+ /**
580
+ * Gets the next line.
581
+ * @param array remaining source lines
582
+ * @return array the next line
583
+ */
584
+ private function getNextLine() {
585
+ $line = array_shift($this->source);
586
+ // Blank lines ore OK
587
+ $haml = trim($line[self::HAML_HAML]);
588
+ if (empty($haml)) {
589
+ $this->line++;
590
+ return null;
591
+ }
592
+ // The regex will strip off a '<' at the start of a line
593
+ if ($line[self::HAML_WHITESPACE_REMOVAL] ===
594
+ self::INNER_WHITESPACE_REMOVAL && empty($line[self::HAML_TAG])) {
595
+ $line[self::HAML_CONTENT] =
596
+ $line[self::HAML_WHITESPACE_REMOVAL].$line[self::HAML_TOKEN].$line[self::HAML_CONTENT];
597
+ }
598
+ // The regex treats lines starting with [.+] as an object reference; they are just content
599
+ if (!empty($line[self::HAML_OBJECT_REFERENCE]) && empty($line[self::HAML_TAG])) {
600
+ unset($line[self::HAML_OBJECT_REFERENCE]);
601
+ $line[self::HAML_CONTENT] = $line[self::HAML_SOURCE];
602
+ }
603
+ $line['line'] = $this->line++;
604
+ $line['level'] = $this->getLevel($line, $this->line);
605
+ $line['filename'] = $this->filename;
606
+ if ($this->isMultiline($line)) {
607
+ $line = $this->getMultiline($line);
608
+ }
609
+ return $line;
610
+ }
611
+
612
+ /**
613
+ * Returns the indent level of the line.
614
+ * @param array the line
615
+ * @param integer line number
616
+ * @return integer the indent level of the line
617
+ * @throws Exception if the indent level is invalid
618
+ */
619
+ private function getLevel($line, $n) {
620
+ if ($line[self::HAML_INDENT] && $this->indentChar === ' ') {
621
+ $indent = strlen($line[self::HAML_INDENT]) / $this->indentSpaces;
622
+ }
623
+ else {
624
+ $indent = strlen($line[self::HAML_INDENT]);
625
+ }
626
+
627
+ if (!is_integer($indent) ||
628
+ preg_match("/[^{$this->indentChar}]/", $line[self::HAML_INDENT])) {
629
+ throw new HamlException('Invalid indentation', array(), $this);
630
+ }
631
+ return $indent;
632
+ }
633
+
634
+ /**
635
+ * Parse a line of Haml into a HamlNode for the document tree
636
+ * @param array line to parse
637
+ * @param HamlNode parent node
638
+ * @return HamlNode
639
+ */
640
+ private function parseLine($line, $parent) {
641
+ if ($this->isHamlComment($line)) {
642
+ return $this->parseHamlComment($line);
643
+ }
644
+ elseif ($this->isXmlComment($line)) {
645
+ return $this->parseXmlComment($line, $parent);
646
+ }
647
+ elseif ($this->isElement($line)) {
648
+ return $this->parseElement($line, $parent);
649
+ }
650
+ elseif ($this->isHelper($line)) {
651
+ return $this->parseHelper($line, $parent);
652
+ }
653
+ elseif ($this->isCode($line)) {
654
+ return $this->parseCode($line, $parent);
655
+ }
656
+ elseif ($this->isDirective($line)) {
657
+ return $this->parseDirective($line, $parent);
658
+ }
659
+ elseif ($this->isFilter($line)) {
660
+ return $this->parseFilter($line, $parent);
661
+ }
662
+ elseif ($this->isDoctype($line)) {
663
+ return $this->parseDoctype($line, $parent);
664
+ }
665
+ else {
666
+ return $this->parseContent($line, $parent);
667
+ }
668
+ }
669
+
670
+ /**
671
+ * Return a value indicating if the line has content.
672
+ * @param array line
673
+ * @return boolean true if the line has a content, false if not
674
+ */
675
+ private function hasContent($line) {
676
+ return !empty($line[self::HAML_CONTENT]);
677
+ }
678
+
679
+ /**
680
+ * Return a value indicating if the line is code to be run.
681
+ * @param array line
682
+ * @return boolean true if the line is code to be run, false if not
683
+ */
684
+ private function isCode($line) {
685
+ return $line[self::HAML_TOKEN] === self::RUN_CODE;
686
+ }
687
+
688
+ /**
689
+ * Return a value indicating if the line is a directive.
690
+ * @param array line
691
+ * @return boolean true if the line is a directive, false if not
692
+ */
693
+ private function isDirective($line) {
694
+ return $line[self::HAML_TOKEN] === self::DIRECTIVE;
695
+ }
696
+
697
+ /**
698
+ * Return a value indicating if the line is a doctype.
699
+ * @param array line
700
+ * @return boolean true if the line is a doctype, false if not
701
+ */
702
+ private function isDoctype($line) {
703
+ return $line[self::HAML_TOKEN] === self::DOCTYPE;
704
+ }
705
+
706
+ /**
707
+ * Return a value indicating if the line is an element.
708
+ * Will set the tag to div if it is an implied div.
709
+ * @param array line
710
+ * @return boolean true if the line is an element, false if not
711
+ */
712
+ private function isElement(&$line) {
713
+ if (empty($line[self::HAML_TAG]) && (
714
+ !empty($line[self::HAML_CLASS]) ||
715
+ !empty($line[self::HAML_ID]) ||
716
+ !empty($line[self::HAML_XML_ATTRIBUTES]) ||
717
+ !empty($line[self::HAML_RUBY_ATTRIBUTES]) ||
718
+ !empty($line[self::HAML_OBJECT_REFERENCE])
719
+ )) {
720
+ $line[self::HAML_TAG] = 'div';
721
+ }
722
+
723
+ return !empty($line[self::HAML_TAG]);
724
+ }
725
+
726
+ /**
727
+ * Return a value indicating if the line starts a filter.
728
+ * @param array line to test
729
+ * @return boolean true if the line starts a filter, false if not
730
+ */
731
+ private function isFilter($line) {
732
+ return !empty($line[self::HAML_FILTER]);
733
+ }
734
+
735
+ /**
736
+ * Return a value indicating if the line is a Haml comment.
737
+ * @param array line to test
738
+ * @return boolean true if the line is a Haml comment, false if not
739
+ */
740
+ private function isHamlComment($line) {
741
+ return preg_match(self::HAML_COMMENT, $line[self::HAML_TOKEN]) > 0;
742
+ }
743
+
744
+ /**
745
+ * Return a value indicating if the line is a HamlHelper.
746
+ * @param array line to test
747
+ * @return boolean true if the line is a HamlHelper, false if not
748
+ */
749
+ private function isHelper($line) {
750
+ return (preg_match(HamlHelperNode::MATCH, $line[self::HAML_CONTENT], $matches)
751
+ ? method_exists($this->helperClass, $matches[HamlHelperNode::NAME]) : false);
752
+ }
753
+
754
+ /**
755
+ * Return a value indicating if the line is an XML comment.
756
+ * @param array line to test
757
+ * @return boolean true if theline is an XML comment, false if not
758
+ */
759
+ private function isXmlComment($line) {
760
+ return $line[self::HAML_SOURCE][0] === self::XML_COMMENT;
761
+ }
762
+
763
+ /**
764
+ * Returns a value indicating whether the line is part of a multilne group
765
+ * @param array the line to test
766
+ * @return boolean true if the line os part of a multiline group, false if not
767
+ */
768
+ private function isMultiline($line) {
769
+ return substr($line[self::HAML_SOURCE], -2) === self::MULTILINE;
770
+ }
771
+
772
+ /**
773
+ * Return a value indicating if the line's tag is a block level tag.
774
+ * @param array line
775
+ * @return boolean true if the line's tag is is a block level tag, false if not
776
+ */
777
+ private function isBlock($line) {
778
+ return (!in_array($line[self::HAML_TAG], $this->inlineTags));
779
+ }
780
+
781
+ /**
782
+ * Return a value indicating if the line's tag is self-closing.
783
+ * @param array line
784
+ * @return boolean true if the line's tag is self-closing, false if not
785
+ */
786
+ private function isSelfClosing($line) {
787
+ return (in_array($line[self::HAML_TAG], $this->emptyTags) ||
788
+ $line[self::HAML_TOKEN] == self::SELF_CLOSE_TAG);
789
+ }
790
+
791
+ /**
792
+ * Gets a filter.
793
+ * Filters are loaded on first use.
794
+ * @param string filter name
795
+ * @throws HamlException if the filter does not exist or does not extend HamlBaseFilter
796
+ */
797
+ private function getFilter($filter) {
798
+ static $firstRun = true;
799
+ $imported = false;
800
+
801
+ if (empty($this->filters[$filter])) {
802
+ if ($firstRun) {
803
+ require_once('filters/HamlBaseFilter.php');
804
+ $firstRun = false;
805
+ }
806
+
807
+ $filterclass = 'Haml' . ucfirst($filter) . 'Filter';
808
+ if (isset($this->filterDir)) {
809
+ $this->filterDir = (substr($this->filterDir, -1) == DIRECTORY_SEPARATOR?
810
+ substr($this->filterDir, 0, -1):$this->filterDir);
811
+ if (file_exists($this->filterDir.DIRECTORY_SEPARATOR."$filterclass.php")) {
812
+ require_once($this->filterDir.DIRECTORY_SEPARATOR."$filterclass.php");
813
+ $imported = true;
814
+ }
815
+ }
816
+
817
+ if (!$imported && file_exists(dirname(__FILE__).DIRECTORY_SEPARATOR.'filters'.DIRECTORY_SEPARATOR."$filterclass.php")) {
818
+ require_once("filters/$filterclass.php");
819
+ $imported = true;
820
+ }
821
+
822
+ if (!$imported) {
823
+ throw new HamlException('Unable to find {what}: {filename}', array('{what}'=>$filter.' filter', '{filename}'=>$filterclass.'.php'), $this);
824
+ }
825
+
826
+ $this->filters[$filter] = new $filterclass();
827
+
828
+ if (!($this->filters[$filter] instanceof HamlBaseFilter)) {
829
+ throw new HamlException('{what} must extend {base} class', array('{what}'=>$filter, '{base}'=>'HamlBaseFilter'), $this);
830
+ }
831
+
832
+ $this->filters[$filter]->init();
833
+ }
834
+ return $this->filters[$filter];
835
+ }
836
+
837
+ /**
838
+ * Gets the next line.
839
+ * @param array first line
840
+ * @return array the next line
841
+ */
842
+ private function getMultiline($line) {
843
+ do {
844
+ $multiLine = array_shift($this->source);
845
+ $line[self::HAML_CONTENT] .= substr($multiLine[self::HAML_SOURCE], 0, -2);
846
+ } while(!empty($this->source) && $this->isMultiline($this->source[0]));
847
+ return $line;
848
+ }
849
+
850
+ /**
851
+ * Parse attributes.
852
+ * @param array line to parse
853
+ * @return array attributes in name=>value pairs
854
+ */
855
+ private function parseAttributes($line) {
856
+ $attributes = array();
857
+ if (!empty($line[self::HAML_OPEN_XML_ATTRIBUTES])) {
858
+ if (empty($line[self::HAML_XML_ATTRIBUTES])) {
859
+ $line[self::HAML_XML_ATTRIBUTES] = $line[self::HAML_CONTENT];
860
+ unset($line[self::HAML_CONTENT]);
861
+ do {
862
+ $multiLine = array_shift($this->source);
863
+ $line[self::HAML_XML_ATTRIBUTES] .= $multiLine[self::HAML_CONTENT];
864
+ } while (substr($line[self::HAML_XML_ATTRIBUTES], -1) !==
865
+ self::CLOSE_XML_ATTRIBUTES);
866
+ }
867
+ if (preg_match(self::HTML_ATTRS, $line[self::HAML_XML_ATTRIBUTES], $htmlAttrs)) {
868
+ $line[self::HAML_XML_ATTRIBUTES] = preg_replace(self::HTML_ATTRS, '', $line[self::HAML_XML_ATTRIBUTES]);
869
+ $attributes = array_merge($attributes, $this->htmlAttrs($htmlAttrs));
870
+ }
871
+ $attributes = array_merge(
872
+ $attributes,
873
+ $this->parseAttributeHash($line[self::HAML_XML_ATTRIBUTES])
874
+ );
875
+ }
876
+ if (!empty($line[self::HAML_OPEN_RUBY_ATTRIBUTES])) {
877
+ if (empty($line[self::HAML_RUBY_ATTRIBUTES])) {
878
+ $line[self::HAML_RUBY_ATTRIBUTES] = $line[self::HAML_CONTENT];
879
+ unset($line[self::HAML_CONTENT]);
880
+ do {
881
+ $multiLine = array_shift($this->source);
882
+ $line[self::HAML_RUBY_ATTRIBUTES] .= $multiLine[self::HAML_CONTENT];
883
+ } while (substr($line[self::HAML_RUBY_ATTRIBUTES], -1) !==
884
+ self::CLOSE_RUBY_ATTRIBUTES);
885
+ }
886
+ if (preg_match(self::HTML_ATTRS, $line[self::HAML_RUBY_ATTRIBUTES], $htmlAttrs)) {
887
+ $line[self::HAML_RUBY_ATTRIBUTES] = preg_replace(self::HTML_ATTRS, '', $line[self::HAML_RUBY_ATTRIBUTES]);
888
+ $attributes = array_merge($attributes, $this->htmlAttrs($htmlAttrs));
889
+ }
890
+ $attributes = array_merge(
891
+ $attributes,
892
+ $this->parseAttributeHash($line[self::HAML_RUBY_ATTRIBUTES])
893
+ );
894
+ }
895
+ if (!empty($line[self::HAML_OBJECT_REFERENCE])) {
896
+ $objectRef = explode(',', preg_replace('/,\s*/', ',', $line[self::HAML_OBJECT_REFERENCE]));
897
+ $prefix = (isset($objectRef[1]) ? $objectRef[1] . '_' : '');
898
+ $class = "strtolower(str_replace(' ', '_', preg_replace('/(?<=\w)([ A-Z])/', '_\1', get_class(" . $objectRef[0] . '))))';
899
+ $attributes['class'] = "<?php echo '$prefix' . $class; ?>";
900
+ $attributes['id'] = "<?php echo '$prefix' . $class . '_' . {$objectRef[0]}->id; ?>";
901
+ }
902
+ else {
903
+ if (!empty($line[self::HAML_CLASS])) {
904
+ $classes = explode('.', $line[self::HAML_CLASS]);
905
+ foreach ($classes as &$class) {
906
+ if (preg_match(self::MATCH_INTERPOLATION, $class)) {
907
+ $class = $this->interpolate($class);
908
+ }
909
+ } // foreach
910
+ $attributes['class'] = join(' ', $classes) .
911
+ (isset($attributes['class']) ? " {$attributes['class']}" : '');
912
+ }
913
+ if (!empty($line[self::HAML_ID])) {
914
+ $attributes['id'] =
915
+ (preg_match(self::MATCH_INTERPOLATION, $line[self::HAML_ID]) ?
916
+ $this->interpolate($line[self::HAML_ID]) : $line[self::HAML_ID]) .
917
+ (isset($attributes['id']) ? "_{$attributes['id']}" : '');
918
+ }
919
+ }
920
+
921
+ ksort($attributes, SORT_STRING);
922
+ return $attributes;
923
+ }
924
+
925
+ /**
926
+ * Parse attributes.
927
+ * @param string the attributes
928
+ * @return array attributes in name=>value pairs
929
+ */
930
+ private function parseAttributeHash($subject) {
931
+ $subject = substr($subject, 0, -1);
932
+ $attributes = array();
933
+ if (preg_match(self::REGEX_ATTRIBUTE_FUNCTION, $subject)) {
934
+ $attributes[0] = "<?php echo $subject; ?>";
935
+ return $attributes;
936
+ }
937
+
938
+ preg_match_all(self::REGEX_ATTRIBUTES, $subject, $attrs, PREG_SET_ORDER);
939
+ foreach ($attrs as $attr) {
940
+ if (!empty($attr[1])) { // HTML5 Custom Data Attributes
941
+ $dataAttributes = $this->parseAttributeHash(substr($attr[2], 1));
942
+ foreach ($dataAttributes as $key=>$value) {
943
+ $attributes["data-$key"] = $value;
944
+ } // foreach
945
+ }
946
+ elseif (!empty($attr[4])) {
947
+ $values = array_map('trim', explode(',', $attr[4]));
948
+ if ($attr[3] !== 'class' && $attr[3] !== 'id') {
949
+ throw new HamlException('Attribute must be "class" or "id" with array value', array(), $this);
950
+ }
951
+ $attributes[$attr[3]] = '<?php echo ' . join(($attr[3] === 'id' ? ".'_'." : ".' '."), $values) . '; ?>';
952
+ }
953
+ elseif (!empty($attr[6])) {
954
+ $attributes[$attr[3]] = $this->interpolate($attr[6]);
955
+ }
956
+ elseif ($attr[6] === '') {
957
+ $attributes[$attr[3]] = $attr[6];
958
+ }
959
+ else {
960
+ switch ($attr[7]) {
961
+ case 'true':
962
+ $attributes[$attr[3]] = $attr[3];
963
+ break;
964
+ case 'false':
965
+ break;
966
+ default:
967
+ $attributes[$attr[3]] = "<?php echo {$attr[7]}; ?>";
968
+ break;
969
+ }
970
+ }
971
+ } // foreach
972
+ return $attributes;
973
+ }
974
+
975
+ /**
976
+ * Returns an array of attributes for the html element.
977
+ * @param array arguments for HamlHelpers::html_attrs
978
+ * @return array attributes for the html element
979
+ */
980
+ private function htmlAttrs($htmlAttrs) {
981
+ if (empty($htmlAttrs[1]) && empty($htmlAttrs[2])) {
982
+ return HamlHelpers::html_attrs();
983
+ }
984
+ else {
985
+ $htmlAttrs[1] = substr($htmlAttrs[1], 1, -1);
986
+ if (substr($htmlAttrs[1], -1) == ';') {
987
+ $htmlAttrs[1] = eval("return {$htmlAttrs[1]}");
988
+ }
989
+ if (isset($htmlAttrs[2])) {
990
+ return HamlHelpers::html_attrs($htmlAttrs[1], eval($htmlAttrs[2] . ';'));
991
+ }
992
+ else {
993
+ return HamlHelpers::html_attrs($htmlAttrs[1]);
994
+ }
995
+ }
996
+ }
997
+
998
+ /**
999
+ * Parse code
1000
+ * @param array line to parse
1001
+ * @param HamlNode parent node
1002
+ * @return HamlCodeBlockNode
1003
+ */
1004
+ private function parseCode($line, $parent) {
1005
+ if (preg_match('/^(if|foreach|for|switch|do|while)\b(.*)$/',
1006
+ $line[self::HAML_CONTENT], $block)) {
1007
+ if ($block[1] === 'do') {
1008
+ $node = new HamlCodeBlockNode('<?php do { ?>', $parent);
1009
+ $node->doWhile = 'while' . $block[2] . ';';
1010
+ }
1011
+ elseif ($block[1] === 'switch') {
1012
+ $node = new HamlCodeBlockNode("<?php {$line[self::HAML_CONTENT]} {", $parent);
1013
+ }
1014
+ else {
1015
+ $node = new HamlCodeBlockNode("<?php {$line[self::HAML_CONTENT]} { ?>", $parent);
1016
+ }
1017
+ }
1018
+ elseif (strpos($line[self::HAML_CONTENT], 'else') === 0) {
1019
+ $node = new HamlCodeBlockNode("<?php } {$line[self::HAML_CONTENT]} { ?>", null);
1020
+ $node->token = $line;
1021
+ $node->showOutput = $this->showOutput;
1022
+ $node->showSource = $this->showSource;
1023
+ $parent->getLastChild()->addElse($node);
1024
+ $this->addChildren($node, $line);
1025
+ $node = null;
1026
+ }
1027
+ elseif (strpos($line[self::HAML_CONTENT], 'case') === 0) {
1028
+ $node = new HamlNode(($parent->hasChildren() ? '<?php ' : '') .
1029
+ "{$line[self::HAML_CONTENT]}: ?>", $parent);
1030
+ }
1031
+ else {
1032
+ $node = new HamlNode("<?php {$line[self::HAML_CONTENT]}; ?>", $parent);
1033
+ }
1034
+ return $node;
1035
+ }
1036
+
1037
+ /**
1038
+ * Parse content
1039
+ * @param array line to parse
1040
+ * @param HamlNode parent node
1041
+ * @return HamlNode
1042
+ */
1043
+ private function parseContent($line, $parent) {
1044
+ switch ($line[self::HAML_TOKEN]) {
1045
+ case self::INSERT_CODE:
1046
+ $content = ($this->suppressEval ? '' :
1047
+ '<?php echo ' . ($this->escapeHtml ?
1048
+ 'htmlentities(' . $line[self::HAML_CONTENT] . ')' :
1049
+ $line[self::HAML_CONTENT]) .
1050
+ "; ?>" .
1051
+ ($this->style == HamlRenderer::STYLE_EXPANDED ||
1052
+ $this->style == HamlRenderer::STYLE_NESTED ? "\n" : ''));
1053
+ break;
1054
+ case self::INSERT_CODE_PRESERVE_WHITESPACE:
1055
+ $content = ($this->suppressEval ? '' :
1056
+ '<?php echo str_replace("\n", \'&#x000a\', ' . ($this->escapeHtml ?
1057
+ 'htmlentities(' . $line[self::HAML_CONTENT] . ')' :
1058
+ $line[self::HAML_CONTENT]) .
1059
+ "; ?>" .
1060
+ ($this->style == HamlRenderer::STYLE_EXPANDED ||
1061
+ $this->style == HamlRenderer::STYLE_NESTED ? "\n" : ''));
1062
+ break;
1063
+ default:
1064
+ $content = $line[self::HAML_CONTENT];
1065
+ break;
1066
+ } // switch
1067
+
1068
+ return new HamlNode($this->interpolate($content), $parent);
1069
+ }
1070
+
1071
+ /**
1072
+ * Parse a directive.
1073
+ * Various options are set according to the directive
1074
+ * @param array line to parse
1075
+ * @return null
1076
+ */
1077
+ private function parseDirective($line) {
1078
+ preg_match('/(\w+)(\+|-)?/', $line[self::HAML_CONTENT], $matches);
1079
+ switch ($matches[1]) {
1080
+ case 's':
1081
+ $this->showSource = ($matches[2] == '+' ? true :
1082
+ ($matches[2] == '-' ? false : $this->showSource));
1083
+ break;
1084
+ case 'o':
1085
+ $this->showOutput = ($matches[2] == '+' ? true :
1086
+ ($matches[2] == '-' ? false : $this->showOutput));
1087
+ break;
1088
+ case 'os':
1089
+ case 'so':
1090
+ $this->showSource = ($matches[2] == '+' ? true :
1091
+ ($matches[2] == '-' ? false : $this->showSource));
1092
+ $this->showOutput = ($matches[2] == '+' ? true :
1093
+ ($matches[2] == '-' ? false : $this->showOutput));
1094
+ break;
1095
+ default:
1096
+ if (!in_array($matches[1], $this->styles)) {
1097
+ throw new HamlException('Invalid {what} ({value})', array('{what}'=>'directive', '{value}'=>self::DIRECTIVE.$matches[0]), $this);
1098
+ }
1099
+ $this->style = $matches[1];
1100
+ break;
1101
+ } // switch
1102
+ }
1103
+
1104
+ /**
1105
+ * Parse a doctype declaration
1106
+ * @param array line to parse
1107
+ * @param HamlNode parent node
1108
+ * @return HamlDoctypeNode
1109
+ */
1110
+ private function parseDoctype($line, $parent) {
1111
+ $content = explode(' ', $line[self::HAML_CONTENT]);
1112
+ if (!empty($content)) {
1113
+ if ($content[0] === self::IS_XML_PROLOG) {
1114
+ $encoding = isset($content[1]) ? $content[1] : self::DEFAULT_XML_ENCODING;
1115
+ $output = str_replace(self::XML_ENCODING, $encoding, self::XML_PROLOG);
1116
+ }
1117
+ elseif (empty($content[0])) {
1118
+ $output = $this->doctypes[$this->format][0];
1119
+ }
1120
+ elseif (array_key_exists($content[0],
1121
+ $this->doctypes[$this->format])) {
1122
+ $output = $this->doctypes[$this->format][$content[0]];
1123
+ }
1124
+ elseif (!empty($this->doctype)) {
1125
+ $output = $this->doctype;
1126
+ }
1127
+ else {
1128
+ $_doctypes = array_keys($this->doctypes[$this->format]);
1129
+ array_shift($_doctypes);
1130
+ throw new HamlException('Invalid {what} ({value}); must be one of "{options}"', array('{what}'=>'doctype', '{value}'=>$content[0], '{options}'=>join(', ', $_doctypes).' or empty'), $this);
1131
+ }
1132
+ }
1133
+ return new HamlDoctypeNode($output, $parent);
1134
+ }
1135
+
1136
+ /**
1137
+ * Parse a Haml comment.
1138
+ * If the comment is an empty comment eat all child lines.
1139
+ * @param array line to parse
1140
+ */
1141
+ private function parseHamlComment($line) {
1142
+ if (!$this->hasContent($line)) {
1143
+ while ($this->hasChild($line, true)) {
1144
+ array_shift($this->source);
1145
+ $this->line++;
1146
+ }
1147
+ }
1148
+ }
1149
+
1150
+ /**
1151
+ * Parse a HamlHelper.
1152
+ * @param array line to parse
1153
+ * @param HamlNode parent node
1154
+ * @return HamlHelperNode
1155
+ */
1156
+ private function parseHelper($line, $parent) {
1157
+ preg_match(HamlHelperNode::MATCH, $line[self::HAML_CONTENT], $matches);
1158
+ $node = new HamlHelperNode($this->helperClass, $matches[HamlHelperNode::PRE], $matches[HamlHelperNode::NAME], $matches[HamlHelperNode::ARGS], $parent);
1159
+ if (isset($matches[HamlHelperNode::BLOCK])) {
1160
+ new HamlNode($matches[HamlHelperNode::BLOCK], $node);
1161
+ }
1162
+ return $node;
1163
+ }
1164
+
1165
+ /**
1166
+ * Parse an element.
1167
+ * @param array line to parse
1168
+ * @param HamlNode parent node
1169
+ * @return HamlElementNode tag node and children
1170
+ */
1171
+ private function parseElement($line, $parent) {
1172
+ $node = new HamlElementNode($line[self::HAML_TAG], $parent);
1173
+ $node->isSelfClosing = $this->isSelfClosing($line);
1174
+ $node->isBlock = $this->isBlock($line);
1175
+ $node->attributes = $this->parseAttributes($line);
1176
+ if ($this->hasContent($line)) {
1177
+ $child = $this->parseContent($line, $node);
1178
+ $child->showOutput = $this->showOutput;
1179
+ $child->showSource = $this->showSource;
1180
+ $child->token = array(
1181
+ self::HAML_SOURCE => $line[self::HAML_SOURCE],
1182
+ 'filename' => $line['filename'],
1183
+ 'line' => $line['line'],
1184
+ 'level' => ($line['level'] + 1)
1185
+ );
1186
+ }
1187
+ $node->whitespaceControl = $this->parseWhitespaceControl($line);
1188
+ return $node;
1189
+ }
1190
+
1191
+ /**
1192
+ * Parse a filter.
1193
+ * @param array line to parse
1194
+ * @param HamlNode parent node
1195
+ * @return HamlNode filter node
1196
+ */
1197
+ private function parseFilter($line, $parent) {
1198
+ $node = new HamlFilterNode($this->getFilter($line[self::HAML_FILTER]), $parent);
1199
+ if ($this->hasContent($line)) {
1200
+ $child = $this->parseContent($line);
1201
+ $child->showOutput = $this->showOutput;
1202
+ $child->showSource = $this->showSource;
1203
+ $child->token = array(
1204
+ 'level' => ($line['level'] + 1),
1205
+ 'line' => $line['line']
1206
+ );
1207
+ }
1208
+ return $node;
1209
+ }
1210
+
1211
+ /**
1212
+ * Parse an Xml comment.
1213
+ * @param array line to parse
1214
+ * @param HamlNode parent node
1215
+ * @return HamlCommentNode
1216
+ */
1217
+ private function parseXmlComment($line, $parent) {
1218
+ return new HamlCommentNode($line[self::HAML_CONTENT], $parent);
1219
+ }
1220
+
1221
+ private function parseWhitespaceControl($line) {
1222
+ $whitespaceControl = array('inner' => false, 'outer' => array('left' => false, 'right' => false));
1223
+
1224
+ if (!empty($line[self::HAML_WHITESPACE_REMOVAL])) {
1225
+ $whitespaceControl['inner'] =
1226
+ (strpos($line[self::HAML_WHITESPACE_REMOVAL],
1227
+ self::INNER_WHITESPACE_REMOVAL) !== false);
1228
+
1229
+ if (strpos($line[self::HAML_WHITESPACE_REMOVAL],
1230
+ self::OUTER_WHITESPACE_REMOVAL) !== false) {
1231
+ $whitespaceControl['outer']['left'] =
1232
+ (strpos($line[self::HAML_WHITESPACE_REMOVAL],
1233
+ self::BLOCK_LEFT_OUTER_WHITESPACE_REMOVAL) === false);
1234
+ $whitespaceControl['outer']['right'] =
1235
+ (strpos($line[self::HAML_WHITESPACE_REMOVAL],
1236
+ self::BLOCK_RIGHT_OUTER_WHITESPACE_REMOVAL) === false);
1237
+ }
1238
+ }
1239
+ return $whitespaceControl;
1240
+ }
1241
+
1242
+ /**
1243
+ * Replace interpolated PHP contained in '#{}'.
1244
+ * @param string the text to interpolate
1245
+ * @return string the interpolated text
1246
+ */
1247
+ protected function interpolate($string) {
1248
+ return preg_replace(self::MATCH_INTERPOLATION, self::INTERPOLATE, $string);
1249
+ }
1250
+ }