<commit_before>function MenuState() {
};

MenuState.prototype.init = function() {
  this.bg_img = loadImage('res/menu.png');

  this.key_cooldown = 0;

  var that = this;
  this.elements = [
    [function() {
      sm.changeState('game');
    }, {x: 14.5, y: 1.8, w: 1.5, h: 1, hover: function() {
      that.select(0);
    }}]
  ];

  this.y_values = [1.8, 3.3, 4.8];
  this.y_time = 1;
  this.y = this.y_values[0];
  this.start_y = this.y_values[0];
  this.end_y = this.y_values[0];
  this.selected = 0;
};

MenuState.prototype.setY = function(y) {
  this.start_y = this.y;
  this.end_y = y;
  this.y_time = 0;
};

MenuState.prototype.select = function(selected) {
  if (this.selected == selected) {
    return;
  }
  this.selected = selected;
  this.setY(this.y_values[this.selected]);
};

MenuState.prototype.pause = function() {
  document.removeEventListener('keypress', this.fullscreenHandler);
  $("#wrapper > .logo").remove();
  $('.player-name-container').hide();
};

MenuState.prototype.resume = function() {
  var that = this;
  this.fullscreenHandler = document.addEventListener('keypress', function(e) {
    if (e.keyCode == 13 && that.selected == 0) {
      document.body.requestFullscreen && document.body.requestFullscreen();
      document.body.webkitRequestFullscreen && document.body.webkitRequestFullscreen();
      document.body.mozRequestFullscreen && document.body.mozRequestFullScreen();
    }
  });
  var logo = $('.logo.template').clone().removeClass('template');
  $('#wrapper').append(logo);
  $('.player-name-container').show();
  $('#player-name-input').val(localStorage.playerName);
};

MenuState.prototype.render = function(ctx) {
  ctx.save();
  var scaler = 16 * GU / this.bg_img.width;
  ctx.translate(CENTER.x * GU, CENTER.y * GU);
  ctx.scale(scaler, scaler);
  ctx.translate(-this.bg_img.width / 2, -this.bg_img.height / 2);
  ctx.drawImage(this.bg_img, 0, 0);
  ctx.restore();
  $('#player-name-input').css({
    'font-size': 0.5 * GU + 'px',
    'width': 5.1 * GU + 'px',
    'margin-top': -0.25 * GU + 'px',
    'padding-left': 0.2 * GU + 'px'
  });

};

MenuState.prototype.update = function() {
  this.key_cooldown && this.key_cooldown--;
  this.y_time += 0.12;
  if (this.y_time < 1) {
    this.y = smoothstep(this.start_y, this.end_y, this.y_time);
  } else if (this.y_time > 1) {
    this.y_time = 1;
    this.y = this.end_y;
  }

  if (!this.key_cooldown) {
    if (KEYS[40]) { /* key down */
      this.selected + 1 < this.y_values.length && this.select(this.selected + 1);
      this.key_cooldown = 10;
    }
    if (KEYS[38]) { /* key up */
      this.selected - 1 >= 0 && this.select(this.selected - 1);
      this.key_cooldown = 10;
    }
    if (KEYS[13]) { /* key enter */
      this.key_cooldown = 10;
      sm.changeState(['game', 'achievements', 'credits'][this.selected]);
    }
  }
};
<commit_msg>Remove automatic fullscreening in menu<commit_after>function MenuState() {
};

MenuState.prototype.init = function() {
  this.bg_img = loadImage('res/menu.png');

  this.key_cooldown = 0;

  var that = this;
  this.elements = [
    [function() {
      sm.changeState('game');
    }, {x: 14.5, y: 1.8, w: 1.5, h: 1, hover: function() {
      that.select(0);
    }}]
  ];

  this.y_values = [1.8, 3.3, 4.8];
  this.y_time = 1;
  this.y = this.y_values[0];
  this.start_y = this.y_values[0];
  this.end_y = this.y_values[0];
  this.selected = 0;
};

MenuState.prototype.setY = function(y) {
  this.start_y = this.y;
  this.end_y = y;
  this.y_time = 0;
};

MenuState.prototype.select = function(selected) {
  if (this.selected == selected) {
    return;
  }
  this.selected = selected;
  this.setY(this.y_values[this.selected]);
};

MenuState.prototype.pause = function() {
  document.removeEventListener('keypress', this.fullscreenHandler);
  $("#wrapper > .logo").remove();
  $('.player-name-container').hide();
};

MenuState.prototype.resume = function() {
  var that = this;
  this.fullscreenHandler = document.addEventListener('keypress', function(e) {
    if (e.keyCode == 13 && that.selected == 0) {
    }
  });
  var logo = $('.logo.template').clone().removeClass('template');
  $('#wrapper').append(logo);
  $('.player-name-container').show();
  $('#player-name-input').val(localStorage.playerName);
};

MenuState.prototype.render = function(ctx) {
  ctx.save();
  var scaler = 16 * GU / this.bg_img.width;
  ctx.translate(CENTER.x * GU, CENTER.y * GU);
  ctx.scale(scaler, scaler);
  ctx.translate(-this.bg_img.width / 2, -this.bg_img.height / 2);
  ctx.drawImage(this.bg_img, 0, 0);
  ctx.restore();
  $('#player-name-input').css({
    'font-size': 0.5 * GU + 'px',
    'width': 5.1 * GU + 'px',
    'margin-top': -0.25 * GU + 'px',
    'padding-left': 0.2 * GU + 'px'
  });

};

MenuState.prototype.update = function() {
  this.key_cooldown && this.key_cooldown--;
  this.y_time += 0.12;
  if (this.y_time < 1) {
    this.y = smoothstep(this.start_y, this.end_y, this.y_time);
  } else if (this.y_time > 1) {
    this.y_time = 1;
    this.y = this.end_y;
  }

  if (!this.key_cooldown) {
    if (KEYS[40]) { /* key down */
      this.selected + 1 < this.y_values.length && this.select(this.selected + 1);
      this.key_cooldown = 10;
    }
    if (KEYS[38]) { /* key up */
      this.selected - 1 >= 0 && this.select(this.selected - 1);
      this.key_cooldown = 10;
    }
    if (KEYS[13]) { /* key enter */
      this.key_cooldown = 10;
      sm.changeState(['game', 'achievements', 'credits'][this.selected]);
    }
  }
};
<|endoftext|>


