├── .gitignore ├── README.md ├── app ├── assets │ ├── jquery.js │ ├── scripts_to_compile │ │ └── compiled.js │ ├── scripts_uncompiled │ │ └── uncompiled.js │ └── stylesheets │ │ ├── bourbon │ │ ├── _bourbon-deprecated-upcoming.scss │ │ ├── _bourbon.scss │ │ ├── addons │ │ │ ├── _button.scss │ │ │ ├── _clearfix.scss │ │ │ ├── _font-family.scss │ │ │ ├── _hide-text.scss │ │ │ ├── _html5-input-types.scss │ │ │ ├── _position.scss │ │ │ ├── _prefixer.scss │ │ │ ├── _retina-image.scss │ │ │ ├── _size.scss │ │ │ ├── _timing-functions.scss │ │ │ └── _triangle.scss │ │ ├── css3 │ │ │ ├── _animation.scss │ │ │ ├── _appearance.scss │ │ │ ├── _backface-visibility.scss │ │ │ ├── _background-image.scss │ │ │ ├── _background.scss │ │ │ ├── _border-image.scss │ │ │ ├── _border-radius.scss │ │ │ ├── _box-sizing.scss │ │ │ ├── _columns.scss │ │ │ ├── _flex-box.scss │ │ │ ├── _font-face.scss │ │ │ ├── _hidpi-media-query.scss │ │ │ ├── _image-rendering.scss │ │ │ ├── _inline-block.scss │ │ │ ├── _keyframes.scss │ │ │ ├── _linear-gradient.scss │ │ │ ├── _perspective.scss │ │ │ ├── _placeholder.scss │ │ │ ├── _radial-gradient.scss │ │ │ ├── _transform.scss │ │ │ ├── _transition.scss │ │ │ └── _user-select.scss │ │ ├── functions │ │ │ ├── _compact.scss │ │ │ ├── _flex-grid.scss │ │ │ ├── _grid-width.scss │ │ │ ├── _linear-gradient.scss │ │ │ ├── _modular-scale.scss │ │ │ ├── _px-to-em.scss │ │ │ ├── _radial-gradient.scss │ │ │ ├── _tint-shade.scss │ │ │ └── _transition-property-name.scss │ │ └── helpers │ │ │ ├── _deprecated-webkit-gradient.scss │ │ │ ├── _gradient-positions-parser.scss │ │ │ ├── _linear-positions-parser.scss │ │ │ ├── _radial-arg-parser.scss │ │ │ ├── _radial-positions-parser.scss │ │ │ ├── _render-gradients.scss │ │ │ └── _shape-size-stripper.scss │ │ ├── compiled.sass │ │ ├── html5-boilerplate.sass │ │ ├── html5-boilerplate.suffix.sass │ │ └── style.css └── views │ ├── 404.haml │ ├── category.haml │ ├── footer.haml │ ├── header.haml │ ├── index.haml │ ├── results.haml │ ├── search.haml │ ├── single.haml │ └── tag.haml ├── install ├── lib ├── MtHaml │ ├── Autoloader.php │ ├── Environment.php │ ├── Escaping.php │ ├── Exception.php │ ├── Exception │ │ └── SyntaxErrorException.php │ ├── Node │ │ ├── Comment.php │ │ ├── Doctype.php │ │ ├── EscapableAbstract.php │ │ ├── Filter.php │ │ ├── Insert.php │ │ ├── InterpolatedString.php │ │ ├── NestAbstract.php │ │ ├── NestInterface.php │ │ ├── NodeAbstract.php │ │ ├── ObjectRefClass.php │ │ ├── ObjectRefId.php │ │ ├── Root.php │ │ ├── Run.php │ │ ├── Statement.php │ │ ├── Tag.php │ │ ├── TagAttribute.php │ │ ├── TagAttributeInterpolation.php │ │ ├── TagAttributeList.php │ │ └── Text.php │ ├── NodeVisitor │ │ ├── Autoclose.php │ │ ├── Escaping.php │ │ ├── MergeAttrs.php │ │ ├── Midblock.php │ │ ├── NodeVisitorAbstract.php │ │ ├── NodeVisitorInterface.php │ │ ├── PhpRenderer.php │ │ ├── Printer.php │ │ ├── RendererAbstract.php │ │ └── TwigRenderer.php │ ├── Parser.php │ ├── Parser │ │ └── Buffer.php │ ├── Runtime.php │ ├── Runtime │ │ ├── AttributeInterpolation.php │ │ └── AttributeList.php │ ├── Support │ │ └── Twig │ │ │ ├── Extension.php │ │ │ └── Loader.php │ ├── Target │ │ ├── Php.php │ │ ├── TargetAbstract.php │ │ ├── TargetInterface.php │ │ └── Twig.php │ └── compile.php ├── closure_compiler.jar └── make.sh ├── theme ├── 404.php ├── category.php ├── compiled.css ├── footer.php ├── header.php ├── index.php ├── results.php ├── scripts │ ├── compiled.min.js │ └── uncompiled.js ├── search.php ├── single.php ├── style.css └── tag.php ├── tmp └── .gitkeep └── watch /.gitignore: -------------------------------------------------------------------------------- 1 | /.sass-cache -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wordpress-haml-sass 2 | ## Easy WordPress theme development in HAML, PHP, CoffeeScript, & SASS with closure compiled JavaScript 3 | 4 | The purpose of this project is to string together a ton of great tools to make creating a WordPress theme a little more 2013 and a little less 2004, without any fancy plugins. Just a simple, compiled WordPress theme from HAML, PHP, SASS, and JavaScript. 5 | 6 | Views like index.php, single.php, header.php, footer.php, etc are all created using the HAML files located in the app/views directory. 7 | 8 | Styles are compiled from SASS files found in the `app/assets/stylesheets` directory. 9 | 10 | JavaScript and CoffeeScript files inside of the `app/assets/scripts_to_compile` directory will be compiled into one manifest file, with jQuery placed before anything else. Scripts inside of `app/assets/scripts_uncompiled` will just be copied to the `/scripts` folder in the theme. 11 | 12 | All other assets are copied from their respective assets folder to the appropriate theme directory. 13 | 14 | After compilation, the theme is stored in the `/theme` directory. You can change this directory by editing the `make` file. See the "Usage" section for a better way - symbolic linking the /theme directory to your local server `wp-content/themes` folder. 15 | 16 | 17 | ## Dependencies, Installation, Usage 18 | 19 | 20 | ### Dependencies 21 | 22 | We are using the amazing [Multi-Target HAML](https://github.com/arnaud-lb/MtHaml) compiler to render PHP along with some custom regexes to strip out anything that would normally be compiled at runtime. 23 | 24 | You'll also need [SASS](http://www.hongkiat.com/blog/getting-started-saas/) installed. [Bourbon](https://github.com/thoughtbot/bourbon) is included by default as well. 25 | 26 | [PHP](http://php.net/manual/en/install.macosx.php) and [Java](http://www.java.com/en/download/help/mac_install.xml) are also required to render your PHP and JavaScript with [Closure Compiler](https://developers.google.com/closure/compiler/). 27 | 28 | ### Installation 29 | 30 | Run `./install` to install fswatcher, which the package uses to watch the /app directory for changes and recompile the theme. You may need to run `chmod +x install` to give it the correct permissions before you run it. 31 | 32 | ### Usage 33 | 34 | Start the watcher by typing `./watch`. You may need to run `chmod +x watch` to give it the correct permissions before you run it. Edit HAML, SASS, and PHP files and save them to recompile the theme. 35 | 36 | You may want to symbolic link the /theme directory to wherever your serving your blog from locally. For instance, if you're using MAMP: 37 | 38 | `sudo ln -s ~/dev/wordpress-haml-sass/theme/ /Applications/MAMP/htdocs/wp-content/themes/theme` 39 | 40 | 41 | ## Contributions, Authors, Contributors, Props 42 | 43 | ### Contributions 44 | 45 | Are happily accepted if they're in the general spirit of the project. Just send a pull request. Also file an issue if you notice any weirdness! 46 | 47 | ### Author 48 | 49 | Zach Feldman [@zachfeldman](https://twitter.com/zachfeldman) 50 | 51 | ### Contributors 52 | 53 | Ian Jennings (Watcher Implementation) [@sw1tch](https://twitter.com/sw1tch) 54 | 55 | Joc O'Connor (CoffeeScript Implementation) [@jococo](https://github.com/jococo) 56 | 57 | ### Props 58 | 59 | Props to [@contently](http://contently.com) for letting me build awesome stuff like this while developing the digital version of our print magazine, [The Content Strategist](http://contently.com/strategist/)! 60 | 61 | [![githalytics.com alpha](https://cruel-carlota.pagodabox.com/fd135d42e687d99d4edfc47a5261e934 "githalytics.com")](http://githalytics.com/zachfeldman/wordpress-haml-sass) -------------------------------------------------------------------------------- /app/assets/scripts_to_compile/compiled.js: -------------------------------------------------------------------------------- 1 | /* JS to compile goes here! 2 | * You can actually put any file in this directory and it will be compiled by closure compiler. 3 | * 4 | */ -------------------------------------------------------------------------------- /app/assets/scripts_uncompiled/uncompiled.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Throw any scripts in this directory that for whatever reason can't be compiled. 3 | * 4 | * 5 | */ -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/_bourbon-deprecated-upcoming.scss: -------------------------------------------------------------------------------- 1 | //************************************************************************// 2 | // These mixins/functions are deprecated 3 | // They will be removed in the next MAJOR version release 4 | //************************************************************************// 5 | @mixin box-shadow ($shadows...) { 6 | @include prefixer(box-shadow, $shadows, spec); 7 | @warn "box-shadow is deprecated and will be removed in the next major version release"; 8 | } 9 | 10 | @mixin background-size ($lengths...) { 11 | @include prefixer(background-size, $lengths, spec); 12 | @warn "background-size is deprecated and will be removed in the next major version release"; 13 | } 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/_bourbon.scss: -------------------------------------------------------------------------------- 1 | // Custom Helpers 2 | @import "helpers/deprecated-webkit-gradient"; 3 | @import "helpers/gradient-positions-parser"; 4 | @import "helpers/linear-positions-parser"; 5 | @import "helpers/radial-arg-parser"; 6 | @import "helpers/radial-positions-parser"; 7 | @import "helpers/render-gradients"; 8 | @import "helpers/shape-size-stripper"; 9 | 10 | // Custom Functions 11 | @import "functions/compact"; 12 | @import "functions/flex-grid"; 13 | @import "functions/grid-width"; 14 | @import "functions/linear-gradient"; 15 | @import "functions/modular-scale"; 16 | @import "functions/px-to-em"; 17 | @import "functions/radial-gradient"; 18 | @import "functions/tint-shade"; 19 | @import "functions/transition-property-name"; 20 | 21 | // CSS3 Mixins 22 | @import "css3/animation"; 23 | @import "css3/appearance"; 24 | @import "css3/backface-visibility"; 25 | @import "css3/background"; 26 | @import "css3/background-image"; 27 | @import "css3/border-image"; 28 | @import "css3/border-radius"; 29 | @import "css3/box-sizing"; 30 | @import "css3/columns"; 31 | @import "css3/flex-box"; 32 | @import "css3/font-face"; 33 | @import "css3/hidpi-media-query"; 34 | @import "css3/image-rendering"; 35 | @import "css3/inline-block"; 36 | @import "css3/keyframes"; 37 | @import "css3/linear-gradient"; 38 | @import "css3/perspective"; 39 | @import "css3/radial-gradient"; 40 | @import "css3/transform"; 41 | @import "css3/transition"; 42 | @import "css3/user-select"; 43 | @import "css3/placeholder"; 44 | 45 | // Addons & other mixins 46 | @import "addons/button"; 47 | @import "addons/clearfix"; 48 | @import "addons/font-family"; 49 | @import "addons/hide-text"; 50 | @import "addons/html5-input-types"; 51 | @import "addons/position"; 52 | @import "addons/prefixer"; 53 | @import "addons/retina-image"; 54 | @import "addons/size"; 55 | @import "addons/timing-functions"; 56 | @import "addons/triangle"; 57 | 58 | // Soon to be deprecated Mixins 59 | @import "bourbon-deprecated-upcoming"; 60 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_button.scss: -------------------------------------------------------------------------------- 1 | @mixin button ($style: simple, $base-color: #4294f0) { 2 | 3 | @if type-of($style) == color { 4 | $base-color: $style; 5 | $style: simple; 6 | } 7 | 8 | // Grayscale button 9 | @if $base-color == grayscale($base-color) { 10 | @if $style == simple { 11 | @include simple($base-color, $grayscale: true); 12 | } 13 | 14 | @else if $style == shiny { 15 | @include shiny($base-color, $grayscale: true); 16 | } 17 | 18 | @else if $style == pill { 19 | @include pill($base-color, $grayscale: true); 20 | } 21 | } 22 | 23 | // Colored button 24 | @else { 25 | @if $style == simple { 26 | @include simple($base-color); 27 | } 28 | 29 | @else if $style == shiny { 30 | @include shiny($base-color); 31 | } 32 | 33 | @else if $style == pill { 34 | @include pill($base-color); 35 | } 36 | } 37 | 38 | &:disabled { 39 | opacity: 0.5; 40 | cursor: not-allowed; 41 | } 42 | } 43 | 44 | 45 | // Simple Button 46 | //************************************************************************// 47 | @mixin simple($base-color, $grayscale: false) { 48 | $color: hsl(0, 0, 100%); 49 | $border: adjust-color($base-color, $saturation: 9%, $lightness: -14%); 50 | $inset-shadow: adjust-color($base-color, $saturation: -8%, $lightness: 15%); 51 | $stop-gradient: adjust-color($base-color, $saturation: 9%, $lightness: -11%); 52 | $text-shadow: adjust-color($base-color, $saturation: 15%, $lightness: -18%); 53 | 54 | @if lightness($base-color) > 70% { 55 | $color: hsl(0, 0, 20%); 56 | $text-shadow: adjust-color($base-color, $saturation: 10%, $lightness: 4%); 57 | } 58 | 59 | @if $grayscale == true { 60 | $border: grayscale($border); 61 | $inset-shadow: grayscale($inset-shadow); 62 | $stop-gradient: grayscale($stop-gradient); 63 | $text-shadow: grayscale($text-shadow); 64 | } 65 | 66 | border: 1px solid $border; 67 | border-radius: 3px; 68 | box-shadow: inset 0 1px 0 0 $inset-shadow; 69 | color: $color; 70 | display: inline-block; 71 | font-size: 11px; 72 | font-weight: bold; 73 | @include linear-gradient ($base-color, $stop-gradient); 74 | padding: 7px 18px; 75 | text-decoration: none; 76 | text-shadow: 0 1px 0 $text-shadow; 77 | background-clip: padding-box; 78 | 79 | &:hover:not(:disabled) { 80 | $base-color-hover: adjust-color($base-color, $saturation: -4%, $lightness: -5%); 81 | $inset-shadow-hover: adjust-color($base-color, $saturation: -7%, $lightness: 5%); 82 | $stop-gradient-hover: adjust-color($base-color, $saturation: 8%, $lightness: -14%); 83 | 84 | @if $grayscale == true { 85 | $base-color-hover: grayscale($base-color-hover); 86 | $inset-shadow-hover: grayscale($inset-shadow-hover); 87 | $stop-gradient-hover: grayscale($stop-gradient-hover); 88 | } 89 | 90 | box-shadow: inset 0 1px 0 0 $inset-shadow-hover; 91 | cursor: pointer; 92 | @include linear-gradient ($base-color-hover, $stop-gradient-hover); 93 | } 94 | 95 | &:active:not(:disabled) { 96 | $border-active: adjust-color($base-color, $saturation: 9%, $lightness: -14%); 97 | $inset-shadow-active: adjust-color($base-color, $saturation: 7%, $lightness: -17%); 98 | 99 | @if $grayscale == true { 100 | $border-active: grayscale($border-active); 101 | $inset-shadow-active: grayscale($inset-shadow-active); 102 | } 103 | 104 | border: 1px solid $border-active; 105 | box-shadow: inset 0 0 8px 4px $inset-shadow-active, inset 0 0 8px 4px $inset-shadow-active, 0 1px 1px 0 #eee; 106 | } 107 | } 108 | 109 | 110 | // Shiny Button 111 | //************************************************************************// 112 | @mixin shiny($base-color, $grayscale: false) { 113 | $color: hsl(0, 0, 100%); 114 | $border: adjust-color($base-color, $red: -117, $green: -111, $blue: -81); 115 | $border-bottom: adjust-color($base-color, $red: -126, $green: -127, $blue: -122); 116 | $fourth-stop: adjust-color($base-color, $red: -79, $green: -70, $blue: -46); 117 | $inset-shadow: adjust-color($base-color, $red: 37, $green: 29, $blue: 12); 118 | $second-stop: adjust-color($base-color, $red: -56, $green: -50, $blue: -33); 119 | $text-shadow: adjust-color($base-color, $red: -140, $green: -141, $blue: -114); 120 | $third-stop: adjust-color($base-color, $red: -86, $green: -75, $blue: -48); 121 | 122 | @if lightness($base-color) > 70% { 123 | $color: hsl(0, 0, 20%); 124 | $text-shadow: adjust-color($base-color, $saturation: 10%, $lightness: 4%); 125 | } 126 | 127 | @if $grayscale == true { 128 | $border: grayscale($border); 129 | $border-bottom: grayscale($border-bottom); 130 | $fourth-stop: grayscale($fourth-stop); 131 | $inset-shadow: grayscale($inset-shadow); 132 | $second-stop: grayscale($second-stop); 133 | $text-shadow: grayscale($text-shadow); 134 | $third-stop: grayscale($third-stop); 135 | } 136 | 137 | border: 1px solid $border; 138 | border-bottom: 1px solid $border-bottom; 139 | border-radius: 5px; 140 | box-shadow: inset 0 1px 0 0 $inset-shadow; 141 | color: $color; 142 | display: inline-block; 143 | font-size: 14px; 144 | font-weight: bold; 145 | @include linear-gradient(top, $base-color 0%, $second-stop 50%, $third-stop 50%, $fourth-stop 100%); 146 | padding: 8px 20px; 147 | text-align: center; 148 | text-decoration: none; 149 | text-shadow: 0 -1px 1px $text-shadow; 150 | 151 | &:hover:not(:disabled) { 152 | $first-stop-hover: adjust-color($base-color, $red: -13, $green: -15, $blue: -18); 153 | $second-stop-hover: adjust-color($base-color, $red: -66, $green: -62, $blue: -51); 154 | $third-stop-hover: adjust-color($base-color, $red: -93, $green: -85, $blue: -66); 155 | $fourth-stop-hover: adjust-color($base-color, $red: -86, $green: -80, $blue: -63); 156 | 157 | @if $grayscale == true { 158 | $first-stop-hover: grayscale($first-stop-hover); 159 | $second-stop-hover: grayscale($second-stop-hover); 160 | $third-stop-hover: grayscale($third-stop-hover); 161 | $fourth-stop-hover: grayscale($fourth-stop-hover); 162 | } 163 | 164 | cursor: pointer; 165 | @include linear-gradient(top, $first-stop-hover 0%, 166 | $second-stop-hover 50%, 167 | $third-stop-hover 50%, 168 | $fourth-stop-hover 100%); 169 | } 170 | 171 | &:active:not(:disabled) { 172 | $inset-shadow-active: adjust-color($base-color, $red: -111, $green: -116, $blue: -122); 173 | 174 | @if $grayscale == true { 175 | $inset-shadow-active: grayscale($inset-shadow-active); 176 | } 177 | 178 | box-shadow: inset 0 0 20px 0 $inset-shadow-active, 0 1px 0 #fff; 179 | } 180 | } 181 | 182 | 183 | // Pill Button 184 | //************************************************************************// 185 | @mixin pill($base-color, $grayscale: false) { 186 | $color: hsl(0, 0, 100%); 187 | $border-bottom: adjust-color($base-color, $hue: 8, $saturation: -11%, $lightness: -26%); 188 | $border-sides: adjust-color($base-color, $hue: 4, $saturation: -21%, $lightness: -21%); 189 | $border-top: adjust-color($base-color, $hue: -1, $saturation: -30%, $lightness: -15%); 190 | $inset-shadow: adjust-color($base-color, $hue: -1, $saturation: -1%, $lightness: 7%); 191 | $stop-gradient: adjust-color($base-color, $hue: 8, $saturation: 14%, $lightness: -10%); 192 | $text-shadow: adjust-color($base-color, $hue: 5, $saturation: -19%, $lightness: -15%); 193 | 194 | @if lightness($base-color) > 70% { 195 | $color: hsl(0, 0, 20%); 196 | $text-shadow: adjust-color($base-color, $saturation: 10%, $lightness: 4%); 197 | } 198 | 199 | @if $grayscale == true { 200 | $border-bottom: grayscale($border-bottom); 201 | $border-sides: grayscale($border-sides); 202 | $border-top: grayscale($border-top); 203 | $inset-shadow: grayscale($inset-shadow); 204 | $stop-gradient: grayscale($stop-gradient); 205 | $text-shadow: grayscale($text-shadow); 206 | } 207 | 208 | border: 1px solid $border-top; 209 | border-color: $border-top $border-sides $border-bottom; 210 | border-radius: 16px; 211 | box-shadow: inset 0 1px 0 0 $inset-shadow, 0 1px 2px 0 #b3b3b3; 212 | color: $color; 213 | display: inline-block; 214 | font-size: 11px; 215 | font-weight: normal; 216 | line-height: 1; 217 | @include linear-gradient ($base-color, $stop-gradient); 218 | padding: 5px 16px; 219 | text-align: center; 220 | text-decoration: none; 221 | text-shadow: 0 -1px 1px $text-shadow; 222 | background-clip: padding-box; 223 | 224 | &:hover:not(:disabled) { 225 | $base-color-hover: adjust-color($base-color, $lightness: -4.5%); 226 | $border-bottom: adjust-color($base-color, $hue: 8, $saturation: 13.5%, $lightness: -32%); 227 | $border-sides: adjust-color($base-color, $hue: 4, $saturation: -2%, $lightness: -27%); 228 | $border-top: adjust-color($base-color, $hue: -1, $saturation: -17%, $lightness: -21%); 229 | $inset-shadow-hover: adjust-color($base-color, $saturation: -1%, $lightness: 3%); 230 | $stop-gradient-hover: adjust-color($base-color, $hue: 8, $saturation: -4%, $lightness: -15.5%); 231 | $text-shadow-hover: adjust-color($base-color, $hue: 5, $saturation: -5%, $lightness: -22%); 232 | 233 | @if $grayscale == true { 234 | $base-color-hover: grayscale($base-color-hover); 235 | $border-bottom: grayscale($border-bottom); 236 | $border-sides: grayscale($border-sides); 237 | $border-top: grayscale($border-top); 238 | $inset-shadow-hover: grayscale($inset-shadow-hover); 239 | $stop-gradient-hover: grayscale($stop-gradient-hover); 240 | $text-shadow-hover: grayscale($text-shadow-hover); 241 | } 242 | 243 | border: 1px solid $border-top; 244 | border-color: $border-top $border-sides $border-bottom; 245 | box-shadow: inset 0 1px 0 0 $inset-shadow-hover; 246 | cursor: pointer; 247 | @include linear-gradient ($base-color-hover, $stop-gradient-hover); 248 | text-shadow: 0 -1px 1px $text-shadow-hover; 249 | background-clip: padding-box; 250 | } 251 | 252 | &:active:not(:disabled) { 253 | $active-color: adjust-color($base-color, $hue: 4, $saturation: -12%, $lightness: -10%); 254 | $border-active: adjust-color($base-color, $hue: 6, $saturation: -2.5%, $lightness: -30%); 255 | $border-bottom-active: adjust-color($base-color, $hue: 11, $saturation: 6%, $lightness: -31%); 256 | $inset-shadow-active: adjust-color($base-color, $hue: 9, $saturation: 2%, $lightness: -21.5%); 257 | $text-shadow-active: adjust-color($base-color, $hue: 5, $saturation: -12%, $lightness: -21.5%); 258 | 259 | @if $grayscale == true { 260 | $active-color: grayscale($active-color); 261 | $border-active: grayscale($border-active); 262 | $border-bottom-active: grayscale($border-bottom-active); 263 | $inset-shadow-active: grayscale($inset-shadow-active); 264 | $text-shadow-active: grayscale($text-shadow-active); 265 | } 266 | 267 | background: $active-color; 268 | border: 1px solid $border-active; 269 | border-bottom: 1px solid $border-bottom-active; 270 | box-shadow: inset 0 0 6px 3px $inset-shadow-active, 0 1px 0 0 #fff; 271 | text-shadow: 0 -1px 1px $text-shadow-active; 272 | } 273 | } 274 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_clearfix.scss: -------------------------------------------------------------------------------- 1 | // Micro clearfix provides an easy way to contain floats without adding additional markup 2 | // 3 | // Example usage: 4 | // 5 | // // Contain all floats within .wrapper 6 | // .wrapper { 7 | // @include clearfix; 8 | // .content, 9 | // .sidebar { 10 | // float : left; 11 | // } 12 | // } 13 | 14 | @mixin clearfix { 15 | *zoom: 1; 16 | 17 | &:before, 18 | &:after { 19 | content: " "; 20 | display: table; 21 | } 22 | 23 | &:after { 24 | clear: both; 25 | } 26 | } 27 | 28 | // Acknowledgements 29 | // Micro clearfix: [Nicolas Gallagher](http://nicolasgallagher.com/micro-clearfix-hack/) 30 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_font-family.scss: -------------------------------------------------------------------------------- 1 | $georgia: Georgia, Cambria, "Times New Roman", Times, serif; 2 | $helvetica: "Helvetica Neue", Helvetica, Arial, sans-serif; 3 | $lucida-grande: "Lucida Grande", Tahoma, Verdana, Arial, sans-serif; 4 | $monospace: "Bitstream Vera Sans Mono", Consolas, Courier, monospace; 5 | $verdana: Verdana, Geneva, sans-serif; 6 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_hide-text.scss: -------------------------------------------------------------------------------- 1 | @mixin hide-text { 2 | color: transparent; 3 | font: 0/0 a; 4 | text-shadow: none; 5 | } 6 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_html5-input-types.scss: -------------------------------------------------------------------------------- 1 | //************************************************************************// 2 | // Generate a variable ($all-text-inputs) with a list of all html5 3 | // input types that have a text-based input, excluding textarea. 4 | // http://diveintohtml5.org/forms.html 5 | //************************************************************************// 6 | $inputs-list: 'input[type="email"]', 7 | 'input[type="number"]', 8 | 'input[type="password"]', 9 | 'input[type="search"]', 10 | 'input[type="tel"]', 11 | 'input[type="text"]', 12 | 'input[type="url"]', 13 | 14 | // Webkit & Gecko may change the display of these in the future 15 | 'input[type="color"]', 16 | 'input[type="date"]', 17 | 'input[type="datetime"]', 18 | 'input[type="datetime-local"]', 19 | 'input[type="month"]', 20 | 'input[type="time"]', 21 | 'input[type="week"]'; 22 | 23 | $unquoted-inputs-list: (); 24 | @each $input-type in $inputs-list { 25 | $unquoted-inputs-list: append($unquoted-inputs-list, unquote($input-type), comma); 26 | } 27 | 28 | $all-text-inputs: $unquoted-inputs-list; 29 | 30 | 31 | // Hover Pseudo-class 32 | //************************************************************************// 33 | $all-text-inputs-hover: (); 34 | @each $input-type in $unquoted-inputs-list { 35 | $input-type-hover: $input-type + ":hover"; 36 | $all-text-inputs-hover: append($all-text-inputs-hover, $input-type-hover, comma); 37 | } 38 | 39 | // Focus Pseudo-class 40 | //************************************************************************// 41 | $all-text-inputs-focus: (); 42 | @each $input-type in $unquoted-inputs-list { 43 | $input-type-focus: $input-type + ":focus"; 44 | $all-text-inputs-focus: append($all-text-inputs-focus, $input-type-focus, comma); 45 | } 46 | 47 | // You must use interpolation on the variable: 48 | // #{$all-text-inputs} 49 | // #{$all-text-inputs-hover} 50 | // #{$all-text-inputs-focus} 51 | 52 | // Example 53 | //************************************************************************// 54 | // #{$all-text-inputs}, textarea { 55 | // border: 1px solid red; 56 | // } 57 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_position.scss: -------------------------------------------------------------------------------- 1 | @mixin position ($position: relative, $coordinates: 0 0 0 0) { 2 | 3 | @if type-of($position) == list { 4 | $coordinates: $position; 5 | $position: relative; 6 | } 7 | 8 | $top: nth($coordinates, 1); 9 | $right: nth($coordinates, 2); 10 | $bottom: nth($coordinates, 3); 11 | $left: nth($coordinates, 4); 12 | 13 | position: $position; 14 | 15 | @if $top == auto { 16 | top: $top; 17 | } 18 | @else if not(unitless($top)) { 19 | top: $top; 20 | } 21 | 22 | @if $right == auto { 23 | right: $right; 24 | } 25 | @else if not(unitless($right)) { 26 | right: $right; 27 | } 28 | 29 | @if $bottom == auto { 30 | bottom: $bottom; 31 | } 32 | @else if not(unitless($bottom)) { 33 | bottom: $bottom; 34 | } 35 | 36 | @if $left == auto { 37 | left: $left; 38 | } 39 | @else if not(unitless($left)) { 40 | left: $left; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_prefixer.scss: -------------------------------------------------------------------------------- 1 | //************************************************************************// 2 | // Example: @include prefixer(border-radius, $radii, webkit ms spec); 3 | //************************************************************************// 4 | $prefix-for-webkit: true !default; 5 | $prefix-for-mozilla: true !default; 6 | $prefix-for-microsoft: true !default; 7 | $prefix-for-opera: true !default; 8 | $prefix-for-spec: true !default; // required for keyframe mixin 9 | 10 | @mixin prefixer ($property, $value, $prefixes) { 11 | @each $prefix in $prefixes { 12 | @if $prefix == webkit { 13 | @if $prefix-for-webkit { 14 | -webkit-#{$property}: $value; 15 | } 16 | } 17 | @else if $prefix == moz { 18 | @if $prefix-for-mozilla { 19 | -moz-#{$property}: $value; 20 | } 21 | } 22 | @else if $prefix == ms { 23 | @if $prefix-for-microsoft { 24 | -ms-#{$property}: $value; 25 | } 26 | } 27 | @else if $prefix == o { 28 | @if $prefix-for-opera { 29 | -o-#{$property}: $value; 30 | } 31 | } 32 | @else if $prefix == spec { 33 | @if $prefix-for-spec { 34 | #{$property}: $value; 35 | } 36 | } 37 | @else { 38 | @warn "Unrecognized prefix: #{$prefix}"; 39 | } 40 | } 41 | } 42 | 43 | @mixin disable-prefix-for-all() { 44 | $prefix-for-webkit: false; 45 | $prefix-for-mozilla: false; 46 | $prefix-for-microsoft: false; 47 | $prefix-for-opera: false; 48 | $prefix-for-spec: false; 49 | } 50 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_retina-image.scss: -------------------------------------------------------------------------------- 1 | @mixin retina-image($filename, $background-size, $extension: png, $retina-filename: null, $asset-pipeline: false) { 2 | @if $asset-pipeline { 3 | background-image: image_url($filename + "." + $extension); 4 | } 5 | @else { 6 | background-image: url($filename + "." + $extension); 7 | } 8 | 9 | @include hidpi { 10 | 11 | @if $asset-pipeline { 12 | @if $retina-filename { 13 | background-image: image_url($retina-filename + "." + $extension); 14 | } 15 | @else { 16 | background-image: image_url($filename + "@2x" + "." + $extension); 17 | } 18 | } 19 | 20 | @else { 21 | @if $retina-filename { 22 | background-image: url($retina-filename + "." + $extension); 23 | } 24 | @else { 25 | background-image: url($filename + "@2x" + "." + $extension); 26 | } 27 | } 28 | 29 | background-size: $background-size; 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_size.scss: -------------------------------------------------------------------------------- 1 | @mixin size($size) { 2 | @if length($size) == 1 { 3 | @if $size == auto { 4 | width: $size; 5 | height: $size; 6 | } 7 | 8 | @else if unitless($size) { 9 | width: $size + px; 10 | height: $size + px; 11 | } 12 | 13 | @else if not(unitless($size)) { 14 | width: $size; 15 | height: $size; 16 | } 17 | } 18 | 19 | // Width x Height 20 | @if length($size) == 2 { 21 | $width: nth($size, 1); 22 | $height: nth($size, 2); 23 | 24 | @if $width == auto { 25 | width: $width; 26 | } 27 | @else if not(unitless($width)) { 28 | width: $width; 29 | } 30 | @else if unitless($width) { 31 | width: $width + px; 32 | } 33 | 34 | @if $height == auto { 35 | height: $height; 36 | } 37 | @else if not(unitless($height)) { 38 | height: $height; 39 | } 40 | @else if unitless($height) { 41 | height: $height + px; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_timing-functions.scss: -------------------------------------------------------------------------------- 1 | // CSS cubic-bezier timing functions. Timing functions courtesy of jquery.easie (github.com/jaukia/easie) 2 | // Timing functions are the same as demo'ed here: http://jqueryui.com/demos/effect/easing.html 3 | 4 | // EASE IN 5 | $ease-in-quad: cubic-bezier(0.550, 0.085, 0.680, 0.530); 6 | $ease-in-cubic: cubic-bezier(0.550, 0.055, 0.675, 0.190); 7 | $ease-in-quart: cubic-bezier(0.895, 0.030, 0.685, 0.220); 8 | $ease-in-quint: cubic-bezier(0.755, 0.050, 0.855, 0.060); 9 | $ease-in-sine: cubic-bezier(0.470, 0.000, 0.745, 0.715); 10 | $ease-in-expo: cubic-bezier(0.950, 0.050, 0.795, 0.035); 11 | $ease-in-circ: cubic-bezier(0.600, 0.040, 0.980, 0.335); 12 | $ease-in-back: cubic-bezier(0.600, -0.280, 0.735, 0.045); 13 | 14 | // EASE OUT 15 | $ease-out-quad: cubic-bezier(0.250, 0.460, 0.450, 0.940); 16 | $ease-out-cubic: cubic-bezier(0.215, 0.610, 0.355, 1.000); 17 | $ease-out-quart: cubic-bezier(0.165, 0.840, 0.440, 1.000); 18 | $ease-out-quint: cubic-bezier(0.230, 1.000, 0.320, 1.000); 19 | $ease-out-sine: cubic-bezier(0.390, 0.575, 0.565, 1.000); 20 | $ease-out-expo: cubic-bezier(0.190, 1.000, 0.220, 1.000); 21 | $ease-out-circ: cubic-bezier(0.075, 0.820, 0.165, 1.000); 22 | $ease-out-back: cubic-bezier(0.175, 0.885, 0.320, 1.275); 23 | 24 | // EASE IN OUT 25 | $ease-in-out-quad: cubic-bezier(0.455, 0.030, 0.515, 0.955); 26 | $ease-in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1.000); 27 | $ease-in-out-quart: cubic-bezier(0.770, 0.000, 0.175, 1.000); 28 | $ease-in-out-quint: cubic-bezier(0.860, 0.000, 0.070, 1.000); 29 | $ease-in-out-sine: cubic-bezier(0.445, 0.050, 0.550, 0.950); 30 | $ease-in-out-expo: cubic-bezier(1.000, 0.000, 0.000, 1.000); 31 | $ease-in-out-circ: cubic-bezier(0.785, 0.135, 0.150, 0.860); 32 | $ease-in-out-back: cubic-bezier(0.680, -0.550, 0.265, 1.550); 33 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_triangle.scss: -------------------------------------------------------------------------------- 1 | @mixin triangle ($size, $color, $direction) { 2 | height: 0; 3 | width: 0; 4 | 5 | @if ($direction == up) or ($direction == down) or ($direction == right) or ($direction == left) { 6 | border-color: transparent; 7 | border-style: solid; 8 | border-width: $size / 2; 9 | 10 | @if $direction == up { 11 | border-bottom-color: $color; 12 | 13 | } @else if $direction == right { 14 | border-left-color: $color; 15 | 16 | } @else if $direction == down { 17 | border-top-color: $color; 18 | 19 | } @else if $direction == left { 20 | border-right-color: $color; 21 | } 22 | } 23 | 24 | @else if ($direction == up-right) or ($direction == up-left) { 25 | border-top: $size solid $color; 26 | 27 | @if $direction == up-right { 28 | border-left: $size solid transparent; 29 | 30 | } @else if $direction == up-left { 31 | border-right: $size solid transparent; 32 | } 33 | } 34 | 35 | @else if ($direction == down-right) or ($direction == down-left) { 36 | border-bottom: $size solid $color; 37 | 38 | @if $direction == down-right { 39 | border-left: $size solid transparent; 40 | 41 | } @else if $direction == down-left { 42 | border-right: $size solid transparent; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_animation.scss: -------------------------------------------------------------------------------- 1 | // http://www.w3.org/TR/css3-animations/#the-animation-name-property- 2 | // Each of these mixins support comma separated lists of values, which allows different transitions for individual properties to be described in a single style rule. Each value in the list corresponds to the value at that same position in the other properties. 3 | 4 | // Official animation shorthand property. 5 | @mixin animation ($animations...) { 6 | @include prefixer(animation, $animations, webkit moz spec); 7 | } 8 | 9 | // Individual Animation Properties 10 | @mixin animation-name ($names...) { 11 | @include prefixer(animation-name, $names, webkit moz spec); 12 | } 13 | 14 | 15 | @mixin animation-duration ($times...) { 16 | @include prefixer(animation-duration, $times, webkit moz spec); 17 | } 18 | 19 | 20 | @mixin animation-timing-function ($motions...) { 21 | // ease | linear | ease-in | ease-out | ease-in-out 22 | @include prefixer(animation-timing-function, $motions, webkit moz spec); 23 | } 24 | 25 | 26 | @mixin animation-iteration-count ($values...) { 27 | // infinite | 28 | @include prefixer(animation-iteration-count, $values, webkit moz spec); 29 | } 30 | 31 | 32 | @mixin animation-direction ($directions...) { 33 | // normal | alternate 34 | @include prefixer(animation-direction, $directions, webkit moz spec); 35 | } 36 | 37 | 38 | @mixin animation-play-state ($states...) { 39 | // running | paused 40 | @include prefixer(animation-play-state, $states, webkit moz spec); 41 | } 42 | 43 | 44 | @mixin animation-delay ($times...) { 45 | @include prefixer(animation-delay, $times, webkit moz spec); 46 | } 47 | 48 | 49 | @mixin animation-fill-mode ($modes...) { 50 | // none | forwards | backwards | both 51 | @include prefixer(animation-fill-mode, $modes, webkit moz spec); 52 | } 53 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_appearance.scss: -------------------------------------------------------------------------------- 1 | @mixin appearance ($value) { 2 | @include prefixer(appearance, $value, webkit moz ms o spec); 3 | } 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_backface-visibility.scss: -------------------------------------------------------------------------------- 1 | //************************************************************************// 2 | // Backface-visibility mixin 3 | //************************************************************************// 4 | @mixin backface-visibility($visibility) { 5 | @include prefixer(backface-visibility, $visibility, webkit spec); 6 | } 7 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_background-image.scss: -------------------------------------------------------------------------------- 1 | //************************************************************************// 2 | // Background-image property for adding multiple background images with 3 | // gradients, or for stringing multiple gradients together. 4 | //************************************************************************// 5 | 6 | @mixin background-image($images...) { 7 | background-image: _add-prefix($images, webkit); 8 | background-image: _add-prefix($images); 9 | } 10 | 11 | @function _add-prefix($images, $vendor: false) { 12 | $images-prefixed: (); 13 | $gradient-positions: false; 14 | @for $i from 1 through length($images) { 15 | $type: type-of(nth($images, $i)); // Get type of variable - List or String 16 | 17 | // If variable is a list - Gradient 18 | @if $type == list { 19 | $gradient-type: nth(nth($images, $i), 1); // linear or radial 20 | $gradient-pos: null; 21 | $gradient-args: null; 22 | 23 | @if ($gradient-type == linear) or ($gradient-type == radial) { 24 | $gradient-pos: nth(nth($images, $i), 2); // Get gradient position 25 | $gradient-args: nth(nth($images, $i), 3); // Get actual gradient (red, blue) 26 | } 27 | @else { 28 | $gradient-args: nth(nth($images, $i), 2); // Get actual gradient (red, blue) 29 | } 30 | 31 | $gradient-positions: _gradient-positions-parser($gradient-type, $gradient-pos); 32 | $gradient: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor); 33 | $images-prefixed: append($images-prefixed, $gradient, comma); 34 | } 35 | // If variable is a string - Image 36 | @else if $type == string { 37 | $images-prefixed: join($images-prefixed, nth($images, $i), comma); 38 | } 39 | } 40 | @return $images-prefixed; 41 | } 42 | 43 | //Examples: 44 | //@include background-image(linear-gradient(top, orange, red)); 45 | //@include background-image(radial-gradient(50% 50%, cover circle, orange, red)); 46 | //@include background-image(url("/images/a.png"), linear-gradient(orange, red)); 47 | //@include background-image(url("image.png"), linear-gradient(orange, red), url("image.png")); 48 | //@include background-image(linear-gradient(hsla(0, 100%, 100%, 0.25) 0%, hsla(0, 100%, 100%, 0.08) 50%, transparent 50%), linear-gradient(orange, red)); 49 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_background.scss: -------------------------------------------------------------------------------- 1 | //************************************************************************// 2 | // Background property for adding multiple backgrounds using shorthand 3 | // notation. 4 | //************************************************************************// 5 | 6 | @mixin background( 7 | $background-1 , $background-2: false, 8 | $background-3: false, $background-4: false, 9 | $background-5: false, $background-6: false, 10 | $background-7: false, $background-8: false, 11 | $background-9: false, $background-10: false, 12 | $fallback: false 13 | ) { 14 | $backgrounds: compact($background-1, $background-2, 15 | $background-3, $background-4, 16 | $background-5, $background-6, 17 | $background-7, $background-8, 18 | $background-9, $background-10); 19 | 20 | $fallback-color: false; 21 | @if (type-of($fallback) == color) or ($fallback == "transparent") { 22 | $fallback-color: $fallback; 23 | } 24 | @else { 25 | $fallback-color: _extract-background-color($backgrounds); 26 | } 27 | 28 | @if $fallback-color { 29 | background-color: $fallback-color; 30 | } 31 | background: _background-add-prefix($backgrounds, webkit); 32 | background: _background-add-prefix($backgrounds); 33 | } 34 | 35 | @function _extract-background-color($backgrounds) { 36 | $final-bg-layer: nth($backgrounds, length($backgrounds)); 37 | @if type-of($final-bg-layer) == list { 38 | @for $i from 1 through length($final-bg-layer) { 39 | $value: nth($final-bg-layer, $i); 40 | @if type-of($value) == color { 41 | @return $value; 42 | } 43 | } 44 | } 45 | @return false; 46 | } 47 | 48 | @function _background-add-prefix($backgrounds, $vendor: false) { 49 | $backgrounds-prefixed: (); 50 | 51 | @for $i from 1 through length($backgrounds) { 52 | $shorthand: nth($backgrounds, $i); // Get member for current index 53 | $type: type-of($shorthand); // Get type of variable - List (gradient) or String (image) 54 | 55 | // If shorthand is a list (gradient) 56 | @if $type == list { 57 | $first-member: nth($shorthand, 1); // Get first member of shorthand 58 | 59 | // Linear Gradient 60 | @if index(linear radial, nth($first-member, 1)) { 61 | $gradient-type: nth($first-member, 1); // linear || radial 62 | $gradient-args: false; 63 | $gradient-positions: false; 64 | $shorthand-start: false; 65 | @if type-of($first-member) == list { // Linear gradient plus additional shorthand values - lg(red,orange)repeat,... 66 | $gradient-positions: nth($first-member, 2); 67 | $gradient-args: nth($first-member, 3); 68 | $shorthand-start: 2; 69 | } 70 | @else { // Linear gradient only - lg(red,orange),... 71 | $gradient-positions: nth($shorthand, 2); 72 | $gradient-args: nth($shorthand, 3); // Get gradient (red, blue) 73 | } 74 | 75 | $gradient-positions: _gradient-positions-parser($gradient-type, $gradient-positions); 76 | $gradient: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor); 77 | 78 | // Append any additional shorthand args to gradient 79 | @if $shorthand-start { 80 | @for $j from $shorthand-start through length($shorthand) { 81 | $gradient: join($gradient, nth($shorthand, $j), space); 82 | } 83 | } 84 | $backgrounds-prefixed: append($backgrounds-prefixed, $gradient, comma); 85 | } 86 | // Image with additional properties 87 | @else { 88 | $backgrounds-prefixed: append($backgrounds-prefixed, $shorthand, comma); 89 | } 90 | } 91 | // If shorthand is a simple string (color or image) 92 | @else if $type == string { 93 | $backgrounds-prefixed: join($backgrounds-prefixed, $shorthand, comma); 94 | } 95 | } 96 | @return $backgrounds-prefixed; 97 | } 98 | 99 | //Examples: 100 | //@include background(linear-gradient(top, orange, red)); 101 | //@include background(radial-gradient(circle at 40% 40%, orange, red)); 102 | //@include background(url("/images/a.png") no-repeat, linear-gradient(orange, red)); 103 | //@include background(url("image.png") center center, linear-gradient(orange, red), url("image.png")); 104 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_border-image.scss: -------------------------------------------------------------------------------- 1 | @mixin border-image($images) { 2 | -webkit-border-image: _border-add-prefix($images, webkit); 3 | -moz-border-image: _border-add-prefix($images, moz); 4 | -o-border-image: _border-add-prefix($images, o); 5 | border-image: _border-add-prefix($images); 6 | } 7 | 8 | @function _border-add-prefix($images, $vendor: false) { 9 | $border-image: null; 10 | $images-type: type-of(nth($images, 1)); 11 | $first-var: nth(nth($images, 1), 1); // Get type of Gradient (Linear || radial) 12 | 13 | // If input is a gradient 14 | @if $images-type == string { 15 | @if ($first-var == "linear") or ($first-var == "radial") { 16 | $gradient-type: nth($images, 1); // Get type of gradient (linear || radial) 17 | $gradient-pos: nth($images, 2); // Get gradient position 18 | $gradient-args: nth($images, 3); // Get actual gradient (red, blue) 19 | $gradient-positions: _gradient-positions-parser($gradient-type, $gradient-pos); 20 | $border-image: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor); 21 | } 22 | // If input is a URL 23 | @else { 24 | $border-image: $images; 25 | } 26 | } 27 | // If input is gradient or url + additional args 28 | @else if $images-type == list { 29 | $type: type-of(nth($images, 1)); // Get type of variable - List or String 30 | 31 | // If variable is a list - Gradient 32 | @if $type == list { 33 | $gradient: nth($images, 1); 34 | $gradient-type: nth($gradient, 1); // Get type of gradient (linear || radial) 35 | $gradient-pos: nth($gradient, 2); // Get gradient position 36 | $gradient-args: nth($gradient, 3); // Get actual gradient (red, blue) 37 | $gradient-positions: _gradient-positions-parser($gradient-type, $gradient-pos); 38 | $border-image: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor); 39 | 40 | @for $i from 2 through length($images) { 41 | $border-image: append($border-image, nth($images, $i)); 42 | } 43 | } 44 | } 45 | @return $border-image; 46 | } 47 | 48 | //Examples: 49 | // @include border-image(url("image.png")); 50 | // @include border-image(url("image.png") 20 stretch); 51 | // @include border-image(linear-gradient(45deg, orange, yellow)); 52 | // @include border-image(linear-gradient(45deg, orange, yellow) stretch); 53 | // @include border-image(linear-gradient(45deg, orange, yellow) 20 30 40 50 stretch round); 54 | // @include border-image(radial-gradient(top, cover, orange, yellow, orange)); 55 | 56 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_border-radius.scss: -------------------------------------------------------------------------------- 1 | //************************************************************************// 2 | // Shorthand Border-radius mixins 3 | //************************************************************************// 4 | @mixin border-top-radius($radii) { 5 | @include prefixer(border-top-left-radius, $radii, spec); 6 | @include prefixer(border-top-right-radius, $radii, spec); 7 | } 8 | 9 | @mixin border-bottom-radius($radii) { 10 | @include prefixer(border-bottom-left-radius, $radii, spec); 11 | @include prefixer(border-bottom-right-radius, $radii, spec); 12 | } 13 | 14 | @mixin border-left-radius($radii) { 15 | @include prefixer(border-top-left-radius, $radii, spec); 16 | @include prefixer(border-bottom-left-radius, $radii, spec); 17 | } 18 | 19 | @mixin border-right-radius($radii) { 20 | @include prefixer(border-top-right-radius, $radii, spec); 21 | @include prefixer(border-bottom-right-radius, $radii, spec); 22 | } 23 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_box-sizing.scss: -------------------------------------------------------------------------------- 1 | @mixin box-sizing ($box) { 2 | // content-box | border-box | inherit 3 | @include prefixer(box-sizing, $box, webkit moz spec); 4 | } 5 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_columns.scss: -------------------------------------------------------------------------------- 1 | @mixin columns($arg: auto) { 2 | // || 3 | @include prefixer(columns, $arg, webkit moz spec); 4 | } 5 | 6 | @mixin column-count($int: auto) { 7 | // auto || integer 8 | @include prefixer(column-count, $int, webkit moz spec); 9 | } 10 | 11 | @mixin column-gap($length: normal) { 12 | // normal || length 13 | @include prefixer(column-gap, $length, webkit moz spec); 14 | } 15 | 16 | @mixin column-fill($arg: auto) { 17 | // auto || length 18 | @include prefixer(columns-fill, $arg, webkit moz spec); 19 | } 20 | 21 | @mixin column-rule($arg) { 22 | // || || 23 | @include prefixer(column-rule, $arg, webkit moz spec); 24 | } 25 | 26 | @mixin column-rule-color($color) { 27 | @include prefixer(column-rule-color, $color, webkit moz spec); 28 | } 29 | 30 | @mixin column-rule-style($style: none) { 31 | // none | hidden | dashed | dotted | double | groove | inset | inset | outset | ridge | solid 32 | @include prefixer(column-rule-style, $style, webkit moz spec); 33 | } 34 | 35 | @mixin column-rule-width ($width: none) { 36 | @include prefixer(column-rule-width, $width, webkit moz spec); 37 | } 38 | 39 | @mixin column-span($arg: none) { 40 | // none || all 41 | @include prefixer(column-span, $arg, webkit moz spec); 42 | } 43 | 44 | @mixin column-width($length: auto) { 45 | // auto || length 46 | @include prefixer(column-width, $length, webkit moz spec); 47 | } 48 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_flex-box.scss: -------------------------------------------------------------------------------- 1 | // CSS3 Flexible Box Model and property defaults 2 | 3 | // Custom shorthand notation for flexbox 4 | @mixin box($orient: inline-axis, $pack: start, $align: stretch) { 5 | @include display-box; 6 | @include box-orient($orient); 7 | @include box-pack($pack); 8 | @include box-align($align); 9 | } 10 | 11 | @mixin display-box { 12 | display: -webkit-box; 13 | display: -moz-box; 14 | display: box; 15 | } 16 | 17 | @mixin box-orient($orient: inline-axis) { 18 | // horizontal|vertical|inline-axis|block-axis|inherit 19 | @include prefixer(box-orient, $orient, webkit moz spec); 20 | } 21 | 22 | @mixin box-pack($pack: start) { 23 | // start|end|center|justify 24 | @include prefixer(box-pack, $pack, webkit moz spec); 25 | } 26 | 27 | @mixin box-align($align: stretch) { 28 | // start|end|center|baseline|stretch 29 | @include prefixer(box-align, $align, webkit moz spec); 30 | } 31 | 32 | @mixin box-direction($direction: normal) { 33 | // normal|reverse|inherit 34 | @include prefixer(box-direction, $direction, webkit moz spec); 35 | } 36 | 37 | @mixin box-lines($lines: single) { 38 | // single|multiple 39 | @include prefixer(box-lines, $lines, webkit moz spec); 40 | } 41 | 42 | @mixin box-ordinal-group($int: 1) { 43 | @include prefixer(box-ordinal-group, $int, webkit moz spec); 44 | } 45 | 46 | @mixin box-flex($value: 0.0) { 47 | @include prefixer(box-flex, $value, webkit moz spec); 48 | } 49 | 50 | @mixin box-flex-group($int: 1) { 51 | @include prefixer(box-flex-group, $int, webkit moz spec); 52 | } 53 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_font-face.scss: -------------------------------------------------------------------------------- 1 | // Order of the includes matters, and it is: normal, bold, italic, bold+italic. 2 | 3 | @mixin font-face($font-family, $file-path, $weight: normal, $style: normal, $asset-pipeline: false ) { 4 | @font-face { 5 | font-family: $font-family; 6 | font-weight: $weight; 7 | font-style: $style; 8 | 9 | @if $asset-pipeline == true { 10 | src: font-url('#{$file-path}.eot'); 11 | src: font-url('#{$file-path}.eot?#iefix') format('embedded-opentype'), 12 | font-url('#{$file-path}.woff') format('woff'), 13 | font-url('#{$file-path}.ttf') format('truetype'), 14 | font-url('#{$file-path}.svg##{$font-family}') format('svg'); 15 | } @else { 16 | src: url('#{$file-path}.eot'); 17 | src: url('#{$file-path}.eot?#iefix') format('embedded-opentype'), 18 | url('#{$file-path}.woff') format('woff'), 19 | url('#{$file-path}.ttf') format('truetype'), 20 | url('#{$file-path}.svg##{$font-family}') format('svg'); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_hidpi-media-query.scss: -------------------------------------------------------------------------------- 1 | // HiDPI mixin. Default value set to 1.3 to target Google Nexus 7 (http://bjango.com/articles/min-device-pixel-ratio/) 2 | @mixin hidpi($ratio: 1.3) { 3 | @media only screen and (-webkit-min-device-pixel-ratio: $ratio), 4 | only screen and (min--moz-device-pixel-ratio: $ratio), 5 | only screen and (-o-min-device-pixel-ratio: #{$ratio}/1), 6 | only screen and (min-resolution: #{round($ratio*96)}dpi), 7 | only screen and (min-resolution: #{$ratio}dppx) { 8 | @content; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_image-rendering.scss: -------------------------------------------------------------------------------- 1 | @mixin image-rendering ($mode:optimizeQuality) { 2 | 3 | @if ($mode == optimize-contrast) { 4 | image-rendering: -moz-crisp-edges; 5 | image-rendering: -o-crisp-edges; 6 | image-rendering: -webkit-optimize-contrast; 7 | image-rendering: optimize-contrast; 8 | } 9 | 10 | @else { 11 | image-rendering: $mode; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_inline-block.scss: -------------------------------------------------------------------------------- 1 | // Legacy support for inline-block in IE7 (maybe IE6) 2 | @mixin inline-block { 3 | display: inline-block; 4 | vertical-align: baseline; 5 | zoom: 1; 6 | *display: inline; 7 | *vertical-align: auto; 8 | } 9 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_keyframes.scss: -------------------------------------------------------------------------------- 1 | // Adds keyframes blocks for supported prefixes, removing redundant prefixes in the block's content 2 | @mixin keyframes($name) { 3 | $original-prefix-for-webkit: $prefix-for-webkit; 4 | $original-prefix-for-mozilla: $prefix-for-mozilla; 5 | $original-prefix-for-microsoft: $prefix-for-microsoft; 6 | $original-prefix-for-opera: $prefix-for-opera; 7 | $original-prefix-for-spec: $prefix-for-spec; 8 | 9 | @if $original-prefix-for-webkit { 10 | @include disable-prefix-for-all(); 11 | $prefix-for-webkit: true; 12 | @-webkit-keyframes #{$name} { 13 | @content; 14 | } 15 | } 16 | @if $original-prefix-for-mozilla { 17 | @include disable-prefix-for-all(); 18 | $prefix-for-mozilla: true; 19 | @-moz-keyframes #{$name} { 20 | @content; 21 | } 22 | } 23 | @if $original-prefix-for-opera { 24 | @include disable-prefix-for-all(); 25 | $prefix-for-opera: true; 26 | @-o-keyframes #{$name} { 27 | @content; 28 | } 29 | } 30 | @if $original-prefix-for-spec { 31 | @include disable-prefix-for-all(); 32 | $prefix-for-spec: true; 33 | @keyframes #{$name} { 34 | @content; 35 | } 36 | } 37 | 38 | $prefix-for-webkit: $original-prefix-for-webkit; 39 | $prefix-for-mozilla: $original-prefix-for-mozilla; 40 | $prefix-for-microsoft: $original-prefix-for-microsoft; 41 | $prefix-for-opera: $original-prefix-for-opera; 42 | $prefix-for-spec: $original-prefix-for-spec; 43 | } 44 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_linear-gradient.scss: -------------------------------------------------------------------------------- 1 | @mixin linear-gradient($pos, $G1, $G2: false, 2 | $G3: false, $G4: false, 3 | $G5: false, $G6: false, 4 | $G7: false, $G8: false, 5 | $G9: false, $G10: false, 6 | $deprecated-pos1: left top, 7 | $deprecated-pos2: left bottom, 8 | $fallback: false) { 9 | // Detect what type of value exists in $pos 10 | $pos-type: type-of(nth($pos, 1)); 11 | $pos-spec: null; 12 | $pos-degree: null; 13 | 14 | // If $pos is missing from mixin, reassign vars and add default position 15 | @if ($pos-type == color) or (nth($pos, 1) == "transparent") { 16 | $G10: $G9; $G9: $G8; $G8: $G7; $G7: $G6; $G6: $G5; 17 | $G5: $G4; $G4: $G3; $G3: $G2; $G2: $G1; $G1: $pos; 18 | $pos: null; 19 | } 20 | 21 | @if $pos { 22 | $positions: _linear-positions-parser($pos); 23 | $pos-degree: nth($positions, 1); 24 | $pos-spec: nth($positions, 2); 25 | } 26 | 27 | $full: compact($G1, $G2, $G3, $G4, $G5, $G6, $G7, $G8, $G9, $G10); 28 | 29 | // Set $G1 as the default fallback color 30 | $fallback-color: nth($G1, 1); 31 | 32 | // If $fallback is a color use that color as the fallback color 33 | @if (type-of($fallback) == color) or ($fallback == "transparent") { 34 | $fallback-color: $fallback; 35 | } 36 | 37 | background-color: $fallback-color; 38 | background-image: _deprecated-webkit-gradient(linear, $deprecated-pos1, $deprecated-pos2, $full); // Safari <= 5.0 39 | background-image: -webkit-linear-gradient($pos-degree $full); // Safari 5.1+, Chrome 40 | background-image: unquote("linear-gradient(#{$pos-spec}#{$full})"); 41 | } 42 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_perspective.scss: -------------------------------------------------------------------------------- 1 | @mixin perspective($depth: none) { 2 | // none | 3 | @include prefixer(perspective, $depth, webkit moz spec); 4 | } 5 | 6 | @mixin perspective-origin($value: 50% 50%) { 7 | @include prefixer(perspective-origin, $value, webkit moz spec); 8 | } 9 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_placeholder.scss: -------------------------------------------------------------------------------- 1 | $placeholders: '-webkit-input-placeholder', 2 | '-moz-placeholder', 3 | '-ms-input-placeholder'; 4 | 5 | @mixin placeholder { 6 | @each $placeholder in $placeholders { 7 | @if $placeholder == "-webkit-input-placeholder" { 8 | &::#{$placeholder} { 9 | @content; 10 | } 11 | } 12 | @else if $placeholder == "-moz-placeholder" { 13 | // FF 18- 14 | &:#{$placeholder} { 15 | @content; 16 | } 17 | 18 | // FF 19+ 19 | &::#{$placeholder} { 20 | @content; 21 | } 22 | } 23 | @else { 24 | &:#{$placeholder} { 25 | @content; 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_radial-gradient.scss: -------------------------------------------------------------------------------- 1 | // Requires Sass 3.1+ 2 | @mixin radial-gradient($G1, $G2, 3 | $G3: false, $G4: false, 4 | $G5: false, $G6: false, 5 | $G7: false, $G8: false, 6 | $G9: false, $G10: false, 7 | $pos: null, 8 | $shape-size: null, 9 | $deprecated-pos1: center center, 10 | $deprecated-pos2: center center, 11 | $deprecated-radius1: 0, 12 | $deprecated-radius2: 460, 13 | $fallback: false) { 14 | 15 | $data: _radial-arg-parser($G1, $G2, $pos, $shape-size); 16 | $G1: nth($data, 1); 17 | $G2: nth($data, 2); 18 | $pos: nth($data, 3); 19 | $shape-size: nth($data, 4); 20 | 21 | $full: compact($G1, $G2, $G3, $G4, $G5, $G6, $G7, $G8, $G9, $G10); 22 | 23 | // Strip deprecated cover/contain for spec 24 | $shape-size-spec: _shape-size-stripper($shape-size); 25 | 26 | // Set $G1 as the default fallback color 27 | $first-color: nth($full, 1); 28 | $fallback-color: nth($first-color, 1); 29 | 30 | @if (type-of($fallback) == color) or ($fallback == "transparent") { 31 | $fallback-color: $fallback; 32 | } 33 | 34 | // Add Commas and spaces 35 | $shape-size: if($shape-size, '#{$shape-size}, ', null); 36 | $pos: if($pos, '#{$pos}, ', null); 37 | $pos-spec: if($pos, 'at #{$pos}', null); 38 | $shape-size-spec: if(($shape-size-spec != ' ') and ($pos == null), '#{$shape-size-spec}, ', '#{$shape-size-spec} '); 39 | 40 | background-color: $fallback-color; 41 | background-image: _deprecated-webkit-gradient(radial, $deprecated-pos1, $deprecated-pos2, $full, $deprecated-radius1, $deprecated-radius2); // Safari <= 5.0 && IOS 4 42 | background-image: -webkit-radial-gradient(unquote(#{$pos}#{$shape-size}#{$full})); 43 | background-image: unquote("radial-gradient(#{$shape-size-spec}#{$pos-spec}#{$full})"); 44 | } 45 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_transform.scss: -------------------------------------------------------------------------------- 1 | @mixin transform($property: none) { 2 | // none | 3 | @include prefixer(transform, $property, webkit moz ms o spec); 4 | } 5 | 6 | @mixin transform-origin($axes: 50%) { 7 | // x-axis - left | center | right | length | % 8 | // y-axis - top | center | bottom | length | % 9 | // z-axis - length 10 | @include prefixer(transform-origin, $axes, webkit moz ms o spec); 11 | } 12 | 13 | @mixin transform-style ($style: flat) { 14 | @include prefixer(transform-style, $style, webkit moz ms o spec); 15 | } 16 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_transition.scss: -------------------------------------------------------------------------------- 1 | // Shorthand mixin. Supports multiple parentheses-deliminated values for each variable. 2 | // Example: @include transition (all, 2.0s, ease-in-out); 3 | // @include transition ((opacity, width), (1.0s, 2.0s), ease-in, (0, 2s)); 4 | // @include transition ($property:(opacity, width), $delay: (1.5s, 2.5s)); 5 | 6 | @mixin transition ($properties...) { 7 | @if length($properties) >= 1 { 8 | @include prefixer(transition, $properties, webkit moz spec); 9 | } 10 | 11 | @else { 12 | $properties: all 0.15s ease-out 0; 13 | @include prefixer(transition, $properties, webkit moz spec); 14 | } 15 | } 16 | 17 | @mixin transition-property ($properties...) { 18 | -webkit-transition-property: transition-property-names($properties, 'webkit'); 19 | -moz-transition-property: transition-property-names($properties, 'moz'); 20 | transition-property: transition-property-names($properties, false); 21 | } 22 | 23 | @mixin transition-duration ($times...) { 24 | @include prefixer(transition-duration, $times, webkit moz spec); 25 | } 26 | 27 | @mixin transition-timing-function ($motions...) { 28 | // ease | linear | ease-in | ease-out | ease-in-out | cubic-bezier() 29 | @include prefixer(transition-timing-function, $motions, webkit moz spec); 30 | } 31 | 32 | @mixin transition-delay ($times...) { 33 | @include prefixer(transition-delay, $times, webkit moz spec); 34 | } 35 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_user-select.scss: -------------------------------------------------------------------------------- 1 | @mixin user-select($arg: none) { 2 | @include prefixer(user-select, $arg, webkit moz ms spec); 3 | } 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_compact.scss: -------------------------------------------------------------------------------- 1 | // Remove `false` values from a list 2 | 3 | @function compact($vars...) { 4 | $list: (); 5 | @each $var in $vars { 6 | @if $var { 7 | $list: append($list, $var, comma); 8 | } 9 | } 10 | @return $list; 11 | } 12 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_flex-grid.scss: -------------------------------------------------------------------------------- 1 | // Flexible grid 2 | @function flex-grid($columns, $container-columns: $fg-max-columns) { 3 | $width: $columns * $fg-column + ($columns - 1) * $fg-gutter; 4 | $container-width: $container-columns * $fg-column + ($container-columns - 1) * $fg-gutter; 5 | @return percentage($width / $container-width); 6 | } 7 | 8 | // Flexible gutter 9 | @function flex-gutter($container-columns: $fg-max-columns, $gutter: $fg-gutter) { 10 | $container-width: $container-columns * $fg-column + ($container-columns - 1) * $fg-gutter; 11 | @return percentage($gutter / $container-width); 12 | } 13 | 14 | // The $fg-column, $fg-gutter and $fg-max-columns variables must be defined in your base stylesheet to properly use the flex-grid function. 15 | // This function takes the fluid grid equation (target / context = result) and uses columns to help define each. 16 | // 17 | // The calculation presumes that your column structure will be missing the last gutter: 18 | // 19 | // -- column -- gutter -- column -- gutter -- column 20 | // 21 | // $fg-column: 60px; // Column Width 22 | // $fg-gutter: 25px; // Gutter Width 23 | // $fg-max-columns: 12; // Total Columns For Main Container 24 | // 25 | // div { 26 | // width: flex-grid(4); // returns (315px / 995px) = 31.65829%; 27 | // margin-left: flex-gutter(); // returns (25px / 995px) = 2.51256%; 28 | // 29 | // p { 30 | // width: flex-grid(2, 4); // returns (145px / 315px) = 46.031746%; 31 | // float: left; 32 | // margin: flex-gutter(4); // returns (25px / 315px) = 7.936508%; 33 | // } 34 | // 35 | // blockquote { 36 | // float: left; 37 | // width: flex-grid(2, 4); // returns (145px / 315px) = 46.031746%; 38 | // } 39 | // } -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_grid-width.scss: -------------------------------------------------------------------------------- 1 | @function grid-width($n) { 2 | @return $n * $gw-column + ($n - 1) * $gw-gutter; 3 | } 4 | 5 | // The $gw-column and $gw-gutter variables must be defined in your base stylesheet to properly use the grid-width function. 6 | // 7 | // $gw-column: 100px; // Column Width 8 | // $gw-gutter: 40px; // Gutter Width 9 | // 10 | // div { 11 | // width: grid-width(4); // returns 520px; 12 | // margin-left: $gw-gutter; // returns 40px; 13 | // } 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_linear-gradient.scss: -------------------------------------------------------------------------------- 1 | @function linear-gradient($pos, $gradients...) { 2 | $type: linear; 3 | $pos-type: type-of(nth($pos, 1)); 4 | 5 | // if $pos doesn't exist, fix $gradient 6 | @if ($pos-type == color) or (nth($pos, 1) == "transparent") { 7 | $gradients: zip($pos $gradients); 8 | $pos: false; 9 | } 10 | 11 | $type-gradient: $type, $pos, $gradients; 12 | @return $type-gradient; 13 | } 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_modular-scale.scss: -------------------------------------------------------------------------------- 1 | @function modular-scale($value, $increment, $ratio) { 2 | @if $increment > 0 { 3 | @for $i from 1 through $increment { 4 | $value: ($value * $ratio); 5 | } 6 | } 7 | 8 | @if $increment < 0 { 9 | $increment: abs($increment); 10 | @for $i from 1 through $increment { 11 | $value: ($value / $ratio); 12 | } 13 | } 14 | 15 | @return $value; 16 | } 17 | 18 | // div { 19 | // Increment Up GR with positive value 20 | // font-size: modular-scale(14px, 1, 1.618); // returns: 22.652px 21 | // 22 | // Increment Down GR with negative value 23 | // font-size: modular-scale(14px, -1, 1.618); // returns: 8.653px 24 | // 25 | // Can be used with ceil(round up) or floor(round down) 26 | // font-size: floor( modular-scale(14px, 1, 1.618) ); // returns: 22px 27 | // font-size: ceil( modular-scale(14px, 1, 1.618) ); // returns: 23px 28 | // } 29 | // 30 | // modularscale.com 31 | 32 | @function golden-ratio($value, $increment) { 33 | @return modular-scale($value, $increment, 1.618) 34 | } 35 | 36 | // div { 37 | // font-size: golden-ratio(14px, 1); // returns: 22.652px 38 | // } 39 | // 40 | // goldenratiocalculator.com 41 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_px-to-em.scss: -------------------------------------------------------------------------------- 1 | // Convert pixels to ems 2 | // eg. for a relational value of 12px write em(12) when the parent is 16px 3 | // if the parent is another value say 24px write em(12, 24) 4 | 5 | @function em($pxval, $base: 16) { 6 | @return ($pxval / $base) * 1em; 7 | } 8 | 9 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_radial-gradient.scss: -------------------------------------------------------------------------------- 1 | // This function is required and used by the background-image mixin. 2 | @function radial-gradient($G1, $G2, 3 | $G3: false, $G4: false, 4 | $G5: false, $G6: false, 5 | $G7: false, $G8: false, 6 | $G9: false, $G10: false, 7 | $pos: null, 8 | $shape-size: null) { 9 | 10 | $data: _radial-arg-parser($G1, $G2, $pos, $shape-size); 11 | $G1: nth($data, 1); 12 | $G2: nth($data, 2); 13 | $pos: nth($data, 3); 14 | $shape-size: nth($data, 4); 15 | 16 | $type: radial; 17 | $gradient: compact($G1, $G2, $G3, $G4, $G5, $G6, $G7, $G8, $G9, $G10); 18 | 19 | $type-gradient: $type, $shape-size $pos, $gradient; 20 | @return $type-gradient; 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_tint-shade.scss: -------------------------------------------------------------------------------- 1 | // Add percentage of white to a color 2 | @function tint($color, $percent){ 3 | @return mix(white, $color, $percent); 4 | } 5 | 6 | // Add percentage of black to a color 7 | @function shade($color, $percent){ 8 | @return mix(black, $color, $percent); 9 | } 10 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_transition-property-name.scss: -------------------------------------------------------------------------------- 1 | // Return vendor-prefixed property names if appropriate 2 | // Example: transition-property-names((transform, color, background), moz) -> -moz-transform, color, background 3 | //************************************************************************// 4 | @function transition-property-names($props, $vendor: false) { 5 | $new-props: (); 6 | 7 | @each $prop in $props { 8 | $new-props: append($new-props, transition-property-name($prop, $vendor), comma); 9 | } 10 | 11 | @return $new-props; 12 | } 13 | 14 | @function transition-property-name($prop, $vendor: false) { 15 | // put other properties that need to be prefixed here aswell 16 | @if $vendor and $prop == transform { 17 | @return unquote('-'+$vendor+'-'+$prop); 18 | } 19 | @else { 20 | @return $prop; 21 | } 22 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/helpers/_deprecated-webkit-gradient.scss: -------------------------------------------------------------------------------- 1 | // Render Deprecated Webkit Gradient - Linear || Radial 2 | //************************************************************************// 3 | @function _deprecated-webkit-gradient($type, 4 | $deprecated-pos1, $deprecated-pos2, 5 | $full, 6 | $deprecated-radius1: false, $deprecated-radius2: false) { 7 | $gradient-list: (); 8 | $gradient: false; 9 | $full-length: length($full); 10 | $percentage: false; 11 | $gradient-type: $type; 12 | 13 | @for $i from 1 through $full-length { 14 | $gradient: nth($full, $i); 15 | 16 | @if length($gradient) == 2 { 17 | $color-stop: color-stop(nth($gradient, 2), nth($gradient, 1)); 18 | $gradient-list: join($gradient-list, $color-stop, comma); 19 | } 20 | @else if $gradient != null { 21 | @if $i == $full-length { 22 | $percentage: 100%; 23 | } 24 | @else { 25 | $percentage: ($i - 1) * (100 / ($full-length - 1)) + "%"; 26 | } 27 | $color-stop: color-stop(unquote($percentage), $gradient); 28 | $gradient-list: join($gradient-list, $color-stop, comma); 29 | } 30 | } 31 | 32 | @if $type == radial { 33 | $gradient: -webkit-gradient(radial, $deprecated-pos1, $deprecated-radius1, $deprecated-pos2, $deprecated-radius2, $gradient-list); 34 | } 35 | @else if $type == linear { 36 | $gradient: -webkit-gradient(linear, $deprecated-pos1, $deprecated-pos2, $gradient-list); 37 | } 38 | @return $gradient; 39 | } 40 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/helpers/_gradient-positions-parser.scss: -------------------------------------------------------------------------------- 1 | @function _gradient-positions-parser($gradient-type, $gradient-positions) { 2 | @if $gradient-positions 3 | and ($gradient-type == linear) 4 | and (type-of($gradient-positions) != color) { 5 | $gradient-positions: _linear-positions-parser($gradient-positions); 6 | } 7 | @else if $gradient-positions 8 | and ($gradient-type == radial) 9 | and (type-of($gradient-positions) != color) { 10 | $gradient-positions: _radial-positions-parser($gradient-positions); 11 | } 12 | @return $gradient-positions; 13 | } 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/helpers/_linear-positions-parser.scss: -------------------------------------------------------------------------------- 1 | @function _linear-positions-parser($pos) { 2 | $type: type-of(nth($pos, 1)); 3 | $spec: null; 4 | $degree: null; 5 | $side: null; 6 | $corner: null; 7 | $length: length($pos); 8 | // Parse Side and corner positions 9 | @if ($length > 1) { 10 | @if nth($pos, 1) == "to" { // Newer syntax 11 | $side: nth($pos, 2); 12 | 13 | @if $length == 2 { // eg. to top 14 | // Swap for backwards compatability 15 | $degree: _position-flipper(nth($pos, 2)); 16 | } 17 | @else if $length == 3 { // eg. to top left 18 | $corner: nth($pos, 3); 19 | } 20 | } 21 | @else if $length == 2 { // Older syntax ("top left") 22 | $side: _position-flipper(nth($pos, 1)); 23 | $corner: _position-flipper(nth($pos, 2)); 24 | } 25 | 26 | @if ("#{$side} #{$corner}" == "left top") or ("#{$side} #{$corner}" == "top left") { 27 | $degree: _position-flipper(#{$side}) _position-flipper(#{$corner}); 28 | } 29 | @else if ("#{$side} #{$corner}" == "right top") or ("#{$side} #{$corner}" == "top right") { 30 | $degree: _position-flipper(#{$side}) _position-flipper(#{$corner}); 31 | } 32 | @else if ("#{$side} #{$corner}" == "right bottom") or ("#{$side} #{$corner}" == "bottom right") { 33 | $degree: _position-flipper(#{$side}) _position-flipper(#{$corner}); 34 | } 35 | @else if ("#{$side} #{$corner}" == "left bottom") or ("#{$side} #{$corner}" == "bottom left") { 36 | $degree: _position-flipper(#{$side}) _position-flipper(#{$corner}); 37 | } 38 | $spec: to $side $corner; 39 | } 40 | @else if $length == 1 { 41 | // Swap for backwards compatability 42 | @if $type == string { 43 | $degree: $pos; 44 | $spec: to _position-flipper($pos); 45 | } 46 | @else { 47 | $degree: -270 - $pos; //rotate the gradient opposite from spec 48 | $spec: $pos; 49 | } 50 | } 51 | $degree: unquote($degree + ","); 52 | $spec: unquote($spec + ","); 53 | @return $degree $spec; 54 | } 55 | 56 | @function _position-flipper($pos) { 57 | @return if($pos == left, right, null) 58 | if($pos == right, left, null) 59 | if($pos == top, bottom, null) 60 | if($pos == bottom, top, null); 61 | } 62 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/helpers/_radial-arg-parser.scss: -------------------------------------------------------------------------------- 1 | @function _radial-arg-parser($G1, $G2, $pos, $shape-size) { 2 | @each $value in $G1, $G2 { 3 | $first-val: nth($value, 1); 4 | $pos-type: type-of($first-val); 5 | $spec-at-index: null; 6 | 7 | // Determine if spec was passed to mixin 8 | @if type-of($value) == list { 9 | $spec-at-index: if(index($value, at), index($value, at), false); 10 | } 11 | @if $spec-at-index { 12 | @if $spec-at-index > 1 { 13 | @for $i from 1 through ($spec-at-index - 1) { 14 | $shape-size: $shape-size nth($value, $i); 15 | } 16 | @for $i from ($spec-at-index + 1) through length($value) { 17 | $pos: $pos nth($value, $i); 18 | } 19 | } 20 | @else if $spec-at-index == 1 { 21 | @for $i from ($spec-at-index + 1) through length($value) { 22 | $pos: $pos nth($value, $i); 23 | } 24 | } 25 | $G1: false; 26 | } 27 | 28 | // If not spec calculate correct values 29 | @else { 30 | @if ($pos-type != color) or ($first-val != "transparent") { 31 | @if ($pos-type == number) 32 | or ($first-val == "center") 33 | or ($first-val == "top") 34 | or ($first-val == "right") 35 | or ($first-val == "bottom") 36 | or ($first-val == "left") { 37 | 38 | $pos: $value; 39 | 40 | @if $pos == $G1 { 41 | $G1: false; 42 | } 43 | } 44 | 45 | @else if 46 | ($first-val == "ellipse") 47 | or ($first-val == "circle") 48 | or ($first-val == "closest-side") 49 | or ($first-val == "closest-corner") 50 | or ($first-val == "farthest-side") 51 | or ($first-val == "farthest-corner") 52 | or ($first-val == "contain") 53 | or ($first-val == "cover") { 54 | 55 | $shape-size: $value; 56 | 57 | @if $value == $G1 { 58 | $G1: false; 59 | } 60 | 61 | @else if $value == $G2 { 62 | $G2: false; 63 | } 64 | } 65 | } 66 | } 67 | } 68 | @return $G1, $G2, $pos, $shape-size; 69 | } 70 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/helpers/_radial-positions-parser.scss: -------------------------------------------------------------------------------- 1 | @function _radial-positions-parser($gradient-pos) { 2 | $shape-size: nth($gradient-pos, 1); 3 | $pos: nth($gradient-pos, 2); 4 | $shape-size-spec: _shape-size-stripper($shape-size); 5 | 6 | $pre-spec: unquote(if($pos, "#{$pos}, ", null)) 7 | unquote(if($shape-size, "#{$shape-size},", null)); 8 | $pos-spec: if($pos, "at #{$pos}", null); 9 | 10 | $spec: "#{$shape-size-spec} #{$pos-spec}"; 11 | 12 | // Add comma 13 | @if ($spec != ' ') { 14 | $spec: "#{$spec}," 15 | } 16 | 17 | @return $pre-spec $spec; 18 | } 19 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/helpers/_render-gradients.scss: -------------------------------------------------------------------------------- 1 | // User for linear and radial gradients within background-image or border-image properties 2 | 3 | @function _render-gradients($gradient-positions, $gradients, $gradient-type, $vendor: false) { 4 | $pre-spec: null; 5 | $spec: null; 6 | $vendor-gradients: null; 7 | @if $gradient-type == linear { 8 | @if $gradient-positions { 9 | $pre-spec: nth($gradient-positions, 1); 10 | $spec: nth($gradient-positions, 2); 11 | } 12 | } 13 | @else if $gradient-type == radial { 14 | $pre-spec: nth($gradient-positions, 1); 15 | $spec: nth($gradient-positions, 2); 16 | } 17 | 18 | @if $vendor { 19 | $vendor-gradients: -#{$vendor}-#{$gradient-type}-gradient(#{$pre-spec} $gradients); 20 | } 21 | @else if $vendor == false { 22 | $vendor-gradients: "#{$gradient-type}-gradient(#{$spec} #{$gradients})"; 23 | $vendor-gradients: unquote($vendor-gradients); 24 | } 25 | @return $vendor-gradients; 26 | } 27 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/helpers/_shape-size-stripper.scss: -------------------------------------------------------------------------------- 1 | @function _shape-size-stripper($shape-size) { 2 | $shape-size-spec: null; 3 | @each $value in $shape-size { 4 | @if ($value == "cover") or ($value == "contain") { 5 | $value: null; 6 | } 7 | $shape-size-spec: "#{$shape-size-spec} #{$value}"; 8 | } 9 | @return $shape-size-spec; 10 | } 11 | -------------------------------------------------------------------------------- /app/assets/stylesheets/compiled.sass: -------------------------------------------------------------------------------- 1 | // Boilerplate + Bourbon 2 | @import "html5-boilerplate.sass" 3 | @import "./bourbon/_bourbon.scss" 4 | @import "html5-boilerplate.suffix.sass" 5 | 6 | 7 | //Your styles here! -------------------------------------------------------------------------------- /app/assets/stylesheets/html5-boilerplate.sass: -------------------------------------------------------------------------------- 1 | /* HTML5 Boilerplate 2 | 3 | article, aside, details, figcaption, figure, footer, header, hgroup, nav, section 4 | display: block 5 | 6 | audio, canvas, video 7 | display: inline-block 8 | *display: inline 9 | *zoom: 1 10 | 11 | audio:not([controls]), [hidden] 12 | display: none 13 | 14 | html 15 | font-size: 100% 16 | -webkit-text-size-adjust: 100% 17 | -ms-text-size-adjust: 100% 18 | font-family: sans-serif 19 | color: #222 20 | 21 | button, input, select, textarea 22 | font-family: sans-serif 23 | color: #222 24 | 25 | body 26 | margin: 0 27 | font-size: 1em 28 | line-height: 1.4 29 | 30 | a 31 | color: #5DBCD2 32 | &:visited 33 | color: #5DBCD2 34 | &:hover 35 | color: #5DBCD2 36 | text-decoration: none 37 | &:focus 38 | outline: thin dotted 39 | &:hover, &:active 40 | outline: 0 41 | 42 | abbr[title] 43 | border-bottom: 1px dotted 44 | 45 | b, strong 46 | font-weight: bold 47 | 48 | blockquote 49 | margin: 1em 40px 50 | 51 | dfn 52 | font-style: italic 53 | 54 | hr 55 | display: block 56 | height: 1px 57 | border: 0 58 | border-top: 1px solid #ccc 59 | margin: 1em 0 60 | padding: 0 61 | 62 | ins 63 | background: #ff9 64 | color: #000 65 | text-decoration: none 66 | 67 | mark 68 | background: #ff0 69 | color: #000 70 | font-style: italic 71 | font-weight: bold 72 | 73 | pre, code, kbd, samp 74 | font-family: monospace, serif 75 | _font-family: 'courier new', monospace 76 | font-size: 1em 77 | 78 | pre 79 | white-space: pre 80 | white-space: pre-wrap 81 | word-wrap: break-word 82 | 83 | q 84 | quotes: none 85 | &:before, &:after 86 | content: "" 87 | content: none 88 | 89 | small 90 | font-size: 85% 91 | 92 | sub 93 | font-size: 75% 94 | line-height: 0 95 | position: relative 96 | vertical-align: baseline 97 | 98 | sup 99 | font-size: 75% 100 | line-height: 0 101 | position: relative 102 | vertical-align: baseline 103 | top: -0.5em 104 | 105 | sub 106 | bottom: -0.25em 107 | 108 | ul, ol 109 | margin: 1em 0 110 | padding: 0 0 0 40px 111 | 112 | dd 113 | margin: 0 0 0 40px 114 | 115 | nav 116 | ul, ol 117 | list-style: none 118 | list-style-image: none 119 | margin: 0 120 | padding: 0 121 | 122 | img 123 | border: 0 124 | -ms-interpolation-mode: bicubic 125 | vertical-align: middle 126 | 127 | svg:not(:root) 128 | overflow: hidden 129 | 130 | figure, form 131 | margin: 0 132 | 133 | fieldset 134 | border: 0 135 | margin: 0 136 | padding: 0 137 | 138 | label 139 | cursor: pointer 140 | 141 | legend 142 | border: 0 143 | *margin-left: -7px 144 | padding: 0 145 | white-space: normal 146 | 147 | button, input, select, textarea 148 | font-size: 100% 149 | margin: 0 150 | vertical-align: baseline 151 | *vertical-align: middle 152 | 153 | button, input 154 | line-height: normal 155 | 156 | button 157 | cursor: pointer 158 | -webkit-appearance: button 159 | *overflow: visible 160 | 161 | input 162 | &[type="button"], &[type="reset"], &[type="submit"] 163 | cursor: pointer 164 | -webkit-appearance: button 165 | *overflow: visible 166 | 167 | button[disabled] 168 | cursor: default 169 | 170 | input 171 | &[disabled] 172 | cursor: default 173 | &[type="checkbox"], &[type="radio"] 174 | box-sizing: border-box 175 | padding: 0 176 | *width: 13px 177 | *height: 13px 178 | &[type="search"] 179 | -webkit-appearance: textfield 180 | -moz-box-sizing: content-box 181 | -webkit-box-sizing: content-box 182 | box-sizing: content-box 183 | &::-webkit-search-decoration, &::-webkit-search-cancel-button 184 | -webkit-appearance: none 185 | 186 | button::-moz-focus-inner, input::-moz-focus-inner 187 | border: 0 188 | padding: 0 189 | 190 | textarea 191 | overflow: auto 192 | vertical-align: top 193 | resize: vertical 194 | 195 | 196 | input:invalid, textarea:invalid 197 | //background-color: #f0dddd 198 | 199 | table 200 | border-collapse: collapse 201 | border-spacing: 0 202 | 203 | td 204 | vertical-align: top 205 | 206 | .chromeframe 207 | margin: 0.2em 0 208 | background: #ccc 209 | color: black 210 | padding: 0.2em 0 211 | -------------------------------------------------------------------------------- /app/assets/stylesheets/html5-boilerplate.suffix.sass: -------------------------------------------------------------------------------- 1 | 2 | .ir 3 | display: block 4 | border: 0 5 | text-indent: -999em 6 | overflow: hidden 7 | background-color: transparent 8 | background-repeat: no-repeat 9 | text-align: left 10 | direction: ltr 11 | *line-height: 0 12 | br 13 | display: none 14 | 15 | .hidden 16 | display: none 17 | 18 | .visuallyhidden 19 | border: 0 20 | clip: rect(0 0 0 0) 21 | height: 1px 22 | margin: -1px 23 | overflow: hidden 24 | padding: 0 25 | position: absolute 26 | width: 1px 27 | &.focusable 28 | &:active, &:focus 29 | clip: auto 30 | height: auto 31 | margin: 0 32 | overflow: visible 33 | position: static 34 | width: auto 35 | 36 | .invisible 37 | visibility: hidden 38 | 39 | .clearfix 40 | &:before 41 | content: "" 42 | display: table 43 | &:after 44 | content: "" 45 | display: table 46 | clear: both 47 | *zoom: 1 48 | 49 | @media print 50 | * 51 | background: transparent !important 52 | color: black !important 53 | box-shadow: none !important 54 | text-shadow: none !important 55 | filter: none !important 56 | -ms-filter: none !important 57 | a 58 | text-decoration: underline 59 | &:visited 60 | text-decoration: underline 61 | &[href]:after 62 | content: " (" attr(href) ")" 63 | abbr[title]:after 64 | content: " (" attr(title) ")" 65 | .ir a:after 66 | content: "" 67 | a 68 | &[href^="javascript:"]:after, &[href^="#"]:after 69 | content: "" 70 | pre, blockquote 71 | border: 1px solid #999 72 | page-break-inside: avoid 73 | thead 74 | display: table-header-group 75 | tr 76 | page-break-inside: avoid 77 | img 78 | page-break-inside: avoid 79 | max-width: 100% !important 80 | @page 81 | margin: 0.5cm 82 | 83 | p, h2, h3 84 | orphans: 3 85 | widows: 3 86 | h2, h3 87 | page-break-after: avoid -------------------------------------------------------------------------------- /app/assets/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | * THEME NAME: The Awesome Thing 3 | * THEME URI: http://awesome.com 4 | * DESCRIPTION: A theme for your blog. 5 | * VERSION: 1.0 6 | * AUTHOR: John Smith 7 | * AUTHOR URI: http://johnsmith.com 8 | */ 9 | 10 | @import url("compiled.css"); -------------------------------------------------------------------------------- /app/views/404.haml: -------------------------------------------------------------------------------- 1 | -get_header() 2 | The page you requested doesn't exist. 3 | -get_footer() -------------------------------------------------------------------------------- /app/views/category.haml: -------------------------------------------------------------------------------- 1 | -get_header() 2 | Category: 3 | =single_cat_title() 4 | %hr 5 | -require("results.php") 6 | -get_footer() -------------------------------------------------------------------------------- /app/views/footer.haml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/views/header.haml: -------------------------------------------------------------------------------- 1 | !!! 2 | 3 | %head 4 | %meta{:content => "text/html; charset=utf-8", "http-equiv" => "Content-Type"} 5 | %title 6 | -wp_title() 7 | %link{:href => '', :type => "text/css", :rel => "stylesheet"} 8 | -wp_head() 9 | %script{:src => "/scripts/compiled.min.js"} 10 | 11 | 12 | 13 | %nav 14 | %ul 15 | %li 16 | %a{:href => ""} Home 17 | %li Another Link 18 | %br 19 | %br 20 | -------------------------------------------------------------------------------- /app/views/index.haml: -------------------------------------------------------------------------------- 1 | -get_header() 2 | -if( have_posts() ) 3 | -while( have_posts() ) 4 | -the_post() 5 | -the_permalink() 6 | -the_title() 7 | -the_content() 8 | %br 9 | -else 10 | Sorry, no posts were found. 11 | -get_footer() 12 | -------------------------------------------------------------------------------- /app/views/results.haml: -------------------------------------------------------------------------------- 1 | -if( have_posts() ) 2 | -while( have_posts() ) 3 | -the_post() 4 | -the_time("F jS, Y") 5 | -the_title() 6 | -the_author() 7 | -else 8 | Sorry, no posts were found. -------------------------------------------------------------------------------- /app/views/search.haml: -------------------------------------------------------------------------------- 1 | 5 | -get_header() 6 | Search results for: 7 | =get_search_query() 8 | %hr 9 | -require("results.php") 10 | -get_footer() -------------------------------------------------------------------------------- /app/views/single.haml: -------------------------------------------------------------------------------- 1 | -get_header() 2 | -while( have_posts() ) 3 | -the_post() 4 | -the_title() 5 | -the_content() 6 | -get_footer() 7 | -------------------------------------------------------------------------------- /app/views/tag.haml: -------------------------------------------------------------------------------- 1 | -get_header() 2 | Tag: 3 | =single_cat_title() 4 | %hr 5 | -require("results.php") 6 | -get_footer() -------------------------------------------------------------------------------- /install: -------------------------------------------------------------------------------- 1 | cd /tmp 2 | git clone https://github.com/alandipert/fswatch 3 | cd fswatch/ 4 | make 5 | cp fswatch /usr/local/bin/fswatch 6 | echo "Watcher Installed" -------------------------------------------------------------------------------- /lib/MtHaml/Autoloader.php: -------------------------------------------------------------------------------- 1 | 'html5', 16 | 'enable_escaper' => true, 17 | 'escape_html' => true, 18 | 'escape_attrs' => true, 19 | 'autoclose' => array('meta', 'img', 'link', 'br', 'hr', 'input', 'area', 'param', 'col', 'base'), 20 | 'charset' => 'UTF-8', 21 | ); 22 | 23 | protected $target; 24 | 25 | public function __construct($target, array $options = array()) 26 | { 27 | $this->target = $target; 28 | $this->options = $options + $this->options; 29 | } 30 | 31 | public function compileString($string, $filename) 32 | { 33 | $target = $this->getTarget(); 34 | 35 | $node = $target->parse($this, $string, $filename); 36 | 37 | foreach($this->getVisitors() as $visitor) { 38 | $node->accept($visitor); 39 | } 40 | 41 | $code = $target->compile($this, $node, $filename); 42 | 43 | return $code; 44 | } 45 | 46 | public function getOption($name) 47 | { 48 | return $this->options[$name]; 49 | } 50 | 51 | public function getTarget() 52 | { 53 | $target = $this->target; 54 | if (is_string($target)) { 55 | switch($target) { 56 | case 'php': 57 | $target = new Php; 58 | break; 59 | case 'twig': 60 | $target = new Twig; 61 | break; 62 | default: 63 | throw new Exception(sprintf('Unknown target language: %s', $target)); 64 | } 65 | $this->target = $target; 66 | } 67 | return $target; 68 | } 69 | 70 | public function getVisitors() 71 | { 72 | $visitors = array(); 73 | 74 | $visitors[] = $this->getAutoclosevisitor(); 75 | $visitors[] = $this->getMidblockVisitor(); 76 | $visitors[] = $this->getMergeAttrsVisitor(); 77 | 78 | if ($this->getOption('enable_escaper')) { 79 | $visitors[] = $this->getEscapingVisitor(); 80 | } 81 | 82 | return $visitors; 83 | } 84 | 85 | public function getEscapingVisitor() 86 | { 87 | $html = EscapingVisitor::ESCAPE_TRUE; 88 | if (!$this->getOption('escape_html')) { 89 | $html = EscapingVisitor::ESCAPE_FALSE; 90 | } 91 | 92 | $attrs = EscapingVisitor::ESCAPE_TRUE; 93 | if ('once' === $this->getOption('escape_attrs')) { 94 | $attrs = EscapingVisitor::ESCAPE_ONCE; 95 | } else if (!$this->getOption('escape_attrs')) { 96 | $attrs = EscapingVisitor::ESCAPE_FALSE; 97 | } 98 | 99 | return new EscapingVisitor($html, $attrs); 100 | } 101 | 102 | public function getAutocloseVisitor() 103 | { 104 | return new Autoclose($this->getOption('autoclose')); 105 | } 106 | 107 | public function getMidblockVisitor() 108 | { 109 | return new Midblock($this->getTarget()->getOption('midblock_regex')); 110 | } 111 | 112 | public function getMergeAttrsVisitor() 113 | { 114 | return new MergeAttrs; 115 | } 116 | } 117 | 118 | -------------------------------------------------------------------------------- /lib/MtHaml/Escaping.php: -------------------------------------------------------------------------------- 1 | enabled = $enabled; 13 | return $this; 14 | } 15 | 16 | public function isEnabled() 17 | { 18 | return $this->enabled; 19 | } 20 | 21 | public function setOnce($once) 22 | { 23 | $this->once = $once; 24 | return $this; 25 | } 26 | 27 | public function isOnce() 28 | { 29 | return $this->once; 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /lib/MtHaml/Exception.php: -------------------------------------------------------------------------------- 1 | rendered = $rendered; 27 | $this->condition = $condition; 28 | } 29 | 30 | public function isRendered() 31 | { 32 | return $this->rendered; 33 | } 34 | 35 | public function hasCondition() 36 | { 37 | return null !== $this->condition; 38 | } 39 | 40 | public function getCondition() 41 | { 42 | return $this->condition; 43 | } 44 | 45 | public function getNodeName() 46 | { 47 | return 'comment'; 48 | } 49 | 50 | public function accept(NodeVisitorInterface $visitor) 51 | { 52 | if (false !== $visitor->enterComment($this)) { 53 | 54 | if (false !== $visitor->enterCommentContent($this)) { 55 | $this->visitContent($visitor); 56 | } 57 | $visitor->leaveCommentContent($this); 58 | 59 | if (false !== $visitor->enterCommentChilds($this)) { 60 | $this->visitChilds($visitor); 61 | } 62 | $visitor->leaveCommentChilds($this); 63 | } 64 | $visitor->leaveComment($this); 65 | } 66 | 67 | public function allowsNestingAndContent() 68 | { 69 | return ! $this->rendered; 70 | } 71 | } 72 | 73 | -------------------------------------------------------------------------------- /lib/MtHaml/Node/Doctype.php: -------------------------------------------------------------------------------- 1 | array( 17 | '' => '', 18 | 'Strict' => '', 19 | 'Frameset' => '', 20 | '5' => '', 21 | '1.1' => '', 22 | 'Basic' => '', 23 | 'Mobile' => '', 24 | 'RDFa' => '', 25 | ), 26 | 'html4' => array( 27 | '' => '', 28 | 'Strict' => '', 29 | 'Frameset' => '', 30 | ), 31 | 'html5' => array( 32 | '' => '', 33 | ), 34 | ); 35 | 36 | public function __construct(array $position, $doctypeId, $options) 37 | { 38 | parent::__construct($position); 39 | $this->doctypeId = $doctypeId; 40 | $this->options = $options; 41 | } 42 | 43 | public function getDoctype($format) 44 | { 45 | if ($this->doctypeId === 'XML') { 46 | if (!empty($this->options)) { 47 | return sprintf("", $this->options); 48 | } else { 49 | return ""; 50 | } 51 | } 52 | 53 | if (empty($this->doctypeId)) { 54 | return $this->doctypes[$format]['']; 55 | } else if (isset($this->doctypes[$format][$this->doctypeId])) { 56 | return $this->doctypes[$format][$this->doctypeId]; 57 | } else { 58 | 59 | $doctypes = array(); 60 | foreach ($this->doctypes[$format] as $key => $doctype) { 61 | $doctypes[] = "'".trim('!!! ' . $key)."'"; 62 | } 63 | 64 | trigger_error(sprintf("No such doctype '!!! %s' for the format '%s'. Available doctypes for the current format are: %s", $this->doctypeId, $format, implode(', ', $doctypes)), E_USER_WARNING); 65 | 66 | return $this->doctypes[$format]['']; 67 | } 68 | } 69 | 70 | public function getDoctypeId() 71 | { 72 | return $this->doctypeId; 73 | } 74 | 75 | public function getOptions() 76 | { 77 | return $this->options; 78 | } 79 | 80 | public function getNodeName() 81 | { 82 | return 'doctype'; 83 | } 84 | 85 | public function accept(NodeVisitorInterface $visitor) 86 | { 87 | $visitor->enterDoctype($this); 88 | $visitor->leaveDoctype($this); 89 | } 90 | } 91 | 92 | -------------------------------------------------------------------------------- /lib/MtHaml/Node/EscapableAbstract.php: -------------------------------------------------------------------------------- 1 | escaping) { 14 | $this->escaping = new Escaping; 15 | } 16 | return $this->escaping; 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /lib/MtHaml/Node/Filter.php: -------------------------------------------------------------------------------- 1 | filter = $filter; 16 | } 17 | 18 | public function getFilter() 19 | { 20 | return $this->filter; 21 | } 22 | 23 | public function addChild(NodeAbstract $node) 24 | { 25 | $this->childs[] = $node; 26 | } 27 | 28 | public function getChilds() 29 | { 30 | return $this->childs; 31 | } 32 | 33 | public function getNodeName() 34 | { 35 | return 'filter'; 36 | } 37 | 38 | public function accept(NodeVisitorInterface $visitor) 39 | { 40 | if (false !== $visitor->enterFilter($this)) { 41 | 42 | if (false !== $visitor->enterFilterChilds($this)) { 43 | foreach($this->getChilds() as $child) { 44 | $child->accept($visitor); 45 | } 46 | } 47 | $visitor->leaveFilterChilds($this); 48 | } 49 | $visitor->leaveFilter($this); 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /lib/MtHaml/Node/Insert.php: -------------------------------------------------------------------------------- 1 | content = $content; 20 | } 21 | 22 | public function getContent() 23 | { 24 | return $this->content; 25 | } 26 | 27 | public function hasContent() 28 | { 29 | return null !== $this->content; 30 | } 31 | 32 | public function getNodeName() 33 | { 34 | return 'echo'; 35 | } 36 | 37 | public function accept(NodeVisitorInterface $visitor) 38 | { 39 | $visitor->enterInsert($this); 40 | $visitor->leaveInsert($this); 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /lib/MtHaml/Node/InterpolatedString.php: -------------------------------------------------------------------------------- 1 | childs = $childs; 21 | } 22 | 23 | /** 24 | * @param Text|Insert $child Child 25 | */ 26 | public function addChild(NodeAbstract $child) 27 | { 28 | 29 | if (!$child instanceof Text && !$child instanceof Insert) { 30 | throw new \InvalidArgumentException(sprintf('Argument 1 passed to %s() must be an instance of MtHaml\Node\Text or MtHaml\Node\Insert, instance of %s given', __METHOD__, get_class($child))); 31 | } 32 | 33 | $this->childs[] = $child; 34 | } 35 | 36 | /** 37 | * @return Text|Insert 38 | */ 39 | public function getChilds() 40 | { 41 | return $this->childs; 42 | } 43 | 44 | public function getNodeName() 45 | { 46 | return 'interpolated string'; 47 | } 48 | 49 | public function accept(NodeVisitorInterface $visitor) 50 | { 51 | if (false !== $visitor->enterInterpolatedString($this)) { 52 | 53 | if (false !== $visitor->enterInterpolatedStringChilds($this)) { 54 | foreach($this->getChilds() as $child) { 55 | $child->accept($visitor); 56 | } 57 | $visitor->leaveInterpolatedStringChilds($this); 58 | } 59 | $visitor->leaveInterpolatedString($this); 60 | } 61 | } 62 | 63 | public function isConst() 64 | { 65 | foreach ($this->childs as $child) { 66 | if (!$child->isConst()) { 67 | return false; 68 | } 69 | } 70 | 71 | return true; 72 | } 73 | } 74 | 75 | -------------------------------------------------------------------------------- /lib/MtHaml/Node/NestAbstract.php: -------------------------------------------------------------------------------- 1 | allowsNestingAndContent() && $this->hasContent()) { 16 | throw new Exception('A node cannot have both content and nested nodes'); 17 | } 18 | if (null !== $parent = $node->getParent()) { 19 | $parent->removeChild($node); 20 | } 21 | 22 | $prev = end($this->childs) ?: null; 23 | 24 | $this->childs[] = $node; 25 | $node->setParent($this); 26 | 27 | if ($prev) { 28 | $prev->setNextSibling($node); 29 | } 30 | $node->setPreviousSibling($prev); 31 | $node->setNextSibling(null); 32 | } 33 | 34 | public function removeChild(NodeAbstract $node) 35 | { 36 | if (false === $key = array_search($node, $this->childs, true)) { 37 | return; 38 | } 39 | 40 | unset($this->childs[$key]); 41 | 42 | $prev = $node->getPreviousSibling(); 43 | $next = $node->getNextSibling(); 44 | 45 | if ($prev) { 46 | $prev->setNextSibling($next); 47 | } 48 | if ($next) { 49 | $next->setPreviousSibling($prev); 50 | } 51 | 52 | $node->setParent(null); 53 | $node->setPreviousSibling(null); 54 | $node->setNextSibling(null); 55 | } 56 | 57 | public function hasChilds() 58 | { 59 | return 0 < count($this->childs); 60 | } 61 | 62 | public function getChilds() 63 | { 64 | return $this->childs; 65 | } 66 | 67 | public function getFirstChild() 68 | { 69 | if (false !== $child = reset($this->childs)) { 70 | return $child; 71 | } 72 | } 73 | 74 | public function getLastChild() 75 | { 76 | if (false !== $child = end($this->childs)) { 77 | return $child; 78 | } 79 | } 80 | 81 | public function setContent($content) 82 | { 83 | if (!$this->allowsNestingAndContent() && $this->hasChilds()) { 84 | throw new Exception('A node cannot have both content and nested nodes'); 85 | } 86 | $this->content = $content; 87 | } 88 | 89 | public function hasContent() 90 | { 91 | return null !== $this->content; 92 | } 93 | 94 | public function getContent() 95 | { 96 | return $this->content; 97 | } 98 | 99 | public function allowsNestingAndContent() 100 | { 101 | return false; 102 | } 103 | 104 | public function visitContent(NodeVisitorInterface $visitor) 105 | { 106 | if ($this->hasContent()) { 107 | $this->getContent()->accept($visitor); 108 | } 109 | } 110 | 111 | public function visitChilds(NodeVisitorInterface $visitor) 112 | { 113 | foreach($this->getChilds() as $child) { 114 | $child->accept($visitor); 115 | } 116 | } 117 | } 118 | 119 | -------------------------------------------------------------------------------- /lib/MtHaml/Node/NestInterface.php: -------------------------------------------------------------------------------- 1 | position = $position; 17 | } 18 | 19 | public function getPosition() 20 | { 21 | return $this->position; 22 | } 23 | 24 | public function getLineno() 25 | { 26 | return $this->position['lineno']; 27 | } 28 | 29 | public function getColumn() 30 | { 31 | return $this->position['column']; 32 | } 33 | 34 | protected function setParent(NodeAbstract $parent = null) 35 | { 36 | $this->parent = $parent; 37 | } 38 | 39 | public function hasParent() 40 | { 41 | return null !== $this->parent; 42 | } 43 | 44 | public function getParent() 45 | { 46 | return $this->parent; 47 | } 48 | 49 | abstract public function getNodeName(); 50 | 51 | abstract public function accept(NodeVisitorInterface $visitor); 52 | 53 | protected function setNextSibling(NodeAbstract $node = null) 54 | { 55 | $this->nextSibling = $node; 56 | } 57 | 58 | public function getNextSibling() 59 | { 60 | return $this->nextSibling; 61 | } 62 | 63 | protected function setPreviousSibling(NodeAbstract $node = null) 64 | { 65 | $this->previousSibling = $node; 66 | } 67 | 68 | public function getPreviousSibling() 69 | { 70 | return $this->previousSibling; 71 | } 72 | 73 | public function isConst() 74 | { 75 | return false; 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /lib/MtHaml/Node/ObjectRefClass.php: -------------------------------------------------------------------------------- 1 | object = $object; 17 | $this->prefix = $prefix; 18 | } 19 | 20 | public function getNodeName() 21 | { 22 | return 'object_ref_class'; 23 | } 24 | 25 | public function accept(NodeVisitorInterface $visitor) 26 | { 27 | if (false !== $visitor->enterObjectRefClass($this)) { 28 | 29 | if (false !== $visitor->enterObjectRefObject($this)) { 30 | $this->object->accept($visitor); 31 | } 32 | $visitor->leaveObjectRefObject($this); 33 | 34 | if ($this->prefix) { 35 | if (false !== $visitor->enterObjectRefPrefix($this)) { 36 | $this->prefix->accept($visitor); 37 | } 38 | $visitor->leaveObjectRefPrefix($this); 39 | } 40 | } 41 | $visitor->leaveObjectRefClass($this); 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /lib/MtHaml/Node/ObjectRefId.php: -------------------------------------------------------------------------------- 1 | object = $object; 17 | $this->prefix = $prefix; 18 | } 19 | 20 | public function getNodeName() 21 | { 22 | return 'object_ref_id'; 23 | } 24 | 25 | public function accept(NodeVisitorInterface $visitor) 26 | { 27 | if (false !== $visitor->enterObjectRefId($this)) { 28 | 29 | if (false !== $visitor->enterObjectRefObject($this)) { 30 | $this->object->accept($visitor); 31 | } 32 | $visitor->leaveObjectRefObject($this); 33 | 34 | if ($this->prefix) { 35 | if (false !== $visitor->enterObjectRefPrefix($this)) { 36 | $this->prefix->accept($visitor); 37 | } 38 | $visitor->leaveObjectRefPrefix($this); 39 | } 40 | } 41 | $visitor->leaveObjectRefId($this); 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /lib/MtHaml/Node/Root.php: -------------------------------------------------------------------------------- 1 | 0, 'column' => 0)); 12 | } 13 | 14 | public function getNodeName() 15 | { 16 | return 'root'; 17 | } 18 | 19 | public function accept(NodeVisitorInterface $visitor) 20 | { 21 | if (false !== $visitor->enterRoot($this)) { 22 | 23 | if (false !== $visitor->enterRootContent($this)) { 24 | $this->visitContent($visitor); 25 | } 26 | $visitor->leaveRootContent($this); 27 | 28 | if (false !== $visitor->enterRootChilds($this)) { 29 | $this->visitChilds($visitor); 30 | } 31 | $visitor->leaveRootChilds($this); 32 | } 33 | $visitor->leaveRoot($this); 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /lib/MtHaml/Node/Run.php: -------------------------------------------------------------------------------- 1 | setContent($content); 21 | } 22 | 23 | public function allowsNestingAndContent() 24 | { 25 | return true; 26 | } 27 | 28 | public function getNodeName() 29 | { 30 | return 'exec'; 31 | } 32 | 33 | public function setMidblock(Run $midblock = null) 34 | { 35 | $this->midblock = $midblock; 36 | } 37 | 38 | public function getMidblock() 39 | { 40 | return $this->midblock; 41 | } 42 | 43 | public function hasMidblock() 44 | { 45 | return null !== $this->midblock; 46 | } 47 | 48 | public function isBlock() 49 | { 50 | return $this->hasChilds() || $this->hasMidblock(); 51 | } 52 | 53 | public function accept(NodeVisitorInterface $visitor) 54 | { 55 | if (false !== $visitor->enterRun($this)) { 56 | 57 | if (false !== $visitor->enterRunChilds($this)) { 58 | $this->visitChilds($visitor); 59 | } 60 | $visitor->leaveRunChilds($this); 61 | 62 | if (false !== $visitor->enterRunMidblock($this)) { 63 | if (null !== $block = $this->getMidblock()) { 64 | $block->accept($visitor); 65 | } 66 | } 67 | $visitor->leaveRunMidblock($this); 68 | } 69 | $visitor->leaveRun($this); 70 | } 71 | } 72 | 73 | -------------------------------------------------------------------------------- /lib/MtHaml/Node/Statement.php: -------------------------------------------------------------------------------- 1 | content = $content; 15 | } 16 | 17 | public function getContent() 18 | { 19 | return $this->content; 20 | } 21 | 22 | public function hasContent() 23 | { 24 | return null !== $this->content; 25 | } 26 | 27 | public function getNodeName() 28 | { 29 | return 'statement'; 30 | } 31 | 32 | public function accept(NodeVisitorInterface $visitor) 33 | { 34 | if (false !== $visitor->enterStatement($this)) { 35 | 36 | if (false !== $visitor->enterStatementContent($this)) { 37 | if ($this->hasContent()) { 38 | $this->getContent()->accept($visitor); 39 | } 40 | } 41 | $visitor->leaveStatementContent($this); 42 | } 43 | $visitor->leaveStatement($this); 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /lib/MtHaml/Node/Tag.php: -------------------------------------------------------------------------------- 1 | tagName = $tagName; 22 | $this->attributes = $attributes; 23 | $this->flags = $flags; 24 | } 25 | 26 | public function getTagName() 27 | { 28 | return $this->tagName; 29 | } 30 | 31 | public function addAttribute(TagAttribute $attribute) 32 | { 33 | $this->attributes[] = $attribute; 34 | } 35 | 36 | public function hasAttributes() 37 | { 38 | return 0 < count($this->attributes); 39 | } 40 | 41 | public function getAttributes() 42 | { 43 | return $this->attributes; 44 | } 45 | 46 | public function removeAttribute(TagAttribute $attribute) 47 | { 48 | if (null !== $key = array_search($attribute, $this->attributes, true)) { 49 | unset($this->attributes[$key]); 50 | } 51 | } 52 | 53 | public function setFlag($flag) 54 | { 55 | $this->flags |= $flag; 56 | } 57 | 58 | public function getFlags() 59 | { 60 | return $this->flags; 61 | } 62 | 63 | public function getNodeName() 64 | { 65 | return 'tag'; 66 | } 67 | 68 | public function accept(NodeVisitorInterface $visitor) 69 | { 70 | if (false !== $visitor->enterTag($this)) { 71 | 72 | if (false !== $visitor->enterTagAttributes($this)) { 73 | foreach($this->getAttributes() as $attribute) { 74 | $attribute->accept($visitor); 75 | } 76 | } 77 | $visitor->leaveTagAttributes($this); 78 | 79 | if (false !== $visitor->enterTagContent($this)) { 80 | $this->visitContent($visitor); 81 | } 82 | $visitor->leaveTagContent($this); 83 | 84 | if (false !== $visitor->enterTagChilds($this)) { 85 | $this->visitChilds($visitor); 86 | } 87 | $visitor->leaveTagChilds($this); 88 | } 89 | $visitor->leaveTag($this); 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /lib/MtHaml/Node/TagAttribute.php: -------------------------------------------------------------------------------- 1 | name = $name; 17 | $this->value = $value; 18 | } 19 | 20 | public function setName(NodeAbstract $name) 21 | { 22 | $this->name = $name; 23 | } 24 | 25 | public function getName() 26 | { 27 | return $this->name; 28 | } 29 | 30 | public function setValue(NodeAbstract $value) 31 | { 32 | $this->value = $value; 33 | } 34 | 35 | public function getValue() 36 | { 37 | return $this->value; 38 | } 39 | 40 | public function getNodeName() 41 | { 42 | return 'attribute'; 43 | } 44 | 45 | public function accept(NodeVisitorInterface $visitor) 46 | { 47 | if (false !== $visitor->enterTagAttribute($this)) { 48 | 49 | if (false !== $visitor->enterTagAttributeName($this)) { 50 | $this->getName()->accept($visitor); 51 | } 52 | $visitor->leaveTagAttributeName($this); 53 | 54 | if ($this->getValue()) { 55 | if (false !== $visitor->enterTagAttributeValue($this)) { 56 | $this->getValue()->accept($visitor); 57 | } 58 | $visitor->leaveTagAttributeValue($this); 59 | } 60 | } 61 | $visitor->leaveTagAttribute($this); 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /lib/MtHaml/Node/TagAttributeInterpolation.php: -------------------------------------------------------------------------------- 1 | enterTagAttribute($this)) { 18 | if (false !== $visitor->enterTagAttributeInterpolation($this)) { 19 | $this->getValue()->accept($visitor); 20 | } 21 | $visitor->leaveTagAttributeInterpolation($this); 22 | } 23 | $visitor->leaveTagAttribute($this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/MtHaml/Node/TagAttributeList.php: -------------------------------------------------------------------------------- 1 | enterTagAttribute($this)) { 18 | if (false !== $visitor->enterTagAttributeList($this)) { 19 | $this->getValue()->accept($visitor); 20 | } 21 | $visitor->leaveTagAttributeList($this); 22 | } 23 | $visitor->leaveTagAttribute($this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/MtHaml/Node/Text.php: -------------------------------------------------------------------------------- 1 | content = $content; 15 | } 16 | 17 | public function getContent() 18 | { 19 | return $this->content; 20 | } 21 | 22 | public function getNodeName() 23 | { 24 | return 'text'; 25 | } 26 | 27 | public function accept(NodeVisitorInterface $visitor) 28 | { 29 | $visitor->enterText($this); 30 | $visitor->leaveText($this); 31 | } 32 | 33 | public function isConst() 34 | { 35 | return true; 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /lib/MtHaml/NodeVisitor/Autoclose.php: -------------------------------------------------------------------------------- 1 | autocloseTags = $autocloseTags; 14 | } 15 | 16 | public function enterTag(Tag $tag) 17 | { 18 | if ($tag->hasChilds() || $tag->hasContent()) { 19 | return; 20 | } 21 | if (in_array($tag->getTagName(), $this->autocloseTags)) { 22 | $tag->setFlag(Tag::FLAG_SELF_CLOSE); 23 | } 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /lib/MtHaml/NodeVisitor/Escaping.php: -------------------------------------------------------------------------------- 1 | escapeHtml = $escapeHtml; 31 | $this->escapeAttrs = $escapeAttrs; 32 | } 33 | 34 | protected function escape(NodeAbstract $node) 35 | { 36 | $enabled = $node->getEscaping()->isEnabled(); 37 | 38 | if ($enabled !== null) { 39 | return; 40 | } 41 | 42 | if ($node instanceof Text) { 43 | // interpolated strings that are not in attribute name/value 44 | // are plain HTML and should not be escaped 45 | if ($this->inInterpolatedString && !$this->inAttr) { 46 | $node->getEscaping()->setEnabled(false); 47 | return; 48 | } 49 | } 50 | 51 | // everything we don't explicitly not escape is escaped 52 | 53 | if ($this->inAttr) { 54 | $this->setEscape($node, $this->escapeAttrs); 55 | } else { 56 | $this->setEscape($node, $this->escapeHtml); 57 | } 58 | } 59 | 60 | protected function setEscape(NodeAbstract $node, $mode) 61 | { 62 | switch($mode) { 63 | case self::ESCAPE_FALSE: 64 | $node->getEscaping()->setEnabled(false); 65 | break; 66 | case self::ESCAPE_ONCE: 67 | $node->getEscaping()->setEnabled(true)->setOnce(true); 68 | break; 69 | case self::ESCAPE_TRUE: 70 | $node->getEscaping()->setEnabled(true); 71 | break; 72 | } 73 | } 74 | 75 | public function enterTagAttribute(TagAttribute $node) 76 | { 77 | ++$this->inAttr; 78 | } 79 | 80 | public function leaveTagAttribute(TagAttribute $node) 81 | { 82 | --$this->inAttr; 83 | } 84 | 85 | public function enterInterpolatedString(InterpolatedString $node) 86 | { 87 | ++$this->inInterpolatedString; 88 | } 89 | 90 | public function leaveInterpolatedString(InterpolatedString $node) 91 | { 92 | --$this->inInterpolatedString; 93 | } 94 | 95 | public function enterText(Text $node) 96 | { 97 | $this->escape($node); 98 | } 99 | 100 | public function enterInsert(Insert $node) 101 | { 102 | $this->escape($node); 103 | } 104 | } 105 | 106 | -------------------------------------------------------------------------------- /lib/MtHaml/NodeVisitor/MergeAttrs.php: -------------------------------------------------------------------------------- 1 | attrs = array(); 19 | $this->tag = $node; 20 | 21 | // Do not attempt to merge attributes if any attribute 22 | // name cannot be guessed at compile time. 23 | // 24 | // Else it may change the output (e.g. the unknown attribute 25 | // name could be 'class') 26 | 27 | foreach ($node->getAttributes() as $attr) { 28 | if (null === $this->getString($attr->getName())) { 29 | return false; 30 | } 31 | } 32 | } 33 | 34 | public function enterTagAttribute(TagAttribute $node) 35 | { 36 | if (null !== $name = $this->getString($node->getName())) { 37 | if (isset($this->attrs[$name])) { 38 | if ('class' === $name) { 39 | $orig = $this->attrs[$name]->getValue(); 40 | $new = $this->mergeClasses($orig, $node->getValue()); 41 | 42 | // Don't merge it if the value isn't const since it could 43 | // be an array; which needs special handling at runtime. 44 | 45 | // Also unset $this->attrs[$name] so that following 46 | // class arguments do not get merged into this one. 47 | 48 | if (!$new || !$new->isConst()) { 49 | unset($this->attrs[$name]); 50 | return; 51 | } 52 | 53 | $this->attrs[$name]->setValue($new); 54 | $this->tag->removeAttribute($node); 55 | } else { 56 | $this->tag->removeAttribute($this->attrs[$name]); 57 | } 58 | } else { 59 | $this->attrs[$name] = $node; 60 | } 61 | } 62 | } 63 | 64 | protected function getString($node) 65 | { 66 | if ($node instanceof Text) { 67 | return $node->getContent(); 68 | } 69 | if ($node instanceof InterpolatedString) { 70 | $ret = ''; 71 | foreach($node->getChilds() as $child) { 72 | if (null !== $string = $this->getString($child)) { 73 | $ret .= $string; 74 | } else { 75 | return null; 76 | } 77 | } 78 | return $ret; 79 | } 80 | } 81 | 82 | protected function mergeClasses($a, $b) 83 | { 84 | $new = new InterpolatedString($a->getPosition()); 85 | if (false === $this->mergeInto($new, $a)) { 86 | return; 87 | } 88 | $new->addChild(new Text($b->getPosition(), ' ')); 89 | if (false === $this->mergeInto($new, $b)) { 90 | return; 91 | } 92 | return $new; 93 | } 94 | 95 | protected function mergeInto(InterpolatedString $dest, $src) 96 | { 97 | if ($src instanceof InterpolatedString) { 98 | foreach($src->getChilds() as $child) { 99 | $dest->addChild($child); 100 | } 101 | } else if ($src instanceof Text || $src instanceof Insert) { 102 | $dest->addChild($src); 103 | } else { 104 | return false; 105 | } 106 | } 107 | } 108 | 109 | -------------------------------------------------------------------------------- /lib/MtHaml/NodeVisitor/Midblock.php: -------------------------------------------------------------------------------- 1 | midblockRegex = $midblockRegex; 14 | $this->skip = new \SplObjectStorage; 15 | } 16 | 17 | public function enterRun(Run $node) 18 | { 19 | do { 20 | if (null === $prev = $node->getPreviousSibling()) { 21 | break; 22 | } 23 | if (!$prev instanceof Run) { 24 | break; 25 | } 26 | if (!preg_match($this->midblockRegex, $node->getContent())) { 27 | break; 28 | } 29 | 30 | $node->getParent()->removeChild($node); 31 | while (null !== $prev->getMidblock()) { 32 | $prev = $prev->getMidblock(); 33 | } 34 | $prev->setMidblock($node); 35 | } while (false); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /lib/MtHaml/NodeVisitor/NodeVisitorAbstract.php: -------------------------------------------------------------------------------- 1 | ", $string); 20 | } 21 | 22 | protected function stringLiteral($string) 23 | { 24 | return var_export((string)$string, true); 25 | } 26 | 27 | public function enterInterpolatedString(InterpolatedString $node) 28 | { 29 | if (!$this->isEchoMode() && 1 < count($node->getChilds())) { 30 | $this->raw('('); 31 | } 32 | } 33 | 34 | public function betweenInterpolatedStringChilds(InterpolatedString $node) 35 | { 36 | if (!$this->isEchoMode()) { 37 | $this->raw(' . '); 38 | } 39 | } 40 | 41 | public function leaveInterpolatedString(InterpolatedString $node) 42 | { 43 | if (!$this->isEchoMode() && 1 < count($node->getChilds())) { 44 | $this->raw(')'); 45 | } 46 | } 47 | 48 | public function enterInsert(Insert $node) 49 | { 50 | $content = $node->getContent(); 51 | $content = $this->trimInlineComments($content); 52 | 53 | if ($this->isEchoMode()) { 54 | $fmt = ''; 55 | 56 | if ($node->getEscaping()->isEnabled()) { 57 | if ($node->getEscaping()->isOnce()) { 58 | $fmt = ""; 59 | } else { 60 | $fmt = ""; 61 | } 62 | } 63 | $this->addDebugInfos($node); 64 | $this->raw(sprintf($fmt, $content, $this->charset)); 65 | } else { 66 | $content = $node->getContent(); 67 | if (!preg_match('~^\$?[a-zA-Z0-9_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$~', $content)) { 68 | $this->raw('(' . $content . ')'); 69 | } else { 70 | $this->raw($content); 71 | } 72 | } 73 | } 74 | 75 | public function enterTopBlock(Run $node) 76 | { 77 | $this->addDebugInfos($node); 78 | 79 | $content = $this->trimInlineComments($node->getContent()); 80 | 81 | if (!$node->isBlock()) { 82 | if (preg_match('~[:;]\s*$~', $content)) { 83 | $this->write(sprintf('' , $content)); 84 | } else { 85 | $this->write(sprintf('' , $content)); 86 | } 87 | } else { 88 | $this->write(sprintf('' , $content)); 89 | } 90 | } 91 | 92 | public function enterMidBlock(Run $node) 93 | { 94 | $this->addDebugInfos($node); 95 | 96 | $content = $this->trimInlineComments($node->getContent()); 97 | 98 | $this->write(sprintf('' , $content)); 99 | } 100 | 101 | public function leaveTopBlock(Run $node) 102 | { 103 | if ($node->isBlock()) { 104 | $this->write(''); 105 | } 106 | } 107 | 108 | public function enterObjectRefClass(ObjectRefClass $node) 109 | { 110 | if ($this->isEchoMode()) { 111 | $this->raw('raw('MtHaml\Runtime::renderObjectRefClass('); 114 | 115 | $this->pushEchoMode(false); 116 | } 117 | 118 | public function leaveObjectRefClass(ObjectRefClass $node) 119 | { 120 | $this->raw(')'); 121 | 122 | $this->popEchoMode(true); 123 | if ($this->isEchoMode()) { 124 | $this->raw('; ?>'); 125 | } 126 | } 127 | 128 | public function enterObjectRefId(ObjectRefId $node) 129 | { 130 | if ($this->isEchoMode()) { 131 | $this->raw('raw('MtHaml\Runtime::renderObjectRefId('); 134 | 135 | $this->pushEchoMode(false); 136 | } 137 | 138 | public function leaveObjectRefId(ObjectRefId $node) 139 | { 140 | $this->raw(')'); 141 | 142 | $this->popEchoMode(true); 143 | if ($this->isEchoMode()) { 144 | $this->raw('; ?>'); 145 | } 146 | } 147 | 148 | public function enterObjectRefPrefix(NodeAbstract $node) 149 | { 150 | $this->raw(', '); 151 | } 152 | 153 | protected function writeDebugInfos($lineno) 154 | { 155 | } 156 | 157 | protected function renderDynamicAttributes(Tag $tag) 158 | { 159 | $list = array(); 160 | $n = 0; 161 | 162 | $this->raw(' setEchoMode(false); 165 | 166 | foreach ($tag->getAttributes() as $attr) { 167 | 168 | if (0 !== $n) { 169 | $this->raw(', '); 170 | } 171 | 172 | if ($attr instanceof TagAttributeInterpolation) { 173 | $this->raw('MtHaml\Runtime\AttributeInterpolation::create('); 174 | $attr->getValue()->accept($this); 175 | $this->raw(')'); 176 | } else if ($attr instanceof TagAttributeList) { 177 | $this->raw('MtHaml\Runtime\AttributeList::create('); 178 | $attr->getValue()->accept($this); 179 | $this->raw(')'); 180 | } else { 181 | $this->raw('array('); 182 | $attr->getName()->accept($this); 183 | $this->raw(', '); 184 | if ($value = $attr->getValue()) { 185 | $attr->getValue()->accept($this); 186 | } else { 187 | $this->raw('TRUE'); 188 | } 189 | $this->raw(')'); 190 | } 191 | 192 | ++$n; 193 | } 194 | 195 | $this->raw(')'); 196 | 197 | $this->setEchoMode(true); 198 | 199 | $this->raw(', '); 200 | $this->raw($this->stringLiteral($this->env->getOption('format'))); 201 | $this->raw(', '); 202 | $this->raw($this->stringLiteral($this->charset)); 203 | 204 | $this->raw('); ?>'); 205 | } 206 | 207 | public function trimInlineComments($code) 208 | { 209 | // Removes inlines comments ('//' and '#'), while ignoring '//' and '#' 210 | // embedded in quoted strings. 211 | 212 | $re = "! 213 | (?P 214 | (?P(?: 215 | # anything except \", ', ` 216 | [^\"'`] 217 | 218 | # double quoted string 219 | | \"(?: [^\"\\\\]+ | \\\\. )*\" 220 | 221 | # single quoted string 222 | | '(?: [^'\\\\]+ | \\\\. )*' 223 | 224 | # backticks string 225 | | `(?: [^`\\\\]+ | \\\\. )*` 226 | )+?) 227 | ) 228 | (?P\s*(?://|\#).*)? 229 | $!xA"; 230 | 231 | return preg_replace($re, '$1', $code); 232 | } 233 | } 234 | 235 | -------------------------------------------------------------------------------- /lib/MtHaml/NodeVisitor/Printer.php: -------------------------------------------------------------------------------- 1 | output; 27 | } 28 | 29 | protected function indent() 30 | { 31 | $this->indent += 1; 32 | return $this; 33 | } 34 | 35 | protected function undent() 36 | { 37 | $this->indent -= 1; 38 | return $this; 39 | } 40 | 41 | protected function write($string, $indent = true, $break = true) 42 | { 43 | if ($indent) { 44 | $this->writeIndentation(); 45 | } 46 | $this->raw($string); 47 | if ($break) { 48 | $this->output .= "\n"; 49 | } 50 | return $this; 51 | } 52 | 53 | protected function raw($string) 54 | { 55 | $this->output .= $string; 56 | return $this; 57 | } 58 | 59 | protected function writeIndentation() 60 | { 61 | $this->output .= str_repeat(' ', $this->indent * 2); 62 | return $this; 63 | } 64 | 65 | 66 | public function enterRoot(Root $node) 67 | { 68 | $this->write('root(')->indent(); 69 | } 70 | public function leaveRoot(Root $node) 71 | { 72 | $this->undent()->write(')'); 73 | } 74 | 75 | public function enterTag(Tag $node) 76 | { 77 | $name = $node->getTagName(); 78 | $flags = $node->getFlags(); 79 | if ($flags & Tag::FLAG_REMOVE_INNER_WHITESPACES) { 80 | $name .= '<'; 81 | } 82 | if ($flags & Tag::FLAG_REMOVE_OUTER_WHITESPACES) { 83 | $name .= '>'; 84 | } 85 | if ($flags & Tag::FLAG_SELF_CLOSE) { 86 | $name .= '/'; 87 | } 88 | 89 | $this->write('tag(' . $name, true, false) 90 | ->indent(); 91 | 92 | if ($node->hasContent()) { 93 | $this->raw(' '); 94 | $node->getContent()->accept($this); 95 | } 96 | 97 | if ($node->hasAttributes() || $node->hasChilds()) { 98 | $this->raw("\n"); 99 | } 100 | } 101 | 102 | public function enterTagContent(Tag $node) 103 | { 104 | return false; 105 | } 106 | 107 | public function leaveTag(Tag $node) 108 | { 109 | $this->undent()->write(')', $node->hasAttributes()||$node->hasChilds()); 110 | } 111 | 112 | public function enterTagAttribute(TagAttribute $node) 113 | { 114 | $this->write('attr(', true, false); 115 | } 116 | 117 | public function leaveTagAttribute(TagAttribute $node) 118 | { 119 | $this->write(')', false, true); 120 | } 121 | 122 | public function enterStatement(Statement $node) 123 | { 124 | $this->write('', true, false); 125 | } 126 | 127 | public function leaveStatement(Statement $node) 128 | { 129 | $this->write('', false, true); 130 | } 131 | 132 | public function enterText(Text $node) 133 | { 134 | $content = $node->getContent(); 135 | 136 | $escaping = $node->getEscaping(); 137 | if (true === $escaping->isEnabled()) { 138 | $flag = '&'; 139 | if ($node->getEscaping()->isOnce()) { 140 | $flag .= '!'; 141 | } 142 | $content = $flag . $content; 143 | } else if (false === $escaping->isEnabled()) { 144 | $content = '!' . $content; 145 | } 146 | 147 | $this->raw('text('.$content.')'); 148 | } 149 | 150 | public function enterInsert(Insert $node) 151 | { 152 | $content = $node->getContent(); 153 | 154 | $escaping = $node->getEscaping(); 155 | if (true === $escaping->isEnabled()) { 156 | $flag = '&'; 157 | if ($node->getEscaping()->isOnce()) { 158 | $flag .= '!'; 159 | } 160 | $content = $flag . $content; 161 | } else if (false === $escaping->isEnabled()) { 162 | $content = '!' . $content; 163 | } 164 | 165 | $this->raw('insert('.$content.')'); 166 | } 167 | 168 | public function enterRun(Run $node) 169 | { 170 | $this->write('run(' . $node->getContent(), true, $node->hasChilds()) 171 | ->indent(); 172 | } 173 | 174 | public function enterRunMidblock(Run $node) 175 | { 176 | if ($node->hasMidblock()) { 177 | $this->write('midblock(')->indent(); 178 | } 179 | } 180 | 181 | public function leaveRunMidblock(Run $node) 182 | { 183 | if ($node->hasMidblock()) { 184 | $this->undent()->write(')'); 185 | } 186 | } 187 | 188 | public function leaveRun(Run $node) 189 | { 190 | $this->undent()->write(')', $node->hasChilds()); 191 | } 192 | 193 | public function enterInterpolatedString(InterpolatedString $node) 194 | { 195 | $this->raw('interpolated('); 196 | } 197 | 198 | public function leaveInterpolatedString(InterpolatedString $node) 199 | { 200 | $this->raw(')'); 201 | } 202 | 203 | public function enterComment(Comment $node) 204 | { 205 | $this->write('comment(' . $node->getCondition(), true, false)->indent(); 206 | } 207 | 208 | public function enterCommentChilds(Comment $node) 209 | { 210 | if ($node->hasChilds()) { 211 | $this->raw("\n"); 212 | } 213 | } 214 | 215 | public function leaveComment(Comment $node) 216 | { 217 | $this->undent()->write(')', $node->hasChilds()); 218 | } 219 | 220 | public function enterDoctype(Doctype $doctype) 221 | { 222 | $str = 'doctype('; 223 | $str .= $doctype->getDoctypeId() ?: 'default'; 224 | if ($options = $doctype->getOptions()) { 225 | $str .= ', ' . $options; 226 | } 227 | $str .= ')'; 228 | $this->write($str); 229 | } 230 | 231 | public function enterFilter(Filter $node) 232 | { 233 | $this->write('filter(' . $node->getFilter())->indent(); 234 | } 235 | 236 | public function leaveFilter(Filter $node) 237 | { 238 | $this->undent()->write(')'); 239 | } 240 | 241 | public function enterObjectRefClass(ObjectRefClass $node) 242 | { 243 | $this->raw('object_ref_class('); 244 | } 245 | 246 | public function leaveObjectRefClass(ObjectRefClass $node) 247 | { 248 | $this->raw(')'); 249 | } 250 | 251 | public function enterObjectRefId(ObjectRefId $node) 252 | { 253 | $this->raw('object_ref_id('); 254 | } 255 | 256 | public function leaveObjectRefId(ObjectRefId $node) 257 | { 258 | $this->raw(')'); 259 | } 260 | 261 | } 262 | 263 | -------------------------------------------------------------------------------- /lib/MtHaml/NodeVisitor/RendererAbstract.php: -------------------------------------------------------------------------------- 1 | in the PHP renderer. 41 | * 42 | * In non echo mode, nodes are rendered as rvalue (e.g. for assignment or 43 | * argument passing). 44 | */ 45 | protected $echoMode = true; 46 | protected $echoModeStack = array(); 47 | 48 | public function __construct(Environment $env) 49 | { 50 | $this->env = $env; 51 | $this->charset = $env->getOption('charset'); 52 | } 53 | 54 | public function getOutput() 55 | { 56 | return $this->output; 57 | } 58 | 59 | protected function indent() 60 | { 61 | $this->indent += 1; 62 | return $this; 63 | } 64 | 65 | protected function undent() 66 | { 67 | $this->indent -= 1; 68 | return $this; 69 | } 70 | 71 | protected function write($string, $indent = true, $break = true) 72 | { 73 | if ($indent) { 74 | $this->writeIndentation(); 75 | } 76 | $this->raw($string); 77 | $this->lineno += substr_count($string, "\n"); 78 | if ($break) { 79 | $this->output .= "\n"; 80 | $this->lineno++; 81 | } 82 | return $this; 83 | } 84 | 85 | protected function raw($string) 86 | { 87 | $this->output .= $string; 88 | $this->lineno += substr_count($string, "\n"); 89 | return $this; 90 | } 91 | 92 | protected function writeIndentation() 93 | { 94 | $this->output .= str_repeat(' ', $this->indent * 2); 95 | return $this; 96 | } 97 | 98 | protected function addDebugInfos(NodeAbstract $node) 99 | { 100 | if ($this->lineno != $node->getLineno() + $this->lineOffset) { 101 | $this->writeDebugInfos($node->getLineno()); 102 | $this->lineOffset = $this->lineno - $node->getLineno(); 103 | } 104 | } 105 | 106 | abstract protected function writeDebugInfos($lineno); 107 | 108 | abstract protected function escapeLanguage($string); 109 | 110 | abstract protected function stringLiteral($string); 111 | 112 | abstract protected function betweenInterpolatedStringChilds(InterpolatedString $node); 113 | 114 | protected function escapeHtml($string, $double = true) 115 | { 116 | return htmlspecialchars($string, ENT_QUOTES, $this->charset, $double); 117 | } 118 | 119 | public function enterTag(Tag $node) 120 | { 121 | $indent = $this->shouldIndentBeforeOpen($node); 122 | 123 | $this->write(sprintf('<%s', $node->getTagName()), $indent, false); 124 | } 125 | 126 | public function enterTagAttributes(Tag $node) 127 | { 128 | $hasDynAttr = false; 129 | 130 | foreach ($node->getAttributes() as $attr) { 131 | $nameNode = $attr->getName(); 132 | $valueNode = $attr->getValue(); 133 | 134 | if ($attr instanceof TagAttributeList) { 135 | $hasDynAttr = true; 136 | break; 137 | } 138 | if ($nameNode && (!$nameNode->isConst() || !$valueNode || !$valueNode->isConst())) { 139 | $hasDynAttr = true; 140 | break; 141 | } 142 | } 143 | 144 | if (!$hasDynAttr) { 145 | return; 146 | } 147 | 148 | $this->renderDynamicAttributes($node); 149 | 150 | return false; 151 | } 152 | 153 | public function leaveTagAttributes(Tag $node) 154 | { 155 | $close = $node->getFlags() & Tag::FLAG_SELF_CLOSE; 156 | 157 | if ($close) { 158 | $break = $this->shouldBreakAfterClose($node); 159 | } else { 160 | $break = $this->shouldBreakAfterOpen($node); 161 | } 162 | 163 | $this->write(($close ? ' /' : '') . '>', false, $break); 164 | 165 | if (!$close && $break) { 166 | $this->indent(); 167 | } 168 | } 169 | 170 | public function enterTagAttributeName(TagAttribute $node) 171 | { 172 | $this->raw(' '); 173 | } 174 | 175 | public function enterTagAttributeValue(TagAttribute $node) 176 | { 177 | $this->raw('="'); 178 | } 179 | 180 | public function leaveTagAttributeValue(TagAttribute $node) 181 | { 182 | $this->raw('"'); 183 | } 184 | 185 | public function enterTagAttributeInterpolation(TagAttributeInterpolation $node) 186 | { 187 | $this->raw(' '); 188 | } 189 | 190 | public function leaveTag(Tag $node) 191 | { 192 | if ($node->getFlags() & Tag::FLAG_SELF_CLOSE) { 193 | return; 194 | } 195 | 196 | $indent = $this->shouldIndentBeforeClose($node); 197 | $break = $this->shouldBreakAfterClose($node); 198 | 199 | if ($this->shouldBreakAfterOpen($node)) { 200 | $this->undent(); 201 | } 202 | 203 | $this->write(sprintf('', $node->getTagName()), $indent, $break); 204 | } 205 | 206 | public function enterStatement(Statement $node) 207 | { 208 | if ($this->shouldIndentBeforeOpen($node)) { 209 | $this->writeIndentation(); 210 | } 211 | } 212 | 213 | public function leaveStatement(Statement $node) 214 | { 215 | if ($this->shouldBreakAfterClose($node)) { 216 | $this->raw("\n"); 217 | } 218 | } 219 | 220 | public function enterText(Text $node) 221 | { 222 | $string = $node->getContent(); 223 | 224 | if ($this->isEchoMode()) { 225 | if ($node->getEscaping()->isEnabled()) { 226 | $once = $node->getEscaping()->isOnce(); 227 | $string = $this->escapeHtml($string, !$once); 228 | } 229 | 230 | $string = $this->escapeLanguage($string); 231 | $this->raw($string); 232 | } else { 233 | $string = $this->stringLiteral($string); 234 | $this->raw($string); 235 | } 236 | } 237 | 238 | public function enterInterpolatedStringChilds(InterpolatedString $node) 239 | { 240 | $n = 0; 241 | 242 | foreach ($node->getChilds() as $child) { 243 | if (0 !== $n) { 244 | $this->betweenInterpolatedStringChilds($node); 245 | } 246 | $child->accept($this); 247 | ++$n; 248 | } 249 | 250 | return false; 251 | } 252 | 253 | public function enterDoctype(Doctype $node) 254 | { 255 | $doctype = $node->getDoctype($this->env->getOption('format')); 256 | $this->write($this->escapeLanguage($doctype)); 257 | } 258 | 259 | public function enterComment(Comment $comment) 260 | { 261 | if (!$comment->isRendered()) { 262 | return false; 263 | } 264 | 265 | if ($comment->hasCondition()) { 266 | $open = ''; 286 | } else { 287 | $close = '-->'; 288 | } 289 | 290 | if ($comment->hasContent()) { 291 | $this->write(' ' . $close, false, $comment->hasParent()); 292 | } else if ($comment->hasChilds()) { 293 | $this->undent()->write($close, true, true); 294 | } 295 | } 296 | 297 | public function enterFilter(Filter $node) 298 | { 299 | // TODO: make filters modular 300 | 301 | switch($node->getFilter()) { 302 | case 'javascript': 303 | $this->write(''); 330 | break; 331 | case 'css': 332 | $this->undent() 333 | ->write('/*]]>*/') 334 | ->write(''); 335 | break; 336 | case 'plain': 337 | break; 338 | case 'preserve': 339 | $this->indent = array_pop($this->savedIndent); 340 | break; 341 | } 342 | } 343 | 344 | public function enterRun(Run $node) 345 | { 346 | $isMidBlock = $this->midblock[0]; 347 | array_unshift($this->midblock, false); 348 | 349 | if (!$isMidBlock) { 350 | $this->enterTopblock($node); 351 | } else { 352 | $this->enterMidblock($node); 353 | } 354 | } 355 | 356 | public function enterRunChilds(Run $node) 357 | { 358 | $this->indent(); 359 | } 360 | 361 | public function leaveRunChilds(Run $node) 362 | { 363 | $this->undent(); 364 | } 365 | 366 | public function enterRunMidblock(Run $node) 367 | { 368 | array_unshift($this->midblock, true); 369 | } 370 | 371 | public function leaveRunMidblock(Run $node) 372 | { 373 | array_shift($this->midblock); 374 | } 375 | 376 | public function leaveRun(Run $node) 377 | { 378 | array_shift($this->midblock); 379 | 380 | if (!$this->midblock[0]) { 381 | $this->leaveTopblock($node); 382 | } else { 383 | $this->leaveMidblock($node); 384 | } 385 | } 386 | 387 | public function enterTopblock(Run $node) 388 | { 389 | } 390 | public function leaveTopblock(Run $node) 391 | { 392 | } 393 | public function enterMidblock(Run $node) 394 | { 395 | } 396 | public function leaveMidblock(Run $node) 397 | { 398 | } 399 | 400 | protected function getParentIfFirstChild(NodeAbstract $node) 401 | { 402 | if (null !== $node->getPreviousSibling()) { 403 | return; 404 | } 405 | return $this->getParentTag($node); 406 | } 407 | 408 | protected function getParentIfLastChild(NodeAbstract $node) 409 | { 410 | if (null !== $node->getNextSibling()) { 411 | return; 412 | } 413 | return $this->getParentTag($node); 414 | } 415 | 416 | protected function getParentTag(NodeAbstract $node) 417 | { 418 | if (null !== $parent = $node->getParent()) { 419 | if ($parent instanceof Tag) { 420 | return $parent; 421 | } 422 | } 423 | } 424 | 425 | protected function getFirstChildIfTag(NodeAbstract $node) 426 | { 427 | if (!($node instanceof NestInterface)) { 428 | return; 429 | } 430 | if (null === $first = $node->getFirstChild()) { 431 | return; 432 | } 433 | if (!($first instanceof Tag)) { 434 | return; 435 | } 436 | return $first; 437 | } 438 | 439 | protected function getLastChildIfTag(NodeAbstract $node) 440 | { 441 | if (!($node instanceof NestInterface)) { 442 | return; 443 | } 444 | if (null === $last = $node->getLastChild()) { 445 | return; 446 | } 447 | if (!($last instanceof Tag)) { 448 | return; 449 | } 450 | return $last; 451 | } 452 | 453 | protected function getPreviousIfTag(NodeAbstract $node) 454 | { 455 | if (null === $tag = $node->getPreviousSibling()) { 456 | return; 457 | } 458 | if (!($tag instanceof Tag)) { 459 | return; 460 | } 461 | return $tag; 462 | } 463 | 464 | protected function getNextIfTag(NodeAbstract $node) 465 | { 466 | if (null === $tag = $node->getNextSibling()) { 467 | return; 468 | } 469 | if (!($tag instanceof Tag)) { 470 | return; 471 | } 472 | return $tag; 473 | } 474 | 475 | protected function shouldIndentBeforeOpen(NodeAbstract $node) 476 | { 477 | if (null !== $parent = $this->getParentIfFirstChild($node)) { 478 | if ($parent->getFlags() & Tag::FLAG_REMOVE_INNER_WHITESPACES) { 479 | return false; 480 | } 481 | } 482 | if ($node instanceof Tag) { 483 | if ($node->getFlags() & Tag::FLAG_REMOVE_OUTER_WHITESPACES) { 484 | return false; 485 | } 486 | } 487 | if (null !== $prev = $this->getPreviousIfTag($node)) { 488 | if ($prev->getFlags() & Tag::FLAG_REMOVE_OUTER_WHITESPACES) { 489 | return false; 490 | } 491 | } 492 | return true; 493 | } 494 | 495 | protected function shouldBreakAfterOpen(NodeAbstract $node) 496 | { 497 | if ($node instanceof Tag) { 498 | if ($node->getFlags() & Tag::FLAG_REMOVE_INNER_WHITESPACES) { 499 | return false; 500 | } 501 | if (!$node->hasChilds()) { 502 | return false; 503 | } 504 | } 505 | if (null !== $child = $this->getFirstChildIfTag($node)) { 506 | if ($child->getFlags() & Tag::FLAG_REMOVE_OUTER_WHITESPACES) { 507 | return false; 508 | } 509 | } 510 | 511 | return true; 512 | } 513 | 514 | protected function shouldIndentBeforeClose(NodeAbstract $node) 515 | { 516 | if ($node instanceof Tag) { 517 | if ($node->getFlags() & Tag::FLAG_REMOVE_INNER_WHITESPACES) { 518 | return false; 519 | } 520 | if (!$node->hasChilds()) { 521 | return false; 522 | } 523 | } 524 | if (null !== $child = $this->getLastChildIfTag($node)) { 525 | if ($child->getFlags() & Tag::FLAG_REMOVE_OUTER_WHITESPACES) { 526 | return false; 527 | } 528 | } 529 | return true; 530 | } 531 | 532 | protected function shouldBreakAfterClose(NodeAbstract $node) 533 | { 534 | if (null !== $parent = $this->getParentIfLastChild($node)) { 535 | if ($parent->getFlags() & Tag::FLAG_REMOVE_INNER_WHITESPACES) { 536 | return false; 537 | } 538 | } 539 | if (null !== $next = $this->getNextIfTag($node)) { 540 | if ($next->getFlags() & Tag::FLAG_REMOVE_OUTER_WHITESPACES) { 541 | return false; 542 | } 543 | } 544 | if ($node instanceof Tag) { 545 | if ($node->getFlags() & Tag::FLAG_REMOVE_OUTER_WHITESPACES) { 546 | return false; 547 | } 548 | } 549 | return true; 550 | } 551 | 552 | public function setEchoMode($enabled) 553 | { 554 | $this->echoMode = $enabled; 555 | } 556 | 557 | public function isEchoMode() 558 | { 559 | return $this->echoMode; 560 | } 561 | 562 | public function pushEchoMode($enabled) 563 | { 564 | $this->echoModeStack[] = $this->echoMode; 565 | $this->setEchoMode($enabled); 566 | } 567 | 568 | public function popEchoMode() 569 | { 570 | $this->echoMode = array_pop($this->echoModeStack); 571 | } 572 | } 573 | 574 | -------------------------------------------------------------------------------- /lib/MtHaml/NodeVisitor/TwigRenderer.php: -------------------------------------------------------------------------------- 1 | isEchoMode() && 1 < count($node->getChilds())) { 30 | $this->raw('('); 31 | } 32 | } 33 | 34 | public function betweenInterpolatedStringChilds(InterpolatedString $node) 35 | { 36 | if (!$this->isEchoMode()) { 37 | $this->raw(' ~ '); 38 | } 39 | } 40 | 41 | public function leaveInterpolatedString(InterpolatedString $node) 42 | { 43 | if (!$this->isEchoMode() && 1 < count($node->getChilds())) { 44 | $this->raw(')'); 45 | } 46 | } 47 | 48 | public function enterInsert(Insert $node) 49 | { 50 | if ($this->isEchoMode()) { 51 | $escaping = $node->getEscaping()->isEnabled(); 52 | if (true === $escaping) { 53 | $fmt = '{{ (%s)|escape }}'; 54 | } else if (false === $escaping) { 55 | $fmt = '{{ (%s)|raw }}'; 56 | } else { 57 | $fmt = '{{ %s }}'; 58 | } 59 | $this->addDebugInfos($node); 60 | $this->raw(sprintf($fmt, $node->getContent())); 61 | } else { 62 | $content = $node->getContent(); 63 | if (!preg_match('~^[a-zA-Z0-9_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$~', $content)) { 64 | $this->raw('(' . $node->getContent() . ')'); 65 | } else { 66 | $this->raw($node->getContent()); 67 | } 68 | } 69 | } 70 | 71 | public function enterTopblock(Run $node) 72 | { 73 | $this->renderBlockTop($node); 74 | } 75 | 76 | public function enterMidblock(Run $node) 77 | { 78 | $this->renderBlockTop($node); 79 | } 80 | 81 | public function leaveTopBlock(Run $node) 82 | { 83 | if ($node->isBlock()) { 84 | if (preg_match('~^(?:-\s*)?(\w+)~', $node->getContent(), $match)) { 85 | $this->write($this->renderTag('end'.$match[1])); 86 | } 87 | } 88 | } 89 | 90 | protected function renderBlockTop(Run $node) 91 | { 92 | $this->addDebugInfos($node); 93 | $this->write($this->renderTag($node->getContent())); 94 | } 95 | 96 | public function enterObjectRefClass(ObjectRefClass $node) 97 | { 98 | if ($this->isEchoMode()) { 99 | $this->raw('{{ '); 100 | } 101 | $this->raw('mthaml_object_ref_class('); 102 | 103 | $this->pushEchoMode(false); 104 | } 105 | 106 | public function leaveObjectRefClass(ObjectRefClass $node) 107 | { 108 | $this->raw(')'); 109 | 110 | $this->popEchoMode(true); 111 | if ($this->isEchoMode()) { 112 | $this->raw(' }}'); 113 | } 114 | } 115 | 116 | public function enterObjectRefId(ObjectRefId $node) 117 | { 118 | if ($this->isEchoMode()) { 119 | $this->raw('{{ '); 120 | } 121 | $this->raw('mthaml_object_ref_id('); 122 | 123 | $this->pushEchoMode(false); 124 | } 125 | 126 | public function leaveObjectRefId(ObjectRefId $node) 127 | { 128 | $this->raw(')'); 129 | 130 | $this->popEchoMode(true); 131 | if ($this->isEchoMode()) { 132 | $this->raw(' }}'); 133 | } 134 | } 135 | 136 | public function enterObjectRefPrefix(NodeAbstract $node) 137 | { 138 | $this->raw(', '); 139 | } 140 | 141 | 142 | 143 | protected function renderTag($content) 144 | { 145 | $prefix = ' '; 146 | $suffix = ' '; 147 | 148 | if (preg_match('/^-/', $content)) { 149 | $prefix = ''; 150 | } 151 | if (preg_match('/-$/', $content)) { 152 | $suffix = ''; 153 | } 154 | 155 | return sprintf('{%%%s%s%s%%}', $prefix, $content, $suffix); 156 | } 157 | 158 | protected function writeDebugInfos($lineno) 159 | { 160 | $infos = sprintf('{%% line %d %%}', $lineno); 161 | $this->raw($infos); 162 | } 163 | 164 | protected function renderDynamicAttributes(Tag $tag) 165 | { 166 | $list = array(); 167 | 168 | $this->raw(' '); 169 | 170 | foreach ($tag->getAttributes() as $attr) { 171 | $this->addDebugInfos($attr); 172 | break; 173 | } 174 | 175 | $this->raw('{{ mthaml_attributes(['); 176 | 177 | $this->setEchoMode(false); 178 | 179 | foreach (array_values($tag->getAttributes()) as $i => $attr) { 180 | 181 | if (0 !== $i) { 182 | $this->raw(', '); 183 | } 184 | 185 | if ($attr instanceof TagAttributeInterpolation) { 186 | $this->raw('mthaml_attribute_interpolation('); 187 | $attr->getValue()->accept($this); 188 | $this->raw(')'); 189 | } else if ($attr instanceof TagAttributeList) { 190 | $this->raw('mthaml_attribute_list('); 191 | $attr->getValue()->accept($this); 192 | $this->raw(')'); 193 | } else { 194 | $this->raw('['); 195 | $attr->getName()->accept($this); 196 | $this->raw(', '); 197 | if ($value = $attr->getValue()) { 198 | $attr->getValue()->accept($this); 199 | } else { 200 | $this->raw('true'); 201 | } 202 | $this->raw(']'); 203 | } 204 | } 205 | 206 | $this->raw(']'); 207 | 208 | $this->setEchoMode(true); 209 | 210 | $this->raw(', '); 211 | $this->raw($this->stringLiteral($this->env->getOption('format'))); 212 | $this->raw(', '); 213 | $this->raw($this->stringLiteral($this->charset)); 214 | 215 | $this->raw(')|raw }}'); 216 | } 217 | } 218 | 219 | -------------------------------------------------------------------------------- /lib/MtHaml/Parser/Buffer.php: -------------------------------------------------------------------------------- 1 | lines = preg_split('~\r\n|\n|\r~', $string); 16 | $this->lineno = $lineno - 1; 17 | } 18 | 19 | public function nextLine() 20 | { 21 | $this->line = array_shift($this->lines); 22 | if (null !== $this->line) { 23 | ++$this->lineno; 24 | $this->column = 1; 25 | return true; 26 | } 27 | return false; 28 | } 29 | 30 | public function peekLine() 31 | { 32 | if (isset($this->lines[0])) { 33 | return $this->lines[0]; 34 | } 35 | } 36 | 37 | public function replaceLine($string) 38 | { 39 | $this->line = $string; 40 | } 41 | 42 | public function isEol() 43 | { 44 | return $this->line === ''; 45 | } 46 | 47 | public function peekChar() 48 | { 49 | if (isset($this->line[0])) { 50 | return $this->line[0]; 51 | } 52 | } 53 | 54 | public function eatChar() 55 | { 56 | if (isset($this->line[0])) { 57 | $char = $this->line[0]; 58 | $this->line = (string) substr($this->line, 1); 59 | ++$this->column; 60 | return $char; 61 | } 62 | } 63 | 64 | public function eatChars($n) 65 | { 66 | $chars = (string) substr($this->line, 0, $n); 67 | $this->line = (string) substr($this->line, $n); 68 | $this->column += strlen($chars); 69 | return $chars; 70 | } 71 | 72 | public function match($pattern, &$match = null, $eat = true) 73 | { 74 | if ($count = preg_match($pattern, $this->line, $match, PREG_OFFSET_CAPTURE)) { 75 | $column = $match[0][1]; 76 | $pos = array(); 77 | 78 | foreach($match as $key => &$capture) { 79 | $pos[$key] = array( 80 | 'lineno' => $this->lineno, 81 | 'column' => $capture[1], 82 | ); 83 | $capture = $capture[0]; 84 | } 85 | unset($capture); // ref 86 | 87 | $match['pos'] = $pos; 88 | 89 | if ($eat) { 90 | $this->eat($match[0]); 91 | } 92 | } 93 | return $count > 0; 94 | } 95 | 96 | public function eat($string) 97 | { 98 | $this->line = (string) substr($this->line, strlen($string)); 99 | $this->column += strlen($string); 100 | } 101 | 102 | public function skipWs() 103 | { 104 | $this->match('~[ \t]+~A'); 105 | } 106 | 107 | public function getColumn() 108 | { 109 | return $this->column; 110 | } 111 | 112 | public function getLineno() 113 | { 114 | return $this->lineno; 115 | } 116 | 117 | public function getPosition() 118 | { 119 | return array( 120 | 'lineno' => $this->lineno, 121 | 'column' => $this->column, 122 | ); 123 | } 124 | 125 | public function getLine() 126 | { 127 | return $this->line; 128 | } 129 | } 130 | 131 | -------------------------------------------------------------------------------- /lib/MtHaml/Runtime.php: -------------------------------------------------------------------------------- 1 | attributes); 41 | continue; 42 | } 43 | 44 | list ($name, $value) = $item; 45 | 46 | if ('data' === $name) { 47 | self::renderDataAttributes($attributes, $value); 48 | } else if ('id' === $name) { 49 | $value = self::renderJoinedValue($value, '_'); 50 | if (null !== $value) { 51 | if (isset($attributes['id'])) { 52 | $attributes['id'] .= '_' . $value; 53 | } else { 54 | $attributes['id'] = $value; 55 | } 56 | } 57 | } else if ('class' === $name) { 58 | $value = self::renderJoinedValue($value, ' '); 59 | if (null !== $value) { 60 | if (isset($attributes['class'])) { 61 | $attributes['class'] .= ' ' . $value; 62 | } else { 63 | $attributes['class'] = $value; 64 | } 65 | } 66 | } else if (true === $value) { 67 | if ('html5' === $format) { 68 | $attributes[$name] = true; 69 | } else { 70 | $attributes[$name] = $name; 71 | } 72 | } else if (false === $value || null === $value) { 73 | // do not output 74 | } else { 75 | if (isset($attributes[$name])) { 76 | // so that next assignment puts the attribute 77 | // at the end for the array 78 | unset($attributes[$name]); 79 | } 80 | $attributes[$name] = $value; 81 | } 82 | } 83 | 84 | $result = null; 85 | 86 | foreach ($attributes as $name => $value) { 87 | if (null !== $result) { 88 | $result .= ' '; 89 | } 90 | if ($value instanceof AttributeInterpolation) { 91 | $result .= $value->value; 92 | } else if (true === $value) { 93 | $result .= 94 | htmlspecialchars($name, ENT_QUOTES, $charset); 95 | } else { 96 | $result .= 97 | htmlspecialchars($name, ENT_QUOTES, $charset) 98 | .'="' 99 | . htmlspecialchars($value, ENT_QUOTES, $charset) 100 | .'"'; 101 | } 102 | } 103 | 104 | return $result; 105 | } 106 | 107 | static private function renderDataAttributes(&$dest, $value, $prefix = 'data') 108 | { 109 | if (\is_array($value) || $value instanceof \Traversable) { 110 | foreach ($value as $subname => $subvalue) { 111 | self::renderDataAttributes($dest, $subvalue, $prefix.'-'.$subname); 112 | } 113 | } else { 114 | if (!isset($dest[$prefix])) { 115 | $dest[$prefix] = $value; 116 | } 117 | } 118 | } 119 | 120 | static private function renderJoinedValue($values, $separator) 121 | { 122 | $result = null; 123 | 124 | if (\is_array($values) || $values instanceof \Traversable) { 125 | foreach ($values as $value) { 126 | if (\is_array($value) || $value instanceof \Traversable) { 127 | $value = self::renderJoinedValue($value, $separator); 128 | } 129 | if (null !== $value && false !== $value) { 130 | if (null !== $result) { 131 | $result .= $separator; 132 | } 133 | $result .= $value; 134 | } 135 | } 136 | } else { 137 | if (null !== $values && false !== $values) { 138 | $result = $values; 139 | } 140 | } 141 | 142 | return $result; 143 | } 144 | 145 | static public function renderObjectRefClass($object, $prefix = null) 146 | { 147 | if (!$object) { 148 | return; 149 | } 150 | 151 | $class = self::getObjectRefClassString($object); 152 | 153 | if (false !== $prefix && null !== $prefix) { 154 | $class = $prefix . '_' . $class; 155 | } 156 | 157 | return $class; 158 | } 159 | 160 | static public function renderObjectRefId($object, $prefix = null) 161 | { 162 | if (!$object) { 163 | return; 164 | } 165 | 166 | $id = null; 167 | 168 | if (\is_callable(array($object, 'getId'))) { 169 | $id = $object->getId(); 170 | } else if (\is_callable(array($object, 'id'))) { 171 | $id = $object->id(); 172 | } 173 | 174 | if (false === $id || null === $id) { 175 | $id = 'new'; 176 | } 177 | 178 | $id = self::getObjectRefClassString($object) . '_' . $id; 179 | 180 | if (false !== $prefix && null !== $prefix) { 181 | $id = $prefix . '_' . $id; 182 | } 183 | 184 | return $id; 185 | } 186 | 187 | static public function getObjectRefClassString($object) 188 | { 189 | $class = self::getObjectRefName($object); 190 | if (false !== $pos = \strrpos($class, '\\')) { 191 | $class = \substr($class, $pos+1); 192 | } 193 | return \strtolower(\preg_replace('#(?<=[a-z])[A-Z]+#', '_$0', $class)); 194 | } 195 | 196 | static public function getObjectRefName($object) 197 | { 198 | return \is_callable(array($object, 'hamlObjectRef')) 199 | ? $object->hamlObjectRef() 200 | : \get_class($object); 201 | } 202 | 203 | } 204 | -------------------------------------------------------------------------------- /lib/MtHaml/Runtime/AttributeInterpolation.php: -------------------------------------------------------------------------------- 1 | value = $value; 13 | return $instance; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/MtHaml/Runtime/AttributeList.php: -------------------------------------------------------------------------------- 1 | attributes = $attributes; 13 | return $instance; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/MtHaml/Support/Twig/Extension.php: -------------------------------------------------------------------------------- 1 | new \Twig_Function_Function('MtHaml\Runtime::renderAttributes'), 11 | 'mthaml_attribute_interpolation' => new \Twig_Function_Function('MtHaml\Runtime\AttributeInterpolation::create'), 12 | 'mthaml_attribute_list' => new \Twig_Function_Function('MtHaml\Runtime\AttributeList::create'), 13 | 'mthaml_object_ref_class' => new \Twig_Function_Function('MtHaml\Runtime::renderObjectRefClass'), 14 | 'mthaml_object_ref_id' => new \Twig_Function_Function('MtHaml\Runtime::renderObjectRefId'), 15 | ); 16 | } 17 | 18 | public function getName() 19 | { 20 | return 'mthaml'; 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /lib/MtHaml/Support/Twig/Loader.php: -------------------------------------------------------------------------------- 1 | env = $env; 15 | $this->loader = $loader; 16 | } 17 | 18 | public function getSource($name) 19 | { 20 | $source = $this->loader->getSource($name); 21 | if (preg_match('#^\s*{%\s*haml\s*%}#', $source, $match)) { 22 | $padding = str_repeat(' ', strlen($match[0])); 23 | $source = $padding . substr($source, strlen($match[0])); 24 | $source = $this->env->compileString($source, $name); 25 | } 26 | return $source; 27 | } 28 | 29 | public function getCacheKey($name) 30 | { 31 | return $this->loader->getCacheKey($name); 32 | } 33 | 34 | public function isFresh($name, $time) 35 | { 36 | return $this->loader->isFresh($name, $time); 37 | } 38 | 39 | public function setPaths($paths) 40 | { 41 | if (method_exists($this->loader, 'setPaths')) { 42 | $this->loader->setPaths($paths); 43 | } 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /lib/MtHaml/Target/Php.php: -------------------------------------------------------------------------------- 1 | '~else\b|else\s*if\b|catch\b~A', 14 | )); 15 | } 16 | 17 | public function getDefaultRendererFactory() 18 | { 19 | return function(Environment $env, array $options) { 20 | return new PhpRenderer($env); 21 | }; 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /lib/MtHaml/Target/TargetAbstract.php: -------------------------------------------------------------------------------- 1 | options = array_merge($this->options, $options); 19 | } 20 | 21 | public function getDefaultParserFactory() 22 | { 23 | return function(Environment $env, array $options) { 24 | return new Parser; 25 | }; 26 | } 27 | 28 | public function getParserFactory() 29 | { 30 | if (null === $this->parserFactory) { 31 | $this->parserFactory = $this->getDefaultParserFactory(); 32 | } 33 | return $this->parserFactory; 34 | } 35 | 36 | public function setParserFactory($factory) 37 | { 38 | $this->parserFactory = $parserFactory; 39 | } 40 | 41 | public function createParser(Environment $env, array $options) 42 | { 43 | return call_user_func($this->getParserFactory(), $env, $options); 44 | } 45 | 46 | abstract public function getDefaultRendererFactory(); 47 | 48 | public function getRendererFactory() 49 | { 50 | if (null === $this->rendererFactory) { 51 | $this->rendererFactory = $this->getDefaultRendererFactory(); 52 | } 53 | return $this->rendererFactory; 54 | } 55 | 56 | public function setRendererFactory($factory) 57 | { 58 | $this->rendererFactory = $factory; 59 | } 60 | 61 | public function createRenderer(Environment $env, array $options) 62 | { 63 | return call_user_func($this->getRendererFactory(), $env, $options); 64 | } 65 | 66 | public function parse(Environment $env, $string, $filename) 67 | { 68 | $parser = $this->createParser($env, $this->options); 69 | return $parser->parse($string, $filename); 70 | } 71 | 72 | public function compile(Environment $env, NodeAbstract $node) 73 | { 74 | $renderer = $this->createRenderer($env, array()); 75 | 76 | $node->accept($renderer); 77 | 78 | return $renderer->getOutput(); 79 | } 80 | 81 | public function getOption($name) 82 | { 83 | return $this->options[$name]; 84 | } 85 | } 86 | 87 | -------------------------------------------------------------------------------- /lib/MtHaml/Target/TargetInterface.php: -------------------------------------------------------------------------------- 1 | '/(?:-\s*)?(?:else\b|elseif\b)/A', 14 | )); 15 | } 16 | 17 | public function getDefaultRendererFactory() 18 | { 19 | return function(Environment $env, array $options) { 20 | return new TwigRenderer($env); 21 | }; 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /lib/MtHaml/compile.php: -------------------------------------------------------------------------------- 1 | false, 'escape_html' => false, 'escape_attrs' => false)); 11 | 12 | echo $haml->getOption("escape_html"); 13 | 14 | $remove_methods = true; 15 | foreach (glob(__DIR__ . "/../../app/views/*.haml") as $file) { 16 | $filename = basename($file); 17 | if($filename !== ""){ 18 | $compiled = $haml->compileString(file_get_contents($file), $filename); 19 | $filename_fixed = str_replace("haml", "php", $filename); 20 | if($remove_methods){ 21 | preg_match_all('/\<\?php echo MtHaml\\\\Runtime::renderAttributes(.*)\?\>/', $compiled, $to_render, PREG_PATTERN_ORDER); 22 | foreach ($to_render[0] as $value) { 23 | $initial_value = $value; 24 | $remove_open_and_close = substr(substr($value, 6), 0, -3); 25 | preg_match_all('/MtHaml\\\\Runtime\\\\AttributeList::create\(\(.*\"\)\)/', $remove_open_and_close, $replace_with_array); 26 | foreach ($replace_with_array as $attribute_list_method) { 27 | if(!empty($attribute_list_method)){ 28 | $item = $attribute_list_method[0]; 29 | $attr = preg_replace('/\"\)\)/', "", preg_replace('/MtHaml\\\\Runtime\\\\AttributeList::create\(\(/', "", $item)); 30 | $remove_quotes = str_replace('"',"", $attr); 31 | $separate_attributes = explode(":", $remove_quotes); 32 | $attributes = array(trim($separate_attributes[0]), trim($separate_attributes[1])); 33 | $value = str_replace($attribute_list_method, $attributes, $value); 34 | 35 | } 36 | } 37 | $to_eval = substr(substr($value, 11), 0, -3); 38 | $final_eval = html_entity_decode(eval("return " . $to_eval), ENT_QUOTES); 39 | 40 | $compiled = str_replace("", "", " -------------------------------------------------------------------------------- /lib/closure_compiler.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zachfeldman/wordpress-haml-sass/d76cea682819e35b1759d104c8c51dde2a80cf0c/lib/closure_compiler.jar -------------------------------------------------------------------------------- /lib/make.sh: -------------------------------------------------------------------------------- 1 | theme_dir="theme" 2 | temp_dir="tmp" 3 | 4 | php lib/MtHaml/compile.php "/../../$theme_dir/" 5 | sass app/assets/stylesheets/compiled.sass:$theme_dir/compiled.css 6 | cp app/assets/stylesheets/style.css $theme_dir/style.css 7 | cp -R app/assets/images $theme_dir 8 | cp -R app/assets/scripts_uncompiled/ $theme_dir/scripts 9 | 10 | coffeefiles=`find app/assets/scripts_to_compile -name '*.coffee'` 11 | for j in $coffeefiles; 12 | do 13 | coffee -c -b -o $temp_dir $j 14 | done 15 | 16 | files=`find app/assets/scripts_to_compile $temp_dir -name '*.js'` 17 | allfiles="" 18 | for i in $files; 19 | do 20 | allfiles="$allfiles --js=$i" 21 | done 22 | echo "Closure JavaScript compiler:" 23 | java -jar lib/closure_compiler.jar --js=app/assets/jquery.js $allfiles --js_output_file=$theme_dir/scripts/compiled.min.js --warning_level QUIET --summary_detail_level 3 24 | 25 | rm $temp_dir/*.js 26 | echo "$(date) - Watcher has compiled theme" -------------------------------------------------------------------------------- /theme/404.php: -------------------------------------------------------------------------------- 1 | 2 | The page you requested doesn't exist. 3 | 4 | -------------------------------------------------------------------------------- /theme/category.php: -------------------------------------------------------------------------------- 1 | 2 | Category: 3 | 4 |
5 | 6 | 7 | -------------------------------------------------------------------------------- /theme/compiled.css: -------------------------------------------------------------------------------- 1 | /* HTML5 Boilerplate */ 2 | article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { 3 | display: block; } 4 | 5 | audio, canvas, video { 6 | display: inline-block; 7 | *display: inline; 8 | *zoom: 1; } 9 | 10 | audio:not([controls]), [hidden] { 11 | display: none; } 12 | 13 | html { 14 | font-size: 100%; 15 | -webkit-text-size-adjust: 100%; 16 | -ms-text-size-adjust: 100%; 17 | font-family: sans-serif; 18 | color: #222222; } 19 | 20 | button, input, select, textarea { 21 | font-family: sans-serif; 22 | color: #222222; } 23 | 24 | body { 25 | margin: 0; 26 | font-size: 1em; 27 | line-height: 1.4; } 28 | 29 | a { 30 | color: #5dbcd2; } 31 | a:visited { 32 | color: #5dbcd2; } 33 | a:hover { 34 | color: #5dbcd2; 35 | text-decoration: none; } 36 | a:focus { 37 | outline: thin dotted; } 38 | a:hover, a:active { 39 | outline: 0; } 40 | 41 | abbr[title] { 42 | border-bottom: 1px dotted; } 43 | 44 | b, strong { 45 | font-weight: bold; } 46 | 47 | blockquote { 48 | margin: 1em 40px; } 49 | 50 | dfn { 51 | font-style: italic; } 52 | 53 | hr { 54 | display: block; 55 | height: 1px; 56 | border: 0; 57 | border-top: 1px solid #cccccc; 58 | margin: 1em 0; 59 | padding: 0; } 60 | 61 | ins { 62 | background: #ffff99; 63 | color: black; 64 | text-decoration: none; } 65 | 66 | mark { 67 | background: yellow; 68 | color: black; 69 | font-style: italic; 70 | font-weight: bold; } 71 | 72 | pre, code, kbd, samp { 73 | font-family: monospace, serif; 74 | _font-family: "courier new", monospace; 75 | font-size: 1em; } 76 | 77 | pre { 78 | white-space: pre; 79 | white-space: pre-wrap; 80 | word-wrap: break-word; } 81 | 82 | q { 83 | quotes: none; } 84 | q:before, q:after { 85 | content: ""; 86 | content: none; } 87 | 88 | small { 89 | font-size: 85%; } 90 | 91 | sub { 92 | font-size: 75%; 93 | line-height: 0; 94 | position: relative; 95 | vertical-align: baseline; } 96 | 97 | sup { 98 | font-size: 75%; 99 | line-height: 0; 100 | position: relative; 101 | vertical-align: baseline; 102 | top: -0.5em; } 103 | 104 | sub { 105 | bottom: -0.25em; } 106 | 107 | ul, ol { 108 | margin: 1em 0; 109 | padding: 0 0 0 40px; } 110 | 111 | dd { 112 | margin: 0 0 0 40px; } 113 | 114 | nav ul, nav ol { 115 | list-style: none; 116 | list-style-image: none; 117 | margin: 0; 118 | padding: 0; } 119 | 120 | img { 121 | border: 0; 122 | -ms-interpolation-mode: bicubic; 123 | vertical-align: middle; } 124 | 125 | svg:not(:root) { 126 | overflow: hidden; } 127 | 128 | figure, form { 129 | margin: 0; } 130 | 131 | fieldset { 132 | border: 0; 133 | margin: 0; 134 | padding: 0; } 135 | 136 | label { 137 | cursor: pointer; } 138 | 139 | legend { 140 | border: 0; 141 | *margin-left: -7px; 142 | padding: 0; 143 | white-space: normal; } 144 | 145 | button, input, select, textarea { 146 | font-size: 100%; 147 | margin: 0; 148 | vertical-align: baseline; 149 | *vertical-align: middle; } 150 | 151 | button, input { 152 | line-height: normal; } 153 | 154 | button { 155 | cursor: pointer; 156 | -webkit-appearance: button; 157 | *overflow: visible; } 158 | 159 | input[type="button"], input[type="reset"], input[type="submit"] { 160 | cursor: pointer; 161 | -webkit-appearance: button; 162 | *overflow: visible; } 163 | 164 | button[disabled] { 165 | cursor: default; } 166 | 167 | input[disabled] { 168 | cursor: default; } 169 | input[type="checkbox"], input[type="radio"] { 170 | box-sizing: border-box; 171 | padding: 0; 172 | *width: 13px; 173 | *height: 13px; } 174 | input[type="search"] { 175 | -webkit-appearance: textfield; 176 | -moz-box-sizing: content-box; 177 | -webkit-box-sizing: content-box; 178 | box-sizing: content-box; } 179 | input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { 180 | -webkit-appearance: none; } 181 | 182 | button::-moz-focus-inner, input::-moz-focus-inner { 183 | border: 0; 184 | padding: 0; } 185 | 186 | textarea { 187 | overflow: auto; 188 | vertical-align: top; 189 | resize: vertical; } 190 | 191 | table { 192 | border-collapse: collapse; 193 | border-spacing: 0; } 194 | 195 | td { 196 | vertical-align: top; } 197 | 198 | .chromeframe { 199 | margin: 0.2em 0; 200 | background: #cccccc; 201 | color: black; 202 | padding: 0.2em 0; } 203 | 204 | .ir { 205 | display: block; 206 | border: 0; 207 | text-indent: -999em; 208 | overflow: hidden; 209 | background-color: transparent; 210 | background-repeat: no-repeat; 211 | text-align: left; 212 | direction: ltr; 213 | *line-height: 0; } 214 | .ir br { 215 | display: none; } 216 | 217 | .hidden { 218 | display: none; } 219 | 220 | .visuallyhidden { 221 | border: 0; 222 | clip: rect(0 0 0 0); 223 | height: 1px; 224 | margin: -1px; 225 | overflow: hidden; 226 | padding: 0; 227 | position: absolute; 228 | width: 1px; } 229 | .visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { 230 | clip: auto; 231 | height: auto; 232 | margin: 0; 233 | overflow: visible; 234 | position: static; 235 | width: auto; } 236 | 237 | .invisible { 238 | visibility: hidden; } 239 | 240 | .clearfix { 241 | *zoom: 1; } 242 | .clearfix:before { 243 | content: ""; 244 | display: table; } 245 | .clearfix:after { 246 | content: ""; 247 | display: table; 248 | clear: both; } 249 | 250 | @media print { 251 | * { 252 | background: transparent !important; 253 | color: black !important; 254 | box-shadow: none !important; 255 | text-shadow: none !important; 256 | filter: none !important; 257 | -ms-filter: none !important; } 258 | 259 | a { 260 | text-decoration: underline; } 261 | a:visited { 262 | text-decoration: underline; } 263 | a[href]:after { 264 | content: " (" attr(href) ")"; } 265 | 266 | abbr[title]:after { 267 | content: " (" attr(title) ")"; } 268 | 269 | .ir a:after { 270 | content: ""; } 271 | 272 | a[href^="javascript:"]:after, a[href^="#"]:after { 273 | content: ""; } 274 | 275 | pre, blockquote { 276 | border: 1px solid #999999; 277 | page-break-inside: avoid; } 278 | 279 | thead { 280 | display: table-header-group; } 281 | 282 | tr { 283 | page-break-inside: avoid; } 284 | 285 | img { 286 | page-break-inside: avoid; 287 | max-width: 100% !important; } 288 | 289 | @page { 290 | margin: 0.5cm; } 291 | 292 | p, h2, h3 { 293 | orphans: 3; 294 | widows: 3; } 295 | 296 | h2, h3 { 297 | page-break-after: avoid; } } 298 | -------------------------------------------------------------------------------- /theme/footer.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /theme/header.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <?php wp_title(); ?> 7 | 8 | 9 | 10 | 11 | 12 | 13 | 23 | -------------------------------------------------------------------------------- /theme/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | Sorry, no posts were found. 12 | 13 | 14 | -------------------------------------------------------------------------------- /theme/results.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Sorry, no posts were found. 10 | 11 | -------------------------------------------------------------------------------- /theme/scripts/uncompiled.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Throw any scripts in this directory that for whatever reason can't be compiled. 3 | * 4 | * 5 | */ -------------------------------------------------------------------------------- /theme/search.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | Search results for: 7 | 8 |
9 | 10 | 11 | -------------------------------------------------------------------------------- /theme/single.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /theme/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | * THEME NAME: The Awesome Thing 3 | * THEME URI: http://awesome.com 4 | * DESCRIPTION: A theme for your blog. 5 | * VERSION: 1.0 6 | * AUTHOR: John Smith 7 | * AUTHOR URI: http://johnsmith.com 8 | */ 9 | 10 | @import url("compiled.css"); -------------------------------------------------------------------------------- /theme/tag.php: -------------------------------------------------------------------------------- 1 | 2 | Tag: 3 | 4 |
5 | 6 | 7 | -------------------------------------------------------------------------------- /tmp/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zachfeldman/wordpress-haml-sass/d76cea682819e35b1759d104c8c51dde2a80cf0c/tmp/.gitkeep -------------------------------------------------------------------------------- /watch: -------------------------------------------------------------------------------- 1 | echo "Watching App For Changes" 2 | fswatch app "sh lib/make.sh" 3 | --------------------------------------------------------------------------------