<commit_before>/**
 * Gmailr v0.0.1
 * Licensed under The MIT License
 *
 * Copyright 2011, James Yu
 */

(function($, window) {

    // Utility methods

    var dbg = function(msg) {
        if(Gmailr.debug)
            console.log(msg);
    };

    var p = function(els, m) {
        if(!els) {
            dbg(els);
        } else if(els.each) {
            if(els.length == 0) {
                dbg('p: Empty');
            } else {
                els.each(function(i,e) {
                    dbg(e);
                });
            }
        } else {
            dbg(els);
        }
    };

    var pm = function(m, els) {
        dbg(m);
        p(els);
    };

    var isDescendant = function(el, t) {
        return t.parents().index(el) >= 0;
    };

    var Gmailr = {

        /*****************************************************************************************
         * Public Methods and Variables
         */

        debug: false,
        inboxLink: null,
        priorityInboxLink: null,
        currentNumUnread: null,
        currentInboxCount: null,
        archived: [],
        elements: {},

        /*
            This is the main initialization routine. It bootstraps Gmailr into the Gmail interface.
            You must call this with a callback, like so:

            Gmailr.init(funciton(G) {
                // .. G is the Gmailr API object
            });
        */

        init: function(cb) {
            var self = this;

            dbg('Initializing Gmailr API');

            var delayed_loader_count = 0;

            // Here we do delayed loading until success. This is in the case
            // that our script loads after Gmail has already loaded.
            self.delayed_loader = setInterval(function() {
                self.elements.canvas = $(document.getElementsByTagName('html')[0]);
                self.elements.body   = self.elements.canvas.find('body').first();

                if(self.loaded) {
                    if(delayed_loader_count != 0)
                        dbg('Delayed loader success.');

                    self.elements.canvas.bind("DOMSubtreeModified", function(e) {
                        self.detectDOMEvents(e);
                    });
                    clearInterval(self.delayed_loader);
                } else {
                    dbg('Calling delayed loader...');
                    delayed_loader_count += 1;
                    // we search from the body node, since there's no event to attach to
                    self.bootstrap(self.elements.body, cb);
                }
            }, 500);
        },

        /*
            Inserts the element to the top of the Gmail interface.
        */

        insertTop: function(el) {
            if(!this.loaded) throw "Call to insertTop before Gmail has loaded";
            this.elements.body.prepend($(el));
        },

        /*
            Allows you to apply jQuery selectors in the Gmail DOM, like so:

            G.$('.my_class');
        */

        $: function(selector) {
            return this.elements.body.find(selector);
        },

        /*
            Inserts a CSS file into the Gmail DOM.
        */

        insertCss: function(cssFile) {
            var css = $('<link rel="stylesheet" type="text/css">');
            css.attr('href', cssFile);
            this.elements.canvas.find('head').first().append(css);
        },

        /**
         * Subscribe to a specific event in Gmail
         *   name                arguments passed to callback
         *   'archive'         - count
         *   'numUnreadChange' - currentVal, previousVal
         *   'delete'          - count
         *   'spam'            - count
         *   'compose'
         *   'viewChanged'
         *   'applyLabel'
         */
        observe: function(type, cb) {
            this.ob_queues[type].push(cb);
        },

        /**
         * Number of unread messages.
         */
        numUnread: function() {
            if(!this.loaded) throw "Call to numUnread before Gmail has loaded";

            // We always look to the inbox link, bc it always displays the number unread
            // no matter where you are in Gmail

            //var title = this.inboxLink[0].title;
            var title = this.inboxLink[0].title;
            var m = /\((\d+)\)/.exec(title);
            return (m && m[1]) ? parseInt(m[1]) : 0;
        },

        /**
         * Email address of the Gmail account.
         */
        emailAddress: function() {
            if(!this.loaded) throw "Call to emailAddress before Gmail has loaded";

            // First, try old Gmail header
            var el = this.elements.canvas.find('#guser b');
            if(el.length > 0) return el.first().html();

            // Try the new one
            var el = this.elements.canvas.find('.gbmp1');
            if(el.length > 0) return el.first().html();
        },

        /**
         * Returns whether the current view is a threaded or conversation view.
         */
        currentView: function() {
            if(!this.loaded) throw "Call to currentView before Gmail has loaded";

            if(this.elements.canvas.find('h1.ha').length > 0) {
                return 'conversation';
            } else {
                return 'thread';
            }
        },

        /*****************************************************************************************
         * Private Methods
         */

        /**
         * This method attempts to bootstrap Gmailr into the Gmail interface.
         * Basically, this amounts polling to make sure Gmail has fully loaded,
         * and then setting up some basic hooks.
         */

        bootstrap: function(el, cb) {
            var self = this;
            if(el) {
                var el = $(el);

                // get handle on the left menu
                if(!this.leftMenu || this.leftMenu.length == 0) {
//                  this.leftMenu = el.find('.no .nM .TK').first().closest('.nn');

                    // use the inbox link as an anchor
                    var v = el.find('a[href$="#inbox"][title^="Inbox"]');
                    if(v.length > 0) this.inboxLink = v.first();

                    var v = el.find('a[href$="#mbox"]');
                    if(v.length > 0) this.priorityInboxLink = v.first();

                    if(this.inboxLink) {
                        this.leftMenu = this.inboxLink.closest('.TO').closest('div');
                    } else if(this.priorityInboxLink) {
                        this.leftMenu = this.priorityInboxLink.closest('.TO').closest('div');
                    }

                    if(this.leftMenu && this.leftMenu.length > 0) {
                        this.leftMenuItems = this.leftMenu.find('.TO');

                        p('Fully loaded.');
                        this.loaded = true;

                        this.currentNumUnread = this.numUnread();

                        if(this.inboxTabHighlighted())
                            this.currentInboxCount = this.toolbarCount();

                        this.xhrWatcher.init();

                        if(cb) cb(self);
                    }

                }
            }
        },

        xhrWatcher: {
            xhrParams: null,
            initialized: null,

            init: function() {
                var self = this;

                if(!this.initialized) {
                    this.initialized = true;
                    var win = top.document.getElementById("js_frame").contentDocument.defaultView;

                    win.XMLHttpRequest.prototype._Gmail_open = win.XMLHttpRequest.prototype.open;
                    win.XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
                        var out = this._Gmail_open.apply(this, arguments);
                        this.xhrParams = {
                            method: method.toString(),
                            url: url.toString()
                        };
                        return out;
                    };

                    win.XMLHttpRequest.prototype._Gmail_send = win.XMLHttpRequest.prototype.send;
                    win.XMLHttpRequest.prototype.send = function (body) {
                        var out = this._Gmail_send.apply(this, arguments);
                        if (this.xhrParams) {
                            this.xhrParams.body = body;
                            Gmailr.detectXHREvents(this.xhrParams);
                        }
                        return out;
                    }

                    if (!top._Gmail_iframeFn) {
                        top._Gmail_iframeFn = top.GG_iframeFn;
                        this.iframeData = {};
                        this.iframeCachedData = [];
                        this.iframeCachedData.push({
                            responseDataId: 1,
                            url: top.location.href,
                            responseData: top.VIEW_DATA
                        });

                        top.GG_iframeFn = function(win, data) {
                            var d = top._Gmail_iframeFn.apply(this, arguments);
                            try {
                                var url = win && win.location ? win.location.href: null;
                                if (url && data && (url.indexOf("act=") != -1 )) {

                                    if(!self.iframeData[url]) {

                                        var body = "";
                                        var parent = win.frameElement.parentNode;
                                        if(parent && $(parent).find('form').length > 0)
                                            body = $(parent).find('form').first().serialize();

                                        self.iframeData[url] = true;
                                        Gmailr.detectXHREvents({
                                            body: body,
                                            url: url
                                        });
                                    }
                                }
                            } catch(e) {
                                try {
                                    dbg("DEBUG error in GG_iframeFn: " + e);
                                } catch(e) {}
                            }
                            return d
                        }
                    }

                }
            }
        },

        currentLeftMenuItem: null,
        ob_queues: {
            archive: [],
            'delete': [],
            spam: [],
            reply: [],
            tabChange: [],
            compose: [],
            numUnreadChange: [],
            inboxCountChange: [],
            viewChanged: [],
            applyLabel: []
        },
        loaded: false,

        liveLeftMenuItem: function() {
            if(!this.loaded) return null;

            var el = this.leftMenuItems.filter('.nZ').find('a');
            if(el[0]) {
                return el[0].title;
            } else {
                return null;
            }
        },

        inboxTabHighlighted: function() {
            return this.currentTabHighlighted() == 'inbox' || this.currentTabHighlighted() == 'priority_inbox';
        },

        currentTabHighlighted: function() {
            if(this.inboxLink && this.inboxLink.closest('.TO').hasClass('nZ')) {
                return 'inbox';
            } else if(this.priorityInboxLink && this.priorityInboxLink.closest('.TO').hasClass('nZ')) {
                return 'priority_inbox';
            } else {
                return null;
            }
        },

        // Return true if a yellow archive highlight actually means the user is archiving
        archiveableState: function() {
            // For threads, this overrestricts:
            //   TODO: should detect if user is archiving an inbox item from a non-inbox view
            // For conversations, this underrestricts:
            //   TODO: should detect if the current email is in the inbox, and only assign points if it is
            return (this.inboxTabHighlighted() && this.currentView() == 'thread') || (this.currentView() != 'thread');
        },

        mainListingEl: function() {
            return this.elements.canvas.find('.Cp').first();
        },

        mainListingEmpty: function() {
            if(this.mainListingEl().length > 0 && this.currentView() == 'thread') {
                return this.mainListingEl().find('table tr').length == 0;
            } else {
                return null;
            }
        },

        toolbarEl: function() {
            return this.elements.canvas.find('.A1.D.E').first();
        },

        toolbarCount: function() {
            var el = this.toolbarEl().find('.Dj');
            if(el[0]) {
                var t = el[0].innerHTML;

                var m = /of <b>(\d+)<\/b>/.exec(t);

                if(m && m[1]) {
                    return parseInt(m[1]);
                } else {
                    return null;
                }
            } else {
                if(this.mainListingEmpty()) {
                    return 0;
                } else {
                    return null;
                }
            }
        },

        detectXHREvents: function(params) {
            var self = this;

            try {
                var m = /[?&]act=([^&]+)/.exec(params.url);
                if(m && m[1]) {
                    var action = decodeURIComponent(m[1]);
                    var count = 1;

                    var urlParams = $.deparam(params.url);

                    if(params.body.length > 0) {
                        var postParams = $.deparam(params.body);
                        if(postParams['t'] instanceof Array)
                            count = postParams['t'].length;

                        if(postParams['ba']) {
                            // The user has cleared more than a pageful, just give'em 50 points
                            count = 50;
                        }
                    }
                    switch(action) {
                        case "rc_^i": // Archiving
                            // only count if from inbox or query
                            // TODO: could do better
                            if(urlParams['search'] == 'inbox' || urlParams['search'] == 'query' || urlParams['search'] == 'cat' || urlParams['search'] == 'mbox') {
                                if(postParams) {
                                    // Get list of email hashes
                                    var emails = postParams['t'] instanceof Array ? postParams['t'] : [ postParams['t'] ];
                                    var emailsArchived = [];
                                    emails.forEach(function(e) {
                                        // Make sure user didn't already archive this email
                                        if(self.archived.indexOf(e) == -1)
                                            emailsArchived.push(e);
                                    });

                                    this.archived = this.archived.concat(emailsArchived);

                                    if(emailsArchived.length > 0) {
                                        p("User archived " + emailsArchived.length + " emails.");
                                        this.executeObQueues('archive', count);
                                    }

                                    delete emails;
                                    delete emailsArchived;
                                }
                            }
                            break;
                        case "arl": //applying label
                            var label = urlParams["acn"];
                            var emails = postParams['t'] instanceof Array ? postParams['t'] : [ postParams['t'] ];
                            this.executeObQueues('applyLabel', label, emails);
                            break;
                        case "tr": // Deleting
                            p("User deleted " + count + " emails.");
                            this.executeObQueues('delete', count);
                            break;
                        case "sm": // Composing
                            if(this.currentView() == 'conversation') {
                                p("User replied to an email.");
                                this.executeObQueues('reply', 1);
                            } else {
                                p("User composed an email.");
                                this.executeObQueues('compose', 1);
                            }
                            break;
                        case "sp": // Spam
                            p("User spammed " + count + " emails.");
                            this.executeObQueues('spam', count);
                            break;
                    }
                }
            } catch(e) {
                dbg("Error in detectXHREvents: " + e);
            }
        },

        inConversationView: false,

        detectDOMEvents: function(e) {
            var el = $(e.target);

            // Left Menu Changes
            /*var s = this.liveLeftMenuItem();
            if(this.currentLeftMenuItem != s) {
                this.currentLeftMenuItem = s;
                this.executeObQueues('tabChange', s);
            }

            // Unread change
            var l = this.inboxLink ? this.inboxLink : this.priorityInboxLink;
            if((el[0] == l[0]) || isDescendant(el, l)) {
                if(this.currentNumUnread != this.numUnread()) {
                    this.executeObQueues('numUnreadChange', this.numUnread(), this.currentNumUnread);
                    this.currentNumUnread = this.numUnread();
                }
            }*/

            if(this.elements.canvas.find('.ha').length > 0) {
                if(!this.inConversationView) {
                    this.inConversationView = true;
                    this.executeObQueues('viewChanged', 'conversation');
                }
            } else {
                if(this.inConversationView) {
                    this.inConversationView = false;
                    this.executeObQueues('viewChanged', 'threaded');
                }
            }

            // Inbox count change
            if(isDescendant(this.toolbarEl(), el)) {
                var toolbarCount = this.toolbarCount();
                if(this.inboxTabHighlighted() && toolbarCount !== null) {
                    if((this.currentInboxCount === null) || (toolbarCount != this.currentInboxCount)) {
                        if(this.currentInboxCount !== null)
                            this.executeObQueues('inboxCountChange', toolbarCount, this.currentInboxCount);
                        this.currentInboxCount = toolbarCount;
                    }
                }
            }
        },

        executeObQueues: function(type, arg) {
            if(this.ob_queues[type])
                for(var i = 0; i < this.ob_queues[type].length; i++) {
                    var args = Array.prototype.slice.call(arguments, 1);
                    (this.ob_queues[type][i]).apply(this, args)
                }
        }
    };

    window.Gmailr = Gmailr;
})(jQuery, window);
<commit_msg>fix for getting email address<commit_after>/**
 * Gmailr v0.0.1
 * Licensed under The MIT License
 *
 * Copyright 2011, James Yu
 */

