<commit_before>const moment = require('moment-timezone');
const path = require('path');
const fs = require('fs-extra');
const membersCSV = require('@tryghost/members-csv');
const errors = require('@tryghost/errors');
const tpl = require('@tryghost/tpl');
const GhostMailer = require('../../mail').GhostMailer;
const urlUtils = require('../../../../shared/url-utils');
const db = require('../../../data/db');
const emailTemplate = require('./email-template');
const jobsService = require('../../jobs');
const labsService = require('../../../../shared/labs');

const messages = {
    filenameCollision: 'Filename already exists, please try again.',
    jobAlreadyComplete: 'Job is already complete.'
};

const ghostMailer = new GhostMailer();
module.exports = class MembersCSVImporter {
    /**
     * @param {Object} config
     * @param {string} config.storagePath - The path to store CSV's in before importing
     * @param {Object} settingsCache - An instance of the Ghost Settings Cache
     * @param {() => Object} getMembersApi
     */
    constructor(config, settingsCache, getMembersApi) {
        this._storagePath = config.storagePath;
        this._settingsCache = settingsCache;
        this._getMembersApi = getMembersApi;
    }

    /**
     * @typedef {string} JobID
     */

    /**
     * @typedef {Object} Job
     * @prop {string} filename
     * @prop {JobID} id
     * @prop {string} status
     */

    /**
     * Get the Job for a jobCode
     * @param {JobID} jobId
     * @returns {Promise<Job>}
     */
    async getJob(jobId) {
        return {
            id: jobId,
            filename: jobId,
            status: 'pending'
        };
    }

    /**
     * Prepares a CSV file for import
     * - Maps headers based on headerMapping, this allows for a non standard CSV
     *   to be imported, so long as a mapping exists between it and a standard CSV
     * - Stores the CSV to be imported in the storagePath
     * - Creates a MemberImport Job and associated MemberImportBatch's
     *
     * @param {string} inputFilePath - The path to the CSV to prepare
     * @param {Object.<string, string>} headerMapping - An object whos keys are headers in the input CSV and values are the header to replace it with
     * @param {Array<string>} defaultLabels - A list of labels to apply to every member
     *
     * @returns {Promise<{id: JobID, batches: number, metadata: Object.<string, any>}>} - A promise resolving to the id of the MemberImport Job
     */
    async prepare(inputFilePath, headerMapping, defaultLabels) {
        const batchSize = 1;

        const siteTimezone = this._settingsCache.get('timezone');
        const currentTime = moment().tz(siteTimezone).format('YYYY-MM-DD HH:mm:ss.SSS');
        const outputFileName = `Members Import ${currentTime}.csv`;
        const outputFilePath = path.join(this._storagePath, '/', outputFileName);

        const pathExists = await fs.pathExists(outputFilePath);

        if (pathExists) {
            throw new errors.DataImportError(tpl(messages.filenameCollision));
        }

        const rows = await membersCSV.parse(inputFilePath, headerMapping, defaultLabels);
        const numberOfBatches = Math.ceil(rows.length / batchSize);
        const mappedCSV = membersCSV.unparse(rows);

        const hasStripeData = rows.find(function rowHasStripeData(row) {
            return !!row.stripe_customer_id || !!row.complimentary_plan;
        });

        await fs.writeFile(outputFilePath, mappedCSV);

        return {
            id: outputFilePath,
            batches: numberOfBatches,
            metadata: {
                hasStripeData
            }
        };
    }

    /**
     * Performs an import of a CSV file
     *
     * @param {JobID} id - The id of the job to perform
     */
    async perform(id) {
        const job = await this.getJob(id);

        if (job.status === 'complete') {
            throw new errors.BadRequestError(tpl(messages.jobAlreadyComplete));
        }

        const rows = membersCSV.parse(job.filename);

        const membersApi = await this._getMembersApi();

        const defaultProductPage = await membersApi.productRepository.list({
            limit: 1
        });

        const defaultProduct = defaultProductPage.data[0];

        const result = await rows.reduce(async (resultPromise, row) => {
            const resultAccumulator = await resultPromise;

            const trx = await db.knex.transaction();
            const options = {
                transacting: trx
            };

            try {
                const existingMember = await membersApi.members.get({email: row.email}, {
                    ...options,
                    withRelated: ['labels']
                });
                let member;
                if (existingMember) {
                    const existingLabels = existingMember.related('labels') ? existingMember.related('labels').toJSON() : [];
                    member = await membersApi.members.update({
                        ...row,
                        labels: existingLabels.concat(row.labels)
                    }, {
                        ...options,
                        id: existingMember.id
                    });
                } else {
                    member = await membersApi.members.create(row, options);
                }

                if (row.stripe_customer_id) {
                    await membersApi.members.linkStripeCustomer({
                        customer_id: row.stripe_customer_id,
                        member_id: member.id
                    }, options);
                } else if (row.complimentary_plan) {
                    if (!labsService.isSet('multipleProducts')) {
                        await membersApi.members.setComplimentarySubscription(member, options);
                    } else if (!row.products) {
                        await membersApi.members.update({
                            products: [{id: defaultProduct.id}]
                        }, {
                            ...options,
                            id: member.id
                        });
                    }
                }

                if (labsService.isSet('multipleProducts')) {
                    if (row.products) {
                        await membersApi.members.update({
                            products: row.products
                        }, {
                            ...options,
                            id: member.id
                        });
                    }
                }

                await trx.commit();
                return {
                    ...resultAccumulator,
                    imported: resultAccumulator.imported + 1
                };
            } catch (error) {
                // The model layer can sometimes throw arrays of errors
                const errorList = [].concat(error);
                const errorMessage = errorList.map(({message}) => message).join(', ');
                await trx.rollback();
                return {
                    ...resultAccumulator,
                    errors: [...resultAccumulator.errors, {
                        ...row,
                        error: errorMessage
                    }]
                };
            }
        }, Promise.resolve({
            imported: 0,
            errors: []
        }));

        return {
            total: result.imported + result.errors.length,
            ...result
        };
    }

    generateCompletionEmail(result, data) {
        const siteUrl = new URL(urlUtils.urlFor('home', null, true));
        const membersUrl = new URL('members', urlUtils.urlFor('admin', null, true));
        if (data.importLabel) {
            membersUrl.searchParams.set('label', data.importLabel.slug);
        }
        return emailTemplate({result, siteUrl, membersUrl, ...data});
    }

    generateErrorCSV(result) {
        const errorsWithFormattedMessages = result.errors.map((row) => {
            const formattedError = row.error
                .replace(
                    'Value in [members.email] cannot be blank.',
                    'Missing email address'
                )
                .replace(
                    'Value in [members.note] exceeds maximum length of 2000 characters.',
                    '"Note" exceeds maximum length of 2000 characters'
                )
                .replace(
                    'Value in [members.subscribed] must be one of true, false, 0 or 1.',
                    'Value in "Subscribed to emails" must be "true" or "false"'
                )
                .replace(
                    'Validation (isEmail) failed for email',
                    'Invalid email address'
                )
                .replace(
                    /No such customer:[^,]*/,
                    'Could not find Stripe customer'
                );

            return {
                ...row,
                error: formattedError
            };
        });
        return membersCSV.unparse(errorsWithFormattedMessages);
    }

    /**
     * Processes CSV file and imports member&label records depending on the size of the imported set
     *
     * @param {Object} config
     * @param {String} config.pathToCSV - path where imported csv with members records is stored
     * @param {Object} config.headerMapping - mapping of CSV headers to member record fields
     * @param {Object} [config.globalLabels] - labels to be applied to whole imported members set
     * @param {Object} config.importLabel -
     * @param {String} config.importLabel.name - label name
     * @param {Object} config.user
     * @param {String} config.user.email - calling user email
     * @param {Object} config.LabelModel - instance of Ghosts Label model
     */
    async process({pathToCSV, headerMapping, globalLabels, importLabel, user, LabelModel}) {
        const job = await this.prepare(pathToCSV, headerMapping, globalLabels);

        if (job.batches <= 500 && !job.metadata.hasStripeData) {
            const result = await this.perform(job.id);
            const importLabelModel = result.imported ? await LabelModel.findOne(importLabel) : null;
            return {
                meta: {
                    stats: {
                        imported: result.imported,
                        invalid: result.errors
                    },
                    import_label: importLabelModel
                }
            };
        } else {
            const emailRecipient = user.email;
            jobsService.addJob({
                job: async () => {
                    const result = await this.perform(job.id);
                    const importLabelModel = result.imported ? await LabelModel.findOne(importLabel) : null;
                    const emailContent = this.generateCompletionEmail(result, {
                        emailRecipient,
                        importLabel: importLabelModel ? importLabelModel.toJSON() : null
                    });
                    const errorCSV = this.generateErrorCSV(result);
                    const emailSubject = result.imported > 0 ? 'Your member import is complete' : 'Your member import was unsuccessful';

                    await ghostMailer.send({
                        to: emailRecipient,
                        subject: emailSubject,
                        html: emailContent,
                        forceTextContent: true,
                        attachments: [{
                            filename: `${importLabel.name} - Errors.csv`,
                            contents: errorCSV,
                            contentType: 'text/csv',
                            contentDisposition: 'attachment'
                        }]
                    });
                },
                offloaded: false
            });

            return {};
        }
    }
};
<commit_msg>Refactored Ghost mailer dependency out of MembersCSVImporter<commit_after>const moment = require('moment-timezone');
const path = require('path');
const fs = require('fs-extra');
const membersCSV = require('@tryghost/members-csv');
const errors = require('@tryghost/errors');
const tpl = require('@tryghost/tpl');

const urlUtils = require('../../../../shared/url-utils');
const db = require('../../../data/db');
const emailTemplate = require('./email-template');
const jobsService = require('../../jobs');
const labsService = require('../../../../shared/labs');

const messages = {
    filenameCollision: 'Filename already exists, please try again.',
    jobAlreadyComplete: 'Job is already complete.'
};

