Commit 0d33455e authored by John-Philip Johansson's avatar John-Philip Johansson Committed by Chris Rebert

Replace Makefile with GruntJS

A rebase (against soon-to-be 3.0.0-rc.1) & squash of
https://github.com/twbs/bootstrap/pull/7786 AKA
https://github.com/twitter/bootstrap/pull/7786
originally by
@seriema
@mokkabonna
@jojohess

Rebased by @cvrebert
parent 995add13
language: node_js
node_js:
- 0.6
- 0.8
before_script:
- npm install -g grunt-cli
\ No newline at end of file
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
// Metadata.
pkg: grunt.file.readJSON('package.json'),
banner: '/**\n' +
'* <%= pkg.name %>.js v<%= pkg.version %> by @fat and @mdo\n' +
'* Copyright <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +
'* <%= _.pluck(pkg.licenses, "url").join(", ") %>\n' +
'*/\n',
// Task configuration.
clean: {
dist: ['dist']
},
concat: {
options: {
banner: '<%= banner %>',
stripBanners: false
},
bootstrap: {
src: ['js/*.js'],
dest: 'dist/js/<%= pkg.name %>.js'
}
},
jshint: {
options: {
jshintrc: 'js/.jshintrc'
},
gruntfile: {
src: 'Gruntfile.js'
},
src: {
src: ['js/*.js']
},
test: {
src: ['js/tests/unit/*.js']
}
},
recess: {
options: {
compile: true
},
bootstrap: {
files: {
'dist/css/bootstrap.css': ['less/bootstrap.less']
}
},
min: {
options: {
compress: true
},
files: {
'dist/css/bootstrap.min.css': ['less/bootstrap.less']
}
}
},
uglify: {
options: {
banner: '<%= banner %>'
},
bootstrap: {
files: {
'dist/js/<%= pkg.name %>.min.js': ['<%= concat.bootstrap.dest %>']
}
}
},
qunit: {
options: {
inject: 'js/tests/unit/phantom.js'
},
files: ['js/tests/*.html']
},
connect: {
server: {
options: {
port: 3000,
base: '.'
}
}
},
watch: {
src: {
files: '<%= jshint.src.src %>',
tasks: ['jshint:src', 'qunit']
},
test: {
files: '<%= jshint.test.src %>',
tasks: ['jshint:test', 'qunit']
},
recess: {
files: 'less/*.less',
tasks: ['recess']
}
}
});
// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-recess');
// Test task.
grunt.registerTask('test', ['jshint', 'qunit']);
// JS distribution task.
grunt.registerTask('dist-js', ['concat', 'uglify']);
// CSS distribution task.
grunt.registerTask('dist-css', ['recess']);
// Full distribution task.
grunt.registerTask('dist', ['clean', 'dist-css', 'dist-js']);
// Default task.
grunt.registerTask('default', ['test', 'dist']);
};
BOOTSTRAP ?= ./dist/css/bootstrap.css
BOOTSTRAP_MIN ?= ./dist/css/bootstrap.min.css
BOOTSTRAP_LESS ?= ./less/bootstrap.less
DATE=$(shell date +%I:%M%p)
CHECK=\033[32m✔ Done\033[39m
HR=\033[37m--------------------------------------------------\033[39m
PATH := ./node_modules/.bin:$(PATH)
#
# BUILD DOCS
#
build:
@echo "\n\n"
@echo "\033[36mBuilding Bootstrap...\033[39m"
@echo "${HR}"
@printf "Running JSHint on JavaScript..."
@jshint js/*.js --config js/.jshintrc
@jshint js/tests/unit/*.js --config js/.jshintrc
@echo " ${CHECK}"
@printf "Compiling LESS with Recess..."
@recess --compile ${BOOTSTRAP_LESS} > ${BOOTSTRAP}
@recess --compress ${BOOTSTRAP_LESS} > ${BOOTSTRAP_MIN}
@echo " ${CHECK}"
@printf "Prepping documentation assets..."
@cp js/tests/vendor/jquery.js assets/js/
@echo " ${CHECK}"
@printf "Compiling and minifying JavaScript..."
@echo "if (!jQuery) { throw new Error(\"Bootstrap requires jQuery\") }\n\n" | cat - js/transition.js js/alert.js js/button.js js/carousel.js js/collapse.js js/dropdown.js js/modal.js js/tooltip.js js/popover.js js/scrollspy.js js/tab.js js/affix.js > dist/js/bootstrap.js
@uglifyjs -nc dist/js/bootstrap.js > dist/js/bootstrap.min.tmp.js
@echo "/**\n* Bootstrap.js v3.0.0 by @fat & @mdo\n* Copyright 2013 Twitter, Inc.\n* http://www.apache.org/licenses/LICENSE-2.0.txt\n*/" > dist/js/copyright.js
@cat dist/js/copyright.js dist/js/bootstrap.min.tmp.js > dist/js/bootstrap.min.js
@rm dist/js/copyright.js dist/js/bootstrap.min.tmp.js
@echo " ${CHECK}"
@echo "${HR}"
@echo "\033[36mSuccess!\n\033[39m"
@echo "\033[37mThanks for using Bootstrap,"
@echo "<3 @mdo and @fat\n\033[39m"
#
# RUN JSHINT & QUNIT TESTS IN PHANTOMJS
#
test:
jshint js/*.js --config js/.jshintrc
jshint js/tests/unit/*.js --config js/.jshintrc
node js/tests/server.js &
phantomjs js/tests/phantom.js "http://localhost:3000/js/tests"
kill -9 `cat js/tests/pid.txt`
rm js/tests/pid.txt
#
# CLEANS THE ROOT DIRECTORY OF PRIOR BUILDS
#
clean:
rm -r bootstrap
#
# BUILD SIMPLE BOOTSTRAP DIRECTORY
# recess & uglifyjs are required
#
bootstrap: bootstrap-css bootstrap-js
#
# JS COMPILE
#
bootstrap-js: bootstrap/js/*.js
bootstrap/js/*.js: js/*.js
mkdir -p bootstrap/js
cat js/transition.js js/alert.js js/button.js js/carousel.js js/collapse.js js/dropdown.js js/modal.js js/tooltip.js js/popover.js js/scrollspy.js js/tab.js js/affix.js > bootstrap/js/bootstrap.js
uglifyjs -nc bootstrap/js/bootstrap.js > bootstrap/js/bootstrap.min.tmp.js
echo "/*!\n* Bootstrap.js by @fat & @mdo\n* Copyright 2013 Twitter, Inc.\n* http://www.apache.org/licenses/LICENSE-2.0.txt\n*/" > bootstrap/js/copyright.js
cat bootstrap/js/copyright.js bootstrap/js/bootstrap.min.tmp.js > bootstrap/js/bootstrap.min.js
rm bootstrap/js/copyright.js bootstrap/js/bootstrap.min.tmp.js
#
# CSS COMPILE
#
bootstrap-css: bootstrap/css/*.css
bootstrap/css/*.css: less/*.less
mkdir -p bootstrap/css
recess --compile ${BOOTSTRAP_LESS} > bootstrap/css/bootstrap.css
recess --compress ${BOOTSTRAP_LESS} > bootstrap/css/bootstrap.min.css
#
# WATCH LESS FILES
#
watch:
echo "Watching less files..."; \
watchr -e "watch('less/.*\.less') { system 'make' }"
#
# BUILD AND START SERVER
#
run: build
jekyll build && jekyll server
.PHONY: docs watch gh-pages bootstrap-css bootstrap-js
......@@ -46,33 +46,36 @@ Documentation for v2.3.2 has been made available for the time being at [http://g
## Compiling CSS and JavaScript
Bootstrap includes a [makefile](Makefile) with convenient methods for working with the framework. Before getting started, install [the necessary local dependencies](package.json):
Bootstrap uses [GruntJS](http://gruntjs.com/) with convenient methods for working with the framework. Before getting started, be sure to have `grunt-cli` installed globally (`npm install -g grunt-cli`) and then install [the necessary local dependencies](package.json):
```
# if grunt-cli isn't already installed
$ npm install -g grunt-cli
$ npm install
```
When completed, you'll be able to run the various make commands provided.
When completed, you'll be able to run the various grunt commands provided.
**Unfamiliar with `npm`? Don't have node installed?** That's a-okay. npm stands for [node packaged modules](http://npmjs.org/) and is a way to manage development dependencies through node.js. [Download and install node.js](http://nodejs.org/download/) before proceeding.
### Available makefile commands
### Available grunt commands
#### Build - `make`
`make` runs the Recess compiler to rebuild the `/less` files and compile the docs. **Requires recess and uglify-js.**
#### Build - `grunt`
`grunt` runs the Recess compiler to rebuild the `/less` files and compile the docs. **Requires recess and uglify-js.**
#### Compile CSS, JS, and fonts - `make bootstrap`
`make bootstrap` creates the `/bootstrap` directory with compiled files. **Requires recess and uglify-js.**
#### Compile CSS, JS, and fonts - `grunt bootstrap`
`grunt bootstrap` creates the `/bootstrap` directory with compiled files. **Requires recess and uglify-js.**
#### Tests - `make test`
#### Tests - `grunt test`
Runs jshint and qunit tests headlessly in [phantomjs](http://code.google.com/p/phantomjs/) (used for ci). **Requires phantomjs.**
#### Watch - `make watch`
This is a convenience method for watching just Less files and automatically building them whenever you save. **Requires the watchr gem.**
#### Watch - `grunt watch`
This is a convenience method for watching just Less files and automatically building them whenever you save.
### Troubleshooting dependencies
Should you encounter problems with installing dependencies or running makefile commands, uninstall all previous dependency versions (global and local). Then, rerun `npm install`.
Should you encounter problems with installing dependencies or running grunt commands, uninstall all previous dependency versions (global and local). Then, rerun `npm install`.
......
......@@ -4668,4 +4668,4 @@ td.visible-print {
td.hidden-print {
display: none !important;
}
}
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
......@@ -11,9 +11,6 @@
<link rel="stylesheet" href="vendor/qunit.css" type="text/css" media="screen" />
<script src="vendor/qunit.js"></script>
<!-- phantomjs logging script-->
<script src="unit/phantom.js"></script>
<!-- plugin sources -->
<script src="../../js/transition.js"></script>
<script src="../../js/alert.js"></script>
......
......@@ -40,14 +40,15 @@ $(function () {
ok(btn.hasClass('disabled'), 'btn has disabled class')
start()
stop()
btn.button('reset')
equals(btn.html(), 'mdo', 'btn text equals mdo')
setTimeout(function () {
ok(!btn.attr('disabled'), 'btn is not disabled')
ok(!btn.hasClass('disabled'), 'btn does not have disabled class')
start()
}, 0)
}, 0)
btn.button('reset')
equals(btn.html(), 'mdo', 'btn text equals mdo')
setTimeout(function () {
ok(!btn.attr('disabled'), 'btn is not disabled')
ok(!btn.hasClass('disabled'), 'btn does not have disabled class')
start()
}, 0)
})
test("should toggle active", function () {
......
// Logging setup for phantom integration
// adapted from Modernizr
QUnit.begin = function () {
console.log("Starting test suite")
console.log("================================================\n")
}
QUnit.moduleDone = function (opts) {
if (opts.failed === 0) {
console.log("\u2714 All tests passed in '" + opts.name + "' module")
} else {
console.log("\u2716 " + opts.failed + " tests failed in '" + opts.name + "' module")
}
}
QUnit.done = function (opts) {
console.log("\n================================================")
console.log("Tests completed in " + opts.runtime + " milliseconds")
console.log(opts.passed + " tests of " + opts.total + " passed, " + opts.failed + " failed.")
}
/*
* grunt-contrib-qunit
* http://gruntjs.com/
*
* Copyright (c) 2013 "Cowboy" Ben Alman, contributors
* Licensed under the MIT license.
*/
/*global QUnit:true, alert:true*/
(function () {
'use strict';
// Don't re-order tests.
QUnit.config.reorder = false
// Run tests serially, not in parallel.
QUnit.config.autorun = false
// Send messages to the parent PhantomJS process via alert! Good times!!
function sendMessage() {
var args = [].slice.call(arguments)
alert(JSON.stringify(args))
}
// These methods connect QUnit to PhantomJS.
QUnit.log = function(obj) {
// What is this I don’t even
if (obj.message === '[object Object], undefined:undefined') { return }
// Parse some stuff before sending it.
var actual = QUnit.jsDump.parse(obj.actual)
var expected = QUnit.jsDump.parse(obj.expected)
// Send it.
sendMessage('qunit.log', obj.result, actual, expected, obj.message, obj.source)
}
QUnit.testStart = function(obj) {
sendMessage('qunit.testStart', obj.name)
}
QUnit.testDone = function(obj) {
sendMessage('qunit.testDone', obj.name, obj.failed, obj.passed, obj.total)
}
QUnit.moduleStart = function(obj) {
sendMessage('qunit.moduleStart', obj.name)
}
QUnit.begin = function () {
sendMessage('qunit.begin')
console.log("Starting test suite")
console.log("================================================\n")
}
QUnit.moduleDone = function (opts) {
if (opts.failed === 0) {
console.log("\r\u2714 All tests passed in '" + opts.name + "' module")
} else {
console.log("\u2716 " + opts.failed + " tests failed in '" + opts.name + "' module")
}
sendMessage('qunit.moduleDone', opts.name, opts.failed, opts.passed, opts.total)
}
QUnit.done = function (opts) {
console.log("\n================================================")
console.log("Tests completed in " + opts.runtime + " milliseconds")
console.log(opts.passed + " tests of " + opts.total + " passed, " + opts.failed + " failed.")
sendMessage('qunit.done', opts.failed, opts.passed, opts.total, opts.runtime)
}
}())
......@@ -5,7 +5,7 @@
, "keywords": ["bootstrap", "css"]
, "homepage": "http://twbs.github.com/bootstrap/"
, "author": "Twitter Inc."
, "scripts": { "test": "make test" }
, "scripts": { "test": "grunt test" }
, "repository": {
"type": "git"
, "url": "https://github.com/twbs/bootstrap.git"
......@@ -17,9 +17,14 @@
}
]
, "devDependencies": {
"uglify-js": "1.3.4"
, "jshint": "2.1.2"
, "recess": "1.1.7"
, "connect": "2.1.3"
"grunt": "~0.4.1"
, "grunt-contrib-connect": "~0.3.0"
, "grunt-contrib-clean": "~0.5.0"
, "grunt-contrib-concat": "~0.3.0"
, "grunt-contrib-jshint": "~0.6.0"
, "grunt-contrib-uglify": "~0.2.2"
, "grunt-contrib-qunit": "~0.2.2"
, "grunt-contrib-watch": "~0.5.1"
, "grunt-recess": "~0.3.3"
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment