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

/**

*/
foam.CLASS({
  package: 'foam.core',
  name: 'InnerClass',

  // documentation: 'Inner-Class Axiom',

  properties: [
    {
      name: 'name',
      getter: function() { return this.model.name; }
    },
    {
      name: 'model',
      adapt: function(_, m) {
        // TODO: Not needed once we have ObjectProperties
        return foam.core.Model.isInstance(m) ? m : foam.core.Model.create(m);
      }
    }
  ],

  methods: [
    function installInClass(cls) {
      cls[this.model.name] = this.model.buildClass();
    },
    function installInProto(proto) {
      // get class already created in installInClass();
      var name = this.model.name;
      var cls = proto.cls_[name];

      // TODO: doc
      Object.defineProperty(proto, name, {
        get: function innerClassGetter() {
          if ( ! this.hasOwnPrivate_(name) ) {
            var parent = this;

            var c = Object.create(cls);
            c.create = function innerClassCreate(args, X) { return cls.create(args, X || parent); };
            this.setPrivate_(name, c);
          }

          return this.getPrivate_(name);
        },
        configurable: true,
        enumerable: false
      });
    }
  ]
});

foam.CLASS({
  refines: 'foam.core.Model',
  properties: [
    {
      class: 'AxiomArray',
      of: 'InnerClass',
      name: 'classes',
      // TODO: is this needed?
      adaptArrayElement: function(o) {
        return foam.core.InnerClass.isInstance(o) ?
          o :
          foam.core.InnerClass.create({model: o}) ;
      }
    }
  ]
});
<commit_msg>Resolve two TODO's in InnerClass.<commit_after>/*
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**

*/
foam.CLASS({
  package: 'foam.core',
  name: 'InnerClass',

  // documentation: 'Inner-Class Axiom',

  properties: [
    {
      name: 'name',
      getter: function() { return this.model.name; }
    },
    {
      name: 'model',
      adapt: function(_, m) {
        return foam.core.Model.isInstance(m) ? m : foam.core.Model.create(m);
      }
    }
  ],

  methods: [
    function installInClass(cls) {
      cls[this.model.name] = this.model.buildClass();
    },
    function installInProto(proto) {
      // get class already created in installInClass();
      var name = this.model.name;
      var cls = proto.cls_[name];

      // TODO: doc
      Object.defineProperty(proto, name, {
        get: function innerClassGetter() {
          if ( ! this.hasOwnPrivate_(name) ) {
            var parent = this;

            var c = Object.create(cls);
            c.create = function innerClassCreate(args, X) { return cls.create(args, X || parent); };
            this.setPrivate_(name, c);
          }

          return this.getPrivate_(name);
        },
        configurable: true,
        enumerable: false
      });
    }
  ]
});

foam.CLASS({
  refines: 'foam.core.Model',
  properties: [
    {
      class: 'AxiomArray',
      of: 'InnerClass',
      name: 'classes',
      // A custom adaptArrayElement is needed because we're
      // passing the model definition as model:, rather than
      // as all of the arguments to create().
      adaptArrayElement: function(o) {
        return foam.core.InnerClass.isInstance(o) ?
          o :
          foam.core.InnerClass.create({model: o}) ;
      }
    }
  ]
});
<|endoftext|>


<commit_before>var grunt = require('grunt');

module.exports = {
  main: {
    options: {
      paths: grunt.file.expand('src/**'),
      sourceMap: true
    },
    files: {
      'demo/static/css/main.css': [
        'src/vendor/normalize-css/normalize.css',
        'src/vendor/normalize-legacy-addon/normalize-legacy-addon.css',
        'src/vendor/font-awesome/font-awesome.css',
        'src/vendor/cf-concat/cf.less'
      ]
    }
  }
};
<commit_msg>Updates the less task to stop duplicate instances of normalize.<commit_after>var grunt = require('grunt');

module.exports = {
  main: {
    options: {
      paths: grunt.file.expand('src/**'),
      sourceMap: true
    },
    files: {
      'demo/static/css/main.css': [
        'src/vendor/cf-concat/cf.less'
      ]
    }
  }
};
<|endoftext|>


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

"use strict";

var invariant = require('invariant');

/**
 * ReactOwners are capable of storing references to owned components.
 *
 * All components are capable of //being// referenced by owner components, but
 * only ReactOwner components are capable of //referencing// owned components.
 * The named reference is known as a "ref".
 *
 * Refs are available when mounted and updated during reconciliation.
 *
 *   var MyComponent = React.createClass({
 *     render: function() {
 *       return (
 *

 *           <CustomComponent ref="custom" />
 *

 *       );
 *     },
 *     handleClick: function() {
 *       this.refs.custom.handleClick();
 *     },
 *     componentDidMount: function() {
 *       this.refs.custom.initialize();
 *     }
 *   });
 *
 * Refs should rarely be used. When refs are used, they should only be done to
 * control data that is not handled by React's data flow.
 *
 * @class ReactOwner
 */
var ReactOwner = {

  /**
   * @param {?object} object
   * @return {boolean} True if `object` is a valid owner.
   * @final
   */
  isValidOwner: function(object) {
    return !!(
      object &&
      typeof object.attachRef === 'function' &&
      typeof object.detachRef === 'function'
    );
  },

  /**
   * Adds a component by ref to an owner component.
   *
   * @param {ReactComponent} component Component to reference.
   * @param {string} ref Name by which to refer to the component.
   * @param {ReactOwner} owner Component on which to record the ref.
   * @final
   * @internal
   */
  addComponentAsRefTo: function(component, ref, owner) {
    invariant(
      ReactOwner.isValidOwner(owner),
      'addComponentAsRefTo(...): Only a ReactOwner can have refs. This ' +
      'usually means that you\'re trying to add a ref to a component that ' +
      'doesn\'t have an owner (that is, was not created inside of another ' +
      'component\'s `render` method). Try rendering this component inside of ' +
      'a new top-level component which will hold the ref.)'
    );
    owner.attachRef(ref, component);
  },

  /**
   * Removes a component by ref from an owner component.
   *
   * @param {ReactComponent} component Component to dereference.
   * @param {string} ref Name of the ref to remove.
   * @param {ReactOwner} owner Component on which the ref is recorded.
   * @final
   * @internal
   */
  removeComponentAsRefFrom: function(component, ref, owner) {
    invariant(
      ReactOwner.isValidOwner(owner),
      'removeComponentAsRefFrom(...): Only a ReactOwner can have refs. This ' +
      'usually means that you\'re trying to remove a ref to a component that ' +
      'doesn\'t have an owner (that is, was not created inside of another ' +
      'component\'s `render` method). Try rendering this component inside of ' +
      'a new top-level component which will hold the ref.'
    );
    // Check that `component` is still the current ref because we do not want to
    // detach the ref if another component stole it.
    if (owner.refs[ref] === component) {
      owner.detachRef(ref);
    }
  },

  /**
   * A ReactComponent must mix this in to have refs.
   *
   * @lends {ReactOwner.prototype}
   */
  Mixin: {

    /**
     * Lazily allocates the refs object and stores `component` as `ref`.
     *
     * @param {string} ref Reference name.
     * @param {component} component Component to store as `ref`.
     * @final
     * @private
     */
    attachRef: function(ref, component) {
      invariant(
        component.isOwnedBy(this),
        'attachRef(%s, ...): Only a component\'s owner can store a ref to it.',
        ref
      );
      var refs = this.refs || (this.refs = {});
      refs[ref] = component;
    },

    /**
     * Detaches a reference name.
     *
     * @param {string} ref Name to dereference.
     * @final
     * @private
     */
    detachRef: function(ref) {
      delete this.refs[ref];
    }

  }

};

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

"use strict";

var invariant = require('invariant');

/**
 * ReactOwners are capable of storing references to owned components.
 *
 * All components are capable of //being// referenced by owner components, but
 * only ReactOwner components are capable of //referencing// owned components.
 * The named reference is known as a "ref".
 *
 * Refs are available when mounted and updated during reconciliation.
 *
 *   var MyComponent = React.createClass({
 *     render: function() {
 *       return (
 *

 *           <CustomComponent ref="custom" />
 *

 *       );
 *     },
 *     handleClick: function() {
 *       this.refs.custom.handleClick();
 *     },
 *     componentDidMount: function() {
 *       this.refs.custom.initialize();
 *     }
 *   });
 *
 * Refs should rarely be used. When refs are used, they should only be done to
 * control data that is not handled by React's data flow.
 *
 * @class ReactOwner
 */
var ReactOwner = {

  /**
   * @param {?object} object
   * @return {boolean} True if `object` is a valid owner.
   * @final
   */
  isValidOwner: function(object) {
    return !!(
      object &&
      typeof object.attachRef === 'function' &&
      typeof object.detachRef === 'function'
    );
  },

  /**
   * Adds a component by ref to an owner component.
   *
   * @param {ReactComponent} component Component to reference.
   * @param {string} ref Name by which to refer to the component.
   * @param {ReactOwner} owner Component on which to record the ref.
   * @final
   * @internal
   */
  addComponentAsRefTo: function(component, ref, owner) {
    invariant(
      ReactOwner.isValidOwner(owner),
      'addComponentAsRefTo(...): Only a ReactOwner can have refs. This ' +
      'usually means that you\'re trying to add a ref to a component that ' +
      'doesn\'t have an owner (that is, was not created inside of another ' +
      'component\'s `render` method). Try rendering this component inside of ' +
      'a new top-level component which will hold the ref.'
    );
    owner.attachRef(ref, component);
  },

  /**
   * Removes a component by ref from an owner component.
   *
   * @param {ReactComponent} component Component to dereference.
   * @param {string} ref Name of the ref to remove.
   * @param {ReactOwner} owner Component on which the ref is recorded.
   * @final
   * @internal
   */
  removeComponentAsRefFrom: function(component, ref, owner) {
    invariant(
      ReactOwner.isValidOwner(owner),
      'removeComponentAsRefFrom(...): Only a ReactOwner can have refs. This ' +
      'usually means that you\'re trying to remove a ref to a component that ' +
      'doesn\'t have an owner (that is, was not created inside of another ' +
      'component\'s `render` method). Try rendering this component inside of ' +
      'a new top-level component which will hold the ref.'
    );
    // Check that `component` is still the current ref because we do not want to
    // detach the ref if another component stole it.
    if (owner.refs[ref] === component) {
      owner.detachRef(ref);
    }
  },

  /**
   * A ReactComponent must mix this in to have refs.
   *
   * @lends {ReactOwner.prototype}
   */
  Mixin: {

    /**
     * Lazily allocates the refs object and stores `component` as `ref`.
     *
     * @param {string} ref Reference name.
     * @param {component} component Component to store as `ref`.
     * @final
     * @private
     */
    attachRef: function(ref, component) {
      invariant(
        component.isOwnedBy(this),
        'attachRef(%s, ...): Only a component\'s owner can store a ref to it.',
        ref
      );
      var refs = this.refs || (this.refs = {});
      refs[ref] = component;
    },

    /**
     * Detaches a reference name.
     *
     * @param {string} ref Name to dereference.
     * @final
     * @private
     */
    detachRef: function(ref) {
      delete this.refs[ref];
    }

  }

};

module.exports = ReactOwner;
<|endoftext|>


