<commit_before>const Util = require('./util/Util');

module.exports = {
  // "Root" classes (starting points)
  BaseClient: require('./client/BaseClient'),
  Client: require('./client/Client'),
  Shard: require('./sharding/Shard'),
  ShardClientUtil: require('./sharding/ShardClientUtil'),
  ShardingManager: require('./sharding/ShardingManager'),
  WebhookClient: require('./client/WebhookClient'),

  // Utilities
  Collection: require('./util/Collection'),
  Constants: require('./util/Constants'),
  DataResolver: require('./util/DataResolver'),
  DataStore: require('./stores/DataStore'),
  DiscordAPIError: require('./rest/DiscordAPIError'),
  Permissions: require('./util/Permissions'),
  Snowflake: require('./util/Snowflake'),
  SnowflakeUtil: require('./util/Snowflake'),
  Structures: require('./util/Structures'),
  Util: Util,
  util: Util,
  version: require('../package.json').version,

  // Stores
  ChannelStore: require('./stores/ChannelStore'),
  ClientPresenceStore: require('./stores/ClientPresenceStore'),
  EmojiStore: require('./stores/EmojiStore'),
  GuildChannelStore: require('./stores/GuildChannelStore'),
  GuildMemberStore: require('./stores/GuildMemberStore'),
  GuildStore: require('./stores/GuildStore'),
  ReactionUserStore: require('./stores/ReactionUserStore'),
  MessageStore: require('./stores/MessageStore'),
  PresenceStore: require('./stores/PresenceStore'),
  RoleStore: require('./stores/RoleStore'),
  UserStore: require('./stores/UserStore'),

  // Shortcuts to Util methods
  escapeMarkdown: Util.escapeMarkdown,
  fetchRecommendedShards: Util.fetchRecommendedShards,
  splitMessage: Util.splitMessage,

  // Structures
  Base: require('./structures/Base'),
  Activity: require('./structures/Presence').Activity,
  CategoryChannel: require('./structures/CategoryChannel'),
  Channel: require('./structures/Channel'),
  ClientApplication: require('./structures/ClientApplication'),
  get ClientUser() {
    // This is a getter so that it properly extends any custom User class
    return require('./structures/ClientUser');
  },
  ClientUserChannelOverride: require('./structures/ClientUserChannelOverride'),
  ClientUserGuildSettings: require('./structures/ClientUserGuildSettings'),
  ClientUserSettings: require('./structures/ClientUserSettings'),
  Collector: require('./structures/interfaces/Collector'),
  DMChannel: require('./structures/DMChannel'),
  Emoji: require('./structures/Emoji'),
  GroupDMChannel: require('./structures/GroupDMChannel'),
  Guild: require('./structures/Guild'),
  GuildAuditLogs: require('./structures/GuildAuditLogs'),
  GuildChannel: require('./structures/GuildChannel'),
  GuildMember: require('./structures/GuildMember'),
  Invite: require('./structures/Invite'),
  Message: require('./structures/Message'),
  MessageAttachment: require('./structures/MessageAttachment'),
  MessageCollector: require('./structures/MessageCollector'),
  MessageEmbed: require('./structures/MessageEmbed'),
  MessageMentions: require('./structures/MessageMentions'),
  MessageReaction: require('./structures/MessageReaction'),
  PermissionOverwrites: require('./structures/PermissionOverwrites'),
  Presence: require('./structures/Presence').Presence,
  ReactionCollector: require('./structures/ReactionCollector'),
  ReactionEmoji: require('./structures/ReactionEmoji'),
  RichPresenceAssets: require('./structures/Presence').RichPresenceAssets,
  Role: require('./structures/Role'),
  TextChannel: require('./structures/TextChannel'),
  User: require('./structures/User'),
  UserConnection: require('./structures/UserConnection'),
  VoiceChannel: require('./structures/VoiceChannel'),
  VoiceRegion: require('./structures/VoiceRegion'),
  Webhook: require('./structures/Webhook'),

  WebSocket: require('./WebSocket'),
};
<commit_msg>Add exports for new util functions<commit_after>const Util = require('./util/Util');

module.exports = {
  // "Root" classes (starting points)
  BaseClient: require('./client/BaseClient'),
  Client: require('./client/Client'),
  Shard: require('./sharding/Shard'),
  ShardClientUtil: require('./sharding/ShardClientUtil'),
  ShardingManager: require('./sharding/ShardingManager'),
  WebhookClient: require('./client/WebhookClient'),

  // Utilities
  Collection: require('./util/Collection'),
  Constants: require('./util/Constants'),
  DataResolver: require('./util/DataResolver'),
  DataStore: require('./stores/DataStore'),
  DiscordAPIError: require('./rest/DiscordAPIError'),
  Permissions: require('./util/Permissions'),
  Snowflake: require('./util/Snowflake'),
  SnowflakeUtil: require('./util/Snowflake'),
  Structures: require('./util/Structures'),
  Util: Util,
  util: Util,
  version: require('../package.json').version,

  // Stores
  ChannelStore: require('./stores/ChannelStore'),
  ClientPresenceStore: require('./stores/ClientPresenceStore'),
  EmojiStore: require('./stores/EmojiStore'),
  GuildChannelStore: require('./stores/GuildChannelStore'),
  GuildMemberStore: require('./stores/GuildMemberStore'),
  GuildStore: require('./stores/GuildStore'),
  ReactionUserStore: require('./stores/ReactionUserStore'),
  MessageStore: require('./stores/MessageStore'),
  PresenceStore: require('./stores/PresenceStore'),
  RoleStore: require('./stores/RoleStore'),
  UserStore: require('./stores/UserStore'),

  // Shortcuts to Util methods
  discordSort: Util.discordSort,
  escapeMarkdown: Util.escapeMarkdown,
  fetchRecommendedShards: Util.fetchRecommendedShards,
  resolveColor: Util.resolveColor,
  resolveString: Util.resolveString,
  splitMessage: Util.splitMessage,

  // Structures
  Base: require('./structures/Base'),
  Activity: require('./structures/Presence').Activity,
  CategoryChannel: require('./structures/CategoryChannel'),
  Channel: require('./structures/Channel'),
  ClientApplication: require('./structures/ClientApplication'),
  get ClientUser() {
    // This is a getter so that it properly extends any custom User class
    return require('./structures/ClientUser');
  },
  ClientUserChannelOverride: require('./structures/ClientUserChannelOverride'),
  ClientUserGuildSettings: require('./structures/ClientUserGuildSettings'),
  ClientUserSettings: require('./structures/ClientUserSettings'),
  Collector: require('./structures/interfaces/Collector'),
  DMChannel: require('./structures/DMChannel'),
  Emoji: require('./structures/Emoji'),
  GroupDMChannel: require('./structures/GroupDMChannel'),
  Guild: require('./structures/Guild'),
  GuildAuditLogs: require('./structures/GuildAuditLogs'),
  GuildChannel: require('./structures/GuildChannel'),
  GuildMember: require('./structures/GuildMember'),
  Invite: require('./structures/Invite'),
  Message: require('./structures/Message'),
  MessageAttachment: require('./structures/MessageAttachment'),
  MessageCollector: require('./structures/MessageCollector'),
  MessageEmbed: require('./structures/MessageEmbed'),
  MessageMentions: require('./structures/MessageMentions'),
  MessageReaction: require('./structures/MessageReaction'),
  PermissionOverwrites: require('./structures/PermissionOverwrites'),
  Presence: require('./structures/Presence').Presence,
  ReactionCollector: require('./structures/ReactionCollector'),
  ReactionEmoji: require('./structures/ReactionEmoji'),
  RichPresenceAssets: require('./structures/Presence').RichPresenceAssets,
  Role: require('./structures/Role'),
  TextChannel: require('./structures/TextChannel'),
  User: require('./structures/User'),
  UserConnection: require('./structures/UserConnection'),
  VoiceChannel: require('./structures/VoiceChannel'),
  VoiceRegion: require('./structures/VoiceRegion'),
  Webhook: require('./structures/Webhook'),

  WebSocket: require('./WebSocket'),
};
<|endoftext|>


<commit_before>var Promise = require('promise');
var shexjs = require("shex");
var n3 = require("n3");
var isNode = require('detect-node');
var DefaultBase = "";
var jsld = require('jsonld')

Validator.prototype = {
    updateSchema: function (base, schemaText) {
        this.schema = parseSchema(base ,schemaText);
        this.schema.done(this.callbacks.schemaParsed, this.callbacks.schemaParseError);
    },
    updateData: function (dataText) {
        this.data = parseData(dataText);
        this.data.done(this.callbacks.dataParsed, this.callbacks.dataParseError);
    },
    findShapes: function () {
        var _this = this;
        return Promise.all([this.schema, this.data]).then(function (a) {
            // console.log('showing shapes');
            // console.log(this.schema);
            // console.log(this.data);
        });
    },
    validate: function(startingNodes) {
        var _this = this;
        return Promise.all([this.schema, this.data, this.options]).then(function (a) {
            console.log('validate called a:',a);
            var node = Object.keys(a[2].resourceShapeMap)[0];
            var validator = shexjs.Validator.construct(a[0].schema);
            try {

                var result = validator.validate(shexjs.Util.makeN3DB(a[1].db), node, a[2].resourceShapeMap[node]);
            } catch (error){
                console.error(error);
            }
            console.log('valres',result);
            // console.log('callbacks in validator',_this.callbacks);
            // console.log('db to validate',a[1].db)
            return cleanResult(result, a[1].triples, _this.callbacks.validationResult)
        });
    }
};

