<commit_before>var gulp = require('gulp');
var server = require('gulp-server-livereload');

gulp.task('webserver', function() {
  gulp.src('./')
    .pipe(server({
      livereload: true,
      directoryListing: true,
      open: true
    }));
});

gulp.task('styles', function () {
    var postcss      = require('gulp-postcss');
    var sourcemaps   = require('gulp-sourcemaps');
    var autoprefixer = require('autoprefixer-core');

    return gulp.src('./build/css/*.css')
        .pipe(sourcemaps.init())
        .pipe(postcss([ autoprefixer({ browsers: ['last 2 version'] }) ]))
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest('./css'));
});

gulp.task('watch', function() {
  gulp.watch('build/css/*.css', ['styles']);
});<commit_msg>changes to gulpfile<commit_after>'use strict';

var gulp = require('gulp');
var server = require('gulp-server-livereload');

gulp.task('serve', function() {
  gulp.src('./')
    .pipe(server({
      livereload: true,
      directoryListing: true,
      open: true
    }));
});

gulp.task('styles', function () {
    var postcss      = require('gulp-postcss');
    var sourcemaps   = require('gulp-sourcemaps');
    var autoprefixer = require('autoprefixer-core');

    return gulp.src('./build/css/*.css')
        .pipe(sourcemaps.init())
        .pipe(postcss([ autoprefixer({ browsers: ['last 2 version'] }) ]))
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest('./css'));
});

gulp.task('watch', function() {
  gulp.watch('build/css/*.css', ['styles']);
});
<|endoftext|>


<commit_before>/* Marginalia  - margin annotation viewer for annotator */

function annotatorMarginalia(options) {

  var _t = annotator.util.gettext;
  var _app;

  options = options || {};
  // Sets the renderer function for the annotations.
  // Defaults to statard formatting.
  if(options.viewer && typeof options.viewer === 'function'){
    options.viewer = options.viewer;
  }
  else{
    options.viewer = function(annotation){
      if (annotation.text) {
        return annotator.util.escapeHtml(annotation.text);
      } else {
        return "" + _t('No comment') + "";
      }
    };
  }

  options.element = options.element || '.content';
  options.margin_class = options.margin_class || 'margin-container';

  // Container element for annotator
  var $container = $(options.element);

  // Define marginalia annotation container
  var $margin_container = $('').attr({
        class:options.margin_class
      });

  // Marginalia variables
  var marginalia_item_class = 'marginalia-item',
      toggle_id = 'toggle-annotations',
      annotations_list_class = 'annotation-list';

// Easing Function for scroll
// from jQuery Easing Plugin (version 1.3)
// http://gsgd.co.uk/sandbox/jquery/easing/
  jQuery.extend( jQuery.easing,{
    easeInOutExpo: function (x, t, b, c, d) {
      if (t==0) return b;
      if (t==d) return b+c;
      if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
      return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
    }
  });

  // Object for Marginalia
  // Defined as a object for namespacing references (i.e. marginalia.render)
  var marginalia = {
      start: function (app) {
        _app = app;
        var toggle_html ='',
            toggle_attrs = {
              class:'btn btn-green',
              id: toggle_id,
              alt: 'Toggle Annotations',
              title: 'Show Annotations'
            },
            $toggle = $('')
              .attr(toggle_attrs) // add attributes to the toggle object
              .hide() // hide the toggle object for now, will show when annotations are loaded
              .html(toggle_html); //add the html to the toggle object

        $container.prepend($margin_container);

        $(".in-page-controls").append($toggle);

        // get the rendered margin container
        $margin_container = $('.'+options.margin_class);

        return true;
      },

      render: function(annotation){
        return options.viewer(annotation);
      },

      // returns an array of the rendered annotation ids
      get_annotiations_array: function(){
        var $highlights = $('.annotator-hl'),
            highlight_group_annotation = '',
            annotations_array = [];

        $highlights.each(function(){
          var $this = $(this),
              this_annotation = $this.data('annotation-id');

          if( highlight_group_annotation !== this_annotation ){
            highlight_group_annotation = this_annotation;
            annotations_array.push(highlight_group_annotation);
          }
        });

        return annotations_array;
      },

      // Returns the annotion in the marginalia list format
      renderAnnotation: function(annotation){
        var text = $('
').attr({
            class:'text'
            }).html(marginalia.render(annotation)),
            controls = [
              '',
                '',
                  '',
                '
',
                  '
 Edit
',
                  '
 Delete
',
                '
',
              ''
            ];

            controls = controls.join('\n');

            $marginalia_item = $('
').attr({
              class:marginalia_item_class,
              'data-annotation-id': annotation.id
            }).append(controls).append(text);

        $marginalia_item.on('click.marginalia','.btn-edit',function(event){
          event.preventDefault();
          var offset = $(this).parents(".controls").siblings(".text").offset();

          _app.annotations.update(annotation);
          $(".annotator-editor").css({
            top: offset.top,
            left: offset.left
          });
        })
        .on('click.marginalia','.btn-delete',function(event){
          event.preventDefault();
          var del = confirm("Are you sure you want to permanently delete this annoation?");

          if( del === true){
            _app.annotations['delete'](annotation);
          }
        });

        return $marginalia_item;
      },

      // Add annotations to the sidebar when loaded
      annotationsLoaded: function(annotations){
        //show toggle object once annotations are loaded
        $("#"+toggle_id).show();

        var $annotaton_list = $('
').attr({
              class:annotations_list_class
            }),
            $empty = $('
').attr({class:'empty-item'});

          $annotaton_list.append($empty);

        var annotations_array = marginalia.get_annotiations_array();
        // Display annotations in the marginalia container
        $.each(annotations_array,function(i){
          var id = annotations_array[i],
              annotation = $.grep(annotations, function(e){ return e.id == id; })[0],
              $marginalia_item = marginalia.renderAnnotation(annotation);

          $annotaton_list.append($marginalia_item);
        });

        $margin_container.html($annotaton_list);

        $('.margin-container').stop().animate({'scrollTop': parseInt($(".margin-container>.annotation-list").css("padding-top")) - 30 },0);

        // Add class to container to hide marginalia aside
        $container.addClass('margin-container-hide');

        // Initalize on click.marginalia event for annotation highlights
        $('.annotator-hl').on('click.marginalia',function(event){
          marginalia.annotationSelected(event);
        });

        // Initalize on click.marginalia event for Marginalia items
        $('.'+marginalia_item_class).find('.text').on('click.marginalia',function(event){
          marginalia.itemSelected(event);
        });

        // Initalize toggle control for marginalia container
        $('#'+toggle_id).on('click.marginalia',function(event){
          event.preventDefault();
          var $this = $(this);

          if($this.hasClass('active')){
            marginalia.toggle.hide();
            $this.attr({'title':'Show Annotations'});
          }
          else{
            marginalia.toggle.show();
            $this.attr({'title':'Hide Annotations'});
          }
        });

        return true;
      },

      // Add marginalia when annotations are created
      annotationCreated: function(annotation){
        var $marginalia_item = marginalia.renderAnnotation(annotation);

        // Get the index of the annotation in context to its siblings
        var annotations_array = marginalia.get_annotiations_array(),
        index = annotations_array.indexOf(annotation.id);

        // Append to annotations list...
        if(index < $('.'+ marginalia_item_class).length){
          $($('.'+annotations_list_class +' .'+ marginalia_item_class)[index]).before($marginalia_item);
        }
        else{
          $('.'+annotations_list_class).append($marginalia_item);
        }
        // highlight created...
        marginalia.onSelected(annotation.id);
        // and show marginalia container.
        marginalia.toggle.show();

        // re-bind annotation/note click to select to apply to the
        // new highlight and margin note
        $('.annotator-hl').on('click.marginalia',function(event){
          marginalia.annotationSelected(event);
        });
        $('.'+marginalia_item_class).find('.text').on('click.marginalia',function(event){
          marginalia.itemSelected(event);
        });

        return true;
      },

      // Remove marginalia when annotations are removed
      beforeAnnotationDeleted: function(annotation){
        var $marginalia_item = $('.'+marginalia_item_class+'[data-annotation-id='+annotation.id+']');
        $marginalia_item.remove();

        return true;
      },

      // Update marginalia when annotations are updated
      annotationUpdated: function(annotation){
        var $marginalia_item = $('.'+marginalia_item_class+'[data-annotation-id='+annotation.id+']'),
            updated_text = marginalia.render(annotation);

        $marginalia_item.find(".text").html(updated_text);

        return true;
      },

      // Toggle functions for the margin container
      toggle: {

        show: function(){
          $container.addClass('margin-container-show');
          $container.removeClass('margin-container-hide');

          $('#'+toggle_id).addClass('active');

          if(options.toggle.show){
            options.toggle.show();
          }
        },

        hide: function(){
          $container.addClass('margin-container-hide');
          $container.removeClass('margin-container-show');

          $('#'+toggle_id).removeClass('active');

          if(options.toggle.hide){
            options.toggle.hide();
          }
        }
      },

      // Custom event for when an annotation is selected
      // Highlight the marginalia item associated with the annotation
      annotationSelected: function(event) {
        event.stopPropagation();

        var $annotation_highlight = $(event.target),
            annotation_id = $annotation_highlight.data('annotation-id');

        marginalia.onSelected(annotation_id);
      },

      // On Marginalia item select event
      // Highlight the annotation highlight associated with the item
      itemSelected: function(event){
        event.stopPropagation();

        var $marginalia_item = $(event.target).parents('.' + marginalia_item_class),
            annotation_id = $marginalia_item.data('annotation-id');
        marginalia.onSelected(annotation_id);
      },

      clearHighlights: function(){
        $('.marginalia-item-selected').removeClass('marginalia-item-selected');
        $('.marginalia-annotation-selected').removeClass('marginalia-annotation-selected');
      },

      applyHighlights: function($annotation, $item){
        marginalia.clearHighlights();

        $annotation.addClass('marginalia-annotation-selected');
        $item.addClass('marginalia-item-selected');
      },

      onSelected: function(annotation_id){
        var id = annotation_id,
            $annotation = $('.annotator-hl'+'[data-annotation-id='+id+']'),
            $item = $('.' + marginalia_item_class + '[data-annotation-id=' + id + ']' );

        // Return false if the id is undefined
        if(id === undefined){
          return false;
        }

        // Return false if the item is already selected to prevent
        // jumping to the top when highlighting text.
        if ($item.hasClass("marginalia-item-selected")){
            return false;
        }

        $margin_container = $('.'+options.margin_class);

        // Scroll to the position of the item
          var cTop = $('.margin-container').offset().top,
              cScrollTop = $('.margin-container').scrollTop(),
              top = $item.position().top,
              top2;

              // Check if the annotation's parent element is the .inner container,
              // so we can get the correct top position.
              // If the annotation is a direct child of .inner,
              // then get the top postion of the element.
              if($annotation.parent().is('.inner')){
                top2 = $annotation.position().top;
              }
              else{
                top2 = $annotation.parent().position().top;
              }

          $margin_container.stop().animate({'scrollTop':top-top2+30},500,'easeInOutExpo');

        // Highlight selected parts
        marginalia.applyHighlights($annotation, $item);

        // Show marginalia container
        marginalia.toggle.show();

      }
  };
  // return marginalia object
  return marginalia;
}
<commit_msg>Changed calculation of annotation position top<commit_after>/* Marginalia  - margin annotation viewer for annotator */