<commit_before>/*globals module:true */
module.exports = function(grunt) {
    'use strict';

    var fileSeparator = require('./config').fileSeparator,
        path = require('path'),
        _ = require('lodash');
            // grunt.util._ is depracated

    grunt.registerTask('releaseNotes', 'read in files to make release notes', function() {
        var types = ['backward incompatibilities', 'features', 'patches'],
            previous = ['0','0','0'],
            notes = '',
            last = '';

        grunt.file.recurse('release_notes', function(file) {
            var name = path.basename(file, '.md'),
                separatorAt = name.indexOf(fileSeparator),
                version = name.substring(0,separatorAt),
                date = name.substring(separatorAt + 1),
                current = version.split('.'),
                updateType = '';

            last = version;

            _.each(current, function(value, index) {
                if (previous[index].trim() != current[index].trim()) {
                    updateType = types[index];
                    return false;
                }
                return undefined;
            });
            previous = current;

            notes += '* ' + version + ' - ' + date + ' - [' + updateType +
                '](https://github.com/Solid-Interactive/masseuse/blob/master/release_notes/' + name + '.md)\n';
        });
        if (grunt.config.get('pkg').version !== last) {
            grunt.fatal('Latest release notes and package.version do not match');
        }
        grunt.log.writeln(notes);
        grunt.config.set('releaseNotes', notes);
    });
};
<commit_msg>updating release notes task to handle 2 digit major, minor, patch version numbers<commit_after>/*globals module:true */
module.exports = function(grunt) {
    'use strict';

    var fileSeparator = require('./config').fileSeparator,
        path = require('path'),
        _ = require('lodash');
            // grunt.util._ is depracated

    grunt.registerTask('releaseNotes', 'read in files to make release notes', function() {
        var types = ['backward incompatibilities', 'features', 'patches'],
            previous = ['0','0','0'],
            notes = '',
            last = '',
            files = [];

        grunt.file.recurse('release_notes', function(file) {
            var name = path.basename(file, '.md'),
                separatorAt = name.indexOf(fileSeparator),
                version = name.substring(0,separatorAt),
                date = name.substring(separatorAt + 1),
                current = version.split('.');

            files.push({name: name, version: version, date: date, current: current});
        });
        files = files.sort(function(fileA, fileB) {
            if (fileA.current[0] !== fileB.current[0]) {
                return fileA.current[0] - fileB.current[0];
            }
            if (fileA.current[1] !== fileB.current[1]) {
                return fileA.current[1] - fileB.current[1];
            }
            if (fileA.current[2] !== fileB.current[2]) {
                return fileA.current[2] - fileB.current[2];
            }
        });
        _.each(files, function(file) {
            var name = file.name,
                version = file.version,
                date = file.date,
                current = file.current,
                updateType = '';

            last = version;
            _.each(current, function(value, index) {
                if (previous[index].trim() != current[index].trim()) {
                    updateType = types[index];
                    return false;
                }
                return undefined;
            });
            previous = current;

            notes += '* ' + version + ' - ' + date + ' - [' + updateType +
                '](https://github.com/Solid-Interactive/masseuse/blob/master/release_notes/' + name + '.md)\n';
        });
        if (grunt.config.get('pkg').version !== last) {
            grunt.fatal('Latest release notes and package.version do not match');
        }
        grunt.log.writeln(notes);
        grunt.config.set('releaseNotes', notes);
    });
};
<|endoftext|>


<commit_before>// import en_US from '../locales/en_US'

/**
 * Translates strings with interpolation & pluralization support.Extensible with custom dictionaries
 * and pluralization functions.
 *
 * Borrows heavily from and inspired by Polyglot https://github.com/airbnb/polyglot.js,
 * basically a stripped-down version of it. Differences: pluralization functions are not hardcoded
 * and can be easily added among with dictionaries, nested objects are used for pluralization
 * as opposed to `||||` delimeter
 *
 * Usage example: `translator.translate('files_chosen', {smart_count: 3})`
 *
 * @param {object} opts
 */
export default class Translator {
  constructor (opts) {
    const defaultOptions = {
      // locale: en_US
    }

    const defaultPluralize = function (n) {
      if (n === 1) {
        return 0
      }
      return 1
    }

    this.opts = Object.assign({}, defaultOptions, opts)
    this.locale = this.opts.locale
    this.locale.pluralize = this.opts.locale.pluralize || defaultPluralize
    // this.locale.strings = Object.assign({}, en_US.strings, this.opts.locale.strings)
  }

/**
 * Takes a string with placeholder variables like `%{smart_count} file selected`
 * and replaces it with values from options `{smart_count: 5}`
 *
 * @license https://github.com/airbnb/polyglot.js/blob/master/LICENSE
 * taken from https://github.com/airbnb/polyglot.js/blob/master/lib/polyglot.js#L299
 *
 * @param {string} phrase that needs interpolation, with placeholders
 * @param {object} options with values that will be used to replace placeholders
 * @return {string} interpolated
 */
  interpolate (phrase, options) {
    const replace = String.prototype.replace
    const dollarRegex = /\$/g
    const dollarBillsYall = '$$$$'

    for (let arg in options) {
      if (arg !== '_' && options.hasOwnProperty(arg)) {
        // Ensure replacement value is escaped to prevent special $-prefixed
        // regex replace tokens. the "$$$$" is needed because each "$" needs to
        // be escaped with "$" itself, and we need two in the resulting output.
        var replacement = options[arg]
        if (typeof replacement === 'string') {
          replacement = replace.call(options[arg], dollarRegex, dollarBillsYall)
        }
        // We create a new `RegExp` each time instead of using a more-efficient
        // string replace so that the same argument can be replaced multiple times
        // in the same phrase.
        phrase = replace.call(phrase, new RegExp('%\\{' + arg + '\\}', 'g'), replacement)
      }
    }
    return phrase
  }

/**
 * Public translate method
 *
 * @param {string} key
 * @param {object} options with values that will be used later to replace placeholders in string
 * @return {string} translated (and interpolated)
 */
  translate (key, options) {
    if (options && options.smart_count) {
      var plural = this.locale.pluralize(options.smart_count)
      return this.interpolate(this.opts.locale.strings[key][plural], options)
    }

    return this.interpolate(this.opts.locale.strings[key], options)
  }
}
<commit_msg>default pluralize fix<commit_after>// import en_US from '../locales/en_US'

/**
 * Translates strings with interpolation & pluralization support.Extensible with custom dictionaries
 * and pluralization functions.
 *
 * Borrows heavily from and inspired by Polyglot https://github.com/airbnb/polyglot.js,
 * basically a stripped-down version of it. Differences: pluralization functions are not hardcoded
 * and can be easily added among with dictionaries, nested objects are used for pluralization
 * as opposed to `||||` delimeter
 *
 * Usage example: `translator.translate('files_chosen', {smart_count: 3})`
 *
 * @param {object} opts
 */
export default class Translator {
  constructor (opts) {
    const defaultOptions = {
      // locale: en_US
    }

    const defaultPluralize = function (n) {
      if (n === 1) {
        return 0
      }
      return 1
    }

    this.opts = Object.assign({}, defaultOptions, opts)
    this.locale = this.opts.locale
    this.locale.pluralize = this.locale.pluralize || defaultPluralize
    // this.locale.strings = Object.assign({}, en_US.strings, this.opts.locale.strings)
  }

/**
 * Takes a string with placeholder variables like `%{smart_count} file selected`
 * and replaces it with values from options `{smart_count: 5}`
 *
 * @license https://github.com/airbnb/polyglot.js/blob/master/LICENSE
 * taken from https://github.com/airbnb/polyglot.js/blob/master/lib/polyglot.js#L299
 *
 * @param {string} phrase that needs interpolation, with placeholders
 * @param {object} options with values that will be used to replace placeholders
 * @return {string} interpolated
 */
  interpolate (phrase, options) {
    const replace = String.prototype.replace
    const dollarRegex = /\$/g
    const dollarBillsYall = '$$$$'

    for (let arg in options) {
      if (arg !== '_' && options.hasOwnProperty(arg)) {
        // Ensure replacement value is escaped to prevent special $-prefixed
        // regex replace tokens. the "$$$$" is needed because each "$" needs to
        // be escaped with "$" itself, and we need two in the resulting output.
        var replacement = options[arg]
        if (typeof replacement === 'string') {
          replacement = replace.call(options[arg], dollarRegex, dollarBillsYall)
        }
        // We create a new `RegExp` each time instead of using a more-efficient
        // string replace so that the same argument can be replaced multiple times
        // in the same phrase.
        phrase = replace.call(phrase, new RegExp('%\\{' + arg + '\\}', 'g'), replacement)
      }
    }
    return phrase
  }

/**
 * Public translate method
 *
 * @param {string} key
 * @param {object} options with values that will be used later to replace placeholders in string
 * @return {string} translated (and interpolated)
 */
  translate (key, options) {
    if (options && options.smart_count) {
      var plural = this.locale.pluralize(options.smart_count)
      return this.interpolate(this.opts.locale.strings[key][plural], options)
    }

    return this.interpolate(this.opts.locale.strings[key], options)
  }
}
<|endoftext|>


<commit_before>import en_US from '../locales/en_US'

/**
 * Translates strings with interpolation & pluralization support.Extensible with custom dictionaries
 * and pluralization functions.
 *
 * Borrows heavily from and inspired by Polyglot https://github.com/airbnb/polyglot.js,
 * basically a stripped-down version of it. Differences: pluralization functions are not hardcoded
 * and can be easily added among with dictionaries, nested objects are used for pluralization
 * as opposed to `||||` delimeter
 *
 * Usage example: `translator.translate('files_chosen', {smart_count: 3})`
 *
 * @param {object} opts
 */
export default class Translator {
  constructor (opts) {
    const defaultOptions = {
      locales: en_US
    }
    this.opts = Object.assign({}, defaultOptions, opts)
    this.locales = this.opts.locales
    this.locales.strings = Object.assign({}, en_US.strings, this.opts.locales.strings)
    console.log(this.locales)
  }

/**
 * Takes a string with placeholder variables like `%{smart_count} file selected`
 * and replaces it with values from options `{smart_count: 5}`
 *
 * @license https://github.com/airbnb/polyglot.js/blob/master/LICENSE
 * taken from https://github.com/airbnb/polyglot.js/blob/master/lib/polyglot.js#L299
 *
 * @param {string} phrase that needs interpolation, with placeholders
 * @param {object} options with values that will be used to replace placeholders
 * @return {string} interpolated
 */
  interpolate (phrase, options) {
    const replace = String.prototype.replace
    const dollarRegex = /\$/g
    const dollarBillsYall = '$$$$'

    for (let arg in options) {
      if (arg !== '_' && options.hasOwnProperty(arg)) {
        // Ensure replacement value is escaped to prevent special $-prefixed
        // regex replace tokens. the "$$$$" is needed because each "$" needs to
        // be escaped with "$" itself, and we need two in the resulting output.
        var replacement = options[arg]
        if (typeof replacement === 'string') {
          replacement = replace.call(options[arg], dollarRegex, dollarBillsYall)
        }
        // We create a new `RegExp` each time instead of using a more-efficient
        // string replace so that the same argument can be replaced multiple times
        // in the same phrase.
        phrase = replace.call(phrase, new RegExp('%\\{' + arg + '\\}', 'g'), replacement)
      }
    }
    return phrase
  }

/**
 * Public translate method
 *
 * @param {string} key
 * @param {object} options with values that will be used later to replace placeholders in string
 * @return {string} translated (and interpolated)
 */
  translate (key, options) {
    if (options && options.smart_count) {
      var plural = this.locales.pluralize(options.smart_count)
      return this.interpolate(this.opts.locales.strings[key][plural], options)
    }

    return this.interpolate(this.opts.locales.strings[key], options)
  }
}
<commit_msg>prevent :loud_sound:<commit_after>import en_US from '../locales/en_US'

/**
 * Translates strings with interpolation & pluralization support.Extensible with custom dictionaries
 * and pluralization functions.
 *
 * Borrows heavily from and inspired by Polyglot https://github.com/airbnb/polyglot.js,
 * basically a stripped-down version of it. Differences: pluralization functions are not hardcoded
 * and can be easily added among with dictionaries, nested objects are used for pluralization
 * as opposed to `||||` delimeter
 *
 * Usage example: `translator.translate('files_chosen', {smart_count: 3})`
 *
 * @param {object} opts
 */
