<commit_before>(function() {

    "use strict";

    angular.module('common.mediaelement', [])

    .directive('mediaelement', [function() {
        return {
            restrict: 'A',
            link: function(scope, element, attrs) {
                attrs.$observe('src', function() {
                    element.mediaelementplayer();
                });
            }
        };
    }]);

})();
<commit_msg>code update<commit_after>(function() {

    "use strict";

    angular.module('common.mediaelement', [])

    .directive('mediaelement', [function() {
        return {
            restrict: 'A',
            link: function(scope, element, attrs) {
                attrs.$observe('src', function() {
                    element.mediaelementplayer({
                        // if set, overrides <video width>
                        videoWidth: -1,
                        // if set, overrides <video height>
                        videoHeight: -1,
                        // width of audio player
                        audioWidth: 400,
                        // height of audio player
                        audioHeight: 30,
                        // initial volume when the player starts
                        startVolume: 0.8,
                        // useful for <audio> player loops
                        loop: false,
                        // enables Flash and Silverlight to resize to content size
                        enableAutosize: true,
                        // the order of controls you want on the control bar (and other plugins below)
                        features: ['playpause','progress','current','duration','tracks','volume','fullscreen'],
                        // Hide controls when playing and mouse is not over the video
                        alwaysShowControls: false,
                        // force iPad's native controls
                        iPadUseNativeControls: false,
                        // force iPhone's native controls
                        iPhoneUseNativeControls: false,
                        // force Android's native controls
                        AndroidUseNativeControls: false,
                        // forces the hour marker (##:00:00)
                        alwaysShowHours: false,
                        // show framecount in timecode (##:00:00:00)
                        showTimecodeFrameCount: false,
                        // used when showTimecodeFrameCount is set to true
                        framesPerSecond: 25,
                        // turns keyboard support on and off for this instance
                        enableKeyboard: true,
                        // when this player starts, it will pause other players
                        pauseOtherPlayers: true,
                        // array of keyboard commands
                        keyActions: []

                    });
                });
            }
        };
    }]);

})();
<|endoftext|>


<commit_before>H5.Camera = (function () {
    'use strict';

    function Camera(viewPort, maxX, maxY) {
        this.viewPort = viewPort;

        // 1st universe grid tiles (u,v)
        // 2nd universe px screen coordinates (x,y)
        // 3rd universe px space coordinates (x,y)
        // - while screen coordinates are relative, space coordinates are an absolute representation of tiles in px

        this.minX = this.viewPort.getWidthHalf();
        this.minY = this.viewPort.getHeightHalf();
        this.maxX = maxX;
        this.maxY = maxY;

        this.isPositionLocked = false;
        this.isShow = true;
        this.__zoom = 1;
    }

    Camera.prototype.calcScreenPosition = function (entity, drawable, ignoreScale, useDrawableScale) {
        if (this.__zoom === 1) {
            var cornerX = this.viewPort.getCornerX();
            var cornerY = this.viewPort.getCornerY();
            if (entity.getEndX() < cornerX || entity.getCornerX() > this.viewPort.getEndX() ||
                entity.getEndY() < cornerY || entity.getCornerY() > this.viewPort.getEndY()) {

                drawable.show = false;
                return;
            }

            drawable.show = this.isShow;

            drawable.x = entity.x - cornerX;
            drawable.y = entity.y - cornerY;
            if (!ignoreScale) {
                drawable.scale = entity.scale;
            }

            return;
        }

        var widthHalf = this.viewPort.getWidthHalf() / this.__zoom;
        var heightHalf = this.viewPort.getHeightHalf() / this.__zoom;
        var left = this.viewPort.x - widthHalf;
        var right = this.viewPort.x + widthHalf;
        var top = this.viewPort.y - heightHalf;
        var bottom = this.viewPort.y + heightHalf;

        var entityRight = entity.getEndX();
        var entityLeft = entity.getCornerX();
        var entityBottom = entity.getEndY();
        var entityTop = entity.getCornerY();

        if (entityRight < left || entityLeft > right || entityBottom < top || entityTop > bottom) {
            drawable.show = false;
            return;
        }

        drawable.show = this.isShow;

        drawable.x = (entity.x - left) * this.__zoom;
        drawable.y = (entity.y - top) * this.__zoom;
        if (useDrawableScale) {
            if (drawable.currentScale === undefined) {
                drawable.currentScale = drawable.scale;
            }
            drawable.scale = drawable.currentScale * this.__zoom;
        } else {
            drawable.scale = entity.scale * this.__zoom;
        }
    };

    Camera.prototype.calcBulletsScreenPosition = function (entity, drawable) {
        var cornerX = this.viewPort.getCornerX();
        var cornerY = this.viewPort.getCornerY();

        var right = entity.data.ax > entity.data.bx ? entity.data.ax : entity.data.bx;
        var left = entity.data.ax < entity.data.bx ? entity.data.ax : entity.data.bx;
        var bottom = entity.data.ay > entity.data.by ? entity.data.ay : entity.data.by;
        var top = entity.data.ay < entity.data.by ? entity.data.ay : entity.data.by;

        if (right < cornerX || left > this.viewPort.getEndX() || bottom < cornerY || top > this.viewPort.getEndY()) {

            drawable.show = false;
            return;
        }

        drawable.show = this.isShow;

        drawable.data.ax = entity.data.ax - cornerX * this.viewPort.scale;
        drawable.data.ay = entity.data.ay - cornerY * this.viewPort.scale;
        drawable.data.bx = entity.data.bx - cornerX * this.viewPort.scale;
        drawable.data.by = entity.data.by - cornerY * this.viewPort.scale;
    };

    Camera.prototype.move = function (anchor) {
        if (this.isPositionLocked) {
            return;
        }

        this.viewPort.x = anchor.x;
        this.viewPort.y = anchor.y;

        var minX = this.minX / this.__zoom;
        var minY = this.minY / this.__zoom;
        var maxX = this.__zoom !== 1 ? this.maxX + minX : this.maxX;
        var maxY = this.__zoom !== 1 ? this.maxY + minY : this.maxY;
        if (this.viewPort.x < minX) {
            this.viewPort.x = minX;
        }
        if (this.viewPort.x > maxX) {
            this.viewPort.x = maxX;
        }
        if (this.viewPort.y < minY) {
            this.viewPort.y = minY;
        }
        if (this.viewPort.y > maxY) {
            this.viewPort.y = maxY;
        }
    };

    Camera.prototype.unlockPosition = function () {
        this.isPositionLocked = false;
    };

    Camera.prototype.lockPosition = function () {
        this.isPositionLocked = true;
    };

    Camera.prototype.hideDrawables = function () {
        this.isShow = false;
    };

    Camera.prototype.showDrawables = function () {
        this.isShow = true;
    };

    Camera.prototype.zoom = function (factor) {
        this.__zoom = factor;
    };

    Camera.prototype.zoomRelative = function (factor) {
        this.__zoom += factor;
    };

    Camera.prototype.getZoom = function (factor) {
        return this.__zoom;
    };

    return Camera;
})();<commit_msg>removed unused parameter<commit_after>H5.Camera = (function () {
    'use strict';

    function Camera(viewPort, maxX, maxY) {
        this.viewPort = viewPort;

        // 1st universe grid tiles (u,v)
        // 2nd universe px screen coordinates (x,y)
        // 3rd universe px space coordinates (x,y)
        // - while screen coordinates are relative, space coordinates are an absolute representation of tiles in px

        this.minX = this.viewPort.getWidthHalf();
        this.minY = this.viewPort.getHeightHalf();
        this.maxX = maxX;
        this.maxY = maxY;

        this.isPositionLocked = false;
        this.isShow = true;
        this.__zoom = 1;
    }

    Camera.prototype.calcScreenPosition = function (entity, drawable, ignoreScale, useDrawableScale) {
        if (this.__zoom === 1) {
            var cornerX = this.viewPort.getCornerX();
            var cornerY = this.viewPort.getCornerY();
            if (entity.getEndX() < cornerX || entity.getCornerX() > this.viewPort.getEndX() ||
                entity.getEndY() < cornerY || entity.getCornerY() > this.viewPort.getEndY()) {

                drawable.show = false;
                return;
            }

            drawable.show = this.isShow;

            drawable.x = entity.x - cornerX;
            drawable.y = entity.y - cornerY;
            if (!ignoreScale) {
                drawable.scale = entity.scale;
            }

            return;
        }

        var widthHalf = this.viewPort.getWidthHalf() / this.__zoom;
        var heightHalf = this.viewPort.getHeightHalf() / this.__zoom;
        var left = this.viewPort.x - widthHalf;
        var right = this.viewPort.x + widthHalf;
        var top = this.viewPort.y - heightHalf;
        var bottom = this.viewPort.y + heightHalf;

        var entityRight = entity.getEndX();
        var entityLeft = entity.getCornerX();
        var entityBottom = entity.getEndY();
        var entityTop = entity.getCornerY();

        if (entityRight < left || entityLeft > right || entityBottom < top || entityTop > bottom) {
            drawable.show = false;
            return;
        }

        drawable.show = this.isShow;

        drawable.x = (entity.x - left) * this.__zoom;
        drawable.y = (entity.y - top) * this.__zoom;
        if (useDrawableScale) {
            if (drawable.currentScale === undefined) {
                drawable.currentScale = drawable.scale;
            }
            drawable.scale = drawable.currentScale * this.__zoom;
        } else {
            drawable.scale = entity.scale * this.__zoom;
        }
    };

    Camera.prototype.calcBulletsScreenPosition = function (entity, drawable) {
        var cornerX = this.viewPort.getCornerX();
        var cornerY = this.viewPort.getCornerY();

        var right = entity.data.ax > entity.data.bx ? entity.data.ax : entity.data.bx;
        var left = entity.data.ax < entity.data.bx ? entity.data.ax : entity.data.bx;
        var bottom = entity.data.ay > entity.data.by ? entity.data.ay : entity.data.by;
        var top = entity.data.ay < entity.data.by ? entity.data.ay : entity.data.by;

        if (right < cornerX || left > this.viewPort.getEndX() || bottom < cornerY || top > this.viewPort.getEndY()) {

            drawable.show = false;
            return;
        }

        drawable.show = this.isShow;

        drawable.data.ax = entity.data.ax - cornerX * this.viewPort.scale;
        drawable.data.ay = entity.data.ay - cornerY * this.viewPort.scale;
        drawable.data.bx = entity.data.bx - cornerX * this.viewPort.scale;
        drawable.data.by = entity.data.by - cornerY * this.viewPort.scale;
    };

    Camera.prototype.move = function (anchor) {
        if (this.isPositionLocked) {
            return;
        }

        this.viewPort.x = anchor.x;
        this.viewPort.y = anchor.y;

        var minX = this.minX / this.__zoom;
        var minY = this.minY / this.__zoom;
        var maxX = this.__zoom !== 1 ? this.maxX + minX : this.maxX;
        var maxY = this.__zoom !== 1 ? this.maxY + minY : this.maxY;
        if (this.viewPort.x < minX) {
            this.viewPort.x = minX;
        }
        if (this.viewPort.x > maxX) {
            this.viewPort.x = maxX;
        }
        if (this.viewPort.y < minY) {
            this.viewPort.y = minY;
        }
        if (this.viewPort.y > maxY) {
            this.viewPort.y = maxY;
        }
    };

    Camera.prototype.unlockPosition = function () {
        this.isPositionLocked = false;
    };

    Camera.prototype.lockPosition = function () {
        this.isPositionLocked = true;
    };

    Camera.prototype.hideDrawables = function () {
        this.isShow = false;
    };

    Camera.prototype.showDrawables = function () {
        this.isShow = true;
    };

    Camera.prototype.zoom = function (factor) {
        this.__zoom = factor;
    };

    Camera.prototype.zoomRelative = function (factor) {
        this.__zoom += factor;
    };

    Camera.prototype.getZoom = function () {
        return this.__zoom;
    };

    return Camera;
})();<|endoftext|>


