<commit_before>function Muppet(age, hobby) {
  this.age = age;
  this.hobby = hobby;

  this.answerNanny = function(){
	return "Everything's cool!";
  }
}

function SwedishChef(age, hobby, mood) {
  Muppet.call(this, age, hobby);
  this.mood = mood;

  this.cook = function() {
    return "Mmmm soup!";
  }
}

SwedishChef.prototype = new Muppet();

describe("About inheritance", function() {
  beforeEach(function(){
    this.muppet = new Muppet(2, "coding");
	this.swedishChef = new SwedishChef(2, "cooking", "chillin");
  });

  it("should be able to call a method on the derived object", function() {
    expect(this.swedishChef.cook()).toEqual(FILL_ME_IN);
  });

  it("should be able to call a method on the base object", function() {
    expect(this.swedishChef.answerNanny()).toEqual(FILL_ME_IN);
  });

  it("should set constructor parameters on the base object", function() {
    expect(this.swedishChef.age).toEqual(FILL_ME_IN);
    expect(this.swedishChef.hobby).toEqual(FILL_ME_IN);
  });

  it("should set constructor parameters on the derived object", function() {
    expect(this.swedishChef.mood).toEqual(FILL_ME_IN);
  });
});

// http://javascript.crockford.com/prototypal.html
Object.prototype.beget = function () {
  function F() {}
  F.prototype = this;
  return new F();
}

function Gonzo(age, hobby, trick) {
  Muppet.call(this, age, hobby);
  this.trick = trick;

  this.doTrick = function() {
    return this.trick;
  }
}

//no longer need to call the Muppet (base type) constructor
Gonzo.prototype = Muppet.prototype.beget();

describe("About Crockford's inheritance improvement", function() {
  beforeEach(function(){
  this.gonzo = new Gonzo(3, "daredevil performer", "eat a tire");
  });

  it("should be able to call a method on the derived object", function() {
    expect(this.gonzo.doTrick()).toEqual(FILL_ME_IN);
  });

  it("should be able to call a method on the base object", function() {
    expect(this.gonzo.answerNanny()).toEqual(FILL_ME_IN);
  });

  it("should set constructor parameters on the base object", function() {
    expect(this.gonzo.age).toEqual(FILL_ME_IN);
    expect(this.gonzo.hobby).toEqual(FILL_ME_IN);
  });

  it("should set constructor parameters on the derived object", function() {
    expect(this.gonzo.trick).toEqual(FILL_ME_IN);
  });
});
<commit_msg>32/38<commit_after>function Muppet(age, hobby) {
  this.age = age;
  this.hobby = hobby;

  this.answerNanny = function(){
	return "Everything's cool!";
  }
}

function SwedishChef(age, hobby, mood) {
  Muppet.call(this, age, hobby);
  this.mood = mood;

  this.cook = function() {
    return "Mmmm soup!";
  }
}

SwedishChef.prototype = new Muppet();

describe("About inheritance", function() {
  beforeEach(function(){
    this.muppet = new Muppet(2, "coding");
	this.swedishChef = new SwedishChef(2, "cooking", "chillin");
  });

  it("should be able to call a method on the derived object", function() {
    expect(this.swedishChef.cook()).toEqual("Mmmm soup!");
  });

  it("should be able to call a method on the base object", function() {
    expect(this.swedishChef.answerNanny()).toEqual("Everything's cool!");
  })

  it("should set constructor parameters on the base object", function() {
    expect(this.swedishChef.age).toEqual(2);
    expect(this.swedishChef.hobby).toEqual("cooking", "coding");
  });

  it("should set constructor parameters on the derived object", function() {
    expect(this.swedishChef.mood).toEqual("chillin");
  });
});

// http://javascript.crockford.com/prototypal.html
Object.prototype.beget = function () {
  function F() {}
  F.prototype = this;
  return new F();
}

function Gonzo(age, hobby, trick) {
  Muppet.call(this, age, hobby);
  this.trick = trick;

  this.doTrick = function() {
    return this.trick;
  }
}

//no longer need to call the Muppet (base type) constructor
Gonzo.prototype = Muppet.prototype.beget();

describe("About Crockford's inheritance improvement", function() {
  beforeEach(function(){
  this.gonzo = new Gonzo(3, "daredevil performer", "eat a tire");
  });

  it("should be able to call a method on the derived object", function() {
    expect(this.gonzo.doTrick()).toEqual("eat a tire");
  });

  it("should be able to call a method on the base object", function() {
    expect(this.gonzo.answerNanny()).toEqual("Everything's cool!");
  });

  it("should set constructor parameters on the base object", function() {
    expect(this.gonzo.age).toEqual(3);
    expect(this.gonzo.hobby).toEqual("daredevil performer");
  });

  it("should set constructor parameters on the derived object", function() {
    expect(this.gonzo.trick).toEqual("eat a tire");
  });
});
<|endoftext|>


<commit_before>// Dependencies
var Barbe = require("barbe")
  , Fs = require("fs")
  , Path = require("path")
  , JxUtils = require("jxutils")
  , MarkDox = require("markdox")
  , IsThere = require("is-there")
  , ReadJson = require("r-json")
  , ParentSearch = require("parent-search")
  , Streamp = require("streamp")
  ;

/*!
 * Blah
 * Creates a new `Blah` instance.
 *
 * @name Blah
 * @function
 */
function Blah(path) {
    this.path = path = path || process.cwd();
    this.pack_path = ParentSearch(this.path, "package.json", { obj: true });
    if (this.pack_path) {
        this.blah_path = Path.join(pack_path.d, ".blah");
    } else {
        this.blah_path = null;
    }
}

/**
 * getPackage
 * Returns the parsed content of package.json
 *
 * @name getPackage
 * @function
 * @return {String} content of package.json file found in the current directory
 */
Blah.prototype.getPackage = function (callback) {
    ReadJson(this.pack_path, callback);
};

Blah.prototype.init = function (callback) {
    var readme = new Streamp.Writable(Path.join(this.blah_path, "README.md"));
    Fs.createReadStream(__dirname + "/templates/README.md").pipe(readme).on("end", function () {
        callback();
    }).on("error", function (e) {
        callback(e);
    });
};

/**
 * generateDocs
 * Generate documentation file from package.json main file.
 *
 * @name generateDocs
 * @function
 * @param {String} input Input file name (default: main file from package.json)
 * @param {String} output Output file name (default: `DOCUMENTATION.md`)
 * @param {Function} callback The callback function
 */
Blah.prototype.docs = function (input, output, callback) {
    MarkDox.process(input, {
        template: __dirname + "/markdox-res/template.ejs"
      , output: output || "./DOCUMENTATION.md"
    }, callback);
};

/**
 * generateReadme
 * Returns a string representing the readme content of the project.
 *
 * @name generateReadme
 * @function
 * @param {Function} callback The callback function
 * @return {undefined}
 */
Blah.prototype.readme = function (path, callback) {

    if (typeof path === "function") {
        callback = path;
        path = process.cwd();
    }

    var self = this
      , pack = self.getPackage()
      , flattenPack = JxUtils.flattenObject(pack)
      , content = Fs.readFileSync(__dirname + "/templates/README.md").toString()
      , outputFile = "./docs-" + Math.random().toString(36) + ".md"
      ;

    this.generateDocs("", outputFile, function (err) {
        if (err) {
            return callback("Error when generating docs." + err.toString());
        }
        var mData = {};
        mData.documentation = Fs.readFileSync(outputFile);
        Fs.unlinkSync(outputFile);
        for (var k in pack) {
            mData[k] = pack[k];
        }
        content = Barbe(content, ["{{", "}}"], mData);
        callback(null, content);
    });

};

/**
 * generateGitignore
 * Returns the content of .gitignore file
 *
 * @name generateGitignore
 * @function
 * @return {String} Content of gitignore file.
 */
Blah.prototype.generateGitignore = function () {

    var content =
        "*.swp\n" +
        "*.swo\n" +
        "*~\n" +
        "*.log\n" +
        "node_modules"
      ;

    return content;
};

/**
 * generateLicense
 * Returns the content of the LICENSE by providing the `@licenseName`.
 *
 * @name generateLicense
 * @function
 * @param {String} licenseName The license name (e.g. `mit`)
 * @return {String} The content of license.
 */
Blah.prototype.generateLicense = function (licenseName) {

    var fullName = null
      , pack = require(process.env.PWD + "/package")
      ;

    try {
        var gitconfigLines = Fs.readFileSync(
            require('path-extra').homedir() + "/.gitconfig"
        ).toString().replace(/\t/g, "").split("\n");
        for (var i = 0; i < gitconfigLines.length; ++i) {
            var cLine = gitconfigLines[i].trim();
            if (/^name/.test(cLine)) {
                fullName = cLine.split("=")[1].trim();
                break;
            }
        }
    } catch(e) {
    }

    if (!fullName) {
        console.log("No fullname found in .gitconfig. Please modify LICENSE [fullname] manually");
        fullName = "[fullname]";
    }

    return Fs
        .readFileSync(__dirname + "/templates/licenses/" + licenseName.toLowerCase() + ".txt")
        .toString()
        .replace("[project]", pack.name)
        .replace("[year]", new Date().getFullYear())
        .replace("[fullname]", fullName)
        .replace("[description]", pack.description)
        ;
};

module.exports = Blah;
<commit_msg>Working on the init method. Commented experimental code<commit_after>// Dependencies
var Barbe = require("barbe")
  , Fs = require("fs")
  , Path = require("path")
  , JxUtils = require("jxutils")
  , MarkDox = require("markdox")
  , IsThere = require("is-there")
  , ReadJson = require("r-json")
  , ParentSearch = require("parent-search")
  , Streamp = require("streamp")
  , Ul = require("ul")
  , SameTime = require("same-time")
  ;

const BLAH_DIR = ".blah"
    , README_NAME = "README.md"
    , TEMPLATES = "templates"
    , PACKAGE_JSON = "package.json"
    , INDEX_JSON = "index.json"
    ;

/*!
 * Blah
 * Creates a new `Blah` instance.
 *
 * @name Blah
 * @function
 */
function Blah(options) {
    if (typeof options === "string") {
        options = {
            path: options
        };
    }

    options = Ul.merge(options, {
        path: process.cwd()
      , templates_path: Path.join(Ul.USER_DIR, BLAH_DIR)
    });

    this.path = options.path;
    if (IsThere(options.templates_path)) {
        this.templates_path = options.templates_path;
    } else {
        this.templates_path = Path.join(__dirname, TEMPLATES)
    }

    this.templates = {};
}

Blah.prototype.prepare = function (callback) {
    var self = this;
    ParentSearch(self.path, PACKAGE_JSON, { obj: true }, function (data) {
        debugger
    });
};

/**
 * getPackage
 * Returns the parsed content of package.json
 *
 * @name getPackage
 * @function
 * @return {String} content of package.json file found in the current directory
 */
Blah.prototype.getPackage = function (callback) {
    ReadJson(this.pack_path, callback);
};

