<commit_before>define([
    "controller/channel",
    "model/model",
    "view/view",
    "queue/queue",
    "events/events",
    "events/states",
    "utils/strings",
    "utils/event",
    "utils/logger",
], function(Channel, Model, View, Queue, Events, States, Strings, Event, Logger) {
    /**
     * gPlayer main controller
     *
     * Responsible for the general flow and creation of the view and models
     */
    var Controller = function(config) {
        this.init(config);
    };

    Controller.prototype = {
        /**
         * Referances
         */
        _view: null,
        _model: null,
        _queue: null,
        _notifications: null,

        _channels: [],
        _state: States.IDLE,

        audioCtx: null,
        mute: false,
        volume: 1,

        /**
         * Constructor function for the main controller
         *
         * Registering important instances to hold here
         *
         * @param {Object} config
         * @param {Object}
         * @return this for chaining
         */
        init: function(config) {
            Logger.debug('CONTROLLER::INIT FIRED');

            this._model = new Model(config);
            this._notifications = new Event();
            this._view = new View(this, this._notifications);
            this._queue = new Queue(this._notifications);

            this.subscribe();

            return this;
        },

        /**
         *
         */
        subscribe: function() {
            var self = this;

            this.getNotifications().on(Events.STATE_CHANGED, function(state) {
                self._state = state;
            });

            this.getNotifications().on(Events.PLAY, function(item) {
                console.log(['CONTROLLER::ITEM ARRIVED', item]);
                self.channelAdd(item);
                self.changeState(States.PLAYING);
            });

            this.getNotifications().on(Events.PAUSE, function() {
                self.changeState(States.PAUSED);
                self.pause();
            });

            this.getNotifications().on(Events.QUEUE_EMPTY, function() {
                self.changeState(States.IDLE);
                self.pause();
            });

            $(window).bind('resize', function() {
                self.getNotifications().fire(Events.RESIZE);
            });

            return this;
        },

        /**
         * Bootstraps the main controller
         */
        bootstrap: function(container) {
            this._model.setup(container);
            this._view.setup();
            this.loop();
        },

        /**
         * Getter for the Queue object, set on constructor
         */
        getQueue: function() {
            return this._queue;
        },

        /**
         * Getter for the Model object, set on constructor
         */
        getModel: function() {
            return this._model;
        },

        /**
         * Getter for the Notifications object, set on constructor
         */
        getNotifications: function() {
            return this._notifications;
        },

        /**
         * Changes the state of the player by boardcasting the proper event on change.
         * This is the only place modifies the state of the player
         *
         * @param {String} newState (ENUM from States object)
         */
        changeState: function(newState) {
            if (newState === this._state) return;

            this.getNotifications().fire(Events.STATE_CHANGED, newState);
        },

        /**
         *
         */
        isPlaying: function() {
            for (var i = 0, len = this._channels.length; i < len; i++) {
                if ('undefined' !== typeof(this._channels[i]) && true === this._channels[i].isPlaying())
                    return true;
            }

            return false;
        },

        /**
         *
         */
        channelAdd: function (item) {
            var channelNew = new Channel({
                parent: this,
                item: item
            });

            this._channels.push(channelNew);
            channelNew.mediaPlay();

            return this;
        },

        /**
         *
         */
        getActiveChannel: function() {
            return this._channels[0]; //channel 0 is the active.. 1 is usually created only while crossfading and even then.. 0 is the active.
        },

        isCrossfade: function() {
            return this._model.crossfade.enabled;
        },

        isMute: function() {
            return this.mute;
        },

        /**
         *
         */
        getVolume: function() {
            return this.volume;
        },

        _onEnd: function(crossfade) {
            if (true === crossfade) {
                setTimeout($.proxy(function() {
                    this.activeChannelCleanup();
                }, this), this._model.crossfade.onBeforeEnd * 1000);
            } else {
                this.activeChannelCleanup();
            }

            this.getNotifications().fire(Events.PLAY_NEXT);
            //api.onEnd();
        },

        /**
         *
         */
        setVolume: function(volume) {
            this.volume = (1 <= volume) ? 1 : volume; // can not be greater than 1
            this.mute = (0 >= volume) ? true : false;

            //update view.
            this._view.getPlayerView().setVolumeBar();

            //updates the channel with volume value.
            for (var i = 0, len = this._channels.length; i < len; i++) {
                if ('undefined' !== typeof(this._channels[i]))
                    this._channels[i].setVolume();
            }

            /*
            var interactiveObj = $('.groovy-interactive');
            interactiveObj.find('.groovy-scrubber').find('img').eq(0).css({
                transform: 'scaleY('+arg+')'
            });

            if(arg == 0){
                cthis.find('.scrub-bg-img-reflect').fadeOut('slow');
            } else {
                cthis.find('.scrub-bg-img-reflect').fadeIn('slow');
            }
            last_vol = arg;
            */
        },

        /**
         *
         */
        loop: function() {
            // verify everything needed for the loop exists. Run loop only when playing.
            if ('undefined' === typeof(this.getActiveChannel()) || !this.isPlaying()) {
                return this._runLoop();
            }

            var scrubberWidth = this._view.getPlayerView().getScrubberWidth(),
                currentTime = $('.groovy-current-time'),
                duration = $('.groovy-duration'),
                scrubberOffset = 0,
                scrubberOffsetPercent = 0,
                scrubberOffsetPixels = 0,
                timeTotal = this.getActiveAudio().duration,
                timeCurr = this.getActiveAudio().currentTime,
                timeOffset = 3;

            /*
            // might not work.. audiobuffer is per channel.. odd location for referances, check!.
            if (this.audioBuffer && 'placeholder' !== this.audioBuffer) {
                timeTotal = this.audioBuffer.duration;
                timeCurr = this.audioCtx.currentTime;
                //console.log(this.audioBuffer.currentTime);
            }*/

            scrubberOffset = ((timeCurr - this._model.style.interactiveSelectOffset) / timeTotal);
            scrubberOffsetPercent = scrubberOffset * 100;

            // console.log(_scrubbar.children('.scrub-prog'), scrubberOffsetPercent, timeTotal, '-timecurr ', timeCurr, scrubberWidth);
            if (null == this.audioBuffer) {
                $('body').find('.groovy-spectrum-progress').css({
                    width: scrubberOffsetPercent + '%'
                });

                $('body').find('.groovy-scrubber-progress').css({
                    width: scrubberOffsetPercent + '%'
                });

                $('body').find('.groovy-play-bar').css({
                    width: scrubberOffsetPercent + '%'
                });
            }

            if (true === this._model.spectrum.enabled)
                this.drawSpectrum();

            if (true === this._model.timerDynamic) {
                scrubberOffsetPixels = scrubberOffset * scrubberWidth;

                currentTime.css({
                    left: scrubberOffsetPercent + '%'
                });

                if (scrubberOffsetPixels > scrubberWidth - 30) {
                    currentTime.css({
                        opacity: 1 - (((scrubberOffsetPixels - (scrubberWidth - 30)) / 30))
                    });
                } else {
                    if (1 !== Number(currentTime.css('opacity'))) {
                        currentTime.css({
                            opacity: 1
                        });
                    }
                };
            };

            //console.info(_currTime, timeCurr, this.formatTime(timeCurr))
            currentTime.text(new Strings(timeCurr).formatTime());
            duration.text(new Strings(timeTotal).formatTime());

            // notify channel
            for (var i = 0, len = this._channels.length; i < len; i++) {
                if ('undefined' !== typeof(this._channels[i])) {
                    this._channels[i].loop();
                } else {
                    console.log(['DEBUG', this._channels, i]);
                }
            }

            this._runLoop();
        },

        /**
         *
         */
        _runLoop: function() {
            requestAnimFrame($.proxy(function() {
                this.loop();
            }, this));

            return this;
        },

        /**
         *
         */
        activeChannelCleanup: function() {
            if ('undefined' !== typeof(this.getActiveChannel())) {
                this.getActiveChannel().destory();
                console.log(this._channels);
                this._channels.shift();
            }

            return this;
        },

        /**
         *
         */
        pause: function() {
            this.activeChannelCleanup();

            return this;
        },

        /**
         *
         */
        getCtx: function() {
            if (null === this.audioCtx) {
                this.audioCtx = new window.AudioContext;
            }

            return this.audioCtx;
        },

        /**
         * Based on a Fiddle I wrote: http://jsfiddle.net/Fc8Jr/
        **/
        drawSpectrum: function() {
            var frequencyByteData = this.getActiveChannel().frequencyByteData,
                canvas = this._view.getPlayerView().getCanvasReferances();

            var width = canvas.el.active.background.width,
                height = canvas.el.active.background.height;

            var BAR_WIDTH = 3,
                SPACER_WIDTH = 1;

            /* test.. disabled.
            var gradient = canvas.context.active.background.createLinearGradient(0, 0, width, height);
            gradient.addColorStop(1,'#000000');
            gradient.addColorStop(0.75,'#ff0000');
            gradient.addColorStop(0.25,'#ffff00');
            gradient.addColorStop(0,'#ffffff');
            */

            //canvas.el.active.background.width = width;
            canvas.context.active.background.clearRect(0, 0, width, height);
            canvas.context.active.background.fillStyle = '#'+ this._model.spectrum.color.bg;

            canvas.context.active.progress.clearRect(0, 0, width, height);
            canvas.context.active.progress.fillStyle = '#'+ this._model.spectrum.color.progress;

            for (var i = 0, magnitude = 0, len = frequencyByteData.length; i < len; i++) {
                magnitude = Math.ceil(frequencyByteData[i] * height / 256);
                if (2 > magnitude) magnitude = 2;

                canvas.context.active.background.fillRect(i * (SPACER_WIDTH + BAR_WIDTH), height, BAR_WIDTH, -magnitude);
                canvas.context.active.progress.fillRect(i * (SPACER_WIDTH + BAR_WIDTH), height, BAR_WIDTH, -magnitude);

                //canvas.context.active.background.fillRect(i/256 * width, height, width/len, -magnitude);
                //canvas.context.active.progress.fillRect(i/256 * width, height, width/len, -magnitude);
            }

            if (true === this._model.reflection) {
                canvas.context.reflect.background.clearRect(0, 0, width, height);
                canvas.context.reflect.background.drawImage(canvas.el.active.background, 0, 0);

                canvas.context.reflect.progress.clearRect(0, 0, width, height);
                canvas.context.reflect.progress.drawImage(canvas.el.active.progress, 0, 0);
            }
        },

        /**
         *
         */
        startedPlaying: function() {
            console.log('CONTROLLER::startedPlaying fired -- oh well.. started, not sure i want to keep this');
        },

        /**
         *
         */
        getActiveAudio: function() {
            return this.getActiveChannel().audioEl;
        }
    };

    window.AudioContext = window.AudioContext || window.webkitAudioContext;

    window.requestAnimFrame = (function() {
        return window.requestAnimationFrame ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame ||
            window.oRequestAnimationFrame ||
            window.msRequestAnimationFrame ||
            function(callback, el) {
                window.setTimeout(callback, 1000 / 60);
            };
    })();

    return Controller;
});<commit_msg>resize comment added# Please enter the commit message for your changes. Lines starting<commit_after>define([
    "controller/channel",
    "model/model",
    "view/view",
    "queue/queue",
    "events/events",
    "events/states",
    "utils/strings",
    "utils/event",
    "utils/logger",
], function(Channel, Model, View, Queue, Events, States, Strings, Event, Logger) {
    /**
     * gPlayer main controller
     *
     * Responsible for the general flow and creation of the view and models
     */
    var Controller = function(config) {
        this.init(config);
    };

    Controller.prototype = {
        /**
         * Referances
         */
        _view: null,
        _model: null,
        _queue: null,
        _notifications: null,

        _channels: [],
        _state: States.IDLE,

        audioCtx: null,
        mute: false,
        volume: 1,

        /**
         * Constructor function for the main controller
         *
         * Registering important instances to hold here
         *
         * @param {Object} config
         * @param {Object}
         * @return this for chaining
         */
        init: function(config) {
            Logger.debug('CONTROLLER::INIT FIRED');

            this._model = new Model(config);
            this._notifications = new Event();
            this._view = new View(this, this._notifications);
            this._queue = new Queue(this._notifications);

            this.subscribe();

            return this;
        },

        /**
         *
         */
        subscribe: function() {
            var self = this;

            this.getNotifications().on(Events.STATE_CHANGED, function(state) {
                self._state = state;
            });

            this.getNotifications().on(Events.PLAY, function(item) {
                console.log(['CONTROLLER::ITEM ARRIVED', item]);
                self.channelAdd(item);
                self.changeState(States.PLAYING);
            });

            this.getNotifications().on(Events.PAUSE, function() {
                self.changeState(States.PAUSED);
                self.pause();
            });

            this.getNotifications().on(Events.QUEUE_EMPTY, function() {
                self.changeState(States.IDLE);
                self.pause();
            });

            // translate native event for resize, for internal event
            $(window).bind('resize', function() {
                self.getNotifications().fire(Events.RESIZE);
            });

            return this;
        },

        /**
         * Bootstraps the main controller
         */
        bootstrap: function(container) {
            this._model.setup(container);
            this._view.setup();
            this.loop();
        },

        /**
         * Getter for the Queue object, set on constructor
         */
        getQueue: function() {
            return this._queue;
        },

        /**
         * Getter for the Model object, set on constructor
         */
        getModel: function() {
            return this._model;
        },

        /**
         * Getter for the Notifications object, set on constructor
         */
        getNotifications: function() {
            return this._notifications;
        },

        /**
         * Changes the state of the player by boardcasting the proper event on change.
         * This is the only place modifies the state of the player
         *
         * @param {String} newState (ENUM from States object)
         */
        changeState: function(newState) {
            if (newState === this._state) return;

            this.getNotifications().fire(Events.STATE_CHANGED, newState);
        },

        /**
         *
         */
        isPlaying: function() {
            for (var i = 0, len = this._channels.length; i < len; i++) {
                if ('undefined' !== typeof(this._channels[i]) && true === this._channels[i].isPlaying())
                    return true;
            }

            return false;
        },

        /**
         *
         */
        channelAdd: function (item) {
            var channelNew = new Channel({
                parent: this,
                item: item
            });

            this._channels.push(channelNew);
            channelNew.mediaPlay();

            return this;
        },

        /**
         *
         */
        getActiveChannel: function() {
            return this._channels[0]; //channel 0 is the active.. 1 is usually created only while crossfading and even then.. 0 is the active.
        },

        isCrossfade: function() {
            return this._model.crossfade.enabled;
        },

        isMute: function() {
            return this.mute;
        },

        /**
         *
         */
        getVolume: function() {
            return this.volume;
        },

        _onEnd: function(crossfade) {
            if (true === crossfade) {
                setTimeout($.proxy(function() {
                    this.activeChannelCleanup();
                }, this), this._model.crossfade.onBeforeEnd * 1000);
            } else {
                this.activeChannelCleanup();
            }

            this.getNotifications().fire(Events.PLAY_NEXT);
            //api.onEnd();
        },

        /**
         *
         */
        setVolume: function(volume) {
            this.volume = (1 <= volume) ? 1 : volume; // can not be greater than 1
            this.mute = (0 >= volume) ? true : false;

            //update view.
            this._view.getPlayerView().setVolumeBar();

            //updates the channel with volume value.
            for (var i = 0, len = this._channels.length; i < len; i++) {
                if ('undefined' !== typeof(this._channels[i]))
                    this._channels[i].setVolume();
            }

            /*
            var interactiveObj = $('.groovy-interactive');
            interactiveObj.find('.groovy-scrubber').find('img').eq(0).css({
                transform: 'scaleY('+arg+')'
            });

            if(arg == 0){
                cthis.find('.scrub-bg-img-reflect').fadeOut('slow');
            } else {
                cthis.find('.scrub-bg-img-reflect').fadeIn('slow');
            }
            last_vol = arg;
            */
        },

        /**
         *
         */
        loop: function() {
            // verify everything needed for the loop exists. Run loop only when playing.
            if ('undefined' === typeof(this.getActiveChannel()) || !this.isPlaying()) {
                return this._runLoop();
            }

            var scrubberWidth = this._view.getPlayerView().getScrubberWidth(),
                currentTime = $('.groovy-current-time'),
                duration = $('.groovy-duration'),
                scrubberOffset = 0,
                scrubberOffsetPercent = 0,
                scrubberOffsetPixels = 0,
                timeTotal = this.getActiveAudio().duration,
                timeCurr = this.getActiveAudio().currentTime,
                timeOffset = 3;

            /*
            // might not work.. audiobuffer is per channel.. odd location for referances, check!.
            if (this.audioBuffer && 'placeholder' !== this.audioBuffer) {
                timeTotal = this.audioBuffer.duration;
                timeCurr = this.audioCtx.currentTime;
                //console.log(this.audioBuffer.currentTime);
            }*/

            scrubberOffset = ((timeCurr - this._model.style.interactiveSelectOffset) / timeTotal);
            scrubberOffsetPercent = scrubberOffset * 100;

            // console.log(_scrubbar.children('.scrub-prog'), scrubberOffsetPercent, timeTotal, '-timecurr ', timeCurr, scrubberWidth);
            if (null == this.audioBuffer) {
                $('body').find('.groovy-spectrum-progress').css({
                    width: scrubberOffsetPercent + '%'
                });

                $('body').find('.groovy-scrubber-progress').css({
                    width: scrubberOffsetPercent + '%'
                });

                $('body').find('.groovy-play-bar').css({
                    width: scrubberOffsetPercent + '%'
                });
            }

            if (true === this._model.spectrum.enabled)
                this.drawSpectrum();

            if (true === this._model.timerDynamic) {
                scrubberOffsetPixels = scrubberOffset * scrubberWidth;

                currentTime.css({
                    left: scrubberOffsetPercent + '%'
                });

                if (scrubberOffsetPixels > scrubberWidth - 30) {
                    currentTime.css({
                        opacity: 1 - (((scrubberOffsetPixels - (scrubberWidth - 30)) / 30))
                    });
                } else {
                    if (1 !== Number(currentTime.css('opacity'))) {
                        currentTime.css({
                            opacity: 1
                        });
                    }
                };
            };

            //console.info(_currTime, timeCurr, this.formatTime(timeCurr))
            currentTime.text(new Strings(timeCurr).formatTime());
            duration.text(new Strings(timeTotal).formatTime());

            // notify channel
            for (var i = 0, len = this._channels.length; i < len; i++) {
                if ('undefined' !== typeof(this._channels[i])) {
                    this._channels[i].loop();
                } else {
                    console.log(['DEBUG', this._channels, i]);
                }
            }

            this._runLoop();
        },

        /**
         *
         */
        _runLoop: function() {
            requestAnimFrame($.proxy(function() {
                this.loop();
            }, this));

            return this;
        },

        /**
         *
         */
        activeChannelCleanup: function() {
            if ('undefined' !== typeof(this.getActiveChannel())) {
                this.getActiveChannel().destory();
                console.log(this._channels);
                this._channels.shift();
            }

            return this;
        },

        /**
         *
         */
        pause: function() {
            this.activeChannelCleanup();

            return this;
        },

        /**
         *
         */
        getCtx: function() {
            if (null === this.audioCtx) {
                this.audioCtx = new window.AudioContext;
            }

            return this.audioCtx;
        },

        /**
         * Based on a Fiddle I wrote: http://jsfiddle.net/Fc8Jr/
        **/
        drawSpectrum: function() {
            var frequencyByteData = this.getActiveChannel().frequencyByteData,
                canvas = this._view.getPlayerView().getCanvasReferances();

            var width = canvas.el.active.background.width,
                height = canvas.el.active.background.height;

            var BAR_WIDTH = 3,
                SPACER_WIDTH = 1;

            /* test.. disabled.
            var gradient = canvas.context.active.background.createLinearGradient(0, 0, width, height);
            gradient.addColorStop(1,'#000000');
            gradient.addColorStop(0.75,'#ff0000');
            gradient.addColorStop(0.25,'#ffff00');
            gradient.addColorStop(0,'#ffffff');
            */

            //canvas.el.active.background.width = width;
            canvas.context.active.background.clearRect(0, 0, width, height);
            canvas.context.active.background.fillStyle = '#'+ this._model.spectrum.color.bg;

            canvas.context.active.progress.clearRect(0, 0, width, height);
            canvas.context.active.progress.fillStyle = '#'+ this._model.spectrum.color.progress;

            for (var i = 0, magnitude = 0, len = frequencyByteData.length; i < len; i++) {
                magnitude = Math.ceil(frequencyByteData[i] * height / 256);
                if (2 > magnitude) magnitude = 2;

                canvas.context.active.background.fillRect(i * (SPACER_WIDTH + BAR_WIDTH), height, BAR_WIDTH, -magnitude);
                canvas.context.active.progress.fillRect(i * (SPACER_WIDTH + BAR_WIDTH), height, BAR_WIDTH, -magnitude);

                //canvas.context.active.background.fillRect(i/256 * width, height, width/len, -magnitude);
                //canvas.context.active.progress.fillRect(i/256 * width, height, width/len, -magnitude);
            }

            if (true === this._model.reflection) {
                canvas.context.reflect.background.clearRect(0, 0, width, height);
                canvas.context.reflect.background.drawImage(canvas.el.active.background, 0, 0);

                canvas.context.reflect.progress.clearRect(0, 0, width, height);
                canvas.context.reflect.progress.drawImage(canvas.el.active.progress, 0, 0);
            }
        },

        /**
         *
         */
        startedPlaying: function() {
            console.log('CONTROLLER::startedPlaying fired -- oh well.. started, not sure i want to keep this');
        },

        /**
         *
         */
        getActiveAudio: function() {
            return this.getActiveChannel().audioEl;
        }
    };

    window.AudioContext = window.AudioContext || window.webkitAudioContext;

    window.requestAnimFrame = (function() {
        return window.requestAnimationFrame ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame ||
            window.oRequestAnimationFrame ||
            window.msRequestAnimationFrame ||
            function(callback, el) {
                window.setTimeout(callback, 1000 / 60);
            };
    })();

    return Controller;
});<|endoftext|>


