<commit_before>import { guidFor } from '@ember/-internals/utils';
import { descriptorForProperty, Mixin, nativeDescDecorator } from '@ember/-internals/metal';
import { assert } from '@ember/debug';
import { hasDOM } from '@ember/-internals/browser-environment';
import { matches } from '../system/utils';
import { default as jQuery, jQueryDisabled } from '../system/jquery';
import { deprecate } from '@ember/debug';
import { JQUERY_INTEGRATION } from '@ember/deprecated-features';

function K() {
  return this;
}

let mixin = {
  /**
   A list of properties of the view to apply as attributes. If the property
   is a string value, the value of that string will be applied as the value
   for an attribute of the property's name.

   The following example creates a tag like `<div priority="high" />`.

   ```app/components/my-component.js
   import Component from '@ember/component';

   export default Component.extend({
      attributeBindings: ['priority'],
      priority: 'high'
    });
   ```

   If the value of the property is a Boolean, the attribute is treated as
   an HTML Boolean attribute. It will be present if the property is `true`
   and omitted if the property is `false`.

   The following example creates markup like `<div visible />`.

   ```app/components/my-component.js
   import Component from '@ember/component';

   export default Component.extend({
      attributeBindings: ['visible'],
      visible: true
    });
   ```

   If you would prefer to use a custom value instead of the property name,
   you can create the same markup as the last example with a binding like
   this:

   ```app/components/my-component.js
   import Component from '@ember/component';

   export default Component.extend({
      attributeBindings: ['isVisible:visible'],
      isVisible: true
    });
   ```

   This list of attributes is inherited from the component's superclasses,
   as well.

   @property attributeBindings
   @type Array
   @default []
   @public
   */
  concatenatedProperties: ['attributeBindings'],

  // ..........................................................
  // TEMPLATE SUPPORT
  //

  /**
   Return the nearest ancestor that is an instance of the provided
   class or mixin.

   @method nearestOfType
   @param {Class,Mixin} klass Subclass of Ember.View (or Ember.View itself),
   or an instance of Mixin.
   @return Ember.View
   @deprecated use `yield` and contextual components for composition instead.
   @private
   */
  nearestOfType(klass) {
    let view = this.parentView;
    let isOfType =
      klass instanceof Mixin ? view => klass.detect(view) : view => klass.detect(view.constructor);

    while (view) {
      if (isOfType(view)) {
        return view;
      }
      view = view.parentView;
    }
  },

  /**
   Return the nearest ancestor that has a given property.

   @method nearestWithProperty
   @param {String} property A property name
   @return Ember.View
   @deprecated use `yield` and contextual components for composition instead.
   @private
   */
  nearestWithProperty(property) {
    let view = this.parentView;

    while (view) {
      if (property in view) {
        return view;
      }
      view = view.parentView;
    }
  },

  /**
   Renders the view again. This will work regardless of whether the
   view is already in the DOM or not. If the view is in the DOM, the
   rendering process will be deferred to give bindings a chance
   to synchronize.

   If children were added during the rendering process using `appendChild`,
   `rerender` will remove them, because they will be added again
   if needed by the next `render`.

   In general, if the display of your view changes, you should modify
   the DOM element directly instead of manually calling `rerender`, which can
   be slow.

   @method rerender
   @public
   */
  rerender() {
    return this._currentState.rerender(this);
  },

  // ..........................................................
  // ELEMENT SUPPORT
  //

  /**
   Returns the current DOM element for the view.

    @property element
    @type DOMElement
    @public
  */
  element: nativeDescDecorator({
    configurable: false,
    enumerable: false,
    get() {
      return this.renderer.getElement(this);
    },
  }),

  /**
   Appends the view's element to the specified parent element.

   Note that this method just schedules the view to be appended; the DOM
   element will not be appended to the given element until all bindings have
   finished synchronizing.

   This is not typically a function that you will need to call directly when
   building your application. If you do need to use `appendTo`, be sure that
   the target element you are providing is associated with an `Application`
   and does not have an ancestor element that is associated with an Ember view.

   @method appendTo
   @param {String|DOMElement|jQuery} A selector, element, HTML string, or jQuery object
   @return {Ember.View} receiver
   @private
   */
  appendTo(selector) {
    let target;

    if (hasDOM) {
      target = typeof selector === 'string' ? document.querySelector(selector) : selector;

      assert(`You tried to append to (${selector}) but that isn't in the DOM`, target);
      assert('You cannot append to an existing Ember.View.', !matches(target, '.ember-view'));
      assert(
        'You cannot append to an existing Ember.View.',
        (() => {
          let node = target.parentNode;
          while (node) {
            if (node.nodeType !== 9 && matches(node, '.ember-view')) {
              return false;
            }

            node = node.parentNode;
          }

          return true;
        })()
      );
    } else {
      target = selector;

      assert(
        `You tried to append to a selector string (${selector}) in an environment without jQuery`,
        typeof target !== 'string'
      );
      assert(
        `You tried to append to a non-Element (${selector}) in an environment without jQuery`,
        typeof selector.appendChild === 'function'
      );
    }

    this.renderer.appendTo(this, target);

    return this;
  },

  /**
   Appends the view's element to the document body. If the view does
   not have an HTML representation yet
   the element will be generated automatically.

   If your application uses the `rootElement` property, you must append
   the view within that element. Rendering views outside of the `rootElement`
   is not supported.

   Note that this method just schedules the view to be appended; the DOM
   element will not be appended to the document body until all bindings have
   finished synchronizing.

   @method append
   @return {Ember.View} receiver
   @private
   */
  append() {
    return this.appendTo(document.body);
  },

  /**
   The HTML `id` of the view's element in the DOM. You can provide this
   value yourself but it must be unique (just as in HTML):

   ```handlebars
   {{my-component elementId="a-really-cool-id"}}
   ```

   If not manually set a default value will be provided by the framework.

   Once rendered an element's `elementId` is considered immutable and you
   should never change it. If you need to compute a dynamic value for the
   `elementId`, you should do this when the component or element is being
   instantiated:

   ```app/components/my-component.js
   import Component from '@ember/component';

   export default Component.extend({
      init() {
        this._super(...arguments);
        let index = this.get('index');
        this.set('elementId', 'component-id' + index);
      }
    });
   ```

   @property elementId
   @type String
   @public
   */
  elementId: null,

  /**
   Attempts to discover the element in the parent element. The default
   implementation looks for an element with an ID of `elementId` (or the
   view's guid if `elementId` is null). You can override this method to
   provide your own form of lookup. For example, if you want to discover your
   element using a CSS class name instead of an ID.

   @method findElementInParentElement
   @param {DOMElement} parentElement The parent's DOM element
   @return {DOMElement} The discovered element
   @private
   */
  findElementInParentElement(parentElem) {
    let id = `#${this.elementId}`;
    return jQuery(id)[0] || jQuery(id, parentElem)[0];
  },

  /**
   Called when a view is going to insert an element into the DOM.

   @event willInsertElement
   @public
   */
  willInsertElement: K,

  /**
   Called when the element of the view has been inserted into the DOM.
   Override this function to do any set up that requires an element
   in the document body.

   When a view has children, didInsertElement will be called on the
   child view(s) first and on itself afterwards.

   @event didInsertElement
   @public
   */
  didInsertElement: K,

  /**
   Called when the view is about to rerender, but before anything has
   been torn down. This is a good opportunity to tear down any manual
   observers you have installed based on the DOM state

   @event willClearRender
   @public
   */
  willClearRender: K,

  /**
   You must call `destroy` on a view to destroy the view (and all of its
   child views). This will remove the view from any parent node, then make
   sure that the DOM element managed by the view can be released by the
   memory manager.

   @method destroy
   @private
   */
  destroy() {
    this._super(...arguments);
    this._currentState.destroy(this);
  },

  /**
   Called when the element of the view is going to be destroyed. Override
   this function to do any teardown that requires an element, like removing
   event listeners.

   Please note: any property changes made during this event will have no
   effect on object observers.

   @event willDestroyElement
   @public
   */
  willDestroyElement: K,

  /**
   Called after the element of the view is destroyed.

   @event willDestroyElement
   @public
   */
  didDestroyElement: K,

  /**
   Called when the parentView property has changed.

   @event parentViewDidChange
   @private
   */
  parentViewDidChange: K,

  // ..........................................................
  // STANDARD RENDER PROPERTIES
  //

  /**
   Tag name for the view's outer element. The tag name is only used when an
   element is first created. If you change the `tagName` for an element, you
   must destroy and recreate the view element.

   By default, the render buffer will use a `<div>` tag for views.

   @property tagName
   @type String
   @default null
   @public
   */

  // We leave this null by default so we can tell the difference between
  // the default case and a user-specified tag.
  tagName: null,

  // .......................................................
  // CORE DISPLAY METHODS
  //

  /**
   Setup a view, but do not finish waking it up.

   * configure `childViews`
   * register the view with the global views hash, which is used for event
   dispatch

   @method init
   @private
   */
  init() {
    this._super(...arguments);

    // tslint:disable-next-line:max-line-length
    assert(
      `You cannot use a computed property for the component's \`elementId\` (${this}).`,
      descriptorForProperty(this, 'elementId') === undefined
    );

    // tslint:disable-next-line:max-line-length
    assert(
      `You cannot use a computed property for the component's \`tagName\` (${this}).`,
      descriptorForProperty(this, 'tagName') === undefined
    );

    if (!this.elementId && this.tagName !== '') {
      this.elementId = guidFor(this);
    }

    assert('Using a custom `.render` function is no longer supported.', !this.render);
  },

  // .......................................................
  // EVENT HANDLING
  //

  /**
   Handle events from `EventDispatcher`

   @method handleEvent
   @param eventName {String}
   @param evt {Event}
   @private
   */
  handleEvent(eventName, evt) {
    return this._currentState.handleEvent(this, eventName, evt);
  },
};

if (JQUERY_INTEGRATION) {
  /**
   Returns a jQuery object for this view's element. If you pass in a selector
   string, this method will return a jQuery object, using the current element
   as its buffer.

   For example, calling `view.$('li')` will return a jQuery object containing
   all of the `li` elements inside the DOM element of this view.

   @method $
   @param {String} [selector] a jQuery-compatible selector string
   @return {jQuery} the jQuery object for the DOM node
   @public
   @deprecated
   */
  mixin.$ = function $(sel) {
    assert(
      "You cannot access this.$() on a component with `tagName: ''` specified.",
      this.tagName !== ''
    );
    assert('You cannot access this.$() with `jQuery` disabled.', !jQueryDisabled);
    deprecate(
      'Using this.$() in a component has been deprecated, consider using this.element',
      false,
      {
        id: 'ember-views.curly-components.jquery-element',
        until: '4.0.0',
        url: 'https://emberjs.com/deprecations/v3.x#toc_jquery-apis',
      }
    );
    if (this.element) {
      return sel ? jQuery(sel, this.element) : jQuery(this.element);
    }
  };
}