function isJSON(str) {
    try {
        return (JSON.parse(str) && !!str);
    } catch (e) {
        return false;
    }
}

function parseData(dataText){
    return new Promise(function (resolve, reject) {
        var lineIndex = new Object();
        var db = n3.Store({meta:true});
        var turtledata = '';
        var inputData = '';
        if (isJSON(dataText)) {
          print('json-ld passed to shex-validator');
          jsld.toRDF(dataText, {format: 'application/nquads'}, function(err, nquads) {
            console.log(nquads);
            console.log(err);
            turtledata = nquads;
            inputData = nquads;
          });
        } else {
          inputData = dataText;
        }

        n3.Parser({documentIRI: DefaultBase}).parse(inputData, function (error, triple, prefixes) {
            // console.log('db', db);
            // console.log('DB');
            // console.log('triple callback')
            if (error) {
                // throw Error("error parsing " + data + ": " + error);
                reject(parseN3Error(error));
            } else if (triple) {
                // console.log("N3triple",triple);
                lineIndex[JSON.stringify({'subject':triple.subject,'predicate':triple.predicate,'object':triple.object,'graph':triple.graph})] = triple.line;
                lineIndex[triple.line] = {'object':triple.object,'subject':triple.subject,'predicate':triple.predicate,'graph':triple.graph};
                console.log('triple added ',triple);
                db.addTriple(triple.subject, triple.predicate, triple.object,triple.graph, {line:triple.line});

            } else {
                // db.setMetaFlag(true);
                var triples = db.getTriples();
                // db.setMetaFlag(false);
                for (var i = triples.length - 1; i >= 0; i--) {
                    var triple_key = JSON.stringify({'subject':triples[i].subject,'predicate':triples[i].predicate,'object':triples[i].object,'graph':""});
                    triples[i].line = lineIndex[triple_key];
                }
                resolve({db: db, triples:triples, turtledata:turtledata});
            }
        });

    });
}

function parseSchema(base, schemaText) {
    return new Promise(function (resolve, reject) {
        var schema;
        try {
            schema = shexjs.Parser.construct(base).parse(schemaText);
        }
        catch (e) {
            reject(e);
        }
        resolve({schema: schema, shapes: schema.shapes});

    });
};

function parseReqLevels(rawSchema, levels){
    var defaultLevels = ['`MUST`','`MAY`','`SHOULD`'];
    var quoteChar = '`';
    if (levels) {
        defaultLevels = levels;
        for (var i = levels.length - 1; i >= 0; i--) {
            defaultLevels[i] = quoteChar + levels[i] + quoteChar;
        }
    }

    var lines = [];
    var result = {'data':'',lineRules:{}};

    lines = rawSchema.split("\n");

    var re = new RegExp('(.*)('+defaultLevels[0]+'|'+defaultLevels[1]+'|'+defaultLevels[2]+')(.*)');

    for (var i = 0; i <= lines.length - 1; i++) {
        var match = lines[i].match(re);
        if (match) {
            result.lineRules[i] = match[2];
            result.data = String.concat(result.data,match[3] + '\n');
        } else {
            result.data = String.concat(result.data,lines[i] + '\n');
        }
    }
    console.log('PREPROCESSING OF schema DONE',result.data);
    return result
}

function cleanResult(result, parsedTriples, callback){
    console.log('validation result', result);
    var errors = [];
    var matches = [];
    if (result.type == 'Failure'){
        errors = cleanErrors(parsedTriples, result);
    } else {
        matches = cleanMatches(parsedTriples, result);
        // console.log('result',result);
        // console.log('matches',matches);
    }
    var clean_result = {
            errors: errors,
            matches: matches,
            startingResource: result.node,
            passed: errors.length === 0,
            full_result:result
        };
    return callback(clean_result);
}

function parseN3Error(error) {
    var line = error.message.match(/line [0-9]*/g);

    line = (line && line.length > 0 && line[0].length > 5)?Number(line[0].substr(5)):null;

    return {
        message: error.message,
        line: line,
        column: 0
    }
}
// returns the matched triples and the corresponding lines

function cleanMatches(parsedTriples, validationResult){
    var results = [];
    var messages = [];
    var matches = parseMatches(validationResult.solution);
    for (var i = matches.length - 1; i >= 0; i--) {
        var currentMatch = {};
        currentMatch.line = matchTriple(parsedTriples, matches[i]).line;
        currentMatch.subject = matches[i].subject;
        currentMatch.predicate = matches[i].predicate;

        if (matches[i].object.value && matches[i].object.type) {
                currentMatch.object = '<type>:' +String(matches[i].object.type) +' <value>:'+ String(matches[i].object.value);

        } else if (matches[i].object.value) {
                currentMatch.object = '<value>:'+ String(matches[i].object.value);
        } else {
            currentMatch.object = matches[i].object;
        }
            currentMatch.message = 'Matched '+ String(currentMatch.predicate)+' '+ String(currentMatch.object) + ' on line ' + String(currentMatch.line);

        // console.log('cleanMatches',matches[i]);

        if (!messages.includes(currentMatch.message)){
            results.push(currentMatch);
            messages.push(currentMatch.message);
        }

    }
    // console.log('results returned',results);
    return results
}

function parseMatches(solution){
    var results = [];
    var values = Object.values(solution)
    // console.log('object values',values);
    for (var i = values.length - 1; i >= 0; i--) {
        if (values[i].subject && values[i].predicate && values[i].object){
            // console.log('istriple',values[i]);
            results.push(values[i]);
        }
        else if (typeof(values[i]) == 'string'){
            // console.log('string found',values[i])
        } else {
            Array.prototype.push.apply(results,parseMatches(values[i]));
        }
    }

    return results
}

function parseErrors(errors){
    var results = [];
    for (var i = errors.length - 1; i >= 0; i--) {
        if (Array.isArray(errors[i])){
            // console.log('rec call',errors[i]);
            Array.prototype.push.apply(results,parseErrors(errors[i]));

        } else {
            // console.log('non rec call',errors[i]);
            results.push(errors[i])
        }
    }
    console.log('results',results);
    return results
}

function matchTriple(parsedTriples, keyTriple){
    var match;

    try {
        match = parsedTriples.find(function (triple) {
            var lookup = []
            if (typeof(keyTriple.subject) == 'string' ){
                if (triple.subject === keyTriple.subject){
                    lookup.push(true)
                } else{
                    return false
                }
            } else {
                lookup.push(true);
            }
            // console.log('subject',keyTriple.subject);

            if (typeof(keyTriple.predicate) == 'string'){
                if (triple.predicate === keyTriple.predicate){
                    lookup.push(true);
                } else {
                    return false
                }
            }else {
                lookup.push(true);
            }

            // console.log('predicate',keyTriple.predicate);

            if (typeof(keyTriple.object) == 'string'){
                if (triple.object === keyTriple.object){
                    lookup.push(true);
                } else {
                    return false
                }
            }else {
                lookup.push(true);
            }
            // console.log('object',keyTriple.object);

            return lookup[0] == lookup[1] == lookup[2]
        });
    } catch (error) {
        console.error(error);
    }
    // console.log('keyTriple',keyTriple,'matchedTriple',match);

    return match
}

function cleanErrors(parsedTriples, validationResult){
    var results = [];
    var messages = [];
    var errors = parseErrors(validationResult.errors);
    // console.log('errors',validationResult.errors);
    //sometimes errors are in arrays of length one for some reason :/

    // console.log('errors',errors);
    // console.log('validationResult',validationResult);
    for (var i = errors.length - 1; i >= 0; i--) {
        if (errors[i].type == 'TypeMismatch'){
            if (errors[i].triple) {

                var match = matchTriple(parsedTriples,errors[i].triple);
                // console.log('match',match);
                errors[i].line = match.line;

                errors[i].message = 'Type mismatch on line ' + String(errors[i].line) + ' in ' + String(validationResult.node);

            } else {
                errors[i].message = ' Missing property ' + String(errors[i].property) + ' in ' + String(validationResult.node);
            }
        }

        else if (errors[i].type == 'MissingProperty') {
            try {
                errors[i].message = ' Missing property ' + String(errors[i].property) ;

            }catch (error){
                console.error(error);
            }
            // console.log('missing property error',errors[i]);

        }
        else {
            console.log('VALIDATION ERROR:',errors[i].type);
        }
        //check if the same error has been already parsed, as the validation library does produce duplicates
        if (!messages.includes(errors[i].message)){
            results.push(errors[i]);
            messages.push(errors[i].message);
        }
    }

    return results
}

function Validator(schemaText, dataText, callbacks, options) {
    console.log(this);

    this.callbacks = callbacks;
    this.options = options;

    this.updateSchema('schema.shex', schemaText);
    if (isNode) {
        console.log("Running under Node.JS");
        this.updateSchema('schema.shex', schemaText);
    } else {
        this.updateSchema(location.origin + '/schema.shex', schemaText);
    }

    this.updateData(dataText);
}

