<commit_before>/* globals Vue */
var DragAndDrop = {}

DragAndDrop.install = function (Vue) {
  Vue.directive('drag-and-drop', {
    params: [
    'v-drag-and-drop',
    'v-drag-start',
    'v-drag-over',
    'v-drag-enter',
    'v-drag-leave',
    'v-drag-end',
    'v-drop'
    ],
    bind: function () {
      // use the VM so we only have 1 dragging item per app
      this.vm._dragSrcEl = null;
      this.handleDragStart = function (e) {
        e.target.classList.add('dragging');
        this.vm._dragSrcEl = e.target;
        e.dataTransfer.effectAllowed = 'move';
        // Need to set to something or else drag doesn't start
        e.dataTransfer.setData('text', '*');
        if (typeof(this.vm[this.params.vDragStart]) === 'function') {
          this.vm[this.params.vDragStart].call(this, e.target);
        }
      }.bind(this);
      this.handleDragOver = function(e) {
        if (e.preventDefault) {
          // allows dropping
          e.preventDefault();
        }
        e.dataTransfer.dropEffect = 'move';
        e.target.classList.add('drag-over');
        if (typeof(this.vm[this.params.vDragOver]) === 'function') {
          this.vm[this.params.vDragOver].call(this, e.target);
        }
        return false;
      }.bind(this);
      this.handleDragEnter = function(e) {
        if (typeof(this.vm[this.params.vDragEnter]) === 'function') {
          this.vm[this.params.vDragEnter].call(this, e.target);
        }
        e.target.classList.add('drag-enter');
      }.bind(this);
      this.handleDragLeave = function(e) {
        if (typeof(this.vm[this.params.vDragLeave]) === 'function') {
          this.vm[this.params.vDragLeave].call(this, e.target);
        }
        e.target.classList.remove('drag-enter');
      }.bind(this);
      this.handleDragEnd = function(e) {
        e.target.classList.remove('dragging', 'drag-over', 'drag-enter');
        if (typeof(this.vm[this.params.vDragEnd]) === 'function') {
          this.vm[this.params.vDragEnd].call(this, e.target);
        }
      }.bind(this);
      this.handleDrop = function(e) {
        if (e.stopPropagation) {
          // stops the browser from redirecting.
          e.stopPropagation();
        }
        // Don't do anything if dropping the same column we're dragging.
        if (this.vm._dragSrcEl != e.target) {
          if (typeof(this.vm[this.params.vDrop]) === 'function') {
            var el = (e.target.draggable) ? e.target : e.target.parentElement;
            this.vm[this.params.vDrop].call(this, this.vm._dragSrcEl, el);
          }
        }
        return false;
      }.bind(this);
      // setup the listeners
      this.el.setAttribute('draggable', 'true');
      this.el.addEventListener('dragstart', this.handleDragStart, false);
      this.el.addEventListener('dragenter', this.handleDragEnter, false);
      this.el.addEventListener('dragover', this.handleDragOver, false);
      this.el.addEventListener('dragleave', this.handleDragLeave, false);
      this.el.addEventListener('drop', this.handleDrop, false);
      this.el.addEventListener('dragend', this.handleDragEnd, false);
    },
    update: function (newValue, oldValue) {
      // console.log(this);
    },
    unbind: function () {
      // shut er' down
      this.el.classList.remove('dragging', 'drag-over', 'drag-enter');
      this.el.removeAttribute('draggable');
      this.el.removeEventListener('dragstart', this.handleDragStart);
      this.el.removeEventListener('dragenter', this.handleDragEnter);
      this.el.removeEventListener('dragover', this.handleDragOver);
      this.el.removeEventListener('dragleave', this.handleDragLeave);
    }
  });
}

module.exports = DragAndDrop<commit_msg>Make sure browsers can unpack this module as well<commit_after>/* globals Vue */
(function () {

  var DragAndDrop = {}

  DragAndDrop.install = function (Vue) {
    Vue.directive('drag-and-drop', {
      params: [
      'v-drag-and-drop',
      'v-drag-start',
      'v-drag-over',
      'v-drag-enter',
      'v-drag-leave',
      'v-drag-end',
      'v-drop'
      ],
      bind: function () {
        // use the VM so we only have 1 dragging item per app
        this.vm._dragSrcEl = null;
        this.handleDragStart = function (e) {
          e.target.classList.add('dragging');
          this.vm._dragSrcEl = e.target;
          e.dataTransfer.effectAllowed = 'move';
          // Need to set to something or else drag doesn't start
          e.dataTransfer.setData('text', '*');
          if (typeof(this.vm[this.params.vDragStart]) === 'function') {
            this.vm[this.params.vDragStart].call(this, e.target);
          }
        }.bind(this);
        this.handleDragOver = function(e) {
          if (e.preventDefault) {
            // allows dropping
            e.preventDefault();
          }
          e.dataTransfer.dropEffect = 'move';
          e.target.classList.add('drag-over');
          if (typeof(this.vm[this.params.vDragOver]) === 'function') {
            this.vm[this.params.vDragOver].call(this, e.target);
          }
          return false;
        }.bind(this);
        this.handleDragEnter = function(e) {
          if (typeof(this.vm[this.params.vDragEnter]) === 'function') {
            this.vm[this.params.vDragEnter].call(this, e.target);
          }
          e.target.classList.add('drag-enter');
        }.bind(this);
        this.handleDragLeave = function(e) {
          if (typeof(this.vm[this.params.vDragLeave]) === 'function') {
            this.vm[this.params.vDragLeave].call(this, e.target);
          }
          e.target.classList.remove('drag-enter');
        }.bind(this);
        this.handleDragEnd = function(e) {
          e.target.classList.remove('dragging', 'drag-over', 'drag-enter');
          if (typeof(this.vm[this.params.vDragEnd]) === 'function') {
            this.vm[this.params.vDragEnd].call(this, e.target);
          }
        }.bind(this);
        this.handleDrop = function(e) {
          if (e.stopPropagation) {
            // stops the browser from redirecting.
            e.stopPropagation();
          }
          // Don't do anything if dropping the same column we're dragging.
          if (this.vm._dragSrcEl != e.target) {
            if (typeof(this.vm[this.params.vDrop]) === 'function') {
              var el = (e.target.draggable) ? e.target : e.target.parentElement;
              this.vm[this.params.vDrop].call(this, this.vm._dragSrcEl, el);
            }
          }
          return false;
        }.bind(this);
        // setup the listeners
        this.el.setAttribute('draggable', 'true');
        this.el.addEventListener('dragstart', this.handleDragStart, false);
        this.el.addEventListener('dragenter', this.handleDragEnter, false);
        this.el.addEventListener('dragover', this.handleDragOver, false);
        this.el.addEventListener('dragleave', this.handleDragLeave, false);
        this.el.addEventListener('drop', this.handleDrop, false);
        this.el.addEventListener('dragend', this.handleDragEnd, false);
      },
      update: function (newValue, oldValue) {
        // console.log(this);
      },
      unbind: function () {
        // shut er' down
        this.el.classList.remove('dragging', 'drag-over', 'drag-enter');
        this.el.removeAttribute('draggable');
        this.el.removeEventListener('dragstart', this.handleDragStart);
        this.el.removeEventListener('dragenter', this.handleDragEnter);
        this.el.removeEventListener('dragover', this.handleDragOver);
        this.el.removeEventListener('dragleave', this.handleDragLeave);
      }
    });
  }

  if (typeof exports == "object") {
    module.exports = DragAndDrop
  } else if (typeof define == "function" && define.amd) {
    define([], function(){ return DragAndDrop })
  } else if (window.Vue) {
    window.DragAndDrop = DragAndDrop
    Vue.use(DragAndDrop)
  }
})()<|endoftext|>


<commit_before>'use strict';

var AnnotationComponent = require('substance/ui/AnnotationComponent');

function XRefComponent() {
  XRefComponent.super.apply(this, arguments);
}

XRefComponent.Prototype = function() {

  var _super = XRefComponent.super.prototype;

  this.render = function($$) {
    var el = _super.render.apply(this, arguments);
    el.addClass('sm-'+this.props.node.referenceType);
    return el;
  };
};

AnnotationComponent.extend(XRefComponent);

module.exports = XRefComponent;
<commit_msg>Fix linter.<commit_after>'use strict';

var AnnotationComponent = require('substance/ui/AnnotationComponent');

function XRefComponent() {
  XRefComponent.super.apply(this, arguments);
}

XRefComponent.Prototype = function() {

  var _super = XRefComponent.super.prototype;

  this.render = function($$) { // eslint-disable-line
    var el = _super.render.apply(this, arguments);
    el.addClass('sm-'+this.props.node.referenceType);
    return el;
  };
};

AnnotationComponent.extend(XRefComponent);

module.exports = XRefComponent;
<|endoftext|>


