<commit_before>/**
 *
 */
module.exports = {
  extends: 'airbnb-base',

  env: {
    jest: true,
  },

  rules: {
    'no-underscore-dangle': ['off'],
    'global-require': ['off'],
    'no-use-before-define': ['warn'],
    'brace-style': ['error', 'stroustrup', { allowSingleLine: true }],
    'import/prefer-default-export': ['off'],
    'import/imports-first': ['off'],
    'import/no-extraneous-dependencies': ['error', {
      devDependencies: ['**/*.test.js', '**/__mocks__/**', '**/__fixtures__/**'],
    }],
  },
};
<commit_msg>tweak: Increase the maximum length of a line<commit_after>/**
 *
 */
module.exports = {
  extends: 'airbnb-base',

  env: {
    jest: true,
  },

  rules: {
    'no-underscore-dangle': ['off'],
    'global-require': ['off'],
    'no-use-before-define': ['warn'],
    'brace-style': ['error', 'stroustrup', { allowSingleLine: true }],
    'import/prefer-default-export': ['off'],
    'import/imports-first': ['off'],
    'import/no-extraneous-dependencies': ['error', {
      devDependencies: ['**/*.test.js', '**/__mocks__/**', '**/__fixtures__/**'],
    }],
    'max-len': ['error', 150, 2, {
      ignoreUrls: true,
      ignoreComments: true,
      ignoreStrings: true,
      ignoreTemplateLiterals: true,
    }],
  },
};
<|endoftext|>


<commit_before>import * as utils from 'utils';
import Events from 'events';

//classes are vzb-portrait, vzb-landscape...
var class_prefix = 'vzb-';
var class_presentation = 'presentation';
var class_portrait = 'vzb-portrait';
var class_lansdcape = 'vzb-landscape';

var Layout = Events.extend({

  screen_profiles: {
    small: {
      min_width: 0,
      min_height: 0
    },
    medium: {
      min_width: 600,
      min_height: 400
    },
    large: {
      min_width: 1000,
      min_height: 700
    }
  },

  /**
   * Initializes the layout manager
   */
  init: function(ui) {
    this.ui = ui || {};

    this._container = null;
    //dom element
    this._curr_profile = null;
    this._prev_size = {};
    //resize when window resizes
    var _this = this;

    this.resizeHandler = this.resizeHandler || resize.bind(this);

    window.addEventListener('resize', this.resizeHandler);
    this._super();
  },

  /**
   * Calculates the size of the newly resized container
   */
  setSize: function() {
    var _this = this;
    var width = this._container.clientWidth;
    var height = this._container.clientHeight;
    if (this._container.clientWidth > this._container.clientHeight
      && /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
      && navigator.userAgent.match(/iPhone/i)
      && this._container.clientWidth < 700) {

      var bodyHeight = this._container.clientHeight;
      var windowHeight = window.innerHeight;

      if (2 < (bodyHeight - windowHeight) && (bodyHeight - windowHeight) <= 45) {
        this._container.style.top =  44 + "px";
        document.body.scrollTop = 44;
      } else {
        this._container.style.top =  0;
      }
    } else {
      this._container.style.top =  0;
    }

    if(this._prev_size && this._prev_size.width === width && this._prev_size.height === height) {
      return;
    }

    // choose profile depending on size
    utils.forEach(this.screen_profiles, function(range, size) {
      //remove class
      utils.removeClass(_this._container, class_prefix + size);
      //find best fit
      if(width >= range.min_width && height >= range.min_height) {
        _this._curr_profile = size;
      }
    });

    //update size class
    utils.addClass(this._container, class_prefix + this._curr_profile);
    //toggle, untoggle classes based on orientation
    if(width < height) {
      utils.addClass(this._container, class_portrait);
      utils.removeClass(this._container, class_lansdcape);
    } else {
      utils.addClass(this._container, class_lansdcape);
      utils.removeClass(this._container, class_portrait);
    }
    this._prev_size.width = width;
    this._prev_size.height = height;
    this.trigger('resize');
  },

  /**
   * Sets the container for this layout
   * @param container DOM element
   */
  setContainer: function(container) {
    this._container = container;
    this.setSize();
    this.updatePresentation();
  },

  /**
   * Sets the presentation mode for this layout
   * @param {Bool} presentation mode on or off
   */
  updatePresentation: function() {
    if (this.ui.presentation) {
        utils.addClass(this._container, class_prefix + class_presentation);
    } else {
        utils.removeClass(this._container, class_prefix + class_presentation);
    }
  },

  getPresentationMode: function() {
    return this.ui.presentation;
  },

  /**
   * Gets the current selected profile
   * @returns {String} name of current profile
   */
  currentProfile: function() {
    return this._curr_profile;
  },

  clear: function() {
    window.removeEventListener('resize', this.resizeHandler);
  }

});

function resize() {
  if(this._container) {
    this.setSize();
  }
}

export default Layout;
<commit_msg>Hidden play button in iphone 6 Safari expanded landscape mode<commit_after>import * as utils from 'utils';
import Events from 'events';

//classes are vzb-portrait, vzb-landscape...
var class_prefix = 'vzb-';
var class_presentation = 'presentation';
var class_portrait = 'vzb-portrait';
var class_lansdcape = 'vzb-landscape';

var Layout = Events.extend({

  screen_profiles: {
    small: {
      min_width: 0,
      min_height: 0
    },
    medium: {
      min_width: 600,
      min_height: 400
    },
    large: {
      min_width: 1000,
      min_height: 700
    }
  },

  /**
   * Initializes the layout manager
   */
  init: function(ui) {
    this.ui = ui || {};

    this._container = null;
    //dom element
    this._curr_profile = null;
    this._prev_size = {};
    //resize when window resizes
    var _this = this;

    this.resizeHandler = this.resizeHandler || resize.bind(this);

    window.addEventListener('resize', this.resizeHandler);
    this._super();
  },

  /**
   * Calculates the size of the newly resized container
   */
  setSize: function() {
    var _this = this;
    var width = this._container.clientWidth;
    var height = this._container.clientHeight;

    /**
     * issue #1118
     * check if device is iPhone then add top margin for searchbar if it visible
     */
    if (this._container.clientWidth > this._container.clientHeight
      && /^((?!chrome|android).)*safari/i.test(navigator.userAgent) // browser is safari
      && navigator.userAgent.match(/iPhone/i) // checking device
      && this._container.clientWidth < 700) {  // small device

      var bodyHeight = this._container.clientHeight;
      var windowHeight = window.innerHeight;

      if (2 < (bodyHeight - windowHeight) && (bodyHeight - windowHeight) <= 45) { // check searchbar is visible
        this._container.style.top =  44 + "px";
        document.body.scrollTop = 44; // scrolling empty space
        document.body.style.overflow = "hidden";
      } else {
        this._container.style.top =  0;
      }
    } else {
      this._container.style.top =  0;
    }

    if(this._prev_size && this._prev_size.width === width && this._prev_size.height === height) {
      return;
    }

    // choose profile depending on size
    utils.forEach(this.screen_profiles, function(range, size) {
      //remove class
      utils.removeClass(_this._container, class_prefix + size);
      //find best fit
      if(width >= range.min_width && height >= range.min_height) {
        _this._curr_profile = size;
      }
    });

    //update size class
    utils.addClass(this._container, class_prefix + this._curr_profile);
    //toggle, untoggle classes based on orientation
    if(width < height) {
      utils.addClass(this._container, class_portrait);
      utils.removeClass(this._container, class_lansdcape);
    } else {
      utils.addClass(this._container, class_lansdcape);
      utils.removeClass(this._container, class_portrait);
    }
    this._prev_size.width = width;
    this._prev_size.height = height;
    this.trigger('resize');
  },

  /**
   * Sets the container for this layout
   * @param container DOM element
   */
  setContainer: function(container) {
    this._container = container;
    this.setSize();
    this.updatePresentation();
  },

  /**
   * Sets the presentation mode for this layout
   * @param {Bool} presentation mode on or off
   */
  updatePresentation: function() {
    if (this.ui.presentation) {
        utils.addClass(this._container, class_prefix + class_presentation);
    } else {
        utils.removeClass(this._container, class_prefix + class_presentation);
    }
  },

  getPresentationMode: function() {
    return this.ui.presentation;
  },

  /**
   * Gets the current selected profile
   * @returns {String} name of current profile
   */
  currentProfile: function() {
    return this._curr_profile;
  },

  clear: function() {
    window.removeEventListener('resize', this.resizeHandler);
  }

});

function resize() {
  if(this._container) {
    this.setSize();
  }
}

export default Layout;
<|endoftext|>


<commit_before>var $ = require('jquery');
var _ = require('underscore');
var Backbone = require('backbone');
var CoreView = require('backbone/core-view');
var template = require('./input-color-categories.tpl');
var StackLayoutView = require('../../../../../../components/stack-layout/stack-layout-view');
var InputColorPickerView = require('../input-color-picker/input-color-picker-view');
var CategoriesListView = require('./input-color-categories-list-view');
var QuerySchemaModel = require('../../../../../../data/query-schema-model');
var TipsyTooltipView = require('../../../../../tipsy-tooltip-view.js');

var DEFAULT_COLORS = ['#A6CEE3', '#1F78B4', '#B2DF8A', '#33A02C', '#FB9A99', '#E31A1C', '#FDBF6F', '#FF7F00', '#CAB2D6', '#6A3D9A', '#DDDDDD'];
var CATEGORY_QUERY = 'SELECT <%= column %>, count(<%= column %>) FROM (<%= sql %>) _table_sql GROUP BY <%= column %> ORDER BY count DESC LIMIT <%= max_values %>';
var MAX_VALUES = 9;