Blah.prototype.init = function (options, callback) {

    if (typeof options === "function") {
        callback = options;
        options = {
        };
    }

    var self = this
      , readme = new Streamp.Writable(Path.join(self.blah_dir, README_NAME))
      , complete = 0
      , _done = false
      , errors = []
      , res = []
      ;

    function done(err, data) {
        if (_done) {
            return;
        }
        errors.push(err);
        if (--complete !== 0) {
            return;
        }
    }

    // Run the init tasks
    SameTime([
        // Prepare data
        self.prepare.bind(self)
        // Read the readme template
      , Fs.readFile.bind(self, Path.join(self.templates_path, README_NAME))
        // Read the .blah/index.json
      , ReadJson.bind(self, Path.join(self.blah_dir, INDEX_JSON))
    ], function (err, data) {
        if (err) { return callback(err); }
        self.blah_data = data[1];
        readme.on("error", callback);
        readme.on("end", callback);
        readme.end(Barbe(data[0], data[1]));
    });
};

///**
// * generateDocs
// * Generate documentation file from package.json main file.
// *
// * @name generateDocs
// * @function
// * @param {String} input Input file name (default: main file from package.json)
// * @param {String} output Output file name (default: `DOCUMENTATION.md`)
// * @param {Function} callback The callback function
// */
//Blah.prototype.docs = function (input, output, callback) {
//    MarkDox.process(input, {
//        template: __dirname + "/markdox-res/template.ejs"
//      , output: output || "./DOCUMENTATION.md"
//    }, callback);
//};
//
///**
// * generateReadme
// * Returns a string representing the readme content of the project.
// *
// * @name generateReadme
// * @function
// * @param {Function} callback The callback function
// * @return {undefined}
// */
//Blah.prototype.readme = function (path, callback) {
//
//    if (typeof path === "function") {
//        callback = path;
//        path = process.cwd();
//    }
//
//    var self = this
//      , pack = self.getPackage()
//      , flattenPack = JxUtils.flattenObject(pack)
//      , content = Fs.readFileSync(__dirname + "/templates/README.md").toString()
//      , outputFile = "./docs-" + Math.random().toString(36) + ".md"
//      ;
//
//    this.generateDocs("", outputFile, function (err) {
//        if (err) {
//            return callback("Error when generating docs." + err.toString());
//        }
//        var mData = {};
//        mData.documentation = Fs.readFileSync(outputFile);
//        Fs.unlinkSync(outputFile);
//        for (var k in pack) {
//            mData[k] = pack[k];
//        }
//        content = Barbe(content, ["{{", "}}"], mData);
//        callback(null, content);
//    });
//
//};
//
///**
// * generateGitignore
// * Returns the content of .gitignore file
// *
// * @name generateGitignore
// * @function
// * @return {String} Content of gitignore file.
// */
//Blah.prototype.generateGitignore = function () {
//
//    var content =
//        "*.swp\n" +
//        "*.swo\n" +
//        "*~\n" +
//        "*.log\n" +
//        "node_modules"
//      ;
//
//    return content;
//};
//
///**
// * generateLicense
// * Returns the content of the LICENSE by providing the `@licenseName`.
// *
// * @name generateLicense
// * @function
// * @param {String} licenseName The license name (e.g. `mit`)
// * @return {String} The content of license.
// */
//Blah.prototype.generateLicense = function (licenseName) {
//
//    var fullName = null
//      , pack = require(process.env.PWD + "/package")
//      ;
//
//    try {
//        var gitconfigLines = Fs.readFileSync(
//            require('path-extra').homedir() + "/.gitconfig"
//        ).toString().replace(/\t/g, "").split("\n");
//        for (var i = 0; i < gitconfigLines.length; ++i) {
//            var cLine = gitconfigLines[i].trim();
//            if (/^name/.test(cLine)) {
//                fullName = cLine.split("=")[1].trim();
//                break;
//            }
//        }
//    } catch(e) {
//    }
//
//    if (!fullName) {
//        console.log("No fullname found in .gitconfig. Please modify LICENSE [fullname] manually");
//        fullName = "[fullname]";
//    }
//
//    return Fs
//        .readFileSync(__dirname + "/templates/licenses/" + licenseName.toLowerCase() + ".txt")
//        .toString()
//        .replace("[project]", pack.name)
//        .replace("[year]", new Date().getFullYear())
//        .replace("[fullname]", fullName)
//        .replace("[description]", pack.description)
//        ;
//};

module.exports = Blah;
<|endoftext|>


<commit_before>
/**
 * juice
 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
 * MIT Licensed
 */

module.exports = exports = juice;

/**
 * Module dependencies.
 */

var soupselect = require('soupselect')
  , utils = require('./utils')
  , Selector = require('./selector')
  , Property = require('./property')

/**
 * Export Selector.
 */

exports.Selector = Selector;

/**
 * Export Property.
 */

exports.Property = Property;

/**
 * Export utils.
 */

exports.utils = require('./utils');

/**
 * Inlines the CSS specified by `css` into the `html`
 *
 * @param {String} html
 * @param {String} css
 * @api public
 */

function juice (html, css, options) {
  var rules = utils.parseCSS(css)
    , dom = utils.parseHTML(html)
    , editedElements = []
    , topmost = new Selector('<style attribute>', [1, 0, 0, 0])
    , options = options || {}

  function select (sel) {
    return soupselect.select(dom, sel);
  }

  rules.forEach(function (rule) {
    var sel = rule[0]
      , style = rule[1]
      , matches = select(sel)
      , selector

    if (options.log)
      console.log('\ngot selector "%s" - matches: %s ', sel, matches.length);

    matches.forEach(function (el) {
      // we initialize the Selector lazily to avoid needless parsing
      if (!selector) {
        selector = new Selector(sel)

        if (options.log)
          console.log(
              'selector "%s" has specificity "%s"'
            , sel
            , JSON.stringify(selector.specificity())
          );
      }

      if (!el.styleProps) {
        el.styleProps = {}

        // if the element has inline styles, fake selector with topmost specificity
        if (el.attribs && el.attribs.style) {
          if (options.log)
            console.log('element has inline style - caching properties');

          addProps(
              utils.parseCSS(el.attribs.style)
            , topmost
          );
        }

        // store reference to an element we need to compile style="" attr for
        editedElements.push(el);
      }

      // go through the properties
      function addProps (style, selector) {
        for (var i = 0, l = style.length; i < l; i++) {
          var name = style[i]
            , value = style[name]
            , sel = style._importants[name]
                ? new Selector('!important', [2,0,0,0])
                : selector
            , prop = new Property(name, value, sel)
            , existing = el.styleProps[name]

          if (existing) {
            var winner = existing.compare(prop)
              , loser = prop == winner ? existing : prop

            if (options.log)
              console.log(
                  '  - "%s" already existing from selector "%s", selector "%s" beats "%s"'
                , name
                , existing.selector.text
                , winner.selector.text
                , loser.selector.text
              );

            if (winner == prop && options.log) {
              console.log('  + new value "%s"', value);
            }
          } else {
            el.styleProps[name] = prop;
            if (options.log)
              console.log(' - property "%s" added with value "%s"', name, value);
          }
        }
      }

      addProps(style, selector);
    });
  });

  console.log('elements affected "%s"', editedElements.length);
  editedElements.forEach(function (el) {
    var style = '';

    for (var i in el.styleProps) {
      style += el.styleProps[i].toString();
    }

    if (!el.attribs) el.attribs = {};

    el.attribs.style = style;
  });

  return utils.domToHTML(dom);
}
<commit_msg>Added conditiona logging<commit_after>
/**
 * juice
 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
 * MIT Licensed
 */

module.exports = exports = juice;

/**
 * Module dependencies.
 */

var soupselect = require('soupselect')
  , utils = require('./utils')
  , Selector = require('./selector')
  , Property = require('./property')

/**
 * Export Selector.
 */

exports.Selector = Selector;

/**
 * Export Property.
 */

exports.Property = Property;

/**
 * Export utils.
 */

exports.utils = require('./utils');

/**
 * Inlines the CSS specified by `css` into the `html`
 *
 * @param {String} html
 * @param {String} css
 * @api public
 */

function juice (html, css, options) {
  var rules = utils.parseCSS(css)
    , dom = utils.parseHTML(html)
    , editedElements = []
    , topmost = new Selector('<style attribute>', [1, 0, 0, 0])
    , options = options || {}

  function select (sel) {
    return soupselect.select(dom, sel);
  }

  rules.forEach(function (rule) {
    var sel = rule[0]
      , style = rule[1]
      , matches = select(sel)
      , selector

    if (options.log)
      console.log('\ngot selector "%s" - matches: %s ', sel, matches.length);

    matches.forEach(function (el) {
      // we initialize the Selector lazily to avoid needless parsing
      if (!selector) {
        selector = new Selector(sel)

        if (options.log)
          console.log(
              'selector "%s" has specificity "%s"'
            , sel
            , JSON.stringify(selector.specificity())
          );
      }

      if (!el.styleProps) {
        el.styleProps = {}

        // if the element has inline styles, fake selector with topmost specificity
        if (el.attribs && el.attribs.style) {
          if (options.log)
            console.log('element has inline style - caching properties');

          addProps(
              utils.parseCSS(el.attribs.style)
            , topmost
          );
        }

        // store reference to an element we need to compile style="" attr for
        editedElements.push(el);
      }

      // go through the properties
      function addProps (style, selector) {
        for (var i = 0, l = style.length; i < l; i++) {
          var name = style[i]
            , value = style[name]
            , sel = style._importants[name]
                ? new Selector('!important', [2,0,0,0])
                : selector
            , prop = new Property(name, value, sel)
            , existing = el.styleProps[name]

          if (existing) {
            var winner = existing.compare(prop)
              , loser = prop == winner ? existing : prop

            if (options.log)
              console.log(
                  '  - "%s" already existing from selector "%s", selector "%s" beats "%s"'
                , name
                , existing.selector.text
                , winner.selector.text
                , loser.selector.text
              );

            if (winner == prop && options.log) {
              console.log('  + new value "%s"', value);
            }
          } else {
            el.styleProps[name] = prop;
            if (options.log)
              console.log(' - property "%s" added with value "%s"', name, value);
          }
        }
      }

      addProps(style, selector);
    });
  });

  if (options.log)
    console.log('elements affected "%s"', editedElements.length);

  editedElements.forEach(function (el) {
    var style = '';

    for (var i in el.styleProps) {
      style += el.styleProps[i].toString();
    }

    if (!el.attribs) el.attribs = {};

    el.attribs.style = style;
  });

  return utils.domToHTML(dom);
}
<|endoftext|>


<commit_before>import m from 'mithril';
import _ from 'underscore';
import $ from 'jquery';
import h from '../h';