export default class Translator {
  constructor (opts) {
    const defaultOptions = {
      locales: en_US
    }
    this.opts = Object.assign({}, defaultOptions, opts)
    this.locales = this.opts.locales
    this.locales.strings = Object.assign({}, en_US.strings, this.opts.locales.strings)
  }

/**
 * Takes a string with placeholder variables like `%{smart_count} file selected`
 * and replaces it with values from options `{smart_count: 5}`
 *
 * @license https://github.com/airbnb/polyglot.js/blob/master/LICENSE
 * taken from https://github.com/airbnb/polyglot.js/blob/master/lib/polyglot.js#L299
 *
 * @param {string} phrase that needs interpolation, with placeholders
 * @param {object} options with values that will be used to replace placeholders
 * @return {string} interpolated
 */
  interpolate (phrase, options) {
    const replace = String.prototype.replace
    const dollarRegex = /\$/g
    const dollarBillsYall = '$$$$'

    for (let arg in options) {
      if (arg !== '_' && options.hasOwnProperty(arg)) {
        // Ensure replacement value is escaped to prevent special $-prefixed
        // regex replace tokens. the "$$$$" is needed because each "$" needs to
        // be escaped with "$" itself, and we need two in the resulting output.
        var replacement = options[arg]
        if (typeof replacement === 'string') {
          replacement = replace.call(options[arg], dollarRegex, dollarBillsYall)
        }
        // We create a new `RegExp` each time instead of using a more-efficient
        // string replace so that the same argument can be replaced multiple times
        // in the same phrase.
        phrase = replace.call(phrase, new RegExp('%\\{' + arg + '\\}', 'g'), replacement)
      }
    }
    return phrase
  }

/**
 * Public translate method
 *
 * @param {string} key
 * @param {object} options with values that will be used later to replace placeholders in string
 * @return {string} translated (and interpolated)
 */
  translate (key, options) {
    if (options && options.smart_count) {
      var plural = this.locales.pluralize(options.smart_count)
      return this.interpolate(this.opts.locales.strings[key][plural], options)
    }

    return this.interpolate(this.opts.locales.strings[key], options)
  }
}
<|endoftext|>


<commit_before>function Tw2Frustum()
{
    this.planes = [quat4.create(), quat4.create(), quat4.create(), quat4.create(), quat4.create(), quat4.create(), ];
    this.viewPos = vec3.create();
    this.viewDir = vec3.create();
    this.halfWidthProjection = 1;
    this._tempVec = vec3.create();
}

Tw2Frustum.prototype.Initialize = function (view, proj, viewportSize)
{
    var viewProj = mat4.create();

    mat4.inverse(view, viewProj);
    this.viewPos.set(viewProj.subarray(12, 14));
    this.viewDir.set(viewProj.subarray(8, 10));

	this.halfWidthProjection = proj[0] * viewportSize * 0.5;

    mat4.multiply(proj, view, viewProj);
    this.planes[0][0] = viewProj[2];
    this.planes[0][1] = viewProj[6];
    this.planes[0][2] = viewProj[10];
    this.planes[0][3] = viewProj[14];

    this.planes[1][0] = viewProj[3] + viewProj[0];
    this.planes[1][1] = viewProj[7] + viewProj[4];
    this.planes[1][2] = viewProj[11] + viewProj[8];
    this.planes[1][3] = viewProj[15] + viewProj[12];

    this.planes[2][0] = viewProj[3] - viewProj[1];
    this.planes[2][1] = viewProj[7] - viewProj[5];
    this.planes[2][2] = viewProj[11] - viewProj[9];
    this.planes[2][3] = viewProj[15] - viewProj[13];

    this.planes[3][0] = viewProj[3] - viewProj[0];
    this.planes[3][1] = viewProj[7] - viewProj[4];
    this.planes[3][2] = viewProj[11] - viewProj[8];
    this.planes[3][3] = viewProj[15] - viewProj[12];

    this.planes[4][0] = viewProj[3] + viewProj[1];
    this.planes[4][1] = viewProj[7] + viewProj[5];
    this.planes[4][2] = viewProj[11] + viewProj[9];
    this.planes[4][3] = viewProj[15] + viewProj[13];

    this.planes[5][0] = viewProj[3] - viewProj[2];
    this.planes[5][1] = viewProj[7] - viewProj[6];
    this.planes[5][2] = viewProj[11] - viewProj[10];
    this.planes[5][3] = viewProj[15] - viewProj[14];

    for (var i = 0; i < 6; ++i)
    {
        var len = vec3.length(this.planes[i]);
        this.planes[i][0] /= len;
        this.planes[i][1] /= len;
        this.planes[i][2] /= len;
        this.planes[i][3] /= len;
    }
}

Tw2Frustum.prototype.IsSphereVisible = function (center, radius)
{
    for (var i = 0; i < 6; ++i)
    {
        if (this.planes[i][0] * center[0] + this.planes[i][1] * center[1] + this.planes[i][2] * center[2] + this.planes[i][3] < -radius)
        {
            return false;
        }
    }
    return true;
}

Tw2Frustum.prototype.GetPixelSizeAccross = function (center, radius)
{
    var d = vec3.subtract(this.viewPos, center, this._tempVec);
    var depth = vec3.dot(this.viewDir, d);
    var epsilon = 1e-5;
    if (depth < epsilon)
    {
        depth = epsilon;
    }
    if (radius < epsilon)
    {
        return 0;
    }
    var ratio = radius / depth;
	return ratio * this.halfWidthProjection * 2;
}<commit_msg>Basic Documentation Tw2Frustum<commit_after>/**
 * Tw2Frustum
 * @property {Array.<quat4>} planes
 * @property {vec3} viewPos
 * @property {vec3} viewDir
 * @property {number} halfWidthProjection
 * @property {vec3} _tempVec
 * @constructor
 */
function Tw2Frustum()
{
    this.planes = [quat4.create(), quat4.create(), quat4.create(), quat4.create(), quat4.create(), quat4.create()];
    this.viewPos = vec3.create();
    this.viewDir = vec3.create();
    this.halfWidthProjection = 1;
    this._tempVec = vec3.create();
}

/**
 * Initializes the Tw2Frustum
 * @param {mat4} view - View Matrix
 * @param {mat4} proj - Projection Matrix
 * @param {number} viewportSize
 * @prototype
 */
Tw2Frustum.prototype.Initialize = function(view, proj, viewportSize)
{
    var viewProj = mat4.create();

    mat4.inverse(view, viewProj);
    this.viewPos.set(viewProj.subarray(12, 14));
    this.viewDir.set(viewProj.subarray(8, 10));

    this.halfWidthProjection = proj[0] * viewportSize * 0.5;

    mat4.multiply(proj, view, viewProj);
    this.planes[0][0] = viewProj[2];
    this.planes[0][1] = viewProj[6];
    this.planes[0][2] = viewProj[10];
    this.planes[0][3] = viewProj[14];

    this.planes[1][0] = viewProj[3] + viewProj[0];
    this.planes[1][1] = viewProj[7] + viewProj[4];
    this.planes[1][2] = viewProj[11] + viewProj[8];
    this.planes[1][3] = viewProj[15] + viewProj[12];

    this.planes[2][0] = viewProj[3] - viewProj[1];
    this.planes[2][1] = viewProj[7] - viewProj[5];
    this.planes[2][2] = viewProj[11] - viewProj[9];
    this.planes[2][3] = viewProj[15] - viewProj[13];

    this.planes[3][0] = viewProj[3] - viewProj[0];
    this.planes[3][1] = viewProj[7] - viewProj[4];
    this.planes[3][2] = viewProj[11] - viewProj[8];
    this.planes[3][3] = viewProj[15] - viewProj[12];

    this.planes[4][0] = viewProj[3] + viewProj[1];
    this.planes[4][1] = viewProj[7] + viewProj[5];
    this.planes[4][2] = viewProj[11] + viewProj[9];
    this.planes[4][3] = viewProj[15] + viewProj[13];

    this.planes[5][0] = viewProj[3] - viewProj[2];
    this.planes[5][1] = viewProj[7] - viewProj[6];
    this.planes[5][2] = viewProj[11] - viewProj[10];
    this.planes[5][3] = viewProj[15] - viewProj[14];

    for (var i = 0; i < 6; ++i)
    {
        var len = vec3.length(this.planes[i]);
        this.planes[i][0] /= len;
        this.planes[i][1] /= len;
        this.planes[i][2] /= len;
        this.planes[i][3] /= len;
    }
};

/**
 * Checks to see if a sphere is visible within the frustum
 * @param {vec3} center
 * @param {number} radius
 * @returns {boolean}
 * @prototype
 */
Tw2Frustum.prototype.IsSphereVisible = function(center, radius)
{
    for (var i = 0; i < 6; ++i)
    {
        if (this.planes[i][0] * center[0] + this.planes[i][1] * center[1] + this.planes[i][2] * center[2] + this.planes[i][3] < -radius)
        {
            return false;
        }
    }
    return true;
};

/**
 * GetPixelSizeAcross
 * @param {vec3} center
 * @param {number} radius
 * @returns {number}
 * @prototype
 */
Tw2Frustum.prototype.GetPixelSizeAcross = function(center, radius)
{
    var d = vec3.subtract(this.viewPos, center, this._tempVec);
    var depth = vec3.dot(this.viewDir, d);
    var epsilon = 1e-5;
    if (depth < epsilon)
    {
        depth = epsilon;
    }
    if (radius < epsilon)
    {
        return 0;
    }
    var ratio = radius / depth;
    return ratio * this.halfWidthProjection * 2;
};
<|endoftext|>


<commit_before>/**
 * Created by alnedorezov on 3/20/17.
 */
function loadJSON(callback) {

    var xobj = new XMLHttpRequest();
    xobj.overrideMimeType("application/json");
    xobj.open('GET', 'classesandparameters.json', true);
    xobj.onreadystatechange = function() {
        if (xobj.readyState == 4 && xobj.status == "200") {

            // .open will NOT return a value but simply returns undefined in async mode so use a callback
            callback(xobj.responseText);

        }
    };
    xobj.send(null);

}

// Call to function with anonymous callback
loadJSON(function(response) {
    jsonresponse = JSON.parse(response);

    alert(jsonresponse[0].name);

});

var json = '{"result":true,"count":1, "rows": [["data00", "data01", "data02", "data03"], ' +
            '["data10", "data11", "data12", "data13"], ' +
            '["data20", "data21", "data22", "data23"],' +
            '["data30", "data31", "data32", "data33"]]}';
    obj = JSON.parse(json);

function checkJSON() {
    alert(obj.rows);
}<commit_msg>LT-65 Modified imageproperties.js<commit_after>/**
 * Created by alnedorezov on 3/20/17.
 */
function loadJSON(callback) {

    var xobj = new XMLHttpRequest();
    xobj.overrideMimeType("application/json");
    xobj.open('GET', 'https://rawgit.com/innosoft-pro/label-them/LT-65/front/classesandparameters.json', true);
    xobj.onreadystatechange = function() {
        if (xobj.readyState == 4 && xobj.status == "200") {

            // .open will NOT return a value but simply returns undefined in async mode so use a callback
            callback(xobj.responseText);

        }
    };
    xobj.send(null);

}

// Call to function with anonymous callback
loadJSON(function(response) {
    jsonresponse = JSON.parse(response);

    alert(jsonresponse[0].name);

});

var json = '{"result":true,"count":1, "rows": [["data00", "data01", "data02", "data03"], ' +
            '["data10", "data11", "data12", "data13"], ' +
            '["data20", "data21", "data22", "data23"],' +
            '["data30", "data31", "data32", "data33"]]}';
    obj = JSON.parse(json);

function checkJSON() {
    alert(obj.rows);
}<|endoftext|>


<commit_before>const dotenv = require(`dotenv`)
dotenv.config({
  path: `../backend/uclapi/.env`,
})

