<commit_before>// The MIT License (MIT)

// Typed.js | Copyright (c) 2014 Matt Boldt | www.mattboldt.com

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

! function($) {

    "use strict";

    var Typed = function(el, options) {

        // chosen element to manipulate text
        this.el = $(el);

        // options
        this.options = $.extend({}, $.fn.typed.defaults, options);

        // attribute to type into
        this.isInput = this.el.is('input');
        this.attr = this.options.attr;

        // show cursor
        this.showCursor = this.isInput ? false : this.options.showCursor;

        // text content of element
        this.elContent = this.attr ? this.el.attr(this.attr) : this.el.text()

        // html or plain text
        this.contentType = this.options.contentType;

        // typing speed
        this.typeSpeed = this.options.typeSpeed;

        // add a delay before typing starts
        this.startDelay = this.options.startDelay;

        // backspacing speed
        this.backSpeed = this.options.backSpeed;

        // amount of time to wait before backspacing
        this.backDelay = this.options.backDelay;

        // remove all written content at once and start typing from the beginning
        this.backFull = this.options.backFull;

        // input strings of text
        this.strings = this.options.strings;

        // character number position of current string
        this.strPos = 0;

        // current array position
        this.arrayPos = 0;

        // number to stop backspacing on.
        // default 0, can change depending on how many chars
        // you want to remove at the time
        this.stopNum = 0;

        // Looping logic
        this.loop = this.options.loop;
        this.loopCount = this.options.loopCount;
        this.curLoop = 0;

        // for stopping
        this.stop = false;

        // custom cursor
        this.cursorChar = this.options.cursorChar;

        // shuffle the strings
        this.shuffle = this.options.shuffle;
        // the order of strings
        this.sequence = [];

        // All systems go!
        this.build();
    };

    Typed.prototype = {

        constructor: Typed

        ,
        init: function() {
            // begin the loop w/ first current string (global self.string)
            // current string will be passed as an argument each time after this
            var self = this;
            self.timeout = setTimeout(function() {
                for (var i=0;i<self.strings.length;++i) self.sequence[i]=i;

                // shuffle the array if true
                if(self.shuffle) self.sequence = self.shuffleArray(self.sequence);

                // Start typing
                self.typewrite(self.strings[self.sequence[self.arrayPos]], self.strPos);
            }, self.startDelay);
        }

        ,
        build: function() {
            // Insert cursor
            if (this.showCursor === true) {
                this.cursor = $("" + this.cursorChar + "");
                this.el.after(this.cursor);
            }
            this.init();
        }

        // pass current string state to each function, types 1 char per call
        ,
        typewrite: function(curString, curStrPos) {
            // exit when stopped
            if (this.stop === true) {
                return;
            }

            // varying values for setTimeout during typing
            // can't be global since number changes each time loop is executed
            var humanize = Math.round(Math.random() * (100 - 30)) + this.typeSpeed;
            var self = this;

            // ------------- optional ------------- //
            // backpaces a certain string faster
            // ------------------------------------ //
            // if (self.arrayPos == 1){
            //  self.backDelay = 50;
            // }
            // else{ self.backDelay = 500; }

            // contain typing function in a timeout humanize'd delay
            self.timeout = setTimeout(function() {
                // check for an escape character before a pause value
                // format: \^\d+ .. eg: ^1000 .. should be able to print the ^ too using ^^
                // single ^ are removed from string
                var charPause = 0;
                var substr = curString.substr(curStrPos);
                if (substr.charAt(0) === '^') {
                    var skip = 1; // skip atleast 1
                    if (/^\^\d+/.test(substr)) {
                        substr = /\d+/.exec(substr)[0];
                        skip += substr.length;
                        charPause = parseInt(substr);
                    }

                    // strip out the escape character and pause value so they're not printed
                    curString = curString.substring(0, curStrPos) + curString.substring(curStrPos + skip);
                }

                if (self.contentType === 'html') {
                    // skip over html tags while typing
                    var curChar = curString.substr(curStrPos).charAt(0)
                    if (curChar === '<' || curChar === '&') {
                        var tag = '';
                        var endTag = '';
                        if (curChar === '<') {
                            endTag = '>'
                        } else {
                            endTag = ';'
                        }
                        while (curString.substr(curStrPos).charAt(0) !== endTag) {
                            tag += curString.substr(curStrPos).charAt(0);
                            curStrPos++;
                        }
                        curStrPos++;
                        tag += endTag;
                    }
                }

                // timeout for any pause after a character
                self.timeout = setTimeout(function() {
                    if (curStrPos === curString.length) {
                        // fires callback function
                        self.options.onStringTyped(self.arrayPos);

                        // is this the final string
                        if (self.arrayPos === self.strings.length - 1) {
                            // animation that occurs on the last typed string
                            self.options.callback();

                            self.curLoop++;

                            // quit if we wont loop back
                            if (self.loop === false || self.curLoop === self.loopCount)
                                return;
                        }

                        self.timeout = setTimeout(function() {
                            self.backspace(curString, curStrPos);
                        }, self.backDelay);
                    } else {

                        /* call before functions if applicable */
                        if (curStrPos === 0)
                            self.options.preStringTyped(self.arrayPos);

                        // start typing each new char into existing string
                        // curString: arg, self.el.html: original text inside element
                        var nextString = curString.substr(0, curStrPos + 1);
                        if (self.attr) {
                            self.el.attr(self.attr, nextString);
                        } else {
                            if (self.isInput) {
                                self.el.val(nextString);
                            } else if (self.contentType === 'html') {
                                self.el.html(nextString);
                            } else {
                                self.el.text(nextString);
                            }
                        }

                        // add characters one by one
                        curStrPos++;
                        // loop the function
                        self.typewrite(curString, curStrPos);
                    }
                    // end of character pause
                }, charPause);

                // humanized value for typing
            }, humanize);

        }

        ,
        backspace: function(curString, curStrPos) {
            // exit when stopped
            if (this.stop === true) {
                return;
            }

            // varying values for setTimeout during typing
            // can't be global since number changes each time loop is executed
            var humanize = Math.round(Math.random() * (100 - 30)) + this.backSpeed;
            var self = this;

            self.timeout = setTimeout(function() {

                // ----- this part is optional ----- //
                // check string array position
                // on the first string, only delete one word
                // the stopNum actually represents the amount of chars to
                // keep in the current string. In my case it's 14.
                // if (self.arrayPos == 1){
                //  self.stopNum = 14;
                // }
                //every other time, delete the whole typed string
                // else{
                //  self.stopNum = 0;
                // }

                if (self.contentType === 'html') {
                    // skip over html tags while backspacing
                    if (curString.substr(curStrPos).charAt(0) === '>') {
                        var tag = '';
                        while (curString.substr(curStrPos).charAt(0) !== '<') {
                            tag -= curString.substr(curStrPos).charAt(0);
                            curStrPos--;
                        }
                        curStrPos--;
                        tag += '<';
                    }
                }

                //if self.backFull is true, then the curStrPos is 0
                if (self.backFull === 1) {
                    curStrPos = 0;
                }

                // ----- continue important stuff ----- //
                // replace text with base text + typed characters
                var nextString = curString.substr(0, curStrPos);
                if (self.attr) {
                    self.el.attr(self.attr, nextString);
                } else {
                    if (self.isInput) {
                        self.el.val(nextString);
                    } else if (self.contentType === 'html') {
                        self.el.html(nextString);
                    } else {
                        self.el.text(nextString);
                    }
                }

                // if the number (id of character in current string) is
                // less than the stop number, keep going
                if (curStrPos > self.stopNum) {
                    // subtract characters one by one
                    curStrPos--;
                    // loop the function
                    self.backspace(curString, curStrPos);
                }
                // if the stop number has been reached, increase
                // array position to next string
                else if (curStrPos <= self.stopNum) {
                    self.arrayPos++;

                    if (self.arrayPos === self.strings.length) {
                        self.arrayPos = 0;

                        // Shuffle sequence again
                        if(self.shuffle) self.sequence = self.shuffleArray(self.sequence);

                        self.init();
                    } else
                        self.typewrite(self.strings[self.sequence[self.arrayPos]], curStrPos);
                }

                // humanized value for typing
            }, humanize);

        }
        /**
         * Shuffles the numbers in the given array.
         * @param {Array} array
         * @returns {Array}
         */
        ,shuffleArray: function(array) {
            var tmp, current, top = array.length;
            if(top) while(--top) {
                current = Math.floor(Math.random() * (top + 1));
                tmp = array[current];
                array[current] = array[top];
                array[top] = tmp;
            }
            return array;
        }

        // Start & Stop currently not working

        // , stop: function() {
        //     var self = this;

        //     self.stop = true;
        //     clearInterval(self.timeout);
        // }

        // , start: function() {
        //     var self = this;
        //     if(self.stop === false)
        //        return;

        //     this.stop = false;
        //     this.init();
        // }

        // Reset and rebuild the element
        ,
        reset: function() {
            var self = this;
            clearInterval(self.timeout);
            var id = this.el.attr('id');
            this.el.after('')
            this.el.remove();
            if (typeof this.cursor !== 'undefined') {
                this.cursor.remove();
            }
            // Send the callback
            self.options.resetCallback();
        }

    };

    $.fn.typed = function(option) {
        return this.each(function() {
            var $this = $(this),
                data = $this.data('typed'),
                options = typeof option == 'object' && option;
            if (!data) $this.data('typed', (data = new Typed(this, options)));
            if (typeof option == 'string') data[option]();
        });
    };

    $.fn.typed.defaults = {
        strings: ["These are the default values...", "You know what you should do?", "Use your own!", "Have a great day!"],
        // typing speed
        typeSpeed: 0,
        // time before typing starts
        startDelay: 0,
        // backspacing speed
        backSpeed: 0,
        // shuffle the strings
        shuffle: false,
        // time before backspacing
        backDelay: 500,
        // loop
        loop: false,
        // false = infinite
        loopCount: false,
        // show cursor
        showCursor: true,
        // character for cursor
        cursorChar: "|",
        // attribute to type (null == text)
        attr: null,
        // either html or text
        contentType: 'html',
        // call when done callback function
        callback: function() {},
        // starting callback function before each string
        preStringTyped: function() {},
        //callback for every typed string
        onStringTyped: function() {},
        // callback for reset
        resetCallback: function() {}
    };

}(window.jQuery);
<commit_msg>Add the default value for the backFull option<commit_after>// The MIT License (MIT)

