<commit_before>"use strict";

var _ = require('./lodash');

var ScribeInterface = require('./scribe-interface');

var config = require('./config');
var utils = require('./utils');
var Dom = require('./packages/dom');
var Events = require('./packages/events');
var BlockMixins = require('./block_mixins');

var SimpleBlock = require('./simple-block');
var BlockReorder = require('./block-reorder');
var BlockDeletion = require('./block-deletion');
var BlockPositioner = require('./block-positioner');
var EventBus = require('./event-bus');

var { Spinner } = require('spin.js');

const DELETE_TEMPLATE = require("./templates/delete");

var Block = function(data, instance_id, mediator, options, editorOptions) {
  SimpleBlock.apply(this, arguments);
};

Block.prototype = Object.create(SimpleBlock.prototype);
Block.prototype.constructor = Block;

Object.assign(Block.prototype, SimpleBlock.fn, require('./block-validations'), {

  bound: [
    "_handleContentPaste", "_onFocus", "_onBlur", "onDrop", "onDeleteClick",
    "clearInsertedStyles", "getSelectionForFormatter", "onBlockRender",
    "onDeleteConfirm", "onPositionerClick"
  ],

  className: 'st-block',

  attributes: function() {
    return Object.assign(SimpleBlock.fn.attributes.call(this));
  },

  icon_name: 'default',

  validationFailMsg: function() {
    return i18n.t('errors:validation_fail', { type: _.isFunction(this.title) ? this.title() : this.title });
  },

  editorHTML: "

",

  toolbarEnabled: true,

  availableMixins: ['droppable', 'pastable', 'uploadable', 'fetchable',
    'ajaxable', 'controllable', 'multi_editable', 'textable'],

  droppable: false,
  pastable: false,
  uploadable: false,
  fetchable: false,
  ajaxable: false,
  mergeable: false,
  multi_editable: false,
  textable: false,

  drop_options: {},
  paste_options: {},
  upload_options: {},

  formattable: true,
  supressKeyListeners: false,

  _previousSelection: '',

  initialize: function() {},

  toMarkdown: function(markdown){ return markdown; },
  toHTML: function(html){ return html; },

  withMixin: function(mixin) {
    if (!_.isObject(mixin)) { return; }

    var initializeMethod = "initialize" + mixin.mixinName;

    if (_.isUndefined(this[initializeMethod])) {
      Object.assign(this, mixin);
      this[initializeMethod]();
    }
  },

  render: function() {
    this.beforeBlockRender();
    this._setBlockInner();

    this.editor = this.inner.children[0];

    this.mixinsRequireInputs = false;
    this.availableMixins.forEach(function(mixin) {
      if (this[mixin]) {
        var blockMixin = BlockMixins[utils.classify(mixin)];
        if (!_.isUndefined(blockMixin.requireInputs) && blockMixin.requireInputs) {
          this.mixinsRequireInputs = true;
        }
      }
    }, this);

    if(this.mixinsRequireInputs) {
      var input_html = document.createElement("div");
      input_html.classList.add('st-block__inputs');
      this.inner.appendChild(input_html);
      this.inputs = input_html;
    }

    if (this.hasTextBlock()) { this._initTextBlocks(); }

    this.availableMixins.forEach(function(mixin) {
      if (this[mixin]) {
        this.withMixin(BlockMixins[utils.classify(mixin)]);
      }
    }, this);

    if (this.formattable) { this._initFormatting(); }

    this._blockPrepare();

    return this;
  },

  remove: function() {
    if (this.ajaxable) {
      this.resolveAllInQueue();
    }

    Dom.remove(this.el);
  },

  loading: function() {
    if(!_.isUndefined(this.spinner)) { this.ready(); }

    this.spinner = new Spinner(config.defaults.spinner);
    this.spinner.spin(this.el);

    this.el.classList.add('st--is-loading');
  },

  ready: function() {
    this.el.classList.remove('st--is-loading');
    if (!_.isUndefined(this.spinner)) {
      this.spinner.stop();
      delete this.spinner;
    }
  },

   //Generic _serializeData implementation to serialize the block into a plain object.
   //Can be overwritten, although hopefully this will cover most situations.
   //If you want to get the data of your block use block.getBlockData()

   // jshint maxdepth:4
  _serializeData: function() {
    utils.log("toData for " + this.blockID);

    var data = {};

    //[> Simple to start. Add conditions later <]
    if (this.hasTextBlock()) {
      data.text = this.getTextBlockHTML();
      data.format = 'html';
    }

    // Add any inputs to the data attr
    var matcher = [
      'input:not([class="st-paste-block"])',
      'textarea:not([class="st-paste-block"])',
      'select:not([class="st-paste-block"])',
      'button:not([class="st-paste-block"])'
    ].join(",");

    if (this.$(matcher).length > 0) {
      Array.prototype.forEach.call(this.$('input, textarea, select, button'), function(input) {

        // Reference elements by their `name` attribute. For elements such as radio buttons
        // which require a unique reference per group of elements a `data-name` attribute can
        // be used to provide the same `name` per block.

        var name = input.getAttribute('data-name') || input.getAttribute('name');

        if (name) {
          if (input.getAttribute('type') === 'number') {
            data[name] = parseInt(input.value);
          }
          else if (input.getAttribute('type') === 'checkbox') {
            var value = "";
            if (input.getAttribute('data-toggle')) {
              value = "off";
              if (input.checked === true) {
                value = "on";
              }
            } else if (input.checked === true) {
              value = input.value;
            }
            data[name] = value;
          }
          else if (input.getAttribute('type') === 'radio') {
            if (input.checked === true) {
              data[name] = input.value;
            }
          }
          else {
            data[name] = input.value;
          }
        }
      });
    }

    return data;
  },

  //[> Generic implementation to tell us when the block is active <]
  focus: function() {
    Array.prototype.forEach.call(this.getTextBlock(), function(el) {
      console.log("fcc");
      el.focus();
    });
  },

  focusAtEnd: function() {
    this.focus();
  },

  blur: function() {
    Array.prototype.forEach.call(this.getTextBlock(), function(el) {
      el.blur();
    });
  },

  onFocus: function() {
    Array.prototype.forEach.call(this.getTextBlock(), (el) => {
      el.addEventListener('focus', this._onFocus);
    });
  },

  onBlur: function() {
    Array.prototype.forEach.call(this.getTextBlock(), (el) => {
      el.addEventListener('blur', this._onBlur);
    });
  },

  //Event handlers
  _onFocus: function() {
    this.trigger('blockFocus', this.el);
  },

  _onBlur: function() {},

  onDrop: function(dataTransferObj) {},

  onDeleteConfirm: function(e) {
    e.preventDefault();
    this.mediator.trigger('block:remove', this.blockID, {focusOnPrevious: true});
  },

  // REFACTOR: have one set of delete controls that moves around like the
  // block controls?
  addDeleteControls: function(){

    var onDeleteDeny = (e) => {
      e.preventDefault();
      this.deleteEl.classList.remove("active");
    };

    this.ui.insertAdjacentHTML("beforeend", DELETE_TEMPLATE());
    Events.delegate(this.el, ".js-st-block-confirm-delete", "click", this.onDeleteConfirm);
    Events.delegate(this.el, ".js-st-block-deny-delete", "click", onDeleteDeny);
  },

  onDeleteClick: function(e) {
    e.preventDefault();
    e.stopPropagation();

    if (this.isEmpty()) {
      this.onDeleteConfirm.call(this, new CustomEvent('click'));
      return;
    }

    this.deleteEl = this.el.querySelector('.st-block__ui-delete-controls');
    this.deleteEl.classList.toggle('active');
  },

  onPositionerClick: function(e) {
    e.preventDefault();

    this.positioner.toggle();
  },

  beforeLoadingData: function() {
    this.loading();

    if(this.mixinsRequireInputs) {
      Dom.show(this.editor);
      Dom.hide(this.inputs);
    }

    SimpleBlock.fn.beforeLoadingData.call(this);

    this.ready();
  },

  execTextBlockCommand: function(cmdName) {
    if (_.isUndefined(this._scribe)) {
      throw "No Scribe instance found to send a command to";
    }

    return ScribeInterface.execTextBlockCommand(this._scribe, cmdName);
  },

  queryTextBlockCommandState: function(cmdName) {
    if (_.isUndefined(this._scribe)) {
      throw "No Scribe instance found to query command";
    }

    return ScribeInterface.queryTextBlockCommandState(this._scribe, cmdName);
  },

  _handleContentPaste: function(ev) {
    setTimeout(this.onContentPasted.bind(this, ev, ev.currentTarget), 0);
  },

  _getBlockClass: function() {
    return 'st-block--' + this.className;
  },

   //Init functions for adding functionality
  _initUIComponents: function() {

    this.addDeleteControls();

    this.positioner = new BlockPositioner(this.el, this.mediator);

    this._withUIComponent(this.positioner, '.st-block-ui-btn__reorder',
                          this.onPositionerClick);

    this._withUIComponent(new BlockReorder(this.el, this.mediator));

    this._withUIComponent(new BlockDeletion(), '.st-block-ui-btn__delete',
                          this.onDeleteClick);

    this.onFocus();
    this.onBlur();
  },

  _initFormatting: function() {

    // Enable formatting keyboard input
    var block = this;

    if (!this.options.formatBar) {
      return;
    }

    this.options.formatBar.commands.forEach(function(cmd) {
      if (_.isUndefined(cmd.keyCode)) {
        return;
      }

      Events.delegate(block.el, '.st-text-block', 'keydown', function (ev) {
        if ((ev.metaKey || ev.ctrlKey) && ev.keyCode === cmd.keyCode) {
          ev.preventDefault();
          block.execTextBlockCommand(cmd.cmd);
        }
      });
    });
  },

  _initTextBlocks: function() {
    Array.prototype.forEach.call(this.getTextBlock(), (el) => {
      el.addEventListener('keyup', this.getSelectionForFormatter);
      el.addEventListener('mousedown', this.addMouseupListener.bind(this));
      el.addEventListener('DOMNodeInserted', this.clearInsertedStyles);
    });

    var textBlock = this.getTextBlock()[0];
    if (!_.isUndefined(textBlock) && _.isUndefined(this._scribe)) {

      var configureScribe =
        _.isFunction(this.configureScribe) ? this.configureScribe.bind(this) : null;
      this._scribe = ScribeInterface.initScribeInstance(
        textBlock, this.scribeOptions, configureScribe
      );
    }
  },

  addMouseupListener: function addMouseupListener() {
    var listener = () => {
      this.getSelectionForFormatter();
      window.removeEventListener('mouseup', listener);
    };
    window.addEventListener('mouseup', listener);
  },

  getSelectionForFormatter: function() {
    setTimeout(() => {
      var selection = window.getSelection(),
          selectionStr = selection.toString().trim(),
          en = 'formatter:' + ((selectionStr === '') ? 'hide' : 'position');

      this.mediator.trigger(en, this);
      EventBus.trigger(en, this);
    }, 1);
  },

  clearInsertedStyles: function(e) {
    var target = e.target;
    if (_.isUndefined(target.tagName)) {
      target = target.parentNode;
    }
    target.removeAttribute('style'); // Hacky fix for Chrome.
  },

  hasTextBlock: function() {
    return this.getTextBlock().length > 0;
  },

  getTextBlock: function() {
    if (_.isUndefined(this.text_block)) {
      this.text_block = this.$('.st-text-block');
    }

    return this.text_block;
  },

  getTextBlockHTML: function() {
    return this._scribe.getContent();
  },

  setTextBlockHTML: function(html) {
    var returnVal = this._scribe.setContent(html);

    // Remove any whitespace in the first node, otherwise selections won't work.
    var firstNode = this._scribe.node.firstDeepestChild(this._scribe.el);
    if (firstNode.nodeName === '#text') {
      firstNode.textContent = utils.leftTrim(firstNode.textContent);
    }

    // Remove all empty nodes at the front to get blocks working.
    // Don't remove nodes that can't contain text content (e.g. <input>)
    while (this._scribe.el.firstChild && this._scribe.el.firstChild.textContent === '' && document.createElement(this._scribe.el.firstChild.tagName).outerHTML.indexOf("/") != -1) {
      this._scribe.el.removeChild(this._scribe.el.firstChild);
    }

    // Firefox adds empty br tags at the end of content.
    while(this._scribe.el.lastChild && this._scribe.el.lastChild.nodeName === 'BR') {
      this._scribe.el.removeChild(this._scribe.el.lastChild);
    }

    return returnVal;
  },

  isEmpty: function() {
    return _.isEmpty(this.getBlockData());
  }

});

