<commit_before>var xml = require('xml');
var generatorName = 'Feed for Node.js';

// ============================================================================
// Feed Main Module
// ============================================================================
function Feed(options) {
    this.title       = options.title;
    this.description = options.description;
    this.link        = options.link;
    this.image       = options.image;
    this.copyright   = options.copyright;
    this.feed        = options.feed;
    this.hub         = options.hub;
    this.updated     = options.updated;

    this.author      = options.author;          // Atom only (at channel level)

    this.items       = [];
    this.categories  = [];
    this.contributors = [];     				// Atom only

    this.addItem = function (options) {
        options = options || {};
        var item = {
            title:          options.title,
            link:           options.link,
            description:    options.description,
            date:           options.date,
            image:          options.image,
            author:         options.author,
            contributor:    options.contributor,	// Atom only
            guid:           options.guid,
            content:        options.content,
            copyright:		options.copyright	// Atom only
        };

        this.items.push(item);
        return this;
    }

    this.addCategory = function (category) {
        this.categories.push(category);
        return this;
    }

    this.addContributor = function (contributor) {
        this.contributors.push(contributor);
        return this;
    }

    this.render = function (format) {
        switch(format) {
            case 'rss-2.0':
                return rss_2_0(this);
            break;

            case 'atom-1.0':
                return atom_1_0(this);
            break;

            default:
                return rss_2_0(this);
        }
    };

    /**
     * DEPRECATED METHODS
     */
    this.item = function (options)  {
        console.warn('DEPRECATED: use addItem() instead of item()');
        return this.addItem(options);
    }

    this.category = function (category) {
        console.warn('DEPRECATED: use addCategory() instead of category()');
        return this.addCategory(category);
    }
};

// ============================================================================
// Atom 1.0 [application/atom+xml]
//
// - Reference: http://www.atomenabled.org/developers/syndication/
// ============================================================================

function atom_1_0(options) {
    var items       = [],
        container   = [],
        feed        = [],

        entries     = options.items,
        categories  = options.categories,
        author      = options.author,
        contributors = options.contributors,
        d           = new Date();

    var doctype = '<?xml version="1.0" encoding="utf-8"?>\n';

    container.push({ feed: feed });
    feed.push({ _attr: { xmlns: 'http://www.w3.org/2005/Atom' }});

    /**************************************************************************
     * "feed" node: REQUIRED elements
     *************************************************************************/

    if(options.title == undefined)
        throw new Error('feed title is mandatory');
    else
        feed.push({ title: options.title });

    if(options.link == undefined)
        throw new Error('feed link is mandatory');
    else
        if(!validateURL(options.link))
            throw new Error('invalid feed link');
        else
            feed.push({ link: options.link });

    if(Object.prototype.toString.call(options.updated) === '[object Date]')
        feed.push({ updated: RFC3339(options.updated) });
    else
       feed.push({ updated: RFC3339(d) });

    /**************************************************************************
     * "feed" node: recommended elements
     *************************************************************************/

    if(author) {
        var authorDetails = [];

        if(author.name)
            authorDetails.push({ name:     author.name });

        if(author.email)
            authorDetails.push({ email:     author.email });

        if(author.link)
            authorDetails.push({ uri:     author.link });

        feed.push({ author: authorDetails });
    }

    // link (rel="alternate")
    if(options.link)
        feed.push({ link: { _attr: { rel: 'alternate', href: options.link }}});

    // link (rel="self")
    if(options.feed)
        feed.push({ link: { _attr: { rel: 'self', href: options.feed }}});

    // link (rel="hub")
    if(options.hub)
        feed.push({ link: { _attr: { rel:'hub', href: options.hub }}});

    /**************************************************************************
     * "feed" node: optional elements
     *************************************************************************/

    if(options.description)
        feed.push({ subtitle:   options.description });

    if(options.image)
        feed.push({ logo:       options.image });

    if(options.copyright)
        feed.push({ rights:     options.copyright });

    feed.push({ generator:      generatorName });

    // Looping through categories (if any set!)
    for(var i=0; i<categories.length; i++)
        feed.push({ category: [{ _attr: { term: categories[i] } }] });

    if(contributors) {
    	for(var y = 0; y < contributors.length; y++) {
	        var contributorDetails = [];

	        if(contributors[y].name)
	        	contributorDetails.push({ name:     contributors[y].name });

	        if(contributors[y].email)
	        	contributorDetails.push({ email:     contributors[y].email });

	        if(contributors[y].link)
	            authorDetails.push({ uri:     contributors[y].link });

	        feed.push({ contributor: contributorDetails });
    	}
    }

    // icon

    /**************************************************************************
     * "entry" nodes
     *************************************************************************/
    for(var i = 0; i < entries.length; i++) {
        //
        // entry: required elements
        //
        if(entries[i].title == undefined)
            throw new Error('entry need a title');

        if(entries[i].link == undefined)
            throw new Error('entry need a link');
        else
            if(!validateURL(entries[i].link))
                throw new Error('invalid entry link');

        if(entries[i].date == undefined || !(entries[i].date instanceof Date))
            throw new Error('entry need a date');

        var entry = [
            { title:        { _attr: { type: 'html' }, _cdata: entries[i].title }},
            { id:           entries[i].link },
            { link:         [{ _attr: { href: entries[i].link } }]},
            { updated:      RFC3339(entries[i].date) }
        ];

        //
        // entry: recommended elements
        //
        if(entries[i].description)
            entry.push({ summary: { _attr: { type: 'html' }, _cdata: entries[i].description }});

        if(entries[i].content)
            entry.push({ content: { _attr: { type: 'html' }, _cdata: entries[i].content }});

        // entry author(s)
        if(entries[i].author) {
            for(var y = 0; y < entries[i].author.length; y++) {
                var entryAuthor = [];

                if(entries[i].author[y].name)
                    entryAuthor.push({ name: entries[i].author[y].name });

                if(entries[i].author[y].email)
                    entryAuthor.push({ email: entries[i].author[y].email });

                if(entries[i].author[y].link)
                    entryAuthor.push({ uri: entries[i].author[y].link });

                entry.push({ author: entryAuthor });
            }
        }

        // content

        // link - relative link to article

        //
        // entry: optional elements
        //

        // category

        // contributor
        if(entries[i].contributor) {
            for(var y = 0; y < entries[i].contributor.length; y++) {
                var entryContributor = [];

                if(entries[i].contributor[y].name)
                    entryContributor.push({ name: entries[i].contributor[y].name });

                if(entries[i].contributor[y].email)
                    entryContributor.push({ email: entries[i].contributor[y].email });

                if(entries[i].contributor[y].link)
                    entryContributor.push({ uri: entries[i].contributor[y].link });

                entry.push({ contributor: entryContributor });
            }
        }

        // published

        // source

        // rights
        if(entries[i].copyright)
        	entry.push({ rights: entries[i].copyright });

        feed.push({ entry: entry });
    }

    return doctype + xml(container, true);
}

// ============================================================================
// Real Simple Syndication 2.0 (RSS 2.0)
//
// - Reference: http://feed2.w3.org/docs/rss2.html
// ============================================================================
function rss_2_0(options) {
    var items       = [],
        channel     = [],
        container   = [];

    var items = options.items;
    var categories = options.categories;
    var d = new Date();
    var bContent = false;
    var bAtom = false;

    var doctype = '<?xml version="1.0" encoding="utf-8"?>\n';

    container.push({ rss: [] });
    container[0].rss.push({ _attr: { version: '2.0' } });
    container[0].rss.push({ channel: channel });

    /**
     * Required Channel Elements
     * http://cyber.law.harvard.edu/rss/rss.html#requiredChannelElements
     */
    if(options.title == undefined)
        throw new Error('channel title is mandatory');
    else
        channel.push({ title: options.title });

    if(options.description == undefined)
        throw new Error('channel description is mandatory');
    else
        channel.push({ description: options.description });

    if(options.link == undefined)
        throw new Error('channel link is mandatory');
    else
        if(!validateURL(options.link))
            throw new Error('invalid channel link');
        else
            channel.push({ link: options.link });

    if(Object.prototype.toString.call(options.updated) === '[object Date]')
        channel.push({ lastBuildDate: options.updated.toUTCString() });
    else
       channel.push({ lastBuildDate: d.toUTCString() });

    channel.push({ docs: 'http://blogs.law.harvard.edu/tech/rss'});

    /**
     * Channel Image
     * http://cyber.law.harvard.edu/rss/rss.html#ltimagegtSubelementOfLtchannelgt
     */
    if(options.image)
        channel.push({
            image: [
                { title: options.title },
                { url: options.image },
                { link: options.link }
            ]
        });

    /**
     * Channel Copyright
     * http://cyber.law.harvard.edu/rss/rss.html#optionalChannelElements
     */
    if(options.copyright)
        channel.push({ copyright: options.copyright });

    channel.push({ generator: generatorName });

    /**
     * Channel Categories
     * http://cyber.law.harvard.edu/rss/rss.html#comments
     */
    for(var i = 0; i < categories.length; i++)
        channel.push({ category: categories[i] });

    /**
     * Feed URL
     * http://validator.w3.org/feed/docs/warning/MissingAtomSelfLink.html
     */
    if(options.feed) {
        bAtom = true;
        channel.push({ "atom:link": { _attr: { href: options.feed, rel: 'self', type: 'application/rss+xml' }}});
    }

    /**
     * Hub for PubSubHubbub
     * https://code.google.com/p/pubsubhubbub/
     */
    if(options.hub) {
        bAtom = true;
        channel.push({ "atom:link": { _attr: { href: options.hub, rel: 'hub' }}});
    }

    /**
     * Channel Categories
     * http://cyber.law.harvard.edu/rss/rss.html#hrelementsOfLtitemgt
     */
    for(var i = 0; i < items.length; i++) {

        // You need to have at least a title OR a description
        if(!items[i].title && !items[i].description)
            throw new Error('item must have at least a title or a description');

        var item = [];

        if(items[i].title)
            item.push({ title: { _cdata: items[i].title }});

        if(items[i].link)
            item.push({ link: items[i].link });

        if(items[i].guid)
            item.push({ guid: items[i].guid });
        else if (items[i].link)
            item.push({ guid: items[i].link });

        if(items[i].date)
            item.push({ pubDate: items[i].date.toUTCString() });

        if(items[i].description)
            item.push({ description: { _cdata: items[i].description }});

        if(items[i].content)
            bContent = true;
            item.push({ 'content:encoded': { _cdata: items[i].content }});

        /**
         * Item Author
         * http://cyber.law.harvard.edu/rss/rss.html#ltauthorgtSubelementOfLtitemgt
         */
        if(items[i].author) {
            for(var y = 0; y < items[i].author.length; y++) {
                var itemAuthor = [];

                if(items[i].author[y].name)
                    itemAuthor.push({ name: items[i].author[y].name });

                if(items[i].author[y].email)
                    itemAuthor.push({ email: items[i].author[y].email });

                if(items[i].author[y].link)
                    itemAuthor.push({ link: items[i].author[y].link });

                item.push({ author: itemAuthor });
            }
        }

        if(items[i].image)
            item.push({ enclosure: [{ _attr: { url: items[i].image } }] });

        channel.push({ item: item });
    }

    if(bContent)
        container[0].rss[0]._attr['xmlns:content'] = 'http://purl.org/rss/1.0/modules/content/';

    if(bAtom)
        container[0].rss[0]._attr['xmlns:atom'] = 'http://www.w3.org/2005/Atom';

    return doctype + xml(container, true);
}

