<commit_before>/*
 * Copyright 2014 Per Eckerdal
 *
 * 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.
 */

'use strict';

var expect = require('chai').expect;

var bddMocha = require('../lib/interface/bdd_mocha');
var suiteRunner = require('../lib/suite_runner');

function parseSuite(name, runtimeContext) {
  return bddMocha(__dirname + '/suite/' + name, runtimeContext);
}

function getKeypath(object, keypath) {
  try {
    /* jshint -W054 */
    return (new Function('obj', 'return obj' + keypath))(object);
    /* jshint +W054 */
  } catch (e) {
    throw new Error('Object ' + object + ' does not contain keypath ' + keypath);
  }
}

function setKeypathToNull(object, keypath) {
  try {
    /* jshint -W054 */
    (new Function('obj', 'obj' + keypath + ' = null;'))(object);
    /* jshint +W054 */
  } catch (e) {
    throw new Error('Failed to set keypath ' + keypath + ' for object ' + object);
  }
}

function expectKeypathIsFunctionAndSetToNull(object, keypath) {
  var value = getKeypath(object, keypath);
  expect(value).to.be.a('function');
  setKeypathToNull(object, keypath);
}

describe('BDD interface (Mocha flavor)', function() {
  it('should handle empty test files', function() {
    expect(parseSuite('suite_empty')).to.be.deep.equal({
      type: 'suite',
      contents: []
    });
  });

  describe('Suites', function() {
    it('should handle describe suites with no body', function() {
      expect(parseSuite('suite_describe_without_body')).to.be.deep.equal({
        type: 'suite',
        contents: [{
          type: 'suite',
          contents: [],
          skipped: true,
          name: 'Skipped suite'
        }]
      });
    });

    it('should handle tests with no body', function() {
      expect(parseSuite('suite_test_without_body')).to.be.deep.equal({
        type: 'suite',
        contents: [{
          type: 'test',
          name: 'should be skipped',
          skipped: true
        }]
      });
    });

    it('should describe suites', function() {
      expect(parseSuite('suite_empty_describe')).to.be.deep.equal({
        type: 'suite',
        contents: [{
          type: 'suite',
          contents: [],
          name: 'Empty'
        }]
      });
    });
  });

  describe('Tests', function() {
    it('should declare tests with it', function() {
      var suite = parseSuite('suite_single_successful_test');
      expectKeypathIsFunctionAndSetToNull(suite, '.contents[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [{
          type: 'test',
          name: 'should succeed',
          run: null
        }]
      });
    });

    it('should skip tests with it.skip', function() {
      var suite = parseSuite('suite_single_skipped_test');
      expectKeypathIsFunctionAndSetToNull(suite, '.contents[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [{
          type: 'test',
          name: 'should be skipped',
          skipped: true,
          run: null
        }]
      });
    });

    it('should mark only tests with it.only', function() {
      var suite = parseSuite('suite_single_only_test');
      expectKeypathIsFunctionAndSetToNull(suite, '.contents[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [{
          type: 'test',
          name: 'should be run only',
          only: true,
          run: null
        }]
      });
    });
  });

  describe('Hooks', function() {
    it('should declare before hooks', function() {
      var suite = parseSuite('suite_before_hook');
      expectKeypathIsFunctionAndSetToNull(suite, '.before[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [],
        before: [{ run: null }]
      });
    });

    it('should declare beforeEach hooks', function() {
      var suite = parseSuite('suite_before_each_hook');
      expectKeypathIsFunctionAndSetToNull(suite, '.before[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [],
        before: [{ run: null }]
      });
    });

    it('should declare after hooks', function() {
      var suite = parseSuite('suite_after_hook');
      expectKeypathIsFunctionAndSetToNull(suite, '.after[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [],
        after: [{ run: null }]
      });
    });

    it('should declare afterEach hooks', function() {
      var suite = parseSuite('suite_after_each_hook');
      expectKeypathIsFunctionAndSetToNull(suite, '.after[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [],
        after: [{ run: null }]
      });
    });

    it('should declare hooks with string names', function() {
      var suite = parseSuite('suite_before_hook_name');
      expectKeypathIsFunctionAndSetToNull(suite, '.before[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [],
        before: [{
          name: 'before hook name',
          run: null
        }]
      });
    });

    it('should declare hooks with function names', function() {
      var suite = parseSuite('suite_before_hook_function_name');
      expectKeypathIsFunctionAndSetToNull(suite, '.before[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [],
        before: [{
          name: 'beforeHookName',
          run: null
        }]
      });
    });

    it('should declare hooks within subsuites', function() {
      var suite = parseSuite('suite_before_hook_within_describe');
      expectKeypathIsFunctionAndSetToNull(suite, '.contents[0].before[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [{
          type: 'suite',
          contents: [],
          name: 'Suite',
          before: [{ run: null }]
        }]
      });
    });
  });

  describe('Timeouts', function() {
    it('should allow getting the timeout for the current test', function() {
      var suite = parseSuite('suite_timeout_return', { getTimeout: function() {
        return 12345;
      }});
      var fn = getKeypath(suite, '.contents[0].run');
      expect(fn).to.be.a('function');
      expect(fn()).to.be.equal(12345);
    });

    it('should allow getting the timeout for the current test via the currentTest property', function() {
      var suite = parseSuite('suite_timeout_return_current_test', { getTimeout: function() {
        return 12345;
      }});
      var fn = getKeypath(suite, '.contents[0].run');
      expect(fn).to.be.a('function');
      expect(fn()).to.be.equal(12345);
    });

    it('should allow setting the timeout for the current test', function(done) {
      var suite = parseSuite('suite_timeout_set', { setTimeout: function(value) {
        expect(value).to.be.equal(10);
        done();
      }});
      var fn = getKeypath(suite, '.contents[0].run');
      fn();
    });

    it('should allow getting the timeout in a hook', function() {
      var suite = parseSuite('suite_timeout_return_in_hook', { getTimeout: function() {
        return 12345;
      }});
      var beforeFn = getKeypath(suite, '.before[0].run');
      expect(beforeFn).to.be.a('function');
      beforeFn();

      var fn = getKeypath(suite, '.contents[0].run');
      expect(fn).to.be.a('function');
      expect(fn()).to.be.equal(12345);
    });
  });

  describe('Slow thresholds', function() {
    it('should allow getting the timeout for the current test', function() {
      var suite = parseSuite('suite_slow_return', { getSlowThreshold: function() {
        return 23456;
      }});
      var fn = getKeypath(suite, '.contents[0].run');
      expect(fn).to.be.a('function');
      expect(fn()).to.be.equal(23456);
    });

    it('should allow setting the slow threshold for the current test', function(done) {
      var suite = parseSuite('suite_slow_set', { setSlowThreshold: function(value) {
        expect(value).to.be.equal(20);
        done();
      }});
      var fn = getKeypath(suite, '.contents[0].run');
      fn();
    });
  });

  describe('Breadcrumbs', function() {
    it('should allow leaving breadcrumbs', function(done) {
      var suite = parseSuite('suite_leave_breadcrumb', { leaveBreadcrumb: function(message, trace) {
        expect(message).to.be.equal('A breadcrumb');
        expect(trace).to.contain('suite_leave_breadcrumb.js:');
        done();
      }});
      var fn = getKeypath(suite, '.contents[0].run');
      fn();
    });
  });

  it('should declare context global', function() {
    return suiteRunner({
      suites: [__dirname + '/suite/suite_access_context'],
      interface: __dirname + '/../lib/interface/bdd_mocha',
      timeout: 500,
      reporters: []
    });
  });
});
<commit_msg>Make style a bit nicer in test_bdd_mocha.js<commit_after>/*
 * Copyright 2014 Per Eckerdal
 *
 * 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.
 */

'use strict';

var expect = require('chai').expect;

var bddMocha = require('../lib/interface/bdd_mocha');
var suiteRunner = require('../lib/suite_runner');

function parseSuite(name, runtimeContext) {
  return bddMocha(__dirname + '/suite/' + name, runtimeContext);
}

function getKeypath(object, keypath) {
  try {
    /* jshint -W054 */
    return (new Function('obj', 'return obj' + keypath))(object);
    /* jshint +W054 */
  } catch (e) {
    throw new Error('Object ' + object + ' does not contain keypath ' + keypath);
  }
}

function setKeypathToNull(object, keypath) {
  try {
    /* jshint -W054 */
    (new Function('obj', 'obj' + keypath + ' = null;'))(object);
    /* jshint +W054 */
  } catch (e) {
    throw new Error('Failed to set keypath ' + keypath + ' for object ' + object);
  }
}

function expectKeypathIsFunctionAndSetToNull(object, keypath) {
  var value = getKeypath(object, keypath);
  expect(value).to.be.a('function');
  setKeypathToNull(object, keypath);
}