(function($, window) {

    // Utility methods

    var dbg = function(msg) {
        if(Gmailr.debug)
            console.log(msg);
    };

    var p = function(els, m) {
        if(!els) {
            dbg(els);
        } else if(els.each) {
            if(els.length == 0) {
                dbg('p: Empty');
            } else {
                els.each(function(i,e) {
                    dbg(e);
                });
            }
        } else {
            dbg(els);
        }
    };

    var pm = function(m, els) {
        dbg(m);
        p(els);
    };

    var isDescendant = function(el, t) {
        return t.parents().index(el) >= 0;
    };

    var Gmailr = {

        /*****************************************************************************************
         * Public Methods and Variables
         */

        debug: false,
        inboxLink: null,
        priorityInboxLink: null,
        currentNumUnread: null,
        currentInboxCount: null,
        archived: [],
        elements: {},

        /*
            This is the main initialization routine. It bootstraps Gmailr into the Gmail interface.
            You must call this with a callback, like so:

            Gmailr.init(funciton(G) {
                // .. G is the Gmailr API object
            });
        */

        init: function(cb) {
            var self = this;

            dbg('Initializing Gmailr API');

            var delayed_loader_count = 0;

            // Here we do delayed loading until success. This is in the case
            // that our script loads after Gmail has already loaded.
            self.delayed_loader = setInterval(function() {
                self.elements.canvas = $(document.getElementsByTagName('html')[0]);
                self.elements.body   = self.elements.canvas.find('body').first();

                if(self.loaded) {
                    if(delayed_loader_count != 0)
                        dbg('Delayed loader success, email: ' + self.emailAddress() );

                    self.elements.canvas.bind("DOMSubtreeModified", function(e) {
                        self.detectDOMEvents(e);
                    });
                    clearInterval(self.delayed_loader);
                } else {
                    dbg('Calling delayed loader...');
                    delayed_loader_count += 1;
                    // we search from the body node, since there's no event to attach to
                    self.bootstrap(self.elements.body, cb);
                }
            }, 500);
        },

        /*
            Inserts the element to the top of the Gmail interface.
        */

        insertTop: function(el) {
            if(!this.loaded) throw "Call to insertTop before Gmail has loaded";
            this.elements.body.prepend($(el));
        },

        /*
            Allows you to apply jQuery selectors in the Gmail DOM, like so:

            G.$('.my_class');
        */

        $: function(selector) {
            return this.elements.body.find(selector);
        },

        /*
            Inserts a CSS file into the Gmail DOM.
        */

        insertCss: function(cssFile) {
            var css = $('<link rel="stylesheet" type="text/css">');
            css.attr('href', cssFile);
            this.elements.canvas.find('head').first().append(css);
        },

        /**
         * Subscribe to a specific event in Gmail
         *   name                arguments passed to callback
         *   'archive'         - count
         *   'numUnreadChange' - currentVal, previousVal
         *   'delete'          - count
         *   'spam'            - count
         *   'compose'
         *   'viewChanged'
         *   'applyLabel'
         */
        observe: function(type, cb) {
            this.ob_queues[type].push(cb);
        },

        /**
         * Number of unread messages.
         */
        numUnread: function() {
            if(!this.loaded) throw "Call to numUnread before Gmail has loaded";

            // We always look to the inbox link, bc it always displays the number unread
            // no matter where you are in Gmail

            //var title = this.inboxLink[0].title;
            var title = this.inboxLink[0].title;
            var m = /\((\d+)\)/.exec(title);
            return (m && m[1]) ? parseInt(m[1]) : 0;
        },

        /**
         * Email address of the Gmail account.
         */
        emailAddress: function() {
            if(!this.loaded) throw "Call to emailAddress before Gmail has loaded";

            // First, try old Gmail header
            var el = this.elements.canvas.find('#guser b');
            if(el.length > 0) return el.first().html();

            // Try the new one
            var el = this.elements.canvas.find('.gbmp1');
            if(el.length > 0) return el.first().html();

            var emailElement = this.$(".gbps2");
            return emailElement.html();
        },

        /**
         * Returns whether the current view is a threaded or conversation view.
         */
        currentView: function() {
            if(!this.loaded) throw "Call to currentView before Gmail has loaded";

            if(this.elements.canvas.find('h1.ha').length > 0) {
                return 'conversation';
            } else {
                return 'thread';
            }
        },

        /*****************************************************************************************
         * Private Methods
         */

        /**
         * This method attempts to bootstrap Gmailr into the Gmail interface.
         * Basically, this amounts polling to make sure Gmail has fully loaded,
         * and then setting up some basic hooks.
         */

        bootstrap: function(el, cb) {
            var self = this;
            if(el) {
                var el = $(el);

                // get handle on the left menu
                if(!this.leftMenu || this.leftMenu.length == 0) {
//                  this.leftMenu = el.find('.no .nM .TK').first().closest('.nn');

                    // use the inbox link as an anchor
                    var v = el.find('a[href$="#inbox"][title^="Inbox"]');
                    if(v.length > 0) this.inboxLink = v.first();

                    var v = el.find('a[href$="#mbox"]');
                    if(v.length > 0) this.priorityInboxLink = v.first();

                    if(this.inboxLink) {
                        this.leftMenu = this.inboxLink.closest('.TO').closest('div');
                    } else if(this.priorityInboxLink) {
                        this.leftMenu = this.priorityInboxLink.closest('.TO').closest('div');
                    }

                    if(this.leftMenu && this.leftMenu.length > 0) {
                        this.leftMenuItems = this.leftMenu.find('.TO');

                        p('Fully loaded');
                        this.loaded = true;

                        this.currentNumUnread = this.numUnread();

                        if(this.inboxTabHighlighted())
                            this.currentInboxCount = this.toolbarCount();

                        this.xhrWatcher.init();

                        if(cb) cb(self);
                    }

                }
            }
        },

        xhrWatcher: {
            xhrParams: null,
            initialized: null,

            init: function() {
                var self = this;

                if(!this.initialized) {
                    this.initialized = true;
                    var win = top.document.getElementById("js_frame").contentDocument.defaultView;

                    win.XMLHttpRequest.prototype._Gmail_open = win.XMLHttpRequest.prototype.open;
                    win.XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
                        var out = this._Gmail_open.apply(this, arguments);
                        this.xhrParams = {
                            method: method.toString(),
                            url: url.toString()
                        };
                        return out;
                    };

                    win.XMLHttpRequest.prototype._Gmail_send = win.XMLHttpRequest.prototype.send;
                    win.XMLHttpRequest.prototype.send = function (body) {
                        var out = this._Gmail_send.apply(this, arguments);
                        if (this.xhrParams) {
                            this.xhrParams.body = body;
                            Gmailr.detectXHREvents(this.xhrParams);
                        }
                        return out;
                    }

                    if (!top._Gmail_iframeFn) {
                        top._Gmail_iframeFn = top.GG_iframeFn;
                        this.iframeData = {};
                        this.iframeCachedData = [];
                        this.iframeCachedData.push({
                            responseDataId: 1,
                            url: top.location.href,
                            responseData: top.VIEW_DATA
                        });

                        top.GG_iframeFn = function(win, data) {
                            var d = top._Gmail_iframeFn.apply(this, arguments);
                            try {
                                var url = win && win.location ? win.location.href: null;
                                if (url && data && (url.indexOf("act=") != -1 )) {

                                    if(!self.iframeData[url]) {

                                        var body = "";
                                        var parent = win.frameElement.parentNode;
                                        if(parent && $(parent).find('form').length > 0)
                                            body = $(parent).find('form').first().serialize();

                                        self.iframeData[url] = true;
                                        Gmailr.detectXHREvents({
                                            body: body,
                                            url: url
                                        });
                                    }
                                }
                            } catch(e) {
                                try {
                                    dbg("DEBUG error in GG_iframeFn: " + e);
                                } catch(e) {}
                            }
                            return d
                        }
                    }

                }
            }
        },

        currentLeftMenuItem: null,
        ob_queues: {
            archive: [],
            'delete': [],
            spam: [],
            reply: [],
            tabChange: [],
            compose: [],
            numUnreadChange: [],
            inboxCountChange: [],
            viewChanged: [],
            applyLabel: []
        },
        loaded: false,

        liveLeftMenuItem: function() {
            if(!this.loaded) return null;

            var el = this.leftMenuItems.filter('.nZ').find('a');
            if(el[0]) {
                return el[0].title;
            } else {
                return null;
            }
        },

        inboxTabHighlighted: function() {
            return this.currentTabHighlighted() == 'inbox' || this.currentTabHighlighted() == 'priority_inbox';
        },

        currentTabHighlighted: function() {
            if(this.inboxLink && this.inboxLink.closest('.TO').hasClass('nZ')) {
                return 'inbox';
            } else if(this.priorityInboxLink && this.priorityInboxLink.closest('.TO').hasClass('nZ')) {
                return 'priority_inbox';
            } else {
                return null;
            }
        },

        // Return true if a yellow archive highlight actually means the user is archiving
        archiveableState: function() {
            // For threads, this overrestricts:
            //   TODO: should detect if user is archiving an inbox item from a non-inbox view
            // For conversations, this underrestricts:
            //   TODO: should detect if the current email is in the inbox, and only assign points if it is
            return (this.inboxTabHighlighted() && this.currentView() == 'thread') || (this.currentView() != 'thread');
        },

        mainListingEl: function() {
            return this.elements.canvas.find('.Cp').first();
        },

        mainListingEmpty: function() {
            if(this.mainListingEl().length > 0 && this.currentView() == 'thread') {
                return this.mainListingEl().find('table tr').length == 0;
            } else {
                return null;
            }
        },

        toolbarEl: function() {
            return this.elements.canvas.find('.A1.D.E').first();
        },

        toolbarCount: function() {
            var el = this.toolbarEl().find('.Dj');
            if(el[0]) {
                var t = el[0].innerHTML;

                var m = /of <b>(\d+)<\/b>/.exec(t);

                if(m && m[1]) {
                    return parseInt(m[1]);
                } else {
                    return null;
                }
            } else {
                if(this.mainListingEmpty()) {
                    return 0;
                } else {
                    return null;
                }
            }
        },

        detectXHREvents: function(params) {
            var self = this;

            try {
                var m = /[?&]act=([^&]+)/.exec(params.url);
                if(m && m[1]) {
                    var action = decodeURIComponent(m[1]);
                    var count = 1;

                    var urlParams = $.deparam(params.url);

                    if(params.body.length > 0) {
                        var postParams = $.deparam(params.body);
                        if(postParams['t'] instanceof Array)
                            count = postParams['t'].length;

                        if(postParams['ba']) {
                            // The user has cleared more than a pageful, just give'em 50 points
                            count = 50;
                        }
                    }
                    switch(action) {
                        case "rc_^i": // Archiving
                            // only count if from inbox or query
                            // TODO: could do better
                            if(urlParams['search'] == 'inbox' || urlParams['search'] == 'query' || urlParams['search'] == 'cat' || urlParams['search'] == 'mbox') {
                                if(postParams) {
                                    // Get list of email hashes
                                    var emails = postParams['t'] instanceof Array ? postParams['t'] : [ postParams['t'] ];
                                    var emailsArchived = [];
                                    emails.forEach(function(e) {
                                        // Make sure user didn't already archive this email
                                        if(self.archived.indexOf(e) == -1)
                                            emailsArchived.push(e);
                                    });

                                    this.archived = this.archived.concat(emailsArchived);

                                    if(emailsArchived.length > 0) {
                                        p("User archived " + emailsArchived.length + " emails.");
                                        this.executeObQueues('archive', count);
                                    }

                                    delete emails;
                                    delete emailsArchived;
                                }
                            }
                            break;
                        case "arl": //applying label
                            var label = urlParams["acn"];
                            var emails = postParams['t'] instanceof Array ? postParams['t'] : [ postParams['t'] ];
                            this.executeObQueues('applyLabel', label, emails);
                            break;
                        case "tr": // Deleting
                            p("User deleted " + count + " emails.");
                            this.executeObQueues('delete', count);
                            break;
                        case "sm": // Composing
                            if(this.currentView() == 'conversation') {
                                p("User replied to an email.");
                                this.executeObQueues('reply', 1);
                            } else {
                                p("User composed an email.");
                                this.executeObQueues('compose', 1);
                            }
                            break;
                        case "sp": // Spam
                            p("User spammed " + count + " emails.");
                            this.executeObQueues('spam', count);
                            break;
                    }
                }
            } catch(e) {
                dbg("Error in detectXHREvents: " + e);
            }
        },

        inConversationView: false,

        detectDOMEvents: function(e) {
            var el = $(e.target);

            // Left Menu Changes
            /*var s = this.liveLeftMenuItem();
            if(this.currentLeftMenuItem != s) {
                this.currentLeftMenuItem = s;
                this.executeObQueues('tabChange', s);
            }

            // Unread change
            var l = this.inboxLink ? this.inboxLink : this.priorityInboxLink;
            if((el[0] == l[0]) || isDescendant(el, l)) {
                if(this.currentNumUnread != this.numUnread()) {
                    this.executeObQueues('numUnreadChange', this.numUnread(), this.currentNumUnread);
                    this.currentNumUnread = this.numUnread();
                }
            }*/

            if(this.elements.canvas.find('.ha').length > 0) {
                if(!this.inConversationView) {
                    this.inConversationView = true;
                    this.executeObQueues('viewChanged', 'conversation');
                }
            } else {
                if(this.inConversationView) {
                    this.inConversationView = false;
                    this.executeObQueues('viewChanged', 'threaded');
                }
            }

            // Inbox count change
            if(isDescendant(this.toolbarEl(), el)) {
                var toolbarCount = this.toolbarCount();
                if(this.inboxTabHighlighted() && toolbarCount !== null) {
                    if((this.currentInboxCount === null) || (toolbarCount != this.currentInboxCount)) {
                        if(this.currentInboxCount !== null)
                            this.executeObQueues('inboxCountChange', toolbarCount, this.currentInboxCount);
                        this.currentInboxCount = toolbarCount;
                    }
                }
            }
        },

        executeObQueues: function(type, arg) {
            if(this.ob_queues[type])
                for(var i = 0; i < this.ob_queues[type].length; i++) {
                    var args = Array.prototype.slice.call(arguments, 1);
                    (this.ob_queues[type][i]).apply(this, args)
                }
        }
    };

    window.Gmailr = Gmailr;
})(jQuery, window);
<|endoftext|>