module.exports = class MembersCSVImporter {
    /**
     * @param {Object} config
     * @param {string} config.storagePath - The path to store CSV's in before importing
     * @param {Object} settingsCache - An instance of the Ghost Settings Cache
     * @param {Object} ghostMailer - An instance of GhostMailer
     * @param {() => Object} getMembersApi
     */
    constructor(config, settingsCache, getMembersApi, ghostMailer) {
        this._storagePath = config.storagePath;
        this._settingsCache = settingsCache;
        this._getMembersApi = getMembersApi;
        this._ghostMailer = ghostMailer;
    }

    /**
     * @typedef {string} JobID
     */

    /**
     * @typedef {Object} Job
     * @prop {string} filename
     * @prop {JobID} id
     * @prop {string} status
     */

    /**
     * Get the Job for a jobCode
     * @param {JobID} jobId
     * @returns {Promise<Job>}
     */
    async getJob(jobId) {
        return {
            id: jobId,
            filename: jobId,
            status: 'pending'
        };
    }

    /**
     * Prepares a CSV file for import
     * - Maps headers based on headerMapping, this allows for a non standard CSV
     *   to be imported, so long as a mapping exists between it and a standard CSV
     * - Stores the CSV to be imported in the storagePath
     * - Creates a MemberImport Job and associated MemberImportBatch's
     *
     * @param {string} inputFilePath - The path to the CSV to prepare
     * @param {Object.<string, string>} headerMapping - An object whos keys are headers in the input CSV and values are the header to replace it with
     * @param {Array<string>} defaultLabels - A list of labels to apply to every member
     *
     * @returns {Promise<{id: JobID, batches: number, metadata: Object.<string, any>}>} - A promise resolving to the id of the MemberImport Job
     */
    async prepare(inputFilePath, headerMapping, defaultLabels) {
        const batchSize = 1;

        const siteTimezone = this._settingsCache.get('timezone');
        const currentTime = moment().tz(siteTimezone).format('YYYY-MM-DD HH:mm:ss.SSS');
        const outputFileName = `Members Import ${currentTime}.csv`;
        const outputFilePath = path.join(this._storagePath, '/', outputFileName);

        const pathExists = await fs.pathExists(outputFilePath);

        if (pathExists) {
            throw new errors.DataImportError(tpl(messages.filenameCollision));
        }

        const rows = await membersCSV.parse(inputFilePath, headerMapping, defaultLabels);
        const numberOfBatches = Math.ceil(rows.length / batchSize);
        const mappedCSV = membersCSV.unparse(rows);

        const hasStripeData = rows.find(function rowHasStripeData(row) {
            return !!row.stripe_customer_id || !!row.complimentary_plan;
        });

        await fs.writeFile(outputFilePath, mappedCSV);

        return {
            id: outputFilePath,
            batches: numberOfBatches,
            metadata: {
                hasStripeData
            }
        };
    }

    /**
     * Performs an import of a CSV file
     *
     * @param {JobID} id - The id of the job to perform
     */
    async perform(id) {
        const job = await this.getJob(id);

        if (job.status === 'complete') {
            throw new errors.BadRequestError(tpl(messages.jobAlreadyComplete));
        }

        const rows = membersCSV.parse(job.filename);

        const membersApi = await this._getMembersApi();

        const defaultProductPage = await membersApi.productRepository.list({
            limit: 1
        });

        const defaultProduct = defaultProductPage.data[0];

        const result = await rows.reduce(async (resultPromise, row) => {
            const resultAccumulator = await resultPromise;

            const trx = await db.knex.transaction();
            const options = {
                transacting: trx
            };

            try {
                const existingMember = await membersApi.members.get({email: row.email}, {
                    ...options,
                    withRelated: ['labels']
                });
                let member;
                if (existingMember) {
                    const existingLabels = existingMember.related('labels') ? existingMember.related('labels').toJSON() : [];
                    member = await membersApi.members.update({
                        ...row,
                        labels: existingLabels.concat(row.labels)
                    }, {
                        ...options,
                        id: existingMember.id
                    });
                } else {
                    member = await membersApi.members.create(row, options);
                }

                if (row.stripe_customer_id) {
                    await membersApi.members.linkStripeCustomer({
                        customer_id: row.stripe_customer_id,
                        member_id: member.id
                    }, options);
                } else if (row.complimentary_plan) {
                    if (!labsService.isSet('multipleProducts')) {
                        await membersApi.members.setComplimentarySubscription(member, options);
                    } else if (!row.products) {
                        await membersApi.members.update({
                            products: [{id: defaultProduct.id}]
                        }, {
                            ...options,
                            id: member.id
                        });
                    }
                }

                if (labsService.isSet('multipleProducts')) {
                    if (row.products) {
                        await membersApi.members.update({
                            products: row.products
                        }, {
                            ...options,
                            id: member.id
                        });
                    }
                }

                await trx.commit();
                return {
                    ...resultAccumulator,
                    imported: resultAccumulator.imported + 1
                };
            } catch (error) {
                // The model layer can sometimes throw arrays of errors
                const errorList = [].concat(error);
                const errorMessage = errorList.map(({message}) => message).join(', ');
                await trx.rollback();
                return {
                    ...resultAccumulator,
                    errors: [...resultAccumulator.errors, {
                        ...row,
                        error: errorMessage
                    }]
                };
            }
        }, Promise.resolve({
            imported: 0,
            errors: []
        }));

        return {
            total: result.imported + result.errors.length,
            ...result
        };
    }

    generateCompletionEmail(result, data) {
        const siteUrl = new URL(urlUtils.urlFor('home', null, true));
        const membersUrl = new URL('members', urlUtils.urlFor('admin', null, true));
        if (data.importLabel) {
            membersUrl.searchParams.set('label', data.importLabel.slug);
        }
        return emailTemplate({result, siteUrl, membersUrl, ...data});
    }

    generateErrorCSV(result) {
        const errorsWithFormattedMessages = result.errors.map((row) => {
            const formattedError = row.error
                .replace(
                    'Value in [members.email] cannot be blank.',
                    'Missing email address'
                )
                .replace(
                    'Value in [members.note] exceeds maximum length of 2000 characters.',
                    '"Note" exceeds maximum length of 2000 characters'
                )
                .replace(
                    'Value in [members.subscribed] must be one of true, false, 0 or 1.',
                    'Value in "Subscribed to emails" must be "true" or "false"'
                )
                .replace(
                    'Validation (isEmail) failed for email',
                    'Invalid email address'
                )
                .replace(
                    /No such customer:[^,]*/,
                    'Could not find Stripe customer'
                );

            return {
                ...row,
                error: formattedError
            };
        });
        return membersCSV.unparse(errorsWithFormattedMessages);
    }

    /**
     * Processes CSV file and imports member&label records depending on the size of the imported set
     *
     * @param {Object} config
     * @param {String} config.pathToCSV - path where imported csv with members records is stored
     * @param {Object} config.headerMapping - mapping of CSV headers to member record fields
     * @param {Object} [config.globalLabels] - labels to be applied to whole imported members set
     * @param {Object} config.importLabel -
     * @param {String} config.importLabel.name - label name
     * @param {Object} config.user
     * @param {String} config.user.email - calling user email
     * @param {Object} config.LabelModel - instance of Ghosts Label model
     */
    async process({pathToCSV, headerMapping, globalLabels, importLabel, user, LabelModel}) {
        const job = await this.prepare(pathToCSV, headerMapping, globalLabels);

        if (job.batches <= 500 && !job.metadata.hasStripeData) {
            const result = await this.perform(job.id);
            const importLabelModel = result.imported ? await LabelModel.findOne(importLabel) : null;
            return {
                meta: {
                    stats: {
                        imported: result.imported,
                        invalid: result.errors
                    },
                    import_label: importLabelModel
                }
            };
        } else {
            const emailRecipient = user.email;
            jobsService.addJob({
                job: async () => {
                    const result = await this.perform(job.id);
                    const importLabelModel = result.imported ? await LabelModel.findOne(importLabel) : null;
                    const emailContent = this.generateCompletionEmail(result, {
                        emailRecipient,
                        importLabel: importLabelModel ? importLabelModel.toJSON() : null
                    });
                    const errorCSV = this.generateErrorCSV(result);
                    const emailSubject = result.imported > 0 ? 'Your member import is complete' : 'Your member import was unsuccessful';

                    await this._ghostMailer.send({
                        to: emailRecipient,
                        subject: emailSubject,
                        html: emailContent,
                        forceTextContent: true,
                        attachments: [{
                            filename: `${importLabel.name} - Errors.csv`,
                            contents: errorCSV,
                            contentType: 'text/csv',
                            contentDisposition: 'attachment'
                        }]
                    });
                },
                offloaded: false
            });

            return {};
        }
    }
};
<|endoftext|>


<commit_before>/*!
 * Chiffon v1.5.0 - A very small ECMAScript parser, tokenizer and minifier written in JavaScript.
 * Copyright (c) 2015 polygon planet <polygon.planet.aqua@gmail.com>
 * @license MIT
 */