<commit_before>require('es6-promise').polyfill();

var request = require('request');
var url = require('url');

module.exports = function(username, password, hostname) {
  var uri = url.resolve(hostname, '/rest/api/content/search');
  return {
    simpleSearch: function(str) {
      return new Promise(function(resolve, reject) {
        request({
          method: 'GET',
          uri: uri,
          json: true,
          qs: {
            limit: 5,
            cql: 'type is page and title ~ "' + str + '"'
          },
          auth: {
            'user': username,
            'pass': password,
            'sendImmediately': true
          },
        }, function( err, response, results) {
          if (err) { return reject(err); }
          //Check for right status code
          if(response.statusCode !== 200) {
            return reject('Invalid Status Code Returned:', response.statusCode);
          }

          if (!results) { return reject("empty result object"); }
          return resolve(results);
        });
      });
    }
  };
};
<commit_msg>search title and text<commit_after>require('es6-promise').polyfill();

var request = require('request');
var url = require('url');

module.exports = function(username, password, hostname) {
  var uri = url.resolve(hostname, '/rest/api/content/search');
  return {
    simpleSearch: function(str) {
      return new Promise(function(resolve, reject) {
        request({
          method: 'GET',
          uri: uri,
          json: true,
          qs: {
            limit: 5,
            cql: 'type is page and (title ~ "' + str + '" or text ~ "' + str + '")'
          },
          auth: {
            'user': username,
            'pass': password,
            'sendImmediately': true
          },
        }, function( err, response, results) {
          if (err) { return reject(err); }
          //Check for right status code
          if(response.statusCode !== 200) {
            return reject('Invalid Status Code Returned:', response.statusCode);
          }

          if (!results) { return reject("empty result object"); }
          return resolve(results);
        });
      });
    }
  };
};
<|endoftext|>