function RFC3339(d) {
    function pad(n) { return n < 10 ? '0' + n : n }

    return d.getUTCFullYear()+'-'
        + pad(d.getUTCMonth()+1)+'-'
        + pad(d.getUTCDate())+'T'
        + pad(d.getUTCHours())+':'
        + pad(d.getUTCMinutes())+':'
        + pad(d.getUTCSeconds())+'Z'
}

function validateURL(str) {
    var urlPattern = /^(?:(?:https?):\/\/)?(?:\S+(?::\S*)?@)?(?:(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))|localhost)(?::\d{2,5})?(?:\/[^\s]*)?$/i;

    return urlPattern.test(str);
}

module.exports = Feed;<commit_msg>fixing parenthesis<commit_after>var xml = require('xml');
var generatorName = 'Feed for Node.js';

// ============================================================================
// Feed Main Module
// ============================================================================
function Feed(options) {
    this.title       = options.title;
    this.description = options.description;
    this.link        = options.link;
    this.image       = options.image;
    this.copyright   = options.copyright;
    this.feed        = options.feed;
    this.hub         = options.hub;
    this.updated     = options.updated;

    this.author      = options.author;          // Atom only (at channel level)

    this.items       = [];
    this.categories  = [];
    this.contributors = [];     				// Atom only

    this.addItem = function (options) {
        options = options || {};
        var item = {
            title:          options.title,
            link:           options.link,
            description:    options.description,
            date:           options.date,
            image:          options.image,
            author:         options.author,
            contributor:    options.contributor,	// Atom only
            guid:           options.guid,
            content:        options.content,
            copyright:		options.copyright	// Atom only
        };

        this.items.push(item);
        return this;
    }

    this.addCategory = function (category) {
        this.categories.push(category);
        return this;
    }

    this.addContributor = function (contributor) {
        this.contributors.push(contributor);
        return this;
    }

    this.render = function (format) {
        switch(format) {
            case 'rss-2.0':
                return rss_2_0(this);
            break;

            case 'atom-1.0':
                return atom_1_0(this);
            break;

            default:
                return rss_2_0(this);
        }
    };

    /**
     * DEPRECATED METHODS
     */
    this.item = function (options)  {
        console.warn('DEPRECATED: use addItem() instead of item()');
        return this.addItem(options);
    }

    this.category = function (category) {
        console.warn('DEPRECATED: use addCategory() instead of category()');
        return this.addCategory(category);
    }
};

// ============================================================================
// Atom 1.0 [application/atom+xml]
//
// - Reference: http://www.atomenabled.org/developers/syndication/
// ============================================================================

function atom_1_0(options) {
    var items       = [],
        container   = [],
        feed        = [],

        entries     = options.items,
        categories  = options.categories,
        author      = options.author,
        contributors = options.contributors,
        d           = new Date();

    var doctype = '<?xml version="1.0" encoding="utf-8"?>\n';

    container.push({ feed: feed });
    feed.push({ _attr: { xmlns: 'http://www.w3.org/2005/Atom' }});

    /**************************************************************************
     * "feed" node: REQUIRED elements
     *************************************************************************/

    if(options.title == undefined)
        throw new Error('feed title is mandatory');
    else
        feed.push({ title: options.title });

    if(options.link == undefined)
        throw new Error('feed link is mandatory');
    else
        if(!validateURL(options.link))
            throw new Error('invalid feed link');
        else
            feed.push({ link: options.link });

    if(Object.prototype.toString.call(options.updated) === '[object Date]')
        feed.push({ updated: RFC3339(options.updated) });
    else
       feed.push({ updated: RFC3339(d) });

    /**************************************************************************
     * "feed" node: recommended elements
     *************************************************************************/

    if(author) {
        var authorDetails = [];

        if(author.name)
            authorDetails.push({ name:     author.name });

        if(author.email)
            authorDetails.push({ email:     author.email });

        if(author.link)
            authorDetails.push({ uri:     author.link });

        feed.push({ author: authorDetails });
    }

    // link (rel="alternate")
    if(options.link)
        feed.push({ link: { _attr: { rel: 'alternate', href: options.link }}});

    // link (rel="self")
    if(options.feed)
        feed.push({ link: { _attr: { rel: 'self', href: options.feed }}});

    // link (rel="hub")
    if(options.hub)
        feed.push({ link: { _attr: { rel:'hub', href: options.hub }}});

    /**************************************************************************
     * "feed" node: optional elements
     *************************************************************************/

    if(options.description)
        feed.push({ subtitle:   options.description });

    if(options.image)
        feed.push({ logo:       options.image });

    if(options.copyright)
        feed.push({ rights:     options.copyright });

    feed.push({ generator:      generatorName });

    // Looping through categories (if any set!)
    for(var i=0; i<categories.length; i++)
        feed.push({ category: [{ _attr: { term: categories[i] } }] });

    if(contributors) {
    	for(var y = 0; y < contributors.length; y++) {
	        var contributorDetails = [];

	        if(contributors[y].name)
	        	contributorDetails.push({ name:     contributors[y].name });

	        if(contributors[y].email)
	        	contributorDetails.push({ email:     contributors[y].email });

	        if(contributors[y].link)
	            authorDetails.push({ uri:     contributors[y].link });

	        feed.push({ contributor: contributorDetails });
    	}
    }

    // icon

    /**************************************************************************
     * "entry" nodes
     *************************************************************************/
    for(var i = 0; i < entries.length; i++) {
        //
        // entry: required elements
        //
        if(entries[i].title == undefined)
            throw new Error('entry need a title');

        if(entries[i].link == undefined)
            throw new Error('entry need a link');
        else
            if(!validateURL(entries[i].link))
                throw new Error('invalid entry link');

        if(entries[i].date == undefined || !(entries[i].date instanceof Date))
            throw new Error('entry need a date');

        var entry = [
            { title:        { _attr: { type: 'html' }, _cdata: entries[i].title }},
            { id:           entries[i].link },
            { link:         [{ _attr: { href: entries[i].link } }]},
            { updated:      RFC3339(entries[i].date) }
        ];

        //
        // entry: recommended elements
        //
        if(entries[i].description)
            entry.push({ summary: { _attr: { type: 'html' }, _cdata: entries[i].description }});

        if(entries[i].content)
            entry.push({ content: { _attr: { type: 'html' }, _cdata: entries[i].content }});

        // entry author(s)
        if(entries[i].author) {
            for(var y = 0; y < entries[i].author.length; y++) {
                var entryAuthor = [];

                if(entries[i].author[y].name)
                    entryAuthor.push({ name: entries[i].author[y].name });

                if(entries[i].author[y].email)
                    entryAuthor.push({ email: entries[i].author[y].email });

                if(entries[i].author[y].link)
                    entryAuthor.push({ uri: entries[i].author[y].link });

                entry.push({ author: entryAuthor });
            }
        }

        // content

        // link - relative link to article

        //
        // entry: optional elements
        //

        // category

        // contributor
        if(entries[i].contributor) {
            for(var y = 0; y < entries[i].contributor.length; y++) {
                var entryContributor = [];

                if(entries[i].contributor[y].name)
                    entryContributor.push({ name: entries[i].contributor[y].name });

                if(entries[i].contributor[y].email)
                    entryContributor.push({ email: entries[i].contributor[y].email });

                if(entries[i].contributor[y].link)
                    entryContributor.push({ uri: entries[i].contributor[y].link });

                entry.push({ contributor: entryContributor });
            }
        }

        // published

        // source

        // rights
        if(entries[i].copyright)
        	entry.push({ rights: entries[i].copyright });

        feed.push({ entry: entry });
    }

    return doctype + xml(container, true);
}