!function(a,b,c){"undefined"!=typeof exports?"undefined"!=typeof module&&module.exports?module.exports=c():exports[a]=c():"function"==typeof define&&define.amd?define(c):b[a]=c()}("Chiffon",this,function(){"use strict";function a(a){return new RegExp("(?:(/[*][\\s\\S]*?[*]/)|(//[^"+E+"]*|<!--[^"+E+"]*)|(?:^|("+F+"))(?:"+G+"|)(-->[^"+E+"]*)|(`(?:\\\\[\\s\\S]|[^`\\\\])*`)"+H+'|("(?:\\\\[\\s\\S]|[^"'+E+"\\\\])*\"|'(?:\\\\[\\s\\S]|[^'"+E+"\\\\])*')|("+(a?J:G)+")"+H+"|(0(?:[xX][0-9a-fA-F]+|[oO][0-7]+|[bB][01]+)|(?:\\d+(?:[.]\\d*)?|[.]\\d+)(?:[eE][+-]?\\d+)?|[1-9]\\d*|0[0-7]+)|("+I+")|(\\\\u[0-9a-fA-F]{4})|"+G+"|("+F+")|("+K+"+))","g")}function b(a){return 10===a||13===a||8232===a||8233===a}function c(a){for(var b=l.call(arguments,1),c=0,d=b.length;d>c;c++){var e=b[c];for(var f in e)n.call(e,f)&&(a[f]=e[f])}return a}function d(a){this.options=c({},a||{})}function e(a,b){b=c({},b||{});for(var d,e=[],f=b.maxLineLen||p,g=0,h=0,i=a.length;i>h;d=a[h++]){var j=a[h],k=j.type,l=j.value,m=a[h+1];if(d){var n="",o=d.type,q=d.value;if(k===r){if(o===r)continue;o===u||m&&m.type===u?l="":g=0}else(R.test(l)&&S.test(q)||P.test(l)&&Q.test(q))&&(n=" "),k===u&&g>f&&(l+="\n",g=0);var s=n+l;g+=s.length,e[e.length]=s}else k!==r&&(e[e.length]=l)}return e.join("")}function f(a,b){return e(X(a,{lineTerminator:!0}),b)}var g,h={},i=Array.prototype,j=Object.prototype,k=i.push,l=i.slice,m=i.splice,n=j.hasOwnProperty,o=String.fromCharCode,p=32e3,q="Comment",r="LineTerminator",s="Template",t="String",u="Punctuator",v="RegularExpression",w="Numeric",x="UnicodeEscapeSequence",y="Identifier",z="Null",A="Boolean",B="Keyword",C=["",q,q,r,q,s,t,v,w,u,x,r,y],D=C.length,E="\\r\\n\\u2028\\u2029",F="(?:\\r\\n|["+E+"])",G="(?:(?!["+E+"])\\s)+",H="(?=\\s*(?:(?!\\s*[/\\\\<>*+%`^\"'\\w$-])[^/\\\\<>*+%`^'\"({[\\w$-]|[!=]==?|[|][|]|&&|/[*/]|[,.;:!?)}\\]"+E+"]|$))",I="(?:>>>=?|[.]{3}|<<=|===|!==|>>=|[+][+](?=[+])|--(?=-)|[=!<>*%+/&|^-]=|&&|[|][|]|[+][+]|--|<<|>>|=>|[-+*/%<>=&|^~!?:;,.()[\\]{}])",J="(?:/(?![*])(?:\\\\.|[^/"+E+"\\\\])+/(?:[gimuy]{0,5}|\\b))",K="[^\\s+/%*=&|^~<>!?:;,.()[\\]{}'\"`-]",L="typeof|in|void|case|instanceof|yield|throw|delete",M="if|while|for|with",N=new RegExp("^(?:"+M+"|"+L+"|var|else|function|this|return|new|break|do|catch|finally|try|default|continue|switch|const|export|import|class|extends|debugger|super|let|static|enum|await|implements|package|protected|interface|private|public)$"),O=new RegExp(F),P=new RegExp("^"+K),Q=new RegExp(K+"$"),R=/^[+-]/,S=/[+-]$/,T=new RegExp("(?:(?:^(?:"+L+")$)|(?:(?![.\\]])"+I+"$))"),U=new RegExp("^(?:"+M+")$"),V=a(),W=a(!0);d.prototype={parseMatches:function(a,b){var c,d=this.line;this.regexParsing?c=this._currentRegexToken._loc.rangeStart+V.lastIndex:(c=W.lastIndex,g&&(c+=this.rangeStart));for(var e=1;D>e;e++){var f=a[e];if(f){var h,i,j=c-f.length-this.prevLineIndex,k=C[e];if(k===q){if("*"===f.charAt(1)&&this.updateLine(f,c),!this.options.comment)break}else if(k===r){if(this.line++,this.prevLineIndex=c,!this.options.lineTerminator)continue}else if(k===t)this.updateLine(f,c);else if(k===s)i=!0;else if(k===y)"null"===f?k=z:"true"===f||"false"===f?k=A:N.test(f)&&(k=B);else if(k===v){if(this.regexParsing)break;i=!0,h=this.parseRegExpFlags(f)}var l={type:k,value:f};h&&(l.regex=h),i&&(l._loc={line:this.line,columnStart:j,rangeStart:c-f.length,prevLineIndex:this.prevLineIndex}),k===s&&this.updateLine(f,c);var m=c-this.prevLineIndex;if(this.addRange(l,c),this.addLoc(l,d,j,this.line,m),b[b.length]=l,f===a[0])break}}},addRange:function(a,b){this.options.range&&(a.range=[b-a.value.length,b])},addLoc:function(a,b,c,d,e){this.options.loc&&(a.loc={start:{line:b,column:c},end:{line:d,column:e}})},updateLine:function(a,b){if(this.options.loc){var c=a.split(O);c.length>1&&(this.line+=c.length-1,this.prevLineIndex=b-c.pop().length)}},parseTemplate:function(a){for(var b=0;b<a.length;b++){var c=a[b];if(c.type===s){var d=this.parseTemplateBlock(c),e=this.parseTemplateExpr(d,c);m.apply(a,[b,1].concat(e)),b+=e.length}}},parseTemplateExpr:function(a,b){for(var d=[],e=0,f=a.length;f>e;e++){var h=a[e];if("tmp-source"===h.type){g=c({},h._loc,{type:s});var i=X(h.value,this.options);g=null,k.apply(d,i)}else d[d.length]=h}return d},parseTemplateBlock:function(a){for(var c,d,e,f,g,h,i,j,k=a.value,l=a._loc,m=l.line,n=m,p=l.columnStart,q=l.rangeStart,r=[l.prevLineIndex],t=[],u=0,v="",w=s,x=0,y=k.length;y>x;f=k.charCodeAt(x++)){var z=k.charCodeAt(x);b(z)&&(13===f&&10===z&&m--,m++,r[r.length]=q+x+1),g?y>x+1&&125===k.charCodeAt(x+1)&&(i=!0,w="tmp-source",g=!1):92===z?92===f?u++:u=1:36===z?h=92!==f||u%2===0:123===z&&h&&36===f&&(i=!0,w=s,g=!0),v+=o(z),x===y-1&&(i=!0,w=s),i&&(j={type:w,value:v},c=q+x+1,d=this.findPrevLineIndex(r,c),e=c-d,w===s?(this.addRange(j,c),this.addLoc(j,n,p,m,e),p=e+1):(c=q+x+1-v.length,d=this.findPrevLineIndex(r,c),j._loc={line:n,rangeStart:c,prevLineIndex:d},p=e),t[t.length]=j,v="",n=m,i=!1)}return t},findPrevLineIndex:function(a,b){for(var c=a.length-1;c>=0;--c){var d=a[c];if(b>=d)return d}},fixRegExpTokens:function(a){for(var b=0;b<a.length;b++)if(a[b].type===v){for(var c,d=b,e=a[b];--d>=0;){var f=a[d],g=f.type;if(g!==q&&g!==r){var h=f.value;if(g===u){if(")"===h){if(this.isValidRegExpPrefix(a,d+1))break}else if(T.test(h))break}else if(g===B&&T.test(h)||g===s&&"${"===h.slice(-2))break;var i=this.parseRegExp(e);m.apply(a,[b,1].concat(i)),c=!0;break}}c||delete e._loc}},isValidRegExpPrefix:function(a,b){for(var c=0;--b>=0;){var d=a[b],e=d.type;if(e===u){var f=d.value;if("("===f){if(0===--c){var g=a[b-1];return g&&g.type===B&&U.test(g.value)?!0:!1}}else")"===f&&c++}}return!1},parseRegExpFlags:function(a){var b=a.lastIndexOf("/"),c=a.substring(b+1),d=a.substr(1,b-1);return{pattern:d,flags:c}},parseRegExp:function(a){this._currentRegexToken=a;var b,c=a.value,d=[];for(this.options.loc&&(this.line=a.loc.start.line,this.prevLineIndex=a._loc.prevLineIndex),this.regexParsing=!0,V.lastIndex=0;null!=(b=V.exec(c));)this.parseMatches(b,d);return this.regexParsing=!1,this._currentRegexToken=null,d},tokenize:function(a){a=""+a,g?c(this,g):(this.line=1,this.prevLineIndex=0),this.regexParsing=!1;var b,d=[];for(W.lastIndex=0;null!=(b=W.exec(a));)this.parseMatches(b,d);return g&&g.type===s||this.parseTemplate(d),this.fixRegExpTokens(d),d}};var X=h.tokenize=function(a,b){return new d(b).tokenize(a)};return h.untokenize=e,h.minify=f,h});<commit_msg>Fix regex<commit_after>/*!
 * Chiffon v1.5.0 - A very small ECMAScript parser, tokenizer and minifier written in JavaScript.
 * Copyright (c) 2015 polygon planet <polygon.planet.aqua@gmail.com>
 * @license MIT
 */
!function(a,b,c){"undefined"!=typeof exports?"undefined"!=typeof module&&module.exports?module.exports=c():exports[a]=c():"function"==typeof define&&define.amd?define(c):b[a]=c()}("Chiffon",this,function(){"use strict";function a(a){return new RegExp("(?:(/[*][\\s\\S]*?[*]/)|(//[^"+D+"]*|<!--[^"+D+"]*)|(?:^|("+E+"))(?:"+F+"|)(-->[^"+D+"]*)|(`(?:\\\\[\\s\\S]|[^`\\\\])*`)"+G+'|("(?:\\\\[\\s\\S]|(?:[^"'+D+'\\\\]|[^"\\r\\\\][^"\\n\\\\]))*"|\'(?:\\\\[\\s\\S]|(?:[^\''+D+"\\\\]|[^'\\r\\\\][^'\\n\\\\]))*')|("+(a?I:F)+")"+G+"|(0(?:[xX][0-9a-fA-F]+|[oO][0-7]+|[bB][01]+)|(?:\\d+(?:[.]\\d*)?|[.]\\d+)(?:[eE][+-]?\\d+)?|[1-9]\\d*|0[0-7]+)|("+H+")|(\\\\u[0-9a-fA-F]{4})|"+F+"|("+E+")|("+J+"+))","g")}function b(a){return 10===a||13===a||8232===a||8233===a}function c(a){for(var b=l.call(arguments,1),c=0,d=b.length;d>c;c++){var e=b[c];for(var f in e)n.call(e,f)&&(a[f]=e[f])}return a}function d(a){this.options=c({},a||{})}function e(a,b){b=c({},b||{});for(var d,e=[],f=b.maxLineLen||X,g=0,h=0,i=a.length;i>h;d=a[h++]){var j=a[h],k=j.type,l=j.value,m=a[h+1];if(d){var n="",o=d.type,p=d.value;if(k===q){if(o===q)continue;o===t||m&&m.type===t?l="":g=0}else(Q.test(l)&&R.test(p)||O.test(l)&&P.test(p))&&(n=" "),k===t&&g>f&&(l+="\n",g=0);var r=n+l;g+=r.length,e[e.length]=r}else k!==q&&(e[e.length]=l)}return e.join("")}function f(a,b){return e(W(a,{lineTerminator:!0}),b)}var g,h={},i=Array.prototype,j=Object.prototype,k=i.push,l=i.slice,m=i.splice,n=j.hasOwnProperty,o=String.fromCharCode,p="Comment",q="LineTerminator",r="Template",s="String",t="Punctuator",u="RegularExpression",v="Numeric",w="UnicodeEscapeSequence",x="Identifier",y="Null",z="Boolean",A="Keyword",B=["",p,p,q,p,r,s,u,v,t,w,q,x],C=B.length,D="\\r\\n\\u2028\\u2029",E="(?:\\r\\n|["+D+"])",F="(?:(?!["+D+"])\\s)+",G="(?=\\s*(?:(?!\\s*[/\\\\<>*+%`^\"'\\w$-])[^/\\\\<>*+%`^'\"({[\\w$-]|[!=]==?|[|][|]|&&|/[*/]|[,.;:!?)}\\]"+D+"]|$))",H="(?:>>>=?|[.]{3}|<<=|===|!==|>>=|[+][+](?=[+])|--(?=-)|[=!<>*%+/&|^-]=|&&|[|][|]|[+][+]|--|<<|>>|=>|[-+*/%<>=&|^~!?:;,.()[\\]{}])",I="(?:/(?![*])(?:\\\\.|[^/"+D+"\\\\])+/(?:[gimuy]{0,5}|\\b))",J="[^\\s+/%*=&|^~<>!?:;,.()[\\]{}'\"`-]",K="typeof|in|void|case|instanceof|yield|throw|delete",L="if|while|for|with",M=new RegExp("^(?:"+L+"|"+K+"|var|else|function|this|return|new|break|do|catch|finally|try|default|continue|switch|const|export|import|class|extends|debugger|super|let|static|enum|await|implements|package|protected|interface|private|public)$"),N=new RegExp(E),O=new RegExp("^"+J),P=new RegExp(J+"$"),Q=/^[+-]/,R=/[+-]$/,S=new RegExp("(?:(?:^(?:"+K+")$)|(?:(?![.\\]])"+H+"$))"),T=new RegExp("^(?:"+L+")$"),U=a(),V=a(!0);d.prototype={parseMatches:function(a,b){var c,d=this.line;this.regexParsing?c=this._currentRegexToken._loc.rangeStart+U.lastIndex:(c=V.lastIndex,g&&(c+=this.rangeStart));for(var e=1;C>e;e++){var f=a[e];if(f){var h,i,j=c-f.length-this.prevLineIndex,k=B[e];if(k===p){if("*"===f.charAt(1)&&this.updateLine(f,c),!this.options.comment)break}else if(k===q){if(this.line++,this.prevLineIndex=c,!this.options.lineTerminator)continue}else if(k===s)this.updateLine(f,c);else if(k===r)i=!0;else if(k===x)"null"===f?k=y:"true"===f||"false"===f?k=z:M.test(f)&&(k=A);else if(k===u){if(this.regexParsing)break;i=!0,h=this.parseRegExpFlags(f)}var l={type:k,value:f};h&&(l.regex=h),i&&(l._loc={line:this.line,columnStart:j,rangeStart:c-f.length,prevLineIndex:this.prevLineIndex}),k===r&&this.updateLine(f,c);var m=c-this.prevLineIndex;if(this.addRange(l,c),this.addLoc(l,d,j,this.line,m),b[b.length]=l,f===a[0])break}}},addRange:function(a,b){this.options.range&&(a.range=[b-a.value.length,b])},addLoc:function(a,b,c,d,e){this.options.loc&&(a.loc={start:{line:b,column:c},end:{line:d,column:e}})},updateLine:function(a,b){if(this.options.loc){var c=a.split(N);c.length>1&&(this.line+=c.length-1,this.prevLineIndex=b-c.pop().length)}},parseTemplate:function(a){for(var b=0;b<a.length;b++){var c=a[b];if(c.type===r){var d=this.parseTemplateBlock(c),e=this.parseTemplateExpr(d,c);m.apply(a,[b,1].concat(e)),b+=e.length}}},parseTemplateExpr:function(a,b){for(var d=[],e=0,f=a.length;f>e;e++){var h=a[e];if("tmp-source"===h.type){g=c({},h._loc,{type:r});var i=W(h.value,this.options);g=null,k.apply(d,i)}else d[d.length]=h}return d},parseTemplateBlock:function(a){for(var c,d,e,f,g,h,i,j,k=a.value,l=a._loc,m=l.line,n=m,p=l.columnStart,q=l.rangeStart,s=[l.prevLineIndex],t=[],u=0,v="",w=r,x=0,y=k.length;y>x;f=k.charCodeAt(x++)){var z=k.charCodeAt(x);b(z)&&(13===f&&10===z&&m--,m++,s[s.length]=q+x+1),g?y>x+1&&125===k.charCodeAt(x+1)&&(i=!0,w="tmp-source",g=!1):92===z?92===f?u++:u=1:36===z?h=92!==f||u%2===0:123===z&&h&&36===f&&(i=!0,w=r,g=!0),v+=o(z),x===y-1&&(i=!0,w=r),i&&(j={type:w,value:v},c=q+x+1,d=this.findPrevLineIndex(s,c),e=c-d,w===r?(this.addRange(j,c),this.addLoc(j,n,p,m,e),p=e+1):(c=q+x+1-v.length,d=this.findPrevLineIndex(s,c),j._loc={line:n,rangeStart:c,prevLineIndex:d},p=e),t[t.length]=j,v="",n=m,i=!1)}return t},findPrevLineIndex:function(a,b){for(var c=a.length-1;c>=0;--c){var d=a[c];if(b>=d)return d}},fixRegExpTokens:function(a){for(var b=0;b<a.length;b++)if(a[b].type===u){for(var c,d=b,e=a[b];--d>=0;){var f=a[d],g=f.type;if(g!==p&&g!==q){var h=f.value;if(g===t){if(")"===h){if(this.isValidRegExpPrefix(a,d+1))break}else if(S.test(h))break}else if(g===A&&S.test(h)||g===r&&"${"===h.slice(-2))break;var i=this.parseRegExp(e);m.apply(a,[b,1].concat(i)),c=!0;break}}c||delete e._loc}},isValidRegExpPrefix:function(a,b){for(var c=0;--b>=0;){var d=a[b],e=d.type;if(e===t){var f=d.value;if("("===f){if(0===--c){var g=a[b-1];return g&&g.type===A&&T.test(g.value)?!0:!1}}else")"===f&&c++}}return!1},parseRegExpFlags:function(a){var b=a.lastIndexOf("/"),c=a.substring(b+1),d=a.substr(1,b-1);return{pattern:d,flags:c}},parseRegExp:function(a){this._currentRegexToken=a;var b,c=a.value,d=[];for(this.options.loc&&(this.line=a.loc.start.line,this.prevLineIndex=a._loc.prevLineIndex),this.regexParsing=!0,U.lastIndex=0;null!=(b=U.exec(c));)this.parseMatches(b,d);return this.regexParsing=!1,this._currentRegexToken=null,d},tokenize:function(a){a=""+a,g?c(this,g):(this.line=1,this.prevLineIndex=0),this.regexParsing=!1;var b,d=[];for(V.lastIndex=0;null!=(b=V.exec(a));)this.parseMatches(b,d);return g&&g.type===r||this.parseTemplate(d),this.fixRegExpTokens(d),d}};var W=h.tokenize=function(a,b){return new d(b).tokenize(a)},X=32e3;return h.untokenize=e,h.minify=f,h});<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var assert = require('assert');
var lex = require('../');