<commit_before>(function (angular, _, moment) {
    'use strict';

    var module = angular.module('angular-input-fields', ['gettext']);

    module.directive('aifSingleChoiceInput', [
        function () {
            return {
                restrict: 'A',
                replace: true,
                scope: {
                    model: '=',
                    choices: '=',
                    disable: '=?',
                    emptyLabel: '=?'
                },
                templateUrl: 'templates/type/single-choice-input.html'
            };
        }
    ]);

    module.directive('aifSelectInput', [
        function () {
            return {
                restrict: 'A',
                scope: {
                    model: '=',
                    choices: '=',
                    disable: '=?',
                    emptyLabel: '=?'
                },
                templateUrl: 'templates/type/select-input.html'
            };
        }
    ]);

    // Renders a pair of select inputs, one for the groups and the other for the
    // selected group's choices.
    module.directive('aifGroupedSelectInput', [
        'gettextCatalog',
        function (gettextCatalog) {
            return {
                restrict: 'A',
                replace: true,
                scope: {
                    model: '=',
                    groupedChoices: '=',
                    disable: '=?',
                    emptyLabel: '=?'
                },
                templateUrl: 'templates/type/grouped-select-input.html',
                link: function (scope, element, attrs) {

                    // Helper method to get a group's choice based on a value.
                    // Returns undefined if no choice is found.
                    var getGroupChoice = function (group, value) {
                        if (angular.isDefined(group)) {
                            return _.findWhere(group.choices, {
                                value: value
                            });
                        }
                    };

                    // Set initialise groups when choice change.
                    scope.$watch('groupedChoices', function (groupedChoices) {
                        scope.groups = [];
                        scope.group = {
                            choices: []
                        };
                        if (angular.isDefined(groupedChoices)) {
                            var otherChoices = [];
                            angular.forEach(groupedChoices, function (item) {
                                if (angular.isDefined(item.choices)) {
                                    // Group with choices

                                    if (scope.emptyLabel && angular.isUndefined(getGroupChoice(item, ''))) {
                                        // jscs:disable requireCamelCaseOrUpperCaseIdentifiers
                                        /* jshint camelcase: false */

                                        // Add the emptyLabel to the start of choices.
                                        item.choices.unshift({
                                            display_name: scope.emptyLabel,
                                            value: ''
                                        });
                                        // jscs:enable requireCamelCaseOrUpperCaseIdentifiers
                                    }

                                    // Reference the item as the value so it is
                                    // used when the item is selected.
                                    item.value = item;

                                    scope.groups.push(item);
                                } else {
                                    // Choice that does not belong to a group
                                    otherChoices.push(item);
                                }
                            });
                            if (otherChoices.length) {
                                // jscs:disable requireCamelCaseOrUpperCaseIdentifiers
                                /* jshint camelcase: false */
                                scope.groups.push({
                                    display_name: gettextCatalog.getString('Other'),
                                    choices: otherChoices
                                });
                                // jscs:enable requireCamelCaseOrUpperCaseIdentifiers
                            }
                        }
                    });

                    // Set group when model changes.
                    scope.$watch('model', function (value) {
                        if (angular.isDefined(value) && value !== null) {
                            angular.forEach(scope.groupedChoices, function (group) {
                                if (angular.isDefined(getGroupChoice(group, value))) {
                                    scope.group = group;
                                }
                            });
                        }
                    });

                    // Check model is valid when group changes.
                    scope.$watch('group', function (group) {
                        if (group !== null && angular.isDefined(getGroupChoice(group, scope.model))) {
                            // Model is one of the group choices.
                            return;
                        }

                        scope.model = null;
                    });
                }
            };
        }
    ]);

    module.directive('aifRadioInput', [
        function () {
            return {
                restrict: 'A',
                scope: {
                    model: '=',
                    choices: '=',
                    disable: '=?'
                },
                templateUrl: 'templates/type/radio-input.html',
                link: function (scope) {
                    scope.localModel = {
                        value: scope.model
                    };

                    scope.$watch('localModel.value', function (value) {
                        scope.model = value;
                    });
                }
            };
        }
    ]);

    module.directive('aifCheckboxInput', [
        function () {
            return {
                restrict: 'A',
                replace: true,
                scope: {
                    model: '=',
                    label: '=',
                    disable: '=?'
                },
                templateUrl: 'templates/type/checkbox-input.html'
            };
        }
    ]);

    module.directive('aifBooleanInput', [
        function () {
            return {
                restrict: 'A',
                replace: true,
                templateUrl: 'templates/type/boolean-input.html',
                scope: {
                    model: '=',
                    disable: '=?'
                },
                link: function (scope, element, attrs) {

                    scope.$watch('boolValue', function () {
                        var value = false;

                        if (scope.boolValue === 'true') {
                            value = true;
                        }

                        scope.model = value;
                    });

                }
            };
        }
    ]);

    module.directive('aifTextInput', [
        function () {
            return {
                restrict: 'A',
                replace: true,
                scope: {
                    model: '=',
                    disable: '=?'
                },
                templateUrl: 'templates/type/text-input.html'
            };
        }
    ]);

    module.directive('aifNumberInput', [
        function () {
            return {
                restrict: 'A',
                replace: true,
                scope: {
                    model: '=',
                    disable: '=?'
                },
                templateUrl: 'templates/type/number-input.html'
            };
        }
    ]);

    module.directive('aifSliderInput', [
        'gettextCatalog',
        function (gettextCatalog) {
            return {
                restrict: 'A',
                replace: true,
                templateUrl: 'templates/type/slider-input.html',
                scope: {
                    model: '=',
                    disable: '=?',
                    ceiling: '=?',
                    translateFn: '=?',
                    className: '@'
                },
                link: function (scope, element, attrs) {
                    if (angular.isUndefined(scope.translateFn)) {
                        scope.translateFn = function (input) {
                            return input;
                        };
                    }

                    if (angular.isUndefined(scope.className)) {
                        scope.className = null;
                    }

                    if (angular.isUndefined(scope.ceiling)) {
                        scope.ceiling = 10;
                    }

                    scope.sliderLowLabel = attrs.sliderLowLabel || gettextCatalog.getString('none');
                    scope.sliderMiddleLabel = attrs.sliderMiddleLabel;
                    scope.sliderHighLabel = attrs.sliderHighLabel || gettextCatalog.getString('very severe');
                }
            };
        }
    ]);

    module.directive('aifSwitchInput', [
        function () {
            return {
                restrict: 'A',
                replace: true,
                scope: {
                    model: '=',
                    choices: '=',
                    disable: '=?'
                },
                templateUrl: 'templates/type/switch-input.html',
                link: function (scope, element, attrs) {
                    // Work around btn-radio ng-model bind issues
                    scope.data = {
                        model: scope.model
                    };
                    scope.$watch('model', function (value) {
                        if (angular.isDefined(value)) {
                            scope.data.model = value;
                        }
                    });
                    scope.$watch('data.model', function (value) {
                        if (angular.isDefined(value)) {
                            scope.model = value;
                        }
                    });
                }
            };
        }
    ]);

    module.filter('aifNumberPadding', [
        function () {
            return _.memoize(function (input, numOfDigits) {
                input = input.toString();
                while (input.length < numOfDigits) {
                    input = '0' + input;
                }

                return input;
            }, function (input, numOfDigits) {
                return input + '' + numOfDigits;
            });
        }
    ]);

    module.directive('aifMomentSelect', [
            '$compile',
        function ($compile) {
            return {
                restrict: 'A',
                scope: {
                    model: '=',
                    disable: '=?',
                    hourMax: '@',
                    minuteMax: '@',
                    hourMin: '@',
                    minuteMin: '@',
                    hourStep: '@',
                    minuteStep: '@',
                    useDuration: '=',
                    hoursLen: '@',
                    minutesLen: '@'
                },
                templateUrl: 'templates/type/moment-select.html',
                compile: function (element, attrs) {
                    // Add default attributes
                    _.defaults(attrs, {
                        hourMin: '0',
                        hourMax: '24',
                        hourStep: '1',
                        minuteMin: '0',
                        minuteMax: '60',
                        minuteStep: '1',
                        useDuration: false,
                        hoursLen: '0',
                        minutesLen: '0'
                    });

                    // Return the (post) link function
                    return function (scope, element, attrs) {
                        scope.hourChoices = _.range(scope.hourMin, scope.hourMax, scope.hourStep);
                        scope.minuteChoices = _.range(scope.minuteMin, scope.minuteMax, scope.minuteStep);

                        var group = ['hours', 'minutes'];

                        var cast = (scope.useDuration) ? moment.duration : moment;

                        scope.$watchGroup(['hours', 'minutes'], function (newValues) {
                            var hours = newValues[0];
                            var minutes = newValues[1];
                            var timeObject = {};

                            if (angular.isDefined(hours)) {
                                timeObject.hours = hours;
                            }
                            if (angular.isDefined(minutes)) {
                                timeObject.minutes = minutes;
                            }
                            scope.model = cast(timeObject);
                        });

                        var deregisterModelWatch = scope.$watch('model', function (value) {
                            if (angular.isDefined(scope.model)) {
                                value = cast(scope.model);
                                var timeObject = {};
                                var hours = group[0];
                                var minutes = group[1];

                                if (angular.isDefined(hours)) {
                                    timeObject.hours = value.get(hours);
                                }
                                if (angular.isDefined(minutes)) {
                                    timeObject.minutes = value.get(minutes);
                                }
                                angular.extend(scope, timeObject);
                                deregisterModelWatch();
                            }
                        });
                    };
                }
            };
        }
    ]);

}(window.angular, window._, window.moment));
<commit_msg>Add module dependencies<commit_after>(function (angular, _, moment) {
    'use strict';

    var module = angular.module('angular-input-fields', [
        'vr.directives.slider',
        'angular-bind-html-compile',
        'gettext'
    ]);

    module.directive('aifSingleChoiceInput', [
        function () {
            return {
                restrict: 'A',
                replace: true,
                scope: {
                    model: '=',
                    choices: '=',
                    disable: '=?',
                    emptyLabel: '=?'
                },
                templateUrl: 'templates/type/single-choice-input.html'
            };
        }
    ]);

    module.directive('aifSelectInput', [
        function () {
            return {
                restrict: 'A',
                scope: {
                    model: '=',
                    choices: '=',
                    disable: '=?',
                    emptyLabel: '=?'
                },
                templateUrl: 'templates/type/select-input.html'
            };
        }
    ]);

    // Renders a pair of select inputs, one for the groups and the other for the
    // selected group's choices.
    module.directive('aifGroupedSelectInput', [
        'gettextCatalog',
        function (gettextCatalog) {
            return {
                restrict: 'A',
                replace: true,
                scope: {
                    model: '=',
                    groupedChoices: '=',
                    disable: '=?',
                    emptyLabel: '=?'
                },
                templateUrl: 'templates/type/grouped-select-input.html',
                link: function (scope, element, attrs) {

                    // Helper method to get a group's choice based on a value.
                    // Returns undefined if no choice is found.
                    var getGroupChoice = function (group, value) {
                        if (angular.isDefined(group)) {
                            return _.findWhere(group.choices, {
                                value: value
                            });
                        }
                    };

                    // Set initialise groups when choice change.
                    scope.$watch('groupedChoices', function (groupedChoices) {
                        scope.groups = [];
                        scope.group = {
                            choices: []
                        };
                        if (angular.isDefined(groupedChoices)) {
                            var otherChoices = [];
                            angular.forEach(groupedChoices, function (item) {
                                if (angular.isDefined(item.choices)) {
                                    // Group with choices

                                    if (scope.emptyLabel && angular.isUndefined(getGroupChoice(item, ''))) {
                                        // jscs:disable requireCamelCaseOrUpperCaseIdentifiers
                                        /* jshint camelcase: false */

                                        // Add the emptyLabel to the start of choices.
                                        item.choices.unshift({
                                            display_name: scope.emptyLabel,
                                            value: ''
                                        });
                                        // jscs:enable requireCamelCaseOrUpperCaseIdentifiers
                                    }

                                    // Reference the item as the value so it is
                                    // used when the item is selected.
                                    item.value = item;

                                    scope.groups.push(item);
                                } else {
                                    // Choice that does not belong to a group
                                    otherChoices.push(item);
                                }
                            });
                            if (otherChoices.length) {
                                // jscs:disable requireCamelCaseOrUpperCaseIdentifiers
                                /* jshint camelcase: false */
                                scope.groups.push({
                                    display_name: gettextCatalog.getString('Other'),
                                    choices: otherChoices
                                });
                                // jscs:enable requireCamelCaseOrUpperCaseIdentifiers
                            }
                        }
                    });

                    // Set group when model changes.
                    scope.$watch('model', function (value) {
                        if (angular.isDefined(value) && value !== null) {
                            angular.forEach(scope.groupedChoices, function (group) {
                                if (angular.isDefined(getGroupChoice(group, value))) {
                                    scope.group = group;
                                }
                            });
                        }
                    });

                    // Check model is valid when group changes.
                    scope.$watch('group', function (group) {
                        if (group !== null && angular.isDefined(getGroupChoice(group, scope.model))) {
                            // Model is one of the group choices.
                            return;
                        }

                        scope.model = null;
                    });
                }
            };
        }
    ]);

    module.directive('aifRadioInput', [
        function () {
            return {
                restrict: 'A',
                scope: {
                    model: '=',
                    choices: '=',
                    disable: '=?'
                },
                templateUrl: 'templates/type/radio-input.html',
                link: function (scope) {
                    scope.localModel = {
                        value: scope.model
                    };

                    scope.$watch('localModel.value', function (value) {
                        scope.model = value;
                    });
                }
            };
        }
    ]);

    module.directive('aifCheckboxInput', [
        function () {
            return {
                restrict: 'A',
                replace: true,
                scope: {
                    model: '=',
                    label: '=',
                    disable: '=?'
                },
                templateUrl: 'templates/type/checkbox-input.html'
            };
        }
    ]);

    module.directive('aifBooleanInput', [
        function () {
            return {
                restrict: 'A',
                replace: true,
                templateUrl: 'templates/type/boolean-input.html',
                scope: {
                    model: '=',
                    disable: '=?'
                },
                link: function (scope, element, attrs) {

                    scope.$watch('boolValue', function () {
                        var value = false;

                        if (scope.boolValue === 'true') {
                            value = true;
                        }

                        scope.model = value;
                    });

                }
            };
        }
    ]);

    module.directive('aifTextInput', [
        function () {
            return {
                restrict: 'A',
                replace: true,
                scope: {
                    model: '=',
                    disable: '=?'
                },
                templateUrl: 'templates/type/text-input.html'
            };
        }
    ]);

    module.directive('aifNumberInput', [
        function () {
            return {
                restrict: 'A',
                replace: true,
                scope: {
                    model: '=',
                    disable: '=?'
                },
                templateUrl: 'templates/type/number-input.html'
            };
        }
    ]);

    module.directive('aifSliderInput', [
        'gettextCatalog',
        function (gettextCatalog) {
            return {
                restrict: 'A',
                replace: true,
                templateUrl: 'templates/type/slider-input.html',
                scope: {
                    model: '=',
                    disable: '=?',
                    ceiling: '=?',
                    translateFn: '=?',
                    className: '@'
                },
                link: function (scope, element, attrs) {
                    if (angular.isUndefined(scope.translateFn)) {
                        scope.translateFn = function (input) {
                            return input;
                        };
                    }

                    if (angular.isUndefined(scope.className)) {
                        scope.className = null;
                    }

                    if (angular.isUndefined(scope.ceiling)) {
                        scope.ceiling = 10;
                    }

                    scope.sliderLowLabel = attrs.sliderLowLabel || gettextCatalog.getString('none');
                    scope.sliderMiddleLabel = attrs.sliderMiddleLabel;
                    scope.sliderHighLabel = attrs.sliderHighLabel || gettextCatalog.getString('very severe');
                }
            };
        }
    ]);

    module.directive('aifSwitchInput', [
        function () {
            return {
                restrict: 'A',
                replace: true,
                scope: {
                    model: '=',
                    choices: '=',
                    disable: '=?'
                },
                templateUrl: 'templates/type/switch-input.html',
                link: function (scope, element, attrs) {
                    // Work around btn-radio ng-model bind issues
                    scope.data = {
                        model: scope.model
                    };
                    scope.$watch('model', function (value) {
                        if (angular.isDefined(value)) {
                            scope.data.model = value;
                        }
                    });
                    scope.$watch('data.model', function (value) {
                        if (angular.isDefined(value)) {
                            scope.model = value;
                        }
                    });
                }
            };
        }
    ]);

    module.filter('aifNumberPadding', [
        function () {
            return _.memoize(function (input, numOfDigits) {
                input = input.toString();
                while (input.length < numOfDigits) {
                    input = '0' + input;
                }

                return input;
            }, function (input, numOfDigits) {
                return input + '' + numOfDigits;
            });
        }
    ]);

    module.directive('aifMomentSelect', [
            '$compile',
        function ($compile) {
            return {
                restrict: 'A',
                scope: {
                    model: '=',
                    disable: '=?',
                    hourMax: '@',
                    minuteMax: '@',
                    hourMin: '@',
                    minuteMin: '@',
                    hourStep: '@',
                    minuteStep: '@',
                    useDuration: '=',
                    hoursLen: '@',
                    minutesLen: '@'
                },
                templateUrl: 'templates/type/moment-select.html',
                compile: function (element, attrs) {
                    // Add default attributes
                    _.defaults(attrs, {
                        hourMin: '0',
                        hourMax: '24',
                        hourStep: '1',
                        minuteMin: '0',
                        minuteMax: '60',
                        minuteStep: '1',
                        useDuration: false,
                        hoursLen: '0',
                        minutesLen: '0'
                    });

                    // Return the (post) link function
                    return function (scope, element, attrs) {
                        scope.hourChoices = _.range(scope.hourMin, scope.hourMax, scope.hourStep);
                        scope.minuteChoices = _.range(scope.minuteMin, scope.minuteMax, scope.minuteStep);

                        var group = ['hours', 'minutes'];

                        var cast = (scope.useDuration) ? moment.duration : moment;

                        scope.$watchGroup(['hours', 'minutes'], function (newValues) {
                            var hours = newValues[0];
                            var minutes = newValues[1];
                            var timeObject = {};

                            if (angular.isDefined(hours)) {
                                timeObject.hours = hours;
                            }
                            if (angular.isDefined(minutes)) {
                                timeObject.minutes = minutes;
                            }
                            scope.model = cast(timeObject);
                        });

                        var deregisterModelWatch = scope.$watch('model', function (value) {
                            if (angular.isDefined(scope.model)) {
                                value = cast(scope.model);
                                var timeObject = {};
                                var hours = group[0];
                                var minutes = group[1];

                                if (angular.isDefined(hours)) {
                                    timeObject.hours = value.get(hours);
                                }
                                if (angular.isDefined(minutes)) {
                                    timeObject.minutes = value.get(minutes);
                                }
                                angular.extend(scope, timeObject);
                                deregisterModelWatch();
                            }
                        });
                    };
                }
            };
        }
    ]);

}(window.angular, window._, window.moment));
<|endoftext|>


