<commit_before>/**
 * Gruntfile
 *
 * If you created your Sails app with `sails new foo --linker`,
 * the following files will be automatically injected (in order)
 * into the EJS and HTML files in your `views` and `assets` folders.
 *
 * At the top part of this file, you'll find a few of the most commonly
 * configured options, but Sails' integration with Grunt is also fully
 * customizable.  If you'd like to work with your assets differently
 * you can change this file to do anything you like!
 *
 * More information on using Grunt to work with static assets:
 * http://gruntjs.com/configuring-tasks
 */

module.exports = function (grunt) {

  /**
   * CSS files to inject in order
   * (uses Grunt-style wildcard/glob/splat expressions)
   *
   * By default, Sails also supports LESS in development and production.
   * To use SASS/SCSS, Stylus, etc., edit the `sails-linker:devStyles` task
   * below for more options.  For this to work, you may need to install new
   * dependencies, e.g. `npm install grunt-contrib-sass`
   */

  var cssFilesToInject = [
    'linker/styles/font-awesome.css',
    'linker/styles/bootstrap.css',
    'linker/**/*.css'
  ];

  /**
   * Javascript files to inject in order
   * (uses Grunt-style wildcard/glob/splat expressions)
   *
   * To use client-side CoffeeScript, TypeScript, etc., edit the
   * `sails-linker:devJs` task below for more options.
   */

  var jsFilesToInject = [

    // Below, as a demonstration, you'll see the built-in dependencies
    // linked in the proper order order
    'linker/js/jquery.js',
    'linker/js/angular.js',
    'linker/js/ui-bootstrap.js',
    'linker/js/ui-bootstrap-tpls.js',
    'linker/js/socket.io.js',
    'linker/js/angular-socket.io.js',
    'linker/js/angular-sails.io.js',
    'linker/js/app.js',

    // All of the rest of your app scripts imported here
    'linker/**/*.js'
  ];

  /**
   * Client-side HTML templates are injected using the sources below
   * The ordering of these templates shouldn't matter.
   * (uses Grunt-style wildcard/glob/splat expressions)
   *
   * By default, Sails uses JST templates and precompiles them into
   * functions for you.  If you want to use jade, handlebars, dust, etc.,
   * edit the relevant sections below.
   */

  var templateFilesToInject = [
    'linker/**/*.html'
  ];

  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  //
  // DANGER:
  //
  // With great power comes great responsibility.
  //
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////

  // Modify css file injection paths to use
  cssFilesToInject = cssFilesToInject.map(function (path) {
    return '.tmp/public/' + path;
  });

  // Modify js file injection paths to use
  jsFilesToInject = jsFilesToInject.map(function (path) {
    return '.tmp/public/' + path;
  });

  templateFilesToInject = templateFilesToInject.map(function (path) {
    return 'assets/' + path;
  });

  // Get path to core grunt dependencies from Sails
  var depsPath = grunt.option('gdsrc') || 'node_modules/sails/node_modules';
  grunt.loadTasks(depsPath + '/grunt-contrib-clean/tasks');
  grunt.loadTasks(depsPath + '/grunt-contrib-copy/tasks');
  grunt.loadTasks(depsPath + '/grunt-contrib-concat/tasks');
  grunt.loadTasks(depsPath + '/grunt-sails-linker/tasks');
  grunt.loadTasks(depsPath + '/grunt-contrib-jst/tasks');
  grunt.loadTasks(depsPath + '/grunt-contrib-watch/tasks');
  grunt.loadTasks(depsPath + '/grunt-contrib-uglify/tasks');
  grunt.loadTasks(depsPath + '/grunt-contrib-cssmin/tasks');
  grunt.loadNpmTasks('grunt-contrib-less');

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    copy: {
      dev: {
        files: [
          {
            expand: true,
            cwd: './assets',
            src: ['**/*.!(coffee|less)'],
            dest: '.tmp/public'
          },
          {
            expand: true,
            cwd: './bower_components/font-awesome/fonts/',
            src: ['**/*'],
            dest: '.tmp/public/linker/fonts'
          },
          { '.tmp/public/linker/js/jquery.js':            './bower_components/jquery/jquery.js' },
          { '.tmp/public/linker/js/socket.io.js':         './bower_components/socket.io-client/dist/socket.io.js' },
          { '.tmp/public/linker/js/angular.js':           './bower_components/angular/angular.js' },
          { '.tmp/public/linker/js/ui-bootstrap.js':      './bower_components/angular-bootstrap/ui-bootstrap.js' },
          { '.tmp/public/linker/js/ui-bootstrap-tpls.js': './bower_components/angular-bootstrap/ui-bootstrap-tpls.js' },
          { '.tmp/public/linker/js/angular-socket.io.js': './bower_components/angular-socket-io/socket.js' }
        ]
      },
      prod : {
          {
            expand: true,
            cwd: './bower_components/font-awesome/fonts/',
            src: ['**/*'],
            dest: '.tmp/public/fonts'
          },
      },
      build: {
        files: [
          {
            expand: true,
            cwd: '.tmp/public',
            src: ['**/*'],
            dest: 'www'
          }
        ]
      }
    },

    clean: {
      dev: ['.tmp/public/**'],
      build: ['www']
    },

    jst: {
      dev: {

        // To use other sorts of templates (mustache), specify the regexp below:
//        options: {
//           templateSettings: {
//             interpolate: /\{\{(.+?)\}\}/g
//           }
//        },
        files: {
          '.tmp/public/jst.js': templateFilesToInject
        }
      }
    },

    less: {
      bootstrap: {
        options: {
          paths: ['assets/linker/styles', 'bower_components/bootstrap/less']
        },
        files: [
          { '.tmp/public/linker/styles/bootstrap.css': 'assets/linker/styles/bootstrap.less' }
        ]
      },
      fontawesome: {
        options: {
          paths: ['assets/linker/styles', 'bower_components/font-awesome/less']
        },
        files: [
          { '.tmp/public/linker/styles/font-awesome.css': 'assets/linker/styles/font-awesome.less' }
        ]
      }
    },

    concat: {
      js: {
        src: jsFilesToInject,
        dest: '.tmp/public/concat/production.js'
      },
      css: {
        src: cssFilesToInject,
        dest: '.tmp/public/concat/production.css'
      }
    },

    uglify: {
      dist: {
        src: ['.tmp/public/concat/production.js'],
        dest: '.tmp/public/min/production-<%= pkg.version %>.js'
      },
      options : {
        mangle : false
      }
    },

    cssmin: {
      dist: {
        src: ['.tmp/public/concat/production.css'],
        dest: '.tmp/public/min/production-<%= pkg.version %>.css'
      }
    },

    'sails-linker': {

      devJs: {
        options: {
          startTag: '<!--SCRIPTS-->',
          endTag: '<!--SCRIPTS END-->',
          fileTmpl: '<script src="%s"></script>',
          appRoot: '.tmp/public'
        },
        files: {
          '.tmp/public/**/*.html': jsFilesToInject,
          'views/**/*.html': jsFilesToInject,
          'views/**/*.ejs': jsFilesToInject
        }
      },

      prodJs: {
        options: {
          startTag: '<!--SCRIPTS-->',
          endTag: '<!--SCRIPTS END-->',
          fileTmpl: '<script src="%s"></script>',
          appRoot: '.tmp/public'
        },
        files: {
          '.tmp/public/**/*.html': ['.tmp/public/min/production-<%= pkg.version %>.js'],
          'views/**/*.html': ['.tmp/public/min/production-<%= pkg.version %>.js'],
          'views/**/*.ejs': ['.tmp/public/min/production-<%= pkg.version %>.js']
        }
      },

      devStyles: {
        options: {
          startTag: '<!--STYLES-->',
          endTag: '<!--STYLES END-->',
          fileTmpl: '<link rel="stylesheet" href="%s">',
          appRoot: '.tmp/public'
        },

        // cssFilesToInject defined up top
        files: {
          '.tmp/public/**/*.html': cssFilesToInject,
          'views/**/*.html': cssFilesToInject,
          'views/**/*.ejs': cssFilesToInject
        }
      },

      prodStyles: {
        options: {
          startTag: '<!--STYLES-->',
          endTag: '<!--STYLES END-->',
          fileTmpl: '<link rel="stylesheet" href="%s">',
          appRoot: '.tmp/public'
        },
        files: {
          '.tmp/public/index.html': ['.tmp/public/min/production-<%= pkg.version %>.css'],
          'views/**/*.html': ['.tmp/public/min/production-<%= pkg.version %>.css'],
          'views/**/*.ejs': ['.tmp/public/min/production-<%= pkg.version %>.css']
        }
      },

      // Bring in JST template object
      devTpl: {
        options: {
          startTag: '<!--TEMPLATES-->',
          endTag: '<!--TEMPLATES END-->',
          fileTmpl: '<script type="text/javascript" src="%s"></script>',
          appRoot: '.tmp/public'
        },
        files: {
          '.tmp/public/index.html': ['.tmp/public/jst.js'],
          'views/**/*.html': ['.tmp/public/jst.js'],
          'views/**/*.ejs': ['.tmp/public/jst.js']
        }
      },

      /*******************************************
       * Jade linkers (TODO: clean this up)
       *******************************************/

      devJsJADE: {
        options: {
          startTag: '// SCRIPTS',
          endTag: '// SCRIPTS END',
          fileTmpl: 'script(type="text/javascript", src="%s")',
          appRoot: '.tmp/public'
        },
        files: {
          'views/**/*.jade': jsFilesToInject
        }
      },

      prodJsJADE: {
        options: {
          startTag: '// SCRIPTS',
          endTag: '// SCRIPTS END',
          fileTmpl: 'script(type="text/javascript", src="%s")',
          appRoot: '.tmp/public'
        },
        files: {
          'views/**/*.jade': ['.tmp/public/min/production-<%= pkg.version %>.js']
        }
      },

      devStylesJADE: {
        options: {
          startTag: '// STYLES',
          endTag: '// STYLES END',
          fileTmpl: 'link(rel="stylesheet", href="%s")',
          appRoot: '.tmp/public'
        },
        files: {
          'views/**/*.jade': cssFilesToInject
        }
      },

      prodStylesJADE: {
        options: {
          startTag: '// STYLES',
          endTag: '// STYLES END',
          fileTmpl: 'link(rel="stylesheet", href="%s")',
          appRoot: '.tmp/public'
        },
        files: {
          'views/**/*.jade': ['.tmp/public/min/production-<%= pkg.version %>.css']
        }
      },

      // Bring in JST template object
      devTplJADE: {
        options: {
          startTag: '// TEMPLATES',
          endTag: '// TEMPLATES END',
          fileTmpl: 'script(type="text/javascript", src="%s")',
          appRoot: '.tmp/public'
        },
        files: {
          'views/**/*.jade': ['.tmp/public/jst.js']
        }
      }
      /************************************
       * Jade linker end
       ************************************/
    },

    watch: {
      api: {

        // API files to watch:
        files: ['api/**/*']
      },
      assets: {

        // Assets to watch:
        files: ['assets/**/*'],

        // When assets are changed:
        tasks: ['compileAssets', 'linkAssets']
      }
    }
  });

  // When Sails is lifted:
  grunt.registerTask('default', [
    'compileAssets',
    'linkAssets',
    'watch'
  ]);

  grunt.registerTask('compileAssets', [
    'clean:dev',
    'jst:dev',
    'less',
    'copy:dev'
  ]);

  // Update link/script/template references in `assets` index.html
  grunt.registerTask('linkAssets', [
    'sails-linker:devJs',
    'sails-linker:devStyles',
    'sails-linker:devTpl',
    'sails-linker:devJsJADE',
    'sails-linker:devStylesJADE',
    'sails-linker:devTplJADE'
  ]);

  // Build the assets into a web accessible folder.
  // (handy for phone gap apps, chrome extensions, etc.)
  grunt.registerTask('build', [
    'compileAssets',
    'linkAssets',
    'clean:build',
    'copy:build'
  ]);

  // When sails is lifted in production
  grunt.registerTask('prod', [
    'clean:dev',
    'jst:dev',
    'less',
    'copy:dev',
    'copy:prod',
    'concat',
    'uglify',
    'cssmin',
    'sails-linker:prodJs',
    'sails-linker:prodStyles',
    'sails-linker:devTpl',
    'sails-linker:prodJsJADE',
    'sails-linker:prodStylesJADE',
    'sails-linker:devTplJADE'
  ]);

  // When API files are changed:
  // grunt.event.on('watch', function(action, filepath) {
  //   grunt.log.writeln(filepath + ' has ' + action);

  //   // Send a request to a development-only endpoint on the server
  //   // which will reuptake the file that was changed.
  //   var baseurl = grunt.option('baseurl');
  //   var gruntSignalRoute = grunt.option('signalpath');
  //   var url = baseurl + gruntSignalRoute + '?action=' + action + '&filepath=' + filepath;

  //   require('http').get(url)
  //   .on('error', function(e) {
  //     console.error(filepath + ' has ' + action + ', but could not signal the Sails.js server: ' + e.message);
  //   });
  // });
};
<commit_msg>fixed grunt typo<commit_after>/**
 * Gruntfile
 *
 * If you created your Sails app with `sails new foo --linker`,
 * the following files will be automatically injected (in order)
 * into the EJS and HTML files in your `views` and `assets` folders.
 *
 * At the top part of this file, you'll find a few of the most commonly
 * configured options, but Sails' integration with Grunt is also fully
 * customizable.  If you'd like to work with your assets differently
 * you can change this file to do anything you like!
 *
 * More information on using Grunt to work with static assets:
 * http://gruntjs.com/configuring-tasks
 */