// Typed.js | Copyright (c) 2014 Matt Boldt | www.mattboldt.com

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

! function($) {

    "use strict";

    var Typed = function(el, options) {

        // chosen element to manipulate text
        this.el = $(el);

        // options
        this.options = $.extend({}, $.fn.typed.defaults, options);

        // attribute to type into
        this.isInput = this.el.is('input');
        this.attr = this.options.attr;

        // show cursor
        this.showCursor = this.isInput ? false : this.options.showCursor;

        // text content of element
        this.elContent = this.attr ? this.el.attr(this.attr) : this.el.text()

        // html or plain text
        this.contentType = this.options.contentType;

        // typing speed
        this.typeSpeed = this.options.typeSpeed;

        // add a delay before typing starts
        this.startDelay = this.options.startDelay;

        // backspacing speed
        this.backSpeed = this.options.backSpeed;

        // amount of time to wait before backspacing
        this.backDelay = this.options.backDelay;

        // remove all written content at once and start typing from the beginning
        this.backFull = this.options.backFull;

        // input strings of text
        this.strings = this.options.strings;

        // character number position of current string
        this.strPos = 0;

        // current array position
        this.arrayPos = 0;

        // number to stop backspacing on.
        // default 0, can change depending on how many chars
        // you want to remove at the time
        this.stopNum = 0;

        // Looping logic
        this.loop = this.options.loop;
        this.loopCount = this.options.loopCount;
        this.curLoop = 0;

        // for stopping
        this.stop = false;

        // custom cursor
        this.cursorChar = this.options.cursorChar;

        // shuffle the strings
        this.shuffle = this.options.shuffle;
        // the order of strings
        this.sequence = [];

        // All systems go!
        this.build();
    };

    Typed.prototype = {

        constructor: Typed

        ,
        init: function() {
            // begin the loop w/ first current string (global self.string)
            // current string will be passed as an argument each time after this
            var self = this;
            self.timeout = setTimeout(function() {
                for (var i=0;i<self.strings.length;++i) self.sequence[i]=i;

                // shuffle the array if true
                if(self.shuffle) self.sequence = self.shuffleArray(self.sequence);

                // Start typing
                self.typewrite(self.strings[self.sequence[self.arrayPos]], self.strPos);
            }, self.startDelay);
        }

        ,
        build: function() {
            // Insert cursor
            if (this.showCursor === true) {
                this.cursor = $("" + this.cursorChar + "");
                this.el.after(this.cursor);
            }
            this.init();
        }

        // pass current string state to each function, types 1 char per call
        ,
        typewrite: function(curString, curStrPos) {
            // exit when stopped
            if (this.stop === true) {
                return;
            }

            // varying values for setTimeout during typing
            // can't be global since number changes each time loop is executed
            var humanize = Math.round(Math.random() * (100 - 30)) + this.typeSpeed;
            var self = this;

            // ------------- optional ------------- //
            // backpaces a certain string faster
            // ------------------------------------ //
            // if (self.arrayPos == 1){
            //  self.backDelay = 50;
            // }
            // else{ self.backDelay = 500; }

            // contain typing function in a timeout humanize'd delay
            self.timeout = setTimeout(function() {
                // check for an escape character before a pause value
                // format: \^\d+ .. eg: ^1000 .. should be able to print the ^ too using ^^
                // single ^ are removed from string
                var charPause = 0;
                var substr = curString.substr(curStrPos);
                if (substr.charAt(0) === '^') {
                    var skip = 1; // skip atleast 1
                    if (/^\^\d+/.test(substr)) {
                        substr = /\d+/.exec(substr)[0];
                        skip += substr.length;
                        charPause = parseInt(substr);
                    }

                    // strip out the escape character and pause value so they're not printed
                    curString = curString.substring(0, curStrPos) + curString.substring(curStrPos + skip);
                }

                if (self.contentType === 'html') {
                    // skip over html tags while typing
                    var curChar = curString.substr(curStrPos).charAt(0)
                    if (curChar === '<' || curChar === '&') {
                        var tag = '';
                        var endTag = '';
                        if (curChar === '<') {
                            endTag = '>'
                        } else {
                            endTag = ';'
                        }
                        while (curString.substr(curStrPos).charAt(0) !== endTag) {
                            tag += curString.substr(curStrPos).charAt(0);
                            curStrPos++;
                        }
                        curStrPos++;
                        tag += endTag;
                    }
                }

                // timeout for any pause after a character
                self.timeout = setTimeout(function() {
                    if (curStrPos === curString.length) {
                        // fires callback function
                        self.options.onStringTyped(self.arrayPos);

                        // is this the final string
                        if (self.arrayPos === self.strings.length - 1) {
                            // animation that occurs on the last typed string
                            self.options.callback();

                            self.curLoop++;

                            // quit if we wont loop back
                            if (self.loop === false || self.curLoop === self.loopCount)
                                return;
                        }

                        self.timeout = setTimeout(function() {
                            self.backspace(curString, curStrPos);
                        }, self.backDelay);
                    } else {

                        /* call before functions if applicable */
                        if (curStrPos === 0)
                            self.options.preStringTyped(self.arrayPos);

                        // start typing each new char into existing string
                        // curString: arg, self.el.html: original text inside element
                        var nextString = curString.substr(0, curStrPos + 1);
                        if (self.attr) {
                            self.el.attr(self.attr, nextString);
                        } else {
                            if (self.isInput) {
                                self.el.val(nextString);
                            } else if (self.contentType === 'html') {
                                self.el.html(nextString);
                            } else {
                                self.el.text(nextString);
                            }
                        }

                        // add characters one by one
                        curStrPos++;
                        // loop the function
                        self.typewrite(curString, curStrPos);
                    }
                    // end of character pause
                }, charPause);

                // humanized value for typing
            }, humanize);

        }

        ,
        backspace: function(curString, curStrPos) {
            // exit when stopped
            if (this.stop === true) {
                return;
            }

            // varying values for setTimeout during typing
            // can't be global since number changes each time loop is executed
            var humanize = Math.round(Math.random() * (100 - 30)) + this.backSpeed;
            var self = this;

            self.timeout = setTimeout(function() {

                // ----- this part is optional ----- //
                // check string array position
                // on the first string, only delete one word
                // the stopNum actually represents the amount of chars to
                // keep in the current string. In my case it's 14.
                // if (self.arrayPos == 1){
                //  self.stopNum = 14;
                // }
                //every other time, delete the whole typed string
                // else{
                //  self.stopNum = 0;
                // }

                if (self.contentType === 'html') {
                    // skip over html tags while backspacing
                    if (curString.substr(curStrPos).charAt(0) === '>') {
                        var tag = '';
                        while (curString.substr(curStrPos).charAt(0) !== '<') {
                            tag -= curString.substr(curStrPos).charAt(0);
                            curStrPos--;
                        }
                        curStrPos--;
                        tag += '<';
                    }
                }

                //if self.backFull is true, then the curStrPos is 0
                if (self.backFull === 1) {
                    curStrPos = 0;
                }

                // ----- continue important stuff ----- //
                // replace text with base text + typed characters
                var nextString = curString.substr(0, curStrPos);
                if (self.attr) {
                    self.el.attr(self.attr, nextString);
                } else {
                    if (self.isInput) {
                        self.el.val(nextString);
                    } else if (self.contentType === 'html') {
                        self.el.html(nextString);
                    } else {
                        self.el.text(nextString);
                    }
                }

                // if the number (id of character in current string) is
                // less than the stop number, keep going
                if (curStrPos > self.stopNum) {
                    // subtract characters one by one
                    curStrPos--;
                    // loop the function
                    self.backspace(curString, curStrPos);
                }
                // if the stop number has been reached, increase
                // array position to next string
                else if (curStrPos <= self.stopNum) {
                    self.arrayPos++;

                    if (self.arrayPos === self.strings.length) {
                        self.arrayPos = 0;

                        // Shuffle sequence again
                        if(self.shuffle) self.sequence = self.shuffleArray(self.sequence);

                        self.init();
                    } else
                        self.typewrite(self.strings[self.sequence[self.arrayPos]], curStrPos);
                }

                // humanized value for typing
            }, humanize);

        }
        /**
         * Shuffles the numbers in the given array.
         * @param {Array} array
         * @returns {Array}
         */
        ,shuffleArray: function(array) {
            var tmp, current, top = array.length;
            if(top) while(--top) {
                current = Math.floor(Math.random() * (top + 1));
                tmp = array[current];
                array[current] = array[top];
                array[top] = tmp;
            }
            return array;
        }

        // Start & Stop currently not working

        // , stop: function() {
        //     var self = this;

        //     self.stop = true;
        //     clearInterval(self.timeout);
        // }

        // , start: function() {
        //     var self = this;
        //     if(self.stop === false)
        //        return;

        //     this.stop = false;
        //     this.init();
        // }

        // Reset and rebuild the element
        ,
        reset: function() {
            var self = this;
            clearInterval(self.timeout);
            var id = this.el.attr('id');
            this.el.after('')
            this.el.remove();
            if (typeof this.cursor !== 'undefined') {
                this.cursor.remove();
            }
            // Send the callback
            self.options.resetCallback();
        }

    };

    $.fn.typed = function(option) {
        return this.each(function() {
            var $this = $(this),
                data = $this.data('typed'),
                options = typeof option == 'object' && option;
            if (!data) $this.data('typed', (data = new Typed(this, options)));
            if (typeof option == 'string') data[option]();
        });
    };

    $.fn.typed.defaults = {
        strings: ["These are the default values...", "You know what you should do?", "Use your own!", "Have a great day!"],
        // typing speed
        typeSpeed: 0,
        // time before typing starts
        startDelay: 0,
        // backspacing speed
        backSpeed: 0,
        // shuffle the strings
        shuffle: false,
        // time before backspacing
        backDelay: 500,
        // default dont delete all content at once
        backFull: 0,
        // loop
        loop: false,
        // false = infinite
        loopCount: false,
        // show cursor
        showCursor: true,
        // character for cursor
        cursorChar: "|",
        // attribute to type (null == text)
        attr: null,
        // either html or text
        contentType: 'html',
        // call when done callback function
        callback: function() {},
        // starting callback function before each string
        preStringTyped: function() {},
        //callback for every typed string
        onStringTyped: function() {},
        // callback for reset
        resetCallback: function() {}
    };

}(window.jQuery);
<|endoftext|>