module.exports.Validator = Validator;
<commit_msg>return n3 db as well as turtle formatted string<commit_after>var Promise = require('promise');
var shexjs = require("shex");
var n3 = require("n3");
var isNode = require('detect-node');
var DefaultBase = "";
var jsld = require('jsonld')

Validator.prototype = {
    updateSchema: function (base, schemaText) {
        this.schema = parseSchema(base ,schemaText);
        this.schema.done(this.callbacks.schemaParsed, this.callbacks.schemaParseError);
    },
    updateData: function (dataText) {
        this.data = parseData(dataText);
        this.data.done(this.callbacks.dataParsed, this.callbacks.dataParseError);
    },
    findShapes: function () {
        var _this = this;
        return Promise.all([this.schema, this.data]).then(function (a) {
            // console.log('showing shapes');
            // console.log(this.schema);
            // console.log(this.data);
        });
    },
    validate: function(startingNodes) {
        var _this = this;
        return Promise.all([this.schema, this.data, this.options]).then(function (a) {
            console.log('validate called a:',a);
            var node = Object.keys(a[2].resourceShapeMap)[0];
            var validator = shexjs.Validator.construct(a[0].schema);
            try {

                var result = validator.validate(shexjs.Util.makeN3DB(a[1].db), node, a[2].resourceShapeMap[node]);
            } catch (error){
                console.error(error);
            }
            console.log('valres',result);
            // console.log('callbacks in validator',_this.callbacks);
            // console.log('db to validate',a[1].db)
            return cleanResult(result, a[1].triples, _this.callbacks.validationResult)
        });
    }
};

function isJSON(str) {
    try {
        return (JSON.parse(str) && !!str);
    } catch (e) {
        return false;
    }
}

function parseData(dataText){
    return new Promise(function (resolve, reject) {
        var lineIndex = new Object();
        var db = n3.Store({meta:true});
        var turtledata = '';
        var inputData = '';
        if (isJSON(dataText)) {
          print('json-ld passed to shex-validator');
          jsld.toRDF(JSON.parse(dataText), {format: 'application/nquads'}, function(err, nquads) {
            console.log(nquads);
            console.log(err);
            turtledata = nquads;
            inputData = nquads;
          });
        } else {
          inputData = dataText;
        }

        n3.Parser({documentIRI: DefaultBase}).parse(inputData, function (error, triple, prefixes) {
            // console.log('db', db);
            // console.log('DB');
            // console.log('triple callback')
            if (error) {
                // throw Error("error parsing " + data + ": " + error);
                reject(parseN3Error(error));
            } else if (triple) {
                // console.log("N3triple",triple);
                lineIndex[JSON.stringify({'subject':triple.subject,'predicate':triple.predicate,'object':triple.object,'graph':triple.graph})] = triple.line;
                lineIndex[triple.line] = {'object':triple.object,'subject':triple.subject,'predicate':triple.predicate,'graph':triple.graph};
                console.log('triple added ',triple);
                db.addTriple(triple.subject, triple.predicate, triple.object,triple.graph, {line:triple.line});

            } else {
                // db.setMetaFlag(true);
                var triples = db.getTriples();
                // db.setMetaFlag(false);
                for (var i = triples.length - 1; i >= 0; i--) {
                    var triple_key = JSON.stringify({'subject':triples[i].subject,'predicate':triples[i].predicate,'object':triples[i].object,'graph':""});
                    triples[i].line = lineIndex[triple_key];
                }
                resolve({db: db, triples:triples, turtledata:turtledata});
            }
        });

    });
}

function parseSchema(base, schemaText) {
    return new Promise(function (resolve, reject) {
        var schema;
        try {
            schema = shexjs.Parser.construct(base).parse(schemaText);
        }
        catch (e) {
            reject(e);
        }
        resolve({schema: schema, shapes: schema.shapes});

    });
};

function parseReqLevels(rawSchema, levels){
    var defaultLevels = ['`MUST`','`MAY`','`SHOULD`'];
    var quoteChar = '`';
    if (levels) {
        defaultLevels = levels;
        for (var i = levels.length - 1; i >= 0; i--) {
            defaultLevels[i] = quoteChar + levels[i] + quoteChar;
        }
    }

    var lines = [];
    var result = {'data':'',lineRules:{}};

    lines = rawSchema.split("\n");

    var re = new RegExp('(.*)('+defaultLevels[0]+'|'+defaultLevels[1]+'|'+defaultLevels[2]+')(.*)');

    for (var i = 0; i <= lines.length - 1; i++) {
        var match = lines[i].match(re);
        if (match) {
            result.lineRules[i] = match[2];
            result.data = String.concat(result.data,match[3] + '\n');
        } else {
            result.data = String.concat(result.data,lines[i] + '\n');
        }
    }
    console.log('PREPROCESSING OF schema DONE',result.data);
    return result
}

function cleanResult(result, parsedTriples, callback){
    console.log('validation result', result);
    var errors = [];
    var matches = [];
    if (result.type == 'Failure'){
        errors = cleanErrors(parsedTriples, result);
    } else {
        matches = cleanMatches(parsedTriples, result);
        // console.log('result',result);
        // console.log('matches',matches);
    }
    var clean_result = {
            errors: errors,
            matches: matches,
            startingResource: result.node,
            passed: errors.length === 0,
            full_result:result
        };
    return callback(clean_result);
}

function parseN3Error(error) {
    var line = error.message.match(/line [0-9]*/g);

    line = (line && line.length > 0 && line[0].length > 5)?Number(line[0].substr(5)):null;

    return {
        message: error.message,
        line: line,
        column: 0
    }
}
// returns the matched triples and the corresponding lines

function cleanMatches(parsedTriples, validationResult){
    var results = [];
    var messages = [];
    var matches = parseMatches(validationResult.solution);
    for (var i = matches.length - 1; i >= 0; i--) {
        var currentMatch = {};
        currentMatch.line = matchTriple(parsedTriples, matches[i]).line;
        currentMatch.subject = matches[i].subject;
        currentMatch.predicate = matches[i].predicate;

        if (matches[i].object.value && matches[i].object.type) {
                currentMatch.object = '<type>:' +String(matches[i].object.type) +' <value>:'+ String(matches[i].object.value);

        } else if (matches[i].object.value) {
                currentMatch.object = '<value>:'+ String(matches[i].object.value);
        } else {
            currentMatch.object = matches[i].object;
        }
            currentMatch.message = 'Matched '+ String(currentMatch.predicate)+' '+ String(currentMatch.object) + ' on line ' + String(currentMatch.line);

        // console.log('cleanMatches',matches[i]);

        if (!messages.includes(currentMatch.message)){
            results.push(currentMatch);
            messages.push(currentMatch.message);
        }

    }
    // console.log('results returned',results);
    return results
}

function parseMatches(solution){
    var results = [];
    var values = Object.values(solution)
    // console.log('object values',values);
    for (var i = values.length - 1; i >= 0; i--) {
        if (values[i].subject && values[i].predicate && values[i].object){
            // console.log('istriple',values[i]);
            results.push(values[i]);
        }
        else if (typeof(values[i]) == 'string'){
            // console.log('string found',values[i])
        } else {
            Array.prototype.push.apply(results,parseMatches(values[i]));
        }
    }

    return results
}

function parseErrors(errors){
    var results = [];
    for (var i = errors.length - 1; i >= 0; i--) {
        if (Array.isArray(errors[i])){
            // console.log('rec call',errors[i]);
            Array.prototype.push.apply(results,parseErrors(errors[i]));

        } else {
            // console.log('non rec call',errors[i]);
            results.push(errors[i])
        }
    }
    console.log('results',results);
    return results
}

function matchTriple(parsedTriples, keyTriple){
    var match;

    try {
        match = parsedTriples.find(function (triple) {
            var lookup = []
            if (typeof(keyTriple.subject) == 'string' ){
                if (triple.subject === keyTriple.subject){
                    lookup.push(true)
                } else{
                    return false
                }
            } else {
                lookup.push(true);
            }
            // console.log('subject',keyTriple.subject);

            if (typeof(keyTriple.predicate) == 'string'){
                if (triple.predicate === keyTriple.predicate){
                    lookup.push(true);
                } else {
                    return false
                }
            }else {
                lookup.push(true);
            }

            // console.log('predicate',keyTriple.predicate);

            if (typeof(keyTriple.object) == 'string'){
                if (triple.object === keyTriple.object){
                    lookup.push(true);
                } else {
                    return false
                }
            }else {
                lookup.push(true);
            }
            // console.log('object',keyTriple.object);

            return lookup[0] == lookup[1] == lookup[2]
        });
    } catch (error) {
        console.error(error);
    }
    // console.log('keyTriple',keyTriple,'matchedTriple',match);

    return match
}