<commit_before>"use strict";

module.exports = function(game) { // eslint-disable-line no-unused-vars
	var file = require("../data/tilemap.json");
	var tile, image, image_index, x, y;
	var player = 1, container = 2;
	var collider, layer, object;
	for (var i = 0; i < file.layers.length; i++) {
		layer = file.layers[i];
		if (layer.type == "tilelayer") {
			/*
			tilemap = game.instantiatePrefab("tilelayer");
			tilemap_component = game.entities.get(tilemap, "tilemap");
			tilelayer_position = game.entities.get(tilemap, "position");
			tilelayer_position.z = i;
			tilemap_component.layer_index = i;
			tilemap_component.layer = layer.name;
			if (tilemap < background_layer) {
				background_layer = tilemap;
			}
			*/
			for (j = 0; j < layer.data.length; j++) {
				tile = game.instantiatePrefab("tile");
				image = game.entities.get(tile, "image");
				x = (j % file.width) * file.tilewidth;
				y = Math.floor(j / file.height) * file.tileheight;
				image_index = layer.data[j] - 1;
				image.name = file.tilesets[image_index].image;
				game.entities.set(tile, "position", { "x": x, "y": y });
			}
		}
		if (layer.name == "Collisions") {
			for (var j = 0; j < layer.objects.length; j++) {
				object = layer.objects[j];
				collider = game.instantiatePrefab("collision");
				game.entities.set(collider, "size", { "width": object.width, "height": object.height });
				game.entities.set(collider, "position", { "x": object.x, "y": object.y });
			}
		}
		if (layer.name == "Spawn") {
			object = layer.objects[0];
			game.entities.set(player, "position", { "x": object.x, "y": object.y });
		}
	}
	var map_size = {
		"width": file.width * file.tilewidth,
		"height": file.height * file.tileheight
	};
	game.entities.set(container, "size", map_size);
	game.entities.set(player, "constrainPosition", { "id": container });
};
<commit_msg>refactor object layers<commit_after>"use strict";