<commit_before>/* Routes file for the server's API
* Author: Deepankar Malhan
*/

var AuthAPI = require('./API/AuthenticationAPI');

module.exports = function(expressApp, path) {
  // -------------------------
  // Authentication Routes
  // -------------------------
  expressApp.post('/api/auth/login', function(req, res) {
    res.set('Content-Type', 'application/json');
    console.log(`[INFO]: Login route activated, request is: ${JSON.stringify(req)}`);
    AuthAPI.login(req, function(authObj) {
      console.log(`Returned from the login function, getting ready to send back ${authObj}`);
      res.send(JSON.stringify(authObj));
    });
  });

  expressApp.post('/api/auth/register', function(req, res) {
    res.set('Content-Type', 'application/json');
    AuthAPI.register(req, function(authObj) {
      res.send(JSON.stringify(authObj));
    });
  });

  // -------------------------------------------------------------------------
  // All remaining requests return to the React App so it can handle routing
  // -------------------------------------------------------------------------
  expressApp.get('*', function(req, res) {
    res.sendFile(path.resolve(__dirname, '../client/build', 'index.html'));
    res.send('Hello World!');
  });
};
<commit_msg>Still debugging<commit_after>/* Routes file for the server's API
* Author: Deepankar Malhan
*/

var AuthAPI = require('./API/AuthenticationAPI');

module.exports = function(expressApp, path) {
  // -------------------------
  // Authentication Routes
  // -------------------------
  expressApp.post('/api/auth/login', function(req, res) {
    res.set('Content-Type', 'application/json');
    console.log(`[INFO]: Login route activated, request is: ${req.body.usernamelogin} and ${req.body.passwdlogin}`);
    AuthAPI.login(req, function(authObj) {
      console.log(`Returned from the login function, getting ready to send back ${JOSN.stringify(authObj)}`);
      res.send(JSON.stringify(authObj));
    });
  });

  expressApp.post('/api/auth/register', function(req, res) {
    res.set('Content-Type', 'application/json');
    AuthAPI.register(req, function(authObj) {
      res.send(JSON.stringify(authObj));
    });
  });

  // -------------------------------------------------------------------------
  // All remaining requests return to the React App so it can handle routing
  // -------------------------------------------------------------------------
  expressApp.get('*', function(req, res) {
    res.sendFile(path.resolve(__dirname, '../client/build', 'index.html'));
    res.send('Hello World!');
  });
};
<|endoftext|>


<commit_before><commit_msg>fix(brew): split meta into own storage<commit_after><|endoftext|>


<commit_before>var path = require('path');
var fs = require('fs');
var gh = require('gh-scrape');
var moment = require('moment');
var LOGIN_PAGE = path.join(__dirname, '..', 'public', 'pages', 'login.html');