/**
 @class ViewMixin
 @namespace Ember
 @private
*/
export default Mixin.create(mixin);
<commit_msg>[DOC release] Documented tagless component behavior<commit_after>import { guidFor } from '@ember/-internals/utils';
import { descriptorForProperty, Mixin, nativeDescDecorator } from '@ember/-internals/metal';
import { assert } from '@ember/debug';
import { hasDOM } from '@ember/-internals/browser-environment';
import { matches } from '../system/utils';
import { default as jQuery, jQueryDisabled } from '../system/jquery';
import { deprecate } from '@ember/debug';
import { JQUERY_INTEGRATION } from '@ember/deprecated-features';

function K() {
  return this;
}

let mixin = {
  /**
   A list of properties of the view to apply as attributes. If the property
   is a string value, the value of that string will be applied as the value
   for an attribute of the property's name.

   The following example creates a tag like `<div priority="high" />`.

   ```app/components/my-component.js
   import Component from '@ember/component';

   export default Component.extend({
      attributeBindings: ['priority'],
      priority: 'high'
    });
   ```

   If the value of the property is a Boolean, the attribute is treated as
   an HTML Boolean attribute. It will be present if the property is `true`
   and omitted if the property is `false`.

   The following example creates markup like `<div visible />`.

   ```app/components/my-component.js
   import Component from '@ember/component';

   export default Component.extend({
      attributeBindings: ['visible'],
      visible: true
    });
   ```

   If you would prefer to use a custom value instead of the property name,
   you can create the same markup as the last example with a binding like
   this:

   ```app/components/my-component.js
   import Component from '@ember/component';

   export default Component.extend({
      attributeBindings: ['isVisible:visible'],
      isVisible: true
    });
   ```

   This list of attributes is inherited from the component's superclasses,
   as well.

   @property attributeBindings
   @type Array
   @default []
   @public
   */
  concatenatedProperties: ['attributeBindings'],

  // ..........................................................
  // TEMPLATE SUPPORT
  //

  /**
   Return the nearest ancestor that is an instance of the provided
   class or mixin.

   @method nearestOfType
   @param {Class,Mixin} klass Subclass of Ember.View (or Ember.View itself),
   or an instance of Mixin.
   @return Ember.View
   @deprecated use `yield` and contextual components for composition instead.
   @private
   */
  nearestOfType(klass) {
    let view = this.parentView;
    let isOfType =
      klass instanceof Mixin ? view => klass.detect(view) : view => klass.detect(view.constructor);

    while (view) {
      if (isOfType(view)) {
        return view;
      }
      view = view.parentView;
    }
  },

  /**
   Return the nearest ancestor that has a given property.

   @method nearestWithProperty
   @param {String} property A property name
   @return Ember.View
   @deprecated use `yield` and contextual components for composition instead.
   @private
   */
  nearestWithProperty(property) {
    let view = this.parentView;

    while (view) {
      if (property in view) {
        return view;
      }
      view = view.parentView;
    }
  },

  /**
   Renders the view again. This will work regardless of whether the
   view is already in the DOM or not. If the view is in the DOM, the
   rendering process will be deferred to give bindings a chance
   to synchronize.

   If children were added during the rendering process using `appendChild`,
   `rerender` will remove them, because they will be added again
   if needed by the next `render`.

   In general, if the display of your view changes, you should modify
   the DOM element directly instead of manually calling `rerender`, which can
   be slow.

   @method rerender
   @public
   */
  rerender() {
    return this._currentState.rerender(this);
  },

  // ..........................................................
  // ELEMENT SUPPORT
  //

  /**
   Returns the current DOM element for the view.

    @property element
    @type DOMElement
    @public
  */
  element: nativeDescDecorator({
    configurable: false,
    enumerable: false,
    get() {
      return this.renderer.getElement(this);
    },
  }),

  /**
   Appends the view's element to the specified parent element.

   Note that this method just schedules the view to be appended; the DOM
   element will not be appended to the given element until all bindings have
   finished synchronizing.

   This is not typically a function that you will need to call directly when
   building your application. If you do need to use `appendTo`, be sure that
   the target element you are providing is associated with an `Application`
   and does not have an ancestor element that is associated with an Ember view.

   @method appendTo
   @param {String|DOMElement|jQuery} A selector, element, HTML string, or jQuery object
   @return {Ember.View} receiver
   @private
   */
  appendTo(selector) {
    let target;

    if (hasDOM) {
      target = typeof selector === 'string' ? document.querySelector(selector) : selector;

      assert(`You tried to append to (${selector}) but that isn't in the DOM`, target);
      assert('You cannot append to an existing Ember.View.', !matches(target, '.ember-view'));
      assert(
        'You cannot append to an existing Ember.View.',
        (() => {
          let node = target.parentNode;
          while (node) {
            if (node.nodeType !== 9 && matches(node, '.ember-view')) {
              return false;
            }

            node = node.parentNode;
          }

          return true;
        })()
      );
    } else {
      target = selector;

      assert(
        `You tried to append to a selector string (${selector}) in an environment without jQuery`,
        typeof target !== 'string'
      );
      assert(
        `You tried to append to a non-Element (${selector}) in an environment without jQuery`,
        typeof selector.appendChild === 'function'
      );
    }

    this.renderer.appendTo(this, target);

    return this;
  },

  /**
   Appends the view's element to the document body. If the view does
   not have an HTML representation yet
   the element will be generated automatically.

   If your application uses the `rootElement` property, you must append
   the view within that element. Rendering views outside of the `rootElement`
   is not supported.

   Note that this method just schedules the view to be appended; the DOM
   element will not be appended to the document body until all bindings have
   finished synchronizing.

   @method append
   @return {Ember.View} receiver
   @private
   */
  append() {
    return this.appendTo(document.body);
  },

  /**
   The HTML `id` of the view's element in the DOM. You can provide this
   value yourself but it must be unique (just as in HTML):

   ```handlebars
   {{my-component elementId="a-really-cool-id"}}
   ```

   If not manually set a default value will be provided by the framework.

   Once rendered an element's `elementId` is considered immutable and you
   should never change it. If you need to compute a dynamic value for the
   `elementId`, you should do this when the component or element is being
   instantiated:

   ```app/components/my-component.js
   import Component from '@ember/component';

   export default Component.extend({
      init() {
        this._super(...arguments);
        let index = this.get('index');
        this.set('elementId', 'component-id' + index);
      }
    });
   ```

   @property elementId
   @type String
   @public
   */
  elementId: null,

  /**
   Attempts to discover the element in the parent element. The default
   implementation looks for an element with an ID of `elementId` (or the
   view's guid if `elementId` is null). You can override this method to
   provide your own form of lookup. For example, if you want to discover your
   element using a CSS class name instead of an ID.

   @method findElementInParentElement
   @param {DOMElement} parentElement The parent's DOM element
   @return {DOMElement} The discovered element
   @private
   */
  findElementInParentElement(parentElem) {
    let id = `#${this.elementId}`;
    return jQuery(id)[0] || jQuery(id, parentElem)[0];
  },

  /**
   Called when a view is going to insert an element into the DOM.

   @event willInsertElement
   @public
   */
  willInsertElement: K,

  /**
   Called when the element of the view has been inserted into the DOM.
   Override this function to do any set up that requires an element
   in the document body.

   When a view has children, didInsertElement will be called on the
   child view(s) first and on itself afterwards.

   @event didInsertElement
   @public
   */
  didInsertElement: K,

  /**
   Called when the view is about to rerender, but before anything has
   been torn down. This is a good opportunity to tear down any manual
   observers you have installed based on the DOM state

   @event willClearRender
   @public
   */
  willClearRender: K,

  /**
   You must call `destroy` on a view to destroy the view (and all of its
   child views). This will remove the view from any parent node, then make
   sure that the DOM element managed by the view can be released by the
   memory manager.

   @method destroy
   @private
   */
  destroy() {
    this._super(...arguments);
    this._currentState.destroy(this);
  },

  /**
   Called when the element of the view is going to be destroyed. Override
   this function to do any teardown that requires an element, like removing
   event listeners.

   Please note: any property changes made during this event will have no
   effect on object observers.

   @event willDestroyElement
   @public
   */
  willDestroyElement: K,

  /**
   Called after the element of the view is destroyed.

   @event willDestroyElement
   @public
   */
  didDestroyElement: K,

  /**
   Called when the parentView property has changed.

   @event parentViewDidChange
   @private
   */
  parentViewDidChange: K,

  // ..........................................................
  // STANDARD RENDER PROPERTIES
  //

  /**
   Tag name for the view's outer element. The tag name is only used when an
   element is first created. If you change the `tagName` for an element, you
   must destroy and recreate the view element.

   By default, the render buffer will use a `<div>` tag for views.

   If the tagName is `''`, the view will be tagless, with no outer element.
   Component properties that depend on the presence of an outer element, such
   as `classNameBindings` and `attributeBindings`, do not work with tagless
   components. Tagless components cannot implement methods to handle events,
   and have no associated jQuery object to return with `$()`.

   @property tagName
   @type String
   @default null
   @public
   */

  // We leave this null by default so we can tell the difference between
  // the default case and a user-specified tag.
  tagName: null,

  // .......................................................
  // CORE DISPLAY METHODS
  //

  /**
   Setup a view, but do not finish waking it up.

   * configure `childViews`
   * register the view with the global views hash, which is used for event
   dispatch

   @method init
   @private
   */
  init() {
    this._super(...arguments);

    // tslint:disable-next-line:max-line-length
    assert(
      `You cannot use a computed property for the component's \`elementId\` (${this}).`,
      descriptorForProperty(this, 'elementId') === undefined
    );

    // tslint:disable-next-line:max-line-length
    assert(
      `You cannot use a computed property for the component's \`tagName\` (${this}).`,
      descriptorForProperty(this, 'tagName') === undefined
    );

    if (!this.elementId && this.tagName !== '') {
      this.elementId = guidFor(this);
    }

    assert('Using a custom `.render` function is no longer supported.', !this.render);
  },

  // .......................................................
  // EVENT HANDLING
  //

  /**
   Handle events from `EventDispatcher`

   @method handleEvent
   @param eventName {String}
   @param evt {Event}
   @private
   */
  handleEvent(eventName, evt) {
    return this._currentState.handleEvent(this, eventName, evt);
  },
};