Block.extend = require('./helpers/extend'); // Allow our Block to be extended.

module.exports = Block;
<commit_msg>Remove console.log<commit_after>"use strict";

var _ = require('./lodash');

var ScribeInterface = require('./scribe-interface');

var config = require('./config');
var utils = require('./utils');
var Dom = require('./packages/dom');
var Events = require('./packages/events');
var BlockMixins = require('./block_mixins');

var SimpleBlock = require('./simple-block');
var BlockReorder = require('./block-reorder');
var BlockDeletion = require('./block-deletion');
var BlockPositioner = require('./block-positioner');
var EventBus = require('./event-bus');

var { Spinner } = require('spin.js');

const DELETE_TEMPLATE = require("./templates/delete");

var Block = function(data, instance_id, mediator, options, editorOptions) {
  SimpleBlock.apply(this, arguments);
};

Block.prototype = Object.create(SimpleBlock.prototype);
Block.prototype.constructor = Block;

Object.assign(Block.prototype, SimpleBlock.fn, require('./block-validations'), {

  bound: [
    "_handleContentPaste", "_onFocus", "_onBlur", "onDrop", "onDeleteClick",
    "clearInsertedStyles", "getSelectionForFormatter", "onBlockRender",
    "onDeleteConfirm", "onPositionerClick"
  ],

  className: 'st-block',

  attributes: function() {
    return Object.assign(SimpleBlock.fn.attributes.call(this));
  },

  icon_name: 'default',

  validationFailMsg: function() {
    return i18n.t('errors:validation_fail', { type: _.isFunction(this.title) ? this.title() : this.title });
  },

  editorHTML: "

",

  toolbarEnabled: true,

  availableMixins: ['droppable', 'pastable', 'uploadable', 'fetchable',
    'ajaxable', 'controllable', 'multi_editable', 'textable'],

  droppable: false,
  pastable: false,
  uploadable: false,
  fetchable: false,
  ajaxable: false,
  mergeable: false,
  multi_editable: false,
  textable: false,

  drop_options: {},
  paste_options: {},
  upload_options: {},

  formattable: true,
  supressKeyListeners: false,

  _previousSelection: '',

  initialize: function() {},

  toMarkdown: function(markdown){ return markdown; },
  toHTML: function(html){ return html; },

  withMixin: function(mixin) {
    if (!_.isObject(mixin)) { return; }

    var initializeMethod = "initialize" + mixin.mixinName;

    if (_.isUndefined(this[initializeMethod])) {
      Object.assign(this, mixin);
      this[initializeMethod]();
    }
  },

  render: function() {
    this.beforeBlockRender();
    this._setBlockInner();

    this.editor = this.inner.children[0];

    this.mixinsRequireInputs = false;
    this.availableMixins.forEach(function(mixin) {
      if (this[mixin]) {
        var blockMixin = BlockMixins[utils.classify(mixin)];
        if (!_.isUndefined(blockMixin.requireInputs) && blockMixin.requireInputs) {
          this.mixinsRequireInputs = true;
        }
      }
    }, this);

    if(this.mixinsRequireInputs) {
      var input_html = document.createElement("div");
      input_html.classList.add('st-block__inputs');
      this.inner.appendChild(input_html);
      this.inputs = input_html;
    }

    if (this.hasTextBlock()) { this._initTextBlocks(); }

    this.availableMixins.forEach(function(mixin) {
      if (this[mixin]) {
        this.withMixin(BlockMixins[utils.classify(mixin)]);
      }
    }, this);

    if (this.formattable) { this._initFormatting(); }

    this._blockPrepare();

    return this;
  },

  remove: function() {
    if (this.ajaxable) {
      this.resolveAllInQueue();
    }

    Dom.remove(this.el);
  },

  loading: function() {
    if(!_.isUndefined(this.spinner)) { this.ready(); }

    this.spinner = new Spinner(config.defaults.spinner);
    this.spinner.spin(this.el);

    this.el.classList.add('st--is-loading');
  },

  ready: function() {
    this.el.classList.remove('st--is-loading');
    if (!_.isUndefined(this.spinner)) {
      this.spinner.stop();
      delete this.spinner;
    }
  },

   //Generic _serializeData implementation to serialize the block into a plain object.
   //Can be overwritten, although hopefully this will cover most situations.
   //If you want to get the data of your block use block.getBlockData()

   // jshint maxdepth:4
  _serializeData: function() {
    utils.log("toData for " + this.blockID);

    var data = {};

    //[> Simple to start. Add conditions later <]
    if (this.hasTextBlock()) {
      data.text = this.getTextBlockHTML();
      data.format = 'html';
    }

    // Add any inputs to the data attr
    var matcher = [
      'input:not([class="st-paste-block"])',
      'textarea:not([class="st-paste-block"])',
      'select:not([class="st-paste-block"])',
      'button:not([class="st-paste-block"])'
    ].join(",");

    if (this.$(matcher).length > 0) {
      Array.prototype.forEach.call(this.$('input, textarea, select, button'), function(input) {

        // Reference elements by their `name` attribute. For elements such as radio buttons
        // which require a unique reference per group of elements a `data-name` attribute can
        // be used to provide the same `name` per block.

        var name = input.getAttribute('data-name') || input.getAttribute('name');

        if (name) {
          if (input.getAttribute('type') === 'number') {
            data[name] = parseInt(input.value);
          }
          else if (input.getAttribute('type') === 'checkbox') {
            var value = "";
            if (input.getAttribute('data-toggle')) {
              value = "off";
              if (input.checked === true) {
                value = "on";
              }
            } else if (input.checked === true) {
              value = input.value;
            }
            data[name] = value;
          }
          else if (input.getAttribute('type') === 'radio') {
            if (input.checked === true) {
              data[name] = input.value;
            }
          }
          else {
            data[name] = input.value;
          }
        }
      });
    }

    return data;
  },

  //[> Generic implementation to tell us when the block is active <]
  focus: function() {
    Array.prototype.forEach.call(this.getTextBlock(), function(el) {
      el.focus();
    });
  },

  focusAtEnd: function() {
    this.focus();
  },

  blur: function() {
    Array.prototype.forEach.call(this.getTextBlock(), function(el) {
      el.blur();
    });
  },

  onFocus: function() {
    Array.prototype.forEach.call(this.getTextBlock(), (el) => {
      el.addEventListener('focus', this._onFocus);
    });
  },

  onBlur: function() {
    Array.prototype.forEach.call(this.getTextBlock(), (el) => {
      el.addEventListener('blur', this._onBlur);
    });
  },

  //Event handlers
  _onFocus: function() {
    this.trigger('blockFocus', this.el);
  },

  _onBlur: function() {},

  onDrop: function(dataTransferObj) {},

  onDeleteConfirm: function(e) {
    e.preventDefault();
    this.mediator.trigger('block:remove', this.blockID, {focusOnPrevious: true});
  },

  // REFACTOR: have one set of delete controls that moves around like the
  // block controls?
  addDeleteControls: function(){

    var onDeleteDeny = (e) => {
      e.preventDefault();
      this.deleteEl.classList.remove("active");
    };

    this.ui.insertAdjacentHTML("beforeend", DELETE_TEMPLATE());
    Events.delegate(this.el, ".js-st-block-confirm-delete", "click", this.onDeleteConfirm);
    Events.delegate(this.el, ".js-st-block-deny-delete", "click", onDeleteDeny);
  },

  onDeleteClick: function(e) {
    e.preventDefault();
    e.stopPropagation();

    if (this.isEmpty()) {
      this.onDeleteConfirm.call(this, new CustomEvent('click'));
      return;
    }

    this.deleteEl = this.el.querySelector('.st-block__ui-delete-controls');
    this.deleteEl.classList.toggle('active');
  },

  onPositionerClick: function(e) {
    e.preventDefault();

    this.positioner.toggle();
  },

  beforeLoadingData: function() {
    this.loading();

    if(this.mixinsRequireInputs) {
      Dom.show(this.editor);
      Dom.hide(this.inputs);
    }

    SimpleBlock.fn.beforeLoadingData.call(this);

    this.ready();
  },

  execTextBlockCommand: function(cmdName) {
    if (_.isUndefined(this._scribe)) {
      throw "No Scribe instance found to send a command to";
    }

    return ScribeInterface.execTextBlockCommand(this._scribe, cmdName);
  },

  queryTextBlockCommandState: function(cmdName) {
    if (_.isUndefined(this._scribe)) {
      throw "No Scribe instance found to query command";
    }

    return ScribeInterface.queryTextBlockCommandState(this._scribe, cmdName);
  },

  _handleContentPaste: function(ev) {
    setTimeout(this.onContentPasted.bind(this, ev, ev.currentTarget), 0);
  },

  _getBlockClass: function() {
    return 'st-block--' + this.className;
  },

   //Init functions for adding functionality
  _initUIComponents: function() {

    this.addDeleteControls();

    this.positioner = new BlockPositioner(this.el, this.mediator);

    this._withUIComponent(this.positioner, '.st-block-ui-btn__reorder',
                          this.onPositionerClick);

    this._withUIComponent(new BlockReorder(this.el, this.mediator));

    this._withUIComponent(new BlockDeletion(), '.st-block-ui-btn__delete',
                          this.onDeleteClick);

    this.onFocus();
    this.onBlur();
  },

  _initFormatting: function() {

    // Enable formatting keyboard input
    var block = this;

    if (!this.options.formatBar) {
      return;
    }

    this.options.formatBar.commands.forEach(function(cmd) {
      if (_.isUndefined(cmd.keyCode)) {
        return;
      }

      Events.delegate(block.el, '.st-text-block', 'keydown', function (ev) {
        if ((ev.metaKey || ev.ctrlKey) && ev.keyCode === cmd.keyCode) {
          ev.preventDefault();
          block.execTextBlockCommand(cmd.cmd);
        }
      });
    });
  },

  _initTextBlocks: function() {
    Array.prototype.forEach.call(this.getTextBlock(), (el) => {
      el.addEventListener('keyup', this.getSelectionForFormatter);
      el.addEventListener('mousedown', this.addMouseupListener.bind(this));
      el.addEventListener('DOMNodeInserted', this.clearInsertedStyles);
    });

    var textBlock = this.getTextBlock()[0];
    if (!_.isUndefined(textBlock) && _.isUndefined(this._scribe)) {

      var configureScribe =
        _.isFunction(this.configureScribe) ? this.configureScribe.bind(this) : null;
      this._scribe = ScribeInterface.initScribeInstance(
        textBlock, this.scribeOptions, configureScribe
      );
    }
  },

  addMouseupListener: function addMouseupListener() {
    var listener = () => {
      this.getSelectionForFormatter();
      window.removeEventListener('mouseup', listener);
    };
    window.addEventListener('mouseup', listener);
  },

  getSelectionForFormatter: function() {
    setTimeout(() => {
      var selection = window.getSelection(),
          selectionStr = selection.toString().trim(),
          en = 'formatter:' + ((selectionStr === '') ? 'hide' : 'position');

      this.mediator.trigger(en, this);
      EventBus.trigger(en, this);
    }, 1);
  },

  clearInsertedStyles: function(e) {
    var target = e.target;
    if (_.isUndefined(target.tagName)) {
      target = target.parentNode;
    }
    target.removeAttribute('style'); // Hacky fix for Chrome.
  },

  hasTextBlock: function() {
    return this.getTextBlock().length > 0;
  },

  getTextBlock: function() {
    if (_.isUndefined(this.text_block)) {
      this.text_block = this.$('.st-text-block');
    }

    return this.text_block;
  },

  getTextBlockHTML: function() {
    return this._scribe.getContent();
  },

  setTextBlockHTML: function(html) {
    var returnVal = this._scribe.setContent(html);

    // Remove any whitespace in the first node, otherwise selections won't work.
    var firstNode = this._scribe.node.firstDeepestChild(this._scribe.el);
    if (firstNode.nodeName === '#text') {
      firstNode.textContent = utils.leftTrim(firstNode.textContent);
    }

    // Remove all empty nodes at the front to get blocks working.
    // Don't remove nodes that can't contain text content (e.g. <input>)
    while (this._scribe.el.firstChild && this._scribe.el.firstChild.textContent === '' && document.createElement(this._scribe.el.firstChild.tagName).outerHTML.indexOf("/") != -1) {
      this._scribe.el.removeChild(this._scribe.el.firstChild);
    }

    // Firefox adds empty br tags at the end of content.
    while(this._scribe.el.lastChild && this._scribe.el.lastChild.nodeName === 'BR') {
      this._scribe.el.removeChild(this._scribe.el.lastChild);
    }

    return returnVal;
  },

  isEmpty: function() {
    return _.isEmpty(this.getBlockData());
  }

});

