<commit_before>/*!
 * Copyright 2012 Sakai Foundation (SF) Licensed under the
 * Educational Community 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.osedu.org/licenses/ECL-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.
 */

var _ = require('underscore');
var shell = require('shelljs');
var util = require('util');
var vm = require('vm');

module.exports = function(grunt) {

    // Project configuration.
    grunt.initConfig({
        'pkg': '<json:package.json>',
        'meta': {
            'banner': '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
                      '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
                      '<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' +
                      '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
                      ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */'
        },
        'qunit': {
            'index': ['tests/qunit/tests/unit/*.html']
        },
        'lint': {
            'files': [
                'grunt.js',
                'admin/**/*.js',
                'shared/**/*.js',
                'ui/**/*.js',
                'node_modules/oae-*/**/*.js'
            ]
        },
        'watch': {
            'files': '<config:lint.files>',
            'tasks': 'lint test'
        },
        'jshint': {
            'options': {
                'sub': true
            },
            'globals': {
                'exports': true,
                'module': false
            }
        },
        'clean': {
            'folder': 'target/'
        },
        'copy': {
            'main': {
                'files': [
                    {
                        'expand': true,
                        'src': [
                            '**',
                            '!target/**',
                            '!tests/**',
                            '!tools/**',
                            '!node_modules/grunt*/**',
                            '!node_modules/shelljs/**',
                            '!node_modules/underscore/**'
                        ],
                        'dest': 'target/original'
                    }
                ]
            }
        },
        'requirejs': {
            'optimize': {
                'options': {
                    'appDir': './',
                    'baseUrl': './shared',
                    'mainConfigFile': './shared/oae/api/oae.bootstrap.js',
                    'dir': 'target/optimized',
                    'optimize': 'uglify',
                    'preserveLicenseComments': false,
                    'optimizeCss': 'standard',
                    'cssImportIgnore': null,
                    'inlineText': true,
                    'useStrict': false,
                    'pragmas': {},
                    'skipPragmas': false,
                    'skipModuleInsertion': false,
                    'modules': [{
                        'name': 'oae.core',
                        'exclude': ['jquery']
                    }],
                    'fileExclusionRegExp': /^(\.|tools|target|tests|grunt|shelljs|underscore$)/,
                    'logLevel': 2
                }
            }
        },
        'ver': {
            'oae': {
                'basedir': 'target/optimized',
                'phases': [
                    {
                        // Rename and hash these folders
                        'folders': [
                            'target/optimized/shared/bundles',
                            'target/optimized/ui/bundles',
                            'target/optimized/admin/bundles',
                            'target/optimized/shared/vendor/js/l10n/cultures'
                        ],

                        // Rename and hash these files
                        'files': _hashFiles([
                            'target/optimized/shared',
                            'target/optimized/ui',
                            'target/optimized/admin',
                            'target/optimized/docs'
                        ], ['html', 'json', 'ico', 'less'], [
                            '!target/optimized/shared/vendor/js/l10n/cultures.*/**',
                            '!target/optimized/ui/bundles.*/**'
                        ]),

                        // Look for and replace references to the above (non-excluded) files and folders in these files
                        'references': [
                            'target/optimized/shared/**/*.js',
                            'target/optimized/shared/**/*.css',
                            'target/optimized/ui/**/*.html',
                            'target/optimized/ui/**/*.js',
                            'target/optimized/ui/**/*.css',
                            'target/optimized/admin/**/*.html',
                            'target/optimized/admin/**/*.js',
                            'target/optimized/admin/**/*.css',
                            'target/optimized/docs/**/*.html',
                            'target/optimized/docs/**/*.js',
                            'target/optimized/docs/**/*.css',
                            'target/optimized/node_modules/oae-*/**/*.html',
                            'target/optimized/node_modules/oae-*/**/*.js',
                            'target/optimized/node_modules/oae-*/**/*.css',
                            'target/optimized/node_modules/oae-*/**/*.json'
                        ]
                    }
                ],
                'version': 'target/optimized/hashes.json'
            }
        },
        'inlineImg': {
            'src': [
                'target/optimized/admin/**/*.css',
                'target/optimized/ui/**/*.css',
                'target/optimized/shared/**/*.css',
                'target/optimized/docs/**/*.css',
                'target/optimized/node_modules/oae-*/**/*.css'
            ],
            'ie8': false,
            'base': __dirname
        },
        'git-describe': {
            'oae': {}
        }
    });

    // Load tasks from npm modules
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-git-describe');
    grunt.loadNpmTasks('grunt-ver');
    grunt.loadNpmTasks('grunt-imagine');
    grunt.loadNpmTasks('grunt-contrib-requirejs');

    // Task to write the version to a file
    grunt.registerTask('writeVersion', function() {
        this.requires('git-describe');
        var json = grunt.template.process('{"sakai:ux-version":"<%= meta.version %>"}');
        grunt.file.write('target/optimized/ui/version.json', json);
    });

    // Task to fill out the nginx config template
    grunt.registerTask('configNginx', function() {
        var infile = './nginx.json';
        if (shell.test('-f', infile)) {
            var nginxConf = require(infile);
            var template = grunt.file.read('./nginx.conf');
            grunt.config.set('nginxConf', nginxConf);
            var conf = grunt.template.process(template);
            grunt.file.write('./target/optimized/nginx.conf', conf);
            grunt.log.writeln('nginx.conf rendered at ./target/optimized/nginx.conf'.green);
        } else {
            var msg = 'No ' + infile + ' found, not rendering nginx.conf template';
            grunt.log.writeln(msg.yellow);
        }
    });

    // Task to hash files
    grunt.registerTask('hashFiles', function() {
        this.requires('requirejs');
        this.requires('inlineImg');

        // Add the modules as phases to ver:oae
        var oaeModules = grunt.file.expand({filter:'isDirectory'}, 'target/optimized/node_modules/oae-*/*');
        oaeModules.forEach(function(module) {
            grunt.log.writeln(module);
            var conf = {
                'folders': [ module + '/bundles' ],
                'files': _hashFiles([module], ['json']),
                'references': [
                    module + '/**/*.html',
                    module + '/**/*.js',
                    module + '/**/*.css',
                    module + '/*.json'
                ]
            };
            grunt.config.set('ver.' + module + '.basedir', module);
            grunt.config.set('ver.' + module + '.phases', [conf]);
            grunt.task.run('ver:' + module);
        });

        grunt.task.run('ver:oae');
        grunt.task.run('updateBootstrapPaths');
    });

    // Task to update the paths in oae.bootstrap to the hashed versions
    grunt.registerTask('updateBootstrapPaths', function() {
        this.requires('ver:oae');

        var basedir = 'target/optimized/';
        var hashedPaths = require('./' + grunt.config.get('ver.oae.version'));
        var bootstrapPath = basedir + hashedPaths['/shared/oae/api/oae.bootstrap.js'];
        var bootstrap = grunt.file.read(bootstrapPath);
        var regex = /paths: ?\{[^}]*\}/;
        var match = bootstrap.match(regex);
        var scriptPaths = 'paths = {' + bootstrap.match(regex) + '}';
        var paths = vm.runInThisContext(scriptPaths).paths;

        // Update the bootstrap file with the hashed paths
        Object.keys(paths).forEach(function(key) {
            var prefix = '/shared/';
            var path = prefix + paths[key] + '.js';
            var hashedPath = '';
            if (hashedPaths[path]) {
                hashedPath = hashedPaths[path];
                // trim off prefix and .js
                paths[key] = hashedPath.substring(prefix.length, hashedPath.length - 3);
            }
        });
        bootstrap = bootstrap.replace(regex, 'paths:' + JSON.stringify(paths));
        grunt.file.write(bootstrapPath, bootstrap);
        grunt.log.writeln('Boots strapped'.green);
    });

    // Override the test task with the qunit task
    grunt.registerTask('test', ['qunit']);

    // Default task.
    grunt.registerTask('default', ['clean', 'copy', 'git-describe', 'requirejs', 'inlineImg', 'hashFiles', 'writeVersion', 'configNginx']);
};

/**
 * Generate the glob expressions to match all files that have extensions that are supposed to be hashed (as defined
 * by `HASHED_EXTENSIONS`). You can optionally exclude extensions for special cases.
 *
 * @param  {String[]}   directories     The list of directories whose files to hash
 * @param  {String[]}   [excludeExts]   The extensions to exclude from the list of `HASHED_EXTENSIONS`, if any
 * @param  {String[]}   [extra]         Extra glob patterns to append, in addition to the ones added for the extensions
 * @return {String[]}                   An array of glob expressions that match the files to hash in the directories
 * @api private
 */
var _hashFiles = function(directories, excludeExts, extra) {
    excludeExts = excludeExts || [];
    var globs = [];
    directories.forEach(function(directory) {
        globs.push(util.format('%s/**', directory));
        excludeExts.forEach(function(ext) {
            // Exclude both direct children of the exlucded extensions, and all grandchildren
            globs.push(util.format('!%s/*.%s', directory, ext));
            globs.push(util.format('!%s/**/*.%s', directory, ext));
        });
    });

    return (extra) ? _.union(globs, extra) : globs;
};
<commit_msg>Excluding .bin folder per review<commit_after>/*!
 * Copyright 2012 Sakai Foundation (SF) Licensed under the
 * Educational Community 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.osedu.org/licenses/ECL-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.
 */

var _ = require('underscore');
var shell = require('shelljs');
var util = require('util');
var vm = require('vm');