module.exports = function(game) { // eslint-disable-line no-unused-vars
	var file = require("../data/tilemap.json");
	var tile, image, image_index, tile_pos;
	var player = 1, container = 2;
	var collider, layer, object;
	for (var i = 0; i < file.layers.length; i++) {
		layer = file.layers[i];
		if (layer.type == "tilelayer") {
			for (j = 0; j < layer.data.length; j++) {
				tile = game.instantiatePrefab("tile");
				image = game.entities.get(tile, "image");
				tile_pos = game.entities.get(tile, "position");
				tile_pos.x = (j % file.width) * file.tilewidth;
				tile_pos.y = Math.floor(j / file.height) * file.tileheight;
				tile_pos.z = (layer.name == "Background") ? -1 : 2;
				image_index = layer.data[j] - 1;
				image.name = file.tilesets[image_index].image;
			}
		}
		if (layer.type == "objectgroup") {
			for (var j = 0; j < layer.objects.length; j++) {
				if (layer.properties.Collidable) {
					object = layer.objects[j];
					collider = game.instantiatePrefab("collision");
					game.entities.set(collider, "size", { "width": object.width, "height": object.height });
					game.entities.set(collider, "position", { "x": object.x, "y": object.y });
				} else if (layer.properties.spawnPoint) {
					object = layer.objects[0];
					game.entities.set(player, "position", { "x": object.x, "y": object.y });
				}
			}
		}
	}
	var map_size = {
		"width": file.width * file.tilewidth,
		"height": file.height * file.tileheight
	};
	game.entities.set(container, "size", map_size);
	game.entities.set(player, "constrainPosition", { "id": container });
};
<|endoftext|>


<commit_before>import { oneLine } from 'common-tags';

import * as utils from 'utils';

import { unexpectedSuccess } from './helpers';

describe('utils.getRootExpression()', () => {
  const node = {
    type: 'CallExpression',
    callee: { // <-- bar()
      type: 'MemberExpression',
      object: {
        type: 'CallExpression',
        callee: { // <-- foo()
          type: 'MemberExpression',
          object: {
            type: 'CallExpression',
            callee: { // <-- pref()
              type: 'Identifier',
              name: 'pref',
            },
          },
          property: {
            type: 'Identifier',
            name: 'foo',
          },
        },
      },
      property: {
        type: 'Identifier',
        name: 'bar',
      },
    },
  };

  it('should verify that the root node is what was expected', () => {
    const root = utils.getRootExpression(node);

    expect(root.name).toEqual('pref');
  });
});

describe('utils.getNodeReference()', () => {
  // Represents scope for following code:
  // const foo = window; foo = bar;
  const context = {
    getScope: () => {
      // TODO: Look into generating these AST nodes using ESPrima
      return {
        variables: [{
          name: 'foo', // Reference name
          type: 'Identifier',
          defs: [{
            parent: {
              parent: {
                body: [{
                  type: 'VariableDeclaration',
                  declarations: [{
                    init: {
                      name: 'window',
                    },
                  }],
                }, {
                  type: 'ExpressionStatement',
                  expression: {
                    type: 'AssignmentExpression',
                    right: {
                      name: 'bar',
                    },
                  },
                },
                ],
              },
            },
          }],
        }],
      };
    },
  };

  it('should return the name of the referenced variable', () => {
    const ref = { name: 'foo' };
    const val = utils.getNodeReference(context, ref);

    expect(val.name).toEqual('bar');
  });

  it('should return the name of the reference if not in scope', () => {
    const ref = { name: 'doesNotExist' };
    const val = utils.getNodeReference(context, ref);

    expect(val.name).toEqual(ref.name);
  });
});

describe('utils.getVariable()', () => {
  // This is the expected schema from eslint
  const context = {
    getScope: () => {
      return {
        variables: [{
          name: 'foo',
          defs: [{
            type: 'Variable',
            name: {
              parent: {
                init: {
                  type: 'Literal',
                  value: 'bar',
                },
              },
            },
          }],
        }],
      };
    },
  };

  const contextWithoutParent = {
    getScope: () => {
      return {
        variables: [{
          name: 'foo',
          defs: [{
            type: 'Variable',
            name: {},
          }],
        }],
      };
    },
  };

  it('should return the correct variable in the given context.', () => {
    const foo = utils.getVariable(context, 'foo');
    expect(foo.type).toEqual('Literal');
    expect(foo.value).toEqual('bar');
  });

  it("should return undefined if the variable doesn't exist.", () => {
    const undef = utils.getVariable(context, 'doesNotExist');
    expect(typeof undef).toEqual('undefined');
  });

  it("should return undefined if the init property isn't on the parent", () => {
    const undef = utils.getVariable(contextWithoutParent, 'foo');
    expect(typeof undef).toEqual('undefined');
  });
});

describe('utils.checkOtherReferences', () => {
  const context = {
    getScope: () => {
      return {
        variables: [],
      };
    },
  };

  it('should return the node if reference is a Literal', () => {
    const literal = utils.getNodeReference(context, { type: 'Literal' });
    expect(literal.type).toEqual('Literal');
  });

  it('should return the node if reference is undefined', () => {
    const undef = utils.getNodeReference(context, { type: 'undefined' });
    expect(undef.type).toEqual('undefined');
  });
});

describe('utils.ensureFilenameExists()', () => {
  it('should throw error when filename is not a string', () => {
    expect(() => {
      utils.ensureFilenameExists();
    }).toThrow('Filename is required');
    expect(() => {
      utils.ensureFilenameExists(0);
    }).toThrow('Filename is required');
    expect(() => {
      utils.ensureFilenameExists(undefined);
    }).toThrow('Filename is required');
    expect(() => {
      utils.ensureFilenameExists(null);
    }).toThrow('Filename is required');
  });

  it('should throw error when filename is empty', () => {
    expect(() => {
      utils.ensureFilenameExists('');
    }).toThrow('Filename is required');
  });

  it('should accept filenames', () => {
    expect(() => {
      utils.ensureFilenameExists('foo.js');
      utils.ensureFilenameExists('0');
    }).not.toThrow();
  });
});

describe('utils.checkMinNodeVersion()', () => {
  it('should reject if version is not high enough', () => {
    const fakeProcess = {
      version: 'v0.12.4',
    };
    return utils.checkMinNodeVersion('0.12.7', fakeProcess)
      .then(unexpectedSuccess)
      .catch((err) => {
        expect(err.message).toContain('Node version must be 0.12.7 or greater');
      });
  });

  it('should not reject if version is not high enough', () => {
    const fakeProcess = {
      version: 'v4.1.2',
    };
    return utils.checkMinNodeVersion('0.12.7', fakeProcess);
  });
});

describe('utils.ignorePrivateFunctions()', () => {
  it('should return only "public" functions', () => {
    const listOfRuleFunctions = {
      checkForEval: sinon.stub(),
      _parseEvalPossibility: sinon.stub(),
      checkForCurlyBraces: sinon.stub(),
      __checkForFunctions: sinon.stub(),
      i_am_an_underscore_function: sinon.stub(),
    };

    const publicFunctions = utils.ignorePrivateFunctions(listOfRuleFunctions);
    expect(typeof publicFunctions).toBe('object');
    expect(Object.keys(publicFunctions).length).toBe(3);
    expect(Object.keys(publicFunctions)).not.toContain('_parseEvalPossibility');
    expect(Object.keys(publicFunctions)).not.toContain('__checkForFunctions');
  });

  it('should return an empty object when given only private functions', () => {
    const listOfRuleFunctions = {
      _parseEvalPossibility: sinon.stub(),
      __checkForFunctions: sinon.stub(),
    };

    const publicFunctions = utils.ignorePrivateFunctions(listOfRuleFunctions);
    expect(typeof publicFunctions).toBe('object');
    expect(Object.keys(publicFunctions).length).toBe(0);
  });

  it('should return only functions', () => {
    const listOfRuleFunctions = {
      iAmARule: sinon.stub(),
      _privateMethod: sinon.stub(),
      IAMCONSTANT: 'foo',
    };

    const publicFunctions = utils.ignorePrivateFunctions(listOfRuleFunctions);
    Object.keys(publicFunctions).forEach((functionName) => {
      expect(typeof publicFunctions[functionName]).toEqual('function');
    });
  });
});

describe('utils.getPackageTypeAsString()', () => {
  it('should look up a package type when passed a number', () => {
    expect(utils.getPackageTypeAsString(2)).toEqual('PACKAGE_THEME');
  });

  it('should look up a package type when passed a string', () => {
    expect(utils.getPackageTypeAsString('2')).toEqual('PACKAGE_THEME');
  });

  it('should throw if given a non-existent package type value', () => {
    expect(() => {
      utils.getPackageTypeAsString(127);
    }).toThrow('Invalid package type constant "127"');
  });

  it('should throw if given a bogus package type value', () => {
    expect(() => {
      utils.getPackageTypeAsString('whatevs');
    }).toThrow('Invalid package type constant "whatevs"');
  });
});