Block.extend = require('./helpers/extend'); // Allow our Block to be extended.

module.exports = Block;
<|endoftext|>


<commit_before>import {describeComponent} from 'ember-mocha'
import {PropTypes} from 'ember-prop-types'
import {validatePropTypes} from '../../utils/template'

describeComponent(
  'frost-bunsen-form',
  'FrostBunsenFormComponent',
  {},
  function () {
    validatePropTypes({
      cancelLabel: PropTypes.string,
      inline: PropTypes.bool,
      model: PropTypes.oneOf([
        PropTypes.EmberObject,
        PropTypes.object
      ]).isRequired,
      onCancel: PropTypes.func,
      onChange: PropTypes.func,
      onSubmit: PropTypes.func,
      onValidation: PropTypes.func,
      renderers: PropTypes.oneOf([
        PropTypes.EmberObject,
        PropTypes.object
      ]),
      submitLabel: PropTypes.string,
      validators: PropTypes.array,
      value: PropTypes.oneOf([
        PropTypes.EmberObject,
        PropTypes.null,
        PropTypes.object
      ]),
      view: PropTypes.oneOf([
        PropTypes.EmberObject,
        PropTypes.object
      ])
    })
  }
)
<commit_msg>Add test to make sure store.formValue is defined<commit_after>const {expect} = chai
import Ember from 'ember'
const {run} = Ember
import {describeComponent} from 'ember-mocha'
import {beforeEach, describe, it} from 'mocha'
import {PropTypes} from 'ember-prop-types'
import {validatePropTypes} from '../../utils/template'

describeComponent(
  'frost-bunsen-form',
  'FrostBunsenFormComponent',
  {},
  function () {
    let component

    beforeEach(function () {
      component = this.subject()

      run(() => {
        component.setProperties({
          model: {
            properties: {
              foo: {type: 'string'}
            },
            type: 'object'
          }
        })
      })
    })

    validatePropTypes({
      cancelLabel: PropTypes.string,
      inline: PropTypes.bool,
      model: PropTypes.oneOf([
        PropTypes.EmberObject,
        PropTypes.object
      ]).isRequired,
      onCancel: PropTypes.func,
      onChange: PropTypes.func,
      onSubmit: PropTypes.func,
      onValidation: PropTypes.func,
      renderers: PropTypes.oneOf([
        PropTypes.EmberObject,
        PropTypes.object
      ]),
      submitLabel: PropTypes.string,
      validators: PropTypes.array,
      value: PropTypes.oneOf([
        PropTypes.EmberObject,
        PropTypes.null,
        PropTypes.object
      ]),
      view: PropTypes.oneOf([
        PropTypes.EmberObject,
        PropTypes.object
      ])
    })

    describe('store', function () {
      let store

      beforeEach(function () {
        store = component.get('store')
      })

      it('has expected formValue', function () {
        expect(store.formValue).to.eql({})
      })

      it('has expected renderers', function () {
        expect(store.renderers).to.eql({
          'multi-select': 'frost-bunsen-input-multi-select',
          'property-chooser': 'frost-bunsen-property-chooser',
          select: 'frost-bunsen-input-select'
        })
      })
    })
  }
)
<|endoftext|>


<commit_before>import Ember from "ember";
import { moduleFor, test } from 'ember-qunit';

moduleFor('controller:gist', {
  // Specify the other units that are required for this test.
  // needs: ['controller:foo']
  needs: ['service:ember-cli']
});

// Replace this with your real tests.
test('it exists', function(assert) {
  var controller = this.subject();
  assert.ok(controller);
});

test('deleting a gist requires confirmation', function(assert) {
  let cacheConfirm = window.confirm;
  let controller = this.subject({
    transitionToRoute() {},
    notify: {
      info() {}
    }
  });
  let gistClass = Ember.Object.extend({
    called: false,
    destroyRecord() {
      this.set('called', true);
    }
  });

  window.confirm = () => true;
  let gist = gistClass.create();
  controller.send('deleteGist', gist);
  assert.ok(gist.get('called'), 'gist.destroyRecord was called when confirmed');

  window.confirm = () => false;
  gist = gistClass.create();
  controller.send('deleteGist', gist);
  assert.ok(!gist.get('called'), 'gist.destroyRecord was not called when not confirmed');

  window.confirm = cacheConfirm;
});
<commit_msg>Address PR comments on unit test for confirm delete<commit_after>import Ember from "ember";
import { moduleFor, test } from 'ember-qunit';

moduleFor('controller:gist', {
  needs: ['service:ember-cli'],

  beforeEach() {
    this._originalConfirm = window.confirm;
  },

  afterEach() {
    window.confirm = this._originalConfirm;
  }
});

test('deleting a gist requires confirmation', function(assert) {
  let controller = this.subject({
    transitionToRoute() {},
    notify: {
      info() {}
    }
  });
  let gistClass = Ember.Object.extend({
    called: false,
    destroyRecord() {
      this.set('called', true);
    }
  });

  window.confirm = () => true;
  let gist = gistClass.create();
  controller.send('deleteGist', gist);
  assert.ok(gist.get('called'), 'gist.destroyRecord was called when confirmed');

  window.confirm = () => false;
  gist = gistClass.create();
  controller.send('deleteGist', gist);
  assert.ok(!gist.get('called'), 'gist.destroyRecord was not called when not confirmed');
});
<|endoftext|>


<commit_before>/*jslint node: true, nomen: true, white: true, unparam: true*/
/*globals describe, beforeEach, afterEach, it, expect, spyOn*/
/*!
 * Sitegear3
 * Copyright(c) 2014 Ben New, Sitegear.org
 * MIT Licensed
 */

(function (_, sitegear3, defaultModule) {
	"use strict";
	require('../setupTests');

	describe('Module: default', function () {
		it('Exports a function', function () {
			expect(_.isFunction(defaultModule)).toBeTruthy();
		});
		describe('Operates correctly', function () {
			var app, module;
			beforeEach(function () {
				app = require('../_mock/app');
				module = defaultModule(app);
			});
			it('Exposes all required action methods', function () {
				expect(_.isFunction(module.index)).toBeTruthy();
			});
			describe('The index() action', function () {
				var mockRequest, mockResponse;
				beforeEach(function () {
					mockRequest = require('../_mock/request');
					mockResponse = require('../_mock/response');
					spyOn(app.interfaces.storage, 'get').andCallThrough();
					spyOn(mockResponse, 'render');
					module.index()(mockRequest, mockResponse);
				});
				it('Makes the correct number of calls to persistence', function () {
					expect(app.interfaces.storage.get).toHaveBeenCalled();
					expect(app.interfaces.storage.get.callCount).toBe(1);
				});
				it('Calls response.render()', function () {
					expect(mockResponse.render).toHaveBeenCalled();
					expect(mockResponse.render.callCount).toBe(1);
				});
			});
			afterEach(function () {
				app.stop();
			});
		});
	});
}(require('lodash'), require('../../../index'), require('../../../lib/modules/default')));
<commit_msg>Improve unit tests for default controller.<commit_after>/*jslint node: true, nomen: true, white: true, unparam: true*/
/*globals describe, beforeEach, afterEach, it, expect, spyOn*/
/*!
 * Sitegear3
 * Copyright(c) 2014 Ben New, Sitegear.org
 * MIT Licensed
 */