module.exports = CoreView.extend({
  events: {
    'click .js-back': '_onClickBack',
    'click .js-switch': '_onClickSwitch'
  },

  initialize: function (opts) {
    if (!opts.columns) throw new Error('columns param is required');
    if (!opts.configModel) throw new Error('configModel param is required');
    if (!opts.query) throw new Error('query param is required');

    this._columns = opts.columns;
    this._configModel = opts.configModel;
    this._query = opts.query;

    this._initBinds();
    this._initViews();

    this._column = this._getColumn();
    this._columnType = this._column && this._column.type;

    this.model.unset('quantification');

    if (!this.model.get('domain') || !this.model.get('range')) {
      this._fetchColumns();
    }
  },

  render: function () {
    this.clearSubViews();
    this.$el.empty();

    this.$el.append(template({
      columnType: this._columnType,
      attribute: this.model.get('attribute')
    }));

    if (this._stackLayoutView) {
      this.$('.js-content').append(this._stackLayoutView.render().$el);
    }

    this._createTooltip();

    return this;
  },

  _initBinds: function () {
    this.model.bind('change:attribute', this._fetchColumns, this);
  },

  _initViews: function () {
    var self = this;

    var stackViewCollection = new Backbone.Collection([{
      createStackView: function (stackLayoutModel, opts) {
        return self._createRangeListView(stackLayoutModel, opts).bind(self);
      }
    }, {
      createStackView: function (stackLayoutModel, opts) {
        return self._createColorPickerView(stackLayoutModel, opts).bind(self);
      }
    }]);

    this._stackLayoutView = new StackLayoutView({
      collection: stackViewCollection
    });
  },

  _createTooltip: function () {
    this._helpTooltip = new TipsyTooltipView({
      el: this.$('.js-switch'),
      gravity: 's',
      offset: 0,
      title: function () {
        return $(this).data('tooltip');
      }
    });
  },

  _getColumn: function () {
    return _.find(this._columns, function (column) {
      return column.label === this.model.get('attribute');
    }, this);
  },

  _fetchColumns: function () {
    if (!this.model.get('attribute')) {
      return;
    }

    this._startLoader();

    this._querySchemaModel = new QuerySchemaModel(null, {
      configModel: this._configModel
    });

    var tmpl = _.template(CATEGORY_QUERY);

    this._querySchemaModel.set('query', tmpl({
      sql: this._query,
      column: this.model.get('attribute'),
      max_values: MAX_VALUES + 1
    }));

    this._querySchemaModel.on('change:status', this._onStatusChange, this);
    this._querySchemaModel.fetch();
  },

  _onStatusChange: function () {
    if (this._querySchemaModel.get('status') === 'fetching') {
      return;
    }

    this._stopLoader();

    var showOthers = false;

    var categoryNames = this._querySchemaModel.rowsSampleCollection.pluck(this.model.get('attribute'));

    if (categoryNames.length >= MAX_VALUES) {
      showOthers = true;
    }

    var domain = _.map(categoryNames, function (name, i) {
      return name;
    }).slice(0, MAX_VALUES).sort();

    var range = _.map(categoryNames, function (name, i) {
      return DEFAULT_COLORS[i];
    }).slice(0, MAX_VALUES);

    if (showOthers) {
      domain.unshift(_t('form-components.editors.fill.input-categories.others'));
      range.unshift(DEFAULT_COLORS[categoryNames.length]);
    }

    this.model.set({
      range: range,
      domain: domain
    });

    this._initViews();
    this.render();
  },

  _startLoader: function () {
    this.$('.js-loader').removeClass('is-hidden');
    this.$('.js-content').addClass('is-hidden');
  },

  _stopLoader: function () {
    this.$('.js-loader').addClass('is-hidden');
    this.$('.js-content').removeClass('is-hidden');
  },

  _updateRange: function (categories) {
    var range = _.clone(this.model.get('range'));
    range[this._index] = categories[this._index].color;
    this.model.set('range', range);
  },

  _createColorPickerView: function (stackLayoutModel, opts) {
    var range = _.map(this.model.get('range'), function (color, i) {
      return { val: color, color: color, title: this.model.get('domain')[i] };
    }, this);

    var view = new InputColorPickerView({
      index: this._index,
      ramp: range
    });

    view.bind('back', function (value) {
      stackLayoutModel.prevStep();
    }, this);

    view.bind('change', this._updateRange, this);
    view.bind('changeIndex', function (index) {
      this._index = index;
    }, this);

    return view;
  },

  _createRangeListView: function (stackLayoutModel, opts) {
    var view = new CategoriesListView({
      model: this.model
    });

    view.bind('back', function (value) {
      stackLayoutModel.prevStep();
    }, this);

    view.bind('selectItem', function (index) {
      this._index = index;
      stackLayoutModel.nextStep();
    }, this);

    return view;
  },

  _onClickSwitch: function (e) {
    this.killEvent(e);
    this._removeTooltip();
    this.trigger('switch', this);
  },

  _onClickBack: function (e) {
    this.killEvent(e);
    this.trigger('back', this);
  },

  _removeTooltip: function () {
    if (this._helpTooltip) {
      this._helpTooltip.clean();
    }
  },

  remove: function () {
    this._removeTooltip();
    CoreView.prototype.remove.apply(this);
  }
});
<commit_msg>Closes #8547<commit_after>var $ = require('jquery');
var _ = require('underscore');
var Backbone = require('backbone');
var CoreView = require('backbone/core-view');
var template = require('./input-color-categories.tpl');
var StackLayoutView = require('../../../../../../components/stack-layout/stack-layout-view');
var InputColorPickerView = require('../input-color-picker/input-color-picker-view');
var CategoriesListView = require('./input-color-categories-list-view');
var QuerySchemaModel = require('../../../../../../data/query-schema-model');
var TipsyTooltipView = require('../../../../../tipsy-tooltip-view.js');

var DEFAULT_COLORS = ['#A6CEE3', '#1F78B4', '#B2DF8A', '#33A02C', '#FB9A99', '#E31A1C', '#FDBF6F', '#FF7F00', '#CAB2D6', '#6A3D9A', '#DDDDDD'];
var CATEGORY_QUERY = 'SELECT <%= column %>, count(<%= column %>) FROM (<%= sql %>) _table_sql GROUP BY <%= column %> ORDER BY count DESC LIMIT <%= max_values %>';
var MAX_VALUES = 9;

module.exports = CoreView.extend({
  events: {
    'click .js-back': '_onClickBack',
    'click .js-switch': '_onClickSwitch'
  },

  initialize: function (opts) {
    if (!opts.columns) throw new Error('columns param is required');
    if (!opts.configModel) throw new Error('configModel param is required');
    if (!opts.query) throw new Error('query param is required');

    this._columns = opts.columns;
    this._configModel = opts.configModel;
    this._query = opts.query;

    this._initBinds();
    this._initViews();

    this.model.unset('quantification');

    if (!this.model.get('domain') || !this.model.get('range')) {
      this._fetchColumns();
    }
  },

  render: function () {
    this.clearSubViews();
    this.$el.empty();

    var column = this._getColumn();
    var columnType = column && column.type;

    this.$el.append(template({
      columnType: columnType,
      attribute: this.model.get('attribute')
    }));

    if (this._stackLayoutView) {
      this.$('.js-content').append(this._stackLayoutView.render().$el);
    }

    this._createTooltip();

    return this;
  },

  _initBinds: function () {
    this.model.bind('change:attribute', this._fetchColumns, this);
  },

  _initViews: function () {
    var self = this;

    var stackViewCollection = new Backbone.Collection([{
      createStackView: function (stackLayoutModel, opts) {
        return self._createRangeListView(stackLayoutModel, opts).bind(self);
      }
    }, {
      createStackView: function (stackLayoutModel, opts) {
        return self._createColorPickerView(stackLayoutModel, opts).bind(self);
      }
    }]);

    this._stackLayoutView = new StackLayoutView({
      collection: stackViewCollection
    });
  },

  _createTooltip: function () {
    this._helpTooltip = new TipsyTooltipView({
      el: this.$('.js-switch'),
      gravity: 's',
      offset: 0,
      title: function () {
        return $(this).data('tooltip');
      }
    });
  },

  _getColumn: function () {
    return _.find(this._columns, function (column) {
      return column.label === this.model.get('attribute');
    }, this);
  },

  _fetchColumns: function () {
    if (!this.model.get('attribute')) {
      return;
    }

    this._startLoader();

    this._querySchemaModel = new QuerySchemaModel(null, {
      configModel: this._configModel
    });

    var tmpl = _.template(CATEGORY_QUERY);

    this._querySchemaModel.set('query', tmpl({
      sql: this._query,
      column: this.model.get('attribute'),
      max_values: MAX_VALUES + 1
    }));

    this._querySchemaModel.on('change:status', this._onStatusChange, this);
    this._querySchemaModel.fetch();
  },

  _onStatusChange: function () {
    if (this._querySchemaModel.get('status') === 'fetching') {
      return;
    }

    this._stopLoader();

    var showOthers = false;

    var categoryNames = this._querySchemaModel.rowsSampleCollection.pluck(this.model.get('attribute'));

    if (categoryNames.length >= MAX_VALUES) {
      showOthers = true;
    }

    var domain = _.map(categoryNames, function (name, i) {
      return name;
    }).slice(0, MAX_VALUES).sort();

    var range = _.map(categoryNames, function (name, i) {
      return DEFAULT_COLORS[i];
    }).slice(0, MAX_VALUES);

    if (showOthers) {
      domain.unshift(_t('form-components.editors.fill.input-categories.others'));
      range.unshift(DEFAULT_COLORS[categoryNames.length]);
    }

    this.model.set({
      range: range,
      domain: domain
    });

    this._initViews();
    this.render();
  },

  _startLoader: function () {
    this.$('.js-loader').removeClass('is-hidden');
    this.$('.js-content').addClass('is-hidden');
  },

  _stopLoader: function () {
    this.$('.js-loader').addClass('is-hidden');
    this.$('.js-content').removeClass('is-hidden');
  },

  _updateRange: function (categories) {
    var range = _.clone(this.model.get('range'));
    range[this._index] = categories[this._index].color;
    this.model.set('range', range);
  },

  _createColorPickerView: function (stackLayoutModel, opts) {
    var range = _.map(this.model.get('range'), function (color, i) {
      return { val: color, color: color, title: this.model.get('domain')[i] };
    }, this);

    var view = new InputColorPickerView({
      index: this._index,
      ramp: range
    });

    view.bind('back', function (value) {
      stackLayoutModel.prevStep();
    }, this);

    view.bind('change', this._updateRange, this);
    view.bind('changeIndex', function (index) {
      this._index = index;
    }, this);

    return view;
  },

  _createRangeListView: function (stackLayoutModel, opts) {
    var view = new CategoriesListView({
      model: this.model
    });

    view.bind('back', function (value) {
      stackLayoutModel.prevStep();
    }, this);

    view.bind('selectItem', function (index) {
      this._index = index;
      stackLayoutModel.nextStep();
    }, this);

    return view;
  },

  _onClickSwitch: function (e) {
    this.killEvent(e);
    this._removeTooltip();
    this.trigger('switch', this);
  },

  _onClickBack: function (e) {
    this.killEvent(e);
    this.trigger('back', this);
  },

  _removeTooltip: function () {
    if (this._helpTooltip) {
      this._helpTooltip.clean();
    }
  },

  remove: function () {
    this._removeTooltip();
    CoreView.prototype.remove.apply(this);
  }
});
<|endoftext|>


<commit_before>export const onRequest = function (event) {
  if (event.requestMeta.url.pathname === '/secret') {
    event.replaceResponse(
      // eslint-disable-next-line no-undef
      new Response('
Access denied
', {
        headers: { 'content-type': 'text/html' },
        status: 404,
      }),
    )
  }
}
<commit_msg>Add logs<commit_after>export const onRequest = function (event) {
  // eslint-disable-next-line no-console, no-restricted-globals
  console.log(event.requestMeta.url.pathname)

  if (event.requestMeta.url.pathname === '/secret') {
    event.replaceResponse(
      // eslint-disable-next-line no-undef
      new Response('
Access denied
', {
        headers: { 'content-type': 'text/html' },
        status: 404,
      }),
    )
  }
}
<|endoftext|>


<commit_before>import Link from 'next/link'
import Head from 'next/head'