module.exports = function(grunt) {

    // Project configuration.
    grunt.initConfig({
        'pkg': '<json:package.json>',
        'meta': {
            'banner': '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
                      '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
                      '<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' +
                      '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
                      ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */'
        },
        'qunit': {
            'index': ['tests/qunit/tests/unit/*.html']
        },
        'lint': {
            'files': [
                'grunt.js',
                'admin/**/*.js',
                'shared/**/*.js',
                'ui/**/*.js',
                'node_modules/oae-*/**/*.js'
            ]
        },
        'watch': {
            'files': '<config:lint.files>',
            'tasks': 'lint test'
        },
        'jshint': {
            'options': {
                'sub': true
            },
            'globals': {
                'exports': true,
                'module': false
            }
        },
        'clean': {
            'folder': 'target/'
        },
        'copy': {
            'main': {
                'files': [
                    {
                        'expand': true,
                        'src': [
                            '**',
                            '!target/**',
                            '!tests/**',
                            '!tools/**',
                            '!node_modules/.*/**',
                            '!node_modules/grunt*/**',
                            '!node_modules/shelljs/**',
                            '!node_modules/underscore/**'
                        ],
                        'dest': 'target/original'
                    }
                ]
            }
        },
        'requirejs': {
            'optimize': {
                'options': {
                    'appDir': './',
                    'baseUrl': './shared',
                    'mainConfigFile': './shared/oae/api/oae.bootstrap.js',
                    'dir': 'target/optimized',
                    'optimize': 'uglify',
                    'preserveLicenseComments': false,
                    'optimizeCss': 'standard',
                    'cssImportIgnore': null,
                    'inlineText': true,
                    'useStrict': false,
                    'pragmas': {},
                    'skipPragmas': false,
                    'skipModuleInsertion': false,
                    'modules': [{
                        'name': 'oae.core',
                        'exclude': ['jquery']
                    }],
                    'fileExclusionRegExp': /^(\.|target|tests|tools|grunt|shelljs|underscore$)/,
                    'logLevel': 2
                }
            }
        },
        'ver': {
            'oae': {
                'basedir': 'target/optimized',
                'phases': [
                    {
                        // Rename and hash these folders
                        'folders': [
                            'target/optimized/shared/bundles',
                            'target/optimized/ui/bundles',
                            'target/optimized/admin/bundles',
                            'target/optimized/shared/vendor/js/l10n/cultures'
                        ],

                        // Rename and hash these files
                        'files': _hashFiles([
                            'target/optimized/shared',
                            'target/optimized/ui',
                            'target/optimized/admin',
                            'target/optimized/docs'
                        ], ['html', 'json', 'ico', 'less'], [
                            '!target/optimized/shared/vendor/js/l10n/cultures.*/**',
                            '!target/optimized/ui/bundles.*/**'
                        ]),

                        // Look for and replace references to the above (non-excluded) files and folders in these files
                        'references': [
                            'target/optimized/shared/**/*.js',
                            'target/optimized/shared/**/*.css',
                            'target/optimized/ui/**/*.html',
                            'target/optimized/ui/**/*.js',
                            'target/optimized/ui/**/*.css',
                            'target/optimized/admin/**/*.html',
                            'target/optimized/admin/**/*.js',
                            'target/optimized/admin/**/*.css',
                            'target/optimized/docs/**/*.html',
                            'target/optimized/docs/**/*.js',
                            'target/optimized/docs/**/*.css',
                            'target/optimized/node_modules/oae-*/**/*.html',
                            'target/optimized/node_modules/oae-*/**/*.js',
                            'target/optimized/node_modules/oae-*/**/*.css',
                            'target/optimized/node_modules/oae-*/**/*.json'
                        ]
                    }
                ],
                'version': 'target/optimized/hashes.json'
            }
        },
        'inlineImg': {
            'src': [
                'target/optimized/admin/**/*.css',
                'target/optimized/ui/**/*.css',
                'target/optimized/shared/**/*.css',
                'target/optimized/docs/**/*.css',
                'target/optimized/node_modules/oae-*/**/*.css'
            ],
            'ie8': false,
            'base': __dirname
        },
        'git-describe': {
            'oae': {}
        }
    });

    // Load tasks from npm modules
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-git-describe');
    grunt.loadNpmTasks('grunt-ver');
    grunt.loadNpmTasks('grunt-imagine');
    grunt.loadNpmTasks('grunt-contrib-requirejs');

    // Task to write the version to a file
    grunt.registerTask('writeVersion', function() {
        this.requires('git-describe');
        var json = grunt.template.process('{"sakai:ux-version":"<%= meta.version %>"}');
        grunt.file.write('target/optimized/ui/version.json', json);
    });

    // Task to fill out the nginx config template
    grunt.registerTask('configNginx', function() {
        var infile = './nginx.json';
        if (shell.test('-f', infile)) {
            var nginxConf = require(infile);
            var template = grunt.file.read('./nginx.conf');
            grunt.config.set('nginxConf', nginxConf);
            var conf = grunt.template.process(template);
            grunt.file.write('./target/optimized/nginx.conf', conf);
            grunt.log.writeln('nginx.conf rendered at ./target/optimized/nginx.conf'.green);
        } else {
            var msg = 'No ' + infile + ' found, not rendering nginx.conf template';
            grunt.log.writeln(msg.yellow);
        }
    });

    // Task to hash files
    grunt.registerTask('hashFiles', function() {
        this.requires('requirejs');
        this.requires('inlineImg');

        // Add the modules as phases to ver:oae
        var oaeModules = grunt.file.expand({filter:'isDirectory'}, 'target/optimized/node_modules/oae-*/*');
        oaeModules.forEach(function(module) {
            grunt.log.writeln(module);
            var conf = {
                'folders': [ module + '/bundles' ],
                'files': _hashFiles([module], ['json']),
                'references': [
                    module + '/**/*.html',
                    module + '/**/*.js',
                    module + '/**/*.css',
                    module + '/*.json'
                ]
            };
            grunt.config.set('ver.' + module + '.basedir', module);
            grunt.config.set('ver.' + module + '.phases', [conf]);
            grunt.task.run('ver:' + module);
        });

        grunt.task.run('ver:oae');
        grunt.task.run('updateBootstrapPaths');
    });

    // Task to update the paths in oae.bootstrap to the hashed versions
    grunt.registerTask('updateBootstrapPaths', function() {
        this.requires('ver:oae');

        var basedir = 'target/optimized/';
        var hashedPaths = require('./' + grunt.config.get('ver.oae.version'));
        var bootstrapPath = basedir + hashedPaths['/shared/oae/api/oae.bootstrap.js'];
        var bootstrap = grunt.file.read(bootstrapPath);
        var regex = /paths: ?\{[^}]*\}/;
        var match = bootstrap.match(regex);
        var scriptPaths = 'paths = {' + bootstrap.match(regex) + '}';
        var paths = vm.runInThisContext(scriptPaths).paths;

        // Update the bootstrap file with the hashed paths
        Object.keys(paths).forEach(function(key) {
            var prefix = '/shared/';
            var path = prefix + paths[key] + '.js';
            var hashedPath = '';
            if (hashedPaths[path]) {
                hashedPath = hashedPaths[path];
                // trim off prefix and .js
                paths[key] = hashedPath.substring(prefix.length, hashedPath.length - 3);
            }
        });
        bootstrap = bootstrap.replace(regex, 'paths:' + JSON.stringify(paths));
        grunt.file.write(bootstrapPath, bootstrap);
        grunt.log.writeln('Boots strapped'.green);
    });

    // Override the test task with the qunit task
    grunt.registerTask('test', ['qunit']);

    // Default task.
    grunt.registerTask('default', ['clean', 'copy', 'git-describe', 'requirejs', 'inlineImg', 'hashFiles', 'writeVersion', 'configNginx']);
};

/**
 * Generate the glob expressions to match all files that have extensions that are supposed to be hashed (as defined
 * by `HASHED_EXTENSIONS`). You can optionally exclude extensions for special cases.
 *
 * @param  {String[]}   directories     The list of directories whose files to hash
 * @param  {String[]}   [excludeExts]   The extensions to exclude from the list of `HASHED_EXTENSIONS`, if any
 * @param  {String[]}   [extra]         Extra glob patterns to append, in addition to the ones added for the extensions
 * @return {String[]}                   An array of glob expressions that match the files to hash in the directories
 * @api private
 */
var _hashFiles = function(directories, excludeExts, extra) {
    excludeExts = excludeExts || [];
    var globs = [];
    directories.forEach(function(directory) {
        globs.push(util.format('%s/**', directory));
        excludeExts.forEach(function(ext) {
            // Exclude both direct children of the exlucded extensions, and all grandchildren
            globs.push(util.format('!%s/*.%s', directory, ext));
            globs.push(util.format('!%s/**/*.%s', directory, ext));
        });
    });

    return (extra) ? _.union(globs, extra) : globs;
};
<|endoftext|>


<commit_before>/**
 * @fileoverview This file defines Angular services to use to get OpenLayers
 * layers for the application.
 */
goog.provide('app.GetLayerForCatalogNode');
goog.provide('app.GetWmsLayer');
goog.provide('app.GetWmtsLayer');

goog.require('app');
goog.require('ngeo.DecorateLayer');
goog.require('ol.layer.Image');
goog.require('ol.layer.Tile');
goog.require('ol.source.ImageWMS');
goog.require('ol.source.WMTS');
goog.require('ol.tilegrid.WMTS');