describe('BDD interface (Mocha flavor)', function() {
  it('should handle empty test files', function() {
    expect(parseSuite('suite_empty')).to.be.deep.equal({
      type: 'suite',
      contents: []
    });
  });

  describe('Suites', function() {
    it('should handle describe suites with no body', function() {
      expect(parseSuite('suite_describe_without_body')).to.be.deep.equal({
        type: 'suite',
        contents: [{
          type: 'suite',
          contents: [],
          skipped: true,
          name: 'Skipped suite'
        }]
      });
    });

    it('should handle tests with no body', function() {
      expect(parseSuite('suite_test_without_body')).to.be.deep.equal({
        type: 'suite',
        contents: [{
          type: 'test',
          name: 'should be skipped',
          skipped: true
        }]
      });
    });

    it('should describe suites', function() {
      expect(parseSuite('suite_empty_describe')).to.be.deep.equal({
        type: 'suite',
        contents: [{
          type: 'suite',
          contents: [],
          name: 'Empty'
        }]
      });
    });
  });

  describe('Tests', function() {
    it('should declare tests with it', function() {
      var suite = parseSuite('suite_single_successful_test');
      expectKeypathIsFunctionAndSetToNull(suite, '.contents[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [{
          type: 'test',
          name: 'should succeed',
          run: null
        }]
      });
    });

    it('should skip tests with it.skip', function() {
      var suite = parseSuite('suite_single_skipped_test');
      expectKeypathIsFunctionAndSetToNull(suite, '.contents[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [{
          type: 'test',
          name: 'should be skipped',
          skipped: true,
          run: null
        }]
      });
    });

    it('should mark only tests with it.only', function() {
      var suite = parseSuite('suite_single_only_test');
      expectKeypathIsFunctionAndSetToNull(suite, '.contents[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [{
          type: 'test',
          name: 'should be run only',
          only: true,
          run: null
        }]
      });
    });
  });

  describe('Hooks', function() {
    it('should declare before hooks', function() {
      var suite = parseSuite('suite_before_hook');
      expectKeypathIsFunctionAndSetToNull(suite, '.before[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [],
        before: [{ run: null }]
      });
    });

    it('should declare beforeEach hooks', function() {
      var suite = parseSuite('suite_before_each_hook');
      expectKeypathIsFunctionAndSetToNull(suite, '.before[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [],
        before: [{ run: null }]
      });
    });

    it('should declare after hooks', function() {
      var suite = parseSuite('suite_after_hook');
      expectKeypathIsFunctionAndSetToNull(suite, '.after[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [],
        after: [{ run: null }]
      });
    });

    it('should declare afterEach hooks', function() {
      var suite = parseSuite('suite_after_each_hook');
      expectKeypathIsFunctionAndSetToNull(suite, '.after[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [],
        after: [{ run: null }]
      });
    });

    it('should declare hooks with string names', function() {
      var suite = parseSuite('suite_before_hook_name');
      expectKeypathIsFunctionAndSetToNull(suite, '.before[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [],
        before: [{
          name: 'before hook name',
          run: null
        }]
      });
    });

    it('should declare hooks with function names', function() {
      var suite = parseSuite('suite_before_hook_function_name');
      expectKeypathIsFunctionAndSetToNull(suite, '.before[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [],
        before: [{
          name: 'beforeHookName',
          run: null
        }]
      });
    });

    it('should declare hooks within subsuites', function() {
      var suite = parseSuite('suite_before_hook_within_describe');
      expectKeypathIsFunctionAndSetToNull(suite, '.contents[0].before[0].run');
      expect(suite).to.be.deep.equal({
        type: 'suite',
        contents: [{
          type: 'suite',
          contents: [],
          name: 'Suite',
          before: [{ run: null }]
        }]
      });
    });
  });

  describe('Timeouts', function() {
    it('should allow getting the timeout for the current test', function() {
      var suite = parseSuite('suite_timeout_return', {
        getTimeout: function() {
          return 12345;
        }
      });
      var fn = getKeypath(suite, '.contents[0].run');
      expect(fn).to.be.a('function');
      expect(fn()).to.be.equal(12345);
    });

    it('should allow getting the timeout for the current test via the currentTest property', function() {
      var suite = parseSuite('suite_timeout_return_current_test', {
        getTimeout: function() {
          return 12345;
        }
      });
      var fn = getKeypath(suite, '.contents[0].run');
      expect(fn).to.be.a('function');
      expect(fn()).to.be.equal(12345);
    });

    it('should allow setting the timeout for the current test', function(done) {
      var suite = parseSuite('suite_timeout_set', {
        setTimeout: function(value) {
          expect(value).to.be.equal(10);
          done();
        }
      });
      var fn = getKeypath(suite, '.contents[0].run');
      fn();
    });

    it('should allow getting the timeout in a hook', function() {
      var suite = parseSuite('suite_timeout_return_in_hook', {
        getTimeout: function() {
          return 12345;
        }
      });
      var beforeFn = getKeypath(suite, '.before[0].run');
      expect(beforeFn).to.be.a('function');
      beforeFn();

      var fn = getKeypath(suite, '.contents[0].run');
      expect(fn).to.be.a('function');
      expect(fn()).to.be.equal(12345);
    });
  });

  describe('Slow thresholds', function() {
    it('should allow getting the timeout for the current test', function() {
      var suite = parseSuite('suite_slow_return', {
        getSlowThreshold: function() {
          return 23456;
        }
      });
      var fn = getKeypath(suite, '.contents[0].run');
      expect(fn).to.be.a('function');
      expect(fn()).to.be.equal(23456);
    });

    it('should allow setting the slow threshold for the current test', function(done) {
      var suite = parseSuite('suite_slow_set', {
        setSlowThreshold: function(value) {
          expect(value).to.be.equal(20);
          done();
        }
      });
      var fn = getKeypath(suite, '.contents[0].run');
      fn();
    });
  });

  describe('Breadcrumbs', function() {
    it('should allow leaving breadcrumbs', function(done) {
      var suite = parseSuite('suite_leave_breadcrumb', {
        leaveBreadcrumb: function(message, trace) {
          expect(message).to.be.equal('A breadcrumb');
          expect(trace).to.contain('suite_leave_breadcrumb.js:');
          done();
        }
      });
      var fn = getKeypath(suite, '.contents[0].run');
      fn();
    });
  });

  it('should declare context global', function() {
    return suiteRunner({
      suites: [__dirname + '/suite/suite_access_context'],
      interface: __dirname + '/../lib/interface/bdd_mocha',
      timeout: 500,
      reporters: []
    });
  });
});
<|endoftext|>


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

  grunt.loadNpmTasks('grunt-tizen');
  grunt.loadNpmTasks('grunt-crosswalk');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-htmlmin');
  grunt.loadNpmTasks('grunt-contrib-imagemin');
  grunt.loadNpmTasks('grunt-release');
  grunt.loadTasks('tools/grunt-tasks');

  grunt.initConfig({
    packageInfo: grunt.file.readJSON('package.json'),
    chromeInfo: grunt.file.readJSON('platforms/chrome-crx/manifest.json'),

    crosswalk: {
      arm: {
        "outDir": 'build',
        verbose: false,
        version: '<%= packageInfo.version %>',
        name: '<%= packageInfo.name %>',
        pkg: 'org.org01.webapps.<%= packageInfo.name.toLowerCase() %>',
        icon: 'icon_128.png',
        fullscreen: true,
        remoteDebugging: true,
        appRoot: 'build/xpk',
        appLocalPath: 'index.html',
        //embedded: true,
        //androidSDKDir: '/opt/android-sdk-linux/',
        //xwalkAndroidDir: process.env.HOME+'/Downloads/crosswalk-3.32.53.4-arm'
        arch: 'arm',
        //androidAPIVersion: "18.0.1"
      },
      x86: {
        "outDir": 'build',
        verbose: false,
        version: '<%= packageInfo.version %>',
        name: '<%= packageInfo.name %>',
        pkg: 'org.org01.webapps.<%= packageInfo.name.toLowerCase() %>',
        icon: 'icon_128.png',
        fullscreen: true,
        remoteDebugging: true,
        appRoot: 'build/xpk',
        appLocalPath: 'index.html',
        //embedded: true,
        //androidSDKDir: '/opt/android-sdk-linux/',
        //xwalkAndroidDir: process.env.HOME+'/Downloads/crosswalk-3.32.53.4-x86'
        arch: 'x86',
        //androidAPIVersion: "18.0.1"
      }
    },

    clean: ['build'],

    release: {
      options: {
        npm: false,
        npmtag: false,
        tagName: 'v<%= version %>'
      }
    },

    tizen_configuration: {
      // location on the device to install the tizen-app.sh script to
      // (default: '/tmp')
      tizenAppScriptDir: '/home/developer/',

      // path to the config.xml file for the Tizen wgt file - post templating
      // (default: 'config.xml')
      configFile: 'build/wgt/config.xml',

      // path to the sdb command (default: process.env.SDB or 'sdb')
      sdbCmd: 'sdb'
    },

    // minify JS
    uglify: {
      dist: {
        files: [
          { expand: true, cwd: '.', src: 'app/js/**/*.js', dest: 'build/' }
        ]
      }
    },

    // minify CSS
    cssmin: {
      dist: {
        files: [
          { expand: true, cwd: '.', src: ['app/css/**/*.css'], dest: 'build/' }
        ]
      }
    },

    copy: {
      common: {
        files: [
          { expand: true, cwd: '.', src: ['app/lib/**'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['app/audio/**'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['app/data/**'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['LICENSE'], dest: 'build/app/' },
          { expand: true, cwd: '.', src: ['app/README.txt'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['app/_locales/**'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['app/images/*.svg'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['app/images/*.xcf'], dest: 'build/' }
        ]
      },

      wgt: {
        files: [
          { expand: true, cwd: 'build/app/', src: ['**'], dest: 'build/wgt/' },
          { expand: true, cwd: '.', src: ['icon_128.png'], dest: 'build/wgt/' }
        ]
      },

      wgt_config: {
        files: [
          { expand: true, cwd: 'platforms/tizen-wgt/', src: ['config.xml'], dest: 'build/wgt/' }
        ],
        options:
        {
          processContent: function(content, srcpath)
          {
            return grunt.template.process(content);
          }
        }
      },

      crx: {
        files: [
          { expand: true, cwd: 'build/app/', src: ['**'], dest: 'build/crx/' },
          { expand: true, cwd: '.', src: ['icon*.png'], dest: 'build/crx/' }
        ]
      },

      crx_unpacked: {
        files: [
          { expand: true, cwd: 'build/app/', src: ['**'], dest: 'build/crx/' },
          { expand: true, cwd: 'app/', src: ['js/**'], dest: 'build/crx/' },
          { expand: true, cwd: 'app/', src: ['css/**'], dest: 'build/crx/' },
          { expand: true, cwd: 'app/', src: ['*.html'], dest: 'build/crx/' },
          { expand: true, cwd: '.', src: ['icon*.png'], dest: 'build/crx/' }
        ]
      },

      crx_manifest:
      {
        files: [
          { expand: true, cwd: 'platforms/chrome-crx/', src: ['manifest.json'], dest: 'build/crx/' }
        ],

        options:
        {
          processContent: function(content, srcpath)
          {
            return grunt.template.process(content);
          }
        }

      },

      xpk: {
        files: [
          { expand: true, cwd: 'build/app/', src: ['**'], dest: 'build/xpk/' },
          { expand: true, cwd: '.', src: ['icon*.png'], dest: 'build/xpk/' }
        ]
      },

      xpk_manifest:
      {
        files: [
          { expand: true, cwd: 'platforms/tizen-xpk/', src: ['manifest.json'], dest: 'build/xpk/' }
        ],

        options:
        {
          processContent: function(content, srcpath)
          {
            return grunt.template.process(content);
          }
        }

      },

      sdk: {
        files: [
          { expand: true, cwd: 'build/app/', src: ['**'], dest: 'build/sdk/' },
          { expand: true, cwd: 'app/', src: ['js/**'], dest: 'build/sdk/' },
          { expand: true, cwd: 'app/', src: ['css/**'], dest: 'build/sdk/' },
          { expand: true, cwd: 'app/', src: ['*.html'], dest: 'build/sdk/' },
          { expand: true, cwd: '.', src: ['icon*.png'], dest: 'build/sdk/' }
        ]
      },

      sdk_platform:
      {
        files: [
          { expand: true, cwd: 'platforms/tizen-sdk/', src: ['.project'], dest: 'build/sdk/' },
          { expand: true, cwd: 'platforms/tizen-wgt/', src: ['config.xml'], dest: 'build/sdk/' }
        ],

        options:
        {
          processContent: function(content, srcpath)
          {
            return grunt.template.process(content);
          }
        }

      },

    },

    htmlmin: {
      dist: {
        files: [
          { expand: true, cwd: '.', src: ['app/*.html'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['app/html/*.html'], dest: 'build/' }
        ],
        options: {
          removeComments: true,
          collapseWhitespace: true,
          removeCommentsFromCDATA: false,
          removeCDATASectionsFromCDATA: false,
          removeEmptyAttributes: true,
          removeEmptyElements: false
        }
      }
    },

    imagemin: {
      dist: {
        options: {
          optimizationLevel: 3,
          progressive: true
        },
        files: [
          { expand: true, cwd: '.', src: ['app/images/**'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['app/css/images/**'], dest: 'build/' }
        ]
      }
    },

    // make wgt package in build/ directory
    package: {
      wgt: {
        appName: '<%= packageInfo.name %>',
        version: '<%= packageInfo.version %>',
        files: 'build/wgt/**',
        stripPrefix: 'build/wgt/',
        outDir: 'build',
        suffix: '.wgt',
        addGitCommitId: false
      },
      sdk: {
        appName: '<%= packageInfo.name %>',
        version: '<%= packageInfo.version %>',
        files: 'build/sdk/**',
        stripPrefix: 'build/sdk/',
        outDir: 'build',
        suffix: '.zip'
      },
      'crx_zip': {
        appName: '<%= packageInfo.name %>-crx',
        version: '<%= packageInfo.version %>',
        files: 'build/crx/**',
        stripPrefix: 'build/crx/',
        outDir: 'build',
        suffix: '.zip'
      }
    },

    simple_server: {
      port: 30303,
      dir: 'build/app/'
    },

    tizen: {
      push: {
        action: 'push',
        localFiles: {
          pattern: 'build/*.wgt',
          filter: 'latest'
        },
        remoteDir: '/home/developer/'
      },

      install: {
        action: 'install',
        remoteFiles: {
          pattern: '/home/developer/<%= packageInfo.name %>*.wgt',
          filter: 'latest'
        }
      },

      uninstall: {
        action: 'uninstall'
      },

      start: {
        action: 'start',
        stopOnFailure: true
      },

      stop: {
        action: 'stop',
        stopOnFailure: false
      },

      debug: {
        action: 'debug',
        browserCmd: 'google-chrome %URL%',
        localPort: 9090,
        stopOnFailure: true
      }
    }
  });

  grunt.registerTask('dist', [
    'clean',
    'imagemin:dist',
    'uglify:dist',
    'cssmin:dist',
    'htmlmin:dist',
    'copy:common'
  ]);

  grunt.registerTask('crx', ['dist', 'copy:crx', 'copy:crx_manifest']);
  grunt.registerTask('crx_unpacked', [
    'clean',
    'imagemin:dist',
    'copy:common',
    'copy:crx_unpacked',
    'copy:crx_manifest',
    'package:crx_zip'
  ]);
  grunt.registerTask('wgt', ['dist', 'copy:wgt', 'copy:wgt_config', 'package:wgt']);
  grunt.registerTask('xpk', ['dist', 'copy:xpk', 'copy:xpk_manifest']);
  grunt.registerTask('sdk', [
    'clean',
    'imagemin:dist',
    'copy:common',
    'copy:sdk',
    'copy:sdk_platform',
    'package:sdk'
  ]);

  grunt.registerTask('perf', [
    'dist',
    'uglify:perf',
    'inline',
    'copy:wgt',
    'copy:wgt_config',
    'package:wgt'
  ]);

  grunt.registerTask('install', [
    'tizen:push',
    'tizen:stop',
    'tizen:uninstall',
    'tizen:install',
    'tizen:start'
  ]);

  grunt.registerTask('wait', function () {
    var done = this.async();
    setTimeout(function () {
      done();
    }, 10000);
  });

  grunt.registerTask('restart', ['tizen:stop', 'tizen:start']);

  grunt.registerTask('server', ['dist', 'simple_server']);

  grunt.registerTask('wgt-install', ['wgt', 'install']);
  grunt.registerTask('sdk-install', ['sdk', 'install']);

  grunt.registerTask('default', 'wgt');
  grunt.registerTask('apk', [
    'xpk',
    'crosswalk:x86',
    'crosswalk:arm'
  ]);
};
<commit_msg>Added shared target for crosswalk.<commit_after>module.exports = function (grunt) {

  grunt.loadNpmTasks('grunt-tizen');
  grunt.loadNpmTasks('grunt-crosswalk');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-htmlmin');
  grunt.loadNpmTasks('grunt-contrib-imagemin');
  grunt.loadNpmTasks('grunt-release');
  grunt.loadTasks('tools/grunt-tasks');

  grunt.initConfig({
    packageInfo: grunt.file.readJSON('package.json'),
    chromeInfo: grunt.file.readJSON('platforms/chrome-crx/manifest.json'),

    crosswalk: {
      shared: {
        "outDir": 'build',
        verbose: false,
        version: '<%= packageInfo.version %>',
        name: '<%= packageInfo.name %>',
        pkg: 'org.org01.webapps.<%= packageInfo.name.toLowerCase() %>',
        icon: 'icon_128.png',
        fullscreen: true,
        remoteDebugging: true,
        appRoot: 'build/xpk',
        appLocalPath: 'index.html',
        embedded: false
        //androidSDKDir: '/opt/android-sdk-linux/',
        //xwalkAndroidDir: process.env.HOME+'/Downloads/crosswalk-3.32.53.4-arm'
        //arch: 'arm',
        //androidAPIVersion: "18.0.1"
      },
      arm: {
        "outDir": 'build',
        verbose: false,
        version: '<%= packageInfo.version %>',
        name: '<%= packageInfo.name %>',
        pkg: 'org.org01.webapps.<%= packageInfo.name.toLowerCase() %>',
        icon: 'icon_128.png',
        fullscreen: true,
        remoteDebugging: true,
        appRoot: 'build/xpk',
        appLocalPath: 'index.html',
        //embedded: true,
        //androidSDKDir: '/opt/android-sdk-linux/',
        //xwalkAndroidDir: process.env.HOME+'/Downloads/crosswalk-3.32.53.4-arm'
        arch: 'arm',
        //androidAPIVersion: "18.0.1"
      },
      x86: {
        "outDir": 'build',
        verbose: false,
        version: '<%= packageInfo.version %>',
        name: '<%= packageInfo.name %>',
        pkg: 'org.org01.webapps.<%= packageInfo.name.toLowerCase() %>',
        icon: 'icon_128.png',
        fullscreen: true,
        remoteDebugging: true,
        appRoot: 'build/xpk',
        appLocalPath: 'index.html',
        //embedded: true,
        //androidSDKDir: '/opt/android-sdk-linux/',
        //xwalkAndroidDir: process.env.HOME+'/Downloads/crosswalk-3.32.53.4-x86'
        arch: 'x86',
        //androidAPIVersion: "18.0.1"
      }
    },

    clean: ['build'],

    release: {
      options: {
        npm: false,
        npmtag: false,
        tagName: 'v<%= version %>'
      }
    },

    tizen_configuration: {
      // location on the device to install the tizen-app.sh script to
      // (default: '/tmp')
      tizenAppScriptDir: '/home/developer/',

      // path to the config.xml file for the Tizen wgt file - post templating
      // (default: 'config.xml')
      configFile: 'build/wgt/config.xml',

      // path to the sdb command (default: process.env.SDB or 'sdb')
      sdbCmd: 'sdb'
    },

    // minify JS
    uglify: {
      dist: {
        files: [
          { expand: true, cwd: '.', src: 'app/js/**/*.js', dest: 'build/' }
        ]
      }
    },

    // minify CSS
    cssmin: {
      dist: {
        files: [
          { expand: true, cwd: '.', src: ['app/css/**/*.css'], dest: 'build/' }
        ]
      }
    },

    copy: {
      common: {
        files: [
          { expand: true, cwd: '.', src: ['app/lib/**'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['app/audio/**'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['app/data/**'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['LICENSE'], dest: 'build/app/' },
          { expand: true, cwd: '.', src: ['app/README.txt'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['app/_locales/**'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['app/images/*.svg'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['app/images/*.xcf'], dest: 'build/' }
        ]
      },

      wgt: {
        files: [
          { expand: true, cwd: 'build/app/', src: ['**'], dest: 'build/wgt/' },
          { expand: true, cwd: '.', src: ['icon_128.png'], dest: 'build/wgt/' }
        ]
      },

      wgt_config: {
        files: [
          { expand: true, cwd: 'platforms/tizen-wgt/', src: ['config.xml'], dest: 'build/wgt/' }
        ],
        options:
        {
          processContent: function(content, srcpath)
          {
            return grunt.template.process(content);
          }
        }
      },

      crx: {
        files: [
          { expand: true, cwd: 'build/app/', src: ['**'], dest: 'build/crx/' },
          { expand: true, cwd: '.', src: ['icon*.png'], dest: 'build/crx/' }
        ]
      },

      crx_unpacked: {
        files: [
          { expand: true, cwd: 'build/app/', src: ['**'], dest: 'build/crx/' },
          { expand: true, cwd: 'app/', src: ['js/**'], dest: 'build/crx/' },
          { expand: true, cwd: 'app/', src: ['css/**'], dest: 'build/crx/' },
          { expand: true, cwd: 'app/', src: ['*.html'], dest: 'build/crx/' },
          { expand: true, cwd: '.', src: ['icon*.png'], dest: 'build/crx/' }
        ]
      },

      crx_manifest:
      {
        files: [
          { expand: true, cwd: 'platforms/chrome-crx/', src: ['manifest.json'], dest: 'build/crx/' }
        ],

        options:
        {
          processContent: function(content, srcpath)
          {
            return grunt.template.process(content);
          }
        }

      },

      xpk: {
        files: [
          { expand: true, cwd: 'build/app/', src: ['**'], dest: 'build/xpk/' },
          { expand: true, cwd: '.', src: ['icon*.png'], dest: 'build/xpk/' }
        ]
      },

      xpk_manifest:
      {
        files: [
          { expand: true, cwd: 'platforms/tizen-xpk/', src: ['manifest.json'], dest: 'build/xpk/' }
        ],

        options:
        {
          processContent: function(content, srcpath)
          {
            return grunt.template.process(content);
          }
        }

      },

      sdk: {
        files: [
          { expand: true, cwd: 'build/app/', src: ['**'], dest: 'build/sdk/' },
          { expand: true, cwd: 'app/', src: ['js/**'], dest: 'build/sdk/' },
          { expand: true, cwd: 'app/', src: ['css/**'], dest: 'build/sdk/' },
          { expand: true, cwd: 'app/', src: ['*.html'], dest: 'build/sdk/' },
          { expand: true, cwd: '.', src: ['icon*.png'], dest: 'build/sdk/' }
        ]
      },

      sdk_platform:
      {
        files: [
          { expand: true, cwd: 'platforms/tizen-sdk/', src: ['.project'], dest: 'build/sdk/' },
          { expand: true, cwd: 'platforms/tizen-wgt/', src: ['config.xml'], dest: 'build/sdk/' }
        ],

        options:
        {
          processContent: function(content, srcpath)
          {
            return grunt.template.process(content);
          }
        }

      },

    },

    htmlmin: {
      dist: {
        files: [
          { expand: true, cwd: '.', src: ['app/*.html'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['app/html/*.html'], dest: 'build/' }
        ],
        options: {
          removeComments: true,
          collapseWhitespace: true,
          removeCommentsFromCDATA: false,
          removeCDATASectionsFromCDATA: false,
          removeEmptyAttributes: true,
          removeEmptyElements: false
        }
      }
    },

    imagemin: {
      dist: {
        options: {
          optimizationLevel: 3,
          progressive: true
        },
        files: [
          { expand: true, cwd: '.', src: ['app/images/**'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['app/css/images/**'], dest: 'build/' }
        ]
      }
    },

    // make wgt package in build/ directory
    package: {
      wgt: {
        appName: '<%= packageInfo.name %>',
        version: '<%= packageInfo.version %>',
        files: 'build/wgt/**',
        stripPrefix: 'build/wgt/',
        outDir: 'build',
        suffix: '.wgt',
        addGitCommitId: false
      },
      sdk: {
        appName: '<%= packageInfo.name %>',
        version: '<%= packageInfo.version %>',
        files: 'build/sdk/**',
        stripPrefix: 'build/sdk/',
        outDir: 'build',
        suffix: '.zip'
      },
      'crx_zip': {
        appName: '<%= packageInfo.name %>-crx',
        version: '<%= packageInfo.version %>',
        files: 'build/crx/**',
        stripPrefix: 'build/crx/',
        outDir: 'build',
        suffix: '.zip'
      }
    },

    simple_server: {
      port: 30303,
      dir: 'build/app/'
    },

    tizen: {
      push: {
        action: 'push',
        localFiles: {
          pattern: 'build/*.wgt',
          filter: 'latest'
        },
        remoteDir: '/home/developer/'
      },

      install: {
        action: 'install',
        remoteFiles: {
          pattern: '/home/developer/<%= packageInfo.name %>*.wgt',
          filter: 'latest'
        }
      },

      uninstall: {
        action: 'uninstall'
      },

      start: {
        action: 'start',
        stopOnFailure: true
      },

      stop: {
        action: 'stop',
        stopOnFailure: false
      },

      debug: {
        action: 'debug',
        browserCmd: 'google-chrome %URL%',
        localPort: 9090,
        stopOnFailure: true
      }
    }
  });

  grunt.registerTask('dist', [
    'clean',
    'imagemin:dist',
    'uglify:dist',
    'cssmin:dist',
    'htmlmin:dist',
    'copy:common'
  ]);

  grunt.registerTask('crx', ['dist', 'copy:crx', 'copy:crx_manifest']);
  grunt.registerTask('crx_unpacked', [
    'clean',
    'imagemin:dist',
    'copy:common',
    'copy:crx_unpacked',
    'copy:crx_manifest',
    'package:crx_zip'
  ]);
  grunt.registerTask('wgt', ['dist', 'copy:wgt', 'copy:wgt_config', 'package:wgt']);
  grunt.registerTask('xpk', ['dist', 'copy:xpk', 'copy:xpk_manifest']);
  grunt.registerTask('sdk', [
    'clean',
    'imagemin:dist',
    'copy:common',
    'copy:sdk',
    'copy:sdk_platform',
    'package:sdk'
  ]);

  grunt.registerTask('perf', [
    'dist',
    'uglify:perf',
    'inline',
    'copy:wgt',
    'copy:wgt_config',
    'package:wgt'
  ]);

  grunt.registerTask('install', [
    'tizen:push',
    'tizen:stop',
    'tizen:uninstall',
    'tizen:install',
    'tizen:start'
  ]);

  grunt.registerTask('wait', function () {
    var done = this.async();
    setTimeout(function () {
      done();
    }, 10000);
  });

  grunt.registerTask('restart', ['tizen:stop', 'tizen:start']);

  grunt.registerTask('server', ['dist', 'simple_server']);

  grunt.registerTask('wgt-install', ['wgt', 'install']);
  grunt.registerTask('sdk-install', ['sdk', 'install']);

  grunt.registerTask('default', 'wgt');
  grunt.registerTask('apk', [
    'xpk',
    'crosswalk:x86',
    'crosswalk:arm'
  ]);
};
<|endoftext|>


<commit_before>'use strict';
module.exports = function(grunt) {
  // Load all tasks
  require('load-grunt-tasks')(grunt);
  // Show elapsed time
  require('time-grunt')(grunt);

  var jsFileList = [
    'assets/vendor/bootstrap/js/transition.js',
    'assets/vendor/bootstrap/js/alert.js',
    'assets/vendor/bootstrap/js/button.js',
    'assets/vendor/bootstrap/js/carousel.js',
    'assets/vendor/bootstrap/js/collapse.js',
    'assets/vendor/bootstrap/js/dropdown.js',
    'assets/vendor/bootstrap/js/modal.js',
    'assets/vendor/bootstrap/js/tooltip.js',
    'assets/vendor/bootstrap/js/popover.js',
    'assets/vendor/bootstrap/js/scrollspy.js',
    'assets/vendor/bootstrap/js/tab.js',
    'assets/vendor/bootstrap/js/affix.js',
    'assets/js/plugins/*.js',
    'assets/js/_*.js'
  ];

  grunt.initConfig({
    jshint: {
      options: {
        jshintrc: '.jshintrc'
      },
      all: [
        'Gruntfile.js',
        'assets/js/*.js',
        '!assets/js/scripts.js',
        '!assets/**/*.min.*'
      ]
    },
    less: {
      dev: {
        files: {
          'assets/css/main.css': [
            'assets/less/main.less'
          ]
        },
        options: {
          compress: false,
          // LESS source map
          // To enable, set sourceMap to true and update sourceMapRootpath based on your install
          sourceMap: true,
          sourceMapFilename: 'assets/css/main.css.map',
          sourceMapRootpath: '/app/themes/roots/'
        }
      },
      build: {
        files: {
          'assets/css/main.min.css': [
            'assets/less/main.less'
          ]
        },
        options: {
          compress: true
        }
      }
    },
    concat: {
      options: {
        separator: ';',
      },
      dist: {
        src: [jsFileList],
        dest: 'assets/js/scripts.js',
      },
    },
    uglify: {
      dist: {
        files: {
          'assets/js/scripts.min.js': [jsFileList]
        }
      }
    },
    autoprefixer: {
      options: {
        browsers: ['last 2 versions', 'ie 8', 'ie 9', 'android 2.3', 'android 4', 'opera 12']
      },
      dev: {
        options: {
          map: {
            prev: 'assets/css/'
          }
        },
        src: 'assets/css/main.css'
      },
      build: {
        src: 'assets/css/main.min.css'
      }
    },
    modernizr: {
      build: {
        devFile: 'assets/vendor/modernizr/modernizr.js',
        outputFile: 'assets/js/vendor/modernizr.min.js',
        files: {
          'src': [
            ['assets/js/scripts.min.js'],
            ['assets/css/main.min.css']
          ]
        },
        uglify: true,
        parseFiles: true
      }
    },
    version: {
      default: {
        options: {
          format: true,
          length: 32,
          manifest: 'assets/manifest.json',
          querystring: {
            style: 'roots_css',
            script: 'roots_js'
          }
        },
        files: {
          'lib/scripts.php': 'assets/{css,js}/{main,scripts}.min.{css,js}'
        }
      }
    },
    watch: {
      less: {
        files: [
          'assets/less/*.less',
          'assets/less/**/*.less'
        ],
        tasks: ['less:dev', 'autoprefixer:dev']
      },
      js: {
        files: [
          jsFileList,
          '<%= jshint.all %>'
        ],
        tasks: ['jshint', 'concat']
      },
      livereload: {
        // Browser live reloading
        // https://github.com/gruntjs/grunt-contrib-watch#live-reloading
        options: {
          livereload: false
        },
        files: [
          'assets/css/main.css',
          'assets/js/scripts.js',
          'templates/*.php',
          '*.php'
        ]
      }
    }
  });

  // Register tasks
  grunt.registerTask('default', [
    'dev'
  ]);
  grunt.registerTask('dev', [
    'jshint',
    'less:dev',
    'autoprefixer:dev',
    'concat'
  ]);
  grunt.registerTask('build', [
    'jshint',
    'less:build',
    'autoprefixer:build',
    'uglify',
    'modernizr',
    'version'
  ]);
};
<commit_msg>Remove HTML5 shiv from Modernizr build<commit_after>'use strict';
module.exports = function(grunt) {
  // Load all tasks
  require('load-grunt-tasks')(grunt);
  // Show elapsed time
  require('time-grunt')(grunt);

  var jsFileList = [
    'assets/vendor/bootstrap/js/transition.js',
    'assets/vendor/bootstrap/js/alert.js',
    'assets/vendor/bootstrap/js/button.js',
    'assets/vendor/bootstrap/js/carousel.js',
    'assets/vendor/bootstrap/js/collapse.js',
    'assets/vendor/bootstrap/js/dropdown.js',
    'assets/vendor/bootstrap/js/modal.js',
    'assets/vendor/bootstrap/js/tooltip.js',
    'assets/vendor/bootstrap/js/popover.js',
    'assets/vendor/bootstrap/js/scrollspy.js',
    'assets/vendor/bootstrap/js/tab.js',
    'assets/vendor/bootstrap/js/affix.js',
    'assets/js/plugins/*.js',
    'assets/js/_*.js'
  ];

  grunt.initConfig({
    jshint: {
      options: {
        jshintrc: '.jshintrc'
      },
      all: [
        'Gruntfile.js',
        'assets/js/*.js',
        '!assets/js/scripts.js',
        '!assets/**/*.min.*'
      ]
    },
    less: {
      dev: {
        files: {
          'assets/css/main.css': [
            'assets/less/main.less'
          ]
        },
        options: {
          compress: false,
          // LESS source map
          // To enable, set sourceMap to true and update sourceMapRootpath based on your install
          sourceMap: true,
          sourceMapFilename: 'assets/css/main.css.map',
          sourceMapRootpath: '/app/themes/roots/'
        }
      },
      build: {
        files: {
          'assets/css/main.min.css': [
            'assets/less/main.less'
          ]
        },
        options: {
          compress: true
        }
      }
    },
    concat: {
      options: {
        separator: ';',
      },
      dist: {
        src: [jsFileList],
        dest: 'assets/js/scripts.js',
      },
    },
    uglify: {
      dist: {
        files: {
          'assets/js/scripts.min.js': [jsFileList]
        }
      }
    },
    autoprefixer: {
      options: {
        browsers: ['last 2 versions', 'ie 8', 'ie 9', 'android 2.3', 'android 4', 'opera 12']
      },
      dev: {
        options: {
          map: {
            prev: 'assets/css/'
          }
        },
        src: 'assets/css/main.css'
      },
      build: {
        src: 'assets/css/main.min.css'
      }
    },
    modernizr: {
      build: {
        devFile: 'assets/vendor/modernizr/modernizr.js',
        outputFile: 'assets/js/vendor/modernizr.min.js',
        files: {
          'src': [
            ['assets/js/scripts.min.js'],
            ['assets/css/main.min.css']
          ]
        },
        extra: {
          shiv: false
        },
        uglify: true,
        parseFiles: true
      }
    },
    version: {
      default: {
        options: {
          format: true,
          length: 32,
          manifest: 'assets/manifest.json',
          querystring: {
            style: 'roots_css',
            script: 'roots_js'
          }
        },
        files: {
          'lib/scripts.php': 'assets/{css,js}/{main,scripts}.min.{css,js}'
        }
      }
    },
    watch: {
      less: {
        files: [
          'assets/less/*.less',
          'assets/less/**/*.less'
        ],
        tasks: ['less:dev', 'autoprefixer:dev']
      },
      js: {
        files: [
          jsFileList,
          '<%= jshint.all %>'
        ],
        tasks: ['jshint', 'concat']
      },
      livereload: {
        // Browser live reloading
        // https://github.com/gruntjs/grunt-contrib-watch#live-reloading
        options: {
          livereload: false
        },
        files: [
          'assets/css/main.css',
          'assets/js/scripts.js',
          'templates/*.php',
          '*.php'
        ]
      }
    }
  });

  // Register tasks
  grunt.registerTask('default', [
    'dev'
  ]);
  grunt.registerTask('dev', [
    'jshint',
    'less:dev',
    'autoprefixer:dev',
    'concat'
  ]);
  grunt.registerTask('build', [
    'jshint',
    'less:build',
    'autoprefixer:build',
    'uglify',
    'modernizr',
    'version'
  ]);
};
<|endoftext|>


<commit_before>'use strict';

module.exports = function (grunt) {
  // Helper function to load pre-defined grunt tasks
  require('load-grunt-tasks')(grunt);

  // Configures grunt tasks
  grunt.initConfig({
    clean: {
      dist: {
        files: [
          {
            dot: true,
            src: ['dist', 'tmp']
          }
        ]
      },
      // remove Javascript sourcemaps from production bundle
      release: ['dist/*.js.map'],
    },

    handlebars: {
      compile: {
        options: {
          namespace: 'mmooc.templates',
          processName: function (filePath) {
            return filePath
              .replace('src/templates/modules/', '')
              .replace('src/addons/badges/templates/', '')
              .replace(/\.hbs$/, '');
          }
        },
        files: {
          'tmp/templates.js': ['src/templates/**/*.hbs'],
          'tmp/badges_template.js': ['src/addons/badges/templates/*.hbs']
        }
      }
    },

    less: {
      all: {
        options: {
          cleancss: true
        },
        files: {
          'tmp/mmooc-min.css': ['src/css/all.less'],
          'dist/badgesafe.css': ['src/addons/badges/css/all.less'],
          'tmp/rootaccount.css': ['src/css/allrootaccount.less']
        }
      }
    },

    concat: {
      options: {
        sourceMap: true,
      },
      js: {
        src: [
          'src/js/3party/*.js',
          'tmp/templates.js',
          'src/js/api/*.js',
          'src/js/settingsRoot.js',
          'src/js/utilRoot.js',
          'src/js/modules/*.js',
          'src/js/settings.js',
          'src/js/i18n.js',
          'src/js/main.js',
          'src/addons/canva_badges/js/*.js'
        ],
        dest: 'tmp/mmooc.js'
      },
      rootaccount: {
        src: ['src/js/settingsRoot.js', 'src/js/utilRoot.js', 'src/js/rootaccount.js'],
        dest: 'tmp/rootaccount.js'
      },
      subaccount: {
        src: ['src/js/settingsRoot.js', 'src/js/utilRoot.js', 'src/js/subaccount.js'],
        dest: 'tmp/subaccount.js'
      },
      extras: {
        src: [
          'node_modules/grunt-contrib-handlebars/node_modules/handlebars/dist/handlebars.min.js', // we need to embed handlebars here because it is not included in the iframe
          'tmp/badges_template.js',
          'src/addons/badges/js/*.js',
          'src/js/modules/template.js',
          'src/js/modules/util.js',
          'src/js/i18n.js',
          'src/js/settings.js'
        ],
        dest: 'tmp/badges-min.js'
      },
      uia: {
        src: ['src/js/i18nuia.js', 'src/js/settingsuia.js'],
        dest: 'dist/uia.js'
      },
    },

    babel: {
      options: {
        sourceType: "script",
        presets: ['@babel/preset-env'],
        compact: false,
        sourceMap: true,
      },
      dist: {
        files: {
          'tmp/mmooc-babel.js': 'tmp/mmooc.js'
        }
      }
    },

    uglify: {
      options: {
        sourceMap: {
          includeSources: true
        },
        sourceMapIn: 'tmp/mmooc-babel.js.map', // input sourcemap from a previous compilation
      },
      dist: {
        files: {
          'dist/mmooc-min.js': ['tmp/mmooc-babel.js']
        }
      }
    },

    replace: {
      production: {
        src: ['tmp/mmooc-min.css','tmp/rootaccount.css', 'dist/mmooc-min.js', 'tmp/rootaccount.js', 'tmp/subaccount.js'],
        dest: 'dist/',
        replacements: [
          {
            from: 'https://server',
            to: 'https://kompetanseudirno.azureedge.net/udirdesign'
          },
          {
            from: 'https://udirdesigncss',
            to: 'https://kompetanseudirno.azureedge.net/udirdesign/mmooc-min.css?version=5'
          },
          {
            from: 'https://udirdesignjs',
            to: 'https://kompetanseudirno.azureedge.net/udirdesign/mmooc-min.js?version=5'
          },
          {
            from: '$KPASAPIURL',
            to: '\'https://kpas-lti.azurewebsites.net/api/\''
          }
        ]
      },
      development: {
        src: ['tmp/mmooc-min.css','tmp/rootaccount.css', 'dist/mmooc-min.js', 'tmp/rootaccount.js','tmp/subaccount.js'],
        dest: 'dist/',
        replacements: [
          {
            from: 'https://server',
            to: 'http://localhost:9000'
          },
          {
            from: 'https://udirdesigncss',
            to: 'http://localhost:9000/mmooc-min.css'
          },
          {
            from: 'https://udirdesignjs',
            to: 'http://localhost:9000/mmooc-min.js'
          },
          {
            from: '$KPASAPIURL',
            to: '\'' + process.env.KPAS_URL + '/api/\''
          }
        ]
      },
      production_dataporten: {
        src: ['src/js/tmp/dataporten.js'],
        dest: 'src/js/modules/',
        replacements: [
          {
            from: '$REQUEST',
            to: "['email','longterm', 'openid', 'profile', 'userid-feide', 'groups', 'gk_kpas']"
          },
          {
            from: '$DATAPORTENCALLBACK',
            to: 'https://bibsys.instructure.com/courses/234?dataportenCallback=1'
          },
          {
            from: '$DATAPORTENCLIENTID',
            to: '823e54e4-9cb7-438f-b551-d1af9de0c2cd'
          },
          {
            from: '$KPASAPIURL',
            to: 'https://kpas.dataporten-api.no'
          }
        ]
      },
      development_dataporten: {
        src: ['src/js/tmp/dataporten.js'],
        dest: 'src/js/modules/',
        replacements: [
          {
            from: '$REQUEST',
            to: "['email','longterm', 'openid', 'profile', 'userid-feide', 'groups', 'gk_netgurukpasapi']"
          },          {
            from: '$DATAPORTENCALLBACK',
            to: 'https://localhost/courses/1?dataportenCallback=1'
          },          {
            from: '$DATAPORTENCLIENTID',
            to: 'fb2f6378-2d35-4354-8ae8-2e82e2af2a8f'
          },          {
            from: '$KPASAPIURL',
            to: 'https://netgurukpasapi.dataporten-api.no'
          }
        ]
      },
      production_settings: {
        src: ['src/js/tmp/settings.js'],
        dest: 'src/js/',
        replacements: [
          {
            from: '$ACCOUNTID',
            to: '[99, 100, 102, 103, 137, 138, 139, 145]'
          }
        ]
      },
      development_settings: {
        src: ['src/js/tmp/settings.js'],
        dest: 'src/js/',
        replacements: [
          {
            from: '$ACCOUNTID',
            to: '[4, 5]'
          }
        ]
      },
      production_badge: {
        src: ['tmp/badges-min.js'],
        dest: 'dist/badgesafe.js',
        replacements: [
          {
            from: 'https://server',
            to: 'https://matematikk-mooc.github.io/frontend'
          }
        ]
      },
      development_badge: {
        src: ['tmp/badges-min.js'],
        dest: 'dist/badges-dev.js',
        replacements: [
          {
            from: 'https://server',
            to: 'http://localhost:9000'
          }
        ]
      }
    },

    copy: {
      main: {
        files: [
          { expand: true, src: ['rootaccount*'], cwd: 'src/css/', dest: 'dist/' },
          { expand: true, src: ['subaccount*'], cwd: 'src/css/', dest: 'dist/' },
          { expand: true, src: ['bitmaps/*'], cwd: 'src/', dest: 'dist/' },
          { expand: true, src: ['vector_images/*'], cwd: 'src/', dest: 'dist/' },
          { expand: true, src: ['subaccount.js.map'], cwd: 'tmp/', dest: 'dist/' },
          { expand: true, src: ['rootaccount.js.map'], cwd: 'tmp/', dest: 'dist/' },
          { expand: true, src: ['badges-min.js.map'], cwd: 'tmp/', dest: 'dist/' }
        ]
      }
    },

    connect: {
      staging: { //setup fo staging
        options: {
          port: 3000,
          base: 'dist',
          hostname: '*',
          open: true
        }
      },
      dev: { //setup fo local development
        options: {
          port: 9000,
          base: 'dist',
          hostname: 'localhost',
          open: true
        }
      },
      test: {
        options: {
          port: 9988,
          base: ['spec', 'src/js/api', 'src/js/modules', 'src/js']
        }
      }
    },

    watch: {
      dist: {
        files: [
          'src/css/**/*.less',
          'src/js/**/*.js',
          'src/templates/**/*.hbs',
          'src/addons/badges/js/*.js',
          'src/addons/badges/css/*.less',
          'Gruntfile.js'
        ],
        tasks: ['rebuildServe']
      }
    },

    karma: {
      unitTest: {
        configFile: 'test/js/karma.conf.js',
        autoWatch: false,
        singleRun: true,
        browsers:
          process.env.KARMA_BROWSER == null
            ? ['Firefox', 'Chrome']
            : ['Firefox', 'Chrome', '<%= extraBrowser %>']
      }
    }
  });

  grunt.registerTask('make', [
    'handlebars',
    'concat',
    'babel',
    'uglify',
    'less',
    'copy',
  ]);

  grunt.registerTask('dev_dataporten', [
    'replace:development_dataporten'
  ]);

  grunt.registerTask('prod_dataporten', [
    'replace:production_dataporten'
  ]);

  grunt.registerTask('dev_settings', [
    'replace:development_settings',
    'replace:development',
    'replace:development_badge',
  ]);
  grunt.registerTask('dev_development', [
    'replace:development',
  ]);
  grunt.registerTask('prod_production', [
    'replace:production',
  ]);

  grunt.registerTask('prod_settings', [
    'replace:production_settings',
    'replace:production_badge',
  ]);

  grunt.registerTask('runTest', ['connect:test', 'karma:unitTest']);

  grunt.registerTask('test', ['clean', 'make', 'runTest']);

  grunt.registerTask('build', ['prod_dataporten', 'prod_settings', 'make', 'prod_production']);

  grunt.registerTask('rebuildServe', ['clean:dist', 'dev_dataporten', 'dev_settings', 'make', 'dev_development']);

  grunt.registerTask('serve', ['clean', 'dev_dataporten', 'dev_settings',  'make',  'dev_development','connect:dev', 'watch']);

  grunt.registerTask('serveStaging', ['clean', 'make', 'connect:staging', 'watch']);

  grunt.registerTask('default', ['clean', 'make']);
};
<commit_msg>Bump version number 6<commit_after>'use strict';

module.exports = function (grunt) {
  // Helper function to load pre-defined grunt tasks
  require('load-grunt-tasks')(grunt);

  // Configures grunt tasks
  grunt.initConfig({
    clean: {
      dist: {
        files: [
          {
            dot: true,
            src: ['dist', 'tmp']
          }
        ]
      },
      // remove Javascript sourcemaps from production bundle
      release: ['dist/*.js.map'],
    },

    handlebars: {
      compile: {
        options: {
          namespace: 'mmooc.templates',
          processName: function (filePath) {
            return filePath
              .replace('src/templates/modules/', '')
              .replace('src/addons/badges/templates/', '')
              .replace(/\.hbs$/, '');
          }
        },
        files: {
          'tmp/templates.js': ['src/templates/**/*.hbs'],
          'tmp/badges_template.js': ['src/addons/badges/templates/*.hbs']
        }
      }
    },

    less: {
      all: {
        options: {
          cleancss: true
        },
        files: {
          'tmp/mmooc-min.css': ['src/css/all.less'],
          'dist/badgesafe.css': ['src/addons/badges/css/all.less'],
          'tmp/rootaccount.css': ['src/css/allrootaccount.less']
        }
      }
    },

    concat: {
      options: {
        sourceMap: true,
      },
      js: {
        src: [
          'src/js/3party/*.js',
          'tmp/templates.js',
          'src/js/api/*.js',
          'src/js/settingsRoot.js',
          'src/js/utilRoot.js',
          'src/js/modules/*.js',
          'src/js/settings.js',
          'src/js/i18n.js',
          'src/js/main.js',
          'src/addons/canva_badges/js/*.js'
        ],
        dest: 'tmp/mmooc.js'
      },
      rootaccount: {
        src: ['src/js/settingsRoot.js', 'src/js/utilRoot.js', 'src/js/rootaccount.js'],
        dest: 'tmp/rootaccount.js'
      },
      subaccount: {
        src: ['src/js/settingsRoot.js', 'src/js/utilRoot.js', 'src/js/subaccount.js'],
        dest: 'tmp/subaccount.js'
      },
      extras: {
        src: [
          'node_modules/grunt-contrib-handlebars/node_modules/handlebars/dist/handlebars.min.js', // we need to embed handlebars here because it is not included in the iframe
          'tmp/badges_template.js',
          'src/addons/badges/js/*.js',
          'src/js/modules/template.js',
          'src/js/modules/util.js',
          'src/js/i18n.js',
          'src/js/settings.js'
        ],
        dest: 'tmp/badges-min.js'
      },
      uia: {
        src: ['src/js/i18nuia.js', 'src/js/settingsuia.js'],
        dest: 'dist/uia.js'
      },
    },

    babel: {
      options: {
        sourceType: "script",
        presets: ['@babel/preset-env'],
        compact: false,
        sourceMap: true,
      },
      dist: {
        files: {
          'tmp/mmooc-babel.js': 'tmp/mmooc.js'
        }
      }
    },

    uglify: {
      options: {
        sourceMap: {
          includeSources: true
        },
        sourceMapIn: 'tmp/mmooc-babel.js.map', // input sourcemap from a previous compilation
      },
      dist: {
        files: {
          'dist/mmooc-min.js': ['tmp/mmooc-babel.js']
        }
      }
    },

    replace: {
      production: {
        src: ['tmp/mmooc-min.css','tmp/rootaccount.css', 'dist/mmooc-min.js', 'tmp/rootaccount.js', 'tmp/subaccount.js'],
        dest: 'dist/',
        replacements: [
          {
            from: 'https://server',
            to: 'https://kompetanseudirno.azureedge.net/udirdesign'
          },
          {
            from: 'https://udirdesigncss',
            to: 'https://kompetanseudirno.azureedge.net/udirdesign/mmooc-min.css?version=6'
          },
          {
            from: 'https://udirdesignjs',
            to: 'https://kompetanseudirno.azureedge.net/udirdesign/mmooc-min.js?version=6'
          },
          {
            from: '$KPASAPIURL',
            to: '\'https://kpas-lti.azurewebsites.net/api/\''
          }
        ]
      },
      development: {
        src: ['tmp/mmooc-min.css','tmp/rootaccount.css', 'dist/mmooc-min.js', 'tmp/rootaccount.js','tmp/subaccount.js'],
        dest: 'dist/',
        replacements: [
          {
            from: 'https://server',
            to: 'http://localhost:9000'
          },
          {
            from: 'https://udirdesigncss',
            to: 'http://localhost:9000/mmooc-min.css'
          },
          {
            from: 'https://udirdesignjs',
            to: 'http://localhost:9000/mmooc-min.js'
          },
          {
            from: '$KPASAPIURL',
            to: '\'' + process.env.KPAS_URL + '/api/\''
          }
        ]
      },
      production_dataporten: {
        src: ['src/js/tmp/dataporten.js'],
        dest: 'src/js/modules/',
        replacements: [
          {
            from: '$REQUEST',
            to: "['email','longterm', 'openid', 'profile', 'userid-feide', 'groups', 'gk_kpas']"
          },
          {
            from: '$DATAPORTENCALLBACK',
            to: 'https://bibsys.instructure.com/courses/234?dataportenCallback=1'
          },
          {
            from: '$DATAPORTENCLIENTID',
            to: '823e54e4-9cb7-438f-b551-d1af9de0c2cd'
          },
          {
            from: '$KPASAPIURL',
            to: 'https://kpas.dataporten-api.no'
          }
        ]
      },
      development_dataporten: {
        src: ['src/js/tmp/dataporten.js'],
        dest: 'src/js/modules/',
        replacements: [
          {
            from: '$REQUEST',
            to: "['email','longterm', 'openid', 'profile', 'userid-feide', 'groups', 'gk_netgurukpasapi']"
          },          {
            from: '$DATAPORTENCALLBACK',
            to: 'https://localhost/courses/1?dataportenCallback=1'
          },          {
            from: '$DATAPORTENCLIENTID',
            to: 'fb2f6378-2d35-4354-8ae8-2e82e2af2a8f'
          },          {
            from: '$KPASAPIURL',
            to: 'https://netgurukpasapi.dataporten-api.no'
          }
        ]
      },
      production_settings: {
        src: ['src/js/tmp/settings.js'],
        dest: 'src/js/',
        replacements: [
          {
            from: '$ACCOUNTID',
            to: '[99, 100, 102, 103, 137, 138, 139, 145]'
          }
        ]
      },
      development_settings: {
        src: ['src/js/tmp/settings.js'],
        dest: 'src/js/',
        replacements: [
          {
            from: '$ACCOUNTID',
            to: '[4, 5]'
          }
        ]
      },
      production_badge: {
        src: ['tmp/badges-min.js'],
        dest: 'dist/badgesafe.js',
        replacements: [
          {
            from: 'https://server',
            to: 'https://matematikk-mooc.github.io/frontend'
          }
        ]
      },
      development_badge: {
        src: ['tmp/badges-min.js'],
        dest: 'dist/badges-dev.js',
        replacements: [
          {
            from: 'https://server',
            to: 'http://localhost:9000'
          }
        ]
      }
    },

    copy: {
      main: {
        files: [
          { expand: true, src: ['rootaccount*'], cwd: 'src/css/', dest: 'dist/' },
          { expand: true, src: ['subaccount*'], cwd: 'src/css/', dest: 'dist/' },
          { expand: true, src: ['bitmaps/*'], cwd: 'src/', dest: 'dist/' },
          { expand: true, src: ['vector_images/*'], cwd: 'src/', dest: 'dist/' },
          { expand: true, src: ['subaccount.js.map'], cwd: 'tmp/', dest: 'dist/' },
          { expand: true, src: ['rootaccount.js.map'], cwd: 'tmp/', dest: 'dist/' },
          { expand: true, src: ['badges-min.js.map'], cwd: 'tmp/', dest: 'dist/' }
        ]
      }
    },

    connect: {
      staging: { //setup fo staging
        options: {
          port: 3000,
          base: 'dist',
          hostname: '*',
          open: true
        }
      },
      dev: { //setup fo local development
        options: {
          port: 9000,
          base: 'dist',
          hostname: 'localhost',
          open: true
        }
      },
      test: {
        options: {
          port: 9988,
          base: ['spec', 'src/js/api', 'src/js/modules', 'src/js']
        }
      }
    },

    watch: {
      dist: {
        files: [
          'src/css/**/*.less',
          'src/js/**/*.js',
          'src/templates/**/*.hbs',
          'src/addons/badges/js/*.js',
          'src/addons/badges/css/*.less',
          'Gruntfile.js'
        ],
        tasks: ['rebuildServe']
      }
    },

    karma: {
      unitTest: {
        configFile: 'test/js/karma.conf.js',
        autoWatch: false,
        singleRun: true,
        browsers:
          process.env.KARMA_BROWSER == null
            ? ['Firefox', 'Chrome']
            : ['Firefox', 'Chrome', '<%= extraBrowser %>']
      }
    }
  });

  grunt.registerTask('make', [
    'handlebars',
    'concat',
    'babel',
    'uglify',
    'less',
    'copy',
  ]);

  grunt.registerTask('dev_dataporten', [
    'replace:development_dataporten'
  ]);

  grunt.registerTask('prod_dataporten', [
    'replace:production_dataporten'
  ]);

  grunt.registerTask('dev_settings', [
    'replace:development_settings',
    'replace:development',
    'replace:development_badge',
  ]);
  grunt.registerTask('dev_development', [
    'replace:development',
  ]);
  grunt.registerTask('prod_production', [
    'replace:production',
  ]);

  grunt.registerTask('prod_settings', [
    'replace:production_settings',
    'replace:production_badge',
  ]);

  grunt.registerTask('runTest', ['connect:test', 'karma:unitTest']);

  grunt.registerTask('test', ['clean', 'make', 'runTest']);

  grunt.registerTask('build', ['prod_dataporten', 'prod_settings', 'make', 'prod_production']);

  grunt.registerTask('rebuildServe', ['clean:dist', 'dev_dataporten', 'dev_settings', 'make', 'dev_development']);

  grunt.registerTask('serve', ['clean', 'dev_dataporten', 'dev_settings',  'make',  'dev_development','connect:dev', 'watch']);

  grunt.registerTask('serveStaging', ['clean', 'make', 'connect:staging', 'watch']);

  grunt.registerTask('default', ['clean', 'make']);
};
<|endoftext|>


<commit_before>/* Service.js
KC3改 Background Service.

It is always running, from Chrome startup until the browser is closed or explicitly terminated.
This will serve as a central script that lets devtools and content scripts communicate.
Sometimes, the scripts on different parts of the extension cannot communicate with each other, thus this can relay messages and events for them.
Sometimes, specific scripts do not have access to Chrome APIs. Those scripts can then request it to be done by this service.

Ultimately, this script handles data management on aspects that are best centralized such as:
> [Countdown Timers]
To have a consistent timer unaffected by lags on devtools and Chrome tabs
> [Quest Management]
To ensure all components are synced in real-time without relying on localStorage

The above aspects are imported into the background service, and not necessarily on this file.
See Manifest File [manifest.json] under "background" > "scripts"
*/
(function(){
	"use strict";

	console.log("KC3改 Background Service loaded");

	window.KC3Service = {

		/* SET API LINK
		API Link extracted, save and open
		------------------------------------------*/
		"set_api_link" :function(request, sender, callback){
			try {
				// Set api link on internal storage
				localStorage.absoluteswf = request.swfsrc;

				// If refreshing API link, close source tabs and re-open game frame
				if(localStorage.extract_api==="true"){
					localStorage.extract_api = false;
					window.open("../pages/game/api.html", "kc3kai_game");
					chrome.tabs.remove([sender.tab.id], function(){});
				}
			}catch(e){ console.error(e); }
		},

		/* NOTIFY DESKTOP
		Check if tab is a KC3改 frame and tell to override styles or not
		------------------------------------------*/
		"notify_desktop" :function(request, sender, callback){
			try {
				// Clear old notification first
				chrome.notifications.clear("kc3kai_"+request.notifId, function(){
					// Add notification
					chrome.notifications.create("kc3kai_"+request.notifId, request.data);
				});
			}catch(e){ console.error(e); }
		},

		/* ACTIVATE GAME
		Try to activate game inside inspected tab
		------------------------------------------*/
		"activate_game" :function(request, sender, response){
			(new TMsg(request.tabId, "gamescreen", "activate_game", {}, response)).execute();
			return true; // dual-async response
		},

		/* SCREENSHOT
		Ask the game container to take a screenshot
		------------------------------------------*/
		"screenshot" :function(request, sender, response){
			(new TMsg(
				request.tabId,
				"gamescreen",
				"screenshot",
				{ playerIndex: request.playerIndex }
			)).execute();
		}

	};

	/* Runtime Message Listener
	https://developer.chrome.com/extensions/messaging#simple
	This script will wait for messages from other parts of the extension
	and execute what they want if applicable
	*/
	chrome.runtime.onMessage.addListener(function(request, sender, callback){
		// Log message contents and sender for debugging
		console.log("Received message", request, "from", sender);

		// Check if message is intended for this script
		if( (request.identifier || false) == "kc3_service"){

			// Check requested action is supported
			if(typeof window.KC3Service[ request.action ] != "undefined"){
				// Execute and pass callback to function
				window.KC3Service[ request.action ](request, sender, callback);
				return true; // dual-async response
			}else{
				// Unknown action
				response({ success: false });
			}

		}
	});

	(new TMsg(123, "gamescreen", "activate_game")).execute();

})();<commit_msg>Background Service Cleanup<commit_after>/* Service.js
KC3改 Background Service.

It is always running, from Chrome startup until the browser is closed or explicitly terminated.
This will serve as a central script that lets devtools and content scripts communicate.
Sometimes, the scripts on different parts of the extension cannot communicate with each other, thus this can relay messages and events for them.
Sometimes, specific scripts do not have access to Chrome APIs. Those scripts can then request it to be done by this service.

Ultimately, this script handles data management on aspects that are best centralized such as:
> [Countdown Timers]
To have a consistent timer unaffected by lags on devtools and Chrome tabs
> [Quest Management]
To ensure all components are synced in real-time without relying on localStorage

The above aspects are imported into the background service, and not necessarily on this file.
See Manifest File [manifest.json] under "background" > "scripts"
*/
(function(){
	"use strict";

	console.log("KC3改 Background Service loaded");

	window.KC3Service = {

		/* SET API LINK
		From osapi content script, the API Link has been extracted
		Save the link onto localStorage and disable extracing API further
		If came from menu "Extract API Link", Open Play via API and close DMM source
		------------------------------------------*/
		"set_api_link" :function(request, sender, callback){
			try {
				// Set api link on internal storage
				localStorage.absoluteswf = request.swfsrc;

				// If refreshing API link, close source tabs and re-open game frame
				if( localStorage.extract_api === "true"){ // localStorage has problems with native boolean
					localStorage.extract_api = "false";
					window.open("../pages/game/api.html", "kc3kai_game");
					chrome.tabs.remove([sender.tab.id], function(){});
				}
			}catch(e){ console.error(e); }
		},

		/* NOTIFY DESKTOP
		Devtools do not have access to chrome.notifications API
		Panel can request this background service to do notifications
		------------------------------------------*/
		"notify_desktop" :function(request, sender, callback){
			try {
				// Clear old notification first
				chrome.notifications.clear("kc3kai_"+request.notifId, function(){
					// Add notification
					chrome.notifications.create("kc3kai_"+request.notifId, request.data);
				});
			}catch(e){ console.error(e); }
		},

		/* ACTIVATE GAME
		Try to activate game inside inspected tab
		------------------------------------------*/
		"activate_game" :function(request, sender, response){
			(new TMsg(request.tabId, "gamescreen", "activate_game", {}, response)).execute();
			return true; // dual-async response
		},

		/* SCREENSHOT
		Ask the game container to take a screenshot
		------------------------------------------*/
		"screenshot" :function(request, sender, response){
			(new TMsg(
				request.tabId,
				"gamescreen",
				"screenshot",
				{ playerIndex: request.playerIndex }
			)).execute();
		}

	};

	/* Runtime Message Listener
	https://developer.chrome.com/extensions/messaging#simple
	This script will wait for messages from other parts of the extension
	and execute what they want if applicable
	*/
	chrome.runtime.onMessage.addListener(function(request, sender, callback){
		// Log message contents and sender for debugging
		console.log("Received message", request, "from", sender);

		// Check if message is intended for this script
		if( (request.identifier || false) == "kc3_service"){

			// Check requested action is supported
			if(typeof window.KC3Service[ request.action ] != "undefined"){
				// Execute and pass callback to function
				window.KC3Service[ request.action ](request, sender, callback);
				return true; // dual-async response
			}else{
				// Unknown action
				response({ success: false });
			}

		}
	});

})();<|endoftext|>


<commit_before>'use strict';

module.exports = function(grunt) {

  grunt.initConfig({
    json_merge: {
      options: {
        replacer: null,
        space: ''
      },
      tours: {
        files: {
          '.tmp/tours.json': ['tours/**/*.json']
        },
      }
    },
    clean: {
      dist: {
        src: ['dist/*']
      },
      tmp: {
        src: ['.tmp']
      }
    },
    concat: {
      tours: {
        options: {
          banner: 'var __tours = ',
          footer: ';',
        },
        files: {
          '.tmp/tours.js': ['.tmp/tours.json'],
        },
      },
      dist: {
        options: {
          banner: 'define([\'introjs\', \'jquery\', \'underscore\', \'moment\', \'Polyglot\'], function (introjs, $, _, moment, P) {\n',
          footer: '});',
        },
        files: {
          'dist/tour.js': ['actions.js', '.tmp/tours.js', 'tour.js']
        }
      }
    },
    sass: {
      dist: {
        options: {
          style: 'compressed',
          sourcemap: 'none'
        },
        files: {
          'dist/tour.css': 'tour.scss'
        }
      }
    },
    autoprefixer: {
      single_file: {
        src: 'dist/tour.css'
      },
    }
  });

  grunt.loadNpmTasks('grunt-json-merge');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-sass');
  grunt.loadNpmTasks('grunt-autoprefixer');

  grunt.registerTask('default', ['clean:dist', 'json_merge', 'concat', 'sass', 'autoprefixer']);

};
<commit_msg>lowercase deps<commit_after>'use strict';

module.exports = function(grunt) {

  grunt.initConfig({
    json_merge: {
      options: {
        replacer: null,
        space: ''
      },
      tours: {
        files: {
          '.tmp/tours.json': ['tours/**/*.json']
        },
      }
    },
    clean: {
      dist: {
        src: ['dist/*']
      },
      tmp: {
        src: ['.tmp']
      }
    },
    concat: {
      tours: {
        options: {
          banner: 'var __tours = ',
          footer: ';',
        },
        files: {
          '.tmp/tours.js': ['.tmp/tours.json'],
        },
      },
      dist: {
        options: {
          banner: 'define([\'introjs\', \'jquery\', \'underscore\', \'moment\', \'polyglot\'], function (introjs, $, _, moment, P) {\n',
          footer: '});',
        },
        files: {
          'dist/tour.js': ['actions.js', '.tmp/tours.js', 'tour.js']
        }
      }
    },
    sass: {
      dist: {
        options: {
          style: 'compressed',
          sourcemap: 'none'
        },
        files: {
          'dist/tour.css': 'tour.scss'
        }
      }
    },
    autoprefixer: {
      single_file: {
        src: 'dist/tour.css'
      },
    }
  });

  grunt.loadNpmTasks('grunt-json-merge');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-sass');
  grunt.loadNpmTasks('grunt-autoprefixer');

  grunt.registerTask('default', ['clean:dist', 'json_merge', 'concat', 'sass', 'autoprefixer']);

};
<|endoftext|>


<commit_before>'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// If you want to recursively match all subfolders, use:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Configurable paths
  var config = {
    app: 'app',
    dist: 'dist'
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    config: config,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= config.app %>/scripts/{,*/}*.js'],
        tasks: ['jshint'],
        options: {
          livereload: true
        }
      },
      jstest: {
        files: ['test/{,*/}*.js'],
        tasks: ['test:watch']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= config.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '<%= config.app %>/images/{,*/}*'
        ]
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9000,
        open: true,
        livereload: 35729,
        // Change this to '0.0.0.0' to access the server from outside
        hostname: 'localhost'
      },
      // livereload: {
      //   options: {
      //     middleware: function (connect) {
      //       return [
      //         connect.static('.tmp'),
      //         connect().use('/bower_components', connect.static('./bower_components')),
      //         connect.static(config.app)
      //       ];
      //     }
      //   }
      // },
      // test: {
      //   options: {
      //     open: false,
      //     port: 9001,
      //     middleware: function (connect) {
      //       return [
      //         connect.static('.tmp'),
      //         connect.static('test'),
      //         connect().use('/bower_components', connect.static('./bower_components')),
      //         connect.static(config.app)
      //       ];
      //     }
      //   }
      // },
      dist: {
        options: {
          base: '<%= config.dist %>',
          livereload: false
        }
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= config.dist %>/*',
            '!<%= config.dist %>/.git*'
          ]
        }]
      },
      requirejs: {
        dot: true,
        src: [
          '<%= config.dist %>/**/*.js',
          '!<%= config.dist %>/scripts/main.js'
        ]
      },
      server: '.tmp'
    },

    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: [
        'Gruntfile.js',
        '<%= config.app %>/scripts/{,*/}*.js',
        'test/{,*/}*.js'
      ]
    },

    // Automatically inject Bower components into the HTML file
    wiredep: {
      app: {
        ignorePath: /^\/|\.\.\//,
        src: ['<%= config.app %>/index.html'],
        exclude: /ractive/
      }
    },

    // Build the application using Require.js
    requirejs: {
      compile: {
        options: {
          almond: true,
          replaceRequireScript: [{
            files: ['<%= config.dist %>/index.html'],
            module: 'main'
          }],
          modules: [{name: 'main'}],
          mainConfigFile: '<%= config.app %>/scripts/main.js',
          dir: '<%= config.dist %>/scripts',
          baseUrl: '<%= config.app %>/scripts',
          optimize: 'none',
          useStrict: true,
          logLevel: 2
        }
      }
    },

    // The following *-min tasks produce minified files in the dist folder
    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= config.app %>/images',
          src: '{,*/}*.{gif,jpeg,jpg,png}',
          dest: '<%= config.dist %>/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          collapseBooleanAttributes: true,
          collapseWhitespace: true,
          removeAttributeQuotes: true,
          removeCommentsFromCDATA: true,
          // removeEmptyAttributes: true,
          removeOptionalTags: true,
          removeRedundantAttributes: true,
          useShortDoctype: true
        },
        files: [{
          expand: true,
          cwd: '<%= config.dist %>',
          src: '{,*/}*.html',
          dest: '<%= config.dist %>'
        }]
      }
    },

    // By default, your `index.html`'s <!-- Usemin block --> will take care
    // of minification. These next options are pre-configured if you do not
    // wish to use the Usemin blocks.
    // cssmin: {
    //   dist: {
    //     files: {
    //       '<%= config.dist %>/styles/main.css': [
    //         '.tmp/styles/{,*/}*.css',
    //         '<%= config.app %>/styles/{,*/}*.css'
    //       ]
    //     }
    //   }

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= config.app %>',
          dest: '<%= config.dist %>',
          src: [
            '*.{ico,png,txt}',
            '.htaccess',
            'images/{,*/}*.webp',
            '{,*/}*.html',
            'styles/fonts/{,*/}*.*',
            '../components/{,*/}*.*'
          ]
        }]
      },
      styles: {
        expand: true,
        dot: true,
        cwd: '<%= config.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    }

  });

  grunt.registerTask('serve', 'start the server and preview your app, ' +
    '--allow-remote for remote access', function (target) {
    if (grunt.option('allow-remote')) {
      grunt.config.set('connect.options.hostname', '0.0.0.0');
    }
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'build',
      'wiredep',
      'connect',
      'watch'
    ]);
  });

  grunt.registerTask('server', function (target) {
    grunt.log.warn('The `server` task has been deprecated. ' +
      'Use `grunt serve` to start a server.'
    );
    // grunt.task.run([target ? ('serve:' + target) : 'serve']);
  });

  grunt.registerTask('test', function (target) {
    if (target !== 'watch') {
      grunt.task.run([
        'clean:server'
      ]);
    }

    grunt.task.run([
      // 'connect:test'
    ]);
  });

  grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    // 'concat',
    'copy:dist',
    'requirejs',
    // 'clean:requirejs',
    // 'htmlmin'
  ]);

  grunt.registerTask('default', [
    'newer:jshint',
    'test',
    'build'
  ]);

};
<commit_msg>Added tasks to compile/recompile coffescript in livereload, copy & clean distribution folder<commit_after>'use strict';