const projectContributionReportContentCard = {
    controller(args) {
        const project = args.project(),
            checked = contribution => _.contains(args.selectedContributions(), contribution.id),
            selectContribution = (contribution) => {
                const anyChecked = $('input:checkbox').is(':checked');

                args.selectedAny(anyChecked);
                if (!checked(contribution)) {
                    args.selectedContributions().push(contribution.id);
                } else {
                    args.selectedContributions(_.without(args.selectedContributions(), contribution.id));
                }
                return true;
            },
            stateClass = (state) => {
                const classes = {
                    online: {
                        paid: 'text-success.fa-circle',
                        refunded: 'text-error.fa-circle',
                        pending_refund: 'text-error.fa-circle',
                        pending: 'text-waiting.fa-circle',
                        refused: 'text-error.fa-circle'
                    },
                    failed: {
                        paid: 'text-error.fa-circle-o',
                        refunded: 'text-refunded.fa-circle',
                        pending_refund: 'text-refunded.fa-circle-o',
                        pending: 'text-refunded',
                        refused: 'text-refunded'
                    },
                    waiting_funds: {
                        paid: 'text-success.fa-circle',
                        refunded: 'text-error.fa-circle',
                        pending_refund: 'text-error.fa-circle',
                        pending: 'text-waiting.fa-circle',
                        refused: 'text-error.fa-circle'
                    },
                    successful: {
                        paid: 'text-success.fa-circle',
                        refunded: 'text-error.fa-circle',
                        pending_refund: 'text-error.fa-circle',
                        pending: 'text-waiting.fa-circle',
                        refused: 'text-error.fa-circle'
                    }
                };

                return classes[project.state][state];
            };

        return {
            stateClass,
            checked,
            selectContribution
        };
    },
    view(ctrl, args) {
        const contribution = args.contribution(),
            project = args.project(),
            profileImg = (_.isEmpty(contribution.profile_img_thumbnail) ? '/assets/catarse_bootstrap/user.jpg' : contribution.profile_img_thumbnail),
            reward = contribution.reward || {
                minimum_value: 0,
                description: 'Nenhuma recompensa selecionada'
            };

        return m(`.w-clearfix.card${ctrl.checked(contribution) ? '.card-alert' : ''}`, [
            m('.w-row', [
                m('.w-col.w-col-1.w-col-small-1.w-col-tiny-1',
                    m('.w-inline-block',
                        m('.w-checkbox.w-clearfix',
                            (contribution.delivery_status !== 'received' && project.state !== 'failed' ?
                                m('input.w-checkbox-input[type=\'checkbox\']', {
                                    checked: ctrl.checked(contribution),
                                    value: contribution.id,
                                    onclick: () => ctrl.selectContribution(contribution)
                                }) : '')
                        )
                    )
                ),
                m('.w-col.w-col-11.w-col-small-11.w-col-tiny-11',
                    m('.w-row', [
                        m('.w-col.w-col-1.w-col-tiny-1', [
                            m(`img.user-avatar.u-marginbottom-10[src='${profileImg}']`)
                        ]),
                        m('.w-col.w-col-11.w-col-tiny-11', [
                            m('.w-row', [
                                m('.w-col.w-col-3', [
                                    m('.fontcolor-secondary.fontsize-mini.fontweight-semibold', h.momentify(contribution.created_at, 'DD/MM/YYYY, HH:mm')),
                                    m('.fontweight-semibold.fontsize-smaller.lineheight-tighter', contribution.user_name),
                                    m('.fontsize-smallest.lineheight-looser', [
                                        (contribution.has_another ? [
                                            m('a.link-hidden-light.badge.badge-light', '+1 apoio '),
                                        ] : ''),
                                        (contribution.anonymous ? m('span.fa.fa-eye-slash.fontcolor-secondary', m('span.fontcolor-secondary[style="font-size:11px;"]', ' Apoio não-público')) : '')
                                    ]),
                                    m('.fontsize-smallest.lineheight-looser', (contribution.email))
                                ]),
                                m('.w-col.w-col-3', [
                                    m('.lineheight-tighter', [
                                        m(`span.fa.fontsize-smallest.${ctrl.stateClass(contribution.state)}`),
                                        '   ',
                                        m('span.fontsize-large', `R$ ${h.formatNumber(contribution.value, 2, 3)}`)
                                    ])
                                ]),
                                m('.w-col.w-col-3.w-hidden-small.w-hidden-tiny', [
                                    m('div',
                                        (contribution.delivery_status === 'error' ?
                                            m('span.badge.badge-attention.fontsize-smaller',
                                                'Erro no envio'
                                            ) : contribution.delivery_status === 'delivered' ?
                                            m('span.badge.badge-success.fontsize-smaller',
                                                'Enviada'
                                            ) : contribution.delivery_status === 'received' ?
                                            m('span.fontsize-smaller.badge.badge-success', [
                                                m('span.fa.fa-check-circle',
                                                    ''
                                                ),
                                                ' Recebida'
                                            ]) : '')
                                    ),
                                    m('.fontsize-smallest.fontweight-semibold', `Recompensa: ${reward.minimum_value ? h.formatNumber(reward.minimum_value, 2, 3) : ''}`),
                                    m('.fontsize-smallest.fontweight-semibold',
                                        reward.title
                                    ),
                                    m('.fontsize-smallest.fontcolor-secondary', `${reward.description.substring(0, 80)}...`)
                                ])
                            ])
                        ])
                    ])
                )
            ])

        ]);
    }
};

export default projectContributionReportContentCard;<commit_msg>contribution report expanded card<commit_after>import m from 'mithril';
import _ from 'underscore';
import $ from 'jquery';
import I18n from 'i18n-js';
import h from '../h';

const I18nScope = _.partial(h.i18nScope, 'projects.reward_fields');

const projectContributionReportContentCard = {
    controller(args) {
        const project = args.project(),
            showDetail = h.toggleProp(false, true),
            currentTab = m.prop('info'),
            checked = contribution => _.contains(args.selectedContributions(), contribution.id),
            selectContribution = (contribution) => {
                const anyChecked = $('input:checkbox').is(':checked');

                args.selectedAny(anyChecked);
                if (!checked(contribution)) {
                    args.selectedContributions().push(contribution.id);
                } else {
                    args.selectedContributions(_.without(args.selectedContributions(), contribution.id));
                }
                return true;
            },
            stateClass = (state) => {
                const classes = {
                    online: {
                        paid: 'text-success.fa-circle',
                        refunded: 'text-error.fa-circle',
                        pending_refund: 'text-error.fa-circle',
                        pending: 'text-waiting.fa-circle',
                        refused: 'text-error.fa-circle'
                    },
                    failed: {
                        paid: 'text-error.fa-circle-o',
                        refunded: 'text-refunded.fa-circle',
                        pending_refund: 'text-refunded.fa-circle-o',
                        pending: 'text-refunded',
                        refused: 'text-refunded'
                    },
                    waiting_funds: {
                        paid: 'text-success.fa-circle',
                        refunded: 'text-error.fa-circle',
                        pending_refund: 'text-error.fa-circle',
                        pending: 'text-waiting.fa-circle',
                        refused: 'text-error.fa-circle'
                    },
                    successful: {
                        paid: 'text-success.fa-circle',
                        refunded: 'text-error.fa-circle',
                        pending_refund: 'text-error.fa-circle',
                        pending: 'text-waiting.fa-circle',
                        refused: 'text-error.fa-circle'
                    }
                };

                return classes[project.state][state];
            };

        return {
            stateClass,
            checked,
            currentTab,
            showDetail,
            selectContribution
        };
    },
    view(ctrl, args) {
        const contribution = args.contribution(),
            project = args.project(),
            profileImg = (_.isEmpty(contribution.profile_img_thumbnail) ? '/assets/catarse_bootstrap/user.jpg' : contribution.profile_img_thumbnail),
            reward = contribution.reward || {
                minimum_value: 0,
                description: 'Nenhuma recompensa selecionada'
            },
            deliveryBadge = () => (contribution.delivery_status === 'error' ?
                                                m('span.badge.badge-attention.fontsize-smaller',
                                                    'Erro no envio'
                                                ) : contribution.delivery_status === 'delivered' ?
                                                m('span.badge.badge-success.fontsize-smaller',
                                                    'Enviada'
                                                ) : contribution.delivery_status === 'received' ?
                                                m('span.fontsize-smaller.badge.badge-success', [
                                                    m('span.fa.fa-check-circle',
                                                        ''
                                                    ),
                                                    ' Recebida'
                                                ]) : '');
        console.log(contribution);

        return m('div', [m(`.w-clearfix.card${ctrl.checked(contribution) ? '.card-alert' : ''}`, [
            m('.w-row', [
                m('.w-col.w-col-1.w-col-small-1.w-col-tiny-1',
                        m('.w-inline-block',
                            m('.w-checkbox.w-clearfix',
                                (contribution.delivery_status !== 'received' && project.state !== 'failed' ?
                                    m('input.w-checkbox-input[type=\'checkbox\']', {
                                        checked: ctrl.checked(contribution),
                                        value: contribution.id,
                                        onclick: () => ctrl.selectContribution(contribution)
                                    }) : '')
                            )
                        )
                    ),
                m('.w-col.w-col-11.w-col-small-11.w-col-tiny-11',
                        m('.w-row', [
                            m('.w-col.w-col-1.w-col-tiny-1', [
                                m(`img.user-avatar.u-marginbottom-10[src='${profileImg}']`)
                            ]),
                            m('.w-col.w-col-11.w-col-tiny-11', [
                                m('.w-row', [
                                    m('.w-col.w-col-3', [
                                        m('.fontcolor-secondary.fontsize-mini.fontweight-semibold', h.momentify(contribution.created_at, 'DD/MM/YYYY, HH:mm')),
                                        m('.fontweight-semibold.fontsize-smaller.lineheight-tighter', contribution.user_name),
                                        m('.fontsize-smallest.lineheight-looser', [
                                            (contribution.has_another ? [
                                                m('a.link-hidden-light.badge.badge-light', '+1 apoio '),
                                            ] : ''),
                                            (contribution.anonymous ? m('span.fa.fa-eye-slash.fontcolor-secondary', m('span.fontcolor-secondary[style="font-size:11px;"]', ' Apoio não-público')) : '')
                                        ]),
                                        m('.fontsize-smallest.lineheight-looser', (contribution.email))
                                    ]),
                                    m('.w-col.w-col-3', [
                                        m('.lineheight-tighter', [
                                            m(`span.fa.fontsize-smallest.${ctrl.stateClass(contribution.state)}`),
                                            '   ',
                                            m('span.fontsize-large', `R$ ${h.formatNumber(contribution.value, 2, 3)}`)
                                        ])
                                    ]),
                                    m('.w-col.w-col-3.w-hidden-small.w-hidden-tiny', [
                                        m('div',
                                            deliveryBadge()
                                        ),
                                        m('.fontsize-smallest.fontweight-semibold', `Recompensa: ${reward.minimum_value ? h.formatNumber(reward.minimum_value, 2, 3) : ''}`),
                                        m('.fontsize-smallest.fontweight-semibold',
                                            reward.title
                                        ),
                                        m('.fontsize-smallest.fontcolor-secondary', `${reward.description.substring(0, 80)}...`)
                                    ]),
                                    m('.w-col.w-col-3.w-col-push-1', [
                                        m('.fontsize-smallest', [
                                            m('a.link-hidden',
                                                'Questionário '
                                            ),
                                            m('span.fontweight-semibold.text-waiting',
                                                'enviado'
                                            )
                                        ]),
                                        m('.fontcolor-terciary.fontsize-smallest',
                                            'em 29/10/2015'
                                        )
                                    ])
                                ])
                            ])
                        ])
                    )
            ]),
            m('a.arrow-admin.fa.fa-chevron-down.fontcolor-secondary.w-inline-block', {
                onclick: ctrl.showDetail.toggle
            })
        ]),
            (ctrl.showDetail() ?
                m('.card.details-backed-project.w-tabs', [
                    m('.w-tab-menu', [
                        m(`a.dashboard-nav-link.w-inline-block.w-tab-link${ctrl.currentTab() === 'info' ? '.w--current' : ''}`, { onclick: () => ctrl.currentTab('info') },
                            m('div',
                                'Info'
                            )
                        ),
                        m(`a.dashboard-nav-link.w-inline-block.w-tab-link${ctrl.currentTab() === 'profile' ? '.w--current' : ''}`, { onclick: () => ctrl.currentTab('profile') },
                            m('div',
                                'Perfil'
                            )
                        )
                    ]),
                    m('.card.card-terciary.w-tab-content', [
                        (ctrl.currentTab() === 'info' ?
                        m('.w-tab-pane.w--tab-active',
                            m('.w-row', [
                                m('.right-divider.w-col.w-col-6', [
                                    m('.u-marginbottom-20', [
                                        m('.fontsize-base.fontweight-semibold.u-marginbottom-10',
                                            'Valor do apoio: R$50'
                                        ),
                                        m('div',
                                            m('.fontsize-smaller', [
                                                m('span.fa.fa-barcode',
                                                    ''
                                                ),
                                                m("a.link-hidden.fontweight-semibold[href='#']", [
                                                    'Boleto',
                                                    m.trust(' ')
                                                ])
                                            ])
                                        ),
                                        m('.fontsize-smaller.fontweight-semibold', [
                                            m('span.fa.fa-circle.text-error',
                                                ''
                                            ),
                                            m.trust(' '),
                                            'Não finalizado'
                                        ]),
                                        m('.fontcolor-secondary.fontsize-smallest',
                                            '19/05/2015, 01:20 h'
                                        )
                                    ]),
                                    m('.fontsize-base.fontweight-semibold',
                                        'Recompensa:'
                                    ),
                                    m('.fontsize-small.fontweight-semibold.u-marginbottom-10', [
                                        `R$${contribution.reward.minimum_value} ${contribution.reward.title ? `- ${contribution.reward.title}` : ''} `,
                                        deliveryBadge()
                                    ]),
                                    m('p.fontsize-smaller',
                                      contribution.reward.description
                                    ),
                                    m('.u-marginbottom-10', [
                                        m('.fontsize-smaller', [
                                            m('span.fontweight-semibold',
                                                'Entrega prevista: '
                                            ),
                                            h.momentify(reward.deliver_at, 'MMMM/YYYY')
                                        ]),
                                        m('.fontsize-smaller', [
                                            m('span.fontweight-semibold',
                                                'Envio: '
                                            ),
                                            I18n.t(`shipping_options.${reward.shipping_options}`, I18nScope())
                                        ])
                                    ])
                                ]),
                                m('.w-col.w-col-6', [
                                    m('.fontsize-base.fontweight-semibold',
                                        'Questionário'
                                    ),
                                    m('.fontsize-smaller.lineheight-tighter.u-marginbottom-20',
                                        'Respondido em 19/10/2015'
                                    ),
                                    m('.fontsize-small', [
                                        m('.fontweight-semibold.lineheight-looser',
                                            'Nome e endereço'
                                        ),
                                        m('p', [
                                            'Ciclana de Tals',
                                            m('br'),
                                            'Rua das Couves, 56',
                                            m('br'),
                                            'Bairro: cosme Velho',
                                            m('br'),
                                            '22241-090 Rio de janeiro-RJ',
                                            m('br'),
                                            'BRAZIL'
                                        ])
                                    ]),
                                    m('.fontsize-small', [
                                        m('.fontweight-semibold.lineheight-looser',
                                            'Tamanho da camisa'
                                        ),
                                        m('p',
                                            'P'
                                        )
                                    ])
                                ])
                            ])
                        ) :
                        m('.w-tab-pane',
                            m('.fontsize-small',
                                m('p', [
                                    contribution.user_name,
                                    m('br'),
                                    contribution.email,
                                    m('br'),
                                    'Conta no Catarse desde Julho 2011',
                                    m('br'),
                                    `Apoiou ${contribution.total_contributed_projects} projetos`,
                                    m('br'),
                                    'Criou 2 projetos'
                                ])
                            )
                        ))
                    ])
                ]) : '')
        ]);
    }
};