const webpack = require(`webpack`)
const path = require(`path`)
const TerserPlugin = require(`terser-webpack-plugin`)
const OptimizeCSSAssetsPlugin = require(`optimize-css-assets-webpack-plugin`)
const BundleTracker = require(`webpack-bundle-tracker`)

const os = require(`os`)

const entryPointsPathPrefix = `./src/pages`

const {
  AWS_S3_STATICS,
  AWS_S3_BUCKET_NAME,
  AWS_S3_BUCKET_PATH,
} = process.env

const publicPath = AWS_S3_STATICS === `true`
  ? `https://${AWS_S3_BUCKET_NAME}.s3.amazonaws.com/${AWS_S3_BUCKET_PATH}`
  : `/static/`

module.exports = {
  mode: `production`,
  optimization: {
    minimize: true,
    minimizer: [],  // This list is built below as per platform requirements
    splitChunks: {
      name: false,
      cacheGroups: {
        vendors: {
          chunks: `all`,
          name: `vendors`,
          test: /[\\/]node_modules[\\/]/,
        },
      },
    },
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(`production`),
      'process.env.SENTRY_DSN_REACT': JSON.stringify(process.env.SENTRY_DSN_REACT),
    }),
    new BundleTracker({
      filename: `../backend/uclapi/static/webpack-stats.json`,
    }),
    new webpack.HashedModuleIdsPlugin(),
  ],
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: `babel-loader`,
        },
      },
      {
        test: /\.scss|css$/,
        use: [
          { loader: `style-loader` },
          { loader: `css-loader` },
          { loader: `sass-loader` },
        ],
      },
      {
        test: /\.(jpg|png|svg|jpeg)$/,
        loader: `url-loader`,
      },
    ],
  },
  resolve: {
    alias: {
      'Images': path.resolve(__dirname, `./src/images`),
      'Layout': path.resolve(__dirname, `./src/components/layout`),
      'Dashboard': path.resolve(__dirname, `./src/components/dashboard`),
      'Styles': path.resolve(__dirname, `./src/sass`),
    },
    extensions: [`.js`, `.json`, `.jsx`],
  },
  entry: {
    index: entryPointsPathPrefix + `/Home`,
    documentation: entryPointsPathPrefix + `/Documentation`,
    about: entryPointsPathPrefix + `/AboutPage`,
    dashboard: entryPointsPathPrefix + `/Dashboard`,
    marketplace: entryPointsPathPrefix + `/Marketplace`,
    authorise: entryPointsPathPrefix + `/Authorise`,
    warning: entryPointsPathPrefix + `/Warning`,
    404: entryPointsPathPrefix + `/404`,
    500: entryPointsPathPrefix + `/500`,
    settings: entryPointsPathPrefix + `/AppSettings`,
    vendors: [`react`],
  },
  output: {
    path: path.resolve(__dirname, `../backend/uclapi/static/`),
    publicPath,
    filename: `[name]-[contenthash].js`,
  },
}

// Do not enable parallelisation for Windows Subsystem for Linux
// https://github.com/webpack-contrib/uglifyjs-webpack-plugin/issues/302
// https://stackoverflow.com/a/44356310/5297057
if (os.platform() == `linux` && os.release().indexOf(`Microsoft`) != -1) {
  module.exports.optimization.minimizer.push(
    new TerserPlugin({
      cache: true,
      sourceMap: true,
    })
  )
} else {
  module.exports.optimization.minimizer.push(
    new TerserPlugin({
      cache: true,
      sourceMap: true,
      parallel: true,
    })
  )
}
module.exports.optimization.minimizer.push(
  new OptimizeCSSAssetsPlugin({})
)
<commit_msg>fix-merge<commit_after>const dotenv = require(`dotenv`)
dotenv.config({
  path: `../backend/uclapi/.env`,
})

const webpack = require(`webpack`)
const path = require(`path`)
const TerserPlugin = require(`terser-webpack-plugin`)
const OptimizeCSSAssetsPlugin = require(`optimize-css-assets-webpack-plugin`)
const BundleTracker = require(`webpack-bundle-tracker`)

const os = require(`os`)

const entryPointsPathPrefix = `./src/pages`

const {
  AWS_S3_STATICS,
  AWS_S3_BUCKET_NAME,
  AWS_S3_BUCKET_PATH,
} = process.env

const publicPath = AWS_S3_STATICS === `true`
  ? `https://${AWS_S3_BUCKET_NAME}.s3.amazonaws.com/${AWS_S3_BUCKET_PATH}`
  : `/static/`

module.exports = {
  mode: `production`,
  optimization: {
    minimize: true,
    minimizer: [],  // This list is built below as per platform requirements
    moduleIds: `deterministic`,
    splitChunks: {
      chunks: `all`,
    },
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(`production`),
      'process.env.SENTRY_DSN_REACT': JSON.stringify(process.env.SENTRY_DSN_REACT),
    }),
    new BundleTracker({
      filename: `../backend/uclapi/static/webpack-stats.json`,
    }),
  ],
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: `babel-loader`,
        },
      },
      {
        test: /\.scss|css$/,
        use: [
          {loader: `style-loader`},
          {loader: `css-loader`},
          {loader: `sass-loader`},
        ],
      },
      {
        test: /\.(jpg|png|svg|jpeg)$/,
        loader: `url-loader`,
      },
    ],
  },
  resolve: {
    alias: {
      'Images': path.resolve(__dirname, `./src/images`),
      'Layout': path.resolve(__dirname, `./src/components/layout`),
      'Dashboard': path.resolve(__dirname, `./src/components/dashboard`),
      'Styles': path.resolve(__dirname, `./src/sass`),
    },
    extensions: [`.js`, `.json`, `.jsx`],
  },
  entry: {
    index: entryPointsPathPrefix + `/Home`,
    documentation: entryPointsPathPrefix + `/Documentation`,
    about: entryPointsPathPrefix + `/AboutPage`,
    dashboard: entryPointsPathPrefix + `/Dashboard`,
    marketplace: entryPointsPathPrefix + `/Marketplace`,
    authorise: entryPointsPathPrefix + `/Authorise`,
    warning: entryPointsPathPrefix + `/Warning`,
    404: entryPointsPathPrefix + `/404`,
    500: entryPointsPathPrefix + `/500`,
    settings: entryPointsPathPrefix + `/AppSettings`,
    vendors: [`react`],
  },
  output: {
    path: path.resolve(__dirname, `../backend/uclapi/static/`),
    publicPath,
    filename: `[name]-[contenthash].js`,
  },
}

// Do not enable parallelisation for Windows Subsystem for Linux
// https://github.com/webpack-contrib/uglifyjs-webpack-plugin/issues/302
// https://stackoverflow.com/a/44356310/5297057
if (os.platform() == `linux` && os.release().indexOf(`Microsoft`) != -1) {
  module.exports.optimization.minimizer.push(
    new TerserPlugin({}),
  )
} else {
  module.exports.optimization.minimizer.push(
    new TerserPlugin({
      parallel: true,
    }),
  )
}
module.exports.optimization.minimizer.push(
  new OptimizeCSSAssetsPlugin({}),
)
<|endoftext|>


<commit_before>import * as matrix from 'redpill'
import { getPrefixedStyleProperty } from '../../utils/browser'

export default function style (element) {
	const computed = window.getComputedStyle(element.node)
	const position = computed.position
	const config = element.config

	/**
	 * Generate inline styles
	 */
	const inlineRegex = /.+[^;]/g
	const inlineStyle = element.node.getAttribute('style') || ''
	const inlineMatch = inlineRegex.exec(inlineStyle)

	let inline = (inlineMatch) ? `${inlineMatch[0]};` : ''
	if (inline.indexOf('visibility: visible') === -1) {
		inline += (inline.length) ? ' ' : ''
		inline += 'visibility: visible;'
	}

	/**
	 * Generate opacity styles
	 */
	const computedOpacity = parseFloat(computed.opacity)
	const configOpacity = (!isNaN(parseFloat(config.opacity)))
		? parseFloat(config.opacity)
		: computedOpacity

	const opacity = {
		computed: (computedOpacity !== configOpacity) ? `opacity: ${computedOpacity}; ` : null,
		generated: (computedOpacity !== configOpacity) ? `opacity: ${configOpacity}; ` : null,
	}

	/**
	 * Generate transformation styles
	 */
	const transformations = []

	if (parseFloat(config.distance)) {
		const axis = (config.origin === 'top' || config.origin === 'bottom') ? 'Y' : 'X'

		/**
		 * Let’s make sure our our pixel distances are negative for top and left.
		 * e.g. { origin: 'top', distance: '25px' } starts at `top: -25px` in CSS.
    	 */
		let distance = config.distance
		if (config.origin === 'top' || config.origin === 'left') {
			distance = /^-/.test(distance)
				? distance.substr(1)
				: `-${distance}`
		}

		const [value, unit] = distance.match(/(^-?\d+\.?\d?)|(em$|px$|\%$)/g)

		switch (unit) {
			case 'em':
				distance = parseInt(computed.fontSize) * value
				break
			case 'px':
				distance = value
				break
			case '%':
				distance = (axis === 'Y')
					? element.node.getBoundingClientRect().height * value / 100
					: element.node.getBoundingClientRect().width * value / 100
				break
			default:
				throw new RangeError('Unrecognized or missing distance unit.')
		}

		transformations.push(matrix[`translate${axis}`](distance))
	}

	if (config.rotate.x) transformations.push(matrix.rotateX(config.rotate.x))
	if (config.rotate.y) transformations.push(matrix.rotateY(config.rotate.y))
	if (config.rotate.z) transformations.push(matrix.rotateZ(config.rotate.z))
	if (config.scale !== 1) transformations.push(matrix.scale(config.scale))

	let transform
	if (transformations.length) {

		const transformProperty = getPrefixedStyleProperty('transform')
		transform = {
			computed: {
				raw: computed[transformProperty],
			},
			property: transformProperty,
		}

		/**
		* The default computed transform value should be one of:
		* undefined || 'none' || 'matrix()' || 'matrix3d()'
		*/
		if (transform.computed.raw === 'none') {
			transform.computed.matrix = matrix.identity()
		} else {
			const match = transform.computed.raw.match(/\(([^)]+)\)/)
			if (match) {
				const values = match[1].split(', ').map(value => parseFloat(value))
				transform.computed.matrix = matrix.format(values)
			} else {
				throw new RangeError('Unrecognized computed transform property value.')
			}
		}

		transformations.unshift(transform.computed.matrix)
		const product = transformations.reduce((m, x) => matrix.multiply(m, x))

		transform.generated = {
			initial: `${transform.property}: matrix3d(${product.join(', ')});`,
			final: `${transform.property}: matrix3d(${transform.computed.matrix.join(', ')});`,
		}
	}

	/**
	 * Generate transition styles
	 */
	let transition
	if (opacity.generated || transform.generated) {

		const transitionProperty = getPrefixedStyleProperty('transition')
		transition = {
			computed: computed[transitionProperty],
			fragments: [],
			property: transitionProperty,
		}

		const { delay, duration, easing } = config

		if (opacity.generated) {
			transition.fragments.push({
				delayed: `opacity ${duration / 1000}s ${easing} ${delay / 1000}s`,
				instant: `opacity ${duration / 1000}s ${easing} 0s`,
			})
		}

		if (transform.generated) {
			transition.fragments.push({
				delayed: `${transform.property} ${duration / 1000}s ${easing} ${delay / 1000}s`,
				instant: `${transform.property} ${duration / 1000}s ${easing} 0s`,
			})
		}

		/**
		 * The default computed transition property should be one of:
		 * undefined || '' || 'all 0s ease 0s' || 'all 0s 0s cubic-bezier()'
		 */
		if (transition.computed && !transition.computed.match(/all 0s/)) {
			transition.fragments.unshift({
				delayed: transition.computed,
				instant: transition.computed,
			})
		}

		const composed = transition.fragments.reduce((composition, fragment, i) => {
			composition.delayed += (i === 0) ? fragment.delayed : `, ${fragment.delayed}`
			composition.instant += (i === 0) ? fragment.instant : `, ${fragment.instant}`
			return composition
		}, {
			delayed: '',
			instant: '',
		})

		transition.generated = {
			delayed: `${transition.property}: ${composed.delayed};`,
			instant: `${transition.property}: ${composed.instant};`,
		}
	}

	return {
		inline,
		opacity,
		position,
		transform,
		transition,
	}
}
<commit_msg>return empty string instead of undefined for skipped styles<commit_after>import * as matrix from 'redpill'
import { getPrefixedStyleProperty } from '../../utils/browser'