<commit_before>const gulp = require('gulp');

// Create an electron-connect server to enable reloading
const electron = require('electron-connect').server.create({
  path: "build/init.js",
  stopOnClose: true
});

gulp.task('start', ()=>{
  electron.start();
  //Watch js files and restart Electron if they change
  gulp.watch(['build/init.js', 'build/core/*.js'], electron.restart);
  //watch css files, but only reload (no restart necessary)
  gulp.watch(['build/main.js', 'build/vendors.js', 'build/main.css'], electron.reload);
  //watch html
  gulp.watch(['build/index.html'], electron.reload);
});<commit_msg>gulp watch core files fix #10<commit_after>const gulp = require('gulp');

// Create an electron-connect server to enable reloading
const electron = require('electron-connect').server.create({
  path: "build/init.js",
  stopOnClose: true
});

gulp.task('start', ()=>{
  electron.start();
  //Watch js files and restart Electron if they change
  gulp.watch(['build/init.js', 'build/core/**/*.js'], electron.restart);
  //watch css files, but only reload (no restart necessary)
  gulp.watch(['build/main.js', 'build/vendors.js', 'build/main.css'], electron.reload);
  //watch html
  gulp.watch(['build/index.html'], electron.reload);
});<|endoftext|>


<commit_before>var gulp = require('gulp');
var less = require('gulp-less');
var bower = require('gulp-bower');

gulp.task('update-libs', function () {
    return bower({ directory: './bower_components', cwd: '.' })
      .pipe(gulp.dest('./assets/themes'));
});

gulp.task('theme-leo', ['update-libs'], function () {
    gulp.src('./assets/themes/leo/default/*.less')
      .pipe(less())
      .pipe(gulp.dest('./assets/themes/leo/default'));

    gulp.src('./assets/themes/leo/dyslexic/*.less')
      .pipe(less())
      .pipe(gulp.dest('./assets/themes/leo/dyslexic'));
});