export default projectContributionReportContentCard;
<|endoftext|>


<commit_before>'use strict';

(function () {

  // Stored options
  var vendorPrefixes = {},
    obfuscate = true,
    minify = false,
    optionsSet = false;
  var existingClassNames = [];
  var existingAnimationNames = [];
  var isMediaQuery = /^@media/;
  var whitespace = /[\n\r\s]/g;
  var indent = '  ';
  var messagePrefix = 'ReactStyleSheets: ';
  var headTag = document.getElementsByTagName('head')[0];
  var styleTag;

  var commaSeparatedProperties = [
    'fontFamily'
  ];

  var noSuffixProperties = [
    'opacity',
    'animationIterationCount'
  ];

  var timeSuffixProperties = [
    'transition',
    'transitionDuration',
    'transitionDelay',
    'animation',
    'animationDuration',
    'animationDelay'
  ];

  var doubleColonSelectors = [
    'before',
    'after',
    'firstLetter',
    'firstLine',
    'selection'
  ];

  var nestedSelectors = [
    'active',
    'after',
    'before',
    'checked',
    'disabled',
    'empty',
    'enabled',
    'firstChild',
    'firstLetter',
    'firstLine',
    'firstOfType',
    'focus',
    'hover',
    'inRange',
    'invalid',
    // 'lang', // Takes arguments
    'lastChild',
    'lastOfType',
    'link',
    // 'not', // Takes arguments
    // 'nthChild', // Takes arguments
    // 'nthLastChild', // Takes arguments
    // 'nthLastOfType', // Takes arguments
    // 'nthOfType', // Takes arguments
    'onlyOfType',
    'onlyChild',
    'optional',
    'outOfRange',
    'readOnly',
    'readWrite',
    'required',
    'root',
    'selection',
    'target',
    'valid',
    'visited'
  ];

  function warn (message) {
    /* istanbul ignore else */
    if (typeof console !== 'undefined' && typeof console.warn === 'function') {
      console.warn(messagePrefix + message);
    }
  }

  function error (message) {
    throw new Error(messagePrefix + message);
  }

  if (!headTag) {
    error('Could not locate head tag. Ensure your javascript is included after the closing head tag.');
  }

  styleTag = document.createElement('style');
  styleTag.setAttribute('type', 'text/css');
  headTag.appendChild(styleTag);

  function toSpinalCase (value) {
    return value.replace(/(^|[a-z])([A-Z])/g, '$1-$2').toLowerCase();
  }

  function removeWhitespace (value) {
    return minify ? value.replace(whitespace, '') : value;
  }

  function generateRandomString (length) {
    var concat = '';

    for (var i = 0; i < length; i += 1) {
      concat += String.fromCharCode(97 + Math.floor(Math.random() * 26));
    }

    return concat;
  }

  function generateUniqueName (name, existingNames, type) {
    if (obfuscate) {
      var obfuscatedName = name + '_' + generateRandomString(5);

      while (existingNames.indexOf(obfuscatedName) >= 0) {
        /* istanbul ignore next */
        obfuscatedName = name + '_' + generateRandomString(5);
      }

      existingNames.push(obfuscatedName);
      return obfuscatedName;
    }

    if (existingNames.indexOf(name) >= 0) {
      error('The ' + type + ' name "' + name + '" is already in use, please choose another.');
    }

    existingNames.push(name);
    return name;
  }

  function formatValue (key, value) {
    if (Array.isArray(value)) {
      var separator = commaSeparatedProperties.indexOf(key) >= 0 ? ', ' : ' ';
      return value.map(formatValue.bind(null, key)).join(separator);
    } else if (typeof value === 'number') {
      if (value === 0 || noSuffixProperties.indexOf(key) >= 0) {
        return value;
      }

      if (timeSuffixProperties.indexOf(key) >= 0) {
        return value + 'ms';
      }

      return value + 'px';
    }

    return value;
  }

  function createStyles (tag, style, indentation) {
    indentation = indentation || '';
    var prefix = '\n' + indentation + tag + ' {\n';
    var nested = '';

    if (isMediaQuery.test(tag)) {
      error('Media queries must be nested inside your tag / class.');
    }

    for (var key in style) {
      if (!isMediaQuery.test(key) && key.indexOf('-') >= 0) {
        error('Found "-" in a style property name. Style property names must be defined in camelcase.');
      }

      var value = style[key];

      if (key in vendorPrefixes) {
        // Vendor prefixes
        for (var i = 0; i < vendorPrefixes[key].length; i += 1) {
          var vendorKey = '-' + vendorPrefixes[key][i] + '-' + key;
          prefix += indentation + indent + toSpinalCase(vendorKey) + ': ' +
            formatValue(key, value) + ';\n';
        }

        prefix += indentation + indent + toSpinalCase(key) + ': ' +
          formatValue(key, value) + ';\n';
      } else if (nestedSelectors.indexOf(key) >= 0) {
        // Nested styles
        if (typeof value !== 'object' || Array.isArray(value)) {
          error('Nested selectors such as hover, active, before, firstChild, etc, must be an object.');
        }

        var colon = doubleColonSelectors.indexOf(key) >= 0 ? '::' : ':';
        nested += createStyles(tag + colon + toSpinalCase(key), value, indentation);
      } else if (isMediaQuery.test(key)) {
        // Media queries
        if (typeof value !== 'object' || Array.isArray(value)) {
          error('Media queries must be an object.');
        }

        nested += '\n' + indentation + key + ' {\n';
        nested += createStyles(tag, value, indentation + indent);
        nested += indentation + '\n' + indentation + '}\n';
      } else if (typeof value === 'object' && !Array.isArray(value)) {
        // Sub styles e.g. {margin: {left, right}}
        for (var subKey in value) {
          var keySubKey;

          if (subKey === 'vertical' || subKey === 'horizontal' || subKey === 'all') {
            if (subKey !== 'horizontal') {
              keySubKey = key + '-' + 'top';
              prefix += indentation + indent + toSpinalCase(keySubKey) + ': ' +
                formatValue(keySubKey, value[subKey]) + ';\n';

              keySubKey = key + '-' + 'bottom';
              prefix += indentation + indent + toSpinalCase(keySubKey) + ': ' +
                formatValue(keySubKey, value[subKey]) + ';\n';
            }

            if (subKey !== 'vertical') {
              keySubKey = key + '-' + 'right';
              prefix += indentation + indent + toSpinalCase(keySubKey) + ': ' +
                formatValue(keySubKey, value[subKey]) + ';\n';

              keySubKey = key + '-' + 'left';
              prefix += indentation + indent + toSpinalCase(keySubKey) + ': ' +
                formatValue(keySubKey, value[subKey]) + ';\n';
            }
          } else {
            keySubKey = key + '-' + subKey;
            prefix += indentation + indent + toSpinalCase(keySubKey) + ': ' +
              formatValue(keySubKey, value[subKey]) + ';\n';
          }
        }
      } else {
        // Basic values & arrays
        prefix += indentation + indent + toSpinalCase(key) + ': ' +
          formatValue(key, value) + ';\n';
      }
    }

    return prefix + indentation + '}\n' + nested;
  }

  function createUnmodifiedIndentedStyles (styles, indentation) {
    var concat = '';

    for (var tag in styles) {
      concat += createStyles(tag, styles[tag], indentation);
    }

    return {
      keys: null,
      values: removeWhitespace(concat)
    };
  }

  var ReactStyleSheets = {
    setOptions: function (options) {
      if (optionsSet) {
        warn('You tried to set options more than once. This is not advised.');
      }

      if (typeof options !== 'object') {
        error('Options must be an object.');
      }

      if (typeof options.vendorPrefixes !== 'undefined') {
        if (typeof options.vendorPrefixes !== 'object' || Array.isArray(options.vendorPrefixes)) {
          error('vendorPrefixes must be an object with style property names as keys, ' +
            'and arrays of prefixes as values.');
        } else {
          vendorPrefixes = options.vendorPrefixes;
        }
      }

      if (typeof options.obfuscate !== 'undefined') {
        obfuscate = options.obfuscate;
      }

      if (typeof options.minify !== 'undefined') {
        minify = options.minify;
      }

      optionsSet = true;
    },
    _createGlobalTagStyles: function (styles) {
      return createUnmodifiedIndentedStyles(styles);
    },
    createGlobalTagStyles: function (styles) {
      var generated = ReactStyleSheets._createGlobalTagStyles(styles);

      styleTag.innerHTML = styleTag.innerHTML + generated.values;
    },
    _createUniqueClassStyles: function (styles) {
      var classNames = {};
      var concat = '';

      for (var className in styles) {
        var obfuscatedClassName = generateUniqueName(className, existingClassNames, 'class');

        concat += createStyles('.' + obfuscatedClassName, styles[className]);

        classNames[className] = obfuscatedClassName;
      }

      return {
        keys: classNames,
        values: removeWhitespace(concat)
      };
    },
    createUniqueClassStyles: function (styles) {
      var generated = ReactStyleSheets._createUniqueClassStyles(styles);

      styleTag.innerHTML = styleTag.innerHTML + generated.values;

      return generated.keys;
    },
    _createUniqueKeyframeAnimations: function (styles) {
      var animations = {};
      var concat = '';

      for (var animationName in styles) {
        var obfuscatedAnimationName = generateUniqueName(animationName, existingAnimationNames, 'keyframe animation');

        concat += '\n@keyframes ' + obfuscatedAnimationName + ' {\n';
        var generated = createUnmodifiedIndentedStyles(styles[animationName], indent);
        concat += generated.values;
        concat += '\n}\n';

        animations[animationName] = obfuscatedAnimationName;
      }

      return {
        keys: animations,
        values: removeWhitespace(concat)
      };
    },
    createUniqueKeyframeAnimations: function (styles) {
      var generated = ReactStyleSheets._createUniqueKeyframeAnimations(styles);

      styleTag.innerHTML = styleTag.innerHTML + generated.values;

      return generated.keys;
    }
  };

  /* istanbul ignore else */

  // Export for commonjs / browserify
  if (typeof exports === 'object' && typeof module !== 'undefined') {
    module.exports = ReactStyleSheets;
  // Export for amd / require
  } else if (typeof define === 'function' && define.amd) { // eslint-disable-line no-undef
    define([], function () { // eslint-disable-line no-undef
      return ReactStyleSheets;
    });
  // Export globally
  } else {
    var root;

    if (typeof window !== 'undefined') {
      root = window;
    } else if (typeof global !== 'undefined') {
      root = global;
    } else if (typeof self !== 'undefined') {
      root = self;
    } else {
      root = this;
    }

    root.ReactStyleSheets = ReactStyleSheets;
  }

})();
<commit_msg>Adjust style concatenation<commit_after>'use strict';