<commit_before>(function(Application, Window) {

  // TODO: Mime check from metadata

  /**
   * Main Window
   */
  var ApplicationPreviewWindow = function(app, opts) {
    Window.apply(this, ['ApplicationPreviewWindow', opts, app]);

    this.menuBar = null;
    this.previewElement = null;
    this.title = "Preview";
    this.$frame = null;

    this._title = this.title;
    this._icon = "/themes/default/icons/16x16/mimetypes/image.png";
    this._properties.allow_drop = true;
  };

  ApplicationPreviewWindow.prototype = Object.create(Window.prototype);

  ApplicationPreviewWindow.prototype.init = function() {
    var root = Window.prototype.init.apply(this, arguments);
    var app = this._appRef;

    this.menuBar = new OSjs.GUI.MenuBar();
    this.menuBar.addItem("File", [
      {title: 'Open', onClick: function() {
        app.action('open');
      }},
      {title: 'Close', onClick: function() {
        app.action('close');
      }}
    ]);

    this.$frame = document.createElement('div');
    this.$frame.className = "Frame";

    root.appendChild(this.menuBar.getRoot());
    root.appendChild(this.$frame);
  };

  ApplicationPreviewWindow.prototype.destroy = function() {
    if ( this.menuBar ) {
      this.menuBar.destroy();
      this.menuBar = null;
    }
    if ( this.previewElement && this.previewElement.parentNode ) {
      this.previewElement.parentNode.removeChild(this.previewElement);
      this.previewElement = null;
    }
    if ( this.$frame && this.$frame.parentNode ) {
      this.$frame.parentNode.removeChild(this.$frame);
      this.$frame = null;
    }
    Window.prototype.destroy.apply(this, arguments);
  };

  ApplicationPreviewWindow.prototype._onDndEvent = function(ev, type, item, args) {
    Window.prototype._onDndEvent.apply(this, arguments);
    if ( type === 'itemDrop' && item ) {
      var data = item.data;
      if ( data && data.type === 'file' && data.mime ) {
        this._appRef.action('open', data.path, data.mime);
      }
    }
  };

  ApplicationPreviewWindow.prototype.setPreview = function(t, mime) {
    console.log("ApplicationPreviewWindow::setPreview()", t, mime);

    if ( this.previewElement && this.previewElement.parentNode ) {
      this.previewElement.parentNode.removeChild(this.previewElement);
      this.previewElement = null;
    }

    var el;
    if ( mime ) {
      if ( !mime.match(/^(image|video|audio)/) ) {
        OSjs.API.error("Preview", "Cannot open file", "Not supported!");
        return;
      }

      if ( t ) {
        try {
          var src = OSjs.API.getFilesystemURL(t);
          if ( mime.match(/^image/) ) {
            el = document.createElement('img');
            el.alt = t;
            el.src = src;
          } else if ( mime.match(/^audio/) ) {
            el = document.createElement('audio');
            el.controls = "controls";
            el.autoplay = "autoplay";
            el.src = src;
          } else if ( mime.match(/^video/) ) {
            el = document.createElement('video');
            el.controls = "controls";
            el.autoplay = "autoplay";
            el.src = src;
          }
        } catch ( e ) {
          console.warn("Preview error: " + e);
        }
      }
    }

    if ( el ) {
      this.previewElement = el;
      this.$frame.appendChild(this.previewElement);

      if ( el.tagName !== 'IMG' ) {
        this._resize(500, 400);
      }
    }

    this._setTitle(t ? (this.title + " - " + t) : this.title);
  };

  ApplicationPreviewWindow.prototype._resize = function(w, h) {
    if ( !Window.prototype._resize.apply(this, arguments) ) return false;

    if ( this.previewElement && this.previewElement.tagName !== 'IMG' ) {
      if ( this.previewElement.parentNode ) {
        this.previewElement.width  = this.previewElement.parentNode.offsetWidth;
        this.previewElement.height = this.previewElement.parentNode.offsetHeight;
      }
    }

    return true;
  };

  /**
   * Application
   */
  var ApplicationPreview = function(args, metadata) {
    Application.apply(this, ['ApplicationPreview', args, metadata]);
  };

  ApplicationPreview.prototype = Object.create(Application.prototype);

  ApplicationPreview.prototype.destroy = function() {
    return Application.prototype.destroy.apply(this, []);
  };

  ApplicationPreview.prototype.init = function(core, session) {
    Application.prototype.init.apply(this, arguments);

    this._addWindow(new ApplicationPreviewWindow(this, {width: 400, height: 200}));

    var open = this._getArgument('file');
    var mime = this._getArgument('mime');
    if ( open ) {
      this.action('open', open, mime);
    }
  };

  ApplicationPreview.prototype._onMessage = function(obj, msg, args) {
    Application.prototype._onMessage.apply(this, arguments);

    if ( msg == 'destroyWindow' && obj._name === 'ApplicationPreviewWindow' ) {
      this.destroy();
    }
  };

  ApplicationPreview.prototype.action = function(action, fname, mime) {
    var w = this._getWindow('ApplicationPreviewWindow');
    if ( !w ) return;
    var self = this;
    switch ( action ) {
      case 'close' :
        this.destroy();
      break;

      case 'open' :
        var _open = function(fname, rmime) {
          if ( fname ) {
            w.setPreview(fname, (mime || rmime) || null);
            self._setArgument('file', fname);
            self._setArgument('mime', (mime || rmime) || null);
          }
        };

        if ( fname ) {
          _open(fname);
        } else {
          this._createDialog('File', [{type: 'open'}, function(btn, fname, rmime) {
            if ( btn !== 'ok' ) return;
            _open(fname, (mime || rmime));
          }], w);
        }
      break;
    }
  };

  //
  // EXPORTS
  //
  OSjs.Applications = OSjs.Applications || {};
  OSjs.Applications.ApplicationPreview = ApplicationPreview;

})(OSjs.Core.Application, OSjs.Core.Window);
<commit_msg>Preview App: MIME in file open fialog<commit_after>(function(Application, Window) {

  // TODO: Mime check from metadata

  /**
   * Main Window
   */
  var ApplicationPreviewWindow = function(app, opts) {
    Window.apply(this, ['ApplicationPreviewWindow', opts, app]);

    this.menuBar = null;
    this.previewElement = null;
    this.title = "Preview";
    this.$frame = null;

    this._title = this.title;
    this._icon = "/themes/default/icons/16x16/mimetypes/image.png";
    this._properties.allow_drop = true;
  };

  ApplicationPreviewWindow.prototype = Object.create(Window.prototype);

  ApplicationPreviewWindow.prototype.init = function() {
    var root = Window.prototype.init.apply(this, arguments);
    var app = this._appRef;

    this.menuBar = new OSjs.GUI.MenuBar();
    this.menuBar.addItem("File", [
      {title: 'Open', onClick: function() {
        app.action('open');
      }},
      {title: 'Close', onClick: function() {
        app.action('close');
      }}
    ]);

    this.$frame = document.createElement('div');
    this.$frame.className = "Frame";

    root.appendChild(this.menuBar.getRoot());
    root.appendChild(this.$frame);
  };

  ApplicationPreviewWindow.prototype.destroy = function() {
    if ( this.menuBar ) {
      this.menuBar.destroy();
      this.menuBar = null;
    }
    if ( this.previewElement && this.previewElement.parentNode ) {
      this.previewElement.parentNode.removeChild(this.previewElement);
      this.previewElement = null;
    }
    if ( this.$frame && this.$frame.parentNode ) {
      this.$frame.parentNode.removeChild(this.$frame);
      this.$frame = null;
    }
    Window.prototype.destroy.apply(this, arguments);
  };

  ApplicationPreviewWindow.prototype._onDndEvent = function(ev, type, item, args) {
    Window.prototype._onDndEvent.apply(this, arguments);
    if ( type === 'itemDrop' && item ) {
      var data = item.data;
      if ( data && data.type === 'file' && data.mime ) {
        this._appRef.action('open', data.path, data.mime);
      }
    }
  };

  ApplicationPreviewWindow.prototype.setPreview = function(t, mime) {
    console.log("ApplicationPreviewWindow::setPreview()", t, mime);

    if ( this.previewElement && this.previewElement.parentNode ) {
      this.previewElement.parentNode.removeChild(this.previewElement);
      this.previewElement = null;
    }

    var el;
    if ( mime ) {
      if ( !mime.match(/^(image|video|audio)/) ) {
        OSjs.API.error("Preview", "Cannot open file", "Not supported!");
        return;
      }

      if ( t ) {
        try {
          var src = OSjs.API.getFilesystemURL(t);
          if ( mime.match(/^image/) ) {
            el = document.createElement('img');
            el.alt = t;
            el.src = src;
          } else if ( mime.match(/^audio/) ) {
            el = document.createElement('audio');
            el.controls = "controls";
            el.autoplay = "autoplay";
            el.src = src;
          } else if ( mime.match(/^video/) ) {
            el = document.createElement('video');
            el.controls = "controls";
            el.autoplay = "autoplay";
            el.src = src;
          }
        } catch ( e ) {
          console.warn("Preview error: " + e);
        }
      }
    }

    if ( el ) {
      this.previewElement = el;
      this.$frame.appendChild(this.previewElement);

      if ( el.tagName !== 'IMG' ) {
        this._resize(500, 400);
      }
    }

    this._setTitle(t ? (this.title + " - " + t) : this.title);
  };

  ApplicationPreviewWindow.prototype._resize = function(w, h) {
    if ( !Window.prototype._resize.apply(this, arguments) ) return false;

    if ( this.previewElement && this.previewElement.tagName !== 'IMG' ) {
      if ( this.previewElement.parentNode ) {
        this.previewElement.width  = this.previewElement.parentNode.offsetWidth;
        this.previewElement.height = this.previewElement.parentNode.offsetHeight;
      }
    }

    return true;
  };

  /**
   * Application
   */
  var ApplicationPreview = function(args, metadata) {
    Application.apply(this, ['ApplicationPreview', args, metadata]);
  };

  ApplicationPreview.prototype = Object.create(Application.prototype);

  ApplicationPreview.prototype.destroy = function() {
    return Application.prototype.destroy.apply(this, []);
  };

  ApplicationPreview.prototype.init = function(core, session) {
    Application.prototype.init.apply(this, arguments);

    this._addWindow(new ApplicationPreviewWindow(this, {width: 400, height: 200}));

    var open = this._getArgument('file');
    var mime = this._getArgument('mime');
    if ( open ) {
      this.action('open', open, mime);
    }
  };

  ApplicationPreview.prototype._onMessage = function(obj, msg, args) {
    Application.prototype._onMessage.apply(this, arguments);

    if ( msg == 'destroyWindow' && obj._name === 'ApplicationPreviewWindow' ) {
      this.destroy();
    }
  };

  ApplicationPreview.prototype.action = function(action, fname, mime) {
    var w = this._getWindow('ApplicationPreviewWindow');
    if ( !w ) return;
    var self = this;
    switch ( action ) {
      case 'close' :
        this.destroy();
      break;

      case 'open' :
        var _open = function(fname, rmime) {
          if ( fname ) {
            w.setPreview(fname, (mime || rmime) || null);
            self._setArgument('file', fname);
            self._setArgument('mime', (mime || rmime) || null);
          }
        };

        if ( fname ) {
          _open(fname);
        } else {
          this._createDialog('File', [{type: 'open', mimes: ['^image', '^audio', '^video']}, function(btn, fname, rmime) {
            if ( btn !== 'ok' ) return;
            _open(fname, (mime || rmime));
          }], w);
        }
      break;
    }
  };

  //
  // EXPORTS
  //
  OSjs.Applications = OSjs.Applications || {};
  OSjs.Applications.ApplicationPreview = ApplicationPreview;

})(OSjs.Core.Application, OSjs.Core.Window);
<|endoftext|>


<commit_before>// Mozilla User Preferences
//dennyhalim.com
//http://kb.mozillazine.org/User.js_file
//http://kb.mozillazine.org/Locking_preferences
//https://developer.mozilla.org/en-US/docs/Mozilla/Preferences/A_brief_guide_to_Mozilla_preferences
pref("app.update.channel", "esr");
user_pref("browser.sessionhistory.max_entries", 10);
user_pref("devtools.memory.enabled", false);
user_pref("browser.cache.memory.enable", false);
user_pref("dom.serviceWorkers.enabled", false);
user_pref("network.cookie.cookieBehavior", 3);
user_pref("network.cookie.lifetimePolicy", 2);
user_pref("privacy.clearOnShutdown.cache", true);
user_pref("privacy.clearOnShutdown.offlineApps", true);
user_pref("privacy.sanitize.pending", "[{\"id\":\"shutdown\",\"itemsToClear\":[\"cache\",\"offlineApps\"],\"options\":{}}]");
//user_pref("privacy.sanitize.pending", "[{\"id\":\"shutdown\",\"itemsToClear\":[\"cache\",\"cookies\",\"offlineApps\",\"formdata\",\"sessions\",\"siteSettings\"],\"options\":{}}]");
user_pref("privacy.sanitize.sanitizeOnShutdown", true);
user_pref("privacy.donottrackheader.enabled", true);
user_pref("privacy.trackingprotection.enabled", true);
user_pref("dom.webnotifications.enabled", false);
user_pref("dom.webnotifications.serviceworker.enabled", false);
user_pref("browser.urlbar.placeholderName", "DuckDuckGo");
user_pref("geo.enabled", false);
user_pref("geo.provider.ms-windows-location", false);
user_pref("geo.provider.use_corelocation", false);
user_pref("geo.provider.use_gpsd", false);
user_pref("toolkit.telemetry.unified", false);
user_pref("toolkit.telemetry.enabled", false);
user_pref("network.trr.mode", 2);
user_pref("network.trr.uri", "https://doh.cleanbrowsing.org/doh/adult-filter/");  //https://cleanbrowsing.org/dnsoverhttps
user_pref("dom.netinfo.enabled", false);
user_pref("media.video_stats.enabled", false);
//user_pref("dom.maxHardwareConcurrency", 1); //faster on slow devices
user_pref("dom.battery.enabled", false);
user_pref("dom.telephony.enabled", false);
user_pref("beacon.enabled", false);
user_pref("device.sensors.enabled", false);
user_pref("dom.vibrator.enabled", false);
user_pref("dom.enable_resource_timing", false);
<commit_msg>Update firefox-user.js<commit_after>// Mozilla User Preferences
//dennyhalim.com
//http://kb.mozillazine.org/User.js_file
//http://kb.mozillazine.org/Locking_preferences
//https://developer.mozilla.org/en-US/docs/Mozilla/Preferences/A_brief_guide_to_Mozilla_preferences
pref("app.update.channel", "esr");
user_pref("browser.sessionhistory.max_entries", 10);
user_pref("devtools.memory.enabled", false);
user_pref("browser.cache.memory.enable", false);
user_pref("dom.serviceWorkers.enabled", false);
user_pref("network.cookie.cookieBehavior", 3);
user_pref("network.cookie.lifetimePolicy", 2);
user_pref("privacy.clearOnShutdown.cache", true);
user_pref("privacy.clearOnShutdown.offlineApps", true);
user_pref("privacy.sanitize.pending", "[{\"id\":\"shutdown\",\"itemsToClear\":[\"cache\",\"offlineApps\"],\"options\":{}}]");
//user_pref("privacy.sanitize.pending", "[{\"id\":\"shutdown\",\"itemsToClear\":[\"cache\",\"cookies\",\"offlineApps\",\"formdata\",\"sessions\",\"siteSettings\"],\"options\":{}}]");
user_pref("privacy.sanitize.sanitizeOnShutdown", true);
user_pref("privacy.donottrackheader.enabled", true);
user_pref("privacy.trackingprotection.enabled", true);
user_pref("dom.webnotifications.enabled", false);
user_pref("dom.webnotifications.serviceworker.enabled", false);
user_pref("browser.urlbar.placeholderName", "DuckDuckGo");
user_pref("geo.enabled", false);
user_pref("geo.provider.ms-windows-location", false);
user_pref("geo.provider.use_corelocation", false);
user_pref("geo.provider.use_gpsd", false);
user_pref("toolkit.telemetry.unified", false);
user_pref("toolkit.telemetry.enabled", false);
user_pref("toolkit.telemetry.archive.enabled", false);
user_pref("network.trr.mode", 2);
user_pref("network.trr.uri", "https://doh.cleanbrowsing.org/doh/adult-filter/");  //https://cleanbrowsing.org/dnsoverhttps
user_pref("dom.netinfo.enabled", false);
user_pref("media.video_stats.enabled", false);
//user_pref("dom.maxHardwareConcurrency", 1); //faster on slow devices
user_pref("dom.battery.enabled", false);
user_pref("dom.telephony.enabled", false);
user_pref("beacon.enabled", false);
user_pref("device.sensors.enabled", false);
user_pref("dom.vibrator.enabled", false);
user_pref("dom.enable_resource_timing", false);
<|endoftext|>