/**
 * @typedef {function(string, string):ol.layer.Tile}
 */
app.GetWmtsLayer;

/**
 * @typedef {function(string, string, string=):ol.layer.Image}
 */
app.GetWmsLayer;

/**
 * @typedef {function(Object):ol.layer.Layer}
 */
app.GetLayerForCatalogNode;

/**
 * @const
 * @type {Object.<string, ol.layer.Layer>}
 * @private
 */
app.layerCache_ = {};

/**
 * @param {string} imageType Image type (e.g. "image/png").
 * @return {string} Image extensino (e.g. "png").
 * @private
 */
app.getImageExtension_ = function(imageType) {
  goog.asserts.assert(imageType.indexOf('/'));
  var imageExt = imageType.split('/')[1];
  goog.asserts.assert(imageExt == 'png' || imageExt == 'jpeg');
  return imageExt;
};

/**
 * @param {ngeo.DecorateLayer} ngeoDecorateLayer ngeo decorate layer service.
 * @return {app.GetWmtsLayer} The getWmtsLayer function.
 * @private
 * @ngInject
 */
app.getWmtsLayer_ = function(ngeoDecorateLayer) {
  return getWmtsLayer;

  /**
   * @param {string} name WMTS layer name.
   * @param {string} imageType Image type (e.g. "image/png").
   * @return {ol.layer.Tile} The layer.
   */
  function getWmtsLayer(name, imageType) {

    var imageExt = app.getImageExtension_(imageType);
    var url = 'http://wmts.geoportail.lu/mapproxy_4_v3/wmts/{Layer}/' +
        '{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.' + imageExt;

    var layer = new ol.layer.Tile({
      source: new ol.source.WMTS({
        url: url,
        layer: name,
        matrixSet: 'GLOBAL_WEBMERCATOR',
        requestEncoding: ol.source.WMTSRequestEncoding.REST,
        projection: ol.proj.get('EPSG:3857'),
        tileGrid: new ol.tilegrid.WMTS({
          origin: [-20037508.3428, 20037508.3428],
          resolutions: [156543.033928, 78271.516964,
            39135.758482, 19567.879241, 9783.9396205,
            4891.96981025, 2445.98490513, 1222.99245256,
            611.496226281, 305.748113141, 152.87405657,
            76.4370282852, 38.2185141426, 19.1092570713,
            9.55462853565, 4.77731426782, 2.38865713391,
            1.19432856696, 0.597164283478, 0.298582141739],
          matrixIds: [
            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
            11, 12, 13, 14, 15, 16, 17, 18, 19
          ]
        }),
        style: 'default'
      })
    });

    layer.set('label', name);
    ngeoDecorateLayer(layer);

    return layer;
  }
};

app.module.factory('appGetWmtsLayer', app.getWmtsLayer_);

/**
 * @param {ngeo.DecorateLayer} ngeoDecorateLayer ngeo decorate layer service.
 * @return {app.GetWmsLayer} The getWmsLayer function.
 * @private
 * @ngInject
 */
app.getWmsLayer_ = function(ngeoDecorateLayer) {
  return getWmsLayer;

  /**
   * @param {string} name WMS layer name.
   * @param {string} layers Comma-separated list of layer names for that WMS
   *     layer.
   * @param {string=} opt_url WMS URL.
   * @return {ol.layer.Image} The layer.
   */
  function getWmsLayer(name, layers, opt_url) {
    var url = goog.isDef(opt_url) ?
        opt_url : 'http://devv3.geoportail.lu/main/wsgi/wms';
    var layer = new ol.layer.Image({
      source: new ol.source.ImageWMS({
        url: url,
        params: {
          'LAYERS': layers
        }
      })
    });

    layer.set('label', name);
    ngeoDecorateLayer(layer);

    return layer;
  }
};

app.module.factory('appGetWmsLayer', app.getWmsLayer_);

/**
 * Function returning a function used to get the layer object for a catalog
 * tree node.
 *
 * @param {app.GetWmtsLayer} appGetWmtsLayer The getWmtsLayer function.
 * @param {app.GetWmsLayer} appGetWmsLayer The getWmsLayer function.
 * @return {app.GetLayerForCatalogNode} The getLayerForCatalogNode function.
 * @private
 * @ngInject
 */
app.getLayerForCatalogNode_ = function(appGetWmtsLayer, appGetWmsLayer) {
  return getLayerForCatalogNode;

  /**
   * @param {Object} node Catalog tree node.
   * @return {ol.layer.Layer} OpenLayers layer.
   */
  function getLayerForCatalogNode(node) {
    var layer, layerCacheKey, type;
    if (!('type' in node)) {
      return null;
    }
    type = node['type'];
    layerCacheKey = type + '_' + node['name'];
    if (layerCacheKey in app.layerCache_) {
      return app.layerCache_[layerCacheKey];
    }
    if (type.indexOf('WMS') != -1) {
      goog.asserts.assert('name' in node);
      goog.asserts.assert('layers' in node);
      layer = appGetWmsLayer(node['name'], node['layers'], node['url']);
    } else if (type == 'WMTS') {
      goog.asserts.assert('name' in node);
      goog.asserts.assert('imageType' in node);
      layer = appGetWmtsLayer(node['name'], node['imageType']);
    } else {
      return null;
    }
    goog.asserts.assert(goog.isDefAndNotNull(layer));
    app.layerCache_[layerCacheKey] = layer;
    layer.set('metadata', node['metadata']);
    return layer;
  }
};

app.module.factory('appGetLayerForCatalogNode', app.getLayerForCatalogNode_);
<commit_msg>Get WMS image type from layer spec<commit_after>/**
 * @fileoverview This file defines Angular services to use to get OpenLayers
 * layers for the application.
 */
goog.provide('app.GetLayerForCatalogNode');
goog.provide('app.GetWmsLayer');
goog.provide('app.GetWmtsLayer');

goog.require('app');
goog.require('ngeo.DecorateLayer');
goog.require('ol.layer.Image');
goog.require('ol.layer.Tile');
goog.require('ol.source.ImageWMS');
goog.require('ol.source.WMTS');
goog.require('ol.tilegrid.WMTS');

/**
 * @typedef {function(string, string):ol.layer.Tile}
 */
app.GetWmtsLayer;

/**
 * @typedef {function(string, string, string, string=):ol.layer.Image}
 */
app.GetWmsLayer;

/**
 * @typedef {function(Object):ol.layer.Layer}
 */
app.GetLayerForCatalogNode;

/**
 * @const
 * @type {Object.<string, ol.layer.Layer>}
 * @private
 */
app.layerCache_ = {};

/**
 * @param {string} imageType Image type (e.g. "image/png").
 * @return {string} Image extensino (e.g. "png").
 * @private
 */
app.getImageExtension_ = function(imageType) {
  goog.asserts.assert(imageType.indexOf('/'));
  var imageExt = imageType.split('/')[1];
  goog.asserts.assert(imageExt == 'png' || imageExt == 'jpeg');
  return imageExt;
};

/**
 * @param {ngeo.DecorateLayer} ngeoDecorateLayer ngeo decorate layer service.
 * @return {app.GetWmtsLayer} The getWmtsLayer function.
 * @private
 * @ngInject
 */
app.getWmtsLayer_ = function(ngeoDecorateLayer) {
  return getWmtsLayer;

  /**
   * @param {string} name WMTS layer name.
   * @param {string} imageType Image type (e.g. "image/png").
   * @return {ol.layer.Tile} The layer.
   */
  function getWmtsLayer(name, imageType) {

    var imageExt = app.getImageExtension_(imageType);
    var url = 'http://wmts.geoportail.lu/mapproxy_4_v3/wmts/{Layer}/' +
        '{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.' + imageExt;

    var layer = new ol.layer.Tile({
      source: new ol.source.WMTS({
        url: url,
        layer: name,
        matrixSet: 'GLOBAL_WEBMERCATOR',
        requestEncoding: ol.source.WMTSRequestEncoding.REST,
        projection: ol.proj.get('EPSG:3857'),
        tileGrid: new ol.tilegrid.WMTS({
          origin: [-20037508.3428, 20037508.3428],
          resolutions: [156543.033928, 78271.516964,
            39135.758482, 19567.879241, 9783.9396205,
            4891.96981025, 2445.98490513, 1222.99245256,
            611.496226281, 305.748113141, 152.87405657,
            76.4370282852, 38.2185141426, 19.1092570713,
            9.55462853565, 4.77731426782, 2.38865713391,
            1.19432856696, 0.597164283478, 0.298582141739],
          matrixIds: [
            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
            11, 12, 13, 14, 15, 16, 17, 18, 19
          ]
        }),
        style: 'default'
      })
    });

    layer.set('label', name);
    ngeoDecorateLayer(layer);

    return layer;
  }
};

app.module.factory('appGetWmtsLayer', app.getWmtsLayer_);

/**
 * @param {ngeo.DecorateLayer} ngeoDecorateLayer ngeo decorate layer service.
 * @return {app.GetWmsLayer} The getWmsLayer function.
 * @private
 * @ngInject
 */