(function (_, sitegear3, defaultModule, jasmine) {
	"use strict";
	require('../setupTests');

	describe('Module: default', function () {
		it('Exports a function', function () {
			expect(_.isFunction(defaultModule)).toBeTruthy();
		});
		describe('Operates correctly', function () {
			var app, module;
			beforeEach(function () {
				app = require('../_mock/app');
				module = defaultModule(app);
			});
			it('Exposes all required action methods', function () {
				expect(_.isFunction(module.index)).toBeTruthy();
			});
			describe('The index() action', function () {
				var mockRequest, mockResponse;
				describe('By default', function () {
					beforeEach(function () {
						mockRequest = require('../_mock/request');
						mockResponse = require('../_mock/response');
						spyOn(app.interfaces.storage, 'get').andCallThrough();
						module.index()(mockRequest, mockResponse);
					});
					it('Makes the correct number of calls to persistence', function () {
						expect(app.interfaces.storage.get).toHaveBeenCalled();
						expect(app.interfaces.storage.get.callCount).toBe(1);
					});
				});
				describe('When persistence is returning data normally', function () {
					beforeEach(function () {
						mockRequest = require('../_mock/request');
						mockResponse = require('../_mock/response');
						spyOn(mockResponse, 'render');
						module.index()(mockRequest, mockResponse);
					});
					it('Calls response.render()', function () {
						expect(mockResponse.render).toHaveBeenCalled();
						expect(mockResponse.render.callCount).toBe(1);
					});
				});
				describe('When persistence is throwing errors', function () {
					var next,
						error = new Error('This is an error from storage interface');
					beforeEach(function () {
						mockRequest = require('../_mock/request');
						mockResponse = require('../_mock/response');
						spyOn(mockResponse, 'render');
						next = jasmine.createSpy('next');
						app.interfaces.storage.get = function (type, key, callback) {
							callback(error);
						};
						module.index()(mockRequest, mockResponse, next);
					});
					it('Calls next() with the error', function () {
						expect(next).toHaveBeenCalledWith(error);
						expect(next.callCount).toBe(1);
					});
					it('Doesn\'t call response.render()', function () {
						expect(mockResponse.render).not.toHaveBeenCalled();
					});
				});
			});
		});
	});
}(require('lodash'), require('../../../index'), require('../../../lib/modules/default'), require('jasmine-node')));
<|endoftext|>


<commit_before>import { shallowMount } from '@vue/test-utils'
import Spinner from '../../../src/components/widgets/Spinner'

describe('Spinner', () => {
  const wrapper = shallowMount(Spinner, {
    propsData: {
      isWhite: undefined,
      size: undefined
    }
  })

  describe('Mount', () => {
    it('should be default', () => {
      expect(wrapper.element.style.width).toMatch('auto')
      expect(wrapper.element.children[0].src).toMatch(new RegExp('spinner.svg$'))
    })

    it('should be 30px wide', () => {
      wrapper.setProps({ size: 30 })
      expect(wrapper.element.style.width).toMatch('30px')
    })

    it('should be white', () => {
      wrapper.setProps({ isWhite: true })
      expect(wrapper.element.children[0].src).toMatch(new RegExp('spinner-white.svg$'))
    })
  })
})
<commit_msg>fix: Spinner component tests<commit_after>import Vue from 'Vue'
import { shallowMount } from '@vue/test-utils'
import Spinner from '../../../src/components/widgets/Spinner'

describe('Spinner', () => {
  const wrapper = shallowMount(Spinner, {
    propsData: {
      isWhite: undefined,
      size: undefined
    }
  })

  describe('Mount', () => {
    it('should be default', () => {
      expect(wrapper.element.style.width).toMatch('auto')
      expect(wrapper.element.children[0].src).toMatch(new RegExp('spinner.svg$'))
    })

    it('should be 30px wide', done => {
      wrapper.setProps({ size: 30 })
      Vue.nextTick(() => {
        expect(wrapper.element.style.width).toMatch('30px')
        done()
      })
    })

    it('should be white', done => {
      wrapper.setProps({ isWhite: true })
      Vue.nextTick(() => {
        expect(wrapper.element.children[0].src).toMatch(new RegExp('spinner-white.svg$'))
        done()
      })
    })
  })
})
<|endoftext|>


<commit_before>'use strict';

(function (angular) {

  // Make sure to include the required dependency to the module
  angular.module('mediaCenterRSSPluginWidget', [
    'ngRoute',
    'infinite-scroll',
    "ngSanitize",
    "com.2fdevs.videogular",
    "com.2fdevs.videogular.plugins.controls",
    "com.2fdevs.videogular.plugins.overlayplay",
    "videosharing-embed"
  ])

    .config(['$routeProvider', '$compileProvider', function ($routeProvider, $compileProvider) {

      /**
       * To make href urls safe on mobile
       */
      $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrome-extension|cdvfile|file):/);

      /*****************************
       *  Redirects and Otherwise  *
       *****************************/

        // Use $routeProvider to configure any redirects (when) and invalid urls (otherwise).
      $routeProvider
        .when('/', {
          templateUrl: 'templates/home.html',
          controllerAs: 'WidgetHome',
          controller: 'WidgetHomeCtrl'
        })
        .when('/item', {
          templateUrl: 'templates/media.html',
          controllerAs: 'WidgetMedia',
          controller: 'WidgetMediaCtrl'
        })

        // If the url is invalid then redirect to '/'
        .otherwise('/');
    }]);
})(window.angular);<commit_msg>Fixed back button<commit_after>'use strict';

(function (angular) {

    // Make sure to include the required dependency to the module
    angular.module('mediaCenterRSSPluginWidget', [
        'ngRoute',
        'infinite-scroll',
        "ngSanitize",
        "com.2fdevs.videogular",
        "com.2fdevs.videogular.plugins.controls",
        "com.2fdevs.videogular.plugins.overlayplay",
        "videosharing-embed"
    ])

        .config(['$routeProvider', '$compileProvider', function ($routeProvider, $compileProvider) {

            /**
             * To make href urls safe on mobile
             */
            $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrome-extension|cdvfile|file):/);

            /*****************************
             *  Redirects and Otherwise  *
             *****************************/

                // Use $routeProvider to configure any redirects (when) and invalid urls (otherwise).
            $routeProvider
                .when('/', {
                    templateUrl: 'templates/home.html',
                    controllerAs: 'WidgetHome',
                    controller: 'WidgetHomeCtrl'
                })
                .when('/item', {
                    templateUrl: 'templates/media.html',
                    controllerAs: 'WidgetMedia',
                    controller: 'WidgetMediaCtrl'
                })

                // If the url is invalid then redirect to '/'
                .otherwise('/');
        }])
        .run(['Location', '$location', function (Location, $location) {
            buildfire.navigation.onBackButtonClick = function () {
                var path = $location.path();
                if (path.indexOf('/item') == 0)
                    Location.goTo('#/');
                else
                    buildfire.navigation.navigateHome();
            }
        }])
    ;
})(window.angular);<|endoftext|>


<commit_before>'use strict';

(function (angular, buildfire) {
  angular.module('eventsFeedPluginWidget', ['ngRoute', 'ngTouch', 'infinite-scroll', 'ui.bootstrap'])
    .config(['$routeProvider', '$compileProvider', function ($routeProvider, $compileProvider) {

      /**
       * To make href urls safe on mobile
       */
      $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrome-extension|cdvfile):/);

      $routeProvider
        .when('/feed', {
          templateUrl: 'templates/home.html',
          controllerAs: 'WidgetFeed',
          controller: 'WidgetFeedCtrl'
        })
        .when('/event/:eventIndex', {
          templateUrl: 'templates/eventDetails.html',
          controller: 'WidgetEventCtrl',
          controllerAs: 'WidgetEvent'
        })
        .otherwise('/feed');
    }])
    .filter('getDateFromTimestamp', function () {
      return function (input) {
        return new Date(input).getDate();
      };
    })
    .filter('getMonthFromTimestamp', function () {
      var monthsObj = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"];
      return function (input) {
        return monthsObj[new Date(input).getMonth()];
      };
    })
    .filter('getTimeZone', function () {

      return function (input) {
        input = new Date(input);
        var result = input.toString().match(/\((.+)\)/i);
        if (result.length)
          return result[1];
        else return "";
      };
    })
    .run(['Location', '$location', function (Location, $location) {
      buildfire.navigation.onBackButtonClick = function () {
        if ($location.path() != "/feed") {
          Location.goTo('#/feed');
        }
      };
    }]);
})(window.angular, window.buildfire);
<commit_msg>Added check in timezone filter<commit_after>'use strict';

(function (angular, buildfire) {
  angular.module('eventsFeedPluginWidget', ['ngRoute', 'ngTouch', 'infinite-scroll', 'ui.bootstrap'])
    .config(['$routeProvider', '$compileProvider', function ($routeProvider, $compileProvider) {

      /**
       * To make href urls safe on mobile
       */
      $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrome-extension|cdvfile):/);

      $routeProvider
        .when('/feed', {
          templateUrl: 'templates/home.html',
          controllerAs: 'WidgetFeed',
          controller: 'WidgetFeedCtrl'
        })
        .when('/event/:eventIndex', {
          templateUrl: 'templates/eventDetails.html',
          controller: 'WidgetEventCtrl',
          controllerAs: 'WidgetEvent'
        })
        .otherwise('/feed');
    }])
    .filter('getDateFromTimestamp', function () {
      return function (input) {
        return new Date(input).getDate();
      };
    })
    .filter('getMonthFromTimestamp', function () {
      var monthsObj = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"];
      return function (input) {
        return monthsObj[new Date(input).getMonth()];
      };
    })
    .filter('getTimeZone', function () {

      return function (input) {
        input = new Date(input);
        var result = input.toString().match(/\((.+)\)/i);
        if (result && result.length)
          return result[1];
        else return "";
      };
    })
    .run(['Location', '$location', function (Location, $location) {
      buildfire.navigation.onBackButtonClick = function () {
        if ($location.path() != "/feed") {
          Location.goTo('#/feed');
        }
      };
    }]);
})(window.angular, window.buildfire);
<|endoftext|>


<commit_before>'use strict';