export default function style (element) {
	const computed = window.getComputedStyle(element.node)
	const position = computed.position
	const config = element.config

	/**
	 * Generate inline styles
	 */
	const inlineRegex = /.+[^;]/g
	const inlineStyle = element.node.getAttribute('style') || ''
	const inlineMatch = inlineRegex.exec(inlineStyle)

	let inline = (inlineMatch) ? `${inlineMatch[0]};` : ''
	if (inline.indexOf('visibility: visible') === -1) {
		inline += (inline.length) ? ' ' : ''
		inline += 'visibility: visible;'
	}

	/**
	 * Generate opacity styles
	 */
	const computedOpacity = parseFloat(computed.opacity)
	const configOpacity = !isNaN(parseFloat(config.opacity))
		? parseFloat(config.opacity)
		: parseFloat(computed.opacity)

	const opacity = {
		computed: (computedOpacity !== configOpacity) ? `opacity: ${computedOpacity};` : '',
		generated: (computedOpacity !== configOpacity) ? `opacity: ${configOpacity};` : '',
	}

	/**
	 * Generate transformation styles
	 */
	const transformations = []

	if (parseFloat(config.distance)) {
		const axis = (config.origin === 'top' || config.origin === 'bottom') ? 'Y' : 'X'

		/**
		 * Let’s make sure our our pixel distances are negative for top and left.
		 * e.g. { origin: 'top', distance: '25px' } starts at `top: -25px` in CSS.
    	 */
		let distance = config.distance
		if (config.origin === 'top' || config.origin === 'left') {
			distance = /^-/.test(distance)
				? distance.substr(1)
				: `-${distance}`
		}

		const [value, unit] = distance.match(/(^-?\d+\.?\d?)|(em$|px$|\%$)/g)

		switch (unit) {
			case 'em':
				distance = parseInt(computed.fontSize) * value
				break
			case 'px':
				distance = value
				break
			case '%':
				distance = (axis === 'Y')
					? element.node.getBoundingClientRect().height * value / 100
					: element.node.getBoundingClientRect().width * value / 100
				break
			default:
				throw new RangeError('Unrecognized or missing distance unit.')
		}

		transformations.push(matrix[`translate${axis}`](distance))
	}

	if (config.rotate.x) transformations.push(matrix.rotateX(config.rotate.x))
	if (config.rotate.y) transformations.push(matrix.rotateY(config.rotate.y))
	if (config.rotate.z) transformations.push(matrix.rotateZ(config.rotate.z))
	if (config.scale !== 1) transformations.push(matrix.scale(config.scale))

	const transform = {}
	if (transformations.length) {

		const transformProperty = getPrefixedStyleProperty('transform')
		transform.property = transformProperty
		transform.computed = {
			raw: computed[transformProperty],
		}

		/**
		* The default computed transform value should be one of:
		* undefined || 'none' || 'matrix()' || 'matrix3d()'
		*/
		if (transform.computed.raw === 'none') {
			transform.computed.matrix = matrix.identity()
		} else {
			const match = transform.computed.raw.match(/\(([^)]+)\)/)
			if (match) {
				const values = match[1].split(', ').map(value => parseFloat(value))
				transform.computed.matrix = matrix.format(values)
			} else {
				throw new RangeError('Unrecognized computed transform property value.')
			}
		}

		transformations.unshift(transform.computed.matrix)
		const product = transformations.reduce((m, x) => matrix.multiply(m, x))

		transform.generated = {
			initial: `${transform.property}: matrix3d(${product.join(', ')});`,
			final: `${transform.property}: matrix3d(${transform.computed.matrix.join(', ')});`,
		}
	} else {
		transform.generated = {
			initial: '',
			final: '',
		}
	}

	/**
	 * Generate transition styles
	 */
	let transition
	if (opacity.generated || transform.generated.initial) {

		const transitionProperty = getPrefixedStyleProperty('transition')
		transition = {
			computed: computed[transitionProperty],
			fragments: [],
			property: transitionProperty,
		}

		const { delay, duration, easing } = config

		if (opacity.generated) {
			transition.fragments.push({
				delayed: `opacity ${duration / 1000}s ${easing} ${delay / 1000}s`,
				instant: `opacity ${duration / 1000}s ${easing} 0s`,
			})
		}

		if (transform.generated.initial) {
			transition.fragments.push({
				delayed: `${transform.property} ${duration / 1000}s ${easing} ${delay / 1000}s`,
				instant: `${transform.property} ${duration / 1000}s ${easing} 0s`,
			})
		}

		/**
		 * The default computed transition property should be one of:
		 * undefined || '' || 'all 0s ease 0s' || 'all 0s 0s cubic-bezier()'
		 */
		if (transition.computed && !transition.computed.match(/all 0s/)) {
			transition.fragments.unshift({
				delayed: transition.computed,
				instant: transition.computed,
			})
		}

		const composed = transition.fragments.reduce((composition, fragment, i) => {
			composition.delayed += (i === 0) ? fragment.delayed : `, ${fragment.delayed}`
			composition.instant += (i === 0) ? fragment.instant : `, ${fragment.instant}`
			return composition
		}, {
			delayed: '',
			instant: '',
		})

		transition.generated = {
			delayed: `${transition.property}: ${composed.delayed};`,
			instant: `${transition.property}: ${composed.instant};`,
		}
	}

	return {
		inline,
		opacity,
		position,
		transform,
		transition,
	}
}
<|endoftext|>


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

'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace ns
*/
var ns = {};

/**
* @name arcsine
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/arcsine}
*/
setReadOnly( ns, 'arcsine', require( '@stdlib/random/iterators/arcsine' ) );

/**
* @name bernoulli
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/bernoulli}
*/
setReadOnly( ns, 'bernoulli', require( '@stdlib/random/iterators/bernoulli' ) );

/**
* @name beta
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/beta}
*/
setReadOnly( ns, 'beta', require( '@stdlib/random/iterators/beta' ) );

/**
* @name betaprime
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/betaprime}
*/
setReadOnly( ns, 'betaprime', require( '@stdlib/random/iterators/betaprime' ) );

/**
* @name frechet
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/frechet}
*/
setReadOnly( ns, 'frechet', require( '@stdlib/random/iterators/frechet' ) );

/**
* @name gamma
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/gamma}
*/
setReadOnly( ns, 'gamma', require( '@stdlib/random/iterators/gamma' ) );

/**
* @name invgamma
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/invgamma}
*/
setReadOnly( ns, 'invgamma', require( '@stdlib/random/iterators/invgamma' ) );

/**
* @name kumaraswamy
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/kumaraswamy}
*/
setReadOnly( ns, 'kumaraswamy', require( '@stdlib/random/iterators/kumaraswamy' ) );

/**
* @name uniform
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/uniform}
*/
setReadOnly( ns, 'uniform', require( '@stdlib/random/iterators/uniform' ) );

/**
* @name weibull
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/weibull}
*/
setReadOnly( ns, 'weibull', require( '@stdlib/random/iterators/weibull' ) );

// EXPORTS //

module.exports = ns;
<commit_msg>Add normal iterator to namespace<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace ns
*/
var ns = {};

/**
* @name arcsine
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/arcsine}
*/
setReadOnly( ns, 'arcsine', require( '@stdlib/random/iterators/arcsine' ) );

/**
* @name bernoulli
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/bernoulli}
*/
setReadOnly( ns, 'bernoulli', require( '@stdlib/random/iterators/bernoulli' ) );

/**
* @name beta
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/beta}
*/
setReadOnly( ns, 'beta', require( '@stdlib/random/iterators/beta' ) );

/**
* @name betaprime
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/betaprime}
*/
setReadOnly( ns, 'betaprime', require( '@stdlib/random/iterators/betaprime' ) );

/**
* @name frechet
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/frechet}
*/
setReadOnly( ns, 'frechet', require( '@stdlib/random/iterators/frechet' ) );

/**
* @name gamma
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/gamma}
*/
setReadOnly( ns, 'gamma', require( '@stdlib/random/iterators/gamma' ) );

/**
* @name invgamma
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/invgamma}
*/
setReadOnly( ns, 'invgamma', require( '@stdlib/random/iterators/invgamma' ) );

/**
* @name kumaraswamy
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/kumaraswamy}
*/
setReadOnly( ns, 'kumaraswamy', require( '@stdlib/random/iterators/kumaraswamy' ) );

/**
* @name normal
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/normal}
*/
setReadOnly( ns, 'normal', require( '@stdlib/random/iterators/normal' ) );

/**
* @name uniform
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/uniform}
*/
setReadOnly( ns, 'uniform', require( '@stdlib/random/iterators/uniform' ) );

/**
* @name weibull
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/iterators/weibull}
*/
setReadOnly( ns, 'weibull', require( '@stdlib/random/iterators/weibull' ) );

// EXPORTS //

module.exports = ns;
<|endoftext|>


<commit_before>require('basis.utils.info');
require('basis.ui');

function runInContext(contextWindow, code){
  (contextWindow.execScript || function(code){
    contextWindow['eval'].call(contextWindow, code);
  })(code);
}

var FrameEnv = basis.ui.Node.subclass({
  applyEnvironment: null,
  initEnv: null,
  html: null,

  postInit: function(){
    basis.ui.Node.prototype.postInit.call(this);
    basis.doc.body.add(this.element);
    //console.log('env created');
  },

  template:
    '<iframe src="{src}"' +
      ' event-load="ready"' +
      ' style="width: 10px; height: 10px; top: -100px; position: absolute; border: none; opacity: 0.0001"/>',
  binding: {
    src: function(node){
      if (node.html && node.html != 'default')
        return node.html;

      // default env
      return basis.path.resolve((require('core.env').baseURI || ''), basis.asset(__dirname + 'iframe.html'));
    }
  },
  action: {
    ready: function(){
      var frameWindow = this.element.contentWindow;
      var initCode = '';

      var code = require('./iframe_inject.code');

      if (typeof code == 'function')
        code = basis.utils.info.fn(code).body;

      runInContext(frameWindow, code);

      if (typeof this.initEnv == 'function')
        initCode = basis.utils.info.fn(this.initEnv).body;

      this.applyEnvironment = frameWindow.__initTestEnvironment(initCode, function(){
        // env deprecates
        this.destroy();
      }.bind(this));

      if (this.runArgs)
      {
        this.run.apply(this, this.runArgs);
        this.runArgs = null;
      }
    }
  },

  run: function(code, context, runTest){
    if (this.applyEnvironment)
      runTest.call(context, this.applyEnvironment(code));
    else
      this.runArgs = arguments;
  },

  destroy: function(){
    basis.ui.Node.prototype.destroy.call(this);
    this.applyEnvironment = null;
    this.runArgs = null;
    //console.log('env destroyed');
  }
});

module.exports = FrameEnv;
<commit_msg>fix iframe inject code build issue<commit_after>require('basis.utils.info');
require('basis.ui');

function runInContext(contextWindow, code){
  (contextWindow.execScript || function(code){
    contextWindow['eval'].call(contextWindow, code);
  })(code);
}

