<commit_before>// Load modules

var Fs = require('fs');
var Escape = require('./escape');

// Declare internals

var internals = {};

// Clone object or array

exports.clone = function (obj, seen) {

    if (typeof obj !== 'object' ||
        obj === null) {

        return obj;
    }

    seen = seen || { orig: [], copy: [] };

    var lookup = seen.orig.indexOf(obj);
    if (lookup !== -1) {
        return seen.copy[lookup];
    }

    var newObj = (obj instanceof Array) ? [] : {};

    seen.orig.push(obj);
    seen.copy.push(newObj);

    for (var i in obj) {
        if (obj.hasOwnProperty(i)) {
            if (obj[i] instanceof Date) {
                newObj[i] = new Date(obj[i].getTime());
            }
            else if (obj[i] instanceof RegExp) {
                var flags = '' + (obj[i].global ? 'g' : '') + (obj[i].ignoreCase ? 'i' : '') + (obj[i].multiline ? 'm' : '');
                newObj[i] = new RegExp(obj[i].source, flags);
            }
            else {
                newObj[i] = exports.clone(obj[i], seen);
            }
        }
    }

    return newObj;
};

// Merge all the properties of source into target, source wins in conflic, and by default null and undefined from source are applied

exports.merge = function (target, source, isNullOverride /* = true */, isMergeArrays /* = true */) {

    exports.assert(target && typeof target == 'object', 'Invalid target value: must be an object');
    exports.assert(source === null || source === undefined || typeof source === 'object', 'Invalid source value: must be null, undefined, or an object');

    if (!source) {
        return target;
    }

    if (source instanceof Array) {
        exports.assert(target instanceof Array, 'Cannot merge array onto an object');
        if (isMergeArrays === false) {                                                  // isMergeArrays defaults to true
            target.length = 0;                                                          // Must not change target assignment
        }

        source.forEach(function (item) {

            target.push(item);
        });

        return target;
    }

    Object.keys(source).forEach(function (key) {

        var value = source[key];
        if (value &&
            typeof value === 'object') {

            if (!target[key] ||
                typeof target[key] !== 'object') {

                target[key] = exports.clone(value);
            }
            else {
                exports.merge(target[key], source[key], isNullOverride, isMergeArrays);
            }
        }
        else {
            if (value !== null && value !== undefined) {            // Explicit to preserve empty strings
                target[key] = value;
            }
            else if (isNullOverride !== false) {                    // Defaults to true
                target[key] = value;
            }
        }
    });

    return target;
};

// Apply options to a copy of the defaults

exports.applyToDefaults = function (defaults, options) {

    exports.assert(defaults && typeof defaults == 'object', 'Invalid defaults value: must be an object');
    exports.assert(!options || options === true || typeof options === 'object', 'Invalid options value: must be true, falsy or an object');

    if (!options) {                                                 // If no options, return null
        return null;
    }

    var copy = exports.clone(defaults);

    if (options === true) {                                         // If options is set to true, use defaults
        return copy;
    }

    return exports.merge(copy, options, false, false);
};

// Remove duplicate items from array

exports.unique = function (array, key) {

    var index = {};
    var result = [];

    for (var i = 0, il = array.length; i < il; ++i) {
        var id = (key ? array[i][key] : array[i]);
        if (index[id] !== true) {

            result.push(array[i]);
            index[id] = true;
        }
    }

    return result;
};

// Convert array into object

exports.mapToObject = function (array, key) {

    if (!array) {
        return null;
    }

    var obj = {};
    for (var i = 0, il = array.length; i < il; ++i) {
        if (key) {
            if (array[i][key]) {
                obj[array[i][key]] = true;
            }
        }
        else {
            obj[array[i]] = true;
        }
    }

    return obj;
};

// Find the common unique items in two arrays

exports.intersect = function (array1, array2) {

    if (!array1 || !array2) {
        return [];
    }

    var common = [];
    var hash = (array1 instanceof Array ? exports.mapToObject(array1) : array1);
    var found = {};
    for (var i = 0, il = array2.length; i < il; ++i) {
        if (hash[array2[i]] && !found[array2[i]]) {
            common.push(array2[i]);
            found[array2[i]] = true;
        }
    }

    return common;
};

// Find which keys are present

exports.matchKeys = function (obj, keys) {

    var matched = [];
    for (var i = 0, il = keys.length; i < il; ++i) {
        if (obj.hasOwnProperty(keys[i])) {
            matched.push(keys[i]);
        }
    }
    return matched;
};

// Flatten array

exports.flatten = function (array, target) {

    var result = target || [];

    for (var i = 0, il = array.length; i < il; ++i) {
        if (Array.isArray(array[i])) {
            exports.flatten(array[i], result);
        }
        else {
            result.push(array[i]);
        }
    }

    return result;
};

// Remove keys

exports.removeKeys = function (object, keys) {

    for (var i = 0, il = keys.length; i < il; i++) {
        delete object[keys[i]];
    }
};

// Convert an object key chain string ('a.b.c') to reference (object[a][b][c])

exports.reach = function (obj, chain) {

    var path = chain.split('.');
    var ref = obj;
    path.forEach(function (level) {

        if (ref) {
            ref = ref[level];
        }
    });

    return ref;
};

// Inherits a selected set of methods from an object, wrapping functions in asynchronous syntax and catching errors

exports.inheritAsync = function (self, obj, keys) {

    keys = keys || null;

    for (var i in obj) {
        if (obj.hasOwnProperty(i)) {
            if (keys instanceof Array &&
                keys.indexOf(i) < 0) {

                continue;
            }

            self.prototype[i] = (function (fn) {

                return function (callback) {

                    var result = null;
                    try {
                        result = fn();
                    }
                    catch (err) {
                        return callback(err);
                    }

                    return callback(null, result);
                };
            })(obj[i]);
        }
    }
};

exports.formatStack = function (stack) {

    var trace = [];
    stack.forEach(function (item) {

        trace.push([item.getFileName(), item.getLineNumber(), item.getColumnNumber(), item.getFunctionName(), item.isConstructor()]);
    });

    return trace;
};

exports.formatTrace = function (trace) {

    var display = [];
    trace.forEach(function (row) {

        display.push((row[4] ? 'new ' : '') + row[3] + ' (' + row[0] + ':' + row[1] + ':' + row[2] + ')');
    });

    return display;
};

exports.callStack = function (slice) {

    // http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi

    var v8 = Error.prepareStackTrace;
    Error.prepareStackTrace = function (err, stack) {

        return stack;
    };

    var capture = {};
    Error.captureStackTrace(capture, arguments.callee);
    var stack = capture.stack;

    Error.prepareStackTrace = v8;

    var trace = exports.formatStack(stack);

    if (slice) {
        return trace.slice(slice);
    }

    return trace;
};

exports.displayStack = function (slice) {

    var trace = exports.callStack(slice === undefined ? 1 : slice + 1);

    return exports.formatTrace(trace);
};

exports.abortThrow = false;

exports.abort = function (message, hideStack) {

    if (process.env.NODE_ENV === 'test' || exports.abortThrow === true) {
        throw new Error(message || 'Unknown error');
    }

    var stack = '';
    if (!hideStack) {
        stack = exports.displayStack(1).join('\n\t');
    }
    console.log('ABORT: ' + message + '\n\t' + stack);
    process.exit(1);
};

exports.assert = function (condition, message) {

    if (!condition) {
        throw new Error(message || 'Unknown error');
    }
};

exports.loadDirModules = function (path, excludeFiles, target) {      // target(filename, name, capName)

    var exclude = {};
    for (var i = 0, il = excludeFiles.length; i < il; ++i) {
        exclude[excludeFiles[i] + '.js'] = true;
    }

    Fs.readdirSync(path).forEach(function (filename) {

        if (/\.js$/.test(filename) &&
            !exclude[filename]) {

            var name = filename.substr(0, filename.lastIndexOf('.'));
            var capName = name.charAt(0).toUpperCase() + name.substr(1).toLowerCase();

            if (typeof target !== 'function') {
                target[capName] = require(path + '/' + name);
            }
            else {
                target(path + '/' + name, name, capName);
            }
        }
    });
};

exports.rename = function (obj, from, to) {

    obj[to] = obj[from];
    delete obj[from];
};

exports.Timer = function () {

    this.reset();
};

exports.Timer.prototype.reset = function () {

    this.ts = Date.now();
};

exports.Timer.prototype.elapsed = function () {

    return Date.now() - this.ts;
};

// Load and parse package.json process root or given directory

exports.loadPackage = function (dir) {

    var result = {};
    var filepath = (dir || process.env.PWD) + '/package.json';
    if (Fs.existsSync(filepath)) {
        try {
            result = JSON.parse(Fs.readFileSync(filepath));
        }
        catch (e) { }
    }

    return result;
};

// Escape string for Regex construction

exports.escapeRegex = function (string) {

    // Escape ^$.*+-?=!:|\/()[]{},
    return string.replace(/[\^\$\.\*\+\-\?\=\!\:\|\\\/\(\)\[\]\{\}\,]/g, '\\$&');
};

// Return an error as first argument of a callback

exports.toss = function (condition /*, [message], callback */) {

    var message = (arguments.length === 3 ? arguments[1] : '');
    var callback = (arguments.length === 3 ? arguments[2] : arguments[1]);

    var err = (message instanceof Error ? message : (message ? new Error(message) : (condition instanceof Error ? condition : new Error())));

    if (condition instanceof Error ||
        !condition) {

        return callback(err);
    }
};

// Base64url (RFC 4648) encode

exports.base64urlEncode = function (value) {

    return (new Buffer(value, 'binary')).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
};

// Base64url (RFC 4648) decode

exports.base64urlDecode = function (encoded) {

    if (encoded &&
        !encoded.match(/^[\w\-]*$/)) {

        return new Error('Invalid character');
    }

    try {
        return (new Buffer(encoded.replace(/-/g, '+').replace(/:/g, '/'), 'base64')).toString('binary');
    }
    catch (err) {
        return err;
    }
};

// Escape attribute value for use in HTTP header