var dir = __dirname + '/cases/';
fs.readdirSync(dir).forEach(function (testCase) {
  if (/\.pug$/.test(testCase)) {
    var expected;
    try {
      expected = fs.readFileSync(dir + testCase.replace(/\.pug$/, '.expected.json'), 'utf8')
                     .split(/\n/).filter(Boolean).map(JSON.parse);
    } catch (ex) {
      if (ex.code !== 'ENOENT') throw ex;
      expected = null;
    }
    var result = lex(fs.readFileSync(dir + testCase, 'utf8'), __dirname + '/cases/' + testCase);
    try {
      assert.deepEqual(expected, result);
    } catch (ex) {
      console.log('Updating ' + testCase);
      fs.writeFileSync(dir + testCase.replace(/\.pug$/, '.expected.json'),
                       result.map(JSON.stringify).join('\n'));
    }
  }
});

var edir = __dirname + '/errors/';
fs.readdirSync(edir).forEach(function (testCase) {
  if (/\.pug$/.test(testCase)) {
    var expected;
    try {
      expected = JSON.parse(fs.readFileSync(edir + testCase.replace(/\.pug$/, '.json'), 'utf8'));
    } catch (ex) {
      if (ex.code !== 'ENOENT') throw ex;
      expected = null;
    }
    var actual;
    try {
      lex(fs.readFileSync(edir + testCase, 'utf8'), edir + testCase);
      throw new Error('Expected ' + testCase + ' to throw an exception.');
    } catch (ex) {
      if (!ex || !ex.code || !ex.code.indexOf('PUG:') === 0) throw ex;
      actual = {
        msg: ex.msg,
        code: ex.code,
        line: ex.line,
        column: ex.column
      };
    }
    try {
      assert.deepEqual(expected, actual);
    } catch (ex) {
      console.log('Updating ' + testCase);
      fs.writeFileSync(edir + testCase.replace(/\.pug$/, '.json'),
                      JSON.stringify(actual, null, '  '));
    }
  }
});
<commit_msg>Make update-test-case working again<commit_after>'use strict';

var fs = require('fs');
var assert = require('assert');
var lex = require('../');

var dir = __dirname + '/cases/';
fs.readdirSync(dir).forEach(function (testCase) {
  if (/\.pug$/.test(testCase)) {
    var expected;
    try {
      expected = fs.readFileSync(dir + testCase.replace(/\.pug$/, '.expected.json'), 'utf8')
                     .split(/\n/).filter(Boolean).map(JSON.parse);
    } catch (ex) {
      if (ex.code !== 'ENOENT') throw ex;
      expected = null;
    }
    var result = lex(fs.readFileSync(dir + testCase, 'utf8'), {filename: __dirname + '/cases/' + testCase});
    try {
      assert.deepEqual(expected, result);
    } catch (ex) {
      console.log('Updating ' + testCase);
      fs.writeFileSync(dir + testCase.replace(/\.pug$/, '.expected.json'),
                       result.map(JSON.stringify).join('\n'));
    }
  }
});

var edir = __dirname + '/errors/';
fs.readdirSync(edir).forEach(function (testCase) {
  if (/\.pug$/.test(testCase)) {
    var expected;
    try {
      expected = JSON.parse(fs.readFileSync(edir + testCase.replace(/\.pug$/, '.json'), 'utf8'));
    } catch (ex) {
      if (ex.code !== 'ENOENT') throw ex;
      expected = null;
    }
    var actual;
    try {
      lex(fs.readFileSync(edir + testCase, 'utf8'), {filename: edir + testCase});
      throw new Error('Expected ' + testCase + ' to throw an exception.');
    } catch (ex) {
      if (!ex || !ex.code || !ex.code.indexOf('PUG:') === 0) throw ex;
      actual = {
        msg: ex.msg,
        code: ex.code,
        line: ex.line,
        column: ex.column
      };
    }
    try {
      assert.deepEqual(expected, actual);
    } catch (ex) {
      console.log('Updating ' + testCase);
      fs.writeFileSync(edir + testCase.replace(/\.pug$/, '.json'),
                      JSON.stringify(actual, null, '  '));
    }
  }
});
<|endoftext|>


<commit_before>const assert = require('assert');
// Have func LetterChanges(str) take the str parameter being
// passed & modify it using this algorithm:
// Replace every letter in string with the letter following it in
// the alphabet(ie. c becomes d). Then, capitalize every vowel in
// this new string and finally return modified string.

const LetterChanges = (str) => {
  const converted = str.replace(
    /[a-z]/gi,
    char =>
      (char === 'z' || char === 'Z'
        ? 'a'
        : String.fromCharCode(char.charCodeAt() + 1)),
  );

  // after converting each letter to the letter following it
  // in the alphabet, we need capitalize the vowels
  const capitalized = converted.replace(/a|e|i|o|u/gi, vowel =>
    vowel.toUpperCase());

  // return the final string
  return capitalized;
};

const a1 = 'dibmmfohf'; // input
const r1 = 'dIbmmfOhf'; // output
const t1 = LetterChanges(a1);
// console.log(r1);
assert(t1, r1);
<commit_msg>edit test<commit_after>const assert = require('assert');
// Have function LetterChanges(str) take the string parameter being
// passed & modify it using this algorithm:
// Replace every letter in string with the letter following it in
// the alphabet(ie. c becomes d). Then, capitalize every vowel in
// this new string and finally return modified string.

const LetterChanges = (str) => {
  const converted = str.replace(
    /[a-z]/gi,
    char =>
      (char === 'z' || char === 'Z'
        ? 'a'
        : String.fromCharCode(char.charCodeAt() + 1)),
  );

  // after converting each letter to the letter following it
  // in the alphabet, we need capitalize the vowels
  const capitalized = converted.replace(/a|e|i|o|u/gi, vowel =>
    vowel.toUpperCase());

  // return the final string
  return capitalized;
};

const a1 = 'challenge'; // input
const r1 = 'dibmmfohf'; // first output
const t1 = LetterChanges(a1);
// console.log(r1);
assert(t1, r1);

const r2 = 'dIbmmfOhf'; // final output
assert(r2);
// console.log(r2);
<|endoftext|>


<commit_before>/**
 * create a sandboxed module from the original source
 * @author sarkiroka
 */
var path = require('path');
var istanbulSourceCodeTransformerFix = require('./sandboxed-module-fix');
var sandboxedModule = require('sandboxed-module');
module.exports = function (filename) {
	if (typeof filename != 'string') {
		throw new Error('must specify the name of the test-file');
	}
	var originalFilename = filename.replace(/(?:\/|\\)test(?:\/|\\)unit(?:\/|\\)/, path.sep);
	return function (options) {
		options = options || {};
		options.sourceTransformers = options.sourceTransformers || {};
		if (!options.sourceTransformers['no-node_modules-transforming-required']) {
			options.sourceTransformers['no-node_modules-transforming-required'] = istanbulSourceCodeTransformerFix
		}
		return sandboxedModule.require(originalFilename, options);
	};
};
<commit_msg>sinon hozzáadva<commit_after>/**
 * create a sandboxed module from the original source
 * @author sarkiroka
 */
var path = require('path');
var istanbulSourceCodeTransformerFix = require('./sandboxed-module-fix');
var sandboxedModule = require('sandboxed-module');
var sinon = require('sinon');
module.exports = function (filename) {
	global.sinon = sinon;
	if (typeof filename != 'string') {
		throw new Error('must specify the name of the test-file');
	}
	var originalFilename = filename.replace(/(?:\/|\\)test(?:\/|\\)unit(?:\/|\\)/, path.sep);
	return function (options) {
		options = options || {};
		options.sourceTransformers = options.sourceTransformers || {};
		if (!options.sourceTransformers['no-node_modules-transforming-required']) {
			options.sourceTransformers['no-node_modules-transforming-required'] = istanbulSourceCodeTransformerFix
		}
		return sandboxedModule.require(originalFilename, options);
	};
};
<|endoftext|>


<commit_before>#!/usr/bin/env node

var argv = require('yargs').argv;
var chalk = require('chalk');
var moment = require('moment');
var keypress = require('keypress');

keypress(process.stdin);
process.stdin.setRawMode(true);
process.stdin.resume();

