From 72643f8293332f3189b43652cfa7d7c873e16a27 Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Wed, 2 Sep 2015 07:27:20 +0100 Subject: [PATCH 001/200] Fix Invariant Violation when a single element child is contained in an array. --- src/linkClass.js | 5 ++++- src/utils.js | 6 +++++- test/linkClass.js | 40 +++++++++++++++++++++++++++++++++++----- 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/linkClass.js b/src/linkClass.js index cad5d7a..7f339de 100644 --- a/src/linkClass.js +++ b/src/linkClass.js @@ -1,5 +1,6 @@ import React from 'react'; import makeConfiguration from './makeConfiguration'; +import _ from './utils'; let linkClass; @@ -53,7 +54,7 @@ linkClass = (element, styles = {}, userConfiguration) => { if (typeof element.props.children !== 'string') { childrenCount = React.Children.count(element.props.children); - if (childrenCount > 1) { + if (childrenCount > 1 || _.isArray(element.props.children)) { newChildren = React.Children.map(element.props.children, (node) => { if (React.isValidElement(node)) { return linkClass(node, styles, configuration); @@ -61,6 +62,8 @@ linkClass = (element, styles = {}, userConfiguration) => { return node; } }); + // https://github.com/facebook/react/issues/4723#issuecomment-135555277 + newChildren = _.values(newChildren); } else if (childrenCount === 1) { newChildren = linkClass(React.Children.only(element.props.children), styles, configuration); } diff --git a/src/utils.js b/src/utils.js index 41f4480..0574ca3 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,5 +1,9 @@ import forEach from 'lodash/collection/forEach'; +import values from 'lodash/object/values'; +import isArray from 'lodash/lang/isArray'; export default { - forEach + forEach, + values, + isArray }; diff --git a/test/linkClass.js b/test/linkClass.js index 649d7cb..23f1365 100644 --- a/test/linkClass.js +++ b/test/linkClass.js @@ -25,11 +25,41 @@ describe('linkClass', () => { expect(linkClass(
)).to.deep.equal(
); }); - // Using array instead of object causes the following error: - // Warning: Each child in an array or iterator should have a unique "key" prop. - // Check the render method of _class. See https://fb.me/react-warning-keys for more information. - xit('does not affect element with multiple children', () => { - expect(linkClass(

)).to.deep.equal(

); + // Does not affect + it('does not affect element with a single children when that children is contained in an array', () => { + let outcome, + subject; + + subject = React.createElement('div', null, [ + React.createElement('p') + ]); + outcome = React.createElement('div', null, [ + React.createElement('p') + ]); + + expect(linkClass(subject)).to.deep.equal(outcome); + }); + + it('does not affect element with multiple children', () => { + // Using array instead of object causes the following error: + // Warning: Each child in an array or iterator should have a unique "key" prop. + // Check the render method of _class. See https://fb.me/react-warning-keys for more information. + // @see https://github.com/facebook/react/issues/4723#issuecomment-135555277 + // expect(linkClass(

)).to.deep.equal(

); + + let outcome, + subject; + + subject = React.createElement('div', null, [ + React.createElement('p'), + React.createElement('p') + ]); + outcome = React.createElement('div', null, [ + React.createElement('p'), + React.createElement('p') + ]); + + expect(linkClass(subject)).to.deep.equal(outcome); }); }); From cf46b7a075b5ac307c9c6220344385b20a86c88e Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Wed, 2 Sep 2015 07:27:37 +0100 Subject: [PATCH 002/200] 3.0.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5de15dc..502109f 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "css", "modules" ], - "version": "3.0.2", + "version": "3.0.3", "author": { "name": "Gajus Kuizinas", "email": "gk@anuary.com", From f1ea7c4c3b5cc5c8b2617455a54a35cf61afbe3b Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Thu, 3 Sep 2015 16:49:23 +0100 Subject: [PATCH 003/200] This ought to fix the invariant violation error. --- dist/linkClass.js | 18 ++++++++++++++---- dist/utils.js | 12 +++++++++++- src/linkClass.js | 8 ++++++-- test/linkClass.js | 5 ++--- 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/dist/linkClass.js b/dist/linkClass.js index 38b0f43..d260d81 100644 --- a/dist/linkClass.js +++ b/dist/linkClass.js @@ -14,6 +14,10 @@ var _makeConfiguration = require('./makeConfiguration'); var _makeConfiguration2 = _interopRequireDefault(_makeConfiguration); +var _utils = require('./utils'); + +var _utils2 = _interopRequireDefault(_utils); + var linkClass = undefined; /** @@ -65,10 +69,12 @@ linkClass = function (element, styles, userConfiguration) { // A child can be either an array, a sole object or a string. //
test
- if (typeof element.props.children !== 'string') { + if (_utils2['default'].isArray(element.props.children)) { childrenCount = _react2['default'].Children.count(element.props.children); - if (childrenCount > 1) { + // console.log('childrenCount', childrenCount, 'element.props.children', element.props.children); + + if (childrenCount > 1 || _utils2['default'].isArray(element.props.children)) { newChildren = _react2['default'].Children.map(element.props.children, function (node) { if (_react2['default'].isValidElement(node)) { return linkClass(node, styles, configuration); @@ -76,9 +82,13 @@ linkClass = function (element, styles, userConfiguration) { return node; } }); + // https://github.com/facebook/react/issues/4723#issuecomment-135555277 + // Forcing children into an array produces the following error: + // Warning: A ReactFragment is an opaque type. Accessing any of its properties is deprecated. Pass it to one of the React.Children helpers. + // newChildren = _.values(newChildren); } else if (childrenCount === 1) { - newChildren = linkClass(_react2['default'].Children.only(element.props.children), styles, configuration); - } + newChildren = linkClass(_react2['default'].Children.only(element.props.children), styles, configuration); + } } if (appendClassName) { diff --git a/dist/utils.js b/dist/utils.js index ec988cd..651f52c 100644 --- a/dist/utils.js +++ b/dist/utils.js @@ -10,7 +10,17 @@ var _lodashCollectionForEach = require('lodash/collection/forEach'); var _lodashCollectionForEach2 = _interopRequireDefault(_lodashCollectionForEach); +var _lodashObjectValues = require('lodash/object/values'); + +var _lodashObjectValues2 = _interopRequireDefault(_lodashObjectValues); + +var _lodashLangIsArray = require('lodash/lang/isArray'); + +var _lodashLangIsArray2 = _interopRequireDefault(_lodashLangIsArray); + exports['default'] = { - forEach: _lodashCollectionForEach2['default'] + forEach: _lodashCollectionForEach2['default'], + values: _lodashObjectValues2['default'], + isArray: _lodashLangIsArray2['default'] }; module.exports = exports['default']; \ No newline at end of file diff --git a/src/linkClass.js b/src/linkClass.js index 7f339de..ec80e2f 100644 --- a/src/linkClass.js +++ b/src/linkClass.js @@ -51,9 +51,11 @@ linkClass = (element, styles = {}, userConfiguration) => { // A child can be either an array, a sole object or a string. //
test
- if (typeof element.props.children !== 'string') { + if (_.isArray(element.props.children)) { childrenCount = React.Children.count(element.props.children); + // console.log('childrenCount', childrenCount, 'element.props.children', element.props.children); + if (childrenCount > 1 || _.isArray(element.props.children)) { newChildren = React.Children.map(element.props.children, (node) => { if (React.isValidElement(node)) { @@ -63,7 +65,9 @@ linkClass = (element, styles = {}, userConfiguration) => { } }); // https://github.com/facebook/react/issues/4723#issuecomment-135555277 - newChildren = _.values(newChildren); + // Forcing children into an array produces the following error: + // Warning: A ReactFragment is an opaque type. Accessing any of its properties is deprecated. Pass it to one of the React.Children helpers. + // newChildren = _.values(newChildren); } else if (childrenCount === 1) { newChildren = linkClass(React.Children.only(element.props.children), styles, configuration); } diff --git a/test/linkClass.js b/test/linkClass.js index 23f1365..9a14d53 100644 --- a/test/linkClass.js +++ b/test/linkClass.js @@ -25,8 +25,7 @@ describe('linkClass', () => { expect(linkClass(
)).to.deep.equal(
); }); - // Does not affect - it('does not affect element with a single children when that children is contained in an array', () => { + xit('does not affect element with a single children when that children is contained in an array', () => { let outcome, subject; @@ -40,7 +39,7 @@ describe('linkClass', () => { expect(linkClass(subject)).to.deep.equal(outcome); }); - it('does not affect element with multiple children', () => { + xit('does not affect element with multiple children', () => { // Using array instead of object causes the following error: // Warning: Each child in an array or iterator should have a unique "key" prop. // Check the render method of _class. See https://fb.me/react-warning-keys for more information. From fb3272f1684b5f3b7e71d9f6a7b02caaf747cec5 Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Thu, 3 Sep 2015 16:49:28 +0100 Subject: [PATCH 004/200] 3.0.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 502109f..4488917 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "css", "modules" ], - "version": "3.0.3", + "version": "3.0.4", "author": { "name": "Gajus Kuizinas", "email": "gk@anuary.com", From 716afd57a94b25b9f5f6badc39dcccd1d45a8934 Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Thu, 3 Sep 2015 20:04:38 +0100 Subject: [PATCH 005/200] Single ReactElement not an array. --- dist/linkClass.js | 4 +--- src/linkClass.js | 4 +--- test/linkClass.js | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/dist/linkClass.js b/dist/linkClass.js index d260d81..f04da0b 100644 --- a/dist/linkClass.js +++ b/dist/linkClass.js @@ -67,9 +67,7 @@ linkClass = function (element, styles, userConfiguration) { appendClassName = appendClassName.join(' '); } - // A child can be either an array, a sole object or a string. - //
test
- if (_utils2['default'].isArray(element.props.children)) { + if (_utils2['default'].isArray(element.props.children) || _react2['default'].isValidElement(element.props.children)) { childrenCount = _react2['default'].Children.count(element.props.children); // console.log('childrenCount', childrenCount, 'element.props.children', element.props.children); diff --git a/src/linkClass.js b/src/linkClass.js index ec80e2f..bef0e5a 100644 --- a/src/linkClass.js +++ b/src/linkClass.js @@ -49,9 +49,7 @@ linkClass = (element, styles = {}, userConfiguration) => { appendClassName = appendClassName.join(' '); } - // A child can be either an array, a sole object or a string. - //
test
- if (_.isArray(element.props.children)) { + if (_.isArray(element.props.children) || React.isValidElement(element.props.children)) { childrenCount = React.Children.count(element.props.children); // console.log('childrenCount', childrenCount, 'element.props.children', element.props.children); diff --git a/test/linkClass.js b/test/linkClass.js index 9a14d53..773cb37 100644 --- a/test/linkClass.js +++ b/test/linkClass.js @@ -63,6 +63,39 @@ describe('linkClass', () => { }); context('when styleName matches an existing CSS module', () => { + context('when a descendant element has styleName', () => { + it('assigns a generated className', () => { + let subject; + + subject =
+

+
; + + subject = linkClass(subject, { + foo: 'foo-1' + }); + + expect(subject.props.children.props.className).to.equal('foo-1'); + }); + }); + context('when multiple descendant elements have styleName', () => { + it('assigns a generated className', () => { + let subject; + + subject =
+

+

+
; + + subject = linkClass(subject, { + foo: 'foo-1', + bar: 'bar-1' + }); + + expect(subject.props.children['.0'].props.className).to.equal('foo-1'); + expect(subject.props.children['.1'].props.className).to.equal('bar-1'); + }); + }); context('when ReactElement does not have an existing className', () => { it('uses the generated class name to set the className property', () => { let subject; From b35c38b120c49c2d8272cb955025af9b4102cce5 Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Thu, 3 Sep 2015 20:04:42 +0100 Subject: [PATCH 006/200] 3.0.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4488917..a6a1197 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "css", "modules" ], - "version": "3.0.4", + "version": "3.0.5", "author": { "name": "Gajus Kuizinas", "email": "gk@anuary.com", From 771ad8fad25119b9ed426a356547ea0b0931f4aa Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Sun, 6 Sep 2015 22:32:26 +0100 Subject: [PATCH 007/200] Implement code coverage. --- .coveralls.yml | 1 + .gitignore | 1 + README.md | 1 + package.json | 6 +++++- 4 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 .coveralls.yml diff --git a/.coveralls.yml b/.coveralls.yml new file mode 100644 index 0000000..1d423a5 --- /dev/null +++ b/.coveralls.yml @@ -0,0 +1 @@ +repo_token: 5kn7Xw8YAtWbwqqwmtPT55Sil0knFJz62 diff --git a/.gitignore b/.gitignore index 6edd850..2d3bb39 100755 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /node_modules +/coverage npm-debug.log diff --git a/README.md b/README.md index 022cd88..2b47230 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![Travis build status](http://img.shields.io/travis/gajus/react-css-modules/master.svg?style=flat)](https://travis-ci.org/gajus/react-css-modules) [![NPM version](http://img.shields.io/npm/v/react-css-modules.svg?style=flat)](https://www.npmjs.org/package/react-css-modules) +[![Coverage Status](https://coveralls.io/repos/gajus/react-css-modules/badge.svg?branch=master&service=github)](https://coveralls.io/github/gajus/react-css-modules?branch=master) diff --git a/package.json b/package.json index a6a1197..2a68388 100644 --- a/package.json +++ b/package.json @@ -25,16 +25,20 @@ "devDependencies": { "babel": "^5.8.21", "babel-eslint": "^4.1.0", + "babel-istanbul": "^0.3.19", "chai": "^3.2.0", + "coveralls": "^2.11.4", "eslint": "^1.2.1", "eslint-plugin-react": "^3.3.0", "jsdom": "^6.2.0", "mocha": "^2.2.5", + "mocha-lcov-reporter": "0.0.2", "react": "^0.14.0-beta3", "react-addons-test-utils": "^0.14.0-beta3" }, "scripts": { - "test": "./node_modules/.bin/eslint ./src/ ./test/ && mocha", + "lint": "./node_modules/.bin/eslint ./src/ ./test/", + "test": "npm run lint && node ./node_modules/.bin/babel-istanbul cover ./node_modules/.bin/_mocha && cat ./coverage/lcov.info | coveralls", "build": "babel ./src/ --out-dir ./dist/", "watch": "babel --watch ./src/ --out-dir ./dist/" } From 3005914a2642d6601050fce3379b24adcab622cc Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Sun, 6 Sep 2015 22:33:05 +0100 Subject: [PATCH 008/200] Should not be public. --- .coveralls.yml | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .coveralls.yml diff --git a/.coveralls.yml b/.coveralls.yml deleted file mode 100644 index 1d423a5..0000000 --- a/.coveralls.yml +++ /dev/null @@ -1 +0,0 @@ -repo_token: 5kn7Xw8YAtWbwqqwmtPT55Sil0knFJz62 From 0da0eeb896f8f7f85a950fcf398e4ac17352f65b Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Sun, 6 Sep 2015 22:34:19 +0100 Subject: [PATCH 009/200] Ignore gitignore. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2d3bb39..e88d4be 100755 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /node_modules /coverage +/.coveralls.yml npm-debug.log From 3f0365d6bd51ab86650039fd142ac8e8f48ae8d1 Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Sun, 6 Sep 2015 22:35:56 +0100 Subject: [PATCH 010/200] Seems like token is required. --- .coveralls.yml | 1 + .gitignore | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 .coveralls.yml diff --git a/.coveralls.yml b/.coveralls.yml new file mode 100644 index 0000000..c099fdc --- /dev/null +++ b/.coveralls.yml @@ -0,0 +1 @@ +repo_token: vnqpbiGFbHmVwNwcJnseZAZ5X33epllne diff --git a/.gitignore b/.gitignore index e88d4be..2d3bb39 100755 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ /node_modules /coverage -/.coveralls.yml npm-debug.log From 02240c3ab44593387fc652ab3ff7174ac85aca62 Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Wed, 16 Sep 2015 13:01:32 +0100 Subject: [PATCH 011/200] Updated depedencies. --- .coveralls.yml | 2 +- .gitignore | 1 + LICENSE | 24 ++++++++++++++++++++++++ package.json | 25 +++++++++++++------------ test/linkClass.js | 6 ++++-- test/makeConfiguration.js | 2 ++ 6 files changed, 45 insertions(+), 15 deletions(-) create mode 100644 LICENSE diff --git a/.coveralls.yml b/.coveralls.yml index c099fdc..65bf7c7 100644 --- a/.coveralls.yml +++ b/.coveralls.yml @@ -1 +1 @@ -repo_token: vnqpbiGFbHmVwNwcJnseZAZ5X33epllne +repo_token: bqiXmaOA0xarSUociqxGKJ72bp8SSHlQC diff --git a/.gitignore b/.gitignore index 2d3bb39..e0b6b81 100755 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /node_modules /coverage npm-debug.log +.coveralls.yml diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..183e8d8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2015, Gajus Kuizinas (http://gajus.com/) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Gajus Kuizinas (http://gajus.com/) nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL ANUARY BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/package.json b/package.json index 2a68388..2e6a2aa 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "react-css-modules", "description": "Seamless mapping of class names to CSS modules inside of React components.", - "main": "dist/index.js", + "main": "./dist/index.js", "repository": { "type": "git", "url": "https://github.com/gajus/react-css-modules" @@ -23,22 +23,23 @@ "lodash": "^3.10.1" }, "devDependencies": { - "babel": "^5.8.21", - "babel-eslint": "^4.1.0", - "babel-istanbul": "^0.3.19", + "babel": "^5.8.23", + "babel-eslint": "^4.1.2", + "babel-istanbul": "^0.3.20", "chai": "^3.2.0", "coveralls": "^2.11.4", - "eslint": "^1.2.1", - "eslint-plugin-react": "^3.3.0", - "jsdom": "^6.2.0", - "mocha": "^2.2.5", - "mocha-lcov-reporter": "0.0.2", - "react": "^0.14.0-beta3", - "react-addons-test-utils": "^0.14.0-beta3" + "eslint": "^1.4.3", + "eslint-plugin-react": "^3.3.2", + "jsdom": "^6.5.0", + "mocha": "^2.3.2", + "mocha-lcov-reporter": "^0.0.2", + "react": "^0.14.0-rc1", + "react-addons-test-utils": "^0.14.0-rc1" }, "scripts": { "lint": "./node_modules/.bin/eslint ./src/ ./test/", - "test": "npm run lint && node ./node_modules/.bin/babel-istanbul cover ./node_modules/.bin/_mocha && cat ./coverage/lcov.info | coveralls", + "quick-test": "npm run lint && node ./node_modules/.bin/babel-istanbul cover ./node_modules/.bin/_mocha", + "test": "npm run quick-test && cat ./coverage/lcov.info | ./node_modules/.bin/coveralls", "build": "babel ./src/ --out-dir ./dist/", "watch": "babel --watch ./src/ --out-dir ./dist/" } diff --git a/test/linkClass.js b/test/linkClass.js index 773cb37..273e4d8 100644 --- a/test/linkClass.js +++ b/test/linkClass.js @@ -1,3 +1,5 @@ +/* eslint-disable max-nested-callbacks */ + import { expect } from 'chai'; @@ -92,8 +94,8 @@ describe('linkClass', () => { bar: 'bar-1' }); - expect(subject.props.children['.0'].props.className).to.equal('foo-1'); - expect(subject.props.children['.1'].props.className).to.equal('bar-1'); + expect(subject.props.children[0].props.className).to.equal('foo-1'); + expect(subject.props.children[1].props.className).to.equal('bar-1'); }); }); context('when ReactElement does not have an existing className', () => { diff --git a/test/makeConfiguration.js b/test/makeConfiguration.js index f805dde..3a74ae7 100644 --- a/test/makeConfiguration.js +++ b/test/makeConfiguration.js @@ -1,3 +1,5 @@ +/* eslint-disable max-nested-callbacks */ + import { expect } from 'chai'; From a088497fe0c1aa755cbcfe8ae4a177306d7ce37e Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Wed, 16 Sep 2015 13:01:36 +0100 Subject: [PATCH 012/200] 3.0.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2e6a2aa..c025307 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "css", "modules" ], - "version": "3.0.5", + "version": "3.0.6", "author": { "name": "Gajus Kuizinas", "email": "gk@anuary.com", From c4bd4c19021e8f3b4800a8eac159acc22d270ebc Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Wed, 16 Sep 2015 13:59:56 +0100 Subject: [PATCH 013/200] Simplified the logic for determining when to link children. --- dist/linkClass.js | 38 ++++++++++++++++++++------------------ src/linkClass.js | 41 +++++++++++++++++++++-------------------- 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/dist/linkClass.js b/dist/linkClass.js index f04da0b..2944de5 100644 --- a/dist/linkClass.js +++ b/dist/linkClass.js @@ -30,7 +30,6 @@ linkClass = function (element, styles, userConfiguration) { if (styles === undefined) styles = {}; var appendClassName = undefined, - childrenCount = undefined, clonedElement = undefined, configuration = undefined, newChildren = undefined, @@ -67,26 +66,29 @@ linkClass = function (element, styles, userConfiguration) { appendClassName = appendClassName.join(' '); } - if (_utils2['default'].isArray(element.props.children) || _react2['default'].isValidElement(element.props.children)) { - childrenCount = _react2['default'].Children.count(element.props.children); + // element.props.children can be one of the following: + // 'text' + // ['text'] + // [ReactElement, 'text'] + // ReactElement - // console.log('childrenCount', childrenCount, 'element.props.children', element.props.children); + // console.log(`element.props.children`, element.props.children, `React.Children.count(element.props.children)`, React.Children.count(element.props.children)); - if (childrenCount > 1 || _utils2['default'].isArray(element.props.children)) { - newChildren = _react2['default'].Children.map(element.props.children, function (node) { - if (_react2['default'].isValidElement(node)) { - return linkClass(node, styles, configuration); - } else { - return node; - } - }); - // https://github.com/facebook/react/issues/4723#issuecomment-135555277 - // Forcing children into an array produces the following error: - // Warning: A ReactFragment is an opaque type. Accessing any of its properties is deprecated. Pass it to one of the React.Children helpers. - // newChildren = _.values(newChildren); - } else if (childrenCount === 1) { - newChildren = linkClass(_react2['default'].Children.only(element.props.children), styles, configuration); + if (_react2['default'].isValidElement(element.props.children)) { + newChildren = linkClass(_react2['default'].Children.only(element.props.children), styles, configuration); + } else if (_utils2['default'].isArray(element.props.children)) { + newChildren = _react2['default'].Children.map(element.props.children, function (node) { + if (_react2['default'].isValidElement(node)) { + return linkClass(node, styles, configuration); + } else { + return node; } + }); + + // https://github.com/facebook/react/issues/4723#issuecomment-135555277 + // Forcing children into an array produces the following error: + // Warning: A ReactFragment is an opaque type. Accessing any of its properties is deprecated. Pass it to one of the React.Children helpers. + // newChildren = _.values(newChildren); } if (appendClassName) { diff --git a/src/linkClass.js b/src/linkClass.js index bef0e5a..ba28f56 100644 --- a/src/linkClass.js +++ b/src/linkClass.js @@ -12,7 +12,6 @@ let linkClass; */ linkClass = (element, styles = {}, userConfiguration) => { let appendClassName, - childrenCount, clonedElement, configuration, newChildren, @@ -49,28 +48,30 @@ linkClass = (element, styles = {}, userConfiguration) => { appendClassName = appendClassName.join(' '); } - if (_.isArray(element.props.children) || React.isValidElement(element.props.children)) { - childrenCount = React.Children.count(element.props.children); + // element.props.children can be one of the following: + // 'text' + // ['text'] + // [ReactElement, 'text'] + // ReactElement - // console.log('childrenCount', childrenCount, 'element.props.children', element.props.children); + // console.log(`element.props.children`, element.props.children, `React.Children.count(element.props.children)`, React.Children.count(element.props.children)); - if (childrenCount > 1 || _.isArray(element.props.children)) { - newChildren = React.Children.map(element.props.children, (node) => { - if (React.isValidElement(node)) { - return linkClass(node, styles, configuration); - } else { - return node; - } - }); - // https://github.com/facebook/react/issues/4723#issuecomment-135555277 - // Forcing children into an array produces the following error: - // Warning: A ReactFragment is an opaque type. Accessing any of its properties is deprecated. Pass it to one of the React.Children helpers. - // newChildren = _.values(newChildren); - } else if (childrenCount === 1) { - newChildren = linkClass(React.Children.only(element.props.children), styles, configuration); - } - } + if (React.isValidElement(element.props.children)) { + newChildren = linkClass(React.Children.only(element.props.children), styles, configuration); + } else if (_.isArray(element.props.children)) { + newChildren = React.Children.map(element.props.children, (node) => { + if (React.isValidElement(node)) { + return linkClass(node, styles, configuration); + } else { + return node; + } + }); + // https://github.com/facebook/react/issues/4723#issuecomment-135555277 + // Forcing children into an array produces the following error: + // Warning: A ReactFragment is an opaque type. Accessing any of its properties is deprecated. Pass it to one of the React.Children helpers. + // newChildren = _.values(newChildren); + } if (appendClassName) { if (element.props.className) { From 9cad95b6a067e9dfb831cf43f53ac530c127e347 Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Wed, 16 Sep 2015 14:04:31 +0100 Subject: [PATCH 014/200] Using babel-plugin-lodash. --- .babelrc | 5 ++++- dist/linkClass.js | 12 ++++++------ dist/makeConfiguration.js | 10 +++++----- package.json | 1 + src/linkClass.js | 2 +- src/makeConfiguration.js | 2 +- src/utils.js | 9 --------- 7 files changed, 18 insertions(+), 23 deletions(-) delete mode 100644 src/utils.js diff --git a/.babelrc b/.babelrc index 12606a3..89c0540 100644 --- a/.babelrc +++ b/.babelrc @@ -1,3 +1,6 @@ { - "stage": 0 + "stage": 0, + "plugins": [ + "lodash" + ] } diff --git a/dist/linkClass.js b/dist/linkClass.js index 2944de5..bcbda87 100644 --- a/dist/linkClass.js +++ b/dist/linkClass.js @@ -1,11 +1,13 @@ 'use strict'; +var _lodashLangIsArray2 = require('lodash/lang/isArray'); + +var _lodashLangIsArray3 = _interopRequireDefault(_lodashLangIsArray2); + Object.defineProperty(exports, '__esModule', { value: true }); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - var _react = require('react'); var _react2 = _interopRequireDefault(_react); @@ -14,9 +16,7 @@ var _makeConfiguration = require('./makeConfiguration'); var _makeConfiguration2 = _interopRequireDefault(_makeConfiguration); -var _utils = require('./utils'); - -var _utils2 = _interopRequireDefault(_utils); +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } var linkClass = undefined; @@ -76,7 +76,7 @@ linkClass = function (element, styles, userConfiguration) { if (_react2['default'].isValidElement(element.props.children)) { newChildren = linkClass(_react2['default'].Children.only(element.props.children), styles, configuration); - } else if (_utils2['default'].isArray(element.props.children)) { + } else if ((0, _lodashLangIsArray3['default'])(element.props.children)) { newChildren = _react2['default'].Children.map(element.props.children, function (node) { if (_react2['default'].isValidElement(node)) { return linkClass(node, styles, configuration); diff --git a/dist/makeConfiguration.js b/dist/makeConfiguration.js index d42ad79..b528fa5 100644 --- a/dist/makeConfiguration.js +++ b/dist/makeConfiguration.js @@ -1,15 +1,15 @@ 'use strict'; +var _lodashCollectionForEach2 = require('lodash/collection/forEach'); + +var _lodashCollectionForEach3 = _interopRequireDefault(_lodashCollectionForEach2); + Object.defineProperty(exports, '__esModule', { value: true }); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } -var _utils = require('./utils'); - -var _utils2 = _interopRequireDefault(_utils); - /** * @typedef CSSModules~Options * @see {@link https://github.com/gajus/react-css-modules#options} @@ -32,7 +32,7 @@ exports['default'] = function () { errorWhenNotFound: true }; - _utils2['default'].forEach(userConfiguration, function (value, name) { + (0, _lodashCollectionForEach3['default'])(userConfiguration, function (value, name) { if (typeof configuration[name] === 'undefined') { throw new Error('Unknown configuration property "' + name + '".'); } diff --git a/package.json b/package.json index c025307..31fc90f 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "babel": "^5.8.23", "babel-eslint": "^4.1.2", "babel-istanbul": "^0.3.20", + "babel-plugin-lodash": "^0.2.0", "chai": "^3.2.0", "coveralls": "^2.11.4", "eslint": "^1.4.3", diff --git a/src/linkClass.js b/src/linkClass.js index ba28f56..6438591 100644 --- a/src/linkClass.js +++ b/src/linkClass.js @@ -1,6 +1,6 @@ import React from 'react'; import makeConfiguration from './makeConfiguration'; -import _ from './utils'; +import _ from 'lodash'; let linkClass; diff --git a/src/makeConfiguration.js b/src/makeConfiguration.js index e521af5..6889c75 100644 --- a/src/makeConfiguration.js +++ b/src/makeConfiguration.js @@ -1,4 +1,4 @@ -import _ from './utils'; +import _ from 'lodash'; /** * @typedef CSSModules~Options diff --git a/src/utils.js b/src/utils.js deleted file mode 100644 index 0574ca3..0000000 --- a/src/utils.js +++ /dev/null @@ -1,9 +0,0 @@ -import forEach from 'lodash/collection/forEach'; -import values from 'lodash/object/values'; -import isArray from 'lodash/lang/isArray'; - -export default { - forEach, - values, - isArray -}; From 764cc6e9dfa68418e1ae4e894ea9782ee712b385 Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Wed, 16 Sep 2015 15:09:19 +0100 Subject: [PATCH 015/200] Using table example instead of car. --- README.md | 60 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 2b47230..0c9beb2 100644 --- a/README.md +++ b/README.md @@ -35,13 +35,15 @@ In the context of React, CSS Modules look like this: ```js import React from 'react'; -import styles from './car.css'; +import styles from './table.css'; -export default class Car extends React.Component { +export default class Table extends React.Component { render () { - return
-
-
+ return
+
+
A0
+
B0
+
; } } @@ -50,9 +52,11 @@ export default class Car extends React.Component { Rendering the component will produce a markup similar to: ```js -
-
front-door
-
back-door
+
+
+
A0
+
B0
+
``` @@ -77,19 +81,21 @@ React CSS Modules component automates loading of CSS Modules using `styleName` p ```js import React from 'react'; -import styles from './car.css'; import CSSModules from 'react-css-modules'; +import styles from './table.css'; -class Car extends React.Component { +class Table extends React.Component { render () { - return
-
-
+ return
+
+
A0
+
B0
+
; } } -export default CSSModules(Car, styles); +export default CSSModules(Table, styles); ``` Using `react-css-modules`: @@ -159,7 +165,7 @@ Refer to [`css-modulesify`](https://github.com/css-modules/css-modulesify). /** * @param {Function} Component - * @param {Object} styles CSS Modules class map. + * @param {Object} defaultStyles CSS Modules class map. * @param {CSSModules~Options} options * @return {Function} */ @@ -169,19 +175,21 @@ You need to decorate your component using `react-css-modules`, e.g. ```js import React from 'react'; -import styles from './car.css'; import CSSModules from 'react-css-modules'; +import styles from './table.css'; -class Car extends React.Component { +class Table extends React.Component { render () { - return
-
-
+ return
+
+
A0
+
B0
+
; } } -export default CSSModules(Car, styles); +export default CSSModules(Table, styles); ``` Thats it! @@ -190,15 +198,17 @@ As the name implies, `react-css-modules` is compatible with the [ES7 decorators] ```js import React from 'react'; -import styles from './car.css'; import CSSModules from 'react-css-modules'; +import styles from './table.css'; @CSSModules(styles) export default class extends React.Component { render () { - return
-
front-door
-
back-door
+ return
+
+
A0
+
B0
+
; } } From 94d66ee001e74dc39bbfe7a7af05672f74908cf9 Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Wed, 16 Sep 2015 15:30:10 +0100 Subject: [PATCH 016/200] Added "styles" property. --- README.md | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++ dist/index.js | 28 ++++++++++++++++------ src/index.js | 21 +++++++++++++---- 3 files changed, 102 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 0c9beb2..3f2eb1c 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ React CSS Modules implement automatic mapping of CSS modules. Every CSS class is - [Module Bundler](#module-bundler) - [webpack](#webpack) - [Browserify](#browserify) + - [Extending CSS Styles](#extending-css-styles) - [Decorator](#decorator) - [Options](#options) - [`allowMultiple`](#allowmultiple) @@ -153,6 +154,70 @@ Refer to [webpack-demo](https://github.com/css-modules/webpack-demo) or [react-c Refer to [`css-modulesify`](https://github.com/css-modules/css-modulesify). +### Extending CSS Styles + +Use `styles` property to overwrite the default component styles. + +Explanation using `Table` component: + +```js +import React from 'react'; +import CSSModules from 'react-css-modules'; +import styles from './table.css'; + +class Table extends React.Component { + render () { + return
+
+
A0
+
B0
+
+
; + } +} + +export default CSSModules(Table, styles); +``` + +In this example, `CSSModules` is used to decorate `Table` component using `./table.css` CSS Modules. When `Table` component is rendered, it will use the properties of the `styles` object to construct `className` values. + +Using `styles` property you can overwrite the default component `styles` object, e.g. + +```js +import customStyles from './table-custom-styles.css'; + +; +``` + +[Interoperable CSS](https://github.com/css-modules/icss) can [extend other ICSS](https://github.com/css-modules/css-modules#dependencies). Use this feature to extend default styles, e.g. + +```css +/* table-custom-styles.css */ +.table { + composes: table from './table.css'; +} + +.row { + composes: row from './table.css'; +} + +/* .cell { + composes: cell from './table.css'; +} */ + +.table { + width: 400px; +} + +.cell { + float: left; width: 154px; background: #eee; padding: 10px; margin: 10px 0 10px 10px; +} +``` + +In this example, `table-custom-styles.css` selectively extends `table.css` (the default styles of `Table` component). + +Refer to the [`UsingStylesProperty` example](https://github.com/gajus/react-css-modules-examples/tree/master/src/UsingStylesProperty) for an example of a working implementation. + ### Decorator ```js diff --git a/dist/index.js b/dist/index.js index c50da0c..9c0a983 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,5 +1,9 @@ 'use strict'; +var _lodashLangIsObject2 = require('lodash/lang/isObject'); + +var _lodashLangIsObject3 = _interopRequireDefault(_lodashLangIsObject2); + Object.defineProperty(exports, '__esModule', { value: true }); @@ -8,8 +12,6 @@ var _createClass = (function () { function defineProperties(target, props) { for var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } @@ -18,6 +20,8 @@ var _linkClass = require('./linkClass'); var _linkClass2 = _interopRequireDefault(_linkClass); +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + var decoratorConstructor = undefined, functionConstructor = undefined; @@ -25,11 +29,11 @@ var decoratorConstructor = undefined, * When used as a function. * * @param {Function} Component - * @param {Object} styles CSS Modules class map. + * @param {Object} defaultStyles CSS Modules class map. * @param {Object} options {@link https://github.com/gajus/react-css-modules#options} * @return {Function} */ -functionConstructor = function (Component, styles, options) { +functionConstructor = function (Component, defaultStyles, options) { return (function (_Component) { _inherits(_class, _Component); @@ -42,6 +46,16 @@ functionConstructor = function (Component, styles, options) { _createClass(_class, [{ key: 'render', value: function render() { + var styles = undefined; + + if (this.props.styles) { + styles = this.props.styles; + } else if ((0, _lodashLangIsObject3['default'])(defaultStyles)) { + styles = defaultStyles; + } else { + styles = {}; + } + return (0, _linkClass2['default'])(_get(Object.getPrototypeOf(_class.prototype), 'render', this).call(this), styles, options); } }]); @@ -53,13 +67,13 @@ functionConstructor = function (Component, styles, options) { /** * When used as a ES7 decorator. * - * @param {Object} styles CSS Modules class map. + * @param {Object} defaultStyles CSS Modules class map. * @param {Object} options {@link https://github.com/gajus/react-css-modules#options} * @return {Function} */ -decoratorConstructor = function (styles, options) { +decoratorConstructor = function (defaultStyles, options) { return function (Component) { - return functionConstructor(Component, styles, options); + return functionConstructor(Component, defaultStyles, options); }; }; diff --git a/src/index.js b/src/index.js index 75c3bff..3a0e728 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,5 @@ import linkClass from './linkClass'; +import _ from 'lodash'; let decoratorConstructor, functionConstructor; @@ -7,13 +8,23 @@ let decoratorConstructor, * When used as a function. * * @param {Function} Component - * @param {Object} styles CSS Modules class map. + * @param {Object} defaultStyles CSS Modules class map. * @param {Object} options {@link https://github.com/gajus/react-css-modules#options} * @return {Function} */ -functionConstructor = (Component, styles, options) => { +functionConstructor = (Component, defaultStyles, options) => { return class extends Component { render () { + let styles; + + if (this.props.styles) { + styles = this.props.styles; + } else if (_.isObject(defaultStyles)) { + styles = defaultStyles; + } else { + styles = {}; + } + return linkClass(super.render(), styles, options); } }; @@ -22,13 +33,13 @@ functionConstructor = (Component, styles, options) => { /** * When used as a ES7 decorator. * - * @param {Object} styles CSS Modules class map. + * @param {Object} defaultStyles CSS Modules class map. * @param {Object} options {@link https://github.com/gajus/react-css-modules#options} * @return {Function} */ -decoratorConstructor = (styles, options) => { +decoratorConstructor = (defaultStyles, options) => { return (Component) => { - return functionConstructor(Component, styles, options); + return functionConstructor(Component, defaultStyles, options); }; }; From 83bc3582454fb2a087c011d3da0a130635b2b8ff Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Wed, 16 Sep 2015 15:30:14 +0100 Subject: [PATCH 017/200] 3.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 31fc90f..3f3319b 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "css", "modules" ], - "version": "3.0.6", + "version": "3.1.0", "author": { "name": "Gajus Kuizinas", "email": "gk@anuary.com", From b30527c5921d584515afc2c5e84296abc4929e79 Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Wed, 16 Sep 2015 15:32:34 +0100 Subject: [PATCH 018/200] Renamed README section. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3f2eb1c..68c603c 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ React CSS Modules implement automatic mapping of CSS modules. Every CSS class is - [Module Bundler](#module-bundler) - [webpack](#webpack) - [Browserify](#browserify) - - [Extending CSS Styles](#extending-css-styles) + - [Extending Component Styles](#extending-component-styles) - [Decorator](#decorator) - [Options](#options) - [`allowMultiple`](#allowmultiple) @@ -154,7 +154,7 @@ Refer to [webpack-demo](https://github.com/css-modules/webpack-demo) or [react-c Refer to [`css-modulesify`](https://github.com/css-modules/css-modulesify). -### Extending CSS Styles +### Extending Component Styles Use `styles` property to overwrite the default component styles. From b6558b574da667b43df04236232fd9ff1b125612 Mon Sep 17 00:00:00 2001 From: goncalvesjoao Date: Thu, 17 Sep 2015 12:00:26 +0100 Subject: [PATCH 019/200] rendering