describe('utils.isLocalUrl', () => {
  it('should not match remote urls', () => {
    expect(utils.isLocalUrl('http://foo.com')).toBeFalsy();
    expect(utils.isLocalUrl('https://foo.com')).toBeFalsy();
    expect(utils.isLocalUrl('ftp://foo.com')).toBeFalsy();
    expect(utils.isLocalUrl('//foo.com')).toBeFalsy();
  });

  it('should not match data uri', () => {
    expect(utils.isLocalUrl('data:image/gif;base64,R0' +
      'lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7')).toBeFalsy();
  });

  it('should match chrome protocol', () => {
    expect(utils.isLocalUrl('chrome://bar/foo')).toBeTruthy();
  });

  it('should match resource protocol', () => {
    expect(utils.isLocalUrl('resource://bar/foo')).toBeTruthy();
  });

  it('should match non-remote urls starting with /', () => {
    expect(utils.isLocalUrl('/bar/foo')).toBeTruthy();
  });

  it('should match non-remote urls starting with alpha', () => {
    expect(utils.isLocalUrl('bar')).toBeTruthy();
  });
});

describe('utils.isBrowserNamespace', () => {
  it('is true for browser', () => {
    expect(utils.isBrowserNamespace('browser')).toEqual(true);
  });

  it('is true for chrome', () => {
    expect(utils.isBrowserNamespace('chrome')).toEqual(true);
  });

  it('is not true for other strings', () => {
    expect(utils.isBrowserNamespace('foo')).toEqual(false);
    expect(utils.isBrowserNamespace('bar')).toEqual(false);
    expect(utils.isBrowserNamespace('BROWSER')).toEqual(false);
    expect(utils.isBrowserNamespace('chrOme')).toEqual(false);
  });
});

describe('utils.parseCspPolicy', () => {
  it('should allow empty policies', () => {
    expect(utils.parseCspPolicy('')).toEqual({});
    expect(utils.parseCspPolicy(null)).toEqual({});
    expect(utils.parseCspPolicy(undefined)).toEqual({});
  });

  it('should parse directives correctly', () => {
    const rawPolicy = oneLine`
      default-src 'none'; script-src 'self'; connect-src https: 'self';
      img-src 'self'; style-src 'self';
    `;

    const parsedPolicy = utils.parseCspPolicy(rawPolicy);

    expect(parsedPolicy['script-src']).toEqual(['\'self\'']);
    expect(parsedPolicy['default-src']).toEqual(['\'none\'']);
    expect(parsedPolicy['connect-src']).toEqual(['https:', '\'self\'']);
    expect(parsedPolicy['img-src']).toEqual(['\'self\'']);
    expect(parsedPolicy['style-src']).toEqual(['\'self\'']);
  });

  it('should handle upper case correctly', () => {
    const parsedPolicy = utils.parseCspPolicy('DEFAULT-SRC \'NoNe\'');

    expect(parsedPolicy['default-src']).toEqual(['\'none\'']);
  });
});

describe('utils.normalizePath', () => {
  it('should normalize given "absolute" path to relative path', () => {
    expect(utils.normalizePath('/foo/bar/baz')).toEqual('foo/bar/baz');
  });

  it('should normalize ./ and ../ relative paths', () => {
    expect(utils.normalizePath('./foo/bar/baz')).toEqual('foo/bar/baz');
    expect(utils.normalizePath('qux/../foo/bar/baz')).toEqual('foo/bar/baz');
  });

  it('should normalize path with fragment identifier', () => {
    expect(utils.normalizePath('foo/bar/baz#qux')).toEqual('foo/bar/baz');
  });

  it('should not escape spaces within path', () => {
    expect(utils.normalizePath('foo/bar baz/qux')).toEqual('foo/bar baz/qux');
  });
});
<commit_msg>refactors test.utils.js<commit_after>import { oneLine } from 'common-tags';

import * as utils from 'utils';

describe('utils.getRootExpression()', () => {
  const node = {
    type: 'CallExpression',
    callee: { // <-- bar()
      type: 'MemberExpression',
      object: {
        type: 'CallExpression',
        callee: { // <-- foo()
          type: 'MemberExpression',
          object: {
            type: 'CallExpression',
            callee: { // <-- pref()
              type: 'Identifier',
              name: 'pref',
            },
          },
          property: {
            type: 'Identifier',
            name: 'foo',
          },
        },
      },
      property: {
        type: 'Identifier',
        name: 'bar',
      },
    },
  };

  it('should verify that the root node is what was expected', () => {
    const root = utils.getRootExpression(node);

    expect(root.name).toEqual('pref');
  });
});

describe('utils.getNodeReference()', () => {
  // Represents scope for following code:
  // const foo = window; foo = bar;
  const context = {
    getScope: () => {
      // TODO: Look into generating these AST nodes using ESPrima
      return {
        variables: [{
          name: 'foo', // Reference name
          type: 'Identifier',
          defs: [{
            parent: {
              parent: {
                body: [{
                  type: 'VariableDeclaration',
                  declarations: [{
                    init: {
                      name: 'window',
                    },
                  }],
                }, {
                  type: 'ExpressionStatement',
                  expression: {
                    type: 'AssignmentExpression',
                    right: {
                      name: 'bar',
                    },
                  },
                },
                ],
              },
            },
          }],
        }],
      };
    },
  };

  it('should return the name of the referenced variable', () => {
    const ref = { name: 'foo' };
    const val = utils.getNodeReference(context, ref);

    expect(val.name).toEqual('bar');
  });

  it('should return the name of the reference if not in scope', () => {
    const ref = { name: 'doesNotExist' };
    const val = utils.getNodeReference(context, ref);

    expect(val.name).toEqual(ref.name);
  });
});

describe('utils.getVariable()', () => {
  // This is the expected schema from eslint
  const context = {
    getScope: () => {
      return {
        variables: [{
          name: 'foo',
          defs: [{
            type: 'Variable',
            name: {
              parent: {
                init: {
                  type: 'Literal',
                  value: 'bar',
                },
              },
            },
          }],
        }],
      };
    },
  };

  const contextWithoutParent = {
    getScope: () => {
      return {
        variables: [{
          name: 'foo',
          defs: [{
            type: 'Variable',
            name: {},
          }],
        }],
      };
    },
  };

  it('should return the correct variable in the given context.', () => {
    const foo = utils.getVariable(context, 'foo');
    expect(foo.type).toEqual('Literal');
    expect(foo.value).toEqual('bar');
  });

  it("should return undefined if the variable doesn't exist.", () => {
    const undef = utils.getVariable(context, 'doesNotExist');
    expect(typeof undef).toEqual('undefined');
  });

  it("should return undefined if the init property isn't on the parent", () => {
    const undef = utils.getVariable(contextWithoutParent, 'foo');
    expect(typeof undef).toEqual('undefined');
  });
});

describe('utils.checkOtherReferences', () => {
  const context = {
    getScope: () => {
      return {
        variables: [],
      };
    },
  };

  it('should return the node if reference is a Literal', () => {
    const literal = utils.getNodeReference(context, { type: 'Literal' });
    expect(literal.type).toEqual('Literal');
  });

  it('should return the node if reference is undefined', () => {
    const undef = utils.getNodeReference(context, { type: 'undefined' });
    expect(undef.type).toEqual('undefined');
  });
});

describe('utils.ensureFilenameExists()', () => {
  it('should throw error when filename is not a string', () => {
    expect(() => {
      utils.ensureFilenameExists();
    }).toThrow('Filename is required');
    expect(() => {
      utils.ensureFilenameExists(0);
    }).toThrow('Filename is required');
    expect(() => {
      utils.ensureFilenameExists(undefined);
    }).toThrow('Filename is required');
    expect(() => {
      utils.ensureFilenameExists(null);
    }).toThrow('Filename is required');
  });

  it('should throw error when filename is empty', () => {
    expect(() => {
      utils.ensureFilenameExists('');
    }).toThrow('Filename is required');
  });

  it('should accept filenames', () => {
    expect(() => {
      utils.ensureFilenameExists('foo.js');
      utils.ensureFilenameExists('0');
    }).not.toThrow();
  });
});

describe('utils.checkMinNodeVersion()', () => {
  it('should reject if version is not high enough', async () => {
    const fakeProcess = {
      version: 'v0.12.4',
    };
    await expect(
      utils.checkMinNodeVersion('0.12.7', fakeProcess)
    ).rejects.toThrow('Node version must be 0.12.7 or greater');
  });

  it('should not reject if version is not high enough', () => {
    const fakeProcess = {
      version: 'v4.1.2',
    };
    return utils.checkMinNodeVersion('0.12.7', fakeProcess);
  });
});

