├── .gitignore ├── Readme.md ├── assets ├── css │ └── obsidian.css ├── img │ ├── background.jpg │ └── silhouette_dune_desktop.jpg ├── index.jade ├── js │ ├── core.ls │ ├── entry.ls │ ├── lib.ls │ ├── site.ls │ └── test.ls └── less │ └── main.less ├── bower.json ├── complete-deploy ├── config.ls ├── dist ├── css │ └── vendor.css └── img │ ├── background.jpg │ └── silhouette_dune_desktop.jpg ├── gulpfile.ls ├── lib └── dyncss.js ├── package.json └── vendor └── less-elements.less /.gitignore: -------------------------------------------------------------------------------- 1 | bower_components 2 | bower_components 3 | status 4 | _site 5 | 6 | dist/css/client.css 7 | 8 | dist/css/client.css 9 | 10 | dist/html/index.html 11 | 12 | dist/index.html 13 | 14 | dist/js/client.js 15 | 16 | dist/js/client.js 17 | 18 | dist/js/client.js 19 | 20 | dist/index.html 21 | 22 | dist/html/index.html 23 | 24 | dist/css/client.css 25 | 26 | dist/css/client.css 27 | 28 | dist/html/index.html 29 | 30 | dist/index.html 31 | 32 | dist/js/client.js 33 | 34 | 35 | dist/js/vendor.js 36 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | 2 | # DynCSS 3 | 4 | Make your site come to life with [Dynamic CSS](http://www.vittoriozaccaria.net/dyn-css). -------------------------------------------------------------------------------- /assets/css/obsidian.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Obsidian style 3 | * ported by Alexander Marenin (http://github.com/ioncreature) 4 | */ 5 | 6 | .hljs { 7 | display: block; padding: 0.5em; 8 | background: #282B2E; 9 | } 10 | 11 | .hljs-keyword, 12 | .hljs-literal, 13 | .hljs-change, 14 | .hljs-winutils, 15 | .hljs-flow, 16 | .lisp .hljs-title, 17 | .clojure .hljs-built_in, 18 | .nginx .hljs-title, 19 | .css .hljs-id, 20 | .tex .hljs-special { 21 | color: #93C763; 22 | } 23 | 24 | .hljs-number { 25 | color: #FFCD22; 26 | } 27 | 28 | .hljs { 29 | color: #E0E2E4; 30 | } 31 | 32 | .css .hljs-tag, 33 | .css .hljs-pseudo { 34 | color: #D0D2B5; 35 | } 36 | 37 | .hljs-attribute, 38 | .hljs .hljs-constant { 39 | color: #668BB0; 40 | } 41 | 42 | .xml .hljs-attribute { 43 | color: #B3B689; 44 | } 45 | 46 | .xml .hljs-tag .hljs-value { 47 | color: #E8E2B7; 48 | } 49 | 50 | .hljs-code, 51 | .hljs-class .hljs-title, 52 | .hljs-header { 53 | color: white; 54 | } 55 | 56 | .hljs-class, 57 | .hljs-hexcolor { 58 | color: #93C763; 59 | } 60 | 61 | .hljs-regexp { 62 | color: #D39745; 63 | } 64 | 65 | .hljs-at_rule, 66 | .hljs-at_rule .hljs-keyword { 67 | color: #A082BD; 68 | } 69 | 70 | .hljs-doctype { 71 | color: #557182; 72 | } 73 | 74 | .hljs-link_url, 75 | .hljs-tag, 76 | .hljs-tag .hljs-title, 77 | .hljs-bullet, 78 | .hljs-subst, 79 | .hljs-emphasis, 80 | .haskell .hljs-type, 81 | .hljs-preprocessor, 82 | .hljs-pragma, 83 | .ruby .hljs-class .hljs-parent, 84 | .hljs-built_in, 85 | .sql .hljs-aggregate, 86 | .django .hljs-template_tag, 87 | .django .hljs-variable, 88 | .smalltalk .hljs-class, 89 | .hljs-javadoc, 90 | .django .hljs-filter .hljs-argument, 91 | .smalltalk .hljs-localvars, 92 | .smalltalk .hljs-array, 93 | .hljs-attr_selector, 94 | .hljs-pseudo, 95 | .hljs-addition, 96 | .hljs-stream, 97 | .hljs-envvar, 98 | .apache .hljs-tag, 99 | .apache .hljs-cbracket, 100 | .tex .hljs-command, 101 | .hljs-prompt { 102 | color: #8CBBAD; 103 | } 104 | 105 | .hljs-string { 106 | color: #EC7600; 107 | } 108 | 109 | .hljs-comment, 110 | .java .hljs-annotation, 111 | .hljs-blockquote, 112 | .hljs-horizontal_rule, 113 | .python .hljs-decorator, 114 | .hljs-template_comment, 115 | .hljs-pi, 116 | .hljs-deletion, 117 | .hljs-shebang, 118 | .apache .hljs-sqbracket, 119 | .tex .hljs-formula { 120 | color: #818E96; 121 | } 122 | 123 | .hljs-keyword, 124 | .hljs-literal, 125 | .css .hljs-id, 126 | .hljs-phpdoc, 127 | .hljs-title, 128 | .hljs-header, 129 | .haskell .hljs-type, 130 | .vbscript .hljs-built_in, 131 | .sql .hljs-aggregate, 132 | .rsl .hljs-built_in, 133 | .smalltalk .hljs-class, 134 | .diff .hljs-header, 135 | .hljs-chunk, 136 | .hljs-winutils, 137 | .bash .hljs-variable, 138 | .apache .hljs-tag, 139 | .tex .hljs-special, 140 | .hljs-request, 141 | .hljs-at_rule .hljs-keyword, 142 | .hljs-status { 143 | font-weight: bold; 144 | } 145 | 146 | .coffeescript .javascript, 147 | .javascript .xml, 148 | .tex .hljs-formula, 149 | .xml .javascript, 150 | .xml .vbscript, 151 | .xml .css, 152 | .xml .hljs-cdata { 153 | opacity: 0.5; 154 | } 155 | -------------------------------------------------------------------------------- /assets/img/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vzaccaria/DynCSS/28411828f1235ed10235e4c62bb4bce7a71a0ec2/assets/img/background.jpg -------------------------------------------------------------------------------- /assets/img/silhouette_dune_desktop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vzaccaria/DynCSS/28411828f1235ed10235e4c62bb4bce7a71a0ec2/assets/img/silhouette_dune_desktop.jpg -------------------------------------------------------------------------------- /assets/index.jade: -------------------------------------------------------------------------------- 1 | mixin fundesc(name, use, description) 2 | .api__element__name #{name} 3 | .api__element__use #{use} 4 | .api__element__command_desc #{description} 5 | 6 | mixin fundesc_transition_to_one 7 | .api__element 8 | +fundesc('@transitionToOne', '@transitionToOne({when: expr, start: val, end: val}, power)', 9 | 'Returns a value that starts at 0, when `expr` is lower than `start`, and approaches 1.0, when `expr` approaches `end`.') 10 | 11 | .api__element__returns 12 | .api__element__returns__element 13 | .api__element__returns__element__value 0 14 | .api__element__returns__element__when`expr` is lower than `start` 15 | 16 | .api__element__returns__element 17 | .api__element__returns__element__value (expr/val)^power 18 | .api__element__returns__element__when`expr` is higher than `start` but lower than `end` 19 | 20 | .api__element__returns__element 21 | .api__element__returns__element__value 1 22 | .api__element__returns__element__when`expr` is higher `end` 23 | 24 | .api__element_example 25 | :markdown 26 | This snippet turns down opacity when scrolling position (`@win-scrollTop`) is 27 | reaching 400px. The transition follows an sqrt law (`power`=.5) 28 | 29 | ```css 30 | .header { 31 | -dyn-opacity: '1-@transitionToOne({when : @win-scrollTop , start: 0, stop: 400 }, .5)'; 32 | } 33 | ``` 34 | .api__hr 35 | 36 | mixin fundesc_should_appear 37 | .api__element 38 | +fundesc('@shouldAppear', '@shouldAppear({when: expr, isHigherThan: val})', 39 | 'Returns a value that approaches 1.0 when expr approaches val.') 40 | 41 | .api__element__returns 42 | .api__element__returns__element 43 | .api__element__returns__element__value 0 44 | .api__element__returns__element__when`expr` is lower than 0 45 | 46 | .api__element__returns__element 47 | .api__element__returns__element__value expr/val 48 | .api__element__returns__element__when`expr` is higher than 0 but lower than `val` 49 | 50 | .api__element__returns__element 51 | .api__element__returns__element__value 1 52 | .api__element__returns__element__when`expr` is higher `val` 53 | 54 | .api__element_example 55 | :markdown 56 | This snippet turns up element visibility when scrolling position (`@win-scrollTop`) is 57 | reaching a half of the window's height: 58 | 59 | ```css 60 | .header { 61 | -dyn-opacity: '@shouldAppear({when: @win-scrollTop, isHigherThan: @win-height/2})'; 62 | } 63 | ``` 64 | .api__element_variations 65 | :markdown 66 | Use `isLowerThan` instead of `isHigherThan` to make elements appear on scroll up. 67 | .api__hr 68 | 69 | mixin fundesc_should_disappear 70 | .api__element 71 | +fundesc('@shouldDisappear', '@shouldDisappear({when: expr, isHigherThan: val})', 'Returns a value that approaches 0.0 when expr approaches val.') 72 | 73 | .api__element__returns 74 | .api__element__returns__element 75 | .api__element__returns__element__value 1 76 | .api__element__returns__element__when`expr` is lower than 0 77 | 78 | .api__element__returns__element 79 | .api__element__returns__element__value 1 - (expr/val) 80 | .api__element__returns__element__when`expr` is higher than 0 but lower than `val` 81 | 82 | .api__element__returns__element 83 | .api__element__returns__element__value 0 84 | .api__element__returns__element__when`expr` is higher `val` 85 | 86 | .api__element_example 87 | :markdown 88 | This snippet turns down opacity when scrolling position (`@win-scrollTop`) is 89 | reaching a fourth of the window's height: 90 | 91 | ```css 92 | .header { 93 | -dyn-opacity: '@shouldDisappear({when: @win-scrollTop, isHigherThan: @win-height/4})'; 94 | } 95 | ``` 96 | .api__element_variations 97 | :markdown 98 | Use `isLowerThan` instead of `isHigherThan` to make elements disappear on scroll up. 99 | .api__hr 100 | 101 | mixin fundesc_select_from 102 | .api__element 103 | +fundesc('@selectFrom', '@selectFrom(array)', 'Returns the element of `array` associated with the currently active breakpoint (i.e., the one with the same index).') 104 | 105 | .api__element_example 106 | :markdown 107 | Here, we set the font size to 3em under the first breakpoint, 4em under the second, and 5em above the second. 108 | 109 | ```css 110 | .header__title { 111 | -dyn-font-size: '@selectFrom(["3em", "4em", "5em"])'; 112 | } 113 | ``` 114 | 115 | Breakpoints should be set in Javascript by using the appropriate `setBreakpoints` method: 116 | 117 | 118 | ```html 119 | 122 | ``` 123 | 124 | sets two breakpoints at window's width (`@win-width`) equal to 320 and 480 pixels. 125 | 126 | mixin fundesc_if 127 | .api__element 128 | +fundesc('@if', '@if(condition, v1, v2)', 'Returns v1 if condition is true, v2 otherwise.') 129 | 130 | .api__element_example 131 | :markdown 132 | Here, we remove the element when scroll-top is higher than its bottom. 133 | 134 | ```css 135 | .element-to-be-removed { 136 | -dyn-display: '@if(@win-scrollTop > @jq-offset.bottom, "none", "block")'; 137 | } 138 | ``` 139 | 140 | mixin fundesc_morph 141 | .api__element 142 | +fundesc('@morph', '@morph(factor, v1, v2)', 'Returns the convex combination (1-factor)*v1 + factor*v2.') 143 | 144 | .api__element_example 145 | :markdown 146 | `factor` can be the state of a transition. This snippet resizes the width of `.element` by using the state 147 | returned by `@transitionToOne`. 148 | 149 | ```css 150 | .element { 151 | -dyn-width: '@morph(transitionToOne(...), 200, 300)'; 152 | } 153 | ``` 154 | 155 | 156 | doctype html 157 | html 158 | head(lang="en") 159 | title DynCSS - Simple dynamic CSS rules to give life to your sites. 160 | meta(http-equiv="content-type", content="text/html, charset=UTF-8") 161 | meta(name="description", content="") 162 | meta(name="keywords", content="") 163 | meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0") 164 | // if lt IE 9 165 | script(type="text/javascript", src="js/html5shiv.js") 166 | link(href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css", rel="stylesheet") 167 | link(rel="stylesheet", href="css/client.css", type="text/css") 168 | link(rel="stylesheet", href="css/vendor.css", type="text/css") 169 | body(style='opacity: 0;') 170 | //- BEM Rules. 171 | .overlay 172 | 173 | .toc 174 | .toc__section.toc__section--what_is_it(onclick="location.href='#what-is-it';", style="cursor: pointer;") What is it 175 | .toc__section.toc__section--features(onclick="location.href='#features';", style="cursor: pointer;") Features 176 | .toc__section.toc__section--responsiveness(onclick="location.href='#responsiveness';", style="cursor: pointer;") Responsiveness 177 | .toc__section.toc__section--dynamic-styles(onclick="location.href='#dynamic-styles';", style="cursor: pointer;") Dynamic styles 178 | .toc__section.toc__section--api(onclick="location.href='#api';", style="cursor: pointer;") API 179 | 180 | .header 181 | .header__title 182 | strong Dyn 183 | |CSS 184 | .header__sub-title Simple, dynamic CSS rules to give life to your sites. 185 | 186 | .header__buttons 187 | a.header__button(onclick="location.href='https://github.com/vzaccaria/DynCSS'", style="cursor: pointer") Github 188 | a.header__button(onclick="location.href='#api';", style="cursor: pointer") Docs 189 | a.header__button(onclick="location.href='http://www.vittoriozaccaria.net/dyncss-example'", style="cursor: pointer") Example 190 | 191 | .sub-header 192 | .sub-header__actions 193 | 194 | .sub-header__action 195 | i.sub-header__action__icon.fa.fa-cloud-download 196 | .sub-header__action__text Install 197 | .sub-header__action__desc 198 | :markdown 199 | ```shell 200 | $ bower install dyn-css 201 | ``` 202 | 203 | .sub-header__action 204 | i.sub-header__action__icon.fa.fa-html5 205 | .sub-header__action__text Include 206 | .sub-header__action__desc 207 | :markdown 208 | ```html 209 | ... 210 | 341 | ``` 342 | 343 | Now, you can define how each property behaves above an below the breakpoints; 344 | for example, we can change dynamically the font size: 345 | 346 | ```css 347 | .header__title { 348 | -dyn-font-size: '@selectFrom(["3em", "4em", "5em"])'; 349 | } 350 | ``` 351 | 352 | `selectFrom` is a built-in function that returns one of the elements of the input list 353 | by using the breakpoints specified with `setBreakpoints`. 354 | Here, the font size will be 3em under 480px, 4em under 960px, and 5em above 960px. 355 | 356 | #dynamic-styles.sub-header__container__short_desc 357 | :markdown 358 | 359 | # Dynamic styles 360 | DynCSS allows to add a class dynamically to all elements of a given selector, based on 361 | a condition to be evaluated at run-time; this is useful to build scroll spies. 362 | You can specify the class name to be added with `-dyn-set-state-(class-name)`: 363 | 364 | ```css 365 | .to-be-highlighted { 366 | -dyn-set-state-highlight: '@isVerticallyVisible("#my-section")'; 367 | } 368 | 369 | ``` 370 | here, we add a `.highlight` class to all elements `.to-be-highlighted` whenever the function 371 | `@isVerticallyVisible` returns true. We assume that `isVerticallyVisible` receives a selector 372 | and checks whether it is in or out of the view port. 373 | 374 | Here's a custom definition of `isVerticallyVisible` in Livescript, but you can write your own of course: 375 | 376 | ```livescript 377 | 378 | isVerticallyVisible = (el, threshold) -> 379 | r = jQuery(el)[0].getBoundingClientRect(); 380 | w = jQuery(window) 381 | vp = {} 382 | vp.top = w.scrollTop() 383 | vp.bottom = w.scrollTop() + w.height() 384 | if not threshold? 385 | threshold := w.height()/3 386 | value = 387 | | r.top >= 0 and r.top < (threshold) => true 388 | | r.top < 0 and r.bottom > (threshold) => true 389 | | otherwise => false 390 | 391 | return value 392 | 393 | ``` 394 | 395 | 396 | 397 | #api.sub-header__container__short_desc 398 | 399 | 400 | 401 | :markdown 402 | 403 | # API 404 | 405 | Here are some built-in functions you can use in your `-dyn-*` rules: 406 | 407 | .sub-header__short_desc__api 408 | +fundesc_should_appear() 409 | +fundesc_should_disappear() 410 | +fundesc_select_from() 411 | +fundesc_transition_to_one() 412 | +fundesc_if() 413 | +fundesc_morph() 414 | 415 | 416 | 417 | .sub-header__footer 418 | .sub-header__footer__container 419 | .sub-header__footer__madeby 420 | a.sub-header__footer__madeby__name_lastname(href='http://www.vittoriozaccaria.net') Vittorio Zaccaria 421 | 422 | 423 | a.sub-header__footer__license BSD 424 | .sub-header__footer__share 425 | #here-reddit.sub-header__footer__share__reddit 426 | 427 | .sub-header__footer__share__twitter 428 | a#here-twitter(href="https://twitter.com/share",class="twitter-share-button",data-count='vertical', data-via="_vzaccaria_") Tweet 429 | 430 | 431 | 432 | script(type="text/javascript", src="js/vendor.js") 433 | script(type="text/javascript", src="js/client.js") 434 | 435 | script. 436 | window.dynCss.api.setBreakpoints([481,961],'@win-width'); 437 | 438 | script(src='//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.0/highlight.min.js') 439 | script. 440 | hljs.initHighlightingOnLoad(); 441 | 442 | 443 | 444 | // if IE 445 | script(type="text/javascript", src="js/placeholder.js") -------------------------------------------------------------------------------- /assets/js/core.ls: -------------------------------------------------------------------------------- 1 | built-in = require('./lib') 2 | 3 | blue = '#3498db' 4 | red = '#c0392b' 5 | normal = 'black' 6 | 7 | core-debug-message = (m) -> 8 | if window.dynCss.config.debug 9 | console.log "%cdyncss-core : %c#m", "color: #blue", "color: #normal" 10 | 11 | core-heavy-debug-message = (m) -> 12 | if window.dynCss.config.debug 13 | console.log "%cdyncss-core : %c#m", "color: #red", "color: #normal" 14 | 15 | dyn-css = (window-di, document-di, jq-di) -> 16 | 17 | inner-module = -> 18 | # Use `inner-module` to inject dependencies into `dep` 19 | # e.g. sinon.stub mod.inner-module().dep, 'method'. 20 | # 21 | # You can access `dep` method with plain `dep.method` 22 | # in functions defined below. 23 | return this 24 | 25 | 26 | window-di.dynCss = {} 27 | window-di.dynCss.lib = built-in 28 | window-di.dynCss.data = {} 29 | window-di.dynCss.config = 30 | debug: false 31 | dontComputeInvisible: false 32 | useRAF: false; 33 | 34 | 35 | # __ __ _ __ 36 | # / /_ ________ ____ _/ /______ ____ (_)___ / /______ 37 | # / __ \/ ___/ _ \/ __ `/ //_/ __ \/ __ \/ / __ \/ __/ ___/ 38 | # / /_/ / / / __/ /_/ / ,< / /_/ / /_/ / / / / / /_(__ ) 39 | # /_.___/_/ \___/\__,_/_/|_/ .___/\____/_/_/ /_/\__/____/ 40 | # /_/ 41 | 42 | class breakpoint 43 | 44 | (@name, @breakpoints, @expression) -> 45 | @expression = transcompile-function @expression 46 | @compiled = window-di.dynCss.api.create-function @expression 47 | 48 | set-named-breakpoints = (name, list, expression) -> 49 | window-di.dynCss.data[name] = new breakpoint(name, list, expression) 50 | 51 | set-breakpoints = (list, variable) -> 52 | set-named-breakpoints 'responsive', list, variable 53 | 54 | window-di.dynCss.api = { 55 | set-breakpoints: set-breakpoints 56 | set-named-breakpoints: set-named-breakpoints 57 | 58 | force-redraw: -> 59 | ss = document.styleSheets[0]; 60 | try 61 | ss.addRule('.xxxxxx', 'position: relative'); 62 | catch 63 | 64 | force-redraw-brute: -> 65 | $(window).hide().show() 66 | } 67 | 68 | 69 | 70 | # 71 | # _________ ________ 72 | # / ___/ __ \/ ___/ _ \ 73 | # / /__/ /_/ / / / __/ 74 | # \___/\____/_/ \___/ 75 | # 76 | 77 | camelize = (str) -> 78 | ex = /[-_\s]+(.)?/g 79 | return str.replace ex, (m, c) -> 80 | | c? => c.toUpperCase() 81 | | otherwise => "" 82 | 83 | 84 | get-scroll-expression = (d) -> 85 | if (results = d.property is /\-dyn\-(.*)/)? 86 | property = results[1] 87 | if (results = d.value is /'(.*)'/)? 88 | expression = results[1] 89 | 90 | if property == 'fixed-right-edge' 91 | 92 | property = 'left' 93 | expression = "#expression - @el-width" 94 | 95 | if property == 'fixed-left-edge' 96 | 97 | property = 'left' 98 | expression = "#expression" 99 | 100 | if property == 'fixed-bottom-edge' 101 | 102 | property = 'top' 103 | expression = "#expression - @el-height" 104 | 105 | if property == 'fixed-top-edge' 106 | 107 | property = 'top' 108 | expression = "#expression" 109 | 110 | if property == 'fixed-horizontal-center' 111 | 112 | property = 'left' 113 | expression = "#expression - @el-width/2" 114 | 115 | if property == 'fixed-vertical-center' 116 | 117 | property = 'top' 118 | expression = "#expression - @el-height/2" 119 | 120 | return { property: property, expression: expression } 121 | return undefined 122 | 123 | transcompile-function = (body) -> 124 | core-debug-message body if window-di.dynCss.config.debug 125 | body = body.replace(/@a-(\w+){(.+)}/g , 'this.lib.jqRef(\'$2\').$1()') 126 | body = body.replace(/\#{(.+)}/g , '"+($1)+"') 127 | body = body.replace(/@i-(\w+)/g , 'parseInt(this.el.css(\'$1\'))') 128 | body = body.replace(/@j-(\w+)/g , 'this.lib.jqRef(this.el).$1()') 129 | body = body.replace(/@w-(\w+)/g , '(this.lib.wRef.$1())') 130 | body = body.replace(/@el-(\w+)/g , 'parseInt(this.el.css(\'$1\'))') 131 | body = body.replace(/@jq-(\w+)/g , 'this.lib.jqRef(this.el).$1()') 132 | body = body.replace(/@win-(\w+)/g , '(this.lib.wRef.$1())') 133 | body = body.replace(/@/g , 'this.lib.') 134 | return body 135 | 136 | window-di.dynCss.api.create-function = (body) -> 137 | 138 | script = document-di.createElement("script") 139 | script.text = "window.tmp = function() { return (#body); }.bind(window.dynCss);" 140 | 141 | document-di.head.appendChild( script ).parentNode.removeChild( script ); 142 | return window-di.tmp 143 | 144 | 145 | build-handlers = (rules, refresh-handler) -> 146 | 147 | window-di.dynCss.lib.jqRef = jq-di 148 | window-di.dynCss.lib.wRef = jq-di(window-di) 149 | 150 | 151 | for rule in rules 152 | if rule.type is "rule" 153 | sel = rule.selectors 154 | 155 | actions = [] 156 | 157 | for decl in rule.declarations 158 | result = get-scroll-expression(decl) 159 | if result? 160 | 161 | { property, expression, trigger} = result 162 | comp = transcompile-function expression 163 | handler = window-di.dynCss.api.create-function comp 164 | actions.push { property: camelize(property), original-property: property, funct: handler, sel: sel } 165 | 166 | wrapper = (next) -> 167 | let act = actions, scoped-sel=sel 168 | (changed) -> 169 | for sct in scoped-sel 170 | jq-di(sct).each (i) -> 171 | window-di.dynCss.el = jq-di(this) 172 | css = {} 173 | for a in act 174 | if (r = (a.original-property == /set-state-(.+)/)) 175 | cc = r[1] 176 | if a.funct() 177 | window-di.dynCss.el.addClass(cc) 178 | else 179 | window-di.dynCss.el.removeClass(cc) 180 | else 181 | core-debug-message "Assigning to #{sct}.#{a.property} value #{a.funct()}" if window-di.dynCss.config.debug 182 | css[a.property] = a.funct() 183 | 184 | 185 | for k,v of css 186 | is-initial-phase = (not this.old-value?) or (not this.old-value?[k]?) 187 | is-changed = (this.old-value? and this.old-value[k]? and css[k] != this.old-value[k]) 188 | # is-not-hidden = (css['display']?) and not (css['display']='hidden') 189 | is-not-hidden = 190 | | not window-di.dynCss.config.dontComputeInvisible => true 191 | | window-di.dynCss.el.css('display') != 'none' => true 192 | | otherwise => false 193 | 194 | is-visibility-toggled = (k == 'display') 195 | if (is-initial-phase and is-not-hidden) or (is-changed and is-not-hidden) or (is-changed and is-visibility-toggled) 196 | core-heavy-debug-message "#sct - #k transition (#{this.old-value?[k]} --> #{css[k]})" if window-di.dynCss.config.debug 197 | window-di.dynCss.el.css({"#k": v}) 198 | this.old-value ?= {} 199 | this.old-value[k] = v 200 | changed := true 201 | 202 | new-value = JSON.stringify(css) 203 | 204 | next(changed) if next? 205 | 206 | if actions.length != 0 207 | refresh-handler := wrapper(refresh-handler) 208 | 209 | return refresh-handler 210 | 211 | return { 212 | inner-module: inner-module 213 | build-handlers: build-handlers 214 | } 215 | 216 | module.exports = dyn-css 217 | -------------------------------------------------------------------------------- /assets/js/entry.ls: -------------------------------------------------------------------------------- 1 | 2 | css-parse = require('css-parse') 3 | built-in = require('./lib') 4 | dyn-css = require('./core') 5 | _q = require('q') 6 | 7 | { build-handlers } = dyn-css(window, document, jQuery) 8 | 9 | # __ ____ 10 | # / /_ ____ _____ ____/ / /__ __________ 11 | # / __ \/ __ `/ __ \/ __ / / _ \/ ___/ ___/ 12 | # / / / / /_/ / / / / /_/ / / __/ / (__ ) 13 | # /_/ /_/\__,_/_/ /_/\__,_/_/\___/_/ /____/ 14 | # 15 | 16 | blue = '#3498db' 17 | red = '#c0392b' 18 | normal = 'black' 19 | 20 | entry-debug-message = (m) -> 21 | if window.dynCss.config.debug 22 | console.log "%cdyncss-entry: %c#m", "color: #blue", "color: #normal" 23 | 24 | var scroll-handler 25 | 26 | refresh-handler = (changed) -> 27 | if changed 28 | window.dynCss.api.force-redraw() 29 | 30 | decimate = 1 31 | iOS = /(iPad|iPhone|iPod)/g.test( navigator.userAgent ); 32 | counter = 0 33 | lt = 0 34 | fixed-ttc = (1000/1) 35 | 36 | install-custom-raf = -> 37 | window.custom-request-animation-frame = (cb) -> 38 | ct = new Date().getTime() 39 | ttc = Math.max(0, 16 - (ct - lt)) 40 | if fixed-ttc? 41 | set-timeout cb, fixed-ttc, true 42 | else 43 | set-timeout cb, ttc, true 44 | 45 | lt := ct + ttc 46 | 47 | install-scroll-handler = (options) -> 48 | scroll-handler := -> 49 | if window.dynCss.config.useRAF 50 | window.request-animation-frame -> 51 | if (counter % decimate) == 0 52 | refresh-handler(false) 53 | counter := counter + 1 54 | else 55 | if (counter % decimate) == 0 56 | refresh-handler(false) 57 | counter := counter + 1 58 | 59 | if options?.only-on-resize? 60 | window.onresize = scroll-handler 61 | else 62 | if not options?.only-on-start? 63 | window.onscroll = scroll-handler 64 | window.ontouchmove = scroll-handler 65 | window.onresize = scroll-handler 66 | 67 | # _ __ 68 | # ____ ___ ____ _(_)___ ___ ____ / /________ __ 69 | # / __ `__ \/ __ `/ / __ \ / _ \/ __ \/ __/ ___/ / / / 70 | # / / / / / / /_/ / / / / / / __/ / / / /_/ / / /_/ / 71 | # /_/ /_/ /_/\__,_/_/_/ /_/ \___/_/ /_/\__/_/ \__, / 72 | # /____/ 73 | 74 | entry-debug-message "Scanning for css" 75 | 76 | parse-css = (n) -> 77 | entry-debug-message "Loading #{n.href}" 78 | _d = _q.defer() 79 | if n.href? 80 | $.get n.href, -> 81 | entry-debug-message "Loaded #{n.href}" 82 | rules = css-parse(it).stylesheet.rules 83 | refresh-handler := build-handlers(rules, refresh-handler) 84 | if refresh-handler? 85 | if iOS 86 | install-scroll-handler({+only-on-start}) 87 | else 88 | install-scroll-handler() 89 | _d.resolve() 90 | return _d.promise 91 | 92 | _loaded_d = _q.defer() 93 | _loaded_p = _loaded_d.promise 94 | 95 | window.onload = -> 96 | entry-debug-message "Content loaded" 97 | _loaded_d.resolve() 98 | 99 | $(document).ready = -> 100 | entry-debug-message "Document parsed." 101 | 102 | results = $('link[type="text/css"]') 103 | p-array = [ parse-css(r) for r in results ] ++ [ _loaded_p ] 104 | 105 | _q.all(p-array).then -> 106 | entry-debug-message "Initializing handler" 107 | scroll-handler() 108 | 109 | window.dynCss.api.initVariable = (vr, value) -> 110 | window.dynCss.lib[vr] = value 111 | 112 | window.dynCss.api.setVariable = (vr, value) -> 113 | window.dynCss.api.initVariable vr, value 114 | scroll-handler() 115 | 116 | window.dynCss.api.initToggle = (vr, value1, value2) -> 117 | window.dynCss.api.initVariable vr, value1 118 | window.dynCss.api.initVariable vr+"Value0", value1 119 | window.dynCss.api.initVariable vr+"Value1", value2 120 | entry-debug-message "Initialising variable #vr to #value1" 121 | 122 | window.dynCss.api.toggle = (vr) -> 123 | vv = window.dynCss.lib[vr] 124 | v1 = window.dynCss.lib[vr+"Value0"] 125 | v2 = window.dynCss.lib[vr+"Value1"] 126 | if vv == v1 127 | window.dynCss.api.setVariable vr, v2 128 | entry-debug-message "Setting #vr to #v2" 129 | else 130 | window.dynCss.api.setVariable vr, v1 131 | entry-debug-message "Setting #vr to #v1" 132 | -------------------------------------------------------------------------------- /assets/js/lib.ls: -------------------------------------------------------------------------------- 1 | 2 | const debug = false 3 | 4 | perspective = (px) -> 5 | return "perspective(#{px}px) " 6 | 7 | sat = (x) -> 8 | | x>1 => 1 9 | | x<0 => 0 10 | | otherwise => x 11 | 12 | as-percentage-of = (/) 13 | 14 | as-remaining-percentage-of = (x, y) -> 15 | 1 - x `as-percentage-of` y 16 | 17 | shouldDisappear = (context) -> 18 | { is-higher-than, is-lower-than, when: wn } = context 19 | if is-higher-than? and wn? 20 | return sat(wn `as-remaining-percentage-of` is-higher-than) 21 | 22 | if is-lower-than? and wn? 23 | v = sat(wn `as-percentage-of` is-lower-than) 24 | return v 25 | 26 | transitionToOne = (context, power = 1) -> 27 | var int, vv, direction 28 | 29 | { start, stop, when: val } = context 30 | orig = val 31 | 32 | pp = 33 | | start 0 34 | | startstop => 1 35 | | start (val - start) / (stop - start) 36 | | start>stop and val>start => 1 37 | | start>stop and val 0 38 | | start>stop => 1 - (val - stop) / (start - stop) 39 | 40 | vv = sat(pp) 41 | return vv ** power 42 | 43 | 44 | shouldAppear = (context) -> 45 | { is-higher-than, is-lower-than, when: wn } = context 46 | wn = context['when'] 47 | var vv, int 48 | 49 | if is-higher-than? and wn? 50 | int := wn `as-percentage-of` is-higher-than 51 | 52 | if is-lower-than? and wn? 53 | int := wn `as-remaining-percentage-of` is-lower-than 54 | 55 | vv := sat(int) 56 | console.log "final: #vv, intermediate: #int, is-higher: #is-higher-than, is-lower: #is-lower-than" if debug 57 | 58 | return vv 59 | 60 | selectFrom = (values) -> 61 | dt = window.dynCss.data['responsive'] 62 | try 63 | if dt.compiled? and values.length > 0 64 | vv = dt.compiled() 65 | for b,i in dt.breakpoints 66 | 67 | if vv < b or (i == (values.length - 1)) 68 | return values[i] 69 | 70 | return values[* - 1] 71 | catch error 72 | 73 | ifThenElse = (cond, v1, v2) -> 74 | if cond 75 | v1 76 | else 77 | v2 78 | 79 | isVerticallyVisible = (el, threshold) -> 80 | 81 | r = jQuery(el)[0].getBoundingClientRect! 82 | w = jQuery(window) 83 | vp = 84 | top: w.scrollTop! 85 | bottom: w.scrollTop! + w.height! 86 | 87 | threshold ?= w.height! / 3 88 | 89 | 90 | value = 91 | | r.top >= 0 and r.top < threshold => true 92 | | r.top < 0 and r.bottom > threshold => true 93 | | otherwise => false 94 | 95 | return value 96 | 97 | 98 | # These work only on fixed position elements 99 | 100 | top-of = (el) -> 101 | if el != window 102 | jQuery(el).offset!top - $(window).scrollTop! 103 | else 104 | 0 105 | 106 | bottom-of = (el) -> 107 | if el != window 108 | jQuery(el).offset!top - $(window).scrollTop! + parseInt(jQuery(el).css('margin-bottom')) + jQuery(el).innerHeight! 109 | else 110 | $(window).height! 111 | 112 | left-of = (el) -> 113 | if el != window 114 | jQuery(el).offset!.left + parseInt(jQuery(el).css('margin-right')) 115 | else 116 | 0 117 | 118 | right-of = (el) -> 119 | if el != window 120 | jQuery(el).offset!.left + parseInt(jQuery(el).css('margin-right')) + jQuery(el).innerWidth() 121 | else 122 | $(window).width! 123 | # jQuery(el).offset().left + parseInt(jQuery(el).css('margin-left')) + jQuery(el).innerWidth() 124 | 125 | 126 | 127 | _module = -> 128 | 129 | 130 | iface = 131 | shouldDisappear : shouldDisappear 132 | convergeToZero : shouldDisappear 133 | shouldAppear : shouldAppear 134 | convergeToOne : shouldAppear 135 | 136 | transitionToOne : transitionToOne 137 | 138 | perspective : perspective 139 | selectFrom : selectFrom 140 | isVerticallyVisible : isVerticallyVisible 141 | if : ifThenElse 142 | 143 | fixed-top-edge : top-of 144 | fixed-bottom-edge : bottom-of 145 | fixed-right-edge : right-of 146 | fixed-left-edge : left-of 147 | 148 | pos: (el) -> # could be (.offset) . ($) 149 | $(el).offset! 150 | 151 | 152 | fixed-horizontal-center: -> 153 | (right-of(it) + left-of(it)) / 2 154 | 155 | fixed-vertical-center: -> 156 | (top-of(it) + bottom-of(it)) / 2 157 | 158 | morph: (c, v1, v2) -> 159 | vv = v1*(1-c) + v2*c 160 | return vv 161 | 162 | 163 | should-be-visible: -> 164 | $w-top = $(window).scrollTop! 165 | $el = jQuery(window.dynCss.el) 166 | $el-top = $el.offset!top 167 | $el-h = $el.innerHeight! 168 | $w-height = $(window).height! 169 | $set-off = $el-top 170 | v = shouldAppear(when: $(window).scrollTop!, is-higher-than: $set-off) 171 | 172 | console.log "top = #{$w-top}, completed-at = #{$set-off}, visible = #v, eltop = #{$el-top}, el-h = #{$el-h}" if debug 173 | return v 174 | 175 | 176 | return iface 177 | 178 | module.exports = _module() 179 | -------------------------------------------------------------------------------- /assets/js/site.ls: -------------------------------------------------------------------------------- 1 | 2 | # Apply it to the div that will contain the widget: 3 | # 4 | # #here-reddit.sub-header__footer__share__reddit 5 | 6 | 7 | add-reddit-button = (selector) -> 8 | thisurl = encodeURIComponent(window.location.href); 9 | url = "http://www.reddit.com/static/button/button2.html?width=51&url=#thisurl" 10 | iframe = '' 11 | $(selector).append(iframe) 12 | 13 | 14 | # Apply it to the a that will contain the widget 15 | # .sub-header__footer__share__twitter 16 | # a#here-twitter(href="https://twitter.com/share",class="twitter-share-button",data-count='vertical', data-via="_vzaccaria_") Tweet 17 | 18 | add-twitter-button = (selector) -> 19 | url = "http://platform.twitter.com/widgets.js" 20 | script = "" 21 | $(selector).before(script) 22 | 23 | 24 | $(document).ready -> 25 | add-reddit-button('#here-reddit') 26 | add-twitter-button('#here-twitter') 27 | $('body').fadeTo(1000, 1.0) 28 | 29 | -------------------------------------------------------------------------------- /assets/js/test.ls: -------------------------------------------------------------------------------- 1 | 2 | 3 | require! 'should' 4 | require! 'sinon' 5 | 6 | moment = require 'moment' 7 | __q = require('q') 8 | 9 | notifies-on-fail = (p, cb) -> 10 | p.then((-> cb(it)),(-> cb())) 11 | 12 | notifies-on-success = (p, cb) -> 13 | p.then((-> cb()), (-> cb(it))) 14 | 15 | create-resolved-promise = -> 16 | d = __q.defer() 17 | p = d.promise 18 | d.resolve() 19 | return p 20 | 21 | create-rejected-promise = -> 22 | d = __q.defer() 23 | p = d.promise 24 | d.reject() 25 | return p 26 | 27 | var dyncss 28 | 29 | var window-di 30 | var jq-di 31 | var el-di 32 | var document-di 33 | var temp-stub1 34 | var rules 35 | var iterator 36 | 37 | quote = (i) -> "\'#i\'" 38 | 39 | describe 'DynCSS tests - base', (empty) -> 40 | before-each -> 41 | 42 | dyncss := require('./core') 43 | 44 | window-di := { type: "window" } 45 | 46 | document-di := { type: "document" } 47 | 48 | el-di := { 49 | type: "element" 50 | css: (css) -> 51 | 52 | } 53 | 54 | iterator := { 55 | each: (cb) -> 56 | cb.apply(el-di, [0]) 57 | } 58 | 59 | # That's a short jquery hack.. 60 | jq-di := (sel) -> 61 | 62 | if not sel.type? and sel == '.test' 63 | return iterator 64 | 65 | if sel.type == "window" 66 | return window-di 67 | 68 | if sel.type == "element" 69 | return el-di 70 | 71 | dyncss := dyncss(window-di, document-di , jq-di) 72 | 73 | window-di.width = -> 100 74 | window-di.height = -> 100 75 | 76 | # sinon.stub window-di, 'height', -> 200 77 | 78 | rules := [ 79 | 80 | * type: 'rule' 81 | selectors: ['.test'] 82 | declarations: [ 83 | * property: '-dyn-width' 84 | value: quote(333) 85 | ] 86 | 87 | ] 88 | 89 | temp-stub1 := sinon.stub window-di.dynCss.api, 'createFunction', (body) -> 90 | (-> eval(body)).bind(window-di.dynCss) 91 | 92 | after-each -> 93 | temp-stub1.restore() 94 | 95 | 96 | 97 | it 'should instantiate correctly main module', -> 98 | should.exist(dyncss) 99 | 100 | it 'should instantiate internal data structures', -> 101 | should.exist(window-di.dynCss.data) 102 | 103 | it 'should instantiate breakpoint api', -> 104 | should.exist(window-di.dynCss.api.set-breakpoints) 105 | 106 | it 'should access inner module functions', -> 107 | should.exist(window-di.dynCss.api.create-function) 108 | 109 | it 'should stub correctly create a function', -> 110 | f = window-di.dynCss.api.create-function('3') 111 | f.should.be.a.Function 112 | f().should.be.exactly(3) 113 | 114 | it 'should create a simple rule', -> 115 | handler = dyncss.build-handlers(rules, undefined) 116 | should.exist(handler) 117 | handler.should.be.a.Function 118 | 119 | it 'should modify the css when created', -> 120 | handler = dyncss.build-handlers(rules, undefined) 121 | cssspy = sinon.spy(el-di, 'css') 122 | handler() 123 | cssspy.callCount.should.be.exactly(1) 124 | should.exist(cssspy.firstCall.args[0].width) 125 | cssspy.firstCall.args[0].width.should.be.exactly(333) 126 | cssspy.restore() 127 | 128 | describe 'DynCSS tests - using built-in', (empty) -> 129 | before-each -> 130 | 131 | dyncss := require('./core') 132 | 133 | window-di := { type: "window" } 134 | 135 | document-di := { type: "document" } 136 | 137 | el-di := { 138 | type: "element" 139 | 140 | css: (css) -> 141 | if css == "size" 142 | return '444' 143 | 144 | width: -> 145 | 222 146 | } 147 | 148 | iterator := { 149 | each: (cb) -> 150 | cb.apply(el-di, [0]) 151 | } 152 | 153 | # That's a short jquery hack.. 154 | jq-di := (sel) -> 155 | 156 | if not sel.type? and sel == '.test' 157 | return iterator 158 | 159 | if sel.type == "window" 160 | return window-di 161 | 162 | if sel.type == "element" 163 | return el-di 164 | 165 | dyncss := dyncss(window-di, document-di , jq-di) 166 | 167 | window-di.width = -> 101 168 | window-di.height = -> 100 169 | 170 | # sinon.stub window-di, 'height', -> 200 171 | 172 | rules := [ 173 | 174 | * type: 'rule' 175 | selectors: ['.test'] 176 | declarations: [ 177 | * property: '-dyn-width' 178 | value: quote('@win-width') 179 | ] 180 | 181 | ] 182 | 183 | temp-stub1 := sinon.stub window-di.dynCss.api, 'createFunction', (body) -> 184 | (-> eval(body)).bind(window-di.dynCss) 185 | 186 | after-each -> 187 | temp-stub1.restore() 188 | 189 | 190 | it 'should create a rule accessing the window width', -> 191 | handler = dyncss.build-handlers(rules, undefined) 192 | should.exist(handler) 193 | handler.should.be.a.Function 194 | 195 | it 'should modify the css when created', -> 196 | handler = dyncss.build-handlers(rules, undefined) 197 | cssspy = sinon.spy(el-di, 'css') 198 | handler() 199 | cssspy.callCount.should.be.exactly(1) 200 | should.exist(cssspy.firstCall.args[0].width) 201 | cssspy.firstCall.args[0].width.should.be.exactly(101) 202 | 203 | it 'should create a rule accessing an element jquery computed value', -> 204 | 205 | rules := [ 206 | 207 | * type: 'rule' 208 | selectors: ['.test'] 209 | declarations: [ 210 | * property: '-dyn-width' 211 | value: quote('@jq-width') 212 | ] 213 | 214 | ] 215 | 216 | handler = dyncss.build-handlers(rules, undefined) 217 | should.exist(handler) 218 | handler.should.be.a.Function 219 | cssspy = sinon.spy(el-di, 'css') 220 | handler() 221 | cssspy.callCount.should.be.exactly(1) 222 | should.exist(cssspy.firstCall.args[0].width) 223 | cssspy.firstCall.args[0].width.should.be.exactly(222) 224 | cssspy.restore() 225 | 226 | it 'should create a rule accessing an element css property width', -> 227 | 228 | rules := [ 229 | 230 | * type: 'rule' 231 | selectors: ['.test'] 232 | declarations: [ 233 | * property: '-dyn-width' 234 | value: quote('@el-size') 235 | ] 236 | 237 | ] 238 | 239 | handler = dyncss.build-handlers(rules, undefined) 240 | should.exist(handler) 241 | handler.should.be.a.Function 242 | cssspy = sinon.spy(el-di, 'css') 243 | handler() 244 | cssspy.callCount.should.be.exactly(2) 245 | should.exist(cssspy.secondCall.args[0].width) 246 | cssspy.secondCall.args[0].width.should.be.exactly(444) 247 | cssspy.restore() 248 | 249 | 250 | 251 | 252 | 253 | -------------------------------------------------------------------------------- /assets/less/main.less: -------------------------------------------------------------------------------- 1 | @import url(http://fonts.googleapis.com/css?family=Lato:100,300,400,700,900); 2 | @import url(http://fonts.googleapis.com/css?family=Inconsolata); 3 | 4 | // _ _ _ 5 | // _ ______ ______(_)___ __ _______ ____ ___ (_) __(_)___ _____ 6 | // | | / / __ `/ ___/ / __ \/ / / / ___/ / __ `__ \/ / |/_/ / __ \/ ___/ 7 | // | |/ / /_/ / / / / /_/ / /_/ (__ ) / / / / / / /> code 216 | { 217 | background-color : darken(white, 5%); 218 | padding : 3px; 219 | .border-radius(6px,6px,6px,6px); 220 | } 221 | 222 | & pre { 223 | text-align : left; 224 | white-space : pre-wrap; 225 | word-wrap : break-word; 226 | background-color: red; 227 | } 228 | 229 | & > table { 230 | box-size : border-box; 231 | width : 100%; 232 | background-color : darken(white, 5%); 233 | & th { 234 | min-width : 15%; 235 | text-align : left; 236 | } 237 | .border-radius(6px,6px,6px,6px); 238 | } 239 | 240 | 241 | } 242 | 243 | // __ 244 | // / /_____ _____ 245 | // / __/ __ \/ ___/ 246 | // / /_/ /_/ / /__ 247 | // \__/\____/\___/ 248 | // 249 | 250 | @lightgray: #ecf0f1; 251 | @darkgray: #34495e; 252 | 253 | .toc { 254 | position : fixed; 255 | -dyn-opacity : '@shouldAppear({when : @win-scrollTop, isHigherThan : @win-height/4}) - 0.3'; 256 | -dyn-display : '@selectFrom(["none" , "none" , "block"])'; 257 | left : 0px; 258 | z-index : +1; 259 | padding-top : 1em; 260 | padding-bottom : 1em; 261 | background-color : @lightgray; 262 | color : @darkgray; 263 | } 264 | 265 | .toc__section { 266 | box-sizing : border-box; 267 | display : block; 268 | font-size : 1em; 269 | padding : 1em 2em 1em 2em; 270 | 271 | 272 | &.highlight { 273 | color : @lightgray; 274 | background-color : @darkgray; 275 | transition : 200ms; 276 | } 277 | 278 | } 279 | 280 | .toc__section--what_is_it { 281 | -dyn-set-state-highlight: '@isVerticallyVisible("#what-is-it.sub-header__container__short_desc")'; 282 | } 283 | 284 | .toc__section--features { 285 | -dyn-set-state-highlight: '@isVerticallyVisible("#features.sub-header__container__short_desc")'; 286 | } 287 | 288 | .toc__section--responsiveness { 289 | -dyn-set-state-highlight: '@isVerticallyVisible("#responsiveness.sub-header__container__short_desc")'; 290 | } 291 | 292 | .toc__section--dynamic-styles { 293 | -dyn-set-state-highlight: '@isVerticallyVisible("#dynamic-styles.sub-header__container__short_desc")'; 294 | } 295 | 296 | .toc__section--api { 297 | -dyn-set-state-highlight: '@isVerticallyVisible("#api.sub-header__container__short_desc")'; 298 | } 299 | 300 | // _ 301 | // ____ _____ (_) 302 | // / __ `/ __ \/ / 303 | // / /_/ / /_/ / / 304 | // \__,_/ .___/_/ 305 | // /_/ 306 | 307 | .api__hr { 308 | // display: block; 309 | margin-top: 1em; 310 | margin-bottom: 1em; 311 | margin-left: auto; 312 | margin-right: auto; 313 | padding-top: 10em; 314 | height: 0; 315 | width: 20%; 316 | max-height: 0; 317 | font-size: 1px; 318 | line-height: 0; 319 | // clear: both; 320 | border: none; 321 | border-top: 1px solid #aaaaaa; 322 | border-bottom: 1px solid #ffffff; 323 | } 324 | 325 | .api__element { 326 | margin-top: 4em; 327 | } 328 | 329 | .api__element__name { 330 | display: inline; 331 | font-size: 1.2em; 332 | padding: .5em; 333 | box-sizing: border-box; 334 | border: solid 1px black; 335 | .border-radius(5px,5px,5px,5px); 336 | } 337 | 338 | .api__element__use { 339 | display: block; 340 | margin-top: 2em; 341 | font-family: Inconsolata; 342 | } 343 | 344 | 345 | .api_font() { 346 | font-family: Lato, Helvetica; 347 | font-weight: 300; 348 | font-size: .9em; 349 | 350 | } 351 | 352 | .api__small_title() { 353 | display: block; 354 | padding-top: 1em; 355 | .smallcaps(black, 300); 356 | } 357 | 358 | .api__element__use:before { 359 | .api_font(); 360 | .api__small_title(); 361 | content: 'invocation:'; 362 | } 363 | 364 | .api__element__command_desc:before { 365 | .api_font(); 366 | .api__small_title(); 367 | content: 'description:'; 368 | } 369 | 370 | .api__element__returns { 371 | &:before { 372 | .api_font(); 373 | .api__small_title(); 374 | content: 'returns:'; 375 | } 376 | } 377 | 378 | 379 | .api__element__returns__element { 380 | margin-top: .5em; 381 | width: 100%; 382 | background-color: darken(white,5%); 383 | } 384 | 385 | .api__element__returns__element__value { 386 | width: 20%; 387 | display: inline-block; 388 | } 389 | 390 | .api__element__returns__element__when { 391 | width: 60%; 392 | display: inline-block; 393 | } 394 | 395 | .api__element__returns__element__when:before { 396 | content: 'when'; 397 | padding-right: 1em; 398 | .api_font(); 399 | } 400 | 401 | .api__element_example { 402 | &:before { 403 | .api_font(); 404 | .api__small_title(); 405 | content: 'example:'; 406 | } 407 | } 408 | 409 | .api__element_variations { 410 | &:before { 411 | .api_font(); 412 | .api__small_title(); 413 | content: 'variations:'; 414 | } 415 | } 416 | 417 | // ____ __ 418 | // / __/___ ____ / /____ _____ 419 | // / /_/ __ \/ __ \/ __/ _ \/ ___/ 420 | // / __/ /_/ / /_/ / /_/ __/ / 421 | // /_/ \____/\____/\__/\___/_/ 422 | // 423 | 424 | .sub-header__footer { 425 | margin-top : 5em; 426 | background-color : @darkgray; 427 | } 428 | 429 | 430 | .sub-header__footer__container { 431 | transition: margin 0.3s ease-out; 432 | -dyn-width : '@selectFrom(["90%" , "80%" , "60%"])'; 433 | -dyn-margin-left : '@selectFrom(["0" , "10%" , "20%"])'; 434 | -dyn-margin-right : '@selectFrom(["0" , "10%" , "20%"])'; 435 | display: inline-block; 436 | } 437 | 438 | .aligned-blocks() { 439 | display: block; 440 | float: left; 441 | -dyn-width : '@selectFrom(["100%", "100%", "33%"])'; 442 | -dyn-margin-left : '@selectFrom(["10px" , "0px" , "0px"])'; 443 | -dyn-margin-right : '@selectFrom(["10px" , "0px" , "0px"])'; 444 | -dyn-margin-top : '@selectFrom(["1em" , "1em" , "1em"])'; 445 | 446 | } 447 | 448 | .footer__common-properties() { 449 | -dyn-padding-top : '@selectFrom(["1em" , "1em" , "4em"])'; 450 | -dyn-padding-bottom : '@selectFrom(["1em" , "1em" , "4em"])'; 451 | } 452 | 453 | a:visited, a:link { 454 | color: white; 455 | } 456 | 457 | .sub-header__footer__madeby { 458 | 459 | .aligned-blocks(); 460 | .footer__common-properties(); 461 | -dyn-text-align : '@selectFrom(["center" , "center" , "right"])'; 462 | &:before { 463 | .smallcaps(white, 300); 464 | content: 'made by'; 465 | margin-right: 1%; 466 | display: block; 467 | } 468 | 469 | } 470 | 471 | .sub-header__footer__license { 472 | .aligned-blocks(); 473 | .footer__common-properties(); 474 | text-align: center; 475 | &:before { 476 | .smallcaps(white, 300); 477 | content: 'license'; 478 | margin-right: 1%; 479 | display: block; 480 | } 481 | } 482 | 483 | .sub-header__footer__share { 484 | .aligned-blocks(); 485 | .footer__common-properties(); 486 | -dyn-text-align : '@selectFrom(["center" , "center" , "left"])'; 487 | } 488 | 489 | 490 | .sub-header__footer__madeby__address { 491 | font-size: .7em; 492 | } 493 | 494 | .sub-header__footer__madeby__title { 495 | .smallcaps(white, 300); 496 | } 497 | 498 | .sub-header__footer__share__reddit { 499 | padding: 1em; 500 | display: inline; 501 | } 502 | 503 | .sub-header__footer__share__twitter { 504 | padding: 1em; 505 | display: inline; 506 | } 507 | 508 | // __ __ 509 | // / /_ ____ ____/ /_ __ 510 | // / __ \/ __ \/ __ / / / / 511 | // / /_/ / /_/ / /_/ / /_/ / 512 | // /_.___/\____/\__,_/\__, / 513 | // /____/ 514 | 515 | body { 516 | background : url(../img/silhouette_dune_desktop.jpg) no-repeat center center; 517 | background-size : cover; 518 | margin : 0px; 519 | -dyn-width : '@win-width'; 520 | -dyn-height : '@win-height'; 521 | } -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dyn-css", 3 | "version": "0.8.1", 4 | "homepage": "https://github.com/vzaccaria/DynCSS", 5 | "authors": [ 6 | "Vittorio Zaccaria " 7 | ], 8 | "description": "Dynamic rules for css", 9 | "main": "lib/dyncss.js", 10 | "keywords": [ 11 | "dynamic", 12 | "css", 13 | "rules" 14 | ], 15 | "license": "MIT", 16 | "private": false, 17 | "ignore": [ 18 | "**/.*", 19 | "assets", 20 | "bower.json", 21 | "bower_components", 22 | "config.ls", 23 | "dist", 24 | "gulpfile.ls", 25 | "node_modules", 26 | "package.json", 27 | "vendor" 28 | ], 29 | "dependencies": { 30 | "jquery": "~2.1.0", 31 | "q": "~2.0.0" 32 | } 33 | } -------------------------------------------------------------------------------- /complete-deploy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -e 3 | 4 | 5 | function build_package { 6 | phase "Building the library" 7 | cult build-clean 8 | cult default 9 | rm -rf lib 10 | mkdir -p lib 11 | 12 | phase "Copying the library" 13 | run 'cp dist/js/client.js lib/dyncss.js' 14 | 15 | phase "Testing the library" 16 | run "cd assets/js && make" 17 | } 18 | 19 | function add_package_to_repo { 20 | run "cd $dstdir" 21 | phase "Adding the library to the repo" 22 | run "git add lib/dyncss.js" 23 | } 24 | 25 | usage=" 26 | Usage: complete-deploy 27 | 28 | description 29 | 30 | -i --increment 31 | Specify the level of the current version number to increment. 32 | Valid levels are 'major', 'minor', 'patch', and 'prerelease'. 33 | 'patch' is assumed if this option is omitted. 34 | 35 | -d --dry-run 36 | Print the commands without evaluating them. 37 | " 38 | 39 | # Absolute path: 40 | # 41 | # Usage: abs=`get_abs_path ./deploy/static` 42 | # echo $abs 43 | # 44 | function get_abs_path { 45 | dir=$(cd `dirname $1` >/dev/null; pwd ) 46 | echo $dir 47 | } 48 | # 49 | 50 | # Get basename: 51 | function get_base_name { 52 | n=$1 53 | n=$(basename "$n") 54 | echo "${n%.*}" 55 | } 56 | 57 | 58 | #if [ $? -eq 0 ] 59 | #then 60 | # echo "it worked" 61 | #else 62 | # echo "it failed" 63 | #fi 64 | 65 | # Source directory 66 | # 67 | srcdir=`dirname $0` 68 | srcdir=`cd $srcdir; pwd` 69 | 70 | # 71 | # Temp directory: 72 | # 73 | # dstdir=`mktemp -d -t bashtmp` 74 | # 75 | # or current: 76 | # 77 | dstdir=`pwd` 78 | 79 | function directory_does_exist { 80 | if [ ! -d "$1" ]; then 81 | echo 'true' 82 | else 83 | echo 'false' 84 | fi 85 | } 86 | 87 | bold=$(tput bold) 88 | reset=$(tput sgr0) 89 | function print_important_message { 90 | printf "${bold}$1${reset}\n" 91 | } 92 | 93 | function ask_for_key { 94 | printf "Press [enter] to continue" 95 | read -s # suppress user input 96 | echo 97 | } 98 | 99 | 100 | # dryrun 101 | dry_run=false 102 | run() { 103 | echo "$1" 104 | if [[ $dry_run == false ]] ; then 105 | eval "$1" 106 | fi 107 | } 108 | 109 | increment=patch 110 | branch=master 111 | 112 | 113 | while (($# > 0)) ; do 114 | option="$1" 115 | shift 116 | 117 | case "$option" in 118 | -h|--help) 119 | echo "$usage" 120 | exit 121 | ;; 122 | -i|--increment) increment="$1" ; shift ;; 123 | -d|--dry-run) dry_run=true ;; 124 | *) 125 | echo "Unrecognized option $option" >&2 126 | exit 1 127 | esac 128 | done 129 | 130 | function phase { 131 | printf "\n" 132 | printf "\n" 133 | printf "# \n" 134 | printf "# $1 \n" 135 | } 136 | 137 | print_important_message "This will commit both the site and a new version of the package" 138 | print_important_message "Make sure you've committed all changes to master" 139 | ask_for_key 140 | 141 | build_package 142 | 143 | add_package_to_repo 144 | 145 | phase "Updating bower package" 146 | name=$(node -p "require('$dstdir/bower.json').name" 2>/dev/null) || 147 | (echo "Cannot read package name" >&2 ; exit 1) 148 | 149 | print_important_message "Current package is: $name" 150 | version=$(node -p "require('$dstdir/bower.json').version" 2>/dev/null) || 151 | (echo "Cannot read package version " >&2 ; exit 1) 152 | 153 | print_important_message "Current package version is: $version" 154 | next_version=$("semver" -i "$increment" "$version") 155 | 156 | 157 | message_template='Version X.Y.Z' 158 | tag_template=vX.Y.Z 159 | message="${message_template//X.Y.Z/$next_version}" 160 | tag="${tag_template//X.Y.Z/$next_version}" 161 | 162 | 163 | run "node -e '$(echo " 164 | var o = require('$dstdir/bower.json'); 165 | o.version = '$next_version'; 166 | var s = JSON.stringify(o, null, 2) + '\n'; 167 | require('fs').writeFileSync('$dstdir/bower.json', s); 168 | " | tr "'" '"' | tr -d "\n" | sed "s/^[ ]*//" | tr -s " ")'" 169 | 170 | phase "Committing bower package" 171 | run "git add bower.json" 172 | run "git commit --message '$message'" 173 | run "git tag --annotate '$tag' --message '$message'" 174 | run "git push origin 'refs/heads/$branch' 'refs/tags/$tag'" 175 | 176 | phase "Updating the website" 177 | run 'cult ftp' -------------------------------------------------------------------------------- /config.ls: -------------------------------------------------------------------------------- 1 | _module = -> 2 | 3 | 4 | iface = { 5 | 6 | # main properties 7 | destination:'dist' 8 | remote:'dyn-css' 9 | 10 | vendor-js: 11 | "./bower_components/jquery/dist/jquery.min.js" 12 | "./dist/js/build/site.js" 13 | ... 14 | 15 | # client files 16 | client-ls: 17 | "./assets/js/*.ls" 18 | ... 19 | 20 | client-brfy-roots: [ 'entry.js' ] 21 | 22 | client-html: 23 | "./assets/*.jade" 24 | "./assets/views/*.jade" 25 | ... 26 | 27 | client-less: 28 | './assets/less/*.less' 29 | ... 30 | 31 | directives:[ 32 | './assets/directives/*.sjs' 33 | ] 34 | 35 | # vendor files 36 | vendor-css: 37 | './assets/css/*.css' 38 | ... 39 | 40 | # other assets 41 | font-dir:'./assets/fonts' 42 | 43 | img-dir:'./assets/img' 44 | 45 | data-to-be-copied:[ 46 | "./data/*.json" 47 | "./assets/less/*.dss" 48 | ] 49 | 50 | 51 | other-deps: [] 52 | 53 | } 54 | 55 | return iface 56 | 57 | module.exports = _module() -------------------------------------------------------------------------------- /dist/css/vendor.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Obsidian style 3 | * ported by Alexander Marenin (http://github.com/ioncreature) 4 | */ 5 | 6 | .hljs { 7 | display: block; padding: 0.5em; 8 | background: #282B2E; 9 | } 10 | 11 | .hljs-keyword, 12 | .hljs-literal, 13 | .hljs-change, 14 | .hljs-winutils, 15 | .hljs-flow, 16 | .lisp .hljs-title, 17 | .clojure .hljs-built_in, 18 | .nginx .hljs-title, 19 | .css .hljs-id, 20 | .tex .hljs-special { 21 | color: #93C763; 22 | } 23 | 24 | .hljs-number { 25 | color: #FFCD22; 26 | } 27 | 28 | .hljs { 29 | color: #E0E2E4; 30 | } 31 | 32 | .css .hljs-tag, 33 | .css .hljs-pseudo { 34 | color: #D0D2B5; 35 | } 36 | 37 | .hljs-attribute, 38 | .hljs .hljs-constant { 39 | color: #668BB0; 40 | } 41 | 42 | .xml .hljs-attribute { 43 | color: #B3B689; 44 | } 45 | 46 | .xml .hljs-tag .hljs-value { 47 | color: #E8E2B7; 48 | } 49 | 50 | .hljs-code, 51 | .hljs-class .hljs-title, 52 | .hljs-header { 53 | color: white; 54 | } 55 | 56 | .hljs-class, 57 | .hljs-hexcolor { 58 | color: #93C763; 59 | } 60 | 61 | .hljs-regexp { 62 | color: #D39745; 63 | } 64 | 65 | .hljs-at_rule, 66 | .hljs-at_rule .hljs-keyword { 67 | color: #A082BD; 68 | } 69 | 70 | .hljs-doctype { 71 | color: #557182; 72 | } 73 | 74 | .hljs-link_url, 75 | .hljs-tag, 76 | .hljs-tag .hljs-title, 77 | .hljs-bullet, 78 | .hljs-subst, 79 | .hljs-emphasis, 80 | .haskell .hljs-type, 81 | .hljs-preprocessor, 82 | .hljs-pragma, 83 | .ruby .hljs-class .hljs-parent, 84 | .hljs-built_in, 85 | .sql .hljs-aggregate, 86 | .django .hljs-template_tag, 87 | .django .hljs-variable, 88 | .smalltalk .hljs-class, 89 | .hljs-javadoc, 90 | .django .hljs-filter .hljs-argument, 91 | .smalltalk .hljs-localvars, 92 | .smalltalk .hljs-array, 93 | .hljs-attr_selector, 94 | .hljs-pseudo, 95 | .hljs-addition, 96 | .hljs-stream, 97 | .hljs-envvar, 98 | .apache .hljs-tag, 99 | .apache .hljs-cbracket, 100 | .tex .hljs-command, 101 | .hljs-prompt { 102 | color: #8CBBAD; 103 | } 104 | 105 | .hljs-string { 106 | color: #EC7600; 107 | } 108 | 109 | .hljs-comment, 110 | .java .hljs-annotation, 111 | .hljs-blockquote, 112 | .hljs-horizontal_rule, 113 | .python .hljs-decorator, 114 | .hljs-template_comment, 115 | .hljs-pi, 116 | .hljs-deletion, 117 | .hljs-shebang, 118 | .apache .hljs-sqbracket, 119 | .tex .hljs-formula { 120 | color: #818E96; 121 | } 122 | 123 | .hljs-keyword, 124 | .hljs-literal, 125 | .css .hljs-id, 126 | .hljs-phpdoc, 127 | .hljs-title, 128 | .hljs-header, 129 | .haskell .hljs-type, 130 | .vbscript .hljs-built_in, 131 | .sql .hljs-aggregate, 132 | .rsl .hljs-built_in, 133 | .smalltalk .hljs-class, 134 | .diff .hljs-header, 135 | .hljs-chunk, 136 | .hljs-winutils, 137 | .bash .hljs-variable, 138 | .apache .hljs-tag, 139 | .tex .hljs-special, 140 | .hljs-request, 141 | .hljs-at_rule .hljs-keyword, 142 | .hljs-status { 143 | font-weight: bold; 144 | } 145 | 146 | .coffeescript .javascript, 147 | .javascript .xml, 148 | .tex .hljs-formula, 149 | .xml .javascript, 150 | .xml .vbscript, 151 | .xml .css, 152 | .xml .hljs-cdata { 153 | opacity: 0.5; 154 | } 155 | -------------------------------------------------------------------------------- /dist/img/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vzaccaria/DynCSS/28411828f1235ed10235e4c62bb4bce7a71a0ec2/dist/img/background.jpg -------------------------------------------------------------------------------- /dist/img/silhouette_dune_desktop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vzaccaria/DynCSS/28411828f1235ed10235e4c62bb4bce7a71a0ec2/dist/img/silhouette_dune_desktop.jpg -------------------------------------------------------------------------------- /gulpfile.ls: -------------------------------------------------------------------------------- 1 | 2 | { client-html, client-less, client-ls, client-brfy-roots, directives, other-deps } = require('./config') 3 | { vendor-js, vendor-css, , data-to-be-copied } = require('./config') 4 | { remote, destination, font-dir, img-dir } = require('./config') 5 | 6 | client-js = [ "#destination/js/build/#s" for s in client-brfy-roots ] 7 | 8 | files-to-watch = client-ls ++ client-less ++ client-html ++ directives ++ other-deps 9 | 10 | force-file-reload = [ 11 | "#destination/**/*.html" 12 | "#destination/**/*.css" 13 | "#destination/**/*.js" 14 | "#destination/**/*.png" 15 | "#destination/**/*.jpg" 16 | ] 17 | 18 | require! 'gulp' 19 | jade = require 'gulp-jade' 20 | stylus = require 'gulp-stylus' 21 | ftp = require 'gulp-ftp' 22 | less = require 'gulp-less' 23 | browserify = require 'gulp-browserify' 24 | live = require 'gulp-livescript' 25 | uglify = require 'gulp-uglify' 26 | concat = require 'gulp-concat' 27 | rename = require 'gulp-rename' 28 | exec = require 'gulp-exec' 29 | clean = require 'gulp-clean' 30 | filesize = require('gulp-filesize'); 31 | spawn = require 'gulp-spawn' 32 | changed = require 'gulp-changed' 33 | plumber = require('gulp-plumber'); 34 | cr = require '/Users/zaccaria/.ssh/sftp_credentials' 35 | 36 | 37 | 38 | EXPRESS_PORT = 4000; 39 | EXPRESS_ROOT = destination; 40 | LIVERELOAD_PORT = 35729; 41 | 42 | start-express = -> 43 | express = require('express'); 44 | app = express(); 45 | app.use(require('connect-livereload')()); 46 | app.use(express.static(EXPRESS_ROOT, {maxAge: 0})); 47 | app.listen(EXPRESS_PORT); 48 | 49 | var lr 50 | 51 | start-livereload = -> 52 | lr := require('tiny-lr')() 53 | lr.listen(LIVERELOAD_PORT) 54 | 55 | 56 | notifyLivereload = (event) -> 57 | fileName = require('path').relative(EXPRESS_ROOT, event.path); 58 | lr.changed body: { files: [fileName] } 59 | 60 | 61 | gulp.task 'build-html', -> 62 | gulp.src client-html 63 | .pipe plumber() 64 | .pipe jade() 65 | .pipe gulp.dest "#destination/html" 66 | 67 | gulp.task 'build-index', ['build-html'] -> 68 | gulp.src "#destination/html/index.html" 69 | .pipe gulp.dest "#destination" 70 | 71 | gulp.task 'build-client-js', ['build-client-ls'], -> 72 | gulp.src client-js, { read: false } 73 | .pipe plumber() 74 | .pipe browserify { 75 | insertGlobals : false 76 | } 77 | .pipe concat('client.js') 78 | .pipe gulp.dest "#destination/js" 79 | 80 | gulp.task 'build-client-ls', -> 81 | gulp.src client-ls 82 | .pipe plumber() 83 | .pipe changed "#destination/js/build" 84 | .pipe live() 85 | .pipe gulp.dest "#destination/js/build" 86 | 87 | gulp.task 'build-vendor-js-prod', ['build-client-js'],-> 88 | gulp.src vendor-js 89 | .pipe(concat('vendor.js')) 90 | .pipe filesize() 91 | .pipe gulp.dest "#destination/js" 92 | .pipe uglify() 93 | .pipe rename('vendor.min.js') 94 | .pipe filesize() 95 | .pipe gulp.dest "#destination/js" 96 | 97 | gulp.task 'build-vendor-js', ['build-client-js'], -> 98 | gulp.src vendor-js 99 | .pipe(concat('vendor.js')) 100 | .pipe gulp.dest "#destination/js" 101 | 102 | gulp.task 'build-less', -> 103 | gulp.src client-less 104 | .pipe plumber() 105 | .pipe changed "#destination/css/build" 106 | .pipe less() 107 | .pipe gulp.dest "#destination/css/build" 108 | 109 | gulp.task 'build-css', ['build-less'], -> 110 | gulp.src "#destination/css/build/*.css" 111 | .pipe plumber() 112 | .pipe concat('client.css') 113 | .pipe gulp.dest "#destination/css" 114 | 115 | gulp.task 'build-vendor-css', -> 116 | gulp.src vendor-css 117 | .pipe concat('vendor.css') 118 | .pipe gulp.dest "#destination/css" 119 | 120 | gulp.task 'build-img', -> 121 | gulp.src ["#img-dir/*.png", "#img-dir/*.jpg"] 122 | .pipe changed "#destination/img" 123 | .pipe gulp.dest "#destination/img" 124 | 125 | gulp.task 'build-fonts', -> 126 | gulp.src [ "#font-dir/*.woff" 127 | "#font-dir/*.otf" 128 | "#font-dir/*.eot" 129 | "#font-dir/*.svg" 130 | "#font-dir/*.ttf" 131 | ] 132 | .pipe changed "#destination/fonts" 133 | .pipe gulp.dest "#destination/fonts" 134 | 135 | gulp.task 'ftp', -> 136 | gulp.src ["#destination/**"] 137 | .pipe ftp { 138 | host: '217.64.195.216' 139 | user: 'vittoriozaccaria.net' 140 | pass: cr['217.64.195.216']['vittoriozaccaria.net'] 141 | remote-path: "htdocs/#remote" 142 | } 143 | 144 | 145 | gulp.task 'sjs', -> 146 | gulp.src directives 147 | .pipe changed "#destination/js" 148 | .pipe((spawn { cmd: 'sweet-angle', args: [ '-a', 'application', '/dev/stdin'] }).on 'error', console.log) 149 | .pipe gulp.dest "#destination/js" 150 | 151 | 152 | gulp.task 'build-clean', -> 153 | gulp.src destination, {read: false} 154 | .pipe clean() 155 | 156 | gulp.task 'js-build-clean', -> 157 | gulp.src "#destination/js/build", {read: false} 158 | .pipe clean() 159 | 160 | gulp.task 'watch-build', -> 161 | startExpress(); 162 | startLivereload(); 163 | gulp.watch(force-file-reload, notifyLivereload); 164 | files-to-watch = client-ls ++ client-less ++ client-html ++ directives ++ other-deps 165 | gulp.watch(files-to-watch, ["default"]) 166 | 167 | 168 | fs = require('fs') 169 | 170 | gulp.task 'build-package-json', -> 171 | fs.readdir "./node_modules", (err, dirs) -> 172 | for dir in dirs 173 | if dir.index-of(".") != 0 174 | packageJsonFile = "./node_modules/#dir/package.json" 175 | if fs.existsSync packageJsonFile 176 | fs.readFile packageJsonFile, (err, data) -> 177 | json = JSON.parse(data) 178 | console.log "\"#{json.name}\": \"#{json.version}\", " 179 | 180 | gulp.task 'copy-data', -> 181 | gulp.src data-to-be-copied 182 | .pipe changed("#destination/data") 183 | .pipe gulp.dest "#destination/data" 184 | 185 | gulp.task 'default', [ 186 | \build-index 187 | \build-client-js 188 | \build-vendor-js 189 | \build-vendor-css 190 | \build-css 191 | \build-fonts 192 | \build-img 193 | \copy-data 194 | \sjs 195 | ... 196 | ] 197 | 198 | gulp.task 'production', [ 199 | \build-index 200 | \build-client-js 201 | \build-vendor-js-prod 202 | \build-vendor-css 203 | \build-css 204 | \build-fonts 205 | \build-img 206 | \copy-data 207 | \sjs 208 | ... 209 | ] 210 | 211 | runSequence = require('run-sequence'); 212 | 213 | gulp.task 'dev', (done) -> 214 | runSequence 'build-clean', 'default', 'watch-build', done 215 | 216 | gulp.task 'deploy', (done) -> 217 | runSequence 'build-clean', 'default', 'ftp' 218 | -------------------------------------------------------------------------------- /lib/dyncss.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o " + css[k] + ")"); 208 | } 209 | windowDi.dynCss.el.css((ref$ = {}, ref$[k + ""] = v, ref$)); 210 | this.oldValue == null && (this.oldValue = {}); 211 | this.oldValue[k] = v; 212 | changed = true; 213 | } 214 | } 215 | return newValue = JSON.stringify(css); 216 | function fn$(){ 217 | switch (false) { 218 | case !!windowDi.dynCss.config.dontComputeInvisible: 219 | return true; 220 | case windowDi.dynCss.el.css('display') === 'none': 221 | return true; 222 | default: 223 | return false; 224 | } 225 | } 226 | } 227 | }; 228 | }.call(this, actions, sel)); 229 | } 230 | }; 231 | return { 232 | innerModule: innerModule, 233 | buildHandlers: buildHandlers 234 | }; 235 | }; 236 | module.exports = dynCss; 237 | }).call(this); 238 | 239 | },{"./lib":3}],2:[function(require,module,exports){ 240 | (function(){ 241 | var cssParse, builtIn, dynCss, _q, buildHandlers, blue, red, normal, entryDebugMessage, scrollHandler, refreshHandler, decimate, iOS, counter, lt, fixedTtc, installCustomRaf, installScrollHandler, parseCss, _loaded_d, _loaded_p, results, pArray, r; 242 | cssParse = require('css-parse'); 243 | builtIn = require('./lib'); 244 | dynCss = require('./core'); 245 | _q = require('q'); 246 | buildHandlers = dynCss(window, document, jQuery).buildHandlers; 247 | blue = '#3498db'; 248 | red = '#c0392b'; 249 | normal = 'black'; 250 | entryDebugMessage = function(m){ 251 | if (window.dynCss.config.debug) { 252 | return console.log("%cdyncss-entry: %c" + m, "color: " + blue, "color: " + normal); 253 | } 254 | }; 255 | refreshHandler = function(changed){ 256 | if (changed) { 257 | return window.dynCss.api.forceRedraw(); 258 | } 259 | }; 260 | decimate = 1; 261 | iOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent); 262 | counter = 0; 263 | lt = 0; 264 | fixedTtc = 1000 / 1; 265 | installCustomRaf = function(){ 266 | return window.customRequestAnimationFrame = function(cb){ 267 | var ct, ttc; 268 | ct = new Date().getTime(); 269 | ttc = Math.max(0, 16 - (ct - lt)); 270 | if (fixedTtc != null) { 271 | setTimeout(cb, fixedTtc, true); 272 | } else { 273 | setTimeout(cb, ttc, true); 274 | } 275 | return lt = ct + ttc; 276 | }; 277 | }; 278 | installScrollHandler = function(options){ 279 | scrollHandler = function(){ 280 | if (window.dynCss.config.useRAF) { 281 | return window.requestAnimationFrame(function(){ 282 | if (counter % decimate === 0) { 283 | refreshHandler(false); 284 | } 285 | return counter = counter + 1; 286 | }); 287 | } else { 288 | if (counter % decimate === 0) { 289 | refreshHandler(false); 290 | } 291 | return counter = counter + 1; 292 | } 293 | }; 294 | if ((options != null ? options.onlyOnResize : void 8) != null) { 295 | return window.onresize = scrollHandler; 296 | } else { 297 | if ((options != null ? options.onlyOnStart : void 8) == null) { 298 | window.onscroll = scrollHandler; 299 | window.ontouchmove = scrollHandler; 300 | return window.onresize = scrollHandler; 301 | } 302 | } 303 | }; 304 | entryDebugMessage("Scanning for css"); 305 | parseCss = function(n){ 306 | var _d; 307 | entryDebugMessage("Loading " + n.href); 308 | _d = _q.defer(); 309 | if (n.href != null) { 310 | $.get(n.href, function(it){ 311 | var rules; 312 | entryDebugMessage("Loaded " + n.href); 313 | rules = cssParse(it).stylesheet.rules; 314 | refreshHandler = buildHandlers(rules, refreshHandler); 315 | if (refreshHandler != null) { 316 | if (iOS) { 317 | installScrollHandler({ 318 | onlyOnStart: true 319 | }); 320 | } else { 321 | installScrollHandler(); 322 | } 323 | } 324 | return _d.resolve(); 325 | }); 326 | } 327 | return _d.promise; 328 | }; 329 | _loaded_d = _q.defer(); 330 | _loaded_p = _loaded_d.promise; 331 | window.onload = function(){ 332 | entryDebugMessage("Content loaded"); 333 | return _loaded_d.resolve(); 334 | }; 335 | $(document).ready = function(){ 336 | return entryDebugMessage("Document parsed."); 337 | }; 338 | results = $('link[type="text/css"]'); 339 | pArray = (function(){ 340 | var i$, ref$, len$, results$ = []; 341 | for (i$ = 0, len$ = (ref$ = results).length; i$ < len$; ++i$) { 342 | r = ref$[i$]; 343 | results$.push(parseCss(r)); 344 | } 345 | return results$; 346 | }()).concat([_loaded_p]); 347 | _q.all(pArray).then(function(){ 348 | entryDebugMessage("Initializing handler"); 349 | return scrollHandler(); 350 | }); 351 | window.dynCss.api.initVariable = function(vr, value){ 352 | return window.dynCss.lib[vr] = value; 353 | }; 354 | window.dynCss.api.setVariable = function(vr, value){ 355 | window.dynCss.api.initVariable(vr, value); 356 | return scrollHandler(); 357 | }; 358 | window.dynCss.api.initToggle = function(vr, value1, value2){ 359 | window.dynCss.api.initVariable(vr, value1); 360 | window.dynCss.api.initVariable(vr + "Value0", value1); 361 | window.dynCss.api.initVariable(vr + "Value1", value2); 362 | return entryDebugMessage("Initialising variable " + vr + " to " + value1); 363 | }; 364 | window.dynCss.api.toggle = function(vr){ 365 | var vv, v1, v2; 366 | vv = window.dynCss.lib[vr]; 367 | v1 = window.dynCss.lib[vr + "Value0"]; 368 | v2 = window.dynCss.lib[vr + "Value1"]; 369 | if (vv === v1) { 370 | window.dynCss.api.setVariable(vr, v2); 371 | return entryDebugMessage("Setting " + vr + " to " + v2); 372 | } else { 373 | window.dynCss.api.setVariable(vr, v1); 374 | return entryDebugMessage("Setting " + vr + " to " + v1); 375 | } 376 | }; 377 | }).call(this); 378 | 379 | },{"./core":1,"./lib":3,"css-parse":4,"q":6}],3:[function(require,module,exports){ 380 | (function(){ 381 | var debug, perspective, sat, asPercentageOf, asRemainingPercentageOf, shouldDisappear, transitionToOne, shouldAppear, selectFrom, ifThenElse, isVerticallyVisible, topOf, bottomOf, leftOf, rightOf, _module; 382 | debug = false; 383 | perspective = function(px){ 384 | return "perspective(" + px + "px) "; 385 | }; 386 | sat = function(x){ 387 | switch (false) { 388 | case !(x > 1): 389 | return 1; 390 | case !(x < 0): 391 | return 0; 392 | default: 393 | return x; 394 | } 395 | }; 396 | asPercentageOf = curry$(function(x$, y$){ 397 | return x$ / y$; 398 | }); 399 | asRemainingPercentageOf = function(x, y){ 400 | return 1 - asPercentageOf(x, y); 401 | }; 402 | shouldDisappear = function(context){ 403 | var isHigherThan, isLowerThan, wn, v; 404 | isHigherThan = context.isHigherThan, isLowerThan = context.isLowerThan, wn = context.when; 405 | if (isHigherThan != null && wn != null) { 406 | return sat(asRemainingPercentageOf(wn, isHigherThan)); 407 | } 408 | if (isLowerThan != null && wn != null) { 409 | v = sat(asPercentageOf(wn, isLowerThan)); 410 | return v; 411 | } 412 | }; 413 | transitionToOne = function(context, power){ 414 | var int, vv, direction, start, stop, val, orig, pp; 415 | power == null && (power = 1); 416 | start = context.start, stop = context.stop, val = context.when; 417 | orig = val; 418 | pp = (function(){ 419 | switch (false) { 420 | case !(start < stop && val < start): 421 | return 0; 422 | case !(start < stop && val > stop): 423 | return 1; 424 | case !(start < stop): 425 | return (val - start) / (stop - start); 426 | case !(start > stop && val > start): 427 | return 1; 428 | case !(start > stop && val < stop): 429 | return 0; 430 | case !(start > stop): 431 | return 1 - (val - stop) / (start - stop); 432 | } 433 | }()); 434 | vv = sat(pp); 435 | return Math.pow(vv, power); 436 | }; 437 | shouldAppear = function(context){ 438 | var isHigherThan, isLowerThan, wn, vv, int; 439 | isHigherThan = context.isHigherThan, isLowerThan = context.isLowerThan, wn = context.when; 440 | wn = context['when']; 441 | if (isHigherThan != null && wn != null) { 442 | int = asPercentageOf(wn, isHigherThan); 443 | } 444 | if (isLowerThan != null && wn != null) { 445 | int = asRemainingPercentageOf(wn, isLowerThan); 446 | } 447 | vv = sat(int); 448 | if (debug) { 449 | console.log("final: " + vv + ", intermediate: " + int + ", is-higher: " + isHigherThan + ", is-lower: " + isLowerThan); 450 | } 451 | return vv; 452 | }; 453 | selectFrom = function(values){ 454 | var dt, vv, i$, ref$, len$, i, b, error; 455 | dt = window.dynCss.data['responsive']; 456 | try { 457 | if (dt.compiled != null && values.length > 0) { 458 | vv = dt.compiled(); 459 | for (i$ = 0, len$ = (ref$ = dt.breakpoints).length; i$ < len$; ++i$) { 460 | i = i$; 461 | b = ref$[i$]; 462 | if (vv < b || i === values.length - 1) { 463 | return values[i]; 464 | } 465 | } 466 | return values[values.length - 1]; 467 | } 468 | } catch (e$) { 469 | return error = e$; 470 | } 471 | }; 472 | ifThenElse = function(cond, v1, v2){ 473 | if (cond) { 474 | return v1; 475 | } else { 476 | return v2; 477 | } 478 | }; 479 | isVerticallyVisible = function(el, threshold){ 480 | var r, w, vp, value; 481 | r = jQuery(el)[0].getBoundingClientRect(); 482 | w = jQuery(window); 483 | vp = { 484 | top: w.scrollTop(), 485 | bottom: w.scrollTop() + w.height() 486 | }; 487 | threshold == null && (threshold = w.height() / 3); 488 | value = (function(){ 489 | switch (false) { 490 | case !(r.top >= 0 && r.top < threshold): 491 | return true; 492 | case !(r.top < 0 && r.bottom > threshold): 493 | return true; 494 | default: 495 | return false; 496 | } 497 | }()); 498 | return value; 499 | }; 500 | topOf = function(el){ 501 | if (el !== window) { 502 | return jQuery(el).offset().top - $(window).scrollTop(); 503 | } else { 504 | return 0; 505 | } 506 | }; 507 | bottomOf = function(el){ 508 | if (el !== window) { 509 | return jQuery(el).offset().top - $(window).scrollTop() + parseInt(jQuery(el).css('margin-bottom')) + jQuery(el).innerHeight(); 510 | } else { 511 | return $(window).height(); 512 | } 513 | }; 514 | leftOf = function(el){ 515 | if (el !== window) { 516 | return jQuery(el).offset().left + parseInt(jQuery(el).css('margin-right')); 517 | } else { 518 | return 0; 519 | } 520 | }; 521 | rightOf = function(el){ 522 | if (el !== window) { 523 | return jQuery(el).offset().left + parseInt(jQuery(el).css('margin-right')) + jQuery(el).innerWidth(); 524 | } else { 525 | return $(window).width(); 526 | } 527 | }; 528 | _module = function(){ 529 | var iface; 530 | iface = { 531 | shouldDisappear: shouldDisappear, 532 | convergeToZero: shouldDisappear, 533 | shouldAppear: shouldAppear, 534 | convergeToOne: shouldAppear, 535 | transitionToOne: transitionToOne, 536 | perspective: perspective, 537 | selectFrom: selectFrom, 538 | isVerticallyVisible: isVerticallyVisible, 539 | 'if': ifThenElse, 540 | fixedTopEdge: topOf, 541 | fixedBottomEdge: bottomOf, 542 | fixedRightEdge: rightOf, 543 | fixedLeftEdge: leftOf, 544 | pos: function(el){ 545 | return $(el).offset(); 546 | }, 547 | fixedHorizontalCenter: function(it){ 548 | return (rightOf(it) + leftOf(it)) / 2; 549 | }, 550 | fixedVerticalCenter: function(it){ 551 | return (topOf(it) + bottomOf(it)) / 2; 552 | }, 553 | morph: function(c, v1, v2){ 554 | var vv; 555 | vv = v1 * (1 - c) + v2 * c; 556 | return vv; 557 | }, 558 | shouldBeVisible: function(){ 559 | var $wTop, $el, $elTop, $elH, $wHeight, $setOff, v; 560 | $wTop = $(window).scrollTop(); 561 | $el = jQuery(window.dynCss.el); 562 | $elTop = $el.offset().top; 563 | $elH = $el.innerHeight(); 564 | $wHeight = $(window).height(); 565 | $setOff = $elTop; 566 | v = shouldAppear({ 567 | when: $(window).scrollTop(), 568 | isHigherThan: $setOff 569 | }); 570 | if (debug) { 571 | console.log("top = " + $wTop + ", completed-at = " + $setOff + ", visible = " + v + ", eltop = " + $elTop + ", el-h = " + $elH); 572 | } 573 | return v; 574 | } 575 | }; 576 | return iface; 577 | }; 578 | module.exports = _module(); 579 | function curry$(f, bound){ 580 | var context, 581 | _curry = function(args) { 582 | return f.length > 1 ? function(){ 583 | var params = args ? args.concat() : []; 584 | context = bound ? context || this : this; 585 | return params.push.apply(params, arguments) < 586 | f.length && arguments.length ? 587 | _curry.call(context, params) : f.apply(context, params); 588 | } : f; 589 | }; 590 | return _curry(); 591 | } 592 | }).call(this); 593 | 594 | },{}],4:[function(require,module,exports){ 595 | 596 | module.exports = function(css, options){ 597 | options = options || {}; 598 | 599 | /** 600 | * Positional. 601 | */ 602 | 603 | var lineno = 1; 604 | var column = 1; 605 | 606 | /** 607 | * Update lineno and column based on `str`. 608 | */ 609 | 610 | function updatePosition(str) { 611 | var lines = str.match(/\n/g); 612 | if (lines) lineno += lines.length; 613 | var i = str.lastIndexOf('\n'); 614 | column = ~i ? str.length - i : column + str.length; 615 | } 616 | 617 | /** 618 | * Mark position and patch `node.position`. 619 | */ 620 | 621 | function position() { 622 | var start = { line: lineno, column: column }; 623 | if (!options.position) return positionNoop; 624 | 625 | return function(node){ 626 | node.position = { 627 | start: start, 628 | end: { line: lineno, column: column }, 629 | source: options.source 630 | }; 631 | 632 | whitespace(); 633 | return node; 634 | } 635 | } 636 | 637 | /** 638 | * Return `node`. 639 | */ 640 | 641 | function positionNoop(node) { 642 | whitespace(); 643 | return node; 644 | } 645 | 646 | /** 647 | * Error `msg`. 648 | */ 649 | 650 | function error(msg) { 651 | var err = new Error(msg + ' near line ' + lineno + ':' + column); 652 | err.filename = options.source; 653 | err.line = lineno; 654 | err.column = column; 655 | err.source = css; 656 | throw err; 657 | } 658 | 659 | /** 660 | * Parse stylesheet. 661 | */ 662 | 663 | function stylesheet() { 664 | return { 665 | type: 'stylesheet', 666 | stylesheet: { 667 | rules: rules() 668 | } 669 | }; 670 | } 671 | 672 | /** 673 | * Opening brace. 674 | */ 675 | 676 | function open() { 677 | return match(/^{\s*/); 678 | } 679 | 680 | /** 681 | * Closing brace. 682 | */ 683 | 684 | function close() { 685 | return match(/^}/); 686 | } 687 | 688 | /** 689 | * Parse ruleset. 690 | */ 691 | 692 | function rules() { 693 | var node; 694 | var rules = []; 695 | whitespace(); 696 | comments(rules); 697 | while (css.charAt(0) != '}' && (node = atrule() || rule())) { 698 | rules.push(node); 699 | comments(rules); 700 | } 701 | return rules; 702 | } 703 | 704 | /** 705 | * Match `re` and return captures. 706 | */ 707 | 708 | function match(re) { 709 | var m = re.exec(css); 710 | if (!m) return; 711 | var str = m[0]; 712 | updatePosition(str); 713 | css = css.slice(str.length); 714 | return m; 715 | } 716 | 717 | /** 718 | * Parse whitespace. 719 | */ 720 | 721 | function whitespace() { 722 | match(/^\s*/); 723 | } 724 | 725 | /** 726 | * Parse comments; 727 | */ 728 | 729 | function comments(rules) { 730 | var c; 731 | rules = rules || []; 732 | while (c = comment()) rules.push(c); 733 | return rules; 734 | } 735 | 736 | /** 737 | * Parse comment. 738 | */ 739 | 740 | function comment() { 741 | var pos = position(); 742 | if ('/' != css.charAt(0) || '*' != css.charAt(1)) return; 743 | 744 | var i = 2; 745 | while (null != css.charAt(i) && ('*' != css.charAt(i) || '/' != css.charAt(i + 1))) ++i; 746 | i += 2; 747 | 748 | var str = css.slice(2, i - 2); 749 | column += 2; 750 | updatePosition(str); 751 | css = css.slice(i); 752 | column += 2; 753 | 754 | return pos({ 755 | type: 'comment', 756 | comment: str 757 | }); 758 | } 759 | 760 | /** 761 | * Parse selector. 762 | */ 763 | 764 | function selector() { 765 | var m = match(/^([^{]+)/); 766 | if (!m) return; 767 | return trim(m[0]).split(/\s*,\s*/); 768 | } 769 | 770 | /** 771 | * Parse declaration. 772 | */ 773 | 774 | function declaration() { 775 | var pos = position(); 776 | 777 | // prop 778 | var prop = match(/^(\*?[-#\/\*\w]+(\[[0-9a-z_-]+\])?)\s*/); 779 | if (!prop) return; 780 | prop = trim(prop[0]); 781 | 782 | // : 783 | if (!match(/^:\s*/)) return error("property missing ':'"); 784 | 785 | // val 786 | var val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)/); 787 | if (!val) return error('property missing value'); 788 | 789 | var ret = pos({ 790 | type: 'declaration', 791 | property: prop, 792 | value: trim(val[0]) 793 | }); 794 | 795 | // ; 796 | match(/^[;\s]*/); 797 | 798 | return ret; 799 | } 800 | 801 | /** 802 | * Parse declarations. 803 | */ 804 | 805 | function declarations() { 806 | var decls = []; 807 | 808 | if (!open()) return error("missing '{'"); 809 | comments(decls); 810 | 811 | // declarations 812 | var decl; 813 | while (decl = declaration()) { 814 | decls.push(decl); 815 | comments(decls); 816 | } 817 | 818 | if (!close()) return error("missing '}'"); 819 | return decls; 820 | } 821 | 822 | /** 823 | * Parse keyframe. 824 | */ 825 | 826 | function keyframe() { 827 | var m; 828 | var vals = []; 829 | var pos = position(); 830 | 831 | while (m = match(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/)) { 832 | vals.push(m[1]); 833 | match(/^,\s*/); 834 | } 835 | 836 | if (!vals.length) return; 837 | 838 | return pos({ 839 | type: 'keyframe', 840 | values: vals, 841 | declarations: declarations() 842 | }); 843 | } 844 | 845 | /** 846 | * Parse keyframes. 847 | */ 848 | 849 | function atkeyframes() { 850 | var pos = position(); 851 | var m = match(/^@([-\w]+)?keyframes */); 852 | 853 | if (!m) return; 854 | var vendor = m[1]; 855 | 856 | // identifier 857 | var m = match(/^([-\w]+)\s*/); 858 | if (!m) return error("@keyframes missing name"); 859 | var name = m[1]; 860 | 861 | if (!open()) return error("@keyframes missing '{'"); 862 | 863 | var frame; 864 | var frames = comments(); 865 | while (frame = keyframe()) { 866 | frames.push(frame); 867 | frames = frames.concat(comments()); 868 | } 869 | 870 | if (!close()) return error("@keyframes missing '}'"); 871 | 872 | return pos({ 873 | type: 'keyframes', 874 | name: name, 875 | vendor: vendor, 876 | keyframes: frames 877 | }); 878 | } 879 | 880 | /** 881 | * Parse supports. 882 | */ 883 | 884 | function atsupports() { 885 | var pos = position(); 886 | var m = match(/^@supports *([^{]+)/); 887 | 888 | if (!m) return; 889 | var supports = trim(m[1]); 890 | 891 | if (!open()) return error("@supports missing '{'"); 892 | 893 | var style = comments().concat(rules()); 894 | 895 | if (!close()) return error("@supports missing '}'"); 896 | 897 | return pos({ 898 | type: 'supports', 899 | supports: supports, 900 | rules: style 901 | }); 902 | } 903 | 904 | /** 905 | * Parse host. 906 | */ 907 | 908 | function athost() { 909 | var pos = position(); 910 | var m = match(/^@host */); 911 | 912 | if (!m) return; 913 | 914 | if (!open()) return error("@host missing '{'"); 915 | 916 | var style = comments().concat(rules()); 917 | 918 | if (!close()) return error("@host missing '}'"); 919 | 920 | return pos({ 921 | type: 'host', 922 | rules: style 923 | }); 924 | } 925 | 926 | /** 927 | * Parse media. 928 | */ 929 | 930 | function atmedia() { 931 | var pos = position(); 932 | var m = match(/^@media *([^{]+)/); 933 | 934 | if (!m) return; 935 | var media = trim(m[1]); 936 | 937 | if (!open()) return error("@media missing '{'"); 938 | 939 | var style = comments().concat(rules()); 940 | 941 | if (!close()) return error("@media missing '}'"); 942 | 943 | return pos({ 944 | type: 'media', 945 | media: media, 946 | rules: style 947 | }); 948 | } 949 | 950 | /** 951 | * Parse paged media. 952 | */ 953 | 954 | function atpage() { 955 | var pos = position(); 956 | var m = match(/^@page */); 957 | if (!m) return; 958 | 959 | var sel = selector() || []; 960 | 961 | if (!open()) return error("@page missing '{'"); 962 | var decls = comments(); 963 | 964 | // declarations 965 | var decl; 966 | while (decl = declaration()) { 967 | decls.push(decl); 968 | decls = decls.concat(comments()); 969 | } 970 | 971 | if (!close()) return error("@page missing '}'"); 972 | 973 | return pos({ 974 | type: 'page', 975 | selectors: sel, 976 | declarations: decls 977 | }); 978 | } 979 | 980 | /** 981 | * Parse document. 982 | */ 983 | 984 | function atdocument() { 985 | var pos = position(); 986 | var m = match(/^@([-\w]+)?document *([^{]+)/); 987 | if (!m) return; 988 | 989 | var vendor = trim(m[1]); 990 | var doc = trim(m[2]); 991 | 992 | if (!open()) return error("@document missing '{'"); 993 | 994 | var style = comments().concat(rules()); 995 | 996 | if (!close()) return error("@document missing '}'"); 997 | 998 | return pos({ 999 | type: 'document', 1000 | document: doc, 1001 | vendor: vendor, 1002 | rules: style 1003 | }); 1004 | } 1005 | 1006 | /** 1007 | * Parse import 1008 | */ 1009 | 1010 | function atimport() { 1011 | return _atrule('import'); 1012 | } 1013 | 1014 | /** 1015 | * Parse charset 1016 | */ 1017 | 1018 | function atcharset() { 1019 | return _atrule('charset'); 1020 | } 1021 | 1022 | /** 1023 | * Parse namespace 1024 | */ 1025 | 1026 | function atnamespace() { 1027 | return _atrule('namespace') 1028 | } 1029 | 1030 | /** 1031 | * Parse non-block at-rules 1032 | */ 1033 | 1034 | function _atrule(name) { 1035 | var pos = position(); 1036 | var m = match(new RegExp('^@' + name + ' *([^;\\n]+);')); 1037 | if (!m) return; 1038 | var ret = { type: name }; 1039 | ret[name] = trim(m[1]); 1040 | return pos(ret); 1041 | } 1042 | 1043 | /** 1044 | * Parse at rule. 1045 | */ 1046 | 1047 | function atrule() { 1048 | if (css[0] != '@') return; 1049 | 1050 | return atkeyframes() 1051 | || atmedia() 1052 | || atsupports() 1053 | || atimport() 1054 | || atcharset() 1055 | || atnamespace() 1056 | || atdocument() 1057 | || atpage() 1058 | || athost(); 1059 | } 1060 | 1061 | /** 1062 | * Parse rule. 1063 | */ 1064 | 1065 | function rule() { 1066 | var pos = position(); 1067 | var sel = selector(); 1068 | 1069 | if (!sel) return; 1070 | comments(); 1071 | 1072 | return pos({ 1073 | type: 'rule', 1074 | selectors: sel, 1075 | declarations: declarations() 1076 | }); 1077 | } 1078 | 1079 | return stylesheet(); 1080 | }; 1081 | 1082 | /** 1083 | * Trim `str`. 1084 | */ 1085 | 1086 | function trim(str) { 1087 | return str ? str.replace(/^\s+|\s+$/g, '') : ''; 1088 | } 1089 | 1090 | },{}],5:[function(require,module,exports){ 1091 | // shim for using process in browser 1092 | 1093 | var process = module.exports = {}; 1094 | 1095 | process.nextTick = (function () { 1096 | var canSetImmediate = typeof window !== 'undefined' 1097 | && window.setImmediate; 1098 | var canPost = typeof window !== 'undefined' 1099 | && window.postMessage && window.addEventListener 1100 | ; 1101 | 1102 | if (canSetImmediate) { 1103 | return function (f) { return window.setImmediate(f) }; 1104 | } 1105 | 1106 | if (canPost) { 1107 | var queue = []; 1108 | window.addEventListener('message', function (ev) { 1109 | var source = ev.source; 1110 | if ((source === window || source === null) && ev.data === 'process-tick') { 1111 | ev.stopPropagation(); 1112 | if (queue.length > 0) { 1113 | var fn = queue.shift(); 1114 | fn(); 1115 | } 1116 | } 1117 | }, true); 1118 | 1119 | return function nextTick(fn) { 1120 | queue.push(fn); 1121 | window.postMessage('process-tick', '*'); 1122 | }; 1123 | } 1124 | 1125 | return function nextTick(fn) { 1126 | setTimeout(fn, 0); 1127 | }; 1128 | })(); 1129 | 1130 | process.title = 'browser'; 1131 | process.browser = true; 1132 | process.env = {}; 1133 | process.argv = []; 1134 | 1135 | function noop() {} 1136 | 1137 | process.on = noop; 1138 | process.once = noop; 1139 | process.off = noop; 1140 | process.emit = noop; 1141 | 1142 | process.binding = function (name) { 1143 | throw new Error('process.binding is not supported'); 1144 | } 1145 | 1146 | // TODO(shtylman) 1147 | process.cwd = function () { return '/' }; 1148 | process.chdir = function (dir) { 1149 | throw new Error('process.chdir is not supported'); 1150 | }; 1151 | 1152 | },{}],6:[function(require,module,exports){ 1153 | (function (process){ 1154 | // vim:ts=4:sts=4:sw=4: 1155 | /*! 1156 | * 1157 | * Copyright 2009-2012 Kris Kowal under the terms of the MIT 1158 | * license found at http://github.com/kriskowal/q/raw/master/LICENSE 1159 | * 1160 | * With parts by Tyler Close 1161 | * Copyright 2007-2009 Tyler Close under the terms of the MIT X license found 1162 | * at http://www.opensource.org/licenses/mit-license.html 1163 | * Forked at ref_send.js version: 2009-05-11 1164 | * 1165 | * With parts by Mark Miller 1166 | * Copyright (C) 2011 Google Inc. 1167 | * 1168 | * Licensed under the Apache License, Version 2.0 (the "License"); 1169 | * you may not use this file except in compliance with the License. 1170 | * You may obtain a copy of the License at 1171 | * 1172 | * http://www.apache.org/licenses/LICENSE-2.0 1173 | * 1174 | * Unless required by applicable law or agreed to in writing, software 1175 | * distributed under the License is distributed on an "AS IS" BASIS, 1176 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1177 | * See the License for the specific language governing permissions and 1178 | * limitations under the License. 1179 | * 1180 | */ 1181 | 1182 | (function (definition) { 1183 | // Turn off strict mode for this function so we can assign to global.Q 1184 | /* jshint strict: false */ 1185 | 1186 | // This file will function properly as a