process.stdin.on('keypress', (ch, key) => {
    if(key && key.ctrl && key.name === 'c'){
        clear(); flush();
        process.stdin.pause();
        process.exit(1);
    }

    if(game.status <= Status.READY) start(); else if(game.status === Status.STARTED) switch(ch){
        case 'e': toggleFlag(cursor); break;
        case 'q': uncoverField(cursor); break;

        case 'w': cursor.w(); break;
        case 'd': cursor.d(); break;
        case 's': cursor.s(); break;
        case 'a': cursor.a(); break;

        default: if(key) switch(key.name){
            case 'up':    cursor.w(); break;
            case 'right': cursor.d(); break;
            case 'down':  cursor.s(); break;
            case 'left':  cursor.a(); break;
            default: return;
        }
    }

    printAll();
});

process.stdout.on('resize', () => {
    clear(); printAll();
});

const FieldType = {
    GROUND: 0,
    BLANK: 1,
    MINE: 2
};

const Border = {
    TOP: '▄', BOTTOM: '▀', CENTER: '█', LEFT: '▐', RIGHT: '▌',
    COLOR: chalk.yellow,
    SELECTION_COLOR: chalk.yellow.bold
};

var isNumeric = (x) => !isNaN(parseFloat(x)) && isFinite(x);

var consoleWidth = () => process.stdout.columns;
var consoleHeight = () => process.stdout.rows;

var fieldWidth = Math.min(2048, isNumeric(argv.x) ? parseFloat(argv.x) : consoleWidth() - 2);
var fieldHeight = Math.min(2048, isNumeric(argv.y) ? parseFloat(argv.y) : consoleHeight() - 3);

var fields = Array.apply(null, Array(fieldWidth)).map((v, x) => Array.apply(null, Array(fieldHeight)).map((v, y) => ({
    x: x, y: y,
    type: FieldType.GROUND,
    flagged: false
})));

var flatFields = () => fields.reduce((a, b) => a.concat(b));

var cursor = {
    x: Math.floor(fieldWidth / 2),
    y: Math.floor(fieldHeight / 2),
    w: () => cursor.y = Math.max(0, cursor.y - 1),
    d: () => cursor.x = Math.min(fieldWidth - 1, cursor.x + 1),
    s: () => cursor.y = Math.min(fieldHeight - 1, cursor.y + 1),
    a: () => cursor.x = Math.max(0, cursor.x - 1)
};

const Status = {
    READY: 0,
    STARTED: 1,
    FAILED: 2,
    SUCCEEDED: 3
};

var game = {
    status: Status.READY,
    startedTime: null,
    finishedTime: null,

    flagCount: 0,
    mineCount: Math.floor((fieldWidth * fieldHeight) / 100 * Math.min(50, isNumeric(argv._[0]) ? parseFloat(argv._[0]) : 15)),
    mineInstalled: false,
};

var vectorToField = (x, y) => {
    if(x && x.hasOwnProperty('x')){
        y = x.y; x = x.x;
    }

    return (fields[x] && fields[x][y]) || null;
};

var toggleFlag = (x, y) => {
    var field = vectorToField(x, y); if(!field) return;
    if(field.type === FieldType.BLANK) return;

    if(field.flagged = !field.flagged) game.flagCount++; else game.flagCount--;
    if(game.flagCount === game.mineCount && flatFields().filter(field => field.flagged).every(field => field.type === FieldType.MINE)) return finish(true);

    printAll();
};

var walkAround = (field, callback) => {
    var xx, yy; for(var i = -1; i <= 1; i++) for(var j = -1; j <= 1; j++) if((i || j) && (xx = field.x + i) >= 0 && (yy = field.y + j) >= 0 && xx < fieldWidth && yy < fieldHeight && callback(fields[xx][yy])) return;
};

var mineCount = (x, y) => {
    var field = vectorToField(x, y); if(!field) return;

    var count = 0; walkAround(field, (f) => {
        if(f.type === FieldType.MINE) count++;
    });

    return count;
};

var uncoverField = (x, y) => {
    var field = vectorToField(x, y); if(!field || field.flagged) return;
    if(!game.mineInstalled){
        game.mineInstalled = true;

        var exception = {}; exception[field.x + ':' + field.y] = true;
        randomVectorArray(game.mineCount, exception).forEach((vector) => fields[vector[0]][vector[1]].type = FieldType.MINE);
    }

    switch(field.type){
        case FieldType.MINE:
            finish(false);
            break;

        case FieldType.GROUND:
            field.type = FieldType.BLANK;

            uncoverGround(field.x, field.y - 1); //w
            uncoverGround(field.x + 1, field.y); //d
            uncoverGround(field.x, field.y + 1); //s
            uncoverGround(field.x - 1, field.y); //a
            break;

        default: return;
    }
};

var uncoverGround = (x, y) => {
    var queue = [vectorToField(x, y)];
    var check = {}, blanks = [];

    while(queue.length > 0){
        var field = queue.shift();
        if(!field || field.type !== FieldType.GROUND) continue;

        var key = field.x + ':' + field.y;
        if(check[key]) continue; check[key] = true;

        if(mineCount(field) !== 0) continue;
        field.type = FieldType.BLANK; blanks.push(field);

        queue.push(vectorToField(field.x, field.y - 1)); //w
        queue.push(vectorToField(field.x + 1, field.y)); //d
        queue.push(vectorToField(field.x, field.y + 1)); //s
        queue.push(vectorToField(field.x - 1, field.y)); //a
    }

    blanks.forEach((field) => walkAround(field, (f) => {
        if(f.type === FieldType.GROUND) f.type = FieldType.BLANK;
    }));
};

var buffer = '';

var write = (text) => buffer += text;
var flush = () => {
    process.stdout.write(buffer);
    buffer = '';
};

var clear = () => write('\033c');
var newLine = () => write('\n');
var moveCursor = (n, m) => write('\033[' + [n, m].map(i => i || '1').join(';') + 'H');

var repeat = (theChalk, text, count) => {
    for(var i = 0; i < count; i++) theChalk ? write(theChalk(text)) : write(text);
};

var capitalize = (str) => str && str.charAt(0).toUpperCase() + str.slice(1);

var random = (min, max) => {
    if(max === undefined){
        max = min; min = 0;
    }

    return min + Math.floor(Math.random() * (max - min));
};

var randomVectorArray = (count, exception) => {
    var check = {};
    var vectors = [];

    while(vectors.length < count){
        var vector = [random(fieldWidth), random(fieldHeight)]; var key = vector.join(':');
        if(!check[key] && !exception[key]){
            check[key] = true;
            vectors.push(vector);
        }
    }
    return vectors;
};

const Title = {
    COLOR: chalk.yellow.bold
};

var printTitle = (text, align) => {
    var spaces = consoleWidth() - text.length;

    switch(align){
        case 'left':
            write(Title.COLOR(text));
            repeat(Title.COLOR, ' ', spaces);
            break;

        default:
        case 'center':
            var leftSpaces = Math.floor(spaces / 2);
            repeat(Title.COLOR, ' ', leftSpaces);
            write(Title.COLOR(text));
            repeat(Title.COLOR, ' ', spaces - leftSpaces);
            break;

        case 'right':
            repeat(Title.COLOR, ' ', spaces);
            write(Title.COLOR(text));
            break;
    }

    newLine();
};

var blankColor = (count) => {
    if(count >= 7) return 'red';
    if(count >= 5) return 'blue';
    if(count >= 3) return 'yellow';
    else return 'black';
};

var getFieldString = (x, y) => {
    var field = fields[x][y];
    var output = {
        background: 'white', foreground: 'black', text: ' ', special: null
    };

    if(field.flagged){
        output.text = 'X';
        output.background = 'cyan';
    }

    else switch(field.type){
        case FieldType.GROUND:
        case FieldType.MINE:
            output.text = '?';
            output.background = 'black';
            break;

        case FieldType.BLANK:
            var count = mineCount(x, y);
            output.foreground = blankColor(count);
            if(count > 0) output.text = Math.min(count, 9).toString(10);
            break;
    }

    if(cursor.x === x && cursor.y === y) output.background = 'green';

    if(game.status > Status.STARTED && field.type === FieldType.MINE){
        output.text = '!';
        output.foreground = 'white';
        output.special = 'bold';

        if(!field.flagged) output.background = 'red';
    }

    var theChalk = chalk['bg' + capitalize(output.background)][output.foreground];
    if(output.special) theChalk = theChalk[output.special];

    return theChalk(output.text);
};

var getElapsedTime = (now) => moment.utc((now || moment()).diff(game.startedTime)).format("HH:mm:ss");

var printAll = (title) => {
    moveCursor();

    var marginTop = Math.round((consoleHeight() - fieldHeight - 3) / 2);
    var marginLeft = Math.round((consoleWidth() - fieldWidth - 2) / 2);

    repeat(null, '\n', marginTop);

    switch(game.status){
        case Status.READY:
            printTitle("Press any key to start...");
            break;

        case Status.STARTED:
            var title = getElapsedTime() + ' | ' + game.flagCount + '/' + game.mineCount;
            var cursorText = ' | (' + cursor.x + ', ' + cursor.y + ')';
            printTitle((title.length + cursorText.length) < consoleWidth() ? title + cursorText : title);
            break;

        case Status.FAILED:
            printTitle(getElapsedTime(game.finishedTime) + ' | ' + game.mineCount + " | Failed");
            break;

        case Status.SUCCEEDED:
            printTitle(getElapsedTime(game.finishedTime) + ' | ' + game.mineCount + " | Succeeded");
            break;
    }

    repeat(null, ' ', marginLeft);
    repeat(Border.COLOR, Border.TOP, cursor.x + 1);
    write(Border.SELECTION_COLOR(Border.TOP));
    repeat(Border.COLOR, Border.TOP, fieldWidth - cursor.x);
    newLine();

    for(var y = 0; y < fieldHeight; y++){
        var border = (y === cursor.y ? Border.SELECTION_COLOR : Border.COLOR)(Border.CENTER);
        repeat(null, ' ', marginLeft); write(border); for(var x = 0; x < fieldWidth; x++) write(getFieldString(x, y)); write(border); newLine();
    }

    repeat(null, ' ', marginLeft); repeat(Border.COLOR, Border.BOTTOM, cursor.x + 1);
    write(Border.SELECTION_COLOR(Border.BOTTOM));
    repeat(Border.COLOR, Border.BOTTOM, fieldWidth - cursor.x);

    flush();
};

var printer = null;

var start = () => {
    if(game.status > Status.READY) return;

    game.status = Status.STARTED;
    game.startedTime = moment();

    printAll();
};

var finish = (succeeded) => {
    if(game.status > Status.STARTED) return;

    game.status = succeeded ? Status.SUCCEEDED : Status.FAILED;
    game.finishedTime = moment();

    printAll();
    setTimeout(() => {
        newLine(); flush();
        process.exit(0);
    }, 3000);
};

game.status = Status.READY; clear(); printAll();
printer = setInterval(printAll, 200);
<commit_msg>Small changes<commit_after>#!/usr/bin/env node

var argv = require('yargs').argv;
var chalk = require('chalk');
var moment = require('moment');
var keypress = require('keypress');

keypress(process.stdin);
process.stdin.setRawMode(true);
process.stdin.resume();

process.stdin.on('keypress', (ch, key) => {
    if(key && key.ctrl && key.name === 'c'){
        clear(); flush();
        process.stdin.pause();
        process.exit(1);
    }

    if(game.status <= Status.READY) start(); else if(game.status === Status.STARTED) switch(ch){
        case 'e': toggleFlag(cursor); break;
        case 'q': uncoverField(cursor); break;

        case 'w': cursor.w(); break;
        case 'd': cursor.d(); break;
        case 's': cursor.s(); break;
        case 'a': cursor.a(); break;

        default: if(key) switch(key.name){
            case 'up':    cursor.w(); break;
            case 'right': cursor.d(); break;
            case 'down':  cursor.s(); break;
            case 'left':  cursor.a(); break;
            default: return;
        }
    }

    printAll();
});

process.stdout.on('resize', () => {
    clear(); printAll();
});

const FieldType = {
    GROUND: 0,
    BLANK: 1,
    MINE: 2
};

