Added logging, changed some directory structure

This commit is contained in:
2018-01-13 21:33:40 -05:00
parent f079a5f067
commit 8e72ffb917
73656 changed files with 35284 additions and 53718 deletions

View File

@@ -0,0 +1,10 @@
{
"presets": ["stage-0", "es2015"],
"env": {
"test": {
"plugins": [
"rewire"
]
}
}
}

View File

@@ -0,0 +1,3 @@
{
"extends": "eslint-config-jss"
}

View File

@@ -0,0 +1,4 @@
src
bench
coverage
tmp

View File

@@ -0,0 +1,8 @@
The MIT License (MIT)
Copyright (c) 2016 Pavel Davydov
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.

View File

@@ -0,0 +1,32 @@
## 4.0.0 / 2017-06-20
- support jss 8
## 3.0.1 / 2017-04-11
- use `onProcessStyle`, fixes an error when rule.style is not defined
## 3.0.0 / 2017-04-10
- support jss 7.0
## 2.1.0 / 2017-02-27
- support multiple space separated classes
## 2.0.1 / 2017-02-27
- mock out generateClassName in tests
## 2.0.0 / 2016-12-09
- remove named option handling
## 1.1.0 / 2016-09-30
- refactoring
- tests integration into jss repo
## 1.0.0 / 2016-09-16
- first release

View File

@@ -0,0 +1,210 @@
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["jssCompose"] = factory();
else
root["jssCompose"] = factory();
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = jssCompose;
var _warning = __webpack_require__(1);
var _warning2 = _interopRequireDefault(_warning);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Set selector.
*
* @param {Object} original rule
* @param {String} className class string
* @return {Boolean} flag, indicating function was successfull or not
*/
function registerClass(rule, className) {
// Skip falsy values
if (!className) return true;
// Support array of class names `{composes: ['foo', 'bar']}`
if (Array.isArray(className)) {
for (var index = 0; index < className.length; index++) {
var isSetted = registerClass(rule, className[index]);
if (!isSetted) return false;
}
return true;
}
// Support space separated class names `{composes: 'foo bar'}`
if (className.indexOf(' ') > -1) {
return registerClass(rule, className.split(' '));
}
var parent = rule.options.parent;
// It is a ref to a local rule.
if (className[0] === '$') {
var refRule = parent.getRule(className.substr(1));
if (!refRule) {
(0, _warning2.default)(false, '[JSS] Referenced rule is not defined. \r\n%s', rule);
return false;
}
if (refRule === rule) {
(0, _warning2.default)(false, '[JSS] Cyclic composition detected. \r\n%s', rule);
return false;
}
parent.classes[rule.key] += ' ' + parent.classes[refRule.key];
return true;
}
rule.options.parent.classes[rule.key] += ' ' + className;
return true;
}
/**
* Convert compose property to additional class, remove property from original styles.
*
* @param {Rule} rule
* @api public
*/
function jssCompose() {
function onProcessStyle(style, rule) {
if (!style.composes) return style;
registerClass(rule, style.composes);
// Remove composes property to prevent infinite loop.
delete style.composes;
return style;
}
return { onProcessStyle: onProcessStyle };
}
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
/**
* Copyright 2014-2015, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
/**
* Similar to invariant but only logs a warning if the condition is not met.
* This can be used to log issues in development environments in critical
* paths. Removing the logging code for production environments will keep the
* same logic and follow the same code paths.
*/
var warning = function() {};
if (true) {
warning = function(condition, format, args) {
var len = arguments.length;
args = new Array(len > 2 ? len - 2 : 0);
for (var key = 2; key < len; key++) {
args[key - 2] = arguments[key];
}
if (format === undefined) {
throw new Error(
'`warning(condition, format, ...args)` requires a warning ' +
'message argument'
);
}
if (format.length < 10 || (/^[s\W]*$/).test(format)) {
throw new Error(
'The warning format should be able to uniquely identify this ' +
'warning. Please, use a more descriptive format than: ' + format
);
}
if (!condition) {
var argIndex = 0;
var message = 'Warning: ' +
format.replace(/%s/g, function() {
return args[argIndex++];
});
if (typeof console !== 'undefined') {
console.error(message);
}
try {
// This error was thrown as a convenience so that you can use this stack
// to find the callsite that caused this warning to fire.
throw new Error(message);
} catch(x) {}
}
};
}
module.exports = warning;
/***/ }
/******/ ])
});
;
//# sourceMappingURL=jss-compose.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.jssCompose=t():e.jssCompose=t()}(this,function(){return function(e){function t(o){if(r[o])return r[o].exports;var n=r[o]={exports:{},id:o,loaded:!1};return e[o].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var r={};return t.m=e,t.c=r,t.p="",t(0)}([function(e,t,r){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function n(e,t){if(!t)return!0;if(Array.isArray(t)){for(var r=0;r<t.length;r++){var o=n(e,t[r]);if(!o)return!1}return!0}if(t.indexOf(" ")>-1)return n(e,t.split(" "));var s=e.options.parent;if("$"===t[0]){var u=s.getRule(t.substr(1));return u?u===e?((0,i["default"])(!1,"[JSS] Cyclic composition detected. \r\n%s",e),!1):(s.classes[e.key]+=" "+s.classes[u.key],!0):((0,i["default"])(!1,"[JSS] Referenced rule is not defined. \r\n%s",e),!1)}return e.options.parent.classes[e.key]+=" "+t,!0}function s(){function e(e,t){return e.composes?(n(t,e.composes),delete e.composes,e):e}return{onProcessStyle:e}}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=s;var u=r(1),i=o(u)},function(e,t,r){"use strict";var o=function(){};e.exports=o}])});
//# sourceMappingURL=jss-compose.min.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,24 @@
const webpackConfig = require('./webpack.config')
module.exports = (config) => {
config.set({
browsers: ['Chrome'],
frameworks: ['mocha'],
files: ['tests.webpack.js'],
preprocessors: {
'tests.webpack.js': ['webpack', 'sourcemap']
},
webpack: Object.assign(webpackConfig, {
devtool: 'inline-source-map'
}),
webpackServer: {
noInfo: true
},
reporters: ['mocha', 'coverage'],
coverageReporter: {
dir: 'coverage',
file: 'coverage.json',
type: 'json'
}
})
}