const linkStyle = {
  marginRight: 15
}

export default function Header() {
  return (

        <title>xd</title>

        <link rel="manifest" href="/static/manifest.json" />

        <link rel="apple-touch-icon" sizes="180x180" href="/static/favicon/apple-touch-icon.png" />
        <link rel="icon" type="image/png" sizes="32x32" href="/static/favicon/favicon-32x32.png" />
        <link rel="icon" type="image/png" sizes="16x16" href="/static/favicon/favicon-16x16.png" />
        <link rel="manifest" href="/static/favicon/site.webmanifest" />
        <link rel="mask-icon" href="/static/favicon/safari-pinned-tab.svg" color="#69c8a4" />
        <link rel="shortcut icon" href="/static/favicon/favicon.ico" />
        <meta name="msapplication-TileColor" content="#2b5797" />
        <meta name="msapplication-config" content="/static/favicon/browserconfig.xml" />
        <meta name="theme-color" content="#69c8a4" />

        <meta httpEquiv="origin-trial" content="AucV22yiUOQFnchsKcbTK0w6kW7pYxqgTZme6YoXqwsUT+ogAoTzzYybtcwTiya4RdmgvEIbeXJ9veB7N8TGSwkAAABTeyJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJmZWF0dXJlIjoiTmF0aXZlRmlsZVN5c3RlbSIsImV4cGlyeSI6MTU3NTMyODIzOX0=" />

      <Link href="/">
        Home
      </Link>
      <Link href="/about">
        About
      </Link>

  )
}
<commit_msg>Add meta description<commit_after>import Link from 'next/link'
import Head from 'next/head'

const linkStyle = {
  marginRight: 15
}