const Border = {
    TOP: '▄', BOTTOM: '▀', CENTER: '█', LEFT: '▐', RIGHT: '▌',
    COLOR: chalk.yellow,
    SELECTION_COLOR: chalk.yellow.bold
};

var isNumeric = (x) => !isNaN(parseFloat(x)) && isFinite(x);

var consoleWidth = () => process.stdout.columns;
var consoleHeight = () => process.stdout.rows;

var fieldWidth = Math.min(2048, isNumeric(argv.x) ? parseFloat(argv.x) : consoleWidth() - 2);
var fieldHeight = Math.min(2048, isNumeric(argv.y) ? parseFloat(argv.y) : consoleHeight() - 3);

var fields = Array.apply(null, Array(fieldWidth)).map((v, x) => Array.apply(null, Array(fieldHeight)).map((v, y) => ({
    x: x, y: y,
    type: FieldType.GROUND,
    flagged: false
})));

var flatFields = () => fields.reduce((a, b) => a.concat(b));

var cursor = {
    x: Math.floor(fieldWidth / 2),
    y: Math.floor(fieldHeight / 2),
    w: () => cursor.y = Math.max(0, cursor.y - 1),
    d: () => cursor.x = Math.min(fieldWidth - 1, cursor.x + 1),
    s: () => cursor.y = Math.min(fieldHeight - 1, cursor.y + 1),
    a: () => cursor.x = Math.max(0, cursor.x - 1)
};

const Status = {
    READY: 0,
    STARTED: 1,
    FAILED: 2,
    SUCCEEDED: 3
};

var game = {
    status: Status.READY,
    startedTime: null,
    finishedTime: null,

    flagCount: 0,
    mineCount: Math.floor((fieldWidth * fieldHeight) / 100 * Math.min(50, isNumeric(argv._[0]) ? parseFloat(argv._[0]) : 15)),
    mineInstalled: false,
};

var vectorToField = (x, y) => {
    if(x && x.hasOwnProperty('x')){
        y = x.y; x = x.x;
    }

    return (fields[x] && fields[x][y]) || null;
};

var toggleFlag = (x, y) => {
    var field = vectorToField(x, y); if(!field) return;
    if(field.type === FieldType.BLANK) return;

    if(field.flagged = !field.flagged) game.flagCount++; else game.flagCount--;
    if(game.flagCount === game.mineCount && flatFields().filter(field => field.flagged).every(field => field.type === FieldType.MINE)) return finish(true);

    printAll();
};

var walkAround = (field, callback) => {
    var xx, yy; for(var i = -1; i <= 1; i++) for(var j = -1; j <= 1; j++) if((i || j) && (xx = field.x + i) >= 0 && (yy = field.y + j) >= 0 && xx < fieldWidth && yy < fieldHeight && callback(fields[xx][yy])) return;
};

var mineCount = (x, y) => {
    var field = vectorToField(x, y); if(!field) return;

    var count = 0; walkAround(field, (f) => {
        if(f.type === FieldType.MINE) count++;
    });

    return count;
};

var uncoverField = (x, y) => {
    var field = vectorToField(x, y); if(!field || field.flagged) return;
    if(!game.mineInstalled){
        game.mineInstalled = true;

        var exception = {}; exception[field.x + ':' + field.y] = true;
        randomVectorArray(game.mineCount, exception).forEach((vector) => fields[vector[0]][vector[1]].type = FieldType.MINE);
    }

    switch(field.type){
        case FieldType.MINE:
            finish(false);
            break;

        case FieldType.GROUND:
            field.type = FieldType.BLANK;

            uncoverGround(field.x, field.y - 1); //w
            uncoverGround(field.x + 1, field.y); //d
            uncoverGround(field.x, field.y + 1); //s
            uncoverGround(field.x - 1, field.y); //a
            break;

        default: return;
    }
};

var uncoverGround = (x, y) => {
    var queue = [vectorToField(x, y)];
    var check = {}, blanks = [];

    while(queue.length > 0){
        var field = queue.shift();
        if(!field || field.type !== FieldType.GROUND) continue;

        var key = field.x + ':' + field.y;
        if(check[key]) continue; check[key] = true;

        if(mineCount(field) !== 0) continue;
        field.type = FieldType.BLANK; blanks.push(field);

        queue.push(vectorToField(field.x, field.y - 1)); //w
        queue.push(vectorToField(field.x + 1, field.y)); //d
        queue.push(vectorToField(field.x, field.y + 1)); //s
        queue.push(vectorToField(field.x - 1, field.y)); //a
    }

    blanks.forEach((field) => walkAround(field, (f) => {
        if(f.type === FieldType.GROUND) f.type = FieldType.BLANK;
    }));
};

var buffer = '';

var write = (text) => buffer += text;
var flush = () => {
    process.stdout.write(buffer);
    buffer = '';
};

var clear = () => write('\033c');
var newLine = () => write('\n');
var moveCursor = (n, m) => write('\033[' + [n, m].map(i => i || '1').join(';') + 'H');

var repeat = (theChalk, text, count) => {
    for(var i = 0; i < count; i++) theChalk ? write(theChalk(text)) : write(text);
};

var capitalize = (str) => str && str.charAt(0).toUpperCase() + str.slice(1);

var random = (min, max) => {
    if(max === undefined){
        max = min; min = 0;
    }

    return min + Math.floor(Math.random() * (max - min));
};

var randomVectorArray = (count, exception) => {
    var check = {};
    var vectors = [];

    while(vectors.length < count){
        var vector = [random(fieldWidth), random(fieldHeight)]; var key = vector.join(':');
        if(!check[key] && !exception[key]){
            check[key] = true;
            vectors.push(vector);
        }
    }
    return vectors;
};

const Title = {
    COLOR: chalk.yellow.bold
};

var printTitle = (text, align) => {
    var spaces = consoleWidth() - text.length;

    switch(align){
        case 'left':
            write(Title.COLOR(text));
            repeat(Title.COLOR, ' ', spaces);
            break;

        default:
        case 'center':
            var leftSpaces = Math.floor(spaces / 2);
            repeat(Title.COLOR, ' ', leftSpaces);
            write(Title.COLOR(text));
            repeat(Title.COLOR, ' ', spaces - leftSpaces);
            break;

        case 'right':
            repeat(Title.COLOR, ' ', spaces);
            write(Title.COLOR(text));
            break;
    }

    newLine();
};

var blankColor = (count) => {
    if(count >= 7) return 'red';
    if(count >= 5) return 'blue';
    if(count >= 3) return 'yellow';
    else return 'black';
};

var getFieldString = (x, y) => {
    var field = fields[x][y];
    var output = {
        background: 'white', foreground: 'black', text: ' ', special: null
    };

    if(field.flagged){
        output.text = 'X';
        output.background = 'cyan';
    }

    else switch(field.type){
        case FieldType.GROUND:
        case FieldType.MINE:
            output.text = '?';
            output.background = 'black';
            break;

        case FieldType.BLANK:
            var count = mineCount(x, y);
            output.foreground = blankColor(count);
            if(count > 0) output.text = Math.min(count, 9).toString(10);
            break;
    }

    if(cursor.x === x && cursor.y === y) output.background = 'green';

    if(game.status > Status.STARTED && field.type === FieldType.MINE){
        output.text = '!';
        output.foreground = 'white';
        output.special = 'bold';

        if(!field.flagged) output.background = 'red';
    }

    var theChalk = chalk['bg' + capitalize(output.background)][output.foreground];
    if(output.special) theChalk = theChalk[output.special];

    return theChalk(output.text);
};

var getElapsedTime = (now) => moment.utc((now || moment()).diff(game.startedTime)).format("HH:mm:ss");

var printAll = (title) => {
    moveCursor();

    var marginTop = Math.floor((consoleHeight() - fieldHeight - 3) / 2);
    var marginLeft = Math.round((consoleWidth() - fieldWidth - 2) / 2);

    repeat(null, '\n', marginTop);

    switch(game.status){
        case Status.READY:
            printTitle("Press any key to start...");
            break;

        case Status.STARTED:
            var title = getElapsedTime() + ' | ' + game.flagCount + '/' + game.mineCount;
            var cursorText = ' | (' + cursor.x + ', ' + cursor.y + ')';
            printTitle((title.length + cursorText.length) < consoleWidth() ? title + cursorText : title);
            break;

        case Status.FAILED:
            printTitle(getElapsedTime(game.finishedTime) + ' | ' + game.mineCount + " | Failed");
            break;

        case Status.SUCCEEDED:
            printTitle(getElapsedTime(game.finishedTime) + ' | ' + game.mineCount + " | Succeeded");
            break;
    }

    repeat(null, ' ', marginLeft);
    repeat(Border.COLOR, Border.TOP, cursor.x + 1);
    write(Border.SELECTION_COLOR(Border.TOP));
    repeat(Border.COLOR, Border.TOP, fieldWidth - cursor.x);
    newLine();

    for(var y = 0; y < fieldHeight; y++){
        var border = (y === cursor.y ? Border.SELECTION_COLOR : Border.COLOR)(Border.CENTER);
        repeat(null, ' ', marginLeft); write(border); for(var x = 0; x < fieldWidth; x++) write(getFieldString(x, y)); write(border); newLine();
    }

    repeat(null, ' ', marginLeft); repeat(Border.COLOR, Border.BOTTOM, cursor.x + 1);
    write(Border.SELECTION_COLOR(Border.BOTTOM));
    repeat(Border.COLOR, Border.BOTTOM, fieldWidth - cursor.x);

    flush();
};

var printer = null;

var start = () => {
    if(game.status > Status.READY) return;

    game.status = Status.STARTED;
    game.startedTime = moment();

    printAll();
};

var finish = (succeeded) => {
    if(game.status > Status.STARTED) return;

    game.status = succeeded ? Status.SUCCEEDED : Status.FAILED;
    game.finishedTime = moment();

    printAll();
    setTimeout(() => {
        newLine(); flush();
        process.exit(0);
    }, 3000);
};

game.status = Status.READY; clear(); printAll();
printer = setInterval(printAll, 200);
<|endoftext|>


<commit_before>importScripts('/assets/js/turfjs/turf.min.js');
importScripts('/assets/js/rtree/rtree.min.js');

function isOdd(num) {
    return num % 2;
}

function generateFinal3DGeoms(constraintedModelDesigns) {

    var finalGJFeats = [];
    var plFeats = [];
    var centerPt = turf.center(constraintedModelDesigns);
    var lat = centerPt.geometry.coordinates[1];
    var lng = centerPt.geometry.coordinates[0];
    var curFeats = constraintedModelDesigns.features;
    var featLen = curFeats.length;

    for (var k = 0; k < featLen; k++) {
        var curFeat = curFeats[k];
        if (curFeat.properties.areatype === 'policy') {
            // create a grid
            var props = curFeat.properties;
            props.color = (props.color === undefined || props.color === null) ? '#808080' : props.color;

            var extent = turf.extent(curFeat);
            var cellWidth = 0.1;
            var units = 'kilometers';
            var squareGrid = turf.squareGrid(extent, cellWidth, units);
            // process policy polygons
            var sqGridFeats = squareGrid.features;
            var sqGridFlen = sqGridFeats.length;
            var finalFeats = [];
            var featcounter = 0;
            for (var k1 = 0; k1 < sqGridFlen; k1++) {
                var cursqFeat = sqGridFeats[k1];
                var ifeat;
                if (isOdd(featcounter)) {
                    try {
                        ifeat = turf.intersect(curFeat, cursqFeat);

                    } catch (err) { //throw JSON.stringify(err)
                        console.log(err);
                    }
                    if (ifeat) {
                        ifeat.properties = props;
                        finalGJFeats.push(ifeat);
                        finalFeats.push(ifeat);
                    }
                }
                featcounter += 1;
            }
        } else {
            curFeat.properties.color = (curFeat.properties.color === undefined || curFeat.properties.color === null) ? '#808080' : curFeat.properties.color;
            finalGJFeats.push(curFeat);
        }

    }

    var f = {
        "type": "FeatureCollection",
        "features": finalFeats
    };
    // console.log(JSON.stringify(f));
    var fpolygons = {
        "type": "FeatureCollection",
        "features": finalGJFeats
    };

    self.postMessage({
        'polygons': JSON.stringify(fpolygons),
        'center': JSON.stringify([lat, lng])
    });
}