if (JQUERY_INTEGRATION) {
  /**
   Returns a jQuery object for this view's element. If you pass in a selector
   string, this method will return a jQuery object, using the current element
   as its buffer.

   For example, calling `view.$('li')` will return a jQuery object containing
   all of the `li` elements inside the DOM element of this view.

   @method $
   @param {String} [selector] a jQuery-compatible selector string
   @return {jQuery} the jQuery object for the DOM node
   @public
   @deprecated
   */
  mixin.$ = function $(sel) {
    assert(
      "You cannot access this.$() on a component with `tagName: ''` specified.",
      this.tagName !== ''
    );
    assert('You cannot access this.$() with `jQuery` disabled.', !jQueryDisabled);
    deprecate(
      'Using this.$() in a component has been deprecated, consider using this.element',
      false,
      {
        id: 'ember-views.curly-components.jquery-element',
        until: '4.0.0',
        url: 'https://emberjs.com/deprecations/v3.x#toc_jquery-apis',
      }
    );
    if (this.element) {
      return sel ? jQuery(sel, this.element) : jQuery(this.element);
    }
  };
}

/**
 @class ViewMixin
 @namespace Ember
 @private
*/
export default Mixin.create(mixin);
<|endoftext|>


<commit_before>// # Ghost Server
// Handles the creation of an HTTP Server for Ghost
var Promise = require('bluebird'),
    chalk = require('chalk'),
    fs = require('fs'),
    errors = require('./errors'),
    config = require('./config'),
    i18n   = require('./i18n'),
    moment = require('moment');

/**
 * ## GhostServer
 * @constructor
 * @param {Object} rootApp - parent express instance
 */
function GhostServer(rootApp) {
    this.rootApp = rootApp;
    this.httpServer = null;
    this.connections = {};
    this.connectionId = 0;

    // Expose config module for use externally.
    this.config = config;
}

/**
 * ## Public API methods
 *
 * ### Start
 * Starts the ghost server listening on the configured port.
 * Alternatively you can pass in your own express instance and let Ghost
 * start listening for you.
 * @param  {Object} externalApp - Optional express app instance.
 * @return {Promise} Resolves once Ghost has started
 */
GhostServer.prototype.start = function (externalApp) {
    var self = this,
        rootApp = externalApp ? externalApp : self.rootApp;

    return new Promise(function (resolve) {
        var socketConfig = config.getSocket();

        if (socketConfig) {
            // Make sure the socket is gone before trying to create another
            try {
                fs.unlinkSync(socketConfig.path);
            } catch (e) {
                // We can ignore this.
            }

            self.httpServer = rootApp.listen(socketConfig.path);

            fs.chmod(socketConfig.path, socketConfig.permissions);
        } else {
            self.httpServer = rootApp.listen(
                config.get('server').port,
                config.get('server').host
            );
        }

        self.httpServer.on('error', function (error) {
            if (error.errno === 'EADDRINUSE') {
                errors.logError(
                    i18n.t('errors.httpServer.addressInUse.error'),
                    i18n.t('errors.httpServer.addressInUse.context', {port: config.get('server').port}),
                    i18n.t('errors.httpServer.addressInUse.help')
                );
            } else {
                errors.logError(
                    i18n.t('errors.httpServer.otherError.error', {errorNumber: error.errno}),
                    i18n.t('errors.httpServer.otherError.context'),
                    i18n.t('errors.httpServer.otherError.help')
                );
            }
            process.exit(-1);
        });
        self.httpServer.on('connection', self.connection.bind(self));
        self.httpServer.on('listening', function () {
            self.logStartMessages();
            resolve(self);
        });
    });
};

/**
 * ### Stop
 * Returns a promise that will be fulfilled when the server stops. If the server has not been started,
 * the promise will be fulfilled immediately
 * @returns {Promise} Resolves once Ghost has stopped
 */
GhostServer.prototype.stop = function () {
    var self = this;

    return new Promise(function (resolve) {
        if (self.httpServer === null) {
            resolve(self);
        } else {
            self.httpServer.close(function () {
                self.httpServer = null;
                self.logShutdownMessages();
                resolve(self);
            });

            self.closeConnections();
        }
    });
};

/**
 * ### Restart
 * Restarts the ghost application
 * @returns {Promise} Resolves once Ghost has restarted
 */
GhostServer.prototype.restart = function () {
    return this.stop().then(this.start.bind(this));
};

/**
 * ### Hammertime
 * To be called after `stop`
 */
GhostServer.prototype.hammertime = function () {
    console.log(chalk.green(i18n.t('notices.httpServer.cantTouchThis')));

    return Promise.resolve(this);
};

/**
 * ## Private (internal) methods
 *
 * ### Connection
 * @param {Object} socket
 */
GhostServer.prototype.connection = function (socket) {
    var self = this;

    self.connectionId += 1;
    socket._ghostId = self.connectionId;

    socket.on('close', function () {
        delete self.connections[this._ghostId];
    });

    self.connections[socket._ghostId] = socket;
};

/**
 * ### Close Connections
 * Most browsers keep a persistent connection open to the server, which prevents the close callback of
 * httpServer from returning. We need to destroy all connections manually.
 */
GhostServer.prototype.closeConnections = function () {
    var self = this;

    Object.keys(self.connections).forEach(function (socketId) {
        var socket = self.connections[socketId];

        if (socket) {
            socket.destroy();
        }
    });
};

/**
 * ### Log Start Messages
 */
GhostServer.prototype.logStartMessages = function () {
    // Startup & Shutdown messages
    if (process.env.NODE_ENV === 'production') {
        console.log(
            chalk.green(i18n.t('notices.httpServer.ghostIsRunningIn', {env: process.env.NODE_ENV})),
            i18n.t('notices.httpServer.yourBlogIsAvailableOn', {url: config.get('url')}),
            chalk.gray(i18n.t('notices.httpServer.ctrlCToShutDown'))
        );
    } else {
        console.log(
            chalk.green(i18n.t('notices.httpServer.ghostIsRunningIn', {env: process.env.NODE_ENV})),
            i18n.t('notices.httpServer.listeningOn'),
            config.getSocket() || config.get('server').host + ':' + config.get('server').port,
            i18n.t('notices.httpServer.urlConfiguredAs', {url: config.get('url')}),
            chalk.gray(i18n.t('notices.httpServer.ctrlCToShutDown'))
        );
    }

    function shutdown() {
        console.log(chalk.red(i18n.t('notices.httpServer.ghostHasShutdown')));
        if (process.env.NODE_ENV === 'production') {
            console.log(
                i18n.t('notices.httpServer.yourBlogIsNowOffline')
            );
        } else {
            console.log(
                i18n.t('notices.httpServer.ghostWasRunningFor'),
                moment.duration(process.uptime(), 'seconds').humanize()
            );
        }
        process.exit(0);
    }
    // ensure that Ghost exits correctly on Ctrl+C and SIGTERM
    process.
        removeAllListeners('SIGINT').on('SIGINT', shutdown).
        removeAllListeners('SIGTERM').on('SIGTERM', shutdown);
};

/**
 * ### Log Shutdown Messages
 */
GhostServer.prototype.logShutdownMessages = function () {
    console.log(chalk.red(i18n.t('notices.httpServer.ghostIsClosingConnections')));
};

module.exports = GhostServer;
<commit_msg>🎨  replace config.getSocket()<commit_after>// # Ghost Server
// Handles the creation of an HTTP Server for Ghost
var Promise = require('bluebird'),
    chalk = require('chalk'),
    fs = require('fs'),
    path = require('path'),
    _ = require('lodash'),
    errors = require('./errors'),
    config = require('./config'),
    i18n   = require('./i18n'),
    moment = require('moment');

/**
 * ## GhostServer
 * @constructor
 * @param {Object} rootApp - parent express instance
 */
function GhostServer(rootApp) {
    this.rootApp = rootApp;
    this.httpServer = null;
    this.connections = {};
    this.connectionId = 0;

    // Expose config module for use externally.
    this.config = config;
}

/**
 * ## Public API methods
 *
 * ### Start
 * Starts the ghost server listening on the configured port.
 * Alternatively you can pass in your own express instance and let Ghost
 * start listening for you.
 * @param  {Object} externalApp - Optional express app instance.
 * @return {Promise} Resolves once Ghost has started
 */
GhostServer.prototype.start = function (externalApp) {
    var self = this,
        rootApp = externalApp ? externalApp : self.rootApp,
        socketConfig, socketValues = {
            path: path.join(config.get('paths').contentPath, process.env.NODE_ENV + '.socket'),
            permissions: '660'
        };

    return new Promise(function (resolve) {
        if (config.get('server').hasOwnProperty('socket')) {
            socketConfig = config.get('server').socket;

            if (_.isString(socketConfig)) {
                socketValues.path = socketConfig;
            } else if (_.isObject(socketConfig)) {
                socketValues.path = socketConfig.path || socketValues.path;
                socketValues.permissions = socketConfig.permissions || socketValues.permissions;
            }

            // Make sure the socket is gone before trying to create another
            try {
                fs.unlinkSync(socketValues.path);
            } catch (e) {
                // We can ignore this.
            }

            self.httpServer = rootApp.listen(socketValues.path);
            fs.chmod(socketValues.path, socketValues.permissions);
            config.set('server:socket', socketValues);
        } else {
            self.httpServer = rootApp.listen(
                config.get('server').port,
                config.get('server').host
            );
        }

        self.httpServer.on('error', function (error) {
            if (error.errno === 'EADDRINUSE') {
                errors.logError(
                    i18n.t('errors.httpServer.addressInUse.error'),
                    i18n.t('errors.httpServer.addressInUse.context', {port: config.get('server').port}),
                    i18n.t('errors.httpServer.addressInUse.help')
                );
            } else {
                errors.logError(
                    i18n.t('errors.httpServer.otherError.error', {errorNumber: error.errno}),
                    i18n.t('errors.httpServer.otherError.context'),
                    i18n.t('errors.httpServer.otherError.help')
                );
            }
            process.exit(-1);
        });
        self.httpServer.on('connection', self.connection.bind(self));
        self.httpServer.on('listening', function () {
            self.logStartMessages();
            resolve(self);
        });
    });
};

/**
 * ### Stop
 * Returns a promise that will be fulfilled when the server stops. If the server has not been started,
 * the promise will be fulfilled immediately
 * @returns {Promise} Resolves once Ghost has stopped
 */
GhostServer.prototype.stop = function () {
    var self = this;

    return new Promise(function (resolve) {
        if (self.httpServer === null) {
            resolve(self);
        } else {
            self.httpServer.close(function () {
                self.httpServer = null;
                self.logShutdownMessages();
                resolve(self);
            });

            self.closeConnections();
        }
    });
};

/**
 * ### Restart
 * Restarts the ghost application
 * @returns {Promise} Resolves once Ghost has restarted
 */
GhostServer.prototype.restart = function () {
    return this.stop().then(this.start.bind(this));
};

/**
 * ### Hammertime
 * To be called after `stop`
 */