<commit_before>var Codesearch = require('../web/codesearch.js'),
    fs         = require('fs'),
    path       = require('path'),
    parseopt   = require('parseopt'),
    log4js     = require('log4js');

log4js.configure({
                   levels: {
                     'codesearch': 'FATAL'
                   }
                 });

var REPO;
var extra_args;
var parser = new parseopt.OptionParser(
  {
    options: [
      {
        name: "--querylist",
        default: path.join(__dirname, 'testcases'),
        type: 'string',
        help: 'Load an alternate list of query terms'
      }
    ]
  });
var opts;

module.exports.parser = parser;

function parseopts(argv) {
  opts = parser.parse(argv);
  REPO = opts.arguments[0];
  extra_args = opts.arguments.slice(1);
  return opts.options;
}
module.exports.parseopts = parseopts;

function get_codesearch(args) {
  if (args === undefined)
    args = [];
  return new Codesearch(
    REPO, [], {
      args: args.concat(extra_args)
    });
}
module.exports.get_codesearch = get_codesearch;

function load_queries() {
  return fs.readFileSync(opts.options.querylist, 'utf8').split(/\n/);
}
module.exports.load_queries = load_queries;

function query_all(cs, q, cb) {
  var search = cs.search(q);
  var matches = [];
  search.on('match', function (m) {
              matches.push(m);
            })
  search.on('done', function () {
              cb(matches)
            });
}
module.exports.query_all = query_all;
<commit_msg>test: Default to reading config.js from web/<commit_after>var Codesearch = require('../web/codesearch.js'),
    fs         = require('fs'),
    path       = require('path'),
    parseopt   = require('parseopt'),
    log4js     = require('log4js'),
    config     = require('../web/config.js');

