<commit_before>'use strict';

const colorConvert = require('color-convert');

const colorOptimizer = require('../optimizations/color');
const Dimension = require('./Dimension');
const Expression = require('./Expression');
const objects = require('../objects');
const optimization = require('../optimization');
const utils = require('../utils');

/**
 * @constructor
 * @param {string} name
 * @param {Expressino} content
 */
function Func(name, content) {
    this.name = name;
    this.content = content;
}

/**
 * @return {string}
 */
Func.prototype.toString = function toString() {
    if (this.content) {
        return this.name + '(' + this.content.toString() + ')';
    } else {
        return this.name + '()';
    }
};

/**
 * @param {int} indent
 * @return {string}
 */
Func.prototype.pretty = function pretty(indent) {
    if (this.content) {
       return this.name + '(' + this.content.pretty(indent) + ')';
    } else {
	   return this.name + '()';
    }
};

/**
 * @param {object} kw
 * @return {Func}
 */
Func.prototype.optimize = function optimize(kw) {
    // OPT: Lowercase function names.
    this.name = this.name.toLowerCase();
    const oldkwf = kw.func;
    kw.func = this.name;
    if (this.content) {
        this.content = optimization.try_(this.content, kw);
    } else if (this.name.indexOf('linear-gradient') !== -1) {
        return null;
    }

    if (
        this.name === 'calc' &&
        !(
            this.content instanceof objects.MathSum ||
            this.content instanceof objects.MathProduct
        )
    ) {
        return this.content;
    }

    let self = this.optimizeColor(kw);
    if (!self || !(self instanceof Func)) {
        kw.func = oldkwf;
        return self;
    }

    self = self.optimizeLinearGradient(kw);
    if (!self || !self.content) {
        kw.func = oldkwf;
        return null;
    }

    self = self.optimizeRadialGradient(kw);
    if (!self || !self.content) {
        kw.func = oldkwf;
        return null;
    }

    if (this.name === 'calc') {
        self = self.optimizeCalc(kw);
    }

    kw.func = oldkwf;

    return self;
};

const recognizedColorFuncs = {
    'rgb': {minArgs: 3, maxArgs: 3},
    'hsl': {minArgs: 3, maxArgs: 3},
    'rgba': {minArgs: 4, maxArgs: 4},
    'hsla': {minArgs: 4, maxArgs: 4},
    'gray': {minArgs: 1, maxArgs: 2},
    'hwb': {minArgs: 3, maxArgs: 4},
    'lab': {minArgs: 3, maxArgs: 4},
    'lch': {minArgs: 3, maxArgs: 4},
};
const ALPHA_INDEX = {
    'gray': 1,
    'rgba': 3,
    'hsla': 3,
    'hwb': 3,
    'lab': 3,
    'lch': 3,
};

/**
 * @param {object} kw
 * @return {Func}
 */
Func.prototype.optimizeColor = function optimizeColor(kw) {
    if (!(this.name in recognizedColorFuncs)) {
        return this;
    }

    const spec = recognizedColorFuncs[this.name];
    if (this.content.chain.length < spec.minArgs || this.content.chain.length > spec.maxArgs) {
        return null;
    }

    if (
        !this.content ||
        !this.content.chain ||
        !this.content.chain.every(function(x, i) {
            if (ALPHA_INDEX[this.name] && i === ALPHA_INDEX[this.name]) {
                return utils.isNum(x[1]);
            }
            if (
                (
                    i === 0 && (this.name === 'hsl' || this.name === 'hsla' || this.name === 'hwb') ||
                    i === 2 && (this.name === 'lch')
                ) &&
                x[1] instanceof Dimension
            ) {
                return true;
            }
            if (
                i === 1 && this.name === 'hwb' ||
                i === 2 && this.name === 'hwb'
            ) {
                return x[1] instanceof Dimension;
            }
            return utils.isNum(x[1]);
        }, this)
    ) {
        return null;
    }

    // OPT: Convert color functions to shortest variants
    var chainLength = this.content.chain.length;
    switch(this.name) {
        case 'rgb':
        case 'hsl':
            if (chainLength !== 3) return this;
            break;
        case 'rgba':
        case 'hsla':
            if (chainLength !== 4) return this;
            break;
        case 'gray':
            if (chainLength < 1 || chainLength > 2) return this;
            break;
        case 'hwb':
        case 'lab':
        case 'lch':
            if (chainLength < 3 || chainLength > 4) return this;
            break;
        default:
            return this;
    }

    let applier;
    let alpha = 1;

    const components = this.content.chain.map(v => asRealNum(v[1])).map(v => Math.max(v, 0));

    switch (this.name) {
        case 'rgba':
        case 'hsla':
            alpha = components[3];
            applier = funcName => {
                const name = this.name.substr(0, 3);
                if (funcName === name) {
                    return components.slice(0, 3);
                }
                return colorConvert[name][funcName](components[0], components[1], components[2]);
            };
            break;
        case 'rgb':
        case 'hsl':
            applier = funcName => {
                if (funcName === this.name) {
                    return components.slice(0, 3);
                }
                return colorConvert[this.name][funcName](components[0], components[1], components[2]);
            };
            break;
        case 'gray':
            if (components.length > 1) {
                alpha = components[1];
            }
            applier = funcName => {
                return colorConvert.gray[funcName](components[0]);
            };
            break;
        case 'hwb':
        case 'lab':
        case 'lch':
            if (components.length > 3) {
                alpha = components[3];
            }
            applier = funcName => {
                if (funcName === this.name) {
                    return components.slice(0, 3);
                }
                return colorConvert[this.name][funcName](components[0], components[1], components[2]);
            };
            break;
        default:
            return this;
    }

    return colorOptimizer(applier, alpha, kw);
};

var GRADIENT_ANGLES = {
    top: () => new objects.Number(0),
    right: () => new Dimension(new objects.Number(90), 'deg'),
    bottom: () => new Dimension(new objects.Number(180), 'deg'),
    left: () => new Dimension(new objects.Number(270), 'deg'),
};

/**
 * @param {object} kw
 * @return {Func}
 */
Func.prototype.optimizeLinearGradient = function optimizeLinearGradient(kw) {
    if (
        !(
            this.name === 'linear-gradient' ||
            this.name === 'repeating-linear-gradient' ||
            this.name === '-webkit-linear-gradient' ||
            this.name === '-webkit-repeating-linear-gradient'
        ) ||
        !this.content ||
        !this.content.chain
    ) {
        return this;
    }

    let chain = this.content.chain;

    if (
        chain.length > 2 &&
        chain[2][0] !== null &&
        chain[0][1] === 'to' &&
        chain[1][1] in GRADIENT_ANGLES
    ) {
        const val = chain[1][1];
        chain = chain.slice(1);
        chain[0] = [null, GRADIENT_ANGLES[val]()];
    }

    const segments = chain.reduce((acc, cur) => {
        if (cur[0] !== null) {
            acc.push([]);
        }
        acc[acc.length - 1].push(cur);
        return acc;
    }, [[]]);
    let lastStop = null;
    segments.forEach((group, idx) => {
        if (group.length !== 2 || !(group[1][1] instanceof Dimension || group[1][1] instanceof objects.Number)) {
            return;
        }
        const isFinal = idx === segments.length - 1;
        if (!lastStop) {
            lastStop = group[1][1];
            if (isFinal) {
                return;
            }
            if (lastStop instanceof Dimension && (lastStop.asNumber() !== 0 || lastStop.unit !== '%')) {
                return;
            }
            if (lastStop instanceof objects.Number && lastStop.asNumber() !== 0) {
                return;
            }
            group[1][1] = null;
            return;
        }

        // TODO: This should consider the units and transform to px if possible
        if (lastStop.unit === group[1][1].unit && lastStop.asNumber() >= group[1][1].asNumber()) {
            group[1][1] = new objects.Number(0);
        }
        lastStop = group[1][1];
        if (isFinal && group[1][1].unit === '%' && group[1][1].asNumber() === 100) {
            group[1][1] = null;
        }
    });

    chain = chain.filter(x => x[1]);
    this.content = (new Expression(chain)).optimize(kw);
    return this;
};

/**
 * @param {object} kw
 * @return {Func}
 */
Func.prototype.optimizeRadialGradient = function optimizeRadialGradient(kw) {
    if (
        this.name !== 'radial-gradient' &&
        this.name !== 'repeating-radial-gradient' &&
        this.name !== '-webkit-radial-gradient' &&
        this.name !== '-webkit-repeating-radial-gradient' ||
        !this.content ||
        !this.content.chain ||
        !this.content.chain.length
    ) {
        return this;
    }

    var chain = this.content.chain;
    var segments = chain.reduce((acc, cur) => {
        if (cur[0] !== null) {
            acc.push([]);
        }
        acc[acc.length - 1].push(cur);
        return acc;
    }, [[]]);
    var lastStop = null;
    segments.forEach((group, idx) => {
        if (group.length !== 2 || !(group[1][1] instanceof Dimension || group[1][1] instanceof objects.Number)) {
            return;
        }
        var isFinal = idx === segments.length - 1;
        if (!lastStop) {
            lastStop = group[1][1];
            if (isFinal) {
                return;
            }
            if (lastStop instanceof Dimension && (lastStop.asNumber() !== 0 || lastStop.unit !== '%')) {
                return;
            }
            if (lastStop instanceof objects.Number && lastStop.asNumber() !== 0) {
                return;
            }
            group[1][1] = null;
            return;
        }

        // TODO: This should consider the units and transform to px if possible
        if (lastStop.unit === group[1][1].unit && lastStop.asNumber() >= group[1][1].asNumber()) {
            group[1][1] = new objects.Number(0);
        }
        lastStop = group[1][1];
        if (isFinal && group[1][1].unit === '%' && group[1][1].asNumber() === 100) {
            group[1][1] = null;
        }
    });

    this.content = (new Expression(chain)).optimize(kw);
    return this;
};

/**
 * @param {object} kw
 * @return {Func}
 */
Func.prototype.optimizeCalc = function optimizeCalc(kw) {
    this.content = this.content.optimize(kw);
    if (!this.content) {
        return null;
    }
    return this;
};

/**
 * Converts Number to JS number
 * @param  {Number} num
 * @return {number}
 */