(function (angular, buildfire) {
    angular.module('vimeoPluginWidget', ['ngRoute', 'infinite-scroll', 'ngAnimate'])
        .config(['$routeProvider', '$compileProvider', function ($routeProvider, $compileProvider) {

            /**
             * To make href urls safe on mobile
             */
            $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrome-extension|cdvfile|file):/);

            $routeProvider
                .when('/', {
                    template: '

'
                })
                .when('/video/:videoId', {
                    templateUrl: 'templates/Item_Details.html',
                    controller: 'WidgetSingleCtrl',
                    controllerAs: 'WidgetSingle'
                })
                .otherwise('/');
        }])
      .filter('getImageUrl', ['Buildfire', function (Buildfire) {
          filter.$stateful = true;
          function filter(url, width, height, type) {
              var _imgUrl;
              if (!_imgUrl) {
                  if (type == 'resize') {
                      Buildfire.imageLib.local.resizeImage(url, {
                          width: width,
                          height: height
                      }, function (err, imgUrl) {
                          _imgUrl = imgUrl;
                      });
                  } else {
                      Buildfire.imageLib.local.cropImage(url, {
                          width: width,
                          height: height
                      }, function (err, imgUrl) {
                          _imgUrl = imgUrl;
                      });
                  }
              }

              return _imgUrl;
          }
          return filter;
      }])
        .directive("backgroundImage", ['$filter', function ($filter) {
            return {
                restrict: 'A',
                link: function (scope, element, attrs) {
                    var getImageUrlFilter = $filter("getImageUrl");
                    var setBackgroundImage = function (backgroundImage) {
                        if (backgroundImage) {
                            element.css(
                                'background', '#010101 url('
                                + getImageUrlFilter(backgroundImage, 342, 770, 'resize')
                                + ') repeat fixed top center');
                        } else {
                            element.css('background', 'none');
                        }
                    };
                    attrs.$observe('backgroundImage', function (newValue) {
                        setBackgroundImage(newValue);
                    });
                }
            };
        }])
        .directive("buildFireCarousel", ["$rootScope", "$timeout", function ($rootScope, $timeout) {
            return {
                restrict: 'A',
                link: function (scope, elem, attrs) {
                    $timeout(function () {
                        $rootScope.$broadcast("Carousel:LOADED");
                    }, 100);
                }
            };
        }])
        .filter('returnVimeoUrl', ['$sce', function ($sce) {
            return function (uri) {
                var id = uri.split("/").pop();
                return $sce.trustAsResourceUrl("http://player.vimeo.com/video/" + id);
            }
        }])
        .directive("triggerNgRepeatRender", [function () {
            return {
                restrict: 'A',
                link: function (scope, elem, attrs) {
                    var a = $(elem).width();
                }
            };
        }])
        .directive("manageAspectRatio", [function () {
            return {
                restrict: 'A',
                link: function (scope, elem, attrs) {
                    setTimeout(function () {
                        var width = $(window).width();
                        var height = (width * 9) / 16;
                        $(elem).css({height: height});
                    }, 100);
                }
            };
        }])
        .directive("loadImage", [function () {
            return {
                restrict: 'A',
                link: function (scope, element, attrs) {
                    element.attr("src", "../../../styles/media/holder-" + attrs.loadImage + ".gif");

                    var elem = $("");
                    elem[0].onload = function () {
                        element.attr("src", attrs.finalSrc);
                        elem.remove();
                    };
                    elem.attr("src", attrs.finalSrc);
                }
            };
        }])
        .directive("loadIframe", [function () {
            return {
                restrict: 'A',
                link: function (scope, element, attrs) {
                    var iframe = document.createElement('iframe'),
                        img = $(element).find("img");
                    iframe.id = 'vimeoPlayer';
                    iframe.onload = function () {
                        iframe.classList.remove("ng-hide");
                        img.remove();
                        //for managing aspect ratio of video player
                        var width = $(window).width();
                        var height = (width * 9) / 16;
                        $(iframe).css({height: height});
                    }; // before setting 'src'
                    iframe.src = attrs.loadIframe;
                    iframe.classList.add("ng-hide");
                    iframe.frameborder = "0";
                    $(element).append(iframe);
                }
            };
        }])
        .run(['Location', '$location', '$rootScope', function (Location, $location, $rootScope) {
            buildfire.navigation.onBackButtonClick = function () {
                var reg = /^\/video/;
                if (reg.test($location.path()) && ($rootScope.contentType == "Channel Feed" || $rootScope.contentType == "User Feed")) {
                    $rootScope.showFeed = true;
                    Location.goTo('#/');
                }
                else {
                    buildfire.navigation._goBackOne();
                }
            };
            if(buildfire.device) {
                buildfire.device.onAppBackgrounded(function () {
                    callVimeoPlayer('vimeoPlayer');
                });
            }
        }]).filter('cropImage', [function () {
          function filter (url, width, height, noDefault) {
              var _imgUrl;
              filter.$stateful = true;
              if(noDefault)
              {
                  if(!url)
                      return '';
              }
              if (!_imgUrl) {
                  buildfire.imageLib.local.cropImage(url, {
                      width: width,
                      height: height
                  }, function (err, imgUrl) {
                      _imgUrl = imgUrl;
                  });
              }
              return _imgUrl;
          }
          return filter;
      }]).directive('backImg', ["$rootScope", function ($rootScope) {
          return function (scope, element, attrs) {
              attrs.$observe('backImg', function (value) {
                  var img = '';
                  if (value) {
                      buildfire.imageLib.local.cropImage(value, {
                          width: $rootScope.deviceWidth,
                          height: $rootScope.deviceHeight
                      }, function (err, imgUrl) {
                          if (imgUrl) {
                              img = imgUrl;
                              element.attr("style", 'background:url(' + img + ') !important');
                          } else {
                              img = '';
                              element.attr("style", 'background-color:white');
                          }
                          element.css({
                              'background-size': 'cover'
                          });
                      });
                      // img = $filter("cropImage")(value, $rootScope.deviceWidth, $rootScope.deviceHeight, true);
                  }
                  else {
                      img = "";
                      element.attr("style", 'background-color:white');
                      element.css({
                          'background-size': 'cover'
                      });
                  }
              });
          };
      }]);
})(window.angular, window.buildfire);
<commit_msg>added background size cover Important<commit_after>'use strict';

(function (angular, buildfire) {
    angular.module('vimeoPluginWidget', ['ngRoute', 'infinite-scroll', 'ngAnimate'])
        .config(['$routeProvider', '$compileProvider', function ($routeProvider, $compileProvider) {

            /**
             * To make href urls safe on mobile
             */
            $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrome-extension|cdvfile|file):/);

            $routeProvider
                .when('/', {
                    template: '

'
                })
                .when('/video/:videoId', {
                    templateUrl: 'templates/Item_Details.html',
                    controller: 'WidgetSingleCtrl',
                    controllerAs: 'WidgetSingle'
                })
                .otherwise('/');
        }])
      .filter('getImageUrl', ['Buildfire', function (Buildfire) {
          filter.$stateful = true;
          function filter(url, width, height, type) {
              var _imgUrl;
              if (!_imgUrl) {
                  if (type == 'resize') {
                      Buildfire.imageLib.local.resizeImage(url, {
                          width: width,
                          height: height
                      }, function (err, imgUrl) {
                          _imgUrl = imgUrl;
                      });
                  } else {
                      Buildfire.imageLib.local.cropImage(url, {
                          width: width,
                          height: height
                      }, function (err, imgUrl) {
                          _imgUrl = imgUrl;
                      });
                  }
              }

              return _imgUrl;
          }
          return filter;
      }])
        .directive("backgroundImage", ['$filter', function ($filter) {
            return {
                restrict: 'A',
                link: function (scope, element, attrs) {
                    var getImageUrlFilter = $filter("getImageUrl");
                    var setBackgroundImage = function (backgroundImage) {
                        if (backgroundImage) {
                            element.css(
                                'background', '#010101 url('
                                + getImageUrlFilter(backgroundImage, 342, 770, 'resize')
                                + ') repeat fixed top center');
                        } else {
                            element.css('background', 'none');
                        }
                    };
                    attrs.$observe('backgroundImage', function (newValue) {
                        setBackgroundImage(newValue);
                    });
                }
            };
        }])
        .directive("buildFireCarousel", ["$rootScope", "$timeout", function ($rootScope, $timeout) {
            return {
                restrict: 'A',
                link: function (scope, elem, attrs) {
                    $timeout(function () {
                        $rootScope.$broadcast("Carousel:LOADED");
                    }, 100);
                }
            };
        }])
        .filter('returnVimeoUrl', ['$sce', function ($sce) {
            return function (uri) {
                var id = uri.split("/").pop();
                return $sce.trustAsResourceUrl("http://player.vimeo.com/video/" + id);
            }
        }])
        .directive("triggerNgRepeatRender", [function () {
            return {
                restrict: 'A',
                link: function (scope, elem, attrs) {
                    var a = $(elem).width();
                }
            };
        }])
        .directive("manageAspectRatio", [function () {
            return {
                restrict: 'A',
                link: function (scope, elem, attrs) {
                    setTimeout(function () {
                        var width = $(window).width();
                        var height = (width * 9) / 16;
                        $(elem).css({height: height});
                    }, 100);
                }
            };
        }])
        .directive("loadImage", [function () {
            return {
                restrict: 'A',
                link: function (scope, element, attrs) {
                    element.attr("src", "../../../styles/media/holder-" + attrs.loadImage + ".gif");

                    var elem = $("");
                    elem[0].onload = function () {
                        element.attr("src", attrs.finalSrc);
                        elem.remove();
                    };
                    elem.attr("src", attrs.finalSrc);
                }
            };
        }])
        .directive("loadIframe", [function () {
            return {
                restrict: 'A',
                link: function (scope, element, attrs) {
                    var iframe = document.createElement('iframe'),
                        img = $(element).find("img");
                    iframe.id = 'vimeoPlayer';
                    iframe.onload = function () {
                        iframe.classList.remove("ng-hide");
                        img.remove();
                        //for managing aspect ratio of video player
                        var width = $(window).width();
                        var height = (width * 9) / 16;
                        $(iframe).css({height: height});
                    }; // before setting 'src'
                    iframe.src = attrs.loadIframe;
                    iframe.classList.add("ng-hide");
                    iframe.frameborder = "0";
                    $(element).append(iframe);
                }
            };
        }])
        .run(['Location', '$location', '$rootScope', function (Location, $location, $rootScope) {
            buildfire.navigation.onBackButtonClick = function () {
                var reg = /^\/video/;
                if (reg.test($location.path()) && ($rootScope.contentType == "Channel Feed" || $rootScope.contentType == "User Feed")) {
                    $rootScope.showFeed = true;
                    Location.goTo('#/');
                }
                else {
                    buildfire.navigation._goBackOne();
                }
            };
            if(buildfire.device) {
                buildfire.device.onAppBackgrounded(function () {
                    callVimeoPlayer('vimeoPlayer');
                });
            }
        }]).filter('cropImage', [function () {
          function filter (url, width, height, noDefault) {
              var _imgUrl;
              filter.$stateful = true;
              if(noDefault)
              {
                  if(!url)
                      return '';
              }
              if (!_imgUrl) {
                  buildfire.imageLib.local.cropImage(url, {
                      width: width,
                      height: height
                  }, function (err, imgUrl) {
                      _imgUrl = imgUrl;
                  });
              }
              return _imgUrl;
          }
          return filter;
      }]).directive('backImg', ["$rootScope", function ($rootScope) {
          return function (scope, element, attrs) {
              attrs.$observe('backImg', function (value) {
                  var img = '';
                  if (value) {
                      buildfire.imageLib.local.cropImage(value, {
                          width: $rootScope.deviceWidth,
                          height: $rootScope.deviceHeight
                      }, function (err, imgUrl) {
                          if (imgUrl) {
                              img = imgUrl;
                              element.attr("style", 'background:url(' + img + ') !important');
                          } else {
                              img = '';
                              element.attr("style", 'background-color:white');
                          }
                          element.css({
                              'background-size': 'cover !important'
                          });
                      });
                      // img = $filter("cropImage")(value, $rootScope.deviceWidth, $rootScope.deviceHeight, true);
                  }
                  else {
                      img = "";
                      element.attr("style", 'background-color:white');
                      element.css({
                          'background-size': 'cover'
                      });
                  }
              });
          };
      }]);
})(window.angular, window.buildfire);
<|endoftext|>


<commit_before>process.env.NODE_ENV = 'production'

const fs = require('fs-extra')
const chalk = require('chalk')
const webpack = require('webpack')
const clearConsole = require('react-dev-utils/clearConsole')
const webpackConfig = require('../webpack/webpack.config.build.js')

const buildPath = webpackConfig.output.path

clearConsole()
console.log('')
console.log(chalk.cyan('  Prepare build ...'))
console.log('')
console.log(chalk.cyan('  Empty directory: ') + chalk.cyan.inverse(buildPath))
fs.removeSync(buildPath)
fs.mkdirsSync(buildPath)

console.log('')
console.log(chalk.cyan('  Begin build ...'))
console.log('')