var FrameEnv = basis.ui.Node.subclass({
  applyEnvironment: null,
  initEnv: null,
  html: null,

  postInit: function(){
    basis.ui.Node.prototype.postInit.call(this);
    basis.doc.body.add(this.element);
    //console.log('env created');
  },

  template:
    '<iframe src="{src}"' +
      ' event-load="ready"' +
      ' style="width: 10px; height: 10px; top: -100px; position: absolute; border: none; opacity: 0.0001"/>',
  binding: {
    src: function(node){
      if (node.html && node.html != 'default')
        return node.html;

      // default env
      return basis.path.resolve((require('core.env').baseURI || ''), basis.asset(__dirname + 'iframe.html'));
    }
  },
  action: {
    ready: function(){
      var frameWindow = this.element.contentWindow;
      var initCode = '';

      // NOTE: to not use require here, because builder replace url for [number].code
      // and basis.require wrogly theats it as namespace
      var code = resource('./iframe_inject.code').fetch();

      if (typeof code == 'function')
        code = basis.utils.info.fn(code).body;

      runInContext(frameWindow, code);

      if (typeof this.initEnv == 'function')
        initCode = basis.utils.info.fn(this.initEnv).body;

      this.applyEnvironment = frameWindow.__initTestEnvironment(initCode, function(){
        // env deprecates
        this.destroy();
      }.bind(this));

      if (this.runArgs)
      {
        this.run.apply(this, this.runArgs);
        this.runArgs = null;
      }
    }
  },

  run: function(code, context, runTest){
    if (this.applyEnvironment)
      runTest.call(context, this.applyEnvironment(code));
    else
      this.runArgs = arguments;
  },

  destroy: function(){
    basis.ui.Node.prototype.destroy.call(this);
    this.applyEnvironment = null;
    this.runArgs = null;
    //console.log('env destroyed');
  }
});

module.exports = FrameEnv;
<|endoftext|>


<commit_before>'use strict';

/**
* Test if a value is an anagram.
*
* @module @stdlib/utils/is-anagram
*
* @example
* var isAnagram = require( '@stdlib/utils/is-anagram' );
*
* var bool = isAnagram( 'I am a weakish speller', 'William Shakespeare' );
* // returns true
*
* bool = isAnagram( 'bat', 'tabba' );
* // returns false
*/

// MODULES //

var isAnagram = require( './is_anagram' );

// EXPORTS //

module.exports = isAnagram;
<commit_msg>Add missing filename extension to require path<commit_after>'use strict';

/**
* Test if a value is an anagram.
*
* @module @stdlib/utils/is-anagram
*
* @example
* var isAnagram = require( '@stdlib/utils/is-anagram' );
*
* var bool = isAnagram( 'I am a weakish speller', 'William Shakespeare' );
* // returns true
*
* bool = isAnagram( 'bat', 'tabba' );
* // returns false
*/

// MODULES //

var isAnagram = require( './is_anagram.js' );

// EXPORTS //

module.exports = isAnagram;
<|endoftext|>


<commit_before>'use strict';

class ProviderDeployFunction {
  constructor(serverless, options) {
    // console.log( 'Here', serverless );
    this.serverless = serverless;
    this.options = options;
    this.aws = this.serverless.getProvider('aws');
    this.function = serverless.service.functions[ this.options.f ];
    // console.log( this.options, this.function );
    this.runtime = this.serverless.service.provider.runtime;

    // set the providers name here
    this.provider = 'aws';

    this.commands = {
      deploy: {
        commands: {
          function: {
            lifecycleEvents: [
              'deploy'
            ]
          },
        }
      },
    };
    this.hooks = {
      'before:deploy:function:deploy': this.beforeDeployFunction.bind(this)
    };

  }

  beforeDeployFunction() {

    let params = {
      FunctionName: this.options.function,
    };

    this.provider.request( 'Lambda', 'getFunction', params, this.options.stage, this.serverless.service.provider.region )
    .catch( () => {
      params = {
        Code: {
          ZipFile: this.function.handler + ' = function() {}'
        },
        FunctionName: this.options.function,
        Handler: this.function.handler,
        Role: this.serverless.service.custom.IamRoleArnForCreate,
        Runtime: this.runtime
      };
      return this.aws.request('Lambda', 'createFunction', params, this.options.stage, this.serverless.service.provider.region)
      .then( (output) => console.log );
    });
  }
}

module.exports = ProviderDeployFunction;<commit_msg>provider->aws<commit_after>'use strict';

class ProviderDeployFunction {
  constructor(serverless, options) {
    // console.log( 'Here', serverless );
    this.serverless = serverless;
    this.options = options;
    this.aws = this.serverless.getProvider('aws');
    this.function = serverless.service.functions[ this.options.f ];
    // console.log( this.options, this.function );
    this.runtime = this.serverless.service.provider.runtime;

    // set the providers name here
    this.provider = 'aws';

    this.commands = {
      deploy: {
        commands: {
          function: {
            lifecycleEvents: [
              'deploy'
            ]
          },
        }
      },
    };
    this.hooks = {
      'before:deploy:function:deploy': this.beforeDeployFunction.bind(this)
    };

  }

  beforeDeployFunction() {

    let params = {
      FunctionName: this.options.function,
    };

    this.aws.request( 'Lambda', 'getFunction', params, this.options.stage, this.serverless.service.provider.region )
    .catch( () => {
      params = {
        Code: {
          ZipFile: this.function.handler + ' = function() {}'
        },
        FunctionName: this.options.function,
        Handler: this.function.handler,
        Role: this.serverless.service.custom.IamRoleArnForCreate,
        Runtime: this.runtime
      };
      return this.aws.request('Lambda', 'createFunction', params, this.options.stage, this.serverless.service.provider.region)
      .then( (output) => console.log );
    });
  }
}

module.exports = ProviderDeployFunction;<|endoftext|>


<commit_before>import 'babel-polyfill';
import aws from 'aws-sdk';
import λ from 'apex.js'
import moment from 'moment';
import Bluebird from 'bluebird';
import axios from 'axios';

//update global promise implementation
global.Promise = Bluebird;

const region = new aws.Config().region;

const ec2 = new aws.EC2({apiVersion: '2014-10-01'});
Bluebird.promisifyAll(Object.getPrototypeOf(ec2));

const defaultTimeToLive = moment.duration(4, 'hours');
const tagPrefix = "ua";
const requiredTags = {
  "environment": /^(production|staging|development|integration)$/,
  "product": /^(b2c|b2b)$/,
  "role": /^.+$/,
  "team": /^.+$/
}

function tagKey(tag) {
  return `${tagPrefix}:${tag}`;
}

function instanceTagMap(instance) {
  return instance.Tags.reduce((map, tag) => {
    map.set(tag.Key, tag.Value);
    return map;
  }, new Map());
}

function validateTagMap(tagMap) {
  const messages = []

  // Check all required tags for existence and pattern match
  for(let [key, pattern] of Object.entries(requiredTags)) {
    key = tagKey(key);

    if(!tagMap.has(key)) {
      messages.push(`missing tag *${key}*`);
    }
    else if(!pattern.test(tagMap.get(key))) {
      messages.push(`malformed tag *${key}* _${pattern}_`);
    }
  }

  return messages;
}

function slackInstance(instance) {
  const tagMap = instanceTagMap(instance);
  const name = tagMap.get('Name');

  return ;
}

export default λ((e, ctx) => {
  //context.succeed(Object result);
  //context.fail(Error error);
  //context.done(Error error, Object result);
  //context.getRemainingTimeInMillis();
  //context.functionName
  //context.functionVersion
  //context.invokedFunctionArn
  //context.memoryLimitInMB
  //context.awsRequestId
  //context.logGroupName
  //context.logStreamname
  //context.identity (Object)
  //context.clientContext (Object)

  const SLACK_WEBHOOK_URL = process.env.SLACK_WEBHOOK_URL;

  if(SLACK_WEBHOOK_URL == null) {
    throw new Error('SLACK_WEBHOOK_URL not set.');
  }

  return ec2.describeInstancesAsync({
    Filters: [
      { Name: 'instance-state-name', Values: ['running'] }
    ]
  })
    .get('Reservations')
    .reduce((acc, res) => acc.concat(res.Instances), [])
    .map(instance => {
      const tagMap = instanceTagMap(instance);
      const errors = validateTagMap(tagMap);
      const warnings = [];

      let stop = true;

      // Check TTL
      if(tagMap.has(tagKey('permanent'))) {
        stop = false;
      }
      else if(tagMap.has(tagKey('ttl-hours'))) {
        const value = parseFloat(tagMap.get(tagKey('ttl-hours')));

        if(Number.isNaN(value)) {
          errors.push(`'${value}' is an invalid TTL.`);
        }
        else {
          const ttl = moment.duration(tagMap.get(tagKey('ttl-hours')), 'hours');
          const upTime = new Date().getTime() - instance.LaunchTime.getTime();

          if (upTime < ttl.asMilliseconds()) {
            ttl.subtract(uptime);
            warnings.push(`${ttl.humanize()} remaining on TTL.`)
            stop = false;
          }
        }
      }
      else {
        errors.push(`no TTL.`);
      }

      return { id: instance.InstanceId, instance, warnings, errors, stop };
    })
    .then(instances => {
      const attachments = [];

      instances.forEach(({ id, instance, warnings, errors, stop }) => {
        const name = instanceTagMap(instance).get('Name');
        const title = `Instance ${id}` + (name ? ` (${name})` : '');
        const title_link = `https://console.aws.amazon.com/ec2/v2/home?region=${region}#Instances:instanceId=${id};sort=instanceState`;
        const mrkdwn_in = ['pretext', 'text'];

        if(warnings.length > 0) {
          let text = warnings.join('\n');

          attachments.push({
            title,
            title_link,
            mrkdwn_in,
            fallback: text,
            text,
            color: 'warning',
          });
        }

        if(errors.length > 0) {
          let text = errors.join('\n');

          attachments.push({
            title,
            title_link,
            mrkdwn_in,
            fallback: text,
            text,
            color: 'danger',
          });
        }

        // #TODO: handle instance stopping
        /*
        if(stop) {
          attachments.push({
            title,
            title_link,
            text: `Stopping Instance (TTL exhausted or absent)`,
            color: 'danger',
          });
        }
        */
      });

      return axios
        .post(SLACK_WEBHOOK_URL, { mrkdwn: true, text: `Successfully reviewed tags of all running instances in *${region}*.`, attachments });
    })
    .then(() => console.log('Successfully reviewd tags of all instances.'));
});
<commit_msg>Add shared option for product<commit_after>import 'babel-polyfill';
import aws from 'aws-sdk';
import λ from 'apex.js'
import moment from 'moment';
import Bluebird from 'bluebird';
import axios from 'axios';

//update global promise implementation
global.Promise = Bluebird;

const region = new aws.Config().region;

const ec2 = new aws.EC2({apiVersion: '2014-10-01'});
Bluebird.promisifyAll(Object.getPrototypeOf(ec2));

const defaultTimeToLive = moment.duration(4, 'hours');
const tagPrefix = "ua";
const requiredTags = {
  "environment": /^(production|staging|development|integration)$/,
  "product": /^(b2c|b2b|shared)$/,
  "role": /^.+$/,
  "team": /^.+$/
}

function tagKey(tag) {
  return `${tagPrefix}:${tag}`;
}

function instanceTagMap(instance) {
  return instance.Tags.reduce((map, tag) => {
    map.set(tag.Key, tag.Value);
    return map;
  }, new Map());
}

function validateTagMap(tagMap) {
  const messages = []

  // Check all required tags for existence and pattern match
  for(let [key, pattern] of Object.entries(requiredTags)) {
    key = tagKey(key);

    if(!tagMap.has(key)) {
      messages.push(`missing tag *${key}*`);
    }
    else if(!pattern.test(tagMap.get(key))) {
      messages.push(`malformed tag *${key}* _${pattern}_`);
    }
  }

  return messages;
}

function slackInstance(instance) {
  const tagMap = instanceTagMap(instance);
  const name = tagMap.get('Name');

  return ;
}