module.exports = function (grunt) {

  /**
   * CSS files to inject in order
   * (uses Grunt-style wildcard/glob/splat expressions)
   *
   * By default, Sails also supports LESS in development and production.
   * To use SASS/SCSS, Stylus, etc., edit the `sails-linker:devStyles` task
   * below for more options.  For this to work, you may need to install new
   * dependencies, e.g. `npm install grunt-contrib-sass`
   */

  var cssFilesToInject = [
    'linker/styles/font-awesome.css',
    'linker/styles/bootstrap.css',
    'linker/**/*.css'
  ];

  /**
   * Javascript files to inject in order
   * (uses Grunt-style wildcard/glob/splat expressions)
   *
   * To use client-side CoffeeScript, TypeScript, etc., edit the
   * `sails-linker:devJs` task below for more options.
   */

  var jsFilesToInject = [

    // Below, as a demonstration, you'll see the built-in dependencies
    // linked in the proper order order
    'linker/js/jquery.js',
    'linker/js/angular.js',
    'linker/js/ui-bootstrap.js',
    'linker/js/ui-bootstrap-tpls.js',
    'linker/js/socket.io.js',
    'linker/js/angular-socket.io.js',
    'linker/js/angular-sails.io.js',
    'linker/js/app.js',

    // All of the rest of your app scripts imported here
    'linker/**/*.js'
  ];

  /**
   * Client-side HTML templates are injected using the sources below
   * The ordering of these templates shouldn't matter.
   * (uses Grunt-style wildcard/glob/splat expressions)
   *
   * By default, Sails uses JST templates and precompiles them into
   * functions for you.  If you want to use jade, handlebars, dust, etc.,
   * edit the relevant sections below.
   */

  var templateFilesToInject = [
    'linker/**/*.html'
  ];

  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  //
  // DANGER:
  //
  // With great power comes great responsibility.
  //
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////

  // Modify css file injection paths to use
  cssFilesToInject = cssFilesToInject.map(function (path) {
    return '.tmp/public/' + path;
  });

  // Modify js file injection paths to use
  jsFilesToInject = jsFilesToInject.map(function (path) {
    return '.tmp/public/' + path;
  });

  templateFilesToInject = templateFilesToInject.map(function (path) {
    return 'assets/' + path;
  });

  // Get path to core grunt dependencies from Sails
  var depsPath = grunt.option('gdsrc') || 'node_modules/sails/node_modules';
  grunt.loadTasks(depsPath + '/grunt-contrib-clean/tasks');
  grunt.loadTasks(depsPath + '/grunt-contrib-copy/tasks');
  grunt.loadTasks(depsPath + '/grunt-contrib-concat/tasks');
  grunt.loadTasks(depsPath + '/grunt-sails-linker/tasks');
  grunt.loadTasks(depsPath + '/grunt-contrib-jst/tasks');
  grunt.loadTasks(depsPath + '/grunt-contrib-watch/tasks');
  grunt.loadTasks(depsPath + '/grunt-contrib-uglify/tasks');
  grunt.loadTasks(depsPath + '/grunt-contrib-cssmin/tasks');
  grunt.loadNpmTasks('grunt-contrib-less');

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    copy: {
      dev: {
        files: [
          {
            expand: true,
            cwd: './assets',
            src: ['**/*.!(coffee|less)'],
            dest: '.tmp/public'
          },
          {
            expand: true,
            cwd: './bower_components/font-awesome/fonts/',
            src: ['**/*'],
            dest: '.tmp/public/linker/fonts'
          },
          { '.tmp/public/linker/js/jquery.js':            './bower_components/jquery/jquery.js' },
          { '.tmp/public/linker/js/socket.io.js':         './bower_components/socket.io-client/dist/socket.io.js' },
          { '.tmp/public/linker/js/angular.js':           './bower_components/angular/angular.js' },
          { '.tmp/public/linker/js/ui-bootstrap.js':      './bower_components/angular-bootstrap/ui-bootstrap.js' },
          { '.tmp/public/linker/js/ui-bootstrap-tpls.js': './bower_components/angular-bootstrap/ui-bootstrap-tpls.js' },
          { '.tmp/public/linker/js/angular-socket.io.js': './bower_components/angular-socket-io/socket.js' }
        ]
      },
      prod : {
		  files : [
          	{
              expand: true,
              cwd: './bower_components/font-awesome/fonts/',
              src: ['**/*'],
              dest: '.tmp/public/fonts'
		  	}
          ]
      },
      build: {
        files: [
          {
            expand: true,
            cwd: '.tmp/public',
            src: ['**/*'],
            dest: 'www'
          }
        ]
      }
    },

    clean: {
      dev: ['.tmp/public/**'],
      build: ['www']
    },

    jst: {
      dev: {

        // To use other sorts of templates (mustache), specify the regexp below:
//        options: {
//           templateSettings: {
//             interpolate: /\{\{(.+?)\}\}/g
//           }
//        },
        files: {
          '.tmp/public/jst.js': templateFilesToInject
        }
      }
    },

    less: {
      bootstrap: {
        options: {
          paths: ['assets/linker/styles', 'bower_components/bootstrap/less']
        },
        files: [
          { '.tmp/public/linker/styles/bootstrap.css': 'assets/linker/styles/bootstrap.less' }
        ]
      },
      fontawesome: {
        options: {
          paths: ['assets/linker/styles', 'bower_components/font-awesome/less']
        },
        files: [
          { '.tmp/public/linker/styles/font-awesome.css': 'assets/linker/styles/font-awesome.less' }
        ]
      }
    },

    concat: {
      js: {
        src: jsFilesToInject,
        dest: '.tmp/public/concat/production.js'
      },
      css: {
        src: cssFilesToInject,
        dest: '.tmp/public/concat/production.css'
      }
    },

    uglify: {
      dist: {
        src: ['.tmp/public/concat/production.js'],
        dest: '.tmp/public/min/production-<%= pkg.version %>.js'
      },
      options : {
        mangle : false
      }
    },

    cssmin: {
      dist: {
        src: ['.tmp/public/concat/production.css'],
        dest: '.tmp/public/min/production-<%= pkg.version %>.css'
      }
    },

    'sails-linker': {

      devJs: {
        options: {
          startTag: '<!--SCRIPTS-->',
          endTag: '<!--SCRIPTS END-->',
          fileTmpl: '<script src="%s"></script>',
          appRoot: '.tmp/public'
        },
        files: {
          '.tmp/public/**/*.html': jsFilesToInject,
          'views/**/*.html': jsFilesToInject,
          'views/**/*.ejs': jsFilesToInject
        }
      },

      prodJs: {
        options: {
          startTag: '<!--SCRIPTS-->',
          endTag: '<!--SCRIPTS END-->',
          fileTmpl: '<script src="%s"></script>',
          appRoot: '.tmp/public'
        },
        files: {
          '.tmp/public/**/*.html': ['.tmp/public/min/production-<%= pkg.version %>.js'],
          'views/**/*.html': ['.tmp/public/min/production-<%= pkg.version %>.js'],
          'views/**/*.ejs': ['.tmp/public/min/production-<%= pkg.version %>.js']
        }
      },

      devStyles: {
        options: {
          startTag: '<!--STYLES-->',
          endTag: '<!--STYLES END-->',
          fileTmpl: '<link rel="stylesheet" href="%s">',
          appRoot: '.tmp/public'
        },

        // cssFilesToInject defined up top
        files: {
          '.tmp/public/**/*.html': cssFilesToInject,
          'views/**/*.html': cssFilesToInject,
          'views/**/*.ejs': cssFilesToInject
        }
      },

      prodStyles: {
        options: {
          startTag: '<!--STYLES-->',
          endTag: '<!--STYLES END-->',
          fileTmpl: '<link rel="stylesheet" href="%s">',
          appRoot: '.tmp/public'
        },
        files: {
          '.tmp/public/index.html': ['.tmp/public/min/production-<%= pkg.version %>.css'],
          'views/**/*.html': ['.tmp/public/min/production-<%= pkg.version %>.css'],
          'views/**/*.ejs': ['.tmp/public/min/production-<%= pkg.version %>.css']
        }
      },

      // Bring in JST template object
      devTpl: {
        options: {
          startTag: '<!--TEMPLATES-->',
          endTag: '<!--TEMPLATES END-->',
          fileTmpl: '<script type="text/javascript" src="%s"></script>',
          appRoot: '.tmp/public'
        },
        files: {
          '.tmp/public/index.html': ['.tmp/public/jst.js'],
          'views/**/*.html': ['.tmp/public/jst.js'],
          'views/**/*.ejs': ['.tmp/public/jst.js']
        }
      },

      /*******************************************
       * Jade linkers (TODO: clean this up)
       *******************************************/

      devJsJADE: {
        options: {
          startTag: '// SCRIPTS',
          endTag: '// SCRIPTS END',
          fileTmpl: 'script(type="text/javascript", src="%s")',
          appRoot: '.tmp/public'
        },
        files: {
          'views/**/*.jade': jsFilesToInject
        }
      },

      prodJsJADE: {
        options: {
          startTag: '// SCRIPTS',
          endTag: '// SCRIPTS END',
          fileTmpl: 'script(type="text/javascript", src="%s")',
          appRoot: '.tmp/public'
        },
        files: {
          'views/**/*.jade': ['.tmp/public/min/production-<%= pkg.version %>.js']
        }
      },

      devStylesJADE: {
        options: {
          startTag: '// STYLES',
          endTag: '// STYLES END',
          fileTmpl: 'link(rel="stylesheet", href="%s")',
          appRoot: '.tmp/public'
        },
        files: {
          'views/**/*.jade': cssFilesToInject
        }
      },

      prodStylesJADE: {
        options: {
          startTag: '// STYLES',
          endTag: '// STYLES END',
          fileTmpl: 'link(rel="stylesheet", href="%s")',
          appRoot: '.tmp/public'
        },
        files: {
          'views/**/*.jade': ['.tmp/public/min/production-<%= pkg.version %>.css']
        }
      },

      // Bring in JST template object
      devTplJADE: {
        options: {
          startTag: '// TEMPLATES',
          endTag: '// TEMPLATES END',
          fileTmpl: 'script(type="text/javascript", src="%s")',
          appRoot: '.tmp/public'
        },
        files: {
          'views/**/*.jade': ['.tmp/public/jst.js']
        }
      }
      /************************************
       * Jade linker end
       ************************************/
    },

    watch: {
      api: {

        // API files to watch:
        files: ['api/**/*']
      },
      assets: {

        // Assets to watch:
        files: ['assets/**/*'],

        // When assets are changed:
        tasks: ['compileAssets', 'linkAssets']
      }
    }
  });

  // When Sails is lifted:
  grunt.registerTask('default', [
    'compileAssets',
    'linkAssets',
    'watch'
  ]);

  grunt.registerTask('compileAssets', [
    'clean:dev',
    'jst:dev',
    'less',
    'copy:dev'
  ]);

  // Update link/script/template references in `assets` index.html
  grunt.registerTask('linkAssets', [
    'sails-linker:devJs',
    'sails-linker:devStyles',
    'sails-linker:devTpl',
    'sails-linker:devJsJADE',
    'sails-linker:devStylesJADE',
    'sails-linker:devTplJADE'
  ]);

  // Build the assets into a web accessible folder.
  // (handy for phone gap apps, chrome extensions, etc.)
  grunt.registerTask('build', [
    'compileAssets',
    'linkAssets',
    'clean:build',
    'copy:build'
  ]);

  // When sails is lifted in production
  grunt.registerTask('prod', [
    'clean:dev',
    'jst:dev',
    'less',
    'copy:dev',
    'copy:prod',
    'concat',
    'uglify',
    'cssmin',
    'sails-linker:prodJs',
    'sails-linker:prodStyles',
    'sails-linker:devTpl',
    'sails-linker:prodJsJADE',
    'sails-linker:prodStylesJADE',
    'sails-linker:devTplJADE'
  ]);

  // When API files are changed:
  // grunt.event.on('watch', function(action, filepath) {
  //   grunt.log.writeln(filepath + ' has ' + action);

  //   // Send a request to a development-only endpoint on the server
  //   // which will reuptake the file that was changed.
  //   var baseurl = grunt.option('baseurl');
  //   var gruntSignalRoute = grunt.option('signalpath');
  //   var url = baseurl + gruntSignalRoute + '?action=' + action + '&filepath=' + filepath;

  //   require('http').get(url)
  //   .on('error', function(e) {
  //     console.error(filepath + ' has ' + action + ', but could not signal the Sails.js server: ' + e.message);
  //   });
  // });
};
<|endoftext|>


