<commit_before>/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

$(document).ready(function () {

    renderPast = function (past, t, f, m) {
        if (t === 'sort') {
            return past;
        } else {
            if (past)
            {
                var cls = '';
                if (new Date() > new Date(f[3]) && f[2] !== 3) {
                    cls = 'alert-danger';
                }
                var dpast = moment(new Date(past))
                return '' + dpast.fromNow() + '';
            }
            return 'Never';
        }
    };

    renderProgress = function (percent, t, f, m) {
        if (t === 'sort') {
            return percent;
        } else {
            if (percent > -1) {
                var cls = '';
                if (f[2] === 3) {
                    cls = 'progress-bar-success';
                } else if (new Date() > new Date(f[3])) {
                    cls = 'progress-bar-danger';
                } else if (f[2] === 2) {
                    cls = 'progress-bar-warning';
                }
//                percent =percent*100;// WHY IT GOT ROUNDING ERROR
                percent = percent * 10000 / 100;
                return `

                    <div class="progress-bar progress-bar-striped ` + cls + `" role="progressbar" aria-valuenow="` + percent + `" aria-valuemin="0" aria-valuemax="100" style="min-width: 2em;width: ` + percent + `%">
                        ` + percent + `%

`;
            } else {
                return 'No task';
            }
        }
    };

    $('#projects-datatable').DataTable({
        responsive: true,
        processing: true,
        serverSide: true,
        ajax: {
            url: base_url + 'project/projects_dt',
            type: 'POST',
            //data: function (d) {}
        },
        columns: [
            // name link
            {
                render: function (n, t, f, m) {
                    if (t === 'sort') {
                        return n;
                    } else {
                        //render link using id
                        return '' + n + ''
                    }
                }
            },
            // PIC
            {},
            // project status
            {},
            // due date
            {render: renderPast},
            // progress
            {render: renderProgress}
        ]
    });
});<commit_msg>use string comparison??<commit_after>/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

$(document).ready(function () {

    renderPast = function (past, t, f, m) {
        if (t === 'sort') {
            return past;
        } else {
            if (past)
            {
                var cls = '';
                if (new Date() > new Date(f[3]) && f[2] !== "3") {
                    cls = 'alert-danger';
                }
                var dpast = moment(new Date(past))
                return '' + dpast.fromNow() + '';
            }
            return 'Never';
        }
    };

    renderProgress = function (percent, t, f, m) {
        if (t === 'sort') {
            return percent;
        } else {
            if (percent > -1) {
                var cls = '';
                if (f[2] === "3") {
                    cls = 'progress-bar-success';
                } else if (new Date() > new Date(f[3])) {
                    cls = 'progress-bar-danger';
                } else if (f[2] === "2") {
                    cls = 'progress-bar-warning';
                }
//                percent =percent*100;// WHY IT GOT ROUNDING ERROR
                percent = percent * 10000 / 100;
                return `

                    <div class="progress-bar progress-bar-striped ` + cls + `" role="progressbar" aria-valuenow="` + percent + `" aria-valuemin="0" aria-valuemax="100" style="min-width: 2em;width: ` + percent + `%">
                        ` + percent + `%

`;
            } else {
                return 'No task';
            }
        }
    };

    $('#projects-datatable').DataTable({
        responsive: true,
        processing: true,
        serverSide: true,
        ajax: {
            url: base_url + 'project/projects_dt',
            type: 'POST',
            //data: function (d) {}
        },
        columns: [
            // name link
            {
                render: function (n, t, f, m) {
                    if (t === 'sort') {
                        return n;
                    } else {
                        //render link using id
                        return '' + n + ''
                    }
                }
            },
            // PIC
            {},
            // project status
            {},
            // due date
            {render: renderPast},
            // progress
            {render: renderProgress}
        ]
    });
});<|endoftext|>


<commit_before>'use strict';