webpack(webpackConfig, function (err, stats) {
  if (err) throw err
  process.stdout.write(stats.toString({
    colors: true,
    modules: false,
    children: false,
    chunks: false,
    chunkModules: false
  }) + '\n')

  console.log('')
  console.log(chalk.cyan('  Build finished.'))
  console.log('')
})
<commit_msg>perf: 使用 fs-extra.emptyDirSync 清空目录<commit_after>process.env.NODE_ENV = 'production'

const fs = require('fs-extra')
const chalk = require('chalk')
const webpack = require('webpack')
const clearConsole = require('react-dev-utils/clearConsole')
const webpackConfig = require('../webpack/webpack.config.build.js')

const buildPath = webpackConfig.output.path

clearConsole()
console.log('')
console.log(chalk.cyan('  Prepare build ...'))
console.log('')
console.log(chalk.cyan('  Empty directory: ') + chalk.cyan.inverse(buildPath))
fs.emptyDirSync(buildPath)

console.log('')
console.log(chalk.cyan('  Begin build ...'))
console.log('')

webpack(webpackConfig, function (err, stats) {
  if (err) throw err
  process.stdout.write(stats.toString({
    colors: true,
    modules: false,
    children: false,
    chunks: false,
    chunkModules: false
  }) + '\n')

  console.log('')
  console.log(chalk.cyan('  Build finished.'))
  console.log('')
})
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var async = require('async');
var _ = require('underscore');

var helpers = require('./helpers.js');
var parse = require('./parse.js');

var propagate = function(callback, func) {
  return function(err) {
    if (err) {
      callback(err);
      return;
    }
    return func.apply(this, Array.prototype.slice.call(arguments, 1));
  };
};
var reduceArray = function(seeds, reducers, transform) {
  return seeds.map(function(seed) {
    return reducers.reduce(transform, seed);
  });
};
var fileSaver = function(files, defaultEncoding, callback) {
  async.forEach(files || [], function(file, callback) {
    fs.writeFile(file.name, file.content, file.encoding || defaultEncoding, callback);
  }, callback);
};
var resolveFileDir = function(filename) {
  return path.resolve(process.cwd(), path.dirname(filename));
};

var defaultExpand = function(f, as, index, callback) {
  callback(null, f);
};
var defaultFetcher = function(file, opraBlock, fetchFileData, callback) {
  var gfiles = file.globs.map(function(x) {
    return _.extend({}, x, {
      params: file.params,
      spaces: file.spaces
    });
  });

  async.mapSeries(gfiles, function(gfile, callback) {
    fetchFileData(gfile, opraBlock, callback);
  }, callback);
};
var defaultSomething = function(data, opraBlock, concatable, callback) {
  callback(null, { tags: data });
};
var defaultTagCreator = function(file, content, callback) {
  if (_.isUndefined(content)) {
    callback();
  } else {
    callback(null, {
      name: 'script',
      attributes: { type: 'text/x-opra' },
      content: content
    });
  }
};
var defaultCompiler = function() {
  return {
    from: undefined,
    to: undefined,
    compile: function(filename, encoding, assetRoot, callback) {
      fs.readFile(filename, encoding, callback);
    }
  };
};

exports.buildConstructor = function(dependencies) {
  var hooks = { };

  // Vet inte riktigt var den här hör hemma...
  hooks.tag = [];
  hooks.tag.push(function(file, tag) {
    var spaces = file.spaces.slice(2);

    if (tag.content && (!_.contains(file.params, 'compress') || file.type == 'other')) {
      tag.content = tag.content.trim().split('\n').map(function(s) {
        return file.spaces + s;
      }).join('\n');
      tag.content = "\n" + tag.content + "\n" + spaces;
    }

    // if (tag.content && _.contains(file.params, 'compress') && (file.type == 'js' || file.type == 'css')) {
    //   tag.content = tag.content.trim();
    // }

    return tag;
  });

  var addTypes = function(res) {
    var filetype = function(filename) {
      var fts = hooks.compiler.reduce(function(memo, compiler) {
        memo[compiler.from] = compiler.target;
        return memo;
      }, {});
      return Object.keys(fts).reduce(function(memo, from) {
        return _.endsWith(filename, '.' + from) ? fts[from] : memo;
      }, 'other');
    };

    return res.map(function(match) {
      return _.extend({}, match, {
        type: filetype(match.filename),
        files: match.files.map(function(file) {
          return _.extend({}, file, {
            type: filetype(file.name),
            globs: file.globs.map(function(x) {
              return _.extend({}, x, {
                type: filetype(x.name)
              });
            })
          });
        })
      });
    });
  };
  var tagify = function(tags, callback) {
    var tagCreators = (hooks.tagCreator || []).concat([defaultTagCreator]);
    async.map(tags, function(intag, callback) {
      helpers.firstNonNullSeries(tagCreators, function(hook, callback) {
        hook(intag.file, intag.content, callback);
      }, propagate(callback, function(tag) {
        if (_.isUndefined(tag)) {
          callback(null, "");
          return;
        }

        tag = hooks.tag.reduce(function(acc, hook) {
          return hook(intag.file, acc);
        }, tag);

        tag = helpers.createTag(tag);

        tag = hooks.postTag.reduce(function(acc, hook) {
          return hook(intag.file, acc);
        }, tag);

        tag = tag ? intag.file.spaces.slice(2) + tag : '';

        callback(null, tag);
      }));

    }, propagate(callback, function(res) {
      callback(null, res.filter(function(x) { return x; }).join('\n'));
    }));
  };

  return {
    extend: function(f) {
      var h = {};
      f(h);

      Object.keys(h).forEach(function(key) {
        hooks[key] = hooks[key] || [];
        if (_.isArray(h[key])) {
          hooks[key] = hooks[key].concat(h[key]);
        } else {
          hooks[key].push(h[key]);
        }
      });
    },
    build: function(indexFile, settings, callback) {

      if (!callback && typeof settings == 'function') {
        callback = settings;
        settings = {};
      }
      settings = settings || {};

      var indexFileDir = resolveFileDir(indexFile);
      var encoding = settings.encoding || 'utf8';
      var assetRoot = path.resolve(settings.assetRoot || indexFileDir);

      var globalFlags = {
        concat: settings.concat,
        inline: settings.inline,
        compress: settings.compress,
        paths: settings.paths,
        escape: settings.escape,
        ids: settings.ids
      };

      var expandFilters = hooks.expand.concat([defaultExpand]);
      var extendedFetchers = hooks.fileFetcher.concat([defaultFetcher]);
      var extendedDataHooks = hooks.data.concat([defaultSomething]);
      var extendedCompilers = hooks.compiler.concat([defaultCompiler()]);

      var getData = function(file, opraBlock, callback) {

        var anyTrue = hooks.preventContent.some(function(hook) {
          return hook(file, opraBlock);
        });

        if (!anyTrue) {
          callback(null, { file: file, content: undefined });
          return;
        }

        helpers.firstNonNullSeries(extendedCompilers, function(compiler, callback) {
          if (_.isUndefined(compiler.from) || _.endsWith(file.name, '.' + compiler.from)) {
            compiler.compile(file.absolutePath, file.encoding, assetRoot, callback);
          } else {
            callback();
          }
        }, propagate(callback, function(data) {
          callback(null, { file: file, content: data });
        }));
      };

      parse.parseFile(assetRoot, globalFlags, indexFile, indexFileDir, encoding, propagate(callback, function(parseResult) {
        async.reduce(addTypes(parseResult.matches), { cont: parseResult.content, files: [] }, function(cc, d, callback) {
          async.map(d.files, function(file, callback) {
            async.map(expandFilters, function(hook, callback) {
              hook(file, assetRoot, indexFile, callback);
            }, propagate(callback, function(suggestions) {
              callback(null, _.compact(suggestions).first());
            }));
          }, propagate(callback, function(expandedFiles) {
            async.reduce(hooks.preproc, _.flatten(expandedFiles), function(acca, hook, callback) {
              hook(acca, { assetRoot: assetRoot, indexFile: indexFile }, callback);
            }, propagate(callback, function(outs) {
              async.mapSeries(outs, function(file, callback) {
                helpers.firstNonNullSeries(extendedFetchers, function(hook, callback) {
                  hook(file, d, getData, callback);
                }, callback);
              }, propagate(callback, function(data) {
                var d2 = reduceArray(_.flatten(data), hooks.file, function(acc, hook) {
                  return hook(acc);
                });
                helpers.firstNonNullSeries(extendedDataHooks, function(hook, callback) {
                  hook(d2, d, hooks.concatable, callback);
                }, propagate(callback, function(out) {
                  tagify(out.tags, propagate(callback, function(data) {
                    callback(null, {
                      cont: helpers.safeReplace(cc.cont, d.match, data),
                      files: cc.files.concat(out.outfiles || [])
                    });
                  }));
                }));
              }));
            }));
          }));
        }, propagate(callback, function(r) {
          fileSaver(r.files, encoding, propagate(callback, function() {
            callback(null, r.cont);
          }));
        }));
      }));
    }
  };
};
<commit_msg>Name refactor<commit_after>var fs = require('fs');
var path = require('path');
var async = require('async');
var _ = require('underscore');

var helpers = require('./helpers.js');
var parse = require('./parse.js');

var propagate = function(callback, func) {
  return function(err) {
    if (err) {
      callback(err);
      return;
    }
    return func.apply(this, Array.prototype.slice.call(arguments, 1));
  };
};
var reduceArray = function(seeds, reducers, transform) {
  return seeds.map(function(seed) {
    return reducers.reduce(transform, seed);
  });
};
var fileSaver = function(files, defaultEncoding, callback) {
  async.forEach(files || [], function(file, callback) {
    fs.writeFile(file.name, file.content, file.encoding || defaultEncoding, callback);
  }, callback);
};
var resolveFileDir = function(filename) {
  return path.resolve(process.cwd(), path.dirname(filename));
};

var defaultExpand = function(f, as, index, callback) {
  callback(null, f);
};
var defaultFetcher = function(file, opraBlock, fetchFileData, callback) {
  var gfiles = file.globs.map(function(x) {
    return _.extend({}, x, {
      params: file.params,
      spaces: file.spaces
    });
  });

  async.mapSeries(gfiles, function(gfile, callback) {
    fetchFileData(gfile, opraBlock, callback);
  }, callback);
};
var defaultSomething = function(data, opraBlock, concatable, callback) {
  callback(null, { tags: data });
};
var defaultTagCreator = function(file, content, callback) {
  if (_.isUndefined(content)) {
    callback();
  } else {
    callback(null, {
      name: 'script',
      attributes: { type: 'text/x-opra' },
      content: content
    });
  }
};
var defaultCompiler = function() {
  return {
    from: undefined,
    to: undefined,
    compile: function(filename, encoding, assetRoot, callback) {
      fs.readFile(filename, encoding, callback);
    }
  };
};