View File

@@ -0,0 +1,82 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = jssCompose;
var _warning = require('warning');
var _warning2 = _interopRequireDefault(_warning);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Set selector.
*
* @param {Object} original rule
* @param {String} className class string
* @return {Boolean} flag, indicating function was successfull or not
*/
function registerClass(rule, className) {
// Skip falsy values
if (!className) return true;
// Support array of class names `{composes: ['foo', 'bar']}`
if (Array.isArray(className)) {
for (var index = 0; index < className.length; index++) {
var isSetted = registerClass(rule, className[index]);
if (!isSetted) return false;
}
return true;
}
// Support space separated class names `{composes: 'foo bar'}`
if (className.indexOf(' ') > -1) {
return registerClass(rule, className.split(' '));
}
var parent = rule.options.parent;
// It is a ref to a local rule.
if (className[0] === '$') {
var refRule = parent.getRule(className.substr(1));
if (!refRule) {
(0, _warning2.default)(false, '[JSS] Referenced rule is not defined. \r\n%s', rule);
return false;
}
if (refRule === rule) {
(0, _warning2.default)(false, '[JSS] Cyclic composition detected. \r\n%s', rule);
return false;
}
parent.classes[rule.key] += ' ' + parent.classes[refRule.key];
return true;
}
rule.options.parent.classes[rule.key] += ' ' + className;
return true;
}
/**
* Convert compose property to additional class, remove property from original styles.
*
* @param {Rule} rule
* @api public
*/
function jssCompose() {
function onProcessStyle(style, rule) {
if (!style.composes) return style;
registerClass(rule, style.composes);
// Remove composes property to prevent infinite loop.
delete style.composes;
return style;
}
return { onProcessStyle: onProcessStyle };
}

View File