module.exports = function(grunt) {

  require('time-grunt')(grunt);

  require('load-grunt-tasks')(grunt);

  var config = {
    app: 'app',
    dist: 'dist'
  };

  grunt.initConfig({
    config: config,

    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      coffee: {
        files: ['<%= config.app %>/coffee/{,*/}*.coffee'],
        tasks: ['coffee'],
        options: {
          livereload: true
        }
      },
      js: {
        files: ['<%= config.app %>/scripts/{,*/}*.js'],
        tasks: ['jshint', 'requirejs'],
        options: {
          livereload: true
        }
      },
      jstest: {
        files: ['test/{,*/}*.js'],
        tasks: ['test:watch']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= config.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '<%= config.app %>/images/{,*/}*'
        ]
      }
    },

    connect: {
      options: {
        port: 9000,
        open: true,
        livereload: 35729,
        // Change this to '0.0.0.0' to access the server from outside
        hostname: 'localhost'
      },
      dist: {
        options: {
          base: '<%= config.dist %>',
          livereload: false
        }
      }
    },

    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: [
        'Gruntfile.js',
        '<%= config.app %>/scripts/{,*/}*.js',
        'test/{,*/}*.js'
      ]
    },

    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= config.dist %>/*',
            '!<%= config.dist %>/.git*',
            '<%= config.app %>/scripts/*'
          ]
        }]
      },
      requirejs: {
        dot: true,
        src: [
          '<%= config.dist %>/**/*.js',
          '!<%= config.dist %>/scripts/main.js'
        ]
      },
      server: '.tmp'
    },

    bower: {
      dev: {
        dest: '<%= config.dist %>/bower_components',
        options: {
          expand: true
        }
      }
    },

    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= config.app %>',
          dest: '<%= config.dist %>',
          src: [
            '*.{ico,png,txt}',
            '.htaccess',
            'images/{,*/}*.webp',
            '{,*/}*.html',
            'styles/fonts/{,*/}*.*',
            '../bower_components/{,*/}*.*'
          ]
        }]
      },
      styles: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= config.app %>/styles',
          dest: '<%= config.dist %>/styles',
          src: '{,*/}*.css'
        }]
      },
      compiled: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= config.app %>/scripts',
          dest: '<%= config.dist %>/scripts',
          src: '{,*/}*.js',
          filter: function (file) {
            return !file.endsWith('main.js');
          }
        }]
      }
    },

    wiredep: {
      app: {
        ignorePath: /^\/|\.\.\//,
        src: ['<%= config.app %>/index.html'],
        exclude: /ractive/
      }
    },

    requirejs: {
      compile: {
        options: {
          almond: true,
          replaceRequireScript: [{
            files: ['<%= config.dist %>/index.html'],
            module: 'main'
          }],
          modules: [{name: 'main'}],
          mainConfigFile: '<%= config.app %>/scripts/main.js',
          dir: '<%= config.dist %>/scripts',
          baseUrl: '<%= config.app %>/scripts',
          optimize: 'none',
          useStrict: true,
          logLevel: 2
        }
      }
    },

    coffee: {
      compile: {
        expand: true,
        cwd: '<%= config.app %>/coffee',
        src: ['{,*/}*.coffee'],
        dest: '<%= config.app %>/scripts',
        ext: '.js'
        //options: {
        //  bare: true
        //}
      }
    }

  });

  /**
      Register task
  */

  grunt.registerTask('serve',
      'start the server and preview your app, --allow-remote for remote access',
      function (target) {
    if (grunt.option('allow-remote')) {
      grunt.config.set('connect.options.hostname', '0.0.0.0');
    }
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'build',
      'wiredep',
      'connect',
      'watch'
    ]);
  });

  grunt.registerTask('server', function (target) {
    grunt.log.warn('The `server` task has been deprecated. ' +
        'Use `grunt serve` to start a server. Target: ' + target
    );
    // grunt.task.run([target ? ('serve:' + target) : 'serve']);
  });

  grunt.registerTask('test', function (target) {
    if (target !== 'watch') {
      grunt.task.run([
        'clean:server'
      ]);
    }

    grunt.task.run([
      // 'connect:test'
    ]);
  });

  grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    'copy:dist',
    'copy:styles',
    'coffee',
    'requirejs',
    'bower'
  ]);

  grunt.registerTask('default', [
    'newer:jshint',
    'build'
  ]);

};<|endoftext|>