function cleanErrors(parsedTriples, validationResult){
    var results = [];
    var messages = [];
    var errors = parseErrors(validationResult.errors);
    // console.log('errors',validationResult.errors);
    //sometimes errors are in arrays of length one for some reason :/

    // console.log('errors',errors);
    // console.log('validationResult',validationResult);
    for (var i = errors.length - 1; i >= 0; i--) {
        if (errors[i].type == 'TypeMismatch'){
            if (errors[i].triple) {

                var match = matchTriple(parsedTriples,errors[i].triple);
                // console.log('match',match);
                errors[i].line = match.line;

                errors[i].message = 'Type mismatch on line ' + String(errors[i].line) + ' in ' + String(validationResult.node);

            } else {
                errors[i].message = ' Missing property ' + String(errors[i].property) + ' in ' + String(validationResult.node);
            }
        }

        else if (errors[i].type == 'MissingProperty') {
            try {
                errors[i].message = ' Missing property ' + String(errors[i].property) ;

            }catch (error){
                console.error(error);
            }
            // console.log('missing property error',errors[i]);

        }
        else {
            console.log('VALIDATION ERROR:',errors[i].type);
        }
        //check if the same error has been already parsed, as the validation library does produce duplicates
        if (!messages.includes(errors[i].message)){
            results.push(errors[i]);
            messages.push(errors[i].message);
        }
    }

    return results
}

function Validator(schemaText, dataText, callbacks, options) {
    console.log(this);

    this.callbacks = callbacks;
    this.options = options;

    this.updateSchema('schema.shex', schemaText);
    if (isNode) {
        console.log("Running under Node.JS");
        this.updateSchema('schema.shex', schemaText);
    } else {
        this.updateSchema(location.origin + '/schema.shex', schemaText);
    }

    this.updateData(dataText);
}

module.exports.Validator = Validator;
<|endoftext|>


<commit_before>'use strict';

var jwt = require('jwt-simple');
var moment = require('moment');
var _ = require('lodash');
var Errors = require('./errors');

/**
* Returns a encoded payload token using the provided sub, secret and expiry.
* @param {*} subject to be encoded
* @param {String} Secret key for encoding
* @param {Number=} An integer to set the expiry days (optional)
* @returns {String} encoded token as a string
*/
var encodeToken = function (sub, secret, expiry) {
  expiry = (_.isInteger(expiry)) ? expiry : 14;
  var payload =  {
    exp: moment().add(expiry, 'days').unix(),
    iat: moment().unix(),
    sub: sub,
  };
  return jwt.encode(payload, secret);
};

/**
* Returns a decoded payload from the token
* @param {String} token to be decoded
* @param {String} Secret key for decoding
* @returns {Object} decoded payload
*/
var decodeToken = function (token, secret) {
  try {
    return { payload: jwt.decode(token, secret) };
  } catch (e) {
    return { error: Errors.DECODE_ERROR,
    };
  }
};

/**
* Returns a decoded payload from the http headers
* @param {String} String containing the authorization heade4r
* @param {String} Secret key for decoding
* @returns {Object} decoded payload
*/
var decodeAuthHeader = function (authHeader, secret) {
  try {
    var header = authHeader.split(' ');
    var token = header[1];
    return decodeToken(token, secret);
  } catch (e) {
    return { error: Errors.INVALID_TOKEN };
  }
};

/**
* Verifies the auth header is valid and has not expired
* @param {String} String containing the authorization heade4r
* @param {String} Secret key for decoding
* @returns {Object} result of the operation with decoded payload as part of the result.
*                   if successful flag isSuccess is set to true in the response
*/
var isAuthenticated = function (authHeader, secret) {

  var result = decodeAuthHeader(authHeader, secret);

  if (result.error) return { isSuccess: false, error: result.error };

  return { isSuccess: true, payload: result.payload };
};

module.exports  = {
  encodeToken: encodeToken,
  decodeToken: decodeToken,
  decodeAuthHeader: decodeAuthHeader,
  isAuthenticated: isAuthenticated,
};
<commit_msg>feat(core): exports errors<commit_after>'use strict';

var jwt = require('jwt-simple');
var moment = require('moment');
var _ = require('lodash');
var Errors = require('./errors');

/**
* Returns a encoded payload token using the provided sub, secret and expiry.
* @param {*} subject to be encoded
* @param {String} Secret key for encoding
* @param {Number=} An integer to set the expiry days (optional)
* @returns {String} encoded token as a string
*/
var encodeToken = function (sub, secret, expiry) {
  expiry = (_.isInteger(expiry)) ? expiry : 14;
  var payload =  {
    exp: moment().add(expiry, 'days').unix(),
    iat: moment().unix(),
    sub: sub,
  };
  return jwt.encode(payload, secret);
};

/**
* Returns a decoded payload from the token
* @param {String} token to be decoded
* @param {String} Secret key for decoding
* @returns {Object} decoded payload
*/
var decodeToken = function (token, secret) {
  try {
    return { payload: jwt.decode(token, secret) };
  } catch (e) {
    return { error: Errors.DECODE_ERROR,
    };
  }
};

/**
* Returns a decoded payload from the http headers
* @param {String} String containing the authorization heade4r
* @param {String} Secret key for decoding
* @returns {Object} decoded payload
*/
var decodeAuthHeader = function (authHeader, secret) {
  try {
    var header = authHeader.split(' ');
    var token = header[1];
    return decodeToken(token, secret);
  } catch (e) {
    return { error: Errors.INVALID_TOKEN };
  }
};

/**
* Verifies the auth header is valid and has not expired
* @param {String} String containing the authorization heade4r
* @param {String} Secret key for decoding
* @returns {Object} result of the operation with decoded payload as part of the result.
*                   if successful flag isSuccess is set to true in the response
*/
var isAuthenticated = function (authHeader, secret) {

  var result = decodeAuthHeader(authHeader, secret);

  if (result.error) return { isSuccess: false, error: result.error };

  return { isSuccess: true, payload: result.payload };
};

module.exports  = {
  encodeToken: encodeToken,
  decodeToken: decodeToken,
  decodeAuthHeader: decodeAuthHeader,
  isAuthenticated: isAuthenticated,
  Errors: Errors,
};
<|endoftext|>


<commit_before>import express from 'express';
import cors from 'cors';

const app = express();
app.use(cors());
app.get('/', (req, res) => {
  res.json({
    hello: 'JS World',
  });
});

app.get('/lesson2/2A', (req, res) =>{
  const a = req.query.a? parseInt(req.query.a) : 0;
  const b = req.query.b? parseInt(req.query.b) : 0;
  const sum = a + b;
  res.send(sum.toString());
});

String.prototype.capitalizeFirstLetter = function() {
    return this.charAt(0).toUpperCase() + this.slice(1).toLowerCase();
};

app.get('/lesson2/2B', (req, res) =>{
  const reg = new RegExp('[A-zА-яЁё]');
  let result = "Invalid fullname";
  const fullname = req.query.fullname.trim();
  if (fullname && !/[0-9]/.test(fullname) && !/_/.test(fullname) && !/\//.test(fullname)) {
      const names = fullname.split(/\s+/);
      const length = names.length;
      switch(length) {
          case 1:
              result = names[0].capitalizeFirstLetter();
              break;
          case 2:
              result = names[1].capitalizeFirstLetter() + " " + names[0].capitalizeFirstLetter().charAt(0) + ".";
              break;
          case 3:
              result = names[2].capitalizeFirstLetter() + " " + names[0].capitalizeFirstLetter().charAt(0) + ". " + names[1].capitalizeFirstLetter().charAt(0) + ".";
      }
  }
  res.send(result);
});

app.listen(3000, () => {
  console.log('Your app listening on port 3000!');
});
<commit_msg>Рефакторинг задачи 2B<commit_after>import express from 'express';
import cors from 'cors';

const app = express();
app.use(cors());
app.get('/', (req, res) => {
    res.json({
        hello: 'JS World',
    });
});

app.get('/lesson2/2A', (req, res) => {
    const a = req.query.a ? parseInt(req.query.a) : 0;
    const b = req.query.b ? parseInt(req.query.b) : 0;
    const sum = a + b;
    res.send(sum.toString());
});

String.prototype.capitalizeFirstLetter = function () {
    return this.charAt(0).toUpperCase() + this.slice(1).toLowerCase();
};

app.get('/lesson2/2B', (req, res) => {
    const reg = new RegExp('[A-zА-яЁё]');
    let result = "Invalid fullname";
    const fullname = req.query.fullname.trim();
    if (fullname && !/[0-9]/.test(fullname) && !/_/.test(fullname) && !/\//.test(fullname)) {
        const names = fullname.split(/\s+/);
        const length = names.length;
        let lastName;
        let firstName;
        let middleName;
        switch (length) {
            case 1:
                result = names[0].capitalizeFirstLetter();
                break;
            case 2:
                lastName = names[1].capitalizeFirstLetter();
                firstName = names[0].capitalizeFirstLetter();
                result = lastName + " " + getFirstChar(firstName) + ".";
                break;
            case 3:
                lastName = names[2].capitalizeFirstLetter();
                firstName = names[0].capitalizeFirstLetter();
                middleName = names[1].capitalizeFirstLetter();
                result = lastName + " " + getFirstChar(firstName) + ". " + getFirstChar(middleName) + ".";
        }
    }
    res.send(result);
});

function getFirstChar(str) {
    return str.charAt(0);
}

app.listen(3000, () => {
    console.log('Your app listening on port 3000!');
});
<|endoftext|>


<commit_before>import events from 'events';
import Clusterize from 'clusterize.js';
import { flatten } from 'flattree';
import { defaultRowRenderer } from './renderer';
import { stopPropagation, addEventListener, removeEventListener } from './polyfill';
import { classNames } from './utils';