module.exports = function(app, request, async, passport) {

    // TEST TODO might need to remove this code?
    app.get('/lol', function(req, res) {
        var name = req.user.github.username;
        var userToken = req.user.github.token;
        getFriendsList(name, userToken, function(names) {
            userData(name, names, userToken, function(results) {
                res.render('login', {data: results});
            });
        });
    });

    ///////////////////////////////////////////
    ///      Default landing page / login   ///
    ///////////////////////////////////////////
    app.get('/', isLoggedIn, function(req, res) {
        //res.sendfile('./public/pages/app.html');
        //res.render('app', {lol: 'hey'});
        var name = req.user.github.username;
        var userToken = req.user.github.token;
        // Grabs Friends List, returns array of names
        // TODO
        /*
        getFriendsList(name, userToken, function(names) {
            // Retrieves Data For Each Friend
            userData(names, names, userToken, function(results) {
                var data = {data: createModels(results)};
                res.render('app', data);
            });
        });*/
        var gitUrl = "https://api.github.com/users/"+ name +"/events?access_token="+userToken;
        var options = {
            url: gitUrl,
            headers: {
                'User-Agent': name
            }
        };
        getRequest(gitUrl, options, 1, function(userData) {
            console.log(userData);
            res.render('app', {data: userData});
            //res.send(data);
        });
    });

    //////////////////////////////////////////
    ///             AUTHENTICATION         ///
    //////////////////////////////////////////
    app.get('/auth/github', passport.authenticate('github', { scope: ['user:email']}));

    /////////////////////////////////////////
    ///             CALL BACK             ///
    /////////////////////////////////////////

    app.get('/auth/github/callback',
        passport.authenticate('github', { failureRedirect : '/'}),
        function(req, res) {
            res.redirect('/');
    });

    //////////////////////////////////////////
    ///             LOGOUT                 ///
    //////////////////////////////////////////
    app.get('/logout', function(req, res) {
        req.logout();
        res.redirect('/');
    });

    ///////////////////////////////////////////
    ///             LOGIN                   ///
    ///////////////////////////////////////////
    app.get('/login',  function(req, res) {
        res.status(200).set('Content-Type', 'text/html').sendFile(LOGIN_PAGE);
    });

    /////////////////////////////////////
    ///  Returns a single user's info ///
    /////////////////////////////////////
    app.get('/git', function(req, res) {
        var name = req.query.name;
        var gitUrl = "https://api.github.com/users/"+ name +"/events?access_token="+ght;
        var options = {
            url: gitUrl,
            headers: {
                'User-Agent': name
            }
        };
        getRequest(gitUrl, options, 1, function(gitObj) {
            res.send(gitObj);
        });
    });

    ///////////////////////////////////////
    /// Returns info of users following ///
    ///////////////////////////////////////
    app.get('/geet', isLoggedIn, function(req, res) {
        var name = req.user.github.username;
        var userToken = req.user.github.token;
        getFriendsList(name, userToken, function(names) {
            var names = names;
            getFriendsEventData(name, userToken, names, function(data){
                getFriendsProfileData(name, names, data, function(results){
                    getFriendsPersonalData(name, userToken, names, function(personalData) {
                    var userList = [];
                    // TODO create a function for this!
                    for (var i = 0; i < data.length - 1; i++) {
                        var user = {
                            contributions: results[i],
                            eventData: data[i],
                            personalData: personalData[i]
                        };
                        userList.push(user);
                    }
                    res.send(userList);
                    });
                });
            });
        });
    });

    function getFriendsEventData(name, userToken, friendsList, callback) {
        var count = 0;
        async.times(friendsList.length, function(_, next) {
            var gitUrl = 'https://api.github.com/users/'+friendsList[count]+'/events?access_token='+userToken;
            var options = {
                url: gitUrl,
                headers: {
                    'User-Agent': name
                }
            };
            count++;
            request.get(options, function(error, response, body) {
                var data = JSON.parse(body);
                var pushEventNum = findPush(data);
                var watchEventNum = findWatch(data);

                var pushEvent = data[pushEventNum];
                var watchEventNum = data[watchEventNum];
                return next(error, ({pushEvents: pushEvent, watchEvents: watchEventNum}));
            });
        }, function(err, results) {
            callback(results);
        });
    };

    function getFriendsPersonalData(name, userToken, friendsList, callback) {
        var count = 0;
        async.times(friendsList.length, function(_, next) {
            var gitUrl = 'https://api.github.com/users/'+friendsList[count]+'?access_token='+userToken;
            var options = {
                url: gitUrl,
                headers: {
                    'User-Agent': name
                }
            };
            count++;
            request.get(options, function(error, response, body) {
                var data = JSON.parse(body);
                return next(error, ({personalData: data}));
            });
        }, function(err, results) {
            callback(results);
        });
    };

    function getFriendsProfileData(name, friendsList, eventData, callback) {
        console.log(friendsList);
        var count = 0;
        async.times(friendsList.length, function(_, next) {
            var name = friendsList[count];
            var gitUrl = "https://github.com/"+friendsList[count];
            var options = {
                url: gitUrl,
                headers: {
                    'User-Agent': name
                }
            };
            count++;
            request.get(options, function(error, response, body) {
                scrapeCon(body, function(body) {
                    var data = body;
                    var total = data.total;
                    var longestStreak = data.longestStreak;
                    var currentStreak = data.currentStreak;
                    var contributions = {totals: total, longestStreaks: longestStreak, currentStreaks: currentStreak};

                    return next(null, contributions);
                });
            });
        }, function(err, results) {
            callback(results);
        });
    };

    function createModels(data) {
        var userArray = [];
        for(var i in data) {
            if(data[i].pushEvents ) {
                var gitUser = {
                    imgUrl: data[i].pushEvents.actor.avatar_url,
                    user: data[i].pushEvents.actor.login,
                    userID: data[i].pushEvents.actor.login.toLowerCase(),
                    repoName: data[i].pushEvents.repo.name,
                    commitMsg: data[i].pushEvents.payload.commits[0].message,
                    commitSha: data[i].pushEvents.payload.commits[0].sha.slice(0,5),
                    commitUrl: 'http://github.com/'+data[i].pushEvents.repo.name+'/commit/'+data[i].pushEvents.payload.commits[0].sha,
                    date: "Last pushed "+moment(data[i].pushEvents.created_at).fromNow(),
                    dateString: data[i].pushEvents.created_at
                };
                if(data[i].watchEvents) {
                    gitUser.watch = data[i].watchEvents.repo.name;
                    gitUser.watchUrl = 'http://www.github.com/'+data[i].watchEvents.repo.name;
                };
                userArray.push(gitUser);
            }
        }
        return userArray;
    };

    function userData(name, names, userToken, callback) {
        var count = 0;
        async.times(names.length, function(_, next) {
            var gitUrl = 'https://api.github.com/users/'+names[count]+'/events?access_token='+userToken;
            var options = {
                url: gitUrl,
                headers: {
                    'User-Agent': name
                }
            };
            count++;
            request.get(options, function(error, response, body) {
                var data = JSON.parse(body);
                var pushEventNum = findPush(data);
                var watchEventNum = findWatch(data);

                var pushEvent = data[pushEventNum];
                var watchEventNum = data[watchEventNum];
                return next(error, ({pushEvents: pushEvent, watchEvents: watchEventNum}));
            });
        }, function(err, results) {
            //console.log(results);
            callback(results);
        });
    };

    function getFriendsList(name, userToken, callback) {
        var page = 1;
        var done = false;
        var names = [];
        async.whilst(
            function () { return done === false },
            function (next) {
                var gitUrl = 'https://api.github.com/users/'+ name +"/following?access_token="+userToken+'&page='+page;
                var options = {
                    url: gitUrl,
                    headers: {
                        'User-Agent': name
                    }
                };
                request.get(options, function(error, response, body) {
                    var data = JSON.parse(body);
                    for (i in data) {
                        names.push(data[i].login);
                    }
                    if (data.length > 0) {
                        console.log("Data is NOT empty");
                        page++;

                    } else {
                        done = true;
                    }
                        return next(error, ({friends: names}));
                });
            },
            function (err) {
                callback(names);
            });
    };

    function getRequest(url, options, page, callback) {
        request.get(options,  function(error, response, body){
            if(!error) {
                var data = JSON.parse(body);
                var count = 0;
                var found = false;
                while(found != true && count < data.length) {
                    if(data[count].type == "PushEvent") {
                        found = true;
                        break;
                    }
                    count++;
                }
                callback(data[count]);
            }
            return error;
        });
    };

    // TODO This is a fucked function remove
    function getRequest2(gitUrl, callback) {
    var options = {
        url: gitUrl
    };
    request.get(options, function(error, response, body){
        if(!error) {
            callback(body);
        }
        return error;
    });
};

    function isLoggedIn(req, res, next) {
        if (req.isAuthenticated()) {
            return next();
        }
        res.redirect('/login');
    };

    function findPush(data) {
        var count = 0;
        var found = false;
        while(found != true && count < data.length) {
            if(data[count].type == "PushEvent") {
                found = true;
                break;
            }
            count++;
        }
        return count;
    };

    function findWatch(data) {
        var count = 0;
        var found = false;
        while(found != true && count < data.length) {
            if(data[count].type == "WatchEvent") {
                found = true;
                break;
            }
            count++;
        }
        return count;
    };

function scrapeCon(html, callback) {
    console.log("made it to the begining");
    var user = {},
        j = 0,
        z = 0,
        index = 0,
        character = '',
        word = "",
        found = false,
        len = html.length - 1;

    for (i = 0; i < len; i++) {
        // Loop over every char on the page
        character = html[i];
        // Finding Contributions in the last year
        if (character === 'C') {
            index = i + 30;
            word = html.slice(i, index);
            // Contributions in the last year
            if (word === "Contributions in the last year") {
                j = i + 30;
                found = false;
                while (j < len && !found) {
                    character = html[j];
                    if (character === 'c') {
                        word = html.slice(j, j + 14);
                        if (word === "contrib-number") {
                            found = true;
                            word = "";
                            z = j + 16;
                            character = html[z];
                            while (character != '<') {
                                word += character;
                                z++;
                                character = html[z];
                            }
                            user.total = word;
                            //console.log("total = ", user.total);
                        }
                    }
                    j++;
                }
            }
            index = i + 14;
            word = html.slice(i, index);
            if (word === "Current streak") {
                j = i + 14;
                found = false;
                while (j < len && !found) {
                    character = html[j];
                    if (character === 'c') {
                        word = html.slice(j, j +14);
                        if (word === "contrib-number") {
                            found = true;
                            word = "";
                            z = j + 16;
                            character = html[z];
                            while (character != '<') {
                                word += character;
                                z++;
                                character = html[z];
                            }
                            user.currentStreak = word;
                            //console.log("Current streak = ", user.currentStreak);
                        }
                    }
                    j++;
                }
            }
        }
        // Finding Longest Streak
        if (character === 'L') {
            index = i + 14;
            word = html.slice(i, index);
            if (word === 'Longest streak') {
                j = i + 15;
                found = false;
                while (j < len && !found) {
                    character = html[j];
                    if (character === 'c') {
                        word = html.slice(j, j +14);
                        if (word === "contrib-number") {
                            found = true;
                            word = "";
                            z = j + 16;
                            character = html[z];
                            while (character != '<') {
                                word += character;
                                z++;
                                character = html[z];
                            }
                            user.longestStreak = word;
                            //console.log("Longest Streak = ", user.streak);
                        }
                    }
                    j++;
                }
            }
        }
    }
    callback(user);
};

};
<commit_msg>changed request made before sending response<commit_after>var path = require('path');
var fs = require('fs');
var gh = require('gh-scrape');
var moment = require('moment');
var LOGIN_PAGE = path.join(__dirname, '..', 'public', 'pages', 'login.html');