@@ -0,0 +1,247 @@
'use strict';
var _expect = require('expect.js');
var _expect2 = _interopRequireDefault(_expect);
var _jss = require('jss');
var _ = require('./');
var _2 = _interopRequireDefault(_);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
describe('jss-compose', function () {
var jss = void 0;
var warning = void 0;
beforeEach(function () {
_2.default.__Rewire__('warning', function (condition, message) {
warning = message;
});
jss = (0, _jss.create)({
createGenerateClassName: function createGenerateClassName() {
return function (rule) {
return rule.key + '-id';
};
}
}).use((0, _2.default)());
});
afterEach(function () {
_2.default.__ResetDependency__('warning');
warning = undefined;
});
describe('Ref composition', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
float: 'left'
},
b: {
composes: '$a',
color: 'red'
}
});
});
afterEach(function () {
(0, _expect2.default)(warning).to.be(undefined);
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
(0, _expect2.default)(sheet.getRule('b')).to.not.be(undefined);
});
it('should compose classes', function () {
(0, _expect2.default)(sheet.classes.b).to.be('b-id a-id');
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' float: left;\n' + '}\n' + '.b-id {\n' + ' color: red;\n' + '}');
});
});
describe('Global class composition', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
composes: 'b',
color: 'red'
}
});
});
afterEach(function () {
(0, _expect2.default)(warning).to.be(undefined);
});
it('should compose classes', function () {
(0, _expect2.default)(sheet.classes.a).to.be('a-id b');
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' color: red;\n' + '}');
});
});
describe('Array of refs composition', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
float: 'left'
},
b: {
color: 'red'
},
c: {
background: 'blue'
},
d: {
composes: ['$a', '$b', '$c'],
border: 'none'
},
e: {
composes: '$a $b $c',
border: 'none'
},
f: {
composes: ['$a', ['$b', '$c']],
border: 'none'
}
});
});
afterEach(function () {
(0, _expect2.default)(warning).to.be(undefined);
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
(0, _expect2.default)(sheet.getRule('b')).to.not.be(undefined);
(0, _expect2.default)(sheet.getRule('c')).to.not.be(undefined);
(0, _expect2.default)(sheet.getRule('d')).to.not.be(undefined);
(0, _expect2.default)(sheet.getRule('e')).to.not.be(undefined);
(0, _expect2.default)(sheet.getRule('f')).to.not.be(undefined);
});
it('should compose classes', function () {
(0, _expect2.default)(sheet.classes.d).to.be('d-id a-id b-id c-id');
(0, _expect2.default)(sheet.classes.e).to.be('e-id a-id b-id c-id');
(0, _expect2.default)(sheet.classes.f).to.be('f-id a-id b-id c-id');
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' float: left;\n' + '}\n' + '.b-id {\n' + ' color: red;\n' + '}\n' + '.c-id {\n' + ' background: blue;\n' + '}\n' + '.d-id {\n' + ' border: none;\n' + '}\n' + '.e-id {\n' + ' border: none;\n' + '}\n' + '.f-id {\n' + ' border: none;\n' + '}');
});
});
describe('Mixed composition', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
float: 'left'
},
b: {
composes: ['$a', 'c', 'd'],
color: 'red'
},
e: {
composes: '$a c d',
color: 'red'
}
});
});
afterEach(function () {
(0, _expect2.default)(warning).to.be(undefined);
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
(0, _expect2.default)(sheet.getRule('b')).to.not.be(undefined);
(0, _expect2.default)(sheet.getRule('e')).to.not.be(undefined);
});
it('should compose classes', function () {
(0, _expect2.default)(sheet.classes.b).to.be('b-id a-id c d');
(0, _expect2.default)(sheet.classes.e).to.be('e-id a-id c d');
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' float: left;\n' + '}\n' + '.b-id {\n' + ' color: red;\n' + '}\n' + '.e-id {\n' + ' color: red;\n' + '}');
});
});
describe('Nested compositions (compose composed)', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
float: 'left'
},
b: {
composes: ['$a', 'd'],
color: 'red'
},
c: {
composes: ['$b'],
background: 'blue'
}
});
});
afterEach(function () {
(0, _expect2.default)(warning).to.be(undefined);
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
(0, _expect2.default)(sheet.getRule('b')).to.not.be(undefined);
(0, _expect2.default)(sheet.getRule('c')).to.not.be(undefined);
});
it('should compose classes', function () {
(0, _expect2.default)(sheet.classes.b).to.be('b-id a-id d');
(0, _expect2.default)(sheet.classes.c).to.be('c-id b-id a-id d');
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' float: left;\n' + '}\n' + '.b-id {\n' + ' color: red;\n' + '}\n' + '.c-id {\n' + ' background: blue;\n' + '}');
});
});
describe('Warnings', function () {
it('should warn when rule try to compose itself', function () {
jss.createStyleSheet({
a: {
composes: ['$a'],
color: 'red'
}
});
(0, _expect2.default)(warning).to.be('[JSS] Cyclic composition detected. \r\n%s');
});
it('should warn when try to compose ref which can\'t be resolved', function () {
jss.createStyleSheet({
a: {
composes: ['$b'],
color: 'red'
}
});
(0, _expect2.default)(warning).to.be('[JSS] Referenced rule is not defined. \r\n%s');
});
});
}); /* eslint-disable no-underscore-dangle */

View File