const extend = (target, ...sources) => {
    sources.forEach((source) => {
        for (let key in source) {
            if (source.hasOwnProperty(key)) {
                target[key] = source[key];
            }
        }
    });

    return target;
};

class InfiniteTree extends events.EventEmitter {
    options = {
        autoOpen: false,
        el: null,
        rowRenderer: defaultRowRenderer
    };
    state = {
        openNodes: [],
        selectedNode: null
    };
    clusterize = null;
    nodebucket = {};
    nodes = [];
    rows = [];
    scrollElement = null;
    contentElement = null;

    contentListener = (evt) => {
        let { target, currentTarget } = evt;

        stopPropagation(evt);

        if (target !== currentTarget) {
            let itemTarget = target;
            let handleToggler = false;

            while (itemTarget && itemTarget.parentElement !== currentTarget) {
                if (itemTarget.className.indexOf('tree-toggler') >= 0) {
                    handleToggler = true;
                }
                itemTarget = itemTarget.parentElement;
            }

            const id = itemTarget.getAttribute('aria-id');
            const node = this.getNodeById(id);

            // Click on the toggler to open/close a tree node
            if (handleToggler) {
                if (this.state.openNodes.indexOf(node) >= 0) { // Close node
                    this.closeNode(node);
                } else {
                    this.openNode(node);
                }
            } else {
                this.selectNode(node);
            }
        }
    };

    constructor(options = {}) {
        super();

        // Assign options
        this.options = extend({}, this.options, options);

        if (!this.options.el) {
            console.error('Failed to initialize infinite-tree: el is not specified.', options);
            return;
        }

        this.create();

        // Load tree data if it's provided
        if (options.data) {
            this.loadData(options.data);
        }
    }
    create() {
        if (!this.options.el) {
            throw new Error('The element option is not specified.');
        }

        const scrollElement = document.createElement('div');
        scrollElement.className = classNames(
            'infinite-tree',
            'infinite-tree-scroll'
        );
        const contentElement = document.createElement('div');
        contentElement.className = classNames(
            'infinite-tree',
            'infinite-tree-content'
        );

        scrollElement.appendChild(contentElement);
        this.options.el.appendChild(scrollElement);

        this.clusterize = new Clusterize({
            tag: 'div',
            rows: [],
            scrollElem: scrollElement,
            contentElem: contentElement,
            no_data_class: 'infinite-tree-no-data',
            callbacks: {
                // Will be called right before replacing previous cluster with new one.
                clusterWillChange: () => {
                },
                // Will be called right after replacing previous cluster with new one.
                clusterChanged: () => {
                },
                // Will be called on scrolling. Returns progress position.
                scrollingProgress: (progress) => {
                    this.emit('scrollProgress', progress);
                }
            }
        });

        this.scrollElement = scrollElement;
        this.contentElement = contentElement;

        addEventListener(this.contentElement, 'click', this.contentListener);
    }
    destroy() {
        removeEventListener(this.contentElement, 'click', this.contentListener);

        this.clear();

        if (this.clusterize) {
            this.clusterize.destroy(true); // True to remove all data from the list
            this.clusterize = null;
        }

        // Remove all child nodes
        while (this.contentElement.firstChild) {
            this.contentElement.removeChild(this.contentElement.firstChild);
        }
        while (this.scrollElement.firstChild) {
            this.scrollElement.removeChild(this.scrollElement.firstChild);
        }
        if (this.options.el) {
            const containerElement = this.options.el;
            while (containerElement.firstChild) {
                containerElement.removeChild(containerElement.firstChild);
            }
        }
        this.contentElement = null;
        this.scrollElement = null;
    }
    clear() {
        this.clusterize.clear();
        this.nodebucket = {};
        this.nodes = [];
        this.rows = [];
        this.state.openNodes = [];
        this.state.selectedNode = null;
    }
    // Updates list with new data
    update() {
        this.clusterize.update(this.rows);
    }
    // Add a new node after this existing node.
    // @param {object} newNode
    // @param {object} node
    addNodeAfter(newNode, node) {
        // TODO
    }
    // Add a new node before this existing node.
    // @param {object} newNode
    // @param {object} node
    addNodeBefore(newNode, node) {
        // TODO
    }
    // Add a new node as parent of this existing node.
    // @param {object} newNode
    // @param {object} node
    addParentNode(newNode, node) {
        // TODO
    }
    // Add a node to this parent node. If parentNode is empty, then the new node becomes a root node.
    // @param {object} newNode The new node
    // @param {object} parentNode The parent node
    appendNode(newNode, parentNode) {
        // TODO
    }
    // Close this node. The node must have child nodes.
    // @param {object} node
    // @return {boolean} Returns true on success, false otherwise.
    closeNode(node) {
        const { rowRenderer } = this.options;

        // Retrieve node index
        const nodeIndex = this.nodes.indexOf(node);
        if (nodeIndex < 0) {
            throw new Error('Invalid node specified: node.id=' + JSON.stringify(node.id));
        }

        // Check if the closeNode action can be performed
        if (this.state.openNodes.indexOf(node) < 0) {
            return false;
        }

        // Keep selected node unchanged if "node" is equal to "this.state.selectedNode"
        if (this.state.selectedNode && (this.state.selectedNode !== node)) {
            // Action:
            //   close "node.0.0"
            //
            // Tree:
            // [0] - node.0
            // [1]  - node.0.0      => next selected node (index=1, total=2)
            // [2]      node.0.0.0  => last selected node (index=2, total=0)
            // [3]      node.0.0.1
            // [4]    node.0.1
            const selectedIndex = this.nodes.indexOf(this.state.selectedNode);
            const rangeFrom = nodeIndex + 1;
            const rangeTo = nodeIndex + node.state.total;

            if ((rangeFrom <= selectedIndex) && (selectedIndex <= rangeTo)) {
                this.selectNode(node);
            }
        }

        node.state.open = false; // Set node.state.open to false
        const openNodes = this.state.openNodes.filter((node) => (node.state.more && node.state.open));
        this.state.openNodes = openNodes;

        const deleteCount = node.state.total;

        { // Traversing up through ancestors to subtract node.state.total
            let p = node;
            while (p) {
                p.state.total = (p.state.total - deleteCount);
                p = p.parent;
            }
        }

        // Remove elements from an array
        this.nodes.splice(nodeIndex + 1, deleteCount);
        this.rows.splice(nodeIndex + 1, deleteCount);
        this.rows[nodeIndex] = rowRenderer(node);

        // Emit the 'closeNode' event
        this.emit('closeNode', node);

        // Updates list with new data
        this.update();

        return true;
    }
    // Get a tree node by the unique node id. This assumes that you have given the nodes in the data a unique id.
    // @param {string|number} id The unique node id. A null value will be returned if node.id not matched.
    getNodeById(id) {
        const node = (this.nodebucket[id] || [])[0];
        return (node !== undefined) ? node : null;
    }
    // Get the selected node. Returns the row data or null.
    getSelectedNode() {
        return this.state.selectedNode;
    }
    // Get the state of the tree.
    // @return {object} Returns an object that contains the ids of open nodes and selected nodes
    getState() {
        // TODO
    }
    // Get the root node of the tree.
    getTree() {
        let tree = (this.nodes.length > 0) ? this.nodes[0] : null;
        while (tree && tree.parent !== null) {
            tree = tree.parent;
        }
        return tree;
    }
    // Load data in the tree.
    // @param {object|array} data The data is a node object or array of nodes
    loadData(data = []) {
        const { autoOpen, rowRenderer } = this.options;

        this.nodes = flatten(data, { openAllNodes: autoOpen });

        // Construct node bucket
        this.nodebucket = {};
        this.nodes.forEach((node) => {
            if (node.id !== undefined) {
                const nodebucket = this.nodebucket[node.id];
                this.nodebucket[node.id] = nodebucket ? nodebucket.concat(node) : [node];
            }
        });

        const openNodes = this.nodes.filter((node) => (node.state.more && node.state.open));
        this.state.openNodes = openNodes;
        this.state.selectedNode = null;

        this.rows = this.nodes.map(node => rowRenderer(node));

        // Updates list with new data
        this.update();
    }
    // Open this node. The node must have child nodes.
    // @param {object} node
    // @return {boolean} Returns true on success, false otherwise.
    openNode(node) {
        const { rowRenderer } = this.options;

        // Retrieve node index
        const nodeIndex = this.nodes.indexOf(node);
        if (nodeIndex < 0) {
            throw new Error('Invalid node specified: node.id=' + JSON.stringify(node.id));
        }

        // Check if the openNode action can be performed
        if (this.state.openNodes.indexOf(node) >= 0) {
            return false;
        }

        node.state.open = true; // Set node.state.open to true
        const openNodes = [node].concat(this.state.openNodes); // the most recently used items first
        this.state.openNodes = openNodes;

        const nodes = flatten(node.children, { openNodes: this.state.openNodes });
        const rows = nodes.map(node => rowRenderer(node));

        // Insert an array inside another array
        this.nodes.splice.apply(this.nodes, [nodeIndex + 1, 0].concat(nodes));
        this.rows.splice.apply(this.rows, [nodeIndex + 1, 0].concat(rows));
        this.rows[nodeIndex] = rowRenderer(node);

        // Emit the 'openNode' event
        this.emit('openNode', node);

        // Updates list with new data
        this.update();

        return true;
    }
    // Remove node from the tree
    // @param {object} node
    removeNode(node) {
        // TODO
    }
    // Set the current scroll position to this node.
    // @param {object} node
    // @return {number} Returns the vertical scroll position, or -1 on error.
    scrollToNode(node) {
        // Retrieve node index
        const nodeIndex = this.nodes.indexOf(node);
        if (nodeIndex < 0) {
            return -1;
        }
        if (!this.contentElement) {
            return -1;
        }
        // Get the offset height of the first child element that contains the "tree-item" class.
        const firstChild = this.contentElement.querySelectorAll('.tree-item')[0];
        const rowHeight = (firstChild && firstChild.offsetHeight) || 0;
        return this.scrollTop(nodeIndex * rowHeight);
    }
    // Get/set the current vertical position of the scroll bar.
    // @param {number} [value] An integer indicating the new position to set the scroll bar to.
    // @return {number} Returns the vertical scroll position.
    scrollTop(value) {
        if (!this.scrollElement) {
            return 0;
        }
        if (value !== undefined) {
            this.scrollElement.scrollTop = Number(value);
        }
        return this.scrollElement.scrollTop;
    }
    // Select this node. You can deselect the current node by calling selectNode(null) or selectNode().
    // @param {object} node
    // @return {boolean} Returns true on success, false otherwise.
    selectNode(node = null) {
        const { rowRenderer } = this.options;

        if (node === null) {
            // Deselect the current node
            if (this.state.selectedNode) {
                const selectedNode = this.state.selectedNode;
                const selectedIndex = this.nodes.indexOf(selectedNode);

                selectedNode.state.selected = false;
                this.rows[selectedIndex] = rowRenderer(selectedNode);
                this.state.selectedNode = null;

                // Emit the 'selectNode' event
                this.emit('selectNode', null);

                // Updates list with new data
                this.update();

                return true;
            }

            return false;
        }

        // Retrieve node index
        const nodeIndex = this.nodes.indexOf(node);
        if (nodeIndex < 0) {
            throw new Error('Invalid node specified: node.id=' + JSON.stringify(node.id));
        }

        // Select this node
        if (this.state.selectedNode !== node) {
            node.state.selected = true;
            this.rows[nodeIndex] = rowRenderer(node);
        }

        // Deselect the current node
        if (this.state.selectedNode) {
            const selectedNode = this.state.selectedNode;
            const selectedIndex = this.nodes.indexOf(selectedNode);
            selectedNode.state.selected = false;
            this.rows[selectedIndex] = rowRenderer(selectedNode);
        }

        if (this.state.selectedNode !== node) {
            this.state.selectedNode = node;

            // Emit the 'selectNode' event
            this.emit('selectNode', node);
        } else {
            this.state.selectedNode = null;

            // Emit the 'selectNode' event
            this.emit('selectNode', null);
        }

        // Updates list with new data
        this.update();

        return true;
    }
    // Set the state of the tree. See getState for more information.
    // @param {object} state The state object
    // @param {string} [state.openNodes] The ids of open nodes
    // @param {string} [state.selectedNode] The id of selected node
    setState(state = {}) {
        // TODO
    }
    // Open or close this node.
    toggle(node) {
        // TODO
    }
    // Get the tree data as string.
    toString() {
        // TODO
    }
    // Update the title of a node. You can also update the data.
    // @param {object} node
    // @param {object} data The data object
    // @param {object} [data.label] The title of a node
    updateNode(node, data) {
        // TODO
    }
}