app.getWmsLayer_ = function(ngeoDecorateLayer) {
  return getWmsLayer;

  /**
   * @param {string} name WMS layer name.
   * @param {string} layers Comma-separated list of layer names for that WMS
   *     layer.
   * @param {string} imageType Image type (e.g. "image/png").
   * @param {string=} opt_url WMS URL.
   * @return {ol.layer.Image} The layer.
   */
  function getWmsLayer(name, layers, imageType, opt_url) {
    var url = goog.isDef(opt_url) ?
        opt_url : 'http://devv3.geoportail.lu/main/wsgi/wms';
    var imageExt = app.getImageExtension_(imageType);
    var layer = new ol.layer.Image({
      source: new ol.source.ImageWMS({
        url: url,
        params: {
          'FORMAT': imageExt,
          'LAYERS': layers
        }
      })
    });

    layer.set('label', name);
    ngeoDecorateLayer(layer);

    return layer;
  }
};

app.module.factory('appGetWmsLayer', app.getWmsLayer_);

/**
 * Function returning a function used to get the layer object for a catalog
 * tree node.
 *
 * @param {app.GetWmtsLayer} appGetWmtsLayer The getWmtsLayer function.
 * @param {app.GetWmsLayer} appGetWmsLayer The getWmsLayer function.
 * @return {app.GetLayerForCatalogNode} The getLayerForCatalogNode function.
 * @private
 * @ngInject
 */
app.getLayerForCatalogNode_ = function(appGetWmtsLayer, appGetWmsLayer) {
  return getLayerForCatalogNode;

  /**
   * @param {Object} node Catalog tree node.
   * @return {ol.layer.Layer} OpenLayers layer.
   */
  function getLayerForCatalogNode(node) {
    var layer, layerCacheKey, type;
    if (!('type' in node)) {
      return null;
    }
    type = node['type'];
    layerCacheKey = type + '_' + node['name'];
    if (layerCacheKey in app.layerCache_) {
      return app.layerCache_[layerCacheKey];
    }
    if (type.indexOf('WMS') != -1) {
      goog.asserts.assert('name' in node);
      goog.asserts.assert('layers' in node);
      goog.asserts.assert('imageType' in node);
      layer = appGetWmsLayer(node['name'], node['layers'], node['imageType'],
          node['url']);
    } else if (type == 'WMTS') {
      goog.asserts.assert('name' in node);
      goog.asserts.assert('imageType' in node);
      layer = appGetWmtsLayer(node['name'], node['imageType']);
    } else {
      return null;
    }
    goog.asserts.assert(goog.isDefAndNotNull(layer));
    app.layerCache_[layerCacheKey] = layer;
    layer.set('metadata', node['metadata']);
    return layer;
  }
};

app.module.factory('appGetLayerForCatalogNode', app.getLayerForCatalogNode_);
<|endoftext|>


<commit_before>if (jQuery != undefined) {
    var django = {
        'jQuery': jQuery,
    }
}