log4js.configure({
                   levels: {
                     'codesearch': 'FATAL'
                   }
                 });

var extra_args;
var parser = new parseopt.OptionParser(
  {
    options: [
      {
        name: "--querylist",
        default: path.join(__dirname, 'testcases'),
        type: 'string',
        help: 'Load an alternate list of query terms'
      },
      {
        name: "--repo",
        default: config.SEARCH_REPO,
        type: 'string',
        help: 'Git repository to search'
      },
      {
        name: "--ref",
        default: config.SEARCH_REF,
        type: 'string',
        help: 'Git ref to search.'
      }
    ]
  });
var opts;

module.exports.parser = parser;

function parseopts(argv) {
  opts = parser.parse(argv);
  extra_args = opts.arguments.slice();
  return opts.options;
}
module.exports.parseopts = parseopts;

function get_codesearch(args) {
  if (args === undefined)
    args = [];
  return new Codesearch(
    opts.options.repo, [opts.options.ref], {
      args: config.SEARCH_ARGS.concat(args).concat(extra_args)
    });
}
module.exports.get_codesearch = get_codesearch;

function load_queries() {
  return fs.readFileSync(opts.options.querylist, 'utf8').split(/\n/);
}
module.exports.load_queries = load_queries;

function query_all(cs, q, cb) {
  var search = cs.search(q);
  var matches = [];
  search.on('match', function (m) {
              matches.push(m);
            })
  search.on('done', function () {
              cb(matches)
            });
}
module.exports.query_all = query_all;
<|endoftext|>


<commit_before>/**
 * Creates a <div> that can serve as a tooltip.
 * Math and styles derived from hojberg/cssarrowplease, MIT License
 *
 */