module.exports = function(app, request, async, passport) {

    // TEST TODO might need to remove this code?
    app.get('/lol', function(req, res) {
        var name = req.user.github.username;
        var userToken = req.user.github.token;
        getFriendsList(name, userToken, function(names) {
            userData(name, names, userToken, function(results) {
                res.render('login', {data: results});
            });
        });
    });

    ///////////////////////////////////////////
    ///      Default landing page / login   ///
    ///////////////////////////////////////////
    app.get('/', isLoggedIn, function(req, res) {
        //res.sendfile('./public/pages/app.html');
        //res.render('app', {lol: 'hey'});
        var name = req.user.github.username;
        var userToken = req.user.github.token;
        // Grabs Friends List, returns array of names
        // TODO
        /*
        getFriendsList(name, userToken, function(names) {
            // Retrieves Data For Each Friend
            userData(names, names, userToken, function(results) {
                var data = {data: createModels(results)};
                res.render('app', data);
            });
        });*/
        var gitUrl = "https://api.github.com/user?access_token="+userToken;
        var options = {
            url: gitUrl,
            headers: {
                'User-Agent': name
            }
        };
        request.get(options, function(error, response, userData) {
            if (!error) {
                res.render('app', {data: JSON.parse(userData)});
            }
        });
    });

    //////////////////////////////////////////
    ///             AUTHENTICATION         ///
    //////////////////////////////////////////
    app.get('/auth/github', passport.authenticate('github', { scope: ['user:email']}));

    /////////////////////////////////////////
    ///             CALL BACK             ///
    /////////////////////////////////////////

    app.get('/auth/github/callback',
        passport.authenticate('github', { failureRedirect : '/'}),
        function(req, res) {
            res.redirect('/');
    });

    //////////////////////////////////////////
    ///             LOGOUT                 ///
    //////////////////////////////////////////
    app.get('/logout', function(req, res) {
        req.logout();
        res.redirect('/');
    });

    ///////////////////////////////////////////
    ///             LOGIN                   ///
    ///////////////////////////////////////////
    app.get('/login',  function(req, res) {
        res.status(200).set('Content-Type', 'text/html').sendFile(LOGIN_PAGE);
    });

    /////////////////////////////////////
    ///  Returns a single user's info ///
    /////////////////////////////////////
    app.get('/git', function(req, res) {
        var name = req.query.name;
        var gitUrl = "https://api.github.com/users/"+ name +"/events?access_token="+ght;
        var options = {
            url: gitUrl,
            headers: {
                'User-Agent': name
            }
        };
        getRequest(gitUrl, options, 1, function(gitObj) {
            res.send(gitObj);
        });
    });

    ///////////////////////////////////////
    /// Returns info of users following ///
    ///////////////////////////////////////
    app.get('/geet', isLoggedIn, function(req, res) {
        var name = req.user.github.username;
        var userToken = req.user.github.token;
        getFriendsList(name, userToken, function(names) {
            var names = names;
            getFriendsEventData(name, userToken, names, function(data){
                getFriendsProfileData(name, names, data, function(results){
                    getFriendsPersonalData(name, userToken, names, function(personalData) {
                    var userList = [];
                    // TODO create a function for this!
                    for (var i = 0; i < data.length - 1; i++) {
                        var user = {
                            contributions: results[i],
                            eventData: data[i],
                            personalData: personalData[i]
                        };
                        userList.push(user);
                    }
                    res.send(userList);
                    });
                });
            });
        });
    });

    function getFriendsEventData(name, userToken, friendsList, callback) {
        var count = 0;
        async.times(friendsList.length, function(_, next) {
            var gitUrl = 'https://api.github.com/users/'+friendsList[count]+'/events?access_token='+userToken;
            var options = {
                url: gitUrl,
                headers: {
                    'User-Agent': name
                }
            };
            count++;
            request.get(options, function(error, response, body) {
                var data = JSON.parse(body);
                var pushEventNum = findPush(data);
                var watchEventNum = findWatch(data);

                var pushEvent = data[pushEventNum];
                var watchEventNum = data[watchEventNum];
                return next(error, ({pushEvents: pushEvent, watchEvents: watchEventNum}));
            });
        }, function(err, results) {
            callback(results);
        });
    };

    function getFriendsPersonalData(name, userToken, friendsList, callback) {
        var count = 0;
        async.times(friendsList.length, function(_, next) {
            var gitUrl = 'https://api.github.com/users/'+friendsList[count]+'?access_token='+userToken;
            var options = {
                url: gitUrl,
                headers: {
                    'User-Agent': name
                }
            };
            count++;
            request.get(options, function(error, response, body) {
                var data = JSON.parse(body);
                return next(error, ({personalData: data}));
            });
        }, function(err, results) {
            callback(results);
        });
    };

    function getFriendsProfileData(name, friendsList, eventData, callback) {
        console.log(friendsList);
        var count = 0;
        async.times(friendsList.length, function(_, next) {
            var name = friendsList[count];
            var gitUrl = "https://github.com/"+friendsList[count];
            var options = {
                url: gitUrl,
                headers: {
                    'User-Agent': name
                }
            };
            count++;
            request.get(options, function(error, response, body) {
                scrapeCon(body, function(body) {
                    var data = body;
                    var total = data.total;
                    var longestStreak = data.longestStreak;
                    var currentStreak = data.currentStreak;
                    var contributions = {totals: total, longestStreaks: longestStreak, currentStreaks: currentStreak};

                    return next(null, contributions);
                });
            });
        }, function(err, results) {
            callback(results);
        });
    };

    function createModels(data) {
        var userArray = [];
        for(var i in data) {
            if(data[i].pushEvents ) {
                var gitUser = {
                    imgUrl: data[i].pushEvents.actor.avatar_url,
                    user: data[i].pushEvents.actor.login,
                    userID: data[i].pushEvents.actor.login.toLowerCase(),
                    repoName: data[i].pushEvents.repo.name,
                    commitMsg: data[i].pushEvents.payload.commits[0].message,
                    commitSha: data[i].pushEvents.payload.commits[0].sha.slice(0,5),
                    commitUrl: 'http://github.com/'+data[i].pushEvents.repo.name+'/commit/'+data[i].pushEvents.payload.commits[0].sha,
                    date: "Last pushed "+moment(data[i].pushEvents.created_at).fromNow(),
                    dateString: data[i].pushEvents.created_at
                };
                if(data[i].watchEvents) {
                    gitUser.watch = data[i].watchEvents.repo.name;
                    gitUser.watchUrl = 'http://www.github.com/'+data[i].watchEvents.repo.name;
                };
                userArray.push(gitUser);
            }
        }
        return userArray;
    };

    function userData(name, names, userToken, callback) {
        var count = 0;
        async.times(names.length, function(_, next) {
            var gitUrl = 'https://api.github.com/users/'+names[count]+'/events?access_token='+userToken;
            var options = {
                url: gitUrl,
                headers: {
                    'User-Agent': name
                }
            };
            count++;
            request.get(options, function(error, response, body) {
                var data = JSON.parse(body);
                var pushEventNum = findPush(data);
                var watchEventNum = findWatch(data);

                var pushEvent = data[pushEventNum];
                var watchEventNum = data[watchEventNum];
                return next(error, ({pushEvents: pushEvent, watchEvents: watchEventNum}));
            });
        }, function(err, results) {
            //console.log(results);
            callback(results);
        });
    };

    function getFriendsList(name, userToken, callback) {
        var page = 1;
        var done = false;
        var names = [];
        async.whilst(
            function () { return done === false },
            function (next) {
                var gitUrl = 'https://api.github.com/users/'+ name +"/following?access_token="+userToken+'&page='+page;
                var options = {
                    url: gitUrl,
                    headers: {
                        'User-Agent': name
                    }
                };
                request.get(options, function(error, response, body) {
                    var data = JSON.parse(body);
                    for (i in data) {
                        names.push(data[i].login);
                    }
                    if (data.length > 0) {
                        console.log("Data is NOT empty");
                        page++;

                    } else {
                        done = true;
                    }
                        return next(error, ({friends: names}));
                });
            },
            function (err) {
                callback(names);
            });
    };

    function getRequest(url, options, page, callback) {
        request.get(options,  function(error, response, body){
            if(!error) {
                var data = JSON.parse(body);
                var count = 0;
                var found = false;
                while(found != true && count < data.length) {
                    if(data[count].type == "PushEvent") {
                        found = true;
                        break;
                    }
                    count++;
                }
                callback(data[count]);
            }
            return error;
        });
    };

    // TODO This is a fucked function remove
    function getRequest2(gitUrl, callback) {
    var options = {
        url: gitUrl
    };
    request.get(options, function(error, response, body){
        if(!error) {
            callback(body);
        }
        return error;
    });
};

    function isLoggedIn(req, res, next) {
        if (req.isAuthenticated()) {
            return next();
        }
        res.redirect('/login');
    };

    function findPush(data) {
        var count = 0;
        var found = false;
        while(found != true && count < data.length) {
            if(data[count].type == "PushEvent") {
                found = true;
                break;
            }
            count++;
        }
        return count;
    };

    function findWatch(data) {
        var count = 0;
        var found = false;
        while(found != true && count < data.length) {
            if(data[count].type == "WatchEvent") {
                found = true;
                break;
            }
            count++;
        }
        return count;
    };

function scrapeCon(html, callback) {
    console.log("made it to the begining");
    var user = {},
        j = 0,
        z = 0,
        index = 0,
        character = '',
        word = "",
        found = false,
        len = html.length - 1;

    for (i = 0; i < len; i++) {
        // Loop over every char on the page
        character = html[i];
        // Finding Contributions in the last year
        if (character === 'C') {
            index = i + 30;
            word = html.slice(i, index);
            // Contributions in the last year
            if (word === "Contributions in the last year") {
                j = i + 30;
                found = false;
                while (j < len && !found) {
                    character = html[j];
                    if (character === 'c') {
                        word = html.slice(j, j + 14);
                        if (word === "contrib-number") {
                            found = true;
                            word = "";
                            z = j + 16;
                            character = html[z];
                            while (character != '<') {
                                word += character;
                                z++;
                                character = html[z];
                            }
                            user.total = word;
                            //console.log("total = ", user.total);
                        }
                    }
                    j++;
                }
            }
            index = i + 14;
            word = html.slice(i, index);
            if (word === "Current streak") {
                j = i + 14;
                found = false;
                while (j < len && !found) {
                    character = html[j];
                    if (character === 'c') {
                        word = html.slice(j, j +14);
                        if (word === "contrib-number") {
                            found = true;
                            word = "";
                            z = j + 16;
                            character = html[z];
                            while (character != '<') {
                                word += character;
                                z++;
                                character = html[z];
                            }
                            user.currentStreak = word;
                            //console.log("Current streak = ", user.currentStreak);
                        }
                    }
                    j++;
                }
            }
        }
        // Finding Longest Streak
        if (character === 'L') {
            index = i + 14;
            word = html.slice(i, index);
            if (word === 'Longest streak') {
                j = i + 15;
                found = false;
                while (j < len && !found) {
                    character = html[j];
                    if (character === 'c') {
                        word = html.slice(j, j +14);
                        if (word === "contrib-number") {
                            found = true;
                            word = "";
                            z = j + 16;
                            character = html[z];
                            while (character != '<') {
                                word += character;
                                z++;
                                character = html[z];
                            }
                            user.longestStreak = word;
                            //console.log("Longest Streak = ", user.streak);
                        }
                    }
                    j++;
                }
            }
        }
    }
    callback(user);
};

};
<|endoftext|>


