Make WordPress Core

source: trunk/Gruntfile.js @ 41201

Last change on this file since 41201 was 41062, checked in by jorbin, 8 years ago

Update autoprefixer browser support matrix

WordPress no longer supports many old old browsers: https://make.wordpress.org/core/2017/04/23/target-browser-coverage/

This also removes alot of no longer necessary CSS. It served us well, but we are never getting back together with IE8,9,10.

So, in the (paraphrased) words of Taylor Swift:

I remember when we dropped support the first time
Saying, "This is it, I've had enough, " 'cause like
We hadn't seen many users in a month
When you said you needed flexbox. (What?)
Then you postMessage again and say
"IE8, I miss you and I swear I'm gonna change, trust me."
Remember how that lasted for a day?
I say, "I hate the box model, " we break up, you call me, "I love css-grids."
Ooh, we called it off again last night
But ooh, this time I'm telling you, I'm telling you

We are never ever ever supporting IE 8,9,10,
We are never ever ever supporting IE 8,9,10,
You go talk to EDGE, talk to my FIREFOX, talk to CHROME
But we are never ever ever ever getting back together
Like, ever...

Fixes #37651.
Props stunnedbeast, netweb, jorbin.

File size: 24.6 KB
Line 
1/* jshint node:true */
2module.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 "&#x1f468;".
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};
Note: See TracBrowser for help on using the repository browser.