exports.escapeHeaderAttribute = function (attribute) {

    // Allowed value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9, \, "

    exports.assert(attribute.match(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~\"\\]*$/), 'Bad attribute value (' + attribute + ')');

    return attribute.replace(/\\/g, '\\\\').replace(/\"/g, '\\"');                             // Escape quotes and slash
};

exports.escapeHtml = function (string) {

    return Escape.escapeHtml(string);
};

exports.escapeJavaScript = function (string) {

    return Escape.escapeJavaScript(string);
};

/*
var event = {
    timestamp: now.getTime(),
    tags: ['tag'],
    data: { some: 'data' }
};
*/

exports.consoleFunc = console.log;

exports.printEvent = function (event) {

    var pad = function (value) {

        return (value < 10 ? '0' : '') + value;
    };

    var now = new Date(event.timestamp);
    var timestring = (now.getYear() - 100).toString() +
        pad(now.getMonth() + 1) +
        pad(now.getDate()) +
        '/' +
        pad(now.getHours()) +
        pad(now.getMinutes()) +
        pad(now.getSeconds()) +
        '.' +
        now.getMilliseconds();

    var data = event.data;
    if (typeof event.data !== 'string') {
        try {
            data = JSON.stringify(event.data);
        }
        catch (e) {
            data = 'JSON Error: ' + e.message;
        }
    }

    var output = timestring + ', ' + event.tags[0] + ', ' + data;
    exports.consoleFunc(output);
};

exports.nextTick = function (callback) {

    return function () {

        var args = arguments;
        process.nextTick(function () {

            callback.apply(null, args);
        });
    };
};
<commit_msg>Update index.js<commit_after>// Load modules

var Fs = require('fs');
var Escape = require('./escape');

// Declare internals

var internals = {};

// Clone object or array

exports.clone = function (obj, seen) {

    if (typeof obj !== 'object' ||
        obj === null) {

        return obj;
    }

    seen = seen || { orig: [], copy: [] };

    var lookup = seen.orig.indexOf(obj);
    if (lookup !== -1) {
        return seen.copy[lookup];
    }

    var newObj = (obj instanceof Array) ? [] : {};

    seen.orig.push(obj);
    seen.copy.push(newObj);

    for (var i in obj) {
        if (obj.hasOwnProperty(i)) {
            if (obj[i] instanceof Date) {
                newObj[i] = new Date(obj[i].getTime());
            }
            else if (obj[i] instanceof RegExp) {
                var flags = '' + (obj[i].global ? 'g' : '') + (obj[i].ignoreCase ? 'i' : '') + (obj[i].multiline ? 'm' : '');
                newObj[i] = new RegExp(obj[i].source, flags);
            }
            else {
                newObj[i] = exports.clone(obj[i], seen);
            }
        }
    }

    return newObj;
};

// Merge all the properties of source into target, source wins in conflic, and by default null and undefined from source are applied

exports.merge = function (target, source, isNullOverride /* = true */, isMergeArrays /* = true */) {

    exports.assert(target && typeof target == 'object', 'Invalid target value: must be an object');
    exports.assert(source === null || source === undefined || typeof source === 'object', 'Invalid source value: must be null, undefined, or an object');

    if (!source) {
        return target;
    }

    if (source instanceof Array) {
        exports.assert(target instanceof Array, 'Cannot merge array onto an object');
        if (isMergeArrays === false) {                                                  // isMergeArrays defaults to true
            target.length = 0;                                                          // Must not change target assignment
        }

        source.forEach(function (item) {

            target.push(item);
        });

        return target;
    }

    Object.keys(source).forEach(function (key) {

        var value = source[key];
        if (value &&
            typeof value === 'object') {

            if (!target[key] ||
                typeof target[key] !== 'object') {

                target[key] = exports.clone(value);
            }
            else {
                exports.merge(target[key], source[key], isNullOverride, isMergeArrays);
            }
        }
        else {
            if (value !== null && value !== undefined) {            // Explicit to preserve empty strings
                target[key] = value;
            }
            else if (isNullOverride !== false) {                    // Defaults to true
                target[key] = value;
            }
        }
    });

    return target;
};

// Apply options to a copy of the defaults

exports.applyToDefaults = function (defaults, options) {

    exports.assert(defaults && typeof defaults == 'object', 'Invalid defaults value: must be an object');
    exports.assert(!options || options === true || typeof options === 'object', 'Invalid options value: must be true, falsy or an object');

    if (!options) {                                                 // If no options, return null
        return null;
    }

    var copy = exports.clone(defaults);

    if (options === true) {                                         // If options is set to true, use defaults
        return copy;
    }

    return exports.merge(copy, options, false, false);
};

// Remove duplicate items from array

exports.unique = function (array, key) {

    var index = {};
    var result = [];

    for (var i = 0, il = array.length; i < il; ++i) {
        var id = (key ? array[i][key] : array[i]);
        if (index[id] !== true) {

            result.push(array[i]);
            index[id] = true;
        }
    }

    return result;
};

// Convert array into object

exports.mapToObject = function (array, key) {

    if (!array) {
        return null;
    }

    var obj = {};
    for (var i = 0, il = array.length; i < il; ++i) {
        if (key) {
            if (array[i][key]) {
                obj[array[i][key]] = true;
            }
        }
        else {
            obj[array[i]] = true;
        }
    }

    return obj;
};

// Find the common unique items in two arrays

exports.intersect = function (array1, array2) {

    if (!array1 || !array2) {
        return [];
    }

    var common = [];
    var hash = (array1 instanceof Array ? exports.mapToObject(array1) : array1);
    var found = {};
    for (var i = 0, il = array2.length; i < il; ++i) {
        if (hash[array2[i]] && !found[array2[i]]) {
            common.push(array2[i]);
            found[array2[i]] = true;
        }
    }

    return common;
};

// Find which keys are present

exports.matchKeys = function (obj, keys) {

    var matched = [];
    for (var i = 0, il = keys.length; i < il; ++i) {
        if (obj.hasOwnProperty(keys[i])) {
            matched.push(keys[i]);
        }
    }
    return matched;
};

// Flatten array

exports.flatten = function (array, target) {

    var result = target || [];

    for (var i = 0, il = array.length; i < il; ++i) {
        if (Array.isArray(array[i])) {
            exports.flatten(array[i], result);
        }
        else {
            result.push(array[i]);
        }
    }

    return result;
};

// Remove keys

exports.removeKeys = function (object, keys) {

    for (var i = 0, il = keys.length; i < il; i++) {
        delete object[keys[i]];
    }
};

// Convert an object key chain string ('a.b.c') to reference (object[a][b][c])

exports.reach = function (obj, chain) {

    var path = chain.split('.');
    var ref = obj;
    path.forEach(function (level) {

        if (ref) {
            ref = ref[level];
        }
    });

    return ref;
};

// Inherits a selected set of methods from an object, wrapping functions in asynchronous syntax and catching errors

exports.inheritAsync = function (self, obj, keys) {

    keys = keys || null;

    for (var i in obj) {
        if (obj.hasOwnProperty(i)) {
            if (keys instanceof Array &&
                keys.indexOf(i) < 0) {

                continue;
            }

            self.prototype[i] = (function (fn) {

                return function (next) {

                    var result = null;
                    try {
                        result = fn();
                    }
                    catch (err) {
                        return next(err);
                    }

                    return next(null, result);
                };
            })(obj[i]);
        }
    }
};

exports.formatStack = function (stack) {

    var trace = [];
    stack.forEach(function (item) {

        trace.push([item.getFileName(), item.getLineNumber(), item.getColumnNumber(), item.getFunctionName(), item.isConstructor()]);
    });

    return trace;
};

exports.formatTrace = function (trace) {

    var display = [];
    trace.forEach(function (row) {

        display.push((row[4] ? 'new ' : '') + row[3] + ' (' + row[0] + ':' + row[1] + ':' + row[2] + ')');
    });

    return display;
};

exports.callStack = function (slice) {

    // http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi

    var v8 = Error.prepareStackTrace;
    Error.prepareStackTrace = function (err, stack) {

        return stack;
    };

    var capture = {};
    Error.captureStackTrace(capture, arguments.callee);
    var stack = capture.stack;

    Error.prepareStackTrace = v8;

    var trace = exports.formatStack(stack);

    if (slice) {
        return trace.slice(slice);
    }

    return trace;
};

exports.displayStack = function (slice) {

    var trace = exports.callStack(slice === undefined ? 1 : slice + 1);

    return exports.formatTrace(trace);
};

exports.abortThrow = false;

exports.abort = function (message, hideStack) {

    if (process.env.NODE_ENV === 'test' || exports.abortThrow === true) {
        throw new Error(message || 'Unknown error');
    }

    var stack = '';
    if (!hideStack) {
        stack = exports.displayStack(1).join('\n\t');
    }
    console.log('ABORT: ' + message + '\n\t' + stack);
    process.exit(1);
};

exports.assert = function (condition, message) {

    if (!condition) {
        throw new Error(message || 'Unknown error');
    }
};

exports.loadDirModules = function (path, excludeFiles, target) {      // target(filename, name, capName)

    var exclude = {};
    for (var i = 0, il = excludeFiles.length; i < il; ++i) {
        exclude[excludeFiles[i] + '.js'] = true;
    }

    Fs.readdirSync(path).forEach(function (filename) {

        if (/\.js$/.test(filename) &&
            !exclude[filename]) {

            var name = filename.substr(0, filename.lastIndexOf('.'));
            var capName = name.charAt(0).toUpperCase() + name.substr(1).toLowerCase();

            if (typeof target !== 'function') {
                target[capName] = require(path + '/' + name);
            }
            else {
                target(path + '/' + name, name, capName);
            }
        }
    });
};

exports.rename = function (obj, from, to) {

    obj[to] = obj[from];
    delete obj[from];
};

exports.Timer = function () {

    this.reset();
};

exports.Timer.prototype.reset = function () {

    this.ts = Date.now();
};

exports.Timer.prototype.elapsed = function () {

    return Date.now() - this.ts;
};

// Load and parse package.json process root or given directory

exports.loadPackage = function (dir) {

    var result = {};
    var filepath = (dir || process.env.PWD) + '/package.json';
    if (Fs.existsSync(filepath)) {
        try {
            result = JSON.parse(Fs.readFileSync(filepath));
        }
        catch (e) { }
    }

    return result;
};

// Escape string for Regex construction

exports.escapeRegex = function (string) {

    // Escape ^$.*+-?=!:|\/()[]{},
    return string.replace(/[\^\$\.\*\+\-\?\=\!\:\|\\\/\(\)\[\]\{\}\,]/g, '\\$&');
};

// Return an error as first argument of a callback

exports.toss = function (condition /*, [message], next */) {

    var message = (arguments.length === 3 ? arguments[1] : '');
    var next = (arguments.length === 3 ? arguments[2] : arguments[1]);

    var err = (message instanceof Error ? message : (message ? new Error(message) : (condition instanceof Error ? condition : new Error())));

    if (condition instanceof Error ||
        !condition) {

        return next(err);
    }
};

// Base64url (RFC 4648) encode

exports.base64urlEncode = function (value) {

    return (new Buffer(value, 'binary')).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
};

// Base64url (RFC 4648) decode

exports.base64urlDecode = function (encoded) {

    if (encoded &&
        !encoded.match(/^[\w\-]*$/)) {

        return new Error('Invalid character');
    }

    try {
        return (new Buffer(encoded.replace(/-/g, '+').replace(/:/g, '/'), 'base64')).toString('binary');
    }
    catch (err) {
        return err;
    }
};

// Escape attribute value for use in HTTP header

exports.escapeHeaderAttribute = function (attribute) {

    // Allowed value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9, \, "

    exports.assert(attribute.match(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~\"\\]*$/), 'Bad attribute value (' + attribute + ')');

    return attribute.replace(/\\/g, '\\\\').replace(/\"/g, '\\"');                             // Escape quotes and slash
};

exports.escapeHtml = function (string) {

    return Escape.escapeHtml(string);
};

exports.escapeJavaScript = function (string) {

    return Escape.escapeJavaScript(string);
};

/*
var event = {
    timestamp: now.getTime(),
    tags: ['tag'],
    data: { some: 'data' }
};
*/

exports.consoleFunc = console.log;

exports.printEvent = function (event) {

    var pad = function (value) {

        return (value < 10 ? '0' : '') + value;
    };

    var now = new Date(event.timestamp);
    var timestring = (now.getYear() - 100).toString() +
        pad(now.getMonth() + 1) +
        pad(now.getDate()) +
        '/' +
        pad(now.getHours()) +
        pad(now.getMinutes()) +
        pad(now.getSeconds()) +
        '.' +
        now.getMilliseconds();

    var data = event.data;
    if (typeof event.data !== 'string') {
        try {
            data = JSON.stringify(event.data);
        }
        catch (e) {
            data = 'JSON Error: ' + e.message;
        }
    }

    var output = timestring + ', ' + event.tags[0] + ', ' + data;
    exports.consoleFunc(output);
};

exports.nextTick = function (callback) {

    return function () {

        var args = arguments;
        process.nextTick(function () {

            callback.apply(null, args);
        });
    };
};
<|endoftext|>


<commit_before>'use babel'

import {TextEditor, Emitter, CompositeDisposable} from 'atom'
export default class EditorLinter {
  constructor(editor) {
    if (!(editor instanceof TextEditor)) {
      throw new Error('Given editor is not really an editor')
    }

    this.editor = editor
    this.emitter = new Emitter()
    this.messages = new Set()
    this.markers = new WeakMap()
    this.gutter = null
    this.subscriptions = new CompositeDisposable

    this.subscriptions.add(atom.config.observe('linter.underlineIssues', underlineIssues =>
      this.underlineIssues = underlineIssues
    ))
    this.subscriptions.add(this.editor.onDidDestroy(() =>
      this.dispose()
    ))
    this.subscriptions.add(this.editor.onDidSave(() =>
      this.emitter.emit('should-lint', false)
    ))
    this.subscriptions.add(this.editor.onDidChangeCursorPosition(({oldBufferPosition, newBufferPosition}) => {
      if (newBufferPosition.row !== oldBufferPosition.row) {
        this.emitter.emit('should-update-line-messages')
      }
      this.emitter.emit('should-update-bubble')
    }))
    this.subscriptions.add(atom.config.observe('linter.gutterEnabled', gutterEnabled => {
      this.gutterEnabled = gutterEnabled
      this.handleGutter()
    }))
    // Using onDidChange instead of observe here 'cause the same function is invoked above
    this.subscriptions.add(atom.config.onDidChange('linter.gutterPosition', () =>
      this.handleGutter()
    ))
    this.subscriptions.add(this.onDidMessageAdd(message => {
      if (!this.underlineIssues && !this.gutterEnabled) {
        return // No-Op
      }
      const marker = this.editor.markBufferRange(message.range, {invalidate: 'inside'})
      this.markers.set(message, marker)
      if (this.underlineIssues) {
        this.editor.decorateMarker(marker, {
          type: 'highlight',
          class: `linter-highlight ${message.class}`
        })
      }
      if (this.gutterEnabled) {
        const item = document.createElement('span')
        item.className = `linter-gutter linter-highlight ${message.class}`
        //item.innerHTML = ' '
        this.gutter.decorateMarker(marker, {
          class: 'linter-row',
          item
        })
      }
    }))
    this.subscriptions.add(this.onDidMessageRemove(message => {
      if (this.markers.has(message)) {
        this.markers.get(message).destroy()
        this.markers.delete(message)
      }
    }))

    // Atom invokes the onDidStopChanging callback immediately on Editor creation. So we wait a moment
    setImmediate(() => {
      this.subscriptions.add(this.editor.onDidStopChanging(() =>
        this.emitter.emit('should-lint', true)
      ))
    })
  }

  handleGutter() {
    if (this.gutter !== null) {
      this.removeGutter()
    }
    if (atom.config.get('linter.gutterEnabled')) {
      this.addGutter()
    }
  }

  addGutter() {
    const position = atom.config.get('linter.gutterPosition')
    this.gutter = this.editor.addGutter({
      name: 'linter',
      priority: position === 'Left' ? -100 : 100
    })
  }

  removeGutter() {
    if (this.gutter !== null) {
      try {
        this.gutter.destroy()
        // Atom throws when we try to remove a gutter container from a closed text editor
      } catch (err) {}
      this.gutter = null
    }
  }

  getMessages() {
    return this.messages
  }

  addMessage(message) {
    if (!this.messages.has(message)) {
      this.messages.add(message)
      this.emitter.emit('did-message-add', message)
      this.emitter.emit('did-message-change', {message, type: 'add'})
    }
  }

  removeMessage(message) {
    if (this.messages.has(message)) {
      this.messages.delete(message)
      this.emitter.emit('did-message-remove', message)
      this.emitter.emit('did-message-change', {message, type: 'remove'})
    }
  }

  lint(onChange = false) {
    this.emitter.emit('should-lint', onChange)
  }

  onDidMessageAdd(callback) {
    return this.emitter.on('did-message-add', callback)
  }

  onDidMessageRemove(callback) {
    return this.emitter.on('did-message-remove', callback)
  }

  onDidMessageChange(callback) {
    return this.emitter.on('did-message-change', callback)
  }

  onShouldUpdateBubble(callback) {
    return this.emitter.on('should-update-bubble', callback)
  }

  onShouldUpdateLineMessages(callback) {
    return this.emitter.on('should-update-line-messages', callback)
  }

  onShouldLint(callback) {
    return this.emitter.on('should-lint', callback)
  }

  onDidDestroy(callback) {
    return this.emitter.on('did-destroy', callback)
  }

  dispose() {
    this.emitter.emit('did-destroy')
    if (this.markers.size) {
      this.markers.forEach(marker => marker.destroy())
      this.markers.clear()
    }
    this.removeGutter()
    this.subscriptions.dispose()
    this.messages.clear()
    this.emitter.dispose()
  }
}
<commit_msg>:fire: Code cleanup<commit_after>'use babel'

import {TextEditor, Emitter, CompositeDisposable} from 'atom'
export default class EditorLinter {
  constructor(editor) {
    if (!(editor instanceof TextEditor)) {
      throw new Error('Given editor is not really an editor')
    }

    this.editor = editor
    this.emitter = new Emitter()
    this.messages = new Set()
    this.markers = new WeakMap()
    this.gutter = null
    this.subscriptions = new CompositeDisposable

    this.subscriptions.add(atom.config.observe('linter.underlineIssues', underlineIssues =>
      this.underlineIssues = underlineIssues
    ))
    this.subscriptions.add(this.editor.onDidDestroy(() =>
      this.dispose()
    ))
    this.subscriptions.add(this.editor.onDidSave(() =>
      this.emitter.emit('should-lint', false)
    ))
    this.subscriptions.add(this.editor.onDidChangeCursorPosition(({oldBufferPosition, newBufferPosition}) => {
      if (newBufferPosition.row !== oldBufferPosition.row) {
        this.emitter.emit('should-update-line-messages')
      }
      this.emitter.emit('should-update-bubble')
    }))
    this.subscriptions.add(atom.config.observe('linter.gutterEnabled', gutterEnabled => {
      this.gutterEnabled = gutterEnabled
      this.handleGutter()
    }))
    // Using onDidChange instead of observe here 'cause the same function is invoked above
    this.subscriptions.add(atom.config.onDidChange('linter.gutterPosition', () =>
      this.handleGutter()
    ))
    this.subscriptions.add(this.onDidMessageAdd(message => {
      if (!this.underlineIssues && !this.gutterEnabled) {
        return // No-Op
      }
      const marker = this.editor.markBufferRange(message.range, {invalidate: 'inside'})
      this.markers.set(message, marker)
      if (this.underlineIssues) {
        this.editor.decorateMarker(marker, {
          type: 'highlight',
          class: `linter-highlight ${message.class}`
        })
      }
      if (this.gutterEnabled) {
        const item = document.createElement('span')
        item.className = `linter-gutter linter-highlight ${message.class}`
        this.gutter.decorateMarker(marker, {
          class: 'linter-row',
          item
        })
      }
    }))
    this.subscriptions.add(this.onDidMessageRemove(message => {
      if (this.markers.has(message)) {
        this.markers.get(message).destroy()
        this.markers.delete(message)
      }
    }))

    // Atom invokes the onDidStopChanging callback immediately on Editor creation. So we wait a moment
    setImmediate(() => {
      this.subscriptions.add(this.editor.onDidStopChanging(() =>
        this.emitter.emit('should-lint', true)
      ))
    })
  }

  handleGutter() {
    if (this.gutter !== null) {
      this.removeGutter()
    }
    if (atom.config.get('linter.gutterEnabled')) {
      this.addGutter()
    }
  }

  addGutter() {
    const position = atom.config.get('linter.gutterPosition')
    this.gutter = this.editor.addGutter({
      name: 'linter',
      priority: position === 'Left' ? -100 : 100
    })
  }

  removeGutter() {
    if (this.gutter !== null) {
      try {
        this.gutter.destroy()
        // Atom throws when we try to remove a gutter container from a closed text editor
      } catch (err) {}
      this.gutter = null
    }
  }

  getMessages() {
    return this.messages
  }

  addMessage(message) {
    if (!this.messages.has(message)) {
      this.messages.add(message)
      this.emitter.emit('did-message-add', message)
      this.emitter.emit('did-message-change', {message, type: 'add'})
    }
  }

  removeMessage(message) {
    if (this.messages.has(message)) {
      this.messages.delete(message)
      this.emitter.emit('did-message-remove', message)
      this.emitter.emit('did-message-change', {message, type: 'remove'})
    }
  }

  lint(onChange = false) {
    this.emitter.emit('should-lint', onChange)
  }

  onDidMessageAdd(callback) {
    return this.emitter.on('did-message-add', callback)
  }

  onDidMessageRemove(callback) {
    return this.emitter.on('did-message-remove', callback)
  }

  onDidMessageChange(callback) {
    return this.emitter.on('did-message-change', callback)
  }

  onShouldUpdateBubble(callback) {
    return this.emitter.on('should-update-bubble', callback)
  }

  onShouldUpdateLineMessages(callback) {
    return this.emitter.on('should-update-line-messages', callback)
  }

  onShouldLint(callback) {
    return this.emitter.on('should-lint', callback)
  }

  onDidDestroy(callback) {
    return this.emitter.on('did-destroy', callback)
  }

  dispose() {
    this.emitter.emit('did-destroy')
    if (this.markers.size) {
      this.markers.forEach(marker => marker.destroy())
      this.markers.clear()
    }
    this.removeGutter()
    this.subscriptions.dispose()
    this.messages.clear()
    this.emitter.dispose()
  }
}
<|endoftext|>


<commit_before>var termops = require('./util/termops'),
    ops = require('./util/ops'),
    _ = require('underscore'),
    queue = require('queue-async'),
    DEBUG = process.env.DEBUG;

// # Store
// @param {Object} source - a Carmen source
// @param {Array} docs - an array of documents
// @param {Function} callback
module.exports = function index(source, docs, callback) {

    // First pass over docs.
    // - Creates termsets (one or more arrays of termids) from document text.
    // - Tallies frequency of termids against current frequencies compiling a
    //   final in-memory frequency count of all terms involved with this set of
    //   documents to be indexed.
    // - Stores new frequencies.

    docs = assignParts(docs);
    var freq = generateFrequency(docs);

    // Ensures all shards are loaded.
    var ids = Object.keys(freq).map(function(v) { return parseInt(v, 10); });
    source._geocoder.getall(source.getCarmen.bind(source), 'freq', ids, function(err) {
        if (err) return callback(err);
        for (var i = 0; i < ids.length; i++) {
            var id = ids[i];
            freq[id][0] = (source._geocoder.get('freq', id) || [0])[0] + freq[id][0];
            source._geocoder.set('freq', id, freq[id]);
        }
        indexDocs(freq[0], freq, callback);
    });

    // Second pass over docs.
    // - Create term => docid index. Uses calculated frequencies to index only
    //   significant terms for each document.
    // - Create id => grid zxy index.
    function indexDocs(approxdocs, freq, callback) {
        var patch = { grid: {}, term: {}, phrase: {}, degen: {} };
        var degenerated = {};

        docs.forEach(loadDoc);

        function loadDoc(doc) {
            doc.id = parseInt(doc.id,10);
            doc.zxy = doc.zxy ? doc.zxy.map(function(zxy) {
                return ops.zxy(doc.id, zxy);
            }) : [];

            var phrases = doc.phrases;
            var termsets = doc.termsets;
            var termsmaps = doc.termsmaps;

            phrases.forEach(function(id, x) {
                patch.phrase[id] = patch.phrase[id] || termsets[x];
                patch.grid[id] = patch.grid[id] || [];
                patch.grid[id].push.apply(patch.grid[id], doc.zxy);
            });

            termsets.forEach(loadTerm);

            function loadTerm(terms, x) {
                var id;
                var termsmap = termsmaps[x];
                var name = phrases[x];
                var weights = [];
                var total = 0;

                for (var i = 0; i < terms.length; i++) {
                    id = terms[i];
                    var weight = Math.log(1 + freq[0][0]/freq[id][0]);
                    weights.push([id, weight]);
                    total += weight;

                    // Degenerate terms are indexed for all terms
                    // (not just significant ones).
                    if (degenerated[id]) continue;
                    degenerated[id] = true;
                    var degens = termops.degens(termsmap[id]);
                    var keys = Object.keys(degens);
                    for (var j = 0; j < keys.length; j++) {
                        var d = keys[j];
                        patch.degen[d] = patch.degen[d] || [];
                        patch.degen[d].push(degens[d]);
                    }
                }

                // Limit indexing to the *most* significant terms for a
                // document. Currently uses rough heuristic (floor+sqrt) to
                // determine how many of the top words to grab.
                weights.sort(function(a,b) {
                    return a[1] > b[1] ? -1 : a[1] < b[1] ? 1 : 0;
                });
                var sigterms = [];
                var limit = Math.floor(Math.sqrt(weights.length));
                for (i = 0; i < limit; i++) sigterms.push(weights[i][0]);

                // Debug significant term selection.
                if (DEBUG) {
                    var debug = termsmap;
                    var oldtext = terms.map(function(id) { return debug[id]; }).join(' ');
                    var sigtext = sigterms.map(function(id) { return debug[id]; }).join(' ');
                    if (oldtext !== sigtext)  console.log('%s => %s', oldtext, sigtext);
                }

                for (i = 0; i < sigterms.length; i++) {
                    id = sigterms[i];
                    patch.term[id] = patch.term[id] || [];
                    patch.term[id].push(name);
                }
            }
        }

        var q = queue(10);
        _(docs).each(putDocumentFeature);
        _(patch).each(setParts);
        q.awaitAll(callback);

        function putDocumentFeature(doc) {
            q.defer(function(doc, callback) {
                source.putFeature(doc.id, doc.doc, callback);
            }, doc);
        }

        function setParts(data, type) {
            q.defer(function(data, type, callback) {
                var ids = Object.keys(data);
                source._geocoder.getall(source.getCarmen.bind(source), type, ids, function(err) {
                    if (err) return callback(err);
                    for (var i = 0; i < ids.length; i++) {
                        var id = ids[i];
                        // This merges new entries on top of old ones.
                        switch (type) {
                        case 'term':
                        case 'grid':
                        case 'degen':
                            var current = source._geocoder.get(type, id) || [];
                            current.push.apply(current, data[id]);
                            source._geocoder.set(type, id, current);
                            break;
                        case 'phrase':
                            source._geocoder.set(type, id, data[id]);
                            break;
                        }
                    }
                    callback();
                });
            }, data, type);
        }
    }
};

function assignParts(docs) {

    for (var i = 0; i < docs.length; i++) {
        var doc = docs[i],
            phrases = [],
            termsets = [],
            termsmaps = [],
            texts = doc.text.split(',');

        for (var x = 0; x < texts.length; x++) {
            if (!termops.tokenize(texts[x]).length) continue;
            phrases.push(termops.phrase(texts[x]));
            termsets.push(termops.terms(texts[x]));
            termsmaps.push(termops.termsMap(texts[x]));
        }

        doc.phrases = phrases;
        doc.termsets = termsets;
        doc.termsmaps = termsmaps;
    }

    return docs;
}

function generateFrequency(docs) {
    var freq = {};

    // Uses freq[0] as a convention for storing total # of docs.
    // @TODO determine whether 0 can really ever be a relevant term
    // when using fnv1a.
    freq[0] = [0];
    for (var i = 0; i < docs.length; i++) {
        var termsets = docs[i].termsets;
        for (var j = 0; j < termsets.length; j++) {
            var terms = termsets[j];
            for (var k = 0; k < terms.length; k++) {
                var id = terms[k];
                freq[id] = freq[id] || [0];
                freq[id][0]++;
                freq[0][0]++;
            }
        }
    }

    return freq;
}
<commit_msg>Optimize indexing process.<commit_after>var termops = require('./util/termops'),
    ops = require('./util/ops'),
    _ = require('underscore'),
    queue = require('queue-async'),
    DEBUG = process.env.DEBUG;

// # Store
// @param {Object} source - a Carmen source
// @param {Array} docs - an array of documents
// @param {Function} callback
module.exports = function index(source, docs, callback) {

    // First pass over docs.
    // - Creates termsets (one or more arrays of termids) from document text.
    // - Tallies frequency of termids against current frequencies compiling a
    //   final in-memory frequency count of all terms involved with this set of
    //   documents to be indexed.
    // - Stores new frequencies.

    docs = assignParts(docs);
    var freq = generateFrequency(docs);

    // Ensures all shards are loaded.
    var ids = Object.keys(freq).map(function(v) { return parseInt(v, 10); });
    source._geocoder.getall(source.getCarmen.bind(source), 'freq', ids, function(err) {
        if (err) return callback(err);
        for (var i = 0; i < ids.length; i++) {
            var id = ids[i];
            freq[id][0] = (source._geocoder.get('freq', id) || [0])[0] + freq[id][0];
            source._geocoder.set('freq', id, freq[id]);
        }
        indexDocs(freq[0], freq, callback);
    });

    // Second pass over docs.
    // - Create term => docid index. Uses calculated frequencies to index only
    //   significant terms for each document.
    // - Create id => grid zxy index.
    function indexDocs(approxdocs, freq, callback) {
        var patch = { grid: {}, term: {}, phrase: {}, degen: {} };
        var degenerated = {};

        docs.forEach(loadDoc);

        function loadDoc(doc) {
            doc.id = parseInt(doc.id,10);
            doc.zxy = doc.zxy ? doc.zxy.map(function(zxy) {
                return ops.zxy(doc.id, zxy);
            }) : [];

            var phrases = doc.phrases;
            var termsets = doc.termsets;
            var termsmaps = doc.termsmaps;

            phrases.forEach(function(id, x) {
                patch.phrase[id] = patch.phrase[id] || termsets[x];
                patch.grid[id] = patch.grid[id] || [];
                patch.grid[id].push.apply(patch.grid[id], doc.zxy);
            });

            termsets.forEach(loadTerm);

            function loadTerm(terms, x) {
                var id;
                var termsmap = termsmaps[x];
                var name = phrases[x];
                var weights = [];
                var total = 0;

                for (var i = 0; i < terms.length; i++) {
                    id = terms[i];
                    var weight = Math.log(1 + freq[0][0]/freq[id][0]);
                    weights.push([id, weight]);
                    total += weight;

                    // Degenerate terms are indexed for all terms
                    // (not just significant ones).
                    if (degenerated[id]) continue;
                    degenerated[id] = true;
                    var degens = termops.degens(termsmap[id]);
                    var keys = Object.keys(degens);
                    for (var j = 0; j < keys.length; j++) {
                        var d = keys[j];
                        patch.degen[d] = patch.degen[d] || [];
                        patch.degen[d].push(degens[d]);
                    }
                }

                // Limit indexing to the *most* significant terms for a
                // document. Currently uses rough heuristic (floor+sqrt) to
                // determine how many of the top words to grab.
                weights.sort(function(a,b) {
                    return a[1] > b[1] ? -1 : a[1] < b[1] ? 1 : 0;
                });
                var sigterms = [];
                var limit = Math.floor(Math.sqrt(weights.length));
                for (i = 0; i < limit; i++) sigterms.push(weights[i][0]);

                // Debug significant term selection.
                if (DEBUG) {
                    var debug = termsmap;
                    var oldtext = terms.map(function(id) { return debug[id]; }).join(' ');
                    var sigtext = sigterms.map(function(id) { return debug[id]; }).join(' ');
                    if (oldtext !== sigtext)  console.log('%s => %s', oldtext, sigtext);
                }

                for (i = 0; i < sigterms.length; i++) {
                    id = sigterms[i];
                    patch.term[id] = patch.term[id] || [];
                    patch.term[id].push(name);
                }
            }
        }

        var q = queue(100);
        _(patch).each(setParts);
        _(docs).each(putDocumentFeature);
        q.awaitAll(callback);

        function putDocumentFeature(doc) {
            q.defer(function(doc, callback) {
                source.putFeature(doc.id, doc.doc, callback);
            }, doc);
        }

        function setParts(data, type) {
            q.defer(function(data, type, callback) {
                var ids = Object.keys(data);
                source._geocoder.getall(source.getCarmen.bind(source), type, ids, function(err) {
                    if (err) return callback(err);
                    for (var i = 0; i < ids.length; i++) {
                        var id = ids[i];
                        // This merges new entries on top of old ones.
                        switch (type) {
                        case 'term':
                        case 'grid':
                        case 'degen':
                            var current = source._geocoder.get(type, id) || [];
                            current.push.apply(current, data[id]);
                            source._geocoder.set(type, id, current);
                            break;
                        case 'phrase':
                            source._geocoder.set(type, id, data[id]);
                            break;
                        }
                    }
                    callback();
                });
            }, data, type);
        }
    }
};

function assignParts(docs) {

    for (var i = 0; i < docs.length; i++) {
        var doc = docs[i],
            phrases = [],
            termsets = [],
            termsmaps = [],
            texts = doc.text.split(',');

        for (var x = 0; x < texts.length; x++) {
            if (!termops.tokenize(texts[x]).length) continue;
            phrases.push(termops.phrase(texts[x]));
            termsets.push(termops.terms(texts[x]));
            termsmaps.push(termops.termsMap(texts[x]));
        }

        doc.phrases = phrases;
        doc.termsets = termsets;
        doc.termsmaps = termsmaps;
    }

    return docs;
}

function generateFrequency(docs) {
    var freq = {};

    // Uses freq[0] as a convention for storing total # of docs.
    // @TODO determine whether 0 can really ever be a relevant term
    // when using fnv1a.
    freq[0] = [0];
    for (var i = 0; i < docs.length; i++) {
        var termsets = docs[i].termsets;
        for (var j = 0; j < termsets.length; j++) {
            var terms = termsets[j];
            for (var k = 0; k < terms.length; k++) {
                var id = terms[k];
                freq[id] = freq[id] || [0];
                freq[id][0]++;
                freq[0][0]++;
            }
        }
    }

    return freq;
}
<|endoftext|>


<commit_before>'use strict'
const url = require('url')
const gitHosts = require('./git-host-info.js')
const GitHost = module.exports = require('./git-host.js')
const LRU = require('lru-cache')
const cache = new LRU({ max: 1000 })

const protocolToRepresentationMap = {
  'git+ssh:': 'sshurl',
  'git+https:': 'https',
  'ssh:': 'sshurl',
  'git:': 'git',
}

function protocolToRepresentation (protocol) {
  return protocolToRepresentationMap[protocol] || protocol.slice(0, -1)
}

const authProtocols = {
  'git:': true,
  'https:': true,
  'git+https:': true,
  'http:': true,
  'git+http:': true,
}

const knownProtocols = Object.keys(gitHosts.byShortcut)
  .concat(['http:', 'https:', 'git:', 'git+ssh:', 'git+https:', 'ssh:'])

module.exports.fromUrl = function (giturl, opts) {
  if (typeof giturl !== 'string') {
    return
  }

  const key = giturl + JSON.stringify(opts || {})

  if (!cache.has(key)) {
    cache.set(key, fromUrl(giturl, opts))
  }

  return cache.get(key)
}

function fromUrl (giturl, opts) {
  if (!giturl) {
    return
  }

  const correctedUrl = isGitHubShorthand(giturl) ? 'github:' + giturl : correctProtocol(giturl)
  const parsed = parseGitUrl(correctedUrl)
  if (!parsed) {
    return parsed
  }

  const gitHostShortcut = gitHosts.byShortcut[parsed.protocol]
  const gitHostDomain =
    gitHosts.byDomain[parsed.hostname.startsWith('www.') ?
      parsed.hostname.slice(4) :
      parsed.hostname]
  const gitHostName = gitHostShortcut || gitHostDomain
  if (!gitHostName) {
    return
  }

  const gitHostInfo = gitHosts[gitHostShortcut || gitHostDomain]
  let auth = null
  if (authProtocols[parsed.protocol] && (parsed.username || parsed.password)) {
    auth = `${parsed.username}${parsed.password ? ':' + parsed.password : ''}`
  }

  let committish = null
  let user = null
  let project = null
  let defaultRepresentation = null

  try {
    if (gitHostShortcut) {
      let pathname = parsed.pathname.startsWith('/') ? parsed.pathname.slice(1) : parsed.pathname
      const firstAt = pathname.indexOf('@')
      // we ignore auth for shortcuts, so just trim it out
      if (firstAt > -1) {
        pathname = pathname.slice(firstAt + 1)
      }

      const lastSlash = pathname.lastIndexOf('/')
      if (lastSlash > -1) {
        user = decodeURIComponent(pathname.slice(0, lastSlash))
        // we want nulls only, never empty strings
        if (!user) {
          user = null
        }
        project = decodeURIComponent(pathname.slice(lastSlash + 1))
      } else {
        project = decodeURIComponent(pathname)
      }

      if (project.endsWith('.git')) {
        project = project.slice(0, -4)
      }

      if (parsed.hash) {
        committish = decodeURIComponent(parsed.hash.slice(1))
      }

      defaultRepresentation = 'shortcut'
    } else {
      if (!gitHostInfo.protocols.includes(parsed.protocol)) {
        return
      }

      const segments = gitHostInfo.extract(parsed)
      if (!segments) {
        return
      }

      user = segments.user && decodeURIComponent(segments.user)
      project = decodeURIComponent(segments.project)
      committish = decodeURIComponent(segments.committish)
      defaultRepresentation = protocolToRepresentation(parsed.protocol)
    }
  } catch (err) {
    /* istanbul ignore else */
    if (err instanceof URIError) {
      return
    } else {
      throw err
    }
  }

  return new GitHost(gitHostName, user, auth, project, committish, defaultRepresentation, opts)
}

// accepts input like git:github.com:user/repo and inserts the // after the first :
const correctProtocol = (arg) => {
  const firstColon = arg.indexOf(':')
  const proto = arg.slice(0, firstColon + 1)
  if (knownProtocols.includes(proto)) {
    return arg
  }

  const firstAt = arg.indexOf('@')
  if (firstAt > -1) {
    if (firstAt > firstColon) {
      return `git+ssh://${arg}`
    } else {
      return arg
    }
  }

  const doubleSlash = arg.indexOf('//')
  if (doubleSlash === firstColon + 1) {
    return arg
  }

  return arg.slice(0, firstColon + 1) + '//' + arg.slice(firstColon + 1)
}

// look for github shorthand inputs, such as npm/cli
const isGitHubShorthand = (arg) => {
  // it cannot contain whitespace before the first #
  // it cannot start with a / because that's probably an absolute file path
  // but it must include a slash since repos are username/repository
  // it cannot start with a . because that's probably a relative file path
  // it cannot start with an @ because that's a scoped package if it passes the other tests
  // it cannot contain a : before a # because that tells us that there's a protocol
  // a second / may not exist before a #
  const firstHash = arg.indexOf('#')
  const firstSlash = arg.indexOf('/')
  const secondSlash = arg.indexOf('/', firstSlash + 1)
  const firstColon = arg.indexOf(':')
  const firstSpace = /\s/.exec(arg)
  const firstAt = arg.indexOf('@')

  const spaceOnlyAfterHash = !firstSpace || (firstHash > -1 && firstSpace.index > firstHash)
  const atOnlyAfterHash = firstAt === -1 || (firstHash > -1 && firstAt > firstHash)
  const colonOnlyAfterHash = firstColon === -1 || (firstHash > -1 && firstColon > firstHash)
  const secondSlashOnlyAfterHash = secondSlash === -1 || (firstHash > -1 && secondSlash > firstHash)
  const hasSlash = firstSlash > 0
  // if a # is found, what we really want to know is that the character
  // immediately before # is not a /
  const doesNotEndWithSlash = firstHash > -1 ? arg[firstHash - 1] !== '/' : !arg.endsWith('/')
  const doesNotStartWithDot = !arg.startsWith('.')

  return spaceOnlyAfterHash && hasSlash && doesNotEndWithSlash &&
    doesNotStartWithDot && atOnlyAfterHash && colonOnlyAfterHash &&
    secondSlashOnlyAfterHash
}

// attempt to correct an scp style url so that it will parse with `new URL()`
const correctUrl = (giturl) => {
  const firstAt = giturl.indexOf('@')
  const lastHash = giturl.lastIndexOf('#')
  let firstColon = giturl.indexOf(':')
  let lastColon = giturl.lastIndexOf(':', lastHash > -1 ? lastHash : Infinity)

  let corrected
  if (lastColon > firstAt) {
    // the last : comes after the first @ (or there is no @)
    // like it would in:
    // proto://hostname.com:user/repo
    // username@hostname.com:user/repo
    // :password@hostname.com:user/repo
    // username:password@hostname.com:user/repo
    // proto://username@hostname.com:user/repo
    // proto://:password@hostname.com:user/repo
    // proto://username:password@hostname.com:user/repo
    // then we replace the last : with a / to create a valid path
    corrected = giturl.slice(0, lastColon) + '/' + giturl.slice(lastColon + 1)
    // // and we find our new : positions
    firstColon = corrected.indexOf(':')
    lastColon = corrected.lastIndexOf(':')
  }

  if (firstColon === -1 && giturl.indexOf('//') === -1) {
    // we have no : at all
    // as it would be in:
    // username@hostname.com/user/repo
    // then we prepend a protocol
    corrected = `git+ssh://${corrected}`
  }

  return corrected
}

// try to parse the url as its given to us, if that throws
// then we try to clean the url and parse that result instead
// THIS FUNCTION SHOULD NEVER THROW
const parseGitUrl = (giturl) => {
  let result
  try {
    result = new url.URL(giturl)
  } catch (err) {}

  if (result) {
    return result
  }

  const correctedUrl = correctUrl(giturl)
  try {
    result = new url.URL(correctedUrl)
  } catch (err) {}

  return result
}
<commit_msg>chore: fix linting<commit_after>'use strict'
const url = require('url')
const gitHosts = require('./git-host-info.js')
const GitHost = module.exports = require('./git-host.js')
const LRU = require('lru-cache')
const cache = new LRU({ max: 1000 })

const protocolToRepresentationMap = {
  'git+ssh:': 'sshurl',
  'git+https:': 'https',
  'ssh:': 'sshurl',
  'git:': 'git',
}

function protocolToRepresentation (protocol) {
  return protocolToRepresentationMap[protocol] || protocol.slice(0, -1)
}

const authProtocols = {
  'git:': true,
  'https:': true,
  'git+https:': true,
  'http:': true,
  'git+http:': true,
}

const knownProtocols = Object.keys(gitHosts.byShortcut)
  .concat(['http:', 'https:', 'git:', 'git+ssh:', 'git+https:', 'ssh:'])

module.exports.fromUrl = function (giturl, opts) {
  if (typeof giturl !== 'string') {
    return
  }

  const key = giturl + JSON.stringify(opts || {})

  if (!cache.has(key)) {
    cache.set(key, fromUrl(giturl, opts))
  }

  return cache.get(key)
}

function fromUrl (giturl, opts) {
  if (!giturl) {
    return
  }

  const correctedUrl = isGitHubShorthand(giturl) ? 'github:' + giturl : correctProtocol(giturl)
  const parsed = parseGitUrl(correctedUrl)
  if (!parsed) {
    return parsed
  }

  const gitHostShortcut = gitHosts.byShortcut[parsed.protocol]
  const gitHostDomain =
    gitHosts.byDomain[parsed.hostname.startsWith('www.') ?
      parsed.hostname.slice(4) :
      parsed.hostname]
  const gitHostName = gitHostShortcut || gitHostDomain
  if (!gitHostName) {
    return
  }

  const gitHostInfo = gitHosts[gitHostShortcut || gitHostDomain]
  let auth = null
  if (authProtocols[parsed.protocol] && (parsed.username || parsed.password)) {
    auth = `${parsed.username}${parsed.password ? ':' + parsed.password : ''}`
  }

  let committish = null
  let user = null
  let project = null
  let defaultRepresentation = null

  try {
    if (gitHostShortcut) {
      let pathname = parsed.pathname.startsWith('/') ? parsed.pathname.slice(1) : parsed.pathname
      const firstAt = pathname.indexOf('@')
      // we ignore auth for shortcuts, so just trim it out
      if (firstAt > -1) {
        pathname = pathname.slice(firstAt + 1)
      }

      const lastSlash = pathname.lastIndexOf('/')
      if (lastSlash > -1) {
        user = decodeURIComponent(pathname.slice(0, lastSlash))
        // we want nulls only, never empty strings
        if (!user) {
          user = null
        }
        project = decodeURIComponent(pathname.slice(lastSlash + 1))
      } else {
        project = decodeURIComponent(pathname)
      }

      if (project.endsWith('.git')) {
        project = project.slice(0, -4)
      }

      if (parsed.hash) {
        committish = decodeURIComponent(parsed.hash.slice(1))
      }

      defaultRepresentation = 'shortcut'
    } else {
      if (!gitHostInfo.protocols.includes(parsed.protocol)) {
        return
      }

      const segments = gitHostInfo.extract(parsed)
      if (!segments) {
        return
      }

      user = segments.user && decodeURIComponent(segments.user)
      project = decodeURIComponent(segments.project)
      committish = decodeURIComponent(segments.committish)
      defaultRepresentation = protocolToRepresentation(parsed.protocol)
    }
  } catch (err) {
    /* istanbul ignore else */
    if (err instanceof URIError) {
      return
    } else {
      throw err
    }
  }

  return new GitHost(gitHostName, user, auth, project, committish, defaultRepresentation, opts)
}

// accepts input like git:github.com:user/repo and inserts the // after the first :
const correctProtocol = (arg) => {
  const firstColon = arg.indexOf(':')
  const proto = arg.slice(0, firstColon + 1)
  if (knownProtocols.includes(proto)) {
    return arg
  }

  const firstAt = arg.indexOf('@')
  if (firstAt > -1) {
    if (firstAt > firstColon) {
      return `git+ssh://${arg}`
    } else {
      return arg
    }
  }

  const doubleSlash = arg.indexOf('//')
  if (doubleSlash === firstColon + 1) {
    return arg
  }

  return arg.slice(0, firstColon + 1) + '//' + arg.slice(firstColon + 1)
}

// look for github shorthand inputs, such as npm/cli
const isGitHubShorthand = (arg) => {
  // it cannot contain whitespace before the first #
  // it cannot start with a / because that's probably an absolute file path
  // but it must include a slash since repos are username/repository
  // it cannot start with a . because that's probably a relative file path
  // it cannot start with an @ because that's a scoped package if it passes the other tests
  // it cannot contain a : before a # because that tells us that there's a protocol
  // a second / may not exist before a #
  const firstHash = arg.indexOf('#')
  const firstSlash = arg.indexOf('/')
  const secondSlash = arg.indexOf('/', firstSlash + 1)
  const firstColon = arg.indexOf(':')
  const firstSpace = /\s/.exec(arg)
  const firstAt = arg.indexOf('@')

  const spaceOnlyAfterHash = !firstSpace || (firstHash > -1 && firstSpace.index > firstHash)
  const atOnlyAfterHash = firstAt === -1 || (firstHash > -1 && firstAt > firstHash)
  const colonOnlyAfterHash = firstColon === -1 || (firstHash > -1 && firstColon > firstHash)
  const secondSlashOnlyAfterHash = secondSlash === -1 || (firstHash > -1 && secondSlash > firstHash)
  const hasSlash = firstSlash > 0
  // if a # is found, what we really want to know is that the character
  // immediately before # is not a /
  const doesNotEndWithSlash = firstHash > -1 ? arg[firstHash - 1] !== '/' : !arg.endsWith('/')
  const doesNotStartWithDot = !arg.startsWith('.')

  return spaceOnlyAfterHash && hasSlash && doesNotEndWithSlash &&
    doesNotStartWithDot && atOnlyAfterHash && colonOnlyAfterHash &&
    secondSlashOnlyAfterHash
}

// attempt to correct an scp style url so that it will parse with `new URL()`
const correctUrl = (giturl) => {
  const firstAt = giturl.indexOf('@')
  const lastHash = giturl.lastIndexOf('#')
  let firstColon = giturl.indexOf(':')
  let lastColon = giturl.lastIndexOf(':', lastHash > -1 ? lastHash : Infinity)

  let corrected
  if (lastColon > firstAt) {
    // the last : comes after the first @ (or there is no @)
    // like it would in:
    // proto://hostname.com:user/repo
    // username@hostname.com:user/repo
    // :password@hostname.com:user/repo
    // username:password@hostname.com:user/repo
    // proto://username@hostname.com:user/repo
    // proto://:password@hostname.com:user/repo
    // proto://username:password@hostname.com:user/repo
    // then we replace the last : with a / to create a valid path
    corrected = giturl.slice(0, lastColon) + '/' + giturl.slice(lastColon + 1)
    // // and we find our new : positions
    firstColon = corrected.indexOf(':')
    lastColon = corrected.lastIndexOf(':')
  }

  if (firstColon === -1 && giturl.indexOf('//') === -1) {
    // we have no : at all
    // as it would be in:
    // username@hostname.com/user/repo
    // then we prepend a protocol
    corrected = `git+ssh://${corrected}`
  }

  return corrected
}

// try to parse the url as its given to us, if that throws
// then we try to clean the url and parse that result instead
// THIS FUNCTION SHOULD NEVER THROW
const parseGitUrl = (giturl) => {
  let result
  try {
    result = new url.URL(giturl)
  } catch {
    // this fn should never throw
  }

  if (result) {
    return result
  }

  const correctedUrl = correctUrl(giturl)
  try {
    result = new url.URL(correctedUrl)
  } catch {
    // this fn should never throw
  }

  return result
}
<|endoftext|>


<commit_before>var glob = require('glob')
var fs = require('fs')
var path = require('path')

// Make the plugin available
module.exports = plugin

/**
 * Metalsmith plugin to take a directory of json files
 * and make them available in the global metadata
 *
 * @param {Object} opts
 * @return {Function}
*/
function plugin (opts) {
  opts = opts || {}
  var dir = opts.directory

  return function (files, metalsmith, done) {
    var metadata = metalsmith.metadata()

    glob(dir, function (err, files) {
      if (err) {
        throw err
      }

      files.forEach(function (file) {
        fs.readFile(file, 'utf8', function (err, data) {
          if (err) {
            throw err
          }

          var fileName = path.basename(file)
          var theKey = fileName.replace(/\.[^/.]+$/, '')
          var theContents = JSON.parse(data)

          metadata[theKey] = theContents
        })
      })
    })

    done()
  }
}
<commit_msg>adjust throw errors<commit_after>var glob = require('glob')
var fs = require('fs')
var path = require('path')

// Make the plugin available
module.exports = plugin

/**
 * Metalsmith plugin to take a directory of json files
 * and make them available in the global metadata
 *
 * @param {Object} opts
 * @return {Function}
*/
function plugin (opts) {
  opts = opts || {}
  var dir = opts.directory

  return function (files, metalsmith, done) {
    var metadata = metalsmith.metadata()

    glob(dir, function (err, files) {
      if (err) {
        throw new Error(err)
      }

      files.forEach(function (file) {
        fs.readFile(file, 'utf8', function (err, data) {
          if (err) {
            throw new Error(err)
          }

          var fileName = path.basename(file)
          var theKey = fileName.replace(/\.[^/.]+$/, '')
          var theContents = JSON.parse(data)

          metadata[theKey] = theContents
        })
      })
    })

    done()
  }
}
<|endoftext|>


<commit_before>var Stack = require('./stack');

exports.stack = function(layers) {
    return new Stack(layers);
};<commit_msg>Pass stack layers as arguments<commit_after>var Stack = require('./stack');

exports.stack = function() {
    var layers = [].slice.call(arguments);
    return new Stack(layers);
};<|endoftext|>


<commit_before>var child = require('child_process');
var dependencies = require('./dependencies');
var deepExtend = require('deep-extend');
var css = require('./css');
var fs = require('fs');
var async = require('async');
var phantomjsPath = 'phantomjs';

var Pdf = module.exports = function(manifest, data, callback) {

	var self = this;

	this.manifest = deepExtend({}, require('./defaults'), manifest);
	if(this.manifest.phantomjsPath)
		phantomjsPath = this.manifest.phantomjsPath;
	this.data = data || {};
  this.callback = callback;
  this.processTimeout = manifest.timeout || 180000; // 3 minute default timeout

	dependencies.isPhantomInstalled(function(installed){
		if(!installed) {
			return self.callback({error: 'PhantomJS not installed'});
		}
		css.process(self.manifest, function(err){
      if(err) {
        self.callback(err);
      } else {
			 self.run();
      }
		});
	});

	return this;
};

Pdf.prototype.run = function() {
	var self = this;
  var rand = Date.now()+''+Math.random();

  var manifestFilename = self.manifest.tmpDir+'/phantom-manifest.'+rand+'.json';
  var dataFilename =  self.manifest.tmpDir+'/phantom-data.'+rand+'.json';

  var phantomError = null;

  async.parallel([
      function(callback) {
        fs.writeFile(manifestFilename, JSON.stringify(self.manifest), function(err) {callback(err)});
      },
      function(callback) {
        fs.writeFile(dataFilename, JSON.stringify(self.data), function(err) {callback(err)});
      }
    ],
    function(err){

      var stdin = [phantomjsPath];
      stdin.push(__dirname+'/../phantom/index.js');
      stdin.push(manifestFilename);
      stdin.push(dataFilename);

      var ps = child.exec(stdin.join(' '));

      // Kill process if it is dangling there too long
      var killTimeout = setTimeout(function(){
        ps.kill('SIGTERM');
      }, self.processTimeout);

      ps.on('error',function(err){
        phantomError = err;
      });

      ps.on('uncaughtException', function(err) {
        phantomError = err;
      });

      ps.on('exit', function(code){
        if(code === null) {
          code = 2;
        }
        clearTimeout(killTimeout);
        // JUST INCASE delete files
        if (code !== 0) {
          return self.callback({
            code: code,
            error: phantomError
          });
        }

        self.callback(null, self.manifest.output);
      });

      ps.stdout.on('data', function(std){
        console.log(std);
      });

      ps.stderr.on('data', function(std){
        console.log(std);
      });

  });
}
<commit_msg>Fix: forgot to add phantom path to installed check<commit_after>var child = require('child_process');
var dependencies = require('./dependencies');
var deepExtend = require('deep-extend');
var css = require('./css');
var fs = require('fs');
var async = require('async');
var phantomjsPath = 'phantomjs';

var Pdf = module.exports = function(manifest, data, callback) {

	var self = this;

	this.manifest = deepExtend({}, require('./defaults'), manifest);
	if(this.manifest.phantomjsPath)
		phantomjsPath = this.manifest.phantomjsPath;
	this.data = data || {};
  this.callback = callback;
  this.processTimeout = manifest.timeout || 180000; // 3 minute default timeout

	dependencies.isPhantomInstalled(function(phantomjsPath, installed){
		if(!installed) {
			return self.callback({error: 'PhantomJS not installed'});
		}
		css.process(self.manifest, function(err){
      if(err) {
        self.callback(err);
      } else {
			 self.run();
      }
		});
	});

	return this;
};

Pdf.prototype.run = function() {
	var self = this;
  var rand = Date.now()+''+Math.random();

  var manifestFilename = self.manifest.tmpDir+'/phantom-manifest.'+rand+'.json';
  var dataFilename =  self.manifest.tmpDir+'/phantom-data.'+rand+'.json';

  var phantomError = null;

  async.parallel([
      function(callback) {
        fs.writeFile(manifestFilename, JSON.stringify(self.manifest), function(err) {callback(err)});
      },
      function(callback) {
        fs.writeFile(dataFilename, JSON.stringify(self.data), function(err) {callback(err)});
      }
    ],
    function(err){

      var stdin = [phantomjsPath];
      stdin.push(__dirname+'/../phantom/index.js');
      stdin.push(manifestFilename);
      stdin.push(dataFilename);

      var ps = child.exec(stdin.join(' '));

      // Kill process if it is dangling there too long
      var killTimeout = setTimeout(function(){
        ps.kill('SIGTERM');
      }, self.processTimeout);

      ps.on('error',function(err){
        phantomError = err;
      });

      ps.on('uncaughtException', function(err) {
        phantomError = err;
      });

      ps.on('exit', function(code){
        if(code === null) {
          code = 2;
        }
        clearTimeout(killTimeout);
        // JUST INCASE delete files
        if (code !== 0) {
          return self.callback({
            code: code,
            error: phantomError
          });
        }

        self.callback(null, self.manifest.output);
      });

      ps.stdout.on('data', function(std){
        console.log(std);
      });

      ps.stderr.on('data', function(std){
        console.log(std);
      });

  });
}
<|endoftext|>


<commit_before>var assign = require('./util/assign')

var fse = {}
var gfs = require('graceful-fs')

// attach fs methods to fse
Object.keys(gfs).forEach(function (key) {
  fse[key] = gfs[key]
})

var fs = fse

assign(fs, require('./copy'))
assign(fs, require('./copy-sync'))
assign(fs, require('./mkdirs'))
assign(fs, require('./remove'))
assign(fs, require('./json'))
assign(fs, require('./move'))
assign(fs, require('./empty'))
assign(fs, require('./ensure'))
assign(fs, require('./output'))

module.exports = fs

// maintain backwards compatibility for awhile
var jsonfile = {}
Object.defineProperty(jsonfile, 'spaces', {
  get: function () {
    return fs.spaces // found in ./json
  },
  set: function (val) {
    fs.spaces = val
  }
})

module.exports.jsonfile = jsonfile // so users of fs-extra can modify jsonFile.spaces
<commit_msg>Refactor index<commit_after>'use strict'

const assign = require('./util/assign')

const fse = {}
const gfs = require('graceful-fs')

// attach fs methods to fse
Object.keys(gfs).forEach(key => {
  fse[key] = gfs[key]
})

const fs = fse

assign(fs, require('./copy'))
assign(fs, require('./copy-sync'))
assign(fs, require('./mkdirs'))
assign(fs, require('./remove'))
assign(fs, require('./json'))
assign(fs, require('./move'))
assign(fs, require('./empty'))
assign(fs, require('./ensure'))
assign(fs, require('./output'))

module.exports = fs

// maintain backwards compatibility for awhile
const jsonfile = {}
Object.defineProperty(jsonfile, 'spaces', {
  get: () => fs.spaces, // found in ./json
  set: val => {
    fs.spaces = val
  }
})

module.exports.jsonfile = jsonfile // so users of fs-extra can modify jsonFile.spaces
<|endoftext|>


<commit_before>'use strict';

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.SchemaSymbol = undefined;

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };

exports.getComponentSchema = getComponentSchema;

exports.default = function (mainSchema) {
    if ((typeof mainSchema === 'undefined' ? 'undefined' : _typeof(mainSchema)) !== 'object') {
        throw new TypeError('Schema must be of type \'object\'');
    }

    for (var _len = arguments.length, otherSchemas = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
        otherSchemas[_key - 1] = arguments[_key];
    }

    var schema = _deepExtend2.default.apply(undefined, [{}, getSchema(mainSchema)].concat(_toConsumableArray(otherSchemas.map(getSchema))));
    if (schema.type !== 'object') {
        throw new Error('Schema must define an object type (currently: ' + schema.type + ')');
    }
    var propTypes = _defineProperty({}, SchemaSymbol, schema);
    if (schema.properties) {
        (function () {
            var validate = _ajvEx2.default.compile(schema);
            for (var prop in schema.properties) {
                if (schema.properties.hasOwnProperty(prop)) {
                    propTypes[prop] = function (props, propName, componentName) {
                        var valid = validate(props);
                        if (valid) return null;
                        var propError = validate.errors.find(function (e) {
                            return new RegExp('^.' + propName + '(.|$)').test(e.dataPath);
                        });
                        if (!propError) return null;
                        return new Error('\'' + propError.dataPath + '\' ' + propError.message + ', found ' + JSON.stringify(props[propName]) + ' instead. Check propTypes of component ' + componentName);
                    };
                }
            }
        })();
    }
    return propTypes;
};

var _deepExtend = require('deep-extend');

var _deepExtend2 = _interopRequireDefault(_deepExtend);

var _ajvEx = require('./ajvEx');

var _ajvEx2 = _interopRequireDefault(_ajvEx);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

var SchemaSymbol = exports.SchemaSymbol = Symbol.for('react-json-schema-proptypes');
function name(component) {
    return component.name || component.displayName;
}
function getSchema(schema) {
    return schema[SchemaSymbol] || schema;
}
function getComponentSchema(component) {
    if (typeof component.propTypes === 'undefined') throw new Error('Component ' + name(component) + ' has no propTypes.');
    if (typeof component.propTypes[SchemaSymbol] === 'undefined') throw new Error('Component ' + name(component) + ' has no JSON Schema propType definition.');
    return component.propTypes[SchemaSymbol];
<commit_msg>Run TS output thru babel for ES5 compat<commit_after>'use strict';

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.SchemaSymbol = undefined;

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };

exports.getComponentSchema = getComponentSchema;

exports.default = function (mainSchema) {
    if ((typeof mainSchema === 'undefined' ? 'undefined' : _typeof(mainSchema)) !== 'object') {
        throw new TypeError('Schema must be of type \'object\'');
    }

    for (var _len = arguments.length, otherSchemas = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
        otherSchemas[_key - 1] = arguments[_key];
    }

    var schema = _deepExtend2.default.apply(undefined, [{}, getSchema(mainSchema)].concat(_toConsumableArray(otherSchemas.map(getSchema))));
    if (schema.type !== 'object') {
        throw new Error('Schema must define an object type (currently: ' + schema.type + ')');
    }
    var propTypes = _defineProperty({}, SchemaSymbol, schema);
    if (schema.properties) {
        (function () {
            var validate = _ajvEx2.default.compile(schema);
            for (var prop in schema.properties) {
                if (schema.properties.hasOwnProperty(prop)) {
                    propTypes[prop] = function (props, propName, componentName) {
                        var valid = validate(props);
                        if (valid) return null;
                        var propError = validate.errors.find(function (e) {
                            return new RegExp('^.' + propName + '(.|$)').test(e.dataPath);
                        });
                        if (!propError) return null;
                        return new Error('\'' + propError.dataPath + '\' ' + propError.message + ', found ' + JSON.stringify(props[propName]) + ' instead. Check propTypes of component ' + componentName);
                    };
                }
            }
        })();
    }
    return propTypes;
};

var _deepExtend = require('deep-extend');

var _deepExtend2 = _interopRequireDefault(_deepExtend);

var _ajvEx = require('./ajvEx');

var _ajvEx2 = _interopRequireDefault(_ajvEx);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

var SchemaSymbol = exports.SchemaSymbol = Symbol.for('react-json-schema-proptypes');
function name(component) {
    return component.name || component.displayName;
}
function getSchema(schema) {
    return schema[SchemaSymbol] || schema;
}
function getComponentSchema(component) {
    if (typeof component.propTypes === 'undefined') throw new Error('Component ' + name(component) + ' has no propTypes.');
    if (typeof component.propTypes[SchemaSymbol] === 'undefined') throw new Error('Component ' + name(component) + ' has no JSON Schema propType definition.');
    return component.propTypes[SchemaSymbol];
}<|endoftext|>


<commit_before>"use strict";

var _ = require('lodash');
var path = require('path');
var Schema = require('node-verifier-schema');
var loader = require('node-verifier-schema/load');

var prepareSchema = function (options, schema) {
	var _rawSchema = schema;
	if (_.isString(schema)) {
		if (/\.(yaml|yml)$/.test(schema)) {
			schema = options.preparePath(schema);
			schema = loader(schema);
		} else {
			schema = Schema.get(schema);
		}
	} else if (_.isFunction(schema)) {
		schema = new Schema();
		_rawSchema(schema);
	}

	if (!(schema instanceof Schema)) {
		throw new Error('must be Schema instance. ' + _rawSchema + ' given');
	}

	return schema;
};

var defaultsOptions = {
	preparePath: function (filepath) {
		return path.join(process.cwd(), filepath);
	},

	objects: {
		params: {
			get: function (req, res) {
				return req.params;
			}
		},

		query: {
			get: function (req, res) {
				return req.query;
			}
		},

		headers: {
			get: function (req, res) {
				return req.headers;
			}
		},

		body: {
			get: function (req, res) {
				console.log('>>>BODY>>>', req.body);
				return req.body;
			}
		}
	}
};

var expressVerifier = function (options) {
	options = _.merge(defaultsOptions, options);

	return function (object) {
		var keys = _.keys(options.objects);
		if (!_.isPlainObject(object)) {
			var schema = prepareSchema(options, object);
			object = _.pick(schema.fields, keys);
			console.log(object);
		}

		var verifiers = [];
		_.each(keys, function (key) {
			if (object[key]) {
				var verifier = prepareSchema(options, object[key]).verifier();
				verifiers.push(_.extend({
					verify: verifier.verify.bind(verifier),
					name: key
				}, options.objects[key]));
			}
		});

		if (!verifiers.length) {
			throw new Error('invalid parameters for verify');
		}

		return function (req, res, next) {
			Schema.utils.iterate.array(verifiers, function (object, index, done) {
				var value = object.get(req, res);
				object.verify(value, function (err) {
					if (err instanceof Schema.ValidationError) {
						err.object = object.name;
					}

					done(err);
				});
			}, next);
		};
	};
};

expressVerifier.Verifier = Schema.Verifier;

module.exports = expressVerifier;
<commit_msg>small refactoring<commit_after>"use strict";

var _ = require('lodash');
var path = require('path');
var Schema = require('node-verifier-schema');
var loader = require('node-verifier-schema/load');

var defaultsOptions = {
	cwd: process.cwd(),

	preparePath: function (filepath) {
		return path.join(this.cwd, filepath);
	},

	prepareSchema: function (schema, options) {
		var _rawSchema = schema;
		if (_.isString(schema)) {
			if (/\.(yaml|yml)$/.test(schema)) {
				schema = options.preparePath(schema);
				schema = loader(schema);
			} else {
				schema = Schema.get(schema);
			}
		} else if (_.isFunction(schema)) {
			schema = new Schema();
			_rawSchema(schema);
		}

		if (!(schema instanceof Schema)) {
			throw new Error('must be Schema instance. ' + _rawSchema + ' given');
		}

		return schema;
	}
};

var expressVerifier = function (globalOptions) {
	var verifier = function (object, options) {
		options = _.extend({}, defaultsOptions, globalOptions, options);

		var keys = _.keys(verifier.objects);

		if (!_.isPlainObject(object)) {
			object = options.prepareSchema(object, options).fields;
		}

		var verifiers = [];
		_.each(keys, function (key) {
			if (_.has(object, key)) {
				verifiers.push({
					name: key,
					verify: verifier.objects[key](object[key], options)
				});
			}
		});

		if (!verifiers.length) {
			throw new Error('invalid parameters for verify');
		}

		var middleware = function (req, res, next) {
			Schema.utils.iterate.array(middleware.verifiers, function (obj, index, done) {
				obj.verify(req, res, function (err) {
					if (err instanceof Schema.ValidationError) {
						err.object = object.name;
					}

					done(err);
				});
			}, next);
		};

		middleware.verifiers = verifiers;

		return middleware;
	};

	verifier.objects = {
		params: function (schema, options) {
			schema = options.prepareSchema(schema, options, 'params');
			var verifier = schema.verifier(options);

			var verf = function (req, res, next) {
				verifier.verify(req.params, next);
			};

			verf.schema = schema;
			return verf;
		},
		query: function (schema, options) {
			schema = options.prepareSchema(schema, options, 'query');
			var verifier = schema.verifier(options);

			var verf = function (req, res, next) {
				verifier.verify(req.query, next);
			};

			verf.schema = schema;
			return verf;
		},
		body: function (schema, options) {
			schema = options.prepareSchema(schema, options, 'body');
			var verifier = schema.verifier(options);

			var verf = function (req, res, next) {
				verifier.verify(req.body, next);
			};

			verf.schema = schema;
			return verf;
		}
	};

	return verifier;
};

expressVerifier.Verifier = Schema.Verifier;

module.exports = expressVerifier;
<|endoftext|>


<commit_before>var _ = require('lodash');
var request = require('request');

var BatchManager = function (opts) {

  // http xhr request batch api handler for outbound rest/rpc like calls
  // (c) 2013 davehigginbotham@gmail.com

  var options = opts || null;

  // external api definitions -------------------------------------------------

  this.prefix = 'batchman';

  this.middleware = [];

  this.key = 'batchman';

  this.end = null;

  if (options) {
    _.merge(this, options);
  };

  var self = this;

  var processRequests = function (input, fn) {

    var batches = input || null;

    var callback = ((typeof fn != 'undefined') && (typeof fn == 'function')) ? fn : null;

    var respArray = [];

    var i = 0;

    var ln = batches.length;

    while (ln--) {

      if (batches[i].hasOwnProperty('url')) {

        self.request(batches[i], function (err, body) {

          respArray.push(body);

          if (respArray.length === batches.length) {
            return fn(null, respArray);
          };

        });

      }

      i++;

    };

  };

  this.batchRequests = function (req, res, next) {

    if (req.body) {

      processRequests(req.body, function (err, resp) {

        req[self.key] = resp;

        return next();

      });

    };

  };

  if (!this.end) {

    this.end = function (req, res) {

      res.send(req[self.key]);

    };

  };

  return this;

};

BatchManager.prototype.request = function (opts, fn) {

  var defaults = {
    url: null,
    qs: null,
    method: 'get',
    form: {}
  };

  var options = opts || null;

  if (options) {
    _.merge(defaults, options);
  } else {
    return fn('You must provide options for request to work properly.', null);
  };

  if (defaults.url) {

    request(defaults, function (err, resp, body) {

      if (err) {
        return fn(err, null);
      };

      return fn(null, JSON.parse(body));

    });

  } else {
    return fn('You must provide a url string', null);
  };

};

BatchManager.prototype.mount = function (app, fn) {

  var app = ((typeof app != 'undefined') && (typeof fn != 'undefined')) ? app : null;

  if (!app) {
    return new Error('You must provide access to express/connect for this to mount routes correctly.');
  };

  // give routes here

  var self = this;

  var prefix = '/' + self.prefix;

  app.post(prefix, self.middleware, self.batchRequests, self.end);

  return fn('Successfully mounted batchman to `' + prefix + '`');

};

module.exports = BatchManager;<commit_msg>codefix<commit_after>var _ = require('lodash');
var request = require('request');

var BatchManager = function (opts) {

  // http xhr request batch api handler for outbound rest/rpc like calls
  // (c) 2013 davehigginbotham@gmail.com

  var options = opts || null;

  this.prefix = 'batchman';

  this.middleware = [];

  this.key = 'batchman';

  this.end = null;

  if (options) {
    _.merge(this, options);
  };

  var self = this;

  var processRequests = function (reqs, fn) {

    var reqs = reqs || null;

    var respArray = [];

    var i = 0;

    var ln = reqs.length;

    while (ln--) {

      if (reqs[i].hasOwnProperty('url')) {

        self.request(reqs[i], function (err, body) {

          respArray.push(body);

          if (respArray.length === reqs.length) {
            return fn(null, respArray);
          };

        });

      }

      i++;

    };

  };

  this.batchRequests = function (req, res, next) {

    if (req.body) {

      processRequests(req.body, function (err, resp) {

        req[self.key] = resp;

        return next();

      });

    };

  };

  if (!this.end) {

    this.end = function (req, res) {

      res.send(req[self.key]);

    };

  };

  return this;

};

BatchManager.prototype.request = function (opts, fn) {

  var defaults = {
    url: null,
    qs: null,
    method: 'get',
    form: {}
  };

  var options = opts || null;

  if (options) {
    _.merge(defaults, options);
  } else {
    return fn('You must provide options for request to work properly.', null);
  };

  if (defaults.url) {

    request(defaults, function (err, resp, body) {

      if (err) {
        return fn(err, null);
      };

      return fn(null, JSON.parse(body));

    });

  } else {
    return fn('You must provide a url string', null);
  };

};

BatchManager.prototype.mount = function (app, fn) {

  var app = (typeof app != 'undefined') ? app : null;

  if (!app) {
    return new Error('You must provide access to express/connect for this to mount routes correctly.');
  };

  // give routes here

  var self = this;

  var prefix = '/' + self.prefix;

  app.post(prefix, self.middleware, self.batchRequests, self.end);

  var out = 'Successfully mounted batchman to `' + prefix + '`';

  return (typeof fn != 'undefined') ? fn(out) : true;

};

module.exports = BatchManager;<|endoftext|>