export default function Header() {
  return (

        <title>xd</title>

        <meta name="Description" content="Explosive Decompression pwa unarchiver" />

        <link rel="manifest" href="/static/manifest.json" />

        <link rel="apple-touch-icon" sizes="180x180" href="/static/favicon/apple-touch-icon.png" />
        <link rel="icon" type="image/png" sizes="32x32" href="/static/favicon/favicon-32x32.png" />
        <link rel="icon" type="image/png" sizes="16x16" href="/static/favicon/favicon-16x16.png" />
        <link rel="manifest" href="/static/favicon/site.webmanifest" />
        <link rel="mask-icon" href="/static/favicon/safari-pinned-tab.svg" color="#69c8a4" />
        <link rel="shortcut icon" href="/static/favicon/favicon.ico" />
        <meta name="msapplication-TileColor" content="#2b5797" />
        <meta name="msapplication-config" content="/static/favicon/browserconfig.xml" />
        <meta name="theme-color" content="#69c8a4" />

        <meta httpEquiv="origin-trial" content="AucV22yiUOQFnchsKcbTK0w6kW7pYxqgTZme6YoXqwsUT+ogAoTzzYybtcwTiya4RdmgvEIbeXJ9veB7N8TGSwkAAABTeyJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJmZWF0dXJlIjoiTmF0aXZlRmlsZVN5c3RlbSIsImV4cGlyeSI6MTU3NTMyODIzOX0=" />

      <Link href="/">
        Home
      </Link>
      <Link href="/about">
        About
      </Link>

  )
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var DebugLogtron = require('debug-logtron');
var fs = require('fs');
var path = require('path');

var TChannelAsThrift = require('../../as/thrift');
var HyperbahnClient = require('../../hyperbahn/index.js');

var source = fs.readFileSync(path.join(__dirname, '../../hyperbahn/hyperbahn.thrift'), 'utf8');
var thrift = new TChannelAsThrift({source: source});

module.exports = runTests;

if (require.main === module) {
    runTests(require('../lib/hyperbahn-cluster.js'));
}

function covertHost(host) {
    var res = '';
    res += ((host.ip.ipv4 & 0xff000000) >> 24) + '.';
    res += ((host.ip.ipv4 & 0xff0000) >> 16) + '.';
    res += ((host.ip.ipv4 & 0xff00) >> 8) + '.';
    res += host.ip.ipv4 & 0xff;
    return res + ':' + host.port;
}

function runTests(HyperbahnCluster) {
    HyperbahnCluster.test('get no host', {
        size: 25
    }, function t(cluster, assert) {
        var bob = cluster.remotes.bob;
        var bobSub = bob.channel.makeSubChannel({
            serviceName: 'hyperbahn',
            peers: cluster.hostPortList
        });
        var request = bobSub.request({
            headers: {
                cn: 'test'
            },
            serviceName: 'hyperbahn',
            hasNoParent: true
        });
        thrift.send(request,
            'Hyperbahn::discover',
            null,
            {
                query: {
                    serviceName: 'matt'
                }
            },
            onResponse
        );
        function onResponse(err, res) {
            if (err) {
                assert.end(err);
            }
            assert.ok(res, 'should be a result');
            assert.ok(!res.ok, 'result should be not ok');
            assert.equals(res.body.message, 'no peer available for matt', 'error message as expected');
            assert.end();
        }
    });

    HyperbahnCluster.test('get host port as expected', {
        size: 5
    }, function t(cluster, assert) {
        var bob = cluster.remotes.bob;
        var steve = cluster.remotes.steve;
        var steveSub = steve.channel.makeSubChannel({
            serviceName: 'hyperbahn',
            peers: cluster.hostPortList
        });
        var request = steveSub.request({
            headers: {
                cn: 'test'
            },
            serviceName: 'hyperbahn',
            hasNoParent: true
        });

        var client = new HyperbahnClient({
            serviceName: 'hello-bob',
            callerName: 'hello-bob-test',
            hostPortList: cluster.hostPortList,
            tchannel: bob.channel,
            logger: DebugLogtron('hyperbahnClient')
        });

        client.once('advertised', onResponse);
        client.advertise();

        function onResponse() {
            thrift.send(request,
                'Hyperbahn::discover',
                null,
                {
                    query: {
                        serviceName: 'hello-bob'
                    }
                },
                check
            );
        }

        function check(err, res) {
            if (err) {
                assert.end(err);
            }
            assert.ok(res, 'should be a result');
            assert.ok(res.ok, 'result should be ok');
            assert.equals(covertHost(res.body.peers[0]), bob.channel.hostPort,
                'should get the expected hostPort');
            client.destroy();
            assert.end();
        }
    });

    HyperbahnCluster.test('malformed thrift IDL: empty serviceName', {
        size: 5
    }, function t(cluster, assert) {
        var bob = cluster.remotes.bob;
        var bobSub = bob.channel.makeSubChannel({
            serviceName: 'hyperbahn',
            peers: cluster.hostPortList
        });
        var request = bobSub.request({
            headers: {
                cn: 'test'
            },
            serviceName: 'hyperbahn',
            hasNoParent: true
        });
        thrift.send(request,
            'Hyperbahn::discover',
            null,
            {
                query: {
                    serviceName: ''
                }
            },
            onResponse
        );
        function onResponse(err, res) {
            if (err) {
                assert.end(err);
            }
            assert.ok(!res.ok, 'should be not ok');
            assert.equals(res.body.message, 'invalid service name: ', 'error message as expected');
            assert.end();
        }
    });

    HyperbahnCluster.test('malformed thrift IDL: an empty body', {
        size: 5
    }, function t(cluster, assert) {
        cluster.logger.whitelist('warn', 'Got unexpected invalid thrift for arg3');
        var bob = cluster.remotes.bob;
        var bobSub = bob.channel.makeSubChannel({
            serviceName: 'hyperbahn',
            peers: cluster.hostPortList
        });
        var request = bobSub.request({
            headers: {
                cn: 'test'
            },
            serviceName: 'hyperbahn',
            hasNoParent: true
        });
        var badSource = fs.readFileSync(path.join(__dirname, 'bad-hyperbahn-empty-req-body.thrift'), 'utf8');
        var badThrift = new TChannelAsThrift({source: badSource});
        badThrift.send(request,
            'Hyperbahn::discover',
            null,
            {},
            onResponse
        );
        function onResponse(err, res) {
            assert.ok(err, 'should be error');
            assert.equals(err.type, 'tchannel.bad-request', 'error should be bad request');
            assert.ok(err.message.indexOf(
                'tchannel-thrift-handler.parse-error.body-failed: Could not parse body (arg3) argument.\n' +
                'Expected Thrift encoded arg3 for endpoint Hyperbahn::discover.') === 0,
                'error message should be a parsing failure');
            assert.ok(err.message.indexOf(
                'Parsing error was: missing required field "query" with id 1 on discover_args') !== -1,
                'error message should be a parsing failure');

            var items = cluster.logger.items();
            assert.ok(items.length > 0 && items[0].msg === 'Got unexpected invalid thrift for arg3',
                'Do not miss the error log');

            assert.end();
        }
    });

    HyperbahnCluster.test('malformed thrift IDL: a body with a query without the serviceName field', {
        size: 5
    }, function t(cluster, assert) {
        cluster.logger.whitelist('warn', 'Got unexpected invalid thrift for arg3');
        var bob = cluster.remotes.bob;
        var bobSub = bob.channel.makeSubChannel({
            serviceName: 'hyperbahn',
            peers: cluster.hostPortList
        });
        var request = bobSub.request({
            headers: {
                cn: 'test'
            },
            serviceName: 'hyperbahn',
            hasNoParent: true
        });
        var badSource = fs.readFileSync(path.join(__dirname, 'bad-hyperbahn-empty-req-body.thrift'), 'utf8');
        var badThrift = new TChannelAsThrift({source: badSource});
        badThrift.send(request,
            'Hyperbahn::discover',
            null,
            {query: {}},
            onResponse
        );
        function onResponse(err, res) {
            assert.ok(err, 'should be error');
            assert.equals(err.type, 'tchannel.bad-request', 'error should be bad request');
            assert.ok(err.message.indexOf(
                'tchannel-thrift-handler.parse-error.body-failed: Could not parse body (arg3) argument.\n' +
                'Expected Thrift encoded arg3 for endpoint Hyperbahn::discover.') === 0,
                'error message should be a parsing failure');
            assert.ok(err.message.indexOf(
                'Parsing error was: missing required field "query" with id 1 on discover_args') !== -1,
                'error message should be a parsing failure');

            var items = cluster.logger.items();
            assert.ok(items.length > 0 && items[0].msg === 'Got unexpected invalid thrift for arg3',
                'Do not miss the error log');

            assert.end();
        }
    });

    HyperbahnCluster.test('malformed thrift IDL: empty serviceName with no exception defined', {
        size: 5
    }, function t(cluster, assert) {
        cluster.logger.whitelist('warn', 'Got unexpected invalid thrift for arg3');
        var bob = cluster.remotes.bob;
        var bobSub = bob.channel.makeSubChannel({
            serviceName: 'hyperbahn',
            peers: cluster.hostPortList
        });
        var request = bobSub.request({
            headers: {
                cn: 'test'
            },
            serviceName: 'hyperbahn',
            hasNoParent: true
        });
        var badSource = fs.readFileSync(path.join(__dirname, 'bad-hyperbahn-no-exception.thrift'), 'utf8');
        var badThrift = new TChannelAsThrift({source: badSource});
        badThrift.send(request,
            'Hyperbahn::discover',
            null,
            {
                query: {
                    serviceName: ''
                }
            },
            onResponse
        );
        function onResponse(err, res) {
            assert.ok(err, 'should be error');
            assert.equals(err.type, 'tchannel-thrift-handler.parse-error.body-failed',
                'error should be parser error');
            assert.ok(err.message.indexOf(
                'Could not parse body (arg3) argument.\n' +
                'Expected Thrift encoded arg3 for endpoint Hyperbahn::discover.') === 0,
                'error message should be a parsing failure');

            var items = cluster.logger.items();
            assert.ok(items.length > 0 && items[0].msg === 'Got unexpected invalid thrift for arg3',
                'Do not miss the error log');

            assert.end();
        }
    });
}
<commit_msg>Setting size > 20 fails for unknown reasons<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var DebugLogtron = require('debug-logtron');
var fs = require('fs');
var path = require('path');

var TChannelAsThrift = require('../../as/thrift');
var HyperbahnClient = require('../../hyperbahn/index.js');

var source = fs.readFileSync(path.join(__dirname, '../../hyperbahn/hyperbahn.thrift'), 'utf8');
var thrift = new TChannelAsThrift({source: source});

module.exports = runTests;

if (require.main === module) {
    runTests(require('../lib/hyperbahn-cluster.js'));
}

function covertHost(host) {
    var res = '';
    res += ((host.ip.ipv4 & 0xff000000) >> 24) + '.';
    res += ((host.ip.ipv4 & 0xff0000) >> 16) + '.';
    res += ((host.ip.ipv4 & 0xff00) >> 8) + '.';
    res += host.ip.ipv4 & 0xff;
    return res + ':' + host.port;
}

function runTests(HyperbahnCluster) {
    HyperbahnCluster.test('get no host', {
        size: 15
    }, function t(cluster, assert) {
        var bob = cluster.remotes.bob;
        var bobSub = bob.channel.makeSubChannel({
            serviceName: 'hyperbahn',
            peers: cluster.hostPortList
        });
        var request = bobSub.request({
            headers: {
                cn: 'test'
            },
            serviceName: 'hyperbahn',
            hasNoParent: true
        });
        thrift.send(request,
            'Hyperbahn::discover',
            null,
            {
                query: {
                    serviceName: 'matt'
                }
            },
            onResponse
        );
        function onResponse(err, res) {
            if (err) {
                assert.end(err);
            }
            assert.ok(res, 'should be a result');
            assert.ok(!res.ok, 'result should be not ok');
            assert.equals(res.body.message, 'no peer available for matt', 'error message as expected');
            assert.end();
        }
    });

    HyperbahnCluster.test('get host port as expected', {
        size: 5
    }, function t(cluster, assert) {
        var bob = cluster.remotes.bob;
        var steve = cluster.remotes.steve;
        var steveSub = steve.channel.makeSubChannel({
            serviceName: 'hyperbahn',
            peers: cluster.hostPortList
        });
        var request = steveSub.request({
            headers: {
                cn: 'test'
            },
            serviceName: 'hyperbahn',
            hasNoParent: true
        });

        var client = new HyperbahnClient({
            serviceName: 'hello-bob',
            callerName: 'hello-bob-test',
            hostPortList: cluster.hostPortList,
            tchannel: bob.channel,
            logger: DebugLogtron('hyperbahnClient')
        });

        client.once('advertised', onResponse);
        client.advertise();

        function onResponse() {
            thrift.send(request,
                'Hyperbahn::discover',
                null,
                {
                    query: {
                        serviceName: 'hello-bob'
                    }
                },
                check
            );
        }

        function check(err, res) {
            if (err) {
                assert.end(err);
            }
            assert.ok(res, 'should be a result');
            assert.ok(res.ok, 'result should be ok');
            assert.equals(covertHost(res.body.peers[0]), bob.channel.hostPort,
                'should get the expected hostPort');
            client.destroy();
            assert.end();
        }
    });

    HyperbahnCluster.test('malformed thrift IDL: empty serviceName', {
        size: 5
    }, function t(cluster, assert) {
        var bob = cluster.remotes.bob;
        var bobSub = bob.channel.makeSubChannel({
            serviceName: 'hyperbahn',
            peers: cluster.hostPortList
        });
        var request = bobSub.request({
            headers: {
                cn: 'test'
            },
            serviceName: 'hyperbahn',
            hasNoParent: true
        });
        thrift.send(request,
            'Hyperbahn::discover',
            null,
            {
                query: {
                    serviceName: ''
                }
            },
            onResponse
        );
        function onResponse(err, res) {
            if (err) {
                assert.end(err);
            }
            assert.ok(!res.ok, 'should be not ok');
            assert.equals(res.body.message, 'invalid service name: ', 'error message as expected');
            assert.end();
        }
    });

    HyperbahnCluster.test('malformed thrift IDL: an empty body', {
        size: 5
    }, function t(cluster, assert) {
        cluster.logger.whitelist('warn', 'Got unexpected invalid thrift for arg3');
        var bob = cluster.remotes.bob;
        var bobSub = bob.channel.makeSubChannel({
            serviceName: 'hyperbahn',
            peers: cluster.hostPortList
        });
        var request = bobSub.request({
            headers: {
                cn: 'test'
            },
            serviceName: 'hyperbahn',
            hasNoParent: true
        });
        var badSource = fs.readFileSync(path.join(__dirname, 'bad-hyperbahn-empty-req-body.thrift'), 'utf8');
        var badThrift = new TChannelAsThrift({source: badSource});
        badThrift.send(request,
            'Hyperbahn::discover',
            null,
            {},
            onResponse
        );
        function onResponse(err, res) {
            assert.ok(err, 'should be error');
            assert.equals(err.type, 'tchannel.bad-request', 'error should be bad request');
            assert.ok(err.message.indexOf(
                'tchannel-thrift-handler.parse-error.body-failed: Could not parse body (arg3) argument.\n' +
                'Expected Thrift encoded arg3 for endpoint Hyperbahn::discover.') === 0,
                'error message should be a parsing failure');
            assert.ok(err.message.indexOf(
                'Parsing error was: missing required field "query" with id 1 on discover_args') !== -1,
                'error message should be a parsing failure');

            var items = cluster.logger.items();
            assert.ok(items.length > 0 && items[0].msg === 'Got unexpected invalid thrift for arg3',
                'Do not miss the error log');

            assert.end();
        }
    });

    HyperbahnCluster.test('malformed thrift IDL: a body with a query without the serviceName field', {
        size: 5
    }, function t(cluster, assert) {
        cluster.logger.whitelist('warn', 'Got unexpected invalid thrift for arg3');
        var bob = cluster.remotes.bob;
        var bobSub = bob.channel.makeSubChannel({
            serviceName: 'hyperbahn',
            peers: cluster.hostPortList
        });
        var request = bobSub.request({
            headers: {
                cn: 'test'
            },
            serviceName: 'hyperbahn',
            hasNoParent: true
        });
        var badSource = fs.readFileSync(path.join(__dirname, 'bad-hyperbahn-empty-req-body.thrift'), 'utf8');
        var badThrift = new TChannelAsThrift({source: badSource});
        badThrift.send(request,
            'Hyperbahn::discover',
            null,
            {query: {}},
            onResponse
        );
        function onResponse(err, res) {
            assert.ok(err, 'should be error');
            assert.equals(err.type, 'tchannel.bad-request', 'error should be bad request');
            assert.ok(err.message.indexOf(
                'tchannel-thrift-handler.parse-error.body-failed: Could not parse body (arg3) argument.\n' +
                'Expected Thrift encoded arg3 for endpoint Hyperbahn::discover.') === 0,
                'error message should be a parsing failure');
            assert.ok(err.message.indexOf(
                'Parsing error was: missing required field "query" with id 1 on discover_args') !== -1,
                'error message should be a parsing failure');

            var items = cluster.logger.items();
            assert.ok(items.length > 0 && items[0].msg === 'Got unexpected invalid thrift for arg3',
                'Do not miss the error log');

            assert.end();
        }
    });

    HyperbahnCluster.test('malformed thrift IDL: empty serviceName with no exception defined', {
        size: 5
    }, function t(cluster, assert) {
        cluster.logger.whitelist('warn', 'Got unexpected invalid thrift for arg3');
        var bob = cluster.remotes.bob;
        var bobSub = bob.channel.makeSubChannel({
            serviceName: 'hyperbahn',
            peers: cluster.hostPortList
        });
        var request = bobSub.request({
            headers: {
                cn: 'test'
            },
            serviceName: 'hyperbahn',
            hasNoParent: true
        });
        var badSource = fs.readFileSync(path.join(__dirname, 'bad-hyperbahn-no-exception.thrift'), 'utf8');
        var badThrift = new TChannelAsThrift({source: badSource});
        badThrift.send(request,
            'Hyperbahn::discover',
            null,
            {
                query: {
                    serviceName: ''
                }
            },
            onResponse
        );
        function onResponse(err, res) {
            assert.ok(err, 'should be error');
            assert.equals(err.type, 'tchannel-thrift-handler.parse-error.body-failed',
                'error should be parser error');
            assert.ok(err.message.indexOf(
                'Could not parse body (arg3) argument.\n' +
                'Expected Thrift encoded arg3 for endpoint Hyperbahn::discover.') === 0,
                'error message should be a parsing failure');

            var items = cluster.logger.items();
            assert.ok(items.length > 0 && items[0].msg === 'Got unexpected invalid thrift for arg3',
                'Do not miss the error log');

            assert.end();
        }
    });
}
<|endoftext|>


<commit_before>import { bindable, customAttribute } from 'aurelia-templating';
import { bindingMode } from 'aurelia-binding';
import { inject } from 'aurelia-dependency-injection';
import { AttributeManager } from '../common/attributeManager';

@customAttribute('md-waves')
@inject(Element)
export class MdWaves {
  @bindable({
    defaultBindingMode: bindingMode.oneTime
  }) color;
  constructor(element) {
    this.element = element;
    this.attributeManager = new AttributeManager(this.element);
  }

  attached() {
    let classes = ['waves-effect'];
    if (this.color) {
      classes.push(`waves-${this.color}`);
    }

    this.attributeManager.addClasses(classes);
    Waves.attach(this.element);
  }

  detached() {
    let classes = ['waves-effect'];
    if (this.color) {
      classes.push(`waves-${this.color}`);
    }

    this.attributeManager.removeClasses(classes);
  }
}
<commit_msg>feat(waves): add block property to activate waves-block (display: block)<commit_after>import { bindable, customAttribute } from 'aurelia-templating';
import { bindingMode } from 'aurelia-binding';
import { inject } from 'aurelia-dependency-injection';
import { AttributeManager } from '../common/attributeManager';
import { getBooleanFromAttributeValue } from '../common/attributes';

@customAttribute('md-waves')
@inject(Element)
export class MdWaves {
  @bindable({
    defaultBindingMode: bindingMode.oneTime
  }) block = false;
  @bindable({
    defaultBindingMode: bindingMode.oneTime
  }) color;
  constructor(element) {
    this.element = element;
    this.attributeManager = new AttributeManager(this.element);
  }

  attached() {
    let classes = ['waves-effect'];
    if (getBooleanFromAttributeValue(this.block)) {
      classes.push('waves-block');
    }
    if (this.color) {
      classes.push(`waves-${this.color}`);
    }

    this.attributeManager.addClasses(classes);
    Waves.attach(this.element);
  }

  detached() {
    let classes = ['waves-effect', 'waves-block'];
    if (this.color) {
      classes.push(`waves-${this.color}`);
    }

    this.attributeManager.removeClasses(classes);
  }
}
<|endoftext|>


<commit_before>/*
 * dns.js
 */
"use strict";

global.include = function(f) { var fs = require('fs'); eval(fs.readFileSync(f)+''); }

include('project_ids.js');
include('config.js');

var dns = require('native-dns');
var util = require('util');
var gcp = require('./gcp');
var server = dns.createServer();

exports.serial = new Date().getTime() / 1000 | 0; /* serial number for this runtime */

// DNS query types
var A = 1;
var NS = 2;
var CNAME = 5;
var SOA = 6;
var PTR = 12;
var MX = 15;
var TXT = 16;

server.on('request', function(request, response) {
  if ([A, SOA].indexOf(request.question[0].type) == -1) {
    response.send();
    return;
  }

  var domain = request.question[0].name;

  /* foramt: <instance name>.<project id or alias>.<type>.foo.dont.care */
  /* type: i = internal, * (else) = external
   */
  var _s = domain.split(".");
  console.log(_s);

  var hostname = _s[0];
  var project = _s[1];
  var isInternal = (3 <= _s.length && 'i' == _s[2].toLowerCase());

  if (SOA == request.question[0].type) {
    var name = _s.slice((isInternal) ? 3 : 2).join('.');
    response.answer.push(dns.SOA({
      'name': name,
      'type': SOA,
      'primary': config['primary_ns'],
      'admin': config['soa_admin'],
      'serial': exports.serial,
      'ttl': config["default_ttl"],
      'refresh': 900,
      'retry': 900,
      'expiration': 1800,
      'minimum': 60
    }));
    response.send();
    return;
  }

  gcp.getInstances(project, function(ret) {
    if (0 == ret.length) {
      console.log("empty result.");
      response.send();
      return;
    }
    var result = ret.filter(function (o) { return (o.name.toUpperCase() == hostname.toUpperCase()) });
    if (null == result) {
      console.log(hostname + " (" + domain + ") not match any.");
      response.send();
      return;
    }
    var record = {'name': domain, 'ttl': result[0].TTL, 'address': ''};
    if (true == isInternal) {
      record.address = result[0].privateIP;
    } else {
      record.address = result[0].publicIP;
    }
    response.answer.push(dns.A(record));
    response.send();
    console.log(record);
  });

});

server.on('error', function (err, buff, req, res) {
  console.log(err.stack);
});

console.log('Listening on '+53);
console.log('Serial: '+exports.serial);
if (!process.getuid || 0 != process.getuid()) {
  console.log('You need root permission to bind on port 53');
  return;
}
server.serve(53);
<commit_msg>logging all request information to console<commit_after>/*
 * dns.js
 */
"use strict";

global.include = function(f) { var fs = require('fs'); eval(fs.readFileSync(f)+''); }

include('project_ids.js');
include('config.js');

var dns = require('native-dns');
var util = require('util');
var gcp = require('./gcp');
var server = dns.createServer();

exports.serial = new Date().getTime() / 1000 | 0; /* serial number for this runtime */

// DNS query types
var A = 1;
var NS = 2;
var CNAME = 5;
var SOA = 6;
var PTR = 12;
var MX = 15;
var TXT = 16;

server.on('request', function(request, response) {
  console.log(util.format("[%s] %s:%s Query: %s Type: %s",Date(), request.address.address, request.address.port, request.question[0].name, request.question[0].type))

  if ([A, SOA].indexOf(request.question[0].type) == -1) {
    response.send();
    return;
  }

  var domain = request.question[0].name;

  /* foramt: <instance name>.<project id or alias>.<type>.foo.dont.care */
  /* type: i = internal, * (else) = external
   */
  var _s = domain.split(".");
  console.log(_s);

  var hostname = _s[0];
  var project = _s[1];
  var isInternal = (3 <= _s.length && 'i' == _s[2].toLowerCase());

  if (SOA == request.question[0].type) {
    var name = _s.slice((isInternal) ? 3 : 2).join('.');
    response.answer.push(dns.SOA({
      'name': name,
      'type': SOA,
      'primary': config['primary_ns'],
      'admin': config['soa_admin'],
      'serial': exports.serial,
      'ttl': config["default_ttl"],
      'refresh': 900,
      'retry': 900,
      'expiration': 1800,
      'minimum': 60
    }));
    response.send();
    return;
  }

  gcp.getInstances(project, function(ret) {
    if (0 == ret.length) {
      console.log("empty result.");
      response.send();
      return;
    }
    var result = ret.filter(function (o) { return (o.name.toUpperCase() == hostname.toUpperCase()) });
    if (null == result) {
      console.log(hostname + " (" + domain + ") not match any.");
      response.send();
      return;
    }
    var record = {'name': domain, 'ttl': result[0].TTL, 'address': ''};
    if (true == isInternal) {
      record.address = result[0].privateIP;
    } else {
      record.address = result[0].publicIP;
    }
    response.answer.push(dns.A(record));
    response.send();
    console.log(record);
  });

});

server.on('error', function (err, buff, req, res) {
  console.log(err.stack);
});

console.log('Listening on '+53);
console.log('Serial: '+exports.serial);
if (!process.getuid || 0 != process.getuid()) {
  console.log('You need root permission to bind on port 53');
  return;
}
server.serve(53);
<|endoftext|>


<commit_before>
export default function (binder) {
    const self = this;

    if (binder.meta.pending) return;
    else binder.meta.pending = true;

    let data;

    const read = function () {
        data = binder.data || [];

        if (!binder.meta.setup) {
            binder.meta.keys = [];
            binder.meta.counts = [];
            binder.meta.setup = false;
            binder.meta.pending = false;
            binder.meta.targetLength = 0;
            binder.meta.currentLength = 0;
            binder.meta.templateString = binder.target.innerHTML;
            binder.meta.fragment = document.createDocumentFragment();
            binder.meta.templateLength = binder.target.childNodes.length;

            while (binder.target.firstChild) {
                binder.target.removeChild(binder.target.firstChild);
            }

            binder.meta.setup = true;
        }

        binder.meta.keys = data ? Object.keys(data) : [];
        binder.meta.targetLength = binder.meta.keys.length;

        if (binder.meta.currentLength === binder.meta.targetLength) {
            binder.meta.pending = false;
            this.write = false;
        }

    };

    const write = function () {

        if (binder.meta.currentLength > binder.meta.targetLength) {
            while (binder.meta.currentLength > binder.meta.targetLength) {
                let count = binder.meta.templateLength;

                while (count--) {
                    const node = binder.target.lastChild;
                    binder.target.removeChild(node);
                    // self.remove(node);
                    Promise.resolve().then(self.remove.bind(self, node)).catch(console.error);
                }

                binder.meta.currentLength--;
            }
        } else if (binder.meta.currentLength < binder.meta.targetLength) {
            while (binder.meta.currentLength < binder.meta.targetLength) {
                const index = binder.meta.currentLength;
                const key = binder.meta.keys[index];

                const variablePattern = new RegExp(`\\[${binder.names[1]}\\]`, 'g');
                const indexPattern = new RegExp(`({{)?\\[${binder.names[2]}\\](}})?`, 'g');
                const keyPattern = new RegExp(`({{)?\\[${binder.names[3]}\\](}})?`, 'g');

                const clone = binder.meta.templateString
                    .replace(variablePattern, `${binder.path}.${key}`)
                    .replace(indexPattern, index)
                    .replace(keyPattern, key);

                const parsed = new DOMParser().parseFromString(clone, 'text/html').body;

                let node;
                while (node = parsed.firstChild) {
                    binder.meta.fragment.appendChild(node);
                    Promise.resolve().then(self.add.bind(self, node, binder.container, binder.scope)).catch(console.error);
                    // self.add(node, binder.container, binder.scope);
                    // binder.target.appendChild(node);
                }

                binder.meta.currentLength++;
            }
            binder.target.appendChild(binder.meta.fragment);
        }

        binder.meta.pending = false;
    };

    return { read, write };
}
<commit_msg>removed comments<commit_after>
export default function (binder) {
    const self = this;

    if (binder.meta.pending) return;
    else binder.meta.pending = true;

    let data;

    const read = function () {
        data = binder.data || [];

        if (!binder.meta.setup) {
            binder.meta.keys = [];
            binder.meta.counts = [];
            binder.meta.setup = false;
            binder.meta.pending = false;
            binder.meta.targetLength = 0;
            binder.meta.currentLength = 0;
            binder.meta.templateString = binder.target.innerHTML;
            binder.meta.fragment = document.createDocumentFragment();
            binder.meta.templateLength = binder.target.childNodes.length;

            while (binder.target.firstChild) {
                binder.target.removeChild(binder.target.firstChild);
            }

            binder.meta.setup = true;
        }

        binder.meta.keys = data ? Object.keys(data) : [];
        binder.meta.targetLength = binder.meta.keys.length;

        if (binder.meta.currentLength === binder.meta.targetLength) {
            binder.meta.pending = false;
            this.write = false;
        }

    };

    const write = function () {

        if (binder.meta.currentLength > binder.meta.targetLength) {
            while (binder.meta.currentLength > binder.meta.targetLength) {
                let count = binder.meta.templateLength;

                while (count--) {
                    const node = binder.target.lastChild;
                    binder.target.removeChild(node);
                    Promise.resolve().then(self.remove.bind(self, node)).catch(console.error);
                }

                binder.meta.currentLength--;
            }
        } else if (binder.meta.currentLength < binder.meta.targetLength) {
            while (binder.meta.currentLength < binder.meta.targetLength) {
                const index = binder.meta.currentLength;
                const key = binder.meta.keys[index];

                const variablePattern = new RegExp(`\\[${binder.names[1]}\\]`, 'g');
                const indexPattern = new RegExp(`({{)?\\[${binder.names[2]}\\](}})?`, 'g');
                const keyPattern = new RegExp(`({{)?\\[${binder.names[3]}\\](}})?`, 'g');

                const clone = binder.meta.templateString
                    .replace(variablePattern, `${binder.path}.${key}`)
                    .replace(indexPattern, index)
                    .replace(keyPattern, key);

                const parsed = new DOMParser().parseFromString(clone, 'text/html').body;

                let node;
                while (node = parsed.firstChild) {
                    binder.meta.fragment.appendChild(node);
                    Promise.resolve().then(self.add.bind(self, node, binder.container, binder.scope)).catch(console.error);
                }

                binder.meta.currentLength++;
            }
            binder.target.appendChild(binder.meta.fragment);
        }

        binder.meta.pending = false;
    };

    return { read, write };
}
<|endoftext|>


<commit_before>/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2022 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

var BaseTween = require('./tween/BaseTween');
var Class = require('../utils/Class');
var Events = require('./events');
var TWEEN_CONST = require('./tween/const');
var TweenBuilder = require('./builders/TweenBuilder');

/**
 * @classdesc
 * A Timeline combines multiple Tweens into one. Its overall behavior is otherwise similar to a single Tween.
 *
 * The Timeline updates all of its Tweens simultaneously. Its methods allow you to easily build a sequence
 * of Tweens (each one starting after the previous one) or run multiple Tweens at once during given parts of the Timeline.
 *
 * @class Timeline
 * @memberof Phaser.Tweens
 * @extends Phaser.Tweens.BaseTween
 * @constructor
 * @since 3.0.0
 *
 * @param {Phaser.Tweens.TweenManager} manager - The Tween Manager which owns this Timeline.
 */
var Timeline = new Class({

    Extends: BaseTween,

    initialize:

    function Timeline (manager)
    {
        BaseTween.call(this, manager);

        this.init();
    },

    /**
     * Initializes the timeline, which means all Tweens get their init() called, and the total duration will be computed.
     * Returns a boolean indicating whether the timeline is auto-started or not.
     *
     * @method Phaser.Tweens.Timeline#init
     * @since 3.0.0
     *
     * @return {boolean} `true` if the Timeline is started. `false` if it is paused.
     */
    init: function ()
    {
        this.calcDuration();

        this.progress = 0;
        this.totalProgress = 0;

        if (this.paused)
        {
            this.state = TWEEN_CONST.PAUSED;

            return false;
        }
        else
        {
            return true;
        }
    },

    /**
     * Calculates the total duration of the timeline.
     *
     * Computes all tween durations and returns the full duration of the timeline.
     *
     * The resulting number is stored in the timeline, not as a return value.
     *
     * @method Phaser.Tweens.Timeline#calcDuration
     * @since 3.0.0
     */
    calcDuration: function ()
    {
        var prevEnd = 0;
        var totalDuration = 0;
        var offsetDuration = 0;

        for (var i = 0; i < this.totalData; i++)
        {
            var tween = this.data[i];

            tween.init();

            if (this.hasOffset(tween))
            {
                if (this.isOffsetAbsolute(tween.offset))
                {
                    //  An actual number, so it defines the start point from the beginning of the timeline
                    tween.calculatedOffset = tween.offset;

                    if (tween.offset === 0)
                    {
                        offsetDuration = 0;
                    }
                }
                else if (this.isOffsetRelative(tween.offset))
                {
                    //  A relative offset (i.e. '-=1000', so starts at 'offset' ms relative to the PREVIOUS Tweens ending time)
                    tween.calculatedOffset = this.getRelativeOffset(tween.offset, prevEnd);
                }
            }
            else
            {
                //  Sequential
                tween.calculatedOffset = offsetDuration;
            }

            prevEnd = tween.totalDuration + tween.calculatedOffset;

            totalDuration += tween.totalDuration;
            offsetDuration += tween.totalDuration;
        }

        //  Excludes loop values
        this.duration = totalDuration;

        this.loopCounter = (this.loop === -1) ? 999999999999 : this.loop;

        if (this.loopCounter > 0)
        {
            this.totalDuration = this.duration + this.completeDelay + ((this.duration + this.loopDelay) * this.loopCounter);
        }
        else
        {
            this.totalDuration = this.duration + this.completeDelay;
        }
    },

    /**
     * Creates a new Tween, based on the given Tween Config, and adds it to this Timeline.
     *
     * @method Phaser.Tweens.Timeline#add
     * @since 3.0.0
     *
     * @param {(Phaser.Types.Tweens.TweenBuilderConfig|object)} config - The configuration object for the Tween.
     *
     * @return {this} This Timeline object.
     */
    add: function (config)
    {
        return this.queue(TweenBuilder(this, config));
    },

    /**
     * Adds an existing Tween to this Timeline.
     *
     * @method Phaser.Tweens.Timeline#queue
     * @since 3.0.0
     *
     * @param {Phaser.Tweens.Tween} tween - The Tween to be added to this Timeline.
     *
     * @return {this} This Timeline object.
     */
    queue: function (tween)
    {
        if (!this.isPlaying())
        {
            tween.parent = this;
            tween.parentIsTimeline = true;

            this.data.push(tween);

            this.totalData = this.data.length;
        }

        return this;
    },

    /**
     * Checks whether a Tween has an offset value.
     *
     * @method Phaser.Tweens.Timeline#hasOffset
     * @since 3.0.0
     *
     * @param {Phaser.Tweens.Tween} tween - The Tween to check.
     *
     * @return {boolean} `true` if the tween has a non-null offset.
     */
    hasOffset: function (tween)
    {
        return (tween.offset !== null);
    },

    /**
     * Checks whether the offset value is a number or a directive that is relative to previous tweens.
     *
     * @method Phaser.Tweens.Timeline#isOffsetAbsolute
     * @since 3.0.0
     *
     * @param {number} value - The offset value to be evaluated.
     *
     * @return {boolean} `true` if the result is a number, `false` if it is a directive like " -= 1000".
     */
    isOffsetAbsolute: function (value)
    {
        return (typeof(value) === 'number');
    },

    /**
     * Checks if the offset is a relative value rather than an absolute one.
     * If the value is just a number, this returns false.
     *
     * @method Phaser.Tweens.Timeline#isOffsetRelative
     * @since 3.0.0
     *
     * @param {string} value - The offset value to be evaluated.
     *
     * @return {boolean} `true` if the value is relative, i.e " -= 1000". If `false`, the offset is absolute.
     */
    isOffsetRelative: function (value)
    {
        var t = typeof(value);

        if (t === 'string')
        {
            var op = value[0];

            if (op === '-' || op === '+')
            {
                return true;
            }
        }

        return false;
    },

    /**
     * Parses the relative offset value, returning a positive or negative number.
     *
     * @method Phaser.Tweens.Timeline#getRelativeOffset
     * @since 3.0.0
     *
     * @param {string} value - The relative offset, in the format of '-=500', for example. The first character determines whether it will be a positive or negative number. Spacing matters here.
     * @param {number} base - The value to use as the offset.
     *
     * @return {number} The parsed offset value.
     */
    getRelativeOffset: function (value, base)
    {
        var op = value[0];
        var num = parseFloat(value.substr(2));
        var result = base;

        switch (op)
        {
            case '+':
                result += num;
                break;

            case '-':
                result -= num;
                break;
        }

        //  Cannot ever be < 0
        return Math.max(0, result);
    },

    /**
     * Resets all of the timeline's tweens back to their initial states.
     * The boolean parameter indicates whether tweens that are looping should reset as well, or not.
     *
     * @method Phaser.Tweens.Timeline#resetTweens
     * @since 3.0.0
     *
     * @param {boolean} resetFromLoop - If `true`, resets all looping tweens to their initial values.
     */
    resetTweens: function (resetFromLoop)
    {
        for (var i = 0; i < this.totalData; i++)
        {
            var tween = this.data[i];

            tween.play(resetFromLoop);
        }
    },

    /**
     * Starts playing the Timeline.
     *
     * @method Phaser.Tweens.Timeline#play
     * @fires Phaser.Tweens.Events#TIMELINE_START
     * @since 3.0.0
     */
    play: function ()
    {
        /*
        if (this.paused)
        {
            this.paused = false;

            this.makeActive(this);

            return;
        }
        else
        {
            this.resetTweens(false);

            this.state = TWEEN_CONST.PLAYING;
        }

        this.dispatchEvent(Events.TIMELINE_START, this.callbacks.onStart);
        */
    },

    /**
     * Updates the Timeline's `state` and fires callbacks and events.
     *
     * @method Phaser.Tweens.Timeline#nextState
     * @fires Phaser.Tweens.Events#TIMELINE_COMPLETE
     * @fires Phaser.Tweens.Events#TIMELINE_LOOP
     * @since 3.0.0
     *
     * @see Phaser.Tweens.Timeline#update
     */
    nextState: function ()
    {
        if (this.loopCounter > 0)
        {
            //  Reset the elapsed time
            this.elapsed = 0;
            this.progress = 0;

            this.loopCounter--;

            this.resetTweens(true);

            if (this.loopDelay > 0)
            {
                this.countdown = this.loopDelay;

                this.state = TWEEN_CONST.LOOP_DELAY;
            }
            else
            {
                this.state = TWEEN_CONST.ACTIVE;

                this.dispatchEvent(Events.TIMELINE_LOOP, this.callbacks.onLoop);
            }
        }
        else if (this.completeDelay > 0)
        {
            this.state = TWEEN_CONST.COMPLETE_DELAY;

            this.countdown = this.completeDelay;
        }
        else
        {
            this.state = TWEEN_CONST.PENDING_REMOVE;

            this.dispatchEvent(Events.TIMELINE_COMPLETE, this.callbacks.onComplete);
        }
    },

    /**
     * Returns 'true' if this Timeline has finished and should be removed from the Tween Manager.
     * Otherwise, returns false.
     *
     * @method Phaser.Tweens.Timeline#update
     * @fires Phaser.Tweens.Events#TIMELINE_COMPLETE
     * @fires Phaser.Tweens.Events#TIMELINE_UPDATE
     * @since 3.0.0
     *
     * @param {number} timestamp - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout.
     * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
     *
     * @return {boolean} Returns `true` if this Timeline has finished and should be removed from the Tween Manager, otherwise `false`.
     */
    update: function (timestamp, delta)
    {
        if (this.state === TWEEN_CONST.PENDING_REMOVE || this.state === TWEEN_CONST.DESTROYED)
        {
            return true;
        }

        if (this.paused)
        {
            return false;
        }

        if (this.useFrames)
        {
            delta = 1 * this.parent.timeScale;
        }
        else
        {
            delta *= this.timeScale * this.parent.timeScale;
        }

        this.elapsed += delta;
        this.progress = Math.min(this.elapsed / this.duration, 1);

        this.totalElapsed += delta;
        this.totalProgress = Math.min(this.totalElapsed / this.totalDuration, 1);

        switch (this.state)
        {
            case TWEEN_CONST.ACTIVE:

                var stillRunning = this.totalData;

                for (var i = 0; i < this.totalData; i++)
                {
                    var tween = this.data[i];

                    if (tween.update(timestamp, delta))
                    {
                        stillRunning--;
                    }
                }

                this.dispatchEvent(Events.TIMELINE_UPDATE, this.callbacks.onUpdate);

                //  Anything still running? If not, we're done
                if (stillRunning === 0)
                {
                    this.nextState();
                }

                break;

            case TWEEN_CONST.LOOP_DELAY:

                this.countdown -= delta;

                if (this.countdown <= 0)
                {
                    this.state = TWEEN_CONST.ACTIVE;

                    this.dispatchEvent(Events.TIMELINE_LOOP, this.callbacks.onLoop);
                }

                break;

            case TWEEN_CONST.COMPLETE_DELAY:

                this.countdown -= delta;

                if (this.countdown <= 0)
                {
                    this.state = TWEEN_CONST.PENDING_REMOVE;

                    this.dispatchEvent(Events.TIMELINE_COMPLETE, this.callbacks.onComplete);
                }

                break;
        }

        return (this.state === TWEEN_CONST.PENDING_REMOVE);
    },

    /**
     * Stops the Timeline immediately, whatever stage of progress it is at and flags it for removal by the TweenManager.
     *
     * @method Phaser.Tweens.Timeline#stop
     * @since 3.0.0
     */
    stop: function ()
    {
        this.state = TWEEN_CONST.PENDING_REMOVE;
    },

    /**
     * Checks if any of the Tweens in this Timeline as operating on the target object.
     *
     * Returns `false` if no Tweens operate on the target object.
     *
     * @method Phaser.Tweens.Timeline#hasTarget
     * @since 3.0.0
     *
     * @param {object} target - The target to check all Tweens against.
     *
     * @return {boolean} `true` if there is at least a single Tween that operates on the target object, otherwise `false`.
     */
    hasTarget: function (target)
    {
        for (var i = 0; i < this.data.length; i++)
        {
            if (this.data[i].hasTarget(target))
            {
                return true;
            }
        }

        return false;
    },

    /**
     * Stops all the Tweens in the Timeline immediately, whatever stage of progress they are at and flags
     * them for removal by the TweenManager.
     *
     * @method Phaser.Tweens.Timeline#destroy
     * @since 3.0.0
     */
    destroy: function ()
    {
        BaseTween.prototype.destroy.call(this);

        for (var i = 0; i < this.data.length; i++)
        {
            this.data[i].stop();
        }

        this.data = null;
    }

});

module.exports = Timeline;
<commit_msg>Working through getting timelines running again<commit_after>/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2022 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

var BaseTween = require('./tween/BaseTween');
var Class = require('../utils/Class');
var Events = require('./events');
var TWEEN_CONST = require('./tween/const');
var TweenBuilder = require('./builders/TweenBuilder');

/**
 * @classdesc
 * A Timeline combines multiple Tweens into one. Its overall behavior is otherwise similar to a single Tween.
 *
 * The Timeline updates all of its Tweens simultaneously. Its methods allow you to easily build a sequence
 * of Tweens (each one starting after the previous one) or run multiple Tweens at once during given parts of the Timeline.
 *
 * @class Timeline
 * @memberof Phaser.Tweens
 * @extends Phaser.Tweens.BaseTween
 * @constructor
 * @since 3.0.0
 *
 * @param {Phaser.Tweens.TweenManager} manager - The Tween Manager which owns this Timeline.
 */
var Timeline = new Class({

    Extends: BaseTween,

    initialize:

    function Timeline (manager)
    {
        BaseTween.call(this, manager);
    },

    /**
     * Initializes the timeline, which means all Tweens get their init() called, and the total duration will be computed.
     * Returns a boolean indicating whether the timeline is auto-started or not.
     *
     * @method Phaser.Tweens.Timeline#init
     * @since 3.0.0
     *
     * @return {this} This Tween instance.
     */
    init: function ()
    {
        this.calcDuration();

        this.progress = 0;
        this.totalProgress = 0;

        this.state = TWEEN_CONST.ACTIVE;

        this.dispatchEvent(Events.TWEEN_ACTIVE, this.callbacks.onActive);

        return this;
    },

    /**
     * Calculates the total duration of the timeline.
     *
     * Computes all tween durations and returns the full duration of the timeline.
     *
     * The resulting number is stored in the timeline, not as a return value.
     *
     * @method Phaser.Tweens.Timeline#calcDuration
     * @since 3.0.0
     */
    calcDuration: function ()
    {
        var prevEnd = 0;
        var totalDuration = 0;
        var offsetDuration = 0;

        for (var i = 0; i < this.totalData; i++)
        {
            var tween = this.data[i];

            tween.init();

            if (this.hasOffset(tween))
            {
                if (this.isOffsetAbsolute(tween.offset))
                {
                    //  An actual number, so it defines the start point from the beginning of the timeline
                    tween.calculatedOffset = tween.offset;

                    if (tween.offset === 0)
                    {
                        offsetDuration = 0;
                    }
                }
                else if (this.isOffsetRelative(tween.offset))
                {
                    //  A relative offset (i.e. '-=1000', so starts at 'offset' ms relative to the PREVIOUS Tweens ending time)
                    tween.calculatedOffset = this.getRelativeOffset(tween.offset, prevEnd);
                }
            }
            else
            {
                //  Sequential
                tween.calculatedOffset = offsetDuration;
            }

            // tween.state = TWEEN_CONST.OFFSET_DELAY;

            prevEnd = tween.totalDuration + tween.calculatedOffset;

            totalDuration += tween.totalDuration;
            offsetDuration += tween.totalDuration;
        }

        //  Excludes loop values
        this.duration = totalDuration;

        this.loopCounter = (this.loop === -1) ? 999999999999 : this.loop;

        if (this.loopCounter > 0)
        {
            this.totalDuration = this.duration + this.completeDelay + ((this.duration + this.loopDelay) * this.loopCounter);
        }
        else
        {
            this.totalDuration = this.duration + this.completeDelay;
        }
    },

    /**
     * Creates a new Tween, based on the given Tween Config, and adds it to this Timeline.
     *
     * @method Phaser.Tweens.Timeline#add
     * @since 3.0.0
     *
     * @param {(Phaser.Types.Tweens.TweenBuilderConfig|object)} config - The configuration object for the Tween.
     *
     * @return {this} This Timeline object.
     */
    add: function (config)
    {
        return this.queue(TweenBuilder(this, config));
    },

    /**
     * Adds an existing Tween to this Timeline.
     *
     * @method Phaser.Tweens.Timeline#queue
     * @since 3.0.0
     *
     * @param {Phaser.Tweens.Tween} tween - The Tween to be added to this Timeline.
     *
     * @return {this} This Timeline object.
     */
    queue: function (tween)
    {
        if (!this.isPlaying())
        {
            tween.parent = this;
            tween.parentIsTimeline = true;

            this.data.push(tween);

            this.totalData = this.data.length;
        }

        return this;
    },

    /**
     * Checks whether a Tween has an offset value.
     *
     * @method Phaser.Tweens.Timeline#hasOffset
     * @since 3.0.0
     *
     * @param {Phaser.Tweens.Tween} tween - The Tween to check.
     *
     * @return {boolean} `true` if the tween has a non-null offset.
     */
    hasOffset: function (tween)
    {
        return (tween.offset !== null);
    },

    /**
     * Checks whether the offset value is a number or a directive that is relative to previous tweens.
     *
     * @method Phaser.Tweens.Timeline#isOffsetAbsolute
     * @since 3.0.0
     *
     * @param {number} value - The offset value to be evaluated.
     *
     * @return {boolean} `true` if the result is a number, `false` if it is a directive like " -= 1000".
     */
    isOffsetAbsolute: function (value)
    {
        return (typeof(value) === 'number');
    },

    /**
     * Checks if the offset is a relative value rather than an absolute one.
     * If the value is just a number, this returns false.
     *
     * @method Phaser.Tweens.Timeline#isOffsetRelative
     * @since 3.0.0
     *
     * @param {string} value - The offset value to be evaluated.
     *
     * @return {boolean} `true` if the value is relative, i.e " -= 1000". If `false`, the offset is absolute.
     */
    isOffsetRelative: function (value)
    {
        return (typeof(value) === 'string' && (value[0] === '-' || value[0] === '+'));
    },

    /**
     * Parses the relative offset value, returning a positive or negative number.
     *
     * @method Phaser.Tweens.Timeline#getRelativeOffset
     * @since 3.0.0
     *
     * @param {string} value - The relative offset, in the format of '-=500', for example. The first character determines whether it will be a positive or negative number. Spacing matters here.
     * @param {number} base - The value to use as the offset.
     *
     * @return {number} The parsed offset value.
     */
    getRelativeOffset: function (value, base)
    {
        var op = value[0];
        var num = parseFloat(value.substring(2));
        var result = base;

        if (op === '+')
        {
            result += num;
        }
        else if (op === '-')
        {
            result -= num;
        }

        //  Cannot ever be < 0
        return Math.max(0, result);
    },

    /**
     * Resets all of the timeline's tweens back to their initial states.
     * The boolean parameter indicates whether tweens that are looping should reset as well, or not.
     *
     * @method Phaser.Tweens.Timeline#resetTweens
     * @since 3.0.0
     *
     * @param {boolean} resetFromLoop - If `true`, resets all looping tweens to their initial values.
     */
    resetTweens: function (resetFromLoop)
    {
        for (var i = 0; i < this.totalData; i++)
        {
            var tween = this.data[i];

            tween.play(resetFromLoop);
        }
    },

    /**
     * Starts playing the Timeline.
     *
     * @method Phaser.Tweens.Timeline#play
     * @fires Phaser.Tweens.Events#TIMELINE_START
     * @since 3.0.0
     */
    play: function ()
    {
        var state = this.state;

        if (state === TWEEN_CONST.DESTROYED)
        {
            console.warn('Cannot play destroyed Timeline');

            return this;
        }

        this.paused = false;
        this.state = TWEEN_CONST.ACTIVE;

        return this;

        // if (this.paused)
        // {
        //     this.paused = false;

        //     this.makeActive(this);

        //     return;
        // }
        // else
        // {
        //     this.resetTweens(false);

        //     this.state = TWEEN_CONST.ACTIVE;
        // }

        // this.dispatchEvent(Events.TIMELINE_START, this.callbacks.onStart);
    },

    /**
     * Updates the Timeline's `state` and fires callbacks and events.
     *
     * @method Phaser.Tweens.Timeline#nextState
     * @fires Phaser.Tweens.Events#TIMELINE_COMPLETE
     * @fires Phaser.Tweens.Events#TIMELINE_LOOP
     * @since 3.0.0
     *
     * @see Phaser.Tweens.Timeline#update
     */
    nextState: function ()
    {
        if (this.loopCounter > 0)
        {
            //  Reset the elapsed time
            this.elapsed = 0;
            this.progress = 0;

            this.loopCounter--;

            this.resetTweens(true);

            if (this.loopDelay > 0)
            {
                this.countdown = this.loopDelay;

                this.state = TWEEN_CONST.LOOP_DELAY;
            }
            else
            {
                this.state = TWEEN_CONST.ACTIVE;

                this.dispatchEvent(Events.TIMELINE_LOOP, this.callbacks.onLoop);
            }
        }
        else if (this.completeDelay > 0)
        {
            this.state = TWEEN_CONST.COMPLETE_DELAY;

            this.countdown = this.completeDelay;
        }
        else
        {
            this.state = TWEEN_CONST.PENDING_REMOVE;

            this.dispatchEvent(Events.TIMELINE_COMPLETE, this.callbacks.onComplete);
        }
    },

    /**
     * Returns 'true' if this Timeline has finished and should be removed from the Tween Manager.
     * Otherwise, returns false.
     *
     * @method Phaser.Tweens.Timeline#update
     * @fires Phaser.Tweens.Events#TIMELINE_COMPLETE
     * @fires Phaser.Tweens.Events#TIMELINE_UPDATE
     * @since 3.0.0
     *
     * @param {number} timestamp - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout.
     * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
     *
     * @return {boolean} Returns `true` if this Timeline has finished and should be removed from the Tween Manager, otherwise `false`.
     */
    update: function (timestamp, delta)
    {
        var state = this.state;

        if (state === TWEEN_CONST.PENDING_REMOVE || state === TWEEN_CONST.DESTROYED)
        {
            return true;
        }

        if ((this.paused && !this.isSeeking) || state === TWEEN_CONST.FINISHED)
        {
            return false;
        }

        if (this.useFrames)
        {
            delta = 1 * this.parent.timeScale;
        }
        else
        {
            delta *= this.timeScale * this.parent.timeScale;
        }

        this.elapsed += delta;
        this.progress = Math.min(this.elapsed / this.duration, 1);

        this.totalElapsed += delta;
        this.totalProgress = Math.min(this.totalElapsed / this.totalDuration, 1);

        if (state === TWEEN_CONST.LOOP_DELAY)
        {
            this.updateCountdown(delta, TWEEN_CONST.ACTIVE, Events.TIMELINE_LOOP, this.callbacks.onLoop);
        }
        else if (state === TWEEN_CONST.COMPLETE_DELAY)
        {
            this.updateCountdown(delta, TWEEN_CONST.PENDING_REMOVE, Events.TIMELINE_COMPLETE, this.callbacks.onComplete);
        }

        //  Make its own check so the states above can toggle to active on the same frame.
        //  Check 'this.state', not 'state' as it may have been updated by the functions above.
        if (this.state === TWEEN_CONST.ACTIVE)
        {
            this.updateActive(timestamp, delta);
        }

        return (this.state === TWEEN_CONST.PENDING_REMOVE);
    },

    /**
     * Internal method that handles the processing of a countdown timer and
     * the dispatch of related events. Called automatically by `Tween.update`.
     *
     * @method Phaser.Tweens.Timeline#updateCountdown
     * @since 3.60.0
     *
     * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
     * @param {number} state - The new Tween State to be set.
     * @param {Phaser.Types.Tweens.Event} [event] - The Tween Event to dispatch, if any.
     * @param {function} [callback] - The Tween Callback to invoke, if any.
     */
    updateCountdown: function (delta, state, event, callback)
    {
        this.countdown -= delta;

        if (this.countdown <= 0)
        {
            this.state = state;

            if (callback)
            {
                this.dispatchEvent(event, callback);
            }
        }
    },

    /**
     * Internal method that handles the updating of the Tween Data and
     * related dispatching of events. Called automatically by `Tween.update`.
     *
     * @method Phaser.Tweens.Timeline#updateActive
     * @fires Phaser.Tweens.Events#TWEEN_START
     * @since 3.60.0
     *
     * @param {number} timestamp - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout.
     * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
     */
    updateActive: function (timestamp, delta)
    {
        if (!this.hasStarted)
        {
            this.hasStarted = true;

            this.dispatchEvent(Events.TIMELINE_START, this.callbacks.onStart);

            // this.startDelay -= delta;

            // if (this.startDelay <= 0)
            // {
            //     this.hasStarted = true;

            //     this.dispatchEvent(Events.TWEEN_START, this.callbacks.onStart);
            // }
        }

        var stillRunning = false;

        // console.log('updateActive', this.totalData);

        for (var i = 0; i < this.totalData; i++)
        {
            var tween = this.data[i];

            // console.log('updateActive', i, tween.state);

            if (!tween.update(timestamp, delta))
            {
                // console.log('tween', i, 'updated');

                //  As long as at least one Tween returns 'false' then we're still running
                stillRunning = true;
            }
        }

        this.dispatchEvent(Events.TIMELINE_UPDATE, this.callbacks.onUpdate);

        //  Anything still running? If not, we're done
        if (!stillRunning)
        {
            console.log('nothing running any more');
            this.nextState();
        }
    },

    /**
     * Stops the Timeline immediately, whatever stage of progress it is at and flags it for removal by the TweenManager.
     *
     * @method Phaser.Tweens.Timeline#stop
     * @since 3.0.0
     */
    stop: function ()
    {
        this.state = TWEEN_CONST.PENDING_REMOVE;
    },

    /**
     * Checks if any of the Tweens in this Timeline as operating on the target object.
     *
     * Returns `false` if no Tweens operate on the target object.
     *
     * @method Phaser.Tweens.Timeline#hasTarget
     * @since 3.0.0
     *
     * @param {object} target - The target to check all Tweens against.
     *
     * @return {boolean} `true` if there is at least a single Tween that operates on the target object, otherwise `false`.
     */
    hasTarget: function (target)
    {
        for (var i = 0; i < this.data.length; i++)
        {
            if (this.data[i].hasTarget(target))
            {
                return true;
            }
        }

        return false;
    },

    /**
     * Stops all the Tweens in the Timeline immediately, whatever stage of progress they are at and flags
     * them for removal by the TweenManager.
     *
     * @method Phaser.Tweens.Timeline#destroy
     * @since 3.0.0
     */
    destroy: function ()
    {
        BaseTween.prototype.destroy.call(this);

        for (var i = 0; i < this.data.length; i++)
        {
            this.data[i].stop();
        }

        this.data = null;
    }

});

module.exports = Timeline;
<|endoftext|>


<commit_before>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
// limitations under the License.

(function(scope, testing) {

  function parseBoxWithCalcLeft(string) {
    var rectangleWithCalcRegExp = /rect\(([^,]+), ([^,]+), ([^,]+), (calc\(.+\))\)/
    match = rectangleWithCalcRegExp.exec(string);
    if (!match) {
      return undefined;
    }
    var out = [
      scope.parseLengthOrPercent(match[1]),
      scope.parseLengthOrPercent(match[2]),
      scope.parseLengthOrPercent(match[3]),
      scope.parseLengthOrPercent(match[4])
      ];
    console.log(out);
    if (out[0] && out[1] && out[2] && out[3]) {
      console.log("returning the other one");
      return out;
    }
    return undefined;
  }

  function parseBox(string) {
    var rectangleRegExp = /rect\(([^,]+),([^,]+),([^,]+),([^)]+)\)/;
    var match = rectangleRegExp.exec(string);
    if (!match) {
      return undefined;
    }
    var out = [
      scope.parseLengthOrPercent(match[1]),
      scope.parseLengthOrPercent(match[2]),
      scope.parseLengthOrPercent(match[3]),
      scope.parseLengthOrPercent(match[4])
      ];
    console.log(out);
    if (out[0] && out[1] && out[2] && out[3]) {
      return out;
    }
    return parseBoxWithCalcLeft(string);
    // return undefined;
  }

  function mergeBoxes(left, right) {
    var mergedTop = scope.mergeDimensions(left[0], right[0]);
    var mergedRight = scope.mergeDimensions(left[1], right[1]);
    var mergedBottom = scope.mergeDimensions(left[2], right[2]);
    var mergedLeft = scope.mergeDimensions(left[3], right[3]);
    return [
      [mergedTop[0], mergedRight[0], mergedBottom[0], mergedLeft[0]],
      [mergedTop[1], mergedRight[1], mergedBottom[1], mergedLeft[1]],
      function(rectValue) {
        return 'rect(' + mergedTop[2](rectValue[0]) + ', '
          + mergedRight[2](rectValue[1]) + ', '
          + mergedBottom[2](rectValue[2]) + ', '
          + mergedLeft[2](rectValue[3]) + ')'
      }
    ];
  }

  scope.addPropertiesHandler(parseBox, mergeBoxes, ['clip']);

  scope.parseBox = parseBox;
  scope.mergeBoxes = mergeBoxes;

})(webAnimationsMinifill, webAnimationsTesting);<commit_msg>Combined two regexps<commit_after>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
// limitations under the License.