describe('utils.ignorePrivateFunctions()', () => {
  it('should return only "public" functions', () => {
    const listOfRuleFunctions = {
      checkForEval: sinon.stub(),
      _parseEvalPossibility: sinon.stub(),
      checkForCurlyBraces: sinon.stub(),
      __checkForFunctions: sinon.stub(),
      i_am_an_underscore_function: sinon.stub(),
    };

    const publicFunctions = utils.ignorePrivateFunctions(listOfRuleFunctions);
    expect(typeof publicFunctions).toBe('object');
    expect(Object.keys(publicFunctions).length).toBe(3);
    expect(Object.keys(publicFunctions)).not.toContain('_parseEvalPossibility');
    expect(Object.keys(publicFunctions)).not.toContain('__checkForFunctions');
  });

  it('should return an empty object when given only private functions', () => {
    const listOfRuleFunctions = {
      _parseEvalPossibility: sinon.stub(),
      __checkForFunctions: sinon.stub(),
    };

    const publicFunctions = utils.ignorePrivateFunctions(listOfRuleFunctions);
    expect(typeof publicFunctions).toBe('object');
    expect(Object.keys(publicFunctions).length).toBe(0);
  });

  it('should return only functions', () => {
    const listOfRuleFunctions = {
      iAmARule: sinon.stub(),
      _privateMethod: sinon.stub(),
      IAMCONSTANT: 'foo',
    };

    const publicFunctions = utils.ignorePrivateFunctions(listOfRuleFunctions);
    Object.keys(publicFunctions).forEach((functionName) => {
      expect(typeof publicFunctions[functionName]).toEqual('function');
    });
  });
});

describe('utils.getPackageTypeAsString()', () => {
  it('should look up a package type when passed a number', () => {
    expect(utils.getPackageTypeAsString(2)).toEqual('PACKAGE_THEME');
  });

  it('should look up a package type when passed a string', () => {
    expect(utils.getPackageTypeAsString('2')).toEqual('PACKAGE_THEME');
  });

  it('should throw if given a non-existent package type value', () => {
    expect(() => {
      utils.getPackageTypeAsString(127);
    }).toThrow('Invalid package type constant "127"');
  });

  it('should throw if given a bogus package type value', () => {
    expect(() => {
      utils.getPackageTypeAsString('whatevs');
    }).toThrow('Invalid package type constant "whatevs"');
  });
});

describe('utils.isLocalUrl', () => {
  it('should not match remote urls', () => {
    expect(utils.isLocalUrl('http://foo.com')).toBeFalsy();
    expect(utils.isLocalUrl('https://foo.com')).toBeFalsy();
    expect(utils.isLocalUrl('ftp://foo.com')).toBeFalsy();
    expect(utils.isLocalUrl('//foo.com')).toBeFalsy();
  });

  it('should not match data uri', () => {
    expect(utils.isLocalUrl('data:image/gif;base64,R0' +
      'lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7')).toBeFalsy();
  });

  it('should match chrome protocol', () => {
    expect(utils.isLocalUrl('chrome://bar/foo')).toBeTruthy();
  });

  it('should match resource protocol', () => {
    expect(utils.isLocalUrl('resource://bar/foo')).toBeTruthy();
  });

  it('should match non-remote urls starting with /', () => {
    expect(utils.isLocalUrl('/bar/foo')).toBeTruthy();
  });

  it('should match non-remote urls starting with alpha', () => {
    expect(utils.isLocalUrl('bar')).toBeTruthy();
  });
});

describe('utils.isBrowserNamespace', () => {
  it('is true for browser', () => {
    expect(utils.isBrowserNamespace('browser')).toEqual(true);
  });

  it('is true for chrome', () => {
    expect(utils.isBrowserNamespace('chrome')).toEqual(true);
  });

  it('is not true for other strings', () => {
    expect(utils.isBrowserNamespace('foo')).toEqual(false);
    expect(utils.isBrowserNamespace('bar')).toEqual(false);
    expect(utils.isBrowserNamespace('BROWSER')).toEqual(false);
    expect(utils.isBrowserNamespace('chrOme')).toEqual(false);
  });
});

describe('utils.parseCspPolicy', () => {
  it('should allow empty policies', () => {
    expect(utils.parseCspPolicy('')).toEqual({});
    expect(utils.parseCspPolicy(null)).toEqual({});
    expect(utils.parseCspPolicy(undefined)).toEqual({});
  });

  it('should parse directives correctly', () => {
    const rawPolicy = oneLine`
      default-src 'none'; script-src 'self'; connect-src https: 'self';
      img-src 'self'; style-src 'self';
    `;

    const parsedPolicy = utils.parseCspPolicy(rawPolicy);

    expect(parsedPolicy['script-src']).toEqual(['\'self\'']);
    expect(parsedPolicy['default-src']).toEqual(['\'none\'']);
    expect(parsedPolicy['connect-src']).toEqual(['https:', '\'self\'']);
    expect(parsedPolicy['img-src']).toEqual(['\'self\'']);
    expect(parsedPolicy['style-src']).toEqual(['\'self\'']);
  });

  it('should handle upper case correctly', () => {
    const parsedPolicy = utils.parseCspPolicy('DEFAULT-SRC \'NoNe\'');

    expect(parsedPolicy['default-src']).toEqual(['\'none\'']);
  });
});

describe('utils.normalizePath', () => {
  it('should normalize given "absolute" path to relative path', () => {
    expect(utils.normalizePath('/foo/bar/baz')).toEqual('foo/bar/baz');
  });

  it('should normalize ./ and ../ relative paths', () => {
    expect(utils.normalizePath('./foo/bar/baz')).toEqual('foo/bar/baz');
    expect(utils.normalizePath('qux/../foo/bar/baz')).toEqual('foo/bar/baz');
  });

  it('should normalize path with fragment identifier', () => {
    expect(utils.normalizePath('foo/bar/baz#qux')).toEqual('foo/bar/baz');
  });

  it('should not escape spaces within path', () => {
    expect(utils.normalizePath('foo/bar baz/qux')).toEqual('foo/bar baz/qux');
  });
});
<|endoftext|>


<commit_before>// Copyright 2013 Google Inc.
// Copyright 2014 Volker Sorge
//
// 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.

/**
 * @fileoverview A class for loading and storing the maps for math atoms from
 * JSON files. The class (and entries) can then be used as via the
 * background page.
 * @author sorge@google.com (Volker Sorge)
 */

goog.provide('sre.MathMap');

goog.require('sre.BaseUtil');
goog.require('sre.BrowserUtil');
goog.require('sre.Engine');
goog.require('sre.MathCompoundStore');
goog.require('sre.AlphabetGenerator');
goog.require('sre.SystemExternal');
goog.require('sre.Variables');

/**
 *
 * @constructor
 */
sre.MathMap = function() {

  /**
   * The compund store for symbol and function mappings.
   * @type {sre.MathCompoundStore}
   */
  this.store = sre.MathCompoundStore.getInstance();

  /**
   * Methods for parsing json structures.
   * @type {Object.<function(Array.<string>)>}
   */
  this.addRules = {
    functions: goog.bind(this.store.addFunctionRules, this.store),
    symbols: goog.bind(this.store.addSymbolRules, this.store),
    units: goog.bind(this.store.addUnitRules, this.store)
  };

  var timeIn = (new Date()).getTime();
  this.retrieveMaps();
  var timeOut = (new Date()).getTime();
  console.log('Time:', timeOut - timeIn);

};
goog.addSingletonGetter(sre.MathMap);

/**
 * Files left to fetch in asynchronous mode.
 * @type {number}
 * @private
 */
sre.MathMap.toFetch_ = 0;
sre.Engine.registerTest(function() {
  return sre.MathMap.getInstance() && !sre.MathMap.toFetch_;
});

sre.MathMap.prototype.retrieveFiles = function(locale) {
  var file = sre.BaseUtil.makePath(sre.SystemExternal.jsonPath) +
      locale + '.js';
  switch (sre.Engine.getInstance().mode) {
    case sre.Engine.Mode.ASYNC:
      sre.MathMap.toFetch_++;
        sre.MathMap.fromFile_(file,
            function(err, json) {
              sre.MathMap.toFetch_--;
              if (err) return;
              goog.bind(this.parse, this)(json);
            });
      break;
    case sre.Engine.Mode.HTTP:
      sre.MathMap.toFetch_++;
      this.getJsonAjax_(file);
      break;
    case sre.Engine.Mode.SYNC:
    default:
    var strs = sre.MathMap.loadFile(file);
    this.parseMaps(strs);
    break;
  }
};

sre.MathMap.prototype.parseMaps = function(json) {
  var js = /** @type {!Object<Array>} */(JSON.parse(json));
  this.addMaps(js);
};

sre.MathMap.prototype.addMaps = function(js) {
  for (var i = 0, key; key = Object.keys(js)[i]; i++) {
    var info = key.split('/');
    js[key].forEach(this.addRules[info[1]]);
  }
};

/**
 * Retrieves mappings and adds them to the respective stores.
 */
sre.MathMap.prototype.retrieveMaps = function() {
  if (sre.Engine.getInstance().isIE &&
      sre.Engine.getInstance().mode === sre.Engine.Mode.HTTP) {
    this.getJsonIE_();
    return;
  }
  for (var i = 0; i < sre.Variables.LOCALES.length; i++) {
    var locale = sre.Variables.LOCALES[i];
    sre.AlphabetGenerator.generate(locale, this.store);
    this.retrieveFiles(locale);
  }
};