<commit_before>// This is a modified version of the draggable element using pure JS code
/*--------------------------------------------------------------------------------------------
|  @desc:      Draggable element using pure javascript
|  @author:    Aravind Buddha
|  @url:       http://www.techumber.com
|  @date:      14 FEB 2013
|  @email:     aravind@techumber.com
|  @license:   Free! to Share,copy, distribute and transmit ,
|              but i'll be glad if my name listed in the credits'
---------------------------------------------------------------------------------------------*/
var Draggable = function (elem) {
    var el = elem,
        isDragReady = false,
    dragoffset = {
      x: 0,
      y: 0
    };
  this.init = function () {
    this.initPosition();
    this.events();
  };
  //only for this demo
  this.initPosition = function () {
    el.style.position = "absolute";
    el.style.bottom = "-5px";
    el.style.left = "50px";
  };
  //events for the element
  this.events = function () {
    var self = this;
    _on(el, 'mousedown', function (e) {
      if(e.target === el || e.target.className === "window-title") {
          isDragReady = true;
        //corssbrowser mouse pointer values
          e.pageX = e.pageX || e.clientX + (document.documentElement.scrollLeft ?
                                document.documentElement.scrollLeft :
            document.body.scrollLeft);
          e.pageY = e.pageY || e.clientY + (document.documentElement.scrollTop ?
            document.documentElement.scrollTop :
            document.body.scrollTop);
          dragoffset.x = e.pageX - el.offsetLeft;
        dragoffset.y = e.pageY - el.offsetTop;
      }
    });
    _on(document, 'mouseup', function () {
      isDragReady = false;
    });
    _on(document, 'mousemove', function (e) {
      if (isDragReady) {
          el.style.bottom = "";
        e.pageX = e.pageX || e.clientX + (document.documentElement.scrollLeft ?
          document.documentElement.scrollLeft :
          document.body.scrollLeft);
        e.pageY = e.pageY || e.clientY + (document.documentElement.scrollTop ?
          document.documentElement.scrollTop :
          document.body.scrollTop);
        el.style.top = (e.pageY - dragoffset.y) + "px";
        el.style.left = (e.pageX - dragoffset.x) + "px";
      }
    });
  };
  //cross browser event Helper function
  var _on = function (el, event, fn) {
    document.attachEvent ? el.attachEvent('on' + event, fn) : el.addEventListener(event, fn, !0);
  };
  this.init();
}
<commit_msg>Random X position on window open<commit_after>// This is a modified version of the draggable element using pure JS code
/*--------------------------------------------------------------------------------------------
|  @desc:      Draggable element using pure javascript
|  @author:    Aravind Buddha
|  @url:       http://www.techumber.com
|  @date:      14 FEB 2013
|  @email:     aravind@techumber.com
|  @license:   Free! to Share,copy, distribute and transmit ,
|              but i'll be glad if my name listed in the credits'
---------------------------------------------------------------------------------------------*/
var Draggable = function (elem) {
    var el = elem,
        isDragReady = false,
    dragoffset = {
      x: 0,
      y: 0
    };
  this.init = function () {
    this.initPosition();
    this.events();
  };
  //only for this demo
  this.initPosition = function () {
    el.style.position = "absolute";
    el.style.bottom = "-5px";
    el.style.left = Math.floor(Math.random() * (document.documentElement.clientWidth - (el.offsetWidth + 20))) + 10 + "px";
  };
  //events for the element
  this.events = function () {
    var self = this;
    _on(el, 'mousedown', function (e) {
      if(e.target === el || e.target.className === "window-title") {
          isDragReady = true;
        //corssbrowser mouse pointer values
          e.pageX = e.pageX || e.clientX + (document.documentElement.scrollLeft ?
                                document.documentElement.scrollLeft :
            document.body.scrollLeft);
          e.pageY = e.pageY || e.clientY + (document.documentElement.scrollTop ?
            document.documentElement.scrollTop :
            document.body.scrollTop);
          dragoffset.x = e.pageX - el.offsetLeft;
        dragoffset.y = e.pageY - el.offsetTop;
      }
    });
    _on(document, 'mouseup', function () {
      isDragReady = false;
    });
    _on(document, 'mousemove', function (e) {
      if (isDragReady) {
          el.style.bottom = "";
        e.pageX = e.pageX || e.clientX + (document.documentElement.scrollLeft ?
          document.documentElement.scrollLeft :
          document.body.scrollLeft);
        e.pageY = e.pageY || e.clientY + (document.documentElement.scrollTop ?
          document.documentElement.scrollTop :
          document.body.scrollTop);
        el.style.top = (e.pageY - dragoffset.y) + "px";
        el.style.left = (e.pageX - dragoffset.x) + "px";
      }
    });
  };
  //cross browser event Helper function
  var _on = function (el, event, fn) {
    document.attachEvent ? el.attachEvent('on' + event, fn) : el.addEventListener(event, fn, !0);
  };
  this.init();
}
<|endoftext|>