//copy themes elements on local to see tests
gulp.task('copy-theme-leo', function () {
    return gulp.src(['../theme-leo/**/*'])
     .pipe(gulp.dest('./assets/themes/leo'));
});

//copy themes elements on local to see tests
gulp.task('copy-css-lib', function () {
   return  gulp.src(['../css-lib/**/*'])
    .pipe(gulp.dest('./assets/themes/entcore-css-lib'));
});

// compile local css to test
gulp.task('compile-leo-css', ['copy-theme-leo', 'copy-css-lib'], function () {
   gulp.src('./assets/themes/leo/default/*.less')
     .pipe(less())
     .pipe(gulp.dest('./assets/themes/leo/default'));

   gulp.src('./assets/themes/leo/dyslexic/*.less')
     .pipe(less())
     .pipe(gulp.dest('./assets/themes/leo/dyslexic'));
});
<commit_msg>copy all themes<commit_after>var gulp = require('gulp');
var less = require('gulp-less');
var bower = require('gulp-bower');

gulp.task('update-libs', function () {
    return bower({ directory: './bower_components', cwd: '.' })
      .pipe(gulp.dest('./assets/themes'));
});

gulp.task('themes', ['update-libs'], function () {
    return gulp.src('./assets/themes/**/theme.less')
      .pipe(less())
      .pipe(gulp.dest('./assets/themes'));
});

//copy themes elements on local to see tests
gulp.task('copy-theme-leo', function () {
    return gulp.src(['../theme-leo/**/*'])
     .pipe(gulp.dest('./assets/themes/leo'));
});

//copy themes elements on local to see tests
gulp.task('copy-css-lib', function () {
   return  gulp.src(['../css-lib/**/*'])
    .pipe(gulp.dest('./assets/themes/entcore-css-lib'));
});

// compile local css to test
gulp.task('compile-leo-css', ['copy-theme-leo', 'copy-css-lib'], function () {
   gulp.src('./assets/themes/leo/default/*.less')
     .pipe(less())
     .pipe(gulp.dest('./assets/themes/leo/default'));

   gulp.src('./assets/themes/leo/dyslexic/*.less')
     .pipe(less())
     .pipe(gulp.dest('./assets/themes/leo/dyslexic'));
});
<|endoftext|>


<commit_before>var gulp = require('gulp');
var clean = require('gulp-clean');
var concat = require('gulp-concat');
var csslint = require('gulp-csslint');
var header = require('gulp-header');
var jshint = require('gulp-jshint');
var minifyCSS = require('gulp-minify-css');
var rename = require('gulp-rename');
var uglify = require('gulp-uglify');
var zip = require('gulp-zip');

var pkg = require('./package.json');
var basename = pkg.name + '-' + pkg.version;
var banner = '/*! {{ pkg.name }} v{{ pkg.version }} */';

// Lint JS + CSS
gulp.task('lint', function() {
  gulp.src('./src/*.js')
    .pipe(jshint())
    .pipe(jshint.reporter());

  gulp.src('./src/*.css')
    .pipe(csslint({
      'adjoining-classes': false,
      'box-sizing': false
    }))
    .pipe(csslint.reporter());
});

// Concat & Minify JS + CSS
gulp.task('minify', function(){
    gulp.src('./src/*.js')
        .pipe(concat(basename +'.js'))
        .pipe(gulp.dest('./dist'))
        .pipe(rename(basename + '.min.js'))
        .pipe(uglify())
        .pipe(header(banner, { pkg : pkg } ))
        .pipe(gulp.dest('./dist'));

    gulp.src('./src/*.css')
        .pipe(concat(basename +'.css'))
        .pipe(gulp.dest('./dist'))
        .pipe(rename(basename + '.min.css'))
        .pipe(minifyCSS())
        .pipe(header(banner, { pkg : pkg } ))
        .pipe(gulp.dest('./dist'));
});

// Package for distribution
gulp.task('zip', ['minify'], function(){
    gulp.src([
      'README.md',
      'LICENSE',
      'dist/' + basename + '.js',
      'dist/' + basename + '.min.js',
      'dist/' + basename + '.css',
      'dist/' + basename + '.min.css',
    ])
    .pipe(rename(function (dir, base, ext) {
        return (dir == 'dist' ? '../' : '') + base + ext;
    }))
    .pipe(zip(basename + '.zip'))
    .pipe(gulp.dest('dist'));
});

// Cleanup
gulp.task('clean', function() {
  gulp.src('./dist', {read: false})
    .pipe(clean());
});

// Default
gulp.task('default', function(){
  gulp.run('lint', 'minify');

  // Watch JS Files
  gulp.watch(['./src/*.js', './src/*.css'], function(event){
    gulp.run('lint', 'minify');
  });
});
<commit_msg>gulp: Split concat from minify task<commit_after>var gulp = require('gulp');
var clean = require('gulp-clean');
var concat = require('gulp-concat');
var csslint = require('gulp-csslint');
var header = require('gulp-header');
var jshint = require('gulp-jshint');
var minifyCSS = require('gulp-minify-css');
var rename = require('gulp-rename');
var uglify = require('gulp-uglify');
var zip = require('gulp-zip');

var pkg = require('./package.json');
var basename = pkg.name + '-' + pkg.version;
var banner = '/*! {{ pkg.name }} v{{ pkg.version }} */';

// Lint JS + CSS
gulp.task('lint', function() {
  gulp.src('./src/*.js')
    .pipe(jshint())
    .pipe(jshint.reporter());

  gulp.src('./src/*.css')
    .pipe(csslint({
      'adjoining-classes': false,
      'box-sizing': false
    }))
    .pipe(csslint.reporter());
});

// Concat JS + CSS
gulp.task('concat', function() {
    gulp.src('./src/*.js')
        .pipe(concat(basename +'.js'))
        .pipe(gulp.dest('./dist'));

    gulp.src('./src/*.css')
        .pipe(concat(basename +'.css'))
        .pipe(gulp.dest('./dist'));
});

// Minify JS + CSS
gulp.task('minify', ['concat'], function() {
    gulp.src('./src/' + basename + '.js')
        .pipe(rename(basename + '.min.js'))
        .pipe(uglify())
        .pipe(header(banner, { pkg : pkg } ))
        .pipe(gulp.dest('./dist'));

    gulp.src('./src/' + basename + '.css')
        .pipe(rename(basename + '.min.css'))
        .pipe(minifyCSS())
        .pipe(header(banner, { pkg : pkg } ))
        .pipe(gulp.dest('./dist'));
});

// Package for distribution
gulp.task('zip', ['minify'], function() {
    gulp.src([
      'README.md',
      'LICENSE',
      'dist/' + basename + '.js',
      'dist/' + basename + '.min.js',
      'dist/' + basename + '.css',
      'dist/' + basename + '.min.css',
    ])
    .pipe(rename(function (dir, base, ext) {
        return (dir == 'dist' ? '../' : '') + base + ext;
    }))
    .pipe(zip(basename + '.zip'))
    .pipe(gulp.dest('dist'));
});

// Cleanup
gulp.task('clean', function() {
  gulp.src('./dist', {read: false})
    .pipe(clean());
});

// Default
gulp.task('default', function(){
  gulp.run('lint', 'minify');

  // Watch JS Files
  gulp.watch(['./src/*.js', './src/*.css'], function(event){
    gulp.run('lint', 'minify');
  });
});
<|endoftext|>


<commit_before>// include plug-ins
var gulp       = require('gulp');
var concat     = require('gulp-concat');
var iife       = require("gulp-iife");
var inject     = require('gulp-inject-string')
var rename     = require('gulp-rename');
var uglify     = require('gulp-uglify');
var babel      = require('gulp-babel');

var HEADER_COMMENT = '// Pressure v2.0.0 | Created By Stuart Yamartino | MIT License | 2015 - Present\n';
var DESTINATION = '.';

// JS concat, strip debugging and minify
gulp.task('pressure', function() {
  gulp.src([
    './src/pressure.js',
    './src/globalize.js',
    './src/element.js',
    './src/adapters/adapter.js',
    './src/adapters/adapter_force_touch.js',
    './src/adapters/adapter_3d_touch.js',
    './src/adapters/adapter_force_touch.js',
    './src/config.js',
    './src/helpers.js',
  ])
  .pipe(concat('dist/pressure.js'))
  .pipe(babel({
      presets: ['es2015']
  }))
  .pipe(iife({
    useStrict: false,
    params: ['window', 'document'],
    args: ['typeof window !== "undefined" ? window : false', 'typeof window !== "undefined" ? window.document : false']
  }))
  .pipe(inject.prepend(HEADER_COMMENT))
  .pipe(inject.replace('//REPLACE-ME-IN-GULP-WITH-RETURN', 'return;'))
  // This will output the non-minified version
  .pipe(gulp.dest(DESTINATION))

  // This will minify and rename to pressure.min.js
  .pipe(uglify())
  .pipe(inject.prepend(HEADER_COMMENT))
  .pipe(rename({ extname: '.min.js' }))
  .pipe(gulp.dest(DESTINATION));
});

gulp.task('jquery-pressure', function() {
  gulp.src([
    './src/jquery_pressure.js',
    './src/globalize.js',
    './src/element.js',
    './src/adapters/adapter.js',
    './src/adapters/adapter_force_touch.js',
    './src/adapters/adapter_3d_touch.js',
    './src/adapters/adapter_force_touch.js',
    './src/config.js',
    './src/helpers.js',
  ])
  .pipe(concat('dist/jquery.pressure.js'))
  .pipe(babel({
      presets: ['es2015']
  }))
  .pipe(iife({
    useStrict: false,
    params: ['window', 'document', '$'],
    args: ['typeof window !== "undefined" ? window : false', 'typeof window !== "undefined" ? window.document : false', 'typeof jQuery !== "undefined" ? jQuery : false']
  }))
  .pipe(inject.prepend(HEADER_COMMENT))
  .pipe(inject.replace('//REPLACE-ME-IN-GULP-WITH-RETURN', 'return;'))
  // This will output the non-minified version
  .pipe(gulp.dest(DESTINATION))

  // This will minify and rename to jquery.pressure.min.js
  .pipe(uglify())
  .pipe(inject.prepend(HEADER_COMMENT))
  .pipe(rename({ extname: '.min.js' }))
  .pipe(gulp.dest(DESTINATION));
});

