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

var dataFiles= require('./dataFiles');

var defaultDataPaths= [
    '/usr/share/GLOBE-elevation',
    '/usr/local/share/GLOBE-elevation',
    'GLOBE-elevation',
    'elevation',
];

// resolution in 1 / degree
var resolution= 120;

// offset to middle of one raster pixel
var offset= 1 / (2 * resolution);

// limit of single points for bounding boxes
var pointLimit= 1000000;

/**
 * End of constants
 */

// First initialization with best guessed values
dataFiles.init({

    // find first existing path (if any)
    dataPath: defaultDataPaths,

    fileOpenTimeout: 1000,
});

/**
 * correct point for bounding boxes crossing date line
 */
var mirrorPoint= function( point ) {
    return [ point[0] + (point[0] < 0 ? 180 : -180), point[1] ];
};

/**
 * correct list of points for bounding boxes crossing date line
 */
var mirrorPoints= function( points ) {
    return points.map(mirrorPoint);
};

/**
 * Reads a number from given file
 */
var readNumberFromFile= (function() {
    var buffer= new Buffer(2);

    return function( name, position ) {
        return dataFiles.openFile(name, function( fd ) {
            if ( fs.readSync(fd, buffer, 0, 2, position) !== 2 ) return null;

            var int16= buffer.readInt16LE(0);

            // return 0 for oceans
            return int16 === -500 ? 0 : int16;
        });
    };
})();

var roundLocation= function( location ) {
    var rlon= Math.round((location[0] + offset) * resolution) / resolution - offset;
    var rlat= Math.round((location[1] + offset) * resolution) / resolution - offset;
    rlat= Math.max(-90 + offset, rlat);
    rlat= Math.min(90 - offset, rlat);
    if (rlon < -180) rlon += 360;
    if (rlon > 180) rlon -= 360;
    return [ rlon, rlat ];
};

var _resolveValue= function( value ) {
    if ( typeof value === 'function' ) return _resolveValue(value());

    return value;
};

var _fixObjectLocation= function( location ) {
    if ( typeof location === 'object' && 'lng' in location && 'lat' in location ) {
        var lng= +_resolveValue(location.lng);
        var lat= +_resolveValue(location.lat);

        if ( isNaN(lng) || isNaN(lat) ) return;

        return [ lng, lat ];
    }
};

var _fixSingleLocation= function( location ) {
    if ( Array.isArray(location) && location.length === 2 ) {
        var lng= +_resolveValue(location[0]);
        var lat= +_resolveValue(location[1]);

        if ( isNaN(lng) || isNaN(lat) ) return;

        return [ lng, lat ];
    }
    return _fixObjectLocation(location);
};

var _fixLocation= function( location ) {
    location= _resolveValue(location);

    var l= _fixSingleLocation(location);

    // location is a single location
    if ( l ) return l;

    if ( !Array.isArray(location) || location.length !== 2 ) return;

    var ul= _fixSingleLocation(location[0]);
    var or= _fixSingleLocation(location[1]);
    if ( ul && or ) return [ ul, or ];
};

var getElevation= function( location, onError ) {
    if ( typeof onError !== 'function' ) onError= function() {};

    location= _fixLocation(location);
    if ( !location ) return onError('Could get location');

    var locations;
    if ( Array.isArray(location[0]) ) {
        var spherewrap= false;
        var ul= roundLocation(location[0]);
        var or= roundLocation(location[1]);

        if ( ul[0] * or[0] < 0 && Math.abs(ul[0] - or[0]) >= 180 ) {
            spherewrap= true;
            ul= mirrorPoint(ul);
            or= mirrorPoint(or);
        }

        var lonMin= ul[0], lonMax= or[0];
        if ( ul[0] > or[0] ) {
            lonMin= or[0];
            lonMax= ul[0];
        }
        var latMin= ul[1], latMax= or[1];
        if ( ul[1] > or[1] ) {
            latMin= or[1];
            latMax= ul[1];
        }

        locations= [];

        // boundingBox assumed -> build locations array
        for ( var lon= lonMin; lon <= lonMax; lon += 1 / resolution ) {
            for ( var lat= latMin; lat <= latMax; lat += 1 / resolution ) {
                locations.push([ lon, lat ]);

                // prevent system from lock up due to allocate a lot of memory
                if ( locations.length > pointLimit ) return onError('Too many points');
            }
        }
        if ( spherewrap ) locations= mirrorPoints(locations);
    }
    else {
        locations= [ roundLocation(location) ];
    }

    if ( !locations.length ) return onError('No location given');

    var altSum= 0;
    for ( var i in locations ) {
        var li= locations[i];
        var fileEntry= dataFiles.findFile(roundLocation(li));

        if ( !fileEntry ) return onError('Could not determine data file');

        var alt= readNumberFromFile(fileEntry.name, dataFiles.fileIndex(li, fileEntry, resolution));

        if ( isNaN(alt) ) return onError('Could not fetch value from file');

        altSum += alt;
    }

    return altSum / locations.length;
};

var init= function( config ) {
    var result= dataFiles.init(config);
    if ( result instanceof Error ) throw result;
    return result;
};

module.exports= {
    init: init,
    getElevation: getElevation,
};

<commit_msg>More code clean up<commit_after>'use strict';
var fs= require('fs');

var dataFiles= require('./dataFiles');

var defaultDataPaths= [
    '/usr/share/GLOBE-elevation',
    '/usr/local/share/GLOBE-elevation',
    'GLOBE-elevation',
    'elevation',
];

// resolution in 1 / degree
var resolution= 120;
var resolutionStep= 1 / resolution;

// offset to middle of one raster pixel
var offset= resolutionStep / 2;

// limit of single points for bounding boxes
var pointLimit= 1e6;

/**
 * End of constants
 */

// First initialization with best guessed values
dataFiles.init({

    // find first existing path (if any)
    dataPath: defaultDataPaths,

    fileOpenTimeout: 1000,
});

/**
 *  mirror a Longitude
 */
var _mirrorLng= function( lng ) {
    return lng + (lng < 0 ? 180 : -180);
};

/**
 *  Lng/lat coordinate
 */
var Point= (function() {
    var _maxLat= 90 - offset;
    var _round= function( l ) {
        return Math.round((l + offset) * resolution) / resolution - offset;
    };

    return function( lng, lat ) {
        if ( Array.isArray(lng) ) {
            lat= lng[1];
            lng= lng[0];
        }

        if ( lat < -_maxLat ) lat= -_maxLat;
        if ( lat >  _maxLat ) lat=  _maxLat;
        if ( lng < -180) lng += 360;
        if ( lng >  180) lg -= 360;

        this.lng= function() { return lng; };
        this.lat= function() { return lat; };
        this.round= function() { return new Point(_round(lng), _round(lat)); };
    };
})();

/**
 *  Bounding box representation
 */
var BoundingBox= function( p1, p2 ) {
    var p1Lng= p1.lng(), p1Lat= p1.lat(),
        p2Lng= p2.lng(), p2Lat= p2.lat();

    var sphereWrap= p1Lng * p2Lng < 0 && Math.abs(p1Lng - p2Lng) >= 180;
    if ( sphereWrap ) {
        p1Lng= _mirrorLng(p1Lng);
        p12ng= _mirrorLng(p2Lng);
    }

    var minLng= Math.min(p1Lng, p2Lng);
    var maxLng= Math.max(p1Lng, p2Lng);
    var minLat= Math.min(p1Lat, p2Lat);
    var maxLat= Math.max(p1Lat, p2Lat);

    this.minLng= function() { return minLng; };
    this.maxLng= function() { return maxLng; };
    this.minLat= function() { return minLat; };
    this.maxLat= function() { return maxLat; };
    this.sphereWrap= function() { return sphereWrap; };
}

/**
 * Reads a number from given file
 */
var readNumberFromFile= (function() {
    var buffer= new Buffer(2);

    return function( name, position ) {
        return dataFiles.openFile(name, function( fd ) {
            if ( fs.readSync(fd, buffer, 0, 2, position) !== 2 ) return null;

            var int16= buffer.readInt16LE(0);

            // return 0 for oceans
            return int16 === -500 ? 0 : int16;
        });
    };
})();

/**
 *  parse parameters
 *  returns Point, BoundingBox or undefined on error
 */
var _fixParam= (function() {
    var _resolveValue= function( value ) {
        if ( typeof value === 'function' ) return _resolveValue(value());

        return value;
    };

    var _fixObjectLocation= function( location ) {
        if ( typeof location === 'object' && 'lng' in location && 'lat' in location ) {
            var lng= +_resolveValue(location.lng);
            var lat= +_resolveValue(location.lat);

            if ( isNaN(lng) || isNaN(lat) ) return;

            return new Point(lng, lat);
        }
    };

    var _fixSingleLocation= function( location ) {
        if ( Array.isArray(location) && location.length === 2 ) {
            var lng= +_resolveValue(location[0]);
            var lat= +_resolveValue(location[1]);

            if ( isNaN(lng) || isNaN(lat) ) return;

            return new Point(lng, lat);
        }
        return _fixObjectLocation(location);
    };

    return function( location ) {
        location= _resolveValue(location);

        var p= _fixSingleLocation(location);

        // location is a single location
        if ( p ) return p;

        if ( !Array.isArray(location) || location.length !== 2 ) return;

        var p1= _fixSingleLocation(location[0]);
        var p2= _fixSingleLocation(location[1]);

        if ( p1 && p2 ) return new BoundingBox(p1, p2);
    };
})();

/**
 *  get elevation
 *  param may be a single location of either [lng, lat] or {lng: lng, lat: lat}
 *      or to locations of the above form, defining a bounding box
 *  onError is optional and is called on error
 *
 *  returns result of onError or elevation
 */
var getElevation= function( param, onError ) {
    if ( typeof onError !== 'function' ) onError= function() {};

    param= _fixParam(param);
    if ( !param ) return onError('Could get location');

    var locations;
    if ( param instanceof BoundingBox ) {
        locations= [];

        var maxLng= param.maxLng();
        var maxLat= param.maxLat();
        var sphereWrap= param.sphereWrap();

        // boundingBox assumed -> build locations array
        for ( var lng= param.minLng(); lng <= maxLng; lng += resolutionStep ) {
            for ( var lat= param.minLat(); lat <= maxLat; lat += resolutionStep ) {
                locations.push([ sphereWrap ? _mirrorLng(lng) : lng, lat ]);

                // prevent system from lock up due to allocate a lot of memory
                if ( locations.length > pointLimit ) return onError('Too many points');
            }
        }
    }
    else {
        locations= [ param.lng(), param.lat() ];
    }

    var altSum= 0;
    for ( var i in locations ) {
        var li= locations[i];
        var fileEntry= dataFiles.findFile(li);

        if ( !fileEntry ) return onError('Could not determine data file');

        var alt= readNumberFromFile(fileEntry.name, dataFiles.fileIndex(li, fileEntry, resolution));

        if ( isNaN(alt) ) return onError('Could not fetch value from file');

        altSum += alt;
    }

    return altSum / locations.length;
};