function asRealNum(num) {
    if (num.unit && num.unit === '%') num = num.number;
    if (num.unit && num.unit === 'deg') return num.number.asNumber() % 360 / 360 * 255;
    if (num.unit && num.unit === 'grad') return num.number.asNumber() % 400 / 400 * 255;
    if (num.unit && num.unit === 'rad') return num.number.asNumber() % (2 * Math.PI) / (2 * Math.PI) * 255;
    if (num.unit && num.unit === 'turn') return num.number.asNumber() % 1 * 255;
    return num.asNumber();
}

module.exports = Func;
<commit_msg>Include prefixed calc() in optimizations<commit_after>'use strict';

const colorConvert = require('color-convert');

const colorOptimizer = require('../optimizations/color');
const Dimension = require('./Dimension');
const Expression = require('./Expression');
const objects = require('../objects');
const optimization = require('../optimization');
const utils = require('../utils');

/**
 * @constructor
 * @param {string} name
 * @param {Expressino} content
 */
function Func(name, content) {
    this.name = name;
    this.content = content;
}

/**
 * @return {string}
 */
Func.prototype.toString = function toString() {
    if (this.content) {
        return this.name + '(' + this.content.toString() + ')';
    } else {
        return this.name + '()';
    }
};

/**
 * @param {int} indent
 * @return {string}
 */
Func.prototype.pretty = function pretty(indent) {
    if (this.content) {
       return this.name + '(' + this.content.pretty(indent) + ')';
    } else {
	   return this.name + '()';
    }
};

/**
 * @param {object} kw
 * @return {Func}
 */
Func.prototype.optimize = function optimize(kw) {
    // OPT: Lowercase function names.
    this.name = this.name.toLowerCase();
    const oldkwf = kw.func;
    kw.func = this.name;
    if (this.content) {
        this.content = optimization.try_(this.content, kw);
    } else if (this.name.indexOf('linear-gradient') !== -1) {
        return null;
    }

    if (
        this.isCalc() &&
        !(
            this.content instanceof objects.MathSum ||
            this.content instanceof objects.MathProduct
        )
    ) {
        return this.content;
    }

    let self = this.optimizeColor(kw);
    if (!self || !(self instanceof Func)) {
        kw.func = oldkwf;
        return self;
    }

    self = self.optimizeLinearGradient(kw);
    if (!self || !self.content) {
        kw.func = oldkwf;
        return null;
    }

    self = self.optimizeRadialGradient(kw);
    if (!self || !self.content) {
        kw.func = oldkwf;
        return null;
    }

    if (this.isCalc()) {
        self = self.optimizeCalc(kw);
    }

    kw.func = oldkwf;

    return self;
};

/**
 * @return {bool} Whether the function is calc or not.
 */
Func.prototype.isCalc = function isCalc() {
    return Boolean(/^(\-[a-zA-Z]+\-)?calc$/i.exec(this.name));
};

const recognizedColorFuncs = {
    'rgb': {minArgs: 3, maxArgs: 3},
    'hsl': {minArgs: 3, maxArgs: 3},
    'rgba': {minArgs: 4, maxArgs: 4},
    'hsla': {minArgs: 4, maxArgs: 4},
    'gray': {minArgs: 1, maxArgs: 2},
    'hwb': {minArgs: 3, maxArgs: 4},
    'lab': {minArgs: 3, maxArgs: 4},
    'lch': {minArgs: 3, maxArgs: 4},
};
const ALPHA_INDEX = {
    'gray': 1,
    'rgba': 3,
    'hsla': 3,
    'hwb': 3,
    'lab': 3,
    'lch': 3,
};

/**
 * @param {object} kw
 * @return {Func}
 */
Func.prototype.optimizeColor = function optimizeColor(kw) {
    if (!(this.name in recognizedColorFuncs)) {
        return this;
    }

    const spec = recognizedColorFuncs[this.name];
    if (this.content.chain.length < spec.minArgs || this.content.chain.length > spec.maxArgs) {
        return null;
    }

    if (
        !this.content ||
        !this.content.chain ||
        !this.content.chain.every(function(x, i) {
            if (ALPHA_INDEX[this.name] && i === ALPHA_INDEX[this.name]) {
                return utils.isNum(x[1]);
            }
            if (
                (
                    i === 0 && (this.name === 'hsl' || this.name === 'hsla' || this.name === 'hwb') ||
                    i === 2 && (this.name === 'lch')
                ) &&
                x[1] instanceof Dimension
            ) {
                return true;
            }
            if (
                i === 1 && this.name === 'hwb' ||
                i === 2 && this.name === 'hwb'
            ) {
                return x[1] instanceof Dimension;
            }
            return utils.isNum(x[1]);
        }, this)
    ) {
        return null;
    }

    // OPT: Convert color functions to shortest variants
    var chainLength = this.content.chain.length;
    switch(this.name) {
        case 'rgb':
        case 'hsl':
            if (chainLength !== 3) return this;
            break;
        case 'rgba':
        case 'hsla':
            if (chainLength !== 4) return this;
            break;
        case 'gray':
            if (chainLength < 1 || chainLength > 2) return this;
            break;
        case 'hwb':
        case 'lab':
        case 'lch':
            if (chainLength < 3 || chainLength > 4) return this;
            break;
        default:
            return this;
    }

    let applier;
    let alpha = 1;

    const components = this.content.chain.map(v => asRealNum(v[1])).map(v => Math.max(v, 0));

    switch (this.name) {
        case 'rgba':
        case 'hsla':
            alpha = components[3];
            applier = funcName => {
                const name = this.name.substr(0, 3);
                if (funcName === name) {
                    return components.slice(0, 3);
                }
                return colorConvert[name][funcName](components[0], components[1], components[2]);
            };
            break;
        case 'rgb':
        case 'hsl':
            applier = funcName => {
                if (funcName === this.name) {
                    return components.slice(0, 3);
                }
                return colorConvert[this.name][funcName](components[0], components[1], components[2]);
            };
            break;
        case 'gray':
            if (components.length > 1) {
                alpha = components[1];
            }
            applier = funcName => {
                return colorConvert.gray[funcName](components[0]);
            };
            break;
        case 'hwb':
        case 'lab':
        case 'lch':
            if (components.length > 3) {
                alpha = components[3];
            }
            applier = funcName => {
                if (funcName === this.name) {
                    return components.slice(0, 3);
                }
                return colorConvert[this.name][funcName](components[0], components[1], components[2]);
            };
            break;
        default:
            return this;
    }

    return colorOptimizer(applier, alpha, kw);
};

var GRADIENT_ANGLES = {
    top: () => new objects.Number(0),
    right: () => new Dimension(new objects.Number(90), 'deg'),
    bottom: () => new Dimension(new objects.Number(180), 'deg'),
    left: () => new Dimension(new objects.Number(270), 'deg'),
};

/**
 * @param {object} kw
 * @return {Func}
 */
Func.prototype.optimizeLinearGradient = function optimizeLinearGradient(kw) {
    if (
        !(
            this.name === 'linear-gradient' ||
            this.name === 'repeating-linear-gradient' ||
            this.name === '-webkit-linear-gradient' ||
            this.name === '-webkit-repeating-linear-gradient'
        ) ||
        !this.content ||
        !this.content.chain
    ) {
        return this;
    }

    let chain = this.content.chain;

    if (
        chain.length > 2 &&
        chain[2][0] !== null &&
        chain[0][1] === 'to' &&
        chain[1][1] in GRADIENT_ANGLES
    ) {
        const val = chain[1][1];
        chain = chain.slice(1);
        chain[0] = [null, GRADIENT_ANGLES[val]()];
    }

    const segments = chain.reduce((acc, cur) => {
        if (cur[0] !== null) {
            acc.push([]);
        }
        acc[acc.length - 1].push(cur);
        return acc;
    }, [[]]);
    let lastStop = null;
    segments.forEach((group, idx) => {
        if (group.length !== 2 || !(group[1][1] instanceof Dimension || group[1][1] instanceof objects.Number)) {
            return;
        }
        const isFinal = idx === segments.length - 1;
        if (!lastStop) {
            lastStop = group[1][1];
            if (isFinal) {
                return;
            }
            if (lastStop instanceof Dimension && (lastStop.asNumber() !== 0 || lastStop.unit !== '%')) {
                return;
            }
            if (lastStop instanceof objects.Number && lastStop.asNumber() !== 0) {
                return;
            }
            group[1][1] = null;
            return;
        }

        // TODO: This should consider the units and transform to px if possible
        if (lastStop.unit === group[1][1].unit && lastStop.asNumber() >= group[1][1].asNumber()) {
            group[1][1] = new objects.Number(0);
        }
        lastStop = group[1][1];
        if (isFinal && group[1][1].unit === '%' && group[1][1].asNumber() === 100) {
            group[1][1] = null;
        }
    });

    chain = chain.filter(x => x[1]);
    this.content = (new Expression(chain)).optimize(kw);
    return this;
};

/**
 * @param {object} kw
 * @return {Func}
 */
Func.prototype.optimizeRadialGradient = function optimizeRadialGradient(kw) {
    if (
        this.name !== 'radial-gradient' &&
        this.name !== 'repeating-radial-gradient' &&
        this.name !== '-webkit-radial-gradient' &&
        this.name !== '-webkit-repeating-radial-gradient' ||
        !this.content ||
        !this.content.chain ||
        !this.content.chain.length
    ) {
        return this;
    }

    var chain = this.content.chain;
    var segments = chain.reduce((acc, cur) => {
        if (cur[0] !== null) {
            acc.push([]);
        }
        acc[acc.length - 1].push(cur);
        return acc;
    }, [[]]);
    var lastStop = null;
    segments.forEach((group, idx) => {
        if (group.length !== 2 || !(group[1][1] instanceof Dimension || group[1][1] instanceof objects.Number)) {
            return;
        }
        var isFinal = idx === segments.length - 1;
        if (!lastStop) {
            lastStop = group[1][1];
            if (isFinal) {
                return;
            }
            if (lastStop instanceof Dimension && (lastStop.asNumber() !== 0 || lastStop.unit !== '%')) {
                return;
            }
            if (lastStop instanceof objects.Number && lastStop.asNumber() !== 0) {
                return;
            }
            group[1][1] = null;
            return;
        }

        // TODO: This should consider the units and transform to px if possible
        if (lastStop.unit === group[1][1].unit && lastStop.asNumber() >= group[1][1].asNumber()) {
            group[1][1] = new objects.Number(0);
        }
        lastStop = group[1][1];
        if (isFinal && group[1][1].unit === '%' && group[1][1].asNumber() === 100) {
            group[1][1] = null;
        }
    });

    this.content = (new Expression(chain)).optimize(kw);
    return this;
};