gulp.task('watch', function() {
  gulp.watch(['src/*', 'src/adapters/*'], ['pressure', 'jquery-pressure']);
});
<commit_msg>Removed double loading force touch adapter<commit_after>// include plug-ins
var gulp       = require('gulp');
var concat     = require('gulp-concat');
var iife       = require("gulp-iife");
var inject     = require('gulp-inject-string')
var rename     = require('gulp-rename');
var uglify     = require('gulp-uglify');
var babel      = require('gulp-babel');

var HEADER_COMMENT = '// Pressure v2.0.0 | Created By Stuart Yamartino | MIT License | 2015 - Present\n';
var DESTINATION = '.';

// JS concat, strip debugging and minify
gulp.task('pressure', function() {
  gulp.src([
    './src/pressure.js',
    './src/globalize.js',
    './src/element.js',
    './src/adapters/adapter.js',
    './src/adapters/adapter_force_touch.js',
    './src/adapters/adapter_3d_touch.js',
    './src/config.js',
    './src/helpers.js',
  ])
  .pipe(concat('dist/pressure.js'))
  .pipe(babel({
      presets: ['es2015']
  }))
  .pipe(iife({
    useStrict: false,
    params: ['window', 'document'],
    args: ['typeof window !== "undefined" ? window : false', 'typeof window !== "undefined" ? window.document : false']
  }))
  .pipe(inject.prepend(HEADER_COMMENT))
  .pipe(inject.replace('//REPLACE-ME-IN-GULP-WITH-RETURN', 'return;'))
  // This will output the non-minified version
  .pipe(gulp.dest(DESTINATION))

  // This will minify and rename to pressure.min.js
  .pipe(uglify())
  .pipe(inject.prepend(HEADER_COMMENT))
  .pipe(rename({ extname: '.min.js' }))
  .pipe(gulp.dest(DESTINATION));
});

gulp.task('jquery-pressure', function() {
  gulp.src([
    './src/jquery_pressure.js',
    './src/globalize.js',
    './src/element.js',
    './src/adapters/adapter.js',
    './src/adapters/adapter_force_touch.js',
    './src/adapters/adapter_3d_touch.js',
    './src/config.js',
    './src/helpers.js',
  ])
  .pipe(concat('dist/jquery.pressure.js'))
  .pipe(babel({
      presets: ['es2015']
  }))
  .pipe(iife({
    useStrict: false,
    params: ['window', 'document', '$'],
    args: ['typeof window !== "undefined" ? window : false', 'typeof window !== "undefined" ? window.document : false', 'typeof jQuery !== "undefined" ? jQuery : false']
  }))
  .pipe(inject.prepend(HEADER_COMMENT))
  .pipe(inject.replace('//REPLACE-ME-IN-GULP-WITH-RETURN', 'return;'))
  // This will output the non-minified version
  .pipe(gulp.dest(DESTINATION))

  // This will minify and rename to jquery.pressure.min.js
  .pipe(uglify())
  .pipe(inject.prepend(HEADER_COMMENT))
  .pipe(rename({ extname: '.min.js' }))
  .pipe(gulp.dest(DESTINATION));
});

gulp.task('watch', function() {
  gulp.watch(['src/*', 'src/adapters/*'], ['pressure', 'jquery-pressure']);
});
<|endoftext|>


<commit_before>'use strict';

// Include Gulp & Tools We'll Use
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var del = require('del');
var runSequence = require('run-sequence');
var browserSync = require('browser-sync');
var pagespeed = require('psi');
var reload = browserSync.reload;
var deploy = require('gulp-gh-pages');

var AUTOPREFIXER_BROWSERS = [
  'ie >= 10',
  'ie_mob >= 10',
  'ff >= 30',
  'chrome >= 34',
  'safari >= 7',
  'opera >= 23',
  'ios >= 7',
  'android >= 4.4',
  'bb >= 10'
];

// Lint JavaScript
gulp.task('lint', function() {
  return gulp.src('app/scripts/**/*.js')
    .pipe(reload({stream: true, once: true}))
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
    .pipe($.jscs())
    .pipe($.if(!browserSync.active, $.jshint.reporter('fail')));
});

// Optimize Images
gulp.task('images', function() {
  return gulp.src('app/images/**/*')
    .pipe($.cache($.imagemin({
      progressive: true,
      interlaced: true
    })))
    .pipe(gulp.dest('dist/images'))
    .pipe($.size({title: 'images'}));
});

// Copy All Files At The Root Level (app)
gulp.task('copy', function() {
  return gulp.src([
    'app/*',
    '!app/*.html',
    'node_modules/apache-server-configs/dist/.htaccess'
  ], {
    dot: true
  }).pipe(gulp.dest('dist'))
    .pipe($.size({title: 'copy'}));
});

// Copy Web Fonts To Dist
gulp.task('fonts', function() {
  return gulp.src(['app/fonts/**'])
    .pipe(gulp.dest('dist/fonts'))
    .pipe($.size({title: 'fonts'}));
});

// Compile and Automatically Prefix Stylesheets
gulp.task('styles', function() {
  // For best performance, don't add Sass partials to `gulp.src`
  return gulp.src([
    'app/styles/*.scss',
    'app/styles/**/*.css'
  ])
    .pipe($.changed('styles', {extension: '.scss'}))
    .pipe($.sass({precision: 10}))
    .on('error', console.error.bind(console))
    .pipe($.autoprefixer({browsers: AUTOPREFIXER_BROWSERS}))
    .pipe(gulp.dest('.tmp/styles'))
    .pipe(gulp.dest('dist/styles'))
    .pipe($.size({title: 'styles'}));
});

// Scan Your HTML For Assets & Optimize Them
gulp.task('html', function() {
  var assets = $.useref.assets({searchPath: '{.tmp,app}'});

  return gulp.src('app/index.html')
    .pipe(assets)
    // Concatenate And Minify JavaScript
    .pipe($.if('*.js', $.uglify()))
    // Remove Any Unused CSS
    .pipe($.if('*.css', $.uncss({
      html: [
        'app/index.html'
      ],
      // CSS Selectors for UnCSS to ignore
      ignore: [
        /.js-email-replace/
      ]
    })))
    // Concatenate And Minify Styles
    .pipe($.if('*.css', $.csso()))
    .pipe($.if('*.css', $.minifyCss({keepSpecialComments : 0})))
    .pipe(assets.restore())
    .pipe($.useref())
    // Minify Any HTML
    .pipe($.if('*.html', $.minifyHtml()))
    .pipe($.if('*.html', $.replace('<script src', '<script async defer src')))
    // Output Files
    .pipe(gulp.dest('dist'))
    .pipe($.size({title: 'html'}));
});

// Clean Output Directory
gulp.task('clean', del.bind(null, ['.tmp', 'dist']));

// Watch Files For Changes & Reload
gulp.task('serve', ['styles'], function() {
  browserSync({
    notify: false,
    server: ['.tmp', 'app']
  });

  gulp.watch(['app/index.html'], reload);
  gulp.watch(['app/styles/**/*.{scss,css}'], ['styles', reload]);
  gulp.watch(['app/scripts/**/*.js'], ['lint']);
  gulp.watch(['app/images/**/*'], reload);
});

// Build and serve the output from the dist build
gulp.task('serve:dist', ['default'], function() {
  browserSync({
    notify: false,
    server: 'dist'
  });
});

// Build Production Files, the Default Task
gulp.task('build', ['clean'], function(cb) {
  runSequence('styles', ['lint', 'html', 'images', 'fonts', 'copy'], cb);
});

// Run PageSpeed Insights
// Update `url` below to the public URL for your site
gulp.task('pagespeed', pagespeed.bind(null, {
  // By default, we use the PageSpeed Insights
  // free (no API key) tier. You can use a Google
  // Developer API key if you have one. See
  // http://goo.gl/RkN0vE for info key: 'YOUR_API_KEY'
  url: 'https://thibweb.github.io/thibaudcolas/',
  strategy: 'mobile'
}));

// Deploy to GitHub Pages.
gulp.task('deploy', function() {
  gulp.src('dist/**/*')
    .pipe(deploy('git@github.com:ThibWeb/thibaudcolas.git', 'origin'));
});

// Build Production Files, the Default Task
gulp.task('default', ['build']);

// Load custom tasks from the `tasks` directory
try { require('require-dir')('tasks'); } catch (err) {}
<commit_msg>Configure gulp-sass to stop crashing watcher<commit_after>'use strict';

// Include Gulp & Tools We'll Use
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var del = require('del');
var runSequence = require('run-sequence');
var browserSync = require('browser-sync');
var pagespeed = require('psi');
var reload = browserSync.reload;
var deploy = require('gulp-gh-pages');

var AUTOPREFIXER_BROWSERS = [
  'ie >= 10',
  'ie_mob >= 10',
  'ff >= 30',
  'chrome >= 34',
  'safari >= 7',
  'opera >= 23',
  'ios >= 7',
  'android >= 4.4',
  'bb >= 10'
];

// Lint JavaScript
gulp.task('lint', function() {
  return gulp.src('app/scripts/**/*.js')
    .pipe(reload({stream: true, once: true}))
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
    .pipe($.jscs())
    .pipe($.if(!browserSync.active, $.jshint.reporter('fail')));
});

// Optimize Images
gulp.task('images', function() {
  return gulp.src('app/images/**/*')
    .pipe($.cache($.imagemin({
      progressive: true,
      interlaced: true
    })))
    .pipe(gulp.dest('dist/images'))
    .pipe($.size({title: 'images'}));
});

// Copy All Files At The Root Level (app)
gulp.task('copy', function() {
  return gulp.src([
    'app/*',
    '!app/*.html',
    'node_modules/apache-server-configs/dist/.htaccess'
  ], {
    dot: true
  }).pipe(gulp.dest('dist'))
    .pipe($.size({title: 'copy'}));
});

// Copy Web Fonts To Dist
gulp.task('fonts', function() {
  return gulp.src(['app/fonts/**'])
    .pipe(gulp.dest('dist/fonts'))
    .pipe($.size({title: 'fonts'}));
});

// Compile and Automatically Prefix Stylesheets
gulp.task('styles', function() {
  // For best performance, don't add Sass partials to `gulp.src`
  return gulp.src([
    'app/styles/*.scss',
    'app/styles/**/*.css'
  ])
    .pipe($.changed('styles', {extension: '.scss'}))
    .pipe($.sass({
      errLogToConsole: true,
      precision: 10
    }))
    .on('error', console.error.bind(console))
    .pipe($.autoprefixer({browsers: AUTOPREFIXER_BROWSERS}))
    .pipe(gulp.dest('.tmp/styles'))
    .pipe(gulp.dest('dist/styles'))
    .pipe($.size({title: 'styles'}));
});