function annotatorMarginalia(options) {

  var _t = annotator.util.gettext;
  var _app;

  options = options || {};
  // Sets the renderer function for the annotations.
  // Defaults to statard formatting.
  if(options.viewer && typeof options.viewer === 'function'){
    options.viewer = options.viewer;
  }
  else{
    options.viewer = function(annotation){
      if (annotation.text) {
        return annotator.util.escapeHtml(annotation.text);
      } else {
        return "" + _t('No comment') + "";
      }
    };
  }

  options.element = options.element || '.content';
  options.margin_class = options.margin_class || 'margin-container';

  // Container element for annotator
  var $container = $(options.element);

  // Define marginalia annotation container
  var $margin_container = $('').attr({
        class:options.margin_class
      });

  // Marginalia variables
  var marginalia_item_class = 'marginalia-item',
      toggle_id = 'toggle-annotations',
      annotations_list_class = 'annotation-list';

// Easing Function for scroll
// from jQuery Easing Plugin (version 1.3)
// http://gsgd.co.uk/sandbox/jquery/easing/
  jQuery.extend( jQuery.easing,{
    easeInOutExpo: function (x, t, b, c, d) {
      if (t==0) return b;
      if (t==d) return b+c;
      if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
      return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
    }
  });

  // Object for Marginalia
  // Defined as a object for namespacing references (i.e. marginalia.render)
  var marginalia = {
      start: function (app) {
        _app = app;
        var toggle_html ='',
            toggle_attrs = {
              class:'btn btn-green',
              id: toggle_id,
              alt: 'Toggle Annotations',
              title: 'Show Annotations'
            },
            $toggle = $('')
              .attr(toggle_attrs) // add attributes to the toggle object
              .hide() // hide the toggle object for now, will show when annotations are loaded
              .html(toggle_html); //add the html to the toggle object

        $container.prepend($margin_container);

        $(".in-page-controls").append($toggle);

        // get the rendered margin container
        $margin_container = $('.'+options.margin_class);

        return true;
      },

      render: function(annotation){
        return options.viewer(annotation);
      },

      // returns an array of the rendered annotation ids
      get_annotiations_array: function(){
        var $highlights = $('.annotator-hl'),
            highlight_group_annotation = '',
            annotations_array = [];

        $highlights.each(function(){
          var $this = $(this),
              this_annotation = $this.data('annotation-id');

          if( highlight_group_annotation !== this_annotation ){
            highlight_group_annotation = this_annotation;
            annotations_array.push(highlight_group_annotation);
          }
        });

        return annotations_array;
      },

      // Returns the annotion in the marginalia list format
      renderAnnotation: function(annotation){
        var text = $('
').attr({
            class:'text'
            }).html(marginalia.render(annotation)),
            controls = [
              '',
                '',
                  '',
                '
',
                  '
 Edit
',
                  '
 Delete
',
                '
',
              ''
            ];

            controls = controls.join('\n');

            $marginalia_item = $('
').attr({
              class:marginalia_item_class,
              'data-annotation-id': annotation.id
            }).append(controls).append(text);

        $marginalia_item.on('click.marginalia','.btn-edit',function(event){
          event.preventDefault();
          var offset = $(this).parents(".controls").siblings(".text").offset();

          _app.annotations.update(annotation);
          $(".annotator-editor").css({
            top: offset.top,
            left: offset.left
          });
        })
        .on('click.marginalia','.btn-delete',function(event){
          event.preventDefault();
          var del = confirm("Are you sure you want to permanently delete this annoation?");

          if( del === true){
            _app.annotations['delete'](annotation);
          }
        });

        return $marginalia_item;
      },

      // Add annotations to the sidebar when loaded
      annotationsLoaded: function(annotations){
        //show toggle object once annotations are loaded
        $("#"+toggle_id).show();

        var $annotaton_list = $('
').attr({
              class:annotations_list_class
            }),
            $empty = $('
').attr({class:'empty-item'});

          $annotaton_list.append($empty);

        var annotations_array = marginalia.get_annotiations_array();
        // Display annotations in the marginalia container
        $.each(annotations_array,function(i){
          var id = annotations_array[i],
              annotation = $.grep(annotations, function(e){ return e.id == id; })[0],
              $marginalia_item = marginalia.renderAnnotation(annotation);

          $annotaton_list.append($marginalia_item);
        });

        $margin_container.html($annotaton_list);

        $('.margin-container').stop().animate({'scrollTop': parseInt($(".margin-container>.annotation-list").css("padding-top")) - 30 },0);

        // Add class to container to hide marginalia aside
        $container.addClass('margin-container-hide');

        // Initalize on click.marginalia event for annotation highlights
        $('.annotator-hl').on('click.marginalia',function(event){
          marginalia.annotationSelected(event);
        });

        // Initalize on click.marginalia event for Marginalia items
        $('.'+marginalia_item_class).find('.text').on('click.marginalia',function(event){
          marginalia.itemSelected(event);
        });

        // Initalize toggle control for marginalia container
        $('#'+toggle_id).on('click.marginalia',function(event){
          event.preventDefault();
          var $this = $(this);

          if($this.hasClass('active')){
            marginalia.toggle.hide();
            $this.attr({'title':'Show Annotations'});
          }
          else{
            marginalia.toggle.show();
            $this.attr({'title':'Hide Annotations'});
          }
        });

        return true;
      },

      // Add marginalia when annotations are created
      annotationCreated: function(annotation){
        var $marginalia_item = marginalia.renderAnnotation(annotation);

        // Get the index of the annotation in context to its siblings
        var annotations_array = marginalia.get_annotiations_array(),
        index = annotations_array.indexOf(annotation.id);

        // Append to annotations list...
        if(index < $('.'+ marginalia_item_class).length){
          $($('.'+annotations_list_class +' .'+ marginalia_item_class)[index]).before($marginalia_item);
        }
        else{
          $('.'+annotations_list_class).append($marginalia_item);
        }
        // highlight created...
        marginalia.onSelected(annotation.id);
        // and show marginalia container.
        marginalia.toggle.show();

        // re-bind annotation/note click to select to apply to the
        // new highlight and margin note
        $('.annotator-hl').on('click.marginalia',function(event){
          marginalia.annotationSelected(event);
        });
        $('.'+marginalia_item_class).find('.text').on('click.marginalia',function(event){
          marginalia.itemSelected(event);
        });

        return true;
      },

      // Remove marginalia when annotations are removed
      beforeAnnotationDeleted: function(annotation){
        var $marginalia_item = $('.'+marginalia_item_class+'[data-annotation-id='+annotation.id+']');
        $marginalia_item.remove();

        return true;
      },

      // Update marginalia when annotations are updated
      annotationUpdated: function(annotation){
        var $marginalia_item = $('.'+marginalia_item_class+'[data-annotation-id='+annotation.id+']'),
            updated_text = marginalia.render(annotation);

        $marginalia_item.find(".text").html(updated_text);

        return true;
      },

      // Toggle functions for the margin container
      toggle: {

        show: function(){
          $container.addClass('margin-container-show');
          $container.removeClass('margin-container-hide');

          $('#'+toggle_id).addClass('active');

          if(options.toggle.show){
            options.toggle.show();
          }
        },

        hide: function(){
          $container.addClass('margin-container-hide');
          $container.removeClass('margin-container-show');

          $('#'+toggle_id).removeClass('active');

          if(options.toggle.hide){
            options.toggle.hide();
          }
        }
      },

      // Custom event for when an annotation is selected
      // Highlight the marginalia item associated with the annotation
      annotationSelected: function(event) {
        event.stopPropagation();

        var $annotation_highlight = $(event.target),
            annotation_id = $annotation_highlight.data('annotation-id');

        marginalia.onSelected(annotation_id);
      },

      // On Marginalia item select event
      // Highlight the annotation highlight associated with the item
      itemSelected: function(event){
        event.stopPropagation();

        var $marginalia_item = $(event.target).parents('.' + marginalia_item_class),
            annotation_id = $marginalia_item.data('annotation-id');
        marginalia.onSelected(annotation_id);
      },

      clearHighlights: function(){
        $('.marginalia-item-selected').removeClass('marginalia-item-selected');
        $('.marginalia-annotation-selected').removeClass('marginalia-annotation-selected');
      },

      applyHighlights: function($annotation, $item){
        marginalia.clearHighlights();

        $annotation.addClass('marginalia-annotation-selected');
        $item.addClass('marginalia-item-selected');
      },

      onSelected: function(annotation_id){
        var id = annotation_id,
            $annotation = $('.annotator-hl'+'[data-annotation-id='+id+']'),
            $item = $('.' + marginalia_item_class + '[data-annotation-id=' + id + ']' );

        // Return false if the id is undefined
        if(id === undefined){
          return false;
        }

        // Return false if the item is already selected to prevent
        // jumping to the top when highlighting text.
        if ($item.hasClass("marginalia-item-selected")){
            return false;
        }

        $margin_container = $('.'+options.margin_class);

        // Scroll to the position of the item
          var cTop = $('.margin-container').offset().top,
              cScrollTop = $('.margin-container').scrollTop(),
              top = $item.position().top,
              top2 = $annotation.parents('.inner>div');

              // If the annotation is wrapped in a child div,
              // we want to get the postion of that parent element.
              if( top2.length>0 ){
                top2 = top2.position().top;
              }
              // Otherwise, get the top position of the element.
              else{
                top2 = $annotation.position().top;
              }

          $margin_container.stop().animate({'scrollTop':top-top2+30},500,'easeInOutExpo');

        // Highlight selected parts
        marginalia.applyHighlights($annotation, $item);

        // Show marginalia container
        marginalia.toggle.show();

      }
  };
  // return marginalia object
  return marginalia;
}
<|endoftext|>


<commit_before>// ==UserScript==
// @name           Craigslist Filter
// @version        0.1.1
// @namespace      http://niw.at/
// @description    Filtering the reuslt of Craigslist
// @include        http://sfbay.craigslist.org/*apa*
// @include        http://sfbay.craigslist.org/*roo*
// ==/UserScript==