// ============================================================================
// Real Simple Syndication 2.0 (RSS 2.0)
//
// - Reference: http://feed2.w3.org/docs/rss2.html
// ============================================================================
function rss_2_0(options) {
    var items       = [],
        channel     = [],
        container   = [];

    var items = options.items;
    var categories = options.categories;
    var d = new Date();
    var bContent = false;
    var bAtom = false;

    var doctype = '<?xml version="1.0" encoding="utf-8"?>\n';

    container.push({ rss: [] });
    container[0].rss.push({ _attr: { version: '2.0' } });
    container[0].rss.push({ channel: channel });

    /**
     * Required Channel Elements
     * http://cyber.law.harvard.edu/rss/rss.html#requiredChannelElements
     */
    if(options.title == undefined)
        throw new Error('channel title is mandatory');
    else
        channel.push({ title: options.title });

    if(options.description == undefined)
        throw new Error('channel description is mandatory');
    else
        channel.push({ description: options.description });

    if(options.link == undefined)
        throw new Error('channel link is mandatory');
    else
        if(!validateURL(options.link))
            throw new Error('invalid channel link');
        else
            channel.push({ link: options.link });

    if(Object.prototype.toString.call(options.updated) === '[object Date]')
        channel.push({ lastBuildDate: options.updated.toUTCString() });
    else
       channel.push({ lastBuildDate: d.toUTCString() });

    channel.push({ docs: 'http://blogs.law.harvard.edu/tech/rss'});

    /**
     * Channel Image
     * http://cyber.law.harvard.edu/rss/rss.html#ltimagegtSubelementOfLtchannelgt
     */
    if(options.image)
        channel.push({
            image: [
                { title: options.title },
                { url: options.image },
                { link: options.link }
            ]
        });

    /**
     * Channel Copyright
     * http://cyber.law.harvard.edu/rss/rss.html#optionalChannelElements
     */
    if(options.copyright)
        channel.push({ copyright: options.copyright });

    channel.push({ generator: generatorName });

    /**
     * Channel Categories
     * http://cyber.law.harvard.edu/rss/rss.html#comments
     */
    for(var i = 0; i < categories.length; i++)
        channel.push({ category: categories[i] });

    /**
     * Feed URL
     * http://validator.w3.org/feed/docs/warning/MissingAtomSelfLink.html
     */
    if(options.feed) {
        bAtom = true;
        channel.push({ "atom:link": { _attr: { href: options.feed, rel: 'self', type: 'application/rss+xml' }}});
    }

    /**
     * Hub for PubSubHubbub
     * https://code.google.com/p/pubsubhubbub/
     */
    if(options.hub) {
        bAtom = true;
        channel.push({ "atom:link": { _attr: { href: options.hub, rel: 'hub' }}});
    }

    /**
     * Channel Categories
     * http://cyber.law.harvard.edu/rss/rss.html#hrelementsOfLtitemgt
     */
    for(var i = 0; i < items.length; i++) {

        // You need to have at least a title OR a description
        if(!items[i].title && !items[i].description)
            throw new Error('item must have at least a title or a description');

        var item = [];

        if(items[i].title)
            item.push({ title: { _cdata: items[i].title }});

        if(items[i].link)
            item.push({ link: items[i].link });

        if(items[i].guid)
            item.push({ guid: items[i].guid });
        else if (items[i].link)
            item.push({ guid: items[i].link });

        if(items[i].date)
            item.push({ pubDate: items[i].date.toUTCString() });

        if(items[i].description)
            item.push({ description: { _cdata: items[i].description }});

        if(items[i].content) {
            bContent = true;
            item.push({ 'content:encoded': { _cdata: items[i].content }});
        }
        /**
         * Item Author
         * http://cyber.law.harvard.edu/rss/rss.html#ltauthorgtSubelementOfLtitemgt
         */
        if(items[i].author) {
            for(var y = 0; y < items[i].author.length; y++) {
                var itemAuthor = [];

                if(items[i].author[y].name)
                    itemAuthor.push({ name: items[i].author[y].name });

                if(items[i].author[y].email)
                    itemAuthor.push({ email: items[i].author[y].email });

                if(items[i].author[y].link)
                    itemAuthor.push({ link: items[i].author[y].link });

                item.push({ author: itemAuthor });
            }
        }

        if(items[i].image)
            item.push({ enclosure: [{ _attr: { url: items[i].image } }] });

        channel.push({ item: item });
    }

    if(bContent)
        container[0].rss[0]._attr['xmlns:content'] = 'http://purl.org/rss/1.0/modules/content/';

    if(bAtom)
        container[0].rss[0]._attr['xmlns:atom'] = 'http://www.w3.org/2005/Atom';

    return doctype + xml(container, true);
}

function RFC3339(d) {
    function pad(n) { return n < 10 ? '0' + n : n }

    return d.getUTCFullYear()+'-'
        + pad(d.getUTCMonth()+1)+'-'
        + pad(d.getUTCDate())+'T'
        + pad(d.getUTCHours())+':'
        + pad(d.getUTCMinutes())+':'
        + pad(d.getUTCSeconds())+'Z'
}

function validateURL(str) {
    var urlPattern = /^(?:(?:https?):\/\/)?(?:\S+(?::\S*)?@)?(?:(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))|localhost)(?::\d{2,5})?(?:\/[^\s]*)?$/i;

    return urlPattern.test(str);
}

module.exports = Feed;
<|endoftext|>


<commit_before>var BotKit = require('botkit');
module.exports = Ears;

var Bot = BotKit.slackbot({
  debug: false,
  storage: undefined
});

function Ears(token) {
  this.scopes = [
    'direct_mention',
    'direct_message',
    'mention'
  ];
  this.token = token;
}

Ears.prototype.listen = function(db) {
  console.log('TOKEN: ' + this.token);
  this.bot = Bot.spawn({
    token: this.token
  }).startRTM();

    var id = db.saveSync("rps",{player1: '', player2:''});
    // @ https://api.slack.com/methods/users.list
    this.bot.api.users.list({}, function (err, response) {
        if (response.hasOwnProperty('members') && response.ok) {
            var total = response.members.length;
            for (var i = 0; i < total; i++) {
                var member = response.members[i];
                var id = db.saveSync(member.id,{name: member.name, rpswin:'0',rpsloss:'0'});
                //fullTeamList.push({name: member.name, id: member.id});
            }
        }
    });
  return this;
}

Ears.prototype.hear = function(pattern, callback) {
  Bot.hears(pattern, this.scopes, callback);
  return this;
};
<commit_msg>Update ears.js<commit_after>var BotKit = require('botkit');
module.exports = Ears;

var Bot = BotKit.slackbot({
  debug: false,
  storage: undefined
});

function Ears(token) {
  this.scopes = [
    'direct_mention',
    'direct_message',
    'mention'
  ];
  this.token = token;
}

Ears.prototype.listen = function(db) {
  console.log('TOKEN: ' + this.token);
  this.bot = Bot.spawn({
    token: this.token
  }).startRTM();

    var id = db.saveSync("rps",{played: ''});
    // @ https://api.slack.com/methods/users.list
    this.bot.api.users.list({}, function (err, response) {
        if (response.hasOwnProperty('members') && response.ok) {
            var total = response.members.length;
            for (var i = 0; i < total; i++) {
                var member = response.members[i];
                var id = db.saveSync(member.id,{name: member.name, rpswin:'0',rpsloss:'0'});
                //fullTeamList.push({name: member.name, id: member.id});
            }
        }
    });
  return this;
}

Ears.prototype.hear = function(pattern, callback) {
  Bot.hears(pattern, this.scopes, callback);
  return this;
};
<|endoftext|>


<commit_before>'use strict';

// An QueryRequest is used to represent a RethinkDB query that a component is
// subscribed to. It should be used for values in the object returned from the
// observe() function of components that use the provided mixin. See Mixin.js
// for the API.
//
// QueryRequests have have 3 required properties.
// * query:   the RethinkDB query to run
// * changes: boolean specifying whether to subscribe to the realtime
//            changefeed too
// * initial: value to be returned before the query finishes loading
//
// Here is a simple example of an QueryRequest that a component might use in
// its observe() function:
//   new QueryRequest({
//     query: r.table('turtles'),
//     changes: true,
//     initial: [],
//   })
export class QueryRequest {
  constructor({query, changes, initial}) {
    this.query = query;
    this.changes = changes;
    this.initial = initial;
  }

  // Convert the QueryRequest into a string that can be used as a
  // deterministic lookup key in an object. The key should be identical for two
  // QueryRequests that need access to the same data.
  //
  // TODO We should recursively sort object keys, using something like
  // json-stable-stringify. But let's do that for query validation in
  // rethinkdb-websocket-server first, after confirming that object sort order is
  // ignored in RethinkDB.
  //
  // TODO This isn't perfectly deterministic for queries with anonymous
  // functions, since the variable identifier keeps incrementing when we create
  // new "identical" queries.
  // E.g. r.table('turtles').filter(x => x('herdId').eq(props.herdId))
  toStringKey() {
    return JSON.stringify({
      query: this.query.build(),
      changes: this.changes,
    });
  }
}
<commit_msg>Comment more on queries with anonymous functions<commit_after>'use strict';

