1 | /* jshint node:true */ |
---|
2 | module.exports = function(grunt) { |
---|
3 | var path = require('path'), |
---|
4 | fs = require( 'fs' ), |
---|
5 | SOURCE_DIR = 'src/', |
---|
6 | BUILD_DIR = 'build/', |
---|
7 | autoprefixer = require('autoprefixer'), |
---|
8 | mediaConfig = {}, |
---|
9 | mediaBuilds = ['audiovideo', 'grid', 'models', 'views']; |
---|
10 | |
---|
11 | // Load tasks. |
---|
12 | require('matchdep').filterDev(['grunt-*', '!grunt-legacy-util']).forEach( grunt.loadNpmTasks ); |
---|
13 | // Load legacy utils |
---|
14 | grunt.util = require('grunt-legacy-util'); |
---|
15 | |
---|
16 | mediaBuilds.forEach( function ( build ) { |
---|
17 | var path = SOURCE_DIR + 'wp-includes/js/media'; |
---|
18 | mediaConfig[ build ] = { files : {} }; |
---|
19 | mediaConfig[ build ].files[ path + '-' + build + '.js' ] = [ path + '/' + build + '.manifest.js' ]; |
---|
20 | } ); |
---|
21 | |
---|
22 | // Project configuration. |
---|
23 | grunt.initConfig({ |
---|
24 | postcss: { |
---|
25 | options: { |
---|
26 | processors: [ |
---|
27 | autoprefixer({ |
---|
28 | browsers: [ |
---|
29 | '> 1%', |
---|
30 | 'ie >= 11', |
---|
31 | 'last 1 Android versions', |
---|
32 | 'last 1 ChromeAndroid versions', |
---|
33 | 'last 2 Chrome versions', |
---|
34 | 'last 2 Firefox versions', |
---|
35 | 'last 2 Safari versions', |
---|
36 | 'last 2 iOS versions', |
---|
37 | 'last 2 Edge versions', |
---|
38 | 'last 2 Opera versions' |
---|
39 | ], |
---|
40 | cascade: false |
---|
41 | }) |
---|
42 | ] |
---|
43 | }, |
---|
44 | core: { |
---|
45 | expand: true, |
---|
46 | cwd: SOURCE_DIR, |
---|
47 | dest: SOURCE_DIR, |
---|
48 | src: [ |
---|
49 | 'wp-admin/css/*.css', |
---|
50 | 'wp-includes/css/*.css' |
---|
51 | ] |
---|
52 | }, |
---|
53 | colors: { |
---|
54 | expand: true, |
---|
55 | cwd: BUILD_DIR, |
---|
56 | dest: BUILD_DIR, |
---|
57 | src: [ |
---|
58 | 'wp-admin/css/colors/*/colors.css' |
---|
59 | ] |
---|
60 | } |
---|
61 | }, |
---|
62 | clean: { |
---|
63 | all: [BUILD_DIR], |
---|
64 | dynamic: { |
---|
65 | dot: true, |
---|
66 | expand: true, |
---|
67 | cwd: BUILD_DIR, |
---|
68 | src: [] |
---|
69 | }, |
---|
70 | tinymce: ['<%= concat.tinymce.dest %>'], |
---|
71 | qunit: ['tests/qunit/compiled.html'] |
---|
72 | }, |
---|
73 | copy: { |
---|
74 | files: { |
---|
75 | files: [ |
---|
76 | { |
---|
77 | dot: true, |
---|
78 | expand: true, |
---|
79 | cwd: SOURCE_DIR, |
---|
80 | src: [ |
---|
81 | '**', |
---|
82 | '!wp-includes/js/media/**', |
---|
83 | '!**/.{svn,git}/**', // Ignore version control directories. |
---|
84 | // Ignore unminified versions of external libs we don't ship: |
---|
85 | '!wp-includes/js/backbone.js', |
---|
86 | '!wp-includes/js/underscore.js', |
---|
87 | '!wp-includes/js/jquery/jquery.masonry.js', |
---|
88 | '!wp-includes/js/jquery/ui/*.js', |
---|
89 | '!wp-includes/js/tinymce/tinymce.js', |
---|
90 | '!wp-includes/version.php' // Exclude version.php |
---|
91 | ], |
---|
92 | dest: BUILD_DIR |
---|
93 | }, |
---|
94 | { |
---|
95 | src: 'wp-config-sample.php', |
---|
96 | dest: BUILD_DIR |
---|
97 | } |
---|
98 | ] |
---|
99 | }, |
---|
100 | 'wp-admin-css-compat-rtl': { |
---|
101 | options: { |
---|
102 | processContent: function( src ) { |
---|
103 | return src.replace( /\.css/g, '-rtl.css' ); |
---|
104 | } |
---|
105 | }, |
---|
106 | src: SOURCE_DIR + 'wp-admin/css/wp-admin.css', |
---|
107 | dest: BUILD_DIR + 'wp-admin/css/wp-admin-rtl.css' |
---|
108 | }, |
---|
109 | 'wp-admin-css-compat-min': { |
---|
110 | options: { |
---|
111 | processContent: function( src ) { |
---|
112 | return src.replace( /\.css/g, '.min.css' ); |
---|
113 | } |
---|
114 | }, |
---|
115 | files: [ |
---|
116 | { |
---|
117 | src: SOURCE_DIR + 'wp-admin/css/wp-admin.css', |
---|
118 | dest: BUILD_DIR + 'wp-admin/css/wp-admin.min.css' |
---|
119 | }, |
---|
120 | { |
---|
121 | src: BUILD_DIR + 'wp-admin/css/wp-admin-rtl.css', |
---|
122 | dest: BUILD_DIR + 'wp-admin/css/wp-admin-rtl.min.css' |
---|
123 | } |
---|
124 | ] |
---|
125 | }, |
---|
126 | version: { |
---|
127 | options: { |
---|
128 | processContent: function( src ) { |
---|
129 | return src.replace( /^\$wp_version = '(.+?)';/m, function( str, version ) { |
---|
130 | version = version.replace( /-src$/, '' ); |
---|
131 | |
---|
132 | // If the version includes an SVN commit (-12345), it's not a released alpha/beta. Append a timestamp. |
---|
133 | version = version.replace( /-[\d]{5}$/, '-' + grunt.template.today( 'yyyymmdd.HHMMss' ) ); |
---|
134 | |
---|
135 | /* jshint quotmark: true */ |
---|
136 | return "$wp_version = '" + version + "';"; |
---|
137 | }); |
---|
138 | } |
---|
139 | }, |
---|
140 | src: SOURCE_DIR + 'wp-includes/version.php', |
---|
141 | dest: BUILD_DIR + 'wp-includes/version.php' |
---|
142 | }, |
---|
143 | dynamic: { |
---|
144 | dot: true, |
---|
145 | expand: true, |
---|
146 | cwd: SOURCE_DIR, |
---|
147 | dest: BUILD_DIR, |
---|
148 | src: [] |
---|
149 | }, |
---|
150 | qunit: { |
---|
151 | src: 'tests/qunit/index.html', |
---|
152 | dest: 'tests/qunit/compiled.html', |
---|
153 | options: { |
---|
154 | processContent: function( src ) { |
---|
155 | return src.replace( /(\".+?\/)src(\/.+?)(?:.min)?(.js\")/g , function( match, $1, $2, $3 ) { |
---|
156 | // Don't add `.min` to files that don't have it. |
---|
157 | return $1 + 'build' + $2 + ( /jquery$/.test( $2 ) ? '' : '.min' ) + $3; |
---|
158 | } ); |
---|
159 | } |
---|
160 | } |
---|
161 | } |
---|
162 | }, |
---|
163 | browserify: mediaConfig, |
---|
164 | sass: { |
---|
165 | colors: { |
---|
166 | expand: true, |
---|
167 | cwd: SOURCE_DIR, |
---|
168 | dest: BUILD_DIR, |
---|
169 | ext: '.css', |
---|
170 | src: ['wp-admin/css/colors/*/colors.scss'], |
---|
171 | options: { |
---|
172 | outputStyle: 'expanded' |
---|
173 | } |
---|
174 | } |
---|
175 | }, |
---|
176 | cssmin: { |
---|
177 | options: { |
---|
178 | compatibility: 'ie7' |
---|
179 | }, |
---|
180 | core: { |
---|
181 | expand: true, |
---|
182 | cwd: SOURCE_DIR, |
---|
183 | dest: BUILD_DIR, |
---|
184 | ext: '.min.css', |
---|
185 | src: [ |
---|
186 | 'wp-admin/css/*.css', |
---|
187 | '!wp-admin/css/wp-admin*.css', |
---|
188 | 'wp-includes/css/*.css', |
---|
189 | 'wp-includes/js/mediaelement/wp-mediaelement.css' |
---|
190 | ] |
---|
191 | }, |
---|
192 | rtl: { |
---|
193 | expand: true, |
---|
194 | cwd: BUILD_DIR, |
---|
195 | dest: BUILD_DIR, |
---|
196 | ext: '.min.css', |
---|
197 | src: [ |
---|
198 | 'wp-admin/css/*-rtl.css', |
---|
199 | '!wp-admin/css/wp-admin*.css', |
---|
200 | 'wp-includes/css/*-rtl.css' |
---|
201 | ] |
---|
202 | }, |
---|
203 | colors: { |
---|
204 | expand: true, |
---|
205 | cwd: BUILD_DIR, |
---|
206 | dest: BUILD_DIR, |
---|
207 | ext: '.min.css', |
---|
208 | src: [ |
---|
209 | 'wp-admin/css/colors/*/*.css' |
---|
210 | ] |
---|
211 | } |
---|
212 | }, |
---|
213 | rtlcss: { |
---|
214 | options: { |
---|
215 | // rtlcss options |
---|
216 | opts: { |
---|
217 | clean: false, |
---|
218 | processUrls: { atrule: true, decl: false }, |
---|
219 | stringMap: [ |
---|
220 | { |
---|
221 | name: 'import-rtl-stylesheet', |
---|
222 | priority: 10, |
---|
223 | exclusive: true, |
---|
224 | search: [ '.css' ], |
---|
225 | replace: [ '-rtl.css' ], |
---|
226 | options: { |
---|
227 | scope: 'url', |
---|
228 | ignoreCase: false |
---|
229 | } |
---|
230 | } |
---|
231 | ] |
---|
232 | }, |
---|
233 | saveUnmodified: false, |
---|
234 | plugins: [ |
---|
235 | { |
---|
236 | name: 'swap-dashicons-left-right-arrows', |
---|
237 | priority: 10, |
---|
238 | directives: { |
---|
239 | control: {}, |
---|
240 | value: [] |
---|
241 | }, |
---|
242 | processors: [ |
---|
243 | { |
---|
244 | expr: /content/im, |
---|
245 | action: function( prop, value ) { |
---|
246 | if ( value === '"\\f141"' ) { // dashicons-arrow-left |
---|
247 | value = '"\\f139"'; |
---|
248 | } else if ( value === '"\\f340"' ) { // dashicons-arrow-left-alt |
---|
249 | value = '"\\f344"'; |
---|
250 | } else if ( value === '"\\f341"' ) { // dashicons-arrow-left-alt2 |
---|
251 | value = '"\\f345"'; |
---|
252 | } else if ( value === '"\\f139"' ) { // dashicons-arrow-right |
---|
253 | value = '"\\f141"'; |
---|
254 | } else if ( value === '"\\f344"' ) { // dashicons-arrow-right-alt |
---|
255 | value = '"\\f340"'; |
---|
256 | } else if ( value === '"\\f345"' ) { // dashicons-arrow-right-alt2 |
---|
257 | value = '"\\f341"'; |
---|
258 | } |
---|
259 | return { prop: prop, value: value }; |
---|
260 | } |
---|
261 | } |
---|
262 | ] |
---|
263 | } |
---|
264 | ] |
---|
265 | }, |
---|
266 | core: { |
---|
267 | expand: true, |
---|
268 | cwd: SOURCE_DIR, |
---|
269 | dest: BUILD_DIR, |
---|
270 | ext: '-rtl.css', |
---|
271 | src: [ |
---|
272 | 'wp-admin/css/*.css', |
---|
273 | 'wp-includes/css/*.css', |
---|
274 | |
---|
275 | // Exceptions |
---|
276 | '!wp-includes/css/dashicons.css', |
---|
277 | '!wp-includes/css/wp-embed-template.css', |
---|
278 | '!wp-includes/css/wp-embed-template-ie.css' |
---|
279 | ] |
---|
280 | }, |
---|
281 | colors: { |
---|
282 | expand: true, |
---|
283 | cwd: BUILD_DIR, |
---|
284 | dest: BUILD_DIR, |
---|
285 | ext: '-rtl.css', |
---|
286 | src: [ |
---|
287 | 'wp-admin/css/colors/*/colors.css' |
---|
288 | ] |
---|
289 | }, |
---|
290 | dynamic: { |
---|
291 | expand: true, |
---|
292 | cwd: SOURCE_DIR, |
---|
293 | dest: BUILD_DIR, |
---|
294 | ext: '-rtl.css', |
---|
295 | src: [] |
---|
296 | } |
---|
297 | }, |
---|
298 | jshint: { |
---|
299 | options: grunt.file.readJSON('.jshintrc'), |
---|
300 | grunt: { |
---|
301 | src: ['Gruntfile.js'] |
---|
302 | }, |
---|
303 | tests: { |
---|
304 | src: [ |
---|
305 | 'tests/qunit/**/*.js', |
---|
306 | '!tests/qunit/vendor/*', |
---|
307 | '!tests/qunit/editor/**' |
---|
308 | ], |
---|
309 | options: grunt.file.readJSON('tests/qunit/.jshintrc') |
---|
310 | }, |
---|
311 | themes: { |
---|
312 | expand: true, |
---|
313 | cwd: SOURCE_DIR + 'wp-content/themes', |
---|
314 | src: [ |
---|
315 | 'twenty*/**/*.js', |
---|
316 | '!twenty{eleven,twelve,thirteen}/**', |
---|
317 | // Third party scripts |
---|
318 | '!twenty{fourteen,fifteen,sixteen}/js/html5.js', |
---|
319 | '!twentyseventeen/assets/js/html5.js', |
---|
320 | '!twentyseventeen/assets/js/jquery.scrollTo.js' |
---|
321 | ] |
---|
322 | }, |
---|
323 | media: { |
---|
324 | options: { |
---|
325 | browserify: true |
---|
326 | }, |
---|
327 | src: [ |
---|
328 | SOURCE_DIR + 'wp-includes/js/media/**/*.js' |
---|
329 | ] |
---|
330 | }, |
---|
331 | core: { |
---|
332 | expand: true, |
---|
333 | cwd: SOURCE_DIR, |
---|
334 | src: [ |
---|
335 | 'wp-admin/js/**/*.js', |
---|
336 | 'wp-includes/js/*.js', |
---|
337 | // Built scripts. |
---|
338 | '!wp-includes/js/media-*', |
---|
339 | // WordPress scripts inside directories |
---|
340 | 'wp-includes/js/jquery/jquery.table-hotkeys.js', |
---|
341 | 'wp-includes/js/mediaelement/wp-mediaelement.js', |
---|
342 | 'wp-includes/js/mediaelement/wp-playlist.js', |
---|
343 | 'wp-includes/js/plupload/handlers.js', |
---|
344 | 'wp-includes/js/plupload/wp-plupload.js', |
---|
345 | 'wp-includes/js/tinymce/plugins/wordpress/plugin.js', |
---|
346 | 'wp-includes/js/tinymce/plugins/wp*/plugin.js', |
---|
347 | // Third party scripts |
---|
348 | '!wp-admin/js/farbtastic.js', |
---|
349 | '!wp-includes/js/backbone*.js', |
---|
350 | '!wp-includes/js/swfobject.js', |
---|
351 | '!wp-includes/js/underscore*.js', |
---|
352 | '!wp-includes/js/colorpicker.js', |
---|
353 | '!wp-includes/js/hoverIntent.js', |
---|
354 | '!wp-includes/js/json2.js', |
---|
355 | '!wp-includes/js/tw-sack.js', |
---|
356 | '!wp-includes/js/twemoji.js', |
---|
357 | '!**/*.min.js' |
---|
358 | ], |
---|
359 | // Remove once other JSHint errors are resolved |
---|
360 | options: { |
---|
361 | curly: false, |
---|
362 | eqeqeq: false |
---|
363 | }, |
---|
364 | // Limit JSHint's run to a single specified file: |
---|
365 | // |
---|
366 | // grunt jshint:core --file=filename.js |
---|
367 | // |
---|
368 | // Optionally, include the file path: |
---|
369 | // |
---|
370 | // grunt jshint:core --file=path/to/filename.js |
---|
371 | // |
---|
372 | filter: function( filepath ) { |
---|
373 | var index, file = grunt.option( 'file' ); |
---|
374 | |
---|
375 | // Don't filter when no target file is specified |
---|
376 | if ( ! file ) { |
---|
377 | return true; |
---|
378 | } |
---|
379 | |
---|
380 | // Normalize filepath for Windows |
---|
381 | filepath = filepath.replace( /\\/g, '/' ); |
---|
382 | index = filepath.lastIndexOf( '/' + file ); |
---|
383 | |
---|
384 | // Match only the filename passed from cli |
---|
385 | if ( filepath === file || ( -1 !== index && index === filepath.length - ( file.length + 1 ) ) ) { |
---|
386 | return true; |
---|
387 | } |
---|
388 | |
---|
389 | return false; |
---|
390 | } |
---|
391 | }, |
---|
392 | plugins: { |
---|
393 | expand: true, |
---|
394 | cwd: SOURCE_DIR + 'wp-content/plugins', |
---|
395 | src: [ |
---|
396 | '**/*.js', |
---|
397 | '!**/*.min.js' |
---|
398 | ], |
---|
399 | // Limit JSHint's run to a single specified plugin directory: |
---|
400 | // |
---|
401 | // grunt jshint:plugins --dir=foldername |
---|
402 | // |
---|
403 | filter: function( dirpath ) { |
---|
404 | var index, dir = grunt.option( 'dir' ); |
---|
405 | |
---|
406 | // Don't filter when no target folder is specified |
---|
407 | if ( ! dir ) { |
---|
408 | return true; |
---|
409 | } |
---|
410 | |
---|
411 | dirpath = dirpath.replace( /\\/g, '/' ); |
---|
412 | index = dirpath.lastIndexOf( '/' + dir ); |
---|
413 | |
---|
414 | // Match only the folder name passed from cli |
---|
415 | if ( -1 !== index ) { |
---|
416 | return true; |
---|
417 | } |
---|
418 | |
---|
419 | return false; |
---|
420 | } |
---|
421 | } |
---|
422 | }, |
---|
423 | qunit: { |
---|
424 | files: [ |
---|
425 | 'tests/qunit/**/*.html', |
---|
426 | '!tests/qunit/editor/**' |
---|
427 | ] |
---|
428 | }, |
---|
429 | phpunit: { |
---|
430 | 'default': { |
---|
431 | cmd: 'phpunit', |
---|
432 | args: ['--verbose', '-c', 'phpunit.xml.dist'] |
---|
433 | }, |
---|
434 | ajax: { |
---|
435 | cmd: 'phpunit', |
---|
436 | args: ['--verbose', '-c', 'phpunit.xml.dist', '--group', 'ajax'] |
---|
437 | }, |
---|
438 | multisite: { |
---|
439 | cmd: 'phpunit', |
---|
440 | args: ['--verbose', '-c', 'tests/phpunit/multisite.xml'] |
---|
441 | }, |
---|
442 | 'external-http': { |
---|
443 | cmd: 'phpunit', |
---|
444 | args: ['--verbose', '-c', 'phpunit.xml.dist', '--group', 'external-http'] |
---|
445 | }, |
---|
446 | 'restapi-jsclient': { |
---|
447 | cmd: 'phpunit', |
---|
448 | args: ['--verbose', '-c', 'phpunit.xml.dist', '--group', 'restapi-jsclient'] |
---|
449 | } |
---|
450 | }, |
---|
451 | uglify: { |
---|
452 | options: { |
---|
453 | ASCIIOnly: true, |
---|
454 | screwIE8: false |
---|
455 | }, |
---|
456 | core: { |
---|
457 | expand: true, |
---|
458 | cwd: SOURCE_DIR, |
---|
459 | dest: BUILD_DIR, |
---|
460 | ext: '.min.js', |
---|
461 | src: [ |
---|
462 | 'wp-admin/js/**/*.js', |
---|
463 | 'wp-includes/js/*.js', |
---|
464 | 'wp-includes/js/mediaelement/wp-mediaelement.js', |
---|
465 | 'wp-includes/js/mediaelement/wp-playlist.js', |
---|
466 | 'wp-includes/js/plupload/handlers.js', |
---|
467 | 'wp-includes/js/plupload/wp-plupload.js', |
---|
468 | 'wp-includes/js/tinymce/plugins/wordpress/plugin.js', |
---|
469 | 'wp-includes/js/tinymce/plugins/wp*/plugin.js', |
---|
470 | |
---|
471 | // Exceptions |
---|
472 | '!wp-admin/js/bookmarklet.*', // Minified and updated in /src with the precommit task. See uglify:bookmarklet. |
---|
473 | '!wp-admin/js/custom-header.js', // Why? We should minify this. |
---|
474 | '!wp-admin/js/farbtastic.js', |
---|
475 | '!wp-admin/js/iris.min.js', |
---|
476 | '!wp-includes/js/backbone.*', |
---|
477 | '!wp-includes/js/masonry.min.js', |
---|
478 | '!wp-includes/js/swfobject.js', |
---|
479 | '!wp-includes/js/underscore.*', |
---|
480 | '!wp-includes/js/zxcvbn.min.js', |
---|
481 | '!wp-includes/js/wp-embed.js' // We have extra options for this, see uglify:embed |
---|
482 | ] |
---|
483 | }, |
---|
484 | embed: { |
---|
485 | options: { |
---|
486 | compress: { |
---|
487 | conditionals: false |
---|
488 | } |
---|
489 | }, |
---|
490 | expand: true, |
---|
491 | cwd: SOURCE_DIR, |
---|
492 | dest: BUILD_DIR, |
---|
493 | ext: '.min.js', |
---|
494 | src: ['wp-includes/js/wp-embed.js'] |
---|
495 | }, |
---|
496 | media: { |
---|
497 | expand: true, |
---|
498 | cwd: SOURCE_DIR, |
---|
499 | dest: BUILD_DIR, |
---|
500 | ext: '.min.js', |
---|
501 | src: [ |
---|
502 | 'wp-includes/js/media-audiovideo.js', |
---|
503 | 'wp-includes/js/media-grid.js', |
---|
504 | 'wp-includes/js/media-models.js', |
---|
505 | 'wp-includes/js/media-views.js' |
---|
506 | ] |
---|
507 | }, |
---|
508 | jqueryui: { |
---|
509 | options: { |
---|
510 | // Preserve comments that start with a bang. |
---|
511 | preserveComments: /^!/ |
---|
512 | }, |
---|
513 | expand: true, |
---|
514 | cwd: SOURCE_DIR, |
---|
515 | dest: BUILD_DIR, |
---|
516 | ext: '.min.js', |
---|
517 | src: ['wp-includes/js/jquery/ui/*.js'] |
---|
518 | }, |
---|
519 | bookmarklet: { |
---|
520 | options: { |
---|
521 | compress: { |
---|
522 | negate_iife: false |
---|
523 | } |
---|
524 | }, |
---|
525 | src: SOURCE_DIR + 'wp-admin/js/bookmarklet.js', |
---|
526 | dest: SOURCE_DIR + 'wp-admin/js/bookmarklet.min.js' |
---|
527 | }, |
---|
528 | masonry: { |
---|
529 | options: { |
---|
530 | // Preserve comments that start with a bang. |
---|
531 | preserveComments: /^!/ |
---|
532 | }, |
---|
533 | src: SOURCE_DIR + 'wp-includes/js/jquery/jquery.masonry.js', |
---|
534 | dest: SOURCE_DIR + 'wp-includes/js/jquery/jquery.masonry.min.js' |
---|
535 | } |
---|
536 | }, |
---|
537 | |
---|
538 | concat: { |
---|
539 | tinymce: { |
---|
540 | options: { |
---|
541 | separator: '\n', |
---|
542 | process: function( src, filepath ) { |
---|
543 | return '// Source: ' + filepath.replace( BUILD_DIR, '' ) + '\n' + src; |
---|
544 | } |
---|
545 | }, |
---|
546 | src: [ |
---|
547 | BUILD_DIR + 'wp-includes/js/tinymce/tinymce.min.js', |
---|
548 | BUILD_DIR + 'wp-includes/js/tinymce/themes/modern/theme.min.js', |
---|
549 | BUILD_DIR + 'wp-includes/js/tinymce/plugins/*/plugin.min.js' |
---|
550 | ], |
---|
551 | dest: BUILD_DIR + 'wp-includes/js/tinymce/wp-tinymce.js' |
---|
552 | }, |
---|
553 | emoji: { |
---|
554 | options: { |
---|
555 | separator: '\n', |
---|
556 | process: function( src, filepath ) { |
---|
557 | return '// Source: ' + filepath.replace( BUILD_DIR, '' ) + '\n' + src; |
---|
558 | } |
---|
559 | }, |
---|
560 | src: [ |
---|
561 | BUILD_DIR + 'wp-includes/js/twemoji.min.js', |
---|
562 | BUILD_DIR + 'wp-includes/js/wp-emoji.min.js' |
---|
563 | ], |
---|
564 | dest: BUILD_DIR + 'wp-includes/js/wp-emoji-release.min.js' |
---|
565 | } |
---|
566 | }, |
---|
567 | compress: { |
---|
568 | tinymce: { |
---|
569 | options: { |
---|
570 | mode: 'gzip', |
---|
571 | level: 9 |
---|
572 | }, |
---|
573 | src: '<%= concat.tinymce.dest %>', |
---|
574 | dest: BUILD_DIR + 'wp-includes/js/tinymce/wp-tinymce.js.gz' |
---|
575 | } |
---|
576 | }, |
---|
577 | jsvalidate:{ |
---|
578 | options: { |
---|
579 | globals: {}, |
---|
580 | esprimaOptions:{}, |
---|
581 | verbose: false |
---|
582 | }, |
---|
583 | build: { |
---|
584 | files: { |
---|
585 | src: [ |
---|
586 | BUILD_DIR + 'wp-{admin,includes}/**/*.js', |
---|
587 | BUILD_DIR + 'wp-content/themes/twenty*/**/*.js' |
---|
588 | ] |
---|
589 | } |
---|
590 | } |
---|
591 | }, |
---|
592 | imagemin: { |
---|
593 | core: { |
---|
594 | expand: true, |
---|
595 | cwd: SOURCE_DIR, |
---|
596 | src: [ |
---|
597 | 'wp-{admin,includes}/images/**/*.{png,jpg,gif,jpeg}', |
---|
598 | 'wp-includes/js/tinymce/skins/wordpress/images/*.{png,jpg,gif,jpeg}' |
---|
599 | ], |
---|
600 | dest: SOURCE_DIR |
---|
601 | } |
---|
602 | }, |
---|
603 | includes: { |
---|
604 | emoji: { |
---|
605 | src: BUILD_DIR + 'wp-includes/formatting.php', |
---|
606 | dest: '.' |
---|
607 | }, |
---|
608 | embed: { |
---|
609 | src: BUILD_DIR + 'wp-includes/embed.php', |
---|
610 | dest: '.' |
---|
611 | } |
---|
612 | }, |
---|
613 | replace: { |
---|
614 | emojiRegex: { |
---|
615 | options: { |
---|
616 | patterns: [ |
---|
617 | { |
---|
618 | match: /\/\/ START: emoji regex[\S\s]*\/\/ END: emoji regex/g, |
---|
619 | replacement: function () { |
---|
620 | var twemoji = grunt.file.read( SOURCE_DIR + 'wp-includes/js/twemoji.js' ), |
---|
621 | found = twemoji.match( /re = \/(.*)\/g,/ ), |
---|
622 | emojiRegex = found[1], |
---|
623 | regex = '', |
---|
624 | entities = ''; |
---|
625 | |
---|
626 | /* |
---|
627 | * Twemoji does some nifty regex optimisations, splitting up surrogate pairs unit, searching by |
---|
628 | * ranges of individual units, and compressing sets of individual units. This is super useful for |
---|
629 | * reducing the size of the regex. |
---|
630 | * |
---|
631 | * Unfortunately, PCRE doesn't allow regexes to search for individual units, so we can't just |
---|
632 | * blindly copy the Twemoji regex. |
---|
633 | * |
---|
634 | * The good news is, we don't have to worry about size restrictions, so we can just unravel the |
---|
635 | * entire regex, and convert it to a PCRE-friendly format. |
---|
636 | */ |
---|
637 | |
---|
638 | // Convert ranges: "\udc68-\udc6a" becomes "\udc68\udc69\udc6a". |
---|
639 | emojiRegex = emojiRegex.replace( /(\\u\w{4})\-(\\u\w{4})/g, function ( match, first, last ) { |
---|
640 | var start = parseInt( first.substr( 2 ), 16 ); |
---|
641 | var end = parseInt( last.substr( 2 ), 16 ); |
---|
642 | |
---|
643 | var replace = ''; |
---|
644 | |
---|
645 | for( var counter = start; counter <= end; counter++ ) { |
---|
646 | replace += '\\u' + counter.toString( 16 ); |
---|
647 | } |
---|
648 | |
---|
649 | return replace; |
---|
650 | } ); |
---|
651 | |
---|
652 | // Convert sets: "\u200d[\u2640\u2642]\ufe0f" becomes "\u200d\u2640\ufe0f|\u200d\u2642\ufe0f". |
---|
653 | emojiRegex = emojiRegex.replace( /((?:\\u\w{4})*)\[((?:\\u\w{4})+)\]((?:\\u\w{4})*)/g, function ( match, before, middle, after ) { |
---|
654 | //return params[1].split( '\\u' ).join( '|' + params[0] + '\\u' ).substr( 1 ); |
---|
655 | if ( ! before && ! after ) { |
---|
656 | return match; |
---|
657 | } |
---|
658 | var set = middle.match( /.{1,6}/g ); |
---|
659 | |
---|
660 | return before + set.join( after + '|' + before ) + after; |
---|
661 | } ); |
---|
662 | |
---|
663 | // Convert surrogate pairs to their equivalent unicode scalar: "\ud83d\udc68" becomes "\u1f468". |
---|
664 | emojiRegex = emojiRegex.replace( /(\\ud[89a-f][0-9a-f]{2})(\\ud[89a-f][0-9a-f]{2})/g, function ( match, first, second ) { |
---|
665 | var high = parseInt( first.substr( 2 ), 16 ); |
---|
666 | var low = parseInt( second.substr( 2 ), 16 ); |
---|
667 | |
---|
668 | var scalar = ( ( high - 0xD800 ) * 0x400 ) + ( low - 0xDC00 ) + 0x10000; |
---|
669 | |
---|
670 | return '\\u' + scalar.toString( 16 ); |
---|
671 | } ); |
---|
672 | |
---|
673 | // Convert JavaScript-style code points to PHP-style: "\u1f468" becomes "\x{1f468}". |
---|
674 | emojiRegex = emojiRegex.replace( /\\u(\w+)/g, '\\x{$1}' ); |
---|
675 | |
---|
676 | // Convert PHP-style code points to HTML entities: "\x{1f468}" becomes "👨". |
---|
677 | entities = emojiRegex.replace( /\\x{(\w+)}/g, '&#x$1;' ); |
---|
678 | entities = entities.replace( /\[([^\]]+)\]/g, function( match, codepoint ) { |
---|
679 | return '(?:' + codepoint.replace( /;&/g, ';|&' ) + ')'; |
---|
680 | } ); |
---|
681 | |
---|
682 | regex += '// START: emoji regex\n'; |
---|
683 | regex += '\t$codepoints = \'/(' + emojiRegex + ')/u\';\n'; |
---|
684 | regex += '\t$entities = \'/(' + entities + ')/u\';\n'; |
---|
685 | regex += '\t// END: emoji regex'; |
---|
686 | |
---|
687 | return regex; |
---|
688 | } |
---|
689 | } |
---|
690 | ] |
---|
691 | }, |
---|
692 | files: [ |
---|
693 | { |
---|
694 | expand: true, |
---|
695 | flatten: true, |
---|
696 | src: [ |
---|
697 | SOURCE_DIR + 'wp-includes/formatting.php' |
---|
698 | ], |
---|
699 | dest: SOURCE_DIR + 'wp-includes/' |
---|
700 | } |
---|
701 | ] |
---|
702 | } |
---|
703 | }, |
---|
704 | _watch: { |
---|
705 | all: { |
---|
706 | files: [ |
---|
707 | SOURCE_DIR + '**', |
---|
708 | '!' + SOURCE_DIR + 'wp-includes/js/media/**', |
---|
709 | // Ignore version control directories. |
---|
710 | '!' + SOURCE_DIR + '**/.{svn,git}/**' |
---|
711 | ], |
---|
712 | tasks: ['clean:dynamic', 'copy:dynamic'], |
---|
713 | options: { |
---|
714 | dot: true, |
---|
715 | spawn: false, |
---|
716 | interval: 2000 |
---|
717 | } |
---|
718 | }, |
---|
719 | config: { |
---|
720 | files: 'Gruntfile.js' |
---|
721 | }, |
---|
722 | colors: { |
---|
723 | files: [SOURCE_DIR + 'wp-admin/css/colors/**'], |
---|
724 | tasks: ['sass:colors'] |
---|
725 | }, |
---|
726 | rtl: { |
---|
727 | files: [ |
---|
728 | SOURCE_DIR + 'wp-admin/css/*.css', |
---|
729 | SOURCE_DIR + 'wp-includes/css/*.css' |
---|
730 | ], |
---|
731 | tasks: ['rtlcss:dynamic'], |
---|
732 | options: { |
---|
733 | spawn: false, |
---|
734 | interval: 2000 |
---|
735 | } |
---|
736 | }, |
---|
737 | test: { |
---|
738 | files: [ |
---|
739 | 'tests/qunit/**', |
---|
740 | '!tests/qunit/editor/**' |
---|
741 | ], |
---|
742 | tasks: ['qunit'] |
---|
743 | } |
---|
744 | } |
---|
745 | }); |
---|
746 | |
---|
747 | // Allow builds to be minimal |
---|
748 | if( grunt.option( 'minimal-copy' ) ) { |
---|
749 | var copyFilesOptions = grunt.config.get( 'copy.files.files' ); |
---|
750 | copyFilesOptions[0].src.push( '!wp-content/plugins/**' ); |
---|
751 | copyFilesOptions[0].src.push( '!wp-content/themes/!(twenty*)/**' ); |
---|
752 | grunt.config.set( 'copy.files.files', copyFilesOptions ); |
---|
753 | } |
---|
754 | |
---|
755 | |
---|
756 | // Register tasks. |
---|
757 | |
---|
758 | // RTL task. |
---|
759 | grunt.registerTask('rtl', ['rtlcss:core', 'rtlcss:colors']); |
---|
760 | |
---|
761 | // Color schemes task. |
---|
762 | grunt.registerTask('colors', ['sass:colors', 'postcss:colors']); |
---|
763 | |
---|
764 | // JSHint task. |
---|
765 | grunt.registerTask( 'jshint:corejs', [ |
---|
766 | 'jshint:grunt', |
---|
767 | 'jshint:tests', |
---|
768 | 'jshint:themes', |
---|
769 | 'jshint:core', |
---|
770 | 'jshint:media' |
---|
771 | ] ); |
---|
772 | |
---|
773 | grunt.registerTask( 'restapi-jsclient', [ |
---|
774 | 'phpunit:restapi-jsclient', |
---|
775 | 'qunit:compiled' |
---|
776 | ] ); |
---|
777 | |
---|
778 | grunt.renameTask( 'watch', '_watch' ); |
---|
779 | |
---|
780 | grunt.registerTask( 'watch', function() { |
---|
781 | if ( ! this.args.length || this.args.indexOf( 'browserify' ) > -1 ) { |
---|
782 | grunt.config( 'browserify.options', { |
---|
783 | browserifyOptions: { |
---|
784 | debug: true |
---|
785 | }, |
---|
786 | watch: true |
---|
787 | } ); |
---|
788 | |
---|
789 | grunt.task.run( 'browserify' ); |
---|
790 | } |
---|
791 | |
---|
792 | grunt.task.run( '_' + this.nameArgs ); |
---|
793 | } ); |
---|
794 | |
---|
795 | grunt.registerTask( 'precommit:image', [ |
---|
796 | 'imagemin:core' |
---|
797 | ] ); |
---|
798 | |
---|
799 | grunt.registerTask( 'precommit:js', [ |
---|
800 | 'browserify', |
---|
801 | 'jshint:corejs', |
---|
802 | 'uglify:bookmarklet', |
---|
803 | 'uglify:masonry', |
---|
804 | 'qunit:compiled' |
---|
805 | ] ); |
---|
806 | |
---|
807 | grunt.registerTask( 'precommit:css', [ |
---|
808 | 'postcss:core' |
---|
809 | ] ); |
---|
810 | |
---|
811 | grunt.registerTask( 'precommit:php', [ |
---|
812 | 'phpunit' |
---|
813 | ] ); |
---|
814 | |
---|
815 | grunt.registerTask( 'precommit:emoji', [ |
---|
816 | 'replace:emojiRegex' |
---|
817 | ] ); |
---|
818 | |
---|
819 | grunt.registerTask( 'precommit', 'Runs test and build tasks in preparation for a commit', function() { |
---|
820 | var done = this.async(); |
---|
821 | var map = { |
---|
822 | svn: 'svn status --ignore-externals', |
---|
823 | git: 'git status --short' |
---|
824 | }; |
---|
825 | |
---|
826 | find( [ |
---|
827 | __dirname + '/.svn', |
---|
828 | __dirname + '/.git', |
---|
829 | path.dirname( __dirname ) + '/.svn' |
---|
830 | ] ); |
---|
831 | |
---|
832 | function find( set ) { |
---|
833 | var dir; |
---|
834 | |
---|
835 | if ( set.length ) { |
---|
836 | fs.stat( dir = set.shift(), function( error ) { |
---|
837 | error ? find( set ) : run( path.basename( dir ).substr( 1 ) ); |
---|
838 | } ); |
---|
839 | } else { |
---|
840 | grunt.fatal( 'This WordPress install is not under version control.' ); |
---|
841 | } |
---|
842 | } |
---|
843 | |
---|
844 | function run( type ) { |
---|
845 | var command = map[ type ].split( ' ' ); |
---|
846 | |
---|
847 | grunt.util.spawn( { |
---|
848 | cmd: command.shift(), |
---|
849 | args: command |
---|
850 | }, function( error, result, code ) { |
---|
851 | var taskList = []; |
---|
852 | |
---|
853 | if ( code !== 0 ) { |
---|
854 | grunt.fatal( 'The `' + map[ type ] + '` command returned a non-zero exit code.', code ); |
---|
855 | } |
---|
856 | |
---|
857 | // Callback for finding modified paths. |
---|
858 | function testPath( path ) { |
---|
859 | var regex = new RegExp( ' ' + path + '$', 'm' ); |
---|
860 | return regex.test( result.stdout ); |
---|
861 | } |
---|
862 | |
---|
863 | // Callback for finding modified files by extension. |
---|
864 | function testExtension( extension ) { |
---|
865 | var regex = new RegExp( '\.' + extension + '$', 'm' ); |
---|
866 | return regex.test( result.stdout ); |
---|
867 | } |
---|
868 | |
---|
869 | if ( [ 'package.json', 'Gruntfile.js' ].some( testPath ) ) { |
---|
870 | grunt.log.writeln( 'Configuration files modified. Running `prerelease`.' ); |
---|
871 | taskList.push( 'prerelease' ); |
---|
872 | } else { |
---|
873 | if ( [ 'png', 'jpg', 'gif', 'jpeg' ].some( testExtension ) ) { |
---|
874 | grunt.log.writeln( 'Image files modified. Minifying.' ); |
---|
875 | taskList.push( 'precommit:image' ); |
---|
876 | } |
---|
877 | |
---|
878 | [ 'js', 'css', 'php' ].forEach( function( extension ) { |
---|
879 | if ( testExtension( extension ) ) { |
---|
880 | grunt.log.writeln( extension.toUpperCase() + ' files modified. ' + extension.toUpperCase() + ' tests will be run.' ); |
---|
881 | taskList.push( 'precommit:' + extension ); |
---|
882 | } |
---|
883 | } ); |
---|
884 | |
---|
885 | if ( [ 'twemoji.js' ].some( testPath ) ) { |
---|
886 | grunt.log.writeln( 'twemoji.js has updated. Running `precommit:emoji.' ); |
---|
887 | taskList.push( 'precommit:emoji' ); |
---|
888 | } |
---|
889 | } |
---|
890 | |
---|
891 | grunt.task.run( taskList ); |
---|
892 | |
---|
893 | done(); |
---|
894 | } ); |
---|
895 | } |
---|
896 | } ); |
---|
897 | |
---|
898 | grunt.registerTask( 'copy:all', [ |
---|
899 | 'copy:files', |
---|
900 | 'copy:wp-admin-css-compat-rtl', |
---|
901 | 'copy:wp-admin-css-compat-min', |
---|
902 | 'copy:version' |
---|
903 | ] ); |
---|
904 | |
---|
905 | grunt.registerTask( 'build', [ |
---|
906 | 'clean:all', |
---|
907 | 'copy:all', |
---|
908 | 'cssmin:core', |
---|
909 | 'colors', |
---|
910 | 'rtl', |
---|
911 | 'cssmin:rtl', |
---|
912 | 'cssmin:colors', |
---|
913 | 'uglify:core', |
---|
914 | 'uglify:embed', |
---|
915 | 'uglify:jqueryui', |
---|
916 | 'concat:tinymce', |
---|
917 | 'compress:tinymce', |
---|
918 | 'clean:tinymce', |
---|
919 | 'concat:emoji', |
---|
920 | 'includes:emoji', |
---|
921 | 'includes:embed', |
---|
922 | 'jsvalidate:build' |
---|
923 | ] ); |
---|
924 | |
---|
925 | grunt.registerTask( 'prerelease', [ |
---|
926 | 'precommit:php', |
---|
927 | 'precommit:js', |
---|
928 | 'precommit:css', |
---|
929 | 'precommit:image' |
---|
930 | ] ); |
---|
931 | |
---|
932 | // Testing tasks. |
---|
933 | grunt.registerMultiTask('phpunit', 'Runs PHPUnit tests, including the ajax, external-http, and multisite tests.', function() { |
---|
934 | grunt.util.spawn({ |
---|
935 | cmd: this.data.cmd, |
---|
936 | args: this.data.args, |
---|
937 | opts: {stdio: 'inherit'} |
---|
938 | }, this.async()); |
---|
939 | }); |
---|
940 | |
---|
941 | grunt.registerTask('qunit:compiled', 'Runs QUnit tests on compiled as well as uncompiled scripts.', |
---|
942 | ['build', 'copy:qunit', 'qunit']); |
---|
943 | |
---|
944 | grunt.registerTask('test', 'Runs all QUnit and PHPUnit tasks.', ['qunit:compiled', 'phpunit']); |
---|
945 | |
---|
946 | // Travis CI tasks. |
---|
947 | grunt.registerTask('travis:js', 'Runs Javascript Travis CI tasks.', [ 'jshint:corejs', 'qunit:compiled' ]); |
---|
948 | grunt.registerTask('travis:phpunit', 'Runs PHPUnit Travis CI tasks.', 'phpunit'); |
---|
949 | |
---|
950 | // Patch task. |
---|
951 | grunt.renameTask('patch_wordpress', 'patch'); |
---|
952 | |
---|
953 | // Add an alias `apply` of the `patch` task name. |
---|
954 | grunt.registerTask('apply', 'patch'); |
---|
955 | |
---|
956 | // Default task. |
---|
957 | grunt.registerTask('default', ['build']); |
---|
958 | |
---|
959 | /* |
---|
960 | * Automatically updates the `:dynamic` configurations |
---|
961 | * so that only the changed files are updated. |
---|
962 | */ |
---|
963 | grunt.event.on('watch', function( action, filepath, target ) { |
---|
964 | var src; |
---|
965 | |
---|
966 | if ( [ 'all', 'rtl', 'browserify' ].indexOf( target ) === -1 ) { |
---|
967 | return; |
---|
968 | } |
---|
969 | |
---|
970 | src = [ path.relative( SOURCE_DIR, filepath ) ]; |
---|
971 | |
---|
972 | if ( action === 'deleted' ) { |
---|
973 | grunt.config( [ 'clean', 'dynamic', 'src' ], src ); |
---|
974 | } else { |
---|
975 | grunt.config( [ 'copy', 'dynamic', 'src' ], src ); |
---|
976 | |
---|
977 | if ( target === 'rtl' ) { |
---|
978 | grunt.config( [ 'rtlcss', 'dynamic', 'src' ], src ); |
---|
979 | } |
---|
980 | } |
---|
981 | }); |
---|
982 | }; |
---|