<commit_before>// Mozilla User Preferences
//dennyhalim.com
//http://kb.mozillazine.org/User.js_file
//http://kb.mozillazine.org/Locking_preferences
//https://developer.mozilla.org/en-US/docs/Mozilla/Preferences/A_brief_guide_to_Mozilla_preferences
pref("app.update.channel", "esr");
user_pref("browser.sessionhistory.max_entries", 10);
user_pref("devtools.memory.enabled", false);
user_pref("browser.cache.memory.enable", false);
user_pref("dom.serviceWorkers.enabled", false);
user_pref("network.cookie.cookieBehavior", 3);
user_pref("network.cookie.lifetimePolicy", 2);
user_pref("privacy.clearOnShutdown.cache", true);
user_pref("privacy.clearOnShutdown.offlineApps", true);
user_pref("privacy.sanitize.pending", "[{\"id\":\"shutdown\",\"itemsToClear\":[\"cache\",\"offlineApps\"],\"options\":{}}]");
//user_pref("privacy.sanitize.pending", "[{\"id\":\"shutdown\",\"itemsToClear\":[\"cache\",\"cookies\",\"offlineApps\",\"formdata\",\"sessions\",\"siteSettings\"],\"options\":{}}]");
user_pref("privacy.sanitize.sanitizeOnShutdown", true);
user_pref("privacy.donottrackheader.enabled", true);
user_pref("privacy.trackingprotection.enabled", true);
user_pref("dom.webnotifications.enabled", false);
user_pref("dom.webnotifications.serviceworker.enabled", false);
user_pref("browser.urlbar.placeholderName", "DuckDuckGo");
user_pref("geo.enabled", false);
user_pref("geo.provider.ms-windows-location", false);
user_pref("geo.provider.use_corelocation", false);
user_pref("geo.provider.use_gpsd", false);
user_pref("toolkit.telemetry.unified", false);
user_pref("toolkit.telemetry.enabled", false);
user_pref("network.trr.mode", 2);
user_pref("network.trr.uri", "https://doh.cleanbrowsing.org/doh/adult-filter/");  //https://cleanbrowsing.org/dnsoverhttps
user_pref("dom.netinfo.enabled", false);
user_pref("media.video_stats.enabled", false);
//user_pref("dom.maxHardwareConcurrency", 1); //faster on slow devices
<commit_msg>Update firefox-user.js<commit_after>// Mozilla User Preferences
//dennyhalim.com
//http://kb.mozillazine.org/User.js_file
//http://kb.mozillazine.org/Locking_preferences
//https://developer.mozilla.org/en-US/docs/Mozilla/Preferences/A_brief_guide_to_Mozilla_preferences
pref("app.update.channel", "esr");
user_pref("browser.sessionhistory.max_entries", 10);
user_pref("devtools.memory.enabled", false);
user_pref("browser.cache.memory.enable", false);
user_pref("dom.serviceWorkers.enabled", false);
user_pref("network.cookie.cookieBehavior", 3);
user_pref("network.cookie.lifetimePolicy", 2);
user_pref("privacy.clearOnShutdown.cache", true);
user_pref("privacy.clearOnShutdown.offlineApps", true);
user_pref("privacy.sanitize.pending", "[{\"id\":\"shutdown\",\"itemsToClear\":[\"cache\",\"offlineApps\"],\"options\":{}}]");
//user_pref("privacy.sanitize.pending", "[{\"id\":\"shutdown\",\"itemsToClear\":[\"cache\",\"cookies\",\"offlineApps\",\"formdata\",\"sessions\",\"siteSettings\"],\"options\":{}}]");
user_pref("privacy.sanitize.sanitizeOnShutdown", true);
user_pref("privacy.donottrackheader.enabled", true);
user_pref("privacy.trackingprotection.enabled", true);
user_pref("dom.webnotifications.enabled", false);
user_pref("dom.webnotifications.serviceworker.enabled", false);
user_pref("browser.urlbar.placeholderName", "DuckDuckGo");
user_pref("geo.enabled", false);
user_pref("geo.provider.ms-windows-location", false);
user_pref("geo.provider.use_corelocation", false);
user_pref("geo.provider.use_gpsd", false);
user_pref("toolkit.telemetry.unified", false);
user_pref("toolkit.telemetry.enabled", false);
user_pref("network.trr.mode", 2);
user_pref("network.trr.uri", "https://doh.cleanbrowsing.org/doh/adult-filter/");  //https://cleanbrowsing.org/dnsoverhttps
user_pref("dom.netinfo.enabled", false);
user_pref("media.video_stats.enabled", false);
//user_pref("dom.maxHardwareConcurrency", 1); //faster on slow devices
user_pref("dom.battery.enabled", false);
user_pref("dom.telephony.enabled", false);
user_pref("beacon.enabled", false);
user_pref("device.sensors.enabled", false);
user_pref("dom.vibrator.enabled", false);
user_pref("dom.enable_resource_timing", false);
<|endoftext|>


<commit_before>#!/usr/bin/env node
var connect = require('connect'),
	colors = require('colors'),
	WebSocket = require('faye-websocket'),
	path = require('path'),
	url = require('url'),
	http = require('http'),
	send = require('send'),
	open = require('open'),
	watchr = require('watchr'),
	ws;

var INJECTED_CODE = require('fs').readFileSync(__dirname + "/injected.html", "utf8");