/**
 * @param {object} kw
 * @return {Func}
 */
Func.prototype.optimizeCalc = function optimizeCalc(kw) {
    this.content = this.content.optimize(kw);
    if (!this.content) {
        return null;
    }
    return this;
};

/**
 * Converts Number to JS number
 * @param  {Number} num
 * @return {number}
 */
function asRealNum(num) {
    if (num.unit && num.unit === '%') num = num.number;
    if (num.unit && num.unit === 'deg') return num.number.asNumber() % 360 / 360 * 255;
    if (num.unit && num.unit === 'grad') return num.number.asNumber() % 400 / 400 * 255;
    if (num.unit && num.unit === 'rad') return num.number.asNumber() % (2 * Math.PI) / (2 * Math.PI) * 255;
    if (num.unit && num.unit === 'turn') return num.number.asNumber() % 1 * 255;
    return num.asNumber();
}

module.exports = Func;
<|endoftext|>


<commit_before>// XXX: To uniform the style of an object literals, we enable `quote-props`
/*eslint quote-props: [2, "always"] no-magic-numbers: 0 */

'use strict';

module.exports = {

    'plugins': [
        'node',
    ],

    // eslint-plugin-node
    // https://github.com/mysticatea/eslint-plugin-node
    'rules': {
        'node/no-missing-import': 0, // Node v5 don't supprt module syntax
        'node/no-missing-require': 2,
        'node/no-unpublished-import': 0, // Disable until this rule follow devDependencies
        'node/no-unpublished-require': 0, // Disable until this rule follow devDependencies
        'node/no-unsupported-features': 0, // Covered by core's `no-restricted-syntax`
        'node/shebang': 0, // we're not writing a stand alone script which requires shebang.
        'node/no-deprecated-api': 2, // we'd like to detect the case of using deprecated apis.
    }
};
<commit_msg>Enable node/no-missing-import by default<commit_after>// XXX: To uniform the style of an object literals, we enable `quote-props`
/*eslint quote-props: [2, "always"] no-magic-numbers: 0 */

'use strict';

module.exports = {

    'plugins': [
        'node',
    ],

    // eslint-plugin-node
    // https://github.com/mysticatea/eslint-plugin-node
    'rules': {
        'node/no-missing-import': 2,
        'node/no-missing-require': 2,
        'node/no-unpublished-import': 0, // Disable until this rule follow devDependencies
        'node/no-unpublished-require': 0, // Disable until this rule follow devDependencies
        'node/no-unsupported-features': 0, // Covered by core's `no-restricted-syntax`
        'node/shebang': 0, // we're not writing a stand alone script which requires shebang.
        'node/no-deprecated-api': 2, // we'd like to detect the case of using deprecated apis.
    }
};
<|endoftext|>