(function () {

  // Stored options
  var vendorPrefixes = {},
    obfuscate = true,
    minify = false,
    optionsSet = false;
  var existingClassNames = [];
  var existingAnimationNames = [];
  var isMediaQuery = /^@media/;
  var whitespace = /[\n\r\s]/g;
  var indent = '  ';
  var messagePrefix = 'ReactStyleSheets: ';
  var headTag = document.getElementsByTagName('head')[0];
  var styleTag;

  var commaSeparatedProperties = [
    'fontFamily'
  ];

  var noSuffixProperties = [
    'opacity',
    'animationIterationCount'
  ];

  var timeSuffixProperties = [
    'transition',
    'transitionDuration',
    'transitionDelay',
    'animation',
    'animationDuration',
    'animationDelay'
  ];

  var doubleColonSelectors = [
    'before',
    'after',
    'firstLetter',
    'firstLine',
    'selection'
  ];

  var nestedSelectors = [
    'active',
    'after',
    'before',
    'checked',
    'disabled',
    'empty',
    'enabled',
    'firstChild',
    'firstLetter',
    'firstLine',
    'firstOfType',
    'focus',
    'hover',
    'inRange',
    'invalid',
    // 'lang', // Takes arguments
    'lastChild',
    'lastOfType',
    'link',
    // 'not', // Takes arguments
    // 'nthChild', // Takes arguments
    // 'nthLastChild', // Takes arguments
    // 'nthLastOfType', // Takes arguments
    // 'nthOfType', // Takes arguments
    'onlyOfType',
    'onlyChild',
    'optional',
    'outOfRange',
    'readOnly',
    'readWrite',
    'required',
    'root',
    'selection',
    'target',
    'valid',
    'visited'
  ];

  function warn (message) {
    /* istanbul ignore else */
    if (typeof console !== 'undefined' && typeof console.warn === 'function') {
      console.warn(messagePrefix + message);
    }
  }

  function error (message) {
    throw new Error(messagePrefix + message);
  }

  if (!headTag) {
    error('Could not locate head tag. Ensure your javascript is included after the closing head tag.');
  }

  styleTag = document.createElement('style');
  styleTag.setAttribute('type', 'text/css');
  headTag.appendChild(styleTag);

  function toSpinalCase (value) {
    return value.replace(/(^|[a-z])([A-Z])/g, '$1-$2').toLowerCase();
  }

  function removeWhitespace (value) {
    return minify ? value.replace(whitespace, '') : value;
  }

  function generateRandomString (length) {
    var concat = '';

    for (var i = 0; i < length; i += 1) {
      concat += String.fromCharCode(97 + Math.floor(Math.random() * 26));
    }

    return concat;
  }

  function generateUniqueName (name, existingNames, type) {
    if (obfuscate) {
      var obfuscatedName = name + '_' + generateRandomString(5);

      while (existingNames.indexOf(obfuscatedName) >= 0) {
        /* istanbul ignore next */
        obfuscatedName = name + '_' + generateRandomString(5);
      }

      existingNames.push(obfuscatedName);
      return obfuscatedName;
    }

    if (existingNames.indexOf(name) >= 0) {
      error('The ' + type + ' name "' + name + '" is already in use, please choose another.');
    }

    existingNames.push(name);
    return name;
  }

  function formatValue (key, value) {
    if (Array.isArray(value)) {
      var separator = commaSeparatedProperties.indexOf(key) >= 0 ? ', ' : ' ';
      return value.map(formatValue.bind(null, key)).join(separator);
    } else if (typeof value === 'number') {
      if (value === 0 || noSuffixProperties.indexOf(key) >= 0) {
        return value;
      }

      if (timeSuffixProperties.indexOf(key) >= 0) {
        return value + 'ms';
      }

      return value + 'px';
    }

    return value;
  }

  function createStyles (tag, style, indentation) {
    indentation = indentation || '';
    var prefix = '\n' + indentation + tag + ' {\n';
    var concat = '';
    var suffix = indentation + '}\n';
    var nested = '';

    if (isMediaQuery.test(tag)) {
      error('Media queries must be nested inside your tag / class.');
    }

    for (var key in style) {
      if (!isMediaQuery.test(key) && key.indexOf('-') >= 0) {
        error('Found "-" in a style property name. Style property names must be defined in camelcase.');
      }

      var value = style[key];

      if (key in vendorPrefixes) {
        // Vendor prefixes
        for (var i = 0; i < vendorPrefixes[key].length; i += 1) {
          var vendorKey = '-' + vendorPrefixes[key][i] + '-' + key;
          concat += indentation + indent + toSpinalCase(vendorKey) + ': ' +
            formatValue(key, value) + ';\n';
        }

        concat += indentation + indent + toSpinalCase(key) + ': ' +
          formatValue(key, value) + ';\n';
      } else if (nestedSelectors.indexOf(key) >= 0) {
        // Nested styles
        if (typeof value !== 'object' || Array.isArray(value)) {
          error('Nested selectors such as hover, active, before, firstChild, etc, must be an object.');
        }

        var colon = doubleColonSelectors.indexOf(key) >= 0 ? '::' : ':';
        nested += createStyles(tag + colon + toSpinalCase(key), value, indentation);
      } else if (isMediaQuery.test(key)) {
        // Media queries
        if (typeof value !== 'object' || Array.isArray(value)) {
          error('Media queries must be an object.');
        }

        nested += '\n' + indentation + key + ' {\n';
        nested += createStyles(tag, value, indentation + indent);
        nested += indentation + '\n' + indentation + '}\n';
      } else if (typeof value === 'object' && !Array.isArray(value)) {
        // Sub styles e.g. {margin: {left, right}}
        for (var subKey in value) {
          var keySubKey;

          if (subKey === 'vertical' || subKey === 'horizontal' || subKey === 'all') {
            if (subKey !== 'horizontal') {
              keySubKey = key + '-' + 'top';
              concat += indentation + indent + toSpinalCase(keySubKey) + ': ' +
                formatValue(keySubKey, value[subKey]) + ';\n';

              keySubKey = key + '-' + 'bottom';
              concat += indentation + indent + toSpinalCase(keySubKey) + ': ' +
                formatValue(keySubKey, value[subKey]) + ';\n';
            }

            if (subKey !== 'vertical') {
              keySubKey = key + '-' + 'right';
              concat += indentation + indent + toSpinalCase(keySubKey) + ': ' +
                formatValue(keySubKey, value[subKey]) + ';\n';

              keySubKey = key + '-' + 'left';
              concat += indentation + indent + toSpinalCase(keySubKey) + ': ' +
                formatValue(keySubKey, value[subKey]) + ';\n';
            }
          } else {
            keySubKey = key + '-' + subKey;
            concat += indentation + indent + toSpinalCase(keySubKey) + ': ' +
              formatValue(keySubKey, value[subKey]) + ';\n';
          }
        }
      } else {
        // Basic values & arrays
        concat += indentation + indent + toSpinalCase(key) + ': ' +
          formatValue(key, value) + ';\n';
      }
    }

    return prefix + concat + suffix + nested;
  }

  function createUnmodifiedIndentedStyles (styles, indentation) {
    var concat = '';

    for (var tag in styles) {
      concat += createStyles(tag, styles[tag], indentation);
    }

    return {
      keys: null,
      values: removeWhitespace(concat)
    };
  }

  var ReactStyleSheets = {
    setOptions: function (options) {
      if (optionsSet) {
        warn('You tried to set options more than once. This is not advised.');
      }

      if (typeof options !== 'object') {
        error('Options must be an object.');
      }

      if (typeof options.vendorPrefixes !== 'undefined') {
        if (typeof options.vendorPrefixes !== 'object' || Array.isArray(options.vendorPrefixes)) {
          error('vendorPrefixes must be an object with style property names as keys, ' +
            'and arrays of prefixes as values.');
        } else {
          vendorPrefixes = options.vendorPrefixes;
        }
      }

      if (typeof options.obfuscate !== 'undefined') {
        obfuscate = options.obfuscate;
      }

      if (typeof options.minify !== 'undefined') {
        minify = options.minify;
      }

      optionsSet = true;
    },
    _createGlobalTagStyles: function (styles) {
      return createUnmodifiedIndentedStyles(styles);
    },
    createGlobalTagStyles: function (styles) {
      var generated = ReactStyleSheets._createGlobalTagStyles(styles);

      styleTag.innerHTML = styleTag.innerHTML + generated.values;
    },
    _createUniqueClassStyles: function (styles) {
      var classNames = {};
      var concat = '';

      for (var className in styles) {
        var obfuscatedClassName = generateUniqueName(className, existingClassNames, 'class');

        concat += createStyles('.' + obfuscatedClassName, styles[className]);

        classNames[className] = obfuscatedClassName;
      }

      return {
        keys: classNames,
        values: removeWhitespace(concat)
      };
    },
    createUniqueClassStyles: function (styles) {
      var generated = ReactStyleSheets._createUniqueClassStyles(styles);

      styleTag.innerHTML = styleTag.innerHTML + generated.values;

      return generated.keys;
    },
    _createUniqueKeyframeAnimations: function (styles) {
      var animations = {};
      var concat = '';

      for (var animationName in styles) {
        var obfuscatedAnimationName = generateUniqueName(animationName, existingAnimationNames, 'keyframe animation');

        concat += '\n@keyframes ' + obfuscatedAnimationName + ' {\n';
        var generated = createUnmodifiedIndentedStyles(styles[animationName], indent);
        concat += generated.values;
        concat += '\n}\n';

        animations[animationName] = obfuscatedAnimationName;
      }

      return {
        keys: animations,
        values: removeWhitespace(concat)
      };
    },
    createUniqueKeyframeAnimations: function (styles) {
      var generated = ReactStyleSheets._createUniqueKeyframeAnimations(styles);

      styleTag.innerHTML = styleTag.innerHTML + generated.values;

      return generated.keys;
    }
  };

  /* istanbul ignore else */

  // Export for commonjs / browserify
  if (typeof exports === 'object' && typeof module !== 'undefined') {
    module.exports = ReactStyleSheets;
  // Export for amd / require
  } else if (typeof define === 'function' && define.amd) { // eslint-disable-line no-undef
    define([], function () { // eslint-disable-line no-undef
      return ReactStyleSheets;
    });
  // Export globally
  } else {
    var root;

    if (typeof window !== 'undefined') {
      root = window;
    } else if (typeof global !== 'undefined') {
      root = global;
    } else if (typeof self !== 'undefined') {
      root = self;
    } else {
      root = this;
    }

    root.ReactStyleSheets = ReactStyleSheets;
  }

})();
<|endoftext|>