function generate3DGeoms(allFeaturesList) {;
    var allFeaturesList = JSON.parse(allFeaturesList);
    var threeDOutput = generateFinal3DGeoms(allFeaturesList);

}

self.onmessage = function(e) {
    generate3DGeoms(e.data.allFeaturesList);

}<commit_msg>Updated to include new structure<commit_after><|endoftext|>


<commit_before>// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path')

module.exports = {
  build: {
    env: require('./prod.env'),
    index: path.resolve(__dirname, '../dist/index.html'),
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    productionSourceMap: true,
    // Gzip off by default as many popular static hosts such as
    // Surge or Netlify already gzip all static assets for you.
    // Before setting to `true`, make sure to:
    // npm install --save-dev compression-webpack-plugin
    productionGzip: false,
    productionGzipExtensions: ['js', 'css'],
    // Run the build command with an extra argument to
    // View the bundle analyzer report after build finishes:
    // `npm run build --report`
    // Set to `true` or `false` to always turn it on or off
    bundleAnalyzerReport: process.env.npm_config_report
  },
  dev: {
    env: require('./dev.env'),
    port: 8080,
    autoOpenBrowser: true,
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {},
    // CSS Sourcemaps off by default because relative paths are "buggy"
    // with this option, according to the CSS-Loader README
    // (https://github.com/webpack/css-loader#sourcemaps)
    // In our experience, they generally work as expected,
    // just be aware of this issue when enabling this option.
    cssSourceMap: false
  }
}
<commit_msg>[#] Build in the public dir of the server<commit_after>// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path')

module.exports = {
  build: {
    env: require('./prod.env'),
    index: path.resolve(__dirname, '../../server/dist/index.html'),
    assetsRoot: path.resolve(__dirname, '../../server/dist'),
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    productionSourceMap: true,
    // Gzip off by default as many popular static hosts such as
    // Surge or Netlify already gzip all static assets for you.
    // Before setting to `true`, make sure to:
    // npm install --save-dev compression-webpack-plugin
    productionGzip: false,
    productionGzipExtensions: ['js', 'css'],
    // Run the build command with an extra argument to
    // View the bundle analyzer report after build finishes:
    // `npm run build --report`
    // Set to `true` or `false` to always turn it on or off
    bundleAnalyzerReport: process.env.npm_config_report
  },
  dev: {
    env: require('./dev.env'),
    port: 8080,
    autoOpenBrowser: true,
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {},
    // CSS Sourcemaps off by default because relative paths are "buggy"
    // with this option, according to the CSS-Loader README
    // (https://github.com/webpack/css-loader#sourcemaps)
    // In our experience, they generally work as expected,
    // just be aware of this issue when enabling this option.
    cssSourceMap: false
  }
}
<|endoftext|>


<commit_before>enyo.kind({
	name        : 'enyo.sample.FlexLayoutSample',
	classes     : 'flex-layout-sample enyo-unselectable',
	layoutKind  : 'enyo.FlexLayout',
	flexSpacing : 10,
	components: [
		{name: 'uberBlock1', flexOrient: 'column', style: 'width: 200px',  content: 'Block 1', components: [
			{name: 'button1', kind: 'onyx.Button', content: 'Add column content',       ontap: 'addContent1'},
			{name: 'button2', kind: 'onyx.Button', content: 'Add row content',          ontap: 'addContent2'},
			{name: 'button3', kind: 'onyx.Button', content: 'Set flexBias to "column"', ontap: 'toggleBias'},
			{name: 'button4', kind: 'onyx.Button', content: 'Set flexStretch to false', ontap: 'toggleStretch'},
			{name: 'stats'}
		]},
		{name: 'uberBlock2', layoutKind : 'enyo.FlexLayout',
			flexStretch       : true,
			flexOrient        : 'column',
			flex              : true,
			flexSpacing       : 10,
			flexBias          : 'row',
			flexResponseWidth : 1000,
			components: [
				{name: 'block1', classes: 'column',	content: 'Block 1',
					flexOrient   : 'column',
					flex         : true
				},
				{name: 'block2', classes: '', content: 'Block 2',
					flexOrient   : 'column',
					flexResponse : 'RowAfterColumns'
				},
				{name: 'block3', content: 'Block 3', classes: '',
					flexOrient   : 'column',
					flexResponse : 'RowAfterColumns',
					flex         : 'content',
					maxWidth     : 200,
					maxHeight    : 100,
					components   : [
						{name: 'block3a', content: 'Block 3a', style: 'border: 1px solid white; display: inline;'}
					]
				},
				{name: 'block5', classes: '', content: 'Block 5',
					flexOrient   : 'column',
					flex         : true
				},
				{name: 'block6', classes: 'column', content: 'Block 6',
					flex         : 'content',
					flexOrient   : 'row',
					maxWidth     : 200,
					maxHeight    : 100
				},
				{name: 'block7', classes: 'column', content: 'Block 7',
					flexOrient   : 'row',
					flex         : true
				},
				{name: 'block8', classes: '', content: 'Block 8',
					flexOrient   : 'column',
					flex         : true
				},
				{name: 'block9', classes: '', content: 'Block 9',
					flexOrient   : 'row',
					flex         : true
				}
			]
		}
	],
	statics: {
		loremIpsum: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, ' +
		'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ' +
		'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut ' +
		'aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in ' +
		'voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint ' +
		'occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit ' +
		'anim id est laborum.'
	},

	people: [
		{name: 'Andrew',      sex: 'male'},
		{name: 'Betty',       sex: 'female'},
		{name: 'Christopher', sex: 'male'},
		{name: 'Donna',       sex: 'female'},
		{name: 'Ephraim',     sex: 'male'},
		{name: 'Frankie',     sex: 'male'},
		{name: 'Gerald',      sex: 'male'},
		{name: 'Heather',     sex: 'female'},
		{name: 'Ingred',      sex: 'female'},
		{name: 'Jack',        sex: 'male'},
		{name: 'Kevin',       sex: 'male'},
		{name: 'Lucy',        sex: 'female'},
		{name: 'Matthew',     sex: 'male'},
		{name: 'Noreen',      sex: 'female'},
		{name: 'Oscar',       sex: 'male'},
		{name: 'Pedro',       sex: 'male'},
		{name: 'Quentin',     sex: 'male'},
		{name: 'Ralph',       sex: 'male'},
		{name: 'Steven',      sex: 'male'},
		{name: 'Tracy',       sex: 'female'},
		{name: 'Uma',         sex: 'female'},
		{name: 'Victor',      sex: 'male'},
		{name: 'Wendy',       sex: 'female'},
		{name: 'Xin',         sex: 'male'},
		{name: 'Yulia',       sex: 'female'}
	],

	create: function() {
		this.inherited(arguments);
		// this.$.repeater.setCount(this.people.length);
	},

	rendered: function() {
		this.inherited(arguments);

		var oControl,
			n       = 0,
			aColors = [
				'#668CFF', '#8C66FF', '#D966FF', '#FF66D9',
				'#FF668C', '#FF8C66', // '#FFD966', '#D9FF66',
//				'#8CFF66', '#66FF8C', '#66FFD9', '#66D9FF',
				'#295EFF', '#003BEB', '#FFC929', '#EBB000'
			];

		for (; n<this.$.uberBlock2.children.length; n++) {
			oControl = this.$.uberBlock2.children[n];
			enyo.Styles.setStyles(oControl, {'background-color' : aColors[n]});
		}

		this.markBlocks();
		// enyo.Styles.setStyles(this.$.uberBlock1, {'background-color' : aColors[aColors.length - 9]});
	},

	markBlocks: function() {
		enyo.forEach(this.$.uberBlock2.children, function(oControl) {
			oControl.setContent('flex:' + (typeof oControl.flex == 'undefined' ? 'false' : oControl.flex) + ', orient:' + oControl.flexOrient);
		});
		this.$.uberBlock2.layout.reflow();
	},

	setupItem: function(inSender, inEvent) {
		var index = inEvent.index;
		var item = inEvent.item;
		var person = this.people[index];
		item.$.personNumber.setContent((index+1) + '. ');
		item.$.personName.setContent(person.name);
		return true;
	},

	addContent: function(oControl, nLength) {
		oControl.addContent(' ' + enyo.sample.FlexLayoutSample.loremIpsum.substr(0, nLength));
	},

	addContent1: function() {
		this.addContent(this.$.block3a, 11);
	},

	addContent2: function() {
		this.addContent(this.$.block6, 100);
	},

	reflowUberBlock2: function() {
		enyo.forEach(this.$.uberBlock2.children, function(oControl) {
			if (oControl.layout) {
				oControl.layout.reflow();
			}
		});
		this.$.uberBlock2.layout.reflow();
	},

	toggleBias: function() {
		if (this.$.uberBlock2.flexBias != 'column') {
			this.$.uberBlock2.flexBias = 'column';
			this.$.button3.setContent('Set flexBias to "row"');
		} else {
			this.$.uberBlock2.flexBias = 'row';
			this.$.button3.setContent('Set flexBias to "column"');
		}
		this.reflowUberBlock2();
		this.markBlocks();
	},

	toggleStretch: function() {
		if (typeof this.$.uberBlock2.flexStretch == 'undefined' || !this.$.uberBlock2.flexStretch) {
			this.$.uberBlock2.flexStretch = true;
			this.$.button4.setContent('Set flexStretch to false');
		} else {
			this.$.uberBlock2.flexStretch = false;
			this.$.button4.setContent('Set flexStretch to true');
		}
		enyo.forEach(this.$.uberBlock2.children, function(oControl) {
			enyo.Styles.setStyles(oControl, {width: 'auto', height: 'auto'});
		});
		this.reflowUberBlock2();
	}
});<commit_msg>Adding final touches to sample<commit_after>enyo.kind({
	name        : 'enyo.sample.FlexLayoutSample',
	classes     : 'flex-layout-sample enyo-unselectable',
	layoutKind  : 'enyo.FlexLayout',
	flexSpacing : 10,
	components: [
		{name: 'uberBlock1', flexOrient: 'column', style: 'width: 200px',  content: 'Block 1', components: [
			{name: 'button1', kind: 'onyx.Button', content: 'Add column content',       ontap: 'addContent1'},
			{name: 'button2', kind: 'onyx.Button', content: 'Add row content',          ontap: 'addContent2'},
			{name: 'button3', kind: 'onyx.Button', content: 'Set flexBias to "column"', ontap: 'toggleBias'},
			{name: 'button4', kind: 'onyx.Button', content: 'Set flexStretch to false', ontap: 'toggleStretch'},
			{name: 'stats'}
		]},
		{name: 'uberBlock2', layoutKind : 'enyo.FlexLayout',
			flexStretch       : true,
			flexOrient        : 'column',
			flex              : true,
			flexSpacing       : 10,
			flexBias          : 'row',
			flexResponseWidth : 1000,
			components: [
				{name: 'block1', classes: 'column',	content: 'Block 1', allowHtml: true,
					flexOrient   : 'column',
					flex         : true
				},
				{name: 'block2', classes: '', content: 'Block 2', allowHtml: true,
					flexOrient   : 'column',
					flexResponse : 'RowAfterColumns'
				},
				{name: 'block3', content: 'Block 3', classes: '', allowHtml: true,
					flexOrient   : 'column',
					flexResponse : 'RowAfterColumns',
					flex         : 'content',
					maxWidth     : 250,
					maxHeight    : 100
				},
				{name: 'block5', classes: '', content: 'Block 5', allowHtml: true,
					flexOrient   : 'column',
					flex         : true
				},
				{name: 'block6', classes: 'column', content: 'Block 6', allowHtml: true,
					flex         : 'content',
					flexOrient   : 'row',
					maxWidth     : 200,
					maxHeight    : 100
				},
				{name: 'block7', classes: 'column', content: 'Block 7', allowHtml: true,
					flexOrient   : 'row',
					flex         : true
				},
				{name: 'block8', classes: '', content: 'Block 8', allowHtml: true,
					flexOrient   : 'column',
					flex         : true
				},
				{name: 'block9', classes: '', content: 'Block 9', allowHtml: true,
					flexOrient   : 'row',
					flex         : true
				}
			]
		}
	],
	statics: {
		loremIpsum: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, ' +
		'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ' +
		'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut ' +
		'aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in ' +
		'voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint ' +
		'occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit ' +
		'anim id est laborum.'
	},

	people: [
		{name: 'Andrew',      sex: 'male'},
		{name: 'Betty',       sex: 'female'},
		{name: 'Christopher', sex: 'male'},
		{name: 'Donna',       sex: 'female'},
		{name: 'Ephraim',     sex: 'male'},
		{name: 'Frankie',     sex: 'male'},
		{name: 'Gerald',      sex: 'male'},
		{name: 'Heather',     sex: 'female'},
		{name: 'Ingred',      sex: 'female'},
		{name: 'Jack',        sex: 'male'},
		{name: 'Kevin',       sex: 'male'},
		{name: 'Lucy',        sex: 'female'},
		{name: 'Matthew',     sex: 'male'},
		{name: 'Noreen',      sex: 'female'},
		{name: 'Oscar',       sex: 'male'},
		{name: 'Pedro',       sex: 'male'},
		{name: 'Quentin',     sex: 'male'},
		{name: 'Ralph',       sex: 'male'},
		{name: 'Steven',      sex: 'male'},
		{name: 'Tracy',       sex: 'female'},
		{name: 'Uma',         sex: 'female'},
		{name: 'Victor',      sex: 'male'},
		{name: 'Wendy',       sex: 'female'},
		{name: 'Xin',         sex: 'male'},
		{name: 'Yulia',       sex: 'female'}
	],

	create: function() {
		this.inherited(arguments);
		// this.$.repeater.setCount(this.people.length);
	},

	rendered: function() {
		this.inherited(arguments);

		var oControl,
			n       = 0,
			aColors = [
				'#668CFF', '#8C66FF', '#D966FF', '#FF66D9',
				'#FF668C', '#FF8C66', // '#FFD966', '#D9FF66',
//				'#8CFF66', '#66FF8C', '#66FFD9', '#66D9FF',
				'#295EFF', '#003BEB', '#FFC929', '#EBB000'
			];

		for (; n<this.$.uberBlock2.children.length; n++) {
			oControl = this.$.uberBlock2.children[n];
			enyo.Styles.setStyles(oControl, {'background-color' : aColors[n]});
		}

		this.markBlocks();
		// enyo.Styles.setStyles(this.$.uberBlock1, {'background-color' : aColors[aColors.length - 9]});
	},

	markBlocks: function() {
		enyo.forEach(this.$.uberBlock2.children, function(oControl) {
			oControl.setContent('flex:' + (typeof oControl.flex == 'undefined' ? 'false' : oControl.flex) + '
flexOrient:' + oControl.flexOrient + '
');
		});
		this.$.uberBlock2.layout.reflow();
	},

	setupItem: function(inSender, inEvent) {
		var index = inEvent.index;
		var item = inEvent.item;
		var person = this.people[index];
		item.$.personNumber.setContent((index+1) + '. ');
		item.$.personName.setContent(person.name);
		return true;
	},

	addContent: function(oControl, nLength) {
		oControl.addContent(' ' + enyo.sample.FlexLayoutSample.loremIpsum.substr(0, nLength));
	},

	addContent1: function() {
		this.addContent(this.$.block3, 11);
	},

	addContent2: function() {
		this.addContent(this.$.block6, 100);
	},

	reflowUberBlock2: function() {
		enyo.forEach(this.$.uberBlock2.children, function(oControl) {
			if (oControl.layout) {
				oControl.layout.reflow();
			}
		});
		this.$.uberBlock2.layout.reflow();
	},

	toggleBias: function() {
		if (this.$.uberBlock2.flexBias != 'column') {
			this.$.uberBlock2.flexBias = 'column';
			this.$.button3.setContent('Set flexBias to "row"');
		} else {
			this.$.uberBlock2.flexBias = 'row';
			this.$.button3.setContent('Set flexBias to "column"');
		}
		this.reflowUberBlock2();
		this.markBlocks();
	},

	toggleStretch: function() {
		if (typeof this.$.uberBlock2.flexStretch == 'undefined' || !this.$.uberBlock2.flexStretch) {
			this.$.uberBlock2.flexStretch = true;
			this.$.button4.setContent('Set flexStretch to false');
		} else {
			this.$.uberBlock2.flexStretch = false;
			this.$.button4.setContent('Set flexStretch to true');
		}
		enyo.forEach(this.$.uberBlock2.children, function(oControl) {
			enyo.Styles.setStyles(oControl, {width: 'auto', height: 'auto'});
		});
		this.reflowUberBlock2();
	}
});<|endoftext|>


<commit_before>var express = require('express');
var router = express.Router();

var userControllers = require("../controllers/user.js");
var logs = require("./logs");
var regex = require("./regex");
var list = require("./list");
var config = require("./config");
var server = require("./server");
var test = require("./test");
var user = require("./user")
var auth = require("../auth");

router.get('/', auth.Auth, function(req, res) {
	var m_result = {
		titile: "index"
	}
	process.nextTick(function () {	//for more effective
		req.getUser(function (err, result) {
			if(err) {
				res.redirect("login");
			}else {
				m_result.user = {
					id: result.id,
					username: result.username
				}
				res.render("index", m_result);
			}
		});
	});
});

router.get('/login', function(req, res) {
	if(req.isAuth) {
		res.redirect('/');
	}else{
		res.render("login");
	}
});

router.post('/login', function(req, res) {
	req.login(req.body.username, req.body.password, function (err) {
		if (err){
			res.redirect('/login');
		}else {
			res.redirect('/')
		}
	})
});

router.get('/logout', function(req, res) {
	req.logout(function (err) {
		if(err){
			// Impossible
			res.writeHead(404);
			res.end();
		}else {
			res.redirect('/login');
		}
	});
});

router.post("/user/:id", user.update);

router.get("/logs", auth.Auth, logs.list);
router.get("/logs/:page", auth.Auth, logs.list);

router.get("/regex", auth.Auth, regex.list);
router.get("/regex/detail/:id", auth.Auth, regex.detail);
router.all("/regex/add", auth.Auth, regex.add);
router.get("/regex/list", auth.Auth, regex.list);
router.get("/regex/list/:page", auth.Auth, regex.list);
router.post("/regex/update/", auth.Auth, regex.update);

router.get("/list", auth.Auth, list.list);
router.get("/list/list", auth.Auth, list.list);
router.get("/list/list/:page", auth.Auth, list.list);
router.get("/list/detail/:id", auth.Auth, list.detail);
router.post("/list/addlist", auth.Auth, list.addList);
router.get("/list/:listid/view/", auth.Auth, list.viewsDetail);
router.get("/list/:listid/view/:viewid", auth.Auth, list.viewsDetail);
router.post("/list/:listid/view/save", auth.Auth, list.viewSave);
router.post("/list/:listid/view/save/:viewid", auth.Auth, list.viewSave);

router.get("/config", auth.Auth, config.getApp);
router.get("/config/app", auth.Auth, config.getApp);
router.get("/config/db", auth.Auth, config.getDb);
router.get("/config/log", auth.Auth, config.getLog);

router.get("/server", auth.Auth, server.listStatus);
router.all("/server/startup", auth.Auth, server.startup);
router.get("/server/liststatus", auth.Auth, server.listStatus);
router.get("/server/stop", auth.Auth, server.stop);
router.get("/server/restart", auth.Auth, server.restart);

router.get("/test", auth.Auth, test.index);
router.post("/test", auth.Auth, test.exec);

module.exports = router;<commit_msg>fix bug of user change password not auth<commit_after>var express = require('express');
var router = express.Router();

var userControllers = require("../controllers/user.js");
var logs = require("./logs");
var regex = require("./regex");
var list = require("./list");
var config = require("./config");
var server = require("./server");
var test = require("./test");
var user = require("./user")
var auth = require("../auth");

router.get('/', auth.Auth, function(req, res) {
	var m_result = {
		titile: "index"
	}
	process.nextTick(function () {	//for more effective
		req.getUser(function (err, result) {
			if(err) {
				res.redirect("login");
			}else {
				m_result.user = {
					id: result.id,
					username: result.username
				}
				res.render("index", m_result);
			}
		});
	});
});

router.get('/login', function(req, res) {
	if(req.isAuth) {
		res.redirect('/');
	}else{
		res.render("login");
	}
});

router.post('/login', function(req, res) {
	req.login(req.body.username, req.body.password, function (err) {
		if (err){
			res.redirect('/login');
		}else {
			res.redirect('/')
		}
	})
});

router.get('/logout', function(req, res) {
	req.logout(function (err) {
		if(err){
			// Impossible
			res.writeHead(404);
			res.end();
		}else {
			res.redirect('/login');
		}
	});
});

router.post("/user/:id", auth.Auth, user.update);

router.get("/logs", auth.Auth, logs.list);
router.get("/logs/:page", auth.Auth, logs.list);

router.get("/regex", auth.Auth, regex.list);
router.get("/regex/detail/:id", auth.Auth, regex.detail);
router.all("/regex/add", auth.Auth, regex.add);
router.get("/regex/list", auth.Auth, regex.list);
router.get("/regex/list/:page", auth.Auth, regex.list);
router.post("/regex/update/", auth.Auth, regex.update);

router.get("/list", auth.Auth, list.list);
router.get("/list/list", auth.Auth, list.list);
router.get("/list/list/:page", auth.Auth, list.list);
router.get("/list/detail/:id", auth.Auth, list.detail);
router.post("/list/addlist", auth.Auth, list.addList);
router.get("/list/:listid/view/", auth.Auth, list.viewsDetail);
router.get("/list/:listid/view/:viewid", auth.Auth, list.viewsDetail);
router.post("/list/:listid/view/save", auth.Auth, list.viewSave);
router.post("/list/:listid/view/save/:viewid", auth.Auth, list.viewSave);

router.get("/config", auth.Auth, config.getApp);
router.get("/config/app", auth.Auth, config.getApp);
router.get("/config/db", auth.Auth, config.getDb);
router.get("/config/log", auth.Auth, config.getLog);

router.get("/server", auth.Auth, server.listStatus);
router.all("/server/startup", auth.Auth, server.startup);
router.get("/server/liststatus", auth.Auth, server.listStatus);
router.get("/server/stop", auth.Auth, server.stop);
router.get("/server/restart", auth.Auth, server.restart);

router.get("/test", auth.Auth, test.index);
router.post("/test", auth.Auth, test.exec);

module.exports = router;<|endoftext|>


<commit_before>export default {
  backend: 'http://sbirejto.cz',
  fbApp: '984162921603980'
}
<commit_msg>updated prod port for data backend<commit_after>export default {
  backend: 'http://sbirejto.cz:8020',
  fbApp: '984162921603980'
}
<|endoftext|>