!function() {
  "use strict"

  var
  // exclude keywords in regular expression (examples)
  EXCLUDE_TITLE_KEYWORDS     = /(sunset|ingleside|tenderloin|excelsior)/i,
  EXCLUDE_CONTENT_KEYWORDS   = /(TMS333|3333|Redstone Properties|Triniy)/gi,
  // highlighted keywords in regular expression (examples)
  HIGHLIGHT_CONTENT_KEYWORDS = /(washer|dryer|in unit|w\/d|parking|garage)/gi,
  // range of budget
  MAX_RATE = 3500,
  MIN_RATE = 1000,

  arrayEach = function(a, f) {
    for(var i = 0, l = a.length; i < l; i++) {
      f(a[i])
    }
  },
  insertNext = function(h, a) {
    h.parentNode.insertBefore(a, h.nextSibling)
  },
  removeTag = function(a) {
    a.parentNode.removeChild(a)
  },
  getText = function(elems) {
    var ret = ""
    for(var i = 0; elems[i]; i++){
      var e = elems[i]
      if(e.nodeType === 3 || e.nodeType === 4) {
        ret += e.nodeValue
      } else if(e.nodeType !== 8) {
        ret += getText(e.childNodes)
      }
    }
    return ret
  },
  xmlHttpRequest = function(option) {
    var xmlhttp = new XMLHttpRequest()
    xmlhttp.onreadystatechange = function() {
      if(xmlhttp.readyState === 4 && option['onload']) {
        option['onload'].call(this, xmlhttp)
      }
    }
    xmlhttp.open(option['method'], option['url'], true)
    xmlhttp.send(option['data'])
    return xmlhttp
  },
  xpath = function(xpath, context) {
    var result = [],
        elements = document.evaluate(xpath, context, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
    for(var i = 0, l = elements.snapshotLength; i < l; i++) {
      result.push(elements.snapshotItem(i))
    }
    return result
  },
  strikeTag = function(e) {
    return function(s) {
      s.setAttribute("style", "color: #ccc; text-decoration: line-through;")
      e.parentNode.insertBefore(s, e)
      s.appendChild(e)
      arrayEach(xpath(".//a", e), function(a) {
        a.setAttribute("style", "color: #ccc;")
      })
      return s
    }(document.createElement("span"))
  },
  addStatusTag = function(e, html, color) {
    var colors = {
        gray: "color: #333; background: #eee; border-color: #ccc;",
        blue: "color: #27b; background: #def; border-color: #379;"
      },
      style = "font-size: 10px; margin: 0 5px; border: 1px solid;"
    return function(s) {
      s.setAttribute("style", style + (colors[color] || colors["gray"]))
      if(html) {
        s.innerHTML = html
      }
      insertNext(e, s)
      return s
    }(document.createElement("span"))
  },
  expandTag = function(anchor_tag) {
    var line_tag = anchor_tag.parentNode,
        status_tag = addStatusTag(anchor_tag, "Loading...")
    xmlHttpRequest({method: "GET", url: anchor_tag.getAttribute("href"), onload: function(http) {
      var html = document.createElement("div")
      html.innerHTML = http.responseText

      var content = getText(xpath(".//div[@id='userbody']", html)), m
      if(m = content.match(EXCLUDE_CONTENT_KEYWORDS)) {
        status_tag.innerHTML = m.join(", ")
        strikeTag(line_tag)
        return
      }
      if(m = content.match(HIGHLIGHT_CONTENT_KEYWORDS)) {
        addStatusTag(anchor_tag, m.join(", "), "blue")
      }

      var inline_tag = document.createElement("div")
      inline_tag.setAttribute("style", "margin-left: 50px; background: #eee; padding: 2px; font-size: 10px; font-family: sans-serif;")

      if(xpath(".//img", html).length === 0) {
        status_tag.innerHTML = "No Images"
        inline_tag.innerHTML = content
      } else {
        var img_tags = xpath(".//img[contains(@alt, 'image ') or contains(@src, 'http://www.postlets.com/create/photos/')]", html)
        arrayEach(img_tags, function(tag) {
          var parent_tag = tag.parentNode,
              href = parent_tag.getAttribute("href")
          if(href && href.match(/\.(jpg|jpeg|png)$/)) {
            tag.setAttribute("src", href)
          }
          tag.setAttribute("height", "120px")
          tag.setAttribute("width", "120px")
          tag.setAttribute("style", "")
          inline_tag.appendChild(tag)
        })
        removeTag(status_tag)
      }

      if(inline_tag.childNodes.length) {
        line_tag.appendChild(inline_tag)
      }
    }})
  }

  arrayEach(xpath("./blockquote/p/a", document.body), function(anchor_tag) {
    var line_tag = anchor_tag.parentNode,
        title = getText([line_tag]),
        m = title.match(/\$([0-9]+)/),
        rate = m ? parseInt(m[1]) : 0
    if(title.match(EXCLUDE_TITLE_KEYWORDS) || rate > MAX_RATE || rate <= MIN_RATE) {
      strikeTag(line_tag)
    } else {
      expandTag(anchor_tag)
    }
  })
}();
<commit_msg>FIX: address some cases can't pick image correctly.<commit_after>// ==UserScript==
// @name           Craigslist Filter
// @version        0.1.1
// @namespace      http://niw.at/
// @description    Filtering the reuslt of Craigslist
// @include        http://sfbay.craigslist.org/*apa*
// @include        http://sfbay.craigslist.org/*roo*
// ==/UserScript==

!function() {
  "use strict"

  var
  // exclude keywords in regular expression (examples)
  EXCLUDE_TITLE_KEYWORDS     = /(sunset|ingleside|tenderloin|excelsior)/i,
  EXCLUDE_CONTENT_KEYWORDS   = /(TMS333|3333|Redstone Properties|Triniy)/gi,
  // highlighted keywords in regular expression (examples)
  HIGHLIGHT_CONTENT_KEYWORDS = /(washer|dryer|in unit|w\/d|parking|garage)/gi,
  // range of budget
  MAX_RATE = 3500,
  MIN_RATE = 1000,

  arrayEach = function(a, f) {
    for(var i = 0, l = a.length; i < l; i++) {
      f(a[i])
    }
  },
  insertNext = function(h, a) {
    h.parentNode.insertBefore(a, h.nextSibling)
  },
  removeTag = function(a) {
    a.parentNode.removeChild(a)
  },
  getText = function(elems) {
    var ret = ""
    for(var i = 0; elems[i]; i++){
      var e = elems[i]
      if(e.nodeType === 3 || e.nodeType === 4) {
        ret += e.nodeValue
      } else if(e.nodeType !== 8) {
        ret += getText(e.childNodes)
      }
    }
    return ret
  },
  xmlHttpRequest = function(option) {
    var xmlhttp = new XMLHttpRequest()
    xmlhttp.onreadystatechange = function() {
      if(xmlhttp.readyState === 4 && option['onload']) {
        option['onload'].call(this, xmlhttp)
      }
    }
    xmlhttp.open(option['method'], option['url'], true)
    xmlhttp.send(option['data'])
    return xmlhttp
  },
  xpath = function(xpath, context) {
    var result = [],
        elements = document.evaluate(xpath, context, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
    for(var i = 0, l = elements.snapshotLength; i < l; i++) {
      result.push(elements.snapshotItem(i))
    }
    return result
  },
  strikeTag = function(e) {
    return function(s) {
      s.setAttribute("style", "color: #ccc; text-decoration: line-through;")
      e.parentNode.insertBefore(s, e)
      s.appendChild(e)
      arrayEach(xpath(".//a", e), function(a) {
        a.setAttribute("style", "color: #ccc;")
      })
      return s
    }(document.createElement("span"))
  },
  addStatusTag = function(e, html, color) {
    var colors = {
        gray: "color: #333; background: #eee; border-color: #ccc;",
        blue: "color: #27b; background: #def; border-color: #379;"
      },
      style = "font-size: 10px; margin: 0 5px; border: 1px solid;"
    return function(s) {
      s.setAttribute("style", style + (colors[color] || colors["gray"]))
      if(html) {
        s.innerHTML = html
      }
      insertNext(e, s)
      return s
    }(document.createElement("span"))
  },
  expandTag = function(anchor_tag) {
    var line_tag = anchor_tag.parentNode,
        status_tag = addStatusTag(anchor_tag, "Loading...")
    xmlHttpRequest({method: "GET", url: anchor_tag.getAttribute("href"), onload: function(http) {
      var html = document.createElement("div")
      html.innerHTML = http.responseText

      var content = getText(xpath(".//div[@id='userbody']", html)), m
      if(m = content.match(EXCLUDE_CONTENT_KEYWORDS)) {
        status_tag.innerHTML = m.join(", ")
        strikeTag(line_tag)
        return
      }
      if(m = content.match(HIGHLIGHT_CONTENT_KEYWORDS)) {
        addStatusTag(anchor_tag, m.join(", "), "blue")
      }

      var inline_tag = document.createElement("div")
      inline_tag.setAttribute("style", "margin-left: 50px; background: #eee; padding: 2px; font-size: 10px; font-family: sans-serif;")

      if(xpath(".//img", html).length === 0) {
        status_tag.innerHTML = "No Images"
        inline_tag.innerHTML = content
      } else {
        var img_tags = xpath(".//img[contains(@alt, 'image ') or contains(@src, 'http://www.postlets.com/create/photos/') or contains(@src, 'IMG_')]", html)
        arrayEach(img_tags, function(tag) {
          var parent_tag = tag.parentNode,
              href = parent_tag.getAttribute("href")
          if(href && parent_tag["onclick"] && href.match(/\.(jpg|jpeg|png)$/)) {
            tag.setAttribute("src", href)
          }
          tag.setAttribute("height", "120px")
          tag.setAttribute("width", "120px")
          tag.setAttribute("style", "")
          inline_tag.appendChild(tag)
        })
        removeTag(status_tag)
      }

      if(inline_tag.childNodes.length) {
        line_tag.appendChild(inline_tag)
      }
    }})
  }

  arrayEach(xpath("./blockquote/p/a", document.body), function(anchor_tag) {
    var line_tag = anchor_tag.parentNode,
        title = getText([line_tag]),
        m = title.match(/\$([0-9]+)/),
        rate = m ? parseInt(m[1]) : 0
    if(title.match(EXCLUDE_TITLE_KEYWORDS) || rate > MAX_RATE || rate <= MIN_RATE) {
      strikeTag(line_tag)
    } else {
      expandTag(anchor_tag)
    }
  })
}();
<|endoftext|>


<commit_before>/**
 * Welcome to Pebble.js!
 *
 * This is where you write your app.
 */

var UI = require('ui');

var title = new UI.Card({
  title: 'PokePebble',
  banner: 'images/LogoPS.png',
  body: 'A Pebble client for Pokemon showdown. Press SELECT to begin.'
});

title.show();

// TODO: Log in

title.on('click', 'select', function (e) {
  var searching = new UI.Card();
  searching.title('Searching for an opponent.');
  searching.body('Press BACK to cancel.');
  searching.show();
  // TODO: Search for an opponent
  searching.on('click', 'back', function (e) {
    // TODO: cancel search
    title.show();
  });
});
<commit_msg>More websockets stuff<commit_after>/**
 * Welcome to Pebble.js!
 *
 * This is where you write your app.
 */

var UI = require('ui');
var ajax = require('ajax');

var title = new UI.Card({
  title: 'PokePebble',
  banner: 'images/LogoPS.png',
  body: 'A Pebble client for Pokemon showdown. Press SELECT to begin.'
});

title.show();

// Login
var ws = new WebSocket("ws://159.203.89.223:8000/showdown/websocket");
var username;
var challstr;
var currRoom = null;
ws.onmessage = function (e) {
  // Parse message
  var message = e.data;
  console.log(message);
  if (currRoom) {
    // Parse battle messages
  } else {
    if (cmd[0] === '>') {
      currRoom = cmd.slice(1);
      return;
    }
    var args = message.split("|");
    var cmd = args[1];
    if (cmd === 'updateuser') {
      // Update username
      username = args[2];
      console.log("Username is", username);
    } else if (cmd === 'challstr') {
      // Get login information
      challstr = message.match(/\|challstr\|(.*)/)[1];
      console.log("Challstr is", challstr);
    }
  }
};

ws.onerror = function (error) {
  // Log error
  console.log("Error:", error);
};

title.on('click', 'back', function (e) {
  // Logout
  ws.close();
});

title.on('click', 'select', function (e) {
  var searching = new UI.Card();
  searching.title('Searching for an opponent.');
  searching.body('Press BACK to cancel.');
  searching.show();
  // Search for an opponent
  ws.send("|/search randombattle");
  console.log("Searching for a battle");
  searching.on('click', 'back', function (e) {
    // Cancel search
    ws.send("|/cancelsearch");
    console.log("Canceling search");
    title.show();
  });
});
<|endoftext|>


<commit_before>(function () {
    'use strict';

    var baseContourVersion =  '0.9.107';
    var contourVersion;
    var samples = [
        "area/area-basic",
        "area/area-combo",
        "area/area-stacked",
        "bar/bar-basic",
        "bar/bar-export",
        "bar/bar-grouped",
        "bar/bar-stacked",
        "bar/bar-styled",
        "bar/bar-image",
        "column/column-basic",
        "column/column-styled",
        "column/column-grouped",
        "column/column-width",
        "column/column-stacked",
        "line/line-basic",
        "line/line-markers",
        "line/line-dates",
        "line/line-export",
        "line/line-multi-basic",
        "line/line-sine",
        "pie/pie-basic",
        "pie/pie-donut",
        "pie/pie-gauge",
        "pie/pie-series",
        "pie/donut-series",
        "scatter/scatter-basic",
        "scatter/scatter-export",
        "scatter/scatter-trendline"
    ];

    contourVersion = getContourVersion();
    buildMenu(samples);
    doRouting();

    function getContourVersion() {
        if (!/ver=/.test(window.location.search)) {
            return baseContourVersion;
        }

        var version = window.location.search.match(/ver=(\d+\.\d+\.\d+)/);
        return version[1] || baseContourVersion;
    }

    function onSampleLoad() {
        var height = $(this.contentDocument).height();
        $(this).height(height);
    }

    function doRouting() {
        var hash = document.location.hash.replace('#', '');
        if (hash.length) {
            loadSamples(hash, onSampleLoad);
        }
    }

    function buildMenu(data) {
        var items = [];
        var curPalette = 'palette-1';

        $.each(data, function (i, d) {
            var li = $('<li>').text(d).attr('data-path', d);
            items.push(li);
        });

        var ul = $('<ul>').addClass('list-unstyled');
        ul.append(items).appendTo('.menu');
        ul.on('click', 'li', function () {
            var path = $(this).data('path');
            document.location.hash = '#/' + path;
            loadSamples(path);
        });

        $('.palette-selector').on('change', function () {
            var iframe = d3.select('iframe').node();
            var newPalette = 'palette-' + $(this).val();

            d3.select(iframe.contentDocument)
                .selectAll('.series')
                    .classed(curPalette, false)
                    .classed(newPalette, true);

            curPalette = newPalette;
        });
    }

    function loadSamples(path, onLoad) {
        var fullPath = 'showcase/' + path;
        var frame = $('#sample');

        $('.chart-id').text(path);

        $.get(fullPath + '/demo.html', function (res) {
            var iframe = frame.get(0);
            var contents = [];
            var doc;

            if (iframe.contentDocument) {
                doc = iframe.contentDocument;
            } else if (iframe.contentWindow) {
                doc = iframe.contentWindow.document;
            } else {
                doc = iframe.document;
            }

            // set up the onload callback... this is where the caller can resize the iframe
            $(iframe).on('load', onLoad);

            // now we start adding stuff
            // add jquery and the demo css to the head first
            contents.push('<script src="../examples/js/vendor/jquery.js"></script>');

            // force a specific contour version
            res = res.replace(/(https?:\/\/forio\.com\/tools\/contour\/)([\w\d\.\-\_]+)/g, function ($1, $2, $3) {
                return $2 + contourVersion + '/' + $3;
            });

            // now add the html
            contents.push(res);

            // add the css after the html so we get the demo.css to have priority over
            // the default contour.css
            contents.push('<link rel="stylesheet" href="' + fullPath + '/demo.css">');
            contents.push('<script src="' + fullPath + '/demo.js"></script>');

            // now write everything the iframes document
            doc.open();
            doc.writeln(contents.join(''));
            doc.close();
        });
    }

})();
<commit_msg>Added ability to use the local contour version with the sample viewer using query ?local-ver<commit_after>(function () {
    'use strict';

    var baseContourVersion =  '0.9.107';
    var contourVersion;
    var samples = [
        "area/area-basic",
        "area/area-combo",
        "area/area-stacked",
        "bar/bar-basic",
        "bar/bar-export",
        "bar/bar-grouped",
        "bar/bar-stacked",
        "bar/bar-styled",
        "bar/bar-image",
        "column/column-basic",
        "column/column-styled",
        "column/column-grouped",
        "column/column-width",
        "column/column-stacked",
        "line/line-basic",
        "line/line-markers",
        "line/line-dates",
        "line/line-export",
        "line/line-multi-basic",
        "line/line-sine",
        "pie/pie-basic",
        "pie/pie-donut",
        "pie/pie-gauge",
        "pie/pie-series",
        "pie/donut-series",
        "scatter/scatter-basic",
        "scatter/scatter-export",
        "scatter/scatter-trendline"
    ];

    contourVersion = getContourVersion();
    buildMenu(samples);
    doRouting();

    function getContourVersion() {
        if (!/ver=/.test(window.location.search)) {
            return baseContourVersion;
        }

        var version = window.location.search.match(/ver=(\d+\.\d+\.\d+)/);
        return version[1] || baseContourVersion;
    }

    function onSampleLoad() {
        var height = $(this.contentDocument).height();
        $(this).height(height);
    }

    function doRouting() {
        var hash = document.location.hash.replace('#', '');
        if (hash.length) {
            loadSamples(hash, onSampleLoad);
        }
    }

    function buildMenu(data) {
        var items = [];
        var curPalette = 'palette-1';

        $.each(data, function (i, d) {
            var li = $('<li>').text(d).attr('data-path', d);
            items.push(li);
        });

        var ul = $('<ul>').addClass('list-unstyled');
        ul.append(items).appendTo('.menu');
        ul.on('click', 'li', function () {
            var path = $(this).data('path');
            document.location.hash = '#/' + path;
            loadSamples(path);
        });

        $('.palette-selector').on('change', function () {
            var iframe = d3.select('iframe').node();
            var newPalette = 'palette-' + $(this).val();

            d3.select(iframe.contentDocument)
                .selectAll('.series')
                    .classed(curPalette, false)
                    .classed(newPalette, true);

            curPalette = newPalette;
        });
    }

    function loadSamples(path, onLoad) {
        var fullPath = 'showcase/' + path;
        var frame = $('#sample');

        $('.chart-id').text(path);

        $.get(fullPath + '/demo.html', function (res) {
            var iframe = frame.get(0);
            var contents = [];
            var doc;

            if (iframe.contentDocument) {
                doc = iframe.contentDocument;
            } else if (iframe.contentWindow) {
                doc = iframe.contentWindow.document;
            } else {
                doc = iframe.document;
            }

            // set up the onload callback... this is where the caller can resize the iframe
            $(iframe).on('load', onLoad);

            // now we start adding stuff
            // add jquery and the demo css to the head first
            contents.push('<script src="../examples/js/vendor/jquery.js"></script>');

            // force a specific contour version
            res = res.replace(/(https?:\/\/forio\.com\/tools\/contour\/)([\w\d\.\-\_]+)/g, function ($1, $2, $3) {
                if (/local-ver/.test(window.location.href)) {
                    return '/dist/' + $3;
                }

                return $2 + contourVersion + '/' + $3;
            });

            // now add the html
            contents.push(res);

            // add the css after the html so we get the demo.css to have priority over
            // the default contour.css
            contents.push('<link rel="stylesheet" href="' + fullPath + '/demo.css">');
            contents.push('<script src="' + fullPath + '/demo.js"></script>');

            // now write everything the iframes document
            doc.open();
            doc.writeln(contents.join(''));
            doc.close();
        });
    }

})();
<|endoftext|>


<commit_before>import React, { createElement } from "react"
import pageFinderFactory from "./find-page"
import emitter from "./emitter"
let findPage

let syncRequires = {}
let asyncRequires = {}
let pathScriptsCache = {}
let resourceStrCache = {}
let resourceCache = {}
let pages = []
// Note we're not actively using the path data atm. There
// could be future optimizations however around trying to ensure
// we load all resources for likely-to-be-visited paths.
let pathArray = []
let pathCount = {}
let resourcesArray = []
let resourcesCount = {}
const preferDefault = m => (m && m.default) || m
let prefetcher
let inInitialRender = true

// Prefetcher logic
if (process.env.NODE_ENV === `production`) {
  prefetcher = require(`./prefetcher`)({
    getNextQueuedResources: () => resourcesArray.slice(-1)[0],
    createResourceDownload: resourceName => {
      fetchResource(resourceName, () => {
        resourcesArray = resourcesArray.filter(r => r !== resourceName)
        prefetcher.onResourcedFinished(resourceName)
      })
    },
  })
  emitter.on(`onPreLoadPageResources`, e => {
    prefetcher.onPreLoadPageResources(e)
  })
  emitter.on(`onPostLoadPageResources`, e => {
    prefetcher.onPostLoadPageResources(e)
  })
}

const sortResourcesByCount = (a, b) => {
  if (resourcesCount[a] > resourcesCount[b]) {
    return 1
  } else if (resourcesCount[a] < resourcesCount[b]) {
    return -1
  } else {
    return 0
  }
}

const sortPagesByCount = (a, b) => {
  if (pathCount[a] > pathCount[b]) {
    return 1
  } else if (pathCount[a] < pathCount[b]) {
    return -1
  } else {
    return 0
  }
}

const fetchResource = (resourceName, cb = () => {}) => {
  if (resourceStrCache[resourceName]) {
    process.nextTick(() => {
      cb(null, resourceStrCache[resourceName])
    })
  } else {
    // Find resource
    const resourceFunction =
      resourceName.slice(0, 12) === `component---`
        ? asyncRequires.components[resourceName] ||
          asyncRequires.layouts[resourceName]
        : asyncRequires.json[resourceName]

    // Download the resource
    resourceFunction((err, executeChunk) => {
      resourceStrCache[resourceName] = executeChunk
      cb(err, executeChunk)
    })
  }
}

const getResourceModule = (resourceName, cb) => {
  if (resourceCache[resourceName]) {
    process.nextTick(() => {
      cb(null, resourceCache[resourceName])
    })
  } else {
    fetchResource(resourceName, (err, executeChunk) => {
      if (err) {
        cb(err)
      } else {
        const module = preferDefault(executeChunk())
        resourceCache[resourceName] = module
        cb(err, module)
      }
    })
  }
}

let mountOrder = 1
const queue = {
  empty: () => {
    pathArray = []
    pathCount = {}
    resourcesCount = {}
    resourcesArray = []
    pages = []
  },
  addPagesArray: newPages => {
    pages = newPages
    let pathPrefix = ``
    if (typeof __PREFIX_PATHS__ !== `undefined`) {
      pathPrefix = __PATH_PREFIX__
    }
    findPage = pageFinderFactory(newPages, pathPrefix)
  },
  addDevRequires: devRequires => {
    syncRequires = devRequires
  },
  addProdRequires: prodRequires => {
    asyncRequires = prodRequires
  },
  dequeue: path => pathArray.pop(),
  enqueue: path => {
    // Check page exists.
    if (!pages.some(p => p.path === path)) {
      return false
    }

    const mountOrderBoost = 1 / mountOrder
    mountOrder += 1
    // console.log(
    // `enqueue "${path}", mountOrder: "${mountOrder}, mountOrderBoost: ${mountOrderBoost}`
    // )

    // Add to path counts.
    if (!pathCount[path]) {
      pathCount[path] = 1
    } else {
      pathCount[path] += 1
    }

    // Add path to queue.
    if (!queue.has(path)) {
      pathArray.unshift(path)
    }

    // Sort pages by pathCount
    pathArray.sort(sortPagesByCount)

    // Add resources to queue.
    const page = findPage(path)
    if (page.jsonName) {
      if (!resourcesCount[page.jsonName]) {
        resourcesCount[page.jsonName] = 1 + mountOrderBoost
      } else {
        resourcesCount[page.jsonName] += 1 + mountOrderBoost
      }

      // Before adding, checking that the JSON resource isn't either
      // already queued or been downloading.
      if (
        resourcesArray.indexOf(page.jsonName) === -1 &&
        !resourceStrCache[page.jsonName]
      ) {
        resourcesArray.unshift(page.jsonName)
      }
    }
    if (page.componentChunkName) {
      if (!resourcesCount[page.componentChunkName]) {
        resourcesCount[page.componentChunkName] = 1 + mountOrderBoost
      } else {
        resourcesCount[page.componentChunkName] += 1 + mountOrderBoost
      }

      // Before adding, checking that the component resource isn't either
      // already queued or been downloading.
      if (
        resourcesArray.indexOf(page.componentChunkName) === -1 &&
        !resourceStrCache[page.jsonName]
      ) {
        resourcesArray.unshift(page.componentChunkName)
      }
    }

    // Sort resources by resourcesCount.
    resourcesArray.sort(sortResourcesByCount)
    if (process.env.NODE_ENV === `production`) {
      prefetcher.onNewResourcesAdded()
    }

    return true
  },
  getResources: () => {
    return {
      resourcesArray,
      resourcesCount,
    }
  },
  getPages: () => {
    return {
      pathArray,
      pathCount,
    }
  },
  getPage: pathname => findPage(pathname),
  has: path => pathArray.some(p => p === path),
  getResourcesForPathname: (path, cb = () => {}) => {
    if (
      inInitialRender &&
      navigator &&
      navigator.serviceWorker &&
      navigator.serviceWorker.controller &&
      navigator.serviceWorker.controller.state === `activated`
    ) {
      // If we're loading from a service worker (it's already activated on
      // this initial render) and we can't find a page, there's a good chance
      // we're on a new page that this (now old) service worker doesn't know
      // about so we'll unregister it and reload.
      if (!findPage(path)) {
        navigator.serviceWorker
          .getRegistrations()
          .then(function(registrations) {
            for (let registration of registrations) {
              registration.unregister()
            }
            window.location.reload()
          })
      }
    }
    inInitialRender = false
    // In development we know the code is loaded already
    // so we just return with it immediately.
    if (process.env.NODE_ENV !== `production`) {
      const page = findPage(path)
      if (!page) return cb()
      const pageResources = {
        component: syncRequires.components[page.componentChunkName],
        json: syncRequires.json[page.jsonName],
        layout: syncRequires.layouts[page.layoutComponentChunkName],
        page,
      }
      cb(pageResources)
      return pageResources
      // Production code path
    } else {
      const page = findPage(path)

      if (!page) {
        console.log(`A page wasn't found for "${path}"`)
        return
      }

      // Use the path from the page so the pathScriptsCache uses
      // the normalized path.
      path = page.path

      // Check if it's in the cache already.
      if (pathScriptsCache[path]) {
        process.nextTick(() => {
          cb(pathScriptsCache[path])
          emitter.emit(`onPostLoadPageResources`, {
            page,
            pageResources: pathScriptsCache[path],
          })
        })
        return pathScriptsCache[path]
      }

      emitter.emit(`onPreLoadPageResources`, { path })
      // Nope, we need to load resource(s)
      let component
      let json
      let layout
      // Load the component/json/layout and parallel and call this
      // function when they're done loading. When both are loaded,
      // we move on.
      const done = () => {
        if (component && json && (!page.layoutComponentChunkName || layout)) {
          pathScriptsCache[path] = { component, json, layout }
          const pageResources = { component, json, layout }
          cb(pageResources)
          emitter.emit(`onPostLoadPageResources`, {
            page,
            pageResources,
          })
        }
      }
      getResourceModule(page.componentChunkName, (err, c) => {
        if (err) {
          console.log(`Loading the component for ${page.path} failed`)
        }
        component = c
        done()
      })
      getResourceModule(page.jsonName, (err, j) => {
        if (err) {
          console.log(`Loading the JSON for ${page.path} failed`)
        }
        json = j
        done()
      })

      page.layoutComponentChunkName &&
        getResourceModule(page.layoutComponentChunkName, (err, l) => {
          if (err) {
            console.log(`Loading the Layout for ${page.path} failed`)
          }
          layout = l
          done()
        })

      return undefined
    }
  },
  peek: path => pathArray.slice(-1)[0],
  length: () => pathArray.length,
  indexOf: path => pathArray.length - pathArray.indexOf(path) - 1,
}

module.exports = queue
<commit_msg>Update loader.js (#2506)<commit_after>import React, { createElement } from "react"
import pageFinderFactory from "./find-page"
import emitter from "./emitter"
let findPage

let syncRequires = {}
let asyncRequires = {}
let pathScriptsCache = {}
let resourceStrCache = {}
let resourceCache = {}
let pages = []
// Note we're not actively using the path data atm. There
// could be future optimizations however around trying to ensure
// we load all resources for likely-to-be-visited paths.
let pathArray = []
let pathCount = {}
let resourcesArray = []
let resourcesCount = {}
const preferDefault = m => (m && m.default) || m
let prefetcher
let inInitialRender = true

// Prefetcher logic
if (process.env.NODE_ENV === `production`) {
  prefetcher = require(`./prefetcher`)({
    getNextQueuedResources: () => resourcesArray.slice(-1)[0],
    createResourceDownload: resourceName => {
      fetchResource(resourceName, () => {
        resourcesArray = resourcesArray.filter(r => r !== resourceName)
        prefetcher.onResourcedFinished(resourceName)
      })
    },
  })
  emitter.on(`onPreLoadPageResources`, e => {
    prefetcher.onPreLoadPageResources(e)
  })
  emitter.on(`onPostLoadPageResources`, e => {
    prefetcher.onPostLoadPageResources(e)
  })
}

const sortResourcesByCount = (a, b) => {
  if (resourcesCount[a] > resourcesCount[b]) {
    return 1
  } else if (resourcesCount[a] < resourcesCount[b]) {
    return -1
  } else {
    return 0
  }
}

const sortPagesByCount = (a, b) => {
  if (pathCount[a] > pathCount[b]) {
    return 1
  } else if (pathCount[a] < pathCount[b]) {
    return -1
  } else {
    return 0
  }
}

const fetchResource = (resourceName, cb = () => {}) => {
  if (resourceStrCache[resourceName]) {
    process.nextTick(() => {
      cb(null, resourceStrCache[resourceName])
    })
  } else {
    // Find resource
    const resourceFunction =
      resourceName.slice(0, 12) === `component---`
        ? asyncRequires.components[resourceName] ||
          asyncRequires.layouts[resourceName]
        : asyncRequires.json[resourceName]

    // Download the resource
    resourceFunction((err, executeChunk) => {
      resourceStrCache[resourceName] = executeChunk
      cb(err, executeChunk)
    })
  }
}

const getResourceModule = (resourceName, cb) => {
  if (resourceCache[resourceName]) {
    process.nextTick(() => {
      cb(null, resourceCache[resourceName])
    })
  } else {
    fetchResource(resourceName, (err, executeChunk) => {
      if (err) {
        cb(err)
      } else {
        const module = preferDefault(executeChunk())
        resourceCache[resourceName] = module
        cb(err, module)
      }
    })
  }
}

let mountOrder = 1
const queue = {
  empty: () => {
    pathArray = []
    pathCount = {}
    resourcesCount = {}
    resourcesArray = []
    pages = []
  },
  addPagesArray: newPages => {
    pages = newPages
    let pathPrefix = ``
    if (typeof __PREFIX_PATHS__ !== `undefined`) {
      pathPrefix = __PATH_PREFIX__
    }
    findPage = pageFinderFactory(newPages, pathPrefix)
  },
  addDevRequires: devRequires => {
    syncRequires = devRequires
  },
  addProdRequires: prodRequires => {
    asyncRequires = prodRequires
  },
  dequeue: path => pathArray.pop(),
  enqueue: path => {
    // Check page exists.
    if (!pages.some(p => p.path === path)) {
      return false
    }

    const mountOrderBoost = 1 / mountOrder
    mountOrder += 1
    // console.log(
    // `enqueue "${path}", mountOrder: "${mountOrder}, mountOrderBoost: ${mountOrderBoost}`
    // )

    // Add to path counts.
    if (!pathCount[path]) {
      pathCount[path] = 1
    } else {
      pathCount[path] += 1
    }

    // Add path to queue.
    if (!queue.has(path)) {
      pathArray.unshift(path)
    }

    // Sort pages by pathCount
    pathArray.sort(sortPagesByCount)

    // Add resources to queue.
    const page = findPage(path)
    if (page.jsonName) {
      if (!resourcesCount[page.jsonName]) {
        resourcesCount[page.jsonName] = 1 + mountOrderBoost
      } else {
        resourcesCount[page.jsonName] += 1 + mountOrderBoost
      }

      // Before adding, checking that the JSON resource isn't either
      // already queued or been downloading.
      if (
        resourcesArray.indexOf(page.jsonName) === -1 &&
        !resourceStrCache[page.jsonName]
      ) {
        resourcesArray.unshift(page.jsonName)
      }
    }
    if (page.componentChunkName) {
      if (!resourcesCount[page.componentChunkName]) {
        resourcesCount[page.componentChunkName] = 1 + mountOrderBoost
      } else {
        resourcesCount[page.componentChunkName] += 1 + mountOrderBoost
      }

      // Before adding, checking that the component resource isn't either
      // already queued or been downloading.
      if (
        resourcesArray.indexOf(page.componentChunkName) === -1 &&
        !resourceStrCache[page.jsonName]
      ) {
        resourcesArray.unshift(page.componentChunkName)
      }
    }

    // Sort resources by resourcesCount.
    resourcesArray.sort(sortResourcesByCount)
    if (process.env.NODE_ENV === `production`) {
      prefetcher.onNewResourcesAdded()
    }

    return true
  },
  getResources: () => {
    return {
      resourcesArray,
      resourcesCount,
    }
  },
  getPages: () => {
    return {
      pathArray,
      pathCount,
    }
  },
  getPage: pathname => findPage(pathname),
  has: path => pathArray.some(p => p === path),
  getResourcesForPathname: (path, cb = () => {}) => {
    if (
      inInitialRender &&
      navigator &&
      navigator.serviceWorker &&
      navigator.serviceWorker.controller &&
      navigator.serviceWorker.controller.state === `activated`
    ) {
      // If we're loading from a service worker (it's already activated on
      // this initial render) and we can't find a page, there's a good chance
      // we're on a new page that this (now old) service worker doesn't know
      // about so we'll unregister it and reload.
      if (!findPage(path)) {
        navigator.serviceWorker
          .getRegistrations()
          .then(function(registrations) {
            for (let registration of registrations) {
              registration.unregister()
            }
            window.location.reload()
          })
      }
    }
    inInitialRender = false
    // In development we know the code is loaded already
    // so we just return with it immediately.
    if (process.env.NODE_ENV !== `production`) {
      const page = findPage(path)
      if (!page) return cb()
      const pageResources = {
        component: syncRequires.components[page.componentChunkName],
        json: syncRequires.json[page.jsonName],
        layout: syncRequires.layouts[page.layoutComponentChunkName],
        page,
      }
      cb(pageResources)
      return pageResources
      // Production code path
    } else {
      const page = findPage(path)

      if (!page) {
        console.log(`A page wasn't found for "${path}"`)
        return
      }

      // Use the path from the page so the pathScriptsCache uses
      // the normalized path.
      path = page.path

      // Check if it's in the cache already.
      if (pathScriptsCache[path]) {
        process.nextTick(() => {
          cb(pathScriptsCache[path])
          emitter.emit(`onPostLoadPageResources`, {
            page,
            pageResources: pathScriptsCache[path],
          })
        })
        return pathScriptsCache[path]
      }

      emitter.emit(`onPreLoadPageResources`, { path })
      // Nope, we need to load resource(s)
      let component
      let json
      let layout
      // Load the component/json/layout and parallel and call this
      // function when they're done loading. When both are loaded,
      // we move on.
      const done = () => {
        if (component && json && (!page.layoutComponentChunkName || layout)) {
          pathScriptsCache[path] = { component, json, layout, page }
          const pageResources = { component, json, layout, page }
          cb(pageResources)
          emitter.emit(`onPostLoadPageResources`, {
            page,
            pageResources,
          })
        }
      }
      getResourceModule(page.componentChunkName, (err, c) => {
        if (err) {
          console.log(`Loading the component for ${page.path} failed`)
        }
        component = c
        done()
      })
      getResourceModule(page.jsonName, (err, j) => {
        if (err) {
          console.log(`Loading the JSON for ${page.path} failed`)
        }
        json = j
        done()
      })

      page.layoutComponentChunkName &&
        getResourceModule(page.layoutComponentChunkName, (err, l) => {
          if (err) {
            console.log(`Loading the Layout for ${page.path} failed`)
          }
          layout = l
          done()
        })

      return undefined
    }
  },
  peek: path => pathArray.slice(-1)[0],
  length: () => pathArray.length,
  indexOf: path => pathArray.length - pathArray.indexOf(path) - 1,
}

module.exports = queue
<|endoftext|>


<commit_before>/*jslint forin:true sub:true anon:true, sloppy:true, stupid:true nomen:true, node:true continue:true*/

/*
 * Copyright (c) 2012, Yahoo! Inc.  All rights reserved.
 * Copyrights licensed under the New BSD License.
 * See the accompanying LICENSE file for terms.
 */

var fs = require('fs');
var colors = require("colors");
var UserAgent = require('useragent');
var FileUtil = require("../util/fileutil");
var path = require('path');
var XMLWriter = require('xml-writer');
var xw;
var log4js = require("log4js");
var existsSync = path.existsSync || fs.existsSync;

/**
 *
 * @param reportObj includes all information about testSessions, wsSessions and the test report itself
 * @constructor
 */
function ReportManager(reportObj) {
    this.passCount = 0;
    this.failCount = 0;
    this.skipCount = 0;
    this.timeCount = 0;
    this.totalCount = 0;
    this.totalTimeTaken = 0;
    this.logger = log4js.getLogger("ReportManager");

    if (reportObj) {
        this.timeReport = reportObj.timeReport;
    }

    xw = new XMLWriter();
    this.xw = xw;

    //checking if we need to do colorless reporting.
    if (global.color === false) {
        colors.mode = "none";
    } else {
        if (!process.stdout.isTTY) {
            colors.mode = "none";
        }
    }
    try {
        if (reportObj.arrTestSessions) {
            this.testSessions = reportObj.arrTestSessions;
        } else {
            this.testSessions = [];
        }
        if (reportObj.arrWDSessions) {
            this.wdSessions = reportObj.arrWDSessions;
        } else {
            this.wdSessions = [];
        }
        this.reportObj = reportObj;

    } catch (ex) {
        //console.log(ex);
    }

}

ReportManager.prototype.addProperty = function (name, val) {
    if (val) {
        val += '';  // convert to string, since XMLWriter is picky
        this.xw.startElement('property');
        this.xw.writeAttribute('name', name);
        this.xw.writeAttribute('value', val);
        this.xw.endElement();
    }
};

ReportManager.prototype.addTest = function (time, className, name, failureMessage) {
    this.xw.startElement('testcase');
    this.xw.writeAttribute('time', (time / 1000).toFixed(2));
    this.xw.writeAttribute('classname', className);
    this.xw.writeAttribute('name', name);

    if (failureMessage) {
        if (failureMessage === "skip") {
            this.xw.writeAttribute('executed', 'false');
        } else {
            this.xw.startElement('failure');
            this.xw.text(failureMessage);
            this.xw.endElement();
        }
    }

    this.xw.endElement();
};

ReportManager.prototype.parseYUIResults = function (testJson, dtName, self) {

    var l, m, errorRep,
        yuiUserAgent = testJson.ua,
        yuiSuiteName = testJson.name,
        browser = UserAgent.parse(yuiUserAgent).toAgent(),
        descTestName = dtName,
        currentUrl = testJson.currentUrl,
        yuiTestCaseName,
        timePerTest,
        className,
        testName;

    if (browser === "Other 0.0.0") {
        browser = "NodeJS";
    }

    for (l in testJson) {
        if (testJson[l]) {
            if (testJson[l].type === "testcase") {
                yuiTestCaseName = testJson[l].name;
                timePerTest = testJson[l].duration / testJson[l].total;
                self.passCount += testJson[l].passed;
                self.failCount += testJson[l].failed;
                self.skipCount += testJson[l].ignored;
                self.timeCount += testJson[l].duration;
                self.totalCount += testJson[l].total;

                for (m in testJson[l]) {
                    if (testJson[l][m].type === "test") {
                        className = browser + "." + descTestName;
                        testName = yuiSuiteName + "::" + yuiTestCaseName + "::" + testJson[l][m].name;
                        if (testJson[l][m].result === "fail") {
                            self.addTest(timePerTest, className, testName, testJson[l][m].message + "." + "\n" + " URL :" + currentUrl);
                        } else if (testJson[l][m].result === "pass") {
                            self.addTest(timePerTest, className, testName);
                        } else if (testJson[l][m].result === "ignore") {
                            self.addTest(timePerTest, className, testName, "skip");
                        }
                    }
                }
            }
        }
    }
};

ReportManager.prototype.showReportOnConsole = function (result, verbose) {

    var lastSuite, suite, k, k1, test, msg, m, browser,
        log = console.log;

    log("");
    browser = result.ua;
    if (result.failed) {
        log("Failed ".red + result.name.blue + " on " + browser);
    } else {
        log("Passed ".green + result.name.blue + " on " + browser);
    }
    log((result.passed + " Passed").green + ", " + (result.failed + " Failed ").red + ", " + (result.ignored + " skipped ").grey);
    if (result.failed) {
        for (k in result) {
            suite = result[k];
            if ("object" === typeof suite) {

                if (suite.failed) {
                    for (k1 in suite) {
                        test = suite[k1];
                        if ("object" === typeof test) {
                            if ("fail" === test.result) {

                                if (!lastSuite || lastSuite !== suite.name) {
                                    log(" in " + suite.name.bold);
                                    lastSuite = suite.name;
                                }
                                msg = test.message.split('\n');
                                log(" " + test.name.bold.red + ":" + msg[0]);
                                for (m = 1; m < msg.length; m = m + 1) {
                                    log(" " + msg[m]);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    log("");
};

ReportManager.prototype.writeReports = function () {

    var i, j, k, strJunitReport, strReport, rep, results, testJson, browser,
        testName, testSuiteName, arrReport, xmlReportName, jsonReportName, errorRep,
        self = this,
        wdSessions = self.wdSessions,
        testSessions = self.testSessions,
        jsonReport = {},
        log = console.log,
        resultPresent = false,
        missingErrorCount = 0,
        xwRoot = new XMLWriter(),
        fileUtil = new FileUtil(),
        dirPath,
        relPath;
    function writeFile(fileName, data) {
        fs.writeFileSync(fileName, data, 'utf8');
        log(("Report Created: " + fileName).inverse.toString());
    }

    /**
     * log test results on console
     */
    function logTestResults(reportObj) {
        log();
        log(("Total Number of Executed Tests: " + reportObj.totalCount).blue.toString());
        log(("Total Number of Passed Tests: " + reportObj.passCount).green.toString());
        log(("Total Number of Failed Tests: " + reportObj.failCount).red.toString());
        log(("Total Number of Skipped Tests: " + reportObj.skipCount).cyan.toString());
        log();
        log(("Total Test Execution Time Inside Browser: " + (reportObj.timeCount / 1000).toFixed(2) + " seconds").green.bold.toString());
        log(("Total Test Execution Time:" + reportObj.totalTimeTaken + " seconds").green.bold.toString());
        log();
    }

    for (i = 0; i < testSessions.length; i = i + 1) {

        rep = testSessions[i].driver.getReports();

        if (rep.scenario) {
            arrReport = rep.scenario;
        } else {
            arrReport = rep.results;
        }
        resultPresent = false;
        for (j = 0; j < arrReport.length; j = j + 1) {
            if (rep.scenario) {
                results = arrReport[j].results;

                for (k = 0; k < results.length; k = k + 1) {

                    testJson = results[k];
                    if (testJson.type === "report") {
                        if (!(testJson.passed === 0 && testJson.failed === 0 && testJson.total === 0)) {
                            resultPresent = true;
                            this.parseYUIResults(testJson, testSessions[i].driver.testName, this);
                        }
                    }
                }
            } else {
                testJson = arrReport[j];
                if (testJson.type === "report") {
                    if (!(testJson.passed === 0 && testJson.failed === 0 && testJson.total === 0)) {
                        resultPresent = true;
                        this.parseYUIResults(testJson, testSessions[i].driver.testName, this);
                    }
                }
            }
        }
        if (!resultPresent) {
            missingErrorCount = missingErrorCount + 1;
            errorRep = arrReport[arrReport.length - 1];
            try {
                if (errorRep.results && errorRep.results.length > 0) {
                    this.addTest(0, "Error." + testSessions[i].driver.testName, "Error", errorRep.results[0].error);
                } else if (errorRep.error) {
                    this.addTest(0, "Error." + testSessions[i].driver.testName, "Error", errorRep.error);
                } else {
                    self.logger.debug("Test Report Error : UNKOWN");
                    this.addTest(0, "Error." + testSessions[i].driver.testName, "Error", "Arrow didn't receive result from the test !!!!");
                }
            } catch (e) {
                self.logger.error(e);
            }
        }
    }
    this.totalCount = this.totalCount + missingErrorCount;
    this.failCount = this.failCount + missingErrorCount;

    if (this.reportObj.descriptor) {

        dirPath = path.dirname(this.reportObj.descriptor);
        if (global.reportFolder) {

            //Get relative path to the descriptor
            relPath = path.relative(global.workingDirectory, dirPath);
            dirPath = path.resolve(global.reportFolder, 'arrow-report', relPath);
            // Create directory if it doesnt exist
            // This check helps when keepTestReport is set to true ( If its not set to true, arrow-report would have been cleaned up as part of setup anyways
            if (!existsSync(dirPath)) {
                fileUtil.createDirectory(dirPath);
            }

        }

        xmlReportName = path.resolve(dirPath, path.basename(this.reportObj.descriptor, '.json') + "-report.xml");
        jsonReportName = path.resolve(dirPath, path.basename(this.reportObj.descriptor, '.json') + "-report.json");

        if (this.failCount > 0) {
            global.failedDescriptors.push({"desc" : this.reportObj.descriptor, "failures" : this.failCount});
        }

        log(("Test Report Summary for the descriptor::" + this.reportObj.descriptor).bold.magenta.toString());

        logTestResults(this);

    } else {

        xmlReportName = "arrow-test-summary.xml";
        jsonReportName = "arrow-test-summary.json";

        if (this.reportObj.showConsolidatedReport) {

            log("\n*************************************************************************************");
            log("                            Consolidated Report                                          ");

            log("Test Report Summary".bold.magenta.toString());
            logTestResults(this);

            log("\n*************************************************************************************");

        }

        if (global.failedDescriptors.length > 0) {

            log("\n*************************************************************************************");
            log("                           List of failed descriptors                                  ");

            for (i = 0; i < global.failedDescriptors.length; i += 1) {
                log('\nFailed Descriptor Path : ' + global.failedDescriptors[i].desc);
                log('Total Number of Failed Tests : ' + global.failedDescriptors[i].failures);
                log("-----------------------------------------------------------------------");
            }
            log('\n');

        }

    }

    testSuiteName = "";
    if (this.reportObj.testSuiteName) {
        testSuiteName = this.reportObj.testSuiteName;
    } else {
        testSuiteName = "TestSuite";
    }
    this.errorCount = this.totalCount - this.passCount - this.failCount - this.skipCount;

    // Store report files in user specified location, if explicitly specified, otherwise store in arrow-target/arrow-report
    if (global.reportFolder) {

        this.xw.startElement("properties");
        this.addProperty("descriptor", this.reportObj.descriptor);
        this.addProperty("parallel", this.reportObj.parallel);
        this.addProperty("driver", this.reportObj.driver);
        this.addProperty("browser", this.reportObj.browser);
        this.addProperty("reuseSession", this.reportObj.reuseSession);
        this.addProperty("activeSeleniumSessionCount", wdSessions.length);
        this.addProperty("seleniumSessionIds", wdSessions.join());
        this.addProperty("group", this.reportObj.group);
        this.addProperty("testName", this.reportObj.testName);
        this.xw.endElement();
        //collecting all report
        strReport = xw.toString();

        //starting report root
        xwRoot.startDocument();
        xwRoot.startElement("testsuite");
        xwRoot.writeAttribute('failures', this.failCount.toString());
        xwRoot.writeAttribute('time', this.totalTimeTaken.toString());
        xwRoot.writeAttribute('errors', this.errorCount.toString());
        xwRoot.writeAttribute('skipped', this.skipCount.toString());
        xwRoot.writeAttribute('tests', this.totalCount.toString());
        xwRoot.writeAttribute('name', testSuiteName.toString());
        xwRoot.text("$$report$$");
        xwRoot.endElement();
        xwRoot.endDocument();
        strJunitReport = xwRoot.toString().replace("$$report$$", strReport);

        xmlReportName = path.resolve(global.reportFolder, 'arrow-report', xmlReportName);
        jsonReportName = path.resolve(global.reportFolder, 'arrow-report', jsonReportName);

        log('\n');
        writeFile(xmlReportName, strJunitReport);

        //writing json file
        for (i = 0; i < testSessions.length; i = i + 1) {
            jsonReport[testSessions[i].driver.testName] = JSON.parse(JSON.stringify(testSessions[i].driver.getReports()));
        }
        jsonReport.testSuiteName = testSuiteName;
        writeFile(jsonReportName, JSON.stringify(jsonReport));
        log('\n');

    }

    return path.resolve(xmlReportName); // Is this return statement required ??
};

ReportManager.prototype.writeTimeReport = function () {

    var timeReportJsonStr,
        descriptor,
        testSessionTimeArr,
        testName;

    timeReportJsonStr = '{ "descriptors" : [';

    for (descriptor in this.timeReport) {

        timeReportJsonStr += "{";
        timeReportJsonStr += ('"descriptor": ' + ' "' + descriptor + '"' + ' ,');
        timeReportJsonStr += ('"time": ' + ' "' + this.timeReport[descriptor].timeTaken + ' seconds' + '",');

        testSessionTimeArr = this.timeReport[descriptor].testSessionTimeArr;

        timeReportJsonStr += '"tests": [';

        for (testName in testSessionTimeArr) {
            timeReportJsonStr += '{';
            timeReportJsonStr += ('"Testname" :' + ' "' + testName + '"' + ',');
            timeReportJsonStr += ('"Time" :' + ' "' + testSessionTimeArr[testName].timeTaken + ' seconds' + '"');
            timeReportJsonStr += '} ,';
        }

        if (timeReportJsonStr.charAt(timeReportJsonStr.length - 1) === ",") {
            timeReportJsonStr = timeReportJsonStr.slice(0, -1);
        }

        timeReportJsonStr += " ] } ,";
    }

    if (timeReportJsonStr.charAt(timeReportJsonStr.length - 1) === ",") {
        timeReportJsonStr = timeReportJsonStr.slice(0, -1);
    }

    timeReportJsonStr += ('] ,"Total time":' + ' "' + this.totalTimeTaken + ' seconds' + '" ');
    timeReportJsonStr += ' }';

    fs.writeFileSync(path.resolve(global.reportFolder, 'arrow-report', 'timeReport.json'), timeReportJsonStr, 'utf8');

};

module.exports = ReportManager;
<commit_msg>Removing unused return statement<commit_after>/*jslint forin:true sub:true anon:true, sloppy:true, stupid:true nomen:true, node:true continue:true*/

/*
 * Copyright (c) 2012, Yahoo! Inc.  All rights reserved.
 * Copyrights licensed under the New BSD License.
 * See the accompanying LICENSE file for terms.
 */

var fs = require('fs');
var colors = require("colors");
var UserAgent = require('useragent');
var FileUtil = require("../util/fileutil");
var path = require('path');
var XMLWriter = require('xml-writer');
var xw;
var log4js = require("log4js");
var existsSync = path.existsSync || fs.existsSync;

/**
 *
 * @param reportObj includes all information about testSessions, wsSessions and the test report itself
 * @constructor
 */
function ReportManager(reportObj) {
    this.passCount = 0;
    this.failCount = 0;
    this.skipCount = 0;
    this.timeCount = 0;
    this.totalCount = 0;
    this.totalTimeTaken = 0;
    this.logger = log4js.getLogger("ReportManager");

    if (reportObj) {
        this.timeReport = reportObj.timeReport;
    }

    xw = new XMLWriter();
    this.xw = xw;

    //checking if we need to do colorless reporting.
    if (global.color === false) {
        colors.mode = "none";
    } else {
        if (!process.stdout.isTTY) {
            colors.mode = "none";
        }
    }
    try {
        if (reportObj.arrTestSessions) {
            this.testSessions = reportObj.arrTestSessions;
        } else {
            this.testSessions = [];
        }
        if (reportObj.arrWDSessions) {
            this.wdSessions = reportObj.arrWDSessions;
        } else {
            this.wdSessions = [];
        }
        this.reportObj = reportObj;

    } catch (ex) {
        //console.log(ex);
    }

}

ReportManager.prototype.addProperty = function (name, val) {
    if (val) {
        val += '';  // convert to string, since XMLWriter is picky
        this.xw.startElement('property');
        this.xw.writeAttribute('name', name);
        this.xw.writeAttribute('value', val);
        this.xw.endElement();
    }
};

ReportManager.prototype.addTest = function (time, className, name, failureMessage) {
    this.xw.startElement('testcase');
    this.xw.writeAttribute('time', (time / 1000).toFixed(2));
    this.xw.writeAttribute('classname', className);
    this.xw.writeAttribute('name', name);

    if (failureMessage) {
        if (failureMessage === "skip") {
            this.xw.writeAttribute('executed', 'false');
        } else {
            this.xw.startElement('failure');
            this.xw.text(failureMessage);
            this.xw.endElement();
        }
    }

    this.xw.endElement();
};

ReportManager.prototype.parseYUIResults = function (testJson, dtName, self) {

    var l, m, errorRep,
        yuiUserAgent = testJson.ua,
        yuiSuiteName = testJson.name,
        browser = UserAgent.parse(yuiUserAgent).toAgent(),
        descTestName = dtName,
        currentUrl = testJson.currentUrl,
        yuiTestCaseName,
        timePerTest,
        className,
        testName;

    if (browser === "Other 0.0.0") {
        browser = "NodeJS";
    }

    for (l in testJson) {
        if (testJson[l]) {
            if (testJson[l].type === "testcase") {
                yuiTestCaseName = testJson[l].name;
                timePerTest = testJson[l].duration / testJson[l].total;
                self.passCount += testJson[l].passed;
                self.failCount += testJson[l].failed;
                self.skipCount += testJson[l].ignored;
                self.timeCount += testJson[l].duration;
                self.totalCount += testJson[l].total;

                for (m in testJson[l]) {
                    if (testJson[l][m].type === "test") {
                        className = browser + "." + descTestName;
                        testName = yuiSuiteName + "::" + yuiTestCaseName + "::" + testJson[l][m].name;
                        if (testJson[l][m].result === "fail") {
                            self.addTest(timePerTest, className, testName, testJson[l][m].message + "." + "\n" + " URL :" + currentUrl);
                        } else if (testJson[l][m].result === "pass") {
                            self.addTest(timePerTest, className, testName);
                        } else if (testJson[l][m].result === "ignore") {
                            self.addTest(timePerTest, className, testName, "skip");
                        }
                    }
                }
            }
        }
    }
};

ReportManager.prototype.showReportOnConsole = function (result, verbose) {

    var lastSuite, suite, k, k1, test, msg, m, browser,
        log = console.log;

    log("");
    browser = result.ua;
    if (result.failed) {
        log("Failed ".red + result.name.blue + " on " + browser);
    } else {
        log("Passed ".green + result.name.blue + " on " + browser);
    }
    log((result.passed + " Passed").green + ", " + (result.failed + " Failed ").red + ", " + (result.ignored + " skipped ").grey);
    if (result.failed) {
        for (k in result) {
            suite = result[k];
            if ("object" === typeof suite) {

                if (suite.failed) {
                    for (k1 in suite) {
                        test = suite[k1];
                        if ("object" === typeof test) {
                            if ("fail" === test.result) {

                                if (!lastSuite || lastSuite !== suite.name) {
                                    log(" in " + suite.name.bold);
                                    lastSuite = suite.name;
                                }
                                msg = test.message.split('\n');
                                log(" " + test.name.bold.red + ":" + msg[0]);
                                for (m = 1; m < msg.length; m = m + 1) {
                                    log(" " + msg[m]);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    log("");
};

ReportManager.prototype.writeReports = function () {

    var i, j, k, strJunitReport, strReport, rep, results, testJson, browser,
        testName, testSuiteName, arrReport, xmlReportName, jsonReportName, errorRep,
        self = this,
        wdSessions = self.wdSessions,
        testSessions = self.testSessions,
        jsonReport = {},
        log = console.log,
        resultPresent = false,
        missingErrorCount = 0,
        xwRoot = new XMLWriter(),
        fileUtil = new FileUtil(),
        dirPath,
        relPath;
    function writeFile(fileName, data) {
        fs.writeFileSync(fileName, data, 'utf8');
        log(("Report Created: " + fileName).inverse.toString());
    }

    /**
     * log test results on console
     */
    function logTestResults(reportObj) {
        log();
        log(("Total Number of Executed Tests: " + reportObj.totalCount).blue.toString());
        log(("Total Number of Passed Tests: " + reportObj.passCount).green.toString());
        log(("Total Number of Failed Tests: " + reportObj.failCount).red.toString());
        log(("Total Number of Skipped Tests: " + reportObj.skipCount).cyan.toString());
        log();
        log(("Total Test Execution Time Inside Browser: " + (reportObj.timeCount / 1000).toFixed(2) + " seconds").green.bold.toString());
        log(("Total Test Execution Time:" + reportObj.totalTimeTaken + " seconds").green.bold.toString());
        log();
    }

    for (i = 0; i < testSessions.length; i = i + 1) {

        rep = testSessions[i].driver.getReports();

        if (rep.scenario) {
            arrReport = rep.scenario;
        } else {
            arrReport = rep.results;
        }
        resultPresent = false;
        for (j = 0; j < arrReport.length; j = j + 1) {
            if (rep.scenario) {
                results = arrReport[j].results;

                for (k = 0; k < results.length; k = k + 1) {

                    testJson = results[k];
                    if (testJson.type === "report") {
                        if (!(testJson.passed === 0 && testJson.failed === 0 && testJson.total === 0)) {
                            resultPresent = true;
                            this.parseYUIResults(testJson, testSessions[i].driver.testName, this);
                        }
                    }
                }
            } else {
                testJson = arrReport[j];
                if (testJson.type === "report") {
                    if (!(testJson.passed === 0 && testJson.failed === 0 && testJson.total === 0)) {
                        resultPresent = true;
                        this.parseYUIResults(testJson, testSessions[i].driver.testName, this);
                    }
                }
            }
        }
        if (!resultPresent) {
            missingErrorCount = missingErrorCount + 1;
            errorRep = arrReport[arrReport.length - 1];
            try {
                if (errorRep.results && errorRep.results.length > 0) {
                    this.addTest(0, "Error." + testSessions[i].driver.testName, "Error", errorRep.results[0].error);
                } else if (errorRep.error) {
                    this.addTest(0, "Error." + testSessions[i].driver.testName, "Error", errorRep.error);
                } else {
                    self.logger.debug("Test Report Error : UNKOWN");
                    this.addTest(0, "Error." + testSessions[i].driver.testName, "Error", "Arrow didn't receive result from the test !!!!");
                }
            } catch (e) {
                self.logger.error(e);
            }
        }
    }
    this.totalCount = this.totalCount + missingErrorCount;
    this.failCount = this.failCount + missingErrorCount;

    if (this.reportObj.descriptor) {

        dirPath = path.dirname(this.reportObj.descriptor);
        if (global.reportFolder) {

            //Get relative path to the descriptor
            relPath = path.relative(global.workingDirectory, dirPath);
            dirPath = path.resolve(global.reportFolder, 'arrow-report', relPath);
            // Create directory if it doesnt exist
            // This check helps when keepTestReport is set to true ( If its not set to true, arrow-report would have been cleaned up as part of setup anyways
            if (!existsSync(dirPath)) {
                fileUtil.createDirectory(dirPath);
            }

        }

        xmlReportName = path.resolve(dirPath, path.basename(this.reportObj.descriptor, '.json') + "-report.xml");
        jsonReportName = path.resolve(dirPath, path.basename(this.reportObj.descriptor, '.json') + "-report.json");

        if (this.failCount > 0) {
            global.failedDescriptors.push({"desc" : this.reportObj.descriptor, "failures" : this.failCount});
        }

        log(("Test Report Summary for the descriptor::" + this.reportObj.descriptor).bold.magenta.toString());

        logTestResults(this);

    } else {

        xmlReportName = "arrow-test-summary.xml";
        jsonReportName = "arrow-test-summary.json";

        if (this.reportObj.showConsolidatedReport) {

            log("\n*************************************************************************************");
            log("                            Consolidated Report                                          ");

            log("Test Report Summary".bold.magenta.toString());
            logTestResults(this);

            log("\n*************************************************************************************");

        }

        if (global.failedDescriptors.length > 0) {

            log("\n*************************************************************************************");
            log("                           List of failed descriptors                                  ");

            for (i = 0; i < global.failedDescriptors.length; i += 1) {
                log('\nFailed Descriptor Path : ' + global.failedDescriptors[i].desc);
                log('Total Number of Failed Tests : ' + global.failedDescriptors[i].failures);
                log("-----------------------------------------------------------------------");
            }
            log('\n');

        }

    }

    testSuiteName = "";
    if (this.reportObj.testSuiteName) {
        testSuiteName = this.reportObj.testSuiteName;
    } else {
        testSuiteName = "TestSuite";
    }
    this.errorCount = this.totalCount - this.passCount - this.failCount - this.skipCount;

    // Store report files in user specified location, if explicitly specified, otherwise store in arrow-target/arrow-report
    if (global.reportFolder) {

        this.xw.startElement("properties");
        this.addProperty("descriptor", this.reportObj.descriptor);
        this.addProperty("parallel", this.reportObj.parallel);
        this.addProperty("driver", this.reportObj.driver);
        this.addProperty("browser", this.reportObj.browser);
        this.addProperty("reuseSession", this.reportObj.reuseSession);
        this.addProperty("activeSeleniumSessionCount", wdSessions.length);
        this.addProperty("seleniumSessionIds", wdSessions.join());
        this.addProperty("group", this.reportObj.group);
        this.addProperty("testName", this.reportObj.testName);
        this.xw.endElement();
        //collecting all report
        strReport = xw.toString();

        //starting report root
        xwRoot.startDocument();
        xwRoot.startElement("testsuite");
        xwRoot.writeAttribute('failures', this.failCount.toString());
        xwRoot.writeAttribute('time', this.totalTimeTaken.toString());
        xwRoot.writeAttribute('errors', this.errorCount.toString());
        xwRoot.writeAttribute('skipped', this.skipCount.toString());
        xwRoot.writeAttribute('tests', this.totalCount.toString());
        xwRoot.writeAttribute('name', testSuiteName.toString());
        xwRoot.text("$$report$$");
        xwRoot.endElement();
        xwRoot.endDocument();
        strJunitReport = xwRoot.toString().replace("$$report$$", strReport);

        xmlReportName = path.resolve(global.reportFolder, 'arrow-report', xmlReportName);
        jsonReportName = path.resolve(global.reportFolder, 'arrow-report', jsonReportName);

        log('\n');
        writeFile(xmlReportName, strJunitReport);

        //writing json file
        for (i = 0; i < testSessions.length; i = i + 1) {
            jsonReport[testSessions[i].driver.testName] = JSON.parse(JSON.stringify(testSessions[i].driver.getReports()));
        }
        jsonReport.testSuiteName = testSuiteName;
        writeFile(jsonReportName, JSON.stringify(jsonReport));
        log('\n');

    }

};

ReportManager.prototype.writeTimeReport = function () {

    var timeReportJsonStr,
        descriptor,
        testSessionTimeArr,
        testName;

    timeReportJsonStr = '{ "descriptors" : [';

    for (descriptor in this.timeReport) {

        timeReportJsonStr += "{";
        timeReportJsonStr += ('"descriptor": ' + ' "' + descriptor + '"' + ' ,');
        timeReportJsonStr += ('"time": ' + ' "' + this.timeReport[descriptor].timeTaken + ' seconds' + '",');

        testSessionTimeArr = this.timeReport[descriptor].testSessionTimeArr;

        timeReportJsonStr += '"tests": [';

        for (testName in testSessionTimeArr) {
            timeReportJsonStr += '{';
            timeReportJsonStr += ('"Testname" :' + ' "' + testName + '"' + ',');
            timeReportJsonStr += ('"Time" :' + ' "' + testSessionTimeArr[testName].timeTaken + ' seconds' + '"');
            timeReportJsonStr += '} ,';
        }

        if (timeReportJsonStr.charAt(timeReportJsonStr.length - 1) === ",") {
            timeReportJsonStr = timeReportJsonStr.slice(0, -1);
        }

        timeReportJsonStr += " ] } ,";
    }

    if (timeReportJsonStr.charAt(timeReportJsonStr.length - 1) === ",") {
        timeReportJsonStr = timeReportJsonStr.slice(0, -1);
    }

    timeReportJsonStr += ('] ,"Total time":' + ' "' + this.totalTimeTaken + ' seconds' + '" ');
    timeReportJsonStr += ' }';

    fs.writeFileSync(path.resolve(global.reportFolder, 'arrow-report', 'timeReport.json'), timeReportJsonStr, 'utf8');

};

module.exports = ReportManager;
<|endoftext|>


<commit_before>/*
 * Shopify Ajax API module
 * Docs for Shopify's Ajax API
 * https://docs.shopify.com/support/your-website/themes/can-i-use-ajax-api
 */

export function getProduct(handle) {
  return fetch(`/products/${handle}`, {
    method: 'GET',
    headers: {
      'Accept': 'text/javascript',
      'Content-Type': 'application/json',
      'X-Requested-With': 'XMLHttpRequest'
    },
    credentials: 'include'
  });
}

export function addCart(id, quantity = 1) {
  return fetch(`/cart/add.js`, {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
      'X-Requested-With': 'XMLHttpRequest'
    },
    credentials: 'include',
    body: JSON.stringify({ id, quantity })
  });
}

export function getCart() {
  return fetch('/cart.js', {
    method: 'GET',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
      'X-Requested-With': 'XMLHttpRequest'
    },
    credentials: 'include'
  });
}

export function updateCart(id, quantity) {
  return fetch('/cart/update.js', {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
      'X-Requested-With': 'XMLHttpRequest'
    },
    credentials: 'include',
    body: JSON.stringify({ id, quantity })
  });
}

export function changeCart(id, quantity) {
  return fetch('/cart/change.js', {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
      'X-Requested-With': 'XMLHttpRequest'
    },
    credentials: 'include',
    body: JSON.stringify({ id, quantity })
  });
}

export function clearCart() {
  return fetch('/cart/clear.js', {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
      'X-Requested-With': 'XMLHttpRequest'
    },
    credentials: 'include'
  });
}

export function getShipping(obj) {
}

<commit_msg>DRY the headers<commit_after>/*
 * Shopify Ajax API module
 * Docs for Shopify's Ajax API
 * https://docs.shopify.com/support/your-website/themes/can-i-use-ajax-api
 */

const headers = {
  'Accept': 'text/javascript',
  'Content-Type': 'application/json',
  'X-Requested-With': 'XMLHttpRequest'
}

export function getProduct(handle) {
  return fetch(`/products/${handle}`, {
    method: 'GET',
    credentials: 'include',
    headers
  });
}

export function addCart(id, quantity = 1) {
  return fetch(`/cart/add.js`, {
    method: 'POST',
    credentials: 'include',
    body: JSON.stringify({ id, quantity }),
    headers
  });
}

export function getCart() {
  return fetch('/cart.js', {
    method: 'GET',
    credentials: 'include',
    headers
  });
}

export function updateCart(id, quantity) {
  return fetch('/cart/update.js', {
    method: 'POST',
    credentials: 'include',
    body: JSON.stringify({ id, quantity }),
    headers
  });
}

export function changeCart(id, quantity) {
  return fetch('/cart/change.js', {
    method: 'POST',
    credentials: 'include',
    body: JSON.stringify({ id, quantity }),
    headers
  });
}

export function clearCart() {
  return fetch('/cart/clear.js', {
    method: 'POST',
    credentials: 'include',
    headers
  });
}

export function getShipping(obj) {
}

<|endoftext|>