// An QueryRequest is used to represent a RethinkDB query that a component is
// subscribed to. It should be used for values in the object returned from the
// observe() function of components that use the provided mixin. See Mixin.js
// for the API.
//
// QueryRequests have have 3 required properties.
// * query:   the RethinkDB query to run
// * changes: boolean specifying whether to subscribe to the realtime
//            changefeed too
// * initial: value to be returned before the query finishes loading
//
// Here is a simple example of an QueryRequest that a component might use in
// its observe() function:
//   new QueryRequest({
//     query: r.table('turtles'),
//     changes: true,
//     initial: [],
//   })
export class QueryRequest {
  constructor({query, changes, initial}) {
    this.query = query;
    this.changes = changes;
    this.initial = initial;
  }

  // Convert the QueryRequest into a string that can be used as a
  // deterministic lookup key in an object. The key should be identical for two
  // QueryRequests that need access to the same data.
  //
  // TODO We should recursively sort object keys, using something like
  // json-stable-stringify. But let's do that for query validation in
  // rethinkdb-websocket-server first, after confirming that object sort order is
  // ignored in RethinkDB.
  //
  // TODO This isn't perfectly deterministic for queries with anonymous
  // functions, since the variable identifier keeps incrementing when we create
  // new "identical" queries.
  // E.g. r.table('turtles').filter(x => x('herdId').eq(props.herdId))
  // It looks like the RethinkDB JavaScript driver has to maintain a global
  // nextVarId counter which can increment between the creation of identical
  // queries. This is probably necessary so that queries that contain multiple
  // functions won't have overlapping var ids. One possible approach is to
  // "normalize" var ids as a query preprocessing step: replace each var id
  // with an index in which that var id was first seen in the query. Further
  // research needs to be done to determine if that is safe.  This approach has
  // a disadvantage of being harder to debug query issues when queries are
  // being altered.
  toStringKey() {
    return JSON.stringify({
      query: this.query.build(),
      changes: this.changes,
    });
  }
}
<|endoftext|>


<commit_before>import { sortDate } from '../../utils/sort.js'
import { isNumber, isDate } from '../../utils/is.js'

export default {
  props: {
    sortMethod: {
      type: Function,
      default (data, sortBy, descending) {
        const col = this.columns.find(def => def.name === sortBy)
        if (col === null || col.field === void 0) {
          return data
        }

        const
          dir = descending === true ? -1 : 1,
          val = typeof col.field === 'function'
            ? v => col.field(v)
            : v => v[col.field]

        return data.sort((a, b) => {
          let
            A = val(a),
            B = val(b)

          if (A === null || A === void 0) {
            return -1 * dir
          }
          if (B === null || B === void 0) {
            return 1 * dir
          }
          if (col.sort !== void 0) {
            return col.sort(A, B, a, b) * dir
          }
          if (isNumber(A) === true && isNumber(B) === true) {
            return (A - B) * dir
          }
          if (isDate(A) === true && isDate(B) === true) {
            return sortDate(A, B) * dir
          }
          if (typeof A === 'boolean' && typeof B === 'boolean') {
            return (A - B) * dir
          }

          [A, B] = [A, B].map(s => (s + '').toLocaleString().toLowerCase())

          return A < B
            ? -1 * dir
            : (A === B ? 0 : dir)
        })
      }
    }
  },

  computed: {
    columnToSort () {
      const { sortBy } = this.computedPagination

      if (sortBy) {
        return this.columns.find(def => def.name === sortBy) || null
      }
    }
  },

  methods: {
    sort (col /* String(col name) or Object(col definition) */) {
      if (col === Object(col)) {
        col = col.name
      }

      let { sortBy, descending } = this.computedPagination

      if (sortBy !== col) {
        sortBy = col
        descending = false
      }
      else if (this.binaryStateSort === true) {
        descending = !descending
      }
      else if (descending === true) {
        sortBy = null
      }
      else {
        descending = true
      }

      this.setPagination({ sortBy, descending, page: 1 })
    }
  }
}
<commit_msg>fix(ui): table sort issue (#5670)<commit_after>import { sortDate } from '../../utils/sort.js'
import { isNumber, isDate } from '../../utils/is.js'

export default {
  props: {
    sortMethod: {
      type: Function,
      default (data, sortBy, descending) {
        const col = this.columns.find(def => def.name === sortBy)
        if (col === void 0 || col.field === void 0) {
          return data
        }

        const
          dir = descending === true ? -1 : 1,
          val = typeof col.field === 'function'
            ? v => col.field(v)
            : v => v[col.field]

        return data.sort((a, b) => {
          let
            A = val(a),
            B = val(b)

          if (A === null || A === void 0) {
            return -1 * dir
          }
          if (B === null || B === void 0) {
            return 1 * dir
          }
          if (col.sort !== void 0) {
            return col.sort(A, B, a, b) * dir
          }
          if (isNumber(A) === true && isNumber(B) === true) {
            return (A - B) * dir
          }
          if (isDate(A) === true && isDate(B) === true) {
            return sortDate(A, B) * dir
          }
          if (typeof A === 'boolean' && typeof B === 'boolean') {
            return (A - B) * dir
          }

          [A, B] = [A, B].map(s => (s + '').toLocaleString().toLowerCase())

          return A < B
            ? -1 * dir
            : (A === B ? 0 : dir)
        })
      }
    }
  },

  computed: {
    columnToSort () {
      const { sortBy } = this.computedPagination

      if (sortBy) {
        return this.columns.find(def => def.name === sortBy) || null
      }
    }
  },

  methods: {
    sort (col /* String(col name) or Object(col definition) */) {
      if (col === Object(col)) {
        col = col.name
      }

      let { sortBy, descending } = this.computedPagination

      if (sortBy !== col) {
        sortBy = col
        descending = false
      }
      else if (this.binaryStateSort === true) {
        descending = !descending
      }
      else if (descending === true) {
        sortBy = null
      }
      else {
        descending = true
      }

      this.setPagination({ sortBy, descending, page: 1 })
    }
  }
}
<|endoftext|>


<commit_before>'use strict';
var path = require('path');
var fs = require('fs');

// File is responsible to gather all information related to a given parsed file, as:
//  - its dir and name
//  - its content
//  - the search paths where referecned resource will be looked at
//  - the list of parsed blocks
//

//
// Returns an array object of all the directives for the given html.
// Each item of the array has the following form:
//
//
//     {
//       type: 'css',
//       dest: 'css/site.css',
//       src: [
//         'css/normalize.css',
//         'css/main.css'
//       ],
//       raw: [
//         '    <!-- build:css css/site.css -->',
//         '    <link rel="stylesheet" href="css/normalize.css">',
//         '    <link rel="stylesheet" href="css/main.css">',
//         '    <!-- endbuild -->'
//       ]
//     }
//
// Note also that dest is expressed relatively from the root. I.e., if the block starts with:
//    <!-- build:css /foo/css/site.css -->
// then dest will equal foo/css/site.css (note missing trailing /)
//
var getBlocks = function (content) {
  // start build pattern: will match
  //  * <!-- build:[target] output -->
  //  * <!-- build:[target](alternate search path) output -->
  // The following matching param are set when there's match
  //   * 0 : the whole matched expression
  //   * 1 : the target (ie. type)
  //   * 2 : the alternate search path
  //   * 3 : the output
  //
  var regbuild = /<!--\s*build:(\w+)(?:\(([^\)]+)\))?\s*([^\s]+)\s*-->/;
  // end build pattern -- <!-- endbuild -->
  var regend = /<!--\s*endbuild\s*-->/;

  var lines = content.replace(/\r\n/g, '\n').split(/\n/),
    block = false,
    sections = [],
    last;

  lines.forEach(function (l) {
    var indent = (l.match(/^\s*/) || [])[0];
    var build = l.match(regbuild);
    var endbuild = regend.test(l);
    var startFromRoot = false;

    // discard empty lines
    if (build) {
      block = true;
      // Handle absolute path (i.e. with respect to the server root)
      // if (build[3][0] === '/') {
      //   startFromRoot = true;
      //   build[3] = build[3].substr(1);
      // }
      last = {
        type: build[1],
        dest: build[3],
        startFromRoot: startFromRoot,
        indent: indent,
        searchPath: [],
        src: [],
        raw: []
      };

      if (build[2]) {
        // Alternate search path
        last.searchPath.push(build[2]);
      }
    }
    // Check IE conditionals
    var isConditionalStart = l.match(/<!--\[[^\]]+\]>/);
    var isConditionalEnd = l.match(/<!\[endif\]-->/);
    if (block && isConditionalStart) {
      last.conditionalStart = isConditionalStart;
    }
    if (block && isConditionalEnd) {
      last.conditionalEnd = isConditionalEnd;
    }

    // switch back block flag when endbuild
    if (block && endbuild) {
      last.raw.push(l);
      sections.push(last);
      block = false;
    }

    if (block && last) {
      var asset = l.match(/(href|src)=["']([^'"]+)["']/);
      if (asset && asset[2]) {
        last.src.push(asset[2]);

        var media = l.match(/media=['"]([^'"]+)['"]/);
        // FIXME: media attribute should be present for all members of the block *and* having the same value
        if ( media ) {
          last.media = media[1];
        }

        // preserve defer attribute
        var defer = / defer/.test(l);
        if (defer && last.defer === false || last.defer && !defer) {
          throw new Error('Error: You are not suppose to mix deferred and non-deferred scripts in one block.');
        } else if (defer) {
          last.defer = true;
        } else {
          last.defer = false;
        }

        // RequireJS uses a data-main attribute on the script tag to tell it
        // to load up the main entry point of the amp app
        //
        // If we find one, we must record the name of the main entry point,
        // as well the name of the destination file, and treat
        // the furnished requirejs as an asset (src)
        var main = l.match(/data-main=['"]([^'"]+)['"]/);
        if (main) {
          throw new Error('require.js blocks are no more supported.');
        }
      }
      last.raw.push(l);
    }
  });

  return sections;
};

