├── src ├── app │ ├── app.spec.coffee │ ├── app.spec.js │ ├── main.jsx │ ├── about │ │ ├── about.jsx │ │ └── _about.tpl.jsx │ ├── com │ │ ├── tabs │ │ │ ├── _tabs.tpl.jsx │ │ │ └── tabs.jsx │ │ ├── products │ │ │ ├── _products.tpl.jsx │ │ │ └── products.jsx │ │ ├── todo │ │ │ ├── _todo.tpl.jsx │ │ │ └── todo.jsx │ │ └── u.jsx │ ├── home │ │ ├── _todo.tpl.jsx │ │ ├── _products.tpl.jsx │ │ ├── home.jsx │ │ └── _home.tpl.jsx │ ├── layout │ │ ├── _layout.tpl.jsx │ │ ├── _footer.tpl.jsx │ │ ├── _header.tpl.jsx │ │ ├── _header.tpl.coffee │ │ └── layout.jsx │ ├── app.jsx │ └── index.html ├── assets │ └── sample.txt └── less │ ├── app.less │ ├── vendor.less │ └── variables.less ├── .bowerrc ├── bower.json ├── public └── products.json ├── .gitattributes ├── LICENSE ├── package.json ├── res └── template-compiler.sjs ├── .gitignore ├── README.md └── gulpfile.js /src/app/app.spec.coffee: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/app.spec.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/sample.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/main.jsx: -------------------------------------------------------------------------------- 1 | require('app'); 2 | -------------------------------------------------------------------------------- /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "vendor" 3 | } 4 | -------------------------------------------------------------------------------- /src/app/about/about.jsx: -------------------------------------------------------------------------------- 1 | exports.controller = function() { 2 | 3 | }; 4 | 5 | exports.view = function(ctrl) { 6 | return INCLUDE('about/about.tpl'); 7 | }; 8 | -------------------------------------------------------------------------------- /src/app/com/tabs/_tabs.tpl.jsx: -------------------------------------------------------------------------------- 1 |
2 | 5 |
6 | {panes} 7 |
8 |
9 | -------------------------------------------------------------------------------- /src/app/home/_todo.tpl.jsx: -------------------------------------------------------------------------------- 1 |
2 |

Mithril Todo example

3 |

Read more: Getting Started

4 |
5 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mithril-boilerplate", 3 | "version": "0.1.2", 4 | "devDependencies": { 5 | "mithril": "~0.1.13", 6 | "min-require": "~0.1.2", 7 | "bootstrap": "~3.1.1" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/app/layout/_layout.tpl.jsx: -------------------------------------------------------------------------------- 1 |
2 | {INCLUDE('layout/header.tpl')} 3 | 4 |
5 | {ctrl.com.$view()} 6 |
7 | 8 | {INCLUDE('layout/footer.tpl')} 9 |
10 | -------------------------------------------------------------------------------- /src/app/app.jsx: -------------------------------------------------------------------------------- 1 | var home = require('home/home'); 2 | var about = require('about/about'); 3 | var layout = require('layout/layout'); 4 | 5 | m.route.mode = 'hash'; 6 | m.route(document.body, '/', { 7 | '/': layout(home), 8 | '/about': layout(about) 9 | }); 10 | -------------------------------------------------------------------------------- /src/app/layout/_footer.tpl.jsx: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /src/app/home/_products.tpl.jsx: -------------------------------------------------------------------------------- 1 |
2 |

Mithril Product List example

3 |

This example is based on an article from React. 4 | Read more:  5 | Thinking in React 6 |

7 |
8 | -------------------------------------------------------------------------------- /src/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Mithril Boilerplate 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/app/layout/_header.tpl.jsx: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /public/products.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"category": "Sporting Goods", "price": "$49.99", "stocked": true, "name": "Football"}, 3 | {"category": "Sporting Goods", "price": "$9.99", "stocked": true, "name": "Baseball"}, 4 | {"category": "Sporting Goods", "price": "$29.99", "stocked": false, "name": "Basketball"}, 5 | {"category": "Electronics", "price": "$99.99", "stocked": true, "name": "iPod Touch"}, 6 | {"category": "Electronics", "price": "$399.99", "stocked": false, "name": "iPhone 5"}, 7 | {"category": "Electronics", "price": "$199.99", "stocked": true, "name": "Nexus 7"} 8 | ] 9 | -------------------------------------------------------------------------------- /src/app/com/products/_products.tpl.jsx: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |

5 | 6 | Only show products in stock 7 |

8 |
9 | 10 | 11 | 12 | 13 | 14 | {rows} 15 | 16 |
NamePrice
17 |
18 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /src/app/com/todo/_todo.tpl.jsx: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 5 |