export default λ((e, ctx) => {
  //context.succeed(Object result);
  //context.fail(Error error);
  //context.done(Error error, Object result);
  //context.getRemainingTimeInMillis();
  //context.functionName
  //context.functionVersion
  //context.invokedFunctionArn
  //context.memoryLimitInMB
  //context.awsRequestId
  //context.logGroupName
  //context.logStreamname
  //context.identity (Object)
  //context.clientContext (Object)

  const SLACK_WEBHOOK_URL = process.env.SLACK_WEBHOOK_URL;

  if(SLACK_WEBHOOK_URL == null) {
    throw new Error('SLACK_WEBHOOK_URL not set.');
  }

  return ec2.describeInstancesAsync({
    Filters: [
      { Name: 'instance-state-name', Values: ['running'] }
    ]
  })
    .get('Reservations')
    .reduce((acc, res) => acc.concat(res.Instances), [])
    .map(instance => {
      const tagMap = instanceTagMap(instance);
      const errors = validateTagMap(tagMap);
      const warnings = [];

      let stop = true;

      // Check TTL
      if(tagMap.has(tagKey('permanent'))) {
        stop = false;
      }
      else if(tagMap.has(tagKey('ttl-hours'))) {
        const value = parseFloat(tagMap.get(tagKey('ttl-hours')));

        if(Number.isNaN(value)) {
          errors.push(`'${value}' is an invalid TTL.`);
        }
        else {
          const ttl = moment.duration(tagMap.get(tagKey('ttl-hours')), 'hours');
          const upTime = new Date().getTime() - instance.LaunchTime.getTime();

          if (upTime < ttl.asMilliseconds()) {
            ttl.subtract(uptime);
            warnings.push(`${ttl.humanize()} remaining on TTL.`)
            stop = false;
          }
        }
      }
      else {
        errors.push(`no TTL.`);
      }

      return { id: instance.InstanceId, instance, warnings, errors, stop };
    })
    .then(instances => {
      const attachments = [];

      instances.forEach(({ id, instance, warnings, errors, stop }) => {
        const name = instanceTagMap(instance).get('Name');
        const title = `Instance ${id}` + (name ? ` (${name})` : '');
        const title_link = `https://console.aws.amazon.com/ec2/v2/home?region=${region}#Instances:instanceId=${id};sort=instanceState`;
        const mrkdwn_in = ['pretext', 'text'];

        if(warnings.length > 0) {
          let text = warnings.join('\n');

          attachments.push({
            title,
            title_link,
            mrkdwn_in,
            fallback: text,
            text,
            color: 'warning',
          });
        }

        if(errors.length > 0) {
          let text = errors.join('\n');

          attachments.push({
            title,
            title_link,
            mrkdwn_in,
            fallback: text,
            text,
            color: 'danger',
          });
        }

        // #TODO: handle instance stopping
        /*
        if(stop) {
          attachments.push({
            title,
            title_link,
            text: `Stopping Instance (TTL exhausted or absent)`,
            color: 'danger',
          });
        }
        */
      });

      return axios
        .post(SLACK_WEBHOOK_URL, { mrkdwn: true, text: `Successfully reviewed tags of all running instances in *${region}*.`, attachments });
    })
    .then(() => console.log('Successfully reviewd tags of all instances.'));
});
<|endoftext|>


<commit_before>var unirest = require('unirest');
var Settings = require('../helper/Settings');

var XFR_ESTIMATING_MIN_SPEED = 20 * 1024; // n bytes/sec
var XFR_ESTIMATING_MIN_TIME = 20; // secs
var XFR_CONNECTION_TIMEOUT = 10; // secs
var XFR_PROXY = "http://proxy.hinet.net:80";

var PCS_HOSTNAME = "pcs.baidu.com";
var PCS_HOSTNAME_D = "pcs.baidu.com"; // "d.pcs.baidu.com";
var PCS_HOSTNAME_C = "c.pcs.baidu.com";
var PCSURI = "/rest/2.0/pcs";
var UD_ROOTPATH = "/apps/APP_ROOT"

var pcs = {};

pcs.init = function (){
  this.USERTOKEN = Settings.get('baidu_pcs_token');
};

pcs._trimRootPath = function (fileMeta){
	if(fileMeta.list){
		for(var i in fileMeta.list){
			var path = fileMeta.list[i].path;
			var mtime = fileMeta.list[i].mtime;
			var ctime = fileMeta.list[i].ctime;
			if( 0 === path.indexOf(UD_ROOTPATH) ){
				fileMeta.list[i].path = path.replace(UD_ROOTPATH, "");
			}
			fileMeta.list[i].mtime = mtime * 1000;
			fileMeta.list[i].ctime = ctime * 1000;
		}
	}
	return fileMeta;
}

pcs._generatePath = function (options){
	var path = "";
	path += PCSURI + "/" + encodeURIComponent(options.cmd);
	path += "?access_token=" + encodeURIComponent(this.USERTOKEN);

	if( options.method ) path += "&method=" + encodeURIComponent(options.method);
	if( options.path ) path += "&path=" + encodeURIComponent(options.path);
	if( options.param ) path += "&param=" + encodeURIComponent(options.param);

	return path;
}

pcs._execute = function (options, cb){
	var link = "https://" + PCS_HOSTNAME + this._generatePath(options);
	unirest.get(link)
	.proxy(XFR_PROXY)
	.timeout(XFR_CONNECTION_TIMEOUT * 1000)
	.end(function (httpResponse) {
		var errorOutput = null;
		var response = {
			queryPara: options,
			uri: link,
			data: null
		};
		if(httpResponse.serverError){
			errorOutput = httpResponse.body;
			console.log({
				code: httpResponse.code,
				status: httpResponse.status,
				statusType: httpResponse.statusType
			});
		}else{
			try {
				var responseJson = JSON.parse(httpResponse.body);
				if ( responseJson.error_code && responseJson.error_code !== 31066 ) { // file does not exist
					//{ error_code: 31326, error_msg: 'anti hotlinking' }
					errorOutput = responseJson;
					console.log(errorOutput);
				} else {
					response.data = pcs._trimRootPath(responseJson);
				}
			} catch (e) {
				errorOutput = httpResponse.body;
			}
		}
		cb(errorOutput, response);
	});
}

pcs._download = function (options, cb){
	var link = "https://" + PCS_HOSTNAME_D + this._generatePath(options);
	var estimationTime = (options.size / XFR_ESTIMATING_MIN_SPEED);
	unirest.get(link)
	.proxy(XFR_PROXY)
	.timeout(XFR_CONNECTION_TIMEOUT * 1000)
	.encoding(null)
	.headers({
		'Range': 'bytes=' + options.offset + '-' + ( options.offset + options.size - 1 )
	})
	.end(function (httpResponse){
		var errorOutput = null;
		var response = {
			queryPara: options,
			uri: link,
			data: null
		};
		if(httpResponse.serverError){
			errorOutput = {
				code: httpResponse.code,
				status: httpResponse.status,
				statusType: httpResponse.statusType
			};
		}else{
			response.data = httpResponse.raw_body;
			response.length = httpResponse.raw_body.length;
		}
		cb(errorOutput, response);
	});
}

pcs.quota = function (cb){
	this._execute({
		cmd: "quota",
		method: "info",
		httpMethod: "GET"
	}, cb);
}

pcs.getFileMeta = function (path, cb){
	this._execute({
		cmd: "file",
		method: "meta",
		httpMethod: "GET",
		path: UD_ROOTPATH + path
	}, cb);
}

pcs.getFileMetaBatch = function (param, cb){
	for(var i = 0; i < param.list.length; i++){
		param.list[i].path = UD_ROOTPATH + param.list[i].path;
	}
	this._execute({
		cmd: "file",
		method: "meta",
		httpMethod: "GET",
		param: ( typeof(param) === 'string' ? param : JSON.stringify(param) )
	}, function (errorOutput, response) {
		if( response && response.data ){
			for(var i = 0; i < response.data.list.length; i++){
				response.data.list[i] =  pcs._trimRootPath(response.data.list[i]);
			}
		}
		cb(errorOutput, response);
	});
}

pcs.getFileDownload = function (path, offset, size, cb){
	this._download({
		cmd: "file",
		method: "download",
		httpMethod: "GET",
		offset: offset,
		size: size,
		path: UD_ROOTPATH + path
	}, cb);
}

pcs.getFileList = function (path, cb){
	this._execute({
		cmd: "file",
		method: "list",
		httpMethod: "GET",
		path: UD_ROOTPATH + path
	}, cb);
}

pcs.getFileListRecycle = function (cb){
	this._execute({
		cmd: "file",
		method: "listrecycle"
	}, cb);
}

pcs._tokenRequest = function (link, cb){
	unirest.get(link)
	.header('Accept', 'application/json')
	.proxy(XFR_PROXY)
	.timeout(XFR_CONNECTION_TIMEOUT * 1000)
	.end(function (httpResponse) {
		var errorOutput = null;
		var response = {
			data: null
		};
		if (httpResponse.serverError) {
			errorOutput = httpResponse.body;
			console.log({
				code: httpResponse.code,
				status: httpResponse.status,
				statusType: httpResponse.statusType
			});
		} else {
			response.data = httpResponse.body;
		}
		cb(errorOutput, response);
	});
};

pcs.getAccessToken = function (api_key, api_secret, cb){
	var self = this;
	var device_code = null;
	var interval = 10;

	function request1st (){
		var link = 'https://openapi.baidu.com/oauth/2.0/device/code?' +
			'client_id=' + api_key + '&' +
			'response_type=device_code&scope=basic,netdisk';
		self._tokenRequest(link, request2nd);
	}

	function request2nd (error, response){
		var msg = response ? response.data : {};
		if (msg.verification_url && msg.user_code) {
			console.log(msg.verification_url);
			console.log(msg.user_code);
		}
		if (msg.interval) {
			interval = msg.interval;
		}
		if (msg.device_code) {
			device_code = msg.device_code;
		}
		var link = 'https://openapi.baidu.com/oauth/2.0/token?' +
			'grant_type=device_token&' +
			'code=' + device_code + '&' +
			'client_id=' + api_key + '&' +
			'client_secret=' + api_secret;

		self._tokenRequest(link, requestEnd);
	}

	function requestEnd (error, response){
		if(response.data.error === 'authorization_pending'){
			console.log('waiting for verification...');
			setTimeout(request2nd, interval * 1000);
		} else if (response.data.access_token){
			cb(error, {
				data: {access_token: response.data.access_token}
			});
		} else {
			cb({error_msg: 'Unknown Error'}, {data: null});
		}
	}

	request1st();
};

module.exports = pcs;
<commit_msg>Workaround solution for pcs and unirest.<commit_after>var unirest = require('unirest');
var Settings = require('../helper/Settings');

var XFR_ESTIMATING_MIN_SPEED = 20 * 1024; // n bytes/sec
var XFR_ESTIMATING_MIN_TIME = 20; // secs
var XFR_CONNECTION_TIMEOUT = 10; // secs
var XFR_PROXY = "http://proxy.hinet.net:80";

var PCS_HOSTNAME = "pcs.baidu.com";
var PCS_HOSTNAME_D = "pcs.baidu.com"; // "d.pcs.baidu.com";
var PCS_HOSTNAME_C = "c.pcs.baidu.com";
var PCSURI = "/rest/2.0/pcs";
var UD_ROOTPATH = "/apps/APP_ROOT"

var pcs = {};

pcs.init = function (){
  this.USERTOKEN = Settings.get('baidu_pcs_token');
};

pcs._trimRootPath = function (fileMeta){
	if(fileMeta.list){
		for(var i in fileMeta.list){
			var path = fileMeta.list[i].path;
			var mtime = fileMeta.list[i].mtime;
			var ctime = fileMeta.list[i].ctime;
			if( 0 === path.indexOf(UD_ROOTPATH) ){
				fileMeta.list[i].path = path.replace(UD_ROOTPATH, "");
			}
			fileMeta.list[i].mtime = mtime * 1000;
			fileMeta.list[i].ctime = ctime * 1000;
		}
	}
	return fileMeta;
}