module.exports = InfiniteTree;
<commit_msg>[API] getChildren/toggleNode/toString/updateNode<commit_after>import events from 'events';
import Clusterize from 'clusterize.js';
import { flatten } from 'flattree';
import { defaultRowRenderer } from './renderer';
import { stopPropagation, addEventListener, removeEventListener } from './polyfill';
import { classNames } from './utils';

const extend = (target, ...sources) => {
    if (target === undefined || target === null) {
        throw new TypeError('Cannot convert undefined or null to object');
    }

    const output = Object(target);
    for (let index = 0; index < sources.length; index++) {
        const source = sources[index];
        if (source !== undefined && source !== null) {
            for (let key in source) {
                if (source.hasOwnProperty(key)) {
                    output[key] = source[key];
                }
            }
        }
    }
    return output;
};

class InfiniteTree extends events.EventEmitter {
    options = {
        autoOpen: false,
        el: null,
        rowRenderer: defaultRowRenderer
    };
    state = {
        openNodes: [],
        selectedNode: null
    };
    clusterize = null;
    nodebucket = {};
    nodes = [];
    rows = [];
    scrollElement = null;
    contentElement = null;

    contentListener = (evt) => {
        let { target, currentTarget } = evt;

        stopPropagation(evt);

        if (target !== currentTarget) {
            let itemTarget = target;
            let handleToggler = false;

            while (itemTarget && itemTarget.parentElement !== currentTarget) {
                if (itemTarget.className.indexOf('tree-toggler') >= 0) {
                    handleToggler = true;
                }
                itemTarget = itemTarget.parentElement;
            }

            const id = itemTarget.getAttribute('aria-id');
            const node = this.getNodeById(id);

            // Click on the toggler to open/close a tree node
            if (handleToggler) {
                this.toggleNode(node);
            } else {
                this.selectNode(node);
            }
        }
    };

