text: module.exports = function (grunt) {
    // Full list of files that must be included by RequireJS
    includes = [
      'jquery.select2',
      'almond',
  
      'jquery-mousewheel' // shimmed for non-full builds
    ];
  
    fullIncludes = [
      'jquery',
  
      'select2/compat/containerCss',
      'select2/compat/dropdownCss',
  
      'select2/compat/initSelection',
      'select2/compat/inputData',
      'select2/compat/matcher',
      'select2/compat/query',
  
      'select2/dropdown/attachContainer',
      'select2/dropdown/stopPropagation',
  
      'select2/selection/stopPropagation'
    ].concat(includes);
  
    var i18nModules = [];
    var i18nPaths = {};
  
    var i18nFiles = grunt.file.expand({
      cwd: 'src/js'
    }, 'select2/i18n/*.js');
  
    var testFiles = grunt.file.expand('tests/**/*.html');
    var testUrls = testFiles.map(function (filePath) {
      return 'http://localhost:9999/' + filePath;
    });
  
    var testBuildNumber = "unknown";
  
    if (process.env.TRAVIS_JOB_ID) {
      testBuildNumber = "travis-" + process.env.TRAVIS_JOB_ID;
    } else {
      var currentTime = new Date();
  
      testBuildNumber = "manual-" + currentTime.getTime();
    }
  
    for (var i = 0; i < i18nFiles.length; i++) {
      var file = i18nFiles[i];
      var name = file.split('.')[0];
  
      i18nModules.push({
        name: name
      });
  
      i18nPaths[name] = '/static/plugins/adminLTE/' + name;
    }
  
    var minifiedBanner = '/*! Select2 <%= package.version %> | https://github.com/select2/select2/blob/master/LICENSE.md */';
  
    grunt.initConfig({
      package: grunt.file.readJSON('package.json'),
  
      clean: {
        docs: ['docs/_site']
      },
  
      concat: {
        'dist': {
          options: {
            banner: grunt.file.read('src/js/wrapper.start.js'),
          },
          src: [
            'dist/js/select2.js',
            'src/js/wrapper.end.js'
          ],
          dest: 'dist/js/select2.js'
        },
        'dist.full': {
          options: {
            banner: grunt.file.read('src/js/wrapper.start.js'),
          },
          src: [
            'dist/js/select2.full.js',
            'src/js/wrapper.end.js'
          ],
          dest: 'dist/js/select2.full.js'
        }
      },
  
      connect: {
        tests: {
          options: {
            base: '.',
            hostname: '127.0.0.1',
            port: 9999
          }
        }
      },
  
      uglify: {
        'dist': {
          src: 'dist/js/select2.js',
          dest: 'dist/js/select2.min.js',
          options: {
            banner: minifiedBanner
          }
        },
        'dist.full': {
          src: 'dist/js/select2.full.js',
          dest: 'dist/js/select2.full.min.js',
          options: {
            banner: minifiedBanner
          }
        }
      },
  
      qunit: {
        all: {
          options: {
            urls: testUrls
          }
        }
      },
  
      'saucelabs-qunit': {
        all: {
          options: {
            build: testBuildNumber,
            tags: ['tests', 'qunit'],
            urls: testUrls,
            testTimeout: 8000,
            testname: 'QUnit test for Select2',
            browsers: [
              {
                browserName: 'internet explorer',
                version: '8',
                platform: 'Windows 7'
              },
              {
                browserName: 'internet explorer',
                version: '9',
                platform: 'Windows 7'
              },
              {
                browserName: 'internet explorer',
                version: '10',
                platform: 'Windows 7'
              },
  
              {
                browserName: 'internet explorer',
                version: '11',
                platform: 'Windows 10'
              },
  
              {
                browserName: 'firefox',
                platform: 'linux'
              },
  
              {
                browserName: 'chrome',
                platform: 'linux'
              },
  
              {
                browserName: 'opera',
                version: '12',
                platform: 'linux'
              }
            ]
          }
        }
      },
  
      'gh-pages': {
        options: {
          base: 'docs',
          branch: 'master',
          clone: 'node_modules/grunt-gh-pages/repo',
          message: 'Updated docs with master',
          push: true,
          repo: 'git@github.com:select2/select2.github.io.git'
        },
        src: '**'
      },
  
      jekyll: {
        options: {
          src: 'docs',
          dest: 'docs/_site'
        },
        build: {
          d: null
        },
        serve: {
          options: {
            serve: true,
            watch: true
          }
        }
      },
  
      jshint: {
        options: {
          jshintrc: true
        },
        code: {
          src: ['src/js/**/*.js']
        },
        tests: {
          src: ['tests/**/*.js']
        }
      },
  
      sass: {
        dist: {
          options: {
            outputStyle: 'compressed'
          },
          files: {
            'dist/css/select2.min.css': [
              'src/scss/core.scss',
              'src/scss/theme/default/layout.css'
            ]
          }
        },
        dev: {
          options: {
            outputStyle: 'nested'
          },
          files: {
            'dist/css/select2.css': [
              'src/scss/core.scss',
              'src/scss/theme/default/layout.css'
            ]
          }
        }
      },
  
      symlink: {
        docs: {
          cwd: 'dist',
          expand: true,
          overwrite: false,
          src: [
            '*'
          ],
          dest: 'docs/dist',
          filter: 'isDirectory'
        }
      },
  
      requirejs: {
        'dist': {
          options: {
            baseUrl: 'src/js',
            optimize: 'none',
            name: 'select2/core',
            out: 'dist/js/select2.js',
            include: includes,
            namespace: 'S2',
            paths: {
              'almond': require.resolve('almond').slice(0, -3),
              'jquery': 'jquery.shim',
              'jquery-mousewheel': 'jquery.mousewheel.shim'
            },
            wrap: {
              startFile: 'src/js/banner.start.js',
              endFile: 'src/js/banner.end.js'
            }
          }
        },
        'dist.full': {
          options: {
            baseUrl: 'src/js',
            optimize: 'none',
            name: 'select2/core',
            out: 'dist/js/select2.full.js',
            include: fullIncludes,
            namespace: 'S2',
            paths: {
              'almond': require.resolve('almond').slice(0, -3),
              'jquery': 'jquery.shim',
              'jquery-mousewheel': require.resolve('jquery-mousewheel').slice(0, -3)
            },
            wrap: {
              startFile: 'src/js/banner.start.js',
              endFile: 'src/js/banner.end.js'
            }
          }
        },
        'i18n': {
          options: {
            baseUrl: 'src/js/select2/i18n',
            dir: 'dist/js/i18n',
            paths: i18nPaths,
            modules: i18nModules,
            namespace: 'S2',
            wrap: {
              start: minifiedBanner + grunt.file.read('src/js/banner.start.js'),
              end: grunt.file.read('src/js/banner.end.js')
            }
          }
        }
      },
  
      watch: {
        js: {
          files: [
            'src/js/select2/**/*.js',
            'tests/**/*.js'
          ],
          tasks: [
            'compile',
            'test',
            'minify'
          ]
        },
        css: {
          files: [
            'src/scss/**/*.scss'
          ],
          tasks: [
            'compile',
            'minify'
          ]
        }
      }
    });
  
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-connect');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-qunit');
    grunt.loadNpmTasks('grunt-contrib-requirejs');
    grunt.loadNpmTasks('grunt-contrib-symlink');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-watch');
  
    grunt.loadNpmTasks('grunt-gh-pages');
    grunt.loadNpmTasks('grunt-jekyll');
    grunt.loadNpmTasks('grunt-saucelabs');
    grunt.loadNpmTasks('grunt-sass');
  
    grunt.registerTask('default', ['compile', 'test', 'minify']);
  
    grunt.registerTask('compile', [
      'requirejs:dist', 'requirejs:dist.full', 'requirejs:i18n',
      'concat:dist', 'concat:dist.full',
      'sass:dev'
    ]);
    grunt.registerTask('minify', ['uglify', 'sass:dist']);
    grunt.registerTask('test', ['connect:tests', 'qunit', 'jshint']);
  
    var ciTasks = [];
  
    ciTasks.push('compile');
    ciTasks.push('connect:tests');
  
    /*
    // grunt-saucelabs appears to be broken with Travis altogether now.
    // Can't run Sauce Labs tests in pull requests
    if (process.env.TRAVIS_PULL_REQUEST == 'false') {
      ciTasks.push('saucelabs-qunit');
    }
    */
  
    ciTasks.push('qunit');
    ciTasks.push('jshint');
  
    grunt.registerTask('ci', ciTasks);
  
    grunt.registerTask('docs', ['symlink:docs', 'jekyll:serve']);
  
    grunt.registerTask('docs-release', ['default', 'clean:docs', 'gh-pages']);
  };
  