pcs._generatePath = function (options){
	var path = "";
	path += PCSURI + "/" + encodeURIComponent(options.cmd);
	path += "?access_token=" + encodeURIComponent(this.USERTOKEN);

	if( options.method ) path += "&method=" + encodeURIComponent(options.method);
	if( options.path ) path += "&path=" + encodeURIComponent(options.path);
	if( options.param ) path += "&param=" + encodeURIComponent(options.param);

	return path;
}

pcs._execute = function (options, cb){
	var link = "https://" + PCS_HOSTNAME + this._generatePath(options);
	unirest.get(link)
	.proxy(XFR_PROXY)
	.timeout(XFR_CONNECTION_TIMEOUT * 1000)
	.end(function (httpResponse) {
		var errorOutput = null;
		var response = {
			queryPara: options,
			uri: link,
			data: null
		};
		if(httpResponse.serverError){
			errorOutput = httpResponse.body;
			console.log({
				code: httpResponse.code,
				status: httpResponse.status,
				statusType: httpResponse.statusType
			});
		}else{
			try {
				var responseJson = JSON.parse(httpResponse.body);
				if ( responseJson.error_code && responseJson.error_code !== 31066 ) { // file does not exist
					//{ error_code: 31326, error_msg: 'anti hotlinking' }
					errorOutput = responseJson;
					console.log(errorOutput);
				} else {
					response.data = pcs._trimRootPath(responseJson);
				}
			} catch (e) {
				errorOutput = httpResponse.body;
			}
		}
		cb(errorOutput, response);
	});
}

pcs._download = function (options, cb){
	var link = "https://" + PCS_HOSTNAME_D + this._generatePath(options);
	var estimationTime = (options.size / XFR_ESTIMATING_MIN_SPEED);
	unirest.get(link)
	.proxy(XFR_PROXY)
	.timeout(XFR_CONNECTION_TIMEOUT * 1000)
	.encoding(null)
	.headers({
		'Range': 'bytes=' + options.offset + '-' + ( options.offset + options.size - 1 )
	})
	.end(function (httpResponse){
		var errorOutput = null;
		var response = {
			queryPara: options,
			uri: link,
			data: null
		};
		if(httpResponse.serverError){
			errorOutput = {
				code: httpResponse.code,
				status: httpResponse.status,
				statusType: httpResponse.statusType
			};
		}else{
			try {
				// XXX: this is a workaround for unstable issue.
				response.data = httpResponse.raw_body;
				response.length = httpResponse.raw_body.length;
			} catch (e) {
				console.log(e)
				errorOutput = httpResponse.body;
			}
		}
		cb(errorOutput, response);
	});
}

pcs.quota = function (cb){
	this._execute({
		cmd: "quota",
		method: "info",
		httpMethod: "GET"
	}, cb);
}

pcs.getFileMeta = function (path, cb){
	this._execute({
		cmd: "file",
		method: "meta",
		httpMethod: "GET",
		path: UD_ROOTPATH + path
	}, cb);
}

pcs.getFileMetaBatch = function (param, cb){
	for(var i = 0; i < param.list.length; i++){
		param.list[i].path = UD_ROOTPATH + param.list[i].path;
	}
	this._execute({
		cmd: "file",
		method: "meta",
		httpMethod: "GET",
		param: ( typeof(param) === 'string' ? param : JSON.stringify(param) )
	}, function (errorOutput, response) {
		if( response && response.data ){
			for(var i = 0; i < response.data.list.length; i++){
				response.data.list[i] =  pcs._trimRootPath(response.data.list[i]);
			}
		}
		cb(errorOutput, response);
	});
}

pcs.getFileDownload = function (path, offset, size, cb){
	this._download({
		cmd: "file",
		method: "download",
		httpMethod: "GET",
		offset: offset,
		size: size,
		path: UD_ROOTPATH + path
	}, cb);
}

pcs.getFileList = function (path, cb){
	this._execute({
		cmd: "file",
		method: "list",
		httpMethod: "GET",
		path: UD_ROOTPATH + path
	}, cb);
}

pcs.getFileListRecycle = function (cb){
	this._execute({
		cmd: "file",
		method: "listrecycle"
	}, cb);
}

pcs._tokenRequest = function (link, cb){
	unirest.get(link)
	.header('Accept', 'application/json')
	.proxy(XFR_PROXY)
	.timeout(XFR_CONNECTION_TIMEOUT * 1000)
	.end(function (httpResponse) {
		var errorOutput = null;
		var response = {
			data: null
		};
		if (httpResponse.serverError) {
			errorOutput = httpResponse.body;
			console.log({
				code: httpResponse.code,
				status: httpResponse.status,
				statusType: httpResponse.statusType
			});
		} else {
			response.data = httpResponse.body;
		}
		cb(errorOutput, response);
	});
};

pcs.getAccessToken = function (api_key, api_secret, cb){
	var self = this;
	var device_code = null;
	var interval = 10;

	function request1st (){
		var link = 'https://openapi.baidu.com/oauth/2.0/device/code?' +
			'client_id=' + api_key + '&' +
			'response_type=device_code&scope=basic,netdisk';
		self._tokenRequest(link, request2nd);
	}

	function request2nd (error, response){
		var msg = response ? response.data : {};
		if (msg.verification_url && msg.user_code) {
			console.log(msg.verification_url);
			console.log(msg.user_code);
		}
		if (msg.interval) {
			interval = msg.interval;
		}
		if (msg.device_code) {
			device_code = msg.device_code;
		}
		var link = 'https://openapi.baidu.com/oauth/2.0/token?' +
			'grant_type=device_token&' +
			'code=' + device_code + '&' +
			'client_id=' + api_key + '&' +
			'client_secret=' + api_secret;

		self._tokenRequest(link, requestEnd);
	}

	function requestEnd (error, response){
		if(response.data.error === 'authorization_pending'){
			console.log('waiting for verification...');
			setTimeout(request2nd, interval * 1000);
		} else if (response.data.access_token){
			cb(error, {
				data: {access_token: response.data.access_token}
			});
		} else {
			cb({error_msg: 'Unknown Error'}, {data: null});
		}
	}

	request1st();
};

module.exports = pcs;
<|endoftext|>


<commit_before>import {isMobile} from '../util/env'
/**
 * Render github corner
 * @param  {Object} data
 * @return {String}
 */
export function corner(data) {
  if (!data) {
    return ''
  }
  if (!/\/\//.test(data)) {
    data = 'https://github.com/' + data
  }
  data = data.replace(/^git\+/, '')

  return (
    `<a href="${data}" class="github-corner" aria-label="View source on Github">` +
    '<svg viewBox="0 0 250 250" aria-hidden="true">' +
    '<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>' +
    '<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>' +
    '<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path>' +
    '</svg>' +
    ''
  )
}

/**
 * Render main content
 */
export function main(config) {
  const aside =
    '<button class="sidebar-toggle">' +
    '
' +
    '' +
    '
' +
    '</button>' +
    '' +
    (config.name ?
      `
${
        config.logo ?
          `<img alt=${config.name} src=${config.logo}>` :
          config.name
      }
` :
      '') +
    '

' +
    ''

  return (
    (isMobile ? `${aside}<main>` : `<main>${aside}`) +
    '
' +
    '

' +
    '
' +
    ''
  )
}

/**
 * Cover Page
 */
export function cover() {
  const SL = ', 100%, 85%'
  const bgc =
    'linear-gradient(to left bottom, ' +
    `hsl(${Math.floor(Math.random() * 255) + SL}) 0%,` +
    `hsl(${Math.floor(Math.random() * 255) + SL}) 100%)`

  return (
    `<section class="cover show" style="background: ${bgc}">` +
    '

' +
    '

' +
    '
'
  )
}

/**
 * Render tree
 * @param  {Array} tree
 * @param  {String} tpl
 * @return {String}
 */
export function tree(toc, tpl = '
{inner}
') {
  if (!toc || !toc.length) {
    return ''
  }
  let innerHTML = ''
  toc.forEach(node => {
    innerHTML += `<li><a class="section-link" href="${node.slug}">${node.title}</a></li>`
    if (node.children) {
      innerHTML += tree(node.children, tpl)
    }
  })
  return tpl.replace('{inner}', innerHTML)
}

export function helper(className, content) {
  return `<p class="${className}">${content.slice(5).trim()}</p>`
}

export function theme(color) {
  return `<style>:root{--theme-color: ${color};}</style>`
}
<commit_msg>Buttons must have discernible text<commit_after>import {isMobile} from '../util/env'
/**
 * Render github corner
 * @param  {Object} data
 * @return {String}
 */
export function corner(data) {
  if (!data) {
    return ''
  }
  if (!/\/\//.test(data)) {
    data = 'https://github.com/' + data
  }
  data = data.replace(/^git\+/, '')

  return (
    `<a href="${data}" class="github-corner" aria-label="View source on Github">` +
    '<svg viewBox="0 0 250 250" aria-hidden="true">' +
    '<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>' +
    '<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>' +
    '<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path>' +
    '</svg>' +
    ''
  )
}

/**
 * Render main content
 */
export function main(config) {
  const aside =
    '<button class="sidebar-toggle" aria-label="Menu">' +
    '
' +
    '' +
    '
' +
    '</button>' +
    '' +
    (config.name ?
      `
${
        config.logo ?
          `<img alt=${config.name} src=${config.logo}>` :
          config.name
      }
` :
      '') +
    '

' +
    ''

  return (
    (isMobile ? `${aside}<main>` : `<main>${aside}`) +
    '
' +
    '

' +
    '
' +
    ''
  )
}

/**
 * Cover Page
 */
export function cover() {
  const SL = ', 100%, 85%'
  const bgc =
    'linear-gradient(to left bottom, ' +
    `hsl(${Math.floor(Math.random() * 255) + SL}) 0%,` +
    `hsl(${Math.floor(Math.random() * 255) + SL}) 100%)`

  return (
    `<section class="cover show" style="background: ${bgc}">` +
    '

' +
    '

' +
    '
'
  )
}

/**
 * Render tree
 * @param  {Array} tree
 * @param  {String} tpl
 * @return {String}
 */
export function tree(toc, tpl = '
{inner}
') {
  if (!toc || !toc.length) {
    return ''
  }
  let innerHTML = ''
  toc.forEach(node => {
    innerHTML += `<li><a class="section-link" href="${node.slug}">${node.title}</a></li>`
    if (node.children) {
      innerHTML += tree(node.children, tpl)
    }
  })
  return tpl.replace('{inner}', innerHTML)
}

export function helper(className, content) {
  return `<p class="${className}">${content.slice(5).trim()}</p>`
}

export function theme(color) {
  return `<style>:root{--theme-color: ${color};}</style>`
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 The Regents of the University of Michigan.
// All Rights Reserved. Licensed according to the terms of the Revised
// BSD License. See LICENSE.txt for details.

module.exports = function() {
  let fsMock = {};

  fsMock.stat = (filename, callback) => {
    callback("error");
  };

  fsMock.readdir = fsMock.stat;

  fsMock.createReadStream = () => {
    let stream = {};

    stream.on = fsMock.stat;

    return stream;
  };

  return fsMock;
};
<commit_msg>:muscle: Use events library<commit_after>// Copyright (c) 2017 The Regents of the University of Michigan.
// All Rights Reserved. Licensed according to the terms of the Revised
// BSD License. See LICENSE.txt for details.

const EventEmitter = require("events");

module.exports = function() {
  let fsMock = {};

  fsMock.stat = (filename, callback) => {
    callback("error");
  };

  fsMock.readdir = fsMock.stat;

  fsMock.createReadStream = () => {
    let stream = {};

    stream.on = fsMock.stat;

    return stream;
  };

  return fsMock;
};
<|endoftext|>