// Scan Your HTML For Assets & Optimize Them
gulp.task('html', function() {
  var assets = $.useref.assets({searchPath: '{.tmp,app}'});

  return gulp.src('app/index.html')
    .pipe(assets)
    // Concatenate And Minify JavaScript
    .pipe($.if('*.js', $.uglify()))
    // Remove Any Unused CSS
    .pipe($.if('*.css', $.uncss({
      html: [
        'app/index.html'
      ],
      // CSS Selectors for UnCSS to ignore
      ignore: [
        /.js-email-replace/
      ]
    })))
    // Concatenate And Minify Styles
    .pipe($.if('*.css', $.csso()))
    .pipe($.if('*.css', $.minifyCss({keepSpecialComments : 0})))
    .pipe(assets.restore())
    .pipe($.useref())
    // Minify Any HTML
    .pipe($.if('*.html', $.minifyHtml()))
    .pipe($.if('*.html', $.replace('<script src', '<script async defer src')))
    // Output Files
    .pipe(gulp.dest('dist'))
    .pipe($.size({title: 'html'}));
});

// Clean Output Directory
gulp.task('clean', del.bind(null, ['.tmp', 'dist']));

// Watch Files For Changes & Reload
gulp.task('serve', ['styles'], function() {
  browserSync({
    notify: false,
    server: ['.tmp', 'app']
  });

  gulp.watch(['app/index.html'], reload);
  gulp.watch(['app/styles/**/*.{scss,css}'], ['styles', reload]);
  gulp.watch(['app/scripts/**/*.js'], ['lint']);
  gulp.watch(['app/images/**/*'], reload);
});

// Build and serve the output from the dist build
gulp.task('serve:dist', ['default'], function() {
  browserSync({
    notify: false,
    server: 'dist'
  });
});

// Build Production Files, the Default Task
gulp.task('build', ['clean'], function(cb) {
  runSequence('styles', ['lint', 'html', 'images', 'fonts', 'copy'], cb);
});

// Run PageSpeed Insights
// Update `url` below to the public URL for your site
gulp.task('pagespeed', pagespeed.bind(null, {
  // By default, we use the PageSpeed Insights
  // free (no API key) tier. You can use a Google
  // Developer API key if you have one. See
  // http://goo.gl/RkN0vE for info key: 'YOUR_API_KEY'
  url: 'https://thibweb.github.io/thibaudcolas/',
  strategy: 'mobile'
}));

// Deploy to GitHub Pages.
gulp.task('deploy', function() {
  gulp.src('dist/**/*')
    .pipe(deploy('git@github.com:ThibWeb/thibaudcolas.git', 'origin'));
});

// Build Production Files, the Default Task
gulp.task('default', ['build']);

// Load custom tasks from the `tasks` directory
try { require('require-dir')('tasks'); } catch (err) {}
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
 */

'use strict';

/* eslint-env node */
/* eslint-disable no-console */

const gulp = require('gulp');
const sourcemaps = require('gulp-sourcemaps');
const buffer = require('vinyl-buffer');
const rename = require('gulp-rename');
const rollup = require('rollup-stream');
const source = require('vinyl-source-stream');
const del = require('del');
const bower = require('bower');
const runseq = require('run-sequence');
const closure = require('google-closure-compiler').gulp();

function debugify(sourceName, fileName, needsContext) {
  if (!fileName)
    fileName = sourceName;

  const options = {
    entry: `./entrypoints/${sourceName}-index.js`,
    format: 'iife',
    moduleName: 'webcomponentsjs',
    sourceMap: true
  };

  // The es6-promise polyfill needs to set the correct context.
  // See https://github.com/rollup/rollup/wiki/Troubleshooting#this-is-undefined
  if (needsContext) {
    options.context = 'window';
  }

  return rollup(options)
  .pipe(source(`${sourceName}-index.js`), 'entrypoints')
  .pipe(rename(fileName + '.js'))
  .pipe(gulp.dest('./'))
}

function closurify(sourceName, fileName) {
  if (!fileName) {
    fileName = sourceName;
  }

  const closureOptions = {
    new_type_inf: true,
    compilation_level: 'ADVANCED',
    language_in: 'ES6_STRICT',
    language_out: 'ES5_STRICT',
    output_wrapper: '(function(){\n%output%\n}).call(self)',
    assume_function_wrapper: true,
    js_output_file: `${fileName}.js`,
    warning_level: 'VERBOSE',
    rewrite_polyfills: false,
    externs: [
      'externs/webcomponents.js',
      'bower_components/custom-elements/externs/custom-elements.js',
      'bower_components/html-imports/externs/html-imports.js',
      'bower_components/shadycss/externs/shadycss-externs.js',
      'bower_components/shadydom/externs/shadydom.js'
    ],
    // entry_point: `/entrypoints/${sourceName}-index.js`,
    // dependency_mode: 'STRICT'
  };

  //   const closureSources = [
  //   'src/*.js',
  //   'entrypoints/*.js',
  //   'bower_components/custom-elements/src/**/*.js',
  //   'bower_components/html-imports/src/*.js',
  //   'bower_components/es6-promise/dist/es6-promise.auto.min.js',
  //   'bower_components/webcomponents-platform/*.js',
  //   'bower_components/shadycss/{src,entrypoints}/*.js',
  //   'bower_components/shadydom/src/*.js',
  //   'bower_components/template/*.js'
  // ];

  const rollupOptions = {
    entry: `entrypoints/${sourceName}-index.js`,
    format: 'iife',
    moduleName: 'webcomponents',
    sourceMap: true,
    context: 'window'
  };

  return rollup(rollupOptions)
  .pipe(source(`${sourceName}-index.js`, 'entrypoints'))
  .pipe(buffer())
  .pipe(sourcemaps.init({loadMaps: true}))
  .pipe(closure(closureOptions))
  .pipe(sourcemaps.write('.'))
  .pipe(gulp.dest('.'));

  // return gulp.src(sources, {base: './'})
  // .pipe(sourcemaps.init({loadMaps: true}))
  // .pipe(closure(closureOptions))
  // .pipe(sourcemaps.write('.'))
  // .pipe(gulp.dest('.'));
}

gulp.task('debugify-hi', () => {
  return debugify('webcomponents-hi')
});

gulp.task('debugify-hi-ce', () => {
  return debugify('webcomponents-hi-ce')
});

gulp.task('debugify-hi-sd-ce', () => {
  return debugify('webcomponents-hi-sd-ce')
});

gulp.task('debugify-hi-sd-ce-pf', () => {
  return debugify('webcomponents-hi-sd-ce-pf', 'webcomponents-lite', true)
});

gulp.task('debugify-sd-ce', () => {
  return debugify('webcomponents-sd-ce')
});

gulp.task('closurify-hi', () => {
  return closurify('webcomponents-hi')
});

gulp.task('closurify-hi-ce', () => {
  return closurify('webcomponents-hi-ce')
});

gulp.task('closurify-hi-sd-ce', () => {
  return closurify('webcomponents-hi-sd-ce')
});

gulp.task('closurify-hi-sd-ce-pf', () => {
  return closurify('webcomponents-hi-sd-ce-pf', 'webcomponents-lite')
});

gulp.task('closurify-sd-ce', () => {
  return closurify('webcomponents-sd-ce')
});

gulp.task('refresh-bower', () => {
  return del('bower_components').then(() => {
    let resolve, reject;
    let p = new Promise((res, rej) => {resolve = res; reject = rej});
    bower.commands.install().on('end', () => resolve()).on('error', (e) => reject(e));
    return p;
  });
});

gulp.task('default', (cb) => {
  runseq('refresh-bower', 'closure', cb);
});

gulp.task('clean-builds', () => {
  return del(['webcomponents*.js{,.map}', '!webcomponents-loader.js']);
})

gulp.task('debug', (cb) => {
  const tasks = [
    'debugify-hi',
    'debugify-hi-ce',
    'debugify-hi-sd-ce',
    'debugify-hi-sd-ce-pf',
    'debugify-sd-ce'
  ];
  runseq('clean-builds', tasks, cb);
});

gulp.task('closure', (cb) => {
  const tasks = [
    'closurify-hi',
    'closurify-hi-ce',
    'closurify-hi-sd-ce',
    'closurify-hi-sd-ce-pf',
    'closurify-sd-ce'
  ];
  runseq('clean-builds', ...tasks, cb);
});<commit_msg>[ci skip] oops, no sourcemaps in rollup for debug<commit_after>/**
 * @license
 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
 */

'use strict';

/* eslint-env node */
/* eslint-disable no-console */

const gulp = require('gulp');
const sourcemaps = require('gulp-sourcemaps');
const buffer = require('vinyl-buffer');
const rename = require('gulp-rename');
const rollup = require('rollup-stream');
const source = require('vinyl-source-stream');
const del = require('del');
const bower = require('bower');
const runseq = require('run-sequence');
const closure = require('google-closure-compiler').gulp();

function debugify(sourceName, fileName, needsContext) {
  if (!fileName)
    fileName = sourceName;

  const options = {
    entry: `./entrypoints/${sourceName}-index.js`,
    format: 'iife',
    moduleName: 'webcomponentsjs'
  };

  // The es6-promise polyfill needs to set the correct context.
  // See https://github.com/rollup/rollup/wiki/Troubleshooting#this-is-undefined
  if (needsContext) {
    options.context = 'window';
  }

  return rollup(options)
  .pipe(source(`${sourceName}-index.js`), 'entrypoints')
  .pipe(rename(fileName + '.js'))
  .pipe(gulp.dest('./'))
}