GhostServer.prototype.hammertime = function () {
    console.log(chalk.green(i18n.t('notices.httpServer.cantTouchThis')));

    return Promise.resolve(this);
};

/**
 * ## Private (internal) methods
 *
 * ### Connection
 * @param {Object} socket
 */
GhostServer.prototype.connection = function (socket) {
    var self = this;

    self.connectionId += 1;
    socket._ghostId = self.connectionId;

    socket.on('close', function () {
        delete self.connections[this._ghostId];
    });

    self.connections[socket._ghostId] = socket;
};

/**
 * ### Close Connections
 * Most browsers keep a persistent connection open to the server, which prevents the close callback of
 * httpServer from returning. We need to destroy all connections manually.
 */
GhostServer.prototype.closeConnections = function () {
    var self = this;

    Object.keys(self.connections).forEach(function (socketId) {
        var socket = self.connections[socketId];

        if (socket) {
            socket.destroy();
        }
    });
};

/**
 * ### Log Start Messages
 */
GhostServer.prototype.logStartMessages = function () {
    // Startup & Shutdown messages
    if (process.env.NODE_ENV === 'production') {
        console.log(
            chalk.green(i18n.t('notices.httpServer.ghostIsRunningIn', {env: process.env.NODE_ENV})),
            i18n.t('notices.httpServer.yourBlogIsAvailableOn', {url: config.get('url')}),
            chalk.gray(i18n.t('notices.httpServer.ctrlCToShutDown'))
        );
    } else {
        console.log(
            chalk.green(i18n.t('notices.httpServer.ghostIsRunningIn', {env: process.env.NODE_ENV})),
            i18n.t('notices.httpServer.listeningOn'),
            config.get('server').socket || config.get('server').host + ':' + config.get('server').port,
            i18n.t('notices.httpServer.urlConfiguredAs', {url: config.get('url')}),
            chalk.gray(i18n.t('notices.httpServer.ctrlCToShutDown'))
        );
    }

    function shutdown() {
        console.log(chalk.red(i18n.t('notices.httpServer.ghostHasShutdown')));
        if (process.env.NODE_ENV === 'production') {
            console.log(
                i18n.t('notices.httpServer.yourBlogIsNowOffline')
            );
        } else {
            console.log(
                i18n.t('notices.httpServer.ghostWasRunningFor'),
                moment.duration(process.uptime(), 'seconds').humanize()
            );
        }
        process.exit(0);
    }
    // ensure that Ghost exits correctly on Ctrl+C and SIGTERM
    process.
        removeAllListeners('SIGINT').on('SIGINT', shutdown).
        removeAllListeners('SIGTERM').on('SIGTERM', shutdown);
};

/**
 * ### Log Shutdown Messages
 */
GhostServer.prototype.logShutdownMessages = function () {
    console.log(chalk.red(i18n.t('notices.httpServer.ghostIsClosingConnections')));
};

module.exports = GhostServer;
<|endoftext|>


<commit_before>import React from "react";
import RichText from "@hig/rich-text";
import "@hig/rich-text/build/index.css";

import DefaultExport from "../index";
import readme from "../../README.md";

export default {
  propTables: [DefaultExport],
  source: true,
  text: <RichText dangerouslySetInnerHTML={{ __html: readme }} />
};
<commit_msg>chore: remove deprecated css import<commit_after>import React from "react";
import RichText from "@hig/rich-text";

import DefaultExport from "../index";
import readme from "../../README.md";

export default {
  propTables: [DefaultExport],
  source: true,
  text: <RichText dangerouslySetInnerHTML={{ __html: readme }} />
};
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Francisco Salavert (SGL-CIPF)
 * Copyright (c) 2014 Alejandro Alemán (SGL-CIPF)
 * Copyright (c) 2014 Ignacio Medina (EBI-EMBL)
 * Copyright (c) 2014 Jag Kandasamy (EBI-EMBL)
 *
 * This file is part of EVA.
 *
 * EVA is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * EVA is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EVA. If not, see <http://www.gnu.org/licenses/>.
 */
var variant = {};
var geneID = '';