(function(scope, testing) {

  // function parseBoxWithCalcLeft(string) {
  //   var rectangleWithCalcRegExp = /rect\(([^,]+), ([^,]+), ([^,]+), (calc\(.+\))\)/
  //   match = rectangleWithCalcRegExp.exec(string);
  //   if (!match) {
  //     return undefined;
  //   }
  //   var out = [
  //     scope.parseLengthOrPercent(match[1]),
  //     scope.parseLengthOrPercent(match[2]),
  //     scope.parseLengthOrPercent(match[3]),
  //     scope.parseLengthOrPercent(match[4])
  //     ];
  //   console.log(out);
  //   if (out[0] && out[1] && out[2] && out[3]) {
  //     console.log("returning the other one");
  //     return out;
  //   }
  //   return undefined;
  // }

  function parseBox(string) {
    // var rectangleRegExp = /rect\(([^,]+),([^,]+),([^,]+),([^)]+)\)/;
    // var rectangleRegExp = /rect\(([^,]+), ([^,]+), ([^,]+), (.+)\)/
    var rectangleRegExp = /rect\((.+), (.+), (.+), (.+)\)/
    var match = rectangleRegExp.exec(string);
    if (!match) {
      return undefined;
    }
    var out = [
      scope.parseLengthOrPercent(match[1]),
      scope.parseLengthOrPercent(match[2]),
      scope.parseLengthOrPercent(match[3]),
      scope.parseLengthOrPercent(match[4])
      ];
    console.log(out);
    if (out[0] && out[1] && out[2] && out[3]) {
      return out;
    }
    // return parseBoxWithCalcLeft(string);
    return undefined;
  }

  function mergeBoxes(left, right) {
    var mergedTop = scope.mergeDimensions(left[0], right[0]);
    var mergedRight = scope.mergeDimensions(left[1], right[1]);
    var mergedBottom = scope.mergeDimensions(left[2], right[2]);
    var mergedLeft = scope.mergeDimensions(left[3], right[3]);
    return [
      [mergedTop[0], mergedRight[0], mergedBottom[0], mergedLeft[0]],
      [mergedTop[1], mergedRight[1], mergedBottom[1], mergedLeft[1]],
      function(rectValue) {
        return 'rect(' + mergedTop[2](rectValue[0]) + ', '
          + mergedRight[2](rectValue[1]) + ', '
          + mergedBottom[2](rectValue[2]) + ', '
          + mergedLeft[2](rectValue[3]) + ')'
      }
    ];
  }

  scope.addPropertiesHandler(parseBox, mergeBoxes, ['clip']);

  scope.parseBox = parseBox;
  scope.mergeBoxes = mergeBoxes;

})(webAnimationsMinifill, webAnimationsTesting);<|endoftext|>