    constructor(options = {}) {
        super();

        // Assign options
        this.options = extend({}, this.options, options);

        if (!this.options.el) {
            console.error('Failed to initialize infinite-tree: el is not specified.', options);
            return;
        }

        this.create();

        // Load tree data if it's provided
        if (options.data) {
            this.loadData(options.data);
        }
    }
    create() {
        if (!this.options.el) {
            throw new Error('The element option is not specified.');
        }

        const scrollElement = document.createElement('div');
        scrollElement.className = classNames(
            'infinite-tree',
            'infinite-tree-scroll'
        );
        const contentElement = document.createElement('div');
        contentElement.className = classNames(
            'infinite-tree',
            'infinite-tree-content'
        );

        scrollElement.appendChild(contentElement);
        this.options.el.appendChild(scrollElement);

        this.clusterize = new Clusterize({
            tag: 'div',
            rows: [],
            scrollElem: scrollElement,
            contentElem: contentElement,
            no_data_class: 'infinite-tree-no-data',
            callbacks: {
                // Will be called right before replacing previous cluster with new one.
                clusterWillChange: () => {
                },
                // Will be called right after replacing previous cluster with new one.
                clusterChanged: () => {
                },
                // Will be called on scrolling. Returns progress position.
                scrollingProgress: (progress) => {
                    this.emit('scrollProgress', progress);
                }
            }
        });

        this.scrollElement = scrollElement;
        this.contentElement = contentElement;

        addEventListener(this.contentElement, 'click', this.contentListener);
    }
    clear() {
        this.clusterize.clear();
        this.nodebucket = {};
        this.nodes = [];
        this.rows = [];
        this.state.openNodes = [];
        this.state.selectedNode = null;
    }
    destroy() {
        removeEventListener(this.contentElement, 'click', this.contentListener);

        this.clear();

        if (this.clusterize) {
            this.clusterize.destroy(true); // True to remove all data from the list
            this.clusterize = null;
        }

        // Remove all child nodes
        while (this.contentElement.firstChild) {
            this.contentElement.removeChild(this.contentElement.firstChild);
        }
        while (this.scrollElement.firstChild) {
            this.scrollElement.removeChild(this.scrollElement.firstChild);
        }
        if (this.options.el) {
            const containerElement = this.options.el;
            while (containerElement.firstChild) {
                containerElement.removeChild(containerElement.firstChild);
            }
        }
        this.contentElement = null;
        this.scrollElement = null;
    }
    // Updates list with new data
    update() {
        this.clusterize.update(this.rows);
    }
    // Adds a child node to a node.
    // @param {object} parent The object that defines the parent node.
    // @param {object} newChild The object that defines the child node.
    addChild(parent, newChild) {
        // TODO
    }
    // Adds a child node to a node at the specified index.
    //   * If the parent is null or undefined, inserts the child at the specified index in the top-level.
    //   * If the parent has children, the method adds the child to it at the specified index.
    //   * If the parent does not have children, the method adds the child to the parent.
    //   * If the index value is greater than or equal to the number of children in the parent, the method adds the child at the end of the children.
    // @param {object} parent The object that defines the parent node.
    // @param {object} newChild The object that defines the child node.
    // @param {number} index The 0-based index of where to insert the child node.
    addChildAt(parent, newChild, index) {
    }
    // Adds a new sibling node after the current node.
    // @param {object} node The object that defines the current node.
    // @param {object} newSibling The object that defines the sibling node.
    addSiblingAfter(node, newSibling) {
        // TODO
    }
    // Adds a new sibling node before the current node.
    // @param {object} node The object that defines the current node.
    // @param {object} newSibling The object that defines the sibling node.
    addSiblingBefore(node, newSibling) {
        // TODO
    }
    // Closes a node to hide its children.
    // @param {object} node
    // @return {boolean} Returns true on success, false otherwise.
    closeNode(node) {
        const { rowRenderer } = this.options;

        // Retrieve node index
        const nodeIndex = this.nodes.indexOf(node);
        if (nodeIndex < 0) {
            throw new Error('Invalid node specified: node.id=' + JSON.stringify(node.id));
        }

        // Check if the closeNode action can be performed
        if (this.state.openNodes.indexOf(node) < 0) {
            return false;
        }

        // Keep selected node unchanged if "node" is equal to "this.state.selectedNode"
        if (this.state.selectedNode && (this.state.selectedNode !== node)) {
            // Action:
            //   close "node.0.0"
            //
            // Tree:
            // [0] - node.0
            // [1]  - node.0.0      => next selected node (index=1, total=2)
            // [2]      node.0.0.0  => last selected node (index=2, total=0)
            // [3]      node.0.0.1
            // [4]    node.0.1
            const selectedIndex = this.nodes.indexOf(this.state.selectedNode);
            const rangeFrom = nodeIndex + 1;
            const rangeTo = nodeIndex + node.state.total;

            if ((rangeFrom <= selectedIndex) && (selectedIndex <= rangeTo)) {
                this.selectNode(node);
            }
        }

        node.state.open = false; // Set node.state.open to false
        const openNodes = this.state.openNodes.filter((node) => (node.state.more && node.state.open));
        this.state.openNodes = openNodes;

        const deleteCount = node.state.total;

        { // Traversing up through ancestors to subtract node.state.total
            let p = node;
            while (p) {
                p.state.total = (p.state.total - deleteCount);
                p = p.parent;
            }
        }

        // Remove elements from an array
        this.nodes.splice(nodeIndex + 1, deleteCount);
        this.rows.splice(nodeIndex + 1, deleteCount);
        this.rows[nodeIndex] = rowRenderer(node);

        // Emit the 'closeNode' event
        this.emit('closeNode', node);

        // Updates list with new data
        this.update();

        return true;
    }
    // Gets a node by its unique id. This assumes that you have given the nodes in the data a unique id.
    // @param {string|number} id An unique node id. A null value will be returned if the id doesn't match.
    getNodeById(id) {
        const node = (this.nodebucket[id] || [])[0];
        return (node !== undefined) ? node : null;
    }
    // Gets the selected node.
    getSelectedNode() {
        return this.state.selectedNode;
    }
    // Gets the state.
    // @return {object} Returns an object that contains the ids of open nodes and selected nodes
    getState() {
        // TODO
    }
    // Returns a list of child nodes.
    // @param {object} [node] The object that defines the node. If null, returns a list of top level nodes.
    getChildren(node = null) {
        if (node) {
            return node.children || [];
        }
        node = (this.nodes.length > 0) ? this.nodes[0] : null;
        while (node && node.parent !== null) {
            node = node.parent;
        }
        return node.children || [];
    }
    // Loads data in the tree.
    // @param {object|array} data The data is an object or array of objects that defines the node.
    loadData(data = []) {
        const { autoOpen, rowRenderer } = this.options;

        this.nodes = flatten(data, { openAllNodes: autoOpen });

        // Construct node bucket
        this.nodebucket = {};
        this.nodes.forEach((node) => {
            if (node.id !== undefined) {
                const nodebucket = this.nodebucket[node.id];
                this.nodebucket[node.id] = nodebucket ? nodebucket.concat(node) : [node];
            }
        });

        const openNodes = this.nodes.filter((node) => (node.state.more && node.state.open));
        this.state.openNodes = openNodes;
        this.state.selectedNode = null;

        this.rows = this.nodes.map(node => rowRenderer(node));

        // Updates list with new data
        this.update();
    }
    // Opens a node to display its children.
    // @param {object} node The object that defines the node.
    // @return {boolean} Returns true on success, false otherwise.
    openNode(node) {
        const { rowRenderer } = this.options;

        // Retrieve node index
        const nodeIndex = this.nodes.indexOf(node);
        if (nodeIndex < 0) {
            throw new Error('Invalid node specified: node.id=' + JSON.stringify(node.id));
        }

        // Check if the openNode action can be performed
        if (this.state.openNodes.indexOf(node) >= 0) {
            return false;
        }

        node.state.open = true; // Set node.state.open to true
        const openNodes = [node].concat(this.state.openNodes); // the most recently used items first
        this.state.openNodes = openNodes;

        const nodes = flatten(node.children, { openNodes: this.state.openNodes });
        const rows = nodes.map(node => rowRenderer(node));

        // Insert an array inside another array
        this.nodes.splice.apply(this.nodes, [nodeIndex + 1, 0].concat(nodes));
        this.rows.splice.apply(this.rows, [nodeIndex + 1, 0].concat(rows));
        this.rows[nodeIndex] = rowRenderer(node);

        // Emit the 'openNode' event
        this.emit('openNode', node);

        // Updates list with new data
        this.update();

        return true;
    }
    // Removes a node.
    // @param {object} node The object that defines the node.
    removeNode(node) {
        // TODO
    }
    // Sets the current scroll position to this node.
    // @param {object} node The object that defines the node.
    // @return {number} Returns the vertical scroll position, or -1 on error.
    scrollToNode(node) {
        // Retrieve node index
        const nodeIndex = this.nodes.indexOf(node);
        if (nodeIndex < 0) {
            return -1;
        }
        if (!this.contentElement) {
            return -1;
        }
        // Get the offset height of the first child element that contains the "tree-item" class.
        const firstChild = this.contentElement.querySelectorAll('.tree-item')[0];
        const rowHeight = (firstChild && firstChild.offsetHeight) || 0;
        return this.scrollTop(nodeIndex * rowHeight);
    }
    // Gets (or sets) the current vertical position of the scroll bar.
    // @param {number} [value] An integer that indicates the new position to set the scroll bar to.
    // @return {number} Returns the vertical scroll position.
    scrollTop(value) {
        if (!this.scrollElement) {
            return 0;
        }
        if (value !== undefined) {
            this.scrollElement.scrollTop = Number(value);
        }
        return this.scrollElement.scrollTop;
    }
    // Selects a node.
    // @param {object} node The object that defines the node. If null or undefined, deselects the current node.
    // @return {boolean} Returns true on success, false otherwise.
    selectNode(node = null) {
        const { rowRenderer } = this.options;

        if (node === null) {
            // Deselect the current node
            if (this.state.selectedNode) {
                const selectedNode = this.state.selectedNode;
                const selectedIndex = this.nodes.indexOf(selectedNode);

                selectedNode.state.selected = false;
                this.rows[selectedIndex] = rowRenderer(selectedNode);
                this.state.selectedNode = null;

                // Emit the 'selectNode' event
                this.emit('selectNode', null);

                // Updates list with new data
                this.update();

                return true;
            }

            return false;
        }

        // Retrieve node index
        const nodeIndex = this.nodes.indexOf(node);
        if (nodeIndex < 0) {
            throw new Error('Invalid node specified: node.id=' + JSON.stringify(node.id));
        }

        // Select this node
        if (this.state.selectedNode !== node) {
            node.state.selected = true;
            this.rows[nodeIndex] = rowRenderer(node);
        }

        // Deselect the current node
        if (this.state.selectedNode) {
            const selectedNode = this.state.selectedNode;
            const selectedIndex = this.nodes.indexOf(selectedNode);
            selectedNode.state.selected = false;
            this.rows[selectedIndex] = rowRenderer(selectedNode);
        }

        if (this.state.selectedNode !== node) {
            this.state.selectedNode = node;

            // Emit the 'selectNode' event
            this.emit('selectNode', node);
        } else {
            this.state.selectedNode = null;

            // Emit the 'selectNode' event
            this.emit('selectNode', null);
        }

        // Updates list with new data
        this.update();

        return true;
    }
    // Sets the state. See getState for more information.
    // @param {object} state The state object.
    // @param {string} [state.openNodes] An array of ids containing the open nodes.
    // @param {string} [state.selectedNode] The id of selected node.
    setState(state = {}) {
        // TODO
    }
    // Toggles a node to display or hide its children.
    // @param {object} node The object that defines the node.
    toggleNode(node) {
        if (this.state.openNodes.indexOf(node) >= 0) {
            // close node
            this.closeNode(node);
        } else {
            // open node
            this.openNode(node);
        }
    }
    // Serializes the current state of a node to a JSON string.
    // @param {object} node The object that defines the node. If null, returns the whole tree.
    // @param {object} [options] The options object.
    // @param {boolean} [options.
    toString(node = null, options) {
        const traverse = (node) => {
            let s = '[';
            if (node && node.children) {
                for (let i = 0; i < node.children.length; ++i) {
                    let list = [];
                    s = s + '{';
                    Object.keys(node).forEach((key) => {
                        let value = node[key];
                        if (key === 'parent') { // ignore parent
                            return;
                        }
                        if (key === 'children') { // traverse child nodes
                            list.push('"' + key + '":' + traverse(node.children[i]));
                            return;
                        }
                        if (typeof value === 'string' || typeof value === 'object') {
                            list.push('"' + key + '":' + JSON.stringify(value));
                        } else { // primitive types
                            list.push('"' + key + '":' + value);
                        }
                    });
                    s = s + list.join(',');
                    s = s + '}' + ((i === node.children.length - 1) ? '' : ',');
                }
            }
            s = s + ']';
            return s;
        };

        if (!node) {
            node = (this.nodes.length > 0) ? this.nodes[0] : null;
            while (node && node.parent !== null) {
                node = node.parent;
            }
        }

        return traverse(node);
    }
    // Updates the data of a node.
    // @param {object} node
    // @param {object} data The data object.
    updateNode(node, data) {
        const { rowRenderer } = this.options;

        // Retrieve node index
        const nodeIndex = this.nodes.indexOf(node);
        if (nodeIndex < 0) {
            throw new Error('Invalid node specified: node.id=' + JSON.stringify(node.id));
        }

        // The static attributes (i.e. children, parent, and state) are being protected
        const { children, parent, state } = node;
        node = extend(node, data, { children, parent, state });

        this.rows[nodeIndex] = rowRenderer(node);

        // Updates list with new data
        this.update();
    }
}