betterlink_user_interface.createModule("FTE Tooltip", function(api, apiInternal) {
	api.requireModules( ["Util.DOM", "Drawer Reset CSS", "Event Messaging"] );

	var TOOLTIP_ID = 'betterlink-tooltip';
	var TOOLTIP_SELECTOR = "#" + TOOLTIP_ID;
	var SHOW_TOOLTIP_CLASS = 'betterlink-tooltip-show';
	var MEASURE_CLASS = 'betterlink-tooltip-measure-drawer';

	var backgroundColor = '#E9E9E9;';
	var backgroundRGB = hexToRGB(backgroundColor.replace(';',''));
	var backgroundRGBa = 'rgba(' + backgroundRGB.join(', ') + ', 0);';

	var borderColor = '#BCBCBC;';
	var borderRGB = hexToRGB(borderColor.replace(';',''));
	var borderRGBa = 'rgba(' + borderRGB.join(', ') + ', 0);';

	var borderWidth = 2;
	var arrowSize = 15; // the 'height' of the arrow from base-to-tip
	var arrowBorder = arrowSize + Math.round(borderWidth * 1.41421356); // cos(PI/4) * 2

	var tooltipCss =
		[   TOOLTIP_SELECTOR + " {",
					"background: " + backgroundColor,
					"border: " + borderWidth + "px solid " + borderColor,
					"box-shadow: 0px 8px 6px -6px rgba(0,0,0,.4);",
					"border-radius: 0;",
					"color: #424242;",
					"clear: none;",
					"font-family: Arial, sans-serif;",
					"font-size: 18px;",
					"font-weight: normal;",
					"letter-spacing: normal;",
					"line-height: normal;",
					"margin: 0;",
					"padding: 5px;",
					"text-align: left;",
					"min-width: " + (2 * (arrowSize+borderWidth)) + "px;",
					"min-height: " + (2 * (arrowSize+borderWidth)) + "px;",
					"max-width: 250px;",
					"width: auto;",
					"z-index: 2147483647;",

					"display: inline-block;",
					"position: absolute;",
					"visibility: hidden; }",

			// Arrow Definition
			TOOLTIP_SELECTOR + ":after," + TOOLTIP_SELECTOR + ":before {",
					"border: solid transparent;",
					"content: ' ';",
					"height: 0;",
					"width: 0;",
					"position: absolute;",
					"pointer-events: none; }",
			TOOLTIP_SELECTOR + ":after {",
					"border-color: " + backgroundRGBa,
					"border-width: " + arrowSize + "px; }",
			TOOLTIP_SELECTOR + ":before {",
					"border-color: " + borderRGBa,
					"border-width: " + arrowBorder + "px; }",

			// Arrow on Right
			TOOLTIP_SELECTOR + ".betterlink-right:after {",
					"left: 100%;",
					"top: 50%;",
					"margin-top: -" + arrowSize + "px;",
					"border-left-color: " + backgroundColor + " }",
			TOOLTIP_SELECTOR + ".betterlink-right:before {",
					"left: 100%;",
					"top: 50%;",
					"margin-top: -" + arrowBorder + "px;",
					"border-left-color: " + borderColor + " }",

			// Arrow on Bottom
			TOOLTIP_SELECTOR + ".betterlink-bottom:after {",
					"top: 100%;",
					"left: 50%;",
					"margin-left: -" + arrowSize + "px;",
					"border-top-color: " + backgroundColor + " }",
			TOOLTIP_SELECTOR + ".betterlink-bottom:before {",
					"top: 100%;",
					"left: 50%;",
					"margin-left: -" + arrowBorder + "px;",
					"border-top-color: " + borderColor + " }",

			// Arrow on Left
			TOOLTIP_SELECTOR + ".betterlink-left:after {",
					"right: 100%;",
					"top: 50%;",
					"margin-top: -" + arrowSize + "px;",
					"border-right-color: " + backgroundColor + " }",
			TOOLTIP_SELECTOR + ".betterlink-left:before {",
					"right: 100%;",
					"top: 50%;",
					"margin-top: -" + arrowBorder + "px;",
					"border-right-color: " + borderColor + " }",

			// Arrow on Top
			TOOLTIP_SELECTOR + ".betterlink-top { box-shadow: 0px -7px 7px -7px rgba(0,0,0,.4); }",
			TOOLTIP_SELECTOR + ".betterlink-top:after {",
					"bottom: 100%;",
					"left: 50%;",
					"margin-left: -" + arrowSize + "px;",
					"border-bottom-color: " + backgroundColor + " }",
			TOOLTIP_SELECTOR + ".betterlink-top:before {",
					"bottom: 100%;",
					"left: 50%;",
					"margin-left: -" + arrowBorder + "px;",
					"border-bottom-color: " + borderColor + " }",

			TOOLTIP_SELECTOR + "." + SHOW_TOOLTIP_CLASS + " { visibility: visible; }",

			// This class is used to get an accurate measurement of the tooltip
			// when it's placed on the DOM. It needs to be sufficiently far from
			// the end of the page for an accurate measurement.
			TOOLTIP_SELECTOR + "." + MEASURE_CLASS + " { left: -" + 100 + "px; }"
		].join(' ');

	var stylesInitialized = false;
	var tooltip;

	apiInternal.fteTooltip = {
		addTooltipToDrawer: addTooltipToDrawer,
		addTooltipToPage: addTooltipToPage,
		remove: removeTooltipFromDom
	};
	/****************************************************************************************************/

	apiInternal.events.registerObserverForRemoveBetterlink(removeTooltipFromDom);

	// If the tooltip is present in the DOM, remove it
	function removeTooltipFromDom() {
		if(tooltip.parentNode) {
			tooltip.parentNode.removeChild(tooltip);
		}
	}

	// Accepts an optional direction (right, left, top, bottom) to
	// indicate which direction the tooltip should point. If not
	// provided, the tooltip will just be a rectangle, no pointer.
	//
	// If the tooltip has already been created, this resets the content
	// and styles.
	function createTooltip(opt_direction) {
		initializeStyles();

		if(!tooltip) {
			tooltip = document.createElement('div');
			tooltip.id = TOOLTIP_ID;
		}
		else {
			removeTooltipFromDom();
			apiInternal.util.dom.removeAllChildren(tooltip);
			tooltip.className = '';
			tooltip.style.left = '';
			tooltip.style.top = '';
			tooltip.style.marginLeft = '';
			tooltip.style.marginTop = '';
		}

		if(opt_direction) {
			apiInternal.util.dom.applyClassToElement(tooltip, "betterlink-" + opt_direction);
		}

		return tooltip;
	}

	function initializeStyles() {
		if(!stylesInitialized) {
			stylesInitialized = true;

			// Writes the styles twice. Once when positioned inside of the drawer. The
			// other when positioned outside of the drawer.
			var regex = new RegExp(TOOLTIP_SELECTOR, 'g');
			apiInternal.util.dom.createAndAppendStyleElement(tooltipCss + tooltipCss.replace(regex, apiInternal.drawerSelector + TOOLTIP_SELECTOR));
		}
	}

	// Create and position the tooltip appropriately as an element
	// nested within the drawer. This means applying the 'left' and
	// 'top' attributes to get the right distances.
	//
	// This assumes that drawerElement has been appended to the DOM
	// already.
	function addTooltipToDrawer(drawerElement, tooltipContent) {
		createTooltip('right');
		apiInternal.util.dom.addOrReplaceChild(tooltip, tooltipContent);

		// Append the tooltip as the first child of the provided element.
		// This ensures that the 'top' of the tooltip will be the top of
		// the drawerElement.
		//
		// The tooltip needs to be on the DOM before checking its
		// dimensions.
		appendAsFirstChild(tooltip, drawerElement);

		apiInternal.util.dom.applyClassToElement(tooltip, MEASURE_CLASS);
		var left = arrowSize + tooltip.offsetWidth;
		tooltip.style.left = '-' + left + 'px';
		apiInternal.util.dom.removeClassFromElement(tooltip, MEASURE_CLASS);

		apiInternal.util.dom.applyClassToElement(tooltip, SHOW_TOOLTIP_CLASS);
	}

	// Create and position the tooltip appropriately as an element
	// nested within the DOM (outside of the drawer). This is likely
	// within a Betterlink-created element (like .betterlink-selected).
	//
	// This assumes that pageElement has been appended to the DOM
	// already.
	function addTooltipToPage(pageElement, tooltipContent) {
		createTooltip('bottom');
		apiInternal.util.dom.addOrReplaceChild(tooltip, tooltipContent);

		// Append the tooltip as the prior sibling of the provided element.
		// This ensures that the tooltip rests at the very beginning and
		// inline with the pageElement. This means we simply move the
		// tooltip up its full height.
		//
		// The tooltip needs to be on the DOM before checking its
		// dimensions.
		pageElement.parentNode.insertBefore(tooltip, pageElement);

		// Make sure we're not going to put the element offpage
		if(tooltip.offsetTop - arrowSize - tooltip.offsetHeight >= 0) {
			var top = tooltip.offsetHeight + arrowSize;
			tooltip.style.marginTop = '-' + top + 'px';
		}
		else {
			// If we can't position it right on top of element, then we'll
			// position it right underneath
			apiInternal.util.dom.removeClassFromElement(tooltip, "betterlink-bottom");
			apiInternal.util.dom.applyClassToElement(tooltip, "betterlink-top");

			// Move the tooltip as the last sibling of the pageElement
			removeTooltipFromDom();
			pageElement.parentNode.insertBefore(tooltip, pageElement.nextSibling);

			var approximateElementLineSize = 30;
			var horizontalOffset = 10;
			var top = arrowSize + approximateElementLineSize;
			var left = (tooltip.offsetWidth / 2) + horizontalOffset;
			tooltip.style.marginTop = top + 'px';
			tooltip.style.marginLeft = '-' + left + 'px';
		}

		apiInternal.util.dom.applyClassToElement(tooltip, SHOW_TOOLTIP_CLASS);
	}

	// Appends the newElement to the DOM as the first child of the
	// provided parentElement
	function appendAsFirstChild(newElement, parentElement) {
		if(parentElement.firstChild) {
			parentElement.insertBefore(newElement, parentElement.firstChild);
		}
		else {
			parentElement.appendChild(newElement);
		}
	}

	// Returns an array specifying an RGB color from a provided hex color
	// ex: #88b7d5 ==> [136, 183, 213]
	function hexToRGB(h) {
		if ( typeof h !== 'string' || !h.match(/^#([0-9A-F]{3}$)|([0-9A-F]{6}$)/i) ) return [0, 0, 0];
		else if ( h.match(/^(#[0-9a-f]{3})$/i) ) h = '#' + h[1] + h[1] + h[2] + h[2] + h[3] + h[3];
		var rgb = [],
			i = 1;

		for(; i < 6; i+=2) {
			rgb.push(parseInt(h.substring(i, i + 2), 16));
		}
		return rgb;
	}
});
<commit_msg>move variable declaration<commit_after>/**
 * Creates a <div> that can serve as a tooltip.
 * Math and styles derived from hojberg/cssarrowplease, MIT License
 *
 */
betterlink_user_interface.createModule("FTE Tooltip", function(api, apiInternal) {
	api.requireModules( ["Util.DOM", "Drawer Reset CSS", "Event Messaging"] );

	var TOOLTIP_ID = 'betterlink-tooltip';
	var TOOLTIP_SELECTOR = "#" + TOOLTIP_ID;
	var SHOW_TOOLTIP_CLASS = 'betterlink-tooltip-show';
	var MEASURE_CLASS = 'betterlink-tooltip-measure-drawer';

	var backgroundColor = '#E9E9E9;';
	var backgroundRGB = hexToRGB(backgroundColor.replace(';',''));
	var backgroundRGBa = 'rgba(' + backgroundRGB.join(', ') + ', 0);';

	var borderColor = '#BCBCBC;';
	var borderRGB = hexToRGB(borderColor.replace(';',''));
	var borderRGBa = 'rgba(' + borderRGB.join(', ') + ', 0);';

	var borderWidth = 2;
	var arrowSize = 15; // the 'height' of the arrow from base-to-tip
	var arrowBorder = arrowSize + Math.round(borderWidth * 1.41421356); // cos(PI/4) * 2

	var tooltipCss =
		[   TOOLTIP_SELECTOR + " {",
					"background: " + backgroundColor,
					"border: " + borderWidth + "px solid " + borderColor,
					"box-shadow: 0px 8px 6px -6px rgba(0,0,0,.4);",
					"border-radius: 0;",
					"color: #424242;",
					"clear: none;",
					"font-family: Arial, sans-serif;",
					"font-size: 18px;",
					"font-weight: normal;",
					"letter-spacing: normal;",
					"line-height: normal;",
					"margin: 0;",
					"padding: 5px;",
					"text-align: left;",
					"min-width: " + (2 * (arrowSize+borderWidth)) + "px;",
					"min-height: " + (2 * (arrowSize+borderWidth)) + "px;",
					"max-width: 250px;",
					"width: auto;",
					"z-index: 2147483647;",

					"display: inline-block;",
					"position: absolute;",
					"visibility: hidden; }",

			// Arrow Definition
			TOOLTIP_SELECTOR + ":after," + TOOLTIP_SELECTOR + ":before {",
					"border: solid transparent;",
					"content: ' ';",
					"height: 0;",
					"width: 0;",
					"position: absolute;",
					"pointer-events: none; }",
			TOOLTIP_SELECTOR + ":after {",
					"border-color: " + backgroundRGBa,
					"border-width: " + arrowSize + "px; }",
			TOOLTIP_SELECTOR + ":before {",
					"border-color: " + borderRGBa,
					"border-width: " + arrowBorder + "px; }",

			// Arrow on Right
			TOOLTIP_SELECTOR + ".betterlink-right:after {",
					"left: 100%;",
					"top: 50%;",
					"margin-top: -" + arrowSize + "px;",
					"border-left-color: " + backgroundColor + " }",
			TOOLTIP_SELECTOR + ".betterlink-right:before {",
					"left: 100%;",
					"top: 50%;",
					"margin-top: -" + arrowBorder + "px;",
					"border-left-color: " + borderColor + " }",

			// Arrow on Bottom
			TOOLTIP_SELECTOR + ".betterlink-bottom:after {",
					"top: 100%;",
					"left: 50%;",
					"margin-left: -" + arrowSize + "px;",
					"border-top-color: " + backgroundColor + " }",
			TOOLTIP_SELECTOR + ".betterlink-bottom:before {",
					"top: 100%;",
					"left: 50%;",
					"margin-left: -" + arrowBorder + "px;",
					"border-top-color: " + borderColor + " }",

			// Arrow on Left
			TOOLTIP_SELECTOR + ".betterlink-left:after {",
					"right: 100%;",
					"top: 50%;",
					"margin-top: -" + arrowSize + "px;",
					"border-right-color: " + backgroundColor + " }",
			TOOLTIP_SELECTOR + ".betterlink-left:before {",
					"right: 100%;",
					"top: 50%;",
					"margin-top: -" + arrowBorder + "px;",
					"border-right-color: " + borderColor + " }",

			// Arrow on Top
			TOOLTIP_SELECTOR + ".betterlink-top { box-shadow: 0px -7px 7px -7px rgba(0,0,0,.4); }",
			TOOLTIP_SELECTOR + ".betterlink-top:after {",
					"bottom: 100%;",
					"left: 50%;",
					"margin-left: -" + arrowSize + "px;",
					"border-bottom-color: " + backgroundColor + " }",
			TOOLTIP_SELECTOR + ".betterlink-top:before {",
					"bottom: 100%;",
					"left: 50%;",
					"margin-left: -" + arrowBorder + "px;",
					"border-bottom-color: " + borderColor + " }",

			TOOLTIP_SELECTOR + "." + SHOW_TOOLTIP_CLASS + " { visibility: visible; }",

			// This class is used to get an accurate measurement of the tooltip
			// when it's placed on the DOM. It needs to be sufficiently far from
			// the end of the page for an accurate measurement.
			TOOLTIP_SELECTOR + "." + MEASURE_CLASS + " { left: -" + 100 + "px; }"
		].join(' ');

	var stylesInitialized = false;
	var tooltip;

	apiInternal.fteTooltip = {
		addTooltipToDrawer: addTooltipToDrawer,
		addTooltipToPage: addTooltipToPage,
		remove: removeTooltipFromDom
	};
	/****************************************************************************************************/

	apiInternal.events.registerObserverForRemoveBetterlink(removeTooltipFromDom);

	// If the tooltip is present in the DOM, remove it
	function removeTooltipFromDom() {
		if(tooltip.parentNode) {
			tooltip.parentNode.removeChild(tooltip);
		}
	}

	// Accepts an optional direction (right, left, top, bottom) to
	// indicate which direction the tooltip should point. If not
	// provided, the tooltip will just be a rectangle, no pointer.
	//
	// If the tooltip has already been created, this resets the content
	// and styles.
	function createTooltip(opt_direction) {
		initializeStyles();

		if(!tooltip) {
			tooltip = document.createElement('div');
			tooltip.id = TOOLTIP_ID;
		}
		else {
			removeTooltipFromDom();
			apiInternal.util.dom.removeAllChildren(tooltip);
			tooltip.className = '';
			tooltip.style.left = '';
			tooltip.style.top = '';
			tooltip.style.marginLeft = '';
			tooltip.style.marginTop = '';
		}

		if(opt_direction) {
			apiInternal.util.dom.applyClassToElement(tooltip, "betterlink-" + opt_direction);
		}

		return tooltip;
	}

	function initializeStyles() {
		if(!stylesInitialized) {
			stylesInitialized = true;

			// Writes the styles twice. Once when positioned inside of the drawer. The
			// other when positioned outside of the drawer.
			var regex = new RegExp(TOOLTIP_SELECTOR, 'g');
			apiInternal.util.dom.createAndAppendStyleElement(tooltipCss + tooltipCss.replace(regex, apiInternal.drawerSelector + TOOLTIP_SELECTOR));
		}
	}

	// Create and position the tooltip appropriately as an element
	// nested within the drawer. This means applying the 'left' and
	// 'top' attributes to get the right distances.
	//
	// This assumes that drawerElement has been appended to the DOM
	// already.
	function addTooltipToDrawer(drawerElement, tooltipContent) {
		createTooltip('right');
		apiInternal.util.dom.addOrReplaceChild(tooltip, tooltipContent);

		// Append the tooltip as the first child of the provided element.
		// This ensures that the 'top' of the tooltip will be the top of
		// the drawerElement.
		//
		// The tooltip needs to be on the DOM before checking its
		// dimensions.
		appendAsFirstChild(tooltip, drawerElement);

		apiInternal.util.dom.applyClassToElement(tooltip, MEASURE_CLASS);
		var left = arrowSize + tooltip.offsetWidth;
		tooltip.style.left = '-' + left + 'px';
		apiInternal.util.dom.removeClassFromElement(tooltip, MEASURE_CLASS);

		apiInternal.util.dom.applyClassToElement(tooltip, SHOW_TOOLTIP_CLASS);
	}

	// Create and position the tooltip appropriately as an element
	// nested within the DOM (outside of the drawer). This is likely
	// within a Betterlink-created element (like .betterlink-selected).
	//
	// This assumes that pageElement has been appended to the DOM
	// already.
	function addTooltipToPage(pageElement, tooltipContent) {
		createTooltip('bottom');
		apiInternal.util.dom.addOrReplaceChild(tooltip, tooltipContent);

		// Append the tooltip as the prior sibling of the provided element.
		// This ensures that the tooltip rests at the very beginning and
		// inline with the pageElement. This means we simply move the
		// tooltip up its full height.
		//
		// The tooltip needs to be on the DOM before checking its
		// dimensions.
		pageElement.parentNode.insertBefore(tooltip, pageElement);

		var top, left;
		// Make sure we're not going to put the element offpage
		if(tooltip.offsetTop - arrowSize - tooltip.offsetHeight >= 0) {
			top = tooltip.offsetHeight + arrowSize;
			tooltip.style.marginTop = '-' + top + 'px';
		}
		else {
			// If we can't position it right on top of element, then we'll
			// position it right underneath
			apiInternal.util.dom.removeClassFromElement(tooltip, "betterlink-bottom");
			apiInternal.util.dom.applyClassToElement(tooltip, "betterlink-top");

			// Move the tooltip as the last sibling of the pageElement
			removeTooltipFromDom();
			pageElement.parentNode.insertBefore(tooltip, pageElement.nextSibling);

			var approximateElementLineSize = 30;
			var horizontalOffset = 10;
			top = arrowSize + approximateElementLineSize;
			left = (tooltip.offsetWidth / 2) + horizontalOffset;
			tooltip.style.marginTop = top + 'px';
			tooltip.style.marginLeft = '-' + left + 'px';
		}

		apiInternal.util.dom.applyClassToElement(tooltip, SHOW_TOOLTIP_CLASS);
	}

	// Appends the newElement to the DOM as the first child of the
	// provided parentElement
	function appendAsFirstChild(newElement, parentElement) {
		if(parentElement.firstChild) {
			parentElement.insertBefore(newElement, parentElement.firstChild);
		}
		else {
			parentElement.appendChild(newElement);
		}
	}

	// Returns an array specifying an RGB color from a provided hex color
	// ex: #88b7d5 ==> [136, 183, 213]
	function hexToRGB(h) {
		if ( typeof h !== 'string' || !h.match(/^#([0-9A-F]{3}$)|([0-9A-F]{6}$)/i) ) return [0, 0, 0];
		else if ( h.match(/^(#[0-9a-f]{3})$/i) ) h = '#' + h[1] + h[1] + h[2] + h[2] + h[3] + h[3];
		var rgb = [],
			i = 1;

		for(; i < 6; i+=2) {
			rgb.push(parseInt(h.substring(i, i + 2), 16));
		}
		return rgb;
	}
});
<|endoftext|>


<commit_before>var sys = require('sys');
global.p = sys.p;
global.puts = sys.puts;

global.couchdb = require('../lib/couchdb');
global.assert = require('assert');
global.checkCallbacks = function(callbacks) {
  for (var k in callbacks) {
    assert.ok(callbacks[k], 'Callback '+k+' fired');
  }
};

// Provide a port/host here if your local db has a non-default setup
GLOBAL.client = couchdb.createClient(undefined, undefined, undefined, undefined, 20);<commit_msg>switching this off is probably more robust for tests<commit_after>var sys = require('sys');
global.p = sys.p;
global.puts = sys.puts;

global.couchdb = require('../lib/couchdb');
global.assert = require('assert');
global.checkCallbacks = function(callbacks) {
  for (var k in callbacks) {
    assert.ok(callbacks[k], 'Callback '+k+' fired');
  }
};

// Provide a port/host here if your local db has a non-default setup
GLOBAL.client = couchdb.createClient(undefined, undefined, undefined, undefined, 0);<|endoftext|>


<commit_before>var fs = require('fs');
var assert = require('assert');
var csso = require('../lib/index.js');

describe('csso', function() {
    it('justDoIt() should works until removed', function() {
        assert.equal(
            csso.justDoIt('.foo { color: #ff0000 } .bar { color: rgb(255, 0, 0) }'),
            '.bar,.foo{color:red}'
        );
    });

    it('walk', function() {
        function visit(withInfo) {
            var visitedTypes = {};

            csso.walk(csso.parse('@media (min-width: 200px) { .foo:nth-child(2n) { color: rgb(100%, 10%, 0%); width: calc(3px + 5%) } }', 'stylesheet', withInfo), function(node) {
                visitedTypes[node[withInfo ? 1 : 0]] = true;
            }, withInfo);

            return Object.keys(visitedTypes).sort();
        }

        var shouldVisitTypes = ['stylesheet', 'atruler', 'atkeyword', 'ident', 'atrulerq', 's', 'braces', 'operator', 'dimension', 'number', 'atrulers', 'ruleset', 'selector', 'simpleselector', 'clazz', 'nthselector', 'nth', 'block', 'declaration', 'property', 'value', 'funktion', 'functionBody', 'percentage', 'decldelim', 'unary'].sort();

        assert.deepEqual(visit(), shouldVisitTypes, 'w/o info');
        assert.deepEqual(visit(true), shouldVisitTypes, 'with info');
    });

    it('strigify', function() {
        assert.equal(
            csso.stringify(csso.parse('.a\n{\rcolor:\r\nred}', 'stylesheet', true)),
            fs.readFileSync(__dirname + '/fixture/stringify.txt', 'utf-8').trim()
        );
    });
});
<commit_msg>don't show justDoIt warning on test<commit_after>var fs = require('fs');
var assert = require('assert');
var csso = require('../lib/index.js');

describe('csso', function() {
    it('justDoIt() should works until removed', function() {
        var output = [];
        var tmp = console.warn;

        try {
            console.warn = function() {
                output.push(Array.prototype.slice.call(arguments).join(' '));
            };

            assert.equal(
                csso.justDoIt('.foo { color: #ff0000 } .bar { color: rgb(255, 0, 0) }'),
                '.bar,.foo{color:red}'
            );
        } finally {
            console.warn = tmp;
        }

        assert.equal(output.length, 1);
        assert(/method is deprecated/.test(String(output[0])), 'should contains `method is deprecated`');
    });

    it('walk', function() {
        function visit(withInfo) {
            var visitedTypes = {};

            csso.walk(csso.parse('@media (min-width: 200px) { .foo:nth-child(2n) { color: rgb(100%, 10%, 0%); width: calc(3px + 5%) } }', 'stylesheet', withInfo), function(node) {
                visitedTypes[node[withInfo ? 1 : 0]] = true;
            }, withInfo);

            return Object.keys(visitedTypes).sort();
        }

        var shouldVisitTypes = ['stylesheet', 'atruler', 'atkeyword', 'ident', 'atrulerq', 's', 'braces', 'operator', 'dimension', 'number', 'atrulers', 'ruleset', 'selector', 'simpleselector', 'clazz', 'nthselector', 'nth', 'block', 'declaration', 'property', 'value', 'funktion', 'functionBody', 'percentage', 'decldelim', 'unary'].sort();

        assert.deepEqual(visit(), shouldVisitTypes, 'w/o info');
        assert.deepEqual(visit(true), shouldVisitTypes, 'with info');
    });

    it('strigify', function() {
        assert.equal(
            csso.stringify(csso.parse('.a\n{\rcolor:\r\nred}', 'stylesheet', true)),
            fs.readFileSync(__dirname + '/fixture/stringify.txt', 'utf-8').trim()
        );
    });
});
<|endoftext|>


<commit_before>/*global require, module*/
/** @jsx React.DOM */
var React = require('react'),
    Validator = require('validator'),
    easyGid = require("easy-guid"),
    _ = require('lodash');

var TextField = React.createClass({
    formNormalClasses: "form-group form-group-label",
    formNormalClassesFocus: "form-group form-group-label control-focus",
    isPointRequired: false,
    getValue: function (){
        return React.findDOMNode(this.refs.textBox).value;
    },

    getInitialState: function () {
        "use strict";
        var intialClass =  this.formNormalClasses;

        if (this.props.value !== null || this.props.value === "") {

            intialClass =  this.formNormalClasses + " control-highlight";
        }

        return {
            formClassCollection: intialClass
        };
    },

    getDefaultProps: function () {
        return { isNumeric: false };
    },

    valueChange: function(event){
        var value = this.getValue();

        if(this.props.isNumeric) {
           value = (value === "") ? 0 : value;
        }

        if(this.props.isNumeric){
            if(_.endsWith(value, '.')){
                this.isPointRequired = true;
               // value = parseInt(value).toFixed(2);
                this.props.onChange(value);
            }
            else{
                this.isPointRequired = false;
                this.props.onChange(value);
            }
        } else {
             this.props.onChange(value);
        }
    },

    allowKeypress: function(event){
        if(this.props.isNumeric === false)
            return true;

         var charCode = (event.which) ? event.which : event.keyCode;
         if (charCode != 46 && charCode > 31 && (charCode < 48 || charCode > 57))
            return false;

         return true;
    },

    onLoosingFocus: function(event){
         var value = this.getValue();
         if(value !== ""){
            this.setState({
                "formClassCollection": this.formNormalClassesFocus + " control-highlight"
            });
         }
    },

    render : function(){
	    var identifier = easyGid.new();
        var textValue = (this.isPointRequired) ? this.props.value + "." : this.props.value;
        textValue = (textValue === 0) ? "" : textValue;
        return (

                  {this.props.label}
                  <input ref="textBox" className="form-control" id={identifier} value={textValue} type="text" onBlur={this.onLoosingFocus} onChange={this.valueChange} onKeyPress={this.allowKeypress}/>

        );
    }
});

module.exports = TextField;<commit_msg>Fix for #37<commit_after>/*global require, module*/
/** @jsx React.DOM */
var React = require('react'),
    Validator = require('validator'),
    easyGid = require("easy-guid"),
    _ = require('lodash');

var TextField = React.createClass({
    formNormalClasses: "form-group form-group-label",
    formNormalClassesFocus: "form-group form-group-label control-focus",
    isPointRequired: false,
    getValue: function (){
        return React.findDOMNode(this.refs.textBox).value;
    },

    getInitialState: function () {
        "use strict";
        var intialClass =  this.formNormalClasses;

        if (this.props.value !== null || this.props.value === "") {

            intialClass =  this.formNormalClasses + " control-highlight";
        }

        return {
            formClassCollection: intialClass
        };
    },

    getDefaultProps: function () {
        return { isNumeric: false };
    },

    valueChange: function(event){
        var value = this.getValue();

        if(this.props.isNumeric) {
           value = (value === "") ? 0 : value;
        }

        if(this.props.isNumeric){
            if(_.endsWith(value, '.')){
                this.isPointRequired = true;
               // value = parseInt(value).toFixed(2);
                this.props.onChange(value);
            }
            else{
                this.isPointRequired = false;
                this.props.onChange(value);
            }
        } else {
             this.props.onChange(value);
        }
    },

    allowKeypress: function(event){
        if(this.props.isNumeric === false)
            return true;

         var charCode = (event.which) ? event.which : event.keyCode;
         if (charCode != 46 && charCode > 31 && (charCode < 48 || charCode > 57))
            return false;

         return true;
    },

    onLoosingFocus: function(event){
         var value = this.getValue();
         if(value !== ""){
            this.setState({
                "formClassCollection": this.formNormalClassesFocus + " control-highlight"
            });
         }
    },

    render : function(){
	      var identifier = easyGid.new();
        var textValue = (this.props.value === null) ? 0 : this.props.value;
        textValue = (this.isPointRequired) ? textValue + "." : textValue;
        textValue = (textValue === 0) ? "" : textValue;
        return (

                  {this.props.label}
                  <input ref="textBox" className="form-control" id={identifier} value={textValue} type="text" onBlur={this.onLoosingFocus} onChange={this.valueChange} onKeyPress={this.allowKeypress}/>

        );
    }
});

module.exports = TextField;<|endoftext|>


<commit_before>'use strict';

var h = require('react-hyperscript');
var React = require('react');
var Router = require('react-router');

var ApplicationStore = require('../../stores/application.store');

function getApplicationStats() {
  var stats = ApplicationStore.getStats();

  return stats;
}

var Dashboard = React.createClass({

  displayName: 'Dashboard',

  mixins: [Router.State, Router.Navigation],

  getInitialState: function getInitialState() {
    return {
      applicationStats: {}
    };
  },

  componentDidMount: function componentDidMount() {
    this.setState({
      applicationStats: getApplicationStats()
    });
  },

  render: function render() {
    return (
      h('div', {className: 'container'}, [
        h('div', {className: 'row'}, [
          h('section', {className: 'col-md-12'}, [
            h('div', {className: 'page__header'}, [
              h('h1', {className: 'page__title'}, 'hackathon-internal'),
              h('p', 'Internal tools for hackathons')
            ])
          ]),
          h('section', {className: 'col-md-12'}, [
            h('div', {className: 'page__body'}, [
              h('div', {className: 'row'}, [
                h('div', {className: 'col-md-4'}, [
                  h('h5', 'Applications received'),
                  h('span', this.state.applicationStats.received)
                ]),
                h('div', {className: 'col-md-4'}, [
                  h('h5', 'Applications reviewed')
                ]),
                h('div', {className: 'col-md-4'}, [
                  h('h5', 'Content')
                ])
              ])
            ])
          ])
        ])
      ])
    );
  }

});

module.exports = Dashboard;
<commit_msg>Edit home dhasboard; add tabbed layout<commit_after>'use strict';

var h = require('react-hyperscript');
var React = require('react');
var Router = require('react-router');

var ApplicationStore = require('../../stores/application.store');
var SessionStore = require('../../stores/session.store');

var tabContent = {
  APPLICATIONS: 'Applications'
};

function getApplicationStats() {
  var stats = ApplicationStore.getStats();

  return stats;
}

function getCurrentHackathon() {
  var hackathon = SessionStore.getCurrentHackathon();

  return hackathon;
}

var DashboardHome = React.createClass({

  displayName: 'DashboardHome',

  getInitialState: function getInitialState() {
    return {};
  },

  render: function render() {
    return (
      h('div', {className: 'row'}, [
        h('div', {className: 'col-md-4'}, [
          h('div', {className: 'panel panel-default'}, [
            h('div', {className: 'panel-heading'}, [
              h('h3', {className: 'panel-title'}, 'Applications')
            ]),
            h('div', {className: 'panel-body'}, [
              h('p', 'Eventual (realtime?) stats here i.e. received/reviewed, etc')
            ])
          ])
        ]),
        h('div', {className: 'col-md-4'}, [
          h('div', {className: 'panel panel-default'}, [
            h('div', {className: 'panel-heading'}, [
              h('h3', {className: 'panel-title'}, 'Metrics')
            ]),
            h('div', {className: 'panel-body'}, [
              h('p', 'Graphs')
            ])
          ])
        ]),
        h('div', {className: 'col-md-4'}, [
          h('div', {className: 'panel panel-default'}, [
            h('div', {className: 'panel-heading'}, [
              h('h3', {className: 'panel-title'}, 'Help/mentor tickets')
            ]),
            h('div', {className: 'panel-body'}, [
              h('p', 'List of current help tickets')
            ])
          ])
        ])
      ])
    );
  }

});

var Dashboard = React.createClass({

  displayName: 'Dashboard',

  mixins: [Router.State, Router.Navigation],

  getInitialState: function getInitialState() {
    return {
      activeTab: 0,
      applicationStats: {}
    };
  },

  componentWillMount: function componentWillMount() {
    var hackathon = getCurrentHackathon();
    var tabs = this._setTabs(hackathon);

    this.setState({
      currentHackathon: getCurrentHackathon(),
      tabs: tabs
    });
  },

  componentWillUnmount: function componentWillUnmount() {
    SessionStore.removeChangeListener(this._onChange);
  },

  componentDidMount: function componentDidMount() {
    this.setState({
      applicationStats: getApplicationStats()
    });

    SessionStore.addChangeListener(this._onChange);
  },

  _onChange: function _onChange() {
    var hackathon = getCurrentHackathon();
    var tabs = this._setTabs(hackathon);

    this.setState({
      currentHackathon: hackathon,
      tabs: tabs
    });
  },

  _onSelection: function _onSelection(event) {
    var target = event.target;

    console.log(target.getAttribute('data-tab'));

    this.setState({
      activeTab: Number(target.getAttribute('data-tab'))
    });
  },

  _setTabs: function _setTabs(hackathon) {
    var tabs = [{
      name: 'Dashboard'
    }];
    var hackathonTabs = [{
      name: 'Applications'
    }, {
      name: 'Emails'
    }, {
      name: 'Announcements'
    }, {
      name: 'Mentors'
    }];

    if (hackathon) {
      Array.prototype.push.apply(tabs, hackathonTabs);
    }

    return tabs;
  },

  _getNavTabs: function _getNavTabs() {
    var self = this;
    var activeTab = this.state.activeTab;

    var tabs = this.state.tabs.map(function(tab, index) {
      return h('li', {
        className: index === activeTab ? 'active' : '',
        role: 'presentation'
      }, [
        h('a', {
          className: 'hi-sudo-link',
          'aria-controls': tab.name.toLowerCase(),
          'data-toggle': 'tab',
          'data-tab': index,
          role: 'tab',
          onClick: self._onSelection,
        }, tab.name)
      ]);
    });

    return h('ul', {className: 'nav nav-tabs', role: 'tablist'}, [
      tabs
    ]);
  },

  _getContentTabs: function _getContentTabs() {
    var activeTab = this.state.activeTab;
    var tabClassname = 'tab-pane _tab-panel';

    var tabs = this.state.tabs.map(function mapContentTabs(tab, index) {
      if (index !== activeTab) {
        return;
      }
      var content;

      switch (tab.name) {
        case tabContent.APPLICATIONS:
          content = h('h5', 'Applications dashboard');
          break;

        default:
          content = h(DashboardHome);
          break;
      }

      return h('div', {
        className: index === activeTab ? tabClassname + ' active' : tabClassname,
        id: tab.name.toLowerCase(),
        role: 'tabpanel'
      }, [
        content
      ]);
    });

    return tabs;
  },

  render: function render() {
    var hackathon = this.state.currentHackathon;
    var tabs = this._getNavTabs();
    var content = this._getContentTabs();

    if (hackathon) {
      return (
        h('div', {className: 'container'}, [
          h('div', {className: 'row'}, [
            h('section', {className: 'col-md-12'}, [
              h('div', {className: 'page__header'}, [
                h('h1', {className: 'page__title'}, hackathon.season)
              ])
            ]),
            h('section', {className: 'col-md-12'}, [
              h('div', {className: 'page__body'}, [
                tabs,
                content
              ])
            ])
          ])
        ])
      );
    } else {
      return (
        h('div', {className: 'container'}, [
          h('div', {className: 'row'}, [
            h('section', {className: 'col-md-12'}, [
              h('div', {className: 'page__header'}, [
                h('h1', {className: 'page__title'}, 'hackathon-internal'),
                h('p', 'Internal tools for hackathons')
              ])
            ]),
            h('section', {className: 'col-md-12'}, [
              h('div', {className: 'page__body'}, [
                h('div', {className: 'row'}, [
                  h('div', {className: 'col-md-4'}, [
                    h('h5', 'Applications received'),
                    h('span', this.state.applicationStats.received)
                  ]),
                  h('div', {className: 'col-md-4'}, [
                    h('h5', 'Applications reviewed')
                  ]),
                  h('div', {className: 'col-md-4'}, [
                    h('h5', 'Content')
                  ])
                ])
              ])
            ])
          ])
        ])
      );
    }

  }

});

module.exports = Dashboard;
<|endoftext|>


<commit_before>(function () {
  angular
    .module("viewpoint.controllers")
    .controller("signupCtrl", signupCtrl);

  signupCtrl.$inject = ["$auth", "errorsService"];

  function signupCtrl ($auth, errorsService) {
    var vm = this;

    vm.user = {};

    vm.fieldErrors      = fieldErrors;
    vm.signupFormSubmit = signupFormSubmit;

    function signupFormSubmit (user) {
      return $auth.signup(user)
        .then(userCreated)
        .catch(userCreationFail)
        .finally(signupFormReset);
    }

    function userCreated (response) {
      console.log(response);
    }

    function userCreationFail (error) {
      console.log(error);
    }

    function signupFormReset () {
      vm.user.password = "";
      vm.user.passwordConfirmation = "";

      vm.signupForm.$setPristine();
    }

    function fieldErrors (field) {
      return errorsService.normalize(vm.signupForm, vm.user, field);
    }
  }
})();
<commit_msg>Faz o parse dos erros do servidor e integra cadastro de usuário<commit_after>(function () {
  angular
    .module("viewpoint.controllers")
    .controller("signupCtrl", signupCtrl);

  signupCtrl.$inject = ["$auth", "$state", "errorsService"];

  function signupCtrl ($auth, $state, errorsService) {
    var vm = this;

    vm.user = {};

    vm.fieldErrors      = fieldErrors;
    vm.signupFormSubmit = signupFormSubmit;

    function signupFormSubmit (user) {
      return $auth.signup({ "user": user })
        .then(userCreated)
        .catch(userCreationFail)
        .finally(signupFormReset);
    }

    function userCreated (response) {
      $auth.setToken(response.data.token);
      $state.go("dashboard");
    }

    function userCreationFail (error) {
      vm.user.errors = errorsService.parse(error.data);
    }

    function signupFormReset () {
      vm.user.password = "";
      vm.user.passwordConfirmation = "";

      vm.signupForm.$setPristine();
    }

    function fieldErrors (field) {
      return errorsService.normalize(vm.signupForm, vm.user, field);
    }
  }
})();
<|endoftext|>


<commit_before>export const SECTIONS = [
  {
    name: "Opinions",
    imageLink: null,
    description: `The Opinions section of the Spectator focuses on analyzing and dissecting important, complex,
    and relevant issues happening in our Stuyvesant community and in the world beyond.
    In each issue, a number of writers across all grades give their opinions on subjects ranging from politics to economics and from technology to culture.
    The Opinions section often includes Point-Counter-Points and spreads that reflect a diverse set of beliefs and perspectives,
    and use their stances to uncover a deeper understanding of the subject at hand.
    The overarching goal is to create engaging, substantive, and relevant content to provide a closer look at the world.`,
    quotes: [
      {
        text: `Joining the Spectator Opinions Department has been the best decision I have made freshman year here at Stuyvesant.
        Throughout the half of a year on the department, I’ve had the opportunity to share many of my opinions that I only told my close friends
        or family to a wider audience. With writing drafts and coming up with arguments, I’ve also seen myself grow as a writer, allowing me to support my
        arguments more effectively. As teenagers, it’s easy to feel like our voices do not matter as much as adults,
        but this department has allowed for many students’ voices to be recognized, and I find that very special.`,
        source: "Angela Wong"
      }
    ],
    link: "https://docs.google.com/document/d/1HJicqJ6RGqiZp6nMU3CM3ltB7wGjmgS5t9JN9o-Txms/edit"
  },
  {
    name: "Arts and Entertainment",
    imageLink: null,
    description: `We here at Arts and Entertainment department of the Spectator and we are the zestiest department in the world.  We get to write about cool stuff like music, movies, books, plays, basically anything, that makes Stuy students less soulless!!
We love everything artsy and cultural (especially like... Beyonce). We also cover major entertainment events like StuySquad, SOS, and SING! So what are you waiting for?
Apply for the Spectator Arts and Entertainment department now!!!`,
    quotes: [{
      text:`Being part of Arts and Entertainment is the best choice I ever made in my life. It is just so fun to write about things that we as human beings already enjoy. Like, it couldn't be more enjoyable than that. (Except eating Häagen-Dazs while listening to Beyonce)`,
      source: "Anonymous"
    }],
    link: "https://docs.google.com/document/d/1eRjH6mz2herbaLhgKSo1ugSxhpBPHtsjyk1_8nXrPIQ/edit"
  },
  {
    name: "Features",
    imageLink: null,
    description: `The best way to describe Features in one word is STORYTELLING.
    This is our main, essential craft. We write profiles telling the stories of interesting people
    or communities at Stuyvesant, provide more information and delve deeper into issues that News has covered,
    uncover information about specific issues at Stuy, and more. We're a very fun, creative department,
    but we also deal with hardcore investigative journalism that can actually affect change and shock people!
    If you love writing stories, digging around, and writing some hard-hitting articles, then the Features Department is the place for you.`,
    quotes: [
      {
        text: `Joining Features as a second term freshman was undeniably my best decision of that year.
        A few articles and meetings later, Features became engraved in my vocabulary.
        Where else can you interview the most wholesome people of Stuy and write a holistic article about them?
        Where I found amazing and unique editors, talented and quirky writers, Whole Foods cupcakes, and endless opportunities,
        I hope you do too. Join Features!`,
        source: "Amy Huang"
      }
    ],
    link: "https://goo.gl/forms/4Lptlm1ixxayzkZo2"
  },
  {
    name: "Humor",
    imageLink: null,
    description: `Do you want to lowkey rant about your life and roast everything?
        Would you like to have a personality glow up?
        Do you want to join a low commitment and fun Spec department?
        Join Spec Humor!
        We write funny and satirical pieces for The Spec and unlike other departments, everything we publish is libel and slander which means that you'll be in control of what everyone says!`,
    quotes: [],
    link: "https://docs.google.com/forms/d/e/1FAIpQLSd4YO5oBHIykZbmM2zx4EMPmjO0FBsP0xtvNVEygDOr1LxoJQ/viewform"
  },
  {
    name: "Sports",
    imageLink: null,
    description: `Were you following March Madness? Are you hype for the start of the MLB season? Do you know who LeBron James is?
If you answered yes (or no!) to any of those questions, the Spectator Sports department is the place for you!! We cover Stuy sports as well as non-Stuy sports topics such as whether NCAA athletes should be paid and steroid use in the MLB. `,
    quotes: [
    {
        text: "Ray hates Spec.",
        source: "Ray Jones"
      },
    ],
    link: "https://docs.google.com/forms/d/e/1FAIpQLSc138Eg8fykxT_bTGlMuknicshDJYhdGLM5bI0C2Px43mPQ3w/viewform"
  },
  {
    name: "News",
    imageLink: null,
    description: `Do you want to be a part of the best department of The Spectator? Do you want to get tight with the administration? Do you want to see your name and your articles on the front page? Do you want to find out about the coolest news at Stuy before anyone else? Do you want to report on that cool news? If so, join the Spectator News Department!!! `,
    quotes: [],
    link: "https://docs.google.com/forms/d/e/1FAIpQLScPEU9ujGzS2XjNGTx7ZNTGRjyXjnHX0t3zyYjfTRwQPofyQw/viewform"
  },
  {
    name: "Copy",
    imageLink: null,
    description: `The Copy department makes sure The Spectator is free of all grammatical errors!
    Being a part of this department means honing your grammar skills and meeting other grammar nerds. We send out articles to edit roughly every two weeks,
    and only expect members to edit one or two articles per issue.
    We are a low-commitment department and don’t have many meetings, so balancing this department and other extracurriculars won’t be a problem.`,
    quotes: [
      {
        text: `Being a part of Spec Copy is incredibly satisfying! I've always been a grammar nerd,
        so being able to use that to my advantage to help out The Spectator is absolutely a win-win situation.
        I love that it also means getting to see the various pieces before the final issue is released.
        We have some really talented writers, and being able to polish their work and contribute to such a great publication is a privilege.`,
        source: "Tasfia Bashar"
      }
    ],
    link: "https://goo.gl/forms/xvgVpZ8GLpAf1RGh1"
  },
  {
    name: "Web",
    imageLink: null,
    description: `The Web department is responsible for designing and updating The Spectator's website, www.stuyspec.com.
    Web teaches how to develop and maintain a server using Ruby on Rails, a website using Javascript and React, and other tools using modern languages like Go.
    These real-world skills are a great resume builder and provide invaluable experience in working together as a team.
    This is the perfect department for both computer programming enthusiasts and novices who want to help The Spectator continue to storm the frontier of online journalism.`,
    quotes: [
      {
        text: `Having the privilege of being a part of the Web Department was
        the highlight of my year—not only did I learn more about different
         technologies in web development and the newest frontiers of programming,
        but I also became friends with an amazing group of people!`,
        source: "Jerry Ye"
      }
    ],
    link: "https://docs.google.com/forms/d/e/1FAIpQLScAXSQmiIaiWxd9dlrxn__dDy8YquI0PD8GdTSSW8NXiJg5Gg/viewform",
  },
  {
    name: "Layout",
    imageLink: null,
    description: `A good publication should interest readers before they even pick it up and read it;
    the Layout department does just that! We are the last department that works with the newspaper and are responsible for formatting all of the articles,
    photos, art, etc. We make sure that the paper is aesthetically appealing and easy to read.
    After all, no one wants to read ugly and confusing blocks of text. With creativity and a certain magic called the InDesign,
    we present to you what you know as the Spectator. \n\nAs a staff member, you will be taught how to use InDesign and asked to critique
    the formatting of each issue as it is released.`,
    quotes: [],
    link: "https://docs.google.com/forms/d/e/1FAIpQLSejlPbzAgIuTyQCV1BD5NprAS6t2TYyY-h-5GACAe2iRMVY9A/viewform"
  },
  {
    name: "Photo",
    imageLink: null,
    description: `Photo is dedicated to providing interesting and dynamic photographs to support the articles in the Spectator.
    Typical assignments include portraits of students and teachers, photos at school events – including sports games – and shots of fun things around the city as well.
    Photography is not just support for articles though, it is journalism in its own right.
    Photo department members regularly contribute to or spearhead photo essay projects.\n\n
    The Spectator Photo department only hosts a few meetings each term, so the most work is coordinated via email.
    Photo assignments are completed on the photographer’s own schedule, so long as they are in by department deadlines.
    This department is a good fit for anyone interested in photography, whether you’re just starting out,
    or you’re an expert looking for a place to practice and refine your skills.`,
    quotes: [
      {
        text: `Being a part of Spec Photo is such a fun and rewarding experience!
        Photography is a great creative outlet and seeing your photos get published makes it so much more cool.
        Taking assignments and going to events, meetings, and clubs that you’ve never even heard of before to take photos lets you
        interact with the Stuyvesant community in a personal and unique way, you never know who you might meet.
        If there’s any way to contribute to the Spectator, I wholeheartedly say the best way is through Photo!`,
        source: "Elena Sapelyuk"
      }
    ],
    link: "https://docs.google.com/forms/d/e/1FAIpQLSfjR58yPm8-7t68PLzFo-krqVSrTNHaNBHFZrPMzKfc7ooetQ/viewform"
  },
  {
    name: "Business",
    imageLink: null,
    description: `The Business Department is the beating heart of The Spectator --
    as an independent student-run newspaper, The Spectator is able to publish thousands of copies every issue because
    of companies that place advertisements and agree to sponsorships. In order to continue this process, SpecBiz members have the responsibility
    in contacting various businesses and acquiring advertisements and sponsorships for the newspaper.
    Members are exposed to real life situations by learning proper etiquette, dealing with money, and communicating with adults in the real world.`,
    quotes: [
      {
        text: `SpecBiz opened up my passion for business and taught me valuable life assets that no other department or club in high school could provide me.
        My confidence built as I began contacting more businesses and became much more comfortable in talking to adults on the phone in a professional manner,
        meeting with business managers throughout the city, and properly formatting emails. Joining this department was a life-changer,
        and even to those who don’t have much interest in money,
        I highly encourage you to join this heartwarming family who will teach you the things that you need beyond college.`,
        source: "Stacey Xue",
      },
      {
        text: `I used to be this shy kid, afraid of talking to strangers or in front of large audiences.
        But after joining SpecBiz and networking with representatives from various types of companies,
        securing deals here and there, I’ve become the most extrovert kind of guy you can ever meet!`,
        source: "Alexander Radu"
      }
    ],
    link: "bit.ly/SpecBizFallApp"
  },
  {
    name: "Art",
    imageLink: null,
    description: `It is often difficult to read through dense blocks of text without something to rest your eyes on.
    In the Art Department, we strive to embellish the newspaper with our unique illustrations, each perfectly suited for its article.
    In a school where artistic abilities are not seen as priority, you can easily find your niche as an artist for the Spectator,
    where your art will be displayed for all of its readers to admire. The limits of your creativity have no bounds;
    you can flaunt your skills in thematic spreads, comics, or Caption Contest illustrations! We encourage the use of all media!`,
    quotes: [
      {
        text: `Why join Spec Art.. why WOULDN'T you join Spec Art?
        Imagine sitting home and drawing away, putting your talent into a drawing that will be shown to almost everyone in the school.
        Drawing for the art department has been such a fantastic experience. The club meetings are incredibly fun and relaxing as well.
        You can socialize with friends and feel free to be yourself.
        With different articles to draw for every 2 weeks, you'll find yourself challenged, but having fun at the same time.`,
        source: "Fahim Rahman"
      },
      {
        text: `Spectator Art is the best club I have joined so far. When I see my art featured in The Spectator, I feel this sense of ecstasy!
        Why doodle in your notebook when you could send it in and have everyone get to see it?
        Although I’m just a freshman, I feel like I really fit into this artistic community; the people are amazing and everyone is so supportive.
        Like every art club, there is always someone better than me, but their art serves as motivation for me to improve!
        All the drawing I do boosts my sense of confidence.
        This club is everything I can ask for.`,
        source: "Alex Lin"
      }
    ],
    link: "https://docs.google.com/forms/d/e/1FAIpQLScYHVmOOyF-bNOdSnW5eJ5CAgKaLOB06SksuJAJwJ9oO0fgww/viewform"
  }
];
<commit_msg>Fixed business app<commit_after>export const SECTIONS = [
  {
    name: "Opinions",
    imageLink: null,
    description: `The Opinions section of the Spectator focuses on analyzing and dissecting important, complex,
    and relevant issues happening in our Stuyvesant community and in the world beyond.
    In each issue, a number of writers across all grades give their opinions on subjects ranging from politics to economics and from technology to culture.
    The Opinions section often includes Point-Counter-Points and spreads that reflect a diverse set of beliefs and perspectives,
    and use their stances to uncover a deeper understanding of the subject at hand.
    The overarching goal is to create engaging, substantive, and relevant content to provide a closer look at the world.`,
    quotes: [
      {
        text: `Joining the Spectator Opinions Department has been the best decision I have made freshman year here at Stuyvesant.
        Throughout the half of a year on the department, I’ve had the opportunity to share many of my opinions that I only told my close friends
        or family to a wider audience. With writing drafts and coming up with arguments, I’ve also seen myself grow as a writer, allowing me to support my
        arguments more effectively. As teenagers, it’s easy to feel like our voices do not matter as much as adults,
        but this department has allowed for many students’ voices to be recognized, and I find that very special.`,
        source: "Angela Wong"
      }
    ],
    link: "https://docs.google.com/document/d/1HJicqJ6RGqiZp6nMU3CM3ltB7wGjmgS5t9JN9o-Txms/edit"
  },
  {
    name: "Arts and Entertainment",
    imageLink: null,
    description: `We here at Arts and Entertainment department of the Spectator and we are the zestiest department in the world.  We get to write about cool stuff like music, movies, books, plays, basically anything, that makes Stuy students less soulless!!
We love everything artsy and cultural (especially like... Beyonce). We also cover major entertainment events like StuySquad, SOS, and SING! So what are you waiting for?
Apply for the Spectator Arts and Entertainment department now!!!`,
    quotes: [{
      text:`Being part of Arts and Entertainment is the best choice I ever made in my life. It is just so fun to write about things that we as human beings already enjoy. Like, it couldn't be more enjoyable than that. (Except eating Häagen-Dazs while listening to Beyonce)`,
      source: "Anonymous"
    }],
    link: "https://docs.google.com/document/d/1eRjH6mz2herbaLhgKSo1ugSxhpBPHtsjyk1_8nXrPIQ/edit"
  },
  {
    name: "Features",
    imageLink: null,
    description: `The best way to describe Features in one word is STORYTELLING.
    This is our main, essential craft. We write profiles telling the stories of interesting people
    or communities at Stuyvesant, provide more information and delve deeper into issues that News has covered,
    uncover information about specific issues at Stuy, and more. We're a very fun, creative department,
    but we also deal with hardcore investigative journalism that can actually affect change and shock people!
    If you love writing stories, digging around, and writing some hard-hitting articles, then the Features Department is the place for you.`,
    quotes: [
      {
        text: `Joining Features as a second term freshman was undeniably my best decision of that year.
        A few articles and meetings later, Features became engraved in my vocabulary.
        Where else can you interview the most wholesome people of Stuy and write a holistic article about them?
        Where I found amazing and unique editors, talented and quirky writers, Whole Foods cupcakes, and endless opportunities,
        I hope you do too. Join Features!`,
        source: "Amy Huang"
      }
    ],
    link: "https://goo.gl/forms/4Lptlm1ixxayzkZo2"
  },
  {
    name: "Humor",
    imageLink: null,
    description: `Do you want to lowkey rant about your life and roast everything?
        Would you like to have a personality glow up?
        Do you want to join a low commitment and fun Spec department?
        Join Spec Humor!
        We write funny and satirical pieces for The Spec and unlike other departments, everything we publish is libel and slander which means that you'll be in control of what everyone says!`,
    quotes: [],
    link: "https://docs.google.com/forms/d/e/1FAIpQLSd4YO5oBHIykZbmM2zx4EMPmjO0FBsP0xtvNVEygDOr1LxoJQ/viewform"
  },
  {
    name: "Sports",
    imageLink: null,
    description: `Were you following March Madness? Are you hype for the start of the MLB season? Do you know who LeBron James is?
If you answered yes (or no!) to any of those questions, the Spectator Sports department is the place for you!! We cover Stuy sports as well as non-Stuy sports topics such as whether NCAA athletes should be paid and steroid use in the MLB. `,
    quotes: [
    {
        text: "Ray hates Spec.",
        source: "Ray Jones"
      },
    ],
    link: "https://docs.google.com/forms/d/e/1FAIpQLSc138Eg8fykxT_bTGlMuknicshDJYhdGLM5bI0C2Px43mPQ3w/viewform"
  },
  {
    name: "News",
    imageLink: null,
    description: `Do you want to be a part of the best department of The Spectator? Do you want to get tight with the administration? Do you want to see your name and your articles on the front page? Do you want to find out about the coolest news at Stuy before anyone else? Do you want to report on that cool news? If so, join the Spectator News Department!!! `,
    quotes: [],
    link: "https://docs.google.com/forms/d/e/1FAIpQLScPEU9ujGzS2XjNGTx7ZNTGRjyXjnHX0t3zyYjfTRwQPofyQw/viewform"
  },
  {
    name: "Copy",
    imageLink: null,
    description: `The Copy department makes sure The Spectator is free of all grammatical errors!
    Being a part of this department means honing your grammar skills and meeting other grammar nerds. We send out articles to edit roughly every two weeks,
    and only expect members to edit one or two articles per issue.
    We are a low-commitment department and don’t have many meetings, so balancing this department and other extracurriculars won’t be a problem.`,
    quotes: [
      {
        text: `Being a part of Spec Copy is incredibly satisfying! I've always been a grammar nerd,
        so being able to use that to my advantage to help out The Spectator is absolutely a win-win situation.
        I love that it also means getting to see the various pieces before the final issue is released.
        We have some really talented writers, and being able to polish their work and contribute to such a great publication is a privilege.`,
        source: "Tasfia Bashar"
      }
    ],
    link: "https://goo.gl/forms/xvgVpZ8GLpAf1RGh1"
  },
  {
    name: "Web",
    imageLink: null,
    description: `The Web department is responsible for designing and updating The Spectator's website, www.stuyspec.com.
    Web teaches how to develop and maintain a server using Ruby on Rails, a website using Javascript and React, and other tools using modern languages like Go.
    These real-world skills are a great resume builder and provide invaluable experience in working together as a team.
    This is the perfect department for both computer programming enthusiasts and novices who want to help The Spectator continue to storm the frontier of online journalism.`,
    quotes: [
      {
        text: `Having the privilege of being a part of the Web Department was
        the highlight of my year—not only did I learn more about different
         technologies in web development and the newest frontiers of programming,
        but I also became friends with an amazing group of people!`,
        source: "Jerry Ye"
      }
    ],
    link: "https://docs.google.com/forms/d/e/1FAIpQLScAXSQmiIaiWxd9dlrxn__dDy8YquI0PD8GdTSSW8NXiJg5Gg/viewform",
  },
  {
    name: "Layout",
    imageLink: null,
    description: `A good publication should interest readers before they even pick it up and read it;
    the Layout department does just that! We are the last department that works with the newspaper and are responsible for formatting all of the articles,
    photos, art, etc. We make sure that the paper is aesthetically appealing and easy to read.
    After all, no one wants to read ugly and confusing blocks of text. With creativity and a certain magic called the InDesign,
    we present to you what you know as the Spectator. \n\nAs a staff member, you will be taught how to use InDesign and asked to critique
    the formatting of each issue as it is released.`,
    quotes: [],
    link: "https://docs.google.com/forms/d/e/1FAIpQLSejlPbzAgIuTyQCV1BD5NprAS6t2TYyY-h-5GACAe2iRMVY9A/viewform"
  },
  {
    name: "Photo",
    imageLink: null,
    description: `Photo is dedicated to providing interesting and dynamic photographs to support the articles in the Spectator.
    Typical assignments include portraits of students and teachers, photos at school events – including sports games – and shots of fun things around the city as well.
    Photography is not just support for articles though, it is journalism in its own right.
    Photo department members regularly contribute to or spearhead photo essay projects.\n\n
    The Spectator Photo department only hosts a few meetings each term, so the most work is coordinated via email.
    Photo assignments are completed on the photographer’s own schedule, so long as they are in by department deadlines.
    This department is a good fit for anyone interested in photography, whether you’re just starting out,
    or you’re an expert looking for a place to practice and refine your skills.`,
    quotes: [
      {
        text: `Being a part of Spec Photo is such a fun and rewarding experience!
        Photography is a great creative outlet and seeing your photos get published makes it so much more cool.
        Taking assignments and going to events, meetings, and clubs that you’ve never even heard of before to take photos lets you
        interact with the Stuyvesant community in a personal and unique way, you never know who you might meet.
        If there’s any way to contribute to the Spectator, I wholeheartedly say the best way is through Photo!`,
        source: "Elena Sapelyuk"
      }
    ],
    link: "https://docs.google.com/forms/d/e/1FAIpQLSfjR58yPm8-7t68PLzFo-krqVSrTNHaNBHFZrPMzKfc7ooetQ/viewform"
  },
  {
    name: "Business",
    imageLink: null,
    description: `The Business Department is the beating heart of The Spectator --
    as an independent student-run newspaper, The Spectator is able to publish thousands of copies every issue because
    of companies that place advertisements and agree to sponsorships. In order to continue this process, SpecBiz members have the responsibility
    in contacting various businesses and acquiring advertisements and sponsorships for the newspaper.
    Members are exposed to real life situations by learning proper etiquette, dealing with money, and communicating with adults in the real world.`,
    quotes: [
      {
        text: `SpecBiz opened up my passion for business and taught me valuable life assets that no other department or club in high school could provide me.
        My confidence built as I began contacting more businesses and became much more comfortable in talking to adults on the phone in a professional manner,
        meeting with business managers throughout the city, and properly formatting emails. Joining this department was a life-changer,
        and even to those who don’t have much interest in money,
        I highly encourage you to join this heartwarming family who will teach you the things that you need beyond college.`,
        source: "Stacey Xue",
      },
      {
        text: `I used to be this shy kid, afraid of talking to strangers or in front of large audiences.
        But after joining SpecBiz and networking with representatives from various types of companies,
        securing deals here and there, I’ve become the most extrovert kind of guy you can ever meet!`,
        source: "Alexander Radu"
      }
    ],
    link: "https://bit.ly/SpecBizFallApp"
  },
  {
    name: "Art",
    imageLink: null,
    description: `It is often difficult to read through dense blocks of text without something to rest your eyes on.
    In the Art Department, we strive to embellish the newspaper with our unique illustrations, each perfectly suited for its article.
    In a school where artistic abilities are not seen as priority, you can easily find your niche as an artist for the Spectator,
    where your art will be displayed for all of its readers to admire. The limits of your creativity have no bounds;
    you can flaunt your skills in thematic spreads, comics, or Caption Contest illustrations! We encourage the use of all media!`,
    quotes: [
      {
        text: `Why join Spec Art.. why WOULDN'T you join Spec Art?
        Imagine sitting home and drawing away, putting your talent into a drawing that will be shown to almost everyone in the school.
        Drawing for the art department has been such a fantastic experience. The club meetings are incredibly fun and relaxing as well.
        You can socialize with friends and feel free to be yourself.
        With different articles to draw for every 2 weeks, you'll find yourself challenged, but having fun at the same time.`,
        source: "Fahim Rahman"
      },
      {
        text: `Spectator Art is the best club I have joined so far. When I see my art featured in The Spectator, I feel this sense of ecstasy!
        Why doodle in your notebook when you could send it in and have everyone get to see it?
        Although I’m just a freshman, I feel like I really fit into this artistic community; the people are amazing and everyone is so supportive.
        Like every art club, there is always someone better than me, but their art serves as motivation for me to improve!
        All the drawing I do boosts my sense of confidence.
        This club is everything I can ask for.`,
        source: "Alex Lin"
      }
    ],
    link: "https://docs.google.com/forms/d/e/1FAIpQLScYHVmOOyF-bNOdSnW5eJ5CAgKaLOB06SksuJAJwJ9oO0fgww/viewform"
  }
];
<|endoftext|>