1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | module.exports = function (grunt) {
|
10 | 'use strict'
|
11 |
|
12 |
|
13 | grunt.util.linefeed = '\n'
|
14 |
|
15 | RegExp.quote = function (string) {
|
16 | return string.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&')
|
17 | }
|
18 |
|
19 | var path = require('path')
|
20 | var isTravis = require('is-travis')
|
21 |
|
22 | var configBridge = grunt.file.readJSON('./grunt/configBridge.json', { encoding: 'utf8' })
|
23 |
|
24 | Object.keys(configBridge.paths).forEach(function (key) {
|
25 | configBridge.paths[key].forEach(function (val, i, arr) {
|
26 | arr[i] = path.join('./docs', val)
|
27 | })
|
28 | })
|
29 |
|
30 |
|
31 | grunt.initConfig({
|
32 |
|
33 |
|
34 | pkg: grunt.file.readJSON('package.json'),
|
35 | banner: '/*!\n' +
|
36 | ' * Bootstrap v<%= pkg.version %> (<%= pkg.homepage %>)\n' +
|
37 | ' * Copyright 2011-<%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +
|
38 | ' * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n' +
|
39 | ' */\n',
|
40 | jqueryCheck: 'if (typeof jQuery === \'undefined\') {\n' +
|
41 | ' throw new Error(\'Bootstrap\\\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\\\'s JavaScript.\')\n' +
|
42 | '}\n',
|
43 | jqueryVersionCheck: '+function ($) {\n' +
|
44 | ' var version = $.fn.jquery.split(\' \')[0].split(\'.\')\n' +
|
45 | ' if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] >= 4)) {\n' +
|
46 | ' throw new Error(\'Bootstrap\\\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0\')\n' +
|
47 | ' }\n' +
|
48 | '}(jQuery);\n\n',
|
49 |
|
50 |
|
51 | clean: {
|
52 | dist: 'dist',
|
53 | docs: 'docs/dist'
|
54 | },
|
55 |
|
56 |
|
57 | babel: {
|
58 | dev: {
|
59 | options: {
|
60 | sourceMap: true
|
61 | },
|
62 | files: {
|
63 | 'js/dist/util.js' : 'js/src/util.js',
|
64 | 'js/dist/alert.js' : 'js/src/alert.js',
|
65 | 'js/dist/button.js' : 'js/src/button.js',
|
66 | 'js/dist/carousel.js' : 'js/src/carousel.js',
|
67 | 'js/dist/collapse.js' : 'js/src/collapse.js',
|
68 | 'js/dist/dropdown.js' : 'js/src/dropdown.js',
|
69 | 'js/dist/modal.js' : 'js/src/modal.js',
|
70 | 'js/dist/scrollspy.js' : 'js/src/scrollspy.js',
|
71 | 'js/dist/tab.js' : 'js/src/tab.js',
|
72 | 'js/dist/tooltip.js' : 'js/src/tooltip.js',
|
73 | 'js/dist/popover.js' : 'js/src/popover.js'
|
74 | }
|
75 | },
|
76 | dist: {
|
77 | options: {
|
78 | extends: '../../js/.babelrc'
|
79 | },
|
80 | files: {
|
81 | '<%= concat.bootstrap.dest %>' : '<%= concat.bootstrap.dest %>'
|
82 | }
|
83 | }
|
84 | },
|
85 |
|
86 | stamp: {
|
87 | options: {
|
88 | banner: '<%= banner %>\n<%= jqueryCheck %>\n<%= jqueryVersionCheck %>\n+function () {\n',
|
89 | footer: '\n}();'
|
90 | },
|
91 | bootstrap: {
|
92 | files: {
|
93 | src: '<%= concat.bootstrap.dest %>'
|
94 | }
|
95 | }
|
96 | },
|
97 |
|
98 | concat: {
|
99 | options: {
|
100 |
|
101 | process: function (src) {
|
102 | return src.replace(/^(export|import).*/gm, '')
|
103 | }
|
104 | },
|
105 | bootstrap: {
|
106 | src: [
|
107 | 'js/src/util.js',
|
108 | 'js/src/alert.js',
|
109 | 'js/src/button.js',
|
110 | 'js/src/carousel.js',
|
111 | 'js/src/collapse.js',
|
112 | 'js/src/dropdown.js',
|
113 | 'js/src/modal.js',
|
114 | 'js/src/scrollspy.js',
|
115 | 'js/src/tab.js',
|
116 | 'js/src/tooltip.js',
|
117 | 'js/src/popover.js'
|
118 | ],
|
119 | dest: 'dist/js/<%= pkg.name %>.js'
|
120 | }
|
121 | },
|
122 |
|
123 | qunit: {
|
124 | options: {
|
125 | inject: 'js/tests/unit/phantom.js'
|
126 | },
|
127 | files: 'js/tests/index.html'
|
128 | },
|
129 |
|
130 |
|
131 | copy: {
|
132 | docs: {
|
133 | expand: true,
|
134 | cwd: 'dist/',
|
135 | src: [
|
136 | '**/*'
|
137 | ],
|
138 | dest: 'docs/dist/'
|
139 | }
|
140 | },
|
141 |
|
142 | connect: {
|
143 | server: {
|
144 | options: {
|
145 | port: 3000,
|
146 | base: '.'
|
147 | }
|
148 | }
|
149 | },
|
150 |
|
151 | jekyll: {
|
152 | options: {
|
153 | bundleExec: true,
|
154 | config: '_config.yml',
|
155 | incremental: false
|
156 | },
|
157 | docs: {},
|
158 | github: {
|
159 | options: {
|
160 | raw: 'github: true'
|
161 | }
|
162 | }
|
163 | },
|
164 |
|
165 | htmllint: {
|
166 | options: {
|
167 | ignore: [
|
168 | 'Attribute “autocomplete” is only allowed when the input type is “color”, “date”, “datetime”, “datetime-local”, “email”, “hidden”, “month”, “number”, “password”, “range”, “search”, “tel”, “text”, “time”, “url”, or “week”.',
|
169 | 'Attribute “autocomplete” not allowed on element “button” at this point.',
|
170 | 'Consider using the “h1” element as a top-level heading only (all “h1” elements are treated as top-level headings by many screen readers and other tools).',
|
171 | 'Element “div” not allowed as child of element “progress” in this context. (Suppressing further errors from this subtree.)',
|
172 | 'Element “img” is missing required attribute “src”.',
|
173 | 'The “color” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.',
|
174 | 'The “date” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.',
|
175 | 'The “datetime” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.',
|
176 | 'The “datetime-local” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.',
|
177 | 'The “month” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.',
|
178 | 'The “time” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.',
|
179 | 'The “week” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.'
|
180 | ]
|
181 | },
|
182 | src: ['_gh_pages/**/*.html', 'js/tests/visual/*.html']
|
183 | },
|
184 |
|
185 | watch: {
|
186 | src: {
|
187 | files: '<%= concat.bootstrap.src %>',
|
188 | tasks: ['babel:dev']
|
189 | },
|
190 | sass: {
|
191 | files: 'scss/**/*.scss',
|
192 | tasks: ['dist-css', 'docs']
|
193 | },
|
194 | docs: {
|
195 | files: 'docs/assets/scss/**/*.scss',
|
196 | tasks: ['dist-css', 'docs']
|
197 | }
|
198 | },
|
199 |
|
200 | 'saucelabs-qunit': {
|
201 | all: {
|
202 | options: {
|
203 | build: process.env.TRAVIS_JOB_ID,
|
204 | concurrency: 10,
|
205 | maxRetries: 3,
|
206 | maxPollRetries: 4,
|
207 | urls: ['http://127.0.0.1:3000/js/tests/index.html?hidepassed'],
|
208 | browsers: grunt.file.readYAML('grunt/sauce_browsers.yml')
|
209 | }
|
210 | }
|
211 | },
|
212 |
|
213 | exec: {
|
214 | 'clean-css': {
|
215 | command: 'npm run clean-css'
|
216 | },
|
217 | 'clean-css-docs': {
|
218 | command: 'npm run clean-css-docs'
|
219 | },
|
220 | postcss: {
|
221 | command: 'npm run postcss'
|
222 | },
|
223 | 'postcss-docs': {
|
224 | command: 'npm run postcss-docs'
|
225 | },
|
226 | htmlhint: {
|
227 | command: 'npm run htmlhint'
|
228 | },
|
229 | sass: {
|
230 | command: 'npm run sass'
|
231 | },
|
232 | 'sass-docs': {
|
233 | command: 'npm run sass-docs'
|
234 | },
|
235 | 'scss-lint': {
|
236 | command: 'npm run scss-lint'
|
237 | },
|
238 | 'scss-lint-docs': {
|
239 | command: 'npm run scss-lint-docs'
|
240 | },
|
241 | uglify: {
|
242 | command: 'npm run uglify'
|
243 | },
|
244 | 'uglify-docs': {
|
245 | command: 'npm run uglify-docs'
|
246 | }
|
247 | },
|
248 |
|
249 | buildcontrol: {
|
250 | options: {
|
251 | dir: '_gh_pages',
|
252 | commit: true,
|
253 | push: true,
|
254 | message: 'Built %sourceName% from commit %sourceCommit% on branch %sourceBranch%'
|
255 | },
|
256 | pages: {
|
257 | options: {
|
258 | remote: 'git@github.com:twbs/derpstrap.git',
|
259 | branch: 'gh-pages'
|
260 | }
|
261 | }
|
262 | },
|
263 |
|
264 | compress: {
|
265 | main: {
|
266 | options: {
|
267 | archive: 'bootstrap-<%= pkg.version %>-dist.zip',
|
268 | mode: 'zip',
|
269 | level: 9,
|
270 | pretty: true
|
271 | },
|
272 | files: [
|
273 | {
|
274 | expand: true,
|
275 | cwd: 'dist/',
|
276 | src: ['**'],
|
277 | dest: 'bootstrap-<%= pkg.version %>-dist'
|
278 | }
|
279 | ]
|
280 | }
|
281 | }
|
282 |
|
283 | })
|
284 |
|
285 |
|
286 |
|
287 | require('load-grunt-tasks')(grunt)
|
288 | require('time-grunt')(grunt)
|
289 |
|
290 |
|
291 | grunt.registerTask('validate-html', ['jekyll:docs', 'htmllint', 'exec:htmlhint'])
|
292 |
|
293 | var runSubset = function (subset) {
|
294 | return !process.env.TWBS_TEST || process.env.TWBS_TEST === subset
|
295 | }
|
296 | var isUndefOrNonZero = function (val) {
|
297 | return val === undefined || val !== '0'
|
298 | }
|
299 |
|
300 |
|
301 | var testSubtasks = []
|
302 |
|
303 | if (runSubset('core') &&
|
304 |
|
305 | process.env.TRAVIS_REPO_SLUG !== 'twbs-savage/bootstrap') {
|
306 | testSubtasks = testSubtasks.concat(['dist-css', 'dist-js', 'test-scss', 'qunit', 'docs'])
|
307 | }
|
308 |
|
309 | if (runSubset('validate-html') &&
|
310 | isTravis &&
|
311 |
|
312 | isUndefOrNonZero(process.env.TWBS_DO_VALIDATOR)) {
|
313 | testSubtasks.push('validate-html')
|
314 | }
|
315 |
|
316 | if (typeof process.env.SAUCE_ACCESS_KEY !== 'undefined' &&
|
317 |
|
318 | runSubset('sauce-js-unit')) {
|
319 | testSubtasks = testSubtasks.concat(['dist', 'docs-css', 'docs-js', 'clean:docs', 'copy:docs'])
|
320 |
|
321 | if (isUndefOrNonZero(process.env.TWBS_DO_SAUCE)) {
|
322 | testSubtasks.push('connect')
|
323 | testSubtasks.push('saucelabs-qunit')
|
324 | }
|
325 | }
|
326 | grunt.registerTask('test', testSubtasks)
|
327 |
|
328 |
|
329 | grunt.registerTask('dist-js', ['babel:dev', 'concat', 'babel:dist', 'stamp', 'exec:uglify'])
|
330 |
|
331 | grunt.registerTask('test-scss', ['exec:scss-lint'])
|
332 |
|
333 |
|
334 | grunt.registerTask('sass-compile', ['exec:sass', 'exec:sass-docs'])
|
335 |
|
336 | grunt.registerTask('dist-css', ['sass-compile', 'exec:postcss', 'exec:clean-css', 'exec:clean-css-docs'])
|
337 |
|
338 |
|
339 | grunt.registerTask('dist', ['clean:dist', 'dist-css', 'dist-js'])
|
340 |
|
341 |
|
342 | grunt.registerTask('default', ['clean:dist', 'test'])
|
343 |
|
344 |
|
345 | grunt.registerTask('docs-css', ['exec:clean-css-docs', 'exec:postcss-docs'])
|
346 | grunt.registerTask('lint-docs-css', ['exec:scss-lint-docs'])
|
347 | grunt.registerTask('docs-js', ['exec:uglify-docs'])
|
348 | grunt.registerTask('docs', ['lint-docs-css', 'docs-css', 'docs-js', 'clean:docs', 'copy:docs'])
|
349 | grunt.registerTask('docs-github', ['jekyll:github'])
|
350 |
|
351 | grunt.registerTask('prep-release', ['dist', 'docs', 'docs-github', 'compress'])
|
352 |
|
353 |
|
354 | grunt.registerTask('publish', ['buildcontrol:pages'])
|
355 | }
|