<commit_before>'use strict';

// =============================
// ------ Import Plugins -------
// =============================

var gulp      = require('gulp');
var bower     = require('gulp-bower');
var watch     = require('gulp-watch');
var postcss   = require('gulp-postcss');
var sass      = require('gulp-sass');
var rigger    = require('gulp-rigger');
var cssmin    = require('gulp-clean-css');
var filter    = require('gulp-filter');
var csscomb   = require('gulp-csscomb');
var zip       = require('gulp-zip');
var plumber   = require('gulp-plumber');
var util      = require('gulp-util');
var posthtml  = require('gulp-posthtml');
var mmq       = require('gulp-merge-media-queries');
var sourcemap = require('gulp-sourcemaps');
var rename    = require("gulp-rename");

var autoprefixer = require('autoprefixer');
var runSequence  = require('run-sequence');
var browserSync  = require('browser-sync').create();
var attrSorter   = require('posthtml-attrs-sorter');
var del          = require('del');
var reload       = browserSync.reload;

// =============================
// -------- Functions ----------
// =============================

// Error handler for gulp-plumber
function errorHandler(err) {
    util.log([ (err.name + ' in ' + err.plugin).bold.red, '', err.message, '' ].join('\n'));

    this.emit('end');
}

function correctNumber(number) {
    return number < 10 ? '0' + number : number;
}

// Return timestamp
function getDateTime() {
    var now = new Date();
    var year = now.getFullYear();
    var month = correctNumber(now.getMonth() + 1);
    var day = correctNumber(now.getDate());
    var hours = correctNumber(now.getHours());
    var minutes = correctNumber(now.getMinutes());
    return year + '-' + month + '-' + day + '-' + hours + minutes;
};

// =============================
// ------- Add var path --------
// =============================

var path = {

    build: {
        html:   'web/',
        js:     'web/js/',
        css:    'web/css/',
        img:    'web/images/',
        fonts:  'web/fonts/',
        libs:   'web/libs/'
    },

    src: {
        html:   'src/*.html',                 // Синтаксис src/*.html говорит gulp что мы хотим взять все файлы с расширением .html
        js:     'src/js/common.js',
        style:  'src/sass/style.scss',
        img:    'src/images/**/*.*',           // Синтаксис images/**/*.* означает - взять все файлы всех расширений из папки и из вложенных каталогов
        fonts:  'src/fonts/**/*.*',
        libs:   './bower_components/'
    },

    watch: {
        html:   'src/**/*.html',
        js:     'src/js/**/*.js',
        style:  'src/sass/**/*.scss',
        img:    'src/images/**/*.*',
        fonts:  'src/fonts/**/*.*'
    },

    clean:      './web'
};

// =============================
// ---- Add plugins options ----
// =============================

var option = {

    browserSync: {
        server: './web',
        tunnel: false,
        open: false,
        host: 'localhost',
        port: 9000,
        logPrefix: "lucas"
    },

    plumber: {
        errorHandler: errorHandler
    },

    sass: {
        outputStyle: 'expanded'
    },

    postcss: [
        autoprefixer({
            cascade: true
        }),
    ],

    posthtml: {
        plugins: [
            attrSorter({
                order: [
                    'class',
                    'id',
                    'name',
                    'data',
                    'ng',
                    'src',
                    'for',
                    'type',
                    'href',
                    'values',
                    'title',
                    'alt',
                    'role',
                    'aria',
                    'tabindex'
                ]
            })
        ],
        options: {}
    },

    mmq: {
        log: true,
        use_external: true
    },

    csscomb: 'csscomb.json',

}

// =============================
// --------- Sub tasks ---------
// =============================

// Удаление скомпилированных файлов
gulp.task('clean', function (cb) {
    return del(path.clean, cb);
});

// Запуск сервера с livereload
gulp.task('serve', function () {
    return browserSync.init(option.browserSync);
});

// Загрузка плагинов из Bower
gulp.task('bower', function() {
    return bower();
});

// =============================
// ------- Build tasks ---------
// =============================

gulp.task('build:html', function () {
    return gulp.src(path.src.html)
        .pipe(plumber(option.plumber))
        .pipe(rigger())
        .pipe(posthtml(option.posthtml.plugins, option.posthtml.options))
        .pipe(gulp.dest(path.build.html))
        .pipe(reload({stream: true}));
});

gulp.task('build:js', function () {
    return gulp.src(path.src.js)
        .pipe(plumber(option.plumber))
        .pipe(rigger())
        .pipe(gulp.dest(path.build.js))
        .pipe(reload({stream: true}));
});

gulp.task('build:css', function (cb) {
    return gulp.src(path.src.style)
        .pipe(plumber(option.plumber))
        .pipe(sourcemap.init())
        .pipe(sass(option.sass))
        .pipe(postcss(option.postcss))
        .pipe(mmq(option.mmq))
        .pipe(csscomb(option.csscomb))
        .pipe(sourcemap.write('.'))
        .pipe(gulp.dest(path.build.css))
        .pipe(reload({stream: true}));
});

gulp.task('build:media', function () {
    gulp.src(path.build.css + '*.responsive.css')
        .pipe(plumber(option.plumber))
        .pipe(sourcemap.init())
        .pipe(rename({basename: 'media'}))
        .pipe(sourcemap.write('.'))
        .pipe(gulp.dest(path.build.css));

    return del(path.build.css + '*.responsive.css');
});

gulp.task('build:img', function () {
    return gulp.src(path.src.img)
        .pipe(plumber(option.plumber))
        .pipe(gulp.dest(path.build.img))
        .pipe(reload({stream: true}));
});

gulp.task('build:fonts', function() {
    return gulp.src(path.src.fonts, {read: false})
        .pipe(plumber(option.plumber))
        .pipe(gulp.dest(path.build.fonts))
        .pipe(reload({stream: true}));
});

gulp.task('build:zip', function() {
    var datetime = '-' + getDateTime();
    var zipName = 'web' + datetime + '.zip';

    return gulp.src('web/**/*.*')
        .pipe(zip(zipName))
        .pipe(gulp.dest('dist'));
});

// =============================
// ------- Watch task ----------
// =============================

gulp.task('watch', function(){
    watch([path.watch.html], function(event, cb) {
        return gulp.start('build:html');
    });

    watch([path.watch.style], function(event, cb) {
        return gulp.start('build:style');
    });

    watch([path.watch.js], function(event, cb) {
        return gulp.start('build:js');
    });

    watch([path.watch.img], function(event, cb) {
        return gulp.start('build:img');
    });

    watch([path.watch.fonts], function(event, cb) {
        return gulp.start('build:fonts');
    });
});

// =============================
// -------- Main task ----------
// =============================

gulp.task('build:style', function (cb) {
    return runSequence(
        'build:css',
        'build:media'
    );
});

gulp.task('build', [
    'build:html',
    'build:style',
    'build:js',
    'build:img',
    'build:fonts'
]);

gulp.task('vendor', function (cb) {
    return runSequence(
        'bower',
        'filter',
        cb
    );
});

gulp.task('zip', function (cb) {
    return runSequence(
        'build',
        'build:zip',
        cb
    );
});

gulp.task('dev', [
    'build',
    'watch',
    'serve'
]);

// Default task
gulp.task('default', ['dev']);

// TODO: Разобрать таск и переписать
// Фильтруем библиотеки и вынимаем только нужные файлы
gulp.task('filter', function() {
    // Настраиваем фильтры для файлов
    const jsFilter = filter(['*.js', '!src/vendor'], {restore: true, passthrough: false});
    const cssFilter = filter(['*.css', '!src/vendor'], {restore: true, passthrough: false});

    // Для нормальных плагинов отработает этот кусок кода
    const stream = gulp.src([
        'bower_components/**/*.min.*',
        'bower_components/**/fonts/*',
        'bower_components/**/*.css',
        '!bower_components/**/*.map'
    ])

    // Фильтруем содержимое на наличие js и css
    .pipe(jsFilter)
    .pipe(cssFilter)
    // run them through a plugin
    .pipe(gulp.dest('dist'));

    // Вываливаем в билд
    jsFilter.restore.pipe(gulp.dest(path.build.libs));

    return stream;
});
<commit_msg>del comments<commit_after>'use strict';