var init= function( config ) {
    var result= dataFiles.init(config);

    if ( result instanceof Error ) throw result;

    return result;
};

module.exports= {
    init: init,
    getElevation: getElevation,
};

<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var util = require('util');
var os = require('os');
var crypto = require('crypto');

/**
 * replace tabs by indent value
 *
 * @param line
 * @param indent
 * @return string
 */
function properIndentation(line, indent) {
    return line.replace(/\t/, indent || '');
}

/**
 * count leading whitespace chars
 *
 * @param line
 * @return integer
 */
function countWhitespace(line) {
    // return a somewhat high value for empty lines
    return line.length ? parseInt(line.match(/^\s*/)[0].length, 10) : 9999;
}

/**
 * get lowest value of leading whitespace in a given block
 *
 * @param previous
 * @param current
 * @returns integer
 */
function getLeadingWhitespace(previous, current) {
    return previous <= current ? previous : current;
}

/**
 * raise offset in lines
 *
 * @param lines
 * @param offset
 * @returns {Array|*|{}}
 */
function raiseIndent(lines, offset) {
    offset = offset || '    ';

    return lines.map((line) => offset + line);
}

/**
 * Formalize any given value as wrap object
 *
 * @param wrap
 * @returns {{before: '', after: ''}}
 */
function formalizeWrap(wrap) {
    const result = { before: '', after: '' };

    if ((typeof wrap === 'string' && wrap.length > 0) || typeof wrap === 'number') {
        result.before = result.after = wrap;
    } else if  (Array.isArray(wrap) && wrap.length > 0) {
        result.before = [].slice.call(wrap, 0, 1)[0];
        result.after = wrap.length > 1 ? [].slice.call(wrap, 1, 2)[0] : result.before;
    } else if (_.isPlainObject(wrap)) {
        let i = 0;

        // crappy method getting the value of the first and second item in object
        for (let el in wrap) {
            if (!wrap.hasOwnProperty(el)) {
                continue;
            }

            if (i < 2) {
                result.before = wrap[el];
            }

            i++;
        }

        // set value of after to the value of before if after is empty
        result.after = result.after.length < 1 ? result.before : result.after;
    }

    return result;
}

/**
 * read options from annotation
 *
 * e.g.:
 * gets:
 * {
     *   extract: 'teaser/content-teaser--small.html',
     *   viewWrap: {before: '
', after: '
'}
     * }
 *
 * @param annotation
 * @param defaults
 * @returns {{}}
 */
function getBlockOptions(annotation, defaults) {
    const optionValues = annotation.split(/\w+:/)
        .map((item) => item.replace(/|^\s+|\s+$/, ''))
        .filter((item) => !!item.length);
    const optionKeys = annotation.match(/(\w+):/g).map((item) => item.replace(/[^\w]/, ''));

    defaults = defaults || {
            viewWrap: {before: '', after: ''}
        };

    const opts = {};

    optionValues.forEach((v, i) => {
        const k = optionKeys[i];

        if (typeof k !== 'string') {
            return;
        }

        // Treat option value as array if it has a colon
        // @todo: Allow escaped colons to be ignored
        // RegEx lookbehind negate does not work :(
        // Should be /(?<!\\):/
        if (v.indexOf(':') > -1) {
            v = v.split(':');
        }

        opts[k] = v;
    });

    // Process options
    opts.wrap = formalizeWrap(opts.wrap || defaults.viewWrap);

    return opts;
}

/**
 * Format options as string of HTML data parameters
 *
 * @param options
 * @returns {string}
 */