exports.buildConstructor = function(dependencies) {
  var hooks = { };

  // Vet inte riktigt var den här hör hemma...
  hooks.tag = [];
  hooks.tag.push(function(file, tag) {
    var spaces = file.spaces.slice(2);

    if (tag.content && (!_.contains(file.params, 'compress') || file.type == 'other')) {
      tag.content = tag.content.trim().split('\n').map(function(s) {
        return file.spaces + s;
      }).join('\n');
      tag.content = "\n" + tag.content + "\n" + spaces;
    }

    // if (tag.content && _.contains(file.params, 'compress') && (file.type == 'js' || file.type == 'css')) {
    //   tag.content = tag.content.trim();
    // }

    return tag;
  });

  var addTypes = function(res) {
    var filetype = function(filename) {
      var fts = hooks.compiler.reduce(function(memo, compiler) {
        memo[compiler.from] = compiler.target;
        return memo;
      }, {});
      return Object.keys(fts).reduce(function(memo, from) {
        return _.endsWith(filename, '.' + from) ? fts[from] : memo;
      }, 'other');
    };

    return res.map(function(match) {
      return _.extend({}, match, {
        type: filetype(match.filename),
        files: match.files.map(function(file) {
          return _.extend({}, file, {
            type: filetype(file.name),
            globs: file.globs.map(function(x) {
              return _.extend({}, x, {
                type: filetype(x.name)
              });
            })
          });
        })
      });
    });
  };
  var tagify = function(tags, callback) {
    var tagCreators = (hooks.tagCreator || []).concat([defaultTagCreator]);
    async.map(tags, function(intag, callback) {
      helpers.firstNonNullSeries(tagCreators, function(hook, callback) {
        hook(intag.file, intag.content, callback);
      }, propagate(callback, function(tag) {
        if (_.isUndefined(tag)) {
          callback(null, "");
          return;
        }

        tag = hooks.tag.reduce(function(acc, hook) {
          return hook(intag.file, acc);
        }, tag);

        tag = helpers.createTag(tag);

        tag = hooks.postTag.reduce(function(acc, hook) {
          return hook(intag.file, acc);
        }, tag);

        tag = tag ? intag.file.spaces.slice(2) + tag : '';

        callback(null, tag);
      }));

    }, propagate(callback, function(res) {
      callback(null, res.filter(function(x) { return x; }).join('\n'));
    }));
  };

  return {
    extend: function(f) {
      var h = {};
      f(h);

      Object.keys(h).forEach(function(key) {
        hooks[key] = hooks[key] || [];
        if (_.isArray(h[key])) {
          hooks[key] = hooks[key].concat(h[key]);
        } else {
          hooks[key].push(h[key]);
        }
      });
    },
    build: function(indexFile, settings, callback) {

      if (!callback && typeof settings == 'function') {
        callback = settings;
        settings = {};
      }
      settings = settings || {};

      var indexFileDir = resolveFileDir(indexFile);
      var encoding = settings.encoding || 'utf8';
      var assetRoot = path.resolve(settings.assetRoot || indexFileDir);

      var globalFlags = {
        concat: settings.concat,
        inline: settings.inline,
        compress: settings.compress,
        paths: settings.paths,
        escape: settings.escape,
        ids: settings.ids
      };

      var expandFilters = hooks.expand.concat([defaultExpand]);
      var extendedFetchers = hooks.fileFetcher.concat([defaultFetcher]);
      var extendedDataHooks = hooks.data.concat([defaultSomething]);
      var extendedCompilers = hooks.compiler.concat([defaultCompiler()]);

      var getData = function(file, opraBlock, callback) {

        var anyTrue = hooks.preventContent.some(function(hook) {
          return hook(file, opraBlock);
        });

        if (!anyTrue) {
          callback(null, { file: file, content: undefined });
          return;
        }

        helpers.firstNonNullSeries(extendedCompilers, function(compiler, callback) {
          if (_.isUndefined(compiler.from) || _.endsWith(file.name, '.' + compiler.from)) {
            compiler.compile(file.absolutePath, file.encoding, assetRoot, callback);
          } else {
            callback();
          }
        }, propagate(callback, function(data) {
          callback(null, { file: file, content: data });
        }));
      };

      parse.parseFile(assetRoot, globalFlags, indexFile, indexFileDir, encoding, propagate(callback, function(parseResult) {
        async.reduce(addTypes(parseResult.matches), { cont: parseResult.content, files: [] }, function(cc, d, callback) {
          async.map(d.files, function(file, callback) {
            async.map(expandFilters, function(hook, callback) {
              hook(file, assetRoot, indexFile, callback);
            }, propagate(callback, function(suggestions) {
              callback(null, _.compact(suggestions).first());
            }));
          }, propagate(callback, function(expandedFiles) {
            async.reduce(hooks.preproc, _.flatten(expandedFiles), function(acc, hook, callback) {
              hook(acc, { assetRoot: assetRoot, indexFile: indexFile }, callback);
            }, propagate(callback, function(outs) {
              async.mapSeries(outs, function(file, callback) {
                helpers.firstNonNullSeries(extendedFetchers, function(hook, callback) {
                  hook(file, d, getData, callback);
                }, callback);
              }, propagate(callback, function(data) {
                var d2 = reduceArray(_.flatten(data), hooks.file, function(acc, hook) {
                  return hook(acc);
                });
                helpers.firstNonNullSeries(extendedDataHooks, function(hook, callback) {
                  hook(d2, d, hooks.concatable, callback);
                }, propagate(callback, function(out) {
                  tagify(out.tags, propagate(callback, function(data) {
                    callback(null, {
                      cont: helpers.safeReplace(cc.cont, d.match, data),
                      files: cc.files.concat(out.outfiles || [])
                    });
                  }));
                }));
              }));
            }));
          }));
        }, propagate(callback, function(r) {
          fileSaver(r.files, encoding, propagate(callback, function() {
            callback(null, r.cont);
          }));
        }));
      }));
    }
  };
};
<|endoftext|>


<commit_before>const base58check = require('bs58check')
const batPublisher = require('./extras-publisher')
const bitcoin = require('bitcoinjs-lib')
const countryCodes = require('country-list')()
const currencyCodes = require('currency-codes')
const Joi = require('joi')
const ethereumAddress = require('ethereum-address')