module.exports = InfiniteTree;
<|endoftext|>


<commit_before>'use strict';

(function () {

  var _ = require('underscore');
  var request = require('superagent');
  var cheerio = require('cheerio');
  var wordCount = require('word-count');

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

  var error = utils.error;
  var isSameDomain = utils.isSameDomain;
  var resolveUrl = utils.resolveUrl;
  var isValidBaseUrl = utils.isValidBaseUrl;

  function getData (scope, html, parentUrl) {
    var $ = cheerio.load(html);

    var links = _.chain($('a[href]').toArray().map(function (el) {
      var element = $(el);

      return element.attr('href');
    }))
    .groupBy(_.identity)
    .map(function (values, key) {
      return {
        url: key,
        resolved: resolveUrl(key, parentUrl),
        references: values.length
      };
    })
    .sortBy('url')
    .groupBy(function (link) {
      if (link.url.indexOf('#') === 0) {
        return 'same-page';
      }

      if (link.url.indexOf('tel:') === 0) {
        return 'phone';
      }

      if (link.url.indexOf('mailto:') === 0) {
        return 'email';
      }

      return isSameDomain(link.url, scope.baseUrl.resolved) ? 'internal' : 'external';
    })
    .value();

    return {
      title: $('title').text() || null,
      wordCount: wordCount($('body').text()),
      charset: $('meta[charset]').attr('charset') || null,
      meta: _.object($('meta[name],meta[property]').toArray().map(function (el) {
        var element = $(el);

        return [element.attr('name') || element.attr('property'), element.attr('content')];
      })),
      links: {
        internal: links.internal || [],
        external: links.external || [],
        'same-page': links['same-page'] || [],
        email: links.email || [],
        phone: links.phone || [],
        unknown: links.unknown || []
      }
    };
  }

  function continueCrawl (scope, url) {
    request
    .get(url)
    .accept('text/html')
    .send()
    .end(function (err, res) {
      if (err) {
        error(err);
      } else {
        if (res.type === 'text/html' && res.text && !(url in scope.json)) {
          scope.json[url] = getData(scope, res.text, url);
        }

        // if (urls.length && currentDepth < depth) {
        //   while (urls.length) {
        //     var childUrl = urls.shift();
        //
        //     continueCrawl(childUrl, url, currentDepth + 1);
        //   }
        // }
        if (typeof process === 'object') {
          process.stdout.write(JSON.stringify(scope.json, null, 2) + '\n'); // eslint-disable-line no-undef
        } else if (typeof scope.callback === 'function') {
          scope.callback(JSON.stringify(scope.json, null, 2) + '\n');
        }
      }
    });
  }

  function crawl (options, callback) {
    isValidBaseUrl(options.url);

    var scope = {
      json: {},
      currentDepth: 0,
      baseUrl: {
        url: options.url,
        resolved: resolveUrl(options.url)
      },
      urlsToCrawl: [options.url],
      urlsCrawled: [],
      depth: options.depth,
      format: options.format,

      callback: callback
    };

    continueCrawl(scope, scope.urlsToCrawl[0]);

  }

  module.exports = {
    crawl: crawl
  };

})();
<commit_msg>Crawl only resolved URLs<commit_after>'use strict';

(function () {

  var _ = require('underscore');
  var request = require('superagent');
  var cheerio = require('cheerio');
  var wordCount = require('word-count');

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

  var error = utils.error;
  var isSameDomain = utils.isSameDomain;
  var resolveUrl = utils.resolveUrl;
  var isValidBaseUrl = utils.isValidBaseUrl;

  function getData (scope, html, parentUrl) {
    var $ = cheerio.load(html);

    var links = _.chain($('a[href]').toArray().map(function (el) {
      var element = $(el);

      return element.attr('href');
    }))
    .groupBy(_.identity)
    .map(function (values, key) {
      return {
        url: key,
        resolved: resolveUrl(key, parentUrl),
        references: values.length
      };
    })
    .sortBy('url')
    .groupBy(function (link) {
      if (link.url.indexOf('#') === 0) {
        return 'same-page';
      }

      if (link.url.indexOf('tel:') === 0) {
        return 'phone';
      }

      if (link.url.indexOf('mailto:') === 0) {
        return 'email';
      }

      return isSameDomain(link.url, scope.baseUrl.resolved) ? 'internal' : 'external';
    })
    .value();

    return {
      title: $('title').text() || null,
      wordCount: wordCount($('body').text()),
      charset: $('meta[charset]').attr('charset') || null,
      meta: _.object($('meta[name],meta[property]').toArray().map(function (el) {
        var element = $(el);

        return [element.attr('name') || element.attr('property'), element.attr('content')];
      })),
      links: {
        internal: links.internal || [],
        external: links.external || [],
        'same-page': links['same-page'] || [],
        email: links.email || [],
        phone: links.phone || [],
        unknown: links.unknown || []
      }
    };
  }

  function continueCrawl (scope, url) {
    request
    .get(url)
    .accept('text/html')
    .send()
    .end(function (err, res) {
      if (err) {
        error(err);
      } else {
        if (res.type === 'text/html' && res.text && !(url in scope.json)) {
          scope.json[url] = getData(scope, res.text, url);
        }

        // if (urls.length && currentDepth < depth) {
        //   while (urls.length) {
        //     var childUrl = urls.shift();
        //
        //     continueCrawl(childUrl, url, currentDepth + 1);
        //   }
        // }
        if (typeof process === 'object') {
          process.stdout.write(JSON.stringify(scope.json, null, 2) + '\n'); // eslint-disable-line no-undef
        } else if (typeof scope.callback === 'function') {
          scope.callback(JSON.stringify(scope.json, null, 2) + '\n');
        }
      }
    });
  }

  function crawl (options, callback) {
    isValidBaseUrl(options.url);

    var resolvedUrl = resolveUrl(options.url);

    var scope = {
      json: {},
      currentDepth: 0,
      baseUrl: {
        url: options.url,
        resolved: resolvedUrl
      },
      urlsToCrawl: [resolvedUrl],
      urlsCrawled: [],
      depth: options.depth,
      format: options.format,

      callback: callback
    };

    continueCrawl(scope, scope.urlsToCrawl[0]);

  }

  module.exports = {
    crawl: crawl
  };

})();
<|endoftext|>


<commit_before>import './style/index.scss';

import './shared/utils/console';

//IE Fix
if (!window.location.origin) {
    window.location.origin = `${window.location.protocol}//${window.location.hostname}${(window.location.port ? `:${window.location.port}` : '')}`;
}

//IE Console-Fix
if (typeof window.console === 'undefined') {
    window.console = {
        log: Function.prototype,
        error: Function.prototype
    };
}

//WorkAround for chrome

/*document.parentWindow = {
    external: {
        SetKeyValue: (name, value) => {
            localStorage.setItem(name, value);
        },
        GetKeyValue: (name) => {
            return localStorage.getItem(name);
        }
    }
};*/

import ChaynsInfo from './web/chaynsInfo';
window.ChaynsInfo = ChaynsInfo;

require('./web/customTappCommunication');
require('./web/jsonCalls');
require('./web/login');
require('./web/chaynsWeb');<commit_msg>fixes chrome workaround<commit_after>import './style/index.scss';

import './shared/utils/console';

//IE Fix
if (!window.location.origin) {
    window.location.origin = `${window.location.protocol}//${window.location.hostname}${(window.location.port ? `:${window.location.port}` : '')}`;
}

//IE Console-Fix
if (typeof window.console === 'undefined') {
    window.console = {
        log: Function.prototype,
        error: Function.prototype
    };
}

//WorkAround for chrome

/*document.parentWindow = {
    external: {
        PutKeyValue: (name, value) => {
            localStorage.setItem(name, value);
        },
        GetKeyValue: (name) => {
            return localStorage.getItem(name);
        }
    }
};*/

import ChaynsInfo from './web/chaynsInfo';
window.ChaynsInfo = ChaynsInfo;

require('./web/customTappCommunication');
require('./web/jsonCalls');
require('./web/login');
require('./web/chaynsWeb');<|endoftext|>


<commit_before>export { default as connect } from './components/connect'
export { default as PromiseState } from './PromiseState'
<commit_msg>Export modules as an object<commit_after>import connect from './components/connect'
import PromiseState from './PromiseState'

export { connect, PromiseState }
<|endoftext|>