// =============================
// ------ Import Plugins -------
// =============================

var gulp      = require('gulp');
var bower     = require('gulp-bower');
var watch     = require('gulp-watch');
var postcss   = require('gulp-postcss');
var sass      = require('gulp-sass');
var rigger    = require('gulp-rigger');
var cssmin    = require('gulp-clean-css');
var filter    = require('gulp-filter');
var csscomb   = require('gulp-csscomb');
var zip       = require('gulp-zip');
var plumber   = require('gulp-plumber');
var util      = require('gulp-util');
var posthtml  = require('gulp-posthtml');
var mmq       = require('gulp-merge-media-queries');
var sourcemap = require('gulp-sourcemaps');
var rename    = require("gulp-rename");

var autoprefixer = require('autoprefixer');
var runSequence  = require('run-sequence');
var browserSync  = require('browser-sync').create();
var attrSorter   = require('posthtml-attrs-sorter');
var del          = require('del');
var reload       = browserSync.reload;

// =============================
// -------- Functions ----------
// =============================

// Error handler for gulp-plumber
function errorHandler(err) {
    util.log([ (err.name + ' in ' + err.plugin).bold.red, '', err.message, '' ].join('\n'));

    this.emit('end');
}

function correctNumber(number) {
    return number < 10 ? '0' + number : number;
}

// Return timestamp
function getDateTime() {
    var now = new Date();
    var year = now.getFullYear();
    var month = correctNumber(now.getMonth() + 1);
    var day = correctNumber(now.getDate());
    var hours = correctNumber(now.getHours());
    var minutes = correctNumber(now.getMinutes());
    return year + '-' + month + '-' + day + '-' + hours + minutes;
};

// =============================
// ------- Add var path --------
// =============================

var path = {

    build: {
        html:   'web/',
        js:     'web/js/',
        css:    'web/css/',
        img:    'web/images/',
        fonts:  'web/fonts/',
        libs:   'web/libs/'
    },

    src: {
        html:   'src/*.html',                 // Синтаксис src/*.html говорит gulp что мы хотим взять все файлы с расширением .html
        js:     'src/js/common.js',
        style:  'src/sass/style.scss',
        img:    'src/images/**/*.*',           // Синтаксис images/**/*.* означает - взять все файлы всех расширений из папки и из вложенных каталогов
        fonts:  'src/fonts/**/*.*',
        libs:   './bower_components/'
    },

    watch: {
        html:   'src/**/*.html',
        js:     'src/js/**/*.js',
        style:  'src/sass/**/*.scss',
        img:    'src/images/**/*.*',
        fonts:  'src/fonts/**/*.*'
    },

    clean:      './web'
};

// =============================
// ---- Add plugins options ----
// =============================

var option = {

    browserSync: {
        server: './web',
        tunnel: false,
        open: false,
        host: 'localhost',
        port: 9000,
        logPrefix: "lucas"
    },

    plumber: {
        errorHandler: errorHandler
    },

    sass: {
        outputStyle: 'expanded'
    },

    postcss: [
        autoprefixer({
            cascade: true
        }),
    ],

    posthtml: {
        plugins: [
            attrSorter({
                order: [
                    'class',
                    'id',
                    'name',
                    'data',
                    'ng',
                    'src',
                    'for',
                    'type',
                    'href',
                    'values',
                    'title',
                    'alt',
                    'role',
                    'aria',
                    'tabindex'
                ]
            })
        ],
        options: {}
    },

    mmq: {
        log: true,
        use_external: true
    },

    csscomb: 'csscomb.json',

}

// =============================
// --------- Sub tasks ---------
// =============================

gulp.task('clean', function (cb) {
    return del(path.clean, cb);
});

gulp.task('serve', function () {
    return browserSync.init(option.browserSync);
});

gulp.task('bower', function() {
    return bower();
});

// =============================
// ------- Build tasks ---------
// =============================

gulp.task('build:html', function () {
    return gulp.src(path.src.html)
        .pipe(plumber(option.plumber))
        .pipe(rigger())
        .pipe(posthtml(option.posthtml.plugins, option.posthtml.options))
        .pipe(gulp.dest(path.build.html))
        .pipe(reload({stream: true}));
});

gulp.task('build:js', function () {
    return gulp.src(path.src.js)
        .pipe(plumber(option.plumber))
        .pipe(rigger())
        .pipe(gulp.dest(path.build.js))
        .pipe(reload({stream: true}));
});

gulp.task('build:css', function (cb) {
    return gulp.src(path.src.style)
        .pipe(plumber(option.plumber))
        .pipe(sourcemap.init())
        .pipe(sass(option.sass))
        .pipe(postcss(option.postcss))
        .pipe(mmq(option.mmq))
        .pipe(csscomb(option.csscomb))
        .pipe(sourcemap.write('.'))
        .pipe(gulp.dest(path.build.css))
        .pipe(reload({stream: true}));
});

gulp.task('build:media', function () {
    gulp.src(path.build.css + '*.responsive.css')
        .pipe(plumber(option.plumber))
        .pipe(sourcemap.init())
        .pipe(rename({basename: 'media'}))
        .pipe(sourcemap.write('.'))
        .pipe(gulp.dest(path.build.css));

    return del(path.build.css + '*.responsive.css');
});

gulp.task('build:img', function () {
    return gulp.src(path.src.img)
        .pipe(plumber(option.plumber))
        .pipe(gulp.dest(path.build.img))
        .pipe(reload({stream: true}));
});

gulp.task('build:fonts', function() {
    return gulp.src(path.src.fonts, {read: false})
        .pipe(plumber(option.plumber))
        .pipe(gulp.dest(path.build.fonts))
        .pipe(reload({stream: true}));
});

gulp.task('build:zip', function() {
    var datetime = '-' + getDateTime();
    var zipName = 'web' + datetime + '.zip';

    return gulp.src('web/**/*.*')
        .pipe(zip(zipName))
        .pipe(gulp.dest('dist'));
});

// =============================
// ------- Watch task ----------
// =============================

gulp.task('watch', function(){
    watch([path.watch.html], function(event, cb) {
        return gulp.start('build:html');
    });

    watch([path.watch.style], function(event, cb) {
        return gulp.start('build:style');
    });

    watch([path.watch.js], function(event, cb) {
        return gulp.start('build:js');
    });

    watch([path.watch.img], function(event, cb) {
        return gulp.start('build:img');
    });

    watch([path.watch.fonts], function(event, cb) {
        return gulp.start('build:fonts');
    });
});

// =============================
// -------- Main task ----------
// =============================

gulp.task('build:style', function (cb) {
    return runSequence(
        'build:css',
        'build:media'
    );
});

gulp.task('build', [
    'build:html',
    'build:style',
    'build:js',
    'build:img',
    'build:fonts'
]);

gulp.task('vendor', function (cb) {
    return runSequence(
        'bower',
        'filter',
        cb
    );
});

gulp.task('zip', function (cb) {
    return runSequence(
        'build',
        'build:zip',
        cb
    );
});

gulp.task('dev', [
    'build',
    'watch',
    'serve'
]);

// Default task
gulp.task('default', ['dev']);

// TODO: Разобрать таск и переписать
// Фильтруем библиотеки и вынимаем только нужные файлы
gulp.task('filter', function() {
    // Настраиваем фильтры для файлов
    const jsFilter = filter(['*.js', '!src/vendor'], {restore: true, passthrough: false});
    const cssFilter = filter(['*.css', '!src/vendor'], {restore: true, passthrough: false});

    // Для нормальных плагинов отработает этот кусок кода
    const stream = gulp.src([
        'bower_components/**/*.min.*',
        'bower_components/**/fonts/*',
        'bower_components/**/*.css',
        '!bower_components/**/*.map'
    ])

    // Фильтруем содержимое на наличие js и css
    .pipe(jsFilter)
    .pipe(cssFilter)
    // run them through a plugin
    .pipe(gulp.dest('dist'));

    // Вываливаем в билд
    jsFilter.restore.pipe(gulp.dest(path.build.libs));

    return stream;
});
<|endoftext|>


<commit_before>import template from './template.js';
import { merge } from 'lodash';

const defaults = {
  filters: [],
  reincorporate: false,
  persistence: true,
  audit: false,
  salienceFormula  (a) { return a; }
};

class Improv {

  constructor (snippets, options = {}) {
    /* Constructor for Improv generators. */
    /* We don't want to mutate the options object we've been given; we don't know
    where it's been. */
    const spec = {}; merge(spec, defaults, options);
    this.snippets = snippets;
    this.filters = spec.filters;
    this.reincorporate = Boolean(spec.reincorporate);
    this.persistence = Boolean(spec.persistence);
    this.audit = Boolean(spec.audit);
    this.salienceFormula = spec.salienceFormula;
    this.history = [];
    this.tagHistory = [];

    if (this.audit) this.instantiateAuditData();
  }

  __gen (snippet, model) {
    /*
      Actually generate text. Separate from #gen() because we don't want to clear
      history or error-handling data while a call to #gen() hasn't finished
      returning
    */
    /* For the sake of better error handling, we try to keep an accurate record
       of what snippet is being generated at any given time. */
    if (typeof model.bindings === 'object' && model.bindings[snippet]) {
      // The snippet already exists in the model's bindings.
      return model.bindings[snippet];
    }
    // Keep a stack of snippets we are using.
    const previousSnippet = this.currentSnippet;
    this.__currentSnippet = snippet;

    const chosenPhrase = this.selectPhrase(
      this.scoreFilter(
        this.applyFilters(snippet, model)
      ), model);
    this.history.unshift(chosenPhrase);

    // -- Auditing code begins -- //
    if (this.audit) {
      const phraseTotal = this.__phraseAudit.get(snippet).get(chosenPhrase);
      this.__phraseAudit.get(snippet).set(chosenPhrase, phraseTotal + 1);
    }
    // -- Auditing code ends -- //

    const output = template(chosenPhrase, model, this.__gen.bind(this));

    if (this.snippets[snippet].bind) {
      // Make sure the model has a bindings property
      if (typeof model.bindings === 'undefined') model.bindings = {};
      model.bindings[snippet] = output;
    }

    this.__currentSnippet = previousSnippet;
    return output;
  }

  get phraseAudit () {
    /* This is a getter so that the internals of how auditing data is stored
       and calculated can change without changing the API. */
    if (!this.audit) throw new Error('Tried retriving audit from generator not in auditing mode.');
    return this.__phraseAudit;
  }

  gen (snippet, model = {}) {
    /*
      Generate text (user-facing API). Since this function can recur, most of
      the heavy lifting is done in __gen().
    */
    // Make sure the model has a tag property.
    if (typeof model.tags === 'undefined') model.tags = [];

    if (typeof this.snippets[snippet] === 'undefined') {
      throw new Error(`Tried generating snippet "${snippet}", but no such snippet exists in spec`);
    }

    const output = this.__gen(snippet, model);

    if (!this.persistence) {
      this.clearHistory(); this.clearTagHistory();
    }

    return output;
  }

