info@54
|
1 |
/* jshint node: true */
|
info@54
|
2 |
|
info@54
|
3 |
module.exports = function(grunt) {
|
info@54
|
4 |
"use strict";
|
info@54
|
5 |
|
info@54
|
6 |
// Force use of Unix newlines
|
info@54
|
7 |
grunt.util.linefeed = '\n';
|
info@54
|
8 |
|
info@54
|
9 |
RegExp.quote = require('regexp-quote')
|
info@54
|
10 |
var btoa = require('btoa')
|
info@54
|
11 |
// Project configuration.
|
info@54
|
12 |
grunt.initConfig({
|
info@54
|
13 |
|
info@54
|
14 |
// Metadata.
|
info@54
|
15 |
pkg: grunt.file.readJSON('package.json'),
|
info@54
|
16 |
banner: '/*!\n' +
|
info@54
|
17 |
' * Bootstrap v<%= pkg.version %> (<%= pkg.homepage %>)\n' +
|
info@54
|
18 |
' * Copyright <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +
|
info@54
|
19 |
' * Licensed under <%= _.pluck(pkg.licenses, "url").join(", ") %>\n' +
|
info@54
|
20 |
' */\n\n',
|
info@54
|
21 |
jqueryCheck: 'if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery") }\n\n',
|
info@54
|
22 |
|
info@54
|
23 |
// Task configuration.
|
info@54
|
24 |
clean: {
|
info@54
|
25 |
dist: ['dist']
|
info@54
|
26 |
},
|
info@54
|
27 |
|
info@54
|
28 |
jshint: {
|
info@54
|
29 |
options: {
|
info@54
|
30 |
jshintrc: 'js/.jshintrc'
|
info@54
|
31 |
},
|
info@54
|
32 |
gruntfile: {
|
info@54
|
33 |
src: 'Gruntfile.js'
|
info@54
|
34 |
},
|
info@54
|
35 |
src: {
|
info@54
|
36 |
src: ['js/*.js']
|
info@54
|
37 |
},
|
info@54
|
38 |
test: {
|
info@54
|
39 |
src: ['js/tests/unit/*.js']
|
info@54
|
40 |
}
|
info@54
|
41 |
},
|
info@54
|
42 |
|
info@54
|
43 |
concat: {
|
info@54
|
44 |
options: {
|
info@54
|
45 |
banner: '<%= banner %><%= jqueryCheck %>',
|
info@54
|
46 |
stripBanners: false
|
info@54
|
47 |
},
|
info@54
|
48 |
bootstrap: {
|
info@54
|
49 |
src: [
|
info@54
|
50 |
'js/transition.js',
|
info@54
|
51 |
'js/alert.js',
|
info@54
|
52 |
'js/button.js',
|
info@54
|
53 |
'js/carousel.js',
|
info@54
|
54 |
'js/collapse.js',
|
info@54
|
55 |
'js/dropdown.js',
|
info@54
|
56 |
'js/modal.js',
|
info@54
|
57 |
'js/tooltip.js',
|
info@54
|
58 |
'js/popover.js',
|
info@54
|
59 |
'js/scrollspy.js',
|
info@54
|
60 |
'js/tab.js',
|
info@54
|
61 |
'js/affix.js'
|
info@54
|
62 |
],
|
info@54
|
63 |
dest: 'dist/js/<%= pkg.name %>.js'
|
info@54
|
64 |
}
|
info@54
|
65 |
},
|
info@54
|
66 |
|
info@54
|
67 |
uglify: {
|
info@54
|
68 |
options: {
|
info@54
|
69 |
banner: '<%= banner %>',
|
info@54
|
70 |
report: 'min'
|
info@54
|
71 |
},
|
info@54
|
72 |
bootstrap: {
|
info@54
|
73 |
src: ['<%= concat.bootstrap.dest %>'],
|
info@54
|
74 |
dest: 'dist/js/<%= pkg.name %>.min.js'
|
info@54
|
75 |
}
|
info@54
|
76 |
},
|
info@54
|
77 |
|
info@54
|
78 |
recess: {
|
info@54
|
79 |
options: {
|
info@54
|
80 |
compile: true,
|
info@54
|
81 |
banner: '<%= banner %>'
|
info@54
|
82 |
},
|
info@54
|
83 |
bootstrap: {
|
info@54
|
84 |
src: ['less/bootstrap.less'],
|
info@54
|
85 |
dest: 'dist/css/<%= pkg.name %>.css'
|
info@54
|
86 |
},
|
info@54
|
87 |
min: {
|
info@54
|
88 |
options: {
|
info@54
|
89 |
compress: true
|
info@54
|
90 |
},
|
info@54
|
91 |
src: ['less/bootstrap.less'],
|
info@54
|
92 |
dest: 'dist/css/<%= pkg.name %>.min.css'
|
info@54
|
93 |
},
|
info@54
|
94 |
theme: {
|
info@54
|
95 |
src: ['less/theme.less'],
|
info@54
|
96 |
dest: 'dist/css/<%= pkg.name %>-theme.css'
|
info@54
|
97 |
},
|
info@54
|
98 |
theme_min: {
|
info@54
|
99 |
options: {
|
info@54
|
100 |
compress: true
|
info@54
|
101 |
},
|
info@54
|
102 |
src: ['less/theme.less'],
|
info@54
|
103 |
dest: 'dist/css/<%= pkg.name %>-theme.min.css'
|
info@54
|
104 |
}
|
info@54
|
105 |
},
|
info@54
|
106 |
|
info@54
|
107 |
copy: {
|
info@54
|
108 |
fonts: {
|
info@54
|
109 |
expand: true,
|
info@54
|
110 |
src: ["fonts/*"],
|
info@54
|
111 |
dest: 'dist/'
|
info@54
|
112 |
}
|
info@54
|
113 |
},
|
info@54
|
114 |
|
info@54
|
115 |
qunit: {
|
info@54
|
116 |
options: {
|
info@54
|
117 |
inject: 'js/tests/unit/phantom.js'
|
info@54
|
118 |
},
|
info@54
|
119 |
files: ['js/tests/*.html']
|
info@54
|
120 |
},
|
info@54
|
121 |
|
info@54
|
122 |
connect: {
|
info@54
|
123 |
server: {
|
info@54
|
124 |
options: {
|
info@54
|
125 |
port: 3000,
|
info@54
|
126 |
base: '.'
|
info@54
|
127 |
}
|
info@54
|
128 |
}
|
info@54
|
129 |
},
|
info@54
|
130 |
|
info@54
|
131 |
jekyll: {
|
info@54
|
132 |
docs: {}
|
info@54
|
133 |
},
|
info@54
|
134 |
|
info@54
|
135 |
validation: {
|
info@54
|
136 |
options: {
|
info@54
|
137 |
reset: true,
|
info@54
|
138 |
relaxerror: [
|
info@54
|
139 |
"Bad value X-UA-Compatible for attribute http-equiv on element meta.",
|
info@54
|
140 |
"Element img is missing required attribute src."
|
info@54
|
141 |
]
|
info@54
|
142 |
},
|
info@54
|
143 |
files: {
|
info@54
|
144 |
src: ["_gh_pages/**/*.html"]
|
info@54
|
145 |
}
|
info@54
|
146 |
},
|
info@54
|
147 |
|
info@54
|
148 |
watch: {
|
info@54
|
149 |
src: {
|
info@54
|
150 |
files: '<%= jshint.src.src %>',
|
info@54
|
151 |
tasks: ['jshint:src', 'qunit']
|
info@54
|
152 |
},
|
info@54
|
153 |
test: {
|
info@54
|
154 |
files: '<%= jshint.test.src %>',
|
info@54
|
155 |
tasks: ['jshint:test', 'qunit']
|
info@54
|
156 |
},
|
info@54
|
157 |
recess: {
|
info@54
|
158 |
files: 'less/*.less',
|
info@54
|
159 |
tasks: ['recess']
|
info@54
|
160 |
}
|
info@54
|
161 |
},
|
info@54
|
162 |
|
info@54
|
163 |
sed: {
|
info@54
|
164 |
versionNumber: {
|
info@54
|
165 |
pattern: (function () {
|
info@54
|
166 |
var old = grunt.option('oldver')
|
info@54
|
167 |
return old ? RegExp.quote(old) : old
|
info@54
|
168 |
})(),
|
info@54
|
169 |
replacement: grunt.option('newver'),
|
info@54
|
170 |
recursive: true
|
info@54
|
171 |
}
|
info@54
|
172 |
},
|
info@54
|
173 |
|
info@54
|
174 |
'saucelabs-qunit': {
|
info@54
|
175 |
all: {
|
info@54
|
176 |
options: {
|
info@54
|
177 |
build: process.env.TRAVIS_JOB_ID,
|
info@54
|
178 |
concurrency: 3,
|
info@54
|
179 |
urls: ['http://127.0.0.1:3000/js/tests/index.html'],
|
info@54
|
180 |
browsers: [
|
info@54
|
181 |
// See https://saucelabs.com/docs/platforms/webdriver
|
info@54
|
182 |
{
|
info@54
|
183 |
browserName: 'safari',
|
info@54
|
184 |
version: '6',
|
info@54
|
185 |
platform: 'OS X 10.8'
|
info@54
|
186 |
},
|
info@54
|
187 |
{
|
info@54
|
188 |
browserName: 'chrome',
|
info@54
|
189 |
version: '28',
|
info@54
|
190 |
platform: 'OS X 10.6'
|
info@54
|
191 |
},
|
info@54
|
192 |
/* FIXME: currently fails 1 tooltip test
|
info@54
|
193 |
{
|
info@54
|
194 |
browserName: 'firefox',
|
info@54
|
195 |
version: '25',
|
info@54
|
196 |
platform: 'OS X 10.6'
|
info@54
|
197 |
},*/
|
info@54
|
198 |
// Mac Opera not currently supported by Sauce Labs
|
info@54
|
199 |
/* FIXME: currently fails 1 tooltip test
|
info@54
|
200 |
{
|
info@54
|
201 |
browserName: 'internet explorer',
|
info@54
|
202 |
version: '11',
|
info@54
|
203 |
platform: 'Windows 8.1'
|
info@54
|
204 |
},*/
|
info@54
|
205 |
/*
|
info@54
|
206 |
{
|
info@54
|
207 |
browserName: 'internet explorer',
|
info@54
|
208 |
version: '10',
|
info@54
|
209 |
platform: 'Windows 8'
|
info@54
|
210 |
},
|
info@54
|
211 |
{
|
info@54
|
212 |
browserName: 'internet explorer',
|
info@54
|
213 |
version: '9',
|
info@54
|
214 |
platform: 'Windows 7'
|
info@54
|
215 |
},
|
info@54
|
216 |
{
|
info@54
|
217 |
browserName: 'internet explorer',
|
info@54
|
218 |
version: '8',
|
info@54
|
219 |
platform: 'Windows 7'
|
info@54
|
220 |
},
|
info@54
|
221 |
{// unofficial
|
info@54
|
222 |
browserName: 'internet explorer',
|
info@54
|
223 |
version: '7',
|
info@54
|
224 |
platform: 'Windows XP'
|
info@54
|
225 |
},
|
info@54
|
226 |
*/
|
info@54
|
227 |
{
|
info@54
|
228 |
browserName: 'chrome',
|
info@54
|
229 |
version: '31',
|
info@54
|
230 |
platform: 'Windows 8.1'
|
info@54
|
231 |
},
|
info@54
|
232 |
{
|
info@54
|
233 |
browserName: 'firefox',
|
info@54
|
234 |
version: '25',
|
info@54
|
235 |
platform: 'Windows 8.1'
|
info@54
|
236 |
},
|
info@54
|
237 |
// Win Opera 15+ not currently supported by Sauce Labs
|
info@54
|
238 |
{
|
info@54
|
239 |
browserName: 'iphone',
|
info@54
|
240 |
version: '6.1',
|
info@54
|
241 |
platform: 'OS X 10.8'
|
info@54
|
242 |
},
|
info@54
|
243 |
// iOS Chrome not currently supported by Sauce Labs
|
info@54
|
244 |
// Linux (unofficial)
|
info@54
|
245 |
{
|
info@54
|
246 |
browserName: 'chrome',
|
info@54
|
247 |
version: '30',
|
info@54
|
248 |
platform: 'Linux'
|
info@54
|
249 |
},
|
info@54
|
250 |
{
|
info@54
|
251 |
browserName: 'firefox',
|
info@54
|
252 |
version: '25',
|
info@54
|
253 |
platform: 'Linux'
|
info@54
|
254 |
}
|
info@54
|
255 |
// Android Chrome not currently supported by Sauce Labs
|
info@54
|
256 |
/* Android Browser (super-unofficial)
|
info@54
|
257 |
{
|
info@54
|
258 |
browserName: 'android',
|
info@54
|
259 |
version: '4.0',
|
info@54
|
260 |
platform: 'Linux'
|
info@54
|
261 |
}
|
info@54
|
262 |
*/
|
info@54
|
263 |
],
|
info@54
|
264 |
}
|
info@54
|
265 |
}
|
info@54
|
266 |
}
|
info@54
|
267 |
});
|
info@54
|
268 |
|
info@54
|
269 |
|
info@54
|
270 |
// These plugins provide necessary tasks.
|
info@54
|
271 |
grunt.loadNpmTasks('grunt-contrib-clean');
|
info@54
|
272 |
grunt.loadNpmTasks('grunt-contrib-concat');
|
info@54
|
273 |
grunt.loadNpmTasks('grunt-contrib-connect');
|
info@54
|
274 |
grunt.loadNpmTasks('grunt-contrib-copy');
|
info@54
|
275 |
grunt.loadNpmTasks('grunt-contrib-jshint');
|
info@54
|
276 |
grunt.loadNpmTasks('grunt-contrib-qunit');
|
info@54
|
277 |
grunt.loadNpmTasks('grunt-contrib-uglify');
|
info@54
|
278 |
grunt.loadNpmTasks('grunt-contrib-watch');
|
info@54
|
279 |
grunt.loadNpmTasks('grunt-html-validation');
|
info@54
|
280 |
grunt.loadNpmTasks('grunt-jekyll');
|
info@54
|
281 |
grunt.loadNpmTasks('grunt-recess');
|
info@54
|
282 |
grunt.loadNpmTasks('grunt-saucelabs');
|
info@54
|
283 |
grunt.loadNpmTasks('grunt-sed');
|
info@54
|
284 |
|
info@54
|
285 |
// Docs HTML validation task
|
info@54
|
286 |
grunt.registerTask('validate-html', ['jekyll', 'validation']);
|
info@54
|
287 |
|
info@54
|
288 |
// Test task.
|
info@54
|
289 |
var testSubtasks = ['dist-css', 'jshint', 'qunit', 'validate-html'];
|
info@54
|
290 |
// Only run Sauce Labs tests if there's a Sauce access key
|
info@54
|
291 |
if (typeof process.env.SAUCE_ACCESS_KEY !== 'undefined') {
|
info@54
|
292 |
testSubtasks.push('connect');
|
info@54
|
293 |
testSubtasks.push('saucelabs-qunit');
|
info@54
|
294 |
}
|
info@54
|
295 |
grunt.registerTask('test', testSubtasks);
|
info@54
|
296 |
|
info@54
|
297 |
// JS distribution task.
|
info@54
|
298 |
grunt.registerTask('dist-js', ['concat', 'uglify']);
|
info@54
|
299 |
|
info@54
|
300 |
// CSS distribution task.
|
info@54
|
301 |
grunt.registerTask('dist-css', ['recess']);
|
info@54
|
302 |
|
info@54
|
303 |
// Fonts distribution task.
|
info@54
|
304 |
grunt.registerTask('dist-fonts', ['copy']);
|
info@54
|
305 |
|
info@54
|
306 |
// Full distribution task.
|
info@54
|
307 |
grunt.registerTask('dist', ['clean', 'dist-css', 'dist-fonts', 'dist-js']);
|
info@54
|
308 |
|
info@54
|
309 |
// Default task.
|
info@54
|
310 |
grunt.registerTask('default', ['test', 'dist', 'build-customizer']);
|
info@54
|
311 |
|
info@54
|
312 |
// Version numbering task.
|
info@54
|
313 |
// grunt change-version-number --oldver=A.B.C --newver=X.Y.Z
|
info@54
|
314 |
// This can be overzealous, so its changes should always be manually reviewed!
|
info@54
|
315 |
grunt.registerTask('change-version-number', ['sed']);
|
info@54
|
316 |
|
info@54
|
317 |
// task for building customizer
|
info@54
|
318 |
grunt.registerTask('build-customizer', 'Add scripts/less files to customizer.', function () {
|
info@54
|
319 |
var fs = require('fs')
|
info@54
|
320 |
|
info@54
|
321 |
function getFiles(type) {
|
info@54
|
322 |
var files = {}
|
info@54
|
323 |
fs.readdirSync(type)
|
info@54
|
324 |
.filter(function (path) {
|
info@54
|
325 |
return type == 'fonts' ? true : new RegExp('\\.' + type + '$').test(path)
|
info@54
|
326 |
})
|
info@54
|
327 |
.forEach(function (path) {
|
info@54
|
328 |
var fullPath = type + '/' + path
|
info@54
|
329 |
return files[path] = (type == 'fonts' ? btoa(fs.readFileSync(fullPath)) : fs.readFileSync(fullPath, 'utf8'))
|
info@54
|
330 |
})
|
info@54
|
331 |
return 'var __' + type + ' = ' + JSON.stringify(files) + '\n'
|
info@54
|
332 |
}
|
info@54
|
333 |
|
info@54
|
334 |
var files = getFiles('js') + getFiles('less') + getFiles('fonts')
|
info@54
|
335 |
fs.writeFileSync('docs-assets/js/raw-files.js', files)
|
info@54
|
336 |
});
|
info@54
|
337 |
};
|