<commit_before>var _ = require('../util')
var Cache = require('../cache')
var expressionCache = new Cache(1000)

function noop () {}

/**
 * Extract all accessor paths from an expression.
 *
 * @param {String} code
 * @return {Array} - extracted paths
 */

// remove strings and object literal keys that could contain arbitrary chars
var PREPARE_RE = /'[^']*'|"[^"]*"|[\{,]\s*[\w\$_]+\s*:/g
// turn anything that is not valid path char into commas
var CONVERT_RE = /[^\w$\.]+/g
// remove keywords & number literals
var KEYWORDS = 'Math,break,case,catch,continue,debugger,default,delete,do,else,false,finally,for,function,if,in,instanceof,new,null,return,switch,this,throw,true,try,typeof,var,void,while,with,undefined,abstract,boolean,byte,char,class,const,double,enum,export,extends,final,float,goto,implements,import,int,interface,long,native,package,private,protected,public,short,static,super,synchronized,throws,transient,volatile,arguments,let,yield'
var KEYWORDS_RE = new RegExp('\\b' + KEYWORDS.replace(/,/g, '\\b|\\b') + '\\b|\\b\\d[^,]*', 'g')
// remove trailing commas
var COMMA_RE = /^,+|,+$/
// split by commas
var SPLIT_RE = /,+/

function extractPaths (code) {
  code = code
    .replace(PREPARE_RE, ',')
    .replace(CONVERT_RE, ',')
    .replace(KEYWORDS_RE, '')
    .replace(COMMA_RE, '')
  return code
    ? code.split(SPLIT_RE)
    : []
}

/**
 * Escape leading dollar signs from paths for regex construction.
 * Otherwise it can be mistaken as the linestart token.
 *
 * @param {String} path
 * @return {String}
 */

function escapeDollar (path) {
  return path.charAt(0) === '$'
    ? '\\' + path
    : path
}

/**
 * Save / Rewrite / Restore
 *
 * When rewriting paths found in an expression, it is possible
 * for the same letter sequences to be found in strings and Object
 * literal property keys. Therefore we remove and store these
 * parts in a temporary array, and restore them after the path
 * rewrite.
 */

var saved = []
var NEWLINE_RE = /\n/g
var RESTORE_RE = /<%(\d+)%>/g

/**
 * Save replacer
 *
 * @param {String} str
 * @return {String} - placeholder with index
 */

function save (str) {
  var i = saved.length
  saved[i] = str.replace(NEWLINE_RE, '\\n')
  return '<%' + i + '%>'
}

/**
 * Path rewrite replacer
 *
 * @param {String} path
 * @return {String}
 */

function rewrite (path) {
  return path.charAt(0) + 'scope.' + path.slice(1)
}

/**
 * Restore replacer
 *
 * @param {String} str
 * @param {String} i - matched save index
 * @return {String}
 */

function restore (str, i) {
  return saved[i]
}

/**
 * Build a getter function. Requires eval.
 * We isolate the try/catch so it doesn't affect the optimization
 * of the parse function when it is not called.
 *
 * @param {String} body
 * @return {Function|undefined}
 */

function build (body) {
  try {
    return new Function('scope', body)
  } catch (e) {}
}

/**
 * Parse an expression and rewrite into a getter function
 *
 * @param {String} code
 * @return {Function}
 */

exports.parse = function (code) {
  // try cache
  var hit = expressionCache.get(code)
  if (hit) {
    return hit
  }
  // extract paths
  var paths = extractPaths(code)
  var body = 'return ' + code + ';'
  // rewrite paths
  if (paths.length) {
    var pathRE = new RegExp(
      '[^$\\w\\.](' +
      paths.map(escapeDollar).join('|') +
      ')[^$\\w\\.]',
      'g'
    )
    saved.length = 0
    body = body
      .replace(PREPARE_RE, save)
      .replace(pathRE, rewrite)
      .replace(RESTORE_RE, restore)
  }
  // generate function
  var fn = build(body)
  if (fn) {
    expressionCache.put(code, fn)
  } else {
    _.warn('Invalid expression: "' + code + '"\nGenerated function body: ' + body)
    console.log(paths)
  }
  return fn || noop
}<commit_msg>remove log<commit_after>var _ = require('../util')
var Cache = require('../cache')
var expressionCache = new Cache(1000)

function noop () {}

/**
 * Extract all accessor paths from an expression.
 *
 * @param {String} code
 * @return {Array} - extracted paths
 */

// remove strings and object literal keys that could contain arbitrary chars
var PREPARE_RE = /'[^']*'|"[^"]*"|[\{,]\s*[\w\$_]+\s*:/g
// turn anything that is not valid path char into commas
var CONVERT_RE = /[^\w$\.]+/g
// remove keywords & number literals
var KEYWORDS = 'Math,break,case,catch,continue,debugger,default,delete,do,else,false,finally,for,function,if,in,instanceof,new,null,return,switch,this,throw,true,try,typeof,var,void,while,with,undefined,abstract,boolean,byte,char,class,const,double,enum,export,extends,final,float,goto,implements,import,int,interface,long,native,package,private,protected,public,short,static,super,synchronized,throws,transient,volatile,arguments,let,yield'
var KEYWORDS_RE = new RegExp('\\b' + KEYWORDS.replace(/,/g, '\\b|\\b') + '\\b|\\b\\d[^,]*', 'g')
// remove trailing commas
var COMMA_RE = /^,+|,+$/
// split by commas
var SPLIT_RE = /,+/

function extractPaths (code) {
  code = code
    .replace(PREPARE_RE, ',')
    .replace(CONVERT_RE, ',')
    .replace(KEYWORDS_RE, '')
    .replace(COMMA_RE, '')
  return code
    ? code.split(SPLIT_RE)
    : []
}

/**
 * Escape leading dollar signs from paths for regex construction.
 * Otherwise it can be mistaken as the linestart token.
 *
 * @param {String} path
 * @return {String}
 */

function escapeDollar (path) {
  return path.charAt(0) === '$'
    ? '\\' + path
    : path
}

/**
 * Save / Rewrite / Restore
 *
 * When rewriting paths found in an expression, it is possible
 * for the same letter sequences to be found in strings and Object
 * literal property keys. Therefore we remove and store these
 * parts in a temporary array, and restore them after the path
 * rewrite.
 */

var saved = []
var NEWLINE_RE = /\n/g
var RESTORE_RE = /<%(\d+)%>/g

/**
 * Save replacer
 *
 * @param {String} str
 * @return {String} - placeholder with index
 */

function save (str) {
  var i = saved.length
  saved[i] = str.replace(NEWLINE_RE, '\\n')
  return '<%' + i + '%>'
}

/**
 * Path rewrite replacer
 *
 * @param {String} path
 * @return {String}
 */

function rewrite (path) {
  return path.charAt(0) + 'scope.' + path.slice(1)
}

/**
 * Restore replacer
 *
 * @param {String} str
 * @param {String} i - matched save index
 * @return {String}
 */

function restore (str, i) {
  return saved[i]
}

/**
 * Build a getter function. Requires eval.
 * We isolate the try/catch so it doesn't affect the optimization
 * of the parse function when it is not called.
 *
 * @param {String} body
 * @return {Function|undefined}
 */

function build (body) {
  try {
    return new Function('scope', body)
  } catch (e) {}
}

/**
 * Parse an expression and rewrite into a getter function
 *
 * @param {String} code
 * @return {Function}
 */

exports.parse = function (code) {
  // try cache
  var hit = expressionCache.get(code)
  if (hit) {
    return hit
  }
  // extract paths
  var paths = extractPaths(code)
  var body = 'return ' + code + ';'
  // rewrite paths
  if (paths.length) {
    var pathRE = new RegExp(
      '[^$\\w\\.](' +
      paths.map(escapeDollar).join('|') +
      ')[^$\\w\\.]',
      'g'
    )
    saved.length = 0
    body = body
      .replace(PREPARE_RE, save)
      .replace(pathRE, rewrite)
      .replace(RESTORE_RE, restore)
  }
  // generate function
  var fn = build(body)
  if (fn) {
    expressionCache.put(code, fn)
  } else {
    _.warn('Invalid expression: "' + code + '"\nGenerated function body: ' + body)
  }
  return fn || noop
}<|endoftext|>