module.exports = function( filepath ) {

  this.dir = path.dirname(filepath);
  this.name = path.basename(filepath);
  // By default referenced content will be looked at relative to the location
  // of the file
  this.searchPath = [this.dir];
  this.content = fs.readFileSync(filepath).toString();

  // Let's parse !!!
  this.blocks = getBlocks(this.content);
};
<commit_msg>updated getBlocks build and end regex for jade<commit_after>'use strict';
var path = require('path');
var fs = require('fs');

// File is responsible to gather all information related to a given parsed file, as:
//  - its dir and name
//  - its content
//  - the search paths where referecned resource will be looked at
//  - the list of parsed blocks
//

//
// Returns an array object of all the directives for the given html.
// Each item of the array has the following form:
//
//
//     {
//       type: 'css',
//       dest: 'css/site.css',
//       src: [
//         'css/normalize.css',
//         'css/main.css'
//       ],
//       raw: [
//         '    <!-- build:css css/site.css -->',
//         '    <link rel="stylesheet" href="css/normalize.css">',
//         '    <link rel="stylesheet" href="css/main.css">',
//         '    <!-- endbuild -->'
//       ]
//     }
//
// Note also that dest is expressed relatively from the root. I.e., if the block starts with:
//    <!-- build:css /foo/css/site.css -->
// then dest will equal foo/css/site.css (note missing trailing /)
//
var getBlocks = function (content) {
  // start build pattern: will match
  //  * <!-- build:[target] output -->
  //  * <!-- build:[target](alternate search path) output -->
  // The following matching param are set when there's match
  //   * 0 : the whole matched expression
  //   * 1 : the target (ie. type)
  //   * 2 : the alternate search path
  //   * 3 : the output
  //
  var regbuild = /\/\/\s*build:(\w+)(?:\(([^\)]+)\))?\s*([^\s]+)\s*/;
  // end build pattern -- <!-- endbuild -->
  var regend = /\/\/\s*endbuild\s*/;

  var lines = content.replace(/\r\n/g, '\n').split(/\n/),
    block = false,
    sections = [],
    last;

  lines.forEach(function (l) {
    var indent = (l.match(/^\s*/) || [])[0];
    var build = l.match(regbuild);
    var endbuild = regend.test(l);
    var startFromRoot = false;

    // discard empty lines
    if (build) {
      block = true;
      // Handle absolute path (i.e. with respect to the server root)
      // if (build[3][0] === '/') {
      //   startFromRoot = true;
      //   build[3] = build[3].substr(1);
      // }
      last = {
        type: build[1],
        dest: build[3],
        startFromRoot: startFromRoot,
        indent: indent,
        searchPath: [],
        src: [],
        raw: []
      };

      if (build[2]) {
        // Alternate search path
        last.searchPath.push(build[2]);
      }
    }
    // Check IE conditionals
    var isConditionalStart = l.match(/<!--\[[^\]]+\]>/);
    var isConditionalEnd = l.match(/<!\[endif\]-->/);
    if (block && isConditionalStart) {
      last.conditionalStart = isConditionalStart;
    }
    if (block && isConditionalEnd) {
      last.conditionalEnd = isConditionalEnd;
    }

    // switch back block flag when endbuild
    if (block && endbuild) {
      last.raw.push(l);
      sections.push(last);
      block = false;
    }

    if (block && last) {
      var asset = l.match(/(href|src)=["']([^'"]+)["']/);
      if (asset && asset[2]) {
        last.src.push(asset[2]);

        var media = l.match(/media=['"]([^'"]+)['"]/);
        // FIXME: media attribute should be present for all members of the block *and* having the same value
        if ( media ) {
          last.media = media[1];
        }

        // preserve defer attribute
        var defer = / defer/.test(l);
        if (defer && last.defer === false || last.defer && !defer) {
          throw new Error('Error: You are not suppose to mix deferred and non-deferred scripts in one block.');
        } else if (defer) {
          last.defer = true;
        } else {
          last.defer = false;
        }

        // RequireJS uses a data-main attribute on the script tag to tell it
        // to load up the main entry point of the amp app
        //
        // If we find one, we must record the name of the main entry point,
        // as well the name of the destination file, and treat
        // the furnished requirejs as an asset (src)
        var main = l.match(/data-main=['"]([^'"]+)['"]/);
        if (main) {
          throw new Error('require.js blocks are no more supported.');
        }
      }
      last.raw.push(l);
    }
  });

  return sections;
};

module.exports = function( filepath ) {

  this.dir = path.dirname(filepath);
  this.name = path.basename(filepath);
  // By default referenced content will be looked at relative to the location
  // of the file
  this.searchPath = [this.dir];
  this.content = fs.readFileSync(filepath).toString();

  // Let's parse !!!
  this.blocks = getBlocks(this.content);
};
<|endoftext|>


<commit_before>// Firefox user.js

// -----------------------------------------------------------------------------
// Startup
// -----------------------------------------------------------------------------

// Show a blank page when opening homepage and new window.
user_pref("browser.startup.page", 0);
user_pref("browser.startup.homepage", "about:blank");
user_pref("browser.startup.homepage_override.mstone", "ignore");

// Show a blank page when opening new tab.
user_pref("browser.newtabpage.enabled", false);
user_pref("browser.newtab.preload", false);

// Disable Activity Stream.
user_pref("browser.newtabpage.activity-stream.default.sites", "");
user_pref("browser.newtabpage.activity-stream.feeds.discoverystreamfeed", false);
user_pref("browser.newtabpage.activity-stream.feeds.section.highlights", false);
user_pref("browser.newtabpage.activity-stream.feeds.section.topstories", false);
user_pref("browser.newtabpage.activity-stream.feeds.snippets", false);
user_pref("browser.newtabpage.activity-stream.feeds.telemetry", false);
user_pref("browser.newtabpage.activity-stream.feeds.topsites", false);
user_pref("browser.newtabpage.activity-stream.showSearch", false);
user_pref("browser.newtabpage.activity-stream.showSponsored", false);
user_pref("browser.newtabpage.activity-stream.telemetry", false);

// -----------------------------------------------------------------------------
// Localization
// -----------------------------------------------------------------------------

// Set preferred language for displaying pages.
user_pref("intl.accept_languages", "ja,zh-tw,zh,en-us,en");

// Disable region updates.
user_pref("browser.region.update.enabled", false);
user_pref("browser.region.network.url", "");

// -----------------------------------------------------------------------------
// Content
// -----------------------------------------------------------------------------

// Set the minimum font size.
user_pref("font.minimum-size.ja", 10);
user_pref("font.minimum-size.ko", 10);
user_pref("font.minimum-size.zh-CN", 10);
user_pref("font.minimum-size.zh-HK", 10);
user_pref("font.minimum-size.zh-TW", 10);

// Disable WebRTC.
user_pref("media.peerconnection.enabled", false);
user_pref("media.peerconnection.ice.default_address_only", true);
user_pref("media.peerconnection.ice.no_host", true);
user_pref("media.peerconnection.ice.proxy_only_if_behind_proxy", true);

// Disable media device enumeration.
user_pref("media.navigator.enabled", false);

// Block all audio and video autoplay.
user_pref("media.autoplay.default", 5);
user_pref("media.autoplay.blocking_policy", 0);

// Block new requests asking for permissions.
user_pref("permissions.default.geo", 2);
user_pref("permissions.default.camera", 2);
user_pref("permissions.default.microphone", 2);
user_pref("permissions.default.desktop-notification", 2);
user_pref("permissions.default.xr", 2);
user_pref("permissions.default.shortcuts", 2);

// Block pop-up windows.
user_pref("dom.disable_open_during_load", true);
user_pref("dom.popup_allowed_events", "click dblclick mousedown mouseup pointerdown pointerup");

// Enforce all links to be opened in new tabs.
user_pref("browser.link.open_newwindow", 3);
user_pref("browser.link.open_newwindow.restriction", 0);

// Disallow JavaScript to move and resize windows.
user_pref("dom.disable_window_move_resize", true);

// -----------------------------------------------------------------------------
// Network
// -----------------------------------------------------------------------------

// Disable prefetching.
user_pref("network.prefetch-next", false);
user_pref("network.predictor.enabled", false);
user_pref("network.predictor.enable-prefetch", false);
user_pref("network.dns.disablePrefetch", true);
user_pref("network.dns.disablePrefetchFromHTTPS", true);

// Disable making speculative connections when mouseover.
user_pref("network.http.speculative-parallel-limit", 0);

// Disable sending additional analytics to web servers.
user_pref("beacon.enabled", false);

// Disable sending full referer header across origins.
user_pref("network.http.referer.XOriginPolicy", 1);
user_pref("network.http.referer.XOriginTrimmingPolicy", 2);

// Disable HTTP authentication credentials dialogs triggered by cross-origin
// sub-resources.
user_pref("network.auth.subresource-http-auth-allow", 1);

// Disable Captive Portal detection.
user_pref("network.captive-portal-service.enabled", false);
user_pref("captivedetect.canonicalURL", "");

// Disable Network Connectivity checks.
user_pref("network.connectivity-service.enabled", false);

// Disable automatic Work Offline mode.
user_pref("network.manage-offline-status", false);

// Enable proxying DNS when using SOCKS v5.
user_pref("network.proxy.socks_remote_dns", true);

// -----------------------------------------------------------------------------
// Privacy
// -----------------------------------------------------------------------------