6 | 14 |
15 | -------------------------------------------------------------------------------- /src/app/home/home.jsx: -------------------------------------------------------------------------------- 1 | var products = require('com/products/products'); 2 | var tabs = require('com/tabs/tabs'); 3 | var todo = require('com/todo/todo'); 4 | var u = require('com/u'); 5 | 6 | exports.controller = function() { 7 | this.tabs = u.init(tabs({ 8 | label: 'Todo', 9 | module: todo 10 | }, { 11 | label: 'Product List', 12 | module: products 13 | })); 14 | }; 15 | 16 | exports.view = function(ctrl) { 17 | 18 | function description() { 19 | var index = ctrl.tabs.index(); 20 | return index === 0? INCLUDE('home/todo.tpl') : INCLUDE('home/products.tpl'); 21 | } 22 | 23 | return INCLUDE('home/home.tpl'); 24 | }; 25 | -------------------------------------------------------------------------------- /src/app/layout/_header.tpl.coffee: -------------------------------------------------------------------------------- 1 | m 'header.navbar' [ 2 | m '.container' [ 3 | m '.navbar-header' [ 4 | m '.navbar-brand' {href:'/'} 'Mithril Boilerplate' 5 | ], 6 | m 'nav.nav.navbar-nav' [ 7 | m 'li' {class:ctrl.tabActive('/')} [ 8 | m 'a' {href='/', config:m.route}], 9 | m 'li' {class:ctrl.tabActive('/about')} [ 10 | m 'a' {href='/about', config:m.route}] 11 | m 'li' [ 12 | m 'a' {href:'https://github.com/ng-vu/mithril-boilerplate'} 'GitHub'] 13 | ] 14 | m 'nav.nav.navbar-nav.navbar-right' [ 15 | m 'li' [ 16 | m 'a' {href='http://lhorie.github.io/mithril'} 'Mithril'] 17 | ] 18 | ] 19 | ] 20 | -------------------------------------------------------------------------------- /src/app/com/u.jsx: -------------------------------------------------------------------------------- 1 | var shift = Array.prototype.shift; 2 | var unshift = Array.prototype.unshift; 3 | var slice = Array.prototype.slice; 4 | 5 | exports.eachFunc = function() { 6 | var funcs = arguments; 7 | return function() { 8 | for (var i=0; i < funcs.length; i++) { 9 | funcs[i].apply(this, arguments); 10 | } 11 | }; 12 | }; 13 | 14 | exports.init = function($module) { 15 | var ctrl = {}; 16 | var obj = Object.create(ctrl); 17 | $module.controller.apply(ctrl, slice.call(arguments, 1)); 18 | obj.$module = $module; 19 | obj.$view = $module.view.bind({}, ctrl); 20 | return obj; 21 | }; 22 | 23 | exports.silence = function(cb) { 24 | return function(e) { 25 | e.preventDefault(); 26 | if (cb) return cb(); 27 | }; 28 | }; 29 | -------------------------------------------------------------------------------- /src/app/layout/layout.jsx: -------------------------------------------------------------------------------- 1 | var u = require('com/u'); 2 | 3 | function layout($module) { 4 | 5 | function controller() { 6 | this.com = u.init($module); 7 | this.tabs = [{href:'/',label:'Home'},{href:'/about',label:'About'}]; 8 | } 9 | 10 | function view(ctrl) { 11 | var tabs = []; 12 | for (var i=0; i < ctrl.tabs.length; i++) { 13 | var tab = ctrl.tabs[i]; 14 | tabs.push( 15 |
  • 16 | {tab.label} 17 |
  • 18 | ); 19 | } 20 | 21 | function isActive(r) { 22 | return m.route() === r? 'active': ''; 23 | } 24 | 25 | return INCLUDE('layout/layout.tpl'); 26 | } 27 | 28 | return { 29 | controller: controller, 30 | view: view 31 | }; 32 | } 33 | 34 | module.exports = layout; 35 | -------------------------------------------------------------------------------- /src/app/com/todo/todo.jsx: -------------------------------------------------------------------------------- 1 | var u = require('com/u'); 2 | var todo = exports; 3 | 4 | todo.Todo = function(data) { 5 | this.description = m.prop(data.description); 6 | this.done = m.prop(false); 7 | }; 8 | 9 | todo.TodoList = Array; 10 | 11 | todo.controller = function() { 12 | this.list = new todo.TodoList(); 13 | this.description = m.prop(""); 14 | 15 | this.addTodo = function(description) { 16 | this.list.push(new todo.Todo({ 17 | description: description 18 | })); 19 | }.bind(this); 20 | 21 | this.add = function() { 22 | if (this.description()) { 23 | this.addTodo(this.description()); 24 | this.description(""); 25 | } 26 | }.bind(this); 27 | 28 | this.addTodo('try next example'); 29 | this.addTodo('learn Mithril'); 30 | this.addTodo('clear this list'); 31 | }; 32 | 33 | todo.view = function(ctrl) { 34 | return INCLUDE('com/todo/todo.tpl'); 35 | }; 36 | -------------------------------------------------------------------------------- /src/less/app.less: -------------------------------------------------------------------------------- 1 | .red { 2 | color: red; 3 | } 4 | 5 | .navbar { 6 | background: #EEE; 7 | } 8 | 9 | .navbar .active a, .navbar .active a:hover { 10 | background: #DDD !important; 11 | } 12 | 13 | .page footer { 14 | color: white; 15 | background: #333; 16 | padding: 20px 0 10px 0; 17 | margin-top: 50px; 18 | 19 | a { 20 | color: white; 21 | text-decoration: underline; 22 | } 23 | } 24 | 25 | .main-page { 26 | 27 | } 28 | 29 | .about { 30 | max-width: 800px; 31 | } 32 | 33 | .tab-pane { 34 | padding-top: 20px; 35 | } 36 | 37 | .description { 38 | padding-top: 70px; 39 | } 40 | 41 | .todo { 42 | ul { 43 | padding: 0; 44 | } 45 | 46 | li { 47 | list-style: none; 48 | } 49 | 50 | label { 51 | font-weight: normal; 52 | cursor: pointer; 53 | } 54 | 55 | .done { 56 | text-decoration: line-through; 57 | color: #999; 58 | } 59 | } 60 | 61 | .products { 62 | th { 63 | padding-top: 10px; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/app/com/products/products.jsx: -------------------------------------------------------------------------------- 1 | var u = require('com/u'); 2 | 3 | function ProductList() { 4 | return m.request({method:'GET', url:'products.json'}); 5 | } 6 | 7 | function controller() { 8 | this.products = ProductList(); 9 | this.filterText = m.prop(""); 10 | this.inStockOnly = m.prop(false); 11 | } 12 | 13 | function view(ctrl) { 14 | var rows = []; 15 | var lastCategory = null; 16 | 17 | ctrl.products().forEach(function(p) { 18 | if (p.name.indexOf(ctrl.filterText()) === -1 || 19 | (!p.stocked && ctrl.inStockOnly())) { 20 | return; 21 | } 22 | 23 | if (p.category !== lastCategory) { 24 | rows.push(m('tr', [ 25 | m('th', {colspan: 2}, p.category) 26 | ])); 27 | lastCategory = p.category; 28 | } 29 | 30 | rows.push( 31 | m('tr', [ 32 | m('td', {style: p.stocked ? {} : {color: 'red'}}, p.name), 33 | m('td', {}, p.price) 34 | ]) 35 | ); 36 | }); 37 | 38 | return INCLUDE('com/products/products.tpl'); 39 | } 40 | 41 | exports.label = 'Products'; 42 | exports.controller = controller; 43 | exports.view = view; 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Vu Nguyen 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /src/app/com/tabs/tabs.jsx: -------------------------------------------------------------------------------- 1 | var u = require('com/u'); 2 | 3 | function tabs() { 4 | var configs = arguments; 5 | 6 | function controller() { 7 | this.index = m.prop(0); 8 | 9 | this.coms = []; 10 | for (var i=0; i < configs.length; i++) { 11 | this.coms.push(u.init(configs[i].module)); 12 | } 13 | 14 | this.current = function() { 15 | return this.coms[this.index()]; 16 | }; 17 | } 18 | 19 | function view(ctrl) { 20 | var coms = ctrl.coms, tabs = [], panes = [], i; 21 | for (i=0; i < coms.length; i++) { 22 | tabs.push( 23 |
  • 24 | {configs[i].label} 25 |
  • 26 | ); 27 | } 28 | for (i=0; i < coms.length; i++) { 29 | panes.push( 30 |
    31 | {coms[i].$view()} 32 |
    33 | ); 34 | } 35 | 36 | function isActive(i) { 37 | return ctrl.index() === i? 'active' : ''; 38 | } 39 | return INCLUDE('com/tabs/tabs.tpl'); 40 | } 41 | 42 | return { 43 | controller: controller, 44 | view: view 45 | }; 46 | } 47 | 48 | module.exports = tabs; 49 | -------------------------------------------------------------------------------- /src/app/home/_home.tpl.jsx: -------------------------------------------------------------------------------- 1 | [ 2 |
    3 |
    4 |

    What is Mithril?

    5 |

    6 | Mithril is a client-side MVC framework - a tool to organize code in a way that is easy to think about and to maintain.
    7 | The framework is created by Leo Horie. For more information, go to official website or read Getting Started. 8 |

    9 |
    10 |
    , 11 |
    , 12 |
    13 |
    14 |

    Light-weight

    15 |

    16 | Only 3kb gzipped, no dependencies
    17 | Small API, small learning curve 18 |

    19 |
    20 |
    21 |

    Robust

    22 |

    23 | Safe-by-default templates
    24 | Hierarchical MVC via components 25 |

    26 |
    27 |
    28 |

    Fast

    29 |

    30 | Virtual DOM diffing and compilable templates
    31 | Intelligent auto-redrawing system 32 |

    33 |
    34 |
    , 35 |
    , 36 |
    37 |
    38 |

    Examples

    39 |
    40 |
    , 41 |
    42 |
    43 | {description()} 44 |
    45 |
    46 | {new ctrl.tabs.$view(ctrl.tabsCtrl)} 47 |
    48 |
    49 | ] 50 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mithril-boilerplate", 3 | "version": "0.1.2", 4 | "author": "Vu Nguyen ", 5 | "description": "Well structured boilerplate code for quickly starting new Mithril.js projects", 6 | "homepage": "http://github.com/ng-vu/mithril-boilerplate", 7 | "license": [ 8 | { 9 | "type": "MIT", 10 | "url": "http://github.com/ng-vu/mithril-boilerplate/blob/master/LICENSE" 11 | } 12 | ], 13 | "repository": { 14 | "type": "git", 15 | "url": "git://github.com/ng-vu/mithril-boilerplate.git" 16 | }, 17 | "dependencies": {}, 18 | "devDependencies": { 19 | "chai": "^1.9.1", 20 | "connect-livereload": "^0.4.0", 21 | "event-stream": "^3.1.5", 22 | "gulp": "^3.6.2", 23 | "gulp-changed": "^0.3.0", 24 | "gulp-clean": "^0.2.4", 25 | "gulp-concat": "^2.2.0", 26 | "gulp-filter": "^0.4.1", 27 | "gulp-include-js": "git://github.com/ng-vu/gulp-include-js.git", 28 | "gulp-inject": "^0.4.1", 29 | "gulp-insert": "^0.3.0", 30 | "gulp-less": "^1.2.3", 31 | "gulp-livereload": "^1.5.0", 32 | "gulp-load-plugins": "^0.5.0", 33 | "gulp-minify-css": "^0.3.4", 34 | "gulp-minify-html": "^0.1.3", 35 | "gulp-msx": "git://github.com/ng-vu/gulp-msx.git", 36 | "gulp-newer": "^0.3.0", 37 | "gulp-plumber": "^0.6.1", 38 | "gulp-rev": "^0.3.2", 39 | "gulp-size": "^0.3.1", 40 | "gulp-streamify": "0.0.5", 41 | "gulp-sweetjs": "^0.4.0", 42 | "gulp-uglify": "^0.3.0", 43 | "gulp-util": "^2.2.14", 44 | "gulp-watch": "^0.6.4", 45 | "gulp-wrap-require": "git://github.com/ng-vu/gulp-wrap-require.git", 46 | "run-sequence": "^0.3.6" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/app/about/_about.tpl.jsx: -------------------------------------------------------------------------------- 1 |
    2 |

    About Mithril-Boilerplate

    3 |

    4 | The project is a well structured boilerplate code for quickly starting new Mithril.js projects.
    5 | For more information, browse project page on GitHub. 6 |

    7 |

    Features

    8 |

    9 |

      10 |
    • Gulpfile
    • 11 |
    • Bower
    • 12 |
    • LESS & Bootstrap (easy to swap with your favourite tools)
    • 13 |
    • JSX (write HTML tags inside .jsx file)
    • 14 |
    • INCLUDE() JavaScript files
    • 15 |
    • Client side modules wrapped in CommonJs
    • 16 |
    • Watch with cache (only rebuild changed files)
    • 17 |
    • LiveReload
    • 18 |
    • Concat and minify stylesheets and scripts for production
    • 19 |
    • Unit testing will be supported soon
    • 20 |
    21 |

    22 |

    Quick start

    23 |

    24 | Make sure you have node and npm installed. Then 25 |

    
    26 |     npm install -g bower gulp http-server

    27 | 28 | git clone https://github.com/ng-vu/mithril-boilerplate.git
    29 | cd mithril-boilerplate

    30 | 31 | npm install
    32 | bower install
    33 | gulp compile
    34 | 35 | http-server build/public 36 |
    37 |

    38 |

    39 | Running above commands compile source and put final code in these directories: 40 |

      41 |
    • build for development
    • 42 |
    • bin for production
    • 43 |
    44 |

    45 |

    46 | You may run the application by either of these commands: 47 |

    
    48 |     http-server build/public
    49 | http-server bin/public 50 |
    51 |

    52 |

    53 | To automatically build project whenever a source file changes: 54 |

    
    55 |     gulp build watch
    56 |     
    57 |

    58 |
    59 | -------------------------------------------------------------------------------- /res/template-compiler.sjs: -------------------------------------------------------------------------------- 1 | /* 2 | Compiles Mithril templates 3 | 4 | Requires sweet.js (https://github.com/mozilla/sweet.js) 5 | Installation: npm install -g sweet.js 6 | Usage: sjs --module /mithril.compile.sjs --output .js .js 7 | */ 8 | 9 | macro m { 10 | case { _ ($selector) } => { 11 | return #{m($selector, {}, [])}; 12 | } 13 | case { _ ($selector, $partial) } => { 14 | var partialSyntax = #{$partial}; 15 | var partial = unwrapSyntax(partialSyntax); 16 | return partial.value == "{}" ? #{m($selector, $partial, [])} : #{m($selector, {}, partial)}; 17 | } 18 | case { _ ($selector, $dynAttrs, $children) } => { 19 | var selectorSyntax = #{$selector}; 20 | var selector = unwrapSyntax(selectorSyntax); 21 | 22 | var dynAttrsSyntax = #{$dynAttrs}; 23 | var dynAttrs = unwrapSyntax(dynAttrsSyntax); 24 | 25 | var parser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[.+?\])/g; 26 | var attrParser = /\[(.+?)=("|'|)(.+?)\2\]/; 27 | var _match = null; 28 | var classes = []; 29 | var cell = {tag: "div", attrs: {}, children: []}; 30 | 31 | while (_match = parser.exec(selector)) { 32 | if (_match[1] == "") cell.tag = _match[2]; 33 | else if (_match[1] == "#") cell.attrs.id = _match[2]; 34 | else if (_match[1] == ".") classes.push(_match[2]); 35 | else if (_match[3][0] == "[") { 36 | var pair = attrParser.exec(_match[3]); 37 | cell.attrs[pair[1]] = pair[3]; 38 | } 39 | } 40 | if (classes.length > 0) cell.attrs["class"] = classes.join(" "); 41 | 42 | var tag = makeValue(cell.tag, #{here}); 43 | var attrsBody = Object.keys(cell.attrs).reduce(function(memo, attrName) { 44 | return memo.concat([ 45 | makeValue(attrName, #{here}), 46 | makePunc(":", #{here}), 47 | makeValue(cell.attrs[attrName], #{here}), 48 | makePunc(",", #{here}) 49 | ]); 50 | }, []).concat(dynAttrs.inner); 51 | var attrs = [makeDelim("{}", attrsBody, #{here})]; 52 | var children = cell.children.map(function(child) { 53 | return makeValue(child, #{here}); 54 | }) 55 | letstx $tag = [tag], $attrs = attrs; 56 | 57 | return #{ ({tag: $tag, attrs: $attrs , children: $children}) }; 58 | } 59 | case { _ } => { 60 | return #{Mithril}; 61 | } 62 | } 63 | 64 | export m; -------------------------------------------------------------------------------- /src/less/vendor.less: -------------------------------------------------------------------------------- 1 | // Core variables and mixins 2 | @import "variables.less"; 3 | 4 | @import "../../vendor/bootstrap/less/mixins.less"; 5 | 6 | // Reset 7 | @import "../../vendor/bootstrap/less/normalize.less"; 8 | @import "../../vendor/bootstrap/less/print.less"; 9 | 10 | // Core CSS 11 | @import "../../vendor/bootstrap/less/scaffolding.less"; 12 | @import "../../vendor/bootstrap/less/type.less"; 13 | @import "../../vendor/bootstrap/less/code.less"; 14 | @import "../../vendor/bootstrap/less/grid.less"; 15 | @import "../../vendor/bootstrap/less/tables.less"; 16 | @import "../../vendor/bootstrap/less/forms.less"; 17 | @import "../../vendor/bootstrap/less/buttons.less"; 18 | 19 | // Components 20 | @import "../../vendor/bootstrap/less/component-animations.less"; 21 | @import "../../vendor/bootstrap/less/glyphicons.less"; 22 | @import "../../vendor/bootstrap/less/dropdowns.less"; 23 | @import "../../vendor/bootstrap/less/button-groups.less"; 24 | @import "../../vendor/bootstrap/less/input-groups.less"; 25 | @import "../../vendor/bootstrap/less/navs.less"; 26 | @import "../../vendor/bootstrap/less/navbar.less"; 27 | @import "../../vendor/bootstrap/less/breadcrumbs.less"; 28 | @import "../../vendor/bootstrap/less/pagination.less"; 29 | @import "../../vendor/bootstrap/less/pager.less"; 30 | @import "../../vendor/bootstrap/less/labels.less"; 31 | @import "../../vendor/bootstrap/less/badges.less"; 32 | @import "../../vendor/bootstrap/less/jumbotron.less"; 33 | @import "../../vendor/bootstrap/less/thumbnails.less"; 34 | @import "../../vendor/bootstrap/less/alerts.less"; 35 | @import "../../vendor/bootstrap/less/progress-bars.less"; 36 | @import "../../vendor/bootstrap/less/media.less"; 37 | @import "../../vendor/bootstrap/less/list-group.less"; 38 | @import "../../vendor/bootstrap/less/panels.less"; 39 | @import "../../vendor/bootstrap/less/wells.less"; 40 | @import "../../vendor/bootstrap/less/close.less"; 41 | 42 | // Components w/ JavaScript 43 | @import "../../vendor/bootstrap/less/modals.less"; 44 | @import "../../vendor/bootstrap/less/tooltip.less"; 45 | @import "../../vendor/bootstrap/less/popovers.less"; 46 | @import "../../vendor/bootstrap/less/carousel.less"; 47 | 48 | // Utility classes 49 | @import "../../vendor/bootstrap/less/utilities.less"; 50 | @import "../../vendor/bootstrap/less/responsive-utilities.less"; 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | /vendor 217 | /node_modules 218 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mithril-boilerplate 2 | 3 | > Well structured boilerplate code for quickly starting new [Mithril.js](http://lhorie.github.io/mithril) projects 4 | 5 | ## Quick start 6 | 7 | Make sure you have `node` and `npm` installed. Then 8 | 9 | ``` 10 | npm install -g bower gulp http-server 11 | 12 | git clone https://github.com/ng-vu/mithril-boilerplate.git 13 | cd mithril-boilerplate 14 | 15 | npm install 16 | bower install 17 | gulp compile 18 | 19 | http-server build/public 20 | ``` 21 | 22 | Running above commands compile source and put final code in these directories: 23 | 24 | * `build` for development 25 | * `bin` for production 26 | 27 | You may run the application by either of these commands: 28 | 29 | * `http-server build/public` 30 | * `http-server bin/public` 31 | 32 | To automatically build project whenever a source file changes: 33 | 34 | ``` 35 | gulp build watch 36 | ``` 37 | 38 | ## Features 39 | 40 | * Gulpfile 41 | * Bower 42 | * LESS & Bootstrap (easy to swap with your favourite tools) 43 | * [JSX](http://lhorie.github.io/mithril/tools.html) (write HTML tags inside .jsx file) 44 | * [INCLUDE()](https://github.com/ng-vu/gulp-include-js) JavaScript files 45 | * Client side modules wrapped in CommonJs 46 | * Watch with cache (only rebuild changed files) 47 | * LiveReload 48 | * Concat and minify stylesheets and scripts for production 49 | * Unit testing will be supported soon 50 | 51 | ## Commands 52 | 53 | ### `gulp clean` 54 | 55 | Clean all files in `build` and `bin` directory. 56 | 57 | ### `gulp build` 58 | 59 | Build the project and put files in `build`. 60 | You may run the application by: 61 | 62 | ``` 63 | gulp build 64 | http-server build/public 65 | ``` 66 | 67 | ### `gulp compile` 68 | 69 | Build the project and put files in `bin`. 70 | All stylesheets are concatenated to `main-***.css` and 71 | all scripts are combined to `main-***.css` with `***` is content hash. 72 | You may run the application by: 73 | ``` 74 | gulp compile 75 | http-server bin/public 76 | ``` 77 | 78 | ### `gulp watch` 79 | 80 | Automatically build the project whenever a source file changes. 81 | It caches source files and only runs tasks on changed files. 82 | You should use `watch` together with `build`: 83 | ``` 84 | gulp build watch 85 | ``` 86 | 87 | ### Running a specific task 88 | 89 | These tasks describe specific steps in building process: 90 | 91 | * `gulp buildAppStyles` 92 | * `gulp buildVendorStyles` 93 | * `gulp buildAppScriptsInject` 94 | * `gulp buildAppScriptsMsx` 95 | * `gulp buildAppScripts` 96 | * `gulp buildVendorScripts` 97 | * `gulp buildAppAssets` 98 | * `gulp buildVendorAssets` 99 | * `gulp buildIndexHtml` 100 | * `gulp buildRootFiles` 101 | * `gulp compileStyles` 102 | * `gulp compileScripts` 103 | * `gulp compileAssets` 104 | * `gulp compileRootFiles` 105 | * `gulp compileIndexHtml` 106 | 107 | ## // TODO 108 | 109 | * Unit testing 110 | * Sample project 111 | * Coffee script 112 | 113 | ## Note 114 | 115 | * Source files must be `.jsx`, not `.js`. 116 | 117 | You should always write source in `.jsx` files. All `.js` files will be ignored by default. 118 | 119 | JSX is basically JavaScript enhanced with HTML tags. Mithril JSX compiler is based on React JSX. Read more: [Mithril Tools](http://lhorie.github.io/mithril/tools.html), [React JSX](http://facebook.github.io/react/docs/jsx-in-depth.html) 120 | 121 | * Each `.jsx` file inside `src/app` without `_` prefix will become a module. 122 | 123 | For example, `src/app/app.jsx` is compiled to module `app` and `src/app/home/home.jsx` to `home/home`. 124 | 125 | Files with `_` prefix are used to be included into other files and will not become a module. 126 | 127 | * A module can be required by `require()`. 128 | 129 | For example, `require('app')` or `require('home/home')`. 130 | 131 | * Main module is `main` (`src/app/main.jsx`). 132 | 133 | Note that if a module is not required (directly or indirectly) by `main`, its code will not run. 134 | 135 | * Include file by `INCLUDE('')`. 136 | 137 | For example `INCLUDE('home/view')` will replace the INCLUDE call with whole content of `src/app/home/_home.view.jsx`. Note that `home/_home.view.jsx` will be translated to `home/home.view`. 138 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | // User configs 2 | 3 | var configs = { 4 | buildAppCss: 'build/public/src/app.css', 5 | buildVendorCss: 'build/public/src/vendor.css', 6 | 7 | buildAssets: 'build/public/assets/', 8 | buildAssetsVendor: 'build/public/assets/vendor/', 9 | buildHtml: 'build/public/', 10 | buildPublic: 'build/public/', 11 | buildSrc: 'build/public/src/', 12 | buildTmpSrc: 'build/tmp/src/', 13 | buildVendor: 'build/public/vendor/', 14 | 15 | compileMainCss: 'main.css', 16 | compileMainJs: 'main.js', 17 | 18 | compileAssets: 'bin/public/assets/', 19 | compileAssetsVendor: 'bin/public/assets/vendor/', 20 | compileHtml: 'bin/public/', 21 | compilePublic: 'bin/public/', 22 | compileSrc: 'bin/public/src/', 23 | 24 | appLess: 'src/less/app.less', 25 | vendorLess: 'src/less/vendor.less', 26 | }; 27 | 28 | var appFiles = { 29 | assets: ['src/assets/**/*.*'], 30 | coffee: ['src/app/**/*.coffee', '!src/app/**/*.spec.coffee'], 31 | coffeeunit: ['src/app/**/*.spec.coffee'], 32 | html: ['src/app/index.html'], 33 | js: ['src/app/**/*.js', '!src/app/**/*.spec.js'], 34 | jsunit: ['src/app/**/*.spec.js'], 35 | jsx: ['src/app/**/*.jsx'], 36 | less: ['src/less/**/*.less', '!' + configs.vendorLess], 37 | tpl: ['src/app/**/*.tpl.html'], 38 | root: ['LICENSE', 'README.md', 'public/**/*.*'] 39 | }; 40 | 41 | var vendorFiles = { 42 | assets: [ 43 | 'vendor/bootstrap/fonts/*.*' 44 | ], 45 | js: [ 46 | 'vendor/mithril/mithril.js', 47 | 'vendor/min-require/min-require.js', 48 | ], 49 | }; 50 | 51 | var consts = { 52 | livereloadPort: 35729, 53 | }; 54 | 55 | /* -------------------------------------------------------------------------- */ 56 | // Implement tasks 57 | 58 | var fs = require('fs'); 59 | var gulp = require('gulp'); 60 | var path = require('path'); 61 | var plugins = require('gulp-load-plugins')(); 62 | var runSequence = require('run-sequence'); 63 | 64 | var colors = plugins.util.colors; 65 | var log = plugins.util.log; 66 | 67 | function clean(filepath, cb) { 68 | log('Cleaning', colors.magenta(filepath)); 69 | gulp.src(filepath, {read: false}) 70 | .pipe(plugins.clean({force: false})) 71 | .on('end', cb || function() {}) 72 | .on('error', log); 73 | } 74 | 75 | function revName(filename) { 76 | var index = filename.search(/\.[^.]*$/); 77 | return filename.substr(0, index) + '-*' + filename.substr(index); 78 | } 79 | 80 | function mainScripts(basepath) { 81 | return configs.mainScripts.map(function(s) { 82 | return path.join(basepath, s); 83 | }); 84 | } 85 | 86 | function buildStyles(src, destFile, options, cb) { 87 | gulp.src(src) 88 | .pipe(plugins.plumber()) 89 | .pipe(plugins.less(options)) 90 | // .pipe(plugins.size({showFiles: true})) 91 | .pipe(gulp.dest(path.dirname(destFile))) 92 | .on('end', cb || function(){}) 93 | .on('error', log); 94 | } 95 | 96 | // Generate build/public/assets/app-***.css 97 | gulp.task('buildAppStyles',function(cb) { 98 | buildStyles(configs.appLess, configs.buildAppCss, {sourceMap:true}, cb); 99 | }); 100 | 101 | // Generate build/public/assets/vendor-***.css 102 | gulp.task('buildVendorStyles', function(cb) { 103 | buildStyles(configs.vendorLess, configs.buildVendorCss, {sourceMap:false}, cb); 104 | }); 105 | 106 | // Generate bin/public/assets/main-***.css 107 | gulp.task('compileStyles', function(cb) { 108 | clean(path.join(configs.compileAssets, revName(configs.compileMainCss)), _compileStyles); 109 | 110 | function _compileStyles() { 111 | gulp.src([ 112 | configs.buildVendorCss, 113 | configs.buildAppCss, 114 | ]) 115 | .pipe(plugins.plumber()) 116 | .pipe(plugins.concat(configs.compileMainCss)) 117 | .pipe(plugins.minifyCss()) 118 | .pipe(plugins.streamify(plugins.rev())) 119 | .pipe(plugins.size({showFiles: true})) 120 | .pipe(gulp.dest(configs.compileAssets)) 121 | .on('end', cb || function(){}) 122 | .on('error', log); 123 | } 124 | }); 125 | 126 | // Combine *.jsx, wrap them in CommonJs style and store in build/src/app 127 | gulp.task('buildAppScriptsInject', function(cb) { 128 | var tmpSrcApp = path.join(configs.buildTmpSrc, 'app'); 129 | gulp.src(path.join(tmpSrcApp, '**/*.js'), {base: tmpSrcApp}) 130 | .pipe(plugins.plumber()) 131 | .pipe(plugins.wrapRequire()) 132 | .pipe(plugins.includeJs({ext:'js', cache:true, showFiles:'Building'})) 133 | // .pipe(plugins.size({showFiles: true})) 134 | .pipe(gulp.dest(path.join(configs.buildSrc, 'app'))) 135 | .on('end', cb || function(){}) 136 | .on('error', log); 137 | }); 138 | 139 | // Convert app scripts from .jsx to .js 140 | gulp.task('buildAppScriptsMsx', function(cb) { 141 | var tmpSrcApp = path.join(configs.buildTmpSrc, 'app'); 142 | gulp.src(appFiles.jsx, {base: 'src/app'}) 143 | .pipe(plugins.plumber()) 144 | .pipe(plugins.changed(tmpSrcApp, {extension: '.js'})) 145 | .pipe(plugins.msx()) 146 | // .pipe(plugins.sweetjs({modules: ['./res/template-compiler.sjs']})) 147 | // .pipe(plugins.size({showFiles: true})) 148 | .pipe(gulp.dest(tmpSrcApp)) 149 | .on('end', cb || function(){}) 150 | .on('error', log); 151 | }); 152 | 153 | // Note: We only support *.jsx files and ignore all *.js files. 154 | // 155 | // gulp.task('buildAppScriptPlain', function(cb) { 156 | // gulp.src(appFiles.js, {base: 'src'}) 157 | // .pipe(plugins.size({showFiles: true})) 158 | // .pipe(gulp.dest(configs.buildSrc)) 159 | // .on('end', cb || function(){}) 160 | // .on('error', log); 161 | // }); 162 | 163 | // Combine and convert *.jsx 164 | gulp.task('buildAppScripts', function(cb) { 165 | runSequence('buildAppScriptsMsx', 'buildAppScriptsInject', cb); 166 | }); 167 | 168 | // Copy vendor scripts to build/public/vendor 169 | gulp.task('buildVendorScripts', function(cb) { 170 | gulp.src(vendorFiles.js, {base: 'vendor'}) 171 | .pipe(gulp.dest('build/public/vendor')) 172 | .on('end', cb || function(){}) 173 | .on('error', log); 174 | }); 175 | 176 | // Concat all scripts to bin/public/assets/main-***.js 177 | gulp.task('compileScripts', function(cb) { 178 | clean(path.join(configs.compileAssets, revName(configs.compileMainJs)), _compileScripts); 179 | 180 | function _compileScripts() { 181 | var glob = [].concat( 182 | vendorFiles.js || [], 183 | [ path.join(configs.buildSrc, 'app/**/*.js'), 184 | path.join('!' + configs.buildSrc, 'app/**/_*.js') ] 185 | ); 186 | gulp.src(glob) 187 | .pipe(plugins.plumber()) 188 | .pipe(plugins.concat(configs.compileMainJs)) 189 | .pipe(plugins.insert.append('\n\nrequire(\'main\');\n')) 190 | .pipe(plugins.streamify(plugins.uglify({mangle: true}))) 191 | .pipe(plugins.streamify(plugins.rev())) 192 | .pipe(plugins.size({showFiles: true})) 193 | .pipe(gulp.dest(configs.compileAssets)) 194 | .on('end', cb || function() {}) 195 | .on('error', log); 196 | } 197 | }); 198 | 199 | // Copy vendor and app assets to build/public/assets 200 | gulp.task('buildAppAssets', function(cb) { 201 | gulp.src(appFiles.assets, {base: 'src/assets'}) 202 | .pipe(plugins.changed(configs.buildAssets)) 203 | .pipe(gulp.dest(configs.buildAssets)) 204 | .on('end', cb || function(){}) 205 | .on('error', log); 206 | }); 207 | 208 | gulp.task('buildVendorAssets', function(cb) { 209 | gulp.src(vendorFiles.assets) 210 | .pipe(gulp.dest(configs.buildAssetsVendor)) 211 | .on('end', cb || function(){}) 212 | .on('error', log); 213 | }); 214 | 215 | // Copy assets from build/public/assets to bin/public/assets 216 | gulp.task('compileAssets', function(cb) { 217 | gulp.src(path.join(configs.buildAssets, '**/*.*'), {base: configs.buildAssets}) 218 | .pipe(gulp.dest(configs.compileAssets)) 219 | .on('end', cb || function(){}) 220 | .on('error', log); 221 | }); 222 | 223 | function injectHtml(tag, path, glob) { 224 | return plugins.inject( 225 | gulp.src(glob, {read:false}), { 226 | starttag: '', 227 | endtag: '', 228 | ignorePath: path, 229 | sort: function(a,b) {return a < b? -1 : a > b? 1 : 0;} 230 | } 231 | ); 232 | } 233 | 234 | gulp.task('buildIndexHtml', function(cb) { 235 | gulp.src(appFiles.html) 236 | .pipe(plugins.plumber()) 237 | .pipe(injectHtml('vendor', configs.buildPublic, 238 | [ 239 | configs.buildVendorCss, 240 | path.join(configs.buildVendor, '**/*.js') 241 | ] 242 | )) 243 | .pipe(injectHtml('app', configs.buildPublic, 244 | [ 245 | configs.buildAppCss, 246 | path.join(configs.buildSrc, 'app/**/*.js'), 247 | path.join('!' + configs.buildSrc, 'app/**/_*.js') 248 | ] 249 | )) 250 | .pipe(plugins.insert.append('')) 251 | .pipe(plugins.insert.append('')) 252 | // .pipe(plugins.size({showFiles:true})) 253 | .pipe(gulp.dest(configs.buildHtml)) 254 | .on('end', cb || function(){}) 255 | .on('error', log); 256 | }); 257 | 258 | gulp.task('compileIndexHtml', function(cb) { 259 | gulp.src(appFiles.html) 260 | .pipe(plugins.plumber()) 261 | .pipe(injectHtml('app', configs.compilePublic, 262 | [ 263 | path.join(configs.compileAssets, revName(configs.compileMainCss)), 264 | path.join(configs.compileAssets, revName(configs.compileMainJs)) 265 | ])) 266 | .pipe(plugins.minifyHtml()) 267 | .pipe(plugins.size({showFiles:true})) 268 | .pipe(gulp.dest(configs.compileHtml)) 269 | .on('end', cb || function(){}) 270 | .on('error', log); 271 | }); 272 | 273 | gulp.task('buildRootFiles', function(cb) { 274 | gulp.src(appFiles.root, {base:'.'}) 275 | .pipe(plugins.changed('build')) 276 | .pipe(gulp.dest('build')) 277 | .on('end', cb || function(){}) 278 | .on('error', log); 279 | }); 280 | 281 | gulp.task('compileRootFiles', function(cb) { 282 | gulp.src(appFiles.root, {base:'.'}) 283 | .pipe(gulp.dest('bin')) 284 | .on('end', cb || function(){}) 285 | .on('error', log); 286 | }); 287 | 288 | gulp.task('testAppScripts', function(cb) { 289 | // TODO 290 | }); 291 | 292 | /* -------------------------------------------------------------------------- */ 293 | // Major tasks 294 | 295 | gulp.task('clean', function(cb) { 296 | clean(['build', 'bin'], cb); 297 | }); 298 | 299 | gulp.task('build', function(cb) { 300 | runSequence('clean',[ 301 | 'buildAppStyles', 'buildVendorStyles', 302 | 'buildAppScripts', 'buildVendorScripts', 303 | 'buildAppAssets', 'buildVendorAssets', 304 | 'buildRootFiles' 305 | ], 306 | 'buildIndexHtml', 307 | cb); 308 | }); 309 | 310 | gulp.task('compile', function(cb) { 311 | runSequence('build', 312 | ['compileStyles', 'compileScripts', 'compileAssets', 'compileRootFiles'], 313 | 'compileIndexHtml', 314 | cb); 315 | }); 316 | 317 | gulp.task('default', ['compile']); 318 | 319 | // Tasks to run whenever a source file changes 320 | gulp.task('watch', function(cb) { 321 | 322 | var eventColors = { 323 | added: colors.green, 324 | changed: colors.magenta, 325 | deleted: colors.red, 326 | renamed: colors.green 327 | }; 328 | function logChanged(e) { 329 | var c = eventColors[e.type] || colors.white; 330 | log('[' + c(e.type) + ']', colors.magenta(path.relative(process.cwd(), e.path))); 331 | } 332 | 333 | var lr = plugins.livereload(consts.livereloadPort); 334 | function runTasks() { 335 | var args = arguments; 336 | return function(e){ runSequence.apply(this, args); }; 337 | } 338 | function reload(filepath) { 339 | return function(cb){ lr.changed(filepath); }; 340 | } 341 | 342 | var indexHtmlPath = 'index.html'; 343 | 344 | gulp.watch(appFiles.assets, runTasks('buildAppAssets')); 345 | gulp.watch(appFiles.less, runTasks('buildAppStyles', reload(configs.buildAppCss))); 346 | gulp.watch(configs.vendorLess, runTasks('buildVendorStyles', reload(configs.buildVendorCss))); 347 | gulp.watch(appFiles.html, runTasks('buildIndexHtml', reload(indexHtmlPath))); 348 | gulp.watch(appFiles.root, runTasks('buildRootFiles')); 349 | gulp.watch(appFiles.jsunit, ['testAppScripts']); 350 | gulp.watch(appFiles.jsx, function(e) { 351 | logChanged(e); 352 | 353 | if (e.type === 'deleted') { 354 | var delFile = path.relative('src', e.path); 355 | clean(path.join(configs.buildTmpSrc, delFile)); 356 | if (path.extname(delFile) === '.jsx') { 357 | var delJs = delFile.slice(0, delFile.length-4) + '.js'; 358 | clean(path.join(configs.buildTmpSrc, delJs)); 359 | clean(path.join(configs.buildSrc, delJs), function() { 360 | runSequence('buildIndexHtml', reload(indexHtmlPath)); 361 | }); 362 | } 363 | return; 364 | } 365 | 366 | if (e.type === 'changed') runSequence('buildAppScripts', reload(indexHtmlPath)); 367 | else runSequence('buildAppScripts', 'buildIndexHtml', reload(indexHtmlPath)); 368 | }); 369 | }); 370 | -------------------------------------------------------------------------------- /src/less/variables.less: -------------------------------------------------------------------------------- 1 | // 2 | // Variables 3 | // -------------------------------------------------- 4 | 5 | 6 | //== Colors 7 | // 8 | //## Gray and brand colors for use across Bootstrap. 9 | 10 | @gray-darker: lighten(#000, 13.5%); // #222 11 | @gray-dark: lighten(#000, 20%); // #333 12 | @gray: lighten(#000, 33.5%); // #555 13 | @gray-light: lighten(#000, 60%); // #999 14 | @gray-lighter: lighten(#000, 93.5%); // #eee 15 | 16 | @brand-primary: #428bca; 17 | @brand-success: #5cb85c; 18 | @brand-info: #5bc0de; 19 | @brand-warning: #f0ad4e; 20 | @brand-danger: #d9534f; 21 | 22 | 23 | //== Scaffolding 24 | // 25 | // ## Settings for some of the most global styles. 26 | 27 | //** Background color for ``. 28 | @body-bg: #fff; 29 | //** Global text color on ``. 30 | @text-color: @gray-dark; 31 | 32 | //** Global textual link color. 33 | @link-color: @brand-primary; 34 | //** Link hover color set via `darken()` function. 35 | @link-hover-color: darken(@link-color, 15%); 36 | 37 | 38 | //== Typography 39 | // 40 | //## Font, line-height, and color for body text, headings, and more. 41 | 42 | @font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif; 43 | @font-family-serif: Georgia, "Times New Roman", Times, serif; 44 | //** Default monospace fonts for ``, ``, and `
    `.
     45 | @font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace;
     46 | @font-family-base:        @font-family-sans-serif;
     47 | 
     48 | @font-size-base:          14px;
     49 | @font-size-large:         ceil((@font-size-base * 1.25)); // ~18px
     50 | @font-size-small:         ceil((@font-size-base * 0.85)); // ~12px
     51 | 
     52 | @font-size-h1:            floor((@font-size-base * 2.6)); // ~36px
     53 | @font-size-h2:            floor((@font-size-base * 2.15)); // ~30px
     54 | @font-size-h3:            ceil((@font-size-base * 1.7)); // ~24px
     55 | @font-size-h4:            ceil((@font-size-base * 1.25)); // ~18px
     56 | @font-size-h5:            @font-size-base;
     57 | @font-size-h6:            ceil((@font-size-base * 0.85)); // ~12px
     58 | 
     59 | //** Unit-less `line-height` for use in components like buttons.
     60 | @line-height-base:        1.428571429; // 20/14
     61 | //** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
     62 | @line-height-computed:    floor((@font-size-base * @line-height-base)); // ~20px
     63 | 
     64 | //** By default, this inherits from the ``.
     65 | @headings-font-family:    inherit;
     66 | @headings-font-weight:    500;
     67 | @headings-line-height:    1.1;
     68 | @headings-color:          inherit;
     69 | 
     70 | 
     71 | //-- Iconography
     72 | //
     73 | //## Specify custom locations of the include Glyphicons icon font. Useful for those including Bootstrap via Bower.
     74 | 
     75 | @icon-font-path:          "../fonts/";
     76 | @icon-font-name:          "glyphicons-halflings-regular";
     77 | @icon-font-svg-id:        "glyphicons_halflingsregular";
     78 | 
     79 | //== Components
     80 | //
     81 | //## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
     82 | 
     83 | @padding-base-vertical:     6px;
     84 | @padding-base-horizontal:   12px;
     85 | 
     86 | @padding-large-vertical:    10px;
     87 | @padding-large-horizontal:  16px;
     88 | 
     89 | @padding-small-vertical:    5px;
     90 | @padding-small-horizontal:  10px;
     91 | 
     92 | @padding-xs-vertical:       1px;
     93 | @padding-xs-horizontal:     5px;
     94 | 
     95 | @line-height-large:         1.33;
     96 | @line-height-small:         1.5;
     97 | 
     98 | @border-radius-base:        4px;
     99 | @border-radius-large:       6px;
    100 | @border-radius-small:       3px;
    101 | 
    102 | //** Global color for active items (e.g., navs or dropdowns).
    103 | @component-active-color:    #fff;
    104 | //** Global background color for active items (e.g., navs or dropdowns).
    105 | @component-active-bg:       @brand-primary;
    106 | 
    107 | //** Width of the `border` for generating carets that indicator dropdowns.
    108 | @caret-width-base:          4px;
    109 | //** Carets increase slightly in size for larger components.
    110 | @caret-width-large:         5px;
    111 | 
    112 | 
    113 | //== Tables
    114 | //
    115 | //## Customizes the `.table` component with basic values, each used across all table variations.
    116 | 
    117 | //** Padding for ``s and ``s.
    118 | @table-cell-padding:            8px;
    119 | //** Padding for cells in `.table-condensed`.
    120 | @table-condensed-cell-padding:  5px;
    121 | 
    122 | //** Default background color used for all tables.
    123 | @table-bg:                      transparent;
    124 | //** Background color used for `.table-striped`.
    125 | @table-bg-accent:               #f9f9f9;
    126 | //** Background color used for `.table-hover`.
    127 | @table-bg-hover:                #f5f5f5;
    128 | @table-bg-active:               @table-bg-hover;
    129 | 
    130 | //** Border color for table and cell borders.
    131 | @table-border-color:            #ddd;
    132 | 
    133 | 
    134 | //== Buttons
    135 | //
    136 | //## For each of Bootstrap's buttons, define text, background and border color.
    137 | 
    138 | @btn-font-weight:                normal;
    139 | 
    140 | @btn-default-color:              #333;
    141 | @btn-default-bg:                 #fff;
    142 | @btn-default-border:             #ccc;
    143 | 
    144 | @btn-primary-color:              #fff;
    145 | @btn-primary-bg:                 @brand-primary;
    146 | @btn-primary-border:             darken(@btn-primary-bg, 5%);
    147 | 
    148 | @btn-success-color:              #fff;
    149 | @btn-success-bg:                 @brand-success;
    150 | @btn-success-border:             darken(@btn-success-bg, 5%);
    151 | 
    152 | @btn-info-color:                 #fff;
    153 | @btn-info-bg:                    @brand-info;
    154 | @btn-info-border:                darken(@btn-info-bg, 5%);
    155 | 
    156 | @btn-warning-color:              #fff;
    157 | @btn-warning-bg:                 @brand-warning;
    158 | @btn-warning-border:             darken(@btn-warning-bg, 5%);
    159 | 
    160 | @btn-danger-color:               #fff;
    161 | @btn-danger-bg:                  @brand-danger;
    162 | @btn-danger-border:              darken(@btn-danger-bg, 5%);
    163 | 
    164 | @btn-link-disabled-color:        @gray-light;
    165 | 
    166 | 
    167 | //== Forms
    168 | //
    169 | //##
    170 | 
    171 | //** `` background color
    172 | @input-bg:                       #fff;
    173 | //** `` background color
    174 | @input-bg-disabled:              @gray-lighter;
    175 | 
    176 | //** Text color for ``s
    177 | @input-color:                    @gray;
    178 | //** `` border color
    179 | @input-border:                   #ccc;
    180 | //** `` border radius
    181 | @input-border-radius:            @border-radius-base;
    182 | //** Border color for inputs on focus
    183 | @input-border-focus:             #66afe9;
    184 | 
    185 | //** Placeholder text color
    186 | @input-color-placeholder:        @gray-light;
    187 | 
    188 | //** Default `.form-control` height
    189 | @input-height-base:              (@line-height-computed + (@padding-base-vertical * 2) + 2);
    190 | //** Large `.form-control` height
    191 | @input-height-large:             (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);
    192 | //** Small `.form-control` height
    193 | @input-height-small:             (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);
    194 | 
    195 | @legend-color:                   @gray-dark;
    196 | @legend-border-color:            #e5e5e5;
    197 | 
    198 | //** Background color for textual input addons
    199 | @input-group-addon-bg:           @gray-lighter;
    200 | //** Border color for textual input addons
    201 | @input-group-addon-border-color: @input-border;
    202 | 
    203 | 
    204 | //== Dropdowns
    205 | //
    206 | //## Dropdown menu container and contents.
    207 | 
    208 | //** Background for the dropdown menu.
    209 | @dropdown-bg:                    #fff;
    210 | //** Dropdown menu `border-color`.
    211 | @dropdown-border:                rgba(0,0,0,.15);
    212 | //** Dropdown menu `border-color` **for IE8**.
    213 | @dropdown-fallback-border:       #ccc;
    214 | //** Divider color for between dropdown items.
    215 | @dropdown-divider-bg:            #e5e5e5;
    216 | 
    217 | //** Dropdown link text color.
    218 | @dropdown-link-color:            @gray-dark;
    219 | //** Hover color for dropdown links.
    220 | @dropdown-link-hover-color:      darken(@gray-dark, 5%);
    221 | //** Hover background for dropdown links.
    222 | @dropdown-link-hover-bg:         #f5f5f5;
    223 | 
    224 | //** Active dropdown menu item text color.
    225 | @dropdown-link-active-color:     @component-active-color;
    226 | //** Active dropdown menu item background color.
    227 | @dropdown-link-active-bg:        @component-active-bg;
    228 | 
    229 | //** Disabled dropdown menu item background color.
    230 | @dropdown-link-disabled-color:   @gray-light;
    231 | 
    232 | //** Text color for headers within dropdown menus.
    233 | @dropdown-header-color:          @gray-light;
    234 | 
    235 | // Note: Deprecated @dropdown-caret-color as of v3.1.0
    236 | @dropdown-caret-color:           #000;
    237 | 
    238 | 
    239 | //-- Z-index master list
    240 | //
    241 | // Warning: Avoid customizing these values. They're used for a bird's eye view
    242 | // of components dependent on the z-axis and are designed to all work together.
    243 | //
    244 | // Note: These variables are not generated into the Customizer.
    245 | 
    246 | @zindex-navbar:            1000;
    247 | @zindex-dropdown:          1000;
    248 | @zindex-popover:           1010;
    249 | @zindex-tooltip:           1030;
    250 | @zindex-navbar-fixed:      1030;
    251 | @zindex-modal-background:  1040;
    252 | @zindex-modal:             1050;
    253 | 
    254 | 
    255 | //== Media queries breakpoints
    256 | //
    257 | //## Define the breakpoints at which your layout will change, adapting to different screen sizes.
    258 | 
    259 | // Extra small screen / phone
    260 | // Note: Deprecated @screen-xs and @screen-phone as of v3.0.1
    261 | @screen-xs:                  480px;
    262 | @screen-xs-min:              @screen-xs;
    263 | @screen-phone:               @screen-xs-min;
    264 | 
    265 | // Small screen / tablet
    266 | // Note: Deprecated @screen-sm and @screen-tablet as of v3.0.1
    267 | @screen-sm:                  768px;
    268 | @screen-sm-min:              @screen-sm;
    269 | @screen-tablet:              @screen-sm-min;
    270 | 
    271 | // Medium screen / desktop
    272 | // Note: Deprecated @screen-md and @screen-desktop as of v3.0.1
    273 | @screen-md:                  992px;
    274 | @screen-md-min:              @screen-md;
    275 | @screen-desktop:             @screen-md-min;
    276 | 
    277 | // Large screen / wide desktop
    278 | // Note: Deprecated @screen-lg and @screen-lg-desktop as of v3.0.1
    279 | @screen-lg:                  1200px;
    280 | @screen-lg-min:              @screen-lg;
    281 | @screen-lg-desktop:          @screen-lg-min;
    282 | 
    283 | // So media queries don't overlap when required, provide a maximum
    284 | @screen-xs-max:              (@screen-sm-min - 1);
    285 | @screen-sm-max:              (@screen-md-min - 1);
    286 | @screen-md-max:              (@screen-lg-min - 1);
    287 | 
    288 | 
    289 | //== Grid system
    290 | //
    291 | //## Define your custom responsive grid.
    292 | 
    293 | //** Number of columns in the grid.
    294 | @grid-columns:              12;
    295 | //** Padding between columns. Gets divided in half for the left and right.
    296 | @grid-gutter-width:         30px;
    297 | // Navbar collapse
    298 | //** Point at which the navbar becomes uncollapsed.
    299 | @grid-float-breakpoint:     @screen-sm-min;
    300 | //** Point at which the navbar begins collapsing.
    301 | @grid-float-breakpoint-max: (@grid-float-breakpoint - 1);
    302 | 
    303 | 
    304 | //== Container sizes
    305 | //
    306 | //## Define the maximum width of `.container` for different screen sizes.
    307 | 
    308 | // Small screen / tablet
    309 | @container-tablet:             ((720px + @grid-gutter-width));
    310 | //** For `@screen-sm-min` and up.
    311 | @container-sm:                 @container-tablet;
    312 | 
    313 | // Medium screen / desktop
    314 | @container-desktop:            ((940px + @grid-gutter-width));
    315 | //** For `@screen-md-min` and up.
    316 | @container-md:                 @container-desktop;
    317 | 
    318 | // Large screen / wide desktop
    319 | @container-large-desktop:      ((1140px + @grid-gutter-width));
    320 | //** For `@screen-lg-min` and up.
    321 | @container-lg:                 @container-large-desktop;
    322 | 
    323 | 
    324 | //== Navbar
    325 | //
    326 | //##
    327 | 
    328 | // Basics of a navbar
    329 | @navbar-height:                    50px;
    330 | @navbar-margin-bottom:             @line-height-computed;
    331 | @navbar-border-radius:             @border-radius-base;
    332 | @navbar-padding-horizontal:        floor((@grid-gutter-width / 2));
    333 | @navbar-padding-vertical:          ((@navbar-height - @line-height-computed) / 2);
    334 | @navbar-collapse-max-height:       340px;
    335 | 
    336 | @navbar-default-color:             #777;
    337 | @navbar-default-bg:                #f8f8f8;
    338 | @navbar-default-border:            darken(@navbar-default-bg, 6.5%);
    339 | 
    340 | // Navbar links
    341 | @navbar-default-link-color:                #777;
    342 | @navbar-default-link-hover-color:          #333;
    343 | @navbar-default-link-hover-bg:             transparent;
    344 | @navbar-default-link-active-color:         #555;
    345 | @navbar-default-link-active-bg:            darken(@navbar-default-bg, 6.5%);
    346 | @navbar-default-link-disabled-color:       #ccc;
    347 | @navbar-default-link-disabled-bg:          transparent;
    348 | 
    349 | // Navbar brand label
    350 | @navbar-default-brand-color:               @navbar-default-link-color;
    351 | @navbar-default-brand-hover-color:         darken(@navbar-default-brand-color, 10%);
    352 | @navbar-default-brand-hover-bg:            transparent;
    353 | 
    354 | // Navbar toggle
    355 | @navbar-default-toggle-hover-bg:           #ddd;
    356 | @navbar-default-toggle-icon-bar-bg:        #888;
    357 | @navbar-default-toggle-border-color:       #ddd;
    358 | 
    359 | 
    360 | // Inverted navbar
    361 | // Reset inverted navbar basics
    362 | @navbar-inverse-color:                      @gray-light;
    363 | @navbar-inverse-bg:                         #222;
    364 | @navbar-inverse-border:                     darken(@navbar-inverse-bg, 10%);
    365 | 
    366 | // Inverted navbar links
    367 | @navbar-inverse-link-color:                 @gray-light;
    368 | @navbar-inverse-link-hover-color:           #fff;
    369 | @navbar-inverse-link-hover-bg:              transparent;
    370 | @navbar-inverse-link-active-color:          @navbar-inverse-link-hover-color;
    371 | @navbar-inverse-link-active-bg:             darken(@navbar-inverse-bg, 10%);
    372 | @navbar-inverse-link-disabled-color:        #444;
    373 | @navbar-inverse-link-disabled-bg:           transparent;
    374 | 
    375 | // Inverted navbar brand label
    376 | @navbar-inverse-brand-color:                @navbar-inverse-link-color;
    377 | @navbar-inverse-brand-hover-color:          #fff;
    378 | @navbar-inverse-brand-hover-bg:             transparent;
    379 | 
    380 | // Inverted navbar toggle
    381 | @navbar-inverse-toggle-hover-bg:            #333;
    382 | @navbar-inverse-toggle-icon-bar-bg:         #fff;
    383 | @navbar-inverse-toggle-border-color:        #333;
    384 | 
    385 | 
    386 | //== Navs
    387 | //
    388 | //##
    389 | 
    390 | //=== Shared nav styles
    391 | @nav-link-padding:                          10px 15px;
    392 | @nav-link-hover-bg:                         @gray-lighter;
    393 | 
    394 | @nav-disabled-link-color:                   @gray-light;
    395 | @nav-disabled-link-hover-color:             @gray-light;
    396 | 
    397 | @nav-open-link-hover-color:                 #fff;
    398 | 
    399 | //== Tabs
    400 | @nav-tabs-border-color:                     #ddd;
    401 | 
    402 | @nav-tabs-link-hover-border-color:          @gray-lighter;
    403 | 
    404 | @nav-tabs-active-link-hover-bg:             @body-bg;
    405 | @nav-tabs-active-link-hover-color:          @gray;
    406 | @nav-tabs-active-link-hover-border-color:   #ddd;
    407 | 
    408 | @nav-tabs-justified-link-border-color:            #ddd;
    409 | @nav-tabs-justified-active-link-border-color:     @body-bg;
    410 | 
    411 | //== Pills
    412 | @nav-pills-border-radius:                   @border-radius-base;
    413 | @nav-pills-active-link-hover-bg:            @component-active-bg;
    414 | @nav-pills-active-link-hover-color:         @component-active-color;
    415 | 
    416 | 
    417 | //== Pagination
    418 | //
    419 | //##
    420 | 
    421 | @pagination-color:                     @link-color;
    422 | @pagination-bg:                        #fff;
    423 | @pagination-border:                    #ddd;
    424 | 
    425 | @pagination-hover-color:               @link-hover-color;
    426 | @pagination-hover-bg:                  @gray-lighter;
    427 | @pagination-hover-border:              #ddd;
    428 | 
    429 | @pagination-active-color:              #fff;
    430 | @pagination-active-bg:                 @brand-primary;
    431 | @pagination-active-border:             @brand-primary;
    432 | 
    433 | @pagination-disabled-color:            @gray-light;
    434 | @pagination-disabled-bg:               #fff;
    435 | @pagination-disabled-border:           #ddd;
    436 | 
    437 | 
    438 | //== Pager
    439 | //
    440 | //##
    441 | 
    442 | @pager-bg:                             @pagination-bg;
    443 | @pager-border:                         @pagination-border;
    444 | @pager-border-radius:                  15px;
    445 | 
    446 | @pager-hover-bg:                       @pagination-hover-bg;
    447 | 
    448 | @pager-active-bg:                      @pagination-active-bg;
    449 | @pager-active-color:                   @pagination-active-color;
    450 | 
    451 | @pager-disabled-color:                 @pagination-disabled-color;
    452 | 
    453 | 
    454 | //== Jumbotron
    455 | //
    456 | //##
    457 | 
    458 | @jumbotron-padding:              30px;
    459 | @jumbotron-color:                inherit;
    460 | @jumbotron-bg:                   @gray-lighter;
    461 | @jumbotron-heading-color:        inherit;
    462 | @jumbotron-font-size:            ceil((@font-size-base * 1.5));
    463 | 
    464 | 
    465 | //== Form states and alerts
    466 | //
    467 | //## Define colors for form feedback states and, by default, alerts.
    468 | 
    469 | @state-success-text:             #3c763d;
    470 | @state-success-bg:               #dff0d8;
    471 | @state-success-border:           darken(spin(@state-success-bg, -10), 5%);
    472 | 
    473 | @state-info-text:                #31708f;
    474 | @state-info-bg:                  #d9edf7;
    475 | @state-info-border:              darken(spin(@state-info-bg, -10), 7%);
    476 | 
    477 | @state-warning-text:             #8a6d3b;
    478 | @state-warning-bg:               #fcf8e3;
    479 | @state-warning-border:           darken(spin(@state-warning-bg, -10), 5%);
    480 | 
    481 | @state-danger-text:              #a94442;
    482 | @state-danger-bg:                #f2dede;
    483 | @state-danger-border:            darken(spin(@state-danger-bg, -10), 5%);
    484 | 
    485 | 
    486 | //== Tooltips
    487 | //
    488 | //##
    489 | 
    490 | //** Tooltip max width
    491 | @tooltip-max-width:           200px;
    492 | //** Tooltip text color
    493 | @tooltip-color:               #fff;
    494 | //** Tooltip background color
    495 | @tooltip-bg:                  #000;
    496 | @tooltip-opacity:             .9;
    497 | 
    498 | //** Tooltip arrow width
    499 | @tooltip-arrow-width:         5px;
    500 | //** Tooltip arrow color
    501 | @tooltip-arrow-color:         @tooltip-bg;
    502 | 
    503 | 
    504 | //== Popovers
    505 | //
    506 | //##
    507 | 
    508 | //** Popover body background color
    509 | @popover-bg:                          #fff;
    510 | //** Popover maximum width
    511 | @popover-max-width:                   276px;
    512 | //** Popover border color
    513 | @popover-border-color:                rgba(0,0,0,.2);
    514 | //** Popover fallback border color
    515 | @popover-fallback-border-color:       #ccc;
    516 | 
    517 | //** Popover title background color
    518 | @popover-title-bg:                    darken(@popover-bg, 3%);
    519 | 
    520 | //** Popover arrow width
    521 | @popover-arrow-width:                 10px;
    522 | //** Popover arrow color
    523 | @popover-arrow-color:                 #fff;
    524 | 
    525 | //** Popover outer arrow width
    526 | @popover-arrow-outer-width:           (@popover-arrow-width + 1);
    527 | //** Popover outer arrow color
    528 | @popover-arrow-outer-color:           fadein(@popover-border-color, 5%);
    529 | //** Popover outer arrow fallback color
    530 | @popover-arrow-outer-fallback-color:  darken(@popover-fallback-border-color, 20%);
    531 | 
    532 | 
    533 | //== Labels
    534 | //
    535 | //##
    536 | 
    537 | //** Default label background color
    538 | @label-default-bg:            @gray-light;
    539 | //** Primary label background color
    540 | @label-primary-bg:            @brand-primary;
    541 | //** Success label background color
    542 | @label-success-bg:            @brand-success;
    543 | //** Info label background color
    544 | @label-info-bg:               @brand-info;
    545 | //** Warning label background color
    546 | @label-warning-bg:            @brand-warning;
    547 | //** Danger label background color
    548 | @label-danger-bg:             @brand-danger;
    549 | 
    550 | //** Default label text color
    551 | @label-color:                 #fff;
    552 | //** Default text color of a linked label
    553 | @label-link-hover-color:      #fff;
    554 | 
    555 | 
    556 | //== Modals
    557 | //
    558 | //##
    559 | 
    560 | //** Padding applied to the modal body
    561 | @modal-inner-padding:         20px;
    562 | 
    563 | //** Padding applied to the modal title
    564 | @modal-title-padding:         15px;
    565 | //** Modal title line-height
    566 | @modal-title-line-height:     @line-height-base;
    567 | 
    568 | //** Background color of modal content area
    569 | @modal-content-bg:                             #fff;
    570 | //** Modal content border color
    571 | @modal-content-border-color:                   rgba(0,0,0,.2);
    572 | //** Modal content border color **for IE8**
    573 | @modal-content-fallback-border-color:          #999;
    574 | 
    575 | //** Modal backdrop background color
    576 | @modal-backdrop-bg:           #000;
    577 | //** Modal backdrop opacity
    578 | @modal-backdrop-opacity:      .5;
    579 | //** Modal header border color
    580 | @modal-header-border-color:   #e5e5e5;
    581 | //** Modal footer border color
    582 | @modal-footer-border-color:   @modal-header-border-color;
    583 | 
    584 | @modal-lg:                    900px;
    585 | @modal-md:                    600px;
    586 | @modal-sm:                    300px;
    587 | 
    588 | 
    589 | //== Alerts
    590 | //
    591 | //## Define alert colors, border radius, and padding.
    592 | 
    593 | @alert-padding:               15px;
    594 | @alert-border-radius:         @border-radius-base;
    595 | @alert-link-font-weight:      bold;
    596 | 
    597 | @alert-success-bg:            @state-success-bg;
    598 | @alert-success-text:          @state-success-text;
    599 | @alert-success-border:        @state-success-border;
    600 | 
    601 | @alert-info-bg:               @state-info-bg;
    602 | @alert-info-text:             @state-info-text;
    603 | @alert-info-border:           @state-info-border;
    604 | 
    605 | @alert-warning-bg:            @state-warning-bg;
    606 | @alert-warning-text:          @state-warning-text;
    607 | @alert-warning-border:        @state-warning-border;
    608 | 
    609 | @alert-danger-bg:             @state-danger-bg;
    610 | @alert-danger-text:           @state-danger-text;
    611 | @alert-danger-border:         @state-danger-border;
    612 | 
    613 | 
    614 | //== Progress bars
    615 | //
    616 | //##
    617 | 
    618 | //** Background color of the whole progress component
    619 | @progress-bg:                 #f5f5f5;
    620 | //** Progress bar text color
    621 | @progress-bar-color:          #fff;
    622 | 
    623 | //** Default progress bar color
    624 | @progress-bar-bg:             @brand-primary;
    625 | //** Success progress bar color
    626 | @progress-bar-success-bg:     @brand-success;
    627 | //** Warning progress bar color
    628 | @progress-bar-warning-bg:     @brand-warning;
    629 | //** Danger progress bar color
    630 | @progress-bar-danger-bg:      @brand-danger;
    631 | //** Info progress bar color
    632 | @progress-bar-info-bg:        @brand-info;
    633 | 
    634 | 
    635 | //== List group
    636 | //
    637 | //##
    638 | 
    639 | //** Background color on `.list-group-item`
    640 | @list-group-bg:                 #fff;
    641 | //** `.list-group-item` border color
    642 | @list-group-border:             #ddd;
    643 | //** List group border radius
    644 | @list-group-border-radius:      @border-radius-base;
    645 | 
    646 | //** Background color of single list elements on hover
    647 | @list-group-hover-bg:           #f5f5f5;
    648 | //** Text color of active list elements
    649 | @list-group-active-color:       @component-active-color;
    650 | //** Background color of active list elements
    651 | @list-group-active-bg:          @component-active-bg;
    652 | //** Border color of active list elements
    653 | @list-group-active-border:      @list-group-active-bg;
    654 | @list-group-active-text-color:  lighten(@list-group-active-bg, 40%);
    655 | 
    656 | @list-group-link-color:         #555;
    657 | @list-group-link-heading-color: #333;
    658 | 
    659 | 
    660 | //== Panels
    661 | //
    662 | //##
    663 | 
    664 | @panel-bg:                    #fff;
    665 | @panel-body-padding:          15px;
    666 | @panel-border-radius:         @border-radius-base;
    667 | 
    668 | //** Border color for elements within panels
    669 | @panel-inner-border:          #ddd;
    670 | @panel-footer-bg:             #f5f5f5;
    671 | 
    672 | @panel-default-text:          @gray-dark;
    673 | @panel-default-border:        #ddd;
    674 | @panel-default-heading-bg:    #f5f5f5;
    675 | 
    676 | @panel-primary-text:          #fff;
    677 | @panel-primary-border:        @brand-primary;
    678 | @panel-primary-heading-bg:    @brand-primary;
    679 | 
    680 | @panel-success-text:          @state-success-text;
    681 | @panel-success-border:        @state-success-border;
    682 | @panel-success-heading-bg:    @state-success-bg;
    683 | 
    684 | @panel-info-text:             @state-info-text;
    685 | @panel-info-border:           @state-info-border;
    686 | @panel-info-heading-bg:       @state-info-bg;
    687 | 
    688 | @panel-warning-text:          @state-warning-text;
    689 | @panel-warning-border:        @state-warning-border;
    690 | @panel-warning-heading-bg:    @state-warning-bg;
    691 | 
    692 | @panel-danger-text:           @state-danger-text;
    693 | @panel-danger-border:         @state-danger-border;
    694 | @panel-danger-heading-bg:     @state-danger-bg;
    695 | 
    696 | 
    697 | //== Thumbnails
    698 | //
    699 | //##
    700 | 
    701 | //** Padding around the thumbnail image
    702 | @thumbnail-padding:           4px;
    703 | //** Thumbnail background color
    704 | @thumbnail-bg:                @body-bg;
    705 | //** Thumbnail border color
    706 | @thumbnail-border:            #ddd;
    707 | //** Thumbnail border radius
    708 | @thumbnail-border-radius:     @border-radius-base;
    709 | 
    710 | //** Custom text color for thumbnail captions
    711 | @thumbnail-caption-color:     @text-color;
    712 | //** Padding around the thumbnail caption
    713 | @thumbnail-caption-padding:   9px;
    714 | 
    715 | 
    716 | //== Wells
    717 | //
    718 | //##
    719 | 
    720 | @well-bg:                     #f5f5f5;
    721 | @well-border:                 darken(@well-bg, 7%);
    722 | 
    723 | 
    724 | //== Badges
    725 | //
    726 | //##
    727 | 
    728 | @badge-color:                 #fff;
    729 | //** Linked badge text color on hover
    730 | @badge-link-hover-color:      #fff;
    731 | @badge-bg:                    @gray-light;
    732 | 
    733 | //** Badge text color in active nav link
    734 | @badge-active-color:          @link-color;
    735 | //** Badge background color in active nav link
    736 | @badge-active-bg:             #fff;
    737 | 
    738 | @badge-font-weight:           bold;
    739 | @badge-line-height:           1;
    740 | @badge-border-radius:         10px;
    741 | 
    742 | 
    743 | //== Breadcrumbs
    744 | //
    745 | //##
    746 | 
    747 | @breadcrumb-padding-vertical:   8px;
    748 | @breadcrumb-padding-horizontal: 15px;
    749 | //** Breadcrumb background color
    750 | @breadcrumb-bg:                 #f5f5f5;
    751 | //** Breadcrumb text color
    752 | @breadcrumb-color:              #ccc;
    753 | //** Text color of current page in the breadcrumb
    754 | @breadcrumb-active-color:       @gray-light;
    755 | //** Textual separator for between breadcrumb elements
    756 | @breadcrumb-separator:          "/";
    757 | 
    758 | 
    759 | //== Carousel
    760 | //
    761 | //##
    762 | 
    763 | @carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6);
    764 | 
    765 | @carousel-control-color:                      #fff;
    766 | @carousel-control-width:                      15%;
    767 | @carousel-control-opacity:                    .5;
    768 | @carousel-control-font-size:                  20px;
    769 | 
    770 | @carousel-indicator-active-bg:                #fff;
    771 | @carousel-indicator-border-color:             #fff;
    772 | 
    773 | @carousel-caption-color:                      #fff;
    774 | 
    775 | 
    776 | //== Close
    777 | //
    778 | //##
    779 | 
    780 | @close-font-weight:           bold;
    781 | @close-color:                 #000;
    782 | @close-text-shadow:           0 1px 0 #fff;
    783 | 
    784 | 
    785 | //== Code
    786 | //
    787 | //##
    788 | 
    789 | @code-color:                  #c7254e;
    790 | @code-bg:                     #f9f2f4;
    791 | 
    792 | @kbd-color:                   #fff;
    793 | @kbd-bg:                      #333;
    794 | 
    795 | @pre-bg:                      #f5f5f5;
    796 | @pre-color:                   @gray-dark;
    797 | @pre-border-color:            #ccc;
    798 | @pre-scrollable-max-height:   340px;
    799 | 
    800 | 
    801 | //== Type
    802 | //
    803 | //##
    804 | 
    805 | //** Text muted color
    806 | @text-muted:                  @gray-light;
    807 | //** Abbreviations and acronyms border color
    808 | @abbr-border-color:           @gray-light;
    809 | //** Headings small color
    810 | @headings-small-color:        @gray-light;
    811 | //** Blockquote small color
    812 | @blockquote-small-color:      @gray-light;
    813 | //** Blockquote font size
    814 | @blockquote-font-size:        (@font-size-base * 1.25);
    815 | //** Blockquote border color
    816 | @blockquote-border-color:     @gray-lighter;
    817 | //** Page header border color
    818 | @page-header-border-color:    @gray-lighter;
    819 | 
    820 | 
    821 | //== Miscellaneous
    822 | //
    823 | //##
    824 | 
    825 | //** Horizontal line color.
    826 | @hr-border:                   @gray-lighter;
    827 | 
    828 | //** Horizontal offset for forms and lists.
    829 | @component-offset-horizontal: 180px;
    830 | 
    
    
    --------------------------------------------------------------------------------