angular.module('tilesortGallery', ['ui.bootstrap']).controller('TilesortModalCtrl', ['$scope', '$uibModalInstance', function ($scope, $uibModalInstance) {
    $scope.close = $uibModalInstance.close;
}]).directive('tilesortGallery', ['$uibModal', '$injector', function ($uibModal, $injector) {

    return {
        restrict: 'AE',
        scope: {
            mode: '=?',
            visibleModes: '=?',
            startIndex: '=?',
            images: '=',

            canEdit: '=?',

            uploadImage: '=?',
            uploadProgress: '=',

            modalTpl: '=?',
            modalCtrl: '=?',

            sortable: '=?'
        },
        templateUrl: 'tilesort-gallery-layout-default',
        link: function link(scope, element, attrs) {
            scope.uploadImage = scope.uploadImage || false;
            scope.filesProgress = scope.uploadProgress;
            scope.$watch('uploadProgress', function() { //watch file upload progress when upload value increases
                scope.filesProgress = scope.uploadProgress;
            });

            // the gallery mode -- by default, only gallery and tiles are available
            scope.mode = scope.mode || 'gallery';

            // the template for the modal
            scope.modalTpl = scope.modalTpl || 'tilesort-modal-default';

            // the controller for the modal
            scope.modalCtrl = scope.modalCtrl || 'TilesortModalCtrl';

            // the visible mode buttons
            scope.visibleModes = scope.visibleModes || [{name: 'tiles', icon: 'fa fa-th'}, {
                    name: 'tiles-large',
                    icon: 'fa fa-th-large'
                }, {name: 'gallery', icon: 'fa fa-square'}];

            var MAX_ITEMS = 3;

            // build the display list for animations to work properly
            var resetDisplayList = function resetDisplayList() {
                var list = [scope.images[scope.currentIndex]];
                var iterable = Math.floor(MAX_ITEMS / 2);

                for (var i = scope.currentIndex - 1; i >= scope.currentIndex - iterable; i--) {
                    list.unshift(scope.images[i]);
                }

                for (var i = scope.currentIndex + 1; i <= scope.currentIndex + iterable; i++) {
                    list.push(scope.images[i]);
                }

                scope.displayList = list;
            };

            // support hitting the left button
            // and rebuilding the display list accordingly
            scope.moveLeft = function () {
                if (scope.currentIndex === 0) return;
                scope.currentIndex = Math.max(0, scope.currentIndex - 1);

                scope.displayList.pop();
                scope.displayList.unshift(scope.images[scope.currentIndex - 1]);
            };

            // hit the right button, rebuild the display list
            scope.moveRight = function () {
                if (scope.currentIndex === scope.images.length - 1) return;
                scope.currentIndex = Math.min(scope.images.length - 1, scope.currentIndex + 1);

                scope.displayList.shift();
                scope.displayList.push(scope.images[scope.currentIndex + 1]);
            };

            // flat-out set the index and reset the display list
            scope.setIndex = function (newIndex) {
                scope.currentIndex = newIndex;
                resetDisplayList();
            };

            scope.onEnd = function (evt) {
                // move the currently active tile to compensate for sorting
                if (evt.oldIndex < scope._currentIndex && evt.newIndex >= scope._currentIndex) {
                    scope.currentIndex--;
                }

                if (evt.oldIndex > scope._currentIndex && evt.newIndex <= scope._currentIndex) {
                    scope.currentIndex++;
                }

                if (evt.oldIndex === scope._currentIndex) {
                    scope.currentIndex = evt.newIndex;
                }

                scope.$root.$emit('tilesort-resort-item-moved', {
                    newIndex: evt.newIndex,
                    oldIndex: evt.oldIndex
                });
            };
            //internal; used to build the sortable / draggable tiles
            scope.sortableOptions = {
                onStart: function onStart(evt) {
                    scope._currentIndex = scope.currentIndex;
                },
                onEnd: function onEnd(evt) {
                    scope.onEnd(evt);
                },
                onEndEvent: function onEndEvent(evt) {
                    scope.onEnd(evt);
                }
            };

            scope.sortableOptionsGallery = {
                sort: false
            };

            // internal; open the modal with some sensible defaults
            scope.openModal = function () {
                $uibModal.open({
                    scope: scope,
                    controller: scope.modalCtrl,
                    templateUrl: scope.modalTpl,
                    backdrop: true,
                    size: 'lg',
                    windowClass: 'tilesort-modal modal-fit',
                    resolve: {
                        scope: function () {
                            return _.cloneDeep(scope);
                        }
                    }
                }).result.then(function(response) {
                    scope.images[scope.currentIndex].title = response;
                });
            };

            // used by the gallery to allow selection of other images and opening the modal
            scope.selectAndOpen = function (index) {
                scope.setIndex(index);
                scope.openModal();
            };

            // whether or not sort should be enabled
            // alternatively, just don't load the plugin since this isn't watched
            if (!scope.sortable) {
                scope.sortableOptions.disabled = true;
            }

            // whether or not title / description are editable in the popup
            scope.canEdit = scope.canEdit || false;

            // if xeditable isn't available, turn editing off
            // an error will be thrown anyway if xeditable is not present
            // and canEdit is set to true, but this cleans up the display
            if (!$injector.has('editableOptions')) {
                scope.canEdit = false;
            }

            scope.$watch('images', function (newVal) {
                if (scope.currentIndex || Array.isArray(newVal) && newVal.length === 0 || typeof newVal === 'undefined') return;
                // initialize the directive
                scope.setIndex(scope.startIndex || 0);
            });
        }
    };
}]).run(['$templateCache', function ($templateCache) {

    // the modal
    // by default, it has the picture, an editable title and description, and close buttons
    $templateCache.put('tilesort-modal-default', '\n
\n        {{images[currentIndex].title}}\n        {{images[currentIndex].title || \'no title\'}}\n        \n
\n
\n
\n
\n            \n
\n
\n\t
\n          {{images[currentIndex].description}}\n          {{images[currentIndex].description || \'no description\'}}\n
\n
\n
\n        <button class="btn btn-default" ng-click="close()">Close</button>\n
\n    ');

    // the directive layout
    // by default, this renders the buttons in the bottom left
    // and has a reasonable amount of space (responsive) for the title / desc //col-md-2 col-xs-3
    // it also has an expand button that opens the current image in a modal //class="col-md-1 col-xs-2"
    $templateCache.put('tilesort-gallery-layout-default', '\n' +
        '' +
            '
' +
                '
' +
                    'Investigate' +
                '
' +
                '
' +
                    '{{images[currentIndex].title}}' +
                    '
' +
                    '
' +
                        '{{images[currentIndex].description}}' +
                    '
' +
                '
' +
                '
' +
                    '
 0">' +
                        '
' +
                            '
' +
                                '' +
                            '
' +
                        '
' +
                    '
' +
                    '
' +
                        '
' +
                            '<button type="button" class="btn btn-default navbar-btn" ng-model="$parent.mode" btn-radio="btn.name" ng-repeat="btn in visibleModes">' +
                                '' +
                            '</button>' +
                        '
' +
                        '<button type="button" class="btn btn-default navbar-btn pull-right margin-right-15" ng-click="openModal()" ng-disabled="images.length === 0" tooltip="View metric">' +
                            '' +
                        '</button>' +
                        '<button type="button" class="btn btn-primary navbar-btn pull-right margin-right-15" ng-disabled="!canEdit" tooltip="Upload" ng-if="uploadImage && canEdit"' +
                            'ngf-select="uploadImage($files)"' +
                            'ngf-multiple="false"' +
                            'ngf-pattern="image/*"' +
                            'ngf-accept="\'image/*\'"' +
                            'ngf-max-size="5MB"' +
                            'ngf-select-disabled="!canEdit"' +
                            'ngf-drop-available="false"' +
                            '>' +
                                '' +
                        '</button>' +
                    '
' +
                '
' +
            '
' +
        '' +
        '
' +
                '

' +
        '
' +
        '
' +
            '

' +
        '
'
    );

    // the gallery layout
    // by default, there are niceish css transitions, left/right buttons, and
    // a reasonable amount of space to display info about the current image
    $templateCache.put('tilesort-view-gallery', '\n
\n         0">\n\n          \n        \n        <span class="tilesort-gallery-nav-item tilesort-gallery-nav-right"\n          ng-click="moveRight()"\n          ng-show="currentIndex < images.length-1">\n\n          \n        \n
\n
\n
= 0 && $index+currentIndex-1 < images.length"\n          >\n          \n
\n\n
\n    ');

    // the tile layout
    // by default, the tiles have a tooltip for their title
    // and they're also drag/drop sortable
    // the active one is indicated by a glowing blue
    $templateCache.put('tilesort-view-tiles', '\n
\n
\n\n          \n
\n
\n    ');

    $templateCache.put('tilesort-view-tiles-large', '\n
\n
\n\n          \n
\n
\n    ');
}]);

// optionally load xeditable if it's there, and set the theme to bs3
try {
    angular.module('xeditable');
    angular.module('tilesortGallery').requires.push('xeditable');
    angular.module('tilesortGallery').run(['$injector', function ($injector) {
        if (!$injector.has('editableOptions')) return;
        $injector.get('editableOptions').theme = 'bs3';
    }]);
} catch (e) {}

// optionally load ng-sortable (Sortable.js) if it's available
try {
    angular.module('ng-sortable');
    angular.module('tilesortGallery').requires.push('ng-sortable');
} catch (e) {}<commit_msg>fix radio buttons<commit_after>'use strict';

angular.module('tilesortGallery', ['ui.bootstrap']).controller('TilesortModalCtrl', ['$scope', '$uibModalInstance', function ($scope, $uibModalInstance) {
    $scope.close = $uibModalInstance.close;
}]).directive('tilesortGallery', ['$uibModal', '$injector', function ($uibModal, $injector) {

    return {
        restrict: 'AE',
        scope: {
            mode: '=?',
            visibleModes: '=?',
            startIndex: '=?',
            images: '=',

            canEdit: '=?',

            uploadImage: '=?',
            uploadProgress: '=',

            modalTpl: '=?',
            modalCtrl: '=?',

            sortable: '=?'
        },
        templateUrl: 'tilesort-gallery-layout-default',
        link: function link(scope, element, attrs) {
            scope.uploadImage = scope.uploadImage || false;
            scope.filesProgress = scope.uploadProgress;
            scope.$watch('uploadProgress', function() { //watch file upload progress when upload value increases
                scope.filesProgress = scope.uploadProgress;
            });

            // the gallery mode -- by default, only gallery and tiles are available
            scope.mode = scope.mode || 'gallery';

            // the template for the modal
            scope.modalTpl = scope.modalTpl || 'tilesort-modal-default';

            // the controller for the modal
            scope.modalCtrl = scope.modalCtrl || 'TilesortModalCtrl';

            // the visible mode buttons
            scope.visibleModes = scope.visibleModes || [{name: 'tiles', icon: 'fa fa-th'}, {
                    name: 'tiles-large',
                    icon: 'fa fa-th-large'
                }, {name: 'gallery', icon: 'fa fa-square'}];

            var MAX_ITEMS = 3;

            // build the display list for animations to work properly
            var resetDisplayList = function resetDisplayList() {
                var list = [scope.images[scope.currentIndex]];
                var iterable = Math.floor(MAX_ITEMS / 2);

                for (var i = scope.currentIndex - 1; i >= scope.currentIndex - iterable; i--) {
                    list.unshift(scope.images[i]);
                }

                for (var i = scope.currentIndex + 1; i <= scope.currentIndex + iterable; i++) {
                    list.push(scope.images[i]);
                }

                scope.displayList = list;
            };

            // support hitting the left button
            // and rebuilding the display list accordingly
            scope.moveLeft = function () {
                if (scope.currentIndex === 0) return;
                scope.currentIndex = Math.max(0, scope.currentIndex - 1);

                scope.displayList.pop();
                scope.displayList.unshift(scope.images[scope.currentIndex - 1]);
            };

            // hit the right button, rebuild the display list
            scope.moveRight = function () {
                if (scope.currentIndex === scope.images.length - 1) return;
                scope.currentIndex = Math.min(scope.images.length - 1, scope.currentIndex + 1);

                scope.displayList.shift();
                scope.displayList.push(scope.images[scope.currentIndex + 1]);
            };

            // flat-out set the index and reset the display list
            scope.setIndex = function (newIndex) {
                scope.currentIndex = newIndex;
                resetDisplayList();
            };

            scope.onEnd = function (evt) {
                // move the currently active tile to compensate for sorting
                if (evt.oldIndex < scope._currentIndex && evt.newIndex >= scope._currentIndex) {
                    scope.currentIndex--;
                }

                if (evt.oldIndex > scope._currentIndex && evt.newIndex <= scope._currentIndex) {
                    scope.currentIndex++;
                }

                if (evt.oldIndex === scope._currentIndex) {
                    scope.currentIndex = evt.newIndex;
                }

                scope.$root.$emit('tilesort-resort-item-moved', {
                    newIndex: evt.newIndex,
                    oldIndex: evt.oldIndex
                });
            };
            //internal; used to build the sortable / draggable tiles
            scope.sortableOptions = {
                onStart: function onStart(evt) {
                    scope._currentIndex = scope.currentIndex;
                },
                onEnd: function onEnd(evt) {
                    scope.onEnd(evt);
                },
                onEndEvent: function onEndEvent(evt) {
                    scope.onEnd(evt);
                }
            };

            scope.sortableOptionsGallery = {
                sort: false
            };

            // internal; open the modal with some sensible defaults
            scope.openModal = function () {
                $uibModal.open({
                    scope: scope,
                    controller: scope.modalCtrl,
                    templateUrl: scope.modalTpl,
                    backdrop: true,
                    size: 'lg',
                    windowClass: 'tilesort-modal modal-fit',
                    resolve: {
                        scope: function () {
                            return _.cloneDeep(scope);
                        }
                    }
                }).result.then(function(response) {
                    scope.images[scope.currentIndex].title = response;
                });
            };

            // used by the gallery to allow selection of other images and opening the modal
            scope.selectAndOpen = function (index) {
                scope.setIndex(index);
                scope.openModal();
            };

            // whether or not sort should be enabled
            // alternatively, just don't load the plugin since this isn't watched
            if (!scope.sortable) {
                scope.sortableOptions.disabled = true;
            }

            // whether or not title / description are editable in the popup
            scope.canEdit = scope.canEdit || false;

            // if xeditable isn't available, turn editing off
            // an error will be thrown anyway if xeditable is not present
            // and canEdit is set to true, but this cleans up the display
            if (!$injector.has('editableOptions')) {
                scope.canEdit = false;
            }

            scope.$watch('images', function (newVal) {
                if (scope.currentIndex || Array.isArray(newVal) && newVal.length === 0 || typeof newVal === 'undefined') return;
                // initialize the directive
                scope.setIndex(scope.startIndex || 0);
            });
        }
    };
}]).run(['$templateCache', function ($templateCache) {

    // the modal
    // by default, it has the picture, an editable title and description, and close buttons
    $templateCache.put('tilesort-modal-default', '\n
\n        {{images[currentIndex].title}}\n        {{images[currentIndex].title || \'no title\'}}\n        \n
\n
\n
\n
\n            \n
\n
\n\t
\n          {{images[currentIndex].description}}\n          {{images[currentIndex].description || \'no description\'}}\n
\n
\n
\n        <button class="btn btn-default" ng-click="close()">Close</button>\n
\n    ');

    // the directive layout
    // by default, this renders the buttons in the bottom left
    // and has a reasonable amount of space (responsive) for the title / desc //col-md-2 col-xs-3
    // it also has an expand button that opens the current image in a modal //class="col-md-1 col-xs-2"
    $templateCache.put('tilesort-gallery-layout-default', '\n' +
        '' +
            '
' +
                '
' +
                    'Investigate' +
                '
' +
                '
' +
                    '{{images[currentIndex].title}}' +
                    '
' +
                    '
' +
                        '{{images[currentIndex].description}}' +
                    '
' +
                '
' +
                '
' +
                    '
 0">' +
                        '
' +
                            '
' +
                                '' +
                            '
' +
                        '
' +
                    '
' +
                    '
' +
                        '
' +
                            '<button type="button" class="btn btn-default navbar-btn" ng-model="$parent.mode" uib-btn-radio="btn.name" ng-repeat="btn in visibleModes">' +
                                '' +
                            '</button>' +
                        '
' +
                        '<button type="button" class="btn btn-default navbar-btn pull-right margin-right-15" ng-click="openModal()" ng-disabled="images.length === 0" tooltip="View metric">' +
                            '' +
                        '</button>' +
                        '<button type="button" class="btn btn-primary navbar-btn pull-right margin-right-15" ng-disabled="!canEdit" tooltip="Upload" ng-if="uploadImage && canEdit"' +
                            'ngf-select="uploadImage($files)"' +
                            'ngf-multiple="false"' +
                            'ngf-pattern="image/*"' +
                            'ngf-accept="\'image/*\'"' +
                            'ngf-max-size="5MB"' +
                            'ngf-select-disabled="!canEdit"' +
                            'ngf-drop-available="false"' +
                            '>' +
                                '' +
                        '</button>' +
                    '
' +
                '
' +
            '
' +
        '' +
        '
' +
                '

' +
        '
' +
        '
' +
            '

' +
        '
'
    );

    // the gallery layout
    // by default, there are niceish css transitions, left/right buttons, and
    // a reasonable amount of space to display info about the current image
    $templateCache.put('tilesort-view-gallery', '\n
\n         0">\n\n          \n        \n        <span class="tilesort-gallery-nav-item tilesort-gallery-nav-right"\n          ng-click="moveRight()"\n          ng-show="currentIndex < images.length-1">\n\n          \n        \n
\n
\n
= 0 && $index+currentIndex-1 < images.length"\n          >\n          \n
\n\n
\n    ');

    // the tile layout
    // by default, the tiles have a tooltip for their title
    // and they're also drag/drop sortable
    // the active one is indicated by a glowing blue
    $templateCache.put('tilesort-view-tiles', '\n
\n
\n\n          \n
\n
\n    ');

    $templateCache.put('tilesort-view-tiles-large', '\n
\n
\n\n          \n
\n
\n    ');
}]);

// optionally load xeditable if it's there, and set the theme to bs3
try {
    angular.module('xeditable');
    angular.module('tilesortGallery').requires.push('xeditable');
    angular.module('tilesortGallery').run(['$injector', function ($injector) {
        if (!$injector.has('editableOptions')) return;
        $injector.get('editableOptions').theme = 'bs3';
    }]);
} catch (e) {}

// optionally load ng-sortable (Sortable.js) if it's available
try {
    angular.module('ng-sortable');
    angular.module('tilesortGallery').requires.push('ng-sortable');
} catch (e) {}<|endoftext|>


<commit_before>
/*!
 * Stylus - Arguments
 * Copyright(c) 2010 LearnBoost <dev@learnboost.com>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var Node = require('./node')
  , nodes = require('../nodes')
  , utils = require('../utils');

/**
 * Initialize a new `Arguments`.
 *
 * @api public
 */

var Arguments = module.exports = function Arguments(){
  nodes.Expression.call(this);
  this.map = {};
};

/**
 * Inherit from `nodes.Expression.prototype`.
 */

Arguments.prototype.__proto__ = nodes.Expression.prototype;

/**
 * Initialize an `Arguments` object with the nodes
 * from the given `expr`.
 *
 * @param {Expression} expr
 * @return {Arguments}
 * @api public
 */

Arguments.fromExpression = function(expr){
  var args = new Arguments
    , len = expr.nodes.length;
  args.lineno = expr.lineno;
  args.isList = expr.isList;
  for (var i = 0; i < len; ++i) {
    args.push(expr.nodes[i]);
  }
  return args;
};
<commit_msg>Added Arguments#clone()<commit_after>
/*!
 * Stylus - Arguments
 * Copyright(c) 2010 LearnBoost <dev@learnboost.com>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var Node = require('./node')
  , nodes = require('../nodes')
  , utils = require('../utils');

/**
 * Initialize a new `Arguments`.
 *
 * @api public
 */

var Arguments = module.exports = function Arguments(){
  nodes.Expression.call(this);
  this.map = {};
};

/**
 * Inherit from `nodes.Expression.prototype`.
 */

Arguments.prototype.__proto__ = nodes.Expression.prototype;

/**
 * Initialize an `Arguments` object with the nodes
 * from the given `expr`.
 *
 * @param {Expression} expr
 * @return {Arguments}
 * @api public
 */

Arguments.fromExpression = function(expr){
  var args = new Arguments
    , len = expr.nodes.length;
  args.lineno = expr.lineno;
  args.isList = expr.isList;
  for (var i = 0; i < len; ++i) {
    args.push(expr.nodes[i]);
  }
  return args;
};

/**
 * Return a clone of this node.
 *
 * @return {Node}
 * @api public
 */

Arguments.prototype.clone = function(){
  var clone = nodes.Expression.prototype.clone.call(this);
  clone.map = this.map;
  return clone;
};

<|endoftext|>


<commit_before>module.exports = normalize

const env = require('../env')
const headers = require('../headers')
const setIfExists = require('../set-if-exists')
const toEntityName = require('../to-entity-name')

function normalize (fixture) {
  // fixture.rawHeaders is an array in the form of ['key1', 'value1', 'key2', 'value2']
  // But the order of these can change, e.g. between local tests and CI on Travis.
  // That’s why we turn them into an object before storing the fixtures and turn
  // them back into an array before loading
  fixture.headers = headers.toObject(fixture.rawHeaders)
  delete fixture.rawHeaders

  // set all IDs in paths to 1
  fixture.path = fixture.path.replace(/\d+$/, 1)
  if (fixture.headers.location) {
    fixture.headers.location = fixture.headers.location.replace(/\d+$/, 1)
  }

  // set all dates to Universe 2017 Keynote time
  setIfExists(fixture.headers, 'date', 'Tue, 10 Oct 2017 16:00:00 GMT')
  setIfExists(fixture.headers, 'last-modified', 'Tue, 10 Oct 2017 16:00:00 GMT')
  setIfExists(fixture.headers, 'x-ratelimit-reset', '1507651200000')

  // Set remaining rate limit to 59 for unauthenticated accounts and
  // to 4999 to authenticated accounts
  const rateLimitRemaining = parseInt(fixture.headers['x-ratelimit-limit'], 10)
  setIfExists(fixture.headers, 'x-ratelimit-remaining', String(rateLimitRemaining - 1))

  // zerofy random stuff
  setIfExists(fixture.headers, 'etag', '"00000000000000000000000000000000"')
  setIfExists(fixture.headers, 'x-runtime-rack', '0.000000')
  setIfExists(fixture.headers, 'x-github-request-id', '0000:00000:0000000:0000000:00000000')

  // zerofy auth token (if present)
  if (fixture.reqheaders.authorization) {
    fixture.reqheaders.authorization = fixture.reqheaders.authorization.replace(/^token \w{40}$/, 'token 0000000000000000000000000000000000000000')
  } else {
    // otherwise add authorization to "badheaders" to help with matching the
    // right fixture to the right request
    fixture.badheaders = ['authorization']
  }

  // workaround for https://github.com/gr2m/octokit-fixtures/issues/3
  if (env.FIXTURES_PROXY) {
    fixture.scope = 'https://api.github.com:443'
    fixture.reqheaders.host = 'api.github.com'
    delete fixture.headers['x-powered-by']
  }

  // leave out headers that tend to change on different environments
  delete fixture.headers['accept-ranges']
  delete fixture.headers.region
  delete fixture.headers.server
  delete fixture.headers.vary

  // The GitHub API has several endpoints that require a PUT or a PATCH verb
  // with an empty body. In that case it’s unclear what content-type to set,
  // or if a content-type header is to be set at all. So we remove it from our
  // fixtures in that case but set content-length to 0 as required via:
  // https://developer.github.com/v3/#http-verbs
  if ((fixture.method === 'put' || fixture.method === 'patch') && !fixture.body) {
    delete fixture.reqheaders['content-type']
    fixture.reqheaders['content-length'] = 0
  }

  const responses = Array.isArray(fixture.response) ? fixture.response : [fixture.response]
  responses.forEach(response => {
    const entityName = toEntityName(response)
    if (entityName) {
      require(`./${entityName}`)(response)
    }
  })

  // update content length
  fixture.headers['content-length'] = String(JSON.stringify(fixture.response).length)

  return fixture
}
<commit_msg>fix: remove proxy header "x-now-region" (#20)<commit_after>module.exports = normalize

const env = require('../env')
const headers = require('../headers')
const setIfExists = require('../set-if-exists')
const toEntityName = require('../to-entity-name')

function normalize (fixture) {
  // fixture.rawHeaders is an array in the form of ['key1', 'value1', 'key2', 'value2']
  // But the order of these can change, e.g. between local tests and CI on Travis.
  // That’s why we turn them into an object before storing the fixtures and turn
  // them back into an array before loading
  fixture.headers = headers.toObject(fixture.rawHeaders)
  delete fixture.rawHeaders

  // set all IDs in paths to 1
  fixture.path = fixture.path.replace(/\d+$/, 1)
  if (fixture.headers.location) {
    fixture.headers.location = fixture.headers.location.replace(/\d+$/, 1)
  }

  // set all dates to Universe 2017 Keynote time
  setIfExists(fixture.headers, 'date', 'Tue, 10 Oct 2017 16:00:00 GMT')
  setIfExists(fixture.headers, 'last-modified', 'Tue, 10 Oct 2017 16:00:00 GMT')
  setIfExists(fixture.headers, 'x-ratelimit-reset', '1507651200000')

  // Set remaining rate limit to 59 for unauthenticated accounts and
  // to 4999 to authenticated accounts
  const rateLimitRemaining = parseInt(fixture.headers['x-ratelimit-limit'], 10)
  setIfExists(fixture.headers, 'x-ratelimit-remaining', String(rateLimitRemaining - 1))

  // zerofy random stuff
  setIfExists(fixture.headers, 'etag', '"00000000000000000000000000000000"')
  setIfExists(fixture.headers, 'x-runtime-rack', '0.000000')
  setIfExists(fixture.headers, 'x-github-request-id', '0000:00000:0000000:0000000:00000000')

  // zerofy auth token (if present)
  if (fixture.reqheaders.authorization) {
    fixture.reqheaders.authorization = fixture.reqheaders.authorization.replace(/^token \w{40}$/, 'token 0000000000000000000000000000000000000000')
  } else {
    // otherwise add authorization to "badheaders" to help with matching the
    // right fixture to the right request
    fixture.badheaders = ['authorization']
  }

  // workaround for https://github.com/gr2m/octokit-fixtures/issues/3
  if (env.FIXTURES_PROXY) {
    fixture.scope = 'https://api.github.com:443'
    fixture.reqheaders.host = 'api.github.com'
    delete fixture.headers['x-powered-by']
  }

  // leave out headers that tend to change on different environments
  delete fixture.headers['accept-ranges']
  delete fixture.headers.region
  delete fixture.headers.server
  delete fixture.headers.vary

  // The GitHub API has several endpoints that require a PUT or a PATCH verb
  // with an empty body. In that case it’s unclear what content-type to set,
  // or if a content-type header is to be set at all. So we remove it from our
  // fixtures in that case but set content-length to 0 as required via:
  // https://developer.github.com/v3/#http-verbs
  if ((fixture.method === 'put' || fixture.method === 'patch') && !fixture.body) {
    delete fixture.reqheaders['content-type']
    fixture.reqheaders['content-length'] = 0
  }

  const responses = Array.isArray(fixture.response) ? fixture.response : [fixture.response]
  responses.forEach(response => {
    const entityName = toEntityName(response)
    if (entityName) {
      require(`./${entityName}`)(response)
    }
  })

  // remove headers added by proxy
  // see https://github.com/gr2m/octokit-fixtures/pull/20#issuecomment-331558385
  delete fixture.headers['x-now-region']

  // update content length
  fixture.headers['content-length'] = String(JSON.stringify(fixture.response).length)

  return fixture
}
<|endoftext|>


<commit_before>/** @babel */

import * as fp from 'fuzzaldrin-plus'
import * as TimSort from 'timsort'
import SelectList from 'atom-select-list'

import * as NotesFs from './notes-fs'

let autocompleteTimeout

/**
  * @typedef DocumentItem
  * @type {Object}
  * @property {string} title - Title of the note.
  * @property {string} fileName - Name of the file where note is stored.
  * @property {string} filePath - Path to the file where note is stored.
  * @property {string} body - Body of the note.
  * @property {Date} modifiedAt - Date and time of last modification to the note.
  */

/**
  * @typedef Options
  * @type {Object}
  * @property {function()} [didHide] - Callback to call whenever this view is hidden.
  */

export default class NotesViewList {
  /** Builds a new notes query and list interface element.
    *
    * @param {Promise.<DocQuery>} store - The document storage for notes.
    * @param {Options} [options] - Behaviour and configuration settings.
    */
  constructor (store, options = {}) {
    store.then(dq => {
      this.dq = dq
      let reload = () => {
        if (!this.isLoaded()) return
        this.selectList.update({items: this.dq.documents})
      }
      let makeReady = () => {
        this.dq.loaded = true
        this.selectList.update({loadingMessage: null})
        reload()
        this.dq.on('added', _ => reload())
        this.dq.on('updated', _ => reload())
        this.dq.on('removed', _ => reload())
      }
      if (this.dq.loaded) makeReady()
      else this.dq.on('ready', () => makeReady())
    })
    if (options.hasOwnProperty('didHide')) {
      this.didHide = options.didHide
    }
    this.filteredItems = []
    this.selectList = new SelectList({
      items: [],
      loadingMessage: 'Loading notes...',
      emptyMessage: 'No matching notes',
      initialSelectionIndex: undefined,
      elementForItem: (item) => this.elementForItem(item),
      filter: (items, query) => this.filter(items, query),
      filterQuery: (query) => this.filterQuery(query),
      didChangeQuery: (query) => this.didChangeQuery(query),
      didConfirmSelection: (item) => this.didConfirmSelection(item),
      didConfirmEmptySelection: () => this.didConfirmEmptySelection(),
      didCancelSelection: () => this.didCancelSelection()
    })
    this.selectList.element.classList.add('atom-notes')
  }

  /** Returns true iff the document storage has finished loading notes. */
  isLoaded () {
    return this.dq !== undefined && this.dq.loaded
  }

  /** Returns HTMLElement object that should represent a single DocumentItem in this view. */
  elementForItem (item) {
    const query = this.selectList.getFilterQuery()
    const matches = fp.match(item.title, query)

    let primary = document.createElement('div')
    primary.classList.add('primary-line')
    primary.appendChild(highlight(item.title, matches))

    let metadata = document.createElement('div')
    metadata.classList.add('metadata')
    metadata.textContent = item.modifiedAt.toLocaleDateString()
    primary.appendChild(metadata)

    let secondary = document.createElement('div')
    secondary.classList.add('secondary-line')
    secondary.textContent = item.body.slice(0, 100)

    let element = document.createElement('li')
    element.classList.add('two-lines')
    element.appendChild(primary)
    element.appendChild(secondary)
    return element
  }

  /** Renders completion for query; if not supplied, re-render existing completion. */
  autocomplete (query = undefined) {
    if (!this.lastAutocompleteQuery) this.lastAutocompleteQuery = ''
    if (!this.isLoaded()) {
      this.lastAutocompleteQuery = ''
      return
    }
    __guard__(autocompleteTimeout, x => {
      clearTimeout(x)
      autocompleteTimeout = null
    })
    if (query) {
      this.filteredItems = fp.filter(this.dq.documents, query, {key: 'title'})
    } else {
      this.lastAutocompleteQuery = ''
      this.selectList.refs.queryEditor.selectAll()
      return
    }
    if (this.filteredItems.length <= 0) {
      this.lastAutocompleteQuery = ''
      return
    }
    autocompleteTimeout = setTimeout(() => {
      if (this.filteredItems.length <= 0) {
        this.lastAutocompleteQuery = ''
        return
      }
      const best = this.filteredItems[0]
      const q = this.selectList.getFilterQuery()
      const complete = (q !== undefined &&
                        q.length > 0 &&
                        best.title.toLowerCase().startsWith(q.toLowerCase()))
      if (complete) {
        let newQuery = q + best.title.slice(q.length)
        this.selectList.setQuery(newQuery, {doDidChangeQuery: false})
        this.selectList.refs.queryEditor.selectLeft(newQuery.length - q.length)
        this.lastAutocompleteQuery = q
      } else {
        this.lastAutocompleteQuery = ''
      }
    }, 300)
  }

  /** Our override for our SelectList's filter() callback. */
  filter (_, query) {
    let items = []
    if (!this.isLoaded()) return items
    if (query === undefined || query.length <= 0) {
      items = this.dq.documents
      TimSort.sort(items, (lhs, rhs) => {
        if (lhs.modifiedAt > rhs.modifiedAt) return -1
        else if (lhs.modifiedAt < rhs.modifiedAt) return 1
        return 0
      })
    } else {
      items = this.dq.search(query)
      TimSort.sort(items, (lhs, rhs) => {
        if (query.length > 0) {
          const li = fp.score(lhs.title, query)
          const ri = fp.score(rhs.title, query)
          if (li > ri) return -1
          else if (li < ri) return 1
          return 0
        }
      })
    }
    // docsearch returned nothing, fallback to fuzzy finder
    if (items.length <= 0) {
      return this.filteredItems
    }
    return items
  }

  /** Our override for our SelectList's filterQuery() callback. */
  filterQuery (query) {
    return __guard__(query, x => {
      let t = x.trim()
      return x.length > 0 && x.endsWith(' ') ? t + ' ' : t
    })
  }

  /** Our override for our SelectList's didChangeQuery() callback. */
  didChangeQuery (query) {
    if (query.toLowerCase() !== this.lastAutocompleteQuery.toLowerCase()) {
      this.autocomplete(query)
    }
  }

  /** Our override for our SelectList's didConfirmSelection() callback. */
  didConfirmSelection (item) {
    this.didHide()
    atom.workspace.open(item.filePath)
  }

  /** Our override for our SelectList's didConfirmEmptySelection() callback. */
  didConfirmEmptySelection () {
    const title = this.selectList.getFilterQuery()
    if (title.length <= 0) return

    this.didHide()
    if (this.selectList.items.length > 0) {
      atom.workspace.open(this.selectList.items[0].filePath)
    } else {
      NotesFs.openNote(title)
    }
  }

  /** Our override for our SelectList's didCancelSelection() callback. */
  didCancelSelection () {
    __guard__(autocompleteTimeout, x => {
      clearTimeout(x)
      autocompleteTimeout = null
    })

    // focus leaving atom-notes unselects any selected item and dismisses modal
    if (!this.selectList.element.contains(document.activeElement)) {
      this.selectList.selectNone()
      this.didHide()
      return
    }

    // cancel with a selected item unselects the item
    if (this.selectList.getSelectedItem()) {
      this.selectList.selectNone()
      return
    }

    // cancel with selected text unselects the text
    const selectedText = this.selectList.refs.queryEditor.getSelectedText()
    if (selectedText !== '') {
      let query = this.selectList.getQuery()
      query = query.slice(0, query.length - selectedText.length)
      this.selectList.setQuery(query, {doDidChangeQuery: false})
      return
    }

    // cancel with no selected item and no selected text dismisses the modal
    __guard__(this.previousFocus, x => x.focus())
    this.didHide()
  }

  destroy () {
    __guard__(autocompleteTimeout, x => {
      clearTimeout(x)
      autocompleteTimeout = null
    })
  }
}

// Taken from https://github.com/atom/fuzzy-finder/blob/master/lib/fuzzy-finder-view.js#L304
function highlight (path, matches, offsetIndex = 0) {
  let lastIndex = 0
  let matchedChars = []
  const fragment = document.createDocumentFragment()
  for (let matchIndex of matches) {
    matchIndex -= offsetIndex
    // If marking up the basename, omit path matches
    if (matchIndex < 0) {
      continue
    }
    const unmatched = path.substring(lastIndex, matchIndex)
    if (unmatched) {
      if (matchedChars.length > 0) {
        const span = document.createElement('span')
        span.classList.add('character-match')
        span.textContent = matchedChars.join('')
        fragment.appendChild(span)
        matchedChars = []
      }

      fragment.appendChild(document.createTextNode(unmatched))
    }

    matchedChars.push(path[matchIndex])
    lastIndex = matchIndex + 1
  }

  if (matchedChars.length > 0) {
    const span = document.createElement('span')
    span.classList.add('character-match')
    span.textContent = matchedChars.join('')
    fragment.appendChild(span)
  }

  // Remaining characters are plain text
  fragment.appendChild(document.createTextNode(path.substring(lastIndex)))
  return fragment
}

function __guard__ (value, transform) {
  return (typeof value !== 'undefined' && value !== null)
    ? transform(value)
    : undefined
}
<commit_msg>Fixes confirm when list has only fuzzy results.<commit_after>/** @babel */

import * as fp from 'fuzzaldrin-plus'
import * as TimSort from 'timsort'
import SelectList from 'atom-select-list'

import * as NotesFs from './notes-fs'

let autocompleteTimeout

/**
  * @typedef DocumentItem
  * @type {Object}
  * @property {string} title - Title of the note.
  * @property {string} fileName - Name of the file where note is stored.
  * @property {string} filePath - Path to the file where note is stored.
  * @property {string} body - Body of the note.
  * @property {Date} modifiedAt - Date and time of last modification to the note.
  */

/**
  * @typedef Options
  * @type {Object}
  * @property {function()} [didHide] - Callback to call whenever this view is hidden.
  */

export default class NotesViewList {
  /** Builds a new notes query and list interface element.
    *
    * @param {Promise.<DocQuery>} store - The document storage for notes.
    * @param {Options} [options] - Behaviour and configuration settings.
    */
  constructor (store, options = {}) {
    store.then(dq => {
      this.dq = dq
      let reload = () => {
        if (!this.isLoaded()) return
        this.selectList.update({items: this.dq.documents})
      }
      let makeReady = () => {
        this.dq.loaded = true
        this.selectList.update({loadingMessage: null})
        reload()
        this.dq.on('added', _ => reload())
        this.dq.on('updated', _ => reload())
        this.dq.on('removed', _ => reload())
      }
      if (this.dq.loaded) makeReady()
      else this.dq.on('ready', () => makeReady())
    })
    if (options.hasOwnProperty('didHide')) {
      this.didHide = options.didHide
    }
    this.filteredItems = []
    this.selectList = new SelectList({
      items: [],
      loadingMessage: 'Loading notes...',
      emptyMessage: 'No matching notes',
      initialSelectionIndex: undefined,
      elementForItem: (item) => this.elementForItem(item),
      filter: (items, query) => this.filter(items, query),
      filterQuery: (query) => this.filterQuery(query),
      didChangeQuery: (query) => this.didChangeQuery(query),
      didConfirmSelection: (item) => this.didConfirmSelection(item),
      didConfirmEmptySelection: () => this.didConfirmEmptySelection(),
      didCancelSelection: () => this.didCancelSelection()
    })
    this.selectList.element.classList.add('atom-notes')
  }

  /** Returns true iff the document storage has finished loading notes. */
  isLoaded () {
    return this.dq !== undefined && this.dq.loaded
  }

  /** Returns HTMLElement object that should represent a single DocumentItem in this view. */
  elementForItem (item) {
    const query = this.selectList.getFilterQuery()
    const matches = fp.match(item.title, query)

    let primary = document.createElement('div')
    primary.classList.add('primary-line')
    primary.appendChild(highlight(item.title, matches))

    let metadata = document.createElement('div')
    metadata.classList.add('metadata')
    metadata.textContent = item.modifiedAt.toLocaleDateString()
    primary.appendChild(metadata)

    let secondary = document.createElement('div')
    secondary.classList.add('secondary-line')
    secondary.textContent = item.body.slice(0, 100)

    let element = document.createElement('li')
    element.classList.add('two-lines')
    element.appendChild(primary)
    element.appendChild(secondary)
    return element
  }

  /** Renders completion for query; if not supplied, re-render existing completion. */
  autocomplete (query = undefined) {
    if (!this.lastAutocompleteQuery) this.lastAutocompleteQuery = ''
    if (!this.isLoaded()) {
      this.lastAutocompleteQuery = ''
      return
    }
    __guard__(autocompleteTimeout, x => {
      clearTimeout(x)
      autocompleteTimeout = null
    })
    if (query) {
      this.filteredItems = fp.filter(this.dq.documents, query, {key: 'title'})
    } else {
      this.lastAutocompleteQuery = ''
      this.selectList.refs.queryEditor.selectAll()
      return
    }
    if (this.filteredItems.length <= 0) {
      this.lastAutocompleteQuery = ''
      return
    }
    autocompleteTimeout = setTimeout(() => {
      if (this.filteredItems.length <= 0) {
        this.lastAutocompleteQuery = ''
        return
      }
      const best = this.filteredItems[0]
      const q = this.selectList.getFilterQuery()
      const complete = (q !== undefined &&
                        q.length > 0 &&
                        best.title.toLowerCase().startsWith(q.toLowerCase()))
      if (complete) {
        let newQuery = q + best.title.slice(q.length)
        this.selectList.setQuery(newQuery, {doDidChangeQuery: false})
        this.selectList.refs.queryEditor.selectLeft(newQuery.length - q.length)
        this.lastAutocompleteQuery = q
      } else {
        this.lastAutocompleteQuery = ''
      }
    }, 300)
  }

  /** Our override for our SelectList's filter() callback. */
  filter (_, query) {
    let items = []
    if (!this.isLoaded()) return items
    if (query === undefined || query.length <= 0) {
      items = this.dq.documents
      TimSort.sort(items, (lhs, rhs) => {
        if (lhs.modifiedAt > rhs.modifiedAt) return -1
        else if (lhs.modifiedAt < rhs.modifiedAt) return 1
        return 0
      })
    } else {
      items = this.dq.search(query)
      TimSort.sort(items, (lhs, rhs) => {
        if (query.length > 0) {
          const li = fp.score(lhs.title, query)
          const ri = fp.score(rhs.title, query)
          if (li > ri) return -1
          else if (li < ri) return 1
          return 0
        }
      })
    }
    // docsearch returned nothing, fallback to fuzzy finder
    if (items.length <= 0) {
      return this.filteredItems
    }
    return items
  }

  /** Our override for our SelectList's filterQuery() callback. */
  filterQuery (query) {
    return __guard__(query, x => {
      let t = x.trim()
      return x.length > 0 && x.endsWith(' ') ? t + ' ' : t
    })
  }

  /** Our override for our SelectList's didChangeQuery() callback. */
  didChangeQuery (query) {
    if (query.toLowerCase() !== this.lastAutocompleteQuery.toLowerCase()) {
      this.autocomplete(query)
    }
  }

  /** Our override for our SelectList's didConfirmSelection() callback. */
  didConfirmSelection (item) {
    this.didHide()
    atom.workspace.open(item.filePath)
  }

  /** Our override for our SelectList's didConfirmEmptySelection() callback. */
  didConfirmEmptySelection () {
    const title = this.selectList.getFilterQuery()
    if (title.length <= 0) return

    this.didHide()
    if (this.selectList.items.length > 0 &&
        this.selectList.items[0].title.toLowerCase().startsWith(title)) {
      atom.workspace.open(this.selectList.items[0].filePath)
    } else {
      NotesFs.openNote(title)
    }
  }

  /** Our override for our SelectList's didCancelSelection() callback. */
  didCancelSelection () {
    __guard__(autocompleteTimeout, x => {
      clearTimeout(x)
      autocompleteTimeout = null
    })

    // focus leaving atom-notes unselects any selected item and dismisses modal
    if (!this.selectList.element.contains(document.activeElement)) {
      this.selectList.selectNone()
      this.didHide()
      return
    }

    // cancel with a selected item unselects the item
    if (this.selectList.getSelectedItem()) {
      this.selectList.selectNone()
      return
    }

    // cancel with selected text unselects the text
    const selectedText = this.selectList.refs.queryEditor.getSelectedText()
    if (selectedText !== '') {
      let query = this.selectList.getQuery()
      query = query.slice(0, query.length - selectedText.length)
      this.selectList.setQuery(query, {doDidChangeQuery: false})
      return
    }

    // cancel with no selected item and no selected text dismisses the modal
    __guard__(this.previousFocus, x => x.focus())
    this.didHide()
  }

  destroy () {
    __guard__(autocompleteTimeout, x => {
      clearTimeout(x)
      autocompleteTimeout = null
    })
  }
}

// Taken from https://github.com/atom/fuzzy-finder/blob/master/lib/fuzzy-finder-view.js#L304
function highlight (path, matches, offsetIndex = 0) {
  let lastIndex = 0
  let matchedChars = []
  const fragment = document.createDocumentFragment()
  for (let matchIndex of matches) {
    matchIndex -= offsetIndex
    // If marking up the basename, omit path matches
    if (matchIndex < 0) {
      continue
    }
    const unmatched = path.substring(lastIndex, matchIndex)
    if (unmatched) {
      if (matchedChars.length > 0) {
        const span = document.createElement('span')
        span.classList.add('character-match')
        span.textContent = matchedChars.join('')
        fragment.appendChild(span)
        matchedChars = []
      }

      fragment.appendChild(document.createTextNode(unmatched))
    }

    matchedChars.push(path[matchIndex])
    lastIndex = matchIndex + 1
  }

  if (matchedChars.length > 0) {
    const span = document.createElement('span')
    span.classList.add('character-match')
    span.textContent = matchedChars.join('')
    fragment.appendChild(span)
  }

  // Remaining characters are plain text
  fragment.appendChild(document.createTextNode(path.substring(lastIndex)))
  return fragment
}

function __guard__ (value, transform) {
  return (typeof value !== 'undefined' && value !== null)
    ? transform(value)
    : undefined
}
<|endoftext|>


<commit_before>var CRC32 = require( 'buffer-crc32' )
var GPT = require( '../' )

/**
 * GPT Partition Table Constructor
 * @param {Buffer} data
 */
function Table( data ) {

  if( !(this instanceof Table) )
    return new Table( data )

  // LBA of partition table
  this.offsetLBA = 2
  // Partition entry size in bytes
  this.entrySize = 128

  // Array of partition entries
  this.partitions = new Array( 128 )

  this._buffer = new Buffer( this.size )
  this._buffer.fill( 0 )

  if( data instanceof Buffer ) {
    this.buffer = data
  }

}

// Exports
module.exports = Table

/**
 * Table Prototype
 * @type {Object}
 */
Table.prototype = {

  constructor: Table,

  get size() {
    return this.entries * this.entrySize
  },

  get crc() {
    return CRC32.unsigned( this.buffer )
  },

  // Number of partition entries
  get entries() {
    return this.partitions.length
  },

  set entries( value ) {

    value = parseInt( value, 10 )

    // Must be at least 128, per spec
    if( value < 128 ) {
      throw new SyntaxError(
        'Invalid number of partition entries.' +
        'Must be at least 128'
      )
    }

    this.partitions.length = value

  },

  get buffer() {

    var i, entries = this.entries

    if( this._buffer.length !== this.size ) {
      this._buffer = new Buffer( this.size )
    }

    this._buffer.fill( 0 )

    for( i = 0; i < entries; i++ ) {
      if( this.partitions[i] ) {
        this.partitions[i].buffer.copy(
          this._buffer, i * this.entrySize
        )
      }
    }

    return this._buffer.slice()

  },

  set buffer( value ) {

    var buffer = Buffer.isBuffer( value ) ?
      value : new Buffer( value )

    if( this._buffer.length !== this.size ) {
      this._buffer = new Buffer( this.size )
    }

    this._buffer.fill( 0 )

    var i, entries = this.entries

    for( i = 0; i < entries; i++ ) {

      var offset = i * this.entrySize
      var end = offset + this.entrySize

      if( this.partitions[i] ) {
        this.partitions[i].buffer =
          buffer.slice( offset, end )
      } else {
        this.partitions[i] = new GPT.Partition(
          buffer.slice( offset, end )
        )
      }

    }

  }

}
<commit_msg>Deleted lib/partition-table: Obsolete<commit_after><|endoftext|>


<commit_before>var addressLookup = function(event) {
    var input = $("#address-lookup :input[name='search']"),
        searchValue = input.val().trim();
    event.preventDefault();
    $('#address-selector').hide();
    $('#addresses').empty();
    $('.message').empty();

    $.ajax({
          type: 'GET',
          url: '/address-search?q='+searchValue+'&q.options={fields:["postcode","street"]}',
          contentType: 'application/json',
          success: function(data) {
                renderAddresses(data);
                $('#address-selector').show();
          },
          error: function(xhr, options, error) {
            console.log(error);
            $('#addresses').empty();
            $('.message').text('No results');
        }
    });
};

var renderAddresses = function(addresses) {
    addresses.hits.hit.sort(function(a,b) {
        return a.fields.street.localeCompare(b.fields.street);
    });
    $.each(addresses.hits.hit, function(index, address) {
        var template = $.templates("#address-template"),
            html = template.render({
                'address': address.fields.address,
                'property': address.fields.property,
                'street': address.fields.street,
                'town': address.fields.town,
                'postcode': address.fields.postcode
            });
        $('#addresses').append(html);
    });
};

$(document).ready(function(){
    $('#address-lookup').submit(addressLookup);
});
<commit_msg>retrieving sorted data from clousearch by specifying sort in query, so removed manual sorting<commit_after>var addressLookup = function(event) {
    var input = $("#address-lookup :input[name='search']"),
        searchValue = input.val().trim();
    event.preventDefault();
    $('#address-selector').hide();
    $('#addresses').empty();
    $('.message').empty();

    $.ajax({
          type: 'GET',
          url: '/address-search?q='+searchValue+'&q.options={fields:["postcode","street"]}&sort=street asc',
          contentType: 'application/json',
          success: function(data) {
                renderAddresses(data);
                $('#address-selector').show();
          },
          error: function(xhr, options, error) {
            console.log(error);
            $('#addresses').empty();
            $('.message').text('No results');
        }
    });
};

var renderAddresses = function(addresses) {
    $.each(addresses.hits.hit, function(index, address) {
        var template = $.templates("#address-template"),
            html = template.render({
                'address': address.fields.address,
                'property': address.fields.property,
                'street': address.fields.street,
                'town': address.fields.town,
                'postcode': address.fields.postcode
            });
        $('#addresses').append(html);
    });
};

$(document).ready(function(){
    $('#address-lookup').submit(addressLookup);
});
<|endoftext|>


<commit_before>// Stylelint supports CSS and SCSS
// https://stylelint.io/user-guide/configuration/
// https://stylelint.io/user-guide/rules/
// https://www.npmjs.com/package/stylelint-scss

//
// NOTE
//
// - This file should contain the rules for OUR custom (S)CSS code.
// - The rules defined here should be accompanied with comments explaining the rationale behind the convention.
//
// Other linter files
//
// - Please keep the ROOT `/.stylelintrc` without modifications, as it is the default for most Vue projcts.
// - You can specify further rules in .eslintrc files under sub folders for more granular, cascading rulesets.
// - You can import these rules in other places, like under tests.

// NOTE
// Apparently this does NOT extend root configuration as one would expect
// All settings must be defined here, including processors and plugins

module.exports = {

	// Treat CSS issues as warnings rather than errors
	defaultSeverity: 'warning',

	processors: [
		'stylelint-processor-html'
	],

	plugins: [
		'stylelint-scss'
	],

	// Coding style

	extends: [
		'stylelint-config-standard'
	],

	rules: {

		// Indent with tabs
		'indentation': ['tab'],

		// These will cause false positives
		'no-empty-source': null,
		'at-rule-no-unknown': null,

		// We're not quite this strict
		'declaration-empty-line-before': null,
		'block-closing-brace-empty-line-before': null,
		'rule-empty-line-before': null,

		// Comments
		'comment-no-empty': true,
		'comment-empty-line-before': null, // Would like to use this, but will warn on commented single-line rules
		'comment-whitespace-inside': null,

		// Misc basic things
		'color-no-invalid-hex': true,
		'function-calc-no-unspaced-operator': true,
		'number-leading-zero': 'always',
		'length-zero-no-unit': true,
		'no-extra-semicolons': true,
		'no-eol-whitespace': true,
		'no-missing-end-of-source-newline': true,
		'no-invalid-double-slash-comments': null,
		'declaration-block-no-duplicate-properties': true,
		'declaration-colon-newline-after': null,
		'function-parentheses-newline-inside': 'always-multi-line',
		'block-closing-brace-newline-after': 'always',
		'block-no-empty': true,

		// Quotes
		// We'd like to enforce single quotes for everything but attribute selectors, but currently this is not possible
		// 'string-quotes': 'single',
		'font-family-name-quotes': 'always-unless-keyword',
		'function-url-quotes': 'always',

		// At rules
		'at-rule-name-space-after': 'always-single-line',
		'at-rule-semicolon-space-before': 'never',
		'at-rule-name-newline-after': null, // 'always-multi-line' is close but sometimes weird
		'at-rule-empty-line-before': [
			'always',
			{
				'ignore': [
					'after-comment',
					'inside-block',
					'blockless-after-blockless'
				]
			}
		],

		// Prefer lowercase in general
		'unit-case': 'lower',
		'color-hex-case': 'lower',
		'function-name-case': 'lower',
		'value-keyword-case': 'lower',
		'at-rule-name-case': 'lower',

		// Misc rules
		'shorthand-property-no-redundant-values': null,
		'number-no-trailing-zeros': null,
		'selector-pseudo-element-colon-notation': 'single',
		'declaration-block-no-redundant-longhand-properties': null,

		// No vendor prefixes in source
		// This is because Autoprefixer enforces correct vendor prefixes better than us humans and will remove them up anyway
		'at-rule-no-vendor-prefix': true,
		'media-feature-name-no-vendor-prefix': true,
		'selector-no-vendor-prefix': true,
		'property-no-vendor-prefix': true,
		'value-no-vendor-prefix': true,

		// Disallow excessive nesting
		// NOTE
		// - While the intention is good, a blanket limit does not do the job well
		// - Many times you should not be nesting even beyond two levels
		// - And sometimes nesting beyond this limit might make sense
		'max-nesting-depth': [
			4
		],

		// Allow convenient spacing, but don't go overboard
		'selector-max-empty-lines': 3,
		'function-max-empty-lines': 3,
		'value-list-max-empty-lines': 3,
		'max-empty-lines': [
			3
		],

		// SCSS-specific linting

		// Stylistic
		'scss/dollar-variable-colon-space-after': 'always',
		'scss/dollar-variable-colon-space-before': 'never',

		// Confusing, not clear if compiles to shorthand or individual properties
		'scss/declaration-nested-properties': 'never'

	}
}
<commit_msg>Stylelint config rollback<commit_after>// Stylelint supports CSS and SCSS
// https://stylelint.io/user-guide/configuration/
// https://stylelint.io/user-guide/rules/
// https://www.npmjs.com/package/stylelint-scss

//
// NOTE
//
// - This file should contain the rules for OUR custom (S)CSS code.
// - The rules defined here should be accompanied with comments explaining the rationale behind the convention.
//
// Other linter files
//
// - Please keep the ROOT `/.stylelintrc` without modifications, as it is the default for most Vue projcts.
// - You can specify further rules in .eslintrc files under sub folders for more granular, cascading rulesets.
// - You can import these rules in other places, like under tests.

// NOTE
// Apparently this does NOT extend root configuration as one would expect
// All settings must be defined here, including processors and plugins

module.exports = {

	// Treat CSS issues as warnings rather than errors
	defaultSeverity: 'warning',

	processors: [
		'stylelint-processor-html'
	],

	plugins: [
		'stylelint-scss'
	],

	// Coding style

	extends: [
		'stylelint-config-standard'
	],

	rules: {

		// Indent with tabs
		'indentation': ['tab'],

		// These will cause false positives
		'no-empty-source': null,
		'at-rule-no-unknown': null,

		// We're not quite this strict
		'declaration-empty-line-before': null,
		'block-closing-brace-empty-line-before': null,
		'rule-empty-line-before': null,

		// Comments
		'comment-no-empty': true,
		'comment-empty-line-before': null, // Would like to use this, but will warn on commented single-line rules
		'comment-whitespace-inside': null,

		// Misc basic things
		'color-no-invalid-hex': true,
		'function-calc-no-unspaced-operator': true,
		'number-leading-zero': 'always',
		'length-zero-no-unit': true,
		'no-extra-semicolons': true,
		'no-eol-whitespace': true,
		'no-missing-end-of-source-newline': true,
		'no-invalid-double-slash-comments': true,
		'declaration-block-no-duplicate-properties': true,
		'declaration-colon-newline-after': null,
		'function-parentheses-newline-inside': 'always-multi-line',
		'block-closing-brace-newline-after': 'always',
		'block-no-empty': true,

		// Quotes
		// We'd like to enforce single quotes for everything but attribute selectors, but currently this is not possible
		// 'string-quotes': 'single',
		'font-family-name-quotes': 'always-unless-keyword',
		'function-url-quotes': 'always',

		// At rules
		'at-rule-name-space-after': 'always-single-line',
		'at-rule-semicolon-space-before': 'never',
		'at-rule-name-newline-after': null, // 'always-multi-line' is close but sometimes weird
		'at-rule-empty-line-before': [
			'always',
			{
				'ignore': [
					'after-comment',
					'inside-block',
					'blockless-after-blockless'
				]
			}
		],

		// Prefer lowercase in general
		'unit-case': 'lower',
		'color-hex-case': 'lower',
		'function-name-case': 'lower',
		'value-keyword-case': 'lower',
		'at-rule-name-case': 'lower',

		// Misc rules
		'shorthand-property-no-redundant-values': null,
		'number-no-trailing-zeros': null,
		'selector-pseudo-element-colon-notation': 'single',
		'declaration-block-no-redundant-longhand-properties': null,

		// No vendor prefixes in source
		// This is because Autoprefixer enforces correct vendor prefixes better than us humans and will remove them up anyway
		'at-rule-no-vendor-prefix': true,
		'media-feature-name-no-vendor-prefix': true,
		'selector-no-vendor-prefix': true,
		'property-no-vendor-prefix': true,
		'value-no-vendor-prefix': true,

		// Disallow excessive nesting
		// NOTE
		// - While the intention is good, a blanket limit does not do the job well
		// - Many times you should not be nesting even beyond two levels
		// - And sometimes nesting beyond this limit might make sense
		'max-nesting-depth': [
			4
		],

		// Allow convenient spacing, but don't go overboard
		'selector-max-empty-lines': 3,
		'function-max-empty-lines': 3,
		'value-list-max-empty-lines': 3,
		'max-empty-lines': [
			3
		],

		// SCSS-specific linting

		// Stylistic
		'scss/dollar-variable-colon-space-after': 'always',
		'scss/dollar-variable-colon-space-before': 'never',

		// Confusing, not clear if compiles to shorthand or individual properties
		'scss/declaration-nested-properties': 'never'

	}
}
<|endoftext|>