module.exports = Joi.extend((joi) => {
  return {
    base: joi.string(),
    type: 'string',
    messages: {
      'string.badAltcurrencyAddress': '{{#label}} invalid altcurrency address {{#value}}',
      'string.badAltcurrencyCode': '{{#label}} invalid alternate currency code {{#value}}',
      'string.badAnycurrencyCode': '{{#label}} invalid alternate/fiat currency code {{#value}}',
      'string.badBase58': '{{#label}} bad Base58 encoding {{#value}}',
      'string.badCountryCode': '{{#label}} invalid country code {{#value}}',
      'string.badCurrencyCode': '{{#label}} invalid currency code {{#value}}',
      'string.badEthAddress': '{{#label}} invalid Ethereum address {{#value}}',
      'string.badFormat': '{{#label}} invalid format {{#value}}'
    },
    rules: {
      altcurrencyAddress: {
        /*
          usage of this method requires being inside of an object where the altcurrency code is the key to the value
        */
        validate (value, helpers, args, options) {
          const { state } = helpers
          const parent = state.ancestors[0]
          const skipKeys = {
            CARD_ID: true,
            BAT: true
          }
          const key = Object.keys(parent).find((key) => {
            if (skipKeys[key]) return
            return parent[key] === value
          })
          if (key === 'BTC' || key === 'LTC') {
            try {
              base58check.decode(value)
            } catch (err) {
              return helpers.error('string.badBase58', { value }, state, options)
            }
          } else {
            if (!ethereumAddress.isAddress(value)) {
              return helpers.error('string.badEthAddress', { value }, state, options)
            }
          }
          return value
        }
      },
      altcurrencyCode: {
        validate (value, helpers, args, options) {
          const { state } = helpers
          const regexp = new RegExp(/^[0-9A-Z]{1,}$/)
          if (!regexp.test(value)) {
            return helpers.error('string.badAltcurrencyCode', { value }, state, options)
          }
          return value
        }
      },
      anycurrencyCode: {
        validate (value, helpers, args, options) {
          const { state } = helpers
          const entry = currencyCodes.code(value)
          const regexp = new RegExp(/^[0-9A-Z]{1,}$/)
          if (!entry && !regexp.test(value)) {
            return helpers.error('string.badAnycurrencyCode', { value }, state, options)
          }
          return value
        }
      },
      base58: {
        validate (value, helpers, args, options) {
          const { state } = helpers
          try {
            base58check.decode(value)
          } catch (err) {
            return helpers.error('string.badBase58', { value }, state, options)
          }
          return value
        }
      },
      countryCode: {
        validate (value, helpers, args, options) {
          const { state } = helpers
          const entry = countryCodes.getName(value)
          if (!entry) {
            return helpers.error('string.badCountryCode', { value }, state, options)
          }
          return value
        }
      },
      currencyCode: {
        validate (value, helpers, args, options) {
          const { state } = helpers
          const entry = currencyCodes.code(value)
          if (!entry) {
            return helpers.error('string.badCurrencyCode', { value }, state, options)
          }
          return value
        }
      },
      numeric: {
        validate (value, helpers, args, options) {
          const { state } = helpers
          const isNumeric = new RegExp(/^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i)
          if (!isNumeric.test(value)) {
            return helpers.error('string.badFormat', { value }, state, options)
          }
          return value
        }
      },
      owner: {
        validate (value, helpers, args, options) {
          const { state } = helpers
          const props = batPublisher.getPublisherProps(value)
          if (!props || !props.publisherType) {
            return helpers.error('string.badFormat', { value }, state, options)
          }
          return value
        }
      },
      publisher: {
        validate (value, helpers, args, options) {
          const { state } = helpers
          if (!batPublisher.isPublisher(value)) {
            return helpers.error('string.badFormat', { value }, state, options)
          }
          return value
        }
      },
      Xpub: {
        // courtesy of the good folks at BitGo!
        validate (value, helpers, args, options) {
          const { state } = helpers
          if (value.substr(0, 4) !== 'xpub') {
            return helpers.error('string.badFormat', { value }, state, options)
          }
          try {
            bitcoin.HDNode.fromBase58(value)
          } catch (err) {
            return helpers.error('string.badBase58', { value }, state, options)
          }
          return value
        }
      }
    }
  }
})
<commit_msg>removed currency codes check (#1020)<commit_after>const base58check = require('bs58check')
const batPublisher = require('./extras-publisher')
const bitcoin = require('bitcoinjs-lib')
const countryCodes = require('country-list')()
const Joi = require('joi')
const ethereumAddress = require('ethereum-address')

module.exports = Joi.extend((joi) => {
  return {
    base: joi.string(),
    type: 'string',
    messages: {
      'string.badAltcurrencyAddress': '{{#label}} invalid altcurrency address {{#value}}',
      'string.badAltcurrencyCode': '{{#label}} invalid alternate currency code {{#value}}',
      'string.badAnycurrencyCode': '{{#label}} invalid alternate/fiat currency code {{#value}}',
      'string.badBase58': '{{#label}} bad Base58 encoding {{#value}}',
      'string.badCountryCode': '{{#label}} invalid country code {{#value}}',
      'string.badCurrencyCode': '{{#label}} invalid currency code {{#value}}',
      'string.badEthAddress': '{{#label}} invalid Ethereum address {{#value}}',
      'string.badFormat': '{{#label}} invalid format {{#value}}'
    },
    rules: {
      altcurrencyAddress: {
        /*
          usage of this method requires being inside of an object where the altcurrency code is the key to the value
        */
        validate (value, helpers, args, options) {
          const { state } = helpers
          const parent = state.ancestors[0]
          const skipKeys = {
            CARD_ID: true,
            BAT: true
          }
          const key = Object.keys(parent).find((key) => {
            if (skipKeys[key]) return
            return parent[key] === value
          })
          if (key === 'BTC' || key === 'LTC') {
            try {
              base58check.decode(value)
            } catch (err) {
              return helpers.error('string.badBase58', { value }, state, options)
            }
          } else {
            if (!ethereumAddress.isAddress(value)) {
              return helpers.error('string.badEthAddress', { value }, state, options)
            }
          }
          return value
        }
      },
      altcurrencyCode: {
        validate (value, helpers, args, options) {
          const { state } = helpers
          const regexp = new RegExp(/^[0-9A-Z]{1,}$/)
          if (!regexp.test(value)) {
            return helpers.error('string.badAltcurrencyCode', { value }, state, options)
          }
          return value
        }
      },
      anycurrencyCode: {
        validate (value, helpers, args, options) {
          const { state } = helpers
          const regexp = new RegExp(/^[0-9A-Z]{1,}$/)
          if (!regexp.test(value)) {
            return helpers.error('string.badAnycurrencyCode', { value }, state, options)
          }
          return value
        }
      },
      base58: {
        validate (value, helpers, args, options) {
          const { state } = helpers
          try {
            base58check.decode(value)
          } catch (err) {
            return helpers.error('string.badBase58', { value }, state, options)
          }
          return value
        }
      },
      countryCode: {
        validate (value, helpers, args, options) {
          const { state } = helpers
          const entry = countryCodes.getName(value)
          if (!entry) {
            return helpers.error('string.badCountryCode', { value }, state, options)
          }
          return value
        }
      },
      currencyCode: {
        validate (value, helpers, args, options) {
          const { state } = helpers
          const regexp = new RegExp(/^[0-9A-Z]{1,}$/)
          if (!regexp.test(value)) {
            return helpers.error('string.badCurrencyCode', { value }, state, options)
          }
          return value
        }
      },
      numeric: {
        validate (value, helpers, args, options) {
          const { state } = helpers
          const isNumeric = new RegExp(/^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i)
          if (!isNumeric.test(value)) {
            return helpers.error('string.badFormat', { value }, state, options)
          }
          return value
        }
      },
      owner: {
        validate (value, helpers, args, options) {
          const { state } = helpers
          const props = batPublisher.getPublisherProps(value)
          if (!props || !props.publisherType) {
            return helpers.error('string.badFormat', { value }, state, options)
          }
          return value
        }
      },
      publisher: {
        validate (value, helpers, args, options) {
          const { state } = helpers
          if (!batPublisher.isPublisher(value)) {
            return helpers.error('string.badFormat', { value }, state, options)
          }
          return value
        }
      },
      Xpub: {
        // courtesy of the good folks at BitGo!
        validate (value, helpers, args, options) {
          const { state } = helpers
          if (value.substr(0, 4) !== 'xpub') {
            return helpers.error('string.badFormat', { value }, state, options)
          }
          try {
            bitcoin.HDNode.fromBase58(value)
          } catch (err) {
            return helpers.error('string.badBase58', { value }, state, options)
          }
          return value
        }
      }
    }
  }
})
<|endoftext|>


<commit_before>const {expect} = chai
import Ember from 'ember'
const {run} = Ember
import {describeComponent} from 'ember-mocha'
import {afterEach, beforeEach, describe, it} from 'mocha'
import {PropTypes} from 'ember-prop-types'
import {validatePropTypes} from '../../utils/template'

describeComponent(
  'frost-bunsen-form',
  'FrostBunsenFormComponent',
  {},
  function () {
    validatePropTypes({
      cancelLabel: PropTypes.string,
      inline: PropTypes.bool,
      model: PropTypes.oneOf([
        PropTypes.EmberObject,
        PropTypes.object
      ]).isRequired,
      onCancel: PropTypes.func,
      onChange: PropTypes.func,
      onSubmit: PropTypes.func,
      onValidation: PropTypes.func,
      renderers: PropTypes.oneOf([
        PropTypes.EmberObject,
        PropTypes.object
      ]),
      submitLabel: PropTypes.string,
      validators: PropTypes.array,
      value: PropTypes.oneOf([
        PropTypes.EmberObject,
        PropTypes.null,
        PropTypes.object
      ]),
      view: PropTypes.oneOf([
        PropTypes.EmberObject,
        PropTypes.object
      ])
    })

    let component, onChangeSpy, onValidationSpy, sandbox

    beforeEach(function () {
      sandbox = sinon.sandbox.create()
      component = this.subject()
      onChangeSpy = sandbox.spy()
      onValidationSpy = sandbox.spy()

      run(() => {
        component.setProperties({
          model: {
            properties: {
              bar: {type: 'string'},
              foo: {type: 'string'}
            },
            required: ['foo'],
            type: 'object'
          },
          onChange: onChangeSpy,
          onValidation: onValidationSpy
        })
      })
    })

    afterEach(function () {
      sandbox.restore()
    })

    describe('update bar', function () {
      let updatedValue, validationResult

      beforeEach(function () {
        run(() => {
          component.actions.onChange.call(component, 'bar', 'test')
        })

        updatedValue = onChangeSpy.lastCall.args[0]
        validationResult = onValidationSpy.lastCall.args[0]
      })

      it('store gets expected formValue', function () {
        const store = component.get('store')
        expect(store.formValue).to.eql({
          bar: 'test'
        })
      })

      it('onChange gets expected value', function () {
        expect(updatedValue).to.eql({
          bar: 'test'
        })
      })

      it('onValidation gets expected validation errors', function () {
        expect(validationResult.errors).to.eql([])
      })

      it('onValidation gets expected validation warnings', function () {
        expect(validationResult.warnings).to.eql([])
      })
    })

    describe('update foo', function () {
      let updatedValue, validationResult

      beforeEach(function () {
        run(() => {
          component.actions.onChange.call(component, 'foo', 'test')
        })

        updatedValue = onChangeSpy.lastCall.args[0]
        validationResult = onValidationSpy.lastCall.args[0]
      })

      it('store gets expected formValue', function () {
        const store = component.get('store')
        expect(store.formValue).to.eql({
          foo: 'test'
        })
      })

      it('onChange gets expected value', function () {
        expect(updatedValue).to.eql({
          foo: 'test'
        })
      })

      it('onValidation gets expected validation errors', function () {
        expect(validationResult.errors).to.eql([])
      })

      it('onValidation gets expected validation warnings', function () {
        expect(validationResult.warnings).to.eql([])
      })
    })

    describe('store', function () {
      let store

      beforeEach(function () {
        store = component.get('store')
      })

      it('has expected formValue', function () {
        expect(store.formValue).to.eql({})
      })

      it('has expected renderers', function () {
        expect(store.renderers).to.eql({
          'multi-select': 'frost-bunsen-input-multi-select',
          'property-chooser': 'frost-bunsen-property-chooser',
          select: 'frost-bunsen-input-select'
        })
      })
    })
  }
)
<commit_msg>fix test<commit_after>const {expect} = chai
import Ember from 'ember'
const {run} = Ember
import {describeComponent} from 'ember-mocha'
import {afterEach, beforeEach, describe, it} from 'mocha'
import {PropTypes} from 'ember-prop-types'
import {validatePropTypes} from '../../utils/template'

describeComponent(
  'frost-bunsen-form',
  'FrostBunsenFormComponent',
  {},
  function () {
    validatePropTypes({
      cancelLabel: PropTypes.string,
      inline: PropTypes.bool,
      model: PropTypes.oneOf([
        PropTypes.EmberObject,
        PropTypes.object
      ]).isRequired,
      onCancel: PropTypes.func,
      onChange: PropTypes.func,
      onSubmit: PropTypes.func,
      onValidation: PropTypes.func,
      renderers: PropTypes.oneOf([
        PropTypes.EmberObject,
        PropTypes.object
      ]),
      submitLabel: PropTypes.string,
      validators: PropTypes.array,
      value: PropTypes.oneOf([
        PropTypes.EmberObject,
        PropTypes.null,
        PropTypes.object
      ]),
      view: PropTypes.oneOf([
        PropTypes.EmberObject,
        PropTypes.object
      ])
    })

    let component, onChangeSpy, onValidationSpy, sandbox

    beforeEach(function () {
      sandbox = sinon.sandbox.create()
      component = this.subject()
      onChangeSpy = sandbox.spy()
      onValidationSpy = sandbox.spy()

      run(() => {
        component.setProperties({
          model: {
            properties: {
              bar: {type: 'string'},
              foo: {type: 'string'}
            },
            required: ['foo'],
            type: 'object'
          },
          onChange: onChangeSpy,
          onValidation: onValidationSpy
        })
      })
    })

    afterEach(function () {
      sandbox.restore()
    })

    describe('update bar', function () {
      let updatedValue, validationResult

      beforeEach(function (done) {
        run(() => {
          component.actions.onChange.call(component, 'bar', 'test')
        })

        setTimeout(() => {
          updatedValue = onChangeSpy.lastCall.args[0]
          validationResult = onValidationSpy.lastCall.args[0]
          done()
        }, 500)
      })

      it('store gets expected formValue', function () {
        const store = component.get('store')
        expect(store.formValue).to.eql({
          bar: 'test'
        })
      })

      it('onChange gets expected value', function () {
        expect(updatedValue).to.eql({
          bar: 'test'
        })
      })

      it('onValidation gets expected validation errors', function () {
        expect(validationResult.errors.length).to.eql(1)

        const error = validationResult.errors[0]

        expect(error.code).to.eql('OBJECT_MISSING_REQUIRED_PROPERTY')
        expect(error.message).to.eql('Field is required.')
        expect(error.path).to.eql('#/foo')
      })

      it('onValidation gets expected validation warnings', function () {
        expect(validationResult.warnings).to.eql([])
      })
    })

    describe('update foo', function () {
      let updatedValue, validationResult

      beforeEach(function (done) {
        run(() => {
          component.actions.onChange.call(component, 'foo', 'test')
        })

        setTimeout(() => {
          updatedValue = onChangeSpy.lastCall.args[0]
          validationResult = onValidationSpy.lastCall.args[0]
          done()
        }, 500)
      })

      it('store gets expected formValue', function () {
        const store = component.get('store')
        expect(store.formValue).to.eql({
          foo: 'test'
        })
      })

      it('onChange gets expected value', function () {
        expect(updatedValue).to.eql({
          foo: 'test'
        })
      })

      it('onValidation gets expected validation errors', function () {
        expect(validationResult.errors).to.eql([])
      })

      it('onValidation gets expected validation warnings', function () {
        expect(validationResult.warnings).to.eql([])
      })
    })

    describe('store', function () {
      let store

      beforeEach(function () {
        store = component.get('store')
      })

      it('has expected formValue', function () {
        expect(store.formValue).to.eql({})
      })

      it('has expected renderers', function () {
        expect(store.renderers).to.eql({
          'multi-select': 'frost-bunsen-input-multi-select',
          'property-chooser': 'frost-bunsen-property-chooser',
          select: 'frost-bunsen-input-select'
        })
      })
    })
  }
)
<|endoftext|>