// Block all third-party cookies.
user_pref("network.cookie.cookieBehavior", 1);
user_pref("browser.contentblocking.category", "custom");

// Enable FPI (First Party Isolation).
user_pref("privacy.firstparty.isolate", true);

// Enable Enhanced Tracking Protection.
user_pref("privacy.trackingprotection.enabled", true);
user_pref("privacy.trackingprotection.pbmode.enabled", true);
user_pref("privacy.trackingprotection.cryptomining.enabled", true);
user_pref("privacy.trackingprotection.fingerprinting.enabled", true);
user_pref("privacy.trackingprotection.socialtracking.enabled", true);

// Enable DNT (Do Not Track) HTTP header.
user_pref("privacy.donottrackheader.enabled", true);

// Disable Telemetry.
user_pref("toolkit.telemetry.unified", false);
user_pref("toolkit.telemetry.enabled", false);
user_pref("toolkit.telemetry.server", "data:,");
user_pref("toolkit.telemetry.archive.enabled", false);
user_pref("toolkit.telemetry.bhrPing.enabled", false);
user_pref("toolkit.telemetry.firstShutdownPing.enabled", false);
user_pref("toolkit.telemetry.newProfilePing.enabled", false);
user_pref("toolkit.telemetry.shutdownPingSender.enabled", false);
user_pref("toolkit.telemetry.updatePing.enabled", false);

// Disable Telemetry Coverage.
user_pref("toolkit.telemetry.coverage.opt-out", true);
user_pref("toolkit.coverage.opt-out", true);
user_pref("toolkit.coverage.endpoint.base", "");

// Disable Health Report.
user_pref("datareporting.healthreport.uploadEnabled", false);
user_pref("datareporting.policy.dataSubmissionEnabled", false);

// Disable Shield Studies.
user_pref("app.shield.optoutstudies.enabled", false);

// Disable Normandy Telemetry.
user_pref("app.normandy.enabled", false);
user_pref("app.normandy.api_url", "");

// Disable sending file information to Google Safe Browsing service.
user_pref("browser.safebrowsing.downloads.remote.enabled", false);
user_pref("browser.safebrowsing.downloads.remote.url", "");

// Disable sending browser crash reports.
user_pref("breakpad.reportURL", "");
user_pref("browser.tabs.crashReporting.sendReport", false);
user_pref("browser.crashReports.unsubmittedCheck.enabled", false);
user_pref("browser.crashReports.unsubmittedCheck.autoSubmit2", false);

// -----------------------------------------------------------------------------
// Security
// -----------------------------------------------------------------------------

// Disable saving logins and passwords.
user_pref("signon.rememberSignons", false);

// Enforce OCSP (Online Certificate Status Protocol) stapling.
user_pref("security.ssl.enable_ocsp_stapling", true);
user_pref("security.OCSP.enabled", 1);
user_pref("security.OCSP.require", true);

// Enforce CSP (Content Security Policy).
user_pref("security.csp.enable", true);

// Enforce no insecure content on HTTPS pages.
user_pref("security.mixed_content.block_active_content", true);
user_pref("security.mixed_content.block_display_content", true);

// -----------------------------------------------------------------------------
// Search
// -----------------------------------------------------------------------------

// Disable search engine updates.
user_pref("browser.search.update", false);

// Enable search suggestions in all windows.
user_pref("browser.search.suggest.enabled", true);
user_pref("browser.search.suggest.enabled.private", true);
user_pref("browser.urlbar.suggest.searches", true);

// Show search suggestions behind other suggestions.
user_pref("browser.urlbar.showSearchSuggestionsFirst", false);

// -----------------------------------------------------------------------------
// Features
// -----------------------------------------------------------------------------

// Disable Firefox Accounts and Sync.
user_pref("identity.fxaccounts.enabled", false);

// Disable Reader View.
user_pref("reader.parse-on-load.enabled", false);

// Disable UITour backend.
user_pref("browser.uitour.enabled", false);
user_pref("browser.uitour.url", "");

// Disable various developer tools.
user_pref("devtools.chrome.enabled", false);
user_pref("devtools.debugger.remote-enabled", false);

// -----------------------------------------------------------------------------
// Add-ons
// -----------------------------------------------------------------------------

// Enable all extensions in Private Windows by default.
user_pref("extensions.allowPrivateBrowsingByDefault", true);

// Disable enforced extension signing in Developer Edition, Nightly and ESR.
user_pref("xpinstall.signatures.required", false);

// Disable extension recommendations in about:addons.
user_pref("extensions.getAddons.showPane", false);
user_pref("extensions.htmlaboutaddons.recommendations.enabled", false);

// Disable extension recommendations when browsing.
user_pref("browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons", false);
user_pref("browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features", false);

// Disable third-party extension install prompts.
user_pref("extensions.postDownloadThirdPartyPrompt", false);

// Disable system add-on updates.
user_pref("extensions.systemAddon.update.enabled", false);
user_pref("extensions.systemAddon.update.url", "");

// Disable Form Autofill.
user_pref("extensions.formautofill.available", "off");
user_pref("extensions.formautofill.addresses.enabled", false);
user_pref("extensions.formautofill.creditCards.available", false);
user_pref("extensions.formautofill.creditCards.enabled", false);
user_pref("extensions.formautofill.heuristics.enabled", false);

// Disable Pocket.
user_pref("extensions.pocket.enabled", false);

// Disable Web Compatibility Reporter.
user_pref("extensions.webcompat-reporter.enabled", false);

// Disable Gecko Media Plugins.
user_pref("media.gmp-provider.enabled", false);
user_pref("media.gmp-gmpopenh264.enabled", false);
user_pref("media.gmp-widevinecdm.enabled", false);

// Disable DRM-controlled content.
user_pref("media.eme.enabled", false);

// -----------------------------------------------------------------------------
// System
// -----------------------------------------------------------------------------

// Disable automatic Firefox updates.
user_pref("app.update.auto", false);

// Disable accessibility services.
user_pref("accessibility.force_disabled", 1);

// Disable disk cache.
user_pref("browser.cache.disk.enable", false);
user_pref("browser.cache.offline.storage.enable", false);
user_pref("browser.privatebrowsing.forceMediaMemoryCache", true);
user_pref("media.memory_cache_max_size", 65536);

// Disable saving page thumbnails.
user_pref("browser.pagethumbnails.capturing_disabled", true);

// Disable saving shortcut favicons.
user_pref("browser.shell.shortcutFavicons", false);

// Set the maximum number of bookmark backups to keep.
user_pref("browser.bookmarks.max_backups", 5);

// Set the minimum interval between session save operations.
user_pref("browser.sessionstore.interval", 60000);

// Always ask where to save files.
user_pref("browser.download.useDownloadDir", false);

// Disable adding downloads to Recent Documents.
user_pref("browser.download.manager.addToRecentDocs", false);

// Disable automatic start and session restore after Windows reboot.
user_pref("toolkit.winRegisterApplicationRestart", false);

// -----------------------------------------------------------------------------
// Appearance
// -----------------------------------------------------------------------------

// Enable userChrome.css and userContent.css customizations.
user_pref("toolkit.legacyUserProfileCustomizations.stylesheets", true);

// Disable site-specific zoom level.
user_pref("browser.zoom.siteSpecific", false);

// Show the full URL in address bar.
user_pref("browser.urlbar.trimURLs", false);

// Show the Punycode for IDNs (Internationalized Domain Names) in address bar.
user_pref("network.IDN_show_punycode", true);

// Show "Downloads" button in toolbar.
user_pref("browser.download.autohideButton", false);

// Hide "What's New" button in toolbar.
user_pref("browser.messaging-system.whatsNewPanel.enabled", false);

// Show weak encryption warning in address bar.
user_pref("security.ssl.require_safe_negotiation", false);
user_pref("security.ssl.treat_unsafe_negotiation_as_broken", true);

// Show advanced information in insecure connection warning pages.
user_pref("browser.xul.error_pages.expert_bad_cert", true);

// -----------------------------------------------------------------------------
// Miscellaneous
// -----------------------------------------------------------------------------

// Disable about:config warning.
user_pref("general.warnOnAboutConfig", false);
user_pref("browser.aboutConfig.showWarning", false);

// Disable form and search history.
user_pref("browser.formfill.enable", false);

// Disable address bar guessing domain.
user_pref("browser.fixup.alternate.enabled", false);

// Disable address bar encoding Unicode characters when copying the URL.
user_pref("browser.urlbar.decodeURLsOnCopy", true);

// Disable address bar making speculative connections.
user_pref("browser.urlbar.speculativeConnect.enabled", false);

// Disable address bar sending search term to DNS server.
user_pref("browser.urlbar.dnsResolveSingleWordsAfterSearch", 0);

// Set the suggestion types in address bar.
user_pref("browser.urlbar.suggest.history", false);
user_pref("browser.urlbar.suggest.bookmark", true);
user_pref("browser.urlbar.suggest.openpage", true);
user_pref("browser.urlbar.suggest.topsites", false);
user_pref("browser.urlbar.suggest.engines", false);

// Set the security delay on some confirmation dialogs.
user_pref("security.dialog_enable_delay", 500);

// Disable closing window with last tab.
user_pref("browser.tabs.closeWindowWithLastTab", false);

// Disable Backspace key navigation.
user_pref("browser.backspace_action", 2);

// Disable Ctrl+Q as quit shortcut.
user_pref("browser.quitShortcut.disabled", true);

// Disable Alt as menu access key.
user_pref("ui.key.menuAccessKey", 0);