function closurify(sourceName, fileName) {
  if (!fileName) {
    fileName = sourceName;
  }

  const closureOptions = {
    new_type_inf: true,
    compilation_level: 'ADVANCED',
    language_in: 'ES6_STRICT',
    language_out: 'ES5_STRICT',
    output_wrapper: '(function(){\n%output%\n}).call(self)',
    assume_function_wrapper: true,
    js_output_file: `${fileName}.js`,
    warning_level: 'VERBOSE',
    rewrite_polyfills: false,
    externs: [
      'externs/webcomponents.js',
      'bower_components/custom-elements/externs/custom-elements.js',
      'bower_components/html-imports/externs/html-imports.js',
      'bower_components/shadycss/externs/shadycss-externs.js',
      'bower_components/shadydom/externs/shadydom.js'
    ],
    // entry_point: `/entrypoints/${sourceName}-index.js`,
    // dependency_mode: 'STRICT'
  };

  //   const closureSources = [
  //   'src/*.js',
  //   'entrypoints/*.js',
  //   'bower_components/custom-elements/src/**/*.js',
  //   'bower_components/html-imports/src/*.js',
  //   'bower_components/es6-promise/dist/es6-promise.auto.min.js',
  //   'bower_components/webcomponents-platform/*.js',
  //   'bower_components/shadycss/{src,entrypoints}/*.js',
  //   'bower_components/shadydom/src/*.js',
  //   'bower_components/template/*.js'
  // ];

  const rollupOptions = {
    entry: `entrypoints/${sourceName}-index.js`,
    format: 'iife',
    moduleName: 'webcomponents',
    sourceMap: true,
    context: 'window'
  };

  return rollup(rollupOptions)
  .pipe(source(`${sourceName}-index.js`, 'entrypoints'))
  .pipe(buffer())
  .pipe(sourcemaps.init({loadMaps: true}))
  .pipe(closure(closureOptions))
  .pipe(sourcemaps.write('.'))
  .pipe(gulp.dest('.'));

  // return gulp.src(sources, {base: './'})
  // .pipe(sourcemaps.init({loadMaps: true}))
  // .pipe(closure(closureOptions))
  // .pipe(sourcemaps.write('.'))
  // .pipe(gulp.dest('.'));
}

gulp.task('debugify-hi', () => {
  return debugify('webcomponents-hi')
});

gulp.task('debugify-hi-ce', () => {
  return debugify('webcomponents-hi-ce')
});

gulp.task('debugify-hi-sd-ce', () => {
  return debugify('webcomponents-hi-sd-ce')
});

gulp.task('debugify-hi-sd-ce-pf', () => {
  return debugify('webcomponents-hi-sd-ce-pf', 'webcomponents-lite', true)
});

gulp.task('debugify-sd-ce', () => {
  return debugify('webcomponents-sd-ce')
});

gulp.task('closurify-hi', () => {
  return closurify('webcomponents-hi')
});

gulp.task('closurify-hi-ce', () => {
  return closurify('webcomponents-hi-ce')
});

gulp.task('closurify-hi-sd-ce', () => {
  return closurify('webcomponents-hi-sd-ce')
});

gulp.task('closurify-hi-sd-ce-pf', () => {
  return closurify('webcomponents-hi-sd-ce-pf', 'webcomponents-lite')
});

gulp.task('closurify-sd-ce', () => {
  return closurify('webcomponents-sd-ce')
});

gulp.task('refresh-bower', () => {
  return del('bower_components').then(() => {
    let resolve, reject;
    let p = new Promise((res, rej) => {resolve = res; reject = rej});
    bower.commands.install().on('end', () => resolve()).on('error', (e) => reject(e));
    return p;
  });
});

gulp.task('default', (cb) => {
  runseq('refresh-bower', 'closure', cb);
});

gulp.task('clean-builds', () => {
  return del(['webcomponents*.js{,.map}', '!webcomponents-loader.js']);
})

gulp.task('debug', (cb) => {
  const tasks = [
    'debugify-hi',
    'debugify-hi-ce',
    'debugify-hi-sd-ce',
    'debugify-hi-sd-ce-pf',
    'debugify-sd-ce'
  ];
  runseq('clean-builds', tasks, cb);
});

gulp.task('closure', (cb) => {
  const tasks = [
    'closurify-hi',
    'closurify-hi-ce',
    'closurify-hi-sd-ce',
    'closurify-hi-sd-ce-pf',
    'closurify-sd-ce'
  ];
  runseq('clean-builds', ...tasks, cb);
});<|endoftext|>


<commit_before>var gulp = require('gulp');
var jsd2md = require('gulp-jsdoc-to-markdown');
var replace = require('gulp-just-replace');
var rename = require("gulp-rename");
var gutil = require("gulp-util");
var me = require('./package.json');
var del = require('del');

console.log(me.name);

gulp.task('replace', function(){
  return gulp.src("readme_template.hbs").
  pipe(replace([
    {
      search: '%%NAME%%',
      replacement: me.name
    },
    {
      search: '%%DESCRIPTION%%',
      replacement: me.description
    }
  ]))
  .pipe(rename('readme.hbs'))
  .pipe(gulp.dest('./'))
})

gulp.task('doc-build', ['replace'], function(){
  var options = {template: "./readme.hbs"};
  return gulp.src('todoist.js')
  .pipe(jsd2md(options))
  .on("error", function(err){
    gutil.log(gutil.colors.red("jsdoc2md failed"), err.message)
  })
  .pipe(rename('README.md'))
  .pipe(gulp.dest('./'))
})

gulp.task('docs',['doc-build'], function(cb){
  return del(['readme.hbs'], cb);
})

gulp.task('default',['docs']);
<commit_msg>spacing and organization in gulpfile<commit_after>var gulp = require('gulp');
var jsd2md = require('gulp-jsdoc-to-markdown');
var replace = require('gulp-just-replace');
var rename = require("gulp-rename");
var gutil = require("gulp-util");
var del = require('del');
var me = require('./package.json');

console.log(me.name);

gulp.task('replace', function(){
  return gulp.src("readme_template.hbs").
  pipe(replace([
    {
      search: '%%NAME%%',
      replacement: me.name
    },
    {
      search: '%%DESCRIPTION%%',
      replacement: me.description
    }
  ]))
  .pipe(rename('readme.hbs'))
  .pipe(gulp.dest('./'))
})

gulp.task('doc-build', ['replace'], function(){
  var options = {template: "./readme.hbs"};
  return gulp.src('todoist.js')
  .pipe(jsd2md(options))
  .on("error", function(err){
    gutil.log(gutil.colors.red("jsdoc2md failed"), err.message)
  })
  .pipe(rename('README.md'))
  .pipe(gulp.dest('./'))
})

gulp.task('docs',['doc-build'], function(cb){
  return del(['readme.hbs'], cb);
})

gulp.task('default',['docs']);
<|endoftext|>


<commit_before>/**
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

"use strict";

const gulp = require('gulp-help')(require('gulp'));
const gls = require('gulp-live-server');
const file = require('gulp-file');
const rename = require('gulp-rename');
const del = require('del');
const cache = require('gulp-cached');
const shell = require('gulp-shell');
const jasmine = require('gulp-jasmine');
const eslint = require('gulp-eslint');
const gutil = require('gulp-util');
const gulpIf = require('gulp-if');
const favicons = require("gulp-favicons");
const runSequence = require('run-sequence');
const argv = require('yargs').argv;
const path = require('path');

const index = require('./tasks/compile-index');
const validateExample = require('./tasks/validate-example');
const compileExample = require('./tasks/compile-example');
const createExample = require('./tasks/create-example');
const FileName = require('./tasks/lib/FileName');
const Metadata = require('./tasks/lib/Metadata');

const SAMPLES_DIR = './src/';
const TEMPLATES_DIR = './templates/';

gulp.task('serve', 'starts a local webserver (--port specifies bound port)',
  function() {
    const port = argv.port || 8000;
    const server = gls.static('dist', port);
    server.start();
    gulp.watch(['dist/*.html',
                'dist/img/*.{png,jpg,gif}',
                'dist/video/*.{mp4,webm}'], function(file) {
      /* eslint-disable */
      server.notify.apply(server, [file]);
      /* eslint-enable */
    });
  });

gulp.task('deploy:prod', 'deploy to production server', function(callback) {
  runSequence('clean',
              'build',
              'deploy:appeng:prod',
              callback);
});

gulp.task('deploy:staging', 'deploy to staging server', function(callback) {
  runSequence('clean',
              'build',
              'deploy:appeng:staging',
              callback);
});

gulp.task('deploy:appeng:prod', 'deploy to production app engine', shell.task([
  'goapp deploy -application  amp-by-example -version 1'
]));

gulp.task('deploy:appeng:staging', 'deploy to staging app engine', shell.task([
  'goapp deploy -application  amp-by-example-staging -version 1'
]));

gulp.task('copy:images', 'copy example images', function() {
  return gulp.src(SAMPLES_DIR + 'img/*.{png,jpg,gif}')
      .pipe(cache('img'))
      .pipe(gulp.dest('dist/img'));
});

gulp.task('copy:videos', 'copy example videos', function() {
  return gulp.src(SAMPLES_DIR + 'video/*.{mp4,webm}')
      .pipe(cache('video'))
      .pipe(gulp.dest('dist/video'));
});

gulp.task('copy:license', 'copy license', function() {
  return gulp.src('LICENSE')
      .pipe(cache('static'))
      .pipe(rename(function(path) {
        path.extname = ".txt";
      }))
      .pipe(gulp.dest('dist'));
});

gulp.task('copy:static', 'copy static files', function() {
  return gulp.src('static/*.*')
      .pipe(cache('static'))
      .pipe(gulp.dest('dist'));
});

gulp.task("compile:favicons", function() {
  return gulp.src(SAMPLES_DIR + 'img/favicon.png')
      .pipe(cache('static'))
      .pipe(favicons({
        appName: "AMP by Example",
        appDescription: "Accelerated Mobile Pages in Action",
        developerName: "Sebastian Benz",
        developerURL: "http://sebastianbenz.de/",
        background: "#fff",
        path: "favicons/",
        url: Metadata.HOST,
        display: "standalone",
        orientation: "portrait",
        version: 1.0,
        logging: false,
        online: false,
        html: "favicons.html",
        pipeHTML: true,
        replace: true
      }))
      .on("error", gutil.log)
      .pipe(gulp.dest("dist/favicons"));
});

gulp.task('validate:example', 'validate example html files', function() {
  return gulp.src('src/*.html')
    .pipe(compileExample('./src/templates/', 'example.html'))
    .pipe(validateExample('./src/templates/', 'example.html'));
});

gulp.task('compile:example', 'compile example html files', function() {
  return gulp.src(SAMPLES_DIR + '*/*.html')
      .pipe(compileExample(TEMPLATES_DIR, 'example.html'))
      .pipe(gulp.dest('dist'));
});