<commit_before>/*
 * hadtodo is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * hadtodo is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with hadtodo.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * All routes used by the server
 */

'use strict';

/**
 * routes singleton definition
 * @typedef {{}} Routes
 */
var routes = {};
/**
 * Initializes routes used by the server
 * @param {Hapi.Server} server A Hapi.js Server
 */
routes.setup = function setupRoutes (server) {
    // Test route
    server.route({
        method: 'GET',
        path: '/test',
        handler: handlers.testHandler
    });
};

/**
 * All handlers used by the requests router
 * @type {object}
 */
var handlers = {};
/**
 * The test request handler
 */
handlers.testHandler = function testHandler (request, reply) {
    var output = {
        message: "This is a test of Hapi.js server."
    };
    reply(output);
};

module.exports = routes;
<commit_msg>routes: Rename handlers<commit_after>/*
 * hadtodo is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * hadtodo is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with hadtodo.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * All routes used by the server
 */

'use strict';

/**
 * routes singleton definition
 * @typedef {{}} Routes
 */
var routes = {};
/**
 * Initializes routes used by the server
 * @param {Hapi.Server} server A Hapi.js Server
 */
routes.setup = function setupRoutes (server) {
    // Test route
    server.route({
        method: 'GET',
        path: '/test',
        handler: handlers.test
    });
};

/**
 * All handlers used by the requests router
 * @type {object}
 */
var handlers = {};
/**
 * The test request handler
 */
handlers.testHandler = function testHandler (request, reply) {
    var output = {
        message: "This is a test of Hapi.js server."
    };
    reply(output);
};

module.exports = routes;
<|endoftext|>


<commit_before>/*
 jQuery Markdown editor
 derived from https://github.com/digitalnature/MarkdownEditor
 and https://github.com/jamiebicknell/Markdown-Helper
*/

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