/**
 * Gets JSON elements from the global JSON object in case of IE browsers.
 * @param {number=} opt_count Optional counter argument for callback.
 * @private
 */
sre.MathMap.prototype.getJsonIE_ = function(opt_count) {
  var count = opt_count || 1;
  if (!sre.BrowserUtil.mapsForIE) {
    if (count <= 5) {
      setTimeout(
        goog.bind(function() {this.getJsonIE_(count++);}, this),
          300);
    } else {
      sre.MathMap.toFetch_--;
    }
    return;
  }
  this.addMaps(sre.BrowserUtil.mapsForIE);
  sre.MathMap.toFetch_--;
};

/**
 * Takes path to a JSON file and returns a JSON object.
 * @param {string} path Contains the path to a JSON file.
 * @param {function(string, string)} func Method adding the rules.
 * @return {string} JSON.
 * @private
 */
sre.MathMap.fromFile_ = function(path, func) {
  return sre.SystemExternal.fs.readFile(path, 'utf8', func);
};

/**
 * Loads JSON for a given file name.
 * @param {string} file A valid filename.
 * @return {string} A string representing a JSON array.
 */
sre.MathMap.loadFile = function(file) {
  try {
    return sre.MathMap.readJSON_(file);
  } catch (x) {
    console.error('Unable to load file: ' + file + ', error: ' + x);
  }
};

// /**
//  * Loads a list of JSON files.
//  * @param {Array.<string>} files An array of valid filenames.
//  * @return {Array.<string>} A string representing JSON array.
//  */
// sre.MathMap.loadFiles = function(files) {
//   return files.map(sre.MathMap.loadFile);
// };

// /**
//  * Creates an array of JSON objects from a list of files.
//  * @param {Array.<string>} files An array of filenames.
//  * @return {Array.<JSONType>} Array of JSON objects.
//  */
// sre.MathMap.parseFiles = function(files) {
//   var strs = sre.MathMap.loadFiles(files);

//   return [].concat.apply([], strs.map(
//       // Note: As JSON.parse does not expect the value index as the second
//       // parameter, we wrap it.
//       function(value) { return JSON.parse(value); }));
// };

/**
 * Takes path to a JSON file and returns a JSON object.
 * @param {string} path Contains the path to a JSON file.
 * @return {string} JSON.
 * @private
 */
sre.MathMap.readJSON_ = function(path) {
  return sre.SystemExternal.fs.readFileSync(path);
};

/**
 * Sents AJAX request to retrieve a JSON rule file.
 * @param {string} file The file to retrieve.
 * @private
 */
sre.MathMap.prototype.getJsonAjax_ = function(file) {
  var httpRequest = new XMLHttpRequest();
  var parse = goog.bind(this.parseMaps, this);
  httpRequest.onreadystatechange = function() {
    if (httpRequest.readyState === 4) {
      sre.MathMap.toFetch_--;
      if (httpRequest.status === 200) {
        parse(httpRequest.responseText);
      }
    }
  };
  httpRequest.open('GET', file, true);
  httpRequest.send();
};
<commit_msg>Code cleanup.<commit_after>// Copyright 2013 Google Inc.
// Copyright 2014 Volker Sorge
//
// 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.

/**
 * @fileoverview A class for loading and storing the maps for math atoms from
 * JSON files. The class (and entries) can then be used as via the
 * background page.
 * @author sorge@google.com (Volker Sorge)
 */

goog.provide('sre.MathMap');

goog.require('sre.BaseUtil');
goog.require('sre.BrowserUtil');
goog.require('sre.Engine');
goog.require('sre.MathCompoundStore');
goog.require('sre.AlphabetGenerator');
goog.require('sre.SystemExternal');
goog.require('sre.Variables');

/**
 *
 * @constructor
 */
sre.MathMap = function() {

  /**
   * The compund store for symbol and function mappings.
   * @type {sre.MathCompoundStore}
   */
  this.store = sre.MathCompoundStore.getInstance();

  /**
   * Methods for parsing json structures.
   * @type {Object.<function(Array.<string>)>}
   */
  this.addRules = {
    functions: goog.bind(this.store.addFunctionRules, this.store),
    symbols: goog.bind(this.store.addSymbolRules, this.store),
    units: goog.bind(this.store.addUnitRules, this.store)
  };

  var timeIn = (new Date()).getTime();
  this.retrieveMaps();
  var timeOut = (new Date()).getTime();
  console.log('Time:', timeOut - timeIn);

};
goog.addSingletonGetter(sre.MathMap);

/**
 * Files left to fetch in asynchronous mode.
 * @type {number}
 * @private
 */
sre.MathMap.toFetch_ = 0;
sre.Engine.registerTest(function() {
  return sre.MathMap.getInstance() && !sre.MathMap.toFetch_;
});

sre.MathMap.prototype.retrieveFiles = function(locale) {
  var file = sre.BaseUtil.makePath(sre.SystemExternal.jsonPath) +
      locale + '.js';
  switch (sre.Engine.getInstance().mode) {
    case sre.Engine.Mode.ASYNC:
      sre.MathMap.toFetch_++;
        sre.MathMap.fromFile_(file,
            function(err, json) {
              sre.MathMap.toFetch_--;
              if (err) return;
              goog.bind(this.parse, this)(json);
            });
      break;
    case sre.Engine.Mode.HTTP:
      sre.MathMap.toFetch_++;
      this.getJsonAjax_(file);
      break;
    case sre.Engine.Mode.SYNC:
    default:
    var strs = sre.MathMap.loadFile(file);
    this.parseMaps(strs);
    break;
  }
};

sre.MathMap.prototype.parseMaps = function(json) {
  var js = /** @type {!Object<Array>} */(JSON.parse(json));
  this.addMaps(js);
};

sre.MathMap.prototype.addMaps = function(js) {
  for (var i = 0, key; key = Object.keys(js)[i]; i++) {
    var info = key.split('/');
    js[key].forEach(this.addRules[info[1]]);
  }
};

/**
 * Retrieves mappings and adds them to the respective stores.
 */
sre.MathMap.prototype.retrieveMaps = function() {
  if (sre.Engine.getInstance().isIE &&
      sre.Engine.getInstance().mode === sre.Engine.Mode.HTTP) {
    this.getJsonIE_();
    return;
  }
  for (var i = 0; i < sre.Variables.LOCALES.length; i++) {
    var locale = sre.Variables.LOCALES[i];
    sre.AlphabetGenerator.generate(locale, this.store);
    this.retrieveFiles(locale);
  }
};

/**
 * Gets JSON elements from the global JSON object in case of IE browsers.
 * @param {number=} opt_count Optional counter argument for callback.
 * @private
 */
sre.MathMap.prototype.getJsonIE_ = function(opt_count) {
  var count = opt_count || 1;
  if (!sre.BrowserUtil.mapsForIE) {
    if (count <= 5) {
      setTimeout(
        goog.bind(function() {this.getJsonIE_(count++);}, this),
          300);
    } else {
      sre.MathMap.toFetch_--;
    }
    return;
  }
  this.addMaps(sre.BrowserUtil.mapsForIE);
  sre.MathMap.toFetch_--;
};

/**
 * Takes path to a JSON file and returns a JSON object.
 * @param {string} path Contains the path to a JSON file.
 * @param {function(string, string)} func Method adding the rules.
 * @return {string} JSON.
 * @private
 */
sre.MathMap.fromFile_ = function(path, func) {
  return sre.SystemExternal.fs.readFile(path, 'utf8', func);
};

/**
 * Loads JSON for a given file name.
 * @param {string} file A valid filename.
 * @return {string} A string representing a JSON array.
 */
sre.MathMap.loadFile = function(file) {
  try {
    return sre.MathMap.readJSON_(file);
  } catch (x) {
    console.error('Unable to load file: ' + file + ', error: ' + x);
  }
};

/**
 * Takes path to a JSON file and returns a JSON object.
 * @param {string} path Contains the path to a JSON file.
 * @return {string} JSON.
 * @private
 */
sre.MathMap.readJSON_ = function(path) {
  return sre.SystemExternal.fs.readFileSync(path);
};

/**
 * Sents AJAX request to retrieve a JSON rule file.
 * @param {string} file The file to retrieve.
 * @private
 */
sre.MathMap.prototype.getJsonAjax_ = function(file) {
  var httpRequest = new XMLHttpRequest();
  var parse = goog.bind(this.parseMaps, this);
  httpRequest.onreadystatechange = function() {
    if (httpRequest.readyState === 4) {
      sre.MathMap.toFetch_--;
      if (httpRequest.status === 200) {
        parse(httpRequest.responseText);
      }
    }
  };
  httpRequest.open('GET', file, true);
  httpRequest.send();
};
<|endoftext|>