<commit_before>// <nowiki>
/* globals TranslateVariants:true */
(function() {

	if (mw.config.get('wgPageName').match(/^MediaWiki:[^/]+(\/zh)?$/)) {
		let link = mw.util.addPortletLink(
			'p-cactions',
			'#',
			'轉換變體'
		)
		$(link).on('click', function() {
			this.remove();
			main();
		});
	} else {
		return;
	}

	if (typeof (TranslateVariants) == 'undefined') {
		TranslateVariants = {};
	}
	if (typeof (TranslateVariants.summary) != 'string') {
		TranslateVariants.summary = '自動轉換變體自[[$1]] via [[User:Xiplus/js/TranslateVariants.js|TranslateVariants]]'
	}

	function main() {
		const langs = ['zh', 'zh-hans', 'zh-cn', 'zh-my', 'zh-sg', 'zh-hant', 'zh-hk', 'zh-mo', 'zh-tw'];
		const langname = {
			'zh': '原始',
			'zh-hans': '简体',
			'zh-cn': '大陆简体',
			'zh-my': '大马简体',
			'zh-sg': '新加坡简体',
			'zh-hant': '繁體',
			'zh-hk': '香港繁體',
			'zh-mo': '澳門繁體',
			'zh-tw': '臺灣正體'
		}
		let result = {};

		var api = new mw.Api();
		api.get({
			action: 'query',
			prop: 'revisions',
			rvprop: ['content', 'timestamp'],
			titles: [mw.config.get('wgPageName')],
			formatversion: '2',
			curtimestamp: true
		}).then(function(data) {
			var page, revision;
			if (!data.query || !data.query.pages) {
				return $.Deferred().reject('unknown');
			}
			page = data.query.pages[0];
			if (!page || page.invalid) {
				return $.Deferred().reject('invalidtitle');
			}
			if (page.missing) {
				return $.Deferred().reject('nocreate-missing');
			}
			revision = page.revisions[0];
			return {
				content: revision.content
			};
		}).then(function(data) {
			let text = data.content;
			result['zh'] = text;

			text = text.replace(/[[\]{}<>|:*'_#&\s]/gim, function(s) {
				return "&#" + s.charCodeAt(0) + ";";
			});
			text = text.replace(/([[)((?:(?!|)(?!]).)+?)(|(?:(?!]).)+?]])/g, '$1-{$2}-$3');
			text = text.replace(/-{(.+?)}-/g, function(s) {
				return s
					.replace('-{', '-{')
					.replace('}-', '}-')
					.replace(/:/g, ':')
			});
			let p = [];
			langs.forEach(lang => {
				p.push(
					api.parse(
						'{{NoteTA|G1=IT|G2=MediaWiki}}
' + text + '
',
						{
							'uselang': lang,
							'prop': 'text'
						}
					).then(function(data) {
						result[lang] = $('
').html(data).find('#TVcontent').text();
					}, function(err) {
						mw.notify('請求時發生錯誤：' + err);
					})
				);
			})
			return Promise.all(p);
		}).then(function() {
			let table = $('
').prependTo('#bodyContent');
			$('
提醒：TranslateVariants小工具仍在試驗階段，編輯完成後亦請複查真正做出的編輯是否正確！
').appendTo(table);
			const basename = mw.config.get('wgPageName').replace(/\/zh$/, '');
			let editlangs = [];
			langs.forEach(lang => {
				if (lang == 'zh') {
					editlangs.push(['', lang]);
				} else {
					editlangs.push(['/' + lang, lang]);
				}
			});
			let diffTables = {}
			editlangs.forEach(lang => {
				diffTables[lang[1]] = $('
').appendTo(table);
				$('
').appendTo(table);
			});
			editlangs.forEach(lang => {
				let newtext = result[lang[1]];
				let targetTitle = basename + lang[0];
				api.post({
					action: 'query',
					prop: 'revisions',
					titles: [targetTitle],
					rvdifftotext: newtext,
					formatversion: '2',
				}).then(function(data) {
					let diffTable = diffTables[lang[1]];
					let tool = $('
' + lang[1] + '（' + langname[lang[1]] + '）（編）
').appendTo(diffTable);
					let page = data.query.pages[0];
					if (page.missing) {
						let submit = $('<button style="float: right;">發佈頁面</button>').appendTo(tool);
						submit.on('click', function() {
							this.remove();
							api.create(
								targetTitle,
								{ summary: TranslateVariants.summary.replace(/\$1/g, mw.config.get('wgPageName')) },
								newtext
							).then(function() {
								mw.notify('已編輯 ' + targetTitle);
							}, function(e) {
								mw.notify('編輯 ' + targetTitle + ' 發生錯誤：' + e);
							});
						});
						$('
').html(newtext.replace(/[<>&]/gim, function(s) {
							return "&#" + s.charCodeAt(0) + ";";
						})).appendTo(diffTable);
						return;
					}
					let diff = page.revisions[0].diff.body;
					if (diff == '') {
						$('無變更').appendTo(tool);
					} else {
						let submit = $('<button style="float: right;">發佈變更</button>').appendTo(tool);
						submit.on('click', function() {
							this.remove();
							api.edit(
								targetTitle,
								function() {
									return {
										text: newtext,
										summary: TranslateVariants.summary.replace(/\$1/g, mw.config.get('wgPageName')),
										nocreate: false
									};
								}
							).then(function() {
								mw.notify('已編輯 ' + targetTitle);
							}, function(e) {
								mw.notify('編輯 ' + targetTitle + ' 發生錯誤：' + e);
							});
						});
						$('
').html(diff).prepend('<colgroup><col class="diff-marker"><col class="diff-content"><col class="diff-marker"><col class="diff-content"></colgroup>').appendTo(diffTable);
					}
				});
			});
		});
	}

})();
// </nowiki>
<commit_msg>TranslateVariants: Always use zhwp to parse<commit_after>// <nowiki>
/* globals TranslateVariants:true */
(function() {

	if (mw.config.get('wgPageName').match(/^MediaWiki:[^/]+(\/zh)?$/)) {
		mw.loader.using(['mediawiki.api', 'mediawiki.ForeignApi']).then(function() {
			let link = mw.util.addPortletLink(
				'p-cactions',
				'#',
				'轉換變體'
			)
			$(link).on('click', function() {
				this.remove();
				main();
			});
		});
	} else {
		return;
	}

	if (typeof (TranslateVariants) == 'undefined') {
		TranslateVariants = {};
	}
	if (typeof (TranslateVariants.summary) != 'string') {
		TranslateVariants.summary = '自動轉換變體自[[$1]] via [[User:Xiplus/js/TranslateVariants.js|TranslateVariants]]'
	}

	function main() {
		const langs = ['zh', 'zh-hans', 'zh-cn', 'zh-my', 'zh-sg', 'zh-hant', 'zh-hk', 'zh-mo', 'zh-tw'];
		const langname = {
			'zh': '原始',
			'zh-hans': '简体',
			'zh-cn': '大陆简体',
			'zh-my': '大马简体',
			'zh-sg': '新加坡简体',
			'zh-hant': '繁體',
			'zh-hk': '香港繁體',
			'zh-mo': '澳門繁體',
			'zh-tw': '臺灣正體'
		}
		let result = {};

		var api = new mw.Api();
		var zhwpapi;
		if (mw.config.get('wgDBname') === 'zhwiki') {
			var zhwpapi = new mw.Api();
		} else {
			var zhwpapi = new mw.ForeignApi('//zh.wikipedia.org/w/api.php');
		}
		api.get({
			action: 'query',
			prop: 'revisions',
			rvprop: ['content', 'timestamp'],
			titles: [mw.config.get('wgPageName')],
			formatversion: '2',
			curtimestamp: true
		}).then(function(data) {
			var page, revision;
			if (!data.query || !data.query.pages) {
				return $.Deferred().reject('unknown');
			}
			page = data.query.pages[0];
			if (!page || page.invalid) {
				return $.Deferred().reject('invalidtitle');
			}
			if (page.missing) {
				return $.Deferred().reject('nocreate-missing');
			}
			revision = page.revisions[0];
			return {
				content: revision.content
			};
		}).then(function(data) {
			let text = data.content;
			result['zh'] = text;

			text = text.replace(/[[\]{}<>|:*'_#&\s]/gim, function(s) {
				return "&#" + s.charCodeAt(0) + ";";
			});
			text = text.replace(/([[)((?:(?!|)(?!]).)+?)(|(?:(?!]).)+?]])/g, '$1-{$2}-$3');
			text = text.replace(/-{(.+?)}-/g, function(s) {
				return s
					.replace('-{', '-{')
					.replace('}-', '}-')
					.replace(/:/g, ':')
			});
			let p = [];
			langs.forEach(lang => {
				p.push(
					zhwpapi.parse(
						'{{NoteTA|G1=IT|G2=MediaWiki}}
' + text + '
',
						{
							'uselang': lang,
							'prop': 'text'
						}
					).then(function(data) {
						result[lang] = $('
').html(data).find('#TVcontent').text();
					}, function(err) {
						mw.notify('請求時發生錯誤：' + err);
					})
				);
			})
			return Promise.all(p);
		}).then(function() {
			let table = $('
').prependTo('#bodyContent');
			$('
提醒：TranslateVariants小工具仍在試驗階段，編輯完成後亦請複查真正做出的編輯是否正確！
').appendTo(table);
			const basename = mw.config.get('wgPageName').replace(/\/zh$/, '');
			let editlangs = [];
			langs.forEach(lang => {
				if (lang == 'zh') {
					editlangs.push(['', lang]);
				} else {
					editlangs.push(['/' + lang, lang]);
				}
			});
			let diffTables = {}
			editlangs.forEach(lang => {
				diffTables[lang[1]] = $('
').appendTo(table);
				$('
').appendTo(table);
			});
			editlangs.forEach(lang => {
				let newtext = result[lang[1]];
				let targetTitle = basename + lang[0];
				api.post({
					action: 'query',
					prop: 'revisions',
					titles: [targetTitle],
					rvdifftotext: newtext,
					formatversion: '2',
				}).then(function(data) {
					let diffTable = diffTables[lang[1]];
					let tool = $('
' + lang[1] + '（' + langname[lang[1]] + '）（編）
').appendTo(diffTable);
					let page = data.query.pages[0];
					if (page.missing) {
						let submit = $('<button style="float: right;">發佈頁面</button>').appendTo(tool);
						submit.on('click', function() {
							this.remove();
							api.create(
								targetTitle,
								{ summary: TranslateVariants.summary.replace(/\$1/g, mw.config.get('wgPageName')) },
								newtext
							).then(function() {
								mw.notify('已編輯 ' + targetTitle);
							}, function(e) {
								mw.notify('編輯 ' + targetTitle + ' 發生錯誤：' + e);
							});
						});
						$('
').html(newtext.replace(/[<>&]/gim, function(s) {
							return "&#" + s.charCodeAt(0) + ";";
						})).appendTo(diffTable);
						return;
					}
					let diff = page.revisions[0].diff.body;
					if (diff == '') {
						$('無變更').appendTo(tool);
					} else {
						let submit = $('<button style="float: right;">發佈變更</button>').appendTo(tool);
						submit.on('click', function() {
							this.remove();
							api.edit(
								targetTitle,
								function() {
									return {
										text: newtext,
										summary: TranslateVariants.summary.replace(/\$1/g, mw.config.get('wgPageName')),
										nocreate: false
									};
								}
							).then(function() {
								mw.notify('已編輯 ' + targetTitle);
							}, function(e) {
								mw.notify('編輯 ' + targetTitle + ' 發生錯誤：' + e);
							});
						});
						$('
').html(diff).prepend('<colgroup><col class="diff-marker"><col class="diff-content"><col class="diff-marker"><col class="diff-content"></colgroup>').appendTo(diffTable);
					}
				});
			});
		});
	}

})();
// </nowiki>
<|endoftext|>


<commit_before>var BackupRestorePage = {
    oninit: function(vnode) {
        BackupRestore.loadBackupTokenStatus();

        BackupRestorePage.showspinner = false;
    },

    view: function() {

        var makeFileDownloader = function(downloadFunc, outfilename, mimetype) {
            return function() {
                BackupRestorePage.showspinner = true;

                downloadFunc()
                    .catch(function(e) {
                        BackupRestorePage.showspinner = false;
                        throw e;
                    })
                    .then(function(result) {
                        var blob = new Blob([result], {type: mimetype});
                        if(window.navigator.msSaveOrOpenBlob) {
                            window.navigator.msSaveOrOpenBlob(blob, outfilename);
                        } else {
                            var a = document.createElement("a");
                            a.style = "display: none";
                            document.body.appendChild(a);
                            var url = window.URL.createObjectURL(blob);
                            a.href = url;
                            a.download = outfilename;
                            a.click();
                            window.URL.revokeObjectURL(url);
                            a.remove();
                        }

                        BackupRestorePage.showspinner = false;
                    });

                return false;
            }
        };

        var makeFileUploader = function(uploaderFunc, successMsg) {
            return function() {
                var input = document.createElement("input");
                input.type = "file";
                input.style = "display: none";
                input.onchange = function(inputEvent) {
                    var reader = new FileReader();
                    reader.onload = function (readerEvent) {
                        BackupRestorePage.showspinner = true;
                        m.redraw();
                        uploaderFunc(readerEvent.target.result)
                            .catch(function(e) {
                                BackupRestorePage.showspinner = false;
                                throw e;
                            })
                            .then(function() {
                                BackupRestorePage.showspinner = false;
                                alert(successMsg);
                            });
                    }

                    reader.readAsArrayBuffer(inputEvent.target.files[0]);
                };

                document.body.appendChild(input);
                input.click();
                input.remove();

                return false;
            }
        };

        var makeBackupTokenButtonForm = function(saveFunc, disableFunc, isTokenEnabled, tokenPostedObj, tokenPostedObjSetter, exampleTarFileName) {
            return m("form.pure-form.pure-form-aligned",
                m("fieldset", [
                    m(".pure-controls", [
                        m("button.pure-button pure-button-primary", {
                            onclick: function(e) {
                                e.preventDefault();

                                if (isTokenEnabled && !confirm("Generating a new token will invalidate your old external backup token. Are you sure?")) {
                                    return;
                                }

                                saveFunc().then(function(result) {
                                    tokenPostedObjSetter(result);
                                    BackupRestore.loadBackupTokenStatus();
                                });
                            }
                        }, !isTokenEnabled ? "Enable external tar backup" : "Generate new token for external tar backup")
                    ])
                ]),
                isTokenEnabled ? m("fieldset", [
                    m(".pure-controls", [
                        m("button[type=submit].pure-button pure-button-primary", {
                            onclick: function(e) {
                                e.preventDefault();

                                if (!confirm("This will disable external tar backup. Are you sure?")) {
                                    return;
                                }

                                disableFunc().then(function(result) {
                                    BackupRestore.loadBackupTokenStatus();
                                });
                            }
                        },
                        "Disable external tar backup")
                    ])
                ]) : null,
                (isTokenEnabled && tokenPostedObj.token) ? [
                    m("p", "Backup tar URL:"),
                    m("pre.code", tokenPostedObj.url),
                    m("p", "Bearer token:"),
                    m("pre.code", tokenPostedObj.token),
                    m("p", "Wget example line:"),
                    m("pre.code", "wget " + tokenPostedObj.url + " \\\n-O " + exampleTarFileName + " \\\n--header \"Authorization: Bearer " + tokenPostedObj.token + "\"")
                ] : null
            );
        }

        return [
            BackupRestorePage.showspinner ? m(".spinneroverlay", m(".spinner")) : null,

            m("h2.content-subhead", "Backup and restore"),

            m("h3.content-subhead", "Plain text CSV file"),

            m("p", m("a[href=]", {
                onclick: makeFileDownloader(BackupRestore.getCsv, "secrets.csv", "text/csv")
            }, "Export all secrets in plain text CSV")),

            m("p", [
                m("a[href=]", {
                    onclick: makeFileUploader(BackupRestore.putCsv, "Successfully imported CSV.")
                }, "Import and merge from plain text CSV"),
                m("br"),
                "Export first to learn the format. Import merges entries where the pwboxId column matches an existing entry. Creates new entries for all other rows.",
            ]),

            m("h3.content-subhead", "Encrypted tar file of secrets"),

            m("p", m("a[href=]", {
                onclick: makeFileDownloader(BackupRestore.getTarSecrets, "secrets.tar", "application/tar")
            }, "Export all secrets encrypted in a tar")),

            m("p", [
                m("a[href=]", {
                    onclick: makeFileUploader(BackupRestore.putTarSecrets, "Successfully imported and replaced secrets from tar of encrypted secrets.")
                }, "Import and replace secrets from tar of encrypted secrets")
            ]),

            m("h3.content-subhead", "Encrypted tar file of users, keys, and groups"),

            m("p", m("a[href=]", {
                onclick: makeFileDownloader(BackupRestore.getTarUsers, "users.tar", "application/tar")
            }, "Export all users and their encryption keys and groups to a tar")),

            m("p", [
                m("a[href=]", {
                    onclick: makeFileUploader(BackupRestore.putTarUsers, "Successfully imported users and their encryption keys and groups from given tar.")
                }, "Import users and their encryption keys and groups from a tar")
            ]),

            m("h3.content-subhead", "External backup of secrets"),

            makeBackupTokenButtonForm(
                BackupRestore.secretsBackupTokenSave,
                BackupRestore.secretsBackupTokenDisable,
                BackupRestore.backupTokenStatus.secretBackupTokenEnabled,
                BackupRestore.secretsBackupToken,
                function(value) { BackupRestore.secretsBackupToken = value; },
                "secrets.tar"
            ),

            m("h3.content-subhead", "External backup of users, keys, and groups"),

            makeBackupTokenButtonForm(
                BackupRestore.usersBackupTokenSave,
                BackupRestore.usersBackupTokenDisable,
                BackupRestore.backupTokenStatus.usersBackupTokenEnabled,
                BackupRestore.usersBackupToken,
                function(value) { BackupRestore.usersBackupToken = value; },
                "users.tar"
            ),
        ];
    }
}
<commit_msg>Improved strings on backup/store page<commit_after>var BackupRestorePage = {
    oninit: function(vnode) {
        BackupRestore.loadBackupTokenStatus();

        BackupRestorePage.showspinner = false;
    },

    view: function() {

        var makeFileDownloader = function(downloadFunc, outfilename, mimetype) {
            return function() {
                BackupRestorePage.showspinner = true;

                downloadFunc()
                    .catch(function(e) {
                        BackupRestorePage.showspinner = false;
                        throw e;
                    })
                    .then(function(result) {
                        var blob = new Blob([result], {type: mimetype});
                        if(window.navigator.msSaveOrOpenBlob) {
                            window.navigator.msSaveOrOpenBlob(blob, outfilename);
                        } else {
                            var a = document.createElement("a");
                            a.style = "display: none";
                            document.body.appendChild(a);
                            var url = window.URL.createObjectURL(blob);
                            a.href = url;
                            a.download = outfilename;
                            a.click();
                            window.URL.revokeObjectURL(url);
                            a.remove();
                        }

                        BackupRestorePage.showspinner = false;
                    });

                return false;
            }
        };

        var makeFileUploader = function(uploaderFunc, successMsg) {
            return function() {
                var input = document.createElement("input");
                input.type = "file";
                input.style = "display: none";
                input.onchange = function(inputEvent) {
                    var reader = new FileReader();
                    reader.onload = function (readerEvent) {
                        BackupRestorePage.showspinner = true;
                        m.redraw();
                        uploaderFunc(readerEvent.target.result)
                            .catch(function(e) {
                                BackupRestorePage.showspinner = false;
                                throw e;
                            })
                            .then(function() {
                                BackupRestorePage.showspinner = false;
                                alert(successMsg);
                            });
                    }

                    reader.readAsArrayBuffer(inputEvent.target.files[0]);
                };

                document.body.appendChild(input);
                input.click();
                input.remove();

                return false;
            }
        };

        var makeBackupTokenButtonForm = function(saveFunc, disableFunc, isTokenEnabled, tokenPostedObj, tokenPostedObjSetter, exampleTarFileName) {
            return m("form.pure-form.pure-form-aligned",
                m("fieldset", [
                    m(".pure-controls", [
                        m("button.pure-button pure-button-primary", {
                            onclick: function(e) {
                                e.preventDefault();

                                if (isTokenEnabled && !confirm("Generating a new token will invalidate your old external backup token. Are you sure?")) {
                                    return;
                                }

                                saveFunc().then(function(result) {
                                    tokenPostedObjSetter(result);
                                    BackupRestore.loadBackupTokenStatus();
                                });
                            }
                        }, !isTokenEnabled ? "Enable external tar backup" : "Generate new token for external tar backup")
                    ])
                ]),
                isTokenEnabled ? m("fieldset", [
                    m(".pure-controls", [
                        m("button[type=submit].pure-button pure-button-primary", {
                            onclick: function(e) {
                                e.preventDefault();

                                if (!confirm("This will disable external tar backup. Are you sure?")) {
                                    return;
                                }

                                disableFunc().then(function(result) {
                                    BackupRestore.loadBackupTokenStatus();
                                });
                            }
                        },
                        "Disable external tar backup")
                    ])
                ]) : null,
                (isTokenEnabled && tokenPostedObj.token) ? [
                    m("p", "Backup tar URL:"),
                    m("pre.code", tokenPostedObj.url),
                    m("p", "Bearer token:"),
                    m("pre.code", tokenPostedObj.token),
                    m("p", "Wget example line:"),
                    m("pre.code", "wget " + tokenPostedObj.url + " \\\n-O " + exampleTarFileName + " \\\n--header \"Authorization: Bearer " + tokenPostedObj.token + "\"")
                ] : null
            );
        }

        return [
            BackupRestorePage.showspinner ? m(".spinneroverlay", m(".spinner")) : null,

            m("h2.content-subhead", "Backup and restore"),

            m("h3.content-subhead", "Plain text CSV file"),

            m("p", m("a[href=]", {
                onclick: makeFileDownloader(BackupRestore.getCsv, "secrets.csv", "text/csv")
            }, "Export all secrets in plain text CSV")),

            m("p", [
                m("a[href=]", {
                    onclick: makeFileUploader(BackupRestore.putCsv, "Successfully imported CSV.")
                }, "Import and merge from plain text CSV"),
                m("br"),
                "Export first to learn the format. Import merges entries where the pwboxId column matches an existing entry. Creates new entries for all other rows.",
            ]),

            m("h3.content-subhead", "Tar file with encrypted secrets"),

            m("p", m("a[href=]", {
                onclick: makeFileDownloader(BackupRestore.getTarSecrets, "secrets.tar", "application/tar")
            }, "Export all encrypted secrets in a tar file")),

            m("p", [
                m("a[href=]", {
                    onclick: makeFileUploader(BackupRestore.putTarSecrets, "Successfully imported and replaced secrets from tar of encrypted secrets.")
                }, "Import and replace secrets from tar of encrypted secrets")
            ]),

            m("h3.content-subhead", "Tar file of users, keys, and groups"),

            m("p", m("a[href=]", {
                onclick: makeFileDownloader(BackupRestore.getTarUsers, "users.tar", "application/tar")
            }, "Export all users and their encryption keys and groups to a tar")),

            m("p", [
                m("a[href=]", {
                    onclick: makeFileUploader(BackupRestore.putTarUsers, "Successfully imported users and their encryption keys and groups from given tar.")
                }, "Import users and their encryption keys and groups from a tar")
            ]),

            m("h3.content-subhead", "External backup of secrets"),

            makeBackupTokenButtonForm(
                BackupRestore.secretsBackupTokenSave,
                BackupRestore.secretsBackupTokenDisable,
                BackupRestore.backupTokenStatus.secretBackupTokenEnabled,
                BackupRestore.secretsBackupToken,
                function(value) { BackupRestore.secretsBackupToken = value; },
                "secrets.tar"
            ),

            m("h3.content-subhead", "External backup of users, keys, and groups"),

            makeBackupTokenButtonForm(
                BackupRestore.usersBackupTokenSave,
                BackupRestore.usersBackupTokenDisable,
                BackupRestore.backupTokenStatus.usersBackupTokenEnabled,
                BackupRestore.usersBackupToken,
                function(value) { BackupRestore.usersBackupToken = value; },
                "users.tar"
            ),
        ];
    }
}
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.Component.extend({
  didInsertElement() {
    var nav = Ember.$('body');
    let scrolled = false;

    Ember.$(window).scroll(function () {
      if (200 < Ember.$(window).scrollTop() && !scrolled) {
        nav.addClass('fixed');
        Ember.$('.banner__header').animate({top: 0}, 0);
        scrolled = true;
      }

      if (200 > Ember.$(window).scrollTop() && scrolled) {
        nav.removeClass('fixed');
        Ember.$('.banner__header').removeAttr('style');
        scrolled = false;
      }
    });
  }
});
<commit_msg>change var to let<commit_after>import Ember from 'ember';

export default Ember.Component.extend({
  didInsertElement() {
    let nav = Ember.$('body');
    let scrolled = false;

    Ember.$(window).scroll(function () {
      if (200 < Ember.$(window).scrollTop() && !scrolled) {
        nav.addClass('fixed');
        Ember.$('.banner__header').animate({top: 0}, 0);
        scrolled = true;
      }

      if (200 > Ember.$(window).scrollTop() && scrolled) {
        nav.removeClass('fixed');
        Ember.$('.banner__header').removeAttr('style');
        scrolled = false;
      }
    });
  }
});
<|endoftext|>


<commit_before>describe("depends-pattern", function() {
    var pattern;

    requireDependencies(["patterns/depends"], function(cls) {
        pattern = cls;
    });

    // Reset the lab before each test
    beforeEach(function() {
        $("#lab *").remove();
    });

    describe("init", function() {
        it("Hide if condition is not met initially", function() {
            $("#lab").html([
                '<input type="checkbox" id="control" value="yes"/>',
                '
'
                ].join("\n"));
            var $slave = $("#slave");
            pattern.init($slave, {condition: "control"});
            expect($slave.css("display")).toBe("none");
        });

        it("Show if condition is not met initially", function() {
            $("#lab").html([
                '<input type="checkbox" id="control" value="yes" checked="checked"/>',
                '
'
                ].join("\n"));
            var $slave = $("#slave");
            pattern.init($slave, {condition: "control"});
            expect($slave.css("display")).not.toBe("none");
        });
    });

    describe("_disable", function() {
        it("Input element", function() {
            $("#lab").append('<button type="button">Click me</button>');
            var $slave = $("#lab button");
            pattern._disable($slave);
            expect($slave[0].disabled).toBeTruthy();
            expect($slave.hasClass("disabled")).toBe(true);
        });

        it("Anchor", function() {
            $("#lab").append('Click me</button>');
            var $slave = $("#lab a");
            pattern._disable($slave);
            var events = $._data($slave[0]).events;
            expect($slave.hasClass("disabled")).toBe(true);
            expect(events.click).toBeDefined();
            expect(events.click[0].namespace).toBe("patternDepends");
        });
    });

    describe("_enable", function() {
        it("Input element", function() {
            $("#lab").append('<button disabled="disabled" class="disabled" type="button">Click me</button>');
            var $slave = $("#lab button");
            pattern._enable($slave);
            expect($slave[0].disabled).toBeFalsy();
            expect($slave.hasClass("disabled")).toBe(false);
        });

        it("Anchor", function() {
            $("#lab").append('Click me</button>');
            var $slave = $("#lab a");
            $slave.on("click.patternDepends", false);
            pattern._enable($slave);
            expect($slave.hasClass("disabled")).toBe(false);
            expect($._data($slave[0]).events).toBe(undefined);
        });
    });
});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<commit_msg>Fix markup error in depends test<commit_after>describe("depends-pattern", function() {
    var pattern;

    requireDependencies(["patterns/depends"], function(cls) {
        pattern = cls;
    });

    // Reset the lab before each test
    beforeEach(function() {
        $("#lab *").remove();
    });

    describe("init", function() {
        it("Hide if condition is not met initially", function() {
            $("#lab").html([
                '<input type="checkbox" id="control" value="yes"/>',
                '
'
                ].join("\n"));
            var $slave = $("#slave");
            pattern.init($slave, {condition: "control"});
            expect($slave.css("display")).toBe("none");
        });

        it("Show if condition is not met initially", function() {
            $("#lab").html([
                '<input type="checkbox" id="control" value="yes" checked="checked"/>',
                '
'
                ].join("\n"));
            var $slave = $("#slave");
            pattern.init($slave, {condition: "control"});
            expect($slave.css("display")).not.toBe("none");
        });
    });

    describe("_disable", function() {
        it("Input element", function() {
            $("#lab").append('<button type="button">Click me</button>');
            var $slave = $("#lab button");
            pattern._disable($slave);
            expect($slave[0].disabled).toBeTruthy();
            expect($slave.hasClass("disabled")).toBe(true);
        });

        it("Anchor", function() {
            $("#lab").append('Click me');
            var $slave = $("#lab a");
            pattern._disable($slave);
            var events = $._data($slave[0]).events;
            expect($slave.hasClass("disabled")).toBe(true);
            expect(events.click).toBeDefined();
            expect(events.click[0].namespace).toBe("patternDepends");
        });
    });

    describe("_enable", function() {
        it("Input element", function() {
            $("#lab").append('<button disabled="disabled" class="disabled" type="button">Click me</button>');
            var $slave = $("#lab button");
            pattern._enable($slave);
            expect($slave[0].disabled).toBeFalsy();
            expect($slave.hasClass("disabled")).toBe(false);
        });

        it("Anchor", function() {
            $("#lab").append('Click me');
            var $slave = $("#lab a");
            $slave.on("click.patternDepends", false);
            pattern._enable($slave);
            expect($slave.hasClass("disabled")).toBe(false);
            expect($._data($slave[0]).events).toBe(undefined);
        });
    });
});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<|endoftext|>


<commit_before>import config from "./color-config";
import mix from "./utils/mix";
import generatePalette from "./palette";

const assertCorrectColorMix = (config, paletteObject) => {
  Object.keys(config).forEach((col) => {
    const match = /([a-z]+)([\d]{0,2})/i.exec(col);

    const func = match[1],
      weight = Number(match[2]);

    expect(paletteObject[func](weight)).toEqual("#" + config[col]);
  });
};

describe("style", () => {
  let colorConfig = {
    brilliantGreenShade20: "00B000",
    brilliantGreenTint50: "80EE80",
    goldTint50: "FFDA80",
    errorRedShade20: "9F2D3F",
    genericGreenTint50: "80CC80",
    genericGreenTint30: "4DB84D",
    genericGreenShade15: "008200",
    genericGreenShade35: "006300",
    genericGreenShade55: "004500",
    productGreenTint50: "80D1BB",
    productGreenTint30: "4DBF9F",
    productGreenShade21: "00815D",
    productGreenShade41: "006046",
    productGreenShade61: "00402E",
    productBlueTint50: "80BBE4",
    productBlueTint30: "4DA0D9",
    productBlueShade3: "0073C2",
    productBlueShade23: "005C9A",
    productBlueShade43: "004472",
    amethystTint50: "AC96C1",
    amethystTint30: "8A6BA8",
    amethystTint10: "69418F",
    amethystShade10: "4F2876",
    amethystShade30: "3E1F5C",
    slateTint95: "F2F5F6",
    slateTint90: "E6EBED",
    slateTint80: "CCD6DB",
    slateTint60: "99ADB6",
    slateTint40: "668592",
    slateTint20: "335C6D",
    slateShade60: "00141D",
  };

  describe("palette", () => {
    let palette;

    beforeEach(() => {
      palette = generatePalette(config);
    });

    it("produces the correct color mix", () => {
      assertCorrectColorMix(colorConfig, palette);
    });
  });

  describe("mix", () => {
    it("defaults to a weight of 50", () => {
      expect(mix(config.genericGreen, "FFFFFF")).toEqual(
        "#" + colorConfig.genericGreenTint50
      );
    });

    it("accepts colors without a hash symbol", () => {
      expect(mix(config.genericGreen, "FFFFFF")).toEqual(
        "#" + colorConfig.genericGreenTint50
      );
    });

    it("accepts colors with a hash symbol", () => {
      expect(mix("#" + config.genericGreen, "#FFFFFF")).toEqual(
        "#" + colorConfig.genericGreenTint50
      );
    });

    it("accepts three-digit hashes", () => {
      expect(mix(config.genericGreen, "FFF")).toEqual(
        "#" + colorConfig.genericGreenTint50
      );
      expect(mix("FFF", config.genericGreen)).toEqual(
        "#" + colorConfig.genericGreenTint50
      );
    });

    it("accepts colors with combinations of with and without hash symbols", () => {
      expect(mix("#" + config.genericGreen, "FFFFFF")).toEqual(
        "#" + colorConfig.genericGreenTint50
      );
      expect(mix(config.genericGreen, "#FFFFFF")).toEqual(
        "#" + colorConfig.genericGreenTint50
      );
    });
  });
});
<commit_msg>refactor(style): replace regexp exec with match<commit_after>import config from "./color-config";
import mix from "./utils/mix";
import generatePalette from "./palette";

const assertCorrectColorMix = (config, paletteObject) => {
  Object.keys(config).forEach((col) => {
    const match = col.match(/([a-z]+)([\d]{0,2})/i);

    const func = match[1],
      weight = Number(match[2]);

    expect(paletteObject[func](weight)).toEqual("#" + config[col]);
  });
};

describe("style", () => {
  let colorConfig = {
    brilliantGreenShade20: "00B000",
    brilliantGreenTint50: "80EE80",
    goldTint50: "FFDA80",
    errorRedShade20: "9F2D3F",
    genericGreenTint50: "80CC80",
    genericGreenTint30: "4DB84D",
    genericGreenShade15: "008200",
    genericGreenShade35: "006300",
    genericGreenShade55: "004500",
    productGreenTint50: "80D1BB",
    productGreenTint30: "4DBF9F",
    productGreenShade21: "00815D",
    productGreenShade41: "006046",
    productGreenShade61: "00402E",
    productBlueTint50: "80BBE4",
    productBlueTint30: "4DA0D9",
    productBlueShade3: "0073C2",
    productBlueShade23: "005C9A",
    productBlueShade43: "004472",
    amethystTint50: "AC96C1",
    amethystTint30: "8A6BA8",
    amethystTint10: "69418F",
    amethystShade10: "4F2876",
    amethystShade30: "3E1F5C",
    slateTint95: "F2F5F6",
    slateTint90: "E6EBED",
    slateTint80: "CCD6DB",
    slateTint60: "99ADB6",
    slateTint40: "668592",
    slateTint20: "335C6D",
    slateShade60: "00141D",
  };

  describe("palette", () => {
    let palette;

    beforeEach(() => {
      palette = generatePalette(config);
    });

    it("produces the correct color mix", () => {
      assertCorrectColorMix(colorConfig, palette);
    });
  });

  describe("mix", () => {
    it("defaults to a weight of 50", () => {
      expect(mix(config.genericGreen, "FFFFFF")).toEqual(
        "#" + colorConfig.genericGreenTint50
      );
    });

    it("accepts colors without a hash symbol", () => {
      expect(mix(config.genericGreen, "FFFFFF")).toEqual(
        "#" + colorConfig.genericGreenTint50
      );
    });

    it("accepts colors with a hash symbol", () => {
      expect(mix("#" + config.genericGreen, "#FFFFFF")).toEqual(
        "#" + colorConfig.genericGreenTint50
      );
    });

    it("accepts three-digit hashes", () => {
      expect(mix(config.genericGreen, "FFF")).toEqual(
        "#" + colorConfig.genericGreenTint50
      );
      expect(mix("FFF", config.genericGreen)).toEqual(
        "#" + colorConfig.genericGreenTint50
      );
    });

    it("accepts colors with combinations of with and without hash symbols", () => {
      expect(mix("#" + config.genericGreen, "FFFFFF")).toEqual(
        "#" + colorConfig.genericGreenTint50
      );
      expect(mix(config.genericGreen, "#FFFFFF")).toEqual(
        "#" + colorConfig.genericGreenTint50
      );
    });
  });
});
<|endoftext|>


<commit_before>const {app, BrowserWindow} = require('electron')
const path = require('path')
const url = require('url')

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win

function createWindow () {
  // Create the browser window.
  win = new BrowserWindow({width: 800, height: 600})

  // and load the index.html of the app.
  win.loadURL(url.format({
    pathname: path.join(__dirname, 'html/login.html'),
    protocol: 'file:',
    slashes: true
  }))

  // Open the DevTools.
  win.webContents.openDevTools()

  // Emitted when the window is closed.
  win.on('closed', () => {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    win = null
  })
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (win === null) {
    createWindow()
  }
})
<commit_msg>Removed binaries, too big for git, finding hosting instead<commit_after>const {app, BrowserWindow} = require('electron')
const path = require('path')
const url = require('url')

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win

function createWindow () {
  // Create the browser window.
  win = new BrowserWindow({width: 800, height: 600})

  // and load the index.html of the app.
  win.loadURL(url.format({
    pathname: path.join(__dirname, 'html/login.html'),
    protocol: 'file:',
    slashes: true
  }))

  // Open the DevTools.
  //win.webContents.openDevTools()

  // Emitted when the window is closed.
  win.on('closed', () => {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    win = null
  })
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (win === null) {
    createWindow()
  }
})
<|endoftext|>


<commit_before>/*
 * This file exports the configuration Express.js back to the application
 * so that it can be used in other parts of the product.
 */

var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

exports.setup = function(app, express) {
	app.use(logger('dev'));
	app.use(bodyParser.json());
	app.use(bodyParser.urlencoded({ extended: false }));
	app.use(cookieParser());
	app.use(express.static(path.join(__dirname, 'public')));
}<commit_msg>Add express-session and create a new session<commit_after>/*
 * This file exports the configuration Express.js back to the application
 * so that it can be used in other parts of the product.
 */

var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');

exports.setup = function(app, express) {
	app.use(logger('dev'));
	app.use(bodyParser.json());
	app.use(bodyParser.urlencoded({ extended: false }));
	app.use(cookieParser());
  app.use(session({ secret: 'mylittlesecret' , resave: false, saveUninitialized: false }));
	app.use(express.static(path.join(__dirname, 'public')));
}<|endoftext|>


<commit_before>/*jslint browser: true, indent: 2, forin: true */
/*global toString */
(function () {
  "use strict";
  var mark = 'visited_by_objgrep',
    objgrep = function (root, regex, depth, context) {
      var className, ret = [], i, newContext;
      if (typeof depth !== "number") {
        depth = Infinity;
      }
      context = context || '';

      if (depth < 1) {
        return [];
      }

      switch (typeof root) {
      case 'string':
      case 'number':
      case 'boolean':
        if (root.toString().match(regex)) {
          return [context];
        }
        break;
      case 'object':
        if (!root || root.hasOwnProperty(mark)) {
          return [];  // cyclic
        }
        root[mark] = true;
        for (i in root) {
          if (i !== mark) {
            if (i.match(/^[$A-Z_][0-9A-Z_$]*$/i)) {
              newContext = [context, i].join('.');
            } else if (i.match(/^[0-9]+$/)) {
              newContext = context + "[" + i + "]";
            } else {
              newContext = context + "['" + i + "']";
            }

            if (i.match(regex)) {
              ret.push(newContext);
            }
            try {
              ret = ret.concat(objgrep(
                root[i],
                regex,
                depth - 1,
                newContext
              ));
            } catch (e) {
              // if we cannot access a property, then so be it
            }
          }
        }
        delete root[mark];
        break;
      default:
        break;
      }
      return ret;
    };

  Object.prototype.grep = function (regex, depth, context) {
    return objgrep(this, regex, depth, context);
  };
})();
<commit_msg>Use smaller default search depth. Fixes #1<commit_after>/*jslint browser: true, indent: 2, forin: true */
/*global toString, console */
(function () {
  "use strict";
  var mark = 'visited_by_objgrep',
    objgrep = function (root, regex, depth, context) {
      var className, ret = [], i, newContext;
      context = context || '';

      if (depth < 1) {
        return [];
      }

      switch (typeof root) {
      case 'string':
      case 'number':
      case 'boolean':
        if (root.toString().match(regex)) {
          return [context];
        }
        break;
      case 'object':
        if (!root || root.hasOwnProperty(mark)) {
          return [];  // cyclic
        }
        root[mark] = true;
        for (i in root) {
          if (i !== mark) {
            if (i.match(/^[$A-Z_][0-9A-Z_$]*$/i)) {
              newContext = [context, i].join('.');
            } else if (i.match(/^[0-9]+$/)) {
              newContext = context + "[" + i + "]";
            } else {
              newContext = context + "['" + i + "']";
            }

            if (i.match(regex)) {
              ret.push(newContext);
            }
            try {
              ret = ret.concat(objgrep(
                root[i],
                regex,
                depth - 1,
                newContext
              ));
            } catch (e) {
              // if we cannot access a property, then so be it
            }
          }
        }
        delete root[mark];
        break;
      default:
        break;
      }
      return ret;
    };

  Object.prototype.grep = function (regex, depth, context) {
    if (typeof depth !== "number") {
      depth = 5;
      console.log('Using a default search depth of ' + depth);
    }
    return objgrep(this, regex, depth, context);
  };
})();
<|endoftext|>


<commit_before>'use strict'

const views = require('../database/views')
const pages = require('../database/pages')

module.exports = {
	Interval: {
		DAILY: require('../constants/intervals').INTERVALS_DAILY,
		MONTHLY: require('../constants/intervals').INTERVALS_MONTHLY,
		YEARLY: require('../constants/intervals').INTERVALS_YEARLY
	},
	Range: {
		LAST_24_HOURS: require('../constants/ranges').RANGES_LAST_24_HOURS,
		LAST_7_DAYS: require('../constants/ranges').RANGES_LAST_7_DAYS,
		LAST_30_DAYS: require('../constants/ranges').RANGES_LAST_30_DAYS,
		ALL_TIME: require('../constants/ranges').RANGES_ALL_TIME
	},
	Sorting: {
		TOP: require('../constants/sortings').SORTINGS_TOP,
		RECENT: require('../constants/sortings').SORTINGS_RECENT,
		NEW: require('../constants/sortings').SORTINGS_NEW
	},
	ViewType: {
		UNIQUE: require('../constants/views').VIEWS_TYPE_UNIQUE,
		TOTAL: require('../constants/views').VIEWS_TYPE_TOTAL
	},
	SystemType: {
		WITH_VERSION: require('../constants/systems').SYSTEMS_TYPE_WITH_VERSION,
		NO_VERSION: require('../constants/systems').SYSTEMS_TYPE_NO_VERSION
	},
	DeviceType: {
		WITH_MODEL: require('../constants/devices').DEVICES_TYPE_WITH_MODEL,
		NO_MODEL: require('../constants/devices').DEVICES_TYPE_NO_MODEL
	},
	BrowserType: {
		WITH_VERSION: require('../constants/browsers').BROWSERS_TYPE_WITH_VERSION,
		NO_VERSION: require('../constants/browsers').BROWSERS_TYPE_NO_VERSION
	},
	SizeType: {
		BROWSER_HEIGHT: require('../constants/sizes').SIZES_TYPE_BROWSER_HEIGHT,
		BROWSER_RESOLUTION: require('../constants/sizes').SIZES_TYPE_BROWSER_RESOLUTION,
		BROWSER_WIDTH: require('../constants/sizes').SIZES_TYPE_BROWSER_WIDTH,
		SCREEN_HEIGHT: require('../constants/sizes').SIZES_TYPE_SCREEN_HEIGHT,
		SCREEN_RESOLUTION: require('../constants/sizes').SIZES_TYPE_SCREEN_RESOLUTION,
		SCREEN_WIDTH: require('../constants/sizes').SIZES_TYPE_SCREEN_WIDTH
	},
	Statistics: {
		// TODO: Add limit and enhancer
		views: async (domain, { type, interval }) => {

			const response = (entry) => ({
				date: new Date(entry._id.year, entry._id.month == null ? 0 : entry._id.month - 1, entry._id.day == null ? 1 : entry._id.day),
				count: entry.count
			})

			const entries = await views.get(domain.id, type, interval)

			return entries.map(response)

		},
		// TODO: Add limit and enhancer
		pages: async (domain, { sorting, range }) => {

			const response = (entry) => ({
				id: entry._id.siteLocation,
				count: entry.count
			})

			const entries = await pages.get(domain.id, sorting, range)

			return entries.map(response)

		}
	}
}<commit_msg>Add more statistics resolver<commit_after>'use strict'

const views = require('../database/views')
const pages = require('../database/pages')
const referrers = require('../database/referrers')
const durations = require('../database/durations')
const systems = require('../database/systems')
const devices = require('../database/devices')
const browsers = require('../database/browsers')
const sizes = require('../database/sizes')
const languages = require('../database/languages')

module.exports = {
	Interval: {
		DAILY: require('../constants/intervals').INTERVALS_DAILY,
		MONTHLY: require('../constants/intervals').INTERVALS_MONTHLY,
		YEARLY: require('../constants/intervals').INTERVALS_YEARLY
	},
	Sorting: {
		TOP: require('../constants/sortings').SORTINGS_TOP,
		RECENT: require('../constants/sortings').SORTINGS_RECENT,
		NEW: require('../constants/sortings').SORTINGS_NEW
	},
	Range: {
		LAST_24_HOURS: require('../constants/ranges').RANGES_LAST_24_HOURS,
		LAST_7_DAYS: require('../constants/ranges').RANGES_LAST_7_DAYS,
		LAST_30_DAYS: require('../constants/ranges').RANGES_LAST_30_DAYS,
		ALL_TIME: require('../constants/ranges').RANGES_ALL_TIME
	},
	ViewType: {
		UNIQUE: require('../constants/views').VIEWS_TYPE_UNIQUE,
		TOTAL: require('../constants/views').VIEWS_TYPE_TOTAL
	},
	SystemType: {
		WITH_VERSION: require('../constants/systems').SYSTEMS_TYPE_WITH_VERSION,
		NO_VERSION: require('../constants/systems').SYSTEMS_TYPE_NO_VERSION
	},
	DeviceType: {
		WITH_MODEL: require('../constants/devices').DEVICES_TYPE_WITH_MODEL,
		NO_MODEL: require('../constants/devices').DEVICES_TYPE_NO_MODEL
	},
	BrowserType: {
		WITH_VERSION: require('../constants/browsers').BROWSERS_TYPE_WITH_VERSION,
		NO_VERSION: require('../constants/browsers').BROWSERS_TYPE_NO_VERSION
	},
	SizeType: {
		BROWSER_HEIGHT: require('../constants/sizes').SIZES_TYPE_BROWSER_HEIGHT,
		BROWSER_RESOLUTION: require('../constants/sizes').SIZES_TYPE_BROWSER_RESOLUTION,
		BROWSER_WIDTH: require('../constants/sizes').SIZES_TYPE_BROWSER_WIDTH,
		SCREEN_HEIGHT: require('../constants/sizes').SIZES_TYPE_SCREEN_HEIGHT,
		SCREEN_RESOLUTION: require('../constants/sizes').SIZES_TYPE_SCREEN_RESOLUTION,
		SCREEN_WIDTH: require('../constants/sizes').SIZES_TYPE_SCREEN_WIDTH
	},
	Statistics: {
		// TODO: Add limit and enhancer
		views: async (domain, { type, interval }) => {

			const response = (entry) => ({
				id: new Date(entry._id.year, entry._id.month == null ? 0 : entry._id.month - 1, entry._id.day == null ? 1 : entry._id.day),
				count: entry.count
			})

			const entries = await views.get(domain.id, type, interval)

			return entries.map(response)

		},
		// TODO: Add limit and enhancer
		pages: async (domain, { sorting, range }) => {

			const response = (entry) => ({
				id: entry._id.siteLocation,
				count: entry.count
			})

			const entries = await pages.get(domain.id, sorting, range)

			return entries.map(response)

		},
		// TODO: Add limit and enhancer
		referrers: async (domain, { sorting, range }) => {

			const response = (entry) => ({
				id: entry._id.siteReferrer,
				count: entry.count,
				created: entry.created
			})

			const entries = await referrers.get(domain.id, sorting, range)

			return entries.map(response)

		},
		// TODO: Add limit and enhancer
		durations: async (domain, { interval }) => {

			const response = (entry) => ({
				id: new Date(entry._id.year, entry._id.month == null ? 0 : entry._id.month - 1, entry._id.day == null ? 1 : entry._id.day),
				count: entry.average
			})

			const entries = await durations.get(domain.id, interval)

			return entries.map(response)

		},
		// TODO: Add limit and enhancer and fix id response
		systems: async (domain, { sorting, type, range }) => {

			const response = (entry) => ({
				id: entry._id.osName,
				count: entry.count,
				created: entry.created
			})

			const entries = await systems.get(domain.id, sorting, type, range)

			return entries.map(response)

		},
		// TODO: Add limit and enhancer and fix id response
		devices: async (domain, { sorting, type, range }) => {

			const response = (entry) => ({
				id: entry._id.deviceManufacturer,
				count: entry.count,
				created: entry.created
			})

			const entries = await devices.get(domain.id, sorting, type, range)

			return entries.map(response)

		},
		// TODO: Add limit and enhancer and fix id response
		browsers: async (domain, { sorting, type, range }) => {

			const response = (entry) => ({
				id: entry._id.browserName,
				count: entry.count,
				created: entry.created
			})

			const entries = await browsers.get(domain.id, sorting, type, range)

			return entries.map(response)

		},
		// TODO: Add limit and enhancer and fix id response + Add support for sorting
		sizes: async (domain, { type, range }) => {

			console.log(range)

			const response = (entry) => ({
				id: entry._id.screenWidth,
				count: entry.count,
				created: entry.created
			})

			const entries = await sizes.get(domain.id, type, range)

			return entries.map(response)

		},
		// TODO: Add limit and enhancer
		languages: async (domain, { sorting, range }) => {

			const response = (entry) => ({
				id: entry._id.siteLanguage,
				count: entry.count,
				created: entry.created
			})

			const entries = await languages.get(domain.id, sorting, range)

			return entries.map(response)

		}
	}
}<|endoftext|>


<commit_before>import React from 'react'
import { connect } from 'react-redux'
import { createSelector } from 'reselect'

import {
  selectOAuth,
  selectSubmissions
} from 'containers/App/selectors'

import {
  logOut
} from 'containers/App/actions'

import Dropdown from 'containers/Dropdown'
import AuthMenuButton from 'components/AuthMenuButton'

import { Container, Hamburger, Nav, StyledButton, StyledLink, StyledA, DropDownItem } from './styles'

import iconSinglePane from 'images/icon-single-pane.svg'
import iconTwoPanes from 'images/icon-split-panes.svg'

export class Menu extends React.Component {

  constructor (props) {
    super(props)
    this.state = {
      showDropdown: false,
      shiftKey: false
    }
  }

  makeProviderList () {
    if (!(this.props.oauth && this.props.oauth.providers)) {
      return []
    } else {
      return this.props.oauth.providers
        .map((provider) => (

        ))
    }
  }

  render () {
    const aboutSelected = this.props.path === 'about'
    const introSelected = this.props.path === 'intro'
    const surveying = !aboutSelected && !introSelected

    const isAuthenicated = this.props.oauth && this.props.oauth.oauth && this.props.oauth.oauth.provider

    let menuItems

    if (isAuthenicated) {
      menuItems = [

      ]

      if (this.state.shiftKey) {
        menuItems = [
          ...menuItems,
          ...this.makeProviderList()
        ]
      }
    } else {
      menuItems = this.makeProviderList()
    }

    menuItems = [
      ,
      ,
      ...menuItems
    ]

    return (
      <Container>
        <AuthMenuButton className='toggle-dropdown' onClick={this.toggleDropdown.bind(this)}
          oauth={this.props.oauth} submissions={this.props.submissions} />
        <Hamburger className='toggle-dropdown' onClick={this.toggleDropdown.bind(this)}>☰</Hamburger>
        <Dropdown show={this.state.showDropdown} onHide={this.hideDropdown.bind(this)}>
          {menuItems.map((item, index) => (
            <DropDownItem key={index}>
              {item}
            </DropDownItem>
          ))}
        </Dropdown>

      </Container>
    )
  }

  hideDropdown () {
    this.setState({
      showDropdown: false
    })
  }

  toggleDropdown (event) {
    const shiftKey = event.nativeEvent && event.nativeEvent.shiftKey
    this.setState({
      showDropdown: !this.state.showDropdown,
      shiftKey
    })
  }
}

function mapDispatchToProps (dispatch) {
  return {
    logOut: () => dispatch(logOut())
  }
}

export default connect(createSelector(
  selectOAuth(),
  selectSubmissions(),
  (oauth, submissions) => ({
    oauth, submissions
  })
), mapDispatchToProps)(Menu)
<commit_msg>Don't show About button in dropdown menu when size is not-mobile - closes #144<commit_after>import React from 'react'
import { connect } from 'react-redux'
import { createSelector } from 'reselect'

import {
  selectOAuth,
  selectSubmissions
} from 'containers/App/selectors'

import {
  logOut
} from 'containers/App/actions'

import Dropdown from 'containers/Dropdown'
import AuthMenuButton from 'components/AuthMenuButton'

import { Container, Hamburger, Nav, StyledButton, StyledLink, StyledA, DropDownItem } from './styles'

import iconSinglePane from 'images/icon-single-pane.svg'
import iconTwoPanes from 'images/icon-split-panes.svg'

export class Menu extends React.Component {

  constructor (props) {
    super(props)
    this.state = {
      showDropdown: false,
      shiftKey: false
    }
  }

  makeProviderList () {
    if (!(this.props.oauth && this.props.oauth.providers)) {
      return []
    } else {
      return this.props.oauth.providers
        .map((provider) => (

        ))
    }
  }

  render () {
    const aboutSelected = this.props.path === 'about'
    const introSelected = this.props.path === 'intro'
    const surveying = !aboutSelected && !introSelected

    const isAuthenicated = this.props.oauth && this.props.oauth.oauth && this.props.oauth.oauth.provider

    let menuItems

    if (isAuthenicated) {
      menuItems = [

      ]

      if (this.state.shiftKey) {
        menuItems = [
          ...menuItems,
          ...this.makeProviderList()
        ]
      }
    } else {
      menuItems = this.makeProviderList()
    }

    const hideFirst = 2
    menuItems = [
      ,
      ,
      ...menuItems
    ]

    return (
      <Container>
        <AuthMenuButton className='toggle-dropdown' onClick={this.toggleDropdown.bind(this)}
          oauth={this.props.oauth} submissions={this.props.submissions} />
        <Hamburger className='toggle-dropdown' onClick={this.toggleDropdown.bind(this)}>☰</Hamburger>
        <Dropdown show={this.state.showDropdown} onHide={this.hideDropdown.bind(this)}>
          {menuItems.map((item, index) => (
            <DropDownItem key={index} className={index < hideFirst ? 'show-on-mobile' : undefined}>
              {item}
            </DropDownItem>
          ))}
        </Dropdown>

      </Container>
    )
  }

  hideDropdown () {
    this.setState({
      showDropdown: false
    })
  }

  toggleDropdown (event) {
    const shiftKey = event.nativeEvent && event.nativeEvent.shiftKey
    this.setState({
      showDropdown: !this.state.showDropdown,
      shiftKey
    })
  }
}

function mapDispatchToProps (dispatch) {
  return {
    logOut: () => dispatch(logOut())
  }
}

export default connect(createSelector(
  selectOAuth(),
  selectSubmissions(),
  (oauth, submissions) => ({
    oauth, submissions
  })
), mapDispatchToProps)(Menu)
<|endoftext|>


<commit_before>/*jslint browser: true, indent: 2, forin: true */
/*global toString, console */
(function () {
  "use strict";
  var mark = 'visited_by_objgrep',
    objgrep = function (root, regex, depth, context) {
      var className, ret = [], i, newContext;
      context = context || '';

      if (depth < 1) {
        return [];
      }

      switch (typeof root) {
      case 'string':
      case 'number':
      case 'boolean':
        if (root.toString().match(regex)) {
          return [context];
        }
        break;
      case 'object':
        if (!root || root.hasOwnProperty(mark)) {
          return [];  // cyclic
        }
        root[mark] = true;
        for (i in root) {
          if (i !== mark) {
            if (i.match(/^[$A-Z_][0-9A-Z_$]*$/i)) {
              newContext = [context, i].join('.');
            } else if (i.match(/^[0-9]+$/)) {
              newContext = context + "[" + i + "]";
            } else {
              newContext = context + "['" + i + "']";
            }

            if (i.match(regex)) {
              ret.push(newContext);
            }
            try {
              ret = ret.concat(objgrep(
                root[i],
                regex,
                depth - 1,
                newContext
              ));
            } catch (e) {
              // if we cannot access a property, then so be it
            }
          }
        }
        delete root[mark];
        break;
      default:
        break;
      }
      return ret;
    };

  Object.defineProperty(Object.prototype, 'grep', {
    enumerable: false,
    value: function (regex, depth, context) {
      if (typeof depth !== "number") {
        depth = 5;
        console.log('Using a default search depth of ' + depth);
      }
      return objgrep(this, regex, depth, context);
    }
  });
})();
<commit_msg>Added allow_dom attribute to be able to filter out DOM<commit_after>/*jslint browser: true, indent: 2, forin: true */
/*global toString, console */
(function () {
  "use strict";
  var mark = 'visited_by_objgrep',
    objgrep = function (root, regex, depth, allow_dom, context) {
      var className, ret = [], i, newContext;
      context = context || '';

      if (depth < 1) {
        return [];
      }

      switch (typeof root) {
      case 'string':
      case 'number':
      case 'boolean':
        if (root.toString().match(regex)) {
          return [context];
        }
        break;
      case 'object':
        if (!root || root.hasOwnProperty(mark)) {
          return [];  // cyclic
        }
        root[mark] = true;
        for (i in root) {
          if (i !== mark) {
            if (i.match(/^[$A-Z_][0-9A-Z_$]*$/i)) {
              newContext = [context, i].join('.');
            } else if (i.match(/^[0-9]+$/)) {
              newContext = context + "[" + i + "]";
            } else {
              newContext = context + "['" + i + "']";
            }

            if (i.match(regex)) {
              ret.push(newContext);
            }
            if (allow_dom || !(root[i] instanceof HTMLElement)) {
              try {
                ret = ret.concat(objgrep(
                  root[i],
                  regex,
                  depth - 1,
                  allow_dom,
                  newContext
                ));
              } catch (e) {
                // if we cannot access a property, then so be it
              }
            }
          }
        }
        delete root[mark];
        break;
      default:
        break;
      }
      return ret;
    };

  Object.defineProperty(Object.prototype, 'grep', {
    enumerable: false,
    value: function (regex, depth, allow_dom, context) {
      if (typeof depth !== "number") {
        depth = 5;
        console.log('Using a default search depth of ' + depth);
      }
      return objgrep(this, regex, depth, allow_dom, context);
    }
  });
})();
<|endoftext|>