$.ajaxSetup({
    beforeSend: function (xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            var csrftoken = getCookie('csrftoken');
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});

function toLines(text, selection) {
    let lines = text.split('\n');
    let pos = 0;
    let start = null
    let end = null
    for (var line = 0; line < length(lines); line++) {
        if (start === null && pos + length(lines[line]) >= selection.start) {
            start = {line: line, pos: selection.start - pos}
        }
        if (pos + length(lines[line]) >= selection.end) {
            end = {line: line, pos: selection.end - pos}
            break;
        }
        pos = pos + length(lines[line]) + 1  // re-add the "/n" chars that
    }

    return {lines: lines, selection: {start: start, end: end}};
}

function length(str) {
    return str.length;
}

(function ($, window, document, undefined) {
    $.fn.MarkdownEditor = function (isFull) {

        var adjustOffset = function (input, offset) {
                let val = input.value, newOffset = offset;

                // adjust starting offset, because some browsers (like Opera) treat new lines as two characters (\r\n) instead of one character (\n)
                if (val.indexOf("\r\n") > -1) {
                    let matches = val.replace(/\r\n/g, "\n").slice(0, offset).match(/\n/g);
                    newOffset += matches ? matches.length : 0;
                }

                return newOffset;
            },

            // creates a selection inside the textarea
            // if selectionStart = selectionEnd the cursor is set to that point
            setCaretToPos = function (input, selectionStart, selectionEnd) {
                input.focus();

                if (input.setSelectionRange) {
                    input.setSelectionRange(adjustOffset(input, selectionStart), adjustOffset(input, selectionEnd));

                    // ie
                } else if (input.createTextRange) {
                    let range = input.createTextRange();
                    range.collapse(true);
                    range.moveEnd('character', selectionEnd);
                    range.moveStart('character', selectionStart);
                    range.select();
                }
            },

            tags = {
                bold: {
                    start: '**', end: '**', placeholder: 'Your bold text',
                    line: false, block: false
                },
                strike: {
                    start: '~~', end: '~~', placeholder: 'Your struckthrough text',
                    line: false, block: false
                },
                italic: {
                    start: '*', end: '*', placeholder: 'Your emphasized text',
                    line: false, block: false
                },
                head: {
                    start: '#', end: '', placeholder: 'Your header',
                    line: true, block: false
                },
                quote: {
                    start: '> ', end: '', placeholder: 'Your quote',
                    line: true, block: false
                },
                link: {
                    start: '[', end: '](https://example.org/)', placeholder: 'Add your link text',
                    line: false, block: false
                },
                image: {
                    start: '![', end: '](https://example.org/)', placeholder: 'Add image description',
                    line: false, block: false
                },
                code: {
                    start: '`', end: '`', placeholder: 'Add inline code here',
                    line: false, block: false
                },
                pre: {
                    start: '    ', end: '', placeholder: 'Block Code',
                    line: true, block: true
                },
                ul: {
                    start: '* ', end: '', placeholder: 'List Item',
                    line: true, block: true
                },
                ol: {
                    start: '1. ', end: '', placeholder: 'List Item',
                    line: true, block: true
                },
            };

        return this.each(function () {
            let txt = this,                          // textarea element
                stale = true,
                endpoint = $(this).data("endpoint") || "/api/md_preview/",
                controls = $('
'); // button container

            const format_classes = "btn btn-light";
            const button_template = '<button type="button" data-toggle="tooltip" data-placement="bottom" title="';
            var md_toolbar = '
'
                + '
'
                + button_template + 'Bold" class="' + format_classes + ' c-bold"></button>'
                + button_template + 'Italic" class="' + format_classes + ' c-italic"></button>'
                + button_template + 'Strikethrough" class="' + format_classes + ' c-strike"></button>'
                + button_template + 'Code" class="' + format_classes + ' c-code"></button>'
                + button_template + 'Heading" class="' + format_classes + ' c-head"></button>'
                + button_template + 'Quote" class="' + format_classes + ' c-quote"></button>'

                + '

'
                + button_template + 'Link" class="' + format_classes + ' c-link"></button>'
                + button_template + 'Image" class="' + format_classes + ' c-image"></button>'

                + '

'
                + button_template + 'Bullet List" class="' + format_classes + ' c-ul"></button>'
                + button_template + 'Ordered List" class="' + format_classes + ' c-ol"></button>'

                + '

'
                + button_template + 'Preview" class="' + format_classes + ' c-preview"></button>'
                + '
'
                + '
'

            if (!isFull) md_toolbar += '

'

            $(txt).before(controls.append(md_toolbar));
            if (!isFull) controls.find('.preview').slideUp();
            $(txt).on('keydown', function (event) {
                controls.find('.card').addClass("text-muted");
                controls.find('.fa-eye-slash').removeClass('fa-eye-slash').addClass('fa-eye');
                stale = true;
                return MarkdownHelper(txt, event);
            });

            $('button', controls).on('click', function (event) {
                event.preventDefault();
                txt.focus();

                let tagName = this.className.substr(format_classes.length + 3),
                    range = {start: txt.selectionStart, end: txt.selectionEnd};
                let tag = tags[tagName]

                if (tagName === "preview") {
                    if (stale) {
                        stale = false;
                        controls.find('.fa-eye').removeClass('fa-eye').addClass('fa-eye-slash');
                        var previewSource = controls;
                        if (isFull) previewSource = $('.full-preview');
                        createPreview(txt, previewSource, endpoint);
                    } else {
                        controls.find('.preview').slideUp();
                        controls.find('.fa-eye-slash').removeClass('fa-eye-slash').addClass('fa-eye');
                        stale = true;
                    }
                    return true;
                }
                let a = toLines(txt.value, range);
                let lines = a.lines;
                let selection = a.selection;

                if (tag === tags.code && selection.start.line !== selection.end.line) {
                    tag = tags.pre;  // Code button changes behaviour in multi-line mode
                }

                let start_delta = 0, end_delta = 0;
                if (tag.line) {
                    if (selection.start.line === selection.end.line && lines[selection.start.line] === "") {

                        lines[selection.start.line] = tag.start + tag.placeholder + tag.end;
                        end_delta += length(lines[selection.start.line]);
                    } else {
                        start_delta += length(tag.start);
                        for (let i = selection.start.line; i <= selection.end.line; i++) {
                            lines[i] = tag.start + lines[i] + tag.end;
                            end_delta += length(tag.start);
                        }
                    }
                } else {
                    if (range.start !== range.end) {
                        lines[selection.end.line] = lines[selection.end.line].substring(0, selection.end.pos) + tag.end + lines[selection.end.line].substring(selection.end.pos);
                        lines[selection.start.line] = lines[selection.start.line].substring(0, selection.start.pos) + tag.start + lines[selection.start.line].substring(selection.start.pos);
                        start_delta += length(tag.start);
                        end_delta += length(tag.start);
                    } else {
                        lines[selection.start.line] = lines[selection.start.line].substring(0, selection.start.pos) + tag.start + tag.placeholder + tag.end + lines[selection.start.line].substring(selection.start.pos);
                        start_delta += length(tag.start);
                        end_delta += length(tag.start + tag.placeholder);
                    }
                }

                if (tag.block && (selection.start.line - 1) >= 0 && lines[selection.start.line - 1] !== "") {
                    lines[selection.start.line] = "\n" + lines[selection.start.line];
                    start_delta += 1;
                }
                if (tag.block && (selection.end.line + 1) <= lines.length && lines[selection.end.line + 1] !== "") {
                    lines[selection.end.line] = lines[selection.end.line] + "\n";
                }
                txt.value = lines.join("\n");
                setCaretToPos(txt, range.start + start_delta, range.end + end_delta);

                stale=true;
                controls.find('.card').addClass("text-muted");
                controls.find('.fa-eye-slash').removeClass('fa-eye-slash').addClass('fa-eye');

                return true;
            });

        });

    };

})(jQuery, window, document);

function createPreview(txt, controls, endpoint) {
    $.post(endpoint, {'md': txt.value}, function (data, status, jqXHR) {
        controls.find('.preview').html(data).slideDown();
    });
}

function MarkdownHelper(block, event) {
    let check, input, start, range, lines, state, value, first, prior, label, begin, width, caret;
    if (event.keyCode === 13) {
        check = false;
        input = block.value.replace(/\r\n/g, '\n');
        if (block.selectionStart) {
            start = block.selectionStart;
        } else {
            block.focus();
            range = document.selection.createRange();
            range.moveStart('character', -input.length);
            start = range.text.replace(/\r\n/g, '\n').length;
        }
        lines = input.split('\n');
        state = input.substr(0, start).split('\n').length;
        value = lines[state - 1].replace(/^\s+/, '');
        first = value.substr(0, 2);
        if (new RegExp('^[0-9]+[.] (.*)$').test(value)) {
            prior = value.substr(0, value.indexOf('. '));
            begin = prior + '. ';
            label = (parseInt(prior, 10) + 1) + '. ';
            check = true;
        }
        if (value && !check && lines[state - 1].substr(0, 4) === '    ') {
            begin = label = '    ';
            check = true;
        }
        if (['* ', '+ ', '- '].indexOf(first) >= 0) {
            begin = label = first;
            check = true;
        }
        if (check) {
            width = lines[state - 1].indexOf(begin);
            if (value.replace(/^\s+/, '') === begin) {
                block.value = input.substr(0, start - 1 - width - label.length) + '\n\n' + input.substr(start, input.length);
                caret = start + 1 - label.length - width;
            } else {
                block.value = input.substr(0, start) + '\n' + (new Array(width + 1).join(' ')) + label + input.substr(start, input.length);
                caret = start + 1 + label.length + width;
            }
            if (block.selectionStart) {
                block.setSelectionRange(caret, caret);
            } else {
                range = block.createTextRange();
                range.move('character', caret);
                range.select();
            }
            return false;
        }
    }
}

function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = cookies[i].trim();
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}<commit_msg>added live preview!<commit_after>/*
 jQuery Markdown editor
 derived from https://github.com/digitalnature/MarkdownEditor
 and https://github.com/jamiebicknell/Markdown-Helper
*/

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

$.ajaxSetup({
    beforeSend: function (xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            var csrftoken = getCookie('csrftoken');
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});

function toLines(text, selection) {
    let lines = text.split('\n');
    let pos = 0;
    let start = null
    let end = null
    for (var line = 0; line < length(lines); line++) {
        if (start === null && pos + length(lines[line]) >= selection.start) {
            start = {line: line, pos: selection.start - pos}
        }
        if (pos + length(lines[line]) >= selection.end) {
            end = {line: line, pos: selection.end - pos}
            break;
        }
        pos = pos + length(lines[line]) + 1  // re-add the "/n" chars that
    }

    return {lines: lines, selection: {start: start, end: end}};
}

function length(str) {
    return str.length;
}

(function ($, window, document, undefined) {
    $.fn.MarkdownEditor = function (isFull) {

        var adjustOffset = function (input, offset) {
                let val = input.value, newOffset = offset;

                // adjust starting offset, because some browsers (like Opera) treat new lines as two characters (\r\n) instead of one character (\n)
                if (val.indexOf("\r\n") > -1) {
                    let matches = val.replace(/\r\n/g, "\n").slice(0, offset).match(/\n/g);
                    newOffset += matches ? matches.length : 0;
                }

                return newOffset;
            },

            // creates a selection inside the textarea
            // if selectionStart = selectionEnd the cursor is set to that point
            setCaretToPos = function (input, selectionStart, selectionEnd) {
                input.focus();

                if (input.setSelectionRange) {
                    input.setSelectionRange(adjustOffset(input, selectionStart), adjustOffset(input, selectionEnd));

                    // ie
                } else if (input.createTextRange) {
                    let range = input.createTextRange();
                    range.collapse(true);
                    range.moveEnd('character', selectionEnd);
                    range.moveStart('character', selectionStart);
                    range.select();
                }
            },

            tags = {
                bold: {
                    start: '**', end: '**', placeholder: 'Your bold text',
                    line: false, block: false
                },
                strike: {
                    start: '~~', end: '~~', placeholder: 'Your struckthrough text',
                    line: false, block: false
                },
                italic: {
                    start: '*', end: '*', placeholder: 'Your emphasized text',
                    line: false, block: false
                },
                head: {
                    start: '#', end: '', placeholder: 'Your header',
                    line: true, block: false
                },
                quote: {
                    start: '> ', end: '', placeholder: 'Your quote',
                    line: true, block: false
                },
                link: {
                    start: '[', end: '](https://example.org/)', placeholder: 'Add your link text',
                    line: false, block: false
                },
                image: {
                    start: '![', end: '](https://example.org/)', placeholder: 'Add image description',
                    line: false, block: false
                },
                code: {
                    start: '`', end: '`', placeholder: 'Add inline code here',
                    line: false, block: false
                },
                pre: {
                    start: '    ', end: '', placeholder: 'Block Code',
                    line: true, block: true
                },
                ul: {
                    start: '* ', end: '', placeholder: 'List Item',
                    line: true, block: true
                },
                ol: {
                    start: '1. ', end: '', placeholder: 'List Item',
                    line: true, block: true
                },
            };

        return this.each(function () {
            let txt = this,                          // textarea element
                stale = true,
                endpoint = $(this).data("endpoint") || "/api/md_preview/",
                controls = $('
'); // button container
                stalePreviewIcon = 'fa-eye-slash'
                previewSource = controls;

            if (isFull) {
                previewSource = $('.full-preview');
                stalePreviewIcon = 'fa-check'
            }

            const format_classes = "btn btn-light";
            const button_template = '<button type="button" data-toggle="tooltip" data-placement="bottom" title="';
            var md_toolbar = '
'
                + '
'
                + button_template + 'Bold" class="' + format_classes + ' c-bold"></button>'
                + button_template + 'Italic" class="' + format_classes + ' c-italic"></button>'
                + button_template + 'Strikethrough" class="' + format_classes + ' c-strike"></button>'
                + button_template + 'Code" class="' + format_classes + ' c-code"></button>'
                + button_template + 'Heading" class="' + format_classes + ' c-head"></button>'
                + button_template + 'Quote" class="' + format_classes + ' c-quote"></button>'

                + '

'
                + button_template + 'Link" class="' + format_classes + ' c-link"></button>'
                + button_template + 'Image" class="' + format_classes + ' c-image"></button>'

                + '

'
                + button_template + 'Bullet List" class="' + format_classes + ' c-ul"></button>'
                + button_template + 'Ordered List" class="' + format_classes + ' c-ol"></button>'

                + '

'
                + button_template + 'Preview" class="' + format_classes + ' c-preview"></button>'
                + '
'
                + '
'

            if (!isFull) md_toolbar += '

'

            let doPreview = function() {
                if (stale) {
                    stale = false;
                    controls.find('.fa-eye').removeClass('fa-eye').addClass(stalePreviewIcon);
                    createPreview(txt, previewSource, endpoint);
                } else {
                    if (!isFull) previewSource.find('.preview').slideUp();
                    controls.find(stalePreviewIcon).removeClass(stalePreviewIcon).addClass('fa-eye');
                    stale = true;
                }
                return true;
            };
            let timeout;
            if (isFull) timeout = setTimeout(doPreview, 1);

            $(txt).before(controls.append(md_toolbar));
            if (!isFull) controls.find('.preview').slideUp();
            $(txt).on('keydown', function (event) {
                previewSource.find('.card').addClass("text-muted");
                controls.find(stalePreviewIcon).removeClass(stalePreviewIcon).addClass('fa-eye');
                stale = true;
                if (isFull) {
                    clearTimeout(timeout);
                    timeout = setTimeout(doPreview, 1000);
                }
                return MarkdownHelper(txt, event);
            });

            $('button', controls).on('click', function (event) {
                event.preventDefault();
                txt.focus();

                let tagName = this.className.substr(format_classes.length + 3),
                    range = {start: txt.selectionStart, end: txt.selectionEnd};
                let tag = tags[tagName]

                if (tagName === "preview") {
                    doPreview();
                }
                let a = toLines(txt.value, range);
                let lines = a.lines;
                let selection = a.selection;

                if (tag === tags.code && selection.start.line !== selection.end.line) {
                    tag = tags.pre;  // Code button changes behaviour in multi-line mode
                }

                let start_delta = 0, end_delta = 0;
                if (tag.line) {
                    if (selection.start.line === selection.end.line && lines[selection.start.line] === "") {

                        lines[selection.start.line] = tag.start + tag.placeholder + tag.end;
                        end_delta += length(lines[selection.start.line]);
                    } else {
                        start_delta += length(tag.start);
                        for (let i = selection.start.line; i <= selection.end.line; i++) {
                            lines[i] = tag.start + lines[i] + tag.end;
                            end_delta += length(tag.start);
                        }
                    }
                } else {
                    if (range.start !== range.end) {
                        lines[selection.end.line] = lines[selection.end.line].substring(0, selection.end.pos) + tag.end + lines[selection.end.line].substring(selection.end.pos);
                        lines[selection.start.line] = lines[selection.start.line].substring(0, selection.start.pos) + tag.start + lines[selection.start.line].substring(selection.start.pos);
                        start_delta += length(tag.start);
                        end_delta += length(tag.start);
                    } else {
                        lines[selection.start.line] = lines[selection.start.line].substring(0, selection.start.pos) + tag.start + tag.placeholder + tag.end + lines[selection.start.line].substring(selection.start.pos);
                        start_delta += length(tag.start);
                        end_delta += length(tag.start + tag.placeholder);
                    }
                }

                if (tag.block && (selection.start.line - 1) >= 0 && lines[selection.start.line - 1] !== "") {
                    lines[selection.start.line] = "\n" + lines[selection.start.line];
                    start_delta += 1;
                }
                if (tag.block && (selection.end.line + 1) <= lines.length && lines[selection.end.line + 1] !== "") {
                    lines[selection.end.line] = lines[selection.end.line] + "\n";
                }
                txt.value = lines.join("\n");
                setCaretToPos(txt, range.start + start_delta, range.end + end_delta);

                stale=true;
                previewSource.find('.card').addClass("text-muted");
                controls.find(stalePreviewIcon).removeClass(stalePreviewIcon).addClass('fa-eye');

                return true;
            });

        });

    };

})(jQuery, window, document);

function createPreview(txt, controls, endpoint) {
    $.post(endpoint, {'md': txt.value}, function (data, status, jqXHR) {
        controls.find('.preview').html(data).slideDown();
    });
}

function MarkdownHelper(block, event) {
    let check, input, start, range, lines, state, value, first, prior, label, begin, width, caret;
    if (event.keyCode === 13) {
        check = false;
        input = block.value.replace(/\r\n/g, '\n');
        if (block.selectionStart) {
            start = block.selectionStart;
        } else {
            block.focus();
            range = document.selection.createRange();
            range.moveStart('character', -input.length);
            start = range.text.replace(/\r\n/g, '\n').length;
        }
        lines = input.split('\n');
        state = input.substr(0, start).split('\n').length;
        value = lines[state - 1].replace(/^\s+/, '');
        first = value.substr(0, 2);
        if (new RegExp('^[0-9]+[.] (.*)$').test(value)) {
            prior = value.substr(0, value.indexOf('. '));
            begin = prior + '. ';
            label = (parseInt(prior, 10) + 1) + '. ';
            check = true;
        }
        if (value && !check && lines[state - 1].substr(0, 4) === '    ') {
            begin = label = '    ';
            check = true;
        }
        if (['* ', '+ ', '- '].indexOf(first) >= 0) {
            begin = label = first;
            check = true;
        }
        if (check) {
            width = lines[state - 1].indexOf(begin);
            if (value.replace(/^\s+/, '') === begin) {
                block.value = input.substr(0, start - 1 - width - label.length) + '\n\n' + input.substr(start, input.length);
                caret = start + 1 - label.length - width;
            } else {
                block.value = input.substr(0, start) + '\n' + (new Array(width + 1).join(' ')) + label + input.substr(start, input.length);
                caret = start + 1 + label.length + width;
            }
            if (block.selectionStart) {
                block.setSelectionRange(caret, caret);
            } else {
                range = block.createTextRange();
                range.move('character', caret);
                range.select();
            }
            return false;
        }
    }
}

function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = cookies[i].trim();
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}<|endoftext|>