  mergeTags (model, groupTags) {
    /*
      Add a group's tags to the model, for reincorporation.
    */
    function mergeTag (a, b) {
      if (a.length < b.length) return b;
      return a;
    }

    groupTags.forEach(function (a) {
      // Find the corresponding tag in the model.
      const site = model.tags.findIndex(b => a[0] === b[0]);
      if (site === -1) {
        // No such tag; simply add the group's tags to the model.
        model.tags = model.tags.concat([a]);
      } else {
        model.tags[site] = mergeTag(model.tags[site], a);
      }
    });
  }

  selectPhrase (groups, model) {
    /*
      Once we have a list of suitable groups, finally select a phrase at random.
    */
    const phrases = this.flattenGroups(groups);
    if (phrases.length === 0) {
      if (this.audit) {
        console.log(groups);
        console.log(model);
      }
      throw new Error(`Ran out of phrases in ${groups} while generating ${this.__currentSnippet}`);
    }
    const chosen = phrases[Math.floor(Math.random() * phrases.length)];
    if (this.reincorporate) this.mergeTags(model, chosen[1]);
    if (Array.isArray(chosen[1])) {
      this.tagHistory = chosen[1].concat(this.tagHistory);
    }
    return chosen[0];
  }

  applyFiltersToGroup (group, model) {
    /*
      Run the filters through an individual group.
    */
    const output = { score: 0 };

    // Make sure the group has tags.
    if (typeof group.tags === 'undefined') group.tags = [];

    // Since we might return a different group than we got, we use a variable.
    let currentGroup = group;

    function applyFilterToGroup (cb) {
      if (output.score === null) return;

      const cbOutput = cb.call(this, currentGroup, model);

      let scoreOffset;

      if (Array.isArray(cbOutput)) {
        // We got a tuple, meaning the filter wants to modify the group before
        // moving on.
        scoreOffset = cbOutput[0];
        currentGroup = cbOutput[1];
      } else {
        scoreOffset = cbOutput;
      }
      if (scoreOffset === null) {
        output.score = null;
        return;
      }
      output.score += scoreOffset;
    }

    this.filters.forEach(applyFilterToGroup.bind(this));

    output.group = currentGroup;
    return output;
  }

  applyFilters (snippetName, model) {
    /*
      Starting with the raw list of groups, return a filtered list with
      scores.
    */
    if (typeof this.snippets[snippetName] === 'undefined')
      throw new Error(`Missing snippet object for snippet ${snippetName}.`)
    const groups = this.snippets[snippetName].groups;
    if (!Array.isArray(groups))
      throw new Error(`Missing or bad groups array for snippet ${snippetName}; was ${typeof groups}`);
    return groups.map(group => this.applyFiltersToGroup(group, model))
      .filter(o => o.score !== null);
  }

  scoreFilter (groups) {
    /*
      Starting with the scored list from applyFilters(), return a list that has
      invalid groups scrubbed out and only includes groups with a score past
      the threshold.
    */
    // Filter out groups emptied out by dryness()
    const validGroups = groups.filter(g => g.group.phrases.length > 0);
    const maxScore = validGroups
      .reduce((currentMax, b) => b.score > currentMax ? b.score : currentMax,
      Number.NEGATIVE_INFINITY);
    const scoreThreshold = this.salienceFormula(maxScore);
    return validGroups.filter(o => o.score >= scoreThreshold);
  }

  flattenGroups (groups) {
    /*
      Starting with a list of scored groups, flatten them into a simple list
      of phrases.
    */
    return groups
      .map(o => o.group.phrases.map(i => [i, o.group.tags]))
      .reduce((a, b) => a.concat(b), []);
  }

  clearHistory () { this.history = []; }

  clearTagHistory () { this.tagHistory = []; }

  instantiateAuditData () {
    /*
      Create and fill audit maps with starter data, ie zeroes.
    */
    this.__phraseAudit = new Map();
    const self = this;

    Object.keys(this.snippets).forEach(function (key) {
      self.phraseAudit.set(key, new Map());
      self.snippets[key].groups.forEach(function (group) {
        group.phrases.forEach(function (phrase) {
          self.__phraseAudit.get(key).set(phrase, 0);
        });
      });
    });
  }
}

import filters from './filters.js';

Improv.filters = filters;

export default Improv;
<commit_msg>Fix eslint errors<commit_after>import template from './template.js';
import { merge } from 'lodash';

const defaults = {
  filters: [],
  reincorporate: false,
  persistence: true,
  audit: false,
  salienceFormula  (a) { return a; }
};

class Improv {

  constructor (snippets, options = {}) {
    /* Constructor for Improv generators. */
    /* We don't want to mutate the options object we've been given; we don't know
    where it's been. */
    const spec = {}; merge(spec, defaults, options);
    this.snippets = snippets;
    this.filters = spec.filters;
    this.reincorporate = Boolean(spec.reincorporate);
    this.persistence = Boolean(spec.persistence);
    this.audit = Boolean(spec.audit);
    this.salienceFormula = spec.salienceFormula;
    this.history = [];
    this.tagHistory = [];

    if (this.audit) this.instantiateAuditData();
  }

  __gen (snippet, model) {
    /*
      Actually generate text. Separate from #gen() because we don't want to clear
      history or error-handling data while a call to #gen() hasn't finished
      returning
    */
    /* For the sake of better error handling, we try to keep an accurate record
       of what snippet is being generated at any given time. */
    if (typeof model.bindings === 'object' && model.bindings[snippet]) {
      // The snippet already exists in the model's bindings.
      return model.bindings[snippet];
    }
    // Keep a stack of snippets we are using.
    const previousSnippet = this.currentSnippet;
    this.__currentSnippet = snippet;

    const chosenPhrase = this.selectPhrase(
      this.scoreFilter(
        this.applyFilters(snippet, model)
      ), model);
    this.history.unshift(chosenPhrase);

    // -- Auditing code begins -- //
    if (this.audit) {
      const phraseTotal = this.__phraseAudit.get(snippet).get(chosenPhrase);
      this.__phraseAudit.get(snippet).set(chosenPhrase, phraseTotal + 1);
    }
    // -- Auditing code ends -- //

    const output = template(chosenPhrase, model, this.__gen.bind(this));

    if (this.snippets[snippet].bind) {
      // Make sure the model has a bindings property
      if (typeof model.bindings === 'undefined') model.bindings = {};
      model.bindings[snippet] = output;
    }

    this.__currentSnippet = previousSnippet;
    return output;
  }

  get phraseAudit () {
    /* This is a getter so that the internals of how auditing data is stored
       and calculated can change without changing the API. */
    if (!this.audit) throw new Error('Tried retriving audit from generator not in auditing mode.');
    return this.__phraseAudit;
  }

  gen (snippet, model = {}) {
    /*
      Generate text (user-facing API). Since this function can recur, most of
      the heavy lifting is done in __gen().
    */
    // Make sure the model has a tag property.
    if (typeof model.tags === 'undefined') model.tags = [];

    if (typeof this.snippets[snippet] === 'undefined') {
      throw new Error(`Tried generating snippet "${snippet}", but no such snippet exists in spec`);
    }

    const output = this.__gen(snippet, model);

    if (!this.persistence) {
      this.clearHistory(); this.clearTagHistory();
    }

    return output;
  }

  mergeTags (model, groupTags) {
    /*
      Add a group's tags to the model, for reincorporation.
    */
    function mergeTag (a, b) {
      if (a.length < b.length) return b;
      return a;
    }

    groupTags.forEach(function (a) {
      // Find the corresponding tag in the model.
      const site = model.tags.findIndex(b => a[0] === b[0]);
      if (site === -1) {
        // No such tag; simply add the group's tags to the model.
        model.tags = model.tags.concat([a]);
      } else {
        model.tags[site] = mergeTag(model.tags[site], a);
      }
    });
  }

  selectPhrase (groups, model) {
    /*
      Once we have a list of suitable groups, finally select a phrase at random.
    */
    const phrases = this.flattenGroups(groups);
    if (phrases.length === 0) {
      if (this.audit) {
        console.log(groups);
        console.log(model);
      }
      throw new Error(`Ran out of phrases in ${groups} while generating ${this.__currentSnippet}`);
    }
    const chosen = phrases[Math.floor(Math.random() * phrases.length)];
    if (this.reincorporate) this.mergeTags(model, chosen[1]);
    if (Array.isArray(chosen[1])) {
      this.tagHistory = chosen[1].concat(this.tagHistory);
    }
    return chosen[0];
  }

  applyFiltersToGroup (group, model) {
    /*
      Run the filters through an individual group.
    */
    const output = { score: 0 };

    // Make sure the group has tags.
    if (typeof group.tags === 'undefined') group.tags = [];

    // Since we might return a different group than we got, we use a variable.
    let currentGroup = group;

    function applyFilterToGroup (cb) {
      if (output.score === null) return;

      const cbOutput = cb.call(this, currentGroup, model);

      let scoreOffset;

      if (Array.isArray(cbOutput)) {
        // We got a tuple, meaning the filter wants to modify the group before
        // moving on.
        scoreOffset = cbOutput[0];
        currentGroup = cbOutput[1];
      } else {
        scoreOffset = cbOutput;
      }
      if (scoreOffset === null) {
        output.score = null;
        return;
      }
      output.score += scoreOffset;
    }

    this.filters.forEach(applyFilterToGroup.bind(this));

    output.group = currentGroup;
    return output;
  }

  applyFilters (snippetName, model) {
    /*
      Starting with the raw list of groups, return a filtered list with
      scores.
    */
    if (typeof this.snippets[snippetName] === 'undefined') {
      throw new Error(`Missing snippet object for snippet ${snippetName}.`);
    }
    const groups = this.snippets[snippetName].groups;
    if (!Array.isArray(groups)) {
      throw new Error(`Missing or bad groups array for snippet ${snippetName}; was ${typeof groups}`);
    }
    return groups.map(group => this.applyFiltersToGroup(group, model))
      .filter(o => o.score !== null);
  }

  scoreFilter (groups) {
    /*
      Starting with the scored list from applyFilters(), return a list that has
      invalid groups scrubbed out and only includes groups with a score past
      the threshold.
    */
    // Filter out groups emptied out by dryness()
    const validGroups = groups.filter(g => g.group.phrases.length > 0);
    const maxScore = validGroups
      .reduce((currentMax, b) => b.score > currentMax ? b.score : currentMax,
      Number.NEGATIVE_INFINITY);
    const scoreThreshold = this.salienceFormula(maxScore);
    return validGroups.filter(o => o.score >= scoreThreshold);
  }

  flattenGroups (groups) {
    /*
      Starting with a list of scored groups, flatten them into a simple list
      of phrases.
    */
    return groups
      .map(o => o.group.phrases.map(i => [i, o.group.tags]))
      .reduce((a, b) => a.concat(b), []);
  }

  clearHistory () { this.history = []; }

  clearTagHistory () { this.tagHistory = []; }

  instantiateAuditData () {
    /*
      Create and fill audit maps with starter data, ie zeroes.
    */
    this.__phraseAudit = new Map();
    const self = this;

    Object.keys(this.snippets).forEach(function (key) {
      self.phraseAudit.set(key, new Map());
      self.snippets[key].groups.forEach(function (group) {
        group.phrases.forEach(function (phrase) {
          self.__phraseAudit.get(key).set(phrase, 0);
        });
      });
    });
  }
}

import filters from './filters.js';

Improv.filters = filters;

export default Improv;
<|endoftext|>