<commit_before>(function($) {

    // DEFAULT ACTION HANDLERS

    function onCreateQuestion(evt, designer, type) {
        var $tmpl = $(".wok-templates .template-question-" + type).children().clone();
        if ($tmpl.length === 1) {
            $tmpl.attr("id", "question-N" + designer.getNextTemporaryId());
            $tmpl.attr("data-question-type", type);
            $tmpl.find("li").attr("id", "option-N" + designer.getNextTemporaryId())
            designer.getTemplate().append(
                $('

')
                    .append($tmpl)
                    .append('

')
                );
            designer.validate();
        }
    }

    function onSave(evt, designer) {
        var sd = designer.getSurveyData();
        var isnew = !sd.id;
        var survey = $('

')
            .attr("id", "survey-" + sd.id)
            .append($("

").text(sd.title).attr('data-shortname', sd.shortname).attr('data-version', sd.version))
            .append(designer.getTemplate().find(".question-wrapper").clone());
        var xml = innerXHTML($('

').append(survey)[0]);
        $.post(designer.getPostUrl(sd.id), {surveyxml: xml}, function(responseText) {
            if (isnew)
                window.location = designer.getSurveyUrl($(responseText).find(".survey").attr("id").replace("survey-", ""));
            else
                window.location.reload();
        })
    }

    // DESIGNER WINDOW

    function PollsterDesigner(context, options) {
        context = context || document;
        options = $.extend({}, window.wok.pollster.options, options);

        var self = this;
        var $canvas = $(options.canvasSelector, context);
        var $tools = $(options.toolsSelector, context);
        var $properties = $(options.propertiesSelector, context);

        $(window).resize(function(evt){
            // show scrollbars if the floating panel is too tall for the current window
            $properties.css( {'max-height': window.innerHeight-5, 'overflow-y': 'auto'});
        }).resize();
        // enable panel scrolling
        $properties.portamento({
            wrapper: $properties.parent(),
            gap: 0
        });

        var $selection = null, $question = null;

        if (!window.pollster_urls)
            return window.wok.error("can't find URLs resolver");
        if ($canvas.length === 0)
            return window.wok.error("can't find canvas element: " + options.canvasSelector);
        if ($canvas.children('.'+options.templateClass).length === 0)
            $canvas.append($('

').addClass(options.templateClass));
        var $template = $canvas.children('.'+options.templateClass);

        // Question numbering.

        function renumberQuestions() {
            self.nextTemporaryId = $template.find(".question:not(.question-builtin)").each(function(i) {
                var $q = $(this);
                var $i = $q.children(".info");
                $q.find(".number").text((i+1)+'.');
                $i.text(self.getQuestionShortname($q));
            }).length + 1;
        }

        // Initialize all property providers (builtins and overrides).

        var providers = {};
        var providerClasses = $.extend({}, window.wok.pollster.propertyProviders, options.propertyProviders);
        $properties.find(".property-group").hide().each(function(i) {
            var $propertyGroup = $(this);
            var group = $.trim($propertyGroup.attr("class").replace("property-group", ""));
            var provider = providerClasses[group];
            if (provider)
                providers[group] = new provider(self, $propertyGroup);
        });

        function getPropertyProviders($target, level) {
            if ($target && $target.length > 0) {
                if ($target.is(".choices > li") && level === 0) {
                    return [providers["builtin-choice"]];
                }
                else if ($target.is(".columns > li") && level === 0) {
                    return [providers["builtin-column"]];
                }
                else if ($target.is(".rows > li") && level === 0) {
                    return [providers["builtin-row"]];
                }
                else if ($target.is(".derived-values > li") && level === 0) {
                    return [providers["builtin-derived-value"]];
                }
                else if ($target.is(".rule") && level === 0) {
                    // Some magic, we locate and bind the question, then we return the rule builtin.
                    providers["builtin-question"].attach($target.closest(".question-wrapper").children('.'+options.questionClass));
                    return [providers["builtin-rule"]];
                }
                else if ($target.hasClass("question") && level <= 1) {
                    return [providers["builtin-question"]];
                }
                else {
                    var provider = providers["tag-"+$target[0].tagName];
                    if (provider  && (!provider.nestingLevel || provider.nestingLevel <= level))
                        return [provider];
                }
            }

            return [];
        }

        function setupProperties($target) {
            var providers = getPropertyProviders($target, 0);
            if (providers.length > 0) {
                for (var i=0 ; i < providers.length ; i++) {
                    if (providers[i].setup)
                        providers[i].setup($target);
                }
            }
        }

        function togglePropertyGroups($target) {
            $properties.find(".property-group").hide();

            // We want to break both if we reach a nesting barrier and if we reach
            // the top of the page, so we keep a running count of the nesting level
            // to pass to getPropertyProviders().

            var level = 0;

            while ($target !== null && $target.length > 0) {
                var providers = getPropertyProviders($target, level);
                if (providers.length > 0) {
                    for (var i=0 ; i < providers.length ; i++)
                        providers[i].attach($target);
                    level += 1;
                }

                if ($target.hasClass("question-wrapper"))
                    break;

                $target = $target.parent();
            }
        }

        // Event handlers.

        function onMouseDown(evt) {
            var $s = $(evt.target);
            if ($selection !== null) {
                if ($selection[0] !== $s[0]) {
                    $selection.removeClass("selected");
                    $selection.closest(".question-wrapper").removeClass("active");
                }
            }

            // Check to make sure we clicked on a valid question/field.

            $question = $s.closest(".question-wrapper").addClass("active");

            if ($question.length !== 0) {
                $selection = $s.addClass("selected");
            }
            else {
                $selection = $question = null;
            }

            togglePropertyGroups($selection);
        }

        $canvas.bind("mousedown.art", onMouseDown);

        $(".action-save").click(function(evt) {
            (options.onSave || onSave)(evt, self);
            return false;
        })

        $(".action-create-question").click(function(evt) {
            var type = $(this).siblings("select").val();
            self.createQuestion(type);
            return false;
        });

        $(".sortable > *").hoverIntent(
            function() {
                var $tmpl = $(".wok-templates .sort-buttons").clone();
                $(this).append($tmpl);
            },
            function() {
                $(this).find('.sort-buttons').remove();
            }
        );

        $(".sortable .sort-buttons .up").live("click", function(){
            var $item = $(this).closest('.sortable > *');
            var $prev = $item.prev();
            if ($prev.length) {
                $item[0].parentNode.insertBefore($item[0], $prev[0]);
                $item.mouseleave();
            }
            return false;
        });

        $(".sortable .sort-buttons .down").live("click", function(){
            var $item = $(this).closest('.sortable > *');
            var $next = $item.next();
            if ($next.length) {
                $item[0].parentNode.insertBefore($next[0], $item[0]);
                $item.mouseleave();
            }
            return false;
        });

        // Public methods.

        $.extend(this, {
            getTemplate: function() {
                return $template;
            },

            getSurveyData: function() {
                return {
                    id: $properties.find("[name='survey-id']").val(),
                    title: $properties.find("[name='survey-title']").val(),
                    shortname: $properties.find("[name='survey-shortname']").val(),
                    version: $properties.find("[name='survey-version']").val()
                };
            },

            getNextTemporaryId: function() {
                var id = self.nextTemporaryId;
                self.nextTemporaryId += 1;
                return id;
            },

            getQuestionShortname: function($element) {
                var dn = $element.attr("data-shortname");
                if (!dn)
                    dn = "Q" + $element.attr("id").replace("question-", "");
                return dn;
            },

            getSurveyUrl: function(surveyId) {
                if (surveyId)
                    return pollster_urls.url('pollster_survey_edit', {id: surveyId});
            },

            getPostUrl: function(surveyId) {
                if (surveyId)
                    return pollster_urls.url('pollster_survey_edit', {id: surveyId});
                else
                    return pollster_urls.url('pollster_survey_add');
            },

            validate: function() {
                renumberQuestions();
            },

            createQuestion: function(type) {
                (options.onCreateQuestion || onCreateQuestion)(null, this, type);
            }
        });

        // Question initialization.

        renumberQuestions();
        $template.disableSelection();
        $template.sortable({
            stop: function(evt, ui) { renumberQuestions(); }
        });

        $canvas.find(".question .derived-values li, .rule").each(function() {
            setupProperties($(this));
        });
    }

    // MODULE FUNCTIONS

    window.wok.pollster.createPollsterDesigner = function(context, options) {
        return new PollsterDesigner(context, options);
    };

})(jQuery);

<commit_msg>Prevent double-saving and popup errors in the editor<commit_after>(function($) {

    // DEFAULT ACTION HANDLERS

    function onCreateQuestion(evt, designer, type) {
        var $tmpl = $(".wok-templates .template-question-" + type).children().clone();
        if ($tmpl.length === 1) {
            $tmpl.attr("id", "question-N" + designer.getNextTemporaryId());
            $tmpl.attr("data-question-type", type);
            $tmpl.find("li").attr("id", "option-N" + designer.getNextTemporaryId())
            designer.getTemplate().append(
                $('

')
                    .append($tmpl)
                    .append('

')
                );
            designer.validate();
        }
    }

    function onSave(evt, designer) {
        var sd = designer.getSurveyData();
        var isnew = !sd.id;
        var survey = $('

')
            .attr("id", "survey-" + sd.id)
            .append($("

").text(sd.title).attr('data-shortname', sd.shortname).attr('data-version', sd.version))
            .append(designer.getTemplate().find(".question-wrapper").clone());
        var xml = innerXHTML($('

').append(survey)[0]);
        $.post(designer.getPostUrl(sd.id), {surveyxml: xml}, function(responseText) {
            if (isnew)
                window.location = designer.getSurveyUrl($(responseText).find(".survey").attr("id").replace("survey-", ""));
            else
                window.location.reload();
        }).error(function(jqXHR, textStatus, errorThrown) { wok.error("error on save: "+errorThrown); });
    }

    // DESIGNER WINDOW

    function PollsterDesigner(context, options) {
        context = context || document;
        options = $.extend({}, window.wok.pollster.options, options);

        var self = this;
        var $canvas = $(options.canvasSelector, context);
        var $tools = $(options.toolsSelector, context);
        var $properties = $(options.propertiesSelector, context);

        $(window).resize(function(evt){
            // show scrollbars if the floating panel is too tall for the current window
            $properties.css( {'max-height': window.innerHeight-5, 'overflow-y': 'auto'});
        }).resize();
        // enable panel scrolling
        $properties.portamento({
            wrapper: $properties.parent(),
            gap: 0
        });

        var $selection = null, $question = null;

        if (!window.pollster_urls)
            return window.wok.error("can't find URLs resolver");
        if ($canvas.length === 0)
            return window.wok.error("can't find canvas element: " + options.canvasSelector);
        if ($canvas.children('.'+options.templateClass).length === 0)
            $canvas.append($('

').addClass(options.templateClass));
        var $template = $canvas.children('.'+options.templateClass);

        // Question numbering.

        function renumberQuestions() {
            self.nextTemporaryId = $template.find(".question:not(.question-builtin)").each(function(i) {
                var $q = $(this);
                var $i = $q.children(".info");
                $q.find(".number").text((i+1)+'.');
                $i.text(self.getQuestionShortname($q));
            }).length + 1;
        }

        // Initialize all property providers (builtins and overrides).

        var providers = {};
        var providerClasses = $.extend({}, window.wok.pollster.propertyProviders, options.propertyProviders);
        $properties.find(".property-group").hide().each(function(i) {
            var $propertyGroup = $(this);
            var group = $.trim($propertyGroup.attr("class").replace("property-group", ""));
            var provider = providerClasses[group];
            if (provider)
                providers[group] = new provider(self, $propertyGroup);
        });

        function getPropertyProviders($target, level) {
            if ($target && $target.length > 0) {
                if ($target.is(".choices > li") && level === 0) {
                    return [providers["builtin-choice"]];
                }
                else if ($target.is(".columns > li") && level === 0) {
                    return [providers["builtin-column"]];
                }
                else if ($target.is(".rows > li") && level === 0) {
                    return [providers["builtin-row"]];
                }
                else if ($target.is(".derived-values > li") && level === 0) {
                    return [providers["builtin-derived-value"]];
                }
                else if ($target.is(".rule") && level === 0) {
                    // Some magic, we locate and bind the question, then we return the rule builtin.
                    providers["builtin-question"].attach($target.closest(".question-wrapper").children('.'+options.questionClass));
                    return [providers["builtin-rule"]];
                }
                else if ($target.hasClass("question") && level <= 1) {
                    return [providers["builtin-question"]];
                }
                else {
                    var provider = providers["tag-"+$target[0].tagName];
                    if (provider  && (!provider.nestingLevel || provider.nestingLevel <= level))
                        return [provider];
                }
            }

            return [];
        }

        function setupProperties($target) {
            var providers = getPropertyProviders($target, 0);
            if (providers.length > 0) {
                for (var i=0 ; i < providers.length ; i++) {
                    if (providers[i].setup)
                        providers[i].setup($target);
                }
            }
        }

        function togglePropertyGroups($target) {
            $properties.find(".property-group").hide();

            // We want to break both if we reach a nesting barrier and if we reach
            // the top of the page, so we keep a running count of the nesting level
            // to pass to getPropertyProviders().

            var level = 0;

            while ($target !== null && $target.length > 0) {
                var providers = getPropertyProviders($target, level);
                if (providers.length > 0) {
                    for (var i=0 ; i < providers.length ; i++)
                        providers[i].attach($target);
                    level += 1;
                }

                if ($target.hasClass("question-wrapper"))
                    break;

                $target = $target.parent();
            }
        }

        // Event handlers.

        function onMouseDown(evt) {
            var $s = $(evt.target);
            if ($selection !== null) {
                if ($selection[0] !== $s[0]) {
                    $selection.removeClass("selected");
                    $selection.closest(".question-wrapper").removeClass("active");
                }
            }

            // Check to make sure we clicked on a valid question/field.

            $question = $s.closest(".question-wrapper").addClass("active");

            if ($question.length !== 0) {
                $selection = $s.addClass("selected");
            }
            else {
                $selection = $question = null;
            }

            togglePropertyGroups($selection);
        }

        $canvas.bind("mousedown.art", onMouseDown);

        $(".action-save").click(function(evt) {
            $(this).attr('disabled', true);
            (options.onSave || onSave)(evt, self);
            return false;
        })

        $(".action-create-question").click(function(evt) {
            var type = $(this).siblings("select").val();
            self.createQuestion(type);
            return false;
        });

        $(".sortable > *").hoverIntent(
            function() {
                var $tmpl = $(".wok-templates .sort-buttons").clone();
                $(this).append($tmpl);
            },
            function() {
                $(this).find('.sort-buttons').remove();
            }
        );

        $(".sortable .sort-buttons .up").live("click", function(){
            var $item = $(this).closest('.sortable > *');
            var $prev = $item.prev();
            if ($prev.length) {
                $item[0].parentNode.insertBefore($item[0], $prev[0]);
                $item.mouseleave();
            }
            return false;
        });

        $(".sortable .sort-buttons .down").live("click", function(){
            var $item = $(this).closest('.sortable > *');
            var $next = $item.next();
            if ($next.length) {
                $item[0].parentNode.insertBefore($next[0], $item[0]);
                $item.mouseleave();
            }
            return false;
        });

        // Public methods.

        $.extend(this, {
            getTemplate: function() {
                return $template;
            },

            getSurveyData: function() {
                return {
                    id: $properties.find("[name='survey-id']").val(),
                    title: $properties.find("[name='survey-title']").val(),
                    shortname: $properties.find("[name='survey-shortname']").val(),
                    version: $properties.find("[name='survey-version']").val()
                };
            },

            getNextTemporaryId: function() {
                var id = self.nextTemporaryId;
                self.nextTemporaryId += 1;
                return id;
            },

            getQuestionShortname: function($element) {
                var dn = $element.attr("data-shortname");
                if (!dn)
                    dn = "Q" + $element.attr("id").replace("question-", "");
                return dn;
            },

            getSurveyUrl: function(surveyId) {
                if (surveyId)
                    return pollster_urls.url('pollster_survey_edit', {id: surveyId});
            },

            getPostUrl: function(surveyId) {
                if (surveyId)
                    return pollster_urls.url('pollster_survey_edit', {id: surveyId});
                else
                    return pollster_urls.url('pollster_survey_add');
            },

            validate: function() {
                renumberQuestions();
            },

            createQuestion: function(type) {
                (options.onCreateQuestion || onCreateQuestion)(null, this, type);
            }
        });

        // Question initialization.

        renumberQuestions();
        $template.disableSelection();
        $template.sortable({
            stop: function(evt, ui) { renumberQuestions(); }
        });

        $canvas.find(".question .derived-values li, .rule").each(function() {
            setupProperties($(this));
        });
    }

    // MODULE FUNCTIONS

    window.wok.pollster.createPollsterDesigner = function(context, options) {
        return new PollsterDesigner(context, options);
    };

})(jQuery);

<|endoftext|>


<commit_before>/*jslint browser: true*/
/*globals chrome: true, gradeInterpreter: true, ordinalize: true,
  average: true, gradeOptions: true, score2grade: true,
  getSelectedGrade: true, populateGradeSelect: true, toggle: true*/

"use strict";

/**
 * This file is loaded by the browser action (toolbar icon).
 *
 * @author Jon-Michael Deldin <dev@jmdeldin.com>
 */

if (chrome.extension !== undefined) {
    var formNode = document.querySelector('form'),
        resultsNode = document.getElementById('results');

    populateGradeSelect('grade_level');
    toggle(resultsNode);

    chrome.extension.onMessage.addListener(function (results) {
        toggle(formNode);
        toggle(resultsNode);
        var resultSection = document.getElementById('results'),
            gr = gradeInterpreter(getSelectedGrade('grade_level'), results.grade_level).interpret(),
            scores = [],
            overall,
            grade;

        document.getElementById('readability_gl_msg').innerHTML = gr[0];
        document.getElementById('readability_gl').innerHTML = ordinalize(results.grade_level);
        document.getElementById('readability_score').innerHTML = gr[1];

        scores.push(gr[1]);

        updateOverallGradeAndScore(scores);
    });

    document.getElementById('submit').addEventListener('click', function (e) {
        // browser action popups aren't part of tabs -- that is why getSelected is used
        chrome.tabs.getSelected(null, function (tab) {
            chrome.tabs.executeScript(tab.id, {file: 'lib/helpers.js'}); // to include
            chrome.tabs.executeScript(tab.id, {file: 'lib/EnglishParser.js'}); // to include
            chrome.tabs.executeScript(tab.id, {file: 'lib/evaluate.js'}); // to do work
        });
    });

    document.getElementById('redo').addEventListener('click', function (e) {
        toggle(formNode);
        toggle(resultsNode);
    });

}
<commit_msg>DRY up the execution of scripts on tabs<commit_after>/*jslint browser: true*/
/*globals chrome: true, gradeInterpreter: true, ordinalize: true,
  average: true, gradeOptions: true, score2grade: true,
  getSelectedGrade: true, populateGradeSelect: true, toggle: true*/

"use strict";

/**
 * This file is loaded by the browser action (toolbar icon).
 *
 * @author Jon-Michael Deldin <dev@jmdeldin.com>
 */

if (chrome.extension !== undefined) {
    var formNode = document.querySelector('form'),
        resultsNode = document.getElementById('results');

    populateGradeSelect('grade_level');
    toggle(resultsNode);

    chrome.extension.onMessage.addListener(function (results) {
        toggle(formNode);
        toggle(resultsNode);
        var resultSection = document.getElementById('results'),
            gr = gradeInterpreter(getSelectedGrade('grade_level'), results.grade_level).interpret(),
            scores = [],
            overall,
            grade;

        document.getElementById('readability_gl_msg').innerHTML = gr[0];
        document.getElementById('readability_gl').innerHTML = ordinalize(results.grade_level);
        document.getElementById('readability_score').innerHTML = gr[1];

        scores.push(gr[1]);

        updateOverallGradeAndScore(scores);
    });

    document.getElementById('submit').addEventListener('click', function (e) {
        var scripts = ['helpers', 'EnglishParser', 'evaluate'], i, fn;

        // browser action popups aren't part of tabs -- that is why getSelected is used
        chrome.tabs.getSelected(null, function (tab) {
            for (i = 0; i < scripts.length; i += 1) {
                var fn = 'lib/' + scripts[i] + '.js';
                chrome.tabs.executeScript(tab.id, {file: fn});
            }
        });
    });

    document.getElementById('redo').addEventListener('click', function (e) {
        toggle(formNode);
        toggle(resultsNode);
    });

}
<|endoftext|>


<commit_before>Package.describe({
  name: 'heaven7:wsl-memberships',
  version: '0.0.3_1',
  summary: 'Memberships package',
  git: 'https://github.com/heaven7/wsl-memberships.git',
  documentation: 'README.md'
});

var both = ['client','server'],
    packages = [
    'heaven7:wsl-core@0.0.3_1',
    'heaven7:wsl-alert@0.0.2',
    'heaven7:wsl-email@0.0.1',
    'heaven7:wsl-translations@0.0.3',
    'heaven7:wsl-i18n@0.0.3_4',
    'iron:router'
    ];

Package.onUse(function(api) {
    api.versionsFrom('1.2');
    api.use(packages, both);
    api.imply(packages);

    api.addFiles([
        'lib/both/memberships.js',
        'lib/both/schemas.js',
        'lib/both/router.js'
    ], both);

    api.addFiles([
        'lib/server/email/templates/send-request.handlebars',
        'lib/server/allow.js',
        'lib/server/methods.js',
        'lib/server/publish.js',
        'lib/server/utils.js'
    ], 'server');

    api.addFiles([
        'lib/client/forms.html',
        'lib/client/forms.js',
        'lib/client/hooks.js',
        'lib/client/templates.html',
        'lib/client/templates.js',
        'lib/client/helpers.js'
    ], 'client');

    api.export([
        'Memberships',
        'membershipsByDoc'
    ], both);
});
<commit_msg>v0.0.3_2<commit_after>Package.describe({
  name: 'heaven7:wsl-memberships',
  version: '0.0.3_2',
  summary: 'Memberships package',
  git: 'https://github.com/heaven7/wsl-memberships.git',
  documentation: 'README.md'
});

var both = ['client','server'],
    packages = [
    'heaven7:wsl-core@0.0.3_1',
    'heaven7:wsl-alert@0.0.2',
    'heaven7:wsl-email@0.0.1',
    'heaven7:wsl-translations@0.0.3',
    'heaven7:wsl-i18n@0.0.3_4',
    'iron:router'
    ];

Package.onUse(function(api) {
    api.versionsFrom('1.2');
    api.use(packages, both);
    api.imply(packages);

    api.addFiles([
        'lib/both/memberships.js',
        'lib/both/schemas.js',
        'lib/both/router.js'
    ], both);

    api.addFiles([
        'lib/server/email/templates/send-request.handlebars',
        'lib/server/allow.js',
        'lib/server/methods.js',
        'lib/server/publish.js',
        'lib/server/utils.js'
    ], 'server');

    api.addFiles([
        'lib/client/forms.html',
        'lib/client/forms.js',
        'lib/client/hooks.js',
        'lib/client/templates.html',
        'lib/client/templates.js',
        'lib/client/helpers.js'
    ], 'client');

    api.export([
        'Memberships',
        'membershipsByDoc'
    ], both);
});
<|endoftext|>


<commit_before>/* global AUDIO_FORMATS */
/* global window */
/* global EventTarget */

export const sample_rate = 24000;
export const fetching_audio_event = 'fetching-audio';
export const fetched_audio_event = 'fetched-audio';
export const decoded_audio_event = 'decoded-audio';
export const ac = new AudioContext({sampleRate:sample_rate});
export const format = (audio_el => AUDIO_FORMATS.find(f => audio_el.canPlayType(f.mime)))(new Audio());
if (!format) {
    console.log('no supported format, no audio');
}

let stub;
let audio;
let timeupdate_interval = null;

class MAudio {
    constructor(stub) {
        if (!format) {
            console.log('no supported format, no audio');
            return null;
        }
        this.stub = stub;
        this.buffer = null;
        this.time = 0;
        this.started_at = null;
        this.is_playing = false;
        this.playing_source = null;
    }

    load() {
        const me = this;
        return new Promise(fulfill => {
            const stub = me.stub;
            const src = [stub, format.suffix].join('.');
            const stored_samples = localStorage.getItem(src);
            if (stored_samples) {
                ;;; console.log('restoring from localStorage');
                me.buffer = ac.createBuffer(1, stored_samples.length, sample_rate)
                me.buffer.copyToChannel(stored_samples, 0);
                ;;; console.log('done');
                fulfill(me);
                return;
            }
            ;;; console.log('downloading');
            fetch(src).then(res => {    // TODO: progress bar
                window.dispatchEvent(new Event(fetched_audio_event));
                res.arrayBuffer().then(encoded_data => {
                    ;;; console.log('decoding');
                    new AudioContext().decodeAudioData(encoded_data, decoded_buffer => {
                        me.buffer = decoded_buffer;
                        ;;; console.log('storing');
                        const samples = decoded_buffer.getChannelData(0);
                        localStorage.setItem(src, samples);
                        window.dispatchEvent(new Event(decoded_audio_event));
                        ;;; console.log('done');
                        fulfill(me);
                    });
                });
            });
        });
    }

    get_source() {
        if (this.buffer === null) { return null }
        const audio_source = ac.createBufferSource();
        this.audio_source = audio_source;
        audio_source.buffer = this.buffer;
        audio_source.connect(ac.destination);
        audio_source.addEventListener('ended', () => audio_source.disconnect());
        return audio_source;
    }

    play() {
        const me = this;
        if (me.buffer === null) { return null }
        if (me.playing_source !== null) {
            playing_source.disconnect();
        }
        me.playing_source = me.get_source();
        me.started_at = ac.currentTime;
        me.playing_source.start(0, me.time);
        me.is_playing = true;
        me.notify_playing();
        return true;
    }

    pause() {
        if (this.playing_source === null) { return null }
        this.time = ac.currentTime - this.started_at;
        this.playing_source.stop();
        this.playing_source = null;
        this.is_playing = false;
        this.unnotify_playing();
    }

    get_time() {
        return this.is_playing ? ac.currentTime - started_at : this.time;
    }

    set_time(new_time) {
        if (new_time < 0 || isNaN(new_time)) {
            throw 'can only set time to non-negative number, not '+new_time;
        }
        this.time = +new_time;
        if (this.is_playing) {
            this.play();
        }
    }

    play_window(from, to) {
        const me = this;
        if (me.buffer === null) { return null }
        const source = me.get_source();
        source.start(0, from, to - from);
        return source;
    }

    notify_playing() {
        const me = this;
        if (me.timeupdate_interval !== null) {
            me.timeupdate_interval = window.setInterval(function () {
                if (typeof me.ontimeupdate === 'function') {
                    me.ontimeupdate();
                }
                if (!me.is_playing) {
                    me.unnotify_playing();
                }
            }, 250);
        }
    }

    unnotify_playing() {
        if (this.timeupdate_interval !== null) {
            window.clearInterval(this.timeupdate_interval);
        }
        this.timeupdate_interval = null;
    }
}

export default function get_audio() {
    return audio;
};
export function load_audio(new_stub) {
    if (new_stub && new_stub !== stub) {
        stub = new_stub;
        audio = new MAudio(new_stub);
        return audio.load();
    }
    else {
        return Promise.resolve(audio);
    }
};
;;; window.get_audio = get_audio;
<commit_msg>forget about localStorage :-(<commit_after>/* global AUDIO_FORMATS */
/* global window */
/* global EventTarget */

export const sample_rate = 24000;
export const fetching_audio_event = 'fetching-audio';
export const fetched_audio_event = 'fetched-audio';
export const decoded_audio_event = 'decoded-audio';
export const ac = new AudioContext({sampleRate:sample_rate});
export const format = (audio_el => AUDIO_FORMATS.find(f => audio_el.canPlayType(f.mime)))(new Audio());
if (!format) {
    console.log('no supported format, no audio');
}

let stub;
let audio;
let timeupdate_interval = null;

class MAudio {
    constructor(stub) {
        if (!format) {
            console.log('no supported format, no audio');
            return null;
        }
        this.stub = stub;
        this.buffer = null;
        this.time = 0;
        this.started_at = null;
        this.is_playing = false;
        this.playing_source = null;
    }

    load() {
        const me = this;
        return new Promise(fulfill => {
            const stub = me.stub;
            const src = [stub, format.suffix].join('.');
            ;;; console.log('downloading');
            fetch(src).then(res => {    // TODO: progress bar
                window.dispatchEvent(new Event(fetched_audio_event));
                res.arrayBuffer().then(encoded_data => {
                    ;;; console.log('decoding');
                    new AudioContext().decodeAudioData(encoded_data, decoded_buffer => {
                        me.buffer = decoded_buffer;
                        window.dispatchEvent(new Event(decoded_audio_event));
                        ;;; console.log('done');
                        fulfill(me);
                    });
                });
            });
        });
    }

    get_source() {
        if (this.buffer === null) { return null }
        const audio_source = ac.createBufferSource();
        this.audio_source = audio_source;
        audio_source.buffer = this.buffer;
        audio_source.connect(ac.destination);
        audio_source.addEventListener('ended', () => audio_source.disconnect());
        return audio_source;
    }

    play() {
        const me = this;
        if (me.buffer === null) { return null }
        if (me.playing_source !== null) {
            playing_source.disconnect();
        }
        me.playing_source = me.get_source();
        me.started_at = ac.currentTime;
        me.playing_source.start(0, me.time);
        me.is_playing = true;
        me.notify_playing();
        return true;
    }

    pause() {
        if (this.playing_source === null) { return null }
        this.time = ac.currentTime - this.started_at;
        this.playing_source.stop();
        this.playing_source = null;
        this.is_playing = false;
        this.unnotify_playing();
    }

    get_time() {
        return this.is_playing ? ac.currentTime - started_at : this.time;
    }

    set_time(new_time) {
        if (new_time < 0 || isNaN(new_time)) {
            throw 'can only set time to non-negative number, not '+new_time;
        }
        this.time = +new_time;
        if (this.is_playing) {
            this.play();
        }
    }

    play_window(from, to) {
        const me = this;
        if (me.buffer === null) { return null }
        const source = me.get_source();
        source.start(0, from, to - from);
        return source;
    }

    notify_playing() {
        const me = this;
        if (me.timeupdate_interval !== null) {
            me.timeupdate_interval = window.setInterval(function () {
                if (typeof me.ontimeupdate === 'function') {
                    me.ontimeupdate();
                }
                if (!me.is_playing) {
                    me.unnotify_playing();
                }
            }, 250);
        }
    }

    unnotify_playing() {
        if (this.timeupdate_interval !== null) {
            window.clearInterval(this.timeupdate_interval);
        }
        this.timeupdate_interval = null;
    }
}

export default function get_audio() {
    return audio;
};
export function load_audio(new_stub) {
    if (new_stub && new_stub !== stub) {
        stub = new_stub;
        audio = new MAudio(new_stub);
        return audio.load();
    }
    else {
        return Promise.resolve(audio);
    }
};
;;; window.get_audio = get_audio;
<|endoftext|>


<commit_before>/* @flow */

import {ConsoleReporter, JSONReporter} from '../reporters/index.js';
import * as commands from './commands/index.js';
import * as constants from '../constants.js';
import * as network from '../util/network.js';
import * as lockfile from 'proper-lockfile';

import aliases from './aliases.js';
import Config from '../config.js';
import onDeath from 'death';

const net = require('net');
const path = require('path');
const fs = require('fs');

let loudRejection = require('loud-rejection');
let commander = require('commander');
let invariant = require('invariant');
let pkg = require('../../package');
let _ = require('lodash');

loudRejection();

let args = process.argv;

// set global options
commander.version(pkg.version);
commander.usage('[command] [flags]');
commander.option('--offline');
commander.option('--prefer-offline');
commander.option('--har', 'Save HAR output of network traffic');
commander.option('--ignore-engines', 'Ignore engines check');
commander.option('--json', '');
commander.option('--modules-folder [path]', 'rather than installing modules into the node_modules ' +
                                            'folder relative to the cwd, output them here');
commander.option('--packages-root [path]', 'rather than storing modules into a global packages root,' +
                                           'store them here');
commander.option(
 '--force-single-instance',
 'pause and wait if other instances are running on the same folder using a tcp server',
);
commander.option(
  '--port [port]',
  `use with --force-single-instance to ovveride the default port (${constants.DEFAULT_PORT_FOR_SINGLE_INSTANCE})`,
);
commander.option(
  '--force-single-instance-with-file',
  'pause and wait if other instances are running on the same folder using a operating system lock file',
);

// get command name
let commandName: string = args.splice(2, 1)[0] || '';

// if command name looks like a flag or doesn't exist then print help
if (!commandName || commandName[0] === '-') {
  if (commandName) {
    args.splice(2, 0, commandName);
  }
  commandName = 'install';
}

// handle aliases: i -> install
// $FlowFixMe: this is a perfectly fine pattern
if (commandName && typeof aliases[commandName] === 'string') {
  commandName = aliases[commandName];
}

//
if (!commandName || commandName === 'help') {
  commander.parse(args);
  commander.help();
  process.exit(1);
}

//
invariant(commandName, 'Missing command name');
let command = commands[_.camelCase(commandName)];

if (!command) {
  args.splice(2, 0, commandName);
  command = commands.run;
}

// parse flags
if (typeof command.setFlags === 'function') {
  command.setFlags(commander);
}
commander.parse(args);

//
let Reporter = ConsoleReporter;
if (commander.json) {
  Reporter = JSONReporter;
}
let reporter = new Reporter({
  emoji: true,
});
reporter.initPeakMemoryCounter();

//
let config = new Config(reporter, {
  modulesFolder: commander.modulesFolder,
  packagesRoot: commander.packagesRoot,
  preferOffline: commander.preferOffline,
  captureHar: commander.har,
  ignoreEngines: commander.ignoreEngines,
  offline: commander.preferOffline || commander.offline,
});

// print header
let outputWrapper = true;
if (typeof command.hasWrapper === 'function') {
  outputWrapper = command.hasWrapper(commander, commander.args);
}
if (outputWrapper) {
  reporter.header(commandName, pkg);
}

//
if (commander.yes) {
  reporter.warn(
    'The yes flag has been set. This will automatically answer yes to all questions which ' +
    'may have security implications.',
  );
}

//
if (!commander.offline && network.isOffline()) {
  reporter.warn(
    "You don't appear to have an internet connection. " +
    'Try the --offline flag to use the cache for registry queries.',
  );
}

//
if (command.requireLockfile && !fs.existsSync(path.join(config.cwd, constants.LOCKFILE_FILENAME))) {
  reporter.error(reporter.lang('noRequiredLockfile'));
  process.exit(1);
}

//
const run = (): Promise<void> => {
  return command.run(config, reporter, commander, commander.args).then(function() {
    reporter.close();
    if (outputWrapper) {
      reporter.footer(false);
    }
  });
};

//
const runEventuallyWithLockFile = (isFirstTime): Promise<void> => {
  return new Promise((ok) => {
    const lock = path.join(config.cwd, constants.SINGLE_INSTANCE_FILENAME);
    lockfile.lock(lock, {realpath: false}, (err, release) => {
      if (err) {
        if (isFirstTime) {
          reporter.warn(reporter.lang('waitingInstance'));
        }
        setTimeout(() => {
          ok(runEventuallyWithLockFile());
        }, 200); // do not starve the CPU
      } else {
        onDeath(() => {
          process.exit(1);
        });
        ok(run().then(release));
      }
    });
  });
};

//
const runEventually = (): Promise<void> => {
  return new Promise((ok) => {
    const connectionOptions = {
      port: commander.port || constants.DEFAULT_PORT_FOR_SINGLE_INSTANCE,
    };

    const clients = [];
    const server = net.createServer((client) => {
      clients.push(client);
    });

    server.on('error', () => {
      // another yarnn instance exists, let's connect to it to know when it dies.
      reporter.warn(reporter.lang('waitingInstance'));
      let socket = net.createConnection(connectionOptions);

      socket
        .on('data', () => {
          // the server has informed us he's going to die soon™.
          socket.unref(); // let it die
          process.nextTick(() => {
            ok(runEventually());
          });
        })
        .on('error', (e) => {
          // No server to listen to ? :O let's retry to become the next server then.
          process.nextTick(() => {
            ok(runEventually());
          });
        });
    });

    const onServerEnd = (): Promise<void> => {
      clients.forEach((client) => {
        client.write('closing. kthanx, bye.');
      });
      server.close();
      return Promise.resolve();
    };

    // open the server and continue only if succeed.
    server.listen(connectionOptions, () => {
      // ensure the server gets closed properly on SIGNALS.
      onDeath(onServerEnd);

      ok(run().then(onServerEnd));
    });
  });
};

//
config.init().then(function(): Promise<void> {
  const exit = () => {
    process.exit(0);
  };

  if (commander.forceSingleInstanceWithFile) {
    return runEventuallyWithLockFile(true).then(exit);
  }

  if (commander.forceSingleInstance) {
    return runEventually().then(exit);
  }

  return run().then(exit);
}).catch(function(errs) {
  function logError(err) {
    reporter.error(err.stack.replace(/^Error: /, ''));
  }

  if (errs) {
    if (Array.isArray(errs)) {
      for (let err of errs) {
        logError(err);
      }
    } else {
      logError(errs);
    }
  }

  process.exit(1);
});
<commit_msg>only enable emoji for osx - closes #405 (#415)<commit_after>/* @flow */

import {ConsoleReporter, JSONReporter} from '../reporters/index.js';
import * as commands from './commands/index.js';
import * as constants from '../constants.js';
import * as network from '../util/network.js';
import * as lockfile from 'proper-lockfile';

import aliases from './aliases.js';
import Config from '../config.js';
import onDeath from 'death';

const net = require('net');
const path = require('path');
const fs = require('fs');

let loudRejection = require('loud-rejection');
let commander = require('commander');
let invariant = require('invariant');
let pkg = require('../../package');
let _ = require('lodash');

loudRejection();

let args = process.argv;

// set global options
commander.version(pkg.version);
commander.usage('[command] [flags]');
commander.option('--offline');
commander.option('--prefer-offline');
commander.option('--har', 'Save HAR output of network traffic');
commander.option('--ignore-engines', 'Ignore engines check');
commander.option('--json', '');
commander.option('--modules-folder [path]', 'rather than installing modules into the node_modules ' +
                                            'folder relative to the cwd, output them here');
commander.option('--packages-root [path]', 'rather than storing modules into a global packages root,' +
                                           'store them here');
commander.option(
 '--force-single-instance',
 'pause and wait if other instances are running on the same folder using a tcp server',
);
commander.option(
  '--port [port]',
  `use with --force-single-instance to ovveride the default port (${constants.DEFAULT_PORT_FOR_SINGLE_INSTANCE})`,
);
commander.option(
  '--force-single-instance-with-file',
  'pause and wait if other instances are running on the same folder using a operating system lock file',
);

// get command name
let commandName: string = args.splice(2, 1)[0] || '';

// if command name looks like a flag or doesn't exist then print help
if (!commandName || commandName[0] === '-') {
  if (commandName) {
    args.splice(2, 0, commandName);
  }
  commandName = 'install';
}

// handle aliases: i -> install
// $FlowFixMe: this is a perfectly fine pattern
if (commandName && typeof aliases[commandName] === 'string') {
  commandName = aliases[commandName];
}

//
if (!commandName || commandName === 'help') {
  commander.parse(args);
  commander.help();
  process.exit(1);
}

//
invariant(commandName, 'Missing command name');
let command = commands[_.camelCase(commandName)];

if (!command) {
  args.splice(2, 0, commandName);
  command = commands.run;
}

// parse flags
if (typeof command.setFlags === 'function') {
  command.setFlags(commander);
}
commander.parse(args);

//
let Reporter = ConsoleReporter;
if (commander.json) {
  Reporter = JSONReporter;
}
let reporter = new Reporter({
  emoji: process.stdout.isTTY && process.platform === 'darwin',
});
reporter.initPeakMemoryCounter();

//
let config = new Config(reporter, {
  modulesFolder: commander.modulesFolder,
  packagesRoot: commander.packagesRoot,
  preferOffline: commander.preferOffline,
  captureHar: commander.har,
  ignoreEngines: commander.ignoreEngines,
  offline: commander.preferOffline || commander.offline,
});

// print header
let outputWrapper = true;
if (typeof command.hasWrapper === 'function') {
  outputWrapper = command.hasWrapper(commander, commander.args);
}
if (outputWrapper) {
  reporter.header(commandName, pkg);
}

//
if (commander.yes) {
  reporter.warn(
    'The yes flag has been set. This will automatically answer yes to all questions which ' +
    'may have security implications.',
  );
}

//
if (!commander.offline && network.isOffline()) {
  reporter.warn(
    "You don't appear to have an internet connection. " +
    'Try the --offline flag to use the cache for registry queries.',
  );
}

//
if (command.requireLockfile && !fs.existsSync(path.join(config.cwd, constants.LOCKFILE_FILENAME))) {
  reporter.error(reporter.lang('noRequiredLockfile'));
  process.exit(1);
}

//
const run = (): Promise<void> => {
  return command.run(config, reporter, commander, commander.args).then(function() {
    reporter.close();
    if (outputWrapper) {
      reporter.footer(false);
    }
  });
};

//
const runEventuallyWithLockFile = (isFirstTime): Promise<void> => {
  return new Promise((ok) => {
    const lock = path.join(config.cwd, constants.SINGLE_INSTANCE_FILENAME);
    lockfile.lock(lock, {realpath: false}, (err, release) => {
      if (err) {
        if (isFirstTime) {
          reporter.warn(reporter.lang('waitingInstance'));
        }
        setTimeout(() => {
          ok(runEventuallyWithLockFile());
        }, 200); // do not starve the CPU
      } else {
        onDeath(() => {
          process.exit(1);
        });
        ok(run().then(release));
      }
    });
  });
};

//
const runEventually = (): Promise<void> => {
  return new Promise((ok) => {
    const connectionOptions = {
      port: commander.port || constants.DEFAULT_PORT_FOR_SINGLE_INSTANCE,
    };

    const clients = [];
    const server = net.createServer((client) => {
      clients.push(client);
    });

    server.on('error', () => {
      // another yarnn instance exists, let's connect to it to know when it dies.
      reporter.warn(reporter.lang('waitingInstance'));
      let socket = net.createConnection(connectionOptions);

      socket
        .on('data', () => {
          // the server has informed us he's going to die soon™.
          socket.unref(); // let it die
          process.nextTick(() => {
            ok(runEventually());
          });
        })
        .on('error', (e) => {
          // No server to listen to ? :O let's retry to become the next server then.
          process.nextTick(() => {
            ok(runEventually());
          });
        });
    });

    const onServerEnd = (): Promise<void> => {
      clients.forEach((client) => {
        client.write('closing. kthanx, bye.');
      });
      server.close();
      return Promise.resolve();
    };

    // open the server and continue only if succeed.
    server.listen(connectionOptions, () => {
      // ensure the server gets closed properly on SIGNALS.
      onDeath(onServerEnd);

      ok(run().then(onServerEnd));
    });
  });
};

//
config.init().then(function(): Promise<void> {
  const exit = () => {
    process.exit(0);
  };

  if (commander.forceSingleInstanceWithFile) {
    return runEventuallyWithLockFile(true).then(exit);
  }

  if (commander.forceSingleInstance) {
    return runEventually().then(exit);
  }

  return run().then(exit);
}).catch(function(errs) {
  function logError(err) {
    reporter.error(err.stack.replace(/^Error: /, ''));
  }

  if (errs) {
    if (Array.isArray(errs)) {
      for (let err of errs) {
        logError(err);
      }
    } else {
      logError(errs);
    }
  }

  process.exit(1);
});
<|endoftext|>


<commit_before>Package.describe({
    summary: "Accounts Templates styled for Semantic UI.",
    version: "1.7.0",
    name: "useraccounts:semantic-ui",
    git: "https://github.com/meteor-useraccounts/semantic-ui.git",
});

Package.on_use(function(api, where) {
    api.versionsFrom("METEOR@1.0");

    api.use([
        "less",
        "templating",
    ], "client");

    api.use([
        "useraccounts:core",
    ], ["client", "server"]);

    api.imply([
        "useraccounts:core@1.7.0",
    ], ["client", "server"]);

    api.add_files([
        "lib/at_error.html",
        "lib/at_error.js",
        "lib/at_form.html",
        "lib/at_form.js",
        "lib/at_input.html",
        "lib/at_input.js",
        "lib/at_nav_button.html",
        "lib/at_nav_button.js",
        "lib/at_oauth.html",
        "lib/at_oauth.js",
        "lib/at_pwd_form.html",
        "lib/at_pwd_form.js",
        "lib/at_pwd_form_btn.html",
        "lib/at_pwd_form_btn.js",
        "lib/at_pwd_link.html",
        "lib/at_pwd_link.js",
        "lib/at_reCaptcha.html",
        "lib/at_reCaptcha.js",
        "lib/at_result.html",
        "lib/at_result.js",
        "lib/at_sep.html",
        "lib/at_sep.js",
        "lib/at_signin_link.html",
        "lib/at_signin_link.js",
        "lib/at_signup_link.html",
        "lib/at_signup_link.js",
        "lib/at_social.html",
        "lib/at_social.js",
        "lib/at_terms_link.html",
        "lib/at_terms_link.js",
        "lib/at_title.html",
        "lib/at_title.js",
        "lib/full_page_at_form.html",
        "lib/at_semantic-ui.less"
    ], ["client"]);
});

Package.on_test(function(api) {
    api.use([
        "useraccounts:semantic-ui",
        "useraccounts:core@1.7.0",
    ]);

    api.use([
        "accounts-password",
        "tinytest",
        "test-helpers"
    ], ["client", "server"]);

    api.add_files([
        "tests/tests.js"
    ], ["client", "server"]);
});
<commit_msg>patch release - Bump to version 1.7.1<commit_after>Package.describe({
    summary: "Accounts Templates styled for Semantic UI.",
    version: "1.7.1",
    name: "useraccounts:semantic-ui",
    git: "https://github.com/meteor-useraccounts/semantic-ui.git",
});

Package.on_use(function(api, where) {
    api.versionsFrom("METEOR@1.0");

    api.use([
        "less",
        "templating",
    ], "client");

    api.use([
        "useraccounts:core",
    ], ["client", "server"]);

    api.imply([
        "useraccounts:core@1.7.1",
    ], ["client", "server"]);

    api.add_files([
        "lib/at_error.html",
        "lib/at_error.js",
        "lib/at_form.html",
        "lib/at_form.js",
        "lib/at_input.html",
        "lib/at_input.js",
        "lib/at_nav_button.html",
        "lib/at_nav_button.js",
        "lib/at_oauth.html",
        "lib/at_oauth.js",
        "lib/at_pwd_form.html",
        "lib/at_pwd_form.js",
        "lib/at_pwd_form_btn.html",
        "lib/at_pwd_form_btn.js",
        "lib/at_pwd_link.html",
        "lib/at_pwd_link.js",
        "lib/at_reCaptcha.html",
        "lib/at_reCaptcha.js",
        "lib/at_result.html",
        "lib/at_result.js",
        "lib/at_sep.html",
        "lib/at_sep.js",
        "lib/at_signin_link.html",
        "lib/at_signin_link.js",
        "lib/at_signup_link.html",
        "lib/at_signup_link.js",
        "lib/at_social.html",
        "lib/at_social.js",
        "lib/at_terms_link.html",
        "lib/at_terms_link.js",
        "lib/at_title.html",
        "lib/at_title.js",
        "lib/full_page_at_form.html",
        "lib/at_semantic-ui.less"
    ], ["client"]);
});

Package.on_test(function(api) {
    api.use([
        "useraccounts:semantic-ui",
        "useraccounts:core@1.7.1",
    ]);

    api.use([
        "accounts-password",
        "tinytest",
        "test-helpers"
    ], ["client", "server"]);

    api.add_files([
        "tests/tests.js"
    ], ["client", "server"]);
});
<|endoftext|>


<commit_before>/*
   Copyright 2011 300 D&C

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

/**
 * Checks if the array contains specified element
 *
 * @memberOf Array#
 * @param {Object} element
 * @returns {Boolean}
 */
Array.prototype.contains = function(element) {
	for (var i = 0; i < this.length; i++) {
		if (this[i] === element) return true;
	}
	return false;
};

/**
 * Left pads this string with specified string while length of this string is less than specified
 *
 * @memberOf String#
 * @param {String} pad
 * @param {Number} length
 * @returns {String}
 */
String.prototype.lpad = function(pad, length) {
	var s = this;
    while (s.length < length)
        s = pad + s;
    return s;
};

/**
 * Trims this string both sides
 *
 * @memberOf String#
 * @returns {String}
 */
String.prototype.trim = function() {
    return this.replace(/^\s+/g, "").replace(/\s+$/g, "");
};

/**
 * @namespace
 */
Core.Helper = {

	/**
	 * Returns array of names in map
	 *
	 * @param {Object} map
	 * @returns {Array}
	 */
	getNames: function(map) {
		var names = [];
		for (name in map) {
			names.push(name);
		}
		return names;
	},

	/**
	 * Returns array of values in map
	 *
	 * @param {Object} map
	 * @returns {Array}
	 */
	getValues: function(map) {
		var values = [];
		for (name in map) {
			values.push(map[name]);
		}
		return values;
	}
};
<commit_msg>Update Core/Core.Helper.js<commit_after>/*
   Copyright 2011 300 D&C

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

/**
 * Checks if array [this] contains provided [element]
 *
 * @memberOf Array#
 * @param {Object} element
 * @returns {Boolean}
 */
Array.prototype.contains = function(element) {
	for (var i = 0; i < this.length; i++) {
		if (this[i] === element) return true;
	}
	return false;
};

/**
 * Left pads this string with specified string while length of this string is less than specified
 *
 * @memberOf String#
 * @param {String} pad
 * @param {Number} length
 * @returns {String}
 */
String.prototype.lpad = function(pad, length) {
	var s = this;
    while (s.length < length)
        s = pad + s;
    return s;
};

/**
 * Trims this string both sides
 *
 * @memberOf String#
 * @returns {String}
 */
String.prototype.trim = function() {
    return this.replace(/^\s+/g, "").replace(/\s+$/g, "");
};

/**
 * @namespace
 */
Core.Helper = {

	/**
	 * Returns array of names in map
	 *
	 * @param {Object} map
	 * @returns {Array}
	 */
	getNames: function(map) {
		var names = [];
		for (name in map) {
			names.push(name);
		}
		return names;
	},

	/**
	 * Returns array of values in map
	 *
	 * @param {Object} map
	 * @returns {Array}
	 */
	getValues: function(map) {
		var values = [];
		for (name in map) {
			values.push(map[name]);
		}
		return values;
	}
};
<|endoftext|>


<commit_before>import Vue from 'vue';
import Vuex from 'vuex';
import firebase from 'firebase';
import { emailIsWhitelisted, addIdToItems } from '../utils';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    user: null,
    error: null,
    challenges: {
      areLoading: true,
      items: [],
      ref: null,
    },
    solutions: {
      areLoading: true,
      items: [],
      ref: null,
    },
  },
  getters: {
    challenges: state => [...state.challenges.items].sort((a, b) => b.createdAt - a.createdAt),
    solutions: state => [...state.solutions.items].sort((a, b) => a.createdAt - b.createdAt),
  },
  mutations: {
    setUser(state, payload) {
      state.user = payload;
    },
    setError(state, payload) {
      state.error = payload;
    },
    setChallenges(state, payload) {
      state.challenges = payload;
    },
    setSolutions(state, payload) {
      state.solutions = payload;
    },
    clearSolutions(state) {
      state.solutions.ref.off();
      state.solutions = {
        areLoading: true,
        items: [],
        ref: null,
      };
    },
  },
  actions: {
    validateUser({ commit, dispatch }, payload) {
      if (emailIsWhitelisted(payload.email)) {
        const { displayName: name, email, photoURL: photoUrl, uid: id } = payload;
        const user = { name, email, photoUrl };
        firebase.database().ref(`/users/${id}`).set(user);
        commit('setUser', { ...user, id });
        commit('setError', null);
      } else {
        dispatch('signOut', 'You must be part of the "umich.edu" domain to use this app.');
      }
    },
    signIn({ dispatch }) {
      const google = new firebase.auth.GoogleAuthProvider();
      google.setCustomParameters({ hd: 'umich.edu' });
      firebase.auth()
        .signInWithPopup(google)
        .then(({ user }) => { dispatch('validateUser', user); })
        .catch(() => {});
    },
    signOut({ commit }, payload) {
      firebase.auth().signOut();
      commit('setUser', null);
      const error = typeof payload === 'string' ? payload : null;
      commit('setError', error);
    },
    loadChallenges({ commit }) {
      const ref = firebase.database().ref('challenges');
      ref.on('value', (snapshot) => {
        commit('setChallenges', {
          items: addIdToItems(snapshot.val() || {}),
          areLoading: false,
          ref,
        });
      });
    },
    loadSolutions({ commit }, challengeId) {
      const ref = firebase.database().ref(`solutions/${challengeId}`);
      ref.on('value', (snapshot) => {
        commit('setSolutions', {
          items: addIdToItems(snapshot.val() || {}),
          areLoading: false,
          ref,
        });
      });
    },
  },
});
<commit_msg>Remove google domain param<commit_after>import Vue from 'vue';
import Vuex from 'vuex';
import firebase from 'firebase';
import { emailIsWhitelisted, addIdToItems } from '../utils';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    user: null,
    error: null,
    challenges: {
      areLoading: true,
      items: [],
      ref: null,
    },
    solutions: {
      areLoading: true,
      items: [],
      ref: null,
    },
  },
  getters: {
    challenges: state => [...state.challenges.items].sort((a, b) => b.createdAt - a.createdAt),
    solutions: state => [...state.solutions.items].sort((a, b) => a.createdAt - b.createdAt),
  },
  mutations: {
    setUser(state, payload) {
      state.user = payload;
    },
    setError(state, payload) {
      state.error = payload;
    },
    setChallenges(state, payload) {
      state.challenges = payload;
    },
    setSolutions(state, payload) {
      state.solutions = payload;
    },
    clearSolutions(state) {
      state.solutions.ref.off();
      state.solutions = {
        areLoading: true,
        items: [],
        ref: null,
      };
    },
  },
  actions: {
    validateUser({ commit, dispatch }, payload) {
      if (emailIsWhitelisted(payload.email)) {
        const { displayName: name, email, photoURL: photoUrl, uid: id } = payload;
        const user = { name, email, photoUrl };
        firebase.database().ref(`/users/${id}`).set(user);
        commit('setUser', { ...user, id });
        commit('setError', null);
      } else {
        dispatch('signOut', 'You must be part of the "umich.edu" domain to use this app.');
      }
    },
    signIn({ dispatch }) {
      const google = new firebase.auth.GoogleAuthProvider();
      firebase.auth()
        .signInWithPopup(google)
        .then(({ user }) => { dispatch('validateUser', user); })
        .catch(() => {});
    },
    signOut({ commit }, payload) {
      firebase.auth().signOut();
      commit('setUser', null);
      const error = typeof payload === 'string' ? payload : null;
      commit('setError', error);
    },
    loadChallenges({ commit }) {
      const ref = firebase.database().ref('challenges');
      ref.on('value', (snapshot) => {
        commit('setChallenges', {
          items: addIdToItems(snapshot.val() || {}),
          areLoading: false,
          ref,
        });
      });
    },
    loadSolutions({ commit }, challengeId) {
      const ref = firebase.database().ref(`solutions/${challengeId}`);
      ref.on('value', (snapshot) => {
        commit('setSolutions', {
          items: addIdToItems(snapshot.val() || {}),
          areLoading: false,
          ref,
        });
      });
    },
  },
});
<|endoftext|>


<commit_before>
/**
 * Represents a wrapped IMP. IMPs are function pointers for methods. The first
 * two arguments are always 1) the object instance the method is being called
 * on, and 2) the SEL selector, respectively. Subsequent arguments are the args
 * that were passed in when invoked.
 */

/**
 * Module exports.
 */

exports.createWrapperPointer = createWrapperPointer
exports.createUnwrapperFunction = createUnwrapperFunction

/**
 * Module dependencies.
 */

var core = require('./core')
  , types = require('./types')

/**
 * Creates an ffi Function Pointer to the passed in 'func' Function. The
 * function gets wrapped in an "wrapper" function, which wraps the passed in
 * arguments, and unwraps the return value.
 *
 * @param {Function} A JS function to be converted to an ffi C function.
 * @param {Object|Array} A "type" object or Array containing the 'retval' and
 *                       'args' for the Function.
 * @api private
 */

function createWrapperPointer (func, type) {
  if (func.pointer) {
    // When an 'unwrapper' function is passed in, return the original pointer
    return func.pointer
  }
  var rtnType = type.retval || type[0] || 'v'
    , argTypes = type.args || type[1] || []
    , ffiCb = new core.Callback([types.map(rtnType), types.mapArray(argTypes)], wrapper)
  function wrapper () {
    var args = core.wrapValues(arguments, argTypes)
      , rtn = func.apply(null, args)
    return core.unwrapValue(rtn, rtnType)
  }
  return ffiCb.getPointer()
}

/**
 * Creates a JS Function from the passed in function pointer. When the returned
 * function is invoked, the passed in arguments are unwrapped before being
 * passed to the native function, and the return value is wrapped up before
 * being returned for real.
 *
 * @param {Pointer} The function pointer to create an unwrapper function around
 * @param {Object|Array} A "type" object or Array containing the 'retval' and
 *                       'args' for the Function.
 * @api private
 */

function createUnwrapperFunction (funcPtr, type) {
  var rtnType = type.retval || type[0] || 'v'
    , argTypes = type.args || type[1] || []
    , func = core.ForeignFunction.build(funcPtr, types.map(rtnType), types.mapArray(argTypes))
  function unwrapper () {
    var args = core.unwrapValues(arguments, argTypes)
      , rtn = func.apply(null, args)
    return core.wrapValue(rtn, rtnType)
  }
  unwrapper.retval = rtnType
  unwrapper.args = argTypes
  unwrapper.pointer = funcPtr
  return unwrapper
}
<commit_msg>Make lines shorter.<commit_after>
/**
 * Represents a wrapped IMP. IMPs are function pointers for methods. The first
 * two arguments are always 1) the object instance the method is being called
 * on, and 2) the SEL selector, respectively. Subsequent arguments are the args
 * that were passed in when invoked.
 */

/**
 * Module exports.
 */

exports.createWrapperPointer = createWrapperPointer
exports.createUnwrapperFunction = createUnwrapperFunction

/**
 * Module dependencies.
 */

var core = require('./core')
  , types = require('./types')

/**
 * Creates an ffi Function Pointer to the passed in 'func' Function. The
 * function gets wrapped in an "wrapper" function, which wraps the passed in
 * arguments, and unwraps the return value.
 *
 * @param {Function} A JS function to be converted to an ffi C function.
 * @param {Object|Array} A "type" object or Array containing the 'retval' and
 *                       'args' for the Function.
 * @api private
 */

function createWrapperPointer (func, type) {
  if (func.pointer) {
    // When an 'unwrapper' function is passed in, return the original pointer
    return func.pointer
  }
  var rtnType = type.retval || type[0] || 'v'
    , argTypes = type.args || type[1] || []
    , ffiDef = [types.map(rtnType), types.mapArray(argTypes)]
    , ffiCb = new core.Callback(ffiDef, wrapper)
  function wrapper () {
    var args = core.wrapValues(arguments, argTypes)
      , rtn = func.apply(null, args)
    return core.unwrapValue(rtn, rtnType)
  }
  return ffiCb.getPointer()
}

/**
 * Creates a JS Function from the passed in function pointer. When the returned
 * function is invoked, the passed in arguments are unwrapped before being
 * passed to the native function, and the return value is wrapped up before
 * being returned for real.
 *
 * @param {Pointer} The function pointer to create an unwrapper function around
 * @param {Object|Array} A "type" object or Array containing the 'retval' and
 *                       'args' for the Function.
 * @api private
 */

function createUnwrapperFunction (funcPtr, type) {
  var rtnType = type.retval || type[0] || 'v'
    , argTypes = type.args || type[1] || []
    , func = core.ForeignFunction.build(funcPtr
                                      , types.map(rtnType)
                                      , types.mapArray(argTypes))
  function unwrapper () {
    var args = core.unwrapValues(arguments, argTypes)
      , rtn = func.apply(null, args)
    return core.wrapValue(rtn, rtnType)
  }
  unwrapper.retval = rtnType
  unwrapper.args = argTypes
  unwrapper.pointer = funcPtr
  return unwrapper
}
<|endoftext|>


<commit_before>import store from '@/store/store'

export const createUniqueKey = () => Date.now().toString(36) + Math.random().toString(36).substring(2)

export function retrieveViewName (pos) {
  if (store.state.history.length <= pos) {
    return ''
  }
  return store.state.history[store.state.history.length - pos].name
}

export function transformViewName (view) {
  view = view.toLowerCase()
  let count = 0

  if (!store.state.isRouterEnabled) {
    count = store.state.history.filter((historicView) => historicView.name.startsWith(view)).length
    view += '--' + count
  }
  return view
}

export function parseView (data) {
  const baseName = (typeof data === 'object') ? data.name : data
  const name = transformViewName(baseName)
  const route = { name, params: data.params }
  let path = '/' + name

  if (typeof data === 'object' && typeof data.params === 'object') {
    let paramPath = ''
    Object.keys(data.params).forEach(function (key) {
      paramPath += '/:' + key
    })
    path += paramPath
  }

  return {
    name,
    route,
    path
  }
}
<commit_msg>fix(retrieveViewName): correctly verify pos parameter<commit_after>import store from '@/store/store'

export const createUniqueKey = () => Date.now().toString(36) + Math.random().toString(36).substring(2)

export function retrieveViewName (pos) {
  if (store.state.history.length < pos || pos < 1) {
    return ''
  }
  return store.state.history[store.state.history.length - pos].name
}

export function transformViewName (view) {
  view = view.toLowerCase()
  let count = 0

  if (!store.state.isRouterEnabled) {
    count = store.state.history.filter((historicView) => historicView.name.startsWith(view)).length
    view += '--' + count
  }
  return view
}

export function parseView (data) {
  const baseName = (typeof data === 'object') ? data.name : data
  const name = transformViewName(baseName)
  const route = { name, params: data.params }
  let path = '/' + name

  if (typeof data === 'object' && typeof data.params === 'object') {
    let paramPath = ''
    Object.keys(data.params).forEach(function (key) {
      paramPath += '/:' + key
    })
    path += paramPath
  }

  return {
    name,
    route,
    path
  }
}
<|endoftext|>


<commit_before>Package.describe({
  name: 'hydraorc:s3-put-signed-url',
  summary: 'Meteor method that helps you to generate a signed url to PUT a file to amazon aws s3',
  version: '1.0.2',
  git: 'https://github.com/hydraorc/meteor-s3-put-signed-url.git'
});

Npm.depends({ 'aws-sdk': '2.54.0' });

Package.onUse(function(api) {
  api.versionsFrom('1.0');

  api.use([
    'alanning:roles@1.2.16',
    'stevezhu:lodash@4.17.2',
    'hydraorc:translit@2.0.1'
  ], 'server');

  api.addFiles([
    'server/s3-put-signed-url.js'
  ], 'server');
});
<commit_msg>Update translit package version<commit_after>Package.describe({
  name: 'hydraorc:s3-put-signed-url',
  summary: 'Meteor method that helps you to generate a signed url to PUT a file to amazon aws s3',
  version: '1.0.3',
  git: 'https://github.com/hydraorc/meteor-s3-put-signed-url.git'
});

Npm.depends({ 'aws-sdk': '2.54.0' });

Package.onUse(function(api) {
  api.versionsFrom('1.0');

  api.use([
    'alanning:roles@1.2.16',
    'stevezhu:lodash@4.17.2',
    'hydraorc:translit@2.0.2'
  ], 'server');

  api.addFiles([
    'server/s3-put-signed-url.js'
  ], 'server');
});
<|endoftext|>


<commit_before>import {Slice, Fragment, DOMParser, DOMSerializer} from "prosemirror-model"
import browser from "./browser"

export function serializeForClipboard(view, slice) {
  let context = [], {content, openStart, openEnd} = slice
  while (openStart > 1 && openEnd > 1 && content.childCount == 1 && content.firstChild.childCount == 1) {
    openStart--
    openEnd--
    let node = content.firstChild
    context.push(node.type.name, node.attrs != node.type.defaultAttrs ? node.attrs : null)
    content = node.content
  }

  let serializer = view.someProp("clipboardSerializer") || DOMSerializer.fromSchema(view.state.schema)
  let doc = detachedDoc(), wrap = doc.createElement("div")
  wrap.appendChild(serializer.serializeFragment(content, {document: doc}))

  let firstChild = wrap.firstChild, needsWrap
  while (firstChild && firstChild.nodeType == 1 && (needsWrap = wrapMap[firstChild.nodeName.toLowerCase()])) {
    for (let i = needsWrap.length - 1; i >= 0; i--) {
      let wrapper = doc.createElement(needsWrap[i])
      while (wrap.firstChild) wrapper.appendChild(wrap.firstChild)
      wrap.appendChild(wrapper)
      if (needsWrap[i] != "tbody") {
        openStart++
        openEnd++
      }
    }
    firstChild = wrap.firstChild
  }

  if (firstChild && firstChild.nodeType == 1)
    firstChild.setAttribute("data-pm-slice", `${openStart} ${openEnd} ${JSON.stringify(context)}`)

  let text = view.someProp("clipboardTextSerializer", f => f(slice)) ||
      slice.content.textBetween(0, slice.content.size, "\n\n")

  return {dom: wrap, text}
}

// : (EditorView, string, string, ?bool, ResolvedPos) → ?Slice
// Read a slice of content from the clipboard (or drop data).
export function parseFromClipboard(view, text, html, plainText, $context) {
  let dom, inCode = $context.parent.type.spec.code, slice
  if (!html && !text) return null
  let asText = text && (plainText || inCode || !html)
  if (asText) {
    view.someProp("transformPastedText", f => { text = f(text, inCode || plainText) })
    if (inCode) return text ? new Slice(Fragment.from(view.state.schema.text(text.replace(/\r\n?/g, "\n"))), 0, 0) : Slice.empty
    let parsed = view.someProp("clipboardTextParser", f => f(text, $context, plainText))
    if (parsed) {
      slice = parsed
    } else {
      let marks = $context.marks()
      let {schema} = view.state, serializer = DOMSerializer.fromSchema(schema)
      dom = document.createElement("div")
      text.split(/(?:\r\n?|\n)+/).forEach(block => {
        let p = dom.appendChild(document.createElement("p"))
        if (block) p.appendChild(serializer.serializeNode(schema.text(block, marks)))
      })
    }
  } else {
    view.someProp("transformPastedHTML", f => { html = f(html) })
    dom = readHTML(html)
    if (browser.webkit) restoreReplacedSpaces(dom)
  }

  let contextNode = dom && dom.querySelector("[data-pm-slice]")
  let sliceData = contextNode && /^(\d+) (\d+) (.*)/.exec(contextNode.getAttribute("data-pm-slice"))
  if (!slice) {
    let parser = view.someProp("clipboardParser") || view.someProp("domParser") || DOMParser.fromSchema(view.state.schema)
    slice = parser.parseSlice(dom, {
      preserveWhitespace: !!(asText || sliceData),
      context: $context,
      ruleFromNode(dom) {
        if (dom.nodeName == "BR" && !dom.nextSibling && (!dom.previousSibling || dom.previousSibling.nodeName == "BR"))
          return {ignore: true}
      }
    })
  }
  if (sliceData) {
    slice = addContext(closeSlice(slice, +sliceData[1], +sliceData[2]), sliceData[3])
  } else { // HTML wasn't created by ProseMirror. Make sure top-level siblings are coherent
    slice = Slice.maxOpen(normalizeSiblings(slice.content, $context), true)
    if (slice.openStart || slice.openEnd) {
      let openStart = 0, openEnd = 0
      for (let node = slice.content.firstChild; openStart < slice.openStart && !node.type.spec.isolating;
           openStart++, node = node.firstChild) {}
      for (let node = slice.content.lastChild; openEnd < slice.openEnd && !node.type.spec.isolating;
           openEnd++, node = node.lastChild) {}
      slice = closeSlice(slice, openStart, openEnd)
    }
  }

  view.someProp("transformPasted", f => { slice = f(slice) })
  return slice
}

// Takes a slice parsed with parseSlice, which means there hasn't been
// any content-expression checking done on the top nodes, tries to
// find a parent node in the current context that might fit the nodes,
// and if successful, rebuilds the slice so that it fits into that parent.
//
// This addresses the problem that Transform.replace expects a
// coherent slice, and will fail to place a set of siblings that don't
// fit anywhere in the schema.
function normalizeSiblings(fragment, $context) {
  if (fragment.childCount < 2) return fragment
  for (let d = $context.depth; d >= 0; d--) {
    let parent = $context.node(d)
    let match = parent.contentMatchAt($context.index(d))
    let lastWrap, result = []
    fragment.forEach(node => {
      if (!result) return
      let wrap = match.findWrapping(node.type), inLast
      if (!wrap) return result = null
      if (inLast = result.length && lastWrap.length && addToSibling(wrap, lastWrap, node, result[result.length - 1], 0)) {
        result[result.length - 1] = inLast
      } else {
        if (result.length) result[result.length - 1] = closeRight(result[result.length - 1], lastWrap.length)
        let wrapped = withWrappers(node, wrap)
        result.push(wrapped)
        match = match.matchType(wrapped.type, wrapped.attrs)
        lastWrap = wrap
      }
    })
    if (result) return Fragment.from(result)
  }
  return fragment
}

function withWrappers(node, wrap, from = 0) {
  for (let i = wrap.length - 1; i >= from; i--)
    node = wrap[i].create(null, Fragment.from(node))
  return node
}

// Used to group adjacent nodes wrapped in similar parents by
// normalizeSiblings into the same parent node
function addToSibling(wrap, lastWrap, node, sibling, depth) {
  if (depth < wrap.length && depth < lastWrap.length && wrap[depth] == lastWrap[depth]) {
    let inner = addToSibling(wrap, lastWrap, node, sibling.lastChild, depth + 1)
    if (inner) return sibling.copy(sibling.content.replaceChild(sibling.childCount - 1, inner))
    let match = sibling.contentMatchAt(sibling.childCount)
    if (match.matchType(depth == wrap.length - 1 ? node.type : wrap[depth + 1]))
      return sibling.copy(sibling.content.append(Fragment.from(withWrappers(node, wrap, depth + 1))))
  }
}

function closeRight(node, depth) {
  if (depth == 0) return node
  let fragment = node.content.replaceChild(node.childCount - 1, closeRight(node.lastChild, depth - 1))
  let fill = node.contentMatchAt(node.childCount).fillBefore(Fragment.empty, true)
  return node.copy(fragment.append(fill))
}

function closeRange(fragment, side, from, to, depth, openEnd) {
  let node = side < 0 ? fragment.firstChild : fragment.lastChild, inner = node.content
  if (depth < to - 1) inner = closeRange(inner, side, from, to, depth + 1, openEnd)
  if (depth >= from)
    inner = side < 0 ? node.contentMatchAt(0).fillBefore(inner, fragment.childCount > 1 || openEnd <= depth).append(inner)
      : inner.append(node.contentMatchAt(node.childCount).fillBefore(Fragment.empty, true))
  return fragment.replaceChild(side < 0 ? 0 : fragment.childCount - 1, node.copy(inner))
}

function closeSlice(slice, openStart, openEnd) {
  if (openStart < slice.openStart)
    slice = new Slice(closeRange(slice.content, -1, openStart, slice.openStart, 0, slice.openEnd), openStart, slice.openEnd)
  if (openEnd < slice.openEnd)
    slice = new Slice(closeRange(slice.content, 1, openEnd, slice.openEnd, 0, 0), slice.openStart, openEnd)
  return slice
}

// Trick from jQuery -- some elements must be wrapped in other
// elements for innerHTML to work. I.e. if you do `div.innerHTML =
// "..	"` the table cells are ignored.
const wrapMap = {
  thead: ["table"],
  tbody: ["table"],
  tfoot: ["table"],
  caption: ["table"],
  colgroup: ["table"],
  col: ["table", "colgroup"],
  tr: ["table", "tbody"],
  td: ["table", "tbody", "tr"],
  th: ["table", "tbody", "tr"]
}

let _detachedDoc = null
function detachedDoc() {
  return _detachedDoc || (_detachedDoc = document.implementation.createHTMLDocument("title"))
}

function readHTML(html) {
  let metas = /^(\s*<meta [^>]*>)*/.exec(html)
  if (metas) html = html.slice(metas[0].length)
  let elt = detachedDoc().createElement("div")
  let firstTag = /<([a-z][^>\s]+)/i.exec(html), wrap
  if (wrap = firstTag && wrapMap[firstTag[1].toLowerCase()])
    html = wrap.map(n => "<" + n + ">").join("") + html + wrap.map(n => "</" + n + ">").reverse().join("")
  elt.innerHTML = html
  if (wrap) for (let i = 0; i < wrap.length; i++) elt = elt.querySelector(wrap[i]) || elt
  return elt
}

// Webkit browsers do some hard-to-predict replacement of regular
// spaces with non-breaking spaces when putting content on the
// clipboard. This tries to convert such non-breaking spaces (which
// will be wrapped in a plain span on Chrome, a span with class
// Apple-converted-space on Safari) back to regular spaces.
function restoreReplacedSpaces(dom) {
  let nodes = dom.querySelectorAll(browser.chrome ? "span:not([class]):not([style])" : "span.Apple-converted-space")
  for (let i = 0; i < nodes.length; i++) {
    let node = nodes[i]
    if (node.childNodes.length == 1 && node.textContent == "\u00a0" && node.parentNode)
      node.parentNode.replaceChild(dom.ownerDocument.createTextNode(" "), node)
  }
}

function addContext(slice, context) {
  if (!slice.size) return slice
  let schema = slice.content.firstChild.type.schema, array
  try { array = JSON.parse(context) }
  catch(e) { return slice }
  let {content, openStart, openEnd} = slice
  for (let i = array.length - 2; i >= 0; i -= 2) {
    let type = schema.nodes[array[i]]
    if (!type || type.hasRequiredAttrs()) break
    content = Fragment.from(type.create(array[i + 1], content))
    openStart++; openEnd++
  }
  return new Slice(content, openStart, openEnd)
}
<commit_msg>Also ignore pasted BR nodes after regular content<commit_after>import {Slice, Fragment, DOMParser, DOMSerializer} from "prosemirror-model"
import browser from "./browser"

export function serializeForClipboard(view, slice) {
  let context = [], {content, openStart, openEnd} = slice
  while (openStart > 1 && openEnd > 1 && content.childCount == 1 && content.firstChild.childCount == 1) {
    openStart--
    openEnd--
    let node = content.firstChild
    context.push(node.type.name, node.attrs != node.type.defaultAttrs ? node.attrs : null)
    content = node.content
  }

  let serializer = view.someProp("clipboardSerializer") || DOMSerializer.fromSchema(view.state.schema)
  let doc = detachedDoc(), wrap = doc.createElement("div")
  wrap.appendChild(serializer.serializeFragment(content, {document: doc}))

  let firstChild = wrap.firstChild, needsWrap
  while (firstChild && firstChild.nodeType == 1 && (needsWrap = wrapMap[firstChild.nodeName.toLowerCase()])) {
    for (let i = needsWrap.length - 1; i >= 0; i--) {
      let wrapper = doc.createElement(needsWrap[i])
      while (wrap.firstChild) wrapper.appendChild(wrap.firstChild)
      wrap.appendChild(wrapper)
      if (needsWrap[i] != "tbody") {
        openStart++
        openEnd++
      }
    }
    firstChild = wrap.firstChild
  }

  if (firstChild && firstChild.nodeType == 1)
    firstChild.setAttribute("data-pm-slice", `${openStart} ${openEnd} ${JSON.stringify(context)}`)

  let text = view.someProp("clipboardTextSerializer", f => f(slice)) ||
      slice.content.textBetween(0, slice.content.size, "\n\n")

  return {dom: wrap, text}
}

// : (EditorView, string, string, ?bool, ResolvedPos) → ?Slice
// Read a slice of content from the clipboard (or drop data).
export function parseFromClipboard(view, text, html, plainText, $context) {
  let dom, inCode = $context.parent.type.spec.code, slice
  if (!html && !text) return null
  let asText = text && (plainText || inCode || !html)
  if (asText) {
    view.someProp("transformPastedText", f => { text = f(text, inCode || plainText) })
    if (inCode) return text ? new Slice(Fragment.from(view.state.schema.text(text.replace(/\r\n?/g, "\n"))), 0, 0) : Slice.empty
    let parsed = view.someProp("clipboardTextParser", f => f(text, $context, plainText))
    if (parsed) {
      slice = parsed
    } else {
      let marks = $context.marks()
      let {schema} = view.state, serializer = DOMSerializer.fromSchema(schema)
      dom = document.createElement("div")
      text.split(/(?:\r\n?|\n)+/).forEach(block => {
        let p = dom.appendChild(document.createElement("p"))
        if (block) p.appendChild(serializer.serializeNode(schema.text(block, marks)))
      })
    }
  } else {
    view.someProp("transformPastedHTML", f => { html = f(html) })
    dom = readHTML(html)
    if (browser.webkit) restoreReplacedSpaces(dom)
  }

  let contextNode = dom && dom.querySelector("[data-pm-slice]")
  let sliceData = contextNode && /^(\d+) (\d+) (.*)/.exec(contextNode.getAttribute("data-pm-slice"))
  if (!slice) {
    let parser = view.someProp("clipboardParser") || view.someProp("domParser") || DOMParser.fromSchema(view.state.schema)
    slice = parser.parseSlice(dom, {
      preserveWhitespace: !!(asText || sliceData),
      context: $context,
      ruleFromNode(dom) {
        if (dom.nodeName == "BR" && !dom.nextSibling) return {ignore: true}
      }
    })
  }
  if (sliceData) {
    slice = addContext(closeSlice(slice, +sliceData[1], +sliceData[2]), sliceData[3])
  } else { // HTML wasn't created by ProseMirror. Make sure top-level siblings are coherent
    slice = Slice.maxOpen(normalizeSiblings(slice.content, $context), true)
    if (slice.openStart || slice.openEnd) {
      let openStart = 0, openEnd = 0
      for (let node = slice.content.firstChild; openStart < slice.openStart && !node.type.spec.isolating;
           openStart++, node = node.firstChild) {}
      for (let node = slice.content.lastChild; openEnd < slice.openEnd && !node.type.spec.isolating;
           openEnd++, node = node.lastChild) {}
      slice = closeSlice(slice, openStart, openEnd)
    }
  }

  view.someProp("transformPasted", f => { slice = f(slice) })
  return slice
}

// Takes a slice parsed with parseSlice, which means there hasn't been
// any content-expression checking done on the top nodes, tries to
// find a parent node in the current context that might fit the nodes,
// and if successful, rebuilds the slice so that it fits into that parent.
//
// This addresses the problem that Transform.replace expects a
// coherent slice, and will fail to place a set of siblings that don't
// fit anywhere in the schema.
function normalizeSiblings(fragment, $context) {
  if (fragment.childCount < 2) return fragment
  for (let d = $context.depth; d >= 0; d--) {
    let parent = $context.node(d)
    let match = parent.contentMatchAt($context.index(d))
    let lastWrap, result = []
    fragment.forEach(node => {
      if (!result) return
      let wrap = match.findWrapping(node.type), inLast
      if (!wrap) return result = null
      if (inLast = result.length && lastWrap.length && addToSibling(wrap, lastWrap, node, result[result.length - 1], 0)) {
        result[result.length - 1] = inLast
      } else {
        if (result.length) result[result.length - 1] = closeRight(result[result.length - 1], lastWrap.length)
        let wrapped = withWrappers(node, wrap)
        result.push(wrapped)
        match = match.matchType(wrapped.type, wrapped.attrs)
        lastWrap = wrap
      }
    })
    if (result) return Fragment.from(result)
  }
  return fragment
}

function withWrappers(node, wrap, from = 0) {
  for (let i = wrap.length - 1; i >= from; i--)
    node = wrap[i].create(null, Fragment.from(node))
  return node
}

// Used to group adjacent nodes wrapped in similar parents by
// normalizeSiblings into the same parent node
function addToSibling(wrap, lastWrap, node, sibling, depth) {
  if (depth < wrap.length && depth < lastWrap.length && wrap[depth] == lastWrap[depth]) {
    let inner = addToSibling(wrap, lastWrap, node, sibling.lastChild, depth + 1)
    if (inner) return sibling.copy(sibling.content.replaceChild(sibling.childCount - 1, inner))
    let match = sibling.contentMatchAt(sibling.childCount)
    if (match.matchType(depth == wrap.length - 1 ? node.type : wrap[depth + 1]))
      return sibling.copy(sibling.content.append(Fragment.from(withWrappers(node, wrap, depth + 1))))
  }
}

function closeRight(node, depth) {
  if (depth == 0) return node
  let fragment = node.content.replaceChild(node.childCount - 1, closeRight(node.lastChild, depth - 1))
  let fill = node.contentMatchAt(node.childCount).fillBefore(Fragment.empty, true)
  return node.copy(fragment.append(fill))
}

function closeRange(fragment, side, from, to, depth, openEnd) {
  let node = side < 0 ? fragment.firstChild : fragment.lastChild, inner = node.content
  if (depth < to - 1) inner = closeRange(inner, side, from, to, depth + 1, openEnd)
  if (depth >= from)
    inner = side < 0 ? node.contentMatchAt(0).fillBefore(inner, fragment.childCount > 1 || openEnd <= depth).append(inner)
      : inner.append(node.contentMatchAt(node.childCount).fillBefore(Fragment.empty, true))
  return fragment.replaceChild(side < 0 ? 0 : fragment.childCount - 1, node.copy(inner))
}

function closeSlice(slice, openStart, openEnd) {
  if (openStart < slice.openStart)
    slice = new Slice(closeRange(slice.content, -1, openStart, slice.openStart, 0, slice.openEnd), openStart, slice.openEnd)
  if (openEnd < slice.openEnd)
    slice = new Slice(closeRange(slice.content, 1, openEnd, slice.openEnd, 0, 0), slice.openStart, openEnd)
  return slice
}

// Trick from jQuery -- some elements must be wrapped in other
// elements for innerHTML to work. I.e. if you do `div.innerHTML =
// "..	"` the table cells are ignored.
const wrapMap = {
  thead: ["table"],
  tbody: ["table"],
  tfoot: ["table"],
  caption: ["table"],
  colgroup: ["table"],
  col: ["table", "colgroup"],
  tr: ["table", "tbody"],
  td: ["table", "tbody", "tr"],
  th: ["table", "tbody", "tr"]
}

let _detachedDoc = null
function detachedDoc() {
  return _detachedDoc || (_detachedDoc = document.implementation.createHTMLDocument("title"))
}

function readHTML(html) {
  let metas = /^(\s*<meta [^>]*>)*/.exec(html)
  if (metas) html = html.slice(metas[0].length)
  let elt = detachedDoc().createElement("div")
  let firstTag = /<([a-z][^>\s]+)/i.exec(html), wrap
  if (wrap = firstTag && wrapMap[firstTag[1].toLowerCase()])
    html = wrap.map(n => "<" + n + ">").join("") + html + wrap.map(n => "</" + n + ">").reverse().join("")
  elt.innerHTML = html
  if (wrap) for (let i = 0; i < wrap.length; i++) elt = elt.querySelector(wrap[i]) || elt
  return elt
}

// Webkit browsers do some hard-to-predict replacement of regular
// spaces with non-breaking spaces when putting content on the
// clipboard. This tries to convert such non-breaking spaces (which
// will be wrapped in a plain span on Chrome, a span with class
// Apple-converted-space on Safari) back to regular spaces.
function restoreReplacedSpaces(dom) {
  let nodes = dom.querySelectorAll(browser.chrome ? "span:not([class]):not([style])" : "span.Apple-converted-space")
  for (let i = 0; i < nodes.length; i++) {
    let node = nodes[i]
    if (node.childNodes.length == 1 && node.textContent == "\u00a0" && node.parentNode)
      node.parentNode.replaceChild(dom.ownerDocument.createTextNode(" "), node)
  }
}

function addContext(slice, context) {
  if (!slice.size) return slice
  let schema = slice.content.firstChild.type.schema, array
  try { array = JSON.parse(context) }
  catch(e) { return slice }
  let {content, openStart, openEnd} = slice
  for (let i = array.length - 2; i >= 0; i -= 2) {
    let type = schema.nodes[array[i]]
    if (!type || type.hasRequiredAttrs()) break
    content = Fragment.from(type.create(array[i + 1], content))
    openStart++; openEnd++
  }
  return new Slice(content, openStart, openEnd)
}
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import 'leaflet/dist/leaflet.css'
import 'leaflet.markercluster/dist/MarkerCluster.css'
import 'react-s-alert/dist/s-alert-default.css'
import 'react-s-alert/dist/s-alert-css-effects/stackslide.css'
import App from './App'
import '../app'

ReactDOM.render(
  <App />,
  document.getElementById('main'),
);
<commit_msg>Add todo for initialization.<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import 'leaflet/dist/leaflet.css'
import 'leaflet.markercluster/dist/MarkerCluster.css'
import 'react-s-alert/dist/s-alert-default.css'
import 'react-s-alert/dist/s-alert-css-effects/stackslide.css'
import App from './App'
import '../app'

// TODO add this to global context (window)
// to call it from the html page and initialize config
// with the passed parameters
//
// export default (config) => {
//   ReactDOM.render(
//     <App />,
//     document.getElementById('main'),
//   )
// }

ReactDOM.render(
  <App />,
  document.getElementById('main'),
)
<|endoftext|>