// Disable selecting any extra spaces when double-clicking text.
user_pref("layout.word_select.eat_space_to_next_word", false);

// -----------------------------------------------------------------------------
// ESR
// -----------------------------------------------------------------------------

// ESR 78.* still uses the following preferences.
user_pref("browser.search.geoSpecificDefaults", false);
user_pref("browser.search.geoSpecificDefaults.url", "");
user_pref("browser.library.activity-stream.enabled", false);
user_pref("browser.urlbar.matchBuckets", "general:5,suggestion:Infinity");
user_pref("dom.ipc.plugins.flash.subprocess.crashreporter.enabled", false);
user_pref("dom.ipc.plugins.reportCrashURL", false);
user_pref("security.mixed_content.block_object_subrequest", true);
<commit_msg>firefox: Update user.js<commit_after>// Firefox user.js

// -----------------------------------------------------------------------------
// Startup
// -----------------------------------------------------------------------------

// Show a blank page when opening homepage and new window.
user_pref("browser.startup.page", 0);
user_pref("browser.startup.homepage", "about:blank");
user_pref("browser.startup.homepage_override.mstone", "ignore");

// Show a blank page when opening new tab.
user_pref("browser.newtabpage.enabled", false);
user_pref("browser.newtab.preload", false);

// Disable Activity Stream.
user_pref("browser.newtabpage.activity-stream.default.sites", "");
user_pref("browser.newtabpage.activity-stream.feeds.discoverystreamfeed", false);
user_pref("browser.newtabpage.activity-stream.feeds.section.highlights", false);
user_pref("browser.newtabpage.activity-stream.feeds.section.topstories", false);
user_pref("browser.newtabpage.activity-stream.feeds.snippets", false);
user_pref("browser.newtabpage.activity-stream.feeds.telemetry", false);
user_pref("browser.newtabpage.activity-stream.feeds.topsites", false);
user_pref("browser.newtabpage.activity-stream.showSearch", false);
user_pref("browser.newtabpage.activity-stream.showSponsored", false);
user_pref("browser.newtabpage.activity-stream.telemetry", false);

// -----------------------------------------------------------------------------
// Localization
// -----------------------------------------------------------------------------

// Set preferred language for displaying pages.
user_pref("intl.accept_languages", "ja,zh-tw,zh,en-us,en");

// Disable region updates.
user_pref("browser.region.update.enabled", false);
user_pref("browser.region.network.url", "");

// -----------------------------------------------------------------------------
// Content
// -----------------------------------------------------------------------------

// Set the minimum font size.
user_pref("font.minimum-size.ja", 10);
user_pref("font.minimum-size.ko", 10);
user_pref("font.minimum-size.zh-CN", 10);
user_pref("font.minimum-size.zh-HK", 10);
user_pref("font.minimum-size.zh-TW", 10);

// Disable WebRTC.
user_pref("media.peerconnection.enabled", false);
user_pref("media.peerconnection.ice.default_address_only", true);
user_pref("media.peerconnection.ice.no_host", true);
user_pref("media.peerconnection.ice.proxy_only_if_behind_proxy", true);

// Disable media device enumeration.
user_pref("media.navigator.enabled", false);

// Block all audio and video autoplay.
user_pref("media.autoplay.default", 5);
user_pref("media.autoplay.blocking_policy", 0);

// Block new requests asking for permissions.
user_pref("permissions.default.geo", 2);
user_pref("permissions.default.camera", 2);
user_pref("permissions.default.microphone", 2);
user_pref("permissions.default.desktop-notification", 2);
user_pref("permissions.default.xr", 2);
user_pref("permissions.default.shortcuts", 2);

// Block pop-up windows.
user_pref("dom.disable_open_during_load", true);
user_pref("dom.popup_allowed_events", "click dblclick mousedown mouseup pointerdown pointerup");

// Enforce all links to be opened in new tabs.
user_pref("browser.link.open_newwindow", 3);
user_pref("browser.link.open_newwindow.restriction", 0);

// Disallow JavaScript to move and resize windows.
user_pref("dom.disable_window_move_resize", true);

// -----------------------------------------------------------------------------
// Network
// -----------------------------------------------------------------------------

// Disable prefetching.
user_pref("network.prefetch-next", false);
user_pref("network.predictor.enabled", false);
user_pref("network.predictor.enable-prefetch", false);
user_pref("network.dns.disablePrefetch", true);
user_pref("network.dns.disablePrefetchFromHTTPS", true);

// Disable making speculative connections when mouseover.
user_pref("network.http.speculative-parallel-limit", 0);

// Disable sending additional analytics to web servers.
user_pref("beacon.enabled", false);

// Disable HTTP authentication credentials dialogs triggered by cross-origin
// sub-resources.
user_pref("network.auth.subresource-http-auth-allow", 1);

// Disable Captive Portal detection.
user_pref("network.captive-portal-service.enabled", false);
user_pref("captivedetect.canonicalURL", "");

// Disable Network Connectivity checks.
user_pref("network.connectivity-service.enabled", false);

// Disable automatic Work Offline mode.
user_pref("network.manage-offline-status", false);

// Enable proxying DNS when using SOCKS v5.
user_pref("network.proxy.socks_remote_dns", true);

// -----------------------------------------------------------------------------
// Privacy
// -----------------------------------------------------------------------------

// Block all third-party cookies.
user_pref("network.cookie.cookieBehavior", 1);
user_pref("browser.contentblocking.category", "custom");

// Enable FPI (First Party Isolation).
user_pref("privacy.firstparty.isolate", true);

// Enable Enhanced Tracking Protection.
user_pref("privacy.trackingprotection.enabled", true);
user_pref("privacy.trackingprotection.pbmode.enabled", true);
user_pref("privacy.trackingprotection.cryptomining.enabled", true);
user_pref("privacy.trackingprotection.fingerprinting.enabled", true);
user_pref("privacy.trackingprotection.socialtracking.enabled", true);

// Enable DNT (Do Not Track) HTTP header.
user_pref("privacy.donottrackheader.enabled", true);

// Disable Telemetry.
user_pref("toolkit.telemetry.unified", false);
user_pref("toolkit.telemetry.enabled", false);
user_pref("toolkit.telemetry.server", "data:,");
user_pref("toolkit.telemetry.archive.enabled", false);
user_pref("toolkit.telemetry.bhrPing.enabled", false);
user_pref("toolkit.telemetry.firstShutdownPing.enabled", false);
user_pref("toolkit.telemetry.newProfilePing.enabled", false);
user_pref("toolkit.telemetry.shutdownPingSender.enabled", false);
user_pref("toolkit.telemetry.updatePing.enabled", false);

// Disable Telemetry Coverage.
user_pref("toolkit.telemetry.coverage.opt-out", true);
user_pref("toolkit.coverage.opt-out", true);
user_pref("toolkit.coverage.endpoint.base", "");

// Disable Health Report.
user_pref("datareporting.healthreport.uploadEnabled", false);
user_pref("datareporting.policy.dataSubmissionEnabled", false);

// Disable Shield Studies.
user_pref("app.shield.optoutstudies.enabled", false);

// Disable Normandy Telemetry.
user_pref("app.normandy.enabled", false);
user_pref("app.normandy.api_url", "");

// Disable sending file information to Google Safe Browsing service.
user_pref("browser.safebrowsing.downloads.remote.enabled", false);
user_pref("browser.safebrowsing.downloads.remote.url", "");

// Disable sending browser crash reports.
user_pref("breakpad.reportURL", "");
user_pref("browser.tabs.crashReporting.sendReport", false);
user_pref("browser.crashReports.unsubmittedCheck.enabled", false);
user_pref("browser.crashReports.unsubmittedCheck.autoSubmit2", false);

// -----------------------------------------------------------------------------
// Security
// -----------------------------------------------------------------------------

// Disable saving logins and passwords.
user_pref("signon.rememberSignons", false);

// Enforce OCSP (Online Certificate Status Protocol) stapling.
user_pref("security.ssl.enable_ocsp_stapling", true);
user_pref("security.OCSP.enabled", 1);
user_pref("security.OCSP.require", true);

// Enforce CSP (Content Security Policy).
user_pref("security.csp.enable", true);

// Enforce no insecure content on HTTPS pages.
user_pref("security.mixed_content.block_active_content", true);
user_pref("security.mixed_content.block_display_content", true);

// -----------------------------------------------------------------------------
// Search
// -----------------------------------------------------------------------------

// Disable search engine updates.
user_pref("browser.search.update", false);

// Enable search suggestions in all windows.
user_pref("browser.search.suggest.enabled", true);
user_pref("browser.search.suggest.enabled.private", true);
user_pref("browser.urlbar.suggest.searches", true);

// Show search suggestions behind other suggestions.
user_pref("browser.urlbar.showSearchSuggestionsFirst", false);

// -----------------------------------------------------------------------------
// Features
// -----------------------------------------------------------------------------

// Disable Firefox Accounts and Sync.
user_pref("identity.fxaccounts.enabled", false);

// Disable Reader View.
user_pref("reader.parse-on-load.enabled", false);

// Disable UITour backend.
user_pref("browser.uitour.enabled", false);
user_pref("browser.uitour.url", "");

// Disable various developer tools.
user_pref("devtools.chrome.enabled", false);
user_pref("devtools.debugger.remote-enabled", false);

// -----------------------------------------------------------------------------
// Add-ons
// -----------------------------------------------------------------------------

// Enable all extensions in Private Windows by default.
user_pref("extensions.allowPrivateBrowsingByDefault", true);