<commit_before>import '../../../public/admin-assets/css/flexboxgrid.min.css'
import '../../../public/admin-assets/css/style.css'

import React from 'react'
import ReactDOM from 'react-dom'
import {createStore, applyMiddleware} from 'redux'
import {Provider} from 'react-redux'
import thunkMiddleware from 'redux-thunk'

import {fetchSettings} from 'modules/settings/actions'
import settings from 'lib/settings'
import * as auth from 'lib/auth'
import {connectToWebSocket} from 'lib/apiWebSocket'
import reducers from './rootReducer'
import App from './app'

const DEVELOPER_MODE = settings.developerMode === true;
if(DEVELOPER_MODE === false){
  auth.validateCurrentToken();
}

const store = createStore(reducers, applyMiddleware(thunkMiddleware));
store.dispatch(fetchSettings());

if (window.WebSocket) {
  connectToWebSocket(store);
}

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('app'));
<commit_msg>Added log if WebSocket is not supported<commit_after>import '../../../public/admin-assets/css/flexboxgrid.min.css'
import '../../../public/admin-assets/css/style.css'

import React from 'react'
import ReactDOM from 'react-dom'
import {createStore, applyMiddleware} from 'redux'
import {Provider} from 'react-redux'
import thunkMiddleware from 'redux-thunk'

import {fetchSettings} from 'modules/settings/actions'
import settings from 'lib/settings'
import * as auth from 'lib/auth'
import {connectToWebSocket} from 'lib/apiWebSocket'
import reducers from './rootReducer'
import App from './app'

const DEVELOPER_MODE = settings.developerMode === true;
if(DEVELOPER_MODE === false){
  auth.validateCurrentToken();
}

const store = createStore(reducers, applyMiddleware(thunkMiddleware));
store.dispatch(fetchSettings());

if (window.WebSocket) {
  connectToWebSocket(store);
} else {
  console.log('WebSocket is not supported by your browser.');
}

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('app'));
<|endoftext|>


<commit_before>module.exports = function(grunt) {

  grunt.initConfig({
    // Project configuration.
    pkg: grunt.file.readJSON('package.json'),

    // Compiles our Sass
    sass: {
      options: {
        precision: 6,
        sourceComments: false,
        outputStyle: 'compressed'
      },
      dist: {
        files: {
          'css/carbon.css': 'scss/carbon.scss'
        }
      }
    },

    // Handle vendor prefixing
    postcss: {
      options: {
        processors: [
          require('autoprefixer-core')({ browsers: ['last 2 versions', 'ie 8', 'ie 9'] })
        ]
      },
      dist: {
        src: 'css/*.css'
      },
      docs: {
        src: '_site/*.css'
      }
    },

    // Runs CSS reporting
    parker: {
      options: {
        metrics: [
          'TotalStylesheets',
          'TotalStylesheetSize',
          'TotalRules',
          'TotalSelectors',
          'TotalIdentifiers',
          'TotalDeclarations',
          'SelectorsPerRule',
          'IdentifiersPerSelector',
          'SpecificityPerSelector',
          'TopSelectorSpecificity',
          'TopSelectorSpecificitySelector',
          'TotalIdSelectors',
          'TotalUniqueColours',
          'TotalImportantKeywords',
          'TotalMediaQueries'
        ],
        file: "css/.carbon-stats.md",
        usePackage: true
      },
      src: [
        'css/*.css'
      ]
    },

    // Build tooling

    watch: {
      sass: {
        files: ['scss/**/*.scss', 'docs/docs.scss'],
        tasks: ['sass', 'postcss', 'parker']
      }
    },

    jekyll: {
      options: {
        src: 'docs',
        dest: '_site',
        raw: "version: <%= pkg.version %>"
      },
      serve: {
        options: {
          config: '_config.yml',
          serve: true,
          raw: 'baseurl: ""'
        }
      },
      dist: {
        options: {
          config: '_config.yml',
          serve: false
        }
      }
    },

    buildcontrol: {
      options: {
        dir: '_site',
        commit: true,
        push: true,
        message: 'Built %sourceName% from commit %sourceCommit% on branch %sourceBranch%'
      },
      pages: {
        options: {
          remote: 'git@github.com:l1f7/simplexmobility-styleguide.git',
          branch: 'gh-pages'
        }
      }
    },

    copy: {
      main: {
        files: [
          // includes files within path
          {
            expand: true,
            flatten: true,
            src: [
              'scss/vendor/font-awesome/fonts/fontawesome-webfont.eot',
              'scss/vendor/font-awesome/fonts/fontawesome-webfont.svg',
              'scss/vendor/font-awesome/fonts/fontawesome-webfont.ttf',
              'scss/vendor/font-awesome/fonts/fontawesome-webfont.woff',
              'scss/vendor/font-awesome/fonts/fontawesome-webfont.woff2'
            ],
            dest: 'docs/fonts/',
            filter: 'isFile'
          }
        ]
      }
    }
  });

  // Load dependencies
  grunt.loadNpmTasks('grunt-postcss');
  grunt.loadNpmTasks('grunt-build-control');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-jekyll');
  grunt.loadNpmTasks('grunt-parker');
  grunt.loadNpmTasks('grunt-sass');
  grunt.loadNpmTasks('grunt-contrib-copy');

  // Generate and format the CSS
  grunt.registerTask('default', ['sass', 'postcss', 'copy', 'jekyll:dist', 'parker']);

  grunt.registerTask('serve', ['sass', 'postcss', 'copy', 'jekyll:serve']);

  // Publish to GitHub
  grunt.registerTask('publish', ['jekyll:dist', 'postcss:docs', 'buildcontrol:pages']);
};
<commit_msg>Add copy task for publishing font files<commit_after>module.exports = function(grunt) {

  grunt.initConfig({
    // Project configuration.
    pkg: grunt.file.readJSON('package.json'),

    // Compiles our Sass
    sass: {
      options: {
        precision: 6,
        sourceComments: false,
        outputStyle: 'compressed'
      },
      dist: {
        files: {
          'css/carbon.css': 'scss/carbon.scss'
        }
      }
    },

    // Handle vendor prefixing
    postcss: {
      options: {
        processors: [
          require('autoprefixer-core')({ browsers: ['last 2 versions', 'ie 8', 'ie 9'] })
        ]
      },
      dist: {
        src: 'css/*.css'
      },
      docs: {
        src: '_site/*.css'
      }
    },

    // Runs CSS reporting
    parker: {
      options: {
        metrics: [
          'TotalStylesheets',
          'TotalStylesheetSize',
          'TotalRules',
          'TotalSelectors',
          'TotalIdentifiers',
          'TotalDeclarations',
          'SelectorsPerRule',
          'IdentifiersPerSelector',
          'SpecificityPerSelector',
          'TopSelectorSpecificity',
          'TopSelectorSpecificitySelector',
          'TotalIdSelectors',
          'TotalUniqueColours',
          'TotalImportantKeywords',
          'TotalMediaQueries'
        ],
        file: "css/.carbon-stats.md",
        usePackage: true
      },
      src: [
        'css/*.css'
      ]
    },

    // Build tooling

    watch: {
      sass: {
        files: ['scss/**/*.scss', 'docs/docs.scss'],
        tasks: ['sass', 'postcss', 'parker']
      }
    },

    jekyll: {
      options: {
        src: 'docs',
        dest: '_site',
        raw: "version: <%= pkg.version %>"
      },
      serve: {
        options: {
          config: '_config.yml',
          serve: true,
          raw: 'baseurl: ""'
        }
      },
      dist: {
        options: {
          config: '_config.yml',
          serve: false
        }
      }
    },

    buildcontrol: {
      options: {
        dir: '_site',
        commit: true,
        push: true,
        message: 'Built %sourceName% from commit %sourceCommit% on branch %sourceBranch%'
      },
      pages: {
        options: {
          remote: 'git@github.com:l1f7/simplexmobility-styleguide.git',
          branch: 'gh-pages'
        }
      }
    },

    copy: {
      main: {
        files: [
          // includes files within path
          {
            expand: true,
            flatten: true,
            src: [
              'scss/vendor/font-awesome/fonts/fontawesome-webfont.eot',
              'scss/vendor/font-awesome/fonts/fontawesome-webfont.svg',
              'scss/vendor/font-awesome/fonts/fontawesome-webfont.ttf',
              'scss/vendor/font-awesome/fonts/fontawesome-webfont.woff',
              'scss/vendor/font-awesome/fonts/fontawesome-webfont.woff2'
            ],
            dest: 'docs/fonts/',
            filter: 'isFile'
          }
        ]
      },
      dist: {
        files: [
          // includes files within path
          {
            expand: true,
            flatten: true,
            src: [
              'scss/vendor/font-awesome/fonts/fontawesome-webfont.eot',
              'scss/vendor/font-awesome/fonts/fontawesome-webfont.svg',
              'scss/vendor/font-awesome/fonts/fontawesome-webfont.ttf',
              'scss/vendor/font-awesome/fonts/fontawesome-webfont.woff',
              'scss/vendor/font-awesome/fonts/fontawesome-webfont.woff2'
            ],
            dest: '_site/fonts/',
            filter: 'isFile'
          }
        ]
      }
    }
  });

  // Load dependencies
  grunt.loadNpmTasks('grunt-postcss');
  grunt.loadNpmTasks('grunt-build-control');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-jekyll');
  grunt.loadNpmTasks('grunt-parker');
  grunt.loadNpmTasks('grunt-sass');
  grunt.loadNpmTasks('grunt-contrib-copy');

  // Generate and format the CSS
  grunt.registerTask('default', ['sass', 'postcss', 'copy', 'jekyll:dist', 'parker']);

  grunt.registerTask('serve', ['sass', 'postcss', 'copy', 'jekyll:serve']);

  // Publish to GitHub
  grunt.registerTask('publish', ['copy:dist', 'jekyll:dist', 'postcss:docs', 'buildcontrol:pages']);
};
<|endoftext|>