function EvaGeneView(args) {
    _.extend(this, Backbone.Events);
    this.id = Utils.genId("EVAGeneView");
    _.extend(this, args);
    this.rendered = false;
    this.render();

}
EvaGeneView.prototype = {
    render: function () {
        var _this = this

        this.targetDiv = (this.target instanceof HTMLElement) ? this.target : document.querySelector('#' + this.target);
        if (!this.targetDiv) {
            console.log('EVAv-GeneView: target ' + this.target + ' not found');
            return;
        }

        this.targetDiv.innerHTML = _this._varinatViewlayout();
        geneID = this.geneId;
        console.log(this.geneId)

        alert(geneID)
        var geneData;

        CellBaseManager.get({
            species: 'hsapiens',
            category: 'feature',
            subCategory: 'gene',
            query: geneID.toUpperCase(),
            resource: "info",
            async: false,
            params: {
//                include: 'chromosome,start,end'
            },
            success: function (data) {
                console.log(data)
                for (var i = 0; i < data.response.length; i++) {
                    var queryResult = data.response[i];
                    console.log(queryResult)
                    if(!_.isEmpty(queryResult.result[0])){
                        geneData = queryResult.result[0];
                    }
                }
            }
        });

        _this.draw(geneData);

        $('#geneViewTabs li').click(function(event) {
            $(this).toggleClass("active");
            $(this).siblings().removeClass("active");
        });
        $( document ).ready(function() {
            $('body').scrollspy({ 'target': '#geneViewScrollspy', 'offset': 250 });
        });
    },
    draw: function (data) {
            var _this = this;
//                     var variantInfoTitle =  document.querySelector("#variantInfo").textContent = variantID+' Info';
            var geneViewDiv = document.querySelector("#geneView");
            $(geneViewDiv).addClass('show-div');
            var summaryContent =  _this._renderSummaryData(data);
            var summaryEl = document.querySelector("#summary-grid");
            var summaryElDiv =  document.createElement("div");
            //       summaryElDiv.innerHTML = '
Summary
';
            summaryElDiv.innerHTML = summaryContent;
            summaryEl.appendChild(summaryElDiv);

            var transcriptEl = document.querySelector("#transcripts-grid");
            var transcriptElDiv = document.createElement("div");
            transcriptElDiv.setAttribute('class', 'eva variant-widget-panel ocb-variant-stats-panel');
            //       transcriptElDiv.innerHTML = '
Studies
';
            transcriptEl.appendChild(transcriptElDiv);
            _this.createTranscriptsPanel(transcriptElDiv,data);

            var gvEl = document.querySelector("#genome-viewer-grid");
            var gvElDiv = document.createElement("div");
            gvElDiv.setAttribute('class', 'ocb-gv');
            gvEl.appendChild(gvElDiv);
            var genomeViewer = _this._createGenomeViewer(gvElDiv);
            genomeViewer.draw();

    },
    _renderSummaryData: function (data) {
            var source = ''+data.source+':'+data.id+''
            var _summaryTable  = '

'
            _summaryTable +='
Gene Type	'+data.biotype+'
' +
                '
Location	'+data.chromosome+':'+data.start+'-'+data.end+'
' +
                '
Description	'+data.description+'
' +
                '
Source	'+source+'
' +
                '
'

            _summaryTable += '

'

            return _summaryTable;

    },
    createTranscriptsPanel: function (target,data) {
        var _this = this;
        var variantTranscriptGrid = new EvaVariantTranscriptGrid({
            target: target
        });

        variantTranscriptGrid.load(data);
        variantTranscriptGrid.draw();

        return variantTranscriptGrid;
    },
    _createGenomeViewer: function (target) {
//        var _this = this;

        var View =  Ext.create('Ext.view.View', {
            tpl: new Ext.XTemplate('

'),
            margin: '5 10 10 10'
        });
        this.headerConfig = {
            baseCls: 'eva-header-1'
        };

        var panel = Ext.create('Ext.panel.Panel', {
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            autoHeight: true,
            overflowY: true,
            height: 900,
            header: this.headerConfig,
            collapsible:true,
//            padding: 10,
            renderTo:target,
            items: [View]
        });
        var View =  Ext.create('Ext.view.View', {
            tpl: new Ext.XTemplate('

'),
            margin: '5 10 10 10'
        });

        var region = new Region({
            chromosome: "13",
            start: 32889611,
            end: 32889611
        });

        var genomeViewer = new GenomeViewer({
            cellBaseHost:'https://wwwdev.ebi.ac.uk/cellbase/webservices/rest',
            sidePanel: false,
            target: 'gene-view-gv',
            border: false,
            resizable: true,
            width: 1200,
            region: region,
            trackListTitle: '',
            drawNavigationBar: true,
            drawKaryotypePanel: true,
            drawChromosomePanel: true,
            drawRegionOverviewPanel: true,
            overviewZoomMultiplier: 50,
            navigationBarConfig: {
                componentsConfig: {
                    restoreDefaultRegionButton: false,
                    regionHistoryButton: false,
                    speciesButton: false,
                    chromosomesButton: false,
                    karyotypeButtonLabel: false,
                    chromosomeButtonLabel: false,
                    //regionButton: false,
//                    zoomControl: false,
                    windowSizeControl: false,
//                    positionControl: false,
//                    moveControl: false,
//                    autoheightButton: false,
//                    compactButton: false,
//                    searchControl: false
                }
            }
        });
        console.log(genomeViewer)
        genomeViewer.setZoom(80);

        var renderer = new FeatureRenderer(FEATURE_TYPES.gene);
        renderer.on({
            'feature:click': function (event) {
                // feature click event example
                console.log(event)
            }
        });
        var geneOverview = new FeatureTrack({
//        title: 'Gene overview',
            minHistogramRegionSize: 20000000,
            maxLabelRegionSize: 10000000,
            height: 100,

            renderer: renderer,

            dataAdapter: new CellBaseAdapter({
                category: "genomic",
                subCategory: "region",
                resource: "gene",
                params: {
                    exclude: 'transcripts,chunkIds'
                },
                species: genomeViewer.species,
                cacheConfig: {
                    chunkSize: 100000
                }
            })
        });

        var sequence = new SequenceTrack({
//        title: 'Sequence',
            height: 30,
            visibleRegionSize: 200,

            renderer: new SequenceRenderer(),

            dataAdapter: new SequenceAdapter({
                category: "genomic",
                subCategory: "region",
                resource: "sequence",
                species: genomeViewer.species
            })
        });

        var gene = new GeneTrack({
            title: 'Gene',
            minHistogramRegionSize: 20000000,
            maxLabelRegionSize: 10000000,
            minTranscriptRegionSize: 200000,
            height: 60,

            renderer: new GeneRenderer(),

            dataAdapter: new CellBaseAdapter({
                category: "genomic",
                subCategory: "region",
                resource: "gene",
                species: genomeViewer.species,
                params: {
                    exclude: 'transcripts.tfbs,transcripts.xrefs,transcripts.exons.sequence'
                },
                cacheConfig: {
                    chunkSize: 100000
                }
            })
        });

        var snp = new FeatureTrack({
            title: 'SNP',
            featureType: 'SNP',
            minHistogramRegionSize: 10000,
            maxLabelRegionSize: 3000,
            height: 100,

            renderer: new FeatureRenderer(FEATURE_TYPES.snp),

            dataAdapter: new CellBaseAdapter({
                category: "genomic",
                subCategory: "region",
                resource: "snp",
                params: {
                    exclude: 'transcriptVariations,xrefs,samples'
                },
                species: genomeViewer.species,
                cacheConfig: {
                    chunkSize: 10000
                }
            })
        });

        genomeViewer.addOverviewTrack(geneOverview);
        genomeViewer.addTrack([sequence, gene, snp]);

        return genomeViewer;
    },

    _varinatViewlayout:function(){

        var layout = '
'+
                        '
'+
                            '

'+
                            '

'+
                        '
'+
                        '
'+
                            '
'+
                                '
'+
                                    '
Summary
'+
                                    '
Transcripts
'+
                                    '
GV
'+
//                                    '
Genomic Co
'+
                               '
'+
                            '
'+
                            '
'+
                                '
'+
                                    '
'+
                                        '
 Summary
'+
                                        '

'+
                                    '
'+
                                '
'+
                                '
'+
                                    '
'+
                                        '
 Transcripts
'+
                                        '

'+
                                    '
'+
                                '
'+
                                '

'+
                                    '
'+
                                        '
 Genome Viewer
'+
                                        '

'+
                                    '
'+
                                '
'+
                            '
'+
                        '
'+
                    '
'
        return layout;
    }

}

<commit_msg>gene view added<commit_after>/*
 * Copyright (c) 2014 Francisco Salavert (SGL-CIPF)
 * Copyright (c) 2014 Alejandro Alemán (SGL-CIPF)
 * Copyright (c) 2014 Ignacio Medina (EBI-EMBL)
 * Copyright (c) 2014 Jag Kandasamy (EBI-EMBL)
 *
 * This file is part of EVA.
 *
 * EVA is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * EVA is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EVA. If not, see <http://www.gnu.org/licenses/>.
 */
var variant = {};
var geneID = '';

function EvaGeneView(args) {
    _.extend(this, Backbone.Events);
    this.id = Utils.genId("EVAGeneView");
    _.extend(this, args);
    this.rendered = false;
    this.render();

}
EvaGeneView.prototype = {
    render: function () {
        var _this = this

        this.targetDiv = (this.target instanceof HTMLElement) ? this.target : document.querySelector('#' + this.target);
        if (!this.targetDiv) {
            console.log('EVAv-GeneView: target ' + this.target + ' not found');
            return;
        }

        this.targetDiv.innerHTML = _this._varinatViewlayout();
        geneID = this.geneId;
        _this.geneData;

        CellBaseManager.get({
            species: 'hsapiens',
            category: 'feature',
            subCategory: 'gene',
            query: geneID.toUpperCase(),
            resource: "info",
            async: false,
            params: {
//                include: 'chromosome,start,end'
            },
            success: function (data) {
                console.log(data)
                for (var i = 0; i < data.response.length; i++) {
                    var queryResult = data.response[i];
                    console.log(queryResult)
                    if(!_.isEmpty(queryResult.result[0])){
                        _this.geneData = queryResult.result[0];
                    }
                }
            }
        });

        _this.draw(_this.geneData);

        $('#geneViewTabs li').click(function(event) {
            $(this).toggleClass("active");
            $(this).siblings().removeClass("active");
        });
        $( document ).ready(function() {
            $('body').scrollspy({ 'target': '#geneViewScrollspy', 'offset': 250 });
        });
    },
    draw: function (data) {
            var _this = this;
//                     var variantInfoTitle =  document.querySelector("#variantInfo").textContent = variantID+' Info';
            var geneViewDiv = document.querySelector("#geneView");
            $(geneViewDiv).addClass('show-div');
            var summaryContent =  _this._renderSummaryData(data);
            var summaryEl = document.querySelector("#summary-grid");
            var summaryElDiv =  document.createElement("div");
            //       summaryElDiv.innerHTML = '
Summary
';
            summaryElDiv.innerHTML = summaryContent;
            summaryEl.appendChild(summaryElDiv);

            var transcriptEl = document.querySelector("#transcripts-grid");
            var transcriptElDiv = document.createElement("div");
            transcriptElDiv.setAttribute('class', 'eva variant-widget-panel ocb-variant-stats-panel');
            //       transcriptElDiv.innerHTML = '
Studies
';
            transcriptEl.appendChild(transcriptElDiv);
            _this.createTranscriptsPanel(transcriptElDiv,data);

            var gvEl = document.querySelector("#genome-viewer-grid");
            var gvElDiv = document.createElement("div");
            gvElDiv.setAttribute('class', 'ocb-gv');
            gvEl.appendChild(gvElDiv);
            var genomeViewer = _this._createGenomeViewer(gvElDiv);
            genomeViewer.draw();

    },
    _renderSummaryData: function (data) {
            var source = ''+data.source+':'+data.id+''
            var _summaryTable  = '

'
            _summaryTable +='
Gene Type	'+data.biotype+'
' +
                '
Location	'+data.chromosome+':'+data.start+'-'+data.end+'
' +
                '
Description	'+data.description+'
' +
                '
Source	'+source+'
' +
                '
'

            _summaryTable += '

'

            return _summaryTable;

    },
    createTranscriptsPanel: function (target,data) {
        var _this = this;
        var variantTranscriptGrid = new EvaVariantTranscriptGrid({
            target: target
        });

        variantTranscriptGrid.load(data);
        variantTranscriptGrid.draw();

        return variantTranscriptGrid;
    },
    _createGenomeViewer: function (target) {
        var _this = this;

        var View =  Ext.create('Ext.view.View', {
            tpl: new Ext.XTemplate('

'),
            margin: '5 10 10 10'
        });
        this.headerConfig = {
            baseCls: 'eva-header-1'
        };
        this.margin = '5 0 0 20';

        var panel = Ext.create('Ext.panel.Panel', {
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            autoHeight: true,
            overflowY: true,
            height: 900,
            header: this.headerConfig,
            collapsible:true,
//            padding: 10,
            renderTo:target,
            items: [View],
            margin:this.margin
        });
        var View =  Ext.create('Ext.view.View', {
            tpl: new Ext.XTemplate('

'),
            margin: this.margin
        });

        console.log(_this.geneData)
        console.log('+++')

        var region = new Region({
            chromosome: _this.geneData.chromosome,
            start:  _this.geneData.start,
            end:  _this.geneData.end
        });

        var genomeViewer = new GenomeViewer({
            cellBaseHost:'https://wwwdev.ebi.ac.uk/cellbase/webservices/rest',
            sidePanel: false,
            target: 'gene-view-gv',
            border: false,
            resizable: true,
            width: 1150,
            region: region,
            trackListTitle: '',
            drawNavigationBar: true,
            drawKaryotypePanel: true,
            drawChromosomePanel: true,
            drawRegionOverviewPanel: true,
            overviewZoomMultiplier: 50,
            navigationBarConfig: {
                componentsConfig: {
                    restoreDefaultRegionButton: false,
                    regionHistoryButton: false,
                    speciesButton: false,
                    chromosomesButton: false,
                    karyotypeButtonLabel: false,
                    chromosomeButtonLabel: false,
                    //regionButton: false,
//                    zoomControl: false,
                    windowSizeControl: false,
//                    positionControl: false,
//                    moveControl: false,
//                    autoheightButton: false,
//                    compactButton: false,
//                    searchControl: false
                }
            }
        });
        console.log(genomeViewer)
        genomeViewer.setZoom(80);

        var renderer = new FeatureRenderer(FEATURE_TYPES.gene);
        renderer.on({
            'feature:click': function (event) {
                // feature click event example
                console.log(event)
            }
        });
        var geneOverview = new FeatureTrack({
//        title: 'Gene overview',
            minHistogramRegionSize: 20000000,
            maxLabelRegionSize: 10000000,
            height: 100,

            renderer: renderer,

            dataAdapter: new CellBaseAdapter({
                category: "genomic",
                subCategory: "region",
                resource: "gene",
                params: {
                    exclude: 'transcripts,chunkIds'
                },
                species: genomeViewer.species,
                cacheConfig: {
                    chunkSize: 100000
                }
            })
        });

        var sequence = new SequenceTrack({
//        title: 'Sequence',
            height: 30,
            visibleRegionSize: 200,

            renderer: new SequenceRenderer(),

            dataAdapter: new SequenceAdapter({
                category: "genomic",
                subCategory: "region",
                resource: "sequence",
                species: genomeViewer.species
            })
        });

        var gene = new GeneTrack({
            title: 'Gene',
            minHistogramRegionSize: 20000000,
            maxLabelRegionSize: 10000000,
            minTranscriptRegionSize: 200000,
            height: 60,

            renderer: new GeneRenderer(),

            dataAdapter: new CellBaseAdapter({
                category: "genomic",
                subCategory: "region",
                resource: "gene",
                species: genomeViewer.species,
                params: {
                    exclude: 'transcripts.tfbs,transcripts.xrefs,transcripts.exons.sequence'
                },
                cacheConfig: {
                    chunkSize: 100000
                }
            })
        });

        var snp = new FeatureTrack({
            title: 'SNP',
            featureType: 'SNP',
            minHistogramRegionSize: 10000,
            maxLabelRegionSize: 3000,
            height: 100,

            renderer: new FeatureRenderer(FEATURE_TYPES.snp),

            dataAdapter: new CellBaseAdapter({
                category: "genomic",
                subCategory: "region",
                resource: "snp",
                params: {
                    exclude: 'transcriptVariations,xrefs,samples'
                },
                species: genomeViewer.species,
                cacheConfig: {
                    chunkSize: 10000
                }
            })
        });

        genomeViewer.addOverviewTrack(geneOverview);
        genomeViewer.addTrack([sequence, gene, snp]);

        return genomeViewer;
    },

    _varinatViewlayout:function(){

        var layout = '
'+
                        '
'+
                            '

'+
                            '

'+
                        '
'+
                        '
'+
                            '
'+
                                '
'+
                                    '
Summary
'+
                                    '
Transcripts
'+
                                    '
GV
'+
//                                    '
Genomic Co
'+
                               '
'+
                            '
'+
                            '
'+
                                '
'+
                                    '
'+
                                        '
 Summary
'+
                                        '

'+
                                    '
'+
                                '
'+
                                '
'+
                                    '
'+
                                        '
 Transcripts
'+
                                        '

'+
                                    '
'+
                                '
'+
                                '

'+
                                    '
'+
                                        '
 Genome Viewer
'+
                                        '

'+
                                    '
'+
                                '
'+
                            '
'+
                        '
'+
                    '
'
        return layout;
    }

}

<|endoftext|>


<commit_before>import bcrypt from "bcrypt"

import Model from "./index"

const saltRounds = 8

export default class User extends Model {
  constructor() {
    super()

    this.on("saving", (user) => this.hashPassword(user))
  }

  get tableName() {
    return "users"
  }

  get hasTimestamps() {
    return true
  }

  async isValidPassword(plaintext) {
    return await bcrypt.compare(plaintext, this.passwordHash)
  }

  async hashPassord(user) {
    if (user.password && user.password.length > 0) {
      user.passwordHash = await bcrypt.hash(user.password, saltRounds)
    }
  }
}
<commit_msg>fix issue with saving hook<commit_after>import bcrypt from "bcrypt"

import Model from "./index"

const saltRounds = 8

export default class User extends Model {
  constructor() {
    super()

    this.on("saving", this.hashPassword)
  }

  get tableName() {
    return "users"
  }

  get hasTimestamps() {
    return true
  }

  async isValidPassword(plaintext) {
    return await bcrypt.compare(plaintext, this.passwordHash)
  }

  async hashPassword(user) {
    if (user.password && user.password.length > 0) {
      user.passwordHash = await bcrypt.hash(user.password, saltRounds)
    }
  }
}
<|endoftext|>


<commit_before>'use strict';

var byline        = require('byline'),
    chalk         = require('chalk'),
    eventStream   = require('event-stream'),
    fs            = require('fs'),
    isBinaryFile  = require('isbinaryfile'),
    minimatch     = require('minimatch'),
    readdirp      = require('readdirp');

var ignoredDirectories  = ['node_modules/**', '.git/**', '.hg/**'],
    filesToScan         = ['**/*.js', 'Makefile', '**/*.sh'],
    fileEncoding        = 'utf8',
    lineLengthLimit     = 1000,
    messageChecks       = {
      note: {
        regex:    /.*(?:\/\/)\s*NOTE(.*):\s*(.+)*/,
        label:    '✐ NOTE: ',
        colorer:  chalk.green
      },
      optimize: {
        regex:    /.*(?:\/\/)\s*OPTIMIZE(.*):\s*(.+)*/,
        label:    '↻ OPTIMIZE: ',
        colorer:  chalk.blue
      },
      todo: {
        regex:    /.*(?:\/\/)\s*TODO(.*):\s*(.+)*/,
        label:    '✓ TODO: ',
        colorer:  chalk.yellow
      },
      hack: {
        regex:    /.*(?:\/\/)\s*HACK(.*):\s*(.+)*/,
        label:    '✄ HACK: ',
        colorer:  chalk.magenta
      },
      fixme: {
        regex:    /.*(?:\/\/)\s*FIXME(.*):\s*(.+)*/,
        label:    '☠ FIXME: ',
        colorer:  chalk.red
      }
    };

/**
 * Determines whether or not to let the file through. by ensuring that the
 * file name does not match one of the excluded directories, and ensuring it
 * matches one of the file filters.
 *
 * It will also ensure that even if a binary file matches the filter patterns,
 * it will not let it through as searching binary file contents for string
 * matches will never make sense.
 *
 * @param   {String} fileInformation
 *
 * @return  {Boolean}
 */
// TODO: This could be simpler using minimatch negation patterns in one set, instead disparate ones for files and directories.
function fileFilterer (fileInformation) {
  var shouldIgnoreDirectory = false,
      shouldIgnoreFile      = true,
      letTheFileThrough;

  ignoredDirectories.forEach(function (directoryPattern) {
    if (shouldIgnoreDirectory) return;
    shouldIgnoreDirectory = minimatch(fileInformation.path, directoryPattern);
  });

  if (!shouldIgnoreDirectory) {
    filesToScan.forEach(function (filePattern) {
      if (!shouldIgnoreFile) return;

      shouldIgnoreFile = !(minimatch(fileInformation.name, filePattern));
    });
  }

  letTheFileThrough = !(shouldIgnoreDirectory || (!shouldIgnoreDirectory && shouldIgnoreFile));

  // Never let binary files through, searching them for comments will make no sense...
  if (letTheFileThrough && isBinaryFile(fileInformation.fullPath)) {
    letTheFileThrough = false;
  }

  return letTheFileThrough;
}

/**
 * Takes a line of a file and the line number, and returns an array of all of
 * the messages found in that line. Can return multiple messages per line, for
 * example, if a message was annotated with more than one type. EG: FIXME TODO
 *
 * Each message in the array will have a label, a line_number, a colorer, and a
 * message. Will also include an author property if one is found on the
 * message.
 *
 * @param   {String} lineString The
 * @param   {Number} lineNumber
 *
 * @return  {Array}
 */
function retrieveMessagesFromLine (lineString, lineNumber) {
  var messageFormat = {
    author:       null,
    message:      null,
    label:        null,
    colorer:      null,
    line_number:  lineNumber
  },
  messages = [];

  Object.keys(messageChecks).forEach(function (checkName) {
    var matchResults  = lineString.match(messageChecks[checkName].regex),
        checker       = messageChecks[checkName],
        thisMessage;

    if (matchResults && matchResults.length) {
      thisMessage = JSON.parse(JSON.stringify(messageFormat)); // Clone the above structure.

      thisMessage.label   = checker.label;
      thisMessage.colorer = checker.colorer;

      if (matchResults[1]) thisMessage.author   = matchResults[1];
      if (matchResults[2]) thisMessage.message  = matchResults[2];
    }

    if (thisMessage) messages.push(thisMessage);
  });

  return messages;
}

/**
 * Takes a line number and returns a padded string matching the total number of
 * characters in totalLinesNumber. EG: A lineNumber of 12 and a
 * totalLinesNumber of 1323 will return the string '  12'.
 *
 * @param   {Number} lineNumber
 * @param   {Number} totalLinesNumber
 *
 * @return  {String}
 */
function getPaddedLineNumber (lineNumber, totalLinesNumber) {
  var paddedLineNumberString = '' + lineNumber;

  while (paddedLineNumberString.length < ('' + totalLinesNumber).length) {
    paddedLineNumberString = ' ' + paddedLineNumberString;
  }

  return paddedLineNumberString;
}

/**
 * Takes an individual message object, as output from retrieveMessagesFromLine
 * and formats it for output.
 *
 * @param     {Object}    individualMessage
 * @property  {String}    individualMessage.author
 * @property  {String}    individualMessage.message
 * @property  {String}    individualMessage.label
 * @property  {Function}  individualMessage.colorer
 * @property  {Number}    individualMessage.line_number
 * @param     {Number}    totalNumberOfLines
 *
 * @return    {String}    The formatted message string.
 */
function formatMessageOutput (individualMessage, totalNumberOfLines) {
  var paddedLineNumber = getPaddedLineNumber(individualMessage.line_number, totalNumberOfLines),
      finalNoteString;

  finalNoteString =   chalk.gray('    [Line ' + paddedLineNumber + '] ');
  finalNoteString +=  chalk.bold(individualMessage.colorer(individualMessage.label));

  if (individualMessage.message && individualMessage.message.length) {
    finalNoteString += individualMessage.colorer(individualMessage.message);
  } else {
    finalNoteString += chalk.grey('[[no message to display]]');
  }

  return finalNoteString;
}

/**
 * Formatter function for the file name. Takes a file path, and the total
 * number of messages in the file, and formats this information for display as
 * the heading for the file messages.
 *
 * @param   {String} filePath
 * @param   {Number} numberOfMessages
 *
 * @return  {String}
 */
function formatFilePathOutput (filePath, numberOfMessages) {
  var filePathOutput = chalk.white('\n  • ' + filePath + ' '),
      messagesString = 'messages';

  if (numberOfMessages === 1) {
    messagesString = 'message';
  }

  filePathOutput += chalk.grey('[' + numberOfMessages + ' ' + messagesString + ']:');

  return filePathOutput;
}

/**
 * Takes an object representing the messages and other meta-info for the file
 * and calls off to the formatters for the messages, as well as logs the
 * formatted result.
 *
 * @param     {Object}  messagesInfo
 * @property  {String}  messagesInfo.path The file path
 * @property  {Array}   messagesInfo.messages All of the message objects for the file.
 * @property  {String}  messagesInfo.total_lines Total number of lines in the file.
 */
function logMessages (messagesInfo) {
  if (messagesInfo.messages.length) {
    console.log(formatFilePathOutput(messagesInfo.path, messagesInfo.messages.length));

    messagesInfo.messages.forEach(function (message) {
      var formattedMessage = formatMessageOutput(message, messagesInfo.total_lines);

      console.log(formattedMessage);
    });
  }
}

/**
 * Reads through the configured path scans the matching files for messages.
 */
function scanAndProcessMessages () {
  var stream = readdirp({
    root:       '../lighthouse',
    fileFilter: fileFilterer
  });

  // TODO: Actually do something meaningful/useful with these handlers.
  stream
    .on('warn', console.warn)
    .on('error', console.error);

  stream
    .pipe(eventStream.map(function (fileInformation, callback) {
      var input                 = fs.createReadStream(fileInformation.fullPath, { encoding: fileEncoding }),
          lineStream            = byline.createStream(input, { encoding: fileEncoding }),
          fileMessages          = { path: null, total_lines: 0, messages: [] },
          currentFileLineNumber = 1;

      fileMessages.path = fileInformation.path;

      lineStream.on('data', function (fileLineString) {
        var messages,
            lengthError;

        if (fileLineString.length < lineLengthLimit) {
          messages = retrieveMessagesFromLine(fileLineString, currentFileLineNumber);

          messages.forEach(function (message) {
            fileMessages.messages.push(message);
          });
        } else {
          lengthError = 'Fixme is skipping this line because its length is ' +
                        'greater than the maximum line-length of ' +
                        lineLengthLimit + '.';

          fileMessages.messages.push({
            message:      lengthError,
            line_number:  currentFileLineNumber,
            label:        '⚠ WARNING: ',
            colorer:      chalk.underline.red
          });
        }

        currentFileLineNumber += 1;
      });

      lineStream.on('end', function () {
        fileMessages.total_lines = currentFileLineNumber;

        logMessages(fileMessages);
      });

      callback();
    }));
}

/**
 * Takes an options object and over-writes the defaults, then calls off to the
 * scanner to scan the files for messages.
 *
 * @param     {Object}  options
 * @property  {String}  options.path                Required. The base directory to recursively scan for messages.
 * @property  {Array}   options.ignored_directories An array of minimatch glob patterns for directories to ignore scanning entirely.
 * @property  {Array}   options.file_patterns       An array of minimatch glob patterns for files to scan for messages.
 * @property  {String}  options.file_encoding       The encoding the files scanned will be opened with, defaults to 'utf8'.
 * @property  {Number}  options.line_length_limit   The number of characters a line can be before it is ignored. Defaults to 1000.
 */
 // TODO(johnp): Allow custom messageChecks to be added via options.
function parseUserOptionsAndScan (options) {
  if (options) {
    if (options.ignored_directories &&
        Array.isArray(options.ignored_directories) &&
        options.ignored_directories.length) {
      ignoredDirectories = options.ignored_directories;
    }

    if (options.file_patterns &&
        Array.isArray(options.file_patterns) &&
        options.file_patterns.length) {
      filesToScan = options.file_patterns;
    }

    if (options.file_encoding) {
      fileEncoding = options.file_encoding;
    }

    if (options.line_length_limit) {
      lineLengthLimit = options.line_length_limit;
    }
  } else {
    throw new Error('Options must be passed to FixMe with at least a `path` property.');
  }

  scanAndProcessMessages();
}

module.exports = parseUserOptionsAndScan;
<commit_msg>Improving the matching regular expressions for author capture.<commit_after>'use strict';

var byline        = require('byline'),
    chalk         = require('chalk'),
    eventStream   = require('event-stream'),
    fs            = require('fs'),
    isBinaryFile  = require('isbinaryfile'),
    minimatch     = require('minimatch'),
    readdirp      = require('readdirp');

var ignoredDirectories  = ['node_modules/**', '.git/**', '.hg/**'],
    filesToScan         = ['**/*.js', 'Makefile', '**/*.sh'],
    fileEncoding        = 'utf8',
    lineLengthLimit     = 1000,
    messageChecks       = {
      note: {
        regex:    /.*\/\/\s*NOTE\s*(?:\(([^:]*)\))\s*:\s*(.*)/,
        label:    '✐ NOTE',
        colorer:  chalk.green
      },
      optimize: {
        regex:    /.*\/\/\s*OPTIMIZE\s*(?:\(([^:]*)\))\s*:\s*(.*)/,
        label:    '↻ OPTIMIZE',
        colorer:  chalk.blue
      },
      todo: {
        regex:    /.*\/\/\s*TODO\s*(?:\(([^:]*)\))\s*:\s*(.*)/,
        label:    '✓ TODO',
        colorer:  chalk.yellow
      },
      hack: {
        regex:    /.*\/\/\s*HACK\s*(?:\(([^:]*)\))\s*:\s*(.*)/,
        label:    '✄ HACK',
        colorer:  chalk.magenta
      },
      fixme: {
        regex:    /.*\/\/\s*FIXME\s*(?:\(([^:]*)\))\s*:\s*(.*)/,
        label:    '☠ FIXME',
        colorer:  chalk.red
      }
    };

/**
 * Determines whether or not to let the file through. by ensuring that the
 * file name does not match one of the excluded directories, and ensuring it
 * matches one of the file filters.
 *
 * It will also ensure that even if a binary file matches the filter patterns,
 * it will not let it through as searching binary file contents for string
 * matches will never make sense.
 *
 * @param   {String} fileInformation
 *
 * @return  {Boolean}
 */
// TODO: This could be simpler using minimatch negation patterns in one set, instead disparate ones for files and directories.
function fileFilterer (fileInformation) {
  var shouldIgnoreDirectory = false,
      shouldIgnoreFile      = true,
      letTheFileThrough;

  ignoredDirectories.forEach(function (directoryPattern) {
    if (shouldIgnoreDirectory) return;
    shouldIgnoreDirectory = minimatch(fileInformation.path, directoryPattern);
  });

  if (!shouldIgnoreDirectory) {
    filesToScan.forEach(function (filePattern) {
      if (!shouldIgnoreFile) return;

      shouldIgnoreFile = !(minimatch(fileInformation.name, filePattern));
    });
  }

  letTheFileThrough = !(shouldIgnoreDirectory || (!shouldIgnoreDirectory && shouldIgnoreFile));

  // Never let binary files through, searching them for comments will make no sense...
  if (letTheFileThrough && isBinaryFile(fileInformation.fullPath)) {
    letTheFileThrough = false;
  }

  return letTheFileThrough;
}

/**
 * Takes a line of a file and the line number, and returns an array of all of
 * the messages found in that line. Can return multiple messages per line, for
 * example, if a message was annotated with more than one type. EG: FIXME TODO
 *
 * Each message in the array will have a label, a line_number, a colorer, and a
 * message. Will also include an author property if one is found on the
 * message.
 *
 * @param   {String} lineString The
 * @param   {Number} lineNumber
 *
 * @return  {Array}
 */
function retrieveMessagesFromLine (lineString, lineNumber) {
  var messageFormat = {
    author:       null,
    message:      null,
    label:        null,
    colorer:      null,
    line_number:  lineNumber
  },
  messages = [];

  Object.keys(messageChecks).forEach(function (checkName) {
    var matchResults  = lineString.match(messageChecks[checkName].regex),
        checker       = messageChecks[checkName],
        thisMessage;

    if (matchResults && matchResults.length) {
      thisMessage = JSON.parse(JSON.stringify(messageFormat)); // Clone the above structure.

      thisMessage.label   = checker.label;
      thisMessage.colorer = checker.colorer;

      if (matchResults[1] && matchResults[1].length) {
        thisMessage.author = matchResults[1].trim();
      }

      if (matchResults[2] && matchResults[2].length) {
        thisMessage.message = matchResults[2].trim();
      }
    }

    if (thisMessage) messages.push(thisMessage);
  });

  return messages;
}

/**
 * Takes a line number and returns a padded string matching the total number of
 * characters in totalLinesNumber. EG: A lineNumber of 12 and a
 * totalLinesNumber of 1323 will return the string '  12'.
 *
 * @param   {Number} lineNumber
 * @param   {Number} totalLinesNumber
 *
 * @return  {String}
 */
function getPaddedLineNumber (lineNumber, totalLinesNumber) {
  var paddedLineNumberString = '' + lineNumber;

  while (paddedLineNumberString.length < ('' + totalLinesNumber).length) {
    paddedLineNumberString = ' ' + paddedLineNumberString;
  }

  return paddedLineNumberString;
}

/**
 * Takes an individual message object, as output from retrieveMessagesFromLine
 * and formats it for output.
 *
 * @param     {Object}    individualMessage
 * @property  {String}    individualMessage.author
 * @property  {String}    individualMessage.message
 * @property  {String}    individualMessage.label
 * @property  {Function}  individualMessage.colorer
 * @property  {Number}    individualMessage.line_number
 * @param     {Number}    totalNumberOfLines
 *
 * @return    {String}    The formatted message string.
 */
function formatMessageOutput (individualMessage, totalNumberOfLines) {
  var paddedLineNumber = getPaddedLineNumber(individualMessage.line_number, totalNumberOfLines),
      finalLabelString,
      finalNoteString;

  finalNoteString = chalk.gray('  [Line ' + paddedLineNumber + '] ');

  finalLabelString = individualMessage.label;

  if (individualMessage.author) {
    finalLabelString += (' from ' + individualMessage.author + ': ');
  } else {
    finalLabelString += ': ';
  }

  finalLabelString = chalk.bold(individualMessage.colorer(finalLabelString));

  finalNoteString += finalLabelString;

  if (individualMessage.message && individualMessage.message.length) {
    finalNoteString += individualMessage.colorer(individualMessage.message);
  } else {
    finalNoteString += chalk.grey('[[no message to display]]');
  }

  return finalNoteString;
}

/**
 * Formatter function for the file name. Takes a file path, and the total
 * number of messages in the file, and formats this information for display as
 * the heading for the file messages.
 *
 * @param   {String} filePath
 * @param   {Number} numberOfMessages
 *
 * @return  {String}
 */
function formatFilePathOutput (filePath, numberOfMessages) {
  var filePathOutput = chalk.white('\n• ' + filePath + ' '),
      messagesString = 'messages';

  if (numberOfMessages === 1) {
    messagesString = 'message';
  }

  filePathOutput += chalk.grey('[' + numberOfMessages + ' ' + messagesString + ']:');

  return filePathOutput;
}

/**
 * Takes an object representing the messages and other meta-info for the file
 * and calls off to the formatters for the messages, as well as logs the
 * formatted result.
 *
 * @param     {Object}  messagesInfo
 * @property  {String}  messagesInfo.path The file path
 * @property  {Array}   messagesInfo.messages All of the message objects for the file.
 * @property  {String}  messagesInfo.total_lines Total number of lines in the file.
 */
function logMessages (messagesInfo) {
  if (messagesInfo.messages.length) {
    console.log(formatFilePathOutput(messagesInfo.path, messagesInfo.messages.length));

    messagesInfo.messages.forEach(function (message) {
      var formattedMessage = formatMessageOutput(message, messagesInfo.total_lines);

      console.log(formattedMessage);
    });
  }
}

/**
 * Reads through the configured path scans the matching files for messages.
 */
function scanAndProcessMessages () {
  var stream = readdirp({
    root:       '../lighthouse',
    fileFilter: fileFilterer
  });

  // TODO: Actually do something meaningful/useful with these handlers.
  stream
    .on('warn', console.warn)
    .on('error', console.error);

  stream
    .pipe(eventStream.map(function (fileInformation, callback) {
      var input                 = fs.createReadStream(fileInformation.fullPath, { encoding: fileEncoding }),
          lineStream            = byline.createStream(input, { encoding: fileEncoding }),
          fileMessages          = { path: null, total_lines: 0, messages: [] },
          currentFileLineNumber = 1;

      fileMessages.path = fileInformation.path;

      lineStream.on('data', function (fileLineString) {
        var messages,
            lengthError;

        if (fileLineString.length < lineLengthLimit) {
          messages = retrieveMessagesFromLine(fileLineString, currentFileLineNumber);

          messages.forEach(function (message) {
            fileMessages.messages.push(message);
          });
        } else {
          lengthError = 'Fixme is skipping this line because its length is ' +
                        'greater than the maximum line-length of ' +
                        lineLengthLimit + '.';

          fileMessages.messages.push({
            message:      lengthError,
            line_number:  currentFileLineNumber,
            label:        '⚠ WARNING',
            colorer:      chalk.underline.red
          });
        }

        currentFileLineNumber += 1;
      });

      lineStream.on('end', function () {
        fileMessages.total_lines = currentFileLineNumber;

        logMessages(fileMessages);
      });

      callback();
    }));
}

/**
 * Takes an options object and over-writes the defaults, then calls off to the
 * scanner to scan the files for messages.
 *
 * @param     {Object}  options
 * @property  {String}  options.path                Required. The base directory to recursively scan for messages.
 * @property  {Array}   options.ignored_directories An array of minimatch glob patterns for directories to ignore scanning entirely.
 * @property  {Array}   options.file_patterns       An array of minimatch glob patterns for files to scan for messages.
 * @property  {String}  options.file_encoding       The encoding the files scanned will be opened with, defaults to 'utf8'.
 * @property  {Number}  options.line_length_limit   The number of characters a line can be before it is ignored. Defaults to 1000.
 */
 // TODO(johnp): Allow custom messageChecks to be added via options.
function parseUserOptionsAndScan (options) {
  if (options) {
    if (options.ignored_directories &&
        Array.isArray(options.ignored_directories) &&
        options.ignored_directories.length) {
      ignoredDirectories = options.ignored_directories;
    }

    if (options.file_patterns &&
        Array.isArray(options.file_patterns) &&
        options.file_patterns.length) {
      filesToScan = options.file_patterns;
    }

    if (options.file_encoding) {
      fileEncoding = options.file_encoding;
    }

    if (options.line_length_limit) {
      lineLengthLimit = options.line_length_limit;
    }
  } else {
    throw new Error('Options must be passed to FixMe with at least a `path` property.');
  }

  scanAndProcessMessages();
}

module.exports = parseUserOptionsAndScan;
<|endoftext|>


<commit_before>import {isSupported} from 'caniuse-api';
import selectorParser from 'postcss-selector-parser';

const cssSel2 = 'css-sel2';
const cssSel3 = 'css-sel3';
const cssGencontent = 'css-gencontent';
const cssFirstLetter = 'css-first-letter';
const cssFirstLine = 'css-first-line';
const cssInOutOfRange = 'css-in-out-of-range';

export const pseudoElements = {
    ':active':            cssSel2,
    ':after':             cssGencontent,
    ':before':            cssGencontent,
    ':checked':           cssSel3,
    ':default':           'css-default-pseudo',
    ':dir':               'css-dir-pseudo',
    ':disabled':          cssSel3,
    ':empty':             cssSel3,
    ':enabled':           cssSel3,
    ':first-child':       cssSel2,
    ':first-letter':      cssFirstLetter,
    ':first-line':        cssFirstLine,
    ':first-of-type':     cssSel3,
    ':focus':             cssSel2,
    ':focus-within':      'css-focus-within',
    ':has':               'css-has',
    ':hover':             cssSel2,
    ':in-range':          cssInOutOfRange,
    ':indeterminate':     'css-indeterminate-pseudo',
    ':lang':              cssSel2,
    ':last-child':        cssSel3,
    ':last-of-type':      cssSel3,
    ':matches':           'css-matches-pseudo',
    ':not':               cssSel3,
    ':nth-child':         cssSel3,
    ':nth-last-child':    cssSel3,
    ':nth-last-of-type':  cssSel3,
    ':nth-of-type':       cssSel3,
    ':only-child':        cssSel3,
    ':only-of-type':      cssSel3,
    ':optional':          'css-optional-pseudo',
    ':out-of-range':      cssInOutOfRange,
    ':placeholder-shown': 'css-placeholder-shown',
    ':root':              cssSel3,
    ':target':            cssSel3,
    '::after':            cssGencontent,
    '::backdrop':         'dialog',
    '::before':           cssGencontent,
    '::first-letter':     cssFirstLetter,
    '::first-line':       cssFirstLine,
    '::marker':           'css-marker-pseudo',
    '::placeholder':      'css-placeholder',
    '::selection':        'css-selection',
};

function isCssMixin (selector) {
    return selector[selector.length - 1] === ':';
}

export default function ensureCompatibility (selectors, browsers) {
    // Should not merge mixins
    if (selectors.some(isCssMixin)) {
        return false;
    }
    return selectors.every(selector => {
        let compatible = true;
        selectorParser(ast => {
            ast.walk(node => {
                const {type, value} = node;
                if (type === 'pseudo') {
                    const entry = pseudoElements[value];
                    if (entry && compatible) {
                        compatible = isSupported(entry, browsers);
                    }
                }
                if (type === 'combinator') {
                    if (~value.indexOf('~')) {
                        compatible = isSupported(cssSel3, browsers);
                    }
                    if (~value.indexOf('>') || ~value.indexOf('+')) {
                        compatible = isSupported(cssSel2, browsers);
                    }
                }
                if (type === 'attribute' && node.attribute) {
                    // [foo]
                    if (!node.operator) {
                        compatible = isSupported(cssSel2, browsers);
                    }

                    if (value) {
                        // [foo="bar"], [foo~="bar"], [foo|="bar"]
                        if (~['=', '~=', '|='].indexOf(node.operator)) {
                            compatible = isSupported(cssSel2, browsers);
                        }
                        // [foo^="bar"], [foo$="bar"], [foo*="bar"]
                        if (~['^=', '$=', '*='].indexOf(node.operator)) {
                            compatible = isSupported(cssSel3, browsers);
                        }
                    }

                    // [foo="bar" i]
                    if (node.insensitive) {
                        compatible = isSupported('css-case-insensitive', browsers);
                    }
                }
            });
        }).process(selector);
        return compatible;
    });
}
<commit_msg>Short-circuit compatibility testing for simple selectors<commit_after>import {isSupported} from 'caniuse-api';
import selectorParser from 'postcss-selector-parser';

const simpleSelectorRe = /^#?[-._a-z0-9 ]+$/i;

const cssSel2 = 'css-sel2';
const cssSel3 = 'css-sel3';
const cssGencontent = 'css-gencontent';
const cssFirstLetter = 'css-first-letter';
const cssFirstLine = 'css-first-line';
const cssInOutOfRange = 'css-in-out-of-range';

export const pseudoElements = {
    ':active':            cssSel2,
    ':after':             cssGencontent,
    ':before':            cssGencontent,
    ':checked':           cssSel3,
    ':default':           'css-default-pseudo',
    ':dir':               'css-dir-pseudo',
    ':disabled':          cssSel3,
    ':empty':             cssSel3,
    ':enabled':           cssSel3,
    ':first-child':       cssSel2,
    ':first-letter':      cssFirstLetter,
    ':first-line':        cssFirstLine,
    ':first-of-type':     cssSel3,
    ':focus':             cssSel2,
    ':focus-within':      'css-focus-within',
    ':has':               'css-has',
    ':hover':             cssSel2,
    ':in-range':          cssInOutOfRange,
    ':indeterminate':     'css-indeterminate-pseudo',
    ':lang':              cssSel2,
    ':last-child':        cssSel3,
    ':last-of-type':      cssSel3,
    ':matches':           'css-matches-pseudo',
    ':not':               cssSel3,
    ':nth-child':         cssSel3,
    ':nth-last-child':    cssSel3,
    ':nth-last-of-type':  cssSel3,
    ':nth-of-type':       cssSel3,
    ':only-child':        cssSel3,
    ':only-of-type':      cssSel3,
    ':optional':          'css-optional-pseudo',
    ':out-of-range':      cssInOutOfRange,
    ':placeholder-shown': 'css-placeholder-shown',
    ':root':              cssSel3,
    ':target':            cssSel3,
    '::after':            cssGencontent,
    '::backdrop':         'dialog',
    '::before':           cssGencontent,
    '::first-letter':     cssFirstLetter,
    '::first-line':       cssFirstLine,
    '::marker':           'css-marker-pseudo',
    '::placeholder':      'css-placeholder',
    '::selection':        'css-selection',
};

function isCssMixin (selector) {
    return selector[selector.length - 1] === ':';
}

export default function ensureCompatibility (selectors, browsers) {
    // Should not merge mixins
    if (selectors.some(isCssMixin)) {
        return false;
    }
    return selectors.every(selector => {
        if (simpleSelectorRe.test(selector)) {
            return true;
        }
        let compatible = true;
        selectorParser(ast => {
            ast.walk(node => {
                const {type, value} = node;
                if (type === 'pseudo') {
                    const entry = pseudoElements[value];
                    if (entry && compatible) {
                        compatible = isSupported(entry, browsers);
                    }
                }
                if (type === 'combinator') {
                    if (~value.indexOf('~')) {
                        compatible = isSupported(cssSel3, browsers);
                    }
                    if (~value.indexOf('>') || ~value.indexOf('+')) {
                        compatible = isSupported(cssSel2, browsers);
                    }
                }
                if (type === 'attribute' && node.attribute) {
                    // [foo]
                    if (!node.operator) {
                        compatible = isSupported(cssSel2, browsers);
                    }

                    if (value) {
                        // [foo="bar"], [foo~="bar"], [foo|="bar"]
                        if (~['=', '~=', '|='].indexOf(node.operator)) {
                            compatible = isSupported(cssSel2, browsers);
                        }
                        // [foo^="bar"], [foo$="bar"], [foo*="bar"]
                        if (~['^=', '$=', '*='].indexOf(node.operator)) {
                            compatible = isSupported(cssSel3, browsers);
                        }
                    }

                    // [foo="bar" i]
                    if (node.insensitive) {
                        compatible = isSupported('css-case-insensitive', browsers);
                    }
                }
            });
        }).process(selector);
        return compatible;
    });
}
<|endoftext|>


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

    var djangular = angular.module('djangular', [])

    djangular.service('CurrentUser', function () {
       return {
                  'username': '{{ user.username|escapejs }}',
                  'is_authenticated': 'True' === '{{ user.is_authenticated|escapejs }}',
                  {% if user.is_authenticated %}
                  'id': '{{ user.id|escapejs }}',
                  'name': '{{ user.get_full_name|escapejs }}',
                  'picture': '{{ user.get_picture_url|escapejs }}',
                  {% endif %}
              }
    });

})(angular);
<commit_msg>add CRSF support to djangular<commit_after>(function(angular) {
  'use strict';

    var app = angular.module('djangular', [])

    app.service('CurrentUser', function () {
      return {
          'username': '{{ user.username|escapejs }}',
          'is_authenticated': 'True' === '{{ user.is_authenticated|escapejs }}',
          {% if user.is_authenticated %}
          'id': '{{ user.id|escapejs }}',
          'name': '{{ user.get_full_name|escapejs }}',
          'picture': '{{ user.get_picture_url|escapejs }}',
          {% endif %}
       }
    });

    app.constant('STATIC_URL', '{{ STATIC_URL }}');
    app.constant('DEBUG', '{{ DEBUG }}');

    app.config(function ($httpProvider, $logProvider, DEBUG, $sceDelegateProvider, STATIC_URL) {
            $httpProvider.defaults.xsrfCookieName = 'csrftoken';
            $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
            $logProvider.debugEnabled(DEBUG);
            $sceDelegateProvider.resourceUrlWhitelist([
                /^https?:\/\/(www\.)?youtube\.com\/.*/,
                'data:text/html, <html style="background: white">',
                'self',
                STATIC_URL + '**'
            ]);
        }
    );

})(angular);
<|endoftext|>