function optionsToDataString(options) {
    if (typeof options !== 'object') {
        return '';
    }

    const prepared = [];
    const processedOptions = Object.assign({}, options);

    // prepare wrap option
    if (processedOptions.hasOwnProperty('wrap')) {
        processedOptions['wrap-before'] = processedOptions.wrap.before;
        processedOptions['wrap-after'] = processedOptions.wrap.after;

        delete(processedOptions.wrap);
    }

    // create data attributes
    for (const el in processedOptions) {
        if (processedOptions.hasOwnProperty(el) === false) {
            continue;
        }

        const value = processedOptions[el];

        // Ignore callbacks
        if (typeof value === 'function') {
            continue;
        }

        // Cleanup: Remove leading and trailing " and ', replace " by ' (e.g. in stringified objects)
        const preparedVal = JSON.stringify(processedOptions[el])
            .replace(/^['"]|['"]$/g, '')
            .replace(/\\?"/g, "'");

        // Build data parameter: data-name="value"
        const param = 'data-' + el + '="' + preparedVal + '"';

        prepared.push(param);
    }

    return prepared.join(' ');
}

/**
 * trim given number of leading characters
 *
 * @param lines
 * @param num Number of chars to be removed
 * @returns Array
 */
function trimLines(lines, num) {
    return lines.map((line) => line.substr(num));
}

/**
 * create sha1 hash from string
 *
 * @param value
 * @returns {*}
 */
function createId(value) {
    return crypto.createHash('sha1').update(value, 'utf8').digest('hex').slice(0, 8);
}

/**
 * get default options, scope as function instead of "public" property
 *
 * @returns {{indent: string, origin: string, resources: {classnames: {root: string, body: string}, meta: Array, scriptsFoot: {files: Array, inline: Array}, scriptsHead: {files: Array, inline: Array}, stylesHead: {files: Array, inline: Array}}, templateWrap: {before: string, after: string}, viewWrap: {before: string, after: string}}}
 */
function getDefaultOptions() {
    const resources = {
        classnames: {
            root: '',
            body: ''
        },
        meta: [],
        scriptsFoot: {
            files: [],
            inline: []
        },
        scriptsHead: {
            files: [],
            inline: []
        },
        stylesHead: {
            files: [],
            inline: []
        }
    };

    return {
        indent: '    ',
        origin: '',
        resources: resources,
        templateWrap: { before: '', after: '' },
        viewWrap: { before: '', after: '' }
    }
}

/**
 * Constructor
 *
 * Use named function to get better backtraces in node
 *
 * @param data
 * @constructor
 */
var InventoryObject = function (data) {
    data                = data || {};

    this.category       = data.hasOwnProperty('category') ? data.category : 'No category';
    this.id             = data.hasOwnProperty('id') ? data.id : '';
    this.group          = data.hasOwnProperty('group') ? data.group : '';
    this.lines          = data.hasOwnProperty('lines') ? data.lines : 0;
    this.name           = data.hasOwnProperty('name') ? data.name : '';
    this.options        = data.hasOwnProperty('options') ? data.options : {};
    this.optionsData    = data.hasOwnProperty('optionsData') ? data.optionsData : '';
    this.origin         = data.hasOwnProperty('origin') ? data.origin : '';
    this.partial        = data.hasOwnProperty('partial') ? data.partial : '';
    this.resources      = data.hasOwnProperty('resources') ? data.resources : Object.assign({}, getDefaultOptions().resources);
    this.template       = data.hasOwnProperty('template') ? data.template : '';
    this.usage          = data.hasOwnProperty('usage') ? data.usage : [];
    this.view           = data.hasOwnProperty('view') ? data.view : '';
    this.viewId         = data.hasOwnProperty('viewId') ? data.viewId : '';
};

/**
 * parse data from extracted part
 *
 * @param src
 * @param opts
 */
InventoryObject.prototype.parseData = function(src, opts) {
    opts = Object.assign({}, getDefaultOptions(), opts);

    const parts = src.match(/(?:((?:.|\n)*?)/i);
    const blockOpts = getBlockOptions(parts[1], opts);
    // remove comments
    const content = _.trimEnd(_.trimStart(src.replace(//gi, ''), '\n\r'));

    // continue if name is empty
    if (!blockOpts.hasOwnProperty('extract')) {
        return;
    }

    // label from name property and fallback to extract value
    const name = blockOpts.hasOwnProperty('name') ? blockOpts.name : blockOpts.extract;

    // set category name
    const category = blockOpts.hasOwnProperty('category') ? blockOpts.category : this.category;

    // set group
    const group = blockOpts.hasOwnProperty('group') ? blockOpts.group : this.group;

    // process source code
    let lines = content.split('\n')
        .map((line) => _.trimEnd(line))
        .map((line) => properIndentation(line, opts.indent));
    const leadingWhitespace = lines.map(countWhitespace);
    const crop = leadingWhitespace.reduce(getLeadingWhitespace);
    const viewWrap = blockOpts.wrap;
    const templateWrapOptions = optionsToDataString(blockOpts);

    lines = trimLines(lines, crop);

    let viewLines = util._extend([], lines);
    let templateLines = util._extend([], lines);

    // wrap partial if inline option viewWrap: exists
    if (viewWrap.before.length) {
        viewLines = raiseIndent(viewLines);
        viewLines.unshift('');
        viewLines.unshift(viewWrap.before);
        viewLines.push('');
        viewLines.push(viewWrap.after);
    }

    // add templateWrap
    if (typeof opts.templateWrap === 'object') {
        let before = opts.templateWrap.before || '';
        let after = opts.templateWrap.after || '';

        before = before.replace('{{wrapData}}', templateWrapOptions);
        after = after.replace('{{wrapData}}', templateWrapOptions);

        templateLines.unshift(before);
        templateLines.push(after);
    }

    // set properties
    this.category       = category;
    this.group          = group;
    // remove all whitespace chars before creating the hash
    this.id             = createId(src.replace(/\s+/gi, ''));
    this.lines          = lines;
    this.name           = name;
    this.options        = blockOpts;
    this.optionsData    = templateWrapOptions;
    this.partial        = lines.join(os.EOL);
    this.resources      = opts.resources;
    this.template       = templateLines.join(os.EOL);
    this.view           = viewLines.join(os.EOL);
    this.viewId         = createId(this.view.replace(/\s+/gi, ''));
};

/**
 * set inventory object property if prop is a valid property name (property exists)
 *
 * @param prop
 * @param value
 * @returns {boolean}
 */
InventoryObject.prototype.setProperty = function (prop, value) {
    if (typeof prop !== 'string' || !this.hasOwnProperty(prop)) {
        return false;
    }

    this[prop] = value;

    return true;
};

/**
 * module
 * @param data
 * @returns {*}
 */
module.exports = InventoryObject;
<commit_msg>Remove ending annotations first<commit_after>'use strict';

var _ = require('lodash');
var util = require('util');
var os = require('os');
var crypto = require('crypto');

/**
 * replace tabs by indent value
 *
 * @param line
 * @param indent
 * @return string
 */
function properIndentation(line, indent) {
    return line.replace(/\t/, indent || '');
}

/**
 * count leading whitespace chars
 *
 * @param line
 * @return integer
 */
function countWhitespace(line) {
    // return a somewhat high value for empty lines
    return line.length ? parseInt(line.match(/^\s*/)[0].length, 10) : 9999;
}

/**
 * get lowest value of leading whitespace in a given block
 *
 * @param previous
 * @param current
 * @returns integer
 */
function getLeadingWhitespace(previous, current) {
    return previous <= current ? previous : current;
}

/**
 * raise offset in lines
 *
 * @param lines
 * @param offset
 * @returns {Array|*|{}}
 */
function raiseIndent(lines, offset) {
    offset = offset || '    ';

    return lines.map((line) => offset + line);
}

/**
 * Formalize any given value as wrap object
 *
 * @param wrap
 * @returns {{before: '', after: ''}}
 */
function formalizeWrap(wrap) {
    const result = { before: '', after: '' };

    if ((typeof wrap === 'string' && wrap.length > 0) || typeof wrap === 'number') {
        result.before = result.after = wrap;
    } else if  (Array.isArray(wrap) && wrap.length > 0) {
        result.before = [].slice.call(wrap, 0, 1)[0];
        result.after = wrap.length > 1 ? [].slice.call(wrap, 1, 2)[0] : result.before;
    } else if (_.isPlainObject(wrap)) {
        let i = 0;

        // crappy method getting the value of the first and second item in object
        for (let el in wrap) {
            if (!wrap.hasOwnProperty(el)) {
                continue;
            }

            if (i < 2) {
                result.before = wrap[el];
            }

            i++;
        }

        // set value of after to the value of before if after is empty
        result.after = result.after.length < 1 ? result.before : result.after;
    }

    return result;
}

/**
 * read options from annotation
 *
 * e.g.:
 * gets:
 * {
     *   extract: 'teaser/content-teaser--small.html',
     *   viewWrap: {before: '
', after: '
'}
     * }
 *
 * @param annotation
 * @param defaults
 * @returns {{}}
 */
function getBlockOptions(annotation, defaults) {
    const optionValues = annotation.split(/\w+\:/)
        .map((item) => item.replace(/|^\s+|\s+$/, ''))
        .filter((item) => !!item.length);
    const optionKeys = annotation.match(/(\w+)\:/gi).map((item) => item.replace(/[^\w]/, ''));

    defaults = defaults || {
            viewWrap: {before: '', after: ''}
        };

    const opts = {};

    optionValues.forEach((v, i) => {
        const k = optionKeys[i];

        if (typeof k !== 'string') {
            return;
        }

        // Treat option value as array if it has a colon
        // @todo: Allow escaped colons to be ignored
        // RegEx lookbehind negate does not work :(
        // Should be /(?<!\\):/
        if (v.indexOf(':') > -1) {
            v = v.split(':');
        }

        opts[k] = v;
    });

    // Process options
    opts.wrap = formalizeWrap(opts.wrap || defaults.viewWrap);

    return opts;
}

/**
 * Format options as string of HTML data parameters
 *
 * @param options
 * @returns {string}
 */
function optionsToDataString(options) {
    if (typeof options !== 'object') {
        return '';
    }

    const prepared = [];
    const processedOptions = Object.assign({}, options);

    // prepare wrap option
    if (processedOptions.hasOwnProperty('wrap')) {
        processedOptions['wrap-before'] = processedOptions.wrap.before;
        processedOptions['wrap-after'] = processedOptions.wrap.after;

        delete(processedOptions.wrap);
    }

    // create data attributes
    for (const el in processedOptions) {
        if (processedOptions.hasOwnProperty(el) === false) {
            continue;
        }

        const value = processedOptions[el];

        // Ignore callbacks
        if (typeof value === 'function') {
            continue;
        }

        // Cleanup: Remove leading and trailing " and ', replace " by ' (e.g. in stringified objects)
        const preparedVal = JSON.stringify(processedOptions[el])
            .replace(/^['"]|['"]$/g, '')
            .replace(/\\?"/g, "'");

        // Build data parameter: data-name="value"
        const param = 'data-' + el + '="' + preparedVal + '"';

        prepared.push(param);
    }

    return prepared.join(' ');
}

/**
 * trim given number of leading characters
 *
 * @param lines
 * @param num Number of chars to be removed
 * @returns Array
 */
function trimLines(lines, num) {
    return lines.map((line) => line.substr(num));
}

/**
 * create sha1 hash from string
 *
 * @param value
 * @returns {*}
 */
function createId(value) {
    return crypto.createHash('sha1').update(value, 'utf8').digest('hex').slice(0, 8);
}

/**
 * get default options, scope as function instead of "public" property
 *
 * @returns {{indent: string, origin: string, resources: {classnames: {root: string, body: string}, meta: Array, scriptsFoot: {files: Array, inline: Array}, scriptsHead: {files: Array, inline: Array}, stylesHead: {files: Array, inline: Array}}, templateWrap: {before: string, after: string}, viewWrap: {before: string, after: string}}}
 */
function getDefaultOptions() {
    const resources = {
        classnames: {
            root: '',
            body: ''
        },
        meta: [],
        scriptsFoot: {
            files: [],
            inline: []
        },
        scriptsHead: {
            files: [],
            inline: []
        },
        stylesHead: {
            files: [],
            inline: []
        }
    };

    return {
        indent: '    ',
        origin: '',
        resources: resources,
        templateWrap: { before: '', after: '' },
        viewWrap: { before: '', after: '' }
    }
}

/**
 * Constructor
 *
 * Use named function to get better backtraces in node
 *
 * @param data
 * @constructor
 */
var InventoryObject = function (data) {
    data                = data || {};

    this.category       = data.hasOwnProperty('category') ? data.category : 'No category';
    this.id             = data.hasOwnProperty('id') ? data.id : '';
    this.group          = data.hasOwnProperty('group') ? data.group : '';
    this.lines          = data.hasOwnProperty('lines') ? data.lines : 0;
    this.name           = data.hasOwnProperty('name') ? data.name : '';
    this.options        = data.hasOwnProperty('options') ? data.options : {};
    this.optionsData    = data.hasOwnProperty('optionsData') ? data.optionsData : '';
    this.origin         = data.hasOwnProperty('origin') ? data.origin : '';
    this.partial        = data.hasOwnProperty('partial') ? data.partial : '';
    this.resources      = data.hasOwnProperty('resources') ? data.resources : Object.assign({}, getDefaultOptions().resources);
    this.template       = data.hasOwnProperty('template') ? data.template : '';
    this.usage          = data.hasOwnProperty('usage') ? data.usage : [];
    this.view           = data.hasOwnProperty('view') ? data.view : '';
    this.viewId         = data.hasOwnProperty('viewId') ? data.viewId : '';
};

/**
 * parse data from extracted part
 *
 * @param src
 * @param opts
 */
InventoryObject.prototype.parseData = function(src, opts) {
    opts = Object.assign({}, getDefaultOptions(), opts);

    // remove ending annotation
    src = src.replace(//gi, '')

    const parts = src.match(/(?:((?:.|\n)*?)/i);
    const blockOpts = getBlockOptions(parts[1], opts);

    // remove extraction annotation and trim
    const content = _.trimEnd(_.trimStart(src.replace(//gi, ''), '\n\r'));

    // continue if name is empty
    if (!blockOpts.hasOwnProperty('extract')) {
        return;
    }

    // label from name property and fallback to extract value
    const name = blockOpts.hasOwnProperty('name') ? blockOpts.name : blockOpts.extract;

    // set category name
    const category = blockOpts.hasOwnProperty('category') ? blockOpts.category : this.category;

    // set group
    const group = blockOpts.hasOwnProperty('group') ? blockOpts.group : this.group;

    // process source code
    let lines = content.split('\n')
        .map((line) => _.trimEnd(line))
        .map((line) => properIndentation(line, opts.indent));
    const leadingWhitespace = lines.map(countWhitespace);
    const crop = leadingWhitespace.reduce(getLeadingWhitespace);
    const viewWrap = blockOpts.wrap;
    const templateWrapOptions = optionsToDataString(blockOpts);

    lines = trimLines(lines, crop);

    let viewLines = util._extend([], lines);
    let templateLines = util._extend([], lines);

    // wrap partial if inline option viewWrap: exists
    if (viewWrap.before.length) {
        viewLines = raiseIndent(viewLines);
        viewLines.unshift('');
        viewLines.unshift(viewWrap.before);
        viewLines.push('');
        viewLines.push(viewWrap.after);
    }

    // add templateWrap
    if (typeof opts.templateWrap === 'object') {
        let before = opts.templateWrap.before || '';
        let after = opts.templateWrap.after || '';

        before = before.replace('{{wrapData}}', templateWrapOptions);
        after = after.replace('{{wrapData}}', templateWrapOptions);

        templateLines.unshift(before);
        templateLines.push(after);
    }

    // set properties
    this.category       = category;
    this.group          = group;
    // remove all whitespace chars before creating the hash
    this.id             = createId(src.replace(/\s+/gi, ''));
    this.lines          = lines;
    this.name           = name;
    this.options        = blockOpts;
    this.optionsData    = templateWrapOptions;
    this.partial        = lines.join(os.EOL);
    this.resources      = opts.resources;
    this.template       = templateLines.join(os.EOL);
    this.view           = viewLines.join(os.EOL);
    this.viewId         = createId(this.view.replace(/\s+/gi, ''));
};

/**
 * set inventory object property if prop is a valid property name (property exists)
 *
 * @param prop
 * @param value
 * @returns {boolean}
 */
InventoryObject.prototype.setProperty = function (prop, value) {
    if (typeof prop !== 'string' || !this.hasOwnProperty(prop)) {
        return false;
    }

    this[prop] = value;

    return true;
};

/**
 * module
 * @param data
 * @returns {*}
 */
module.exports = InventoryObject;
<|endoftext|>


<commit_before>var scuttleup = require('scuttleup')
var fwdb = require('fwdb')
var through = require('through2')
var sublevel = require('level-sublevel')
var after = require('after-all')
var concat = require('concat-stream')
var protobuf = require('protocol-buffers')
var fs = require('fs')
var encoders = require('./encoders')

var messages = protobuf(fs.readFileSync(__dirname+'/schema.proto'))

var split = function(id) {
  var i = id.lastIndexOf('@')
  var peer = id.slice(0, i)
  var seq = Number(id.slice(i+1))

  return [peer, seq]
}

var toHead = function(data) {
  return {peer:data.key, seq:Number(data.value)}
}

var next = function(data, cb) {
  cb()
}

var link = function(a, b) {
  b.on('close', function() {
    a.destroy()
  })
  a.on('error', function(err) {
    b.emit('error', err)
  })
  return a.pipe(b)
}

var create = function(db, opts) {
  if (!opts) opts = {}

  var subs = sublevel(db)
  var latest = subs.sublevel('latest')
  var seqs = subs.sublevel('seqs')
  var log = scuttleup(subs.sublevel('log'), opts)
  var fdb = fwdb(db) // sublevel blows up if we pass in a sublevel :(

  var preupdate = opts.preupdate || next
  var postupdate = opts.postupdate || next
  var enc = encoders(opts.valueEncoding || opts.encoding)

  var head = 0
  var cbs = {}
  var call = function() {
    if (cbs[head]) cbs[head]()
    delete cbs[head]
  }

  var index = function(data, enc, cb) {
    var entry = messages.Entry.decode(data.entry)
    var key = entry.key
    var d = postupdate !== next || preupdate !== next ? {peer:data.peer, seq:data.seq, key:key, value:enc.decode(entry)} : null

    preupdate(d, function(err) {
      if (err) return cb(err)

      fdb.heads(key, function(err, heads) {
        if (err) return cb(err)
        if (!heads) heads = []

        heads = heads
          .filter(function(h) {
            var parts = split(h.hash)
            return parts[0] === data.peer
          })
          .map(function(m) {
            return m.hash
          })

        if (entry.prev) heads = heads.concat(entry.prev)

        fdb.create({
          key: key,
          hash: data.peer+'@'+data.seq,
          prev: heads
        }, function(err) {
          if (err) return cb(err)
          seqs.put(data.peer, ''+data.seq, function() {
            postupdate(d, function(err) {
              if (data.peer === log.id) call(head = data.seq)
              cb(err)
            })
          })
        })
      })
    })
  }

  seqs.createReadStream().pipe(concat(function(head) {
    log.createReadStream({live:true, since:head.map(toHead)}).pipe(through.obj(index))
  }))

  var that = {}

  that.fwdb = fdb
  that.log = log
  that.db = db

  that.sync = function(opts) {
    return log.createReplicationStream(opts)
  }

  that.replicate = function(other, opts) {
    var tmp = other.sync()
    tmp.pipe(that.sync(opts)).pipe(tmp)
    return other
  }

  that.merge = function(key, list, val, cb) {
    var prev = [].concat(list).map(function(doc) {
      return doc.peer+'@'+doc.seq
    })

    that.put(key, val, {prev:prev}, cb)
  }

  that.createKeyStream = function(opts) {
    var keys = fdb.keys(opts)
    var fmt = through.obj(function(data, enc, cb) {
      cb(null, data.key)
    })
    return link(keys, fmt)
  }

  that.createValueStream = function(opts) {
    var keys = fdb.keys(opts)
    var fmt = through.obj(function(data, enc, cb) {
      that.get(data.key, opts, function(err, docs) {
        cb(null, docs.map(function(x) {
          return x.value
        }))
      })
    })
    return link(keys, fmt)
  }

  that.createReadStream = function(opts) {
    var combine = opts && opts.combine
    var keys = fdb.keys(opts)
    var fmt = through.obj(function(data, enc, cb) {
      that.get(data.key, opts, function(err, docs) {
        if (err) return cb(err)
        if (combine) return cb(null, docs)
        for (var i = 0; i < docs.length; i++) fmt.push(docs[i])
        cb()
      })
    })
    return link(keys, fmt)
  }

  that.put = function(key, val, opts, cb) {
    if (typeof opts === 'function') return that.put(key, val, null, opts)
    if (!opts) opts = {}

    var prev = [].concat(opts.prev || [])
    var e = opts.encoding ? encoders(opts.encoding) : enc

    log.append(messages.Entry.encode({key:key, value:e.encode(val), prev:prev}), cb && function(err, change) {
      if (err) return cb(err)
      var inserted = {peer:change.peer, seq:change.seq, key:key, value:val}
      if (head >= change.seq) return cb(null, inserted)
      cbs[change.seq] = function() { cb(null, inserted) }
    })
  }

  that.get = function(key, opts, cb) {
    if (typeof opts === 'function') return that.get(key, null, opts)
    if (!opts) opts = {}

    var e = opts.encoding ? encoders(opts.encoding) : enc

    fdb.heads(key, function(err, heads) {
      if (err) return cb(err)

      var list = []
      var next = after(function(err) {
        if (err) return cb(err)
        cb(null, list)
      })

      heads.forEach(function(val) {
        var n = next()
        var parts = split(val.hash)

        if (opts.data === false) {
          list.push({peer:parts[0], seq:parts[1], key:key})
          return n()
        }

        log.entry(parts[0], parts[1], function(err, entry) {
          if (err) return n(err)

          entry = messages.Entry.decode(entry)
          list.push({
            peer: parts[0],
            seq: parts[1],
            key: key,
            value: e.decode(entry.value)
          })

          n()
        })
      })
    })
  }

  return that
}

module.exports = create
<commit_msg>Add missing error handling.<commit_after>var scuttleup = require('scuttleup')
var fwdb = require('fwdb')
var through = require('through2')
var sublevel = require('level-sublevel')
var after = require('after-all')
var concat = require('concat-stream')
var protobuf = require('protocol-buffers')
var fs = require('fs')
var encoders = require('./encoders')

var messages = protobuf(fs.readFileSync(__dirname+'/schema.proto'))

var split = function(id) {
  var i = id.lastIndexOf('@')
  var peer = id.slice(0, i)
  var seq = Number(id.slice(i+1))

  return [peer, seq]
}

var toHead = function(data) {
  return {peer:data.key, seq:Number(data.value)}
}

var next = function(data, cb) {
  cb()
}

var link = function(a, b) {
  b.on('close', function() {
    a.destroy()
  })
  a.on('error', function(err) {
    b.emit('error', err)
  })
  return a.pipe(b)
}

var create = function(db, opts) {
  if (!opts) opts = {}

  var subs = sublevel(db)
  var latest = subs.sublevel('latest')
  var seqs = subs.sublevel('seqs')
  var log = scuttleup(subs.sublevel('log'), opts)
  var fdb = fwdb(db) // sublevel blows up if we pass in a sublevel :(

  var preupdate = opts.preupdate || next
  var postupdate = opts.postupdate || next
  var enc = encoders(opts.valueEncoding || opts.encoding)

  var head = 0
  var cbs = {}
  var call = function() {
    if (cbs[head]) cbs[head]()
    delete cbs[head]
  }

  var index = function(data, enc, cb) {
    var entry = messages.Entry.decode(data.entry)
    var key = entry.key
    var d = postupdate !== next || preupdate !== next ? {peer:data.peer, seq:data.seq, key:key, value:enc.decode(entry)} : null

    preupdate(d, function(err) {
      if (err) return cb(err)

      fdb.heads(key, function(err, heads) {
        if (err) return cb(err)
        if (!heads) heads = []

        heads = heads
          .filter(function(h) {
            var parts = split(h.hash)
            return parts[0] === data.peer
          })
          .map(function(m) {
            return m.hash
          })

        if (entry.prev) heads = heads.concat(entry.prev)

        fdb.create({
          key: key,
          hash: data.peer+'@'+data.seq,
          prev: heads
        }, function(err) {
          if (err) return cb(err)
          seqs.put(data.peer, ''+data.seq, function() {
            postupdate(d, function(err) {
              if (data.peer === log.id) call(head = data.seq)
              cb(err)
            })
          })
        })
      })
    })
  }

  seqs.createReadStream().pipe(concat(function(head) {
    log.createReadStream({live:true, since:head.map(toHead)}).pipe(through.obj(index))
  }))

  var that = {}

  that.fwdb = fdb
  that.log = log
  that.db = db

  that.sync = function(opts) {
    return log.createReplicationStream(opts)
  }

  that.replicate = function(other, opts) {
    var tmp = other.sync()
    tmp.pipe(that.sync(opts)).pipe(tmp)
    return other
  }

  that.merge = function(key, list, val, cb) {
    var prev = [].concat(list).map(function(doc) {
      return doc.peer+'@'+doc.seq
    })

    that.put(key, val, {prev:prev}, cb)
  }

  that.createKeyStream = function(opts) {
    var keys = fdb.keys(opts)
    var fmt = through.obj(function(data, enc, cb) {
      cb(null, data.key)
    })
    return link(keys, fmt)
  }

  that.createValueStream = function(opts) {
    var keys = fdb.keys(opts)
    var fmt = through.obj(function(data, enc, cb) {
      that.get(data.key, opts, function(err, docs) {
        if (err) return cb(err)
        cb(null, docs.map(function(x) {
          return x.value
        }))
      })
    })
    return link(keys, fmt)
  }

  that.createReadStream = function(opts) {
    var combine = opts && opts.combine
    var keys = fdb.keys(opts)
    var fmt = through.obj(function(data, enc, cb) {
      that.get(data.key, opts, function(err, docs) {
        if (err) return cb(err)
        if (combine) return cb(null, docs)
        for (var i = 0; i < docs.length; i++) fmt.push(docs[i])
        cb()
      })
    })
    return link(keys, fmt)
  }

  that.put = function(key, val, opts, cb) {
    if (typeof opts === 'function') return that.put(key, val, null, opts)
    if (!opts) opts = {}

    var prev = [].concat(opts.prev || [])
    var e = opts.encoding ? encoders(opts.encoding) : enc

    log.append(messages.Entry.encode({key:key, value:e.encode(val), prev:prev}), cb && function(err, change) {
      if (err) return cb(err)
      var inserted = {peer:change.peer, seq:change.seq, key:key, value:val}
      if (head >= change.seq) return cb(null, inserted)
      cbs[change.seq] = function() { cb(null, inserted) }
    })
  }

  that.get = function(key, opts, cb) {
    if (typeof opts === 'function') return that.get(key, null, opts)
    if (!opts) opts = {}

    var e = opts.encoding ? encoders(opts.encoding) : enc

    fdb.heads(key, function(err, heads) {
      if (err) return cb(err)

      var list = []
      var next = after(function(err) {
        if (err) return cb(err)
        cb(null, list)
      })

      heads.forEach(function(val) {
        var n = next()
        var parts = split(val.hash)

        if (opts.data === false) {
          list.push({peer:parts[0], seq:parts[1], key:key})
          return n()
        }

        log.entry(parts[0], parts[1], function(err, entry) {
          if (err) return n(err)

          entry = messages.Entry.decode(entry)
          list.push({
            peer: parts[0],
            seq: parts[1],
            key: key,
            value: e.decode(entry.value)
          })

          n()
        })
      })
    })
  }

  return that
}

module.exports = create
<|endoftext|>


<commit_before>/*!
 * on-finished
 * Copyright(c) 2013 Jonathan Ong
 * Copyright(c) 2014 Douglas Christopher Wilson
 * MIT Licensed
 */

'use strict'

/**
 * Module exports.
 * @public
 */

module.exports = onFinished
module.exports.isFinished = isFinished

/**
 * Module dependencies.
 * @private
 */

var first = require('ee-first')

/**
 * Variables.
 * @private
 */

/* istanbul ignore next */
var defer = typeof setImmediate === 'function'
  ? setImmediate
  : function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) }

/**
 * Invoke callback when the response has finished, useful for
 * cleaning up resources afterwards.
 *
 * @param {object} msg
 * @param {function} listener
 * @return {object}
 * @public
 */

function onFinished(msg, listener) {
  if (isFinished(msg) !== false) {
    defer(listener, null, msg)
    return msg
  }

  // attach the listener to the message
  attachListener(msg, listener)

  return msg
}

/**
 * Determine if message is already finished.
 *
 * @param {object} msg
 * @return {boolean}
 * @public
 */

function isFinished(msg) {
  var socket = msg.socket

  if (typeof msg.finished === 'boolean') {
    // OutgoingMessage
    return Boolean(msg.finished || (socket && !socket.writable))
  }

  if (typeof msg.complete === 'boolean') {
    // IncomingMessage
    return Boolean(msg.upgrade || !socket || !socket.readable || (msg.complete && !msg.readable))
  }

  // don't know
  return undefined
}

/**
 * Attach a finished listener to the message.
 *
 * @param {object} msg
 * @param {function} callback
 * @private
 */

function attachFinishedListener(msg, callback) {
  var eeMsg
  var eeSocket
  var finished = false

  function onFinish(error) {
    eeMsg.cancel()
    eeSocket.cancel()

    finished = true
    callback(error)
  }

  // finished on first message event
  eeMsg = eeSocket = first([[msg, 'end', 'finish']], onFinish)

  function onSocket(socket) {
    // remove listener
    msg.removeListener('socket', onSocket)

    if (finished) return
    if (eeMsg !== eeSocket) return

    // finished on first socket event
    eeSocket = first([[socket, 'error', 'close']], onFinish)
  }

  if (msg.socket) {
    // socket already assigned
    onSocket(msg.socket)
    return
  }

  // wait for socket to be assigned
  msg.on('socket', onSocket)

  if (msg.socket === undefined) {
    // node.js 0.8 patch
    patchAssignSocket(msg, onSocket)
  }
}

/**
 * Attach the listener to the message.
 *
 * @param {object} msg
 * @return {function}
 * @private
 */

function attachListener(msg, listener) {
  var attached = msg.__onFinished

  // create a private single listener with queue
  if (!attached || !attached.queue) {
    attached = msg.__onFinished = createListener(msg)
    attachFinishedListener(msg, attached)
  }

  attached.queue.push(listener)
}

/**
 * Create listener on message.
 *
 * @param {object} msg
 * @return {function}
 * @private
 */

function createListener(msg) {
  function listener(err) {
    if (msg.__onFinished === listener) msg.__onFinished = null
    if (!listener.queue) return

    var queue = listener.queue
    listener.queue = null

    for (var i = 0; i < queue.length; i++) {
      queue[i](err, msg)
    }
  }

  listener.queue = []

  return listener
}

/**
 * Patch ServerResponse.prototype.assignSocket for node.js 0.8.
 *
 * @param {ServerResponse} res
 * @param {function} callback
 * @private
 */

function patchAssignSocket(res, callback) {
  var assignSocket = res.assignSocket

  if (typeof assignSocket !== 'function') return

  // res.on('socket', callback) is broken in 0.8
  res.assignSocket = function _assignSocket(socket) {
    assignSocket.call(this, socket)
    callback(socket)
  }
}
<commit_msg>build: ignore 0.8 code since istanbul does not run<commit_after>/*!
 * on-finished
 * Copyright(c) 2013 Jonathan Ong
 * Copyright(c) 2014 Douglas Christopher Wilson
 * MIT Licensed
 */

'use strict'

/**
 * Module exports.
 * @public
 */

module.exports = onFinished
module.exports.isFinished = isFinished

/**
 * Module dependencies.
 * @private
 */

var first = require('ee-first')

/**
 * Variables.
 * @private
 */

/* istanbul ignore next */
var defer = typeof setImmediate === 'function'
  ? setImmediate
  : function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) }

/**
 * Invoke callback when the response has finished, useful for
 * cleaning up resources afterwards.
 *
 * @param {object} msg
 * @param {function} listener
 * @return {object}
 * @public
 */

function onFinished(msg, listener) {
  if (isFinished(msg) !== false) {
    defer(listener, null, msg)
    return msg
  }

  // attach the listener to the message
  attachListener(msg, listener)

  return msg
}

/**
 * Determine if message is already finished.
 *
 * @param {object} msg
 * @return {boolean}
 * @public
 */

function isFinished(msg) {
  var socket = msg.socket

  if (typeof msg.finished === 'boolean') {
    // OutgoingMessage
    return Boolean(msg.finished || (socket && !socket.writable))
  }

  if (typeof msg.complete === 'boolean') {
    // IncomingMessage
    return Boolean(msg.upgrade || !socket || !socket.readable || (msg.complete && !msg.readable))
  }

  // don't know
  return undefined
}

/**
 * Attach a finished listener to the message.
 *
 * @param {object} msg
 * @param {function} callback
 * @private
 */

function attachFinishedListener(msg, callback) {
  var eeMsg
  var eeSocket
  var finished = false

  function onFinish(error) {
    eeMsg.cancel()
    eeSocket.cancel()

    finished = true
    callback(error)
  }

  // finished on first message event
  eeMsg = eeSocket = first([[msg, 'end', 'finish']], onFinish)

  function onSocket(socket) {
    // remove listener
    msg.removeListener('socket', onSocket)

    if (finished) return
    if (eeMsg !== eeSocket) return

    // finished on first socket event
    eeSocket = first([[socket, 'error', 'close']], onFinish)
  }

  if (msg.socket) {
    // socket already assigned
    onSocket(msg.socket)
    return
  }

  // wait for socket to be assigned
  msg.on('socket', onSocket)

  if (msg.socket === undefined) {
    // istanbul ignore next: node.js 0.8 patch
    patchAssignSocket(msg, onSocket)
  }
}

/**
 * Attach the listener to the message.
 *
 * @param {object} msg
 * @return {function}
 * @private
 */

function attachListener(msg, listener) {
  var attached = msg.__onFinished

  // create a private single listener with queue
  if (!attached || !attached.queue) {
    attached = msg.__onFinished = createListener(msg)
    attachFinishedListener(msg, attached)
  }

  attached.queue.push(listener)
}

/**
 * Create listener on message.
 *
 * @param {object} msg
 * @return {function}
 * @private
 */

function createListener(msg) {
  function listener(err) {
    if (msg.__onFinished === listener) msg.__onFinished = null
    if (!listener.queue) return

    var queue = listener.queue
    listener.queue = null

    for (var i = 0; i < queue.length; i++) {
      queue[i](err, msg)
    }
  }

  listener.queue = []

  return listener
}

/**
 * Patch ServerResponse.prototype.assignSocket for node.js 0.8.
 *
 * @param {ServerResponse} res
 * @param {function} callback
 * @private
 */

// istanbul ignore next: node.js 0.8 patch
function patchAssignSocket(res, callback) {
  var assignSocket = res.assignSocket

  if (typeof assignSocket !== 'function') return

  // res.on('socket', callback) is broken in 0.8
  res.assignSocket = function _assignSocket(socket) {
    assignSocket.call(this, socket)
    callback(socket)
  }
}
<|endoftext|>


<commit_before>import Domodule from 'domodule';
import Ajax from 'bequest';
import formobj from 'formobj';
import tinytemplate from 'tinytemplate';
import { on } from 'domassist';

class Formjax extends Domodule {
  preInit() {
    if (this.el.tagName !== 'FORM') {
      throw new Error('Formjax need to be attached to a form');
    }

    this.method = this.el.getAttribute('method').toUpperCase();
    this.url = this.el.getAttribute('action');
    this.form = formobj(this.el);
    this.sending = false;

    on(this.form, 'submit', event => {
      this.submit(this.el, event);
    });
  }

  get defaults() {
    return {
      confirm: false,
      successReload: false,
      confirmText: 'Are you sure you want to submit?'
    };
  }

  confirm(sendForm) {
    if (window.confirm(this.options.confirmText)) { // eslint-disable-line no-alert
      sendForm();
    }
  }

  submit(el, event) {
    event.preventDefault();

    if (this.options.confirm) {
      this.confirm(this.sendForm.bind(this));
    } else {
      this.sendForm();
    }
  }

  sendForm() {
    if (this.sending) {
      return;
    }

    this.sending = true;
    const args = [this.url, this.method];

    if (this.method === 'GET') {
      let url = this.url;
      const uri = this.form.getQueryString();

      if (url.indexOf('?') > -1) {
        url = `${url}&${uri}`;
      } else {
        url = `${url}?${uri}`;
      }

      args[0] = url;
    } else {
      args.push(this.form.getJSON());
    }

    Ajax.request(...args, (err, resp) => {
      if (!err && resp.statusCode === 200) {
        if (this.options.successReload) {
          Formjax.reload();
        } else if (this.options.success) {
          Formjax.goTo(tinytemplate(this.options.success, resp.data));
        }
      } else {
        alert(resp.data.message);
        this.sending = false;
      }
    });
  }

  static reload() {
    window.location.reload();
  }

  static goTo(url) {
    window.location.href = url;
  }
}

Domodule.register('Formjax', Formjax);

export default Formjax;
<commit_msg>Removing eslint error<commit_after>import Domodule from 'domodule';
import Ajax from 'bequest';
import formobj from 'formobj';
import tinytemplate from 'tinytemplate';
import { on } from 'domassist';

class Formjax extends Domodule {
  preInit() {
    if (this.el.tagName !== 'FORM') {
      throw new Error('Formjax need to be attached to a form');
    }

    this.method = this.el.getAttribute('method').toUpperCase();
    this.url = this.el.getAttribute('action');
    this.form = formobj(this.el);
    this.sending = false;

    on(this.form, 'submit', event => {
      this.submit(this.el, event);
    });
  }

  get defaults() {
    return {
      confirm: false,
      successReload: false,
      confirmText: 'Are you sure you want to submit?'
    };
  }

  confirm(sendForm) {
    if (window.confirm(this.options.confirmText)) { // eslint-disable-line no-alert
      sendForm();
    }
  }

  submit(el, event) {
    event.preventDefault();

    if (this.options.confirm) {
      this.confirm(this.sendForm.bind(this));
    } else {
      this.sendForm();
    }
  }

  sendForm() {
    if (this.sending) {
      return;
    }

    this.sending = true;
    const args = [this.url, this.method];

    if (this.method === 'GET') {
      let url = this.url;
      const uri = this.form.getQueryString();

      if (url.indexOf('?') > -1) {
        url = `${url}&${uri}`;
      } else {
        url = `${url}?${uri}`;
      }

      args[0] = url;
    } else {
      args.push(this.form.getJSON());
    }

    Ajax.request(...args, (err, resp) => {
      if (!err && resp.statusCode === 200) {
        if (this.options.successReload) {
          Formjax.reload();
        } else if (this.options.success) {
          Formjax.goTo(tinytemplate(this.options.success, resp.data));
        }
      } else {
        alert(resp.data.message); // eslint-disable-line no-alert
        this.sending = false;
      }
    });
  }

  static reload() {
    window.location.reload();
  }

  static goTo(url) {
    window.location.href = url;
  }
}

Domodule.register('Formjax', Formjax);

export default Formjax;
<|endoftext|>


<commit_before>var net = require('net');
var util = require('util');
var assert = require('assert');
var Stream = require('stream');
var forge = require('node-forge');

// Compatibility shim for the browser
if (forge.forge) {
	forge = forge.forge;
}

function TLSSocket(socket, options, debug) {
	if (!(this instanceof TLSSocket)) return new TLSSocket(socket, options);

	var self = this;

	// Disallow wrapping TLSSocket in TLSSocket
	assert(!(socket instanceof TLSSocket));

	net.Socket.call(this);

	this._tlsOptions = options;
	this._secureEstablished = false;
        this.debug = debug || false;

	// Just a documented property to make secure sockets
	// distinguishable from regular ones.
	this.encrypted = true;

	if (!socket) { // connect() will be called later
		this.once('connect', function() {
			self._init(null);
		});
	} else {
		this._connecting = socket._connecting;

		this._socket = socket;
		this._init(socket);
	}

	// Make sure to setup all required properties like: `_connecting` before
	// starting the flow of the data
	this.readable = true;
	this.writable = true;
	this.read(0);
}
util.inherits(TLSSocket, net.Socket);

exports.TLSSocket = TLSSocket;

TLSSocket.prototype.log = function(arguments) {
    if (this.debug) {
        console.log.apply(console, Array.prototype.slice.call(arguments));
    }
}

TLSSocket.prototype._init = function(socket) {
	var self = this;
	var options = this._tlsOptions;

	this.ssl = forge.tls.createConnection({
		server: false,
		verify: function(connection, verified, depth, certs) {
			if (!options.rejectUnauthorized || !options.servername) {
				self.log('[tls] server certificate verification skipped');
				return true;
			}

			self.log('[tls] skipping certificate trust verification');
			verified = true;

			if (depth === 0) {
				var cn = certs[0].subject.getField('CN').value;
				if (cn !== options.servername) {
					verified = {
						alert: forge.tls.Alert.Description.bad_certificate,
						message: 'Certificate common name does not match hostname.'
					};
					console.warn('[tls] '+cn+' !== '+options.servername);
				}
				self.log('[tls] server certificate verified');
			}

			return verified;
		},
		connected: function(connection) {
			self.log('[tls] connected', self);
			// prepare some data to send (note that the string is interpreted as
			// 'binary' encoded, which works for HTTP which only uses ASCII, use
			// forge.util.encodeUtf8(str) otherwise
			//client.prepare('GET / HTTP/1.0\r\n\r\n');

			self._secureEstablished = true;
			self.emit('secure');
		},
		tlsDataReady: function(connection) {
			// encrypted data is ready to be sent to the server
			var data = connection.tlsData.getBytes();
			//self.log('[tls] sending encrypted: ', data, data.length);
			//self._socket.write(data, 'binary'); // encoding should be 'binary'
			net.Socket.prototype.write.call(self._socket, data, 'binary'); // encoding should be 'binary'
		},
		dataReady: function(connection) {
			// clear data from the server is ready
			var data = connection.data.getBytes(),
				buffer = new Buffer(data, 'binary');

			self.log('[tls] received: ', data);
			self.push(buffer);
		},
		closed: function() {
			self.log('[tls] disconnected');
			self.end();
		},
		error: function(connection, error) {
			self.log('[tls] error', error);
			error.toString = function () {
				return 'TLS error: '+error.message;
			};
			self.emit('error', error);
		}
	});

	this._socket.push = function (data) {
		self.ssl.process(data.toString('binary')); // encoding should be 'binary'
	};

	// Socket already has some buffered data - emulate receiving it
	if (socket && socket._readableState.length) {
		var buf;
		while ((buf = socket.read()) !== null) {
			this.ssl.process(buf); // Do we need this?
		}
	}

	this.log('[tls] init');

	// Start handshaking if connected
	if (this._socket.readyState != 'open') {
		this._socket.once('connect', function () {
			self.emit('connect');
			self._start();
		});
	} else {
		this._start();
	}
};

TLSSocket.prototype._start = function () {
	this.log('[tls] handshaking');
	this.ssl.handshake();
};

TLSSocket.prototype._read = function () {};

TLSSocket.prototype._writenow = function (data, encoding, cb) {
	cb = cb || function () {};

	this.log('[tls] sending: ', data.toString('utf8'));
	var result = this.ssl.prepare(data.toString('binary'));

	process.nextTick(function () {
		var err = (result !== false) ? null : 'Error while packaging data into a TLS record';
		cb(err);
	});
};

TLSSocket.prototype._write = function (data, encoding, cb) {
    var self = this;
    if (!self._secureEstablished) {
        this.once('secure', function () {
            self._writenow(data, encoding, cb);
        });
    } else {
        this._writenow(data, encoding, cb);
    }
};

TLSSocket.prototype.connect = function () {
	var self = this;

	self._connecting = true;

	this._socket = new net.Socket();
	this._socket.on('connect', function () {
		self._connecting = false;
		self._init(null);
	});
	this._socket.connect.apply(this._socket, arguments);

	return this;
};

TLSSocket.prototype.push = function () {
	net.Socket.prototype.push.apply(this, arguments);
	net.Socket.prototype.push.apply(this._socket, arguments);
};

function normalizeConnectArgs(listArgs) {
	var args = net._normalizeConnectArgs(listArgs);
	var options = args[0];
	var cb = args[1];
	if (util.isObject(listArgs[1])) {
		options = util._extend(options, listArgs[1]);
	} else if (util.isObject(listArgs[2])) {
		options = util._extend(options, listArgs[2]);
	}
	return (cb) ? [options, cb] : [options];
}

exports.connect = function (/* [port, host], options, cb */) {
	var args = normalizeConnectArgs(arguments);
	var options = args[0];
	var cb = args[1];

	var defaults = {
		rejectUnauthorized: '0' !== process.env.NODE_TLS_REJECT_UNAUTHORIZED,
		ciphers: null //tls.DEFAULT_CIPHERS
	};
	options = util._extend(defaults, options || {});

	var hostname = options.servername ||
		options.host ||
		options.socket && options.socket._host;

	var socket = new TLSSocket(options.socket, {
		rejectUnauthorized: options.rejectUnauthorized
	});

	// Not even started connecting yet (or probably resolving dns address),
	// catch socket errors and assign handle.
	if (options.socket) {
		options.socket.once('connect', function() {
			/*assert(options.socket._handle);
			socket._handle = options.socket._handle;
			socket._handle.owner = socket;
			socket.emit('connect');*/
		});
	}

	if (options.servername) {
		//socket.setServername(options.servername);
	}

	if (cb)
		socket.once('secure', cb);

	if (!options.socket) {
		socket.connect({
			host: options.host,
			port: options.port
		});
	}

	return socket;
};
<commit_msg>Move debug arg into options<commit_after>var net = require('net');
var util = require('util');
var assert = require('assert');
var Stream = require('stream');
var forge = require('node-forge');

// Compatibility shim for the browser
if (forge.forge) {
	forge = forge.forge;
}

function TLSSocket(socket, options) {
	if (!(this instanceof TLSSocket)) return new TLSSocket(socket, options);

	var self = this;

	// Disallow wrapping TLSSocket in TLSSocket
	assert(!(socket instanceof TLSSocket));

	net.Socket.call(this);

	this._tlsOptions = options;
	this._secureEstablished = false;

	// Just a documented property to make secure sockets
	// distinguishable from regular ones.
	this.encrypted = true;

	if (!socket) { // connect() will be called later
		this.once('connect', function() {
			self._init(null);
		});
	} else {
		this._connecting = socket._connecting;

		this._socket = socket;
		this._init(socket);
	}

	// Make sure to setup all required properties like: `_connecting` before
	// starting the flow of the data
	this.readable = true;
	this.writable = true;
	this.read(0);
}
util.inherits(TLSSocket, net.Socket);

exports.TLSSocket = TLSSocket;

TLSSocket.prototype.log = function(arguments) {
    if (this._tlsOptions.debug) {
        console.log.apply(console, Array.prototype.slice.call(arguments));
    }
}

TLSSocket.prototype._init = function(socket) {
	var self = this;
	var options = this._tlsOptions;

	this.ssl = forge.tls.createConnection({
		server: false,
		verify: function(connection, verified, depth, certs) {
			if (!options.rejectUnauthorized || !options.servername) {
				self.log('[tls] server certificate verification skipped');
				return true;
			}

			self.log('[tls] skipping certificate trust verification');
			verified = true;

			if (depth === 0) {
				var cn = certs[0].subject.getField('CN').value;
				if (cn !== options.servername) {
					verified = {
						alert: forge.tls.Alert.Description.bad_certificate,
						message: 'Certificate common name does not match hostname.'
					};
					console.warn('[tls] '+cn+' !== '+options.servername);
				}
				self.log('[tls] server certificate verified');
			}

			return verified;
		},
		connected: function(connection) {
			self.log('[tls] connected', self);
			// prepare some data to send (note that the string is interpreted as
			// 'binary' encoded, which works for HTTP which only uses ASCII, use
			// forge.util.encodeUtf8(str) otherwise
			//client.prepare('GET / HTTP/1.0\r\n\r\n');

			self._secureEstablished = true;
			self.emit('secure');
		},
		tlsDataReady: function(connection) {
			// encrypted data is ready to be sent to the server
			var data = connection.tlsData.getBytes();
			//self.log('[tls] sending encrypted: ', data, data.length);
			//self._socket.write(data, 'binary'); // encoding should be 'binary'
			net.Socket.prototype.write.call(self._socket, data, 'binary'); // encoding should be 'binary'
		},
		dataReady: function(connection) {
			// clear data from the server is ready
			var data = connection.data.getBytes(),
				buffer = new Buffer(data, 'binary');

			self.log('[tls] received: ', data);
			self.push(buffer);
		},
		closed: function() {
			self.log('[tls] disconnected');
			self.end();
		},
		error: function(connection, error) {
			self.log('[tls] error', error);
			error.toString = function () {
				return 'TLS error: '+error.message;
			};
			self.emit('error', error);
		}
	});

	this._socket.push = function (data) {
		self.ssl.process(data.toString('binary')); // encoding should be 'binary'
	};

	// Socket already has some buffered data - emulate receiving it
	if (socket && socket._readableState.length) {
		var buf;
		while ((buf = socket.read()) !== null) {
			this.ssl.process(buf); // Do we need this?
		}
	}

	this.log('[tls] init');

	// Start handshaking if connected
	if (this._socket.readyState != 'open') {
		this._socket.once('connect', function () {
			self.emit('connect');
			self._start();
		});
	} else {
		this._start();
	}
};

TLSSocket.prototype._start = function () {
	this.log('[tls] handshaking');
	this.ssl.handshake();
};

TLSSocket.prototype._read = function () {};

TLSSocket.prototype._writenow = function (data, encoding, cb) {
	cb = cb || function () {};

	this.log('[tls] sending: ', data.toString('utf8'));
	var result = this.ssl.prepare(data.toString('binary'));

	process.nextTick(function () {
		var err = (result !== false) ? null : 'Error while packaging data into a TLS record';
		cb(err);
	});
};

TLSSocket.prototype._write = function (data, encoding, cb) {
    var self = this;
    if (!self._secureEstablished) {
        this.once('secure', function () {
            self._writenow(data, encoding, cb);
        });
    } else {
        this._writenow(data, encoding, cb);
    }
};

TLSSocket.prototype.connect = function () {
	var self = this;

	self._connecting = true;

	this._socket = new net.Socket();
	this._socket.on('connect', function () {
		self._connecting = false;
		self._init(null);
	});
	this._socket.connect.apply(this._socket, arguments);

	return this;
};

TLSSocket.prototype.push = function () {
	net.Socket.prototype.push.apply(this, arguments);
	net.Socket.prototype.push.apply(this._socket, arguments);
};

function normalizeConnectArgs(listArgs) {
	var args = net._normalizeConnectArgs(listArgs);
	var options = args[0];
	var cb = args[1];
	if (util.isObject(listArgs[1])) {
		options = util._extend(options, listArgs[1]);
	} else if (util.isObject(listArgs[2])) {
		options = util._extend(options, listArgs[2]);
	}
	return (cb) ? [options, cb] : [options];
}

exports.connect = function (/* [port, host], options, cb */) {
	var args = normalizeConnectArgs(arguments);
	var options = args[0];
	var cb = args[1];

	var defaults = {
		rejectUnauthorized: '0' !== process.env.NODE_TLS_REJECT_UNAUTHORIZED,
		ciphers: null //tls.DEFAULT_CIPHERS
	};
	options = util._extend(defaults, options || {});

	var hostname = options.servername ||
		options.host ||
		options.socket && options.socket._host;

	var socket = new TLSSocket(options.socket, {
		rejectUnauthorized: options.rejectUnauthorized
	});

	// Not even started connecting yet (or probably resolving dns address),
	// catch socket errors and assign handle.
	if (options.socket) {
		options.socket.once('connect', function() {
			/*assert(options.socket._handle);
			socket._handle = options.socket._handle;
			socket._handle.owner = socket;
			socket.emit('connect');*/
		});
	}

	if (options.servername) {
		//socket.setServername(options.servername);
	}

	if (cb)
		socket.once('secure', cb);

	if (!options.socket) {
		socket.connect({
			host: options.host,
			port: options.port
		});
	}

	return socket;
};
<|endoftext|>


<commit_before>function Texture(gl, width, height) {
    this.gl = gl;
    this.width = width; this.height = height;
    this.texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, this.texture);

    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
}
Texture.prototype.bind = function (n, program, name) {
    var gl = this.gl;
    gl.activeTexture([gl.TEXTURE0, gl.TEXTURE1, gl.TEXTURE2][n]);
    gl.bindTexture(gl.TEXTURE_2D, this.texture);
    gl.uniform1i(gl.getUniformLocation(program, name), n);
}
Texture.prototype.fill = function (data) {
    var gl = this.gl;
    gl.bindTexture(gl.TEXTURE_2D, this.texture);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, this.width, this.height, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, data);
}

function render(canvas, videoFrame, vlc) {
    if (!vlc.playing) return;
    var gl = canvas.gl;
    var len = videoFrame.length;
    gl.y.fill(videoFrame.subarray(0, videoFrame.uOffset));
    gl.u.fill(videoFrame.subarray(videoFrame.uOffset, videoFrame.vOffset));
    gl.v.fill(videoFrame.subarray(videoFrame.vOffset, len));
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
}

var renderFallback = function(canvas, videoFrame) {
    var buf = canvas.img.data;
    var width = videoFrame.width;
    var height = videoFrame.height;
    for (var i = 0; i < height; ++i) {
        for (var j = 0; j < width; ++j) {
            var o = (j + (width*i))*4;
            buf[o + 0] = videoFrame[o+2];
            buf[o + 1] = videoFrame[o+1];
            buf[o + 2] = videoFrame[o+0];
            buf[o + 3] = videoFrame[o+3];
        }
    };
    canvas.ctx.putImageData(canvas.img, 0, 0);
}

function setupCanvas(canvas, vlc, fallbackRenderer) {
    if (!fallbackRenderer) canvas.gl = canvas.getContext("webgl"); // Comment this line out to test fallback
    var gl = canvas.gl;
    if (!gl || fallbackRenderer) {
        console.log(fallbackRenderer ? "Fallback renderer forced, not using WebGL" : "Unable to initialize WebGL, falling back to canvas rendering");
        vlc.pixelFormat = vlc.RV32;
        canvas.ctx = canvas.getContext("2d");
        delete canvas.gl; // in case of fallback renderer
        return;
    }

    vlc.pixelFormat = vlc.I420;
    canvas.I420Program = gl.createProgram();
    var program = canvas.I420Program;
    var vertexShaderSource = [
        "attribute highp vec4 aVertexPosition;",
        "attribute vec2 aTextureCoord;",
        "varying highp vec2 vTextureCoord;",
        "void main(void) {",
        " gl_Position = aVertexPosition;",
        " vTextureCoord = aTextureCoord;",
        "}"].join("\n");
    var vertexShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertexShader, vertexShaderSource);
    gl.compileShader(vertexShader);
    var fragmentShaderSource = [
        "precision highp float;",
        "varying lowp vec2 vTextureCoord;",
        "uniform sampler2D YTexture;",
        "uniform sampler2D UTexture;",
        "uniform sampler2D VTexture;",
        "const mat4 YUV2RGB = mat4",
        "(",
        " 1.1643828125, 0, 1.59602734375, -.87078515625,",
        " 1.1643828125, -.39176171875, -.81296875, .52959375,",
        " 1.1643828125, 2.017234375, 0, -1.081390625,",
        " 0, 0, 0, 1",
        ");",
        "void main(void) {",
        " gl_FragColor = vec4( texture2D(YTexture, vTextureCoord).x, texture2D(UTexture, vTextureCoord).x, texture2D(VTexture, vTextureCoord).x, 1) * YUV2RGB;",
        "}"].join("\n");

    var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragmentShader, fragmentShaderSource);
    gl.compileShader(fragmentShader);
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    gl.useProgram(program);
    if(!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        console.log("Shader link failed.");
    }
    var vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition");
    gl.enableVertexAttribArray(vertexPositionAttribute);
    var textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord");
    gl.enableVertexAttribArray(textureCoordAttribute);

    var verticesBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, verticesBuffer);
    gl.bufferData(gl.ARRAY_BUFFER,
                  new Float32Array([1.0, 1.0, 0.0, -1.0, 1.0, 0.0, 1.0, -1.0, 0.0, -1.0, -1.0, 0.0]),
                  gl.STATIC_DRAW);
    gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
    var texCoordBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
    gl.bufferData(gl.ARRAY_BUFFER,
                  new Float32Array([1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0]),
                  gl.STATIC_DRAW);
    gl.vertexAttribPointer(textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
}

function frameSetup(canvas, width, height, pixelFormat) {
    var gl = canvas.gl;
    canvas.width = width;
    canvas.height = height;
    if (!gl) {
        canvas.img = canvas.ctx.createImageData(width, height);
        return;
    }
    var program = canvas.I420Program;
    gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
    gl.y = new Texture(gl, width, height);
    gl.u = new Texture(gl, width >> 1, height >> 1);
    gl.v = new Texture(gl, width >> 1, height >> 1);
    gl.y.bind(0, program, "YTexture");
    gl.u.bind(1, program, "UTexture");
    gl.v.bind(2, program, "VTexture");
}

module.exports = {
    init: function(canvas,params,fallbackRenderer) {
        var wcAddon = require("webchimera.js");

        this._canvas = canvas;

        if (typeof params !== 'undefined') var vlc = wcAddon.createPlayer(params);
        else var vlc = wcAddon.createPlayer();

        if (typeof canvas === 'string') setupCanvas(window.document.querySelector(canvas), vlc, fallbackRenderer);
        else setupCanvas(canvas, vlc, fallbackRenderer);

        vlc.onFrameSetup =
            function(width, height, pixelFormat) {
                frameSetup(canvas, width, height, pixelFormat);

                canvas.addEventListener("webglcontextlost",
                    function(event) {
                        event.preventDefault();
                        console.log("webgl context lost");
                    }, false);

                canvas.addEventListener("webglcontextrestored",
                    function(w,h,p) {
                        return function(event) {
                            setupCanvas(canvas, vlc);
                            frameSetup(canvas, w, h, p);
                            console.log("webgl context restored");
                        }
                    }(width,height,pixelFormat), false);

            };
        setFrame = this;
        vlc.onFrameReady =
            function(videoFrame) {
                (canvas.gl ? render : renderFallback)(canvas, videoFrame, vlc);
                setFrame._lastFrame = videoFrame;
            };
        return vlc;
    },

    clearCanvas: function() {
        if (this._lastFrame) {
            var gl = this._canvas.gl,
                arr1 = new Uint8Array(this._lastFrame.uOffset),
                arr2 = new Uint8Array(this._lastFrame.vOffset - this._lastFrame.uOffset);

            for (var i = 0; i < arr2.length; ++i) arr2[i] = 128;

            gl.y.fill(arr1);
            gl.u.fill(arr2);
            gl.v.fill(arr2);

            gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
        }
    },

    _lastFrame: false,
    _canvas: false
};
<commit_msg>there are no need to check if vlcParams si undefined<commit_after>function Texture(gl, width, height) {
    this.gl = gl;
    this.width = width; this.height = height;
    this.texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, this.texture);

    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
}
Texture.prototype.bind = function (n, program, name) {
    var gl = this.gl;
    gl.activeTexture([gl.TEXTURE0, gl.TEXTURE1, gl.TEXTURE2][n]);
    gl.bindTexture(gl.TEXTURE_2D, this.texture);
    gl.uniform1i(gl.getUniformLocation(program, name), n);
}
Texture.prototype.fill = function (data) {
    var gl = this.gl;
    gl.bindTexture(gl.TEXTURE_2D, this.texture);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, this.width, this.height, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, data);
}

function render(canvas, videoFrame, vlc) {
    if (!vlc.playing) return;
    var gl = canvas.gl;
    var len = videoFrame.length;
    gl.y.fill(videoFrame.subarray(0, videoFrame.uOffset));
    gl.u.fill(videoFrame.subarray(videoFrame.uOffset, videoFrame.vOffset));
    gl.v.fill(videoFrame.subarray(videoFrame.vOffset, len));
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
}

var renderFallback = function(canvas, videoFrame) {
    var buf = canvas.img.data;
    var width = videoFrame.width;
    var height = videoFrame.height;
    for (var i = 0; i < height; ++i) {
        for (var j = 0; j < width; ++j) {
            var o = (j + (width*i))*4;
            buf[o + 0] = videoFrame[o+2];
            buf[o + 1] = videoFrame[o+1];
            buf[o + 2] = videoFrame[o+0];
            buf[o + 3] = videoFrame[o+3];
        }
    };
    canvas.ctx.putImageData(canvas.img, 0, 0);
}

function setupCanvas(canvas, vlc, fallbackRenderer) {
    if (!fallbackRenderer) canvas.gl = canvas.getContext("webgl"); // Comment this line out to test fallback
    var gl = canvas.gl;
    if (!gl || fallbackRenderer) {
        console.log(fallbackRenderer ? "Fallback renderer forced, not using WebGL" : "Unable to initialize WebGL, falling back to canvas rendering");
        vlc.pixelFormat = vlc.RV32;
        canvas.ctx = canvas.getContext("2d");
        delete canvas.gl; // in case of fallback renderer
        return;
    }

    vlc.pixelFormat = vlc.I420;
    canvas.I420Program = gl.createProgram();
    var program = canvas.I420Program;
    var vertexShaderSource = [
        "attribute highp vec4 aVertexPosition;",
        "attribute vec2 aTextureCoord;",
        "varying highp vec2 vTextureCoord;",
        "void main(void) {",
        " gl_Position = aVertexPosition;",
        " vTextureCoord = aTextureCoord;",
        "}"].join("\n");
    var vertexShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertexShader, vertexShaderSource);
    gl.compileShader(vertexShader);
    var fragmentShaderSource = [
        "precision highp float;",
        "varying lowp vec2 vTextureCoord;",
        "uniform sampler2D YTexture;",
        "uniform sampler2D UTexture;",
        "uniform sampler2D VTexture;",
        "const mat4 YUV2RGB = mat4",
        "(",
        " 1.1643828125, 0, 1.59602734375, -.87078515625,",
        " 1.1643828125, -.39176171875, -.81296875, .52959375,",
        " 1.1643828125, 2.017234375, 0, -1.081390625,",
        " 0, 0, 0, 1",
        ");",
        "void main(void) {",
        " gl_FragColor = vec4( texture2D(YTexture, vTextureCoord).x, texture2D(UTexture, vTextureCoord).x, texture2D(VTexture, vTextureCoord).x, 1) * YUV2RGB;",
        "}"].join("\n");

    var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragmentShader, fragmentShaderSource);
    gl.compileShader(fragmentShader);
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    gl.useProgram(program);
    if(!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        console.log("Shader link failed.");
    }
    var vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition");
    gl.enableVertexAttribArray(vertexPositionAttribute);
    var textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord");
    gl.enableVertexAttribArray(textureCoordAttribute);

    var verticesBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, verticesBuffer);
    gl.bufferData(gl.ARRAY_BUFFER,
                  new Float32Array([1.0, 1.0, 0.0, -1.0, 1.0, 0.0, 1.0, -1.0, 0.0, -1.0, -1.0, 0.0]),
                  gl.STATIC_DRAW);
    gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
    var texCoordBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
    gl.bufferData(gl.ARRAY_BUFFER,
                  new Float32Array([1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0]),
                  gl.STATIC_DRAW);
    gl.vertexAttribPointer(textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
}

function frameSetup(canvas, width, height, pixelFormat) {
    var gl = canvas.gl;
    canvas.width = width;
    canvas.height = height;
    if (!gl) {
        canvas.img = canvas.ctx.createImageData(width, height);
        return;
    }
    var program = canvas.I420Program;
    gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
    gl.y = new Texture(gl, width, height);
    gl.u = new Texture(gl, width >> 1, height >> 1);
    gl.v = new Texture(gl, width >> 1, height >> 1);
    gl.y.bind(0, program, "YTexture");
    gl.u.bind(1, program, "UTexture");
    gl.v.bind(2, program, "VTexture");
}

module.exports = {
    init: function(canvas,params,fallbackRenderer) {
        var wcAddon = require("webchimera.js");

        this._canvas = canvas;

        var vlc = wcAddon.createPlayer(params);

        if (typeof canvas === 'string') setupCanvas(window.document.querySelector(canvas), vlc, fallbackRenderer);
        else setupCanvas(canvas, vlc, fallbackRenderer);

        vlc.onFrameSetup =
            function(width, height, pixelFormat) {
                frameSetup(canvas, width, height, pixelFormat);

                canvas.addEventListener("webglcontextlost",
                    function(event) {
                        event.preventDefault();
                        console.log("webgl context lost");
                    }, false);

                canvas.addEventListener("webglcontextrestored",
                    function(w,h,p) {
                        return function(event) {
                            setupCanvas(canvas, vlc);
                            frameSetup(canvas, w, h, p);
                            console.log("webgl context restored");
                        }
                    }(width,height,pixelFormat), false);

            };
        setFrame = this;
        vlc.onFrameReady =
            function(videoFrame) {
                (canvas.gl ? render : renderFallback)(canvas, videoFrame, vlc);
                setFrame._lastFrame = videoFrame;
            };
        return vlc;
    },

    clearCanvas: function() {
        if (this._lastFrame) {
            var gl = this._canvas.gl,
                arr1 = new Uint8Array(this._lastFrame.uOffset),
                arr2 = new Uint8Array(this._lastFrame.vOffset - this._lastFrame.uOffset);

            for (var i = 0; i < arr2.length; ++i) arr2[i] = 128;

            gl.y.fill(arr1);
            gl.u.fill(arr2);
            gl.v.fill(arr2);

            gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
        }
    },

    _lastFrame: false,
    _canvas: false
};
<|endoftext|>


<commit_before>"use strict";

var path = require('path');
var fs = require('fs');

module.exports = function (gulp, sep) {
	sep = sep || ':';

	var submodules = {};

	gulp.submodule = function(submodule, opt) {
		var source;

		if (opt.package || opt.pkg) {
			source = opt.package || opt.pkg;
		} else {
			source = opt.filepath || submodule;
			source = path.resolve(source);

			// if source is directory, append 'gulpfile.js' to the path
			if (fs.lstatSync(source).isDirectory()) {
				source = path.join(source, 'gulpfile.js');
			}
		}

		// get submodules task name
		function getName(name) {
			return [submodule, name].join(sep);
		}

		submodules[submodule] = { tasks: [], ret: null };

		// cache original gulp.task method
		var _task = gulp.task;
		gulp.task = function(name, deps, fn) {
			// prefix deps with submodule name
			if (Array.isArray(deps)) {
				deps = deps.map(getName);
			} else if (typeof deps === 'string') {
				deps = getName(deps);
			}
			submodules[submodule].tasks.push(name);
			// call original gulp.task method
			return _task.call(this, getName(name), deps, fn);
		};
		var mod = require(source);
		submodules[submodule].ret = mod;
		// restore original gulp.task method
		gulp.task = _task;

		// return required module
		return mod;
	};

	return submodules;
};
<commit_msg>opt parameter is actually optional now<commit_after>"use strict";

var path = require('path');
var fs = require('fs');

module.exports = function (gulp, sep) {
	sep = sep || ':';

	var submodules = {};

	gulp.submodule = function(submodule, opt) {
		opt = opt || {};

		var source;

		if (opt.package || opt.pkg) {
			source = opt.package || opt.pkg;
		} else {
			source = opt.filepath || submodule;
			source = path.resolve(source);

			// if source is directory, append 'gulpfile.js' to the path
			if (fs.lstatSync(source).isDirectory()) {
				source = path.join(source, 'gulpfile.js');
			}
		}

		// get submodules task name
		function getName(name) {
			return [submodule, name].join(sep);
		}

		submodules[submodule] = { tasks: [], ret: null };

		// cache original gulp.task method
		var _task = gulp.task;
		gulp.task = function(name, deps, fn) {
			// prefix deps with submodule name
			if (Array.isArray(deps)) {
				deps = deps.map(getName);
			} else if (typeof deps === 'string') {
				deps = getName(deps);
			}
			submodules[submodule].tasks.push(name);
			// call original gulp.task method
			return _task.call(this, getName(name), deps, fn);
		};
		var mod = require(source);
		submodules[submodule].ret = mod;
		// restore original gulp.task method
		gulp.task = _task;

		// return required module
		return mod;
	};

	return submodules;
};
<|endoftext|>