gulp.task('compile:index', 'generate index.html', function() {
  return gulp.src(SAMPLES_DIR + '*/*.html')
      .pipe(index('index.html',TEMPLATES_DIR, 'index.html'))
      .pipe(gulp.dest('dist'));
});

gulp.task('create', 'create a new AMP example', function() {
  const title = argv.n || argv.name;
  const fileName = FileName.fromString(title);
  if (!fileName) {
    throwInvalidArgumentError('example name missing');
  }
  let examplePath;
  const dest = argv.d || argv.dest;
  const category = argv.c || argv.category;
  if (dest) {
    examplePath = path.join(path.basename(dest), fileName);
  } else if (category) {
    examplePath = FileName.fromString(category, title);
  } else {
    throwInvalidArgumentError('example category or directory missing');
  }
  return file(examplePath, '', {src: true})
      .pipe(createExample(TEMPLATES_DIR, 'new-example.html'))
      .pipe(gulp.dest(SAMPLES_DIR));
});

function throwInvalidArgumentError(message) {
  throw new gutil.PluginError({
    plugin: 'create',
    message: gutil.colors.red('\nError: ' + message + '\n\n') +
        gutil.colors.blue('create a new category:\n') +
        'gulp create -n "The Name" -c "The Category"\n\n' +
        gutil.colors.blue('add to existing category:\n') +
        'gulp create -n "The Name" -d src/directory'
  });
}

gulp.task('clean', 'delete all generated resources', function() {
  cache.caches = {};
  return del(['dist']);
});

gulp.task('watch', 'watch for changes in the examples', function() {
  gulp.watch(['src/**/*.html', 'src/**/*.css'],
             ['compile:example', 'compile:index']);
  gulp.watch('src/img/*.{png,jpg,gif}', ['copy:images']);
});

gulp.task('test', function() {
  return gulp.src('spec/**/*Spec.js')
      .pipe(jasmine());
});

gulp.task('lint', function() {
  const hasFixFlag = argv.fix;
  let errorsFound = false;
  return gulp.src(['tasks/**/*.js', 'gulpfile.js'], {base: './'})
      .pipe(eslint({fix: hasFixFlag}))
      .pipe(eslint.formatEach('stylish', function(msg) {
        errorsFound = true;
        gutil.log(gutil.colors.red(msg));
      }))
      .pipe(gulpIf(isFixed, gulp.dest('.')))
      .on('end', function() {
        if (errorsFound && !hasFixFlag) {
          gutil.log(gutil.colors.blue('Run `gulp lint --fix` to ' +
          'fix some of these lint warnings/errors. This is a destructive ' +
          'operation (operates on the file system) so please make sure ' +
          'you commit before running.'));
          process.exit(1);
        }
      });
});

gulp.task('default', 'Run a webserver and watch for changes', [
  'build',
  'watch',
  'serve']);

gulp.task('validate', 'validate all examples', [
  'validate:example']);

gulp.task('build', 'build all resources', [
  'copy:images',
  'copy:videos',
  'copy:license',
  'copy:static',
  'compile:favicons',
  'compile:example',
  'compile:index']);

function isFixed(file) {
  return file.eslint.fixed;
}

<commit_msg>fix trailing whitespace<commit_after>/**
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

"use strict";

const gulp = require('gulp-help')(require('gulp'));
const gls = require('gulp-live-server');
const file = require('gulp-file');
const rename = require('gulp-rename');
const del = require('del');
const cache = require('gulp-cached');
const shell = require('gulp-shell');
const jasmine = require('gulp-jasmine');
const eslint = require('gulp-eslint');
const gutil = require('gulp-util');
const gulpIf = require('gulp-if');
const favicons = require("gulp-favicons");
const runSequence = require('run-sequence');
const argv = require('yargs').argv;
const path = require('path');

const index = require('./tasks/compile-index');
const validateExample = require('./tasks/validate-example');
const compileExample = require('./tasks/compile-example');
const createExample = require('./tasks/create-example');
const FileName = require('./tasks/lib/FileName');
const Metadata = require('./tasks/lib/Metadata');

const SAMPLES_DIR = './src/';
const TEMPLATES_DIR = './templates/';

gulp.task('serve', 'starts a local webserver (--port specifies bound port)',
  function() {
    const port = argv.port || 8000;
    const server = gls.static('dist', port);
    server.start();
    gulp.watch(['dist/*.html',
                'dist/img/*.{png,jpg,gif}',
                'dist/video/*.{mp4,webm}'], function(file) {
      /* eslint-disable */
      server.notify.apply(server, [file]);
      /* eslint-enable */
    });
  });

gulp.task('deploy:prod', 'deploy to production server', function(callback) {
  runSequence('clean',
              'build',
              'deploy:appeng:prod',
              callback);
});

gulp.task('deploy:staging', 'deploy to staging server', function(callback) {
  runSequence('clean',
              'build',
              'deploy:appeng:staging',
              callback);
});

gulp.task('deploy:appeng:prod', 'deploy to production app engine', shell.task([
  'goapp deploy -application  amp-by-example -version 1'
]));

gulp.task('deploy:appeng:staging', 'deploy to staging app engine', shell.task([
  'goapp deploy -application  amp-by-example-staging -version 1'
]));

gulp.task('copy:images', 'copy example images', function() {
  return gulp.src(SAMPLES_DIR + 'img/*.{png,jpg,gif}')
      .pipe(cache('img'))
      .pipe(gulp.dest('dist/img'));
});

gulp.task('copy:videos', 'copy example videos', function() {
  return gulp.src(SAMPLES_DIR + 'video/*.{mp4,webm}')
      .pipe(cache('video'))
      .pipe(gulp.dest('dist/video'));
});

gulp.task('copy:license', 'copy license', function() {
  return gulp.src('LICENSE')
      .pipe(cache('static'))
      .pipe(rename(function(path) {
        path.extname = ".txt";
      }))
      .pipe(gulp.dest('dist'));
});

gulp.task('copy:static', 'copy static files', function() {
  return gulp.src('static/*.*')
      .pipe(cache('static'))
      .pipe(gulp.dest('dist'));
});

gulp.task("compile:favicons", function() {
  return gulp.src(SAMPLES_DIR + 'img/favicon.png')
      .pipe(cache('static'))
      .pipe(favicons({
        appName: "AMP by Example",
        appDescription: "Accelerated Mobile Pages in Action",
        developerName: "Sebastian Benz",
        developerURL: "http://sebastianbenz.de/",
        background: "#fff",
        path: "favicons/",
        url: Metadata.HOST,
        display: "standalone",
        orientation: "portrait",
        version: 1.0,
        logging: false,
        online: false,
        html: "favicons.html",
        pipeHTML: true,
        replace: true
      }))
      .on("error", gutil.log)
      .pipe(gulp.dest("dist/favicons"));
});

gulp.task('validate:example', 'validate example html files', function() {
  return gulp.src('src/*.html')
    .pipe(compileExample('./src/templates/', 'example.html'))
    .pipe(validateExample('./src/templates/', 'example.html'));
});

gulp.task('compile:example', 'compile example html files', function() {
  return gulp.src(SAMPLES_DIR + '*/*.html')
      .pipe(compileExample(TEMPLATES_DIR, 'example.html'))
      .pipe(gulp.dest('dist'));
});

gulp.task('compile:index', 'generate index.html', function() {
  return gulp.src(SAMPLES_DIR + '*/*.html')
      .pipe(index('index.html',TEMPLATES_DIR, 'index.html'))
      .pipe(gulp.dest('dist'));
});

gulp.task('create', 'create a new AMP example', function() {
  const title = argv.n || argv.name;
  const fileName = FileName.fromString(title);
  if (!fileName) {
    throwInvalidArgumentError('example name missing');
  }
  let examplePath;
  const dest = argv.d || argv.dest;
  const category = argv.c || argv.category;
  if (dest) {
    examplePath = path.join(path.basename(dest), fileName);
  } else if (category) {
    examplePath = FileName.fromString(category, title);
  } else {
    throwInvalidArgumentError('example category or directory missing');
  }
  return file(examplePath, '', {src: true})
      .pipe(createExample(TEMPLATES_DIR, 'new-example.html'))
      .pipe(gulp.dest(SAMPLES_DIR));
});

function throwInvalidArgumentError(message) {
  throw new gutil.PluginError({
    plugin: 'create',
    message: gutil.colors.red('\nError: ' + message + '\n\n') +
        gutil.colors.blue('create a new category:\n') +
        'gulp create -n "The Name" -c "The Category"\n\n' +
        gutil.colors.blue('add to existing category:\n') +
        'gulp create -n "The Name" -d src/directory'
  });
}

gulp.task('clean', 'delete all generated resources', function() {
  cache.caches = {};
  return del(['dist']);
});

gulp.task('watch', 'watch for changes in the examples', function() {
  gulp.watch(['src/**/*.html', 'src/**/*.css'],
             ['compile:example', 'compile:index']);
  gulp.watch('src/img/*.{png,jpg,gif}', ['copy:images']);
});

gulp.task('test', function() {
  return gulp.src('spec/**/*Spec.js')
      .pipe(jasmine());
});

gulp.task('lint', function() {
  const hasFixFlag = argv.fix;
  let errorsFound = false;
  return gulp.src(['tasks/**/*.js', 'gulpfile.js'], {base: './'})
      .pipe(eslint({fix: hasFixFlag}))
      .pipe(eslint.formatEach('stylish', function(msg) {
        errorsFound = true;
        gutil.log(gutil.colors.red(msg));
      }))
      .pipe(gulpIf(isFixed, gulp.dest('.')))
      .on('end', function() {
        if (errorsFound && !hasFixFlag) {
          gutil.log(gutil.colors.blue('Run `gulp lint --fix` to ' +
          'fix some of these lint warnings/errors. This is a destructive ' +
          'operation (operates on the file system) so please make sure ' +
          'you commit before running.'));
          process.exit(1);
        }
      });
});

gulp.task('default', 'Run a webserver and watch for changes', [
  'build',
  'watch',
  'serve']);

gulp.task('validate', 'validate all examples', [
  'validate:example']);

gulp.task('build', 'build all resources', [
  'copy:images',
  'copy:videos',
  'copy:license',
  'copy:static',
  'compile:favicons',
  'compile:example',
  'compile:index']);

function isFixed(file) {
  return file.eslint.fixed;
}

<|endoftext|>