[Pkg-javascript-commits] [node-classnames] 01/02: Import Upstream version 2.2.5

Daniel Ring techwolf-guest at moszumanska.debian.org
Fri Dec 15 10:03:22 UTC 2017


This is an automated email from the git hooks/post-receive script.

techwolf-guest pushed a commit to branch master
in repository node-classnames.

commit 83877ff1a4e745429fa815f466da1d13ab2c1bf0
Author: Daniel Ring <dring at wolfishly.me>
Date:   Fri Dec 15 00:39:22 2017 -0800

    Import Upstream version 2.2.5
---
 .editorconfig           |  14 ++++
 .gitignore              |  26 +++++++
 .npmignore              |   4 ++
 .travis.yml             |  10 +++
 CONTRIBUTING.md         |  21 ++++++
 HISTORY.md              |  81 +++++++++++++++++++++
 LICENSE                 |  21 ++++++
 README.md               | 188 ++++++++++++++++++++++++++++++++++++++++++++++++
 benchmarks/package.json |  16 +++++
 benchmarks/run.js       |  97 +++++++++++++++++++++++++
 bind.js                 |  48 +++++++++++++
 bower.json              |  37 ++++++++++
 dedupe.js               | 109 ++++++++++++++++++++++++++++
 index.js                |  48 +++++++++++++
 package.json            |  30 ++++++++
 tests/bind.js           | 146 +++++++++++++++++++++++++++++++++++++
 tests/dedupe.js         |  77 ++++++++++++++++++++
 tests/index.js          |  62 ++++++++++++++++
 18 files changed, 1035 insertions(+)

diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..396ff4f
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,14 @@
+# This file is for unifying the coding style for different editors and IDEs
+# editorconfig.org
+root = true
+
+[*]
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = false
+insert_final_newline = true
+indent_style = tab
+
+[*.json]
+indent_style = space
+indent_size = 2
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..33e56de
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,26 @@
+# Logs
+logs
+*.log
+
+# Runtime data
+pids
+*.pid
+*.seed
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory
+coverage
+
+# Compiled binary addons (http://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directory
+node_modules
+
+# Users Environment Variables
+.lock-wscript
+
+# Mac OS X DS_Store
+.DS_Store
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..92100ce
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,4 @@
+/.*/
+/.*
+/benchmarks/
+/tests/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..3264f36
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,10 @@
+language: node_js
+before_install:
+  - "npm install npm -g"
+node_js:
+  - "0.10"
+  - "0.12"
+  - "iojs"
+env:
+  - TEST_SUITE=unit
+script: "npm run-script $TEST_SUITE"
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..5904061
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,21 @@
+# Contributing
+
+Thanks for your interest in classNames. Issues, PRs and suggestions welcome :)
+
+Before working on a PR, please consider the following:
+
+* Speed is a serious concern for this package as it is likely to be called a
+significant number of times in any project that uses it. As such, new features
+will only be accepted if they improve (or at least do not negatively impact)
+performance.
+* To demonstrate performance differences please set up a
+[JSPerf](http://jsperf.com) test and link to it from your issue / PR.
+* Tests must be added for any change or new feature before it will be accepted.
+
+A benchmark utilitiy is included so that changes may be tested against the
+current published version. To run the benchmarks, `npm install` in the
+`./benchmarks` directory then run `npm run benchmarks` in the package root.
+
+Please be aware though that local benchmarks are just a smoke-signal; they will
+run in the v8 version that your node/iojs uses, while classNames is _most_
+often run across a wide variety of browsers and browser versions.
diff --git a/HISTORY.md b/HISTORY.md
new file mode 100644
index 0000000..492952f
--- /dev/null
+++ b/HISTORY.md
@@ -0,0 +1,81 @@
+# Changelog
+
+## v2.2.5 / 2016-05-02
+
+* Improved performance of `dedupe` variant even further, thanks [Andres Suarez](https://github.com/zertosh)
+
+## v2.2.4 / 2016-04-25
+
+* Improved performance of `dedupe` variant by about 2x, thanks [Bartosz Gościński](https://github.com/bgoscinski)
+
+## v2.2.3 / 2016-01-05
+
+* Updated `bind` variant to use `[].join(' ')` as per the main script in 2.2.2
+
+## v2.2.2 / 2016-01-04
+
+* Switched from string concatenation to `[].join(' ')` for a slight performance gain in the main function.
+
+## v2.2.1 / 2015-11-26
+
+* Add deps parameter to the AMD module, fixes an issue using the Dojo loader, thanks [Chris Jordan](https://github.com/flipperkid)
+
+## v2.2.0 / 2015-10-18
+
+* added a new `bind` variant for use with [css-modules](https://github.com/css-modules/css-modules) and similar abstractions, thanks to [Kirill Yakovenko](https://github.com/blia)
+
+## v2.1.5 / 2015-09-30
+
+* reverted a new usage of `Object.keys` in `dedupe.js` that slipped through in the last release
+
+## v2.1.4 / 2015-09-30
+
+* new case added to benchmarks
+* safer `hasOwnProperty` check
+* AMD module is now named, so you can do the following:
+
+```
+define(["classnames"], function (classNames) {
+  var style = classNames("foo", "bar");
+  // ...
+});
+```
+
+## v2.1.3 / 2015-07-02
+
+* updated UMD wrapper to support AMD and CommonJS on the same pacge
+
+## v2.1.2 / 2015-05-28
+
+* added a proper UMD wrapper
+
+## v2.1.1 / 2015-05-06
+
+* minor performance improvement thanks to type caching
+* improved benchmarking and results output
+
+## v2.1.0 / 2015-05-05
+
+* added alternate `dedupe` version of classNames, which is slower (10x) but ensures that if a class is added then overridden by a falsy value in a subsequent argument, it is excluded from the result.
+
+## v2.0.0 / 2015-05-03
+
+* performance improvement; switched to `Array.isArray` for type detection, which is much faster in modern browsers. A polyfill is now required for IE8 support, see the Readme for details.
+
+## v1.2.2 / 2015-04-28
+
+* license comment updates to simiplify certain build scenarios
+
+## v1.2.1 / 2015-04-22
+
+* added safe exporting for requireJS usage
+* clarified Bower usage and instructions
+
+## v1.2.0 / 2015-03-17
+
+* added comprehensive support for array arguments, including nested arrays
+* simplified code slightly
+
+## Previous
+
+Please see the git history for the details of previous versions.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..e6620b5
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Jed Watson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..265a2ba
--- /dev/null
+++ b/README.md
@@ -0,0 +1,188 @@
+Classnames
+===========
+
+[![Version](http://img.shields.io/npm/v/classnames.svg)](https://www.npmjs.org/package/classnames)
+[![Build Status](https://travis-ci.org/JedWatson/classnames.svg?branch=master)](https://travis-ci.org/JedWatson/classnames)
+
+A simple javascript utility for conditionally joining classNames together.
+
+Install with npm or Bower.
+
+```sh
+npm install classnames
+```
+
+Use with node.js, browserify or webpack:
+
+```js
+var classNames = require('classnames');
+classNames('foo', 'bar'); // => 'foo bar'
+```
+
+Alternatively, you can simply include `index.js` on your page with a standalone `<script>` tag and it will export a global `classNames` method, or define the module if you are using RequireJS.
+
+### Project philosophy
+
+We take the stability and performance of this package seriously, because it is run millions of times a day in browsers all around the world. Updates are thoroughly reviewed for performance impacts before being released, and we have a comprehensive test suite.
+
+Classnames follows the [SemVer](http://semver.org/) standard for versioning.
+
+There is also a [Changelog](https://github.com/JedWatson/classnames/blob/master/HISTORY.md).
+
+## Usage
+
+The `classNames` function takes any number of arguments which can be a string or object.
+The argument `'foo'` is short for `{ foo: true }`. If the value of the key is falsy, it won't be included in the output.
+
+```js
+classNames('foo', 'bar'); // => 'foo bar'
+classNames('foo', { bar: true }); // => 'foo bar'
+classNames({ 'foo-bar': true }); // => 'foo-bar'
+classNames({ 'foo-bar': false }); // => ''
+classNames({ foo: true }, { bar: true }); // => 'foo bar'
+classNames({ foo: true, bar: true }); // => 'foo bar'
+
+// lots of arguments of various types
+classNames('foo', { bar: true, duck: false }, 'baz', { quux: true }); // => 'foo bar baz quux'
+
+// other falsy values are just ignored
+classNames(null, false, 'bar', undefined, 0, 1, { baz: null }, ''); // => 'bar 1'
+```
+
+Arrays will be recursively flattened as per the rules above:
+
+```js
+var arr = ['b', { c: true, d: false }];
+classNames('a', arr); // => 'a b c'
+```
+
+### Dynamic class names with ES2015
+
+If you're in an environment that supports [computed keys](http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer) (available in ES2015 and Babel) you can use dynamic class names:
+
+```js
+let buttonType = 'primary';
+classNames({ [`btn-${buttonType}`]: true });
+```
+
+### Usage with React.js
+
+This package is the official replacement for `classSet`, which was originally shipped in the React.js Addons bundle.
+
+One of its primary use cases is to make dynamic and conditional className props simpler to work with (especially more so than conditional string manipulation). So where you may have the following code to generate a `className` prop for a `<button>` in React:
+
+```js
+var Button = React.createClass({
+  // ...
+  render () {
+    var btnClass = 'btn';
+    if (this.state.isPressed) btnClass += ' btn-pressed';
+    else if (this.state.isHovered) btnClass += ' btn-over';
+    return <button className={btnClass}>{this.props.label}</button>;
+  }
+});
+```
+
+You can express the conditional classes more simply as an object:
+
+```js
+var classNames = require('classnames');
+
+var Button = React.createClass({
+  // ...
+  render () {
+    var btnClass = classNames({
+      'btn': true,
+      'btn-pressed': this.state.isPressed,
+      'btn-over': !this.state.isPressed && this.state.isHovered
+    });
+    return <button className={btnClass}>{this.props.label}</button>;
+  }
+});
+```
+
+Because you can mix together object, array and string arguments, supporting optional className props is also simpler as only truthy arguments get included in the result:
+
+```js
+var btnClass = classNames('btn', this.props.className, {
+  'btn-pressed': this.state.isPressed,
+  'btn-over': !this.state.isPressed && this.state.isHovered
+});
+```
+
+
+### Alternate `dedupe` version
+
+There is an alternate version of `classNames` available which correctly dedupes classes and ensures that falsy classes specified in later arguments are excluded from the result set.
+
+This version is slower (about 5x) so it is offered as an opt-in.
+
+To use the dedupe version with node, browserify or webpack:
+
+```js
+var classNames = require('classnames/dedupe');
+
+classNames('foo', 'foo', 'bar'); // => 'foo bar'
+classNames('foo', { foo: false, bar: true }); // => 'bar'
+```
+
+For standalone (global / AMD) use, include `dedupe.js` in a `<script>` tag on your page.
+
+
+### Alternate `bind` version (for [css-modules](https://github.com/css-modules/css-modules))
+
+If you are using [css-modules](https://github.com/css-modules/css-modules), or a similar approach to abstract class "names" and the real `className` values that are actually output to the DOM, you may want to use the `bind` variant.
+
+_Note that in ES2015 environments, it may be better to use the "dynamic class names" approach documented above._
+
+```js
+var classNames = require('classnames/bind');
+
+var styles = {
+  foo: 'abc',
+  bar: 'def',
+  baz: 'xyz'
+};
+
+var cx = classNames.bind(styles);
+
+var className = cx('foo', ['bar'], { baz: true }); // => "abc def xyz"
+```
+
+Real-world example:
+
+```js
+/* components/submit-button.js */
+import { Component } from 'react';
+import classNames from 'classnames/bind';
+import styles from './submit-button.css';
+
+let cx = classNames.bind(styles);
+
+export default class SubmitButton extends Component {
+  render () {
+    let text = this.props.store.submissionInProgress ? 'Processing...' : 'Submit';
+    let className = cx({
+      base: true,
+      inProgress: this.props.store.submissionInProgress,
+      error: this.props.store.errorOccurred,
+      disabled: this.props.form.valid,
+    });
+    return <button className={className}>{text}</button>;
+  }
+};
+
+```
+
+
+## Polyfills needed to support older browsers
+
+#### `classNames >=2.0.0`
+
+`Array.isArray`: see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray) for details about unsupported older browsers (e.g. <= IE8) and a simple polyfill.
+
+`Object.keys`: see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) for details about unsupported older browsers (e.g. <= IE8) and a simple polyfill. This is only used in `dedupe.js`.
+
+## License
+
+[MIT](LICENSE). Copyright (c) 2016 Jed Watson.
diff --git a/benchmarks/package.json b/benchmarks/package.json
new file mode 100644
index 0000000..92ff0c3
--- /dev/null
+++ b/benchmarks/package.json
@@ -0,0 +1,16 @@
+{
+  "name": "classnames-benchmarks",
+  "version": "1.0.0",
+  "private": true,
+  "description": "",
+  "main": "run.js",
+  "scripts": {
+    "test": "echo \"Tests should be run in the main classnames package.\" && exit 1"
+  },
+  "author": "Jed Watson",
+  "license": "MIT",
+  "devDependencies": {
+    "benchmark": "^1.0.0",
+    "classnames": "*"
+  }
+}
diff --git a/benchmarks/run.js b/benchmarks/run.js
new file mode 100644
index 0000000..88ab063
--- /dev/null
+++ b/benchmarks/run.js
@@ -0,0 +1,97 @@
+var fixtures = [
+	{
+		description: 'strings',
+		args: ['one', 'two', 'three'],
+		expected: 'one two three'
+	},
+	{
+		description: 'object',
+		args: [{ one: true, two: true, three: false }],
+		expected: 'one two'
+	},
+	{
+		description: 'strings, object',
+		args: ['one', 'two', { four: true, three: false }],
+		expected: 'one two four'
+	},
+	{
+		description: 'mix',
+		args: ['one', { two: true, three: false }, { four: 'four', five: true }, 6, {}],
+		expected: 'one two four five 6'
+	},
+	{
+		description: 'arrays',
+		args: [['one', 'two'], ['three'], ['four', ['five']], [{ six: true }, { seven: false }]],
+		expected: 'one two three four five six'
+	}
+];
+
+var local = require('../');
+var dedupe = require('../dedupe');
+var localPackage = require('../package.json');
+
+try {
+	var npm = require('classnames');
+	var npmDedupe = require('classnames/dedupe');
+	var npmPackage = require('./node_modules/classnames/package.json');
+} catch (e) {
+	console.log('There was an error loading the benchmark classnames package.\n' +
+		'Please make sure you have run `npm install` in ./benchmarks\n');
+	process.exit(0);
+}
+
+if (localPackage.version !== npmPackage.version) {
+	console.log('Your local version (' + localPackage.version + ') does not match the installed version (' + npmPackage.version + ')\n\n' +
+		'Please run `npm update` in ./benchmarks to ensure you are benchmarking\n' +
+		'the latest version of this package.\n');
+	process.exit(0);
+}
+
+var assert = require('assert');
+var benchmark = require('benchmark');
+
+function sortClasses (str) {
+	return str.split(' ').sort().join(' ');
+}
+
+fixtures.forEach(function (f) {
+	// sort assertions because dedupe returns results in a different order
+	assert.equal(sortClasses(local.apply(null, f.args)), sortClasses(f.expected));
+	assert.equal(sortClasses(dedupe.apply(null, f.args)), sortClasses(f.expected));
+	assert.equal(sortClasses(npm.apply(null, f.args)), sortClasses(f.expected));
+	assert.equal(sortClasses(npmDedupe.apply(null, f.args)), sortClasses(f.expected));
+
+	var suite = new benchmark.Suite();
+
+	suite.add('local#' + f.description, function () {
+		local.apply(null, f.args);
+	});
+
+	suite.add('  npm#' + f.description, function () {
+		npm.apply(null, f.args);
+	});
+
+	suite.add('local/dedupe#' + f.description, function () {
+		dedupe.apply(null, f.args);
+	});
+
+	suite.add('  npm/dedupe#' + f.description, function () {
+		npmDedupe.apply(null, f.args);
+	});
+
+	// after each cycle
+	suite.on('cycle', function (event) {
+		console.log('*', String(event.target));
+	});
+
+	// other handling
+	suite.on('complete', function () {
+		console.log('\n> Fastest is' + (' ' + this.filter('fastest').pluck('name').join(' | ')).replace(/\s+/, ' ') + '\n');
+	});
+
+	suite.on('error', function (event) {
+		throw event.target.error;
+	});
+
+	suite.run();
+});
diff --git a/bind.js b/bind.js
new file mode 100644
index 0000000..342aa68
--- /dev/null
+++ b/bind.js
@@ -0,0 +1,48 @@
+/*!
+  Copyright (c) 2016 Jed Watson.
+  Licensed under the MIT License (MIT), see
+  http://jedwatson.github.io/classnames
+*/
+/* global define */
+
+(function () {
+	'use strict';
+
+	var hasOwn = {}.hasOwnProperty;
+
+	function classNames () {
+		var classes = [];
+
+		for (var i = 0; i < arguments.length; i++) {
+			var arg = arguments[i];
+			if (!arg) continue;
+
+			var argType = typeof arg;
+
+			if (argType === 'string' || argType === 'number') {
+				classes.push(this && this[arg] || arg);
+			} else if (Array.isArray(arg)) {
+				classes.push(classNames.apply(this, arg));
+			} else if (argType === 'object') {
+				for (var key in arg) {
+					if (hasOwn.call(arg, key) && arg[key]) {
+						classes.push(this && this[key] || key);
+					}
+				}
+			}
+		}
+
+		return classes.join(' ');
+	}
+
+	if (typeof module !== 'undefined' && module.exports) {
+		module.exports = classNames;
+	} else if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
+		// register as 'classnames', consistent with npm package name
+		define('classnames', [], function () {
+			return classNames;
+		});
+	} else {
+		window.classNames = classNames;
+	}
+}());
diff --git a/bower.json b/bower.json
new file mode 100644
index 0000000..0619a48
--- /dev/null
+++ b/bower.json
@@ -0,0 +1,37 @@
+{
+  "name": "classnames",
+  "version": "2.2.5",
+  "description": "A simple utility for conditionally joining classNames together",
+  "main": [
+    "index.js",
+    "bind.js",
+    "dedupe.js"
+  ],
+  "homepage": "https://github.com/JedWatson/classnames",
+  "authors": [
+    "Jed Watson"
+  ],
+  "moduleType": [
+    "amd",
+    "globals",
+    "node"
+  ],
+  "keywords": [
+    "react",
+    "css",
+    "classes",
+    "classname",
+    "classnames",
+    "util",
+    "utility"
+  ],
+  "license": "MIT",
+  "ignore": [
+    ".editorconfig",
+    ".gitignore",
+    "gulpfile.js",
+    "package.json",
+    "node_modules",
+    "tests.js"
+  ]
+}
diff --git a/dedupe.js b/dedupe.js
new file mode 100644
index 0000000..139fddc
--- /dev/null
+++ b/dedupe.js
@@ -0,0 +1,109 @@
+/*!
+  Copyright (c) 2016 Jed Watson.
+  Licensed under the MIT License (MIT), see
+  http://jedwatson.github.io/classnames
+*/
+/* global define */
+
+(function () {
+	'use strict';
+
+	var classNames = (function () {
+		// don't inherit from Object so we can skip hasOwnProperty check later
+		// http://stackoverflow.com/questions/15518328/creating-js-object-with-object-createnull#answer-21079232
+		function StorageObject() {}
+		StorageObject.prototype = Object.create(null);
+
+		function _parseArray (resultSet, array) {
+			var length = array.length;
+
+			for (var i = 0; i < length; ++i) {
+				_parse(resultSet, array[i]);
+			}
+		}
+
+		var hasOwn = {}.hasOwnProperty;
+
+		function _parseNumber (resultSet, num) {
+			resultSet[num] = true;
+		}
+
+		function _parseObject (resultSet, object) {
+			for (var k in object) {
+				if (hasOwn.call(object, k)) {
+					// set value to false instead of deleting it to avoid changing object structure
+					// https://www.smashingmagazine.com/2012/11/writing-fast-memory-efficient-javascript/#de-referencing-misconceptions
+					resultSet[k] = !!object[k];
+				}
+			}
+		}
+
+		var SPACE = /\s+/;
+		function _parseString (resultSet, str) {
+			var array = str.split(SPACE);
+			var length = array.length;
+
+			for (var i = 0; i < length; ++i) {
+				resultSet[array[i]] = true;
+			}
+		}
+
+		function _parse (resultSet, arg) {
+			if (!arg) return;
+			var argType = typeof arg;
+
+			// 'foo bar'
+			if (argType === 'string') {
+				_parseString(resultSet, arg);
+
+			// ['foo', 'bar', ...]
+			} else if (Array.isArray(arg)) {
+				_parseArray(resultSet, arg);
+
+			// { 'foo': true, ... }
+			} else if (argType === 'object') {
+				_parseObject(resultSet, arg);
+
+			// '130'
+			} else if (argType === 'number') {
+				_parseNumber(resultSet, arg);
+			}
+		}
+
+		function _classNames () {
+			// don't leak arguments
+			// https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments
+			var len = arguments.length;
+			var args = Array(len);
+			for (var i = 0; i < len; i++) {
+				args[i] = arguments[i];
+			}
+
+			var classSet = new StorageObject();
+			_parseArray(classSet, args);
+
+			var list = [];
+
+			for (var k in classSet) {
+				if (classSet[k]) {
+					list.push(k)
+				}
+			}
+
+			return list.join(' ');
+		}
+
+		return _classNames;
+	})();
+
+	if (typeof module !== 'undefined' && module.exports) {
+		module.exports = classNames;
+	} else if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
+		// register as 'classnames', consistent with npm package name
+		define('classnames', [], function () {
+			return classNames;
+		});
+	} else {
+		window.classNames = classNames;
+	}
+}());
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..169de84
--- /dev/null
+++ b/index.js
@@ -0,0 +1,48 @@
+/*!
+  Copyright (c) 2016 Jed Watson.
+  Licensed under the MIT License (MIT), see
+  http://jedwatson.github.io/classnames
+*/
+/* global define */
+
+(function () {
+	'use strict';
+
+	var hasOwn = {}.hasOwnProperty;
+
+	function classNames () {
+		var classes = [];
+
+		for (var i = 0; i < arguments.length; i++) {
+			var arg = arguments[i];
+			if (!arg) continue;
+
+			var argType = typeof arg;
+
+			if (argType === 'string' || argType === 'number') {
+				classes.push(arg);
+			} else if (Array.isArray(arg)) {
+				classes.push(classNames.apply(null, arg));
+			} else if (argType === 'object') {
+				for (var key in arg) {
+					if (hasOwn.call(arg, key) && arg[key]) {
+						classes.push(key);
+					}
+				}
+			}
+		}
+
+		return classes.join(' ');
+	}
+
+	if (typeof module !== 'undefined' && module.exports) {
+		module.exports = classNames;
+	} else if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
+		// register as 'classnames', consistent with npm package name
+		define('classnames', [], function () {
+			return classNames;
+		});
+	} else {
+		window.classNames = classNames;
+	}
+}());
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..04eec26
--- /dev/null
+++ b/package.json
@@ -0,0 +1,30 @@
+{
+  "name": "classnames",
+  "version": "2.2.5",
+  "description": "A simple utility for conditionally joining classNames together",
+  "main": "index.js",
+  "author": "Jed Watson",
+  "license": "MIT",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/JedWatson/classnames.git"
+  },
+  "scripts": {
+    "benchmarks": "node ./benchmarks/run",
+    "unit": "mocha tests/*.js",
+    "test": "npm run unit"
+  },
+  "keywords": [
+    "react",
+    "css",
+    "classes",
+    "classname",
+    "classnames",
+    "util",
+    "utility"
+  ],
+  "devDependencies": {
+    "benchmark": "^1.0.0",
+    "mocha": "^2.1.0"
+  }
+}
diff --git a/tests/bind.js b/tests/bind.js
new file mode 100644
index 0000000..e241a1e
--- /dev/null
+++ b/tests/bind.js
@@ -0,0 +1,146 @@
+/* global describe, it */
+
+var assert = require('assert');
+var classNames = require('../bind');
+
+var cssModulesMock = {
+	a: "#a",
+	b: "#b",
+	c: "#c",
+	d: "#d",
+	e: "#e",
+	f: "#f"
+};
+
+var classNamesBound = classNames.bind(cssModulesMock);
+
+describe('bind', function () {
+	describe('classNames', function () {
+		it('keeps object keys with truthy values', function () {
+			assert.equal(classNames({
+				a: true,
+				b: false,
+				c: 0,
+				d: null,
+				e: undefined,
+				f: 1
+			}), 'a f');
+		});
+
+		it('joins arrays of class names and ignore falsy values', function () {
+			assert.equal(classNames('a', 0, null, undefined, true, 1, 'b'), 'a 1 b');
+		});
+
+		it('supports heterogenous arguments', function () {
+			assert.equal(classNames({a: true}, 'b', 0), 'a b');
+		});
+
+		it('should be trimmed', function () {
+			assert.equal(classNames('', 'b', {}, ''), 'b');
+		});
+
+		it('returns an empty string for an empty configuration', function () {
+			assert.equal(classNames({}), '');
+		});
+
+		it('supports an array of class names', function () {
+			assert.equal(classNames(['a', 'b']), 'a b');
+		});
+
+		it('joins array arguments with string arguments', function () {
+			assert.equal(classNames(['a', 'b'], 'c'), 'a b c');
+			assert.equal(classNames('c', ['a', 'b']), 'c a b');
+		});
+
+		it('handles multiple array arguments', function () {
+			assert.equal(classNames(['a', 'b'], ['c', 'd']), 'a b c d');
+		});
+
+		it('handles arrays that include falsy and true values', function () {
+			assert.equal(classNames(['a', 0, null, undefined, false, true, 'b']), 'a b');
+		});
+
+		it('handles arrays that include arrays', function () {
+			assert.equal(classNames(['a', ['b', 'c']]), 'a b c');
+		});
+
+		it('handles arrays that include objects', function () {
+			assert.equal(classNames(['a', {b: true, c: false}]), 'a b');
+		});
+
+		it('handles deep array recursion', function () {
+			assert.equal(classNames(['a', ['b', ['c', {d: true}]]]), 'a b c d');
+		});
+	});
+
+	describe('classNamesBound', function () {
+		it('keeps object keys with truthy values', function () {
+			assert.equal(classNamesBound({
+				a: true,
+				b: false,
+				c: 0,
+				d: null,
+				e: undefined,
+				f: 1
+			}), '#a #f');
+		});
+		it('keeps class names undefined in bound hash', function () {
+			assert.equal(classNamesBound({
+				a: true,
+				b: false,
+				c: 0,
+				d: null,
+				e: undefined,
+				f: 1,
+				x: true,
+				y: null,
+				z: 1
+			}), '#a #f x z');
+		})
+		it('joins arrays of class names and ignore falsy values', function () {
+			assert.equal(classNamesBound('a', 0, null, undefined, true, 1, 'b'), '#a 1 #b');
+		});
+
+		it('supports heterogenous arguments', function () {
+			assert.equal(classNamesBound({a: true}, 'b', 0), '#a #b');
+		});
+
+		it('should be trimmed', function () {
+			assert.equal(classNamesBound('', 'b', {}, ''), '#b');
+		});
+
+		it('returns an empty string for an empty configuration', function () {
+			assert.equal(classNamesBound({}), '');
+		});
+
+		it('supports an array of class names', function () {
+			assert.equal(classNamesBound(['a', 'b']), '#a #b');
+		});
+
+		it('joins array arguments with string arguments', function () {
+			assert.equal(classNamesBound(['a', 'b'], 'c'), '#a #b #c');
+			assert.equal(classNamesBound('c', ['a', 'b']), '#c #a #b');
+		});
+
+		it('handles multiple array arguments', function () {
+			assert.equal(classNamesBound(['a', 'b'], ['c', 'd']), '#a #b #c #d');
+		});
+
+		it('handles arrays that include falsy and true values', function () {
+			assert.equal(classNamesBound(['a', 0, null, undefined, false, true, 'b']), '#a #b');
+		});
+
+		it('handles arrays that include arrays', function () {
+			assert.equal(classNamesBound(['a', ['b', 'c']]), '#a #b #c');
+		});
+
+		it('handles arrays that include objects', function () {
+			assert.equal(classNamesBound(['a', {b: true, c: false}]), '#a #b');
+		});
+
+		it('handles deep array recursion', function () {
+			assert.equal(classNamesBound(['a', ['b', ['c', {d: true}]]]), '#a #b #c #d');
+		});
+	});
+
+})
diff --git a/tests/dedupe.js b/tests/dedupe.js
new file mode 100644
index 0000000..41dc71e
--- /dev/null
+++ b/tests/dedupe.js
@@ -0,0 +1,77 @@
+/* global describe, it */
+
+var assert = require('assert');
+var dedupe = require('../dedupe');
+
+describe('dedupe', function () {
+	it('keeps object keys with truthy values', function () {
+		assert.equal(dedupe({
+			a: true,
+			b: false,
+			c: 0,
+			d: null,
+			e: undefined,
+			f: 1
+		}), 'a f');
+	});
+
+	it('should dedupe dedupe', function () {
+		assert.equal(dedupe('foo', 'bar', 'foo', 'bar', { foo: true }), 'foo bar');
+	});
+
+	it('should make sure subsequent objects can remove/add classes', function () {
+		assert.equal(dedupe('foo', { foo: false }, { foo: true, bar: true }), 'foo bar');
+	});
+
+	it('should make sure object with falsy value wipe out previous classes', function () {
+		assert.equal(dedupe('foo foo', 0, null, undefined, true, 1, 'b', { 'foo': false }), '1 b');
+		assert.equal(dedupe('foo', 'foobar', 'bar', { foo: false }), 'foobar bar');
+		assert.equal(dedupe('foo', 'foo-bar', 'bar', { foo: false }), 'foo-bar bar');
+		assert.equal(dedupe('foo', '-moz-foo-bar', 'bar', { foo: false }), '-moz-foo-bar bar');
+	});
+
+	it('joins arrays of class names and ignore falsy values', function () {
+		assert.equal(dedupe('a', 0, null, undefined, true, 1, 'b'), '1 a b');
+	});
+
+	it('supports heterogenous arguments', function () {
+		assert.equal(dedupe({a: true}, 'b', 0), 'a b');
+	});
+
+	it('should be trimmed', function () {
+		assert.equal(dedupe('', 'b', {}, ''), 'b');
+	});
+
+	it('returns an empty string for an empty configuration', function () {
+		assert.equal(dedupe({}), '');
+	});
+
+	it('supports an array of class names', function () {
+		assert.equal(dedupe(['a', 'b']), 'a b');
+	});
+
+	it('joins array arguments with string arguments', function () {
+		assert.equal(dedupe(['a', 'b'], 'c'), 'a b c');
+		assert.equal(dedupe('c', ['a', 'b']), 'c a b');
+	});
+
+	it('handles multiple array arguments', function () {
+		assert.equal(dedupe(['a', 'b'], ['c', 'd']), 'a b c d');
+	});
+
+	it('handles arrays that include falsy and true values', function () {
+		assert.equal(dedupe(['a', 0, null, undefined, false, true, 'b']), 'a b');
+	});
+
+	it('handles arrays that include arrays', function () {
+		assert.equal(dedupe(['a', ['b', 'c']]), 'a b c');
+	});
+
+	it('handles arrays that include objects', function () {
+		assert.equal(dedupe(['a', {b: true, c: false}]), 'a b');
+	});
+
+	it('handles deep array recursion', function () {
+		assert.equal(dedupe(['a', ['b', ['c', {d: true}]]]), 'a b c d');
+	});
+});
diff --git a/tests/index.js b/tests/index.js
new file mode 100644
index 0000000..378d110
--- /dev/null
+++ b/tests/index.js
@@ -0,0 +1,62 @@
+/* global describe, it */
+
+var assert = require('assert');
+var classNames = require('../');
+
+describe('classNames', function () {
+	it('keeps object keys with truthy values', function () {
+		assert.equal(classNames({
+			a: true,
+			b: false,
+			c: 0,
+			d: null,
+			e: undefined,
+			f: 1
+		}), 'a f');
+	});
+
+	it('joins arrays of class names and ignore falsy values', function () {
+		assert.equal(classNames('a', 0, null, undefined, true, 1, 'b'), 'a 1 b');
+	});
+
+	it('supports heterogenous arguments', function () {
+		assert.equal(classNames({a: true}, 'b', 0), 'a b');
+	});
+
+	it('should be trimmed', function () {
+		assert.equal(classNames('', 'b', {}, ''), 'b');
+	});
+
+	it('returns an empty string for an empty configuration', function () {
+		assert.equal(classNames({}), '');
+	});
+
+	it('supports an array of class names', function () {
+		assert.equal(classNames(['a', 'b']), 'a b');
+	});
+
+	it('joins array arguments with string arguments', function () {
+		assert.equal(classNames(['a', 'b'], 'c'), 'a b c');
+		assert.equal(classNames('c', ['a', 'b']), 'c a b');
+	});
+
+	it('handles multiple array arguments', function () {
+		assert.equal(classNames(['a', 'b'], ['c', 'd']), 'a b c d');
+	});
+
+	it('handles arrays that include falsy and true values', function () {
+		assert.equal(classNames(['a', 0, null, undefined, false, true, 'b']), 'a b');
+	});
+
+	it('handles arrays that include arrays', function () {
+		assert.equal(classNames(['a', ['b', 'c']]), 'a b c');
+	});
+
+	it('handles arrays that include objects', function () {
+		assert.equal(classNames(['a', {b: true, c: false}]), 'a b');
+	});
+
+	it('handles deep array recursion', function () {
+		assert.equal(classNames(['a', ['b', ['c', {d: true}]]]), 'a b c d');
+	});
+});

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-classnames.git



More information about the Pkg-javascript-commits mailing list