<commit_before>define([
    'require',
    '../lib/jquery.form/jquery.form',
    '../logging',
    './inject'
], function(require) {
    var log = require('../logging').getLogger('ajaxify');

    var init = function($el, opts) {
        // skip elements that are covered by old-style injection
        if ($el.is('.injection,[data-injection]')) {
            log.debug('skipping element claimed by old injection', $el);
            return false;
        }

        var url = ($el.attr('action') || $el.attr('href') || '').split('#')[0];
        if (!url) {
            log.error('Element has neither action nor href', $el);
            return false;
        }

        // ajaxify form
        if ($el.is('form')) {
            if (($el.attr('method') || '').toLowerCase() === 'get') {
                log.warn('Ignoring form method GET, enforcing POST');
            }
            $el.ajaxForm({
                context: $el,
                // in plone we use this to figure out whether a form is
                // requested or submitted
                // XXX: consider setting this via $.ajaxSetup in a
                // specific application
                data: {submit: "submit"},
                // enforce POST, as we compare the url to figure out
                // who was triggered
                //type: $el.attr('method') || 'POST',
                type: 'POST',
                url: url
            });
        } else {
            $el.on('click.ajaxify', function(ev, opts) {
                ev.preventDefault();
                $.ajax({
                    context: $el,
                    url: url
                });
            });
        }

        $el.ajaxError(function(ev, jqxhr, ajaxopts, error) {
            // ajaxHandlers are global, we are only interested in our form
            if (url !== ajaxopts.url) {
                log.debug('ignoring ajax event', ajaxopts.url, url);
                return;
            }
            log.debug('error', ev, jqxhr, opts, error);

            // XXX: this needs to be solved differently
            var msg = [jqxhr.status, jqxhr.statusText, error, opts.url].join(' '),
                // XXX: error notification pattern!
                $error = $('
'
                           + '
Error
'
                           + '
'+msg+'
'
                           + '
');
            var inject = require('./inject');
            inject.append($error, $('body'));
        });

        $el.ajaxSuccess(function(ev, jqxhr, ajaxopts, data) {
            // ajaxHandlers are global, we are only interested in our form
            // XXX: figure out how much of this is true with a multi-form test
            if (url !== ajaxopts.url) {
                log.debug('ignoring ajax event - not ours', ajaxopts.url, url);
                return;
            }
            log.debug('success', ev, jqxhr, opts);

            // XXX: this needs to be solved differently
            if (!data) return;
            var $forms = $(data).find('form[id]');
            $forms.each(function() {
                var $form = $(this),
                    id = $(this).attr('id'),
                    $ourform = $('#' + id);
                if ($ourform.length > 0) {
                    $ourform.attr({action: $form.attr('action')});
                } else {
                    console.warn(
                        'Ignored form in respone data: not matching id', $form);
                }
            });
        });

        return $el;
    };

    return {
        markup_trigger: 'form.ajaxify, a.ajaxify',
        initialised_class: 'ajaxified',
        init: init
    };
});
<commit_msg>handle redirects to rewrite form actions<commit_after>define([
    'require',
    '../lib/jquery.form/jquery.form',
    '../logging',
    './inject'
], function(require) {
    var log = require('../logging').getLogger('ajaxify');

    var init = function($el, opts) {
        // skip elements that are covered by old-style injection
        if ($el.is('.injection,[data-injection]')) {
            log.debug('skipping element claimed by old injection', $el);
            return false;
        }

        var url = ($el.attr('action') || $el.attr('href') || '').split('#')[0];
        if (!url) {
            log.error('Element has neither action nor href', $el);
            return false;
        }

        // ajaxify form
        if ($el.is('form')) {
            if (($el.attr('method') || '').toLowerCase() === 'get') {
                log.warn('Ignoring form method GET, enforcing POST');
            }
            $el.ajaxForm({
                context: $el,
                // in plone we use this to figure out whether a form is
                // requested or submitted
                // XXX: consider setting this via $.ajaxSetup in a
                // specific application
                data: {submit: "submit"},
                // enforce POST, as we compare the url to figure out
                // who was triggered
                //type: $el.attr('method') || 'POST',
                type: 'POST',
                url: url
            });
        } else {
            $el.on('click.ajaxify', function(ev, opts) {
                ev.preventDefault();
                $.ajax({
                    context: $el,
                    url: url
                });
            });
        }

        $el.ajaxError(function(ev, jqxhr, ajaxopts, error) {
            // ajaxHandlers are global, we are only interested in our form
            if (url !== ajaxopts.url) {
                log.debug('ignoring ajax event', ajaxopts.url, url);
                return;
            }
            log.debug('error', ev, jqxhr, opts, error);

            // XXX: this needs to be solved differently
            var msg = [jqxhr.status, jqxhr.statusText, error, opts.url].join(' '),
                // XXX: error notification pattern!
                $error = $('
'
                           + '
Error
'
                           + '
'+msg+'
'
                           + '
');
            var inject = require('./inject');
            inject.append($error, $('body'));
        });

        $el.ajaxSuccess(function(ev, jqxhr, ajaxopts, data) {
            // ajaxHandlers are global, we are only interested in our form
            // XXX: figure out how much of this is true with a multi-form test
            if (url !== ajaxopts.url) {
                log.debug('ignoring ajax event - not ours', ajaxopts.url, url);
                return;
            }
            var redirect = jqxhr.getResponseHeader('X-Patterns-Redirect-Url'),
                oldurl = jqxhr.getResponseHeader('X-Patterns-Previous-Url');
            if (!redirect) {
                // We are done
                log.debug('success', ev, jqxhr, opts);
                return;
            }
            log.debug('received redirect', redirect);
            if (!oldurl) {
                log.error('Missing header: X-Patterns-Previous-Url');
                return;
            }
            if (!oldurl.slice(-1) === '/') oldurl = oldurl + '/';

            $('form[action^="' + oldurl + '"]').each(function() {
                var $form = $(this),
                    action = $form.attr('action').replace(oldurl, redirect);
                $form.attr({action: action});
                log.debug('rewrote form action: s:', oldurl, ":", redirect, ":", $form);
            });
        });

        return $el;
    };

    return {
        markup_trigger: 'form.ajaxify, a.ajaxify',
        initialised_class: 'ajaxified',
        init: init
    };
});
<|endoftext|>


<commit_before>define([
    'require',
    '../lib/jquery.form/jquery.form',
    '../logging',
    './inject'
], function(require) {
    var log = require('../logging').getLogger('ajaxify');

    var init = function($el, opts) {
        // skip elements that are covered by old-style injection
        if ($el.is('.injection,[data-injection]')) {
            log.debug('skipping element claimed by old injection', $el);
            return false;
        }

        // ajaxify form
        if ($el.is('form')) {
            $el.ajaxForm({
                context: $el,
                // in plone we use this to figure out whether a form is
                // requested or submitted
                // XXX: consider setting this via $.ajaxSetup in a
                // specific application
                data: {submit: "submit"},
                type: $el.attr('method') || 'POST',
                url: $el.attr('action')
            });
        } else {
            $el.on('click.ajaxify', function(ev, opts) {
                ev.preventDefault();
                $.ajax({
                    context: $el,
                    url: $el.attr('href')
                });
            });
        }

        $el.ajaxError(function(ev, jqxhr, opts, error) {
            log.debug('error', ev, jqxhr, opts, error);
            // ajaxHandlers are global, we are only interested in our form
            if (!(ev.target === $el[0])) return;

            // XXX: this needs to be solved differently
            var msg = [jqxhr.status, jqxhr.statusText, error, opts.url].join(' '),
                // XXX: error notification pattern!
                $error = $('
'
                           + '
Error
'
                           + '
'+msg+'
'
                           + '
');
            var inject = require('./inject');
            inject.append($error, $('body'));
        });

        $el.ajaxSuccess(function(ev, jqxhr, opts, data) {
            log.debug('success', ev, jqxhr, opts);
            // ajaxHandlers are global, we are only interested in our form
            // XXX: figure out how much of this is true with a multi-form test
            if (!(ev.target === $el[0])) return;

            // XXX: this needs to be solved differently
            if (!data) return;
            var $forms = $(data).find('form[id]');
            $forms.each(function() {
                var $form = $(this),
                    id = $(this).attr('id'),
                    $ourform = $('#' + id);
                if ($ourform.length > 0) {
                    $ourform.attr({action: $form.attr('action')});
                } else {
                    console.warn(
                        'Ignored form in respone data: not matching id', $form);
                }
            });
        });

        return $el;
    };

    return {
        markup_trigger: 'form, a.ajaxify',
        initialised_class: 'ajaxified',
        init: init
    };
});<commit_msg>not all forms<commit_after>define([
    'require',
    '../lib/jquery.form/jquery.form',
    '../logging',
    './inject'
], function(require) {
    var log = require('../logging').getLogger('ajaxify');

    var init = function($el, opts) {
        // skip elements that are covered by old-style injection
        if ($el.is('.injection,[data-injection]')) {
            log.debug('skipping element claimed by old injection', $el);
            return false;
        }

        // ajaxify form
        if ($el.is('form')) {
            $el.ajaxForm({
                context: $el,
                // in plone we use this to figure out whether a form is
                // requested or submitted
                // XXX: consider setting this via $.ajaxSetup in a
                // specific application
                data: {submit: "submit"},
                type: $el.attr('method') || 'POST',
                url: $el.attr('action')
            });
        } else {
            $el.on('click.ajaxify', function(ev, opts) {
                ev.preventDefault();
                $.ajax({
                    context: $el,
                    url: $el.attr('href')
                });
            });
        }

        $el.ajaxError(function(ev, jqxhr, opts, error) {
            log.debug('error', ev, jqxhr, opts, error);
            // ajaxHandlers are global, we are only interested in our form
            if (!(ev.target === $el[0])) return;

            // XXX: this needs to be solved differently
            var msg = [jqxhr.status, jqxhr.statusText, error, opts.url].join(' '),
                // XXX: error notification pattern!
                $error = $('
'
                           + '
Error
'
                           + '
'+msg+'
'
                           + '
');
            var inject = require('./inject');
            inject.append($error, $('body'));
        });

        $el.ajaxSuccess(function(ev, jqxhr, opts, data) {
            log.debug('success', ev, jqxhr, opts);
            // ajaxHandlers are global, we are only interested in our form
            // XXX: figure out how much of this is true with a multi-form test
            if (!(ev.target === $el[0])) return;

            // XXX: this needs to be solved differently
            if (!data) return;
            var $forms = $(data).find('form[id]');
            $forms.each(function() {
                var $form = $(this),
                    id = $(this).attr('id'),
                    $ourform = $('#' + id);
                if ($ourform.length > 0) {
                    $ourform.attr({action: $form.attr('action')});
                } else {
                    console.warn(
                        'Ignored form in respone data: not matching id', $form);
                }
            });
        });

        return $el;
    };

    return {
        markup_trigger: 'form.ajaxify, a.ajaxify',
        initialised_class: 'ajaxified',
        init: init
    };
});
<|endoftext|>


<commit_before>/**
 * @license
 * Patterns @VERSION@ tooltip - tooltips
 *
 * Copyright 2008-2012 Simplon B.V.
 * Copyright 2011 Humberto Sermeño
 * Copyright 2011 SYSLAB.COM GmbH
 */
define([
    'require',
    '../core/init',
    '../utils'
], function(require) {
    var utils = require('../utils'),
        mapal = require('../core/init');

    var tooltip = {
        count: 0,

        init: function() {
        },

        initContent: function(root) {
            var $root = $(root);
            var init = function($trigger) {
                var options = utils.parseOptions($trigger.data("tooltip"));
                options.title = $trigger.attr("title");
                $trigger.removeAttr("title");
                $trigger.data("mapal.tooltip", options);
                tooltip.setupShowEvents($trigger);
            };
            if ($root.is('[data-tooltip]')) init($root);
            $("*[data-tooltip]", $root).each(function() {
                init($(this));
            });
        },

        setupShowEvents: function($trigger) {
            var parameters = $trigger.data("mapal.tooltip");
            if (parameters.click) {
                $trigger.on("click.tooltip", $trigger, tooltip.show);
            } else {
                $trigger.on("mouseover.tooltip", $trigger, tooltip.show);
                // Make sure click on the trigger element becomes a NOP
                $trigger.on("click.tooltip", $trigger, tooltip.blockDefault);
            }
        },

        removeShowEvents: function($trigger) {
            $trigger.off(".tooltip");
        },

        setupHideEvents: function($trigger) {
            var $container = tooltip.getContainer($trigger),
                parameters = $trigger.data("mapal.tooltip");
            if (parameters.sticky) {
                $container.find(".closePanel")
                    .on("click.tooltip", $trigger, tooltip.hide);
                // Make sure click on the trigger element becomes a NOP
                $trigger.on("click.tooltip", $trigger, tooltip.blockDefault);
            } else {
                if (parameters.click) {
                    $container.on("click.tooltip", $trigger, function(ev) {
                        ev.stopPropagation();
                    });
                    $(document).on("click.tooltip", $trigger, tooltip.hide);
                    $trigger.on("click.tooltip", tooltip.blockDefault);
                    // close if something inside the tooltip triggered an injection
                    $container.on('patterns-inject-triggered.tooltip',
                                  $trigger, tooltip.hide);
                    $container.on('patterns-inject_interim-triggered.tooltip',
                                  $trigger, tooltip.hide);
                    $container.on('submit.tooltip', $trigger, tooltip.hide);
                } else {
                    $container.on("click.tooltip", $trigger, tooltip.hide);
                    $trigger.on("mouseleave.tooltip", $trigger, tooltip.hide);
                    $trigger.on("click.tooltip", tooltip.blockDefault);
                }
            }
        },

        removeHideEvents: function($trigger) {
            var $container = tooltip.getContainer($trigger);
            $(document).off(".tooltip");
            $container.off(".tooltip");
            $container.find(".closePanel").off(".tooltip");
            $trigger.off(".tooltip");
        },

        blockDefault: function(event) {
            event.preventDefault();
        },

        show: function(event) {
            event.preventDefault();
            var $trigger = event.data,
                $container = tooltip.getContainer($trigger),
                namespace = $container.attr("id"),
                options = $trigger.data("mapal.tooltip");

            tooltip.removeShowEvents($trigger);
            // Wrap in a timeout to make sure this click is not used to
            // trigger a hide as well.
            setTimeout(function() { tooltip.setupHideEvents($trigger) }, 50);

            function ajax_show() {
                $container.find(">div >*").css("opacity", 1);
                tooltip.positionContainer($trigger, $container);
            }

            if (options.ajax) {
                var source = $trigger.attr("href").split("#"),
                    target_id = $container.find("progress").attr("id");
                mapal.injection.load($trigger, source[0], target_id+":replace", source[1] || [],
                        ajax_show, true);
                // always load fresh tooltips
                // delete options.ajax;
                $trigger.data("mapal.tooltip", options);
            }

            tooltip.positionContainer($trigger, $container);
            $container.css("visibility", "visible");

            // reposition tooltip everytime we scroll or resize
            $(window).on("scroll." + namespace + " resize." + namespace, function () {
                 tooltip.positionContainer($trigger, $container);
            });
        },

        hide: function(event) {
            var $trigger = event.data,
                $container = tooltip.getContainer($trigger),
                namespace = $container.attr("id");
            tooltip.removeHideEvents($trigger);
            $container.css("visibility", "hidden");
            $(window).off("." + namespace);
            tooltip.setupShowEvents($trigger);
        },

        getContainer: function($trigger) {
            var $container = $trigger.data("mapal.tooltip.container");
            if ($container===undefined) {
                $container=tooltip.createContainer($trigger);
                $trigger.data("mapal.tooltip.container", $container);
            }
            return $container;
        },

        createContainer: function($trigger) {
            var options = $trigger.data("mapal.tooltip"),
                count = ++tooltip.count,
                $content, $container;

            $container = $("
", {"class": "tooltip-container",
                                     "id": "tooltip" + count});
            $container.css("visibility", "hidden");
            if (options.ajax) {
                $content = $("<progress/>", {"id": "tooltip-load-" + count});
            } else {
                $content = $("
").text(options.title);
            }
            $container.append(
                $("
").css("display", "block").append($content))
                .append($("", {"class": "pointer"}));
            if (options.sticky && !options.noclose) {
                $("<button/>", {"class": "closePanel"})
                    .text("Close")
                    .insertBefore($container.find("*"));
            }
            $("body").append($container);
            return $container;
        },

        boundingBox: function($el) {
            var box = $el.offset();
            box.height = $el.height();
            box.width = $el.width();
            box.bottom = box.top + box.height;
            box.right = box.left + box.width;
            return box;
        },

        positionStatus: function($trigger, $container) {
            var trigger_box = tooltip.boundingBox($trigger),
                tooltip_box = tooltip.boundingBox($container),
                $window = $(window),
                window_width = $window.width(),
                window_height = $window.height(),
                trigger_center,
                scroll = {},
                space = {},
                container_offset = {},
                tip_offset = {},
                cls = "";

            scroll.top = $window.scrollTop();
            scroll.left = $window.scrollLeft();
            trigger_center = {top: trigger_box.top + (trigger_box.height/2),
                              left: trigger_box.left + (trigger_box.width/2)};
            space.top = trigger_box.top - scroll.top;
            space.bottom = window_height - space.top - trigger_box.height;
            space.left = trigger_box.left - scroll.left;
            space.right = window_width - space.left - trigger_box.width;

            return {space: space,
                    trigger_center: trigger_center,
                    trigger_box: trigger_box,
                    tooltip_box: tooltip_box,
                    scroll: scroll,
                    window: {width: window_width, height: window_height}
            };
        },

        // Help function to determine the best position for a tooltip.  Takes
        // the positioning status (as generated by positionStatus) as input
        // and returns a two-character position indiciator.
        findBestPosition: function(status) {
            var space = status.space,
                 cls = "";

            if (space.top > Math.max(space.right, space.bottom, space.left)) {
                cls = "b";
            } else if (space.right > Math.max(space.bottom, space.left, space.top)) {
                cls = "l";
            } else if (space.bottom > Math.max(space.left, space.top, space.right)) {
                cls = "t";
            } else {
                cls = "r";
            }

            switch (cls[0]) {
            case "t":
            case "b":
                if (Math.abs(space.left-space.right) < 20) {
                    cls += "m";
                } else if (space.left > space.right) {
                    cls += "r";
                } else {
                    cls += "l";
                }
                break;
            case "l":
            case "r":
                if (Math.abs(space.top-space.bottom) < 20) {
                    cls += "m";
                } else if (space.top > space.bottom) {
                    cls += "b";
                } else {
                    cls += "t";
                }
            }
            return cls;
        },

        isVisible: function(status, position) {
            var space = status.space,
                tooltip_box = status.tooltip_box;

            switch (position[0]) {
            case "t":
                if (tooltip_box.height > space.bottom) {
                    return false;
                }
                break;
            case "r":
                if (tooltip_box.width > space.left) {
                    return false;
                }
                break;
            case "b":
                if (tooltip_box.height > space.top) {
                    return false;
                }
                break;
            case "l":
                if (tooltip_box.width > space.right) {
                    return false;
                }
                break;
            default:
                return false;
            }

            switch (position[0]) {
            case "t":
            case "b":
                switch (position[1]) {
                    case "l":
                        if ((tooltip_box.width-20)>space.right) {
                            return false;
                        }
                        break;
                    case "m":
                        if ((tooltip_box.width/2)>space.left || (tooltip_box.width/2)>space.right) {
                            return false;
                        }
                        break;
                    case "r":
                        if ((tooltip_box.width-20)>space.left) {
                            return false;
                        }
                        break;
                    default:
                        return false;
                }
                break;
            case "l":
            case "r":
                switch (position[1]) {
                    case "t":
                        if ((tooltip_box.height-20)>space.bottom) {
                            return false;
                        }
                        break;
                    case "m":
                        if ((tooltip_box.height/2)>space.top || (tooltip_box.height/2)>space.bottom) {
                            return false;
                        }
                        break;
                    case "b":
                        if ((tooltip_box.height-20)>space.top) {
                            return false;
                        }
                    default:
                        return false;
                }
                break;
            }
            return true;
        },

        VALIDPOSITION: /^([lr][tmb]|[tb][lmr])$/,

        positionContainer: function($trigger, $container) {
            var status = tooltip.positionStatus($trigger, $container),
                options = $trigger.data("mapal.tooltip"),
                container_offset = {},
                tip_offset = {},
                position;

            if (options.position) {
                var positions = options.position.split("-"), i;
                for (i=0; i<positions.length; i++) {
                    if (!tooltip.VALIDPOSITION.test(positions[i])) {
                        continue;
                    }

                    if (options.forcePosition || tooltip.isVisible(status, positions[i])) {
                        position = positions[i];
                        break;
                    }
                }
            }

            if (!position) {
                position = tooltip.findBestPosition(status);
            }

            var trigger_box = status.trigger_box,
                tooltip_box = status.tooltip_box,
                trigger_center = status.trigger_center,
                content_css = {"max-height": "", "max-width": ""},
                $window = $(window),
                bottom_row, x;

            switch (position[0]) {
            case "t":
                container_offset.top = trigger_box.bottom + 20;
                tip_offset.top = -23;
                bottom_row = status.scroll.top + status.window.height,
                content_css["max-height"] = (bottom_row - container_offset.top - 30) + "px";
                break;
            case "l":
                container_offset.left = trigger_box.right + 20;
                tip_offset.left = -23;
                break;
            case "b":
                container_offset.top = trigger_box.top - tooltip_box.height + 10;
                tip_offset.top = tooltip_box.height;
                x = (status.scroll.top + 10) - container_offset.top;
                if (x>0) {
                    tip_offset.top -= x;
                    content_css["max-height"] = (tooltip_box.height - x) + "px";
                    container_offset.top += x;
                }
                break;
            case "r":
                container_offset.left = trigger_box.left - tooltip_box.width - 20;
                tip_offset.left = tooltip_box.width;
                break;
            }

            switch (position[0]) {
            case "t":
            case "b":
                switch (position[1]) {
                case "l":
                    container_offset.left = trigger_center.left - 20;
                    tip_offset.left = 0;
                    break;
                case "m":
                    container_offset.left = trigger_center.left - (tooltip_box.width/2);
                    tip_offset.left = tooltip_box.width/2 - 10;
                    break;
                case "r":
                    container_offset.left = trigger_center.left + 29 - tooltip_box.width;
                    tip_offset.left = tooltip_box.width - 20;
                    break;
                }
                break;
            case "l":
            case "r":
                switch (position[1]) {
                    case "t":
                        container_offset.top = trigger_center.top - 30;
                        tip_offset.top = 0;
                        break;
                    case "m":
                        container_offset.top = trigger_center.top - (tooltip_box.height/2);
                        tip_offset.top = tooltip_box.height/2 - 10;
                        break;
                    case "b":
                        container_offset.top = trigger_center.top + 20 - tooltip_box.height;
                        tip_offset.top = tooltip_box.height - 20;
                        break;
                }
                break;
            }

            $container.find("> div").css(content_css);
            $container.attr("class", "tooltip-container " + position);
            $container.css({
                top: container_offset.top+"px",
                left: container_offset.left+"px",
            });
            $container.find(".pointer").css({
                top: tip_offset.top+"px",
                left: tip_offset.left+"px"});
        }
    };

    return tooltip;
});

// vim: sw=4 expandtab
<commit_msg>Set max width on l-positioned tips.<commit_after>/**
 * @license
 * Patterns @VERSION@ tooltip - tooltips
 *
 * Copyright 2008-2012 Simplon B.V.
 * Copyright 2011 Humberto Sermeño
 * Copyright 2011 SYSLAB.COM GmbH
 */
define([
    'require',
    '../core/init',
    '../utils'
], function(require) {
    var utils = require('../utils'),
        mapal = require('../core/init');

    var tooltip = {
        count: 0,

        init: function() {
        },

        initContent: function(root) {
            var $root = $(root);
            var init = function($trigger) {
                var options = utils.parseOptions($trigger.data("tooltip"));
                options.title = $trigger.attr("title");
                $trigger.removeAttr("title");
                $trigger.data("mapal.tooltip", options);
                tooltip.setupShowEvents($trigger);
            };
            if ($root.is('[data-tooltip]')) init($root);
            $("*[data-tooltip]", $root).each(function() {
                init($(this));
            });
        },

        setupShowEvents: function($trigger) {
            var parameters = $trigger.data("mapal.tooltip");
            if (parameters.click) {
                $trigger.on("click.tooltip", $trigger, tooltip.show);
            } else {
                $trigger.on("mouseover.tooltip", $trigger, tooltip.show);
                // Make sure click on the trigger element becomes a NOP
                $trigger.on("click.tooltip", $trigger, tooltip.blockDefault);
            }
        },

        removeShowEvents: function($trigger) {
            $trigger.off(".tooltip");
        },

        setupHideEvents: function($trigger) {
            var $container = tooltip.getContainer($trigger),
                parameters = $trigger.data("mapal.tooltip");
            if (parameters.sticky) {
                $container.find(".closePanel")
                    .on("click.tooltip", $trigger, tooltip.hide);
                // Make sure click on the trigger element becomes a NOP
                $trigger.on("click.tooltip", $trigger, tooltip.blockDefault);
            } else {
                if (parameters.click) {
                    $container.on("click.tooltip", $trigger, function(ev) {
                        ev.stopPropagation();
                    });
                    $(document).on("click.tooltip", $trigger, tooltip.hide);
                    $trigger.on("click.tooltip", tooltip.blockDefault);
                    // close if something inside the tooltip triggered an injection
                    $container.on('patterns-inject-triggered.tooltip',
                                  $trigger, tooltip.hide);
                    $container.on('patterns-inject_interim-triggered.tooltip',
                                  $trigger, tooltip.hide);
                    $container.on('submit.tooltip', $trigger, tooltip.hide);
                } else {
                    $container.on("click.tooltip", $trigger, tooltip.hide);
                    $trigger.on("mouseleave.tooltip", $trigger, tooltip.hide);
                    $trigger.on("click.tooltip", tooltip.blockDefault);
                }
            }
        },

        removeHideEvents: function($trigger) {
            var $container = tooltip.getContainer($trigger);
            $(document).off(".tooltip");
            $container.off(".tooltip");
            $container.find(".closePanel").off(".tooltip");
            $trigger.off(".tooltip");
        },

        blockDefault: function(event) {
            event.preventDefault();
        },

        show: function(event) {
            event.preventDefault();
            var $trigger = event.data,
                $container = tooltip.getContainer($trigger),
                namespace = $container.attr("id"),
                options = $trigger.data("mapal.tooltip");

            tooltip.removeShowEvents($trigger);
            // Wrap in a timeout to make sure this click is not used to
            // trigger a hide as well.
            setTimeout(function() { tooltip.setupHideEvents($trigger) }, 50);

            function ajax_show() {
                $container.find(">div >*").css("opacity", 1);
                tooltip.positionContainer($trigger, $container);
            }

            if (options.ajax) {
                var source = $trigger.attr("href").split("#"),
                    target_id = $container.find("progress").attr("id");
                mapal.injection.load($trigger, source[0], target_id+":replace", source[1] || [],
                        ajax_show, true);
                // always load fresh tooltips
                // delete options.ajax;
                $trigger.data("mapal.tooltip", options);
            }

            tooltip.positionContainer($trigger, $container);
            $container.css("visibility", "visible");

            // reposition tooltip everytime we scroll or resize
            $(window).on("scroll." + namespace + " resize." + namespace, function () {
                 tooltip.positionContainer($trigger, $container);
            });
        },

        hide: function(event) {
            var $trigger = event.data,
                $container = tooltip.getContainer($trigger),
                namespace = $container.attr("id");
            tooltip.removeHideEvents($trigger);
            $container.css("visibility", "hidden");
            $(window).off("." + namespace);
            tooltip.setupShowEvents($trigger);
        },

        getContainer: function($trigger) {
            var $container = $trigger.data("mapal.tooltip.container");
            if ($container===undefined) {
                $container=tooltip.createContainer($trigger);
                $trigger.data("mapal.tooltip.container", $container);
            }
            return $container;
        },

        createContainer: function($trigger) {
            var options = $trigger.data("mapal.tooltip"),
                count = ++tooltip.count,
                $content, $container;

            $container = $("
", {"class": "tooltip-container",
                                     "id": "tooltip" + count});
            $container.css("visibility", "hidden");
            if (options.ajax) {
                $content = $("<progress/>", {"id": "tooltip-load-" + count});
            } else {
                $content = $("
").text(options.title);
            }
            $container.append(
                $("
").css("display", "block").append($content))
                .append($("", {"class": "pointer"}));
            if (options.sticky && !options.noclose) {
                $("<button/>", {"class": "closePanel"})
                    .text("Close")
                    .insertBefore($container.find("*"));
            }
            $("body").append($container);
            return $container;
        },

        boundingBox: function($el) {
            var box = $el.offset();
            box.height = $el.height();
            box.width = $el.width();
            box.bottom = box.top + box.height;
            box.right = box.left + box.width;
            return box;
        },

        positionStatus: function($trigger, $container) {
            var trigger_box = tooltip.boundingBox($trigger),
                tooltip_box = tooltip.boundingBox($container),
                $window = $(window),
                window_width = $window.width(),
                window_height = $window.height(),
                trigger_center,
                scroll = {},
                space = {},
                container_offset = {},
                tip_offset = {},
                cls = "";

            scroll.top = $window.scrollTop();
            scroll.left = $window.scrollLeft();
            trigger_center = {top: trigger_box.top + (trigger_box.height/2),
                              left: trigger_box.left + (trigger_box.width/2)};
            space.top = trigger_box.top - scroll.top;
            space.bottom = window_height - space.top - trigger_box.height;
            space.left = trigger_box.left - scroll.left;
            space.right = window_width - space.left - trigger_box.width;

            return {space: space,
                    trigger_center: trigger_center,
                    trigger_box: trigger_box,
                    tooltip_box: tooltip_box,
                    scroll: scroll,
                    window: {width: window_width, height: window_height}
            };
        },

        // Help function to determine the best position for a tooltip.  Takes
        // the positioning status (as generated by positionStatus) as input
        // and returns a two-character position indiciator.
        findBestPosition: function(status) {
            var space = status.space,
                 cls = "";

            if (space.top > Math.max(space.right, space.bottom, space.left)) {
                cls = "b";
            } else if (space.right > Math.max(space.bottom, space.left, space.top)) {
                cls = "l";
            } else if (space.bottom > Math.max(space.left, space.top, space.right)) {
                cls = "t";
            } else {
                cls = "r";
            }

            switch (cls[0]) {
            case "t":
            case "b":
                if (Math.abs(space.left-space.right) < 20) {
                    cls += "m";
                } else if (space.left > space.right) {
                    cls += "r";
                } else {
                    cls += "l";
                }
                break;
            case "l":
            case "r":
                if (Math.abs(space.top-space.bottom) < 20) {
                    cls += "m";
                } else if (space.top > space.bottom) {
                    cls += "b";
                } else {
                    cls += "t";
                }
            }
            return cls;
        },

        isVisible: function(status, position) {
            var space = status.space,
                tooltip_box = status.tooltip_box;

            switch (position[0]) {
            case "t":
                if (tooltip_box.height > space.bottom) {
                    return false;
                }
                break;
            case "r":
                if (tooltip_box.width > space.left) {
                    return false;
                }
                break;
            case "b":
                if (tooltip_box.height > space.top) {
                    return false;
                }
                break;
            case "l":
                if (tooltip_box.width > space.right) {
                    return false;
                }
                break;
            default:
                return false;
            }

            switch (position[0]) {
            case "t":
            case "b":
                switch (position[1]) {
                    case "l":
                        if ((tooltip_box.width-20)>space.right) {
                            return false;
                        }
                        break;
                    case "m":
                        if ((tooltip_box.width/2)>space.left || (tooltip_box.width/2)>space.right) {
                            return false;
                        }
                        break;
                    case "r":
                        if ((tooltip_box.width-20)>space.left) {
                            return false;
                        }
                        break;
                    default:
                        return false;
                }
                break;
            case "l":
            case "r":
                switch (position[1]) {
                    case "t":
                        if ((tooltip_box.height-20)>space.bottom) {
                            return false;
                        }
                        break;
                    case "m":
                        if ((tooltip_box.height/2)>space.top || (tooltip_box.height/2)>space.bottom) {
                            return false;
                        }
                        break;
                    case "b":
                        if ((tooltip_box.height-20)>space.top) {
                            return false;
                        }
                    default:
                        return false;
                }
                break;
            }
            return true;
        },

        VALIDPOSITION: /^([lr][tmb]|[tb][lmr])$/,

        positionContainer: function($trigger, $container) {
            var status = tooltip.positionStatus($trigger, $container),
                options = $trigger.data("mapal.tooltip"),
                container_offset = {},
                tip_offset = {},
                position;

            if (options.position) {
                var positions = options.position.split("-"), i;
                for (i=0; i<positions.length; i++) {
                    if (!tooltip.VALIDPOSITION.test(positions[i])) {
                        continue;
                    }

                    if (options.forcePosition || tooltip.isVisible(status, positions[i])) {
                        position = positions[i];
                        break;
                    }
                }
            }

            if (!position) {
                position = tooltip.findBestPosition(status);
            }

            var trigger_box = status.trigger_box,
                tooltip_box = status.tooltip_box,
                trigger_center = status.trigger_center,
                content_css = {"max-height": "", "max-width": ""},
                $window = $(window),
                bottom_row, x;

            switch (position[0]) {
            case "t":
                container_offset.top = trigger_box.bottom + 20;
                tip_offset.top = -23;
                bottom_row = status.scroll.top + status.window.height,
                content_css["max-height"] = (bottom_row - container_offset.top - 30) + "px";
                break;
            case "l":
                container_offset.left = trigger_box.right + 20;
                tip_offset.left = -23;
                x = status.window.width + status.scroll.left;
                content_css["max-width"] = (x - container_offset.left - 30) + "px";
                break;
            case "b":
                container_offset.top = trigger_box.top - tooltip_box.height + 10;
                tip_offset.top = tooltip_box.height;
                x = (status.scroll.top + 10) - container_offset.top;
                if (x>0) {
                    tip_offset.top -= x;
                    content_css["max-height"] = (tooltip_box.height - x) + "px";
                    container_offset.top += x;
                }
                break;
            case "r":
                container_offset.left = trigger_box.left - tooltip_box.width - 20;
                tip_offset.left = tooltip_box.width;
                break;
            }

            switch (position[0]) {
            case "t":
            case "b":
                switch (position[1]) {
                case "l":
                    container_offset.left = trigger_center.left - 20;
                    tip_offset.left = 0;
                    break;
                case "m":
                    container_offset.left = trigger_center.left - (tooltip_box.width/2);
                    tip_offset.left = tooltip_box.width/2 - 10;
                    break;
                case "r":
                    container_offset.left = trigger_center.left + 29 - tooltip_box.width;
                    tip_offset.left = tooltip_box.width - 20;
                    break;
                }
                break;
            case "l":
            case "r":
                switch (position[1]) {
                    case "t":
                        container_offset.top = trigger_center.top - 30;
                        tip_offset.top = 0;
                        break;
                    case "m":
                        container_offset.top = trigger_center.top - (tooltip_box.height/2);
                        tip_offset.top = tooltip_box.height/2 - 10;
                        break;
                    case "b":
                        container_offset.top = trigger_center.top + 20 - tooltip_box.height;
                        tip_offset.top = tooltip_box.height - 20;
                        break;
                }
                break;
            }

            $container.find("> div").css(content_css);
            $container.attr("class", "tooltip-container " + position);
            $container.css({
                top: container_offset.top+"px",
                left: container_offset.left+"px",
            });
            $container.find(".pointer").css({
                top: tip_offset.top+"px",
                left: tip_offset.left+"px"});
        }
    };

    return tooltip;
});

// vim: sw=4 expandtab
<|endoftext|>


<commit_before>// @flow

const Swarm = require('libp2p-swarm')
const TCP = require('libp2p-tcp')
// const UTP = require('libp2p-utp')
const WS = require('libp2p-websockets')
const spdy = require('libp2p-spdy')
const secio = require('libp2p-secio')
const PeerId = require('peer-id')
const PeerInfo = require('peer-info')
const PeerBook = require('peer-book')
const multiaddr = require('multiaddr')
const mafmt = require('mafmt')
const Abortable = require('pull-abortable')

import type { Connection } from 'interface-connection'

const OFFLINE_ERROR_MESSAGE = 'The libp2p node is not started yet'
const IPFS_CODE = 421

class P2PNode {
  peerInfo: PeerInfo
  peerBook: PeerBook
  swarm: Swarm
  isOnline: boolean
  abortables: Set<Abortable>

  constructor (pInfo: ?PeerInfo, pBook: PeerBook = new PeerBook()) {
    this.isOnline = false

    if (!pInfo) {
      pInfo = new PeerInfo()
      pInfo.multiaddr.add(multiaddr('/ip4/0.0.0.0/tcp/0'))
    }

    this.peerInfo = pInfo
    this.peerBook = pBook

    // Swarm
    this.swarm = new Swarm(pInfo)
    this.swarm.connection.addStreamMuxer(spdy)
    this.swarm.connection.reuse()

    this.swarm.connection.crypto(secio.tag, secio.encrypt)

    this.swarm.on('peer-mux-established', (peerInfo) => {
      this.peerBook.put(peerInfo)
    })

    this.swarm.on('peer-mux-closed', (peerInfo) => {
      this.peerBook.removeByB58String(peerInfo.id.toB58String())
    })

    this.abortables = new Set()
  }

  newAbortable (): Abortable {
    const abortable = Abortable()
    this.abortables.add(abortable)
    return abortable
  }

  start (): Promise<void> {
    if (this.isOnline) return Promise.resolve()

    const ws = new WS()
    const tcp = new TCP()

    // Do not activate the dialer if no listener is going to be present
    if (ws.filter(this.peerInfo.multiaddrs).length > 0) {
      this.swarm.transport.add('ws', new WS())
    }
    if (tcp.filter(this.peerInfo.multiaddrs).length > 0) {
      this.swarm.transport.add('tcp', new TCP())
    }

    return new Promise((resolve, reject) => {
      this.swarm.listen((err) => {
        if (err) {
          return reject(err)
        }

        this.isOnline = true
        resolve()
      })
    })
  }

  stop (): Promise<void> {
    if (!this.isOnline) return Promise.resolve()

    this.isOnline = false
    return new Promise(resolve => {
      // abort any ongoing pull-stream connections
      this.abortables.forEach(a => { a.abort() })
      this.abortables.clear()

      this.swarm.close(resolve)
    })
  }

  dialById (id: PeerId, protocol: string): Promise<Connection> {
    if (!this.isOnline) {
      return Promise.reject(new Error(OFFLINE_ERROR_MESSAGE))
    }
    // NOTE, these dialById only works if a previous dial
    // was made until we have PeerRouting
    // TODO support PeerRouting when it is Ready
    return Promise.reject(new Error('not implemented yet'))
  }

  dialByMultiaddr (maddr: multiaddr, protocol: string): Promise<Connection> {
    if (!this.isOnline) {
      return Promise.reject(new Error(OFFLINE_ERROR_MESSAGE))
    }

    if (typeof maddr === 'string') {
      maddr = multiaddr(maddr)
    }

    if (!mafmt.IPFS.matches(maddr.toString())) {
      return Promise.reject(new Error('multiaddr not valid'))
    }

    const ipfsIdB58String = maddr.stringTuples().filter((tuple) => {
      if (tuple[0] === IPFS_CODE) {
        return true
      }
    })[0][1]

    let peer
    try {
      peer = this.peerBook.getByB58String(ipfsIdB58String)
    } catch (err) {
      peer = new PeerInfo(PeerId.createFromB58String(ipfsIdB58String))
    }

    peer.multiaddr.add(maddr)
    return this.dialByPeerInfo(peer, protocol)
  }

  dialByPeerInfo (peer: PeerInfo, protocol: string): Promise<Connection> {
    if (!this.isOnline) {
      return Promise.reject(new Error(OFFLINE_ERROR_MESSAGE))
    }

    return new Promise((resolve, reject) => {
      this.swarm.dial(peer, protocol, (err, conn) => {
        if (err) {
          return reject(err)
        }
        this.peerBook.put(peer)
        resolve(conn)
      })
    })
  }

  hangUpById (id: PeerId): Promise<void> {
    return Promise.reject(new Error('not implemented yet'))
    // TODO
  }

  hangUpByMultiaddr (maddr: multiaddr): Promise<void> {
    if (!this.isOnline) {
      return Promise.reject(new Error(OFFLINE_ERROR_MESSAGE))
    }

    if (typeof maddr === 'string') {
      maddr = multiaddr(maddr)
    }

    if (!mafmt.IPFS.matches(maddr.toString())) {
      return Promise.reject(new Error('multiaddr not valid'))
    }

    const ipfsIdB58String = maddr.stringTuples().filter((tuple) => {
      if (tuple[0] === IPFS_CODE) {
        return true
      }
    })[0][1]

    try {
      const peerInfo = this.peerBook.getByB58String(ipfsIdB58String)
      return this.hangUpByPeerInfo(peerInfo)
    } catch (err) {
      // already disconnected
      return Promise.resolve()
    }
  }

  hangUpByPeerInfo (peer: PeerInfo): Promise<void> {
    if (!this.isOnline) {
      return Promise.reject(new Error(OFFLINE_ERROR_MESSAGE))
    }

    this.peerBook.removeByB58String(peer.id.toB58String())
    return new Promise((resolve) => {
      this.swarm.hangUp(peer, resolve)
    })
  }

  handle (protocol: string, handler: Function): any {
    return this.swarm.handle(protocol, handler)
  }

  unhandle (protocol: string): any {
    return this.swarm.unhandle(protocol)
  }
}

module.exports = P2PNode
<commit_msg>add method to P2PNode to disable secure io<commit_after>// @flow

const Swarm = require('libp2p-swarm')
const TCP = require('libp2p-tcp')
// const UTP = require('libp2p-utp')
const WS = require('libp2p-websockets')
const spdy = require('libp2p-spdy')
const secio = require('libp2p-secio')
const PeerId = require('peer-id')
const PeerInfo = require('peer-info')
const PeerBook = require('peer-book')
const multiaddr = require('multiaddr')
const mafmt = require('mafmt')
const Abortable = require('pull-abortable')

import type { Connection } from 'interface-connection'

const OFFLINE_ERROR_MESSAGE = 'The libp2p node is not started yet'
const IPFS_CODE = 421

class P2PNode {
  peerInfo: PeerInfo
  peerBook: PeerBook
  swarm: Swarm
  isOnline: boolean
  abortables: Set<Abortable>

  constructor (pInfo: ?PeerInfo, pBook: PeerBook = new PeerBook()) {
    this.isOnline = false

    if (!pInfo) {
      pInfo = new PeerInfo()
      pInfo.multiaddr.add(multiaddr('/ip4/0.0.0.0/tcp/0'))
    }

    this.peerInfo = pInfo
    this.peerBook = pBook

    // Swarm
    this.swarm = new Swarm(pInfo)
    this.swarm.connection.addStreamMuxer(spdy)
    this.swarm.connection.reuse()

    this.swarm.connection.crypto(secio.tag, secio.encrypt)

    this.swarm.on('peer-mux-established', (peerInfo) => {
      this.peerBook.put(peerInfo)
    })

    this.swarm.on('peer-mux-closed', (peerInfo) => {
      this.peerBook.removeByB58String(peerInfo.id.toB58String())
    })

    this.abortables = new Set()
  }

  newAbortable (): Abortable {
    const abortable = Abortable()
    this.abortables.add(abortable)
    return abortable
  }

  start (): Promise<void> {
    if (this.isOnline) return Promise.resolve()

    const ws = new WS()
    const tcp = new TCP()

    // Do not activate the dialer if no listener is going to be present
    if (ws.filter(this.peerInfo.multiaddrs).length > 0) {
      this.swarm.transport.add('ws', new WS())
    }
    if (tcp.filter(this.peerInfo.multiaddrs).length > 0) {
      this.swarm.transport.add('tcp', new TCP())
    }

    return new Promise((resolve, reject) => {
      this.swarm.listen((err) => {
        if (err) {
          return reject(err)
        }

        this.isOnline = true
        resolve()
      })
    })
  }

  stop (): Promise<void> {
    if (!this.isOnline) return Promise.resolve()

    this.isOnline = false
    return new Promise(resolve => {
      // abort any ongoing pull-stream connections
      this.abortables.forEach(a => { a.abort() })
      this.abortables.clear()

      this.swarm.close(resolve)
    })
  }

  setSecureIOEnabled (use: boolean = true) {
    if (use) {
      this.swarm.connection.crypto(secio.tag, secio.encrypt)
    } else {
      this.swarm.connection.crypto()
    }
  }

  dialById (id: PeerId, protocol: string): Promise<Connection> {
    if (!this.isOnline) {
      return Promise.reject(new Error(OFFLINE_ERROR_MESSAGE))
    }
    // NOTE, these dialById only works if a previous dial
    // was made until we have PeerRouting
    // TODO support PeerRouting when it is Ready
    return Promise.reject(new Error('not implemented yet'))
  }

  dialByMultiaddr (maddr: multiaddr, protocol: string): Promise<Connection> {
    if (!this.isOnline) {
      return Promise.reject(new Error(OFFLINE_ERROR_MESSAGE))
    }

    if (typeof maddr === 'string') {
      maddr = multiaddr(maddr)
    }

    if (!mafmt.IPFS.matches(maddr.toString())) {
      return Promise.reject(new Error('multiaddr not valid'))
    }

    const ipfsIdB58String = maddr.stringTuples().filter((tuple) => {
      if (tuple[0] === IPFS_CODE) {
        return true
      }
    })[0][1]

    let peer
    try {
      peer = this.peerBook.getByB58String(ipfsIdB58String)
    } catch (err) {
      peer = new PeerInfo(PeerId.createFromB58String(ipfsIdB58String))
    }

    peer.multiaddr.add(maddr)
    return this.dialByPeerInfo(peer, protocol)
  }

  dialByPeerInfo (peer: PeerInfo, protocol: string): Promise<Connection> {
    if (!this.isOnline) {
      return Promise.reject(new Error(OFFLINE_ERROR_MESSAGE))
    }

    return new Promise((resolve, reject) => {
      this.swarm.dial(peer, protocol, (err, conn) => {
        if (err) {
          return reject(err)
        }
        this.peerBook.put(peer)
        resolve(conn)
      })
    })
  }

  hangUpById (id: PeerId): Promise<void> {
    return Promise.reject(new Error('not implemented yet'))
    // TODO
  }

  hangUpByMultiaddr (maddr: multiaddr): Promise<void> {
    if (!this.isOnline) {
      return Promise.reject(new Error(OFFLINE_ERROR_MESSAGE))
    }

    if (typeof maddr === 'string') {
      maddr = multiaddr(maddr)
    }

    if (!mafmt.IPFS.matches(maddr.toString())) {
      return Promise.reject(new Error('multiaddr not valid'))
    }

    const ipfsIdB58String = maddr.stringTuples().filter((tuple) => {
      if (tuple[0] === IPFS_CODE) {
        return true
      }
    })[0][1]

    try {
      const peerInfo = this.peerBook.getByB58String(ipfsIdB58String)
      return this.hangUpByPeerInfo(peerInfo)
    } catch (err) {
      // already disconnected
      return Promise.resolve()
    }
  }

  hangUpByPeerInfo (peer: PeerInfo): Promise<void> {
    if (!this.isOnline) {
      return Promise.reject(new Error(OFFLINE_ERROR_MESSAGE))
    }

    this.peerBook.removeByB58String(peer.id.toB58String())
    return new Promise((resolve) => {
      this.swarm.hangUp(peer, resolve)
    })
  }

  handle (protocol: string, handler: Function): any {
    return this.swarm.handle(protocol, handler)
  }

  unhandle (protocol: string): any {
    return this.swarm.unhandle(protocol)
  }
}

module.exports = P2PNode
<|endoftext|>


<commit_before>/**
 * Route Mappings
 * (sails.config.routes)
 *
 * Your routes map URLs to views and controllers.
 *
 * If Sails receives a URL that doesn't match any of the routes below,
 * it will check for matching files (images, scripts, stylesheets, etc.)
 * in your assets directory.  e.g. `http://localhost:1337/images/foo.jpg`
 * might match an image file: `/assets/images/foo.jpg`
 *
 * Finally, if those don't match either, the default 404 handler is triggered.
 * See `api/responses/notFound.js` to adjust your app's 404 logic.
 *
 * Note: Sails doesn't ACTUALLY serve stuff from `assets`-- the default Gruntfile in Sails copies
 * flat files from `assets` to `.tmp/public`.  This allows you to do things like compile LESS or
 * CoffeeScript for the front-end.
 *
 * For more information on configuring custom routes, check out:
 * http://sailsjs.org/#!/documentation/concepts/Routes/RouteTargetSyntax.html
 */

module.exports.routes = {

  /***************************************************************************
  *                                                                          *
  * Make the view located at `views/homepage.ejs` (or `views/homepage.jade`, *
  * etc. depending on your default view engine) your home page.              *
  *                                                                          *
  * (Alternatively, remove this and add an `index.html` file in your         *
  * `assets` directory)                                                      *
  *                                                                          *
  ***************************************************************************/

  '/': 'http://www.weus.eu',

  /***************************************************************************
  *                                                                          *
  * Custom routes here...                                                    *
  *                                                                          *
  * If a request to a URL doesn't match any of the custom routes above, it   *
  * is matched against Sails route blueprints. See `config/blueprints.js`    *
  * for configuration options and examples.                                  *
  *                                                                          *
  ***************************************************************************/

  /* Login */
  'POST /login': 'Contact.login',

  /* Contact */
  'GET /contact': 'Contact.getContacts',
  'GET /contact/:nickname': 'Contact.getContactByNickname',
  'GET /contact/:nickname/sms': 'Contact.getSMSByNickname',

  'PUT /contact': 'Contact.updateContact',

  'POST /contact': 'Contact.createContact',

  'DELETE /contact': 'Contact.deleteContact',

  /* Phone */
  'PUT /phone': 'Phone.updatePhone',

  /* SMS */
  'POST /sms': 'Sms.send',

  /* Groupe */
  'GET /group': 'Group.getGroups',
  'GET /group/:name': 'Group.getGroupByName',

  'PUT /group': 'Group.updateGroup',

  'POST /group': 'Group.createGroup',

  'DELETE /group': 'Group.deleteGroup',

  /* Campagne */
  'GET /campaign': 'Campaign.getCampaigns',
  'GET /campaign/:name': 'Campaign.getCampaignByName',

  'PUT /campaign': 'Campaign.updateCampaign',

  'POST /campaign': 'Campaign.createCampaign',

  'DELETE /campaign': 'Campaign.deleteCampaign'

};
<commit_msg>Change route /<commit_after>/**
 * Route Mappings
 * (sails.config.routes)
 *
 * Your routes map URLs to views and controllers.
 *
 * If Sails receives a URL that doesn't match any of the routes below,
 * it will check for matching files (images, scripts, stylesheets, etc.)
 * in your assets directory.  e.g. `http://localhost:1337/images/foo.jpg`
 * might match an image file: `/assets/images/foo.jpg`
 *
 * Finally, if those don't match either, the default 404 handler is triggered.
 * See `api/responses/notFound.js` to adjust your app's 404 logic.
 *
 * Note: Sails doesn't ACTUALLY serve stuff from `assets`-- the default Gruntfile in Sails copies
 * flat files from `assets` to `.tmp/public`.  This allows you to do things like compile LESS or
 * CoffeeScript for the front-end.
 *
 * For more information on configuring custom routes, check out:
 * http://sailsjs.org/#!/documentation/concepts/Routes/RouteTargetSyntax.html
 */

module.exports.routes = {

  /***************************************************************************
  *                                                                          *
  * Make the view located at `views/homepage.ejs` (or `views/homepage.jade`, *
  * etc. depending on your default view engine) your home page.              *
  *                                                                          *
  * (Alternatively, remove this and add an `index.html` file in your         *
  * `assets` directory)                                                      *
  *                                                                          *
  ***************************************************************************/

  '/': {
    view: 'homepage'
  },

  /***************************************************************************
  *                                                                          *
  * Custom routes here...                                                    *
  *                                                                          *
  * If a request to a URL doesn't match any of the custom routes above, it   *
  * is matched against Sails route blueprints. See `config/blueprints.js`    *
  * for configuration options and examples.                                  *
  *                                                                          *
  ***************************************************************************/

  /* Login */
  'POST /login': 'Contact.login',

  /* Contact */
  'GET /contact': 'Contact.getContacts',
  'GET /contact/:nickname': 'Contact.getContactByNickname',
  'GET /contact/:nickname/sms': 'Contact.getSMSByNickname',

  'PUT /contact': 'Contact.updateContact',

  'POST /contact': 'Contact.createContact',

  'DELETE /contact': 'Contact.deleteContact',

  /* Phone */
  'PUT /phone': 'Phone.updatePhone',

  /* SMS */
  'POST /sms': 'Sms.send',

  /* Groupe */
  'GET /group': 'Group.getGroups',
  'GET /group/:name': 'Group.getGroupByName',

  'PUT /group': 'Group.updateGroup',

  'POST /group': 'Group.createGroup',

  'DELETE /group': 'Group.deleteGroup',

  /* Campagne */
  'GET /campaign': 'Campaign.getCampaigns',
  'GET /campaign/:name': 'Campaign.getCampaignByName',

  'PUT /campaign': 'Campaign.updateCampaign',

  'POST /campaign': 'Campaign.createCampaign',

  'DELETE /campaign': 'Campaign.deleteCampaign'

};
<|endoftext|>


<commit_before>const fetch = require('node-fetch');
const fs = require('fs');
const configs = require('./configs');
const contractList = require('./lists/contracts.json');
const IMAGE_PROXY = 'https://img.mewapi.io/?image=';
if (!fs.existsSync(configs.GENERATED_FOLDER_PATH)) {
  fs.mkdirSync(configs.GENERATED_FOLDER_PATH);
}
const getFormattedList = async (url, network) => {
  const response = await fetch(url);
  const data = await response.json();
  const tokens = Object.values(data.tokens)
    .map(t => {
      t.contract_address = t.address.toLowerCase();
      t.icon = IMAGE_PROXY + t.logoURI;
      t.icon_png = IMAGE_PROXY + t.logoURI;
      t.network = network;
      delete t.logoURI;
      delete t.chainId;
      return t;
    })
    .filter(t => t.address !== '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee');
  return tokens;
};
const fetchOneInchLists = async () => {
  const ethTokens = await getFormattedList(
    'https://api.1inch.exchange/v3.0/1/tokens',
    'eth'
  );
  const bscTokens = await getFormattedList(
    'https://api.1inch.exchange/v3.0/56/tokens',
    'bsc'
  );
  const maticTokens = await getFormattedList(
    'https://api.1inch.exchange/v3.0/137/tokens',
    'matic'
  );
  return {
    eth: ethTokens,
    bsc: bscTokens,
    matic: maticTokens
  };
};
const fetchCGtokenList = async () => {
  const ethTokens = await getFormattedList(
    'https://requestcache.mewapi.io/?url=https://tokens.coingecko.com/ethereum/all.json',
    'eth'
  );
  const bscTokens = await getFormattedList(
    'https://requestcache.mewapi.io/?url=https://tokens.coingecko.com/binance-smart-chain/all.json',
    'bsc'
  );
  const maticTokens = await getFormattedList(
    'https://requestcache.mewapi.io/?url=https://tokens.coingecko.com/polygon-pos/all.json',
    'matic'
  );
  return {
    eth: ethTokens,
    bsc: bscTokens,
    matic: maticTokens
  };
};
const fetchContracts = async () => {
  try {
    if (!fs.existsSync(configs.CONTRACTS_PATH)) {
      fs.mkdirSync(configs.CONTRACTS_PATH);
    }
    if (!fs.existsSync(configs.TOKENS_PATH)) {
      fs.mkdirSync(configs.TOKENS_PATH);
    }
    const contractFileURL =
      'https://raw.githubusercontent.com/MyEtherWallet/ethereum-lists/master/dist/contracts/';
    if (contractList !== undefined && contractList.length > 0) {
      for (let i = 0; i < contractList.length; i++) {
        const contractFile = contractList[i];
        const contractsCollection = await fetch(
          `${contractFileURL + contractFile.name}/contract-abi-${
            contractFile.name
          }.json`
        )
          .then(res => res.json())
          .then(json => {
            if (json.length === 1 && json[0].name === 'TEST') return [];
            return json;
          })
          .catch(err => console.log(err));
        if (contractsCollection !== undefined) {
          console.log('Writing contract for the network: ' + contractFile.name);
          fs.writeFileSync(
            `${configs.CONTRACTS_PATH}/contract-abi-${contractFile.name}.json`,
            JSON.stringify(contractsCollection)
          );
        }
      }
    }
  } catch (e) {
    console.error(e); // todo replace with proper error
  }
};

const fetchMasterFile = async () => {
  try {
    if (!fs.existsSync(configs.MASTER_FILE_PATH)) {
      fs.mkdirSync(configs.MASTER_FILE_PATH);
    }
    const oneInchTokens = await fetchOneInchLists();
    const CGTokens = await fetchCGtokenList();
    const response = await fetch(
      'https://raw.githubusercontent.com/MyEtherWallet/ethereum-lists/master/dist/master-file.json'
    )
      .then(res => res.json())
      .then(tokens => {
        const networkTokens = {};
        tokens.forEach(token => {
          token.contract_address = token.contract_address.toLowerCase();
          token.address = token.contract_address;
          if (token.icon !== '') {
            token.icon = IMAGE_PROXY + token.icon;
            token.icon_png = IMAGE_PROXY + token.icon_png;
          }
          delete token.link;
          if (!networkTokens[token.network]) networkTokens[token.network] = {};
          networkTokens[token.network][token.address] = token;
        });
        const oneInchNetworks = Object.keys(oneInchTokens);
        for (const network of oneInchNetworks) {
          if (!networkTokens[network]) networkTokens[network] = {};
          oneInchTokens[network].forEach(t => {
            t.address = t.address.toLowerCase();
            if (!networkTokens[network][t.address]) {
              networkTokens[network][t.address] = t;
              tokens.push(t);
            } else if (!networkTokens[network][t.address].icon) {
              networkTokens[network][t.address].icon = t.icon;
              networkTokens[network][t.address].icon_png = t.icon_png;
            }
          });
        }
        const CGNetworks = Object.keys(CGTokens);
        for (const network of CGNetworks) {
          if (!networkTokens[network]) networkTokens[network] = {};
          CGTokens[network].forEach(t => {
            t.address = t.address.toLowerCase();
            if (!networkTokens[network][t.address]) {
              networkTokens[network][t.address] = t;
              tokens.push(t);
            } else if (!networkTokens[network][t.address].icon) {
              networkTokens[network][t.address].icon = t.icon;
              networkTokens[network][t.address].icon_png = t.icon_png;
            }
          });
        }
        const networks = Object.keys(networkTokens);
        for (const network of networks) {
          console.log('Writing tokens for the network: ' + network);
          fs.writeFileSync(
            `${configs.TOKENS_PATH}/tokens-${network}.json`,
            JSON.stringify(Object.values(networkTokens[network]))
          );
        }
        return tokens;
      })
      .catch(console.log);
    console.log('Writing masterfile');
    fs.writeFileSync(
      `${configs.MASTER_FILE_PATH}/master-file.json`,
      JSON.stringify(response)
    );
  } catch (e) {
    console.error(e); // Not captured by sentry
  }
};
const fetchPlatformCoinList = async () => {
  const list = await fetch(
    'https://api.coingecko.com/api/v3/coins/list?include_platform=true'
  )
    .then(res => res.json())
    .then(l => {
      const idmap = {};
      l.forEach(t => {
        const vals = Object.values(t.platforms);
        vals.forEach(val => {
          if (val) idmap[val] = t.id;
        });
      });
      return idmap;
    })
    .catch(console.error);
  fs.writeFileSync(
    configs.MASTER_FILE_PATH + '/platformlist.json',
    JSON.stringify(list)
  );
};
const run = async () => {
  await fetchContracts().then(fetchMasterFile).then(fetchPlatformCoinList);
};

(async () => {
  try {
    await run();
    console.log('Done');
  } catch (e) {
    console.error(e);
  }
})();
<commit_msg>devop: 🔧 pass random user agent for coingecko<commit_after>const fetch = require('node-fetch');
const fs = require('fs');
const configs = require('./configs');
const contractList = require('./lists/contracts.json');
const IMAGE_PROXY = 'https://img.mewapi.io/?image=';
const v4 = require('uuid').v4;
if (!fs.existsSync(configs.GENERATED_FOLDER_PATH)) {
  fs.mkdirSync(configs.GENERATED_FOLDER_PATH);
}
const getFormattedList = async (url, network) => {
  const response = await fetch(url, {
    headers: {
      'User-Agent': v4()
    }
  });
  const data = await response.json();
  const tokens = Object.values(data.tokens)
    .map(t => {
      t.contract_address = t.address.toLowerCase();
      t.icon = IMAGE_PROXY + t.logoURI;
      t.icon_png = IMAGE_PROXY + t.logoURI;
      t.network = network;
      delete t.logoURI;
      delete t.chainId;
      return t;
    })
    .filter(t => t.address !== '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee');
  return tokens;
};
const fetchOneInchLists = async () => {
  const ethTokens = await getFormattedList(
    'https://api.1inch.exchange/v3.0/1/tokens',
    'eth'
  );
  const bscTokens = await getFormattedList(
    'https://api.1inch.exchange/v3.0/56/tokens',
    'bsc'
  );
  const maticTokens = await getFormattedList(
    'https://api.1inch.exchange/v3.0/137/tokens',
    'matic'
  );
  return {
    eth: ethTokens,
    bsc: bscTokens,
    matic: maticTokens
  };
};
const fetchCGtokenList = async () => {
  const ethTokens = await getFormattedList(
    'https://requestcache.mewapi.io/?url=https://tokens.coingecko.com/ethereum/all.json',
    'eth'
  );
  const bscTokens = await getFormattedList(
    'https://requestcache.mewapi.io/?url=https://tokens.coingecko.com/binance-smart-chain/all.json',
    'bsc'
  );
  const maticTokens = await getFormattedList(
    'https://requestcache.mewapi.io/?url=https://tokens.coingecko.com/polygon-pos/all.json',
    'matic'
  );
  return {
    eth: ethTokens,
    bsc: bscTokens,
    matic: maticTokens
  };
};
const fetchContracts = async () => {
  try {
    if (!fs.existsSync(configs.CONTRACTS_PATH)) {
      fs.mkdirSync(configs.CONTRACTS_PATH);
    }
    if (!fs.existsSync(configs.TOKENS_PATH)) {
      fs.mkdirSync(configs.TOKENS_PATH);
    }
    const contractFileURL =
      'https://raw.githubusercontent.com/MyEtherWallet/ethereum-lists/master/dist/contracts/';
    if (contractList !== undefined && contractList.length > 0) {
      for (let i = 0; i < contractList.length; i++) {
        const contractFile = contractList[i];
        const contractsCollection = await fetch(
          `${contractFileURL + contractFile.name}/contract-abi-${
            contractFile.name
          }.json`
        )
          .then(res => res.json())
          .then(json => {
            if (json.length === 1 && json[0].name === 'TEST') return [];
            return json;
          })
          .catch(err => console.log(err));
        if (contractsCollection !== undefined) {
          console.log('Writing contract for the network: ' + contractFile.name);
          fs.writeFileSync(
            `${configs.CONTRACTS_PATH}/contract-abi-${contractFile.name}.json`,
            JSON.stringify(contractsCollection)
          );
        }
      }
    }
  } catch (e) {
    console.error(e); // todo replace with proper error
  }
};

const fetchMasterFile = async () => {
  try {
    if (!fs.existsSync(configs.MASTER_FILE_PATH)) {
      fs.mkdirSync(configs.MASTER_FILE_PATH);
    }
    const oneInchTokens = await fetchOneInchLists();
    const CGTokens = await fetchCGtokenList();
    const response = await fetch(
      'https://raw.githubusercontent.com/MyEtherWallet/ethereum-lists/master/dist/master-file.json'
    )
      .then(res => res.json())
      .then(tokens => {
        const networkTokens = {};
        tokens.forEach(token => {
          token.contract_address = token.contract_address.toLowerCase();
          token.address = token.contract_address;
          if (token.icon !== '') {
            token.icon = IMAGE_PROXY + token.icon;
            token.icon_png = IMAGE_PROXY + token.icon_png;
          }
          delete token.link;
          if (!networkTokens[token.network]) networkTokens[token.network] = {};
          networkTokens[token.network][token.address] = token;
        });
        const oneInchNetworks = Object.keys(oneInchTokens);
        for (const network of oneInchNetworks) {
          if (!networkTokens[network]) networkTokens[network] = {};
          oneInchTokens[network].forEach(t => {
            t.address = t.address.toLowerCase();
            if (!networkTokens[network][t.address]) {
              networkTokens[network][t.address] = t;
              tokens.push(t);
            } else if (!networkTokens[network][t.address].icon) {
              networkTokens[network][t.address].icon = t.icon;
              networkTokens[network][t.address].icon_png = t.icon_png;
            }
          });
        }
        const CGNetworks = Object.keys(CGTokens);
        for (const network of CGNetworks) {
          if (!networkTokens[network]) networkTokens[network] = {};
          CGTokens[network].forEach(t => {
            t.address = t.address.toLowerCase();
            if (!networkTokens[network][t.address]) {
              networkTokens[network][t.address] = t;
              tokens.push(t);
            } else if (!networkTokens[network][t.address].icon) {
              networkTokens[network][t.address].icon = t.icon;
              networkTokens[network][t.address].icon_png = t.icon_png;
            }
          });
        }
        const networks = Object.keys(networkTokens);
        for (const network of networks) {
          console.log('Writing tokens for the network: ' + network);
          fs.writeFileSync(
            `${configs.TOKENS_PATH}/tokens-${network}.json`,
            JSON.stringify(Object.values(networkTokens[network]))
          );
        }
        return tokens;
      })
      .catch(console.log);
    console.log('Writing masterfile');
    fs.writeFileSync(
      `${configs.MASTER_FILE_PATH}/master-file.json`,
      JSON.stringify(response)
    );
  } catch (e) {
    console.error(e); // Not captured by sentry
  }
};
const fetchPlatformCoinList = async () => {
  const list = await fetch(
    'https://api.coingecko.com/api/v3/coins/list?include_platform=true'
  )
    .then(res => res.json())
    .then(l => {
      const idmap = {};
      l.forEach(t => {
        const vals = Object.values(t.platforms);
        vals.forEach(val => {
          if (val) idmap[val] = t.id;
        });
      });
      return idmap;
    })
    .catch(console.error);
  fs.writeFileSync(
    configs.MASTER_FILE_PATH + '/platformlist.json',
    JSON.stringify(list)
  );
};
const run = async () => {
  await fetchContracts().then(fetchMasterFile).then(fetchPlatformCoinList);
};

(async () => {
  try {
    await run();
    console.log('Done');
  } catch (e) {
    console.error(e);
  }
})();
<|endoftext|>


<commit_before>/**
* Original author of PixelateFilter: Mat Groves http://matgroves.com/ @Doormat23
* adapted for Phaser.js
*/

/**
* This filter applies a pixelate effect making display objects appear 'blocky'
* @class PixelateFilter
* @contructor
*/
Phaser.Filter.Pixelate = function(game) {

    Phaser.Filter.call(this, game);

    this.passes = [this];

    this.uniforms.invert = { type: '1f', value: 0 };
    this.uniforms.pixelSize = { type: '2f', value: { x: 10, y: 10 } };
    this.uniforms.dimensions = { type: '4fv', value: { x: 10000, y: 100, z: 10, w: 10 } };

    this.fragmentSrc = [

        "precision mediump float;",
        "varying vec2 vTextureCoord;",
        "varying vec4 vColor;",
        "uniform vec2 testDim;",
        "uniform vec4 dimensions;",
        "uniform vec2 pixelSize;",
        "uniform sampler2D uSampler;",

        "void main(void)",
        "{",

            "vec2 coord = vTextureCoord;",
            "vec2 size = dimensions.xy/pixelSize;",
            "vec2 color = floor( ( vTextureCoord * size ) ) / size + pixelSize/dimensions.xy * 0.5;",
            "gl_FragColor = texture2D(uSampler, color);",
        "}"
    ];
};

Phaser.Filter.Pixelate.prototype = Object.create(Phaser.Filter.prototype);
Phaser.Filter.Pixelate.prototype.constructor = Phaser.Filter.Pixelate;

/**
 * This a point that describes the size of the blocs. x is the width of the block and y is the the height
 * @property size
 * @type Point
 */
Object.defineProperty(Phaser.Filter.prototype, 'size', {

    get: function() {

        return this.uniforms.pixelSize.value;

    },

    set: function(value) {

        this.dirty = true;
        this.uniforms.pixelSize.value = value;

    }

});
<commit_msg>Fixed the Pixelate filter, changing the `dimensions` uniform to a 2f and removing un-needed vecs from the fragment src. Also fixed the size getter and added sizeX and sizeY getters/setters (#1780)<commit_after>/**
* Original author of PixelateFilter: Mat Groves http://matgroves.com/ @Doormat23
* adapted for Phaser.js
*/

/**
* This filter applies a pixelate effect making display objects appear 'blocky'.
* @class PixelateFilter
* @constructor
*/
Phaser.Filter.Pixelate = function(game) {

    Phaser.Filter.call(this, game);

    this.uniforms.invert = { type: '1f', value: 0 };
    this.uniforms.pixelSize = { type: '2f', value: { x: 1.0, y: 1.0 } };
    this.uniforms.dimensions = { type: '2f', value: { x: 1000.0, y: 1000.0 } };

    this.fragmentSrc = [

        "precision mediump float;",
        "varying vec2 vTextureCoord;",
        "uniform vec2 dimensions;",
        "uniform vec2 pixelSize;",
        "uniform sampler2D uSampler;",

        "void main(void)",
        "{",

            "vec2 coord = vTextureCoord;",
            "vec2 size = dimensions.xy/pixelSize;",
            "vec2 color = floor( ( vTextureCoord * size ) ) / size + pixelSize/dimensions.xy * 0.5;",
            "gl_FragColor = texture2D(uSampler, color);",
        "}"
    ];
};

Phaser.Filter.Pixelate.prototype = Object.create(Phaser.Filter.prototype);
Phaser.Filter.Pixelate.prototype.constructor = Phaser.Filter.Pixelate;

/**
* An object with visible x and y properties that are used to define the size of the filter effect per pixel.
*
* @property size
* @type Phaser.Point
*/
Object.defineProperty(Phaser.Filter.Pixelate.prototype, 'size', {

    get: function() {

        return this.uniforms.pixelSize.value;

    },

    set: function(value) {

        this.dirty = true;
        this.uniforms.pixelSize.value = value;

    }

});

/**
* A value that defines the horizontal size of the filter effect per pixel.
*
* @property sizeX
* @type number
*/
Object.defineProperty(Phaser.Filter.Pixelate.prototype, 'sizeX', {

    get: function() {

        return this.uniforms.pixelSize.value.x;

    },

    set: function(value) {

        this.dirty = true;
        this.uniforms.pixelSize.value.x = value;

    }

});

/**
* A value that defines the vertical size of the filter effect per pixel.
*
* @property sizeY
* @type number
*/
Object.defineProperty(Phaser.Filter.Pixelate.prototype, 'sizeY', {

    get: function() {

        return this.uniforms.pixelSize.value.y;

    },

    set: function(value) {

        this.dirty = true;
        this.uniforms.pixelSize.value.y = value;

    }

});
<|endoftext|>