@@ -0,0 +1,116 @@
{
"_args": [
[
"jss-compose@4.0.0",
"C:\\Users\\deranjer\\go\\src\\github.com\\deranjer\\goTorrent\\torrent-project"
]
],
"_from": "jss-compose@4.0.0",
"_id": "jss-compose@4.0.0",
"_inBundle": false,
"_integrity": "sha512-VnsEziD2Lwrfwp10wx39FNybRLW5+RX/E2qQAXPAMbS+nHc0Jf2dC6ZiCfn5FaBGrpzLfIZ9MalTJDx4CQoMAQ==",
"_location": "/material-ui/jss-compose",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "jss-compose@4.0.0",
"name": "jss-compose",
"escapedName": "jss-compose",
"rawSpec": "4.0.0",
"saveSpec": null,
"fetchSpec": "4.0.0"
},
"_requiredBy": [
"/material-ui/jss-preset-default"
],
"_resolved": "https://registry.npmjs.org/jss-compose/-/jss-compose-4.0.0.tgz",
"_spec": "4.0.0",
"_where": "C:\\Users\\deranjer\\go\\src\\github.com\\deranjer\\goTorrent\\torrent-project",
"author": {
"name": "Pavel Davydov",
"email": "typical000@gmail.com"
},
"bugs": {
"url": "https://github.com/cssinjs/jss-compose/issues"
},
"dependencies": {
"warning": "^3.0.0"
},
"description": "JSS plugin for classes composition",
"devDependencies": {
"babel-cli": "^6.5.1",
"babel-core": "^6.5.1",
"babel-eslint": "^7.0.0",
"babel-loader": "^6.2.4",
"babel-plugin-rewire": "^1.0.0",
"babel-preset-es2015": "^6.9.0",
"babel-preset-stage-0": "^6.5.0",
"cross-env": "^3.0.0",
"eslint": "^3.6.1",
"eslint-config-airbnb": "^12.0.0",
"eslint-config-jss": "^2.4.0",
"eslint-plugin-import": "^1.12.0",
"eslint-plugin-jsx-a11y": "^2.2.2",
"eslint-plugin-react": "^6.3.0",
"expect.js": "^0.3.1",
"jss": "^8.0.0",
"karma": "^1.1.1",
"karma-chrome-launcher": "^2.0.0",
"karma-coverage": "^1.1.0",
"karma-mocha": "^1.0.1",
"karma-mocha-reporter": "^2.0.2",
"karma-sourcemap-loader": "^0.3.5",
"karma-webpack": "^1.7.0",
"lint-staged": "^3.0.1",
"mocha": "^3.0.2",
"pre-commit": "^1.1.3",
"rimraf": "^2.5.4",
"webpack": "^1.12.2"
},
"homepage": "https://github.com/cssinjs/jss-compose#readme",
"keywords": [
"cssinnjs",
"css-in-js",
"css in js",
"jss",
"plugin",
"compose",
"composition"
],
"license": "MIT",
"lint-staged": {
"./src/*.js": [
"eslint",
"git add"
]
},
"main": "./lib/index.js",
"name": "jss-compose",
"peerDependencies": {
"jss": "^8.0.0"
},
"pre-commit": "lint:staged",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/cssinjs/jss-compose.git"
},
"scripts": {
"all": "npm run lint && npm run test && npm run build",
"build": "npm run clean && npm run build:lib && npm run build:tests && npm run build:dist",
"build:dist": "npm run build:dist:max && npm run build:dist:min",
"build:dist:max": "cross-env NODE_ENV=development webpack src/index.js dist/jss-compose.js",
"build:dist:min": "cross-env NODE_ENV=production webpack src/index.js dist/jss-compose.min.js",
"build:lib": "babel src --out-dir lib",
"build:tests": "npm run build:tests:lib && npm run build:tests:local",
"build:tests:lib": "cross-env NODE_ENV=test babel src --out-dir tests",
"build:tests:local": "cross-env NODE_ENV=test webpack src/index.test.js tmp/tests.js",
"clean": "rimraf '{lib,dist,tests,tmp}/*'",
"lint": "eslint ./src",
"lint:staged": "lint-staged",
"prepublishOnly": "npm run all",
"test": "cross-env NODE_ENV=test karma start --single-run ",
"test:watch": "cross-env NODE_ENV=test karma start"
},
"version": "4.0.0"
}

View File