// Disable enforced extension signing in Developer Edition, Nightly and ESR.
user_pref("xpinstall.signatures.required", false);

// Disable extension recommendations in about:addons.
user_pref("extensions.getAddons.showPane", false);
user_pref("extensions.htmlaboutaddons.recommendations.enabled", false);

// Disable extension recommendations when browsing.
user_pref("browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons", false);
user_pref("browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features", false);

// Disable third-party extension install prompts.
user_pref("extensions.postDownloadThirdPartyPrompt", false);

// Disable system add-on updates.
user_pref("extensions.systemAddon.update.enabled", false);
user_pref("extensions.systemAddon.update.url", "");

// Disable Form Autofill.
user_pref("extensions.formautofill.available", "off");
user_pref("extensions.formautofill.addresses.enabled", false);
user_pref("extensions.formautofill.creditCards.available", false);
user_pref("extensions.formautofill.creditCards.enabled", false);
user_pref("extensions.formautofill.heuristics.enabled", false);

// Disable Pocket.
user_pref("extensions.pocket.enabled", false);

// Disable Web Compatibility Reporter.
user_pref("extensions.webcompat-reporter.enabled", false);

// Disable Gecko Media Plugins.
user_pref("media.gmp-provider.enabled", false);
user_pref("media.gmp-gmpopenh264.enabled", false);
user_pref("media.gmp-widevinecdm.enabled", false);

// Disable DRM-controlled content.
user_pref("media.eme.enabled", false);

// -----------------------------------------------------------------------------
// System
// -----------------------------------------------------------------------------

// Disable automatic Firefox updates.
user_pref("app.update.auto", false);

// Disable accessibility services.
user_pref("accessibility.force_disabled", 1);

// Disable disk cache.
user_pref("browser.cache.disk.enable", false);
user_pref("browser.cache.offline.storage.enable", false);
user_pref("browser.privatebrowsing.forceMediaMemoryCache", true);
user_pref("media.memory_cache_max_size", 65536);

// Disable saving page thumbnails.
user_pref("browser.pagethumbnails.capturing_disabled", true);

// Disable saving shortcut favicons.
user_pref("browser.shell.shortcutFavicons", false);

// Set the maximum number of bookmark backups to keep.
user_pref("browser.bookmarks.max_backups", 5);

// Set the minimum interval between session save operations.
user_pref("browser.sessionstore.interval", 60000);

// Always ask where to save files.
user_pref("browser.download.useDownloadDir", false);

// Disable adding downloads to Recent Documents.
user_pref("browser.download.manager.addToRecentDocs", false);

// Disable automatic start and session restore after Windows reboot.
user_pref("toolkit.winRegisterApplicationRestart", false);

// -----------------------------------------------------------------------------
// Appearance
// -----------------------------------------------------------------------------

// Enable userChrome.css and userContent.css customizations.
user_pref("toolkit.legacyUserProfileCustomizations.stylesheets", true);

// Disable site-specific zoom level.
user_pref("browser.zoom.siteSpecific", false);

// Show the full URL in address bar.
user_pref("browser.urlbar.trimURLs", false);

// Show the Punycode for IDNs (Internationalized Domain Names) in address bar.
user_pref("network.IDN_show_punycode", true);

// Show weak encryption warning in address bar.
user_pref("security.ssl.require_safe_negotiation", false);
user_pref("security.ssl.treat_unsafe_negotiation_as_broken", true);

// Show advanced information in insecure connection warning pages.
user_pref("browser.xul.error_pages.expert_bad_cert", true);

// -----------------------------------------------------------------------------
// Miscellaneous
// -----------------------------------------------------------------------------

// Disable about:config warning.
user_pref("general.warnOnAboutConfig", false);
user_pref("browser.aboutConfig.showWarning", false);

// Disable form and search history.
user_pref("browser.formfill.enable", false);

// Disable address bar guessing domain.
user_pref("browser.fixup.alternate.enabled", false);

// Disable address bar encoding Unicode characters when copying the URL.
user_pref("browser.urlbar.decodeURLsOnCopy", true);

// Disable address bar making speculative connections.
user_pref("browser.urlbar.speculativeConnect.enabled", false);

// Disable address bar sending search term to DNS server.
user_pref("browser.urlbar.dnsResolveSingleWordsAfterSearch", 0);

// Set the suggestion types in address bar.
user_pref("browser.urlbar.suggest.history", false);
user_pref("browser.urlbar.suggest.bookmark", true);
user_pref("browser.urlbar.suggest.openpage", true);
user_pref("browser.urlbar.suggest.topsites", false);
user_pref("browser.urlbar.suggest.engines", false);
user_pref("browser.urlbar.suggest.quicksuggest", true);
user_pref("browser.urlbar.suggest.calculator", true);

// Set the security delay on some confirmation dialogs.
user_pref("security.dialog_enable_delay", 500);

// Disable closing window with last tab.
user_pref("browser.tabs.closeWindowWithLastTab", false);

// Disable Backspace key navigation.
user_pref("browser.backspace_action", 2);

// Disable Ctrl+Q as quit shortcut.
user_pref("browser.quitShortcut.disabled", true);

// Disable Alt as menu access key.
user_pref("ui.key.menuAccessKey", 0);

// Disable selecting any extra spaces when double-clicking text.
user_pref("layout.word_select.eat_space_to_next_word", false);

// -----------------------------------------------------------------------------
// ESR
// -----------------------------------------------------------------------------

// ESR 78.* still uses the following preferences.
user_pref("browser.search.geoSpecificDefaults", false);
user_pref("browser.search.geoSpecificDefaults.url", "");
user_pref("browser.library.activity-stream.enabled", false);
user_pref("browser.urlbar.matchBuckets", "general:5,suggestion:Infinity");
user_pref("dom.ipc.plugins.flash.subprocess.crashreporter.enabled", false);
user_pref("dom.ipc.plugins.reportCrashURL", false);
user_pref("security.mixed_content.block_object_subrequest", true);
<|endoftext|>


<commit_before>const fs = require('fs');
const path = require('path');
const yaml = require('js-yaml');
const normalizeModel = require('../normalize-model');

// This function reads and parses the resource from the disk, and returns it.
// At the moment, only YAML files are supported, although it'd be simple to add
// in support for JSON.
function loadResource(filename, resourcesDir) {
  const filePath = path.join(resourcesDir, filename);

  let doc;
  try {
    doc = yaml.safeLoad(fs.readFileSync(filePath, 'utf8'));
  } catch (e) {
    console.log(chalk.red(`There was an error while parsing the "${filename}" resource file.`));
    process.exit(1);
  }

  return doc;
}

module.exports = function(resourcesDir) {
  // Loop through all files in the directory
  return fs.readdirSync(resourcesDir)
    // Open them up and parse them as JSON
    .map(r => loadResource(r, resourcesDir))
    .map(normalizeModel);
}
<commit_msg>Fix linting<commit_after>'use strict';

const fs = require('fs');
const path = require('path');
const chalk = require('chalk');
const yaml = require('js-yaml');
const normalizeModel = require('../normalize-model');

// This function reads and parses the resource from the disk, and returns it.
// At the moment, only YAML files are supported, although it'd be simple to add
// in support for JSON.
function loadResource(filename, resourcesDir) {
  const filePath = path.join(resourcesDir, filename);

  let doc;
  try {
    doc = yaml.safeLoad(fs.readFileSync(filePath, 'utf8'));
  } catch (e) {
    console.log(chalk.red(`There was an error while parsing the "${filename}" resource file.`));
    process.exit(1);
  }

  return doc;
}

module.exports = function(resourcesDir) {
  // Loop through all files in the directory
  return fs.readdirSync(resourcesDir)
    // Open them up and parse them as JSON
    .map(r => loadResource(r, resourcesDir))
    .map(normalizeModel);
};
<|endoftext|>


<commit_before>var arr = [2,1,9,6,4,3]

// 选择排序
function selectionSort(arr) {
  let temp = []
  let len = arr.length
  while (temp.length < len) {
    let min = 1000000000
    let index = 0
    arr.forEach( (a, i) => {
      if (a < min){
        min = a
        index = i
      }
    });
    temp.push(min)
    arr.splice(index, 1)
  }
  return temp
}

console.log(sort(arr));
<commit_msg>selectSort done<commit_after>// 1. 在未排序序列中找到最小（大）元素
// 2. 存放到排序序列的起始位置
// 3. 从剩余未排序元素中继续寻找最小（大）元素
// 4. 然后放到已排序序列的末尾
// 5. 以此类推，直到所有元素排序完毕

var arr = [
  2,
  1,
  9,
  6,
  4,
  3
]

// 方法一 每找出一个最小元素，将此元素添加进临时数组， 并在原数组中删除此元素，继续遍历，直到原数 组的长度为0

function selectionSort(arr) {
  let temp = [], // 存放最小的元素，每次push进去
    len = arr.length
  while (temp.length < len) {
    let min = Math.min(...arr) // 当前数组的最小元素
    temp.push(min)
    arr.splice(arr.indexOf(min), 1) // 移除最小元素
  }
  return temp
}

// ES5
function selectionSortES5(arr) {
  var len = arr.length;
  var temp,
    minIndex;
  for (var i = 0; i < len - 1; i++) {
    minIndex = i;
    for (var j = i + 1; j < len; j++) {
      if (arr[j] < arr[minIndex]) {
        minIndex = j
      }
    }
    temp = arr[i]
    arr[i] = arr[minIndex]
    arr[minIndex] = temp
  }
  return arr
}

console.log(selectionSort(arr));
console.log(selectionSortES5(arr));
<|endoftext|>