function escape(html){
	return String(html)
		.replace(/&(?!\w+;)/g, '&')
		.replace(/</g, '<')
		.replace(/>/g, '>')
		.replace(/"/g, '"');
}

// Based on connect.static(), but streamlined and with added code injecter
function staticServer(root) {
	return function(req, res, next) {
		if ('GET' != req.method && 'HEAD' != req.method) return next();
		var reqpath = url.parse(req.url).pathname;

		function directory() {
			var pathname = url.parse(req.originalUrl).pathname;
			res.statusCode = 301;
			res.setHeader('Location', pathname + '/');
			res.end('Redirecting to ' + escape(pathname) + '/');
		}

		function error(err) {
			if (404 == err.status) return next();
			next(err);
		}

		function inject(stream) {
			var x = path.extname(reqpath);
			if (x === "" || x == ".html" || x == ".htm" || x == ".xhtml" || x == ".php") {
				// We need to modify the length given to browser
				var len = INJECTED_CODE.length + res.getHeader('Content-Length');
				res.setHeader('Content-Length', len);
				// Write the injected code
				res.write(INJECTED_CODE);
			}
		}

		send(req, reqpath)
			.root(root)
			.on('error', error)
			.on('stream', inject)
			.on('directory', directory)
			.pipe(res);
	};
}

function start(port, directory) {
	port = port || 8080;
	directory = directory || process.cwd();
	// Setup a web server
	var app = connect()
		.use(staticServer(directory)) // Custom static server
		.use(connect.directory(directory, { icons: true }))
		.use(connect.logger('dev'));
	var server = http.createServer(app).listen(port);
	// WebSocket
	server.addListener('upgrade', function(request, socket, head) {
		ws = new WebSocket(request, socket, head);
		ws.onopen = function() { ws.send('connected'); };
	});
	// Setup file watcher
	watchr.watch({
		path: directory,
		ignorePatterns: true,
		ignoreHiddenFiles: true,
		listener: function(eventName, filePath, fileCurrentStat, filePreviousStat) {
			if (!ws) return;
			if (path.extname(filePath) == ".css") ws.send('refreshcss');
			else ws.send('reload');
		}
	});
	// Output
	console.log(('Serving "' + directory + '" at http://localhost:' + port).green);
	// Launch browser
	open('http://localhost:' + port);
}

start(process.env.PORT);
<commit_msg>Allow specifying the directory to serve.<commit_after>#!/usr/bin/env node
var connect = require('connect'),
	colors = require('colors'),
	WebSocket = require('faye-websocket'),
	path = require('path'),
	url = require('url'),
	http = require('http'),
	send = require('send'),
	open = require('open'),
	watchr = require('watchr'),
	ws;

var INJECTED_CODE = require('fs').readFileSync(__dirname + "/injected.html", "utf8");

function escape(html){
	return String(html)
		.replace(/&(?!\w+;)/g, '&')
		.replace(/</g, '<')
		.replace(/>/g, '>')
		.replace(/"/g, '"');
}

// Based on connect.static(), but streamlined and with added code injecter
function staticServer(root) {
	return function(req, res, next) {
		if ('GET' != req.method && 'HEAD' != req.method) return next();
		var reqpath = url.parse(req.url).pathname;

		function directory() {
			var pathname = url.parse(req.originalUrl).pathname;
			res.statusCode = 301;
			res.setHeader('Location', pathname + '/');
			res.end('Redirecting to ' + escape(pathname) + '/');
		}

		function error(err) {
			if (404 == err.status) return next();
			next(err);
		}

		function inject(stream) {
			var x = path.extname(reqpath);
			if (x === "" || x == ".html" || x == ".htm" || x == ".xhtml" || x == ".php") {
				// We need to modify the length given to browser
				var len = INJECTED_CODE.length + res.getHeader('Content-Length');
				res.setHeader('Content-Length', len);
				// Write the injected code
				res.write(INJECTED_CODE);
			}
		}

		send(req, reqpath)
			.root(root)
			.on('error', error)
			.on('stream', inject)
			.on('directory', directory)
			.pipe(res);
	};
}

function start(port, directory) {
	port = port || 8080;
	directory = directory || process.cwd();
	// Setup a web server
	var app = connect()
		.use(staticServer(directory)) // Custom static server
		.use(connect.directory(directory, { icons: true }))
		.use(connect.logger('dev'));
	var server = http.createServer(app).listen(port);
	// WebSocket
	server.addListener('upgrade', function(request, socket, head) {
		ws = new WebSocket(request, socket, head);
		ws.onopen = function() { ws.send('connected'); };
	});
	// Setup file watcher
	watchr.watch({
		path: directory,
		ignorePatterns: true,
		ignoreHiddenFiles: true,
		listener: function(eventName, filePath, fileCurrentStat, filePreviousStat) {
			if (!ws) return;
			if (path.extname(filePath) == ".css") ws.send('refreshcss');
			else ws.send('reload');
		}
	});
	// Output
	console.log(('Serving "' + directory + '" at http://localhost:' + port).green);
	// Launch browser
	open('http://localhost:' + port);
}

if (process.argv[2])
	process.chdir(process.argv[2]);

start(process.env.PORT);
<|endoftext|>


<commit_before>module.exports = {

  load: function() {
    return require(__LORE_ROOT__ + '/routes.js');
  }

};
<commit_msg>[lore] ES6 hack to load project routes correctly<commit_after>module.exports = {

  load: function() {
    var routes = require(__LORE_ROOT__ + '/routes.js');

    // ES6 hack around: return .default if it exists.
    return routes.default ? routes.default : routes;
  }

};
<|endoftext|>


<commit_before>Package.describe({
  name: 'meteor-autosize',
  summary: 'Automatically adjust textarea height based on user input.',
  version: '5.0.1',
  git: "https://github.com/DeDeSt/meteor-autosize.git",
  documentation: 'README.md'
});

Package.on_use(function (api) {
  api.versionsFrom("METEOR@0.9.0");
  api.add_files(['lib/autosize.js'], 'client');
});
<commit_msg>meteor-autosize, on_use replaced with onUse, add_files replaced with addFiles<commit_after>Package.describe({
  name: 'meteor-autosize',
  summary: 'Automatically adjust textarea height based on user input.',
  version: '5.0.1',
  git: "https://github.com/DeDeSt/meteor-autosize.git",
  documentation: 'README.md'
});

Package.onUse(function (api) {
  api.versionsFrom("METEOR@0.9.0");
  api.addFiles(['lib/autosize.js'], 'client');
});
<|endoftext|>


<commit_before>Package.describe({
  summary: "Include a standard set of Meteor packages in your app",
  version: '1.1.2-pre.0'
});

Package.on_use(function(api) {
  // The "imply" here means that if your app uses "meteor-platform", it is
  // treated as if it also directly included all of these packages (and it gets
  // their exports, plugins, etc).
  //
  // If you want, you can "meteor remove meteor-platform" and add some of
  // these back in individually. We haven't tested every subset, though :)
  api.imply([
    // The normal "every package uses 'meteor'" rule only applies to packages
    // built from a package source directory, so we make sure apps get it too.
    // Meteor.isServer! The CSS extension handler! And so much more!
    'meteor',
    // A standard Meteor app is a web app. (Without this, there will be no
    // 'main' function unless you define one yourself.)
    'webapp',
    // It's Log! It's better than bad, it's good!
    'logging',
    // Tracker.autorun and friends. What's Meteor without reactivity?
    'tracker',
    'deps', // XXX COMPAT WITH PACKAGES BUILT FOR 0.9.0.
    // The easiest way to get a little reactivity into your app.
    'session',
    // DDP: Meteor's client/server protocol.
    'ddp',
    'livedata', // XXX COMPAT WITH PACKAGES BUILT FOR 0.9.0.
    // You want to keep your data somewhere? How about MongoDB?
    'mongo',
    // Blaze: Reactive DOM!
    'blaze',
    'ui', // XXX COMPAT WITH PACKAGES BUILT FOR 0.9.0.
    // A great template language!
    'spacebars',
    // Turn templates into views!
    'templating',
    // Easy type assertions? check.
    'check',
    // _.isUseful(true)
    'underscore',
    // $(".usefulToo")
    'jquery',
    // Life isn't always predictable.
    'random',
    // People like being able to clone objects.
    'ejson'
  ]);

  // These are useful too!  But you don't have to see their exports
  // unless you want to.
  api.use([
    // We can reload the client without messing up methods in flight.
    'reload',
    // And update automatically when new client code is available!
    'autoupdate'
  ], ['client', 'server']);

  api.use([
    // Remove the 300ms click delay on mobile
    'fastclick',
    // Good defaults for the mobile status bar
    'mobile-status-bar'
  ], 'web.cordova');
});

Cordova.depends({
  'org.apache.cordova.device': '0.2.11',
  'com.meteor.cordova-update': 'https://github.com/meteor/com.meteor.cordova-update/tarball/31640d593ac99012cd7670295ebbec40ffa7f3f0'
});
<commit_msg>bump the version of cordova-update<commit_after>Package.describe({
  summary: "Include a standard set of Meteor packages in your app",
  version: '1.1.2-pre.0'
});

Package.on_use(function(api) {
  // The "imply" here means that if your app uses "meteor-platform", it is
  // treated as if it also directly included all of these packages (and it gets
  // their exports, plugins, etc).
  //
  // If you want, you can "meteor remove meteor-platform" and add some of
  // these back in individually. We haven't tested every subset, though :)
  api.imply([
    // The normal "every package uses 'meteor'" rule only applies to packages
    // built from a package source directory, so we make sure apps get it too.
    // Meteor.isServer! The CSS extension handler! And so much more!
    'meteor',
    // A standard Meteor app is a web app. (Without this, there will be no
    // 'main' function unless you define one yourself.)
    'webapp',
    // It's Log! It's better than bad, it's good!
    'logging',
    // Tracker.autorun and friends. What's Meteor without reactivity?
    'tracker',
    'deps', // XXX COMPAT WITH PACKAGES BUILT FOR 0.9.0.
    // The easiest way to get a little reactivity into your app.
    'session',
    // DDP: Meteor's client/server protocol.
    'ddp',
    'livedata', // XXX COMPAT WITH PACKAGES BUILT FOR 0.9.0.
    // You want to keep your data somewhere? How about MongoDB?
    'mongo',
    // Blaze: Reactive DOM!
    'blaze',
    'ui', // XXX COMPAT WITH PACKAGES BUILT FOR 0.9.0.
    // A great template language!
    'spacebars',
    // Turn templates into views!
    'templating',
    // Easy type assertions? check.
    'check',
    // _.isUseful(true)
    'underscore',
    // $(".usefulToo")
    'jquery',
    // Life isn't always predictable.
    'random',
    // People like being able to clone objects.
    'ejson'
  ]);

  // These are useful too!  But you don't have to see their exports
  // unless you want to.
  api.use([
    // We can reload the client without messing up methods in flight.
    'reload',
    // And update automatically when new client code is available!
    'autoupdate'
  ], ['client', 'server']);

  api.use([
    // Remove the 300ms click delay on mobile
    'fastclick',
    // Good defaults for the mobile status bar
    'mobile-status-bar'
  ], 'web.cordova');
});

Cordova.depends({
  'org.apache.cordova.device': '0.2.11',
  'com.meteor.cordova-update': 'https://github.com/meteor/com.meteor.cordova-update/tarball/0e10582dd4998bfc5f39455591ce450f9ec2c2cd'
});
<|endoftext|>


<commit_before>function topPosition(domElt) {
  if (!domElt) {
    return 0;
  }
  return domElt.offsetTop + topPosition(domElt.offsetParent);
}

module.exports = function (React) {
  if (React.addons && React.addons.InfiniteScroll) {
    return React.addons.InfiniteScroll;
  }
  React.addons = React.addons || {};
  var InfiniteScroll = React.addons.InfiniteScroll = React.createClass({
    getDefaultProps: function () {
      return {
        pageStart: 0,
        hasMore: false,
        loadMore: function () {},
        threshold: 250,
        loader: InfiniteScroll._defaultLoader
      };
    },
    getInitialState: function () {
      this.pageLoaded = this.props.pageStart;
    },
    componentDidMount: function () {
      this.attachScrollListener();
    },
    componentDidUpdate: function () {
      this.attachScrollListener();
    },
    render: function () {
      var props = this.props;
      return React.DOM.div(null, props.children, props.hasMore && props.loader);
    },
    scrollListener: function () {
      var el = this.getDOMNode();
      var scrollTop = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
      if (topPosition(el) + el.offsetHeight - scrollTop - window.innerHeight < Number(this.props.threshold)) {
        this.props.loadMore(this.pageLoaded += 1);
        this.detachScrollListener();
      }
    },
    attachScrollListener: function () {
      if (!this.props.hasMore) {
        return;
      }
      window.addEventListener('scroll', this.scrollListener);
      this.scrollListener();
    },
    detachScrollListener: function () {
      window.removeEventListener('scroll', this.scrollListener);
    },
    componentWillUnmount: function () {
      this.detachScrollListener();
    }
  });
  InfiniteScroll.setDefaultLoader = function (loader) {
    InfiniteScroll._defaultLoader = loader;
  };
  return InfiniteScroll;
};<commit_msg>Allow custom component. Fix updating on mobile page<commit_after>module.exports = function (React) {
  if (React.addons && React.addons.InfiniteScroll) {
    return React.addons.InfiniteScroll;
  }
  React.addons = React.addons || {};
  var InfiniteScroll = React.addons.InfiniteScroll = React.createClass({
    getDefaultProps: function () {
      return {
        pageStart: 0,
        hasMore: false,
        loadMore: function () {},
        threshold: 250,
        loader: InfiniteScroll._defaultLoader,
        component: React.DOM.div
      };
    },
    getInitialState: function () {
      this.pageLoaded = this.props.pageStart;
      this.updated = true;
    },
    componentDidMount: function () {
      this.attachScrollListener();
    },
    componentDidUpdate: function () {
      this.updated = true;
      if (!this.props.hasMore) {
        this.detachScrollListener();
      }
    },
    render: function () {
      var props = this.props;
      return this.transferPropsTo(props.component({
        pageStart: null
      , hasMore: null
      , loadMore: null
      , threshold: null
      , loader: null
      , component: null
      }, props.children, props.hasMore && props.loader));
    },
    scrollListener: function () {
      if (!this.updated) return;
      var coords = this.getDOMNode().getBoundingClientRect();
      var cutoff = (window.innerHeight || document.documentElement.clientHeight) + this.props.threshold;

      if ((coords.bottom >= 0 && coords.left >= 0 && coords.bottom) <= cutoff) {
        this.updated = false;
        this.props.loadMore(this.pageLoaded += 1);
      }
    },
    attachScrollListener: function () {
      if (!this.props.hasMore) {
        return;
      }
      window.addEventListener('scroll', this.scrollListener);
      this.scrollListener();
    },
    detachScrollListener: function () {
      window.removeEventListener('scroll', this.scrollListener);
    },
    componentWillUnmount: function () {
      this.detachScrollListener();
    }
  });
  InfiniteScroll.setDefaultLoader = function (loader) {
    InfiniteScroll._defaultLoader = loader;
  };
  return InfiniteScroll;
};<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import JSONTree from './JSONTree';
import LogMonitorEntryAction from './LogMonitorEntryAction';

function colorFromString(theme, token) {
  const splitToken = token.split('');
  const finalToken = splitToken.concat(splitToken.reverse());
  const number = (parseInt(finalToken, 36) + finalToken.length) % 8;
  const themeNumber = 'base0' + (number + 8).toString(16).toUpperCase();
  return theme[themeNumber];
}

const styles = {
  entry: {
    display: 'block',
    WebkitUserSelect: 'none'
  }
};

export default class LogMonitorEntry {
  static propTypes = {
    index: PropTypes.number.isRequired,
    state: PropTypes.object.isRequired,
    action: PropTypes.object.isRequired,
    select: PropTypes.func.isRequired,
    error: PropTypes.string,
    onActionClick: PropTypes.func.isRequired,
    collapsed: PropTypes.bool
  };

  printState(state, error) {
    let errorText = error;
    if (!errorText) {
      try {
        return <JSONTree theme={this.props.theme} keyName={'state'} data={this.props.select(state)} />;
      } catch (err) {
        errorText = 'Error selecting state.';
      }
    }
    return (

        ({errorText})

    );
  }

  handleActionClick() {
    const { index, onActionClick } = this.props;
    if (index > 0) {
      onActionClick(index);
    }
  }

  render() {
    const { index, error, action, state, collapsed } = this.props;
    const styleEntry = {
      opacity: collapsed ? 0.5 : 1,
      color: colorFromString(this.props.theme, action.type),
      cursor: (index > 0) ? 'pointer' : 'default'
    };
    return (

        <LogMonitorEntryAction
          theme={this.props.theme}
          collapsed={collapsed}
          action={action}
          onClick={::this.handleActionClick}
          style={{...styles.entry, ...styleEntry}}/>
        {!collapsed &&

            {this.printState(state, error)}

        }

    );
  }
}
<commit_msg>fixed error display<commit_after>import React, { PropTypes } from 'react';
import JSONTree from './JSONTree';
import LogMonitorEntryAction from './LogMonitorEntryAction';

function colorFromString(theme, token) {
  const splitToken = token.split('');
  const finalToken = splitToken.concat(splitToken.reverse());
  const number = (parseInt(finalToken, 36) + finalToken.length) % 8;
  const themeNumber = 'base0' + (number + 8).toString(16).toUpperCase();
  return theme[themeNumber];
}

const styles = {
  entry: {
    display: 'block',
    WebkitUserSelect: 'none'
  }
};

export default class LogMonitorEntry {
  static propTypes = {
    index: PropTypes.number.isRequired,
    state: PropTypes.object.isRequired,
    action: PropTypes.object.isRequired,
    select: PropTypes.func.isRequired,
    error: PropTypes.string,
    onActionClick: PropTypes.func.isRequired,
    collapsed: PropTypes.bool
  };

  printState(state, error) {
    let errorText = error;
    if (!errorText) {
      try {
        return <JSONTree theme={this.props.theme} keyName={'state'} data={this.props.select(state)} />;
      } catch (err) {
        errorText = 'Error selecting state.';
      }
    }
    return (

        ({errorText})

    );
  }

  handleActionClick() {
    const { index, onActionClick } = this.props;
    if (index > 0) {
      onActionClick(index);
    }
  }

  render() {
    const { index, error, action, state, collapsed } = this.props;
    const styleEntry = {
      opacity: collapsed ? 0.5 : 1,
      color: colorFromString(this.props.theme, action.type),
      cursor: (index > 0) ? 'pointer' : 'default'
    };
    return (

        <LogMonitorEntryAction
          theme={this.props.theme}
          collapsed={collapsed}
          action={action}
          onClick={::this.handleActionClick}
          style={{...styles.entry, ...styleEntry}}/>
        {!collapsed &&

            {this.printState(state, error)}

        }

    );
  }
}
<|endoftext|>


<commit_before>var d3, topojson;

function type(d) {
  d.count = +d.count; // coerce to number
  return d;
}

var margin = {top: 20, right: 30, bottom: 30, left: 50},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var x = d3.time.scale()
  .domain([new Date('2002-01-01'), new Date('2013-01-01')])
  .range([0, width]);

//var x = d3.scale.ordinal()
//    .rangeRoundBands([0, width], .1);

var y = d3.scale.linear()
    .range([height, 0]);

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom")
    .ticks(d3.time.years, 1)
    .tickFormat(d3.time.format('%Y'));

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

var chart = d3.select("#demo1")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

d3.csv("/static/proceedings-by-month.csv", type, function(error, data) {
  var yearly_averages = [], month, monthIndex, yearIndex, lineFunction;
  y.domain([0, d3.max(data, function(d) { return d.count; })]);

  chart.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

  chart.append("g")
      .attr("class", "y axis")
      .call(yAxis);

  chart.selectAll(".bar")
      .data(data)
    .enter().append("rect")
      .attr("class", function(d,i) { return d.year%2 ? "bar oddbar" : "bar evenbar"; })
      .attr("x", function(d) { return x(new Date(d.year,d.month,1)) - 7; })
      .attr("y", function(d) { return y(d.count); })
      .attr("height", function(d) { return height - y(d.count); })
      .attr("width", 8);

  for (month=0; month<data.length; month++) {
    monthIndex = month%12;
    yearIndex = Math.floor(month/12);
    if (monthIndex === 0) {
      yearly_averages[yearIndex] = {average: 0, year: 2002+yearIndex};
    }
    yearly_averages[yearIndex].average += data[month].count/12;
  }

  lineFunction = d3.svg.line()
    .x(function(d) { return x(new Date(d.year,7,1)); })
    .y(function(d) { return y(d.average); })
    .interpolate("linear");

  chart
    .append("path")
    .attr("class","line")
    .attr("d", lineFunction(yearly_averages));
});

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Map

width = 1000;
height = 800;

var svg = d3.select("#demo2")
  .attr("width", width)
  .attr("height", height);

var projection = d3.geo.albers()
    .center([0, 53])
    .rotate([4.4, 0])
    .parallels([50, 60])
    .scale(1450 * 5)
    .translate([-200+width / 2, height / 2]);

var path = d3.geo.path()
    .projection(projection);

d3.json("/static/uk.json", function(error, uk) {
  svg
    .append("path")
    .datum(topojson.feature(uk, uk.objects.subunits))
    .attr("class","subunit")
    .attr("d", path);

  d3.json("/static/court-locations.json", function(error, topology) {
    d3.csv("/static/ages.csv", function(error, court_ages) {
      function averageAge(courtNumber) {
        var court;
        for (court in court_ages) {
          if (court_ages[court].court == courtNumber) {
            return court_ages[court].avg;
          }
        }
        return 0;
      }

      var courts = topojson.feature(topology, topology.objects.courts).features;
      courts = courts.filter(function(element) {
        var rgb = averageAge(element.properties.court_number);
        return rgb!=0;
      });

      svg.selectAll("circle")
        .data(courts)
        .enter()
        .append("circle")
        .attr("cx", function(d) {
          return projection(d.geometry.coordinates)[0];
        })
        .attr("cy", function(d) {
          return projection(d.geometry.coordinates)[1];
        })
        .attr("r", 7)
        .style("fill", function(d) {
          var rgb = averageAge(d.properties.court_number);
          rgb = Math.floor(23*(rgb-25));
          return "rgba("+rgb+","+rgb+","+rgb+",1)";
        })
        .on("mouseover", function(e) {
          console.log(e.properties, averageAge(e.properties.court_number));
        })
        .append("title").text(function(d) { return Math.floor(averageAge(d.properties.court_number));});
    });
  });
});
<commit_msg>show court name<commit_after>var d3, topojson;

function type(d) {
  d.count = +d.count; // coerce to number
  return d;
}

var margin = {top: 20, right: 30, bottom: 30, left: 50},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var x = d3.time.scale()
  .domain([new Date('2002-01-01'), new Date('2013-01-01')])
  .range([0, width]);

//var x = d3.scale.ordinal()
//    .rangeRoundBands([0, width], .1);

var y = d3.scale.linear()
    .range([height, 0]);

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom")
    .ticks(d3.time.years, 1)
    .tickFormat(d3.time.format('%Y'));

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

var chart = d3.select("#demo1")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

d3.csv("/static/proceedings-by-month.csv", type, function(error, data) {
  var yearly_averages = [], month, monthIndex, yearIndex, lineFunction;
  y.domain([0, d3.max(data, function(d) { return d.count; })]);

  chart.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

  chart.append("g")
      .attr("class", "y axis")
      .call(yAxis);

  chart.selectAll(".bar")
      .data(data)
    .enter().append("rect")
      .attr("class", function(d,i) { return d.year%2 ? "bar oddbar" : "bar evenbar"; })
      .attr("x", function(d) { return x(new Date(d.year,d.month,1)) - 7; })
      .attr("y", function(d) { return y(d.count); })
      .attr("height", function(d) { return height - y(d.count); })
      .attr("width", 8);

  for (month=0; month<data.length; month++) {
    monthIndex = month%12;
    yearIndex = Math.floor(month/12);
    if (monthIndex === 0) {
      yearly_averages[yearIndex] = {average: 0, year: 2002+yearIndex};
    }
    yearly_averages[yearIndex].average += data[month].count/12;
  }

  lineFunction = d3.svg.line()
    .x(function(d) { return x(new Date(d.year,7,1)); })
    .y(function(d) { return y(d.average); })
    .interpolate("linear");

  chart
    .append("path")
    .attr("class","line")
    .attr("d", lineFunction(yearly_averages));
});

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Map

width = 1000;
height = 800;

var svg = d3.select("#demo2")
  .attr("width", width)
  .attr("height", height);

var projection = d3.geo.albers()
    .center([0, 53])
    .rotate([4.4, 0])
    .parallels([50, 60])
    .scale(1450 * 5)
    .translate([-200+width / 2, height / 2]);

var path = d3.geo.path()
    .projection(projection);

d3.json("/static/uk.json", function(error, uk) {
  svg
    .append("path")
    .datum(topojson.feature(uk, uk.objects.subunits))
    .attr("class","subunit")
    .attr("d", path);

  d3.json("/static/court-locations.json", function(error, topology) {
    d3.csv("/static/ages.csv", function(error, court_ages) {
      function averageAge(courtNumber) {
        var court;
        for (court in court_ages) {
          if (court_ages[court].court == courtNumber) {
            return court_ages[court].avg;
          }
        }
        return 0;
      }

      var courts = topojson.feature(topology, topology.objects.courts).features;
      courts = courts.filter(function(element) {
        return averageAge(element.properties.court_number) != 0;
      });

      svg.selectAll("circle")
        .data(courts)
        .enter()
        .append("circle")
        .attr("cx", function(d) {
          return projection(d.geometry.coordinates)[0];
        })
        .attr("cy", function(d) {
          return projection(d.geometry.coordinates)[1];
        })
        .attr("r", 7)
        .style("fill", function(d) {
          var rgb = averageAge(d.properties.court_number);
          rgb = Math.floor(23*(rgb-25));
          return "rgba("+rgb+","+rgb+","+rgb+",1)";
        })
        .append("title").text(function(d) { return d.properties.name+": "+Math.floor(averageAge(d.properties.court_number))+" years old";});
    });
  });
});
<|endoftext|>


<commit_before>var YamcsWebSocket = function(instance) {
    var PROTOCOL_VERSION=1;
    var MESSAGE_TYPE_REQUEST=1;
    var MESSAGE_TYPE_REPLY=2;
    var MESSAGE_TYPE_EXCEPTION=3;
    var MESSAGE_TYPE_DATA=4;

    var requestSeqCount=-1;
    var wsproto = "ws";

    if(window.location.protocol=='https:') {
        wsproto = "wss"
    }
    var conn = new WebSocket(wsproto+"://"+window.location.host+"/"+instance+"/_websocket");

    var dataCallbacks = {};
    var exceptionHandlers = {};
    var replyHandlers = {};
    var invalidDataBindings={};

    /*
     * Web Socket Protocol Handling.
     * Each message sent is a list [1=protoversion, 1=request, request id, request object]
     * The message received back has to contain the same id and can be of type reply or exception
     */

    conn.onmessage = function(msg) {
        var json = JSON.parse(msg.data)
        switch(json[1]) {
        case MESSAGE_TYPE_REPLY:
            dispatchReply(json[2], json[3]);
            break;
        case MESSAGE_TYPE_EXCEPTION:
            dispatchException(json[2], json[3]);
            break;
        case MESSAGE_TYPE_DATA:
            var data=json[3];
            dispatchData(data.dt, data.data);
            break;
        }
    };

    conn.onclose = function(event){dispatchData('close',event)}
    conn.onopen = function(){dispatchData('open',null)}

    var sendRequest = function(requestName, requestData, replyHandler, exceptionHandler){
        requestSeqCount++;
        if(replyHandler) replyHandlers[requestSeqCount]=replyHandler;
        if(exceptionHandler) exceptionHandlers[requestSeqCount]=exceptionHandler;
        var payload = JSON.stringify([PROTOCOL_VERSION, MESSAGE_TYPE_REQUEST, requestSeqCount, {request:requestName, data: requestData}]);
        conn.send( payload ); // <= send JSON data to socket server
        return this;
    };

    var dispatchException = function(requestId, data) {
       var h = exceptionHandlers[requestId];
       delete exceptionHandlers[requestId];
       delete replyHandlers[requestId];

       if(h === undefined) {
           console.log("Exception received for request id "+requestId+", and no handler available. Exception data: ", data);
           return;
       }
       h(data.et, data.msg);
   }

   var dispatchReply = function(requestId, data) {
       var h = replyHandlers[requestId];
       delete exceptionHandlers[requestId];
       delete replyHandlers[requestId];

       if(h === undefined)  return;
       h(data);
   }

    this.bindDataHandler = function(dataType, callback){
        dataCallbacks[dataType] = dataCallbacks[dataType] || [];
        dataCallbacks[dataType].push(callback);
        return this;// chainable
    };

    var dispatchData = function(dataType, message) {
        var chain = dataCallbacks[dataType];
        if(chain == undefined) return; // no callbacks for this event
        for(var i = 0; i < chain.length; i++){
            chain[i]( message )
        }
    }

    this.isConnected = function() {
        return conn.readyState == WebSocket.OPEN;
    }

/************** Parameter subscription (could be moved to its own 'class' *************/
    var subscribedParameters = {}; //this collects the databindings from all the open displays

    var addSubscribedParameter = function(paraname, p) {
       var dbs=subscribedParameters[paraname];
       if(!dbs) {
           dbs = [];
           subscribedParameters[paraname]=dbs;
       }
       var pdb = p.bindings;
       for(var j = 0; j < pdb.length; j++){
           dbs.push(pdb[j]);
       }
    }

    var doSubscribeParameters = function(parameters, addToList) {
        var paraList=[];
        for(var paraname in parameters) {
            var p=parameters[paraname];
            if (p.type=='ExternalDataSource') {
                if(addToList) addSubscribedParameter(paraname, p);
                paraList.push({name: paraname, namespace: 'MDB:OPS Name'});
            }
        }
        if(paraList.length==0) return;
        //console.log(paraList);
        var that=this;
        sendRequest("subscribe", {list: paraList}, null,
            function(exceptionType, exceptionMsg) { //exception handler
                if(exceptionType == 'InvalidIdentification') {
                    var invalidParams=exceptionMsg.list;
                    console.log('The following parameters are invalid: ', invalidParams);
                    for(var i=0; i<invalidParams.length; i++) {
                        var name=invalidParams[i].name;
                        var db=parameters[name];
                        delete parameters[name];
                        invalidDataBindings[name]=db;
                    }
                    console.log('retrying without them');
                    doSubscribeParameters(parameters, false, false);
            } else {
                console.log('got exception from subscription: ',exceptionType, exceptionMsg);
            }
        });
    }

    this.subscribeParameters = function(parameters) {
        doSubscribeParameters(parameters, true);
    }

    var doSubscribeComputations = function(parameters, addToList) {
        var compDefList=[];
        for(var paraname in parameters) {
            var p=parameters[paraname];
            if (p.type=='Computation') {
                var cdef={name: paraname, expression: p.expression, argument: [], language: 'jformula'};
                var args=p.args;
                for(var i=0;i<args.length;i++) {
                    var a=args[i];
                    cdef.argument.push({name: a.Opsname, namespace: 'MDB:OPS Name'});
                }
                compDefList.push(cdef);
                if(addToList) addSubscribedParameter(paraname, p);
            }
        }
        if(compDefList.length == 0) return;
        //console.log(paraList);
        //console.log('compDefList: ', compDefList);
        var that=this;
        sendRequest("subscribeComputations", {compDef: compDefList}, null,
            function(exceptionType, exceptionMsg) { //exception handler
                if(exceptionType == 'InvalidIdentification') {
                    var invalidParams=exceptionMsg.list;
                    console.log('The following parameters are invalid: ', invalidParams);
                    //remove computations that have as arguments the invalid parameters
                    for(var i=0; i<invalidParams.length; i++) {
                        var invParaName=invalidParams[i].name;
                        var cnameToRemove=null;
                        for(var paraname in parameters) {
                            var p=parameters[paraname];
                            if (p.type=='Computation') {
                                var args=p.args;
                                for(var k=0; k<args.length; k++) {
                                    var a=args[k];
                                    if(invParaName == a.Opsname) {
                                        cnameToRemove = paraname;
                                        break;
                                    }
                                }
                            if(cnameToRemove) break;
                            }
                        }
                        if(cnameToRemove) {
                            var db=parameters[cnameToRemove];
                            delete parameters[cnameToRemove];
                            invalidDataBindings[cnameToRemove]=db;
                        }
                    }
                    console.log('retrying without them');
                    doSubscribeComputations(parameters, false);
                } else {
                    console.log('got exception from subscription: ',exceptionType, exceptionMsg);
                }
            });
    }

    this.subscribeComputations = function(parameters) {
        doSubscribeComputations(parameters,true)
    }

    this.bindDataHandler('ParameterData', function(pdata){
        var params=pdata.parameter;
        for(var i=0; i<params.length; i++) {
            var p=params[i];
            var dbs = subscribedParameters[p.id.name];
            if(!dbs) {
                console.log("cannot find bindings for "+ p.id.name, subscribedParameters);
            }
            for(var j = 0; j < dbs.length; j++){
                USS.updateWidget(dbs[j], p);
            }
        }
    });
};
<commit_msg>fixed the data type<commit_after>var YamcsWebSocket = function(instance) {
    var PROTOCOL_VERSION=1;
    var MESSAGE_TYPE_REQUEST=1;
    var MESSAGE_TYPE_REPLY=2;
    var MESSAGE_TYPE_EXCEPTION=3;
    var MESSAGE_TYPE_DATA=4;

    var requestSeqCount=-1;
    var wsproto = "ws";

    if(window.location.protocol=='https:') {
        wsproto = "wss"
    }
    var conn = new WebSocket(wsproto+"://"+window.location.host+"/"+instance+"/_websocket");

    var dataCallbacks = {};
    var exceptionHandlers = {};
    var replyHandlers = {};
    var invalidDataBindings={};

    /*
     * Web Socket Protocol Handling.
     * Each message sent is a list [1=protoversion, 1=request, request id, request object]
     * The message received back has to contain the same id and can be of type reply or exception
     */

    conn.onmessage = function(msg) {
        var json = JSON.parse(msg.data)

        switch(json[1]) {
        case MESSAGE_TYPE_REPLY:
            dispatchReply(json[2], json[3]);
            break;
        case MESSAGE_TYPE_EXCEPTION:
            dispatchException(json[2], json[3]);
            break;
        case MESSAGE_TYPE_DATA:
            var data=json[3];
            dispatchData(data.dt, data.data);
            break;
        }
    };

    conn.onclose = function(event){dispatchData('close',event)}
    conn.onopen = function(){dispatchData('open',null)}

    var sendRequest = function(requestName, requestData, replyHandler, exceptionHandler){
        requestSeqCount++;
        if(replyHandler) replyHandlers[requestSeqCount]=replyHandler;
        if(exceptionHandler) exceptionHandlers[requestSeqCount]=exceptionHandler;
        var payload = JSON.stringify([PROTOCOL_VERSION, MESSAGE_TYPE_REQUEST, requestSeqCount, {request:requestName, data: requestData}]);
        conn.send( payload ); // <= send JSON data to socket server
        return this;
    };

    var dispatchException = function(requestId, data) {
       var h = exceptionHandlers[requestId];
       delete exceptionHandlers[requestId];
       delete replyHandlers[requestId];

       if(h === undefined) {
           console.log("Exception received for request id "+requestId+", and no handler available. Exception data: ", data);
           return;
       }
       h(data.et, data.msg);
   }

   var dispatchReply = function(requestId, data) {
       var h = replyHandlers[requestId];
       delete exceptionHandlers[requestId];
       delete replyHandlers[requestId];

       if(h === undefined)  return;
       h(data);
   }

    this.bindDataHandler = function(dataType, callback){
        dataCallbacks[dataType] = dataCallbacks[dataType] || [];
        dataCallbacks[dataType].push(callback);
        return this;// chainable
    };

    var dispatchData = function(dataType, message) {

        var chain = dataCallbacks[dataType];

        if(chain == undefined) return; // no callbacks for this event

        for(var i = 0; i < chain.length; i++){
            chain[i]( message )
        }
    }

    this.isConnected = function() {
        return conn.readyState == WebSocket.OPEN;
    }

/************** Parameter subscription (could be moved to its own 'class' *************/
    var subscribedParameters = {}; //this collects the databindings from all the open displays

    var addSubscribedParameter = function(paraname, p) {
       var dbs=subscribedParameters[paraname];
       if(!dbs) {
           dbs = [];
           subscribedParameters[paraname]=dbs;
       }
       var pdb = p.bindings;
       for(var j = 0; j < pdb.length; j++){
           dbs.push(pdb[j]);
       }
    }

    var doSubscribeParameters = function(parameters, addToList) {
        var paraList=[];
        for(var paraname in parameters) {
            var p=parameters[paraname];
            if (p.type=='ExternalDataSource') {
                if(addToList) addSubscribedParameter(paraname, p);
                paraList.push({name: paraname, namespace: 'MDB:OPS Name'});
            }
        }
        if(paraList.length==0) return;
        //console.log(paraList);
        var that=this;
        sendRequest("subscribe", {list: paraList}, null,
            function(exceptionType, exceptionMsg) { //exception handler
                if(exceptionType == 'InvalidIdentification') {
                    var invalidParams=exceptionMsg.list;
                    console.log('The following parameters are invalid: ', invalidParams);
                    for(var i=0; i<invalidParams.length; i++) {
                        var name=invalidParams[i].name;
                        var db=parameters[name];
                        delete parameters[name];
                        invalidDataBindings[name]=db;
                    }
                    console.log('retrying without them');
                    doSubscribeParameters(parameters, false, false);
            } else {
                console.log('got exception from subscription: ',exceptionType, exceptionMsg);
            }
        });
    }

    this.subscribeParameters = function(parameters) {
        doSubscribeParameters(parameters, true);
    }

    var doSubscribeComputations = function(parameters, addToList) {
        var compDefList=[];
        for(var paraname in parameters) {
            var p=parameters[paraname];
            if (p.type=='Computation') {
                var cdef={name: paraname, expression: p.expression, argument: [], language: 'jformula'};
                var args=p.args;
                for(var i=0;i<args.length;i++) {
                    var a=args[i];
                    cdef.argument.push({name: a.Opsname, namespace: 'MDB:OPS Name'});
                }
                compDefList.push(cdef);
                if(addToList) addSubscribedParameter(paraname, p);
            }
        }
        if(compDefList.length == 0) return;
        //console.log(paraList);
        //console.log('compDefList: ', compDefList);
        var that=this;
        sendRequest("subscribeComputations", {compDef: compDefList}, null,
            function(exceptionType, exceptionMsg) { //exception handler
                if(exceptionType == 'InvalidIdentification') {
                    var invalidParams=exceptionMsg.list;
                    console.log('The following parameters are invalid: ', invalidParams);
                    //remove computations that have as arguments the invalid parameters
                    for(var i=0; i<invalidParams.length; i++) {
                        var invParaName=invalidParams[i].name;
                        var cnameToRemove=null;
                        for(var paraname in parameters) {
                            var p=parameters[paraname];
                            if (p.type=='Computation') {
                                var args=p.args;
                                for(var k=0; k<args.length; k++) {
                                    var a=args[k];
                                    if(invParaName == a.Opsname) {
                                        cnameToRemove = paraname;
                                        break;
                                    }
                                }
                            if(cnameToRemove) break;
                            }
                        }
                        if(cnameToRemove) {
                            var db=parameters[cnameToRemove];
                            delete parameters[cnameToRemove];
                            invalidDataBindings[cnameToRemove]=db;
                        }
                    }
                    console.log('retrying without them');
                    doSubscribeComputations(parameters, false);
                } else {
                    console.log('got exception from subscription: ',exceptionType, exceptionMsg);
                }
            });
    }

    this.subscribeComputations = function(parameters) {
        doSubscribeComputations(parameters,true)
    }

    this.bindDataHandler('PARAMETER', function(pdata){
        var params=pdata.parameter;
        for(var i=0; i<params.length; i++) {
            var p=params[i];
            var dbs = subscribedParameters[p.id.name];
            if(!dbs) {
                console.log("cannot find bindings for "+ p.id.name, subscribedParameters);
            }
            for(var j = 0; j < dbs.length; j++){
                USS.updateWidget(dbs[j], p);
            }
        }
    });
};
<|endoftext|>


<commit_before>#! /usr/bin/env node
const puppeteer = require('puppeteer');
const webpack = require('webpack');
const config = require('./webpack.config');
const webpackMiddleware = require('webpack-dev-middleware');
const http = require('http');
const path = require('path');
const png = require('pngjs');
const fs = require('fs');
const fse = require('fs-extra');
const pixelmatch = require('pixelmatch');
const yargs = require('yargs');
const log = require('loglevelnext');
const globby = require('globby');
const serveStatic = require('serve-static');

const compiler = webpack(Object.assign({mode: 'development'}, config));

function getHref(entry) {
  return path.dirname(entry).slice(1) + '/';
}

const staticHandler = serveStatic(__dirname);

const defaultHandler = serveStatic(path.join(__dirname, 'default'));

const srcHandler = serveStatic(path.join(__dirname, '..', 'src'));

function indexHandler(req, res) {
  const items = [];
  for (const key in config.entry) {
    const href = getHref(config.entry[key]);
    items.push(`<li><a href="${href}">${href}</a></li>`);
  }
  const markup = `<!DOCTYPE html><body><ul>${items.join('')}</ul></body>`;

  res.writeHead(404, {
    'Content-Type': 'text/html'
  });
  res.end(markup);
}

function notFound(req, res) {
  return () => {
    // first, try the default directory
    if (req.url.match(/^\/cases\/[^\/]+\/(index.html)?$/)) {
      // request for a case index file, and file not found, use default
      req.url = '/index.html';
      return defaultHandler(req, res, () => indexHandler(req, res));
    }

    // next try the src directory (only needed for ol/ol.css)
    return srcHandler(req, res, () => indexHandler(req, res));
  };
}

function serve(options) {
  const webpackHandler = webpackMiddleware(compiler, {
    lazy: true,
    logger: options.log,
    stats: 'minimal'
  });

  return new Promise((resolve, reject) => {
    const server = http.createServer((req, res) => {
      if (req.url === '/favicon.ico') {
        res.writeHead(204);
        res.end();
        return;
      }

      const ext = path.extname(req.url);
      if (ext === '.js' || ext === '.map') {
        webpackHandler(req, res, notFound(req, res));
        return;
      }

      staticHandler(req, res, notFound(req, res));
    });

    server.listen(options.port, options.host, err => {
      if (err) {
        return reject(err);
      }
      const address = server.address();
      options.log.info(`test server listening http://${address.address}:${address.port}/`);
      resolve(() => server.close());
    });
  });
}

function getActualScreenshotPath(entry) {
  return path.join(__dirname, path.dirname(entry), 'actual.png');
}

function getExpectedScreenshotPath(entry) {
  return path.join(__dirname, path.dirname(entry), 'expected.png');
}

function getPassFilePath(entry) {
  return path.join(__dirname, path.dirname(entry), 'pass');
}

function parsePNG(filepath) {
  return new Promise((resolve, reject) => {
    const stream = fs.createReadStream(filepath);
    stream.on('error', err => {
      if (err.code === 'ENOENT') {
        return reject(new Error(`File not found: ${filepath}`));
      }
      reject(err);
    });

    const image = stream.pipe(new png.PNG());
    image.on('parsed', () => resolve(image));
    image.on('error', reject);
  });
}

async function match(actual, expected) {
  const actualImage = await parsePNG(actual);
  const expectedImage = await parsePNG(expected);
  const width = expectedImage.width;
  const height = expectedImage.height;
  if (actualImage.width != width) {
    throw new Error(`Unexpected width for ${actual}: expected ${width}, got ${actualImage.width}`);
  }
  if (actualImage.height != height) {
    throw new Error(`Unexpected height for ${actual}: expected ${height}, got ${actualImage.height}`);
  }
  const count = pixelmatch(actualImage.data, expectedImage.data, null, width, height);
  return count / (width * height);
}

async function getScreenshotsMismatch(entry) {
  const actual = getActualScreenshotPath(entry);
  const expected = getExpectedScreenshotPath(entry);
  let mismatch, error;
  try {
    mismatch = await match(actual, expected);
  } catch (err) {
    error = err;
  }
  return {error, mismatch};
}

let handleRender;
async function exposeRender(page) {
  await page.exposeFunction('render', (message) => {
    if (!handleRender) {
      throw new Error('No render handler set for current page');
    }
    handleRender(message);
  });
}

async function renderPage(page, entry, options) {
  const renderCalled = new Promise(resolve => {
    handleRender = (config) => {
      handleRender = null;
      resolve(config || {});
    };
  });
  options.log.debug('navigating', entry);
  await page.goto(`http://${options.host}:${options.port}${getHref(entry)}`, {waitUntil: 'networkidle0'});
  const config = await renderCalled;
  options.log.debug('screenshot', entry);
  await page.screenshot({path: getActualScreenshotPath(entry)});
  return config;
}

async function touch(filepath) {
  const fd = await fse.open(filepath, 'w');
  await fse.close(fd);
}

async function copyActualToExpected(entry) {
  const actual = getActualScreenshotPath(entry);
  const expected = getExpectedScreenshotPath(entry);
  await fse.copy(actual, expected);
  await touch(getPassFilePath(entry));
}

async function renderEach(page, entries, options) {
  let fail = false;
  for (const entry of entries) {
    const {tolerance = 0, message = ''} = await renderPage(page, entry, options);

    if (options.fix) {
      await copyActualToExpected(entry);
      continue;
    }

    const {error, mismatch} = await getScreenshotsMismatch(entry);
    if (error) {
      options.log.error(error);
      fail = true;
      continue;
    }

    let detail = `case ${entry}`;
    if (message) {
      detail = `${detail} (${message})`;
    }

    if (mismatch > tolerance) {
      options.log.error(`${detail}': mismatch ${mismatch.toFixed(3)}`);
      fail = true;
    } else {
      options.log.info(`${detail}': ok`);
      await touch(getPassFilePath(entry));
    }
  }
  return fail;
}

async function render(entries, options) {
  const browser = await puppeteer.launch({
    args: options.puppeteerArgs,
    headless: options.headless
  });

  let fail = false;

  try {
    const page = await browser.newPage();
    page.on('error', err => {
      options.log.error('page crash', err);
    });
    page.on('pageerror', err => {
      options.log.error('uncaught exception', err);
    });
    page.on('console', message => {
      const type = message.type();
      if (options.log[type]) {
        options.log[type](message.text());
      }
    });

    page.setDefaultNavigationTimeout(options.timeout);
    await exposeRender(page);
    await page.setViewport({width: 256, height: 256});
    fail = await renderEach(page, entries, options);
  } finally {
    browser.close();
  }

  if (fail) {
    throw new Error('RENDERING TESTS FAILED');
  }
}

async function getLatest(patterns) {
  const stats = await globby(patterns, {stats: true});
  let latest = 0;
  for (const stat of stats) {
    if (stat.mtime > latest) {
      latest = stat.mtime;
    }
  }
  return latest;
}

async function getOutdated(entries, options) {
  const libTime = await getLatest(path.join(__dirname, '..', 'src', 'ol', '**', '*'));
  options.log.debug('library time', libTime);
  const outdated = [];
  for (const entry of entries) {
    const passPath = getPassFilePath(entry);
    const passTime = await getLatest(passPath);
    options.log.debug('pass time', entry, passTime);
    if (passTime < libTime) {
      outdated.push(entry);
      continue;
    }

    const caseTime = await getLatest(path.join(__dirname, path.dirname(entry), '**', '*'));
    options.log.debug('case time', entry, caseTime);
    if (passTime < caseTime) {
      outdated.push(entry);
      continue;
    }

    options.log.info('skipping', entry);
  }
  return outdated;
}

async function main(entries, options) {
  if (!options.force && !options.match) {
    entries = await getOutdated(entries, options);
  }
  if (options.match) {
    const exp = new RegExp(options.match);
    entries = entries.filter(entry => exp.test(entry));
  }
  if (!options.interactive && entries.length === 0) {
    return;
  }

  const done = await serve(options);
  try {
    await render(entries, options);
  } finally {
    if (!options.interactive) {
      done();
    }
  }
}

if (require.main === module) {

  const options = yargs.
    option('fix', {
      describe: 'Accept all screenshots as accepted',
      type: 'boolean',
      default: false
    }).
    option('host', {
      describe: 'The host for serving rendering cases',
      default: '127.0.0.1'
    }).
    option('port', {
      describe: 'The port for serving rendering cases',
      type: 'number',
      default: 3000
    }).
    option('match', {
      describe: 'Only run tests matching the provided string RegExp pattern',
      type: 'string'
    }).
    option('force', {
      describe: 'Run all tests (instead of just outdated tests)',
      type: 'boolean',
      default: false
    }).
    option('interactive', {
      describe: 'Run all tests and keep the test server running (this option will be reworked later)',
      type: 'boolean',
      default: false
    }).
    option('log-level', {
      describe: 'The level for logging',
      choices: ['trace', 'debug', 'info', 'warn', 'error', 'silent'],
      default: 'error'
    }).
    option('timeout', {
      describe: 'The timeout for loading pages (in milliseconds)',
      type: 'number',
      default: 60000
    }).
    option('headless', {
      describe: 'Launch Puppeteer in headless mode',
      type: 'boolean',
      default: false
    }).
    option('puppeteer-args', {
      describe: 'Additional args for Puppeteer',
      type: 'array',
      default: process.env.CI ? ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage'] : []
    }).
    parse();

  const entries = Object.keys(config.entry).map(key => config.entry[key]);

  options.log = log.create({name: 'rendering', level: options.logLevel});

  main(entries, options).catch(err => {
    options.log.error(err.message);
    process.exit(1);
  });
}
<commit_msg>Update to work with globby@10<commit_after>#! /usr/bin/env node
const puppeteer = require('puppeteer');
const webpack = require('webpack');
const config = require('./webpack.config');
const webpackMiddleware = require('webpack-dev-middleware');
const http = require('http');
const path = require('path');
const png = require('pngjs');
const fs = require('fs');
const fse = require('fs-extra');
const pixelmatch = require('pixelmatch');
const yargs = require('yargs');
const log = require('loglevelnext');
const globby = require('globby');
const serveStatic = require('serve-static');

const compiler = webpack(Object.assign({mode: 'development'}, config));

function getHref(entry) {
  return path.dirname(entry).slice(1) + '/';
}

const staticHandler = serveStatic(__dirname);

const defaultHandler = serveStatic(path.join(__dirname, 'default'));

const srcHandler = serveStatic(path.join(__dirname, '..', 'src'));

function indexHandler(req, res) {
  const items = [];
  for (const key in config.entry) {
    const href = getHref(config.entry[key]);
    items.push(`<li><a href="${href}">${href}</a></li>`);
  }
  const markup = `<!DOCTYPE html><body><ul>${items.join('')}</ul></body>`;

  res.writeHead(404, {
    'Content-Type': 'text/html'
  });
  res.end(markup);
}

function notFound(req, res) {
  return () => {
    // first, try the default directory
    if (req.url.match(/^\/cases\/[^\/]+\/(index.html)?$/)) {
      // request for a case index file, and file not found, use default
      req.url = '/index.html';
      return defaultHandler(req, res, () => indexHandler(req, res));
    }

    // next try the src directory (only needed for ol/ol.css)
    return srcHandler(req, res, () => indexHandler(req, res));
  };
}

function serve(options) {
  const webpackHandler = webpackMiddleware(compiler, {
    lazy: true,
    logger: options.log,
    stats: 'minimal'
  });

  return new Promise((resolve, reject) => {
    const server = http.createServer((req, res) => {
      if (req.url === '/favicon.ico') {
        res.writeHead(204);
        res.end();
        return;
      }

      const ext = path.extname(req.url);
      if (ext === '.js' || ext === '.map') {
        webpackHandler(req, res, notFound(req, res));
        return;
      }

      staticHandler(req, res, notFound(req, res));
    });

    server.listen(options.port, options.host, err => {
      if (err) {
        return reject(err);
      }
      const address = server.address();
      options.log.info(`test server listening http://${address.address}:${address.port}/`);
      resolve(() => server.close());
    });
  });
}

function getActualScreenshotPath(entry) {
  return path.join(__dirname, path.dirname(entry), 'actual.png');
}

function getExpectedScreenshotPath(entry) {
  return path.join(__dirname, path.dirname(entry), 'expected.png');
}

function getPassFilePath(entry) {
  return path.join(__dirname, path.dirname(entry), 'pass');
}

function parsePNG(filepath) {
  return new Promise((resolve, reject) => {
    const stream = fs.createReadStream(filepath);
    stream.on('error', err => {
      if (err.code === 'ENOENT') {
        return reject(new Error(`File not found: ${filepath}`));
      }
      reject(err);
    });

    const image = stream.pipe(new png.PNG());
    image.on('parsed', () => resolve(image));
    image.on('error', reject);
  });
}

async function match(actual, expected) {
  const actualImage = await parsePNG(actual);
  const expectedImage = await parsePNG(expected);
  const width = expectedImage.width;
  const height = expectedImage.height;
  if (actualImage.width != width) {
    throw new Error(`Unexpected width for ${actual}: expected ${width}, got ${actualImage.width}`);
  }
  if (actualImage.height != height) {
    throw new Error(`Unexpected height for ${actual}: expected ${height}, got ${actualImage.height}`);
  }
  const count = pixelmatch(actualImage.data, expectedImage.data, null, width, height);
  return count / (width * height);
}

async function getScreenshotsMismatch(entry) {
  const actual = getActualScreenshotPath(entry);
  const expected = getExpectedScreenshotPath(entry);
  let mismatch, error;
  try {
    mismatch = await match(actual, expected);
  } catch (err) {
    error = err;
  }
  return {error, mismatch};
}

let handleRender;
async function exposeRender(page) {
  await page.exposeFunction('render', (message) => {
    if (!handleRender) {
      throw new Error('No render handler set for current page');
    }
    handleRender(message);
  });
}

async function renderPage(page, entry, options) {
  const renderCalled = new Promise(resolve => {
    handleRender = (config) => {
      handleRender = null;
      resolve(config || {});
    };
  });
  options.log.debug('navigating', entry);
  await page.goto(`http://${options.host}:${options.port}${getHref(entry)}`, {waitUntil: 'networkidle0'});
  const config = await renderCalled;
  options.log.debug('screenshot', entry);
  await page.screenshot({path: getActualScreenshotPath(entry)});
  return config;
}

async function touch(filepath) {
  const fd = await fse.open(filepath, 'w');
  await fse.close(fd);
}

async function copyActualToExpected(entry) {
  const actual = getActualScreenshotPath(entry);
  const expected = getExpectedScreenshotPath(entry);
  await fse.copy(actual, expected);
  await touch(getPassFilePath(entry));
}

async function renderEach(page, entries, options) {
  let fail = false;
  for (const entry of entries) {
    const {tolerance = 0, message = ''} = await renderPage(page, entry, options);

    if (options.fix) {
      await copyActualToExpected(entry);
      continue;
    }

    const {error, mismatch} = await getScreenshotsMismatch(entry);
    if (error) {
      options.log.error(error);
      fail = true;
      continue;
    }

    let detail = `case ${entry}`;
    if (message) {
      detail = `${detail} (${message})`;
    }

    if (mismatch > tolerance) {
      options.log.error(`${detail}': mismatch ${mismatch.toFixed(3)}`);
      fail = true;
    } else {
      options.log.info(`${detail}': ok`);
      await touch(getPassFilePath(entry));
    }
  }
  return fail;
}

async function render(entries, options) {
  const browser = await puppeteer.launch({
    args: options.puppeteerArgs,
    headless: options.headless
  });

  let fail = false;

  try {
    const page = await browser.newPage();
    page.on('error', err => {
      options.log.error('page crash', err);
    });
    page.on('pageerror', err => {
      options.log.error('uncaught exception', err);
    });
    page.on('console', message => {
      const type = message.type();
      if (options.log[type]) {
        options.log[type](message.text());
      }
    });

    page.setDefaultNavigationTimeout(options.timeout);
    await exposeRender(page);
    await page.setViewport({width: 256, height: 256});
    fail = await renderEach(page, entries, options);
  } finally {
    browser.close();
  }

  if (fail) {
    throw new Error('RENDERING TESTS FAILED');
  }
}

async function getLatest(patterns) {
  const infoList = await globby(patterns, {stats: true});
  let latest = 0;
  for (const info of infoList) {
    if (info.stats.mtime > latest) {
      latest = info.stats.mtime;
    }
  }
  return latest;
}

async function getOutdated(entries, options) {
  const libTime = await getLatest(path.join(__dirname, '..', 'src', 'ol', '**', '*'));
  options.log.debug('library time', libTime);
  const outdated = [];
  for (const entry of entries) {
    const passPath = getPassFilePath(entry);
    const passTime = await getLatest(passPath);
    options.log.debug('pass time', entry, passTime);
    if (passTime < libTime) {
      outdated.push(entry);
      continue;
    }

    const caseTime = await getLatest(path.join(__dirname, path.dirname(entry), '**', '*'));
    options.log.debug('case time', entry, caseTime);
    if (passTime < caseTime) {
      outdated.push(entry);
      continue;
    }

    options.log.info('skipping', entry);
  }
  return outdated;
}

async function main(entries, options) {
  if (!options.force && !options.match) {
    entries = await getOutdated(entries, options);
  }
  if (options.match) {
    const exp = new RegExp(options.match);
    entries = entries.filter(entry => exp.test(entry));
  }
  if (!options.interactive && entries.length === 0) {
    return;
  }

  const done = await serve(options);
  try {
    await render(entries, options);
  } finally {
    if (!options.interactive) {
      done();
    }
  }
}

if (require.main === module) {

  const options = yargs.
    option('fix', {
      describe: 'Accept all screenshots as accepted',
      type: 'boolean',
      default: false
    }).
    option('host', {
      describe: 'The host for serving rendering cases',
      default: '127.0.0.1'
    }).
    option('port', {
      describe: 'The port for serving rendering cases',
      type: 'number',
      default: 3000
    }).
    option('match', {
      describe: 'Only run tests matching the provided string RegExp pattern',
      type: 'string'
    }).
    option('force', {
      describe: 'Run all tests (instead of just outdated tests)',
      type: 'boolean',
      default: false
    }).
    option('interactive', {
      describe: 'Run all tests and keep the test server running (this option will be reworked later)',
      type: 'boolean',
      default: false
    }).
    option('log-level', {
      describe: 'The level for logging',
      choices: ['trace', 'debug', 'info', 'warn', 'error', 'silent'],
      default: 'error'
    }).
    option('timeout', {
      describe: 'The timeout for loading pages (in milliseconds)',
      type: 'number',
      default: 60000
    }).
    option('headless', {
      describe: 'Launch Puppeteer in headless mode',
      type: 'boolean',
      default: false
    }).
    option('puppeteer-args', {
      describe: 'Additional args for Puppeteer',
      type: 'array',
      default: process.env.CI ? ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage'] : []
    }).
    parse();

  const entries = Object.keys(config.entry).map(key => config.entry[key]);

  options.log = log.create({name: 'rendering', level: options.logLevel});

  main(entries, options).catch(err => {
    options.log.error(err.message);
    process.exit(1);
  });
}
<|endoftext|>


<commit_before>/*!
  Copyright (c) 2016 Jed Watson.
  Licensed under the MIT License (MIT), see
  http://jedwatson.github.io/classnames
*/
/* global define */

(function () {
	'use strict';

	var classNames = (function () {
		function _parseArray (resultSet, array) {
			var length = array.length;

			for (var i = 0; i < length; ++i) {
				_parse(resultSet, array[i]);
			}
		}

		var hasOwn = {}.hasOwnProperty;

		function _parseNumber (resultSet, num) {
			resultSet[num] = true;
		}

		function _parseObject (resultSet, object) {
			for (var k in object) {
				if (hasOwn.call(object, k)) {
					if (object[k]) {
						resultSet[k] = true;
					} else {
						delete resultSet[k];
					}
				}
			}
		}

		var SPACE = /\s+/;
		function _parseString (resultSet, str) {
			var array = str.split(SPACE);
			var length = array.length;

			for (var i = 0; i < length; ++i) {
				resultSet[array[i]] = true;
			}
		}

		function _parse (resultSet, arg) {
			if (!arg) return;
			var argType = typeof arg;

			// 'foo bar'
			if (argType === 'string') {
				_parseString(resultSet, arg);

			// ['foo', 'bar', ...]
			} else if (Array.isArray(arg)) {
				_parseArray(resultSet, arg);

			// { 'foo': true, ... }
			} else if (argType === 'object') {
				_parseObject(resultSet, arg);

			// '130'
			} else if (argType === 'number') {
				_parseNumber(resultSet, arg);
			}
		}

		function _classNames () {
			// don't leak arguments
			// https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments
			var len = arguments.length;
			var args = Array(len);
			for (var i = 0; i < len; i++) {
				args[i] = arguments[i];
			}

			var classSet = {};
			_parseArray(classSet, args);

			var list = [];

			for (var k in classSet) {
				if (hasOwn.call(classSet, k) && classSet[k]) {
					list.push(k)
				}
			}

			return list.join(' ');
		}

		return _classNames;
	})();

	if (typeof module !== 'undefined' && module.exports) {
		module.exports = classNames;
	} else if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
		// register as 'classnames', consistent with npm package name
		define('classnames', [], function () {
			return classNames;
		});
	} else {
		window.classNames = classNames;
	}
}());
<commit_msg>skip hasOwnProperty check in dedupe<commit_after>/*!
  Copyright (c) 2016 Jed Watson.
  Licensed under the MIT License (MIT), see
  http://jedwatson.github.io/classnames
*/
/* global define */

(function () {
	'use strict';

	var classNames = (function () {
		function _parseArray (resultSet, array) {
			var length = array.length;

			for (var i = 0; i < length; ++i) {
				_parse(resultSet, array[i]);
			}
		}

		var hasOwn = {}.hasOwnProperty;

		function _parseNumber (resultSet, num) {
			resultSet[num] = true;
		}

		function _parseObject (resultSet, object) {
			for (var k in object) {
				if (hasOwn.call(object, k)) {
					if (object[k]) {
						resultSet[k] = true;
					} else {
						delete resultSet[k];
					}
				}
			}
		}

		var SPACE = /\s+/;
		function _parseString (resultSet, str) {
			var array = str.split(SPACE);
			var length = array.length;

			for (var i = 0; i < length; ++i) {
				resultSet[array[i]] = true;
			}
		}

		function _parse (resultSet, arg) {
			if (!arg) return;
			var argType = typeof arg;

			// 'foo bar'
			if (argType === 'string') {
				_parseString(resultSet, arg);

			// ['foo', 'bar', ...]
			} else if (Array.isArray(arg)) {
				_parseArray(resultSet, arg);

			// { 'foo': true, ... }
			} else if (argType === 'object') {
				_parseObject(resultSet, arg);

			// '130'
			} else if (argType === 'number') {
				_parseNumber(resultSet, arg);
			}
		}

		function _classNames () {
			// don't leak arguments
			// https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments
			var len = arguments.length;
			var args = Array(len);
			for (var i = 0; i < len; i++) {
				args[i] = arguments[i];
			}

			// don't inherit from Object so we can skip hasOwnProperty check later
			// http://stackoverflow.com/questions/15518328/creating-js-object-with-object-createnull#answer-21079232
			var classSet = Object.create(null);
			_parseArray(classSet, args);

			var list = [];

			for (var k in classSet) {
				if (classSet[k]) {
					list.push(k)
				}
			}

			return list.join(' ');
		}

		return _classNames;
	})();

	if (typeof module !== 'undefined' && module.exports) {
		module.exports = classNames;
	} else if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
		// register as 'classnames', consistent with npm package name
		define('classnames', [], function () {
			return classNames;
		});
	} else {
		window.classNames = classNames;
	}
}());
<|endoftext|>