@@ -0,0 +1,175 @@
# JSS plugin for classes composition
This plugin allows you to use CSS frameworks and legacy code together with JSS as well as reuse Rules more granularly.
Make sure you read [how to use
plugins](https://github.com/cssinjs/jss/blob/master/docs/setup.md#setup-with-plugins)
in general.
[![Gitter](https://badges.gitter.im/JoinChat.svg)](https://gitter.im/cssinjs/lobby)
## Compose with global classes.
To combine JSS with CSS framework like [Material Design Lite](https://getmdl.io/) or [Bootstrap](http://getbootstrap.com/) and others.
```javascript
const styles = {
button: {
// Using space separated class names.
composes: 'btn btn-primary',
color: 'red'
}
buttonActive: {
// Using an array of class names.
composes: ['btn', 'btn-primary'],
color: 'blue'
}
}
```
Compiles to:
```css
.button-123456 {
color: red;
}
.buttonActive-123456 {
color: blue;
}
```
When you use it:
```javascript
<button className={classes.button}>Button</button>
<button className={classes.buttonActive}>Active Button</button>
```
It renders to:
```html
<button class="button-123456 btn">Button</button>
<button class="button-123456 btn btn-primary">Active Button</button>
```
## Compose with local classes.
Manage element states without rules duplication.
To reference a local rule, prefix the rule name with `$` symbol.
```javascript
const styles = {
button: {
color: 'black'
},
// You can chain compositions
buttonActive: {
composes: '$button',
color: 'red'
},
buttonActiveDisabled: {
composes: '$buttonActive',
opacity: 0.5
},
// Or use arrays
disabled: {
opacity: 0.5
},
active: {
color: 'red'
},
buttonDisabled: {
composes: ['$button', '$active', '$disabled']
}
}
```
Compiles to:
```css
.button-123456 {
color: black;
}
.buttonActive-123456 {
color: red;
}
.buttonActiveDisabled-123456 {
opacity: 0.5;
}
.disabled-123456 {
opacity: 0.5;
}
.active-123456 {
color: red;
}
/* Rule `buttonDisabled` is not compiled to CSS, because it has no own properties. */
```
When you use it:
```javascript
<button className={classes.buttonActiveDisabled}>Active Disabled Button</button>
<button className={classes.buttonDisabled}>Disabled Button with active state</button>
```
It renders to:
```html
<button class="button-123456 buttonActive-123456">Active Disabled Button</button>
<button class="buttonDisabled-123456 button-123456 active-123456 disabled-123456">Disabled Button with active state</button>
```
## Mix global and local classes.
You can compose both local and global classes at the same time.
```javascript
const styles = {
active: {
color: 'red'
},
button: {
composes: ['$active', 'btn', 'btn-primary'],
color: 'blue'
}
}
```
Compiles to:
```css
.active-123456 {
color: red;
}
.button-123456 {
color: blue;
}
```
When you use it:
```javascript
<button className={classes.button}>Button</button>
```
It renders to:
```html
<button class="button-123456 active-123456 btn btn-primary">Button</button>
```
## Caveats
- Doesn't work within [global Style Sheets](https://github.com/cssinjs/jss-global).
- Does not work inside of [nested rules](https://github.com/cssinjs/jss-nested).
- When composing local rules, they need to be defined first. Otherwise you get wrong css selector order and specificity.
## Issues
File a bug against [cssinjs/jss prefixed with \[jss-compose\]](https://github.com/cssinjs/jss/issues/new?title=[jss-compose]%20).
## Run tests
```bash
npm i
npm test
```
## License
MIT

View File

@@ -0,0 +1,19 @@
<html>
<head>
<meta charset="utf-8">
<title>JSS Tests</title>
<link href="./node_modules/mocha/mocha.css" rel="stylesheet" />
</head>
<body>
<div id="mocha"></div>
<script src="./node_modules/expect.js/index.js"></script>
<script src="./node_modules/mocha/mocha.js"></script>
<script>mocha.setup('bdd')</script>
<script src="./tmp/tests.js"></script>
<script>
mocha.checkLeaks();
mocha.run();
</script>
</body>
</html>

View File

@@ -0,0 +1,2 @@
const context = require.context('./src', true, /\.test\.js$/)
context.keys().forEach(context)

View File

@@ -0,0 +1,236 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.__RewireAPI__ = exports.__ResetDependency__ = exports.__set__ = exports.__Rewire__ = exports.__GetDependency__ = exports.__get__ = undefined;
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
exports.default = jssCompose;
var _warning = require('warning');
var _warning2 = _interopRequireDefault(_warning);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Set selector.
*
* @param {Object} original rule
* @param {String} className class string
* @return {Boolean} flag, indicating function was successfull or not
*/
function registerClass(rule, className) {
// Skip falsy values
if (!className) return true;
// Support array of class names `{composes: ['foo', 'bar']}`
if (Array.isArray(className)) {
for (var index = 0; index < className.length; index++) {
var isSetted = _get__('registerClass')(rule, className[index]);
if (!isSetted) return false;
}
return true;
}
// Support space separated class names `{composes: 'foo bar'}`
if (className.indexOf(' ') > -1) {
return _get__('registerClass')(rule, className.split(' '));
}
var parent = rule.options.parent;
// It is a ref to a local rule.
if (className[0] === '$') {
var refRule = parent.getRule(className.substr(1));
if (!refRule) {
_get__('warning')(false, '[JSS] Referenced rule is not defined. \r\n%s', rule);
return false;
}
if (refRule === rule) {
_get__('warning')(false, '[JSS] Cyclic composition detected. \r\n%s', rule);
return false;
}
parent.classes[rule.key] += ' ' + parent.classes[refRule.key];
return true;
}
rule.options.parent.classes[rule.key] += ' ' + className;
return true;
}
/**
* Convert compose property to additional class, remove property from original styles.
*
* @param {Rule} rule
* @api public
*/
function jssCompose() {
function onProcessStyle(style, rule) {
if (!style.composes) return style;
_get__('registerClass')(rule, style.composes);
// Remove composes property to prevent infinite loop.
delete style.composes;
return style;
}
return { onProcessStyle: onProcessStyle };
}
var _RewiredData__ = Object.create(null);
var INTENTIONAL_UNDEFINED = '__INTENTIONAL_UNDEFINED__';
var _RewireAPI__ = {};
(function () {
function addPropertyToAPIObject(name, value) {
Object.defineProperty(_RewireAPI__, name, {
value: value,
enumerable: false,
configurable: true
});
}
addPropertyToAPIObject('__get__', _get__);
addPropertyToAPIObject('__GetDependency__', _get__);
addPropertyToAPIObject('__Rewire__', _set__);
addPropertyToAPIObject('__set__', _set__);
addPropertyToAPIObject('__reset__', _reset__);
addPropertyToAPIObject('__ResetDependency__', _reset__);
addPropertyToAPIObject('__with__', _with__);
})();
function _get__(variableName) {
if (_RewiredData__ === undefined || _RewiredData__[variableName] === undefined) {
return _get_original__(variableName);
} else {
var value = _RewiredData__[variableName];
if (value === INTENTIONAL_UNDEFINED) {
return undefined;
} else {
return value;
}
}
}
function _get_original__(variableName) {
switch (variableName) {
case 'registerClass':
return registerClass;
case 'warning':
return _warning2.default;
}
return undefined;
}
function _assign__(variableName, value) {
if (_RewiredData__ === undefined || _RewiredData__[variableName] === undefined) {
return _set_original__(variableName, value);
} else {
return _RewiredData__[variableName] = value;
}
}
function _set_original__(variableName, _value) {
switch (variableName) {}
return undefined;
}
function _update_operation__(operation, variableName, prefix) {
var oldValue = _get__(variableName);
var newValue = operation === '++' ? oldValue + 1 : oldValue - 1;
_assign__(variableName, newValue);
return prefix ? newValue : oldValue;
}
function _set__(variableName, value) {
if ((typeof variableName === 'undefined' ? 'undefined' : _typeof(variableName)) === 'object') {
Object.keys(variableName).forEach(function (name) {
_RewiredData__[name] = variableName[name];
});
} else {
if (value === undefined) {
_RewiredData__[variableName] = INTENTIONAL_UNDEFINED;
} else {
_RewiredData__[variableName] = value;
}
return function () {
_reset__(variableName);
};
}
}
function _reset__(variableName) {
delete _RewiredData__[variableName];
}
function _with__(object) {
var rewiredVariableNames = Object.keys(object);
var previousValues = {};
function reset() {
rewiredVariableNames.forEach(function (variableName) {
_RewiredData__[variableName] = previousValues[variableName];
});
}
return function (callback) {
rewiredVariableNames.forEach(function (variableName) {
previousValues[variableName] = _RewiredData__[variableName];
_RewiredData__[variableName] = object[variableName];
});
var result = callback();
if (!!result && typeof result.then == 'function') {
result.then(reset).catch(reset);
} else {
reset();
}
return result;
};
}
var _typeOfOriginalExport = typeof jssCompose === 'undefined' ? 'undefined' : _typeof(jssCompose);
function addNonEnumerableProperty(name, value) {
Object.defineProperty(jssCompose, name, {
value: value,
enumerable: false,
configurable: true
});
}
if ((_typeOfOriginalExport === 'object' || _typeOfOriginalExport === 'function') && Object.isExtensible(jssCompose)) {
addNonEnumerableProperty('__get__', _get__);
addNonEnumerableProperty('__GetDependency__', _get__);
addNonEnumerableProperty('__Rewire__', _set__);
addNonEnumerableProperty('__set__', _set__);
addNonEnumerableProperty('__reset__', _reset__);
addNonEnumerableProperty('__ResetDependency__', _reset__);
addNonEnumerableProperty('__with__', _with__);
addNonEnumerableProperty('__RewireAPI__', _RewireAPI__);
}
exports.__get__ = _get__;
exports.__GetDependency__ = _get__;
exports.__Rewire__ = _set__;
exports.__set__ = _set__;
exports.__ResetDependency__ = _reset__;
exports.__RewireAPI__ = _RewireAPI__;

View File

@@ -0,0 +1,387 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.__RewireAPI__ = exports.__ResetDependency__ = exports.__set__ = exports.__Rewire__ = exports.__GetDependency__ = exports.__get__ = undefined;
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; /* eslint-disable no-underscore-dangle */
var _expect = require('expect.js');
var _expect2 = _interopRequireDefault(_expect);
var _jss = require('jss');
var _ = require('./');
var _2 = _interopRequireDefault(_);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
describe('jss-compose', function () {
var jss = void 0;
var warning = void 0;
beforeEach(function () {
_get__('compose').__Rewire__('warning', function (condition, message) {
warning = message;
});
jss = _get__('create')({
createGenerateClassName: function createGenerateClassName() {
return function (rule) {
return rule.key + '-id';
};
}
}).use(_get__('compose')());
});
afterEach(function () {
_get__('compose').__ResetDependency__('warning');
warning = undefined;
});
describe('Ref composition', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
float: 'left'
},
b: {
composes: '$a',
color: 'red'
}
});
});
afterEach(function () {
_get__('expect')(warning).to.be(undefined);
});
it('should add rules', function () {
_get__('expect')(sheet.getRule('a')).to.not.be(undefined);
_get__('expect')(sheet.getRule('b')).to.not.be(undefined);
});
it('should compose classes', function () {
_get__('expect')(sheet.classes.b).to.be('b-id a-id');
});
it('should generate correct CSS', function () {
_get__('expect')(sheet.toString()).to.be('.a-id {\n' + ' float: left;\n' + '}\n' + '.b-id {\n' + ' color: red;\n' + '}');
});
});
describe('Global class composition', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
composes: 'b',
color: 'red'
}
});
});
afterEach(function () {
_get__('expect')(warning).to.be(undefined);
});
it('should compose classes', function () {
_get__('expect')(sheet.classes.a).to.be('a-id b');
});
it('should generate correct CSS', function () {
_get__('expect')(sheet.toString()).to.be('.a-id {\n' + ' color: red;\n' + '}');
});
});
describe('Array of refs composition', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
float: 'left'
},
b: {
color: 'red'
},
c: {
background: 'blue'
},
d: {
composes: ['$a', '$b', '$c'],
border: 'none'
},
e: {
composes: '$a $b $c',
border: 'none'
},
f: {
composes: ['$a', ['$b', '$c']],
border: 'none'
}
});
});
afterEach(function () {
_get__('expect')(warning).to.be(undefined);
});
it('should add rules', function () {
_get__('expect')(sheet.getRule('a')).to.not.be(undefined);
_get__('expect')(sheet.getRule('b')).to.not.be(undefined);
_get__('expect')(sheet.getRule('c')).to.not.be(undefined);
_get__('expect')(sheet.getRule('d')).to.not.be(undefined);
_get__('expect')(sheet.getRule('e')).to.not.be(undefined);
_get__('expect')(sheet.getRule('f')).to.not.be(undefined);
});
it('should compose classes', function () {
_get__('expect')(sheet.classes.d).to.be('d-id a-id b-id c-id');
_get__('expect')(sheet.classes.e).to.be('e-id a-id b-id c-id');
_get__('expect')(sheet.classes.f).to.be('f-id a-id b-id c-id');
});
it('should generate correct CSS', function () {
_get__('expect')(sheet.toString()).to.be('.a-id {\n' + ' float: left;\n' + '}\n' + '.b-id {\n' + ' color: red;\n' + '}\n' + '.c-id {\n' + ' background: blue;\n' + '}\n' + '.d-id {\n' + ' border: none;\n' + '}\n' + '.e-id {\n' + ' border: none;\n' + '}\n' + '.f-id {\n' + ' border: none;\n' + '}');
});
});
describe('Mixed composition', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
float: 'left'
},
b: {
composes: ['$a', 'c', 'd'],
color: 'red'
},
e: {
composes: '$a c d',
color: 'red'
}
});
});
afterEach(function () {
_get__('expect')(warning).to.be(undefined);
});
it('should add rules', function () {
_get__('expect')(sheet.getRule('a')).to.not.be(undefined);
_get__('expect')(sheet.getRule('b')).to.not.be(undefined);
_get__('expect')(sheet.getRule('e')).to.not.be(undefined);
});
it('should compose classes', function () {
_get__('expect')(sheet.classes.b).to.be('b-id a-id c d');
_get__('expect')(sheet.classes.e).to.be('e-id a-id c d');
});
it('should generate correct CSS', function () {
_get__('expect')(sheet.toString()).to.be('.a-id {\n' + ' float: left;\n' + '}\n' + '.b-id {\n' + ' color: red;\n' + '}\n' + '.e-id {\n' + ' color: red;\n' + '}');
});
});
describe('Nested compositions (compose composed)', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
float: 'left'
},
b: {
composes: ['$a', 'd'],
color: 'red'
},
c: {
composes: ['$b'],
background: 'blue'
}
});
});
afterEach(function () {
_get__('expect')(warning).to.be(undefined);
});
it('should add rules', function () {
_get__('expect')(sheet.getRule('a')).to.not.be(undefined);
_get__('expect')(sheet.getRule('b')).to.not.be(undefined);
_get__('expect')(sheet.getRule('c')).to.not.be(undefined);
});
it('should compose classes', function () {
_get__('expect')(sheet.classes.b).to.be('b-id a-id d');
_get__('expect')(sheet.classes.c).to.be('c-id b-id a-id d');
});
it('should generate correct CSS', function () {
_get__('expect')(sheet.toString()).to.be('.a-id {\n' + ' float: left;\n' + '}\n' + '.b-id {\n' + ' color: red;\n' + '}\n' + '.c-id {\n' + ' background: blue;\n' + '}');
});
});
describe('Warnings', function () {
it('should warn when rule try to compose itself', function () {
jss.createStyleSheet({
a: {
composes: ['$a'],
color: 'red'
}
});
_get__('expect')(warning).to.be('[JSS] Cyclic composition detected. \r\n%s');
});
it('should warn when try to compose ref which can\'t be resolved', function () {
jss.createStyleSheet({
a: {
composes: ['$b'],
color: 'red'
}
});
_get__('expect')(warning).to.be('[JSS] Referenced rule is not defined. \r\n%s');
});
});
});
var _RewiredData__ = Object.create(null);
var INTENTIONAL_UNDEFINED = '__INTENTIONAL_UNDEFINED__';
var _RewireAPI__ = {};
(function () {
function addPropertyToAPIObject(name, value) {
Object.defineProperty(_RewireAPI__, name, {
value: value,
enumerable: false,
configurable: true
});
}
addPropertyToAPIObject('__get__', _get__);
addPropertyToAPIObject('__GetDependency__', _get__);
addPropertyToAPIObject('__Rewire__', _set__);
addPropertyToAPIObject('__set__', _set__);
addPropertyToAPIObject('__reset__', _reset__);
addPropertyToAPIObject('__ResetDependency__', _reset__);
addPropertyToAPIObject('__with__', _with__);
})();
function _get__(variableName) {
if (_RewiredData__ === undefined || _RewiredData__[variableName] === undefined) {
return _get_original__(variableName);
} else {
var value = _RewiredData__[variableName];
if (value === INTENTIONAL_UNDEFINED) {
return undefined;
} else {
return value;
}
}
}
function _get_original__(variableName) {
switch (variableName) {
case 'compose':
return _2.default;
case 'create':
return _jss.create;
case 'expect':
return _expect2.default;
}
return undefined;
}
function _assign__(variableName, value) {
if (_RewiredData__ === undefined || _RewiredData__[variableName] === undefined) {
return _set_original__(variableName, value);
} else {
return _RewiredData__[variableName] = value;
}
}
function _set_original__(variableName, _value) {
switch (variableName) {}
return undefined;
}
function _update_operation__(operation, variableName, prefix) {
var oldValue = _get__(variableName);
var newValue = operation === '++' ? oldValue + 1 : oldValue - 1;
_assign__(variableName, newValue);
return prefix ? newValue : oldValue;
}
function _set__(variableName, value) {
if ((typeof variableName === 'undefined' ? 'undefined' : _typeof(variableName)) === 'object') {
Object.keys(variableName).forEach(function (name) {
_RewiredData__[name] = variableName[name];
});
} else {
if (value === undefined) {
_RewiredData__[variableName] = INTENTIONAL_UNDEFINED;
} else {
_RewiredData__[variableName] = value;
}
return function () {
_reset__(variableName);
};
}
}
function _reset__(variableName) {
delete _RewiredData__[variableName];
}
function _with__(object) {
var rewiredVariableNames = Object.keys(object);
var previousValues = {};
function reset() {
rewiredVariableNames.forEach(function (variableName) {
_RewiredData__[variableName] = previousValues[variableName];
});
}
return function (callback) {
rewiredVariableNames.forEach(function (variableName) {
previousValues[variableName] = _RewiredData__[variableName];
_RewiredData__[variableName] = object[variableName];
});
var result = callback();
if (!!result && typeof result.then == 'function') {
result.then(reset).catch(reset);
} else {
reset();
}
return result;
};
}
exports.__get__ = _get__;
exports.__GetDependency__ = _get__;
exports.__Rewire__ = _set__;
exports.__set__ = _set__;
exports.__ResetDependency__ = _reset__;
exports.__RewireAPI__ = _RewireAPI__;
exports.default = _RewireAPI__;

View File

@@ -0,0 +1,35 @@
var webpack = require('webpack')
var plugins = [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
__DEV__: process.env.NODE_ENV === 'development',
__TEST__: process.env.NODE_ENV === 'test'
})
]
if (process.env.NODE_ENV === 'production') {
plugins.push(new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}))
}
module.exports = {
output: {
library: 'jssCompose',
libraryTarget: 'umd'
},
plugins,
module: {
loaders: [
{
loader: 'babel-loader',
test: /\.js$/,
exclude: /node_modules/
}
]
},
devtool: 'source-map'
}