(function($) {
    $(document).ready(function() {
        var mapDefaults = {
            'mapTypeId': google.maps.MapTypeId.ROADMAP,
            'scrollwheel': false,
            'streetViewControl': false,
            'panControl': false
        };

        var markerDefaults = {
            'draggable': true,
            'animation': google.maps.Animation.DROP
        };

        $('.geoposition-widget').each(function() {
            var $container = $(this),
                $mapContainer = $('
'),
                $addressRow = $('
'),
                $searchRow = $('
'),
                $searchInput = $('<input>', {'type': 'search', 'placeholder': 'Start typing an address …'}),
                $latitudeField = $container.find('input.geoposition:eq(0)'),
                $longitudeField = $container.find('input.geoposition:eq(1)'),
                latitude = parseFloat($latitudeField.val()) || null,
                longitude = parseFloat($longitudeField.val()) || null,
                map,
                mapLatLng,
                mapOptions,
                mapCustomOptions,
                markerOptions,
                markerCustomOptions,
                marker;

            $mapContainer.css('height', $container.data('map-widget-height') + 'px');
            mapCustomOptions = $container.data('map-options') || {};
            markerCustomOptions = $container.data('marker-options') || {};

            function doSearch() {
                var gc = new google.maps.Geocoder();
                $searchInput.parent().find('ul.geoposition-results').remove();
                gc.geocode({
                    'address': $searchInput.val()
                }, function(results, status) {
                    if (status == 'OK') {
                        var updatePosition = function(result) {
                            if (result.geometry.bounds) {
                                map.fitBounds(result.geometry.bounds);
                            } else {
                                map.panTo(result.geometry.location);
                                map.setZoom(18);
                            }
                            marker.setPosition(result.geometry.location);
                            google.maps.event.trigger(marker, 'dragend');
                        };
                        if (results.length == 1) {
                            updatePosition(results[0]);
                        } else {
                            var $ul = $('
', {'class': 'geoposition-results'});
                            $.each(results, function(i, result) {
                                var $li = $('
');
                                $li.text(result.formatted_address);
                                $li.on('click', function() {
                                    updatePosition(result);
                                    $li.closest('ul').remove();
                                });
                                $li.appendTo($ul);
                            });
                            $searchInput.after($ul);
                        }
                    }
                });
            }

            function doGeocode() {
                var gc = new google.maps.Geocoder();
                gc.geocode({
                    'latLng': marker.position
                }, function(results, status) {
                    $addressRow.text('');
                    if (results && results[0]) {
                        $addressRow.text(results[0].formatted_address);
                    }
                });
            }

            var autoSuggestTimer = null;
            $searchInput.on('keydown', function(e) {
                if (autoSuggestTimer) {
                    clearTimeout(autoSuggestTimer);
                    autoSuggestTimer = null;
                }

                // if enter, search immediately
                if (e.keyCode == 13) {
                    e.preventDefault();
                    doSearch();
                }
                else {
                    // otherwise, search after a while after typing ends
                    autoSuggestTimer = setTimeout(function(){
                        doSearch();
                    }, 1000);
                }
            }).on('abort', function() {
                $(this).parent().find('ul.geoposition-results').remove();
            });
            $searchInput.appendTo($searchRow);
            $container.append($searchRow, $mapContainer, $addressRow);

            mapLatLng = new google.maps.LatLng(latitude, longitude);

            mapOptions = $.extend({}, mapDefaults, mapCustomOptions);

            if (!(latitude === null && longitude === null && mapOptions['center'])) {
                mapOptions['center'] = mapLatLng;
            }

            if (!mapOptions['zoom']) {
                mapOptions['zoom'] = latitude && longitude ? 15 : 1;
            }

            map = new google.maps.Map($mapContainer.get(0), mapOptions);
            markerOptions = $.extend({}, markerDefaults, markerCustomOptions, {
                'map': map
            });

            if (!(latitude === null && longitude === null && markerOptions['position'])) {
                markerOptions['position'] = mapLatLng;
            }

            marker = new google.maps.Marker(markerOptions);
            google.maps.event.addListener(marker, 'dragend', function() {
                $latitudeField.val(this.position.lat());
                $longitudeField.val(this.position.lng());
                doGeocode();
            });
            if ($latitudeField.val() && $longitudeField.val()) {
                google.maps.event.trigger(marker, 'dragend');
            }

            $latitudeField.add($longitudeField).on('keyup', function(e) {
                var latitude = parseFloat($latitudeField.val()) || 0;
                var longitude = parseFloat($longitudeField.val()) || 0;
                var center = new google.maps.LatLng(latitude, longitude);
                map.setCenter(center);
                map.setZoom(15);
                marker.setPosition(center);
                doGeocode();
            });
        });
    });
})(django.jQuery);
<commit_msg>detect no internet available and not render Google map<commit_after>if (jQuery != undefined) {
    var django = {
        'jQuery': jQuery,
    }
}

(function($) {

    $(document).ready(function() {

        try {
            var _ = google;
        } catch (ReferenceError) {
            console.log('geoposition: "google" not defined.  You might not be connected to the internet.');
            return;
        }

        var mapDefaults = {
            'mapTypeId': google.maps.MapTypeId.ROADMAP,
            'scrollwheel': false,
            'streetViewControl': false,
            'panControl': false
        };

        var markerDefaults = {
            'draggable': true,
            'animation': google.maps.Animation.DROP
        };

        $('.geoposition-widget').each(function() {
            var $container = $(this),
                $mapContainer = $('
'),
                $addressRow = $('
'),
                $searchRow = $('
'),
                $searchInput = $('<input>', {'type': 'search', 'placeholder': 'Start typing an address …'}),
                $latitudeField = $container.find('input.geoposition:eq(0)'),
                $longitudeField = $container.find('input.geoposition:eq(1)'),
                latitude = parseFloat($latitudeField.val()) || null,
                longitude = parseFloat($longitudeField.val()) || null,
                map,
                mapLatLng,
                mapOptions,
                mapCustomOptions,
                markerOptions,
                markerCustomOptions,
                marker;

            $mapContainer.css('height', $container.data('map-widget-height') + 'px');
            mapCustomOptions = $container.data('map-options') || {};
            markerCustomOptions = $container.data('marker-options') || {};

            function doSearch() {
                var gc = new google.maps.Geocoder();
                $searchInput.parent().find('ul.geoposition-results').remove();
                gc.geocode({
                    'address': $searchInput.val()
                }, function(results, status) {
                    if (status == 'OK') {
                        var updatePosition = function(result) {
                            if (result.geometry.bounds) {
                                map.fitBounds(result.geometry.bounds);
                            } else {
                                map.panTo(result.geometry.location);
                                map.setZoom(18);
                            }
                            marker.setPosition(result.geometry.location);
                            google.maps.event.trigger(marker, 'dragend');
                        };
                        if (results.length == 1) {
                            updatePosition(results[0]);
                        } else {
                            var $ul = $('
', {'class': 'geoposition-results'});
                            $.each(results, function(i, result) {
                                var $li = $('
');
                                $li.text(result.formatted_address);
                                $li.on('click', function() {
                                    updatePosition(result);
                                    $li.closest('ul').remove();
                                });
                                $li.appendTo($ul);
                            });
                            $searchInput.after($ul);
                        }
                    }
                });
            }

            function doGeocode() {
                var gc = new google.maps.Geocoder();
                gc.geocode({
                    'latLng': marker.position
                }, function(results, status) {
                    $addressRow.text('');
                    if (results && results[0]) {
                        $addressRow.text(results[0].formatted_address);
                    }
                });
            }

            var autoSuggestTimer = null;
            $searchInput.on('keydown', function(e) {
                if (autoSuggestTimer) {
                    clearTimeout(autoSuggestTimer);
                    autoSuggestTimer = null;
                }

                // if enter, search immediately
                if (e.keyCode == 13) {
                    e.preventDefault();
                    doSearch();
                }
                else {
                    // otherwise, search after a while after typing ends
                    autoSuggestTimer = setTimeout(function(){
                        doSearch();
                    }, 1000);
                }
            }).on('abort', function() {
                $(this).parent().find('ul.geoposition-results').remove();
            });
            $searchInput.appendTo($searchRow);
            $container.append($searchRow, $mapContainer, $addressRow);

            mapLatLng = new google.maps.LatLng(latitude, longitude);

            mapOptions = $.extend({}, mapDefaults, mapCustomOptions);

            if (!(latitude === null && longitude === null && mapOptions['center'])) {
                mapOptions['center'] = mapLatLng;
            }

            if (!mapOptions['zoom']) {
                mapOptions['zoom'] = latitude && longitude ? 15 : 1;
            }

            map = new google.maps.Map($mapContainer.get(0), mapOptions);
            markerOptions = $.extend({}, markerDefaults, markerCustomOptions, {
                'map': map
            });

            if (!(latitude === null && longitude === null && markerOptions['position'])) {
                markerOptions['position'] = mapLatLng;
            }

            marker = new google.maps.Marker(markerOptions);
            google.maps.event.addListener(marker, 'dragend', function() {
                $latitudeField.val(this.position.lat());
                $longitudeField.val(this.position.lng());
                doGeocode();
            });
            if ($latitudeField.val() && $longitudeField.val()) {
                google.maps.event.trigger(marker, 'dragend');
            }

            $latitudeField.add($longitudeField).on('keyup', function(e) {
                var latitude = parseFloat($latitudeField.val()) || 0;
                var longitude = parseFloat($longitudeField.val()) || 0;
                var center = new google.maps.LatLng(latitude, longitude);
                map.setCenter(center);
                map.setZoom(15);
                marker.setPosition(center);
                doGeocode();
            });
        });
    });
})(django.jQuery);
<|endoftext|>


<commit_before>var execSync = require('child_process').execSync;
var exec = require('child_process').exec;
var fs = require('fs');

// Defines build process
module.exports = function(grunt) {

  grunt.initConfig({
    cssmin: {
      style: {
        options: {
          shorthandCompacting: false,
          roundingPrecision: -1,
          keepSpecialComments: 0
        },
        files: { 'dist/chart.min.css': 'src/chart.css' }
      }
    },
    usebanner: {
      banner: {
        options: {
          position: 'top',
          linebreak: true,
          process: function() {
            var latestTag = execSync("git describe --tags").toString().split('-')[0].replace("\n", "");
            var firstYear = "2015";
            var lastYear = execSync("git log --format='%ai' | head -n 1").toString().split('-')[0];

            return "/*\n" +
              " * JS Chart v" + latestTag + " (https://github.com/the-software-factory/js-chart)\n" +
              " * Copyright " + ((firstYear === lastYear) ? firstYear : (firstYear + "-" + lastYear)) + " Vendini srl\n" +
              " * Licensed under MIT (https://github.com/the-software-factory/js-chart/blob/master/LICENSE.md)\n" +
              " */";
            }
          },
          files: {
              src: ['dist/chart.min.css', 'dist/chart.min.js']
          }
      }
    },
    devserver: {
      options: {
        port: '9000',
        base: './',
        cache: "no-store",
        async: false
      },
      server: {}
    },
    jshint: {
      options: {
        multistr: true
      },
      all: ['Gruntfile.js', 'src/**/*.js', 'test/*.js', 'test/src/**/*.js']
    },
    uglify: {
      minification: {
        files: {
          'dist/chart.min.js': ['bower_components/Chart.js/Chart.min.js', 'bower_components/jquery.boxfit/dist/jquery.boxfit.min.js', 'src/chart.js']
        }
      }
    },
    watch: {
      scripts: {
        files: ['Gruntfile.js', 'src/**/*', 'test/**/*.js'],
        tasks: ['default']
      }
  },
  conventionalChangelog: {
    options: {
      changelogOpts: {
        preset: 'jshint',
        releaseCount: 0
      }
    },
    release: {
        src: 'CHANGELOG.md'
    }
  }
});

  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-banner');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-devserver');
  grunt.loadNpmTasks('grunt-conventional-changelog');

  grunt.registerTask("emptyTheChangelog", function() {
    fs.truncateSync(grunt.config.get("conventionalChangelog.release.src"), 0);
  });

  grunt.registerTask("changelogCommit", function() {
    var done = this.async();

    var gitAdder = exec('git add CHANGELOG.md');

    gitAdder.on("exit", function(exitCode) {
      if (exitCode !== 0) {
        grunt.fail.fatal("changelogCommit task couldn't exec git add command");
      }

      var gitCommitter = exec('git commit -m "CHANGELOG.md Updated"');

      gitCommitter.on("exit", function(exitCode) {
        if (exitCode !== 0) {
          grunt.fail.fatal("changelogCommit task couldn't exec git commit command");
        }

        grunt.log.ok("Changelog commit is ready");
          done();
      });
    });
  });

  grunt.registerTask('default', ['jshint', 'uglify', 'cssmin', 'usebanner']);
  grunt.registerTask('development', ['default', 'devserver', 'watch']);
  grunt.registerTask("changelog", ["emptyTheChangelog", "conventionalChangelog", "changelogCommit"]);
};
<commit_msg>[[FIX]] Changelog hashes are now clickable links to respective GitHub pages<commit_after>var execSync = require('child_process').execSync;
var exec = require('child_process').exec;
var fs = require('fs');

// Defines build process
module.exports = function(grunt) {

  grunt.initConfig({
    cssmin: {
      style: {
        options: {
          shorthandCompacting: false,
          roundingPrecision: -1,
          keepSpecialComments: 0
        },
        files: { 'dist/chart.min.css': 'src/chart.css' }
      }
    },
    usebanner: {
      banner: {
        options: {
          position: 'top',
          linebreak: true,
          process: function() {
            var latestTag = execSync("git describe --tags").toString().split('-')[0].replace("\n", "");
            var firstYear = "2015";
            var lastYear = execSync("git log --format='%ai' | head -n 1").toString().split('-')[0];

            return "/*\n" +
              " * JS Chart v" + latestTag + " (https://github.com/the-software-factory/js-chart)\n" +
              " * Copyright " + ((firstYear === lastYear) ? firstYear : (firstYear + "-" + lastYear)) + " Vendini srl\n" +
              " * Licensed under MIT (https://github.com/the-software-factory/js-chart/blob/master/LICENSE.md)\n" +
              " */";
            }
          },
          files: {
              src: ['dist/chart.min.css', 'dist/chart.min.js']
          }
      }
    },
    devserver: {
      options: {
        port: '9000',
        base: './',
        cache: "no-store",
        async: false
      },
      server: {}
    },
    jshint: {
      options: {
        multistr: true
      },
      all: ['Gruntfile.js', 'src/**/*.js', 'test/*.js', 'test/src/**/*.js']
    },
    uglify: {
      minification: {
        files: {
          'dist/chart.min.js': ['bower_components/Chart.js/Chart.min.js', 'bower_components/jquery.boxfit/dist/jquery.boxfit.min.js', 'src/chart.js']
        }
      }
    },
    watch: {
      scripts: {
        files: ['Gruntfile.js', 'src/**/*', 'test/**/*.js'],
        tasks: ['default']
      }
  },
  conventionalChangelog: {
    options: {
      changelogOpts: {
        preset: 'jshint',
        releaseCount: 0,
        transform: function(commit, cb) {
          if (typeof commit.gitTags === 'string') {
            var rtag = /tag:\s*[v=]?(.+?)[,\)]/gi;
            var match = rtag.exec(commit.gitTags);
            rtag.lastIndex = 0;

            if (match) {
              commit.version = match[1];
            }
          }

          commit.shortDesc += " [" + commit.hash.slice(0, 7) +
          "](https://github.com/the-software-factory/jquery-chart/commit/" + commit.hash + ")";
          delete commit.hash;

          cb(null, commit);
        }
      }
    },
    release: {
      src: 'CHANGELOG.md'
    }
  }
});

  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-banner');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-devserver');
  grunt.loadNpmTasks('grunt-conventional-changelog');

  grunt.registerTask("emptyTheChangelog", function() {
    fs.truncateSync(grunt.config.get("conventionalChangelog.release.src"), 0);
  });

  grunt.registerTask("changelogCommit", function() {
    var done = this.async();

    var gitAdder = exec('git add CHANGELOG.md');

    gitAdder.on("exit", function(exitCode) {
      if (exitCode !== 0) {
        grunt.fail.fatal("changelogCommit task couldn't exec git add command");
      }

      var gitCommitter = exec('git commit -m "CHANGELOG.md Updated"');

      gitCommitter.on("exit", function(exitCode) {
        if (exitCode !== 0) {
          grunt.fail.fatal("changelogCommit task couldn't exec git commit command");
        }

        grunt.log.ok("Changelog commit is ready");
          done();
      });
    });
  });

  grunt.registerTask('default', ['jshint', 'uglify', 'cssmin', 'usebanner']);
  grunt.registerTask('development', ['default', 'devserver', 'watch']);
  grunt.registerTask("changelog", ["emptyTheChangelog", "conventionalChangelog", "changelogCommit"]);
};
<|endoftext|>


<commit_before>import moment from 'moment';
import {getNonDecimal, getSymbol} from 'ghost-admin/utils/currency';

export default function parseMemberEvent(event) {
    let subject = event.data.member.name || event.data.member.email;
    let icon = getIcon(event);
    let action = getAction(event);
    let object = getObject(event);
    let info = getInfo(event);
    let timestamp = moment(event.data.created_at);

    return {
        memberId: event.data.member_id,
        member: event.data.member,
        emailId: event.data.email_id,
        email: event.data.email,
        icon,
        subject,
        action,
        object,
        info,
        timestamp
    };
}

/* internal helper functions */

function getIcon(event) {
    let icon;

    if (event.type === 'signup_event') {
        icon = 'signed-up';
    }

    if (event.type === 'login_event') {
        icon = 'logged-in';
    }

    if (event.type === 'payment_event') {
        icon = 'made-a-payment';
    }

    if (event.type === 'newsletter_event') {
        if (event.data.subscribed) {
            icon = 'subscribed-to-email';
        } else {
            icon = 'unsubscribed-from-email';
        }
    }

    if (event.type === 'subscription_event') {
        if (event.data.from_plan === null) {
            icon = 'started-subscription';
        }

        if (event.data.to_plan === null) {
            icon = 'canceled-subscription';
        }

        icon = 'started-subscription';
    }

    if (event.type === 'email_opened_event') {
        icon = 'opened-email';
    }

    if (event.type === 'email_delivered_event') {
        icon = 'received-email';
    }

    if (event.type === 'email_failed_event') {
        icon = 'email-delivery-failed';
    }

    return 'event-' + icon;
}

function getAction(event) {
    if (event.type === 'signup_event') {
        return 'signed up';
    }

    if (event.type === 'login_event') {
        return 'logged in';
    }

    if (event.type === 'payment_event') {
        return 'made a payment';
    }

    if (event.type === 'newsletter_event') {
        if (event.data.subscribed) {
            return 'subscribed to';
        } else {
            return 'unsubscribed from';
        }
    }

    if (event.type === 'subscription_event') {
        if (event.data.from_plan === null) {
            return 'started';
        }

        if (event.data.to_plan === null) {
            return 'cancelled';
        }

        return 'changed';
    }

    if (event.type === 'email_opened_event') {
        return 'opened';
    }

    if (event.type === 'email_delivered_event') {
        return 'received';
    }

    if (event.type === 'email_failed_event') {
        return 'failed to receive';
    }
}

function getObject(event) {
    if (event.type === 'newsletter_event') {
        return 'emails';
    }

    if (event.type === 'subscription_event') {
        return 'their subscription';
    }

    if (event.type.match?.(/^email_/)) {
        return 'an email';
    }

    return '';
}

function getInfo(event) {
    if (event.type === 'subscription_event') {
        let mrrDelta = getNonDecimal(event.data.mrr_delta, event.data.currency);
        if (mrrDelta === 0) {
            return;
        }
        let sign = mrrDelta > 0 ? '+' : '-';
        let symbol = getSymbol(event.data.currency);
        return `(MRR ${sign}${symbol}${Math.abs(mrrDelta)})`;
    }
    return;
}
<commit_msg>Ensure from and to plan icons aren't overridden with default icon in Activity Feed<commit_after>import moment from 'moment';
import {getNonDecimal, getSymbol} from 'ghost-admin/utils/currency';

export default function parseMemberEvent(event) {
    let subject = event.data.member.name || event.data.member.email;
    let icon = getIcon(event);
    let action = getAction(event);
    let object = getObject(event);
    let info = getInfo(event);
    let timestamp = moment(event.data.created_at);

    return {
        memberId: event.data.member_id,
        member: event.data.member,
        emailId: event.data.email_id,
        email: event.data.email,
        icon,
        subject,
        action,
        object,
        info,
        timestamp
    };
}

/* internal helper functions */

function getIcon(event) {
    let icon;

    if (event.type === 'signup_event') {
        icon = 'signed-up';
    }

    if (event.type === 'login_event') {
        icon = 'logged-in';
    }

    if (event.type === 'payment_event') {
        icon = 'made-a-payment';
    }

    if (event.type === 'newsletter_event') {
        if (event.data.subscribed) {
            icon = 'subscribed-to-email';
        } else {
            icon = 'unsubscribed-from-email';
        }
    }

    if (event.type === 'subscription_event') {
        icon = 'started-subscription';

        if (event.data.from_plan === null) {
            icon = 'started-subscription';
        }

        if (event.data.to_plan === null) {
            icon = 'canceled-subscription';
        }
    }

    if (event.type === 'email_opened_event') {
        icon = 'opened-email';
    }

    if (event.type === 'email_delivered_event') {
        icon = 'received-email';
    }

    if (event.type === 'email_failed_event') {
        icon = 'email-delivery-failed';
    }

    return 'event-' + icon;
}

function getAction(event) {
    if (event.type === 'signup_event') {
        return 'signed up';
    }

    if (event.type === 'login_event') {
        return 'logged in';
    }

    if (event.type === 'payment_event') {
        return 'made a payment';
    }

    if (event.type === 'newsletter_event') {
        if (event.data.subscribed) {
            return 'subscribed to';
        } else {
            return 'unsubscribed from';
        }
    }

    if (event.type === 'subscription_event') {
        if (event.data.from_plan === null) {
            return 'started';
        }

        if (event.data.to_plan === null) {
            return 'cancelled';
        }

        return 'changed';
    }

    if (event.type === 'email_opened_event') {
        return 'opened';
    }

    if (event.type === 'email_delivered_event') {
        return 'received';
    }

    if (event.type === 'email_failed_event') {
        return 'failed to receive';
    }
}

function getObject(event) {
    if (event.type === 'newsletter_event') {
        return 'emails';
    }

    if (event.type === 'subscription_event') {
        return 'their subscription';
    }

    if (event.type.match?.(/^email_/)) {
        return 'an email';
    }

    return '';
}

function getInfo(event) {
    if (event.type === 'subscription_event') {
        let mrrDelta = getNonDecimal(event.data.mrr_delta, event.data.currency);
        if (mrrDelta === 0) {
            return;
        }
        let sign = mrrDelta > 0 ? '+' : '-';
        let symbol = getSymbol(event.data.currency);
        return `(MRR ${sign}${symbol}${Math.abs(mrrDelta)})`;
    }
    return;
}
<|endoftext|>


<commit_before>/*
 * (C) Copyright 2014 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 */

module.exports = function (grunt) {
  var DIST_DIR = 'dist';

  var pkg = grunt.file.readJSON('package.json');

  const PKG_BROWSER = 'lib/browser.js';

  var bower = {
    TOKEN: process.env.TOKEN,
    repository: 'git://github.com/Kurento/<%= pkg.name %>-bower.git'
  };

  // Project configuration.
  grunt.initConfig({
    pkg: pkg,
    bower: bower,

    // Plugins configuration
    clean: {
      generated_code: DIST_DIR,

      generated_doc: '<%= jsdoc.all.dest %>'
    },

    // Generate documentation
    jsdoc: {
      all: {
        src: [
          'README.md',
          'lib/**/*.js',
          'node_modules/kurento-client-core/lib/**/*.js',
          'node_modules/kurento-client-elements/lib/**/*.js',
          'node_modules/kurento-client-filters/lib/**/*.js',
          'test/*.js'
        ],
        dest: 'doc/jsdoc'
      }
    },

    // Generate browser versions and mapping debug file
    browserify: {
      options: {
        alias: ['<%= pkg.main %>:<%= pkg.name %>']
      },

      'standard': {
        src: PKG_BROWSER,
        dest: DIST_DIR + '/<%= pkg.name %>.js'
      },

      'minified': {
        src: PKG_BROWSER,
        dest: DIST_DIR + '/<%= pkg.name %>.min.js',

        options: {
          browserifyOptions: {
            debug: true
          },
          plugin: [
            ['minifyify', {
              compressPath: DIST_DIR,
              map: '<%= pkg.name %>.map',
              output: DIST_DIR + '/<%= pkg.name %>.map'
            }]
          ]
        }
      }
    },

    // Generate bower.json file from package.json data
    sync: {
      bower: {
        options: {
          sync: [
            'name', 'description', 'license', 'keywords', 'homepage',
            'repository'
          ],
          overrides: {
            authors: (pkg.author ? [pkg.author] : []).concat(pkg.contributors || []),
            main: 'js/<%= pkg.name %>.js'
          }
        }
      }
    },

    // Publish / update package info in Bower
    shell: {
      bower: {
        command: [
          'curl -X DELETE "https://bower.herokuapp.com/packages/<%= pkg.name %>?auth_token=<%= bower.TOKEN %>"',
          'node_modules/.bin/bower register <%= pkg.name %> <%= bower.repository %>',
          'node_modules/.bin/bower cache clean'
        ].join('&&')
      }
    },

    // githooks configuration
    githooks: {
      options: {
        // Task-specific options go here.
      },
      all: {
        'pre-commit': 'clean'
          // Hook definitions go there
      }
    },

    jsbeautifier: {
      "default": {
        src: ["lib/**/*.js", "*.js"],
        options: {
          js: {
            braceStyle: "collapse",
            breakChainedMethods: false,
            e4x: false,
            evalCode: false,
            indentChar: " ",
            indentLevel: 0,
            indentSize: 2,
            indentWithTabs: false,
            jslintHappy: true,
            keepArrayIndentation: false,
            keepFunctionIndentation: false,
            maxPreserveNewlines: 2,
            preserveNewlines: true,
            spaceBeforeConditional: true,
            spaceInParen: false,
            unescapeStrings: false,
            wrapLineLength: 80
          }
        }
      },
      "git-pre-commit": {
        src: ["lib/**/*.js", "*.js"],
        options: {
          mode: "VERIFY_ONLY",
          js: {
            braceStyle: "collapse",
            breakChainedMethods: false,
            e4x: false,
            evalCode: false,
            indentChar: " ",
            indentLevel: 0,
            indentSize: 2,
            indentWithTabs: false,
            jslintHappy: true,
            keepArrayIndentation: false,
            keepFunctionIndentation: false,
            maxPreserveNewlines: 2,
            preserveNewlines: true,
            spaceBeforeConditional: true,
            spaceInParen: false,
            unescapeStrings: false,
            wrapLineLength: 80
          }
        }
      }
    }
  });

  // Load plugins
  grunt.loadNpmTasks('grunt-browserify');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-jsdoc');
  grunt.loadNpmTasks('grunt-npm2bower-sync');
  grunt.loadNpmTasks('grunt-shell');
  grunt.loadNpmTasks('grunt-githooks');
  grunt.loadNpmTasks('grunt-jsbeautifier');

  // Alias tasks
  grunt.registerTask('default', ['clean', 'jsdoc', 'browserify']);
  grunt.registerTask('bower', ['sync:bower', 'shell:bower']);
};
<commit_msg>Gruntfile.js: Add jsbeautifier to git hook<commit_after>/*
 * (C) Copyright 2014 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 */

module.exports = function (grunt) {
  var DIST_DIR = 'dist';

  var pkg = grunt.file.readJSON('package.json');

  const PKG_BROWSER = 'lib/browser.js';

  var bower = {
    TOKEN: process.env.TOKEN,
    repository: 'git://github.com/Kurento/<%= pkg.name %>-bower.git'
  };

  // Project configuration.
  grunt.initConfig({
    pkg: pkg,
    bower: bower,

    // Plugins configuration
    clean: {
      generated_code: DIST_DIR,

      generated_doc: '<%= jsdoc.all.dest %>'
    },

    // Generate documentation
    jsdoc: {
      all: {
        src: [
          'README.md',
          'lib/**/*.js',
          'node_modules/kurento-client-core/lib/**/*.js',
          'node_modules/kurento-client-elements/lib/**/*.js',
          'node_modules/kurento-client-filters/lib/**/*.js',
          'test/*.js'
        ],
        dest: 'doc/jsdoc'
      }
    },

    // Generate browser versions and mapping debug file
    browserify: {
      options: {
        alias: ['<%= pkg.main %>:<%= pkg.name %>']
      },

      'standard': {
        src: PKG_BROWSER,
        dest: DIST_DIR + '/<%= pkg.name %>.js'
      },

      'minified': {
        src: PKG_BROWSER,
        dest: DIST_DIR + '/<%= pkg.name %>.min.js',

        options: {
          browserifyOptions: {
            debug: true
          },
          plugin: [
            ['minifyify', {
              compressPath: DIST_DIR,
              map: '<%= pkg.name %>.map',
              output: DIST_DIR + '/<%= pkg.name %>.map'
            }]
          ]
        }
      }
    },

    // Generate bower.json file from package.json data
    sync: {
      bower: {
        options: {
          sync: [
            'name', 'description', 'license', 'keywords', 'homepage',
            'repository'
          ],
          overrides: {
            authors: (pkg.author ? [pkg.author] : []).concat(pkg.contributors || []),
            main: 'js/<%= pkg.name %>.js'
          }
        }
      }
    },

    // Publish / update package info in Bower
    shell: {
      bower: {
        command: [
          'curl -X DELETE "https://bower.herokuapp.com/packages/<%= pkg.name %>?auth_token=<%= bower.TOKEN %>"',
          'node_modules/.bin/bower register <%= pkg.name %> <%= bower.repository %>',
          'node_modules/.bin/bower cache clean'
        ].join('&&')
      }
    },

    // githooks configuration
    githooks: {
      options: {
        // Task-specific options go here.
      },
      all: {
        'pre-commit': 'jsbeautifier:git-pre-commit'
          // Hook definitions go there
      }
    },

    jsbeautifier: {
      "default": {
        src: ["lib/**/*.js", "*.js"],
        options: {
          js: {
            braceStyle: "collapse",
            breakChainedMethods: false,
            e4x: false,
            evalCode: false,
            indentChar: " ",
            indentLevel: 0,
            indentSize: 2,
            indentWithTabs: false,
            jslintHappy: true,
            keepArrayIndentation: false,
            keepFunctionIndentation: false,
            maxPreserveNewlines: 2,
            preserveNewlines: true,
            spaceBeforeConditional: true,
            spaceInParen: false,
            unescapeStrings: false,
            wrapLineLength: 80
          }
        }
      },
      "git-pre-commit": {
        src: ["lib/**/*.js", "*.js"],
        options: {
          mode: "VERIFY_ONLY",
          js: {
            braceStyle: "collapse",
            breakChainedMethods: false,
            e4x: false,
            evalCode: false,
            indentChar: " ",
            indentLevel: 0,
            indentSize: 2,
            indentWithTabs: false,
            jslintHappy: true,
            keepArrayIndentation: false,
            keepFunctionIndentation: false,
            maxPreserveNewlines: 2,
            preserveNewlines: true,
            spaceBeforeConditional: true,
            spaceInParen: false,
            unescapeStrings: false,
            wrapLineLength: 80
          }
        }
      }
    }
  });

  // Load plugins
  grunt.loadNpmTasks('grunt-browserify');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-jsdoc');
  grunt.loadNpmTasks('grunt-npm2bower-sync');
  grunt.loadNpmTasks('grunt-shell');
  grunt.loadNpmTasks('grunt-githooks');
  grunt.loadNpmTasks('grunt-jsbeautifier');

  // Alias tasks
  grunt.registerTask('default', ['clean', 'jsdoc', 'browserify']);
  grunt.registerTask('bower', ['sync:bower', 'shell:bower']);
};
<|endoftext|>


<commit_before>/*
 * lintel-contrib-navs
 * https://github.com/lintelio/lintel-contrib-navs
 *
 * Copyright (c) 2015 Marius Craciunoiu
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function (grunt) {
  var lintel = {
    test: 'test',
    dist: 'dist'
  };

  // Load all npm grunt tasks
  require('load-grunt-tasks')(grunt);

  // Project configuration.
  grunt.initConfig({
    lintel: lintel,

    // Compile sass
    sass: {
      options: {
        sourceMap: true,
        includePaths: [
          'bower_components/lintel/sass',
          'bower_components',
          'sass'
        ]
      },
      dist: {
        files: {
          '<%= lintel.dist %>/navs.css': 'sass/lintel-core-loader.scss'
        }
      }
    },

    // Autoprefix sass
    autoprefixer: {
      dist: {
        src: '<%= lintel.dist %>/navs.css'
      }
    },

    // Minify css
    cssmin: {
      // TODO: sourcemap
      dist: {
        src: '<%= lintel.dist %>/navs.css',
        dest: '<%= lintel.dist %>/navs.min.css'
      }
    },

    // Lint css
    csslint: {
      options: {
        csslintrc: '.csslintrc'
      },
      dist: {
        src: ['<%= lintel.dist %>/navs.css']
      }
    },

    // Start test server
    connect: {
      test: {
        options: {
          base: [
            './',
            '<%= lintel.dist %>',
            '<%= lintel.test %>/fixtures'
          ],
          livereload: true,
          port: 4554
        }
      }
    },

    // Remove previous screenshots
    clean: {
      tests: ['<%= lintel.test %>/tmp']
    },

    // Take new screenshots
    webshot: {
      xs: {
        options: {
          siteType: 'url',
          site: 'http://localhost:4554/navs.html',
          savePath: '<%= lintel.test %>/tmp/xs.png',
          windowSize: {
              width: 320,
              height: 568
          },
          shotSize: {
              width: 320,
              height: 'all'
          }
        }
      },
      sm: {
        options: {
          siteType: 'url',
          site: 'http://localhost:4554/navs.html',
          savePath: '<%= lintel.test %>/tmp/sm.png',
          windowSize: {
              width: 480,
              height: 568
          },
          shotSize: {
              width: 480,
              height: 'all'
          }
        }
      },
      md: {
        options: {
          siteType: 'url',
          site: 'http://localhost:4554/navs.html',
          savePath: '<%= lintel.test %>/tmp/md.png',
          windowSize: {
              width: 768,
              height: 1024
          },
          shotSize: {
              width: 768,
              height: 'all'
          }
        }
      },
      lg: {
        options: {
          siteType: 'url',
          site: 'http://localhost:4554/navs.html',
          savePath: '<%= lintel.test %>/tmp/lg.png',
          windowSize: {
              width: 1024,
              height: 768
          },
          shotSize: {
              width: 1024,
              height: 'all'
          }
        }
      },
      xl: {
        options: {
          siteType: 'url',
          site: 'http://localhost:4554/navs.html',
          savePath: '<%= lintel.test %>/tmp/xl.png',
          windowSize: {
              width: 1280,
              height: 800
          },
          shotSize: {
              width: 1280,
              height: 'all'
          }
        }
      },
      "2xl": {
        options: {
          siteType: 'url',
          site: 'http://localhost:4554/navs.html',
          savePath: '<%= lintel.test %>/tmp/2xl.png',
          windowSize: {
              width: 1440,
              height: 900
          },
          shotSize: {
              width: 1440,
              height: 'all'
          }
        }
      },
      "3xl": {
        options: {
          siteType: 'url',
          site: 'http://localhost:4554/navs.html',
          savePath: '<%= lintel.test %>/tmp/3xl.png',
          windowSize: {
              width: 1680,
              height: 1050
          },
          shotSize: {
              width: 1680,
              height: 'all'
          }
        }
      },
      max: {
        options: {
          siteType: 'url',
          site: 'http://localhost:4554/navs.html',
          savePath: '<%= lintel.test %>/tmp/max.png',
          windowSize: {
              width: 1920,
              height: 1080
          },
          shotSize: {
              width: 1920,
              height: 'all'
          }
        }
      }
    },

    // Lint js
    jshint: {
      options: {
        jshintrc: '.jshintrc'
      },
      files: {
        src: ['js/**/*.js']
      }
    },

    // Minify js
    uglify: {
      options: {
        mangle: true,
        compress: true,
        sourceMap: true,
      },
      individual: {
        files: [{
          expand: true,
          cwd: 'js',
          src: '**/*.js',
          dest: 'dist/'
        }]
      },
      concat: {
        files: {
          'dist/navs.min.js': ['js/**/*.js']
        }
      }
    },

    // Run tests
    nodeunit: {
      tests: ['<%= lintel.test %>/*_test.js']
    },

    // Watch for changes
    watch: {
      sass: {
        files: [
          'sass/**/*.scss'
        ],
        tasks: ['sass-compile']
      },
      js: {
        files: [
          'js/**/*.js'
        ],
        tasks: ['js-compile']
      },
      livereload: {
        files: [
          '<%= lintel.dist %>/**/*.css'
        ],
        options: {
          livereload: true
        }
      },
    },

    // Notify of changes
    notify: {
      sass: {
        options: {
          title: 'lintel-contrib-navs',
          message: 'SASS Compiled'
        }
      },
      js: {
        options: {
          title: 'lintel-contrib-navs',
          message: 'JS Compiled'
        }
      }
    }

  });

  grunt.registerTask('sass-compile', ['sass:dist', 'autoprefixer:dist', 'cssmin:dist', 'csslint', 'notify:sass']);

  grunt.registerTask('js-compile', ['uglify', 'jshint', 'notify:js']);

  grunt.registerTask('test', ['sass-compile', 'js-compile', 'connect', 'clean:tests', 'webshot', 'nodeunit']);

  // By default, lint and run all tests.
  grunt.registerTask('default', ['test', 'watch']);

};
<commit_msg>Copy original js files.<commit_after>/*
 * lintel-contrib-navs
 * https://github.com/lintelio/lintel-contrib-navs
 *
 * Copyright (c) 2015 Marius Craciunoiu
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function (grunt) {
  var lintel = {
    test: 'test',
    dist: 'dist'
  };

  // Load all npm grunt tasks
  require('load-grunt-tasks')(grunt);

  // Project configuration.
  grunt.initConfig({
    lintel: lintel,

    // Compile sass
    sass: {
      options: {
        sourceMap: true,
        includePaths: [
          'bower_components/lintel/sass',
          'bower_components',
          'sass'
        ]
      },
      dist: {
        files: {
          '<%= lintel.dist %>/navs.css': 'sass/lintel-core-loader.scss'
        }
      }
    },

    // Autoprefix sass
    autoprefixer: {
      dist: {
        src: '<%= lintel.dist %>/navs.css'
      }
    },

    // Minify css
    cssmin: {
      // TODO: sourcemap
      dist: {
        src: '<%= lintel.dist %>/navs.css',
        dest: '<%= lintel.dist %>/navs.min.css'
      }
    },

    // Lint css
    csslint: {
      options: {
        csslintrc: '.csslintrc'
      },
      dist: {
        src: ['<%= lintel.dist %>/navs.css']
      }
    },

    // Start test server
    connect: {
      test: {
        options: {
          base: [
            './',
            '<%= lintel.dist %>',
            '<%= lintel.test %>/fixtures'
          ],
          livereload: true,
          port: 4554
        }
      }
    },

    // Remove previous screenshots
    clean: {
      tests: ['<%= lintel.test %>/tmp']
    },

    // Take new screenshots
    webshot: {
      xs: {
        options: {
          siteType: 'url',
          site: 'http://localhost:4554/navs.html',
          savePath: '<%= lintel.test %>/tmp/xs.png',
          windowSize: {
              width: 320,
              height: 568
          },
          shotSize: {
              width: 320,
              height: 'all'
          }
        }
      },
      sm: {
        options: {
          siteType: 'url',
          site: 'http://localhost:4554/navs.html',
          savePath: '<%= lintel.test %>/tmp/sm.png',
          windowSize: {
              width: 480,
              height: 568
          },
          shotSize: {
              width: 480,
              height: 'all'
          }
        }
      },
      md: {
        options: {
          siteType: 'url',
          site: 'http://localhost:4554/navs.html',
          savePath: '<%= lintel.test %>/tmp/md.png',
          windowSize: {
              width: 768,
              height: 1024
          },
          shotSize: {
              width: 768,
              height: 'all'
          }
        }
      },
      lg: {
        options: {
          siteType: 'url',
          site: 'http://localhost:4554/navs.html',
          savePath: '<%= lintel.test %>/tmp/lg.png',
          windowSize: {
              width: 1024,
              height: 768
          },
          shotSize: {
              width: 1024,
              height: 'all'
          }
        }
      },
      xl: {
        options: {
          siteType: 'url',
          site: 'http://localhost:4554/navs.html',
          savePath: '<%= lintel.test %>/tmp/xl.png',
          windowSize: {
              width: 1280,
              height: 800
          },
          shotSize: {
              width: 1280,
              height: 'all'
          }
        }
      },
      "2xl": {
        options: {
          siteType: 'url',
          site: 'http://localhost:4554/navs.html',
          savePath: '<%= lintel.test %>/tmp/2xl.png',
          windowSize: {
              width: 1440,
              height: 900
          },
          shotSize: {
              width: 1440,
              height: 'all'
          }
        }
      },
      "3xl": {
        options: {
          siteType: 'url',
          site: 'http://localhost:4554/navs.html',
          savePath: '<%= lintel.test %>/tmp/3xl.png',
          windowSize: {
              width: 1680,
              height: 1050
          },
          shotSize: {
              width: 1680,
              height: 'all'
          }
        }
      },
      max: {
        options: {
          siteType: 'url',
          site: 'http://localhost:4554/navs.html',
          savePath: '<%= lintel.test %>/tmp/max.png',
          windowSize: {
              width: 1920,
              height: 1080
          },
          shotSize: {
              width: 1920,
              height: 'all'
          }
        }
      }
    },

    // Lint js
    jshint: {
      options: {
        jshintrc: '.jshintrc'
      },
      files: {
        src: ['js/**/*.js']
      }
    },

    // Minify js
    uglify: {
      options: {
        mangle: true,
        compress: true,
        sourceMap: true,
      },
      individual: {
        files: [{
          expand: true,
          cwd: 'js',
          src: '**/*.js',
          dest: 'dist/'
        }]
      },
      concat: {
        files: {
          'dist/navs.min.js': ['js/**/*.js']
        }
      }
    },

    // Copy files
    copy: {
      js: {
        files: [{
          expand: true,
          cwd: 'js/',
          src: ['**/*.js'],
          dest: 'dist/'
        }]
      }
    },

    // Run tests
    nodeunit: {
      tests: ['<%= lintel.test %>/*_test.js']
    },

    // Watch for changes
    watch: {
      sass: {
        files: [
          'sass/**/*.scss'
        ],
        tasks: ['sass-compile']
      },
      js: {
        files: [
          'js/**/*.js'
        ],
        tasks: ['js-compile']
      },
      livereload: {
        files: [
          '<%= lintel.dist %>/**/*.css'
        ],
        options: {
          livereload: true
        }
      },
    },

    // Notify of changes
    notify: {
      sass: {
        options: {
          title: 'lintel-contrib-navs',
          message: 'SASS Compiled'
        }
      },
      js: {
        options: {
          title: 'lintel-contrib-navs',
          message: 'JS Compiled'
        }
      }
    }

  });

  grunt.registerTask('sass-compile', ['sass:dist', 'autoprefixer:dist', 'cssmin:dist', 'csslint', 'notify:sass']);

  grunt.registerTask('js-compile', ['copy:js', 'uglify:concat', 'jshint', 'notify:js']);

  grunt.registerTask('test', ['sass-compile', 'js-compile', 'connect', 'clean:tests', 'webshot', 'nodeunit']);

  // By default, lint and run all tests.
  grunt.registerTask('default', ['test', 'watch']);

};
<|endoftext|>