<commit_before>var Path = require('path')

var papath = require('./lib/path')
var media = papath.media('stable')

module.exports = function(grunt) {
  var ais = grunt.file.readJSON('ais.json')
  ais.ais.forEach(function(ai) {
    ai.path = ai.path.replace('%media%', media)
    if (ai.base_path) {
      ai.base_path = ai.base_path.replace('%media%', media)
    }
  })
  var identifier = 'com.wondible.pa.ai_showdown.' + ais.ais.map(function(ai) {return ai.rule_postfix}).join('')
  var modPath = '../../server_mods/' + identifier + '/'

  // Project configuration.
  var config = {
    copy: {
      ai_config: {
        files: [
          {
            src: ais.ai_config,
            dest: 'pa/ai/ai_config.json',
          },
        ],
      },
      ai_configs: {
        files: ais.ais.map(function(ai) {
          return {
            src: ai.path + '/ai_config.json',
            dest: 'pa/ai/ai_config' + ai.rule_postfix + '.json',
          }
        })
      },
      mod: {
        files: [
          {
            src: [
              'LICENSE.txt',
              'README.md',
              'CHANGELOG.md',
              'ui/**',
              'pa/**'],
            dest: modPath,
          },
        ],
      },
      modinfo: {
        files: [
          {
            src: ['modinfo.json'],
            dest: modPath,
          },
        ],
        options: {
          process: function(content, srcpath) {
            var info = JSON.parse(content)
            info.display_name = 'AI Showdown: ' + ais.ais.map(function(ai) {return ai.name}).join(' vs. ')
            info.description = ais.ais.map(function(ai) {
              return ai.name
            }).join(', ')
            info.date = require('dateformat')(new Date(), 'yyyy/mm/dd')
            info.identifier = identifier
            console.log(info.display_name, info.identifier, info.version, info.date)
            return JSON.stringify(info, null, 2)
          }
        }
      },
      vanilla: {
        files: [
          {
            expand: true,
            cwd: media + 'pa/ai/',
            src: ['**', '!neural_networks/**'],
            dest: 'ai/vanilla/',
          },
        ],
        options: {
          process: function(contents, path) {
            return JSON.stringify(JSON.parse(contents), null, 2)
          }
        },
      },
    },
    clean: ['pa', 'ui', 'ai/vanilla', modPath],
    platoons: {},
  }

  grunt.initConfig(config)

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');

  grunt.registerTask('media_check', 'Check if the media path is configured correctly', function() {
    if (grunt.file.exists(media + 'pa/ai/ai_config.json')) {
      console.log("media path appears to be pointing at a copy of PA")
      console.log(media)
    } else {
      console.log("Could not find AI files at the current media path.  Please edit `var media =` at the top of `Gruntfile.js`")
      console.log(media)
    }
  })

  var processMaps = function(basePath, ai) {
    var files = grunt.file.expandMapping([
      '**/*.json',
    ], Path.join('pa/ai/unit_maps', (ai.directory || ai.file_postfix || '')),
      {cwd: Path.join(basePath, 'unit_maps')})
    files.forEach(function(map) {
      grunt.file.copy(map.src, map.dest)
    })
  }

  grunt.registerTask('ai_unit_map', 'Copy and rename unit maps', function() {
    ais.ais.forEach(function(ai) {
      if (ai.base_path) {
        processMaps(ai.base_path, ai)
      }
      processMaps(ai.path, ai)
    })
  })

  var processPlatoonFile = function(map, ai) {
    var platoons = grunt.file.readJSON(map.src).platoon_templates
    var out = {}
    Object.keys(platoons).forEach(function(name) {
      out[name + ai.rule_postfix] = platoons[name]
    })
    if (Object.keys(out).length > 0) {
      grunt.file.write(map.dest, JSON.stringify({platoon_templates: out}, null, 2))
    }
  }

  var processPlatoons = function(basePath, ai) {
    var files = grunt.file.expandMapping([
      '**/*.json',
    ], Path.join('pa/ai/platoon_templates', (ai.directory || ai.file_postfix || '')),
      {cwd: Path.join(basePath, 'platoon_templates')})
    files.forEach(function(path) {processPlatoonFile(path, ai)})
  }

  grunt.registerTask('platoon_templates', 'Rename templates and copy files', function() {
    ais.ais.forEach(function(ai) {
      if (ai.base_path) {
        processPlatoons(ai.base_path, ai)
      }
      processPlatoons(ai.path, ai)
    })
  })

  var processBuildFile = function(map, ai) {
    var builds = grunt.file.readJSON(map.src)
    builds.build_list.forEach(function(rule) {
      rule.name = ai.name_prefix + rule.name
      if (/platoon_builds/.test(map.src)){
        rule.to_build = rule.to_build + ai.rule_postfix
      }
      rule.build_conditions.forEach(function(cond) {
        cond.unshift({
          "boolean": true,
          "string0": ai.personality_tag || ai.name,
          "test_type": "HasPersonalityTag"
        })
      })
    })
    grunt.file.write(map.dest, JSON.stringify(builds, null, 2))
  }

  var processBuildDir = function(basePath, dir, ai) {
    var files = grunt.file.expandMapping([
      '**/*.json',
    ], Path.join('pa/ai', dir, (ai.directory || ai.file_postfix || '')),
      {cwd: Path.join(basePath, dir)})
    files.forEach(function(path) {processBuildFile(path, ai)})
  }

  var processBuilds = function(basePath, ai) {
    processBuildDir(basePath, '/platoon_builds', ai)
    processBuildDir(basePath, '/fabber_builds', ai)
    processBuildDir(basePath, '/factory_builds', ai)
  }

  grunt.registerTask('builds', 'Rename builds and copy files', function() {
    ais.ais.forEach(function(ai) {
      if (ai.base_path) {
        processBuilds(ai.base_path, ai)
      }
      processBuilds(ai.path, ai)
    })
  })

  var locatePersonalityFile = function(ai) {
    var path

    path = ai.path + '/../../ui/main/game/new_game/js/ai.js'
    if (grunt.file.exists(path)) return path
  }

  var extractPersonalities = function(path) {
    var text = grunt.file.read(path)
    var perString = text.match(/({(\s|\n)*'(Idle|Normal)'(.|\r|\n)*});/m)[1]
    var json = perString.replace(/'/g, '"').replace(/(\w+):/g, '"$1":').replace(/},\r?\n\s+}/, '}}')
    return JSON.parse(json)
  }

  grunt.registerTask('personalities', 'Look for custom ai personalities', function() {
    var out = {}
    ais.ais.forEach(function(ai) {
      var path = locatePersonalityFile(ai)
      if (path) {
        var mod = extractPersonalities(path)
        Object.keys(mod).forEach(function(personality) {
          var name = ai.name_prefix + personality
          mod[personality].name = name
          mod[personality].personality_tags = mod[personality].personality_tags || []
          mod[personality].personality_tags.push(ai.personality_tag || ai.name)
          out[name] = mod[personality]
        })
      }
    })
    var template = grunt.file.read('template/personalities.js')
    var js = JSON.stringify(out, null, 2)
    var mod = template.replace('var extensions = {}', 'var extensions = ' + js)
    grunt.file.write('ui/mods/ai_showdown/personalities.js', mod)
  })

  grunt.registerTask('build', [
    'copy:ai_configs',
    'copy:ai_config',
    'ai_unit_map',
    'platoon_templates',
    'builds',
    'personalities',
  ]);
  grunt.registerTask('default', ['build']);

  grunt.registerTask('mod', [
    'copy:modinfo',
    'copy:mod',
  ])
};

<commit_msg>try vanilla personality file<commit_after>var Path = require('path')

var papath = require('./lib/path')
var media = papath.media('stable')

module.exports = function(grunt) {
  var ais = grunt.file.readJSON('ais.json')
  ais.ais.forEach(function(ai) {
    ai.path = ai.path.replace('%media%', media)
    if (ai.base_path) {
      ai.base_path = ai.base_path.replace('%media%', media)
    }
  })
  var identifier = 'com.wondible.pa.ai_showdown.' + ais.ais.map(function(ai) {return ai.rule_postfix}).join('')
  var modPath = '../../server_mods/' + identifier + '/'

  // Project configuration.
  var config = {
    copy: {
      ai_config: {
        files: [
          {
            src: ais.ai_config,
            dest: 'pa/ai/ai_config.json',
          },
        ],
      },
      ai_configs: {
        files: ais.ais.map(function(ai) {
          return {
            src: ai.path + '/ai_config.json',
            dest: 'pa/ai/ai_config' + ai.rule_postfix + '.json',
          }
        })
      },
      mod: {
        files: [
          {
            src: [
              'LICENSE.txt',
              'README.md',
              'CHANGELOG.md',
              'ui/**',
              'pa/**'],
            dest: modPath,
          },
        ],
      },
      modinfo: {
        files: [
          {
            src: ['modinfo.json'],
            dest: modPath,
          },
        ],
        options: {
          process: function(content, srcpath) {
            var info = JSON.parse(content)
            info.display_name = 'AI Showdown: ' + ais.ais.map(function(ai) {return ai.name}).join(' vs. ')
            info.description = ais.ais.map(function(ai) {
              return ai.name
            }).join(', ')
            info.date = require('dateformat')(new Date(), 'yyyy/mm/dd')
            info.identifier = identifier
            console.log(info.display_name, info.identifier, info.version, info.date)
            return JSON.stringify(info, null, 2)
          }
        }
      },
      vanilla: {
        files: [
          {
            expand: true,
            cwd: media + 'pa/ai/',
            src: ['**', '!neural_networks/**'],
            dest: 'ai/vanilla/',
          },
        ],
        options: {
          process: function(contents, path) {
            return JSON.stringify(JSON.parse(contents), null, 2)
          }
        },
      },
    },
    clean: ['pa', 'ui', 'ai/vanilla', modPath],
    platoons: {},
  }

  grunt.initConfig(config)

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');

  grunt.registerTask('media_check', 'Check if the media path is configured correctly', function() {
    if (grunt.file.exists(media + 'pa/ai/ai_config.json')) {
      console.log("media path appears to be pointing at a copy of PA")
      console.log(media)
    } else {
      console.log("Could not find AI files at the current media path.  Please edit `var media =` at the top of `Gruntfile.js`")
      console.log(media)
    }
  })

  var processMaps = function(basePath, ai) {
    var files = grunt.file.expandMapping([
      '**/*.json',
    ], Path.join('pa/ai/unit_maps', (ai.directory || ai.file_postfix || '')),
      {cwd: Path.join(basePath, 'unit_maps')})
    files.forEach(function(map) {
      grunt.file.copy(map.src, map.dest)
    })
  }

  grunt.registerTask('ai_unit_map', 'Copy and rename unit maps', function() {
    ais.ais.forEach(function(ai) {
      if (ai.base_path) {
        processMaps(ai.base_path, ai)
      }
      processMaps(ai.path, ai)
    })
  })

  var processPlatoonFile = function(map, ai) {
    var platoons = grunt.file.readJSON(map.src).platoon_templates
    var out = {}
    Object.keys(platoons).forEach(function(name) {
      out[name + ai.rule_postfix] = platoons[name]
    })
    if (Object.keys(out).length > 0) {
      grunt.file.write(map.dest, JSON.stringify({platoon_templates: out}, null, 2))
    }
  }

  var processPlatoons = function(basePath, ai) {
    var files = grunt.file.expandMapping([
      '**/*.json',
    ], Path.join('pa/ai/platoon_templates', (ai.directory || ai.file_postfix || '')),
      {cwd: Path.join(basePath, 'platoon_templates')})
    files.forEach(function(path) {processPlatoonFile(path, ai)})
  }

  grunt.registerTask('platoon_templates', 'Rename templates and copy files', function() {
    ais.ais.forEach(function(ai) {
      if (ai.base_path) {
        processPlatoons(ai.base_path, ai)
      }
      processPlatoons(ai.path, ai)
    })
  })

  var processBuildFile = function(map, ai) {
    var builds = grunt.file.readJSON(map.src)
    builds.build_list.forEach(function(rule) {
      rule.name = ai.name_prefix + rule.name
      if (/platoon_builds/.test(map.src)){
        rule.to_build = rule.to_build + ai.rule_postfix
      }
      rule.build_conditions.forEach(function(cond) {
        cond.unshift({
          "boolean": true,
          "string0": ai.personality_tag || ai.name,
          "test_type": "HasPersonalityTag"
        })
      })
    })
    grunt.file.write(map.dest, JSON.stringify(builds, null, 2))
  }

  var processBuildDir = function(basePath, dir, ai) {
    var files = grunt.file.expandMapping([
      '**/*.json',
    ], Path.join('pa/ai', dir, (ai.directory || ai.file_postfix || '')),
      {cwd: Path.join(basePath, dir)})
    files.forEach(function(path) {processBuildFile(path, ai)})
  }

  var processBuilds = function(basePath, ai) {
    processBuildDir(basePath, '/platoon_builds', ai)
    processBuildDir(basePath, '/fabber_builds', ai)
    processBuildDir(basePath, '/factory_builds', ai)
  }

  grunt.registerTask('builds', 'Rename builds and copy files', function() {
    ais.ais.forEach(function(ai) {
      if (ai.base_path) {
        processBuilds(ai.base_path, ai)
      }
      processBuilds(ai.path, ai)
    })
  })

  var locatePersonalityFile = function(ai) {
    var path

    path = ai.path + '/../../ui/main/game/new_game/js/ai.js'
    if (grunt.file.exists(path)) return path

    path = media + 'ui/main/game/new_game/js/ai.js'
    if (grunt.file.exists(path)) return path
  }

  var extractPersonalities = function(path) {
    var text = grunt.file.read(path)
    var perString = text.match(/({(\s|\n)*'(Idle|Normal)'(.|\r|\n)*});/m)[1]
    var json = perString.replace(/'/g, '"').replace(/(\w+):/g, '"$1":').replace(/},\r?\n\s+}/, '}}')
    return JSON.parse(json)
  }

  grunt.registerTask('personalities', 'Look for custom ai personalities', function() {
    var out = {}
    ais.ais.forEach(function(ai) {
      var path = locatePersonalityFile(ai)
      if (path) {
        var mod = extractPersonalities(path)
        Object.keys(mod).forEach(function(personality) {
          var name = ai.name_prefix + personality
          mod[personality].name = name
          mod[personality].personality_tags = mod[personality].personality_tags || []
          mod[personality].personality_tags.push(ai.personality_tag || ai.name)
          out[name] = mod[personality]
        })
      }
    })
    var template = grunt.file.read('template/personalities.js')
    var js = JSON.stringify(out, null, 2)
    var mod = template.replace('var extensions = {}', 'var extensions = ' + js)
    grunt.file.write('ui/mods/ai_showdown/personalities.js', mod)
  })

  grunt.registerTask('build', [
    'copy:ai_configs',
    'copy:ai_config',
    'ai_unit_map',
    'platoon_templates',
    'builds',
    'personalities',
  ]);
  grunt.registerTask('default', ['build']);

  grunt.registerTask('mod', [
    'copy:modinfo',
    'copy:mod',
  ])
};

<|endoftext|>


<commit_before>module.exports = function(grunt) {
    grunt.initConfig({
      jshint: {
        all: ['Gruntfile.js', 'hulk.js'],
        options: {
            "forin": true,
            "latedef": true,
            "unused": true,
            "trailing": true
        }
      },
      uglify: {
        options: {
            mangle: {
                except: ['jQuery']
            },
            compress: true
        },
        my_target: {
            files: {
                'hulk.min.js': ['hulk.js']
            }
        }
      }
    });

    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-uglify');
};
<commit_msg>auto sass recompiling<commit_after>module.exports = function(grunt) {
    grunt.initConfig({
      jshint: {
        all: ['Gruntfile.js', 'hulk.js'],
        options: {
            "forin": true,
            "latedef": true,
            "unused": true,
            "trailing": true
        }
      },

      uglify: {
        options: {
            mangle: {
                except: ['jQuery']
            },
            compress: true
        },
        my_target: {
            files: {
                'hulk.min.js': ['hulk.js']
            }
        }
      },

      qunit: {
        files: ['tests/test.html']
      },

      sass: {
          dev: {
              src: 'hulk.scss',
              dest: 'hulk.css'
          },
          colors: {
            src: 'hulk-colors.scss',
            dest: 'hulk-colors.css'
        }
      },

      watch: {
          sass: {
              // We watch and compile sass files as normal but don't live reload here
              files: ['hulk.scss', 'hulk-colors.scss'],
              tasks: ['sass'],
          }
      }
    });

    grunt.loadNpmTasks('grunt-contrib-sass');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    //grunt.loadNpmTasks('grunt-contrib-qunit');
    grunt.loadNpmTasks('grunt-contrib-watch');
};
<|endoftext|>


<commit_before>/**
 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import ReactCompatibleBaseElement from './react-compat-base-element.js';
import {
  AmpContext,
} from './amp-context.js';
import {Slot} from './slot.js';

const {
  useContext,
  useEffect,
  useLayoutEffect,
  useRef,
  useState,
} = preactHooks;

export const AmpSelectorContext = preact.createContext();

export function AmpSelector(props) {
  const {multiple, value, defaultValue} = props;
  const [selected, setSelectedState] = useState(
    value ? [].concat(value) :
    defaultValue ? [].concat(defaultValue) :
    []);
  const setSelectedRef = useRef(value => {
    if (props.onChange) {
      props.onChange({target: {value: multiple ? value : value[0]}});
    }
    setSelectedState(value);
  });
  return preact.createElement(
    props.tagName || 'div',
    {
      ...props,
    },
    preact.createElement(
      AmpSelectorContext.Provider,
      {
        value: {
          multiple,
          // TBD: controlled values require override of properties.
          selected: value ? [].concat(value) : selected,
          setSelected: setSelectedRef.current,
        },
      },
      props.children
    )
  );
}

AmpSelector.Option = function(props) {
  const {option} = props;
  const selectorContext = useContext(AmpSelectorContext);
  const {selected, setSelected, multiple} = selectorContext;
  const optionProps = {
    ...props,
    option,
    selected: selected.includes(option),
    onClick: () => selectOption(option, multiple, selected, setSelected),
  };
  if (props.render) {
    return props.render(optionProps);
  }
  return preact.createElement(
    props.type || props.tagName || 'div',
    optionProps,
    props.children);
}

function selectOption(option, multiple, selected, setSelected) {
  if (multiple) {
    setSelected(
      selected.includes(option) ?
      selected.filter(v => v != option) :
      selected.concat(option));
  } else {
    if (!selected.includes(option)) {
      setSelected([option]);
    }
  }
}

const AmpReactSelector = ReactCompatibleBaseElement(AmpSelector, {
  className: 'i-amphtml-fill-content i-amphtml-replaced-content',
  attrs: {
  },
  template: true,
  // TODO: simply override ReactBaseElement instead.
  init(reactBaseElement) {
    const {element} = reactBaseElement;
    const mu = new MutationObserver(records => {
      rebuild();
    });
    const rebuild = () => {
      const children = [];
      const optionChildren = element.querySelectorAll('[option]');
      const value = [];
      optionChildren.forEach(child => {
        // TODO: check that an option is not within another option.
        const option = child.getAttribute('option');
        const props = {
          option,
          type: Slot,
          retarget: true,
          assignedElements: [child],
          postRender: () => {
            // Skip mutations to avoid cycles.
            mu.takeRecords();
          },
        };
        if (child.hasAttribute('selected')) {
          value.push(option);
        }
        children.push(preact.createElement(AmpSelector.Option, props));
      });

      reactBaseElement.mutateProps({defaultValue: value, children});
    };
    mu.observe(element, {attributeFilter: ['option', 'selected'], subtree: true});

    // Run the first build.
    rebuild();
  },
});
customElements.define('amp-react-selector', AmpReactSelector);
<commit_msg>refactor selectOption for simplicity<commit_after>/**
 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import ReactCompatibleBaseElement from './react-compat-base-element.js';
import {
  AmpContext,
} from './amp-context.js';
import {Slot} from './slot.js';

const {
  useContext,
  useEffect,
  useLayoutEffect,
  useRef,
  useState,
} = preactHooks;

export const AmpSelectorContext = preact.createContext();

export function AmpSelector(props) {
  const {value, defaultValue} = props;
  const [selectedState, setSelectedState] = useState(
    value ? [].concat(value) :
    defaultValue ? [].concat(defaultValue) :
    []);
  // TBD: controlled values require override of properties.
  const selected = value ? [].concat(value) : selectedState;
  const selectOption = option => {
    const {multiple, onChange} = props;
    let newValue = null;
    if (multiple) {
      newValue =
        selected.includes(option) ?
          selected.filter(v => v != option) :
          selected.concat(option);
    } else if (!selected.includes(option)) {
      newValue = [option];
    }
    if (newValue) {
      setSelectedState(newValue);
      if (onChange) {
        onChange({target: {value: multiple ? newValue : newValue[0]}});
      }
    }
  };
  return preact.createElement(
    props.tagName || 'div',
    {
      ...props,
    },
    preact.createElement(
      AmpSelectorContext.Provider,
      {
        value: {
          selected,
          selectOption,
        },
      },
      props.children
    )
  );
}

AmpSelector.Option = function(props) {
  const {option} = props;
  const selectorContext = useContext(AmpSelectorContext);
  const {selected, selectOption} = selectorContext;
  const optionProps = {
    ...props,
    option,
    selected: selected.includes(option),
    onClick: () => selectOption(option),
  };
  if (props.render) {
    return props.render(optionProps);
  }
  return preact.createElement(
    props.type || props.tagName || 'div',
    optionProps,
    props.children);
}

const AmpReactSelector = ReactCompatibleBaseElement(AmpSelector, {
  className: 'i-amphtml-fill-content i-amphtml-replaced-content',
  attrs: {
  },
  template: true,
  // TODO: simply override ReactBaseElement instead.
  init(reactBaseElement) {
    const {element} = reactBaseElement;
    const mu = new MutationObserver(records => {
      rebuild();
    });
    const rebuild = () => {
      const children = [];
      const optionChildren = element.querySelectorAll('[option]');
      const value = [];
      optionChildren.forEach(child => {
        // TODO: check that an option is not within another option.
        const option = child.getAttribute('option');
        const props = {
          option,
          type: Slot,
          retarget: true,
          assignedElements: [child],
          postRender: () => {
            // Skip mutations to avoid cycles.
            mu.takeRecords();
          },
        };
        if (child.hasAttribute('selected')) {
          value.push(option);
        }
        children.push(preact.createElement(AmpSelector.Option, props));
      });

      reactBaseElement.mutateProps({defaultValue: value, children});
    };
    mu.observe(element, {attributeFilter: ['option', 'selected'], subtree: true});

    // Run the first build.
    rebuild();
  },
});
customElements.define('amp-react-selector', AmpReactSelector);
<|endoftext|>


<commit_before>/* eslint-disable */
module.exports = function(grunt) {
  require('load-grunt-tasks')(grunt);
  var nodeResolve = require('rollup-plugin-node-resolve');
  var json = require('rollup-plugin-json');
  var babel = require('rollup-plugin-babel');
  var commonjs = require('rollup-plugin-commonjs');
  var istanbul = require('rollup-plugin-istanbul');

  var env = function () {
    var envString = JSON.stringify(process.env);
    return {
      intro() {
        return `
window.process = window.process || {};
process.env = process.env || {};`;
      }
    };
  };
  var commonjsGlobal = function () {
    return {
      intro() {
        return `
var global = typeof window !== 'undefined' ? window :
             typeof global !== 'undefined' ? global :
             this;
var require = require || function(id) {throw new Error('Unexpected required ' + id)};
`;
      }
    };
  };

  var SAUCE_BROWSERS = [{
    browserName: 'chrome'
  }, {
    browserName: 'firefox',
    version: 'beta'
  }, {
    browserName: 'iPhone',
    version: '8.0'
  }, {
    browserName: 'android',
    version: '4.4'
  }, {
    browserName: 'MicrosoftEdge'
  }, {
    browserName: 'chrome',
    version: '31'
  }];

  var HINT_SRCS = ['src/**/*.js', 'test/**/*.js', /* 'demo/**\/*.js', */ '!**/browser/**/*.js', '!**/*.browser.js', '!**/*.bundle.js'];

  grunt.initConfig({
    watch: {
      scripts: {
        files: HINT_SRCS,
        tasks: ['build-test', 'release']
      },
    },
    eslint: {
      target: HINT_SRCS
    },
    rollup: {
      options: {
        sourceMap: true
      },
      dist: {
        dest: 'dist/bundle.js',
        src: 'src/realtime.js',
        options: {
          plugins: [
            json(),
            babel({ runtimeHelpers: true , exclude: 'node_modules/**' }),
            //nodeResolve({
            //  jsnext: true,
            //  main: true,
            //  skip: ['memcpy'],
            //}),
            commonjs({
              //include: ['node_modules/**', 'proto/**'],
              include: ['proto/**'],
            })
          ],
          format: 'cjs'
        }
      },
      'dist-browser': {
        dest: 'dist/bundle.browser.js',
        src: 'src/realtime.js',
        options: {
          plugins: [
            json(),
            babel({ runtimeHelpers: true , exclude: 'node_modules/**' }),
            nodeResolve({
              jsnext: true,
              main: true,
              browser: true
            }),
            commonjsGlobal(),
            commonjs({
              include: ['node_modules/**', 'proto/**'],
            })
          ],
          format: 'umd',
          moduleName: 'AV.realtime'
        }
      },
      test: {
        dest: 'test/index.bundle.js',
        src: 'test/index.js',
        options: {
          plugins: [
            istanbul({
              exclude: ['test/*.js', 'proto/*.js', '*.json'],
              instrumenter: require('istanbul'),
              instrumenterConfig: {
                esModules: true,
                noCompact: true,
              }
            }),
            json(),
            babel({ runtimeHelpers: true , exclude: 'node_modules/**' }),
            commonjs({
              include: ['proto/**'],
            }),
          ],
          format: 'cjs'
        }
      },
      'test-browser': {
        dest: 'test/browser/index.js',
        src: 'test/index.js',
        options: {
          plugins: [
            json(),
            babel({ runtimeHelpers: true , exclude: 'node_modules/**' }),
            nodeResolve({
              jsnext: true,
              main: true,
              browser: true
            }),
            commonjsGlobal(),
            commonjs({
              include: ['node_modules/**', 'proto/**'],
            }),
            env()
          ],
          format: 'umd',
          moduleName: 'AV.realtime'
        }
      }
    },
    envify: {
      'test-browser': {
        files: {
          'test/browser/index.env.js': ['test/browser/index.js']
        }
      }
    },
    uglify: {
      browser: {
        options: {
          sourceMap: true,
          sourceMapIn: 'dist/bundle.browser.js.map'
        },
        files: {
          'dist/bundle.browser.min.js': ['dist/bundle.browser.js']
        }
      }
    },
    mochaTest: {
      options: {
        timeout: 30000,
      },
      src: ['test/index.bundle.js']
    },
    storeCoverage: {
      options: {
        dir: 'coverage'
      }
    },
    connect: {
      server: {
        options: {
          port: 8000,
          base: ''
        }
      }
    },
    'mocha_phantomjs': {
      all: {
        options: {
          urls: [
            'http://localhost:8000/test/browser/'
          ]
        }
      }
    },
    'saucelabs-mocha': {
      all: {
        options: {
          urls: ['http://localhost:8000/test/browser/'],
          build: process.env.CI_BUILD_NUMBER,
          testname: 'Sauce Test for LeanCloud realtime SDK',
          browsers: SAUCE_BROWSERS,
          throttled: 5,
          tunnelArgs: ['--vm-version', 'dev-varnish']
        }
      }
    }
  });
  grunt.registerTask('default', []);
  grunt.registerTask('lint', ['eslint']);
  grunt.registerTask('build-test', ['rollup:test', 'rollup:test-browser', 'envify:test-browser']);
  grunt.registerTask('test', '', function() {
    var tasks = ['lint', 'build-test', /*'mocha_phantomjs',*/ 'mochaTest', 'storeCoverage'];
    if (process.env.SAUCE_USERNAME && process.env.SAUCE_ACCESS_KEY) {
      tasks = tasks.concat(['connect', 'saucelabs-mocha']);
    } else {
      grunt.log.writeln('Skip saucelabs test, set SAUCE_USERNAME and SAUCE_ACCESS_KEY to start it.');
    }
    grunt.task.run(tasks);
  });
  grunt.registerTask('release', ['rollup:dist-browser', 'rollup:dist', 'uglify:browser']);
  grunt.registerTask('dev', ['build-test', 'release', 'connect', 'watch']);
  grunt.registerTask('cdn', 'Upload dist to CDN.', function() {

    grunt.task.requires('release');
    var done = this.async();
    var version = require('./package.json').version;
    uploadCDN('./dist/AV.realtime.js', version, function() {
      uploadCDN('./dist/AV.realtime.min.js', version, done);
    });
  });
  grunt.registerTask('upload', ['release', 'cdn']);

  var qiniu = require('qiniu');
  var path = require('path');
  var fs = require('fs');

  qiniu.conf.ACCESS_KEY = process.env.CDN_QINIU_KEY;
  qiniu.conf.SECRET_KEY = process.env.CDN_QINIU_SECRET;

  function uploadCDN(file, version, cb) {
    var bucketname = 'paas_files';
    var key = 'static/js/' + path.basename(file, '.js') + '-' +
      version + '.js';
    var putPolicy = new qiniu.rs.PutPolicy(bucketname + ':' + key);
    var uptoken = putPolicy.token();
    var extra = new qiniu.io.PutExtra();
    extra.mimeType = 'application/javascript';
    var buffer = fs.readFileSync(file);
    qiniu.io.put(uptoken, key, buffer, extra, function(err, ret) {
      if (!err) {
        console.log('https://cdn1.lncld.net/' + ret.key);
      } else {
        console.log(err);
      }
      cb();
    });
  }

};
<commit_msg>fix(test): byebye IE<commit_after>/* eslint-disable */
module.exports = function(grunt) {
  require('load-grunt-tasks')(grunt);
  var nodeResolve = require('rollup-plugin-node-resolve');
  var json = require('rollup-plugin-json');
  var babel = require('rollup-plugin-babel');
  var commonjs = require('rollup-plugin-commonjs');
  var istanbul = require('rollup-plugin-istanbul');

  var env = function () {
    var envString = JSON.stringify(process.env);
    return {
      intro() {
        return `
window.process = window.process || {};
process.env = process.env || {};`;
      }
    };
  };
  var commonjsGlobal = function () {
    return {
      intro() {
        return `
var global = typeof window !== 'undefined' ? window :
             typeof global !== 'undefined' ? global :
             this;
var require = require || function(id) {throw new Error('Unexpected required ' + id)};
`;
      }
    };
  };

  var SAUCE_BROWSERS = [{
    browserName: 'chrome'
  }, {
    browserName: 'firefox',
    version: 'beta'
  }, {
    browserName: 'iPhone',
    version: '8.0'
  }, {
    browserName: 'android',
    version: '4.4'
  }, {
    browserName: 'chrome',
    version: '31'
  }];

  var HINT_SRCS = ['src/**/*.js', 'test/**/*.js', /* 'demo/**\/*.js', */ '!**/browser/**/*.js', '!**/*.browser.js', '!**/*.bundle.js'];

  grunt.initConfig({
    watch: {
      scripts: {
        files: HINT_SRCS,
        tasks: ['build-test', 'release']
      },
    },
    eslint: {
      target: HINT_SRCS
    },
    rollup: {
      options: {
        sourceMap: true
      },
      dist: {
        dest: 'dist/bundle.js',
        src: 'src/realtime.js',
        options: {
          plugins: [
            json(),
            babel({ runtimeHelpers: true , exclude: 'node_modules/**' }),
            //nodeResolve({
            //  jsnext: true,
            //  main: true,
            //  skip: ['memcpy'],
            //}),
            commonjs({
              //include: ['node_modules/**', 'proto/**'],
              include: ['proto/**'],
            })
          ],
          format: 'cjs'
        }
      },
      'dist-browser': {
        dest: 'dist/bundle.browser.js',
        src: 'src/realtime.js',
        options: {
          plugins: [
            json(),
            babel({ runtimeHelpers: true , exclude: 'node_modules/**' }),
            nodeResolve({
              jsnext: true,
              main: true,
              browser: true
            }),
            commonjsGlobal(),
            commonjs({
              include: ['node_modules/**', 'proto/**'],
            })
          ],
          format: 'umd',
          moduleName: 'AV.realtime'
        }
      },
      test: {
        dest: 'test/index.bundle.js',
        src: 'test/index.js',
        options: {
          plugins: [
            istanbul({
              exclude: ['test/*.js', 'proto/*.js', '*.json'],
              instrumenter: require('istanbul'),
              instrumenterConfig: {
                esModules: true,
                noCompact: true,
              }
            }),
            json(),
            babel({ runtimeHelpers: true , exclude: 'node_modules/**' }),
            commonjs({
              include: ['proto/**'],
            }),
          ],
          format: 'cjs'
        }
      },
      'test-browser': {
        dest: 'test/browser/index.js',
        src: 'test/index.js',
        options: {
          plugins: [
            json(),
            babel({ runtimeHelpers: true , exclude: 'node_modules/**' }),
            nodeResolve({
              jsnext: true,
              main: true,
              browser: true
            }),
            commonjsGlobal(),
            commonjs({
              include: ['node_modules/**', 'proto/**'],
            }),
            env()
          ],
          format: 'umd',
          moduleName: 'AV.realtime'
        }
      }
    },
    envify: {
      'test-browser': {
        files: {
          'test/browser/index.env.js': ['test/browser/index.js']
        }
      }
    },
    uglify: {
      browser: {
        options: {
          sourceMap: true,
          sourceMapIn: 'dist/bundle.browser.js.map'
        },
        files: {
          'dist/bundle.browser.min.js': ['dist/bundle.browser.js']
        }
      }
    },
    mochaTest: {
      options: {
        timeout: 30000,
      },
      src: ['test/index.bundle.js']
    },
    storeCoverage: {
      options: {
        dir: 'coverage'
      }
    },
    connect: {
      server: {
        options: {
          port: 8000,
          base: ''
        }
      }
    },
    'mocha_phantomjs': {
      all: {
        options: {
          urls: [
            'http://localhost:8000/test/browser/'
          ]
        }
      }
    },
    'saucelabs-mocha': {
      all: {
        options: {
          urls: ['http://localhost:8000/test/browser/'],
          build: process.env.CI_BUILD_NUMBER,
          testname: 'Sauce Test for LeanCloud realtime SDK',
          browsers: SAUCE_BROWSERS,
          throttled: 5,
          tunnelArgs: ['--vm-version', 'dev-varnish']
        }
      }
    }
  });
  grunt.registerTask('default', []);
  grunt.registerTask('lint', ['eslint']);
  grunt.registerTask('build-test', ['rollup:test', 'rollup:test-browser', 'envify:test-browser']);
  grunt.registerTask('test', '', function() {
    var tasks = ['lint', 'build-test', /*'mocha_phantomjs',*/ 'mochaTest', 'storeCoverage'];
    if (process.env.SAUCE_USERNAME && process.env.SAUCE_ACCESS_KEY) {
      tasks = tasks.concat(['connect', 'saucelabs-mocha']);
    } else {
      grunt.log.writeln('Skip saucelabs test, set SAUCE_USERNAME and SAUCE_ACCESS_KEY to start it.');
    }
    grunt.task.run(tasks);
  });
  grunt.registerTask('release', ['rollup:dist-browser', 'rollup:dist', 'uglify:browser']);
  grunt.registerTask('dev', ['build-test', 'release', 'connect', 'watch']);
  grunt.registerTask('cdn', 'Upload dist to CDN.', function() {

    grunt.task.requires('release');
    var done = this.async();
    var version = require('./package.json').version;
    uploadCDN('./dist/AV.realtime.js', version, function() {
      uploadCDN('./dist/AV.realtime.min.js', version, done);
    });
  });
  grunt.registerTask('upload', ['release', 'cdn']);

  var qiniu = require('qiniu');
  var path = require('path');
  var fs = require('fs');

  qiniu.conf.ACCESS_KEY = process.env.CDN_QINIU_KEY;
  qiniu.conf.SECRET_KEY = process.env.CDN_QINIU_SECRET;

  function uploadCDN(file, version, cb) {
    var bucketname = 'paas_files';
    var key = 'static/js/' + path.basename(file, '.js') + '-' +
      version + '.js';
    var putPolicy = new qiniu.rs.PutPolicy(bucketname + ':' + key);
    var uptoken = putPolicy.token();
    var extra = new qiniu.io.PutExtra();
    extra.mimeType = 'application/javascript';
    var buffer = fs.readFileSync(file);
    qiniu.io.put(uptoken, key, buffer, extra, function(err, ret) {
      if (!err) {
        console.log('https://cdn1.lncld.net/' + ret.key);
      } else {
        console.log(err);
      }
      cb();
    });
  }

};
<|endoftext|>