Removed GopherJS, basic frontend completed, need backend changes for

torrent storage
This commit is contained in:
2017-11-30 18:12:11 -05:00
parent 67fdef16b1
commit e98ad2cc88
69321 changed files with 5498914 additions and 337 deletions

View File

@@ -0,0 +1,3 @@
{
"presets": ["stage-0", "es2015"]
}

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,21 @@
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,8 @@
{
".link": {
"margin": [ 0, 0, "5px", 0 ],
"padding": [ 0, "20px", 0 ],
"border-radius": [ "10px", "20px" ],
"box-shadow": [ "0 0 5px #f00", "0 5px 20px #ff0" ]
}
}

View File

@@ -0,0 +1,8 @@
{
".link": {
"margin": [[ 0, 0, "5px", 0 ]],
"padding": [[ 0, "20px", 0 ]],
"border-radius": [[ "10px", "20px" ]],
"box-shadow": [ "0 0 5px #f00", "0 5px 20px #ff0" ]
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,71 @@
{
".link": {
"background": {
"color": "rgba(0, 0, 0, 0.3)",
"image": "url(test.jpg)",
"repeat": "no-repeat",
"position": [0, 0]
},
"border": {
"width": "1px",
"style": "solid",
"color": "black"
},
"border-left": 0,
"clear": "both",
"margin": [ 0, 0, "5px", 0 ],
"text-decoration": "none",
"display": "block",
"transition": [{
"property": "opacity",
"duration": "0.5s",
"timing-function": "linear"
}, {
"property": "background",
"duration": "1s",
"timing-function": "ease"
}]
},
".element": {
"transition": [{
"property": "opacity",
"duration": "1s",
"timing-function": "linear"
}, {
"property": "background",
"duration": "0.5s",
"timing-function": "ease"
}],
"background": "#fff",
"opacity": 1,
"padding": [ "10px", 0 ],
"font": "bold 16px/30px Helvetica, Arial, sans-serif",
"box-shadow": {
"blur": "25px",
"color": "rgba(0, 0, 0, 0.5)",
"inset": "inset"
},
"text-shadow": {
"x": 0,
"y": "1px",
"blur": 0,
"color": "#fff"
}
},
".container": {
"margin": {
"top": "5px",
"bottom": 0,
"right": "10px",
"left": "5px"
},
"padding": {
"top": "15px",
"bottom": 0,
"right": "15px",
"left": "15px"
},
"max-width": "1180px",
"width": "100%"
}
}

View File

@@ -0,0 +1,30 @@
{
".link": {
"background": "rgba(0, 0, 0, 0.3) url(test.jpg) no-repeat 0 0",
"border": "1px solid black",
"border-left": 0,
"clear": "both",
"margin": [[ 0, 0, "5px", 0 ]],
"text-decoration": "none",
"display": "block",
"transition": ["opacity 0.5s linear", "background 1s ease"]
},
".element": {
"transition": [
[["opacity", "1s", "linear"]],
[["background", "0.5s", "ease"]]
],
"background": "#fff",
"opacity": 1,
"padding": [[ "10px", 0 ]],
"font": "bold 16px/30px Helvetica, Arial, sans-serif",
"box-shadow": "0 0 25px rgba(0, 0, 0, 0.5) inset",
"text-shadow": "0 1px 0 #fff"
},
".container": {
"margin": [[ "5px", "10px", 0, "5px"]],
"margin": [[ "15px", "15px", 0, "15px"]],
"max-width": "1180px",
"width": "100%"
}
}

View File

@@ -0,0 +1,30 @@
import {create} from 'jss'
import jssExpand from './../../src'
import arraysWithoutPlugin from '../fixtures/arrays-without-plugin.json'
import arraysWithPlugin from '../fixtures/arrays-with-plugin.json'
suite('Array with DIFFERENT sheets', () => {
benchmark('Pure JSS', () => {
const jss = create()
jss.createStyleSheet(arraysWithoutPlugin).toString()
})
benchmark('JSS + Plugin', () => {
const jss = create()
jss.use(jssExpand())
jss.createStyleSheet(arraysWithPlugin).toString()
})
})
suite('Array with SAME sheets', () => {
benchmark('Pure JSS', () => {
const jss = create()
jss.createStyleSheet(arraysWithoutPlugin).toString()
})
benchmark('JSS + Plugin', () => {
const jss = create()
jss.use(jssExpand())
jss.createStyleSheet(arraysWithoutPlugin).toString()
})
})

View File

@@ -0,0 +1,16 @@
import {create} from 'jss'
import jssExpand from './../../src'
import styles from '../fixtures/bootstrap.json'
suite('Bootstrap unnamed JSS test', () => {
benchmark('Pure JSS', () => {
const jss = create()
jss.createStyleSheet(styles, {named: false}).toString()
})
benchmark('JSS + Plugin', () => {
const jss = create()
jss.use(jssExpand())
jss.createStyleSheet(styles, {named: false}).toString()
})
})

View File

@@ -0,0 +1,30 @@
import {create} from 'jss'
import jssExpand from '../../src'
import stylesWithoutPlugin from '../fixtures/sheet-without-plugin.json'
import stylesWithPlugin from '../fixtures/sheet-with-plugin.json'
suite('General test with DIFFERENT sheets', () => {
benchmark('Pure JSS', () => {
const jss = create()
jss.createStyleSheet(stylesWithoutPlugin).toString()
})
benchmark('JSS + Plugin', () => {
const jss = create()
jss.use(jssExpand())
jss.createStyleSheet(stylesWithPlugin).toString()
})
})
suite('General test with SAME sheet)', () => {
benchmark('Pure JSS', () => {
const jss = create()
jss.createStyleSheet(stylesWithoutPlugin).toString()
})
benchmark('JSS + Plugin', () => {
const jss = create()
jss.use(jssExpand())
jss.createStyleSheet(stylesWithoutPlugin).toString()
})
})

View File

@@ -0,0 +1,87 @@
## 4.0.1 / 2017-08-17
- Support box-shadow spread property without blur one cssinjs/jss#563
## 4.0.0 / 2017-06-20
- Support jss 8
## 3.0.1 / 2017-04-18
- Add webpack to the devDeps
## 3.0.0 / 2017-04-10
- Support jss 7.0
## 2.1.0 / 2017-02-26
- Added support of all flexbox and align related properties.
## 2.0.3 / 2016-12-31
- Support empty arrays cssinjs/jss#398
## 2.0.2 / 2016-12-21
- Support custom props inside fallbacks.
- Always generate `background-image` from `background: {image}`.
## 2.0.1 / 2016-12-09
- update to jss 6.0
- docs
## 1.6.1 / 2016-11-24
- Add more supported space separated properties
## 1.6.0 / 2016-11-12
- Fix benchmark test
- Add possibility to write custom properties
## 1.5.2 / 2016-10-11
- fix build name
## 1.5.1 / 2016-09-30
- refactoring
- tests integration into jss repo
## 1.5.0 / 2016-09-06
- Migrate from jQunit to mocha
## 1.4.2 / 2016-08-07
- Integration with jss-camel-case
## 1.4.1 / 2016-08-07
- Minor code updates
## 1.4.0 / 2016-08-06
- Performance optimizations
## 1.3.0 / 2016-07-31
- Add benchmarks
## 1.2.0 / 2016-07-11
- Update dependencies
- Updated code to match JSS 5.0.0 release (add handling of new fallback feature)
- Add tests
## 1.1.0 / 2016-07-07
- Renamed plugin
- Write additional tests
- Add new fallbacks handling
## 1.0.0 / 2016-06-15
- Stable version

View File

@@ -0,0 +1,413 @@
(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["jssExpand"] = factory();
else
root["jssExpand"] = 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
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
exports.default = jssExpand;
var _props = __webpack_require__(1);
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
/**
* Map values by given prop.
*
* @param {Array} array of values
* @param {String} original property
* @param {String} original rule
* @return {String} mapped values
*/
function mapValuesByProp(value, prop, rule) {
return value.map(function (item) {
return objectToString(item, prop, rule);
});
}
/**
* Convert array to string.
*
* @param {Array} array of values
* @param {String} original property
* @param {Object} sheme, for converting arrays in strings
* @param {Object} original rule
* @return {String} converted string
*/
function arrayToString(value, prop, scheme, rule) {
if (scheme[prop] == null) return value.join(',');
if (value.length === 0) return '';
if (Array.isArray(value[0])) return arrayToString(value[0], prop, scheme);
if (_typeof(value[0]) === 'object') return mapValuesByProp(value, prop, rule);
return value.join(' ');
}
/**
* Convert object to string.
*
* @param {Object} object of values
* @param {String} original property
* @param {Object} original rule
* @param {Boolean} is fallback prop
* @return {String} converted string
*/
function objectToString(value, prop, rule, isFallback) {
if (!(_props.propObj[prop] || _props.customPropObj[prop])) return '';
var result = [];
// Check if exists any non-standart property
if (_props.customPropObj[prop]) {
value = customPropsToStyle(value, rule, _props.customPropObj[prop], isFallback);
}
// Pass throught all standart props
if (Object.keys(value).length) {
for (var baseProp in _props.propObj[prop]) {
if (value[baseProp]) {
if (Array.isArray(value[baseProp])) {
result.push(arrayToString(value[baseProp], baseProp, _props.propArrayInObj));
} else result.push(value[baseProp]);
continue;
}
// Add default value from props config.
if (_props.propObj[prop][baseProp] != null) {
result.push(_props.propObj[prop][baseProp]);
}
}
}
return result.join(' ');
}
/**
* Convert custom properties values to styles adding them to rule directly
*
* @param {Object} object of values
* @param {Object} original rule
* @param {String} property, that contain partial custom properties
* @param {Boolean} is fallback prop
* @return {Object} value without custom properties, that was already added to rule
*/
function customPropsToStyle(value, rule, customProps, isFallback) {
for (var prop in customProps) {
var propName = customProps[prop];
// If current property doesn't exist already in rule - add new one
if (typeof value[prop] !== 'undefined' && (isFallback || !rule.prop(propName))) {
var appendedValue = styleDetector(_defineProperty({}, propName, value[prop]), rule)[propName];
// Add style directly in rule
if (isFallback) rule.style.fallbacks[propName] = appendedValue;else rule.style[propName] = appendedValue;
}
// Delete converted property to avoid double converting
delete value[prop];
}
return value;
}
/**
* Detect if a style needs to be converted.
*
* @param {Object} style
* @param {Object} rule
* @param {Boolean} is fallback prop
* @return {Object} convertedStyle
*/
function styleDetector(style, rule, isFallback) {
for (var prop in style) {
var value = style[prop];
if (Array.isArray(value)) {
// Check double arrays to avoid recursion.
if (!Array.isArray(value[0])) {
if (prop === 'fallbacks') {
for (var index = 0; index < style.fallbacks.length; index++) {
style.fallbacks[index] = styleDetector(style.fallbacks[index], rule, true);
}
continue;
}
style[prop] = arrayToString(value, prop, _props.propArray);
// Avoid creating properties with empty values
if (!style[prop]) delete style[prop];
}
} else if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object') {
if (prop === 'fallbacks') {
style.fallbacks = styleDetector(style.fallbacks, rule, true);
continue;
}
style[prop] = objectToString(value, prop, rule, isFallback);
// Avoid creating properties with empty values
if (!style[prop]) delete style[prop];
}
// Maybe a computed value resulting in an empty string
else if (style[prop] === '') delete style[prop];
}
return style;
}
/**
* Adds possibility to write expanded styles.
*
* @param {Rule} rule
* @api public
*/
function jssExpand() {
function onProcessStyle(style, rule) {
if (!style || rule.type !== 'style') return style;
if (Array.isArray(style)) {
// Pass rules one by one and reformat them
for (var index = 0; index < style.length; index++) {
style[index] = styleDetector(style[index], rule);
}
return style;
}
return styleDetector(style, rule);
}
return { onProcessStyle: onProcessStyle };
}
/***/ }),
/* 1 */
/***/ (function(module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
/**
* A scheme for converting properties from array to regular style.
* All properties listed below will be transformed to a string separated by space.
*/
var propArray = exports.propArray = {
'background-size': true,
'background-position': true,
border: true,
'border-bottom': true,
'border-left': true,
'border-top': true,
'border-right': true,
'border-radius': true,
'box-shadow': true,
flex: true,
margin: true,
padding: true,
outline: true,
'transform-origin': true,
transform: true,
transition: true
};
/**
* A scheme for converting arrays to regular styles inside of objects.
* For e.g.: "{position: [0, 0]}" => "background-position: 0 0;".
*/
var propArrayInObj = exports.propArrayInObj = {
position: true, // background-position
size: true // background-size
};
/**
* A scheme for parsing and building correct styles from passed objects.
*/
var propObj = exports.propObj = {
padding: {
top: 0,
right: 0,
bottom: 0,
left: 0
},
margin: {
top: 0,
right: 0,
bottom: 0,
left: 0
},
background: {
attachment: null,
color: null,
image: null,
position: null,
repeat: null
},
border: {
width: null,
style: null,
color: null
},
'border-top': {
width: null,
style: null,
color: null
},
'border-right': {
width: null,
style: null,
color: null
},
'border-bottom': {
width: null,
style: null,
color: null
},
'border-left': {
width: null,
style: null,
color: null
},
outline: {
width: null,
style: null,
color: null
},
'list-style': {
type: null,
position: null,
image: null
},
transition: {
property: null,
duration: null,
'timing-function': null,
timingFunction: null, // Needed for avoiding comilation issues with jss-camel-case
delay: null
},
animation: {
name: null,
duration: null,
'timing-function': null,
timingFunction: null, // Needed to avoid compilation issues with jss-camel-case
delay: null,
'iteration-count': null,
iterationCount: null, // Needed to avoid compilation issues with jss-camel-case
direction: null,
'fill-mode': null,
fillMode: null, // Needed to avoid compilation issues with jss-camel-case
'play-state': null,
playState: null // Needed to avoid compilation issues with jss-camel-case
},
'box-shadow': {
x: 0,
y: 0,
blur: 0,
spread: 0,
color: null,
inset: null
},
'text-shadow': {
x: 0,
y: 0,
blur: null,
color: null
}
};
/**
* A scheme for converting non-standart properties inside object.
* For e.g.: include 'border-radius' property inside 'border' object.
*/
var customPropObj = exports.customPropObj = {
border: {
radius: 'border-radius'
},
background: {
size: 'background-size',
image: 'background-image'
},
font: {
style: 'font-style',
variant: 'font-variant',
weight: 'font-weight',
stretch: 'font-stretch',
size: 'font-size',
family: 'font-family',
lineHeight: 'line-height', // Needed to avoid compilation issues with jss-camel-case
'line-height': 'line-height'
},
flex: {
grow: 'flex-grow',
basis: 'flex-basis',
direction: 'flex-direction',
wrap: 'flex-wrap',
flow: 'flex-flow',
shrink: 'flex-shrink'
},
align: {
self: 'align-self',
items: 'align-items',
content: 'align-content'
}
};
/***/ })
/******/ ])
});
;
//# sourceMappingURL=jss-expand.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
!function(n,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.jssExpand=t():n.jssExpand=t()}(this,function(){return function(n){function t(e){if(l[e])return l[e].exports;var r=l[e]={exports:{},id:e,loaded:!1};return n[e].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var l={};return t.m=n,t.c=l,t.p="",t(0)}([function(n,t,l){"use strict";function e(n,t,l){return t in n?Object.defineProperty(n,t,{value:l,enumerable:!0,configurable:!0,writable:!0}):n[t]=l,n}function r(n,t,l){return n.map(function(n){return i(n,t,l)})}function o(n,t,l,e){return null==l[t]?n.join(","):0===n.length?"":Array.isArray(n[0])?o(n[0],t,l):"object"===s(n[0])?r(n,t,e):n.join(" ")}function i(n,t,l,e){if(!c.propObj[t]&&!c.customPropObj[t])return"";var r=[];if(c.customPropObj[t]&&(n=u(n,l,c.customPropObj[t],e)),Object.keys(n).length)for(var i in c.propObj[t])n[i]?Array.isArray(n[i])?r.push(o(n[i],i,c.propArrayInObj)):r.push(n[i]):null!=c.propObj[t][i]&&r.push(c.propObj[t][i]);return r.join(" ")}function u(n,t,l,r){for(var o in l){var i=l[o];if("undefined"!=typeof n[o]&&(r||!t.prop(i))){var u=a(e({},i,n[o]),t)[i];r?t.style.fallbacks[i]=u:t.style[i]=u}delete n[o]}return n}function a(n,t,l){for(var e in n){var r=n[e];if(Array.isArray(r)){if(!Array.isArray(r[0])){if("fallbacks"===e){for(var u=0;u<n.fallbacks.length;u++)n.fallbacks[u]=a(n.fallbacks[u],t,!0);continue}n[e]=o(r,e,c.propArray),n[e]||delete n[e]}}else if("object"===("undefined"==typeof r?"undefined":s(r))){if("fallbacks"===e){n.fallbacks=a(n.fallbacks,t,!0);continue}n[e]=i(r,e,t,l),n[e]||delete n[e]}else""===n[e]&&delete n[e]}return n}function f(){function n(n,t){if(!n||"style"!==t.type)return n;if(Array.isArray(n)){for(var l=0;l<n.length;l++)n[l]=a(n[l],t);return n}return a(n,t)}return{onProcessStyle:n}}Object.defineProperty(t,"__esModule",{value:!0});var s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(n){return typeof n}:function(n){return n&&"function"==typeof Symbol&&n.constructor===Symbol&&n!==Symbol.prototype?"symbol":typeof n};t.default=f;var c=l(1)},function(n,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.propArray={"background-size":!0,"background-position":!0,border:!0,"border-bottom":!0,"border-left":!0,"border-top":!0,"border-right":!0,"border-radius":!0,"box-shadow":!0,flex:!0,margin:!0,padding:!0,outline:!0,"transform-origin":!0,transform:!0,transition:!0},t.propArrayInObj={position:!0,size:!0},t.propObj={padding:{top:0,right:0,bottom:0,left:0},margin:{top:0,right:0,bottom:0,left:0},background:{attachment:null,color:null,image:null,position:null,repeat:null},border:{width:null,style:null,color:null},"border-top":{width:null,style:null,color:null},"border-right":{width:null,style:null,color:null},"border-bottom":{width:null,style:null,color:null},"border-left":{width:null,style:null,color:null},outline:{width:null,style:null,color:null},"list-style":{type:null,position:null,image:null},transition:{property:null,duration:null,"timing-function":null,timingFunction:null,delay:null},animation:{name:null,duration:null,"timing-function":null,timingFunction:null,delay:null,"iteration-count":null,iterationCount:null,direction:null,"fill-mode":null,fillMode:null,"play-state":null,playState:null},"box-shadow":{x:0,y:0,blur:0,spread:0,color:null,inset:null},"text-shadow":{x:0,y:0,blur:null,color:null}},t.customPropObj={border:{radius:"border-radius"},background:{size:"background-size",image:"background-image"},font:{style:"font-style",variant:"font-variant",weight:"font-weight",stretch:"font-stretch",size:"font-size",family:"font-family",lineHeight:"line-height","line-height":"line-height"},flex:{grow:"flex-grow",basis:"flex-basis",direction:"flex-direction",wrap:"flex-wrap",flow:"flex-flow",shrink:"flex-shrink"},align:{self:"align-self",items:"align-items",content:"align-content"}}}])});
//# sourceMappingURL=jss-expand.min.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,286 @@
# Features
### Expanded properties.
A much more readable syntax and less repeatitions compared to CSS.
```js
border: {
color: 'black',
width: 1,
style: 'solid'
}
```
will output:
```css
border: 1px solid black;
```
See [properties section](#supported-properties) for more details.
### Using arrays for space separated properties.
```js
padding: [5, 10, 5],
margin: [10, 5]
```
will output
```css
padding: 5px 10px 5px;
margin: 10px 5px
```
Supported properties:
- `backgroundSize`
- `backgroundPosition`
- `border`
- `borderBottom`
- `borderLeft`
- `borderTop`
- `borderRight`
- `boxShadow`
- `flex`
- `margin`
- `padding`
- `outline`
- `transformOrigin`
- `transform`
- `transition`
### Using arrays for multi value properties.
```js
transition: [
['opacity', '200ms'],
['width', '300ms']
]
```
will output
```css
transition: opacity 200ms, width 300ms;
```
### Use objects inside of arrays.
```js
transition: [{
property: 'opacity',
duration: '200ms'
}, {
property: 'width',
duration: '300ms'
}]
```
will output:
```css
transition: opacity 200ms, width 300ms;
```
### Fallbacks are supported.
JSS has a [fallbacks api](https://github.com/cssinjs/jss/blob/master/docs/json-api.md#fallbacks) which is also supported.
```js
button: {
background: {
image: 'linear-gradient(red, green)'
},
fallbacks: {
background: {
color: 'red',
repeat: 'no-repeat',
position: [0 , 0]
}
}
}
```
will output:
```css
foo {
background: red no-repeat 0 0;
background: linear-gradient(red, green);
}
```
## Supported properties.
A list of all properties supported in expanded syntax and their corresponding defaults.
```js
padding: {
top: 10 // Props right, bottom, left will get 0 as defaults, as opposite to `padding: 10px`.
}
```
Will output:
```css
padding: 10px 0 0 0;
```
### padding
```js
padding: {
top: 0,
right: 0,
bottom: 0,
left: 0
}
```
### margin
```js
margin: {
top: 0,
right: 0,
bottom: 0,
left: 0
}
```
### font
```js
font: {
style: null,
variant: null,
weight: null,
stretch: null,
size: null,
family: null,
lineHeight: null
}
```
### background
Unlike pure CSS, `background-size` property can be written inside common `background` property.
```js
background: {
attachment: null,
color: null,
image: null,
position: null, // Can be written using array e.g. `[0, 0]`
repeat: null,
size: null, // Can be written using array e.g. `['center', 'center']`
}
```
### border
Same goes for `borderTop`, `borderRight`, `borderBottom`, `borderLeft`.
Unlike pure CSS, `border-radius` property can be written inside common `border` property.
```js
border: {
width: null,
style: null,
color: null
}
```
### outline
```js
outline: {
width: null,
style: null,
color: null
}
```
### listStyle
```js
listStyle: {
type: null,
position: null,
image: null
}
```
### transition
```js
transition: {
property: null,
duration: null,
timingFunction: null,
delay: null
}
```
### animation
```js
animation: {
name: null,
duration: null,
timingFunction: null,
delay: null,
iterationCount: null,
direction: null,
fillMode: null,
playState: null
}
```
### boxShadow
```js
boxShadow: {
x: 0,
y: 0,
blur: null,
spread: null,
color: null,
inset: null // If you want to add inset you need to write "inset: 'inset'"
}
```
### textShadow
```js
textShadow: {
x: 0,
y: 0,
blur: null,
color: null
}
```
### flex
```js
flex: {
basis: null,
direction: null,
flow: null,
grow: null,
shrink: null,
wrap: null
}
```
### align
```js
align: {
self: null,
items: null,
content: null
}
```

View File

@@ -0,0 +1,36 @@
const webpackConfig = require('./webpack.config')
const isBench = process.env.BENCHMARK === 'true'
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'
}
})
if (isBench) {
Object.assign(config, {
browsers: ['Chrome'],
frameworks: ['benchmark'],
files: ['benchmark/**/*.js'],
preprocessors: {'benchmark/**/*.js': ['webpack']},
reporters: ['benchmark']
})
}
}

View File

@@ -0,0 +1,178 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
exports.default = jssExpand;
var _props = require('./props');
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
/**
* Map values by given prop.
*
* @param {Array} array of values
* @param {String} original property
* @param {String} original rule
* @return {String} mapped values
*/
function mapValuesByProp(value, prop, rule) {
return value.map(function (item) {
return objectToString(item, prop, rule);
});
}
/**
* Convert array to string.
*
* @param {Array} array of values
* @param {String} original property
* @param {Object} sheme, for converting arrays in strings
* @param {Object} original rule
* @return {String} converted string
*/
function arrayToString(value, prop, scheme, rule) {
if (scheme[prop] == null) return value.join(',');
if (value.length === 0) return '';
if (Array.isArray(value[0])) return arrayToString(value[0], prop, scheme);
if (_typeof(value[0]) === 'object') return mapValuesByProp(value, prop, rule);
return value.join(' ');
}
/**
* Convert object to string.
*
* @param {Object} object of values
* @param {String} original property
* @param {Object} original rule
* @param {Boolean} is fallback prop
* @return {String} converted string
*/
function objectToString(value, prop, rule, isFallback) {
if (!(_props.propObj[prop] || _props.customPropObj[prop])) return '';
var result = [];
// Check if exists any non-standart property
if (_props.customPropObj[prop]) {
value = customPropsToStyle(value, rule, _props.customPropObj[prop], isFallback);
}
// Pass throught all standart props
if (Object.keys(value).length) {
for (var baseProp in _props.propObj[prop]) {
if (value[baseProp]) {
if (Array.isArray(value[baseProp])) {
result.push(arrayToString(value[baseProp], baseProp, _props.propArrayInObj));
} else result.push(value[baseProp]);
continue;
}
// Add default value from props config.
if (_props.propObj[prop][baseProp] != null) {
result.push(_props.propObj[prop][baseProp]);
}
}
}
return result.join(' ');
}
/**
* Convert custom properties values to styles adding them to rule directly
*
* @param {Object} object of values
* @param {Object} original rule
* @param {String} property, that contain partial custom properties
* @param {Boolean} is fallback prop
* @return {Object} value without custom properties, that was already added to rule
*/
function customPropsToStyle(value, rule, customProps, isFallback) {
for (var prop in customProps) {
var propName = customProps[prop];
// If current property doesn't exist already in rule - add new one
if (typeof value[prop] !== 'undefined' && (isFallback || !rule.prop(propName))) {
var appendedValue = styleDetector(_defineProperty({}, propName, value[prop]), rule)[propName];
// Add style directly in rule
if (isFallback) rule.style.fallbacks[propName] = appendedValue;else rule.style[propName] = appendedValue;
}
// Delete converted property to avoid double converting
delete value[prop];
}
return value;
}
/**
* Detect if a style needs to be converted.
*
* @param {Object} style
* @param {Object} rule
* @param {Boolean} is fallback prop
* @return {Object} convertedStyle
*/
function styleDetector(style, rule, isFallback) {
for (var prop in style) {
var value = style[prop];
if (Array.isArray(value)) {
// Check double arrays to avoid recursion.
if (!Array.isArray(value[0])) {
if (prop === 'fallbacks') {
for (var index = 0; index < style.fallbacks.length; index++) {
style.fallbacks[index] = styleDetector(style.fallbacks[index], rule, true);
}
continue;
}
style[prop] = arrayToString(value, prop, _props.propArray);
// Avoid creating properties with empty values
if (!style[prop]) delete style[prop];
}
} else if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object') {
if (prop === 'fallbacks') {
style.fallbacks = styleDetector(style.fallbacks, rule, true);
continue;
}
style[prop] = objectToString(value, prop, rule, isFallback);
// Avoid creating properties with empty values
if (!style[prop]) delete style[prop];
}
// Maybe a computed value resulting in an empty string
else if (style[prop] === '') delete style[prop];
}
return style;
}
/**
* Adds possibility to write expanded styles.
*
* @param {Rule} rule
* @api public
*/
function jssExpand() {
function onProcessStyle(style, rule) {
if (!style || rule.type !== 'style') return style;
if (Array.isArray(style)) {
// Pass rules one by one and reformat them
for (var index = 0; index < style.length; index++) {
style[index] = styleDetector(style[index], rule);
}
return style;
}
return styleDetector(style, rule);
}
return { onProcessStyle: onProcessStyle };
}

View File

@@ -0,0 +1,306 @@
'use strict';
var _expect = require('expect.js');
var _expect2 = _interopRequireDefault(_expect);
var _index = require('./index');
var _index2 = _interopRequireDefault(_index);
var _jss = require('jss');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var settings = {
createGenerateClassName: function createGenerateClassName() {
return function (rule) {
return rule.key + '-id';
};
}
};
describe('jss-expand', function () {
var jss = void 0;
beforeEach(function () {
jss = (0, _jss.create)(settings).use((0, _index2.default)());
});
describe('space-separated values as arrays', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
padding: [20, 10],
'background-size': [10, 'auto'],
'border-radius': [10, 15, 20, 20]
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' padding: 20 10;\n' + ' background-size: 10 auto;\n' + ' border-radius: 10 15 20 20;\n' + '}');
});
});
describe('comma-separated values as arrays (using double arrays)', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
transition: [['opacity', 1, 'linear'], ['transform', 300, 'ease']]
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' transition: opacity 1 linear, transform 300 ease;\n' + '}');
});
});
describe('simple expanded rules', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
border: {
width: 1,
style: 'solid',
color: '#f00'
}
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' border: 1 solid #f00;\n' + '}');
});
});
describe('expanded rules as an object (without some styles)', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
background: {
color: '#000',
image: 'url(test.jpg)',
position: [0, 0],
repeat: 'no-repeat'
}
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' background: #000 0 0 no-repeat;\n' + ' background-image: url(test.jpg);\n' + '}');
});
});
describe('expand with fallbacks', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
background: {
color: 'rgba(255, 255, 255, 0.8)'
},
padding: 50,
fallbacks: {
background: {
color: 'white'
},
padding: 20
}
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' background: white;\n' + ' padding: 20;\n' + ' background: rgba(255, 255, 255, 0.8);\n' + ' padding: 50;\n' + '}');
});
});
describe('expand with multiple fallbacks for the same prop', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
background: 'linear-gradient(red 0%, green 100%)',
fallbacks: [{
background: 'red'
}, {
background: {
color: 'url(test.png)',
repeat: 'no-repeat',
position: [0, 0]
}
}]
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' background: red;\n' + ' background: url(test.png) 0 0 no-repeat;\n' + ' background: linear-gradient(red 0%, green 100%);\n' + '}');
});
});
describe('expand with fallbacks and custom properties', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
background: {
image: 'linear-gradient(red 0%, green 100%)',
size: [10, 20]
},
fallbacks: {
background: {
image: 'url(gradient.png)',
size: 'auto'
}
}
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' background-size: auto;\n' + ' background-image: url(gradient.png);\n' + ' background-size: 10 20;\n' + ' background-image: linear-gradient(red 0%, green 100%);\n' + '}');
});
});
describe('integration with jss-camel-case', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
transition: {
timingFunction: 'linear',
delay: '300ms',
property: 'opacity',
duration: '200ms'
}
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' transition: opacity 200ms linear 300ms;\n' + '}');
});
});
describe('non-standart properties support', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
border: {
width: '2px',
style: 'solid',
color: 'black',
radius: ['5px', '10px']
}
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' border: 2px solid black;\n' + ' border-radius: 5px 10px;\n' + '}');
});
});
describe('non-standart properties should not overwrite standart properties notation', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
border: {
radius: ['5px', '10px']
},
'border-radius': '10px'
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' border-radius: 10px;\n' + '}');
});
});
describe('gracefully handle invalid values', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
padding: [], // Empty: incorrect, to ignore
color: '',
margin: 0,
'border-radius': '10px' // Still one correct value
},
p: {
margin: [] // Will lead to empty rule, eliminated
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' margin: 0;\n' + ' border-radius: 10px;\n' + '}');
});
});
});

View File

@@ -0,0 +1,168 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
/**
* A scheme for converting properties from array to regular style.
* All properties listed below will be transformed to a string separated by space.
*/
var propArray = exports.propArray = {
'background-size': true,
'background-position': true,
border: true,
'border-bottom': true,
'border-left': true,
'border-top': true,
'border-right': true,
'border-radius': true,
'box-shadow': true,
flex: true,
margin: true,
padding: true,
outline: true,
'transform-origin': true,
transform: true,
transition: true
};
/**
* A scheme for converting arrays to regular styles inside of objects.
* For e.g.: "{position: [0, 0]}" => "background-position: 0 0;".
*/
var propArrayInObj = exports.propArrayInObj = {
position: true, // background-position
size: true // background-size
};
/**
* A scheme for parsing and building correct styles from passed objects.
*/
var propObj = exports.propObj = {
padding: {
top: 0,
right: 0,
bottom: 0,
left: 0
},
margin: {
top: 0,
right: 0,
bottom: 0,
left: 0
},
background: {
attachment: null,
color: null,
image: null,
position: null,
repeat: null
},
border: {
width: null,
style: null,
color: null
},
'border-top': {
width: null,
style: null,
color: null
},
'border-right': {
width: null,
style: null,
color: null
},
'border-bottom': {
width: null,
style: null,
color: null
},
'border-left': {
width: null,
style: null,
color: null
},
outline: {
width: null,
style: null,
color: null
},
'list-style': {
type: null,
position: null,
image: null
},
transition: {
property: null,
duration: null,
'timing-function': null,
timingFunction: null, // Needed for avoiding comilation issues with jss-camel-case
delay: null
},
animation: {
name: null,
duration: null,
'timing-function': null,
timingFunction: null, // Needed to avoid compilation issues with jss-camel-case
delay: null,
'iteration-count': null,
iterationCount: null, // Needed to avoid compilation issues with jss-camel-case
direction: null,
'fill-mode': null,
fillMode: null, // Needed to avoid compilation issues with jss-camel-case
'play-state': null,
playState: null // Needed to avoid compilation issues with jss-camel-case
},
'box-shadow': {
x: 0,
y: 0,
blur: 0,
spread: 0,
color: null,
inset: null
},
'text-shadow': {
x: 0,
y: 0,
blur: null,
color: null
}
};
/**
* A scheme for converting non-standart properties inside object.
* For e.g.: include 'border-radius' property inside 'border' object.
*/
var customPropObj = exports.customPropObj = {
border: {
radius: 'border-radius'
},
background: {
size: 'background-size',
image: 'background-image'
},
font: {
style: 'font-style',
variant: 'font-variant',
weight: 'font-weight',
stretch: 'font-stretch',
size: 'font-size',
family: 'font-family',
lineHeight: 'line-height', // Needed to avoid compilation issues with jss-camel-case
'line-height': 'line-height'
},
flex: {
grow: 'flex-grow',
basis: 'flex-basis',
direction: 'flex-direction',
wrap: 'flex-wrap',
flow: 'flex-flow',
shrink: 'flex-shrink'
},
align: {
self: 'align-self',
items: 'align-items',
content: 'align-content'
}
};

View File

@@ -0,0 +1,118 @@
{
"_args": [
[
"jss-expand@4.0.1",
"C:\\Users\\deranjer\\GoglandProjects\\torrent-project\\torrent-project"
]
],
"_from": "jss-expand@4.0.1",
"_id": "jss-expand@4.0.1",
"_inBundle": false,
"_integrity": "sha512-LRIMXXChAOgnhwSqYLJg8MS6dI98bf/sg52pAg04pbjOAtjfzyS0JTnQAiyk3PxqR3nKFR/Yv44ahpIpkdcxVA==",
"_location": "/material-ui/jss-expand",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "jss-expand@4.0.1",
"name": "jss-expand",
"escapedName": "jss-expand",
"rawSpec": "4.0.1",
"saveSpec": null,
"fetchSpec": "4.0.1"
},
"_requiredBy": [
"/material-ui/jss-preset-default"
],
"_resolved": "https://registry.npmjs.org/jss-expand/-/jss-expand-4.0.1.tgz",
"_spec": "4.0.1",
"_where": "C:\\Users\\deranjer\\GoglandProjects\\torrent-project\\torrent-project",
"author": {
"name": "Pavel Davydov",
"email": "typical000@gmail.com"
},
"bugs": {
"url": "https://github.com/cssinjs/jss-expand/issues"
},
"description": "JSS plugin that gives you a better syntax than CSS.",
"devDependencies": {
"babel-cli": "^6.14.0",
"babel-core": "^6.14.0",
"babel-eslint": "^6.1.2",
"babel-loader": "^6.2.5",
"babel-preset-es2015": "^6.14.0",
"babel-preset-stage-0": "^6.5.0",
"cross-env": "^2.0.1",
"eslint": "^2.13.1",
"eslint-config-airbnb": "^8.0.0",
"eslint-config-jss": "^1.1.0",
"eslint-plugin-import": "^1.14.0",
"eslint-plugin-jsx-a11y": "^1.5.5",
"eslint-plugin-react": "^5.2.2",
"expect.js": "^0.3.1",
"json-loader": "^0.5.4",
"jss": "^8.0.0",
"karma": "^1.2.0",
"karma-benchmark": "^0.6.0",
"karma-benchmark-reporter": "^0.1.1",
"karma-browserstack-launcher": "^1.1.1",
"karma-chrome-launcher": "^2.0.0",
"karma-coverage": "^1.1.1",
"karma-firefox-launcher": "^1.0.0",
"karma-mocha": "^1.1.1",
"karma-mocha-reporter": "^2.1.0",
"karma-safari-launcher": "^1.0.0",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^1.8.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-expand#readme",
"keywords": [
"cssinjs",
"css-in-js",
"css in js",
"jss",
"plugin",
"expand"
],
"license": "MIT",
"lint-staged": {
"./src/*.js": [
"eslint",
"git add"
]
},
"main": "./lib/index.js",
"name": "jss-expand",
"peerDependencies": {
"jss": "^8.0.0"
},
"pre-commit": "lint:staged",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/cssinjs/jss-expand.git"
},
"scripts": {
"all": "npm run lint && npm run test && npm run build",
"bench": "cross-env NODE_ENV=test BENCHMARK=true karma start --single-run ",
"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-expand.js",
"build:dist:min": "cross-env NODE_ENV=production webpack src/index.js dist/jss-expand.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.1"
}

View File

@@ -0,0 +1,114 @@
# JSS plugin that gives you a better syntax than CSS
Can you remember what each of those values mean `box-shadow: 2px 2px 2px 1px gold;` and in which order they have to be used? Me neither. CSS values are sometimes cryptic. This plugin makes them easy to read and to remember.
Make sure you read [how to use
plugins](https://github.com/cssinjs/jss/blob/master/docs/setup.md#setup-with-plugins)
in general and [read full documentation](https://github.com/cssinjs/jss-expand/blob/master/docs/index.md).
[![Gitter](https://badges.gitter.im/JoinChat.svg)](https://gitter.im/cssinjs/lobby)
## Example
```javascript
const styles = {
container: {
padding: [20, 10],
background: {
color: 'green',
image: 'url(image.jpg)',
position: [0, 0],
repeat: 'no-repeat'
},
boxShadow: {x: 10, y: 10, blur: 5, spread: 5, color: 'black'},
transition: [
{
property: 'opacity',
duration: '200ms'
},
{
property: 'width',
duration: '300ms'
}
]
}
}
```
Compiles to:
```css
.container-3kjh2 {
padding: 20px 10px;
background: green url(image.jpg) 0 0 no-repeat;
box-shadow: 10px 10px 5px 5px black;
transition: opacity 200ms, width 300ms;
}
```
## Features
1. Expanded object notation for all properties.
```javascript
border: {
width: '1px',
style: 'solid',
color: 'red'
}
```
will be converted to
```css
border: 1px solid red;
```
1. Array notation for properties like `margin`, `padding` and others.
```javascript
padding: [20, 10],
borderRadius: ['50%', '10%']
```
1. Expanded arrays for multi value properties.
```javascript
transition: [{
property: 'opacity',
duration: '200ms'
}, {
property: 'width',
duration: '300ms'
}]
```
will be converted to
```css
transition: opacity 200ms, width 300ms;
```
1. Default unit support.
Now, using expanded arrays and objects syntax, you don't need to use quotes for the most numeric values! This is achieved in combination with [jss-default-unit](https://github.com/cssinjs/jss-default-unit) plugin.
## Issues
File a bug against [cssinjs/jss prefixed with \[jss-expand\]](https://github.com/cssinjs/jss/issues/new?title=[jss-expand]%20).
## Run tests
```bash
npm i
npm run test
```
## Run benchmark tests
```bash
npm i
npm run bench
```
## Licence
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 @@
var context = require.context('./src', true, /\.test\.js$/)
context.keys().forEach(context)

View File

@@ -0,0 +1,178 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
exports.default = jssExpand;
var _props = require('./props');
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
/**
* Map values by given prop.
*
* @param {Array} array of values
* @param {String} original property
* @param {String} original rule
* @return {String} mapped values
*/
function mapValuesByProp(value, prop, rule) {
return value.map(function (item) {
return objectToString(item, prop, rule);
});
}
/**
* Convert array to string.
*
* @param {Array} array of values
* @param {String} original property
* @param {Object} sheme, for converting arrays in strings
* @param {Object} original rule
* @return {String} converted string
*/
function arrayToString(value, prop, scheme, rule) {
if (scheme[prop] == null) return value.join(',');
if (value.length === 0) return '';
if (Array.isArray(value[0])) return arrayToString(value[0], prop, scheme);
if (_typeof(value[0]) === 'object') return mapValuesByProp(value, prop, rule);
return value.join(' ');
}
/**
* Convert object to string.
*
* @param {Object} object of values
* @param {String} original property
* @param {Object} original rule
* @param {Boolean} is fallback prop
* @return {String} converted string
*/
function objectToString(value, prop, rule, isFallback) {
if (!(_props.propObj[prop] || _props.customPropObj[prop])) return '';
var result = [];
// Check if exists any non-standart property
if (_props.customPropObj[prop]) {
value = customPropsToStyle(value, rule, _props.customPropObj[prop], isFallback);
}
// Pass throught all standart props
if (Object.keys(value).length) {
for (var baseProp in _props.propObj[prop]) {
if (value[baseProp]) {
if (Array.isArray(value[baseProp])) {
result.push(arrayToString(value[baseProp], baseProp, _props.propArrayInObj));
} else result.push(value[baseProp]);
continue;
}
// Add default value from props config.
if (_props.propObj[prop][baseProp] != null) {
result.push(_props.propObj[prop][baseProp]);
}
}
}
return result.join(' ');
}
/**
* Convert custom properties values to styles adding them to rule directly
*
* @param {Object} object of values
* @param {Object} original rule
* @param {String} property, that contain partial custom properties
* @param {Boolean} is fallback prop
* @return {Object} value without custom properties, that was already added to rule
*/
function customPropsToStyle(value, rule, customProps, isFallback) {
for (var prop in customProps) {
var propName = customProps[prop];
// If current property doesn't exist already in rule - add new one
if (typeof value[prop] !== 'undefined' && (isFallback || !rule.prop(propName))) {
var appendedValue = styleDetector(_defineProperty({}, propName, value[prop]), rule)[propName];
// Add style directly in rule
if (isFallback) rule.style.fallbacks[propName] = appendedValue;else rule.style[propName] = appendedValue;
}
// Delete converted property to avoid double converting
delete value[prop];
}
return value;
}
/**
* Detect if a style needs to be converted.
*
* @param {Object} style
* @param {Object} rule
* @param {Boolean} is fallback prop
* @return {Object} convertedStyle
*/
function styleDetector(style, rule, isFallback) {
for (var prop in style) {
var value = style[prop];
if (Array.isArray(value)) {
// Check double arrays to avoid recursion.
if (!Array.isArray(value[0])) {
if (prop === 'fallbacks') {
for (var index = 0; index < style.fallbacks.length; index++) {
style.fallbacks[index] = styleDetector(style.fallbacks[index], rule, true);
}
continue;
}
style[prop] = arrayToString(value, prop, _props.propArray);
// Avoid creating properties with empty values
if (!style[prop]) delete style[prop];
}
} else if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object') {
if (prop === 'fallbacks') {
style.fallbacks = styleDetector(style.fallbacks, rule, true);
continue;
}
style[prop] = objectToString(value, prop, rule, isFallback);
// Avoid creating properties with empty values
if (!style[prop]) delete style[prop];
}
// Maybe a computed value resulting in an empty string
else if (style[prop] === '') delete style[prop];
}
return style;
}
/**
* Adds possibility to write expanded styles.
*
* @param {Rule} rule
* @api public
*/
function jssExpand() {
function onProcessStyle(style, rule) {
if (!style || rule.type !== 'style') return style;
if (Array.isArray(style)) {
// Pass rules one by one and reformat them
for (var index = 0; index < style.length; index++) {
style[index] = styleDetector(style[index], rule);
}
return style;
}
return styleDetector(style, rule);
}
return { onProcessStyle: onProcessStyle };
}

View File

@@ -0,0 +1,306 @@
'use strict';
var _expect = require('expect.js');
var _expect2 = _interopRequireDefault(_expect);
var _index = require('./index');
var _index2 = _interopRequireDefault(_index);
var _jss = require('jss');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var settings = {
createGenerateClassName: function createGenerateClassName() {
return function (rule) {
return rule.key + '-id';
};
}
};
describe('jss-expand', function () {
var jss = void 0;
beforeEach(function () {
jss = (0, _jss.create)(settings).use((0, _index2.default)());
});
describe('space-separated values as arrays', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
padding: [20, 10],
'background-size': [10, 'auto'],
'border-radius': [10, 15, 20, 20]
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' padding: 20 10;\n' + ' background-size: 10 auto;\n' + ' border-radius: 10 15 20 20;\n' + '}');
});
});
describe('comma-separated values as arrays (using double arrays)', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
transition: [['opacity', 1, 'linear'], ['transform', 300, 'ease']]
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' transition: opacity 1 linear, transform 300 ease;\n' + '}');
});
});
describe('simple expanded rules', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
border: {
width: 1,
style: 'solid',
color: '#f00'
}
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' border: 1 solid #f00;\n' + '}');
});
});
describe('expanded rules as an object (without some styles)', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
background: {
color: '#000',
image: 'url(test.jpg)',
position: [0, 0],
repeat: 'no-repeat'
}
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' background: #000 0 0 no-repeat;\n' + ' background-image: url(test.jpg);\n' + '}');
});
});
describe('expand with fallbacks', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
background: {
color: 'rgba(255, 255, 255, 0.8)'
},
padding: 50,
fallbacks: {
background: {
color: 'white'
},
padding: 20
}
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' background: white;\n' + ' padding: 20;\n' + ' background: rgba(255, 255, 255, 0.8);\n' + ' padding: 50;\n' + '}');
});
});
describe('expand with multiple fallbacks for the same prop', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
background: 'linear-gradient(red 0%, green 100%)',
fallbacks: [{
background: 'red'
}, {
background: {
color: 'url(test.png)',
repeat: 'no-repeat',
position: [0, 0]
}
}]
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' background: red;\n' + ' background: url(test.png) 0 0 no-repeat;\n' + ' background: linear-gradient(red 0%, green 100%);\n' + '}');
});
});
describe('expand with fallbacks and custom properties', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
background: {
image: 'linear-gradient(red 0%, green 100%)',
size: [10, 20]
},
fallbacks: {
background: {
image: 'url(gradient.png)',
size: 'auto'
}
}
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' background-size: auto;\n' + ' background-image: url(gradient.png);\n' + ' background-size: 10 20;\n' + ' background-image: linear-gradient(red 0%, green 100%);\n' + '}');
});
});
describe('integration with jss-camel-case', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
transition: {
timingFunction: 'linear',
delay: '300ms',
property: 'opacity',
duration: '200ms'
}
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' transition: opacity 200ms linear 300ms;\n' + '}');
});
});
describe('non-standart properties support', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
border: {
width: '2px',
style: 'solid',
color: 'black',
radius: ['5px', '10px']
}
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' border: 2px solid black;\n' + ' border-radius: 5px 10px;\n' + '}');
});
});
describe('non-standart properties should not overwrite standart properties notation', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
border: {
radius: ['5px', '10px']
},
'border-radius': '10px'
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' border-radius: 10px;\n' + '}');
});
});
describe('gracefully handle invalid values', function () {
var sheet = void 0;
beforeEach(function () {
sheet = jss.createStyleSheet({
a: {
padding: [], // Empty: incorrect, to ignore
color: '',
margin: 0,
'border-radius': '10px' // Still one correct value
},
p: {
margin: [] // Will lead to empty rule, eliminated
}
});
});
it('should add rules', function () {
(0, _expect2.default)(sheet.getRule('a')).to.not.be(undefined);
});
it('should generate correct CSS', function () {
(0, _expect2.default)(sheet.toString()).to.be('.a-id {\n' + ' margin: 0;\n' + ' border-radius: 10px;\n' + '}');
});
});
});

View File

@@ -0,0 +1,168 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
/**
* A scheme for converting properties from array to regular style.
* All properties listed below will be transformed to a string separated by space.
*/
var propArray = exports.propArray = {
'background-size': true,
'background-position': true,
border: true,
'border-bottom': true,
'border-left': true,
'border-top': true,
'border-right': true,
'border-radius': true,
'box-shadow': true,
flex: true,
margin: true,
padding: true,
outline: true,
'transform-origin': true,
transform: true,
transition: true
};
/**
* A scheme for converting arrays to regular styles inside of objects.
* For e.g.: "{position: [0, 0]}" => "background-position: 0 0;".
*/
var propArrayInObj = exports.propArrayInObj = {
position: true, // background-position
size: true // background-size
};
/**
* A scheme for parsing and building correct styles from passed objects.
*/
var propObj = exports.propObj = {
padding: {
top: 0,
right: 0,
bottom: 0,
left: 0
},
margin: {
top: 0,
right: 0,
bottom: 0,
left: 0
},
background: {
attachment: null,
color: null,
image: null,
position: null,
repeat: null
},
border: {
width: null,
style: null,
color: null
},
'border-top': {
width: null,
style: null,
color: null
},
'border-right': {
width: null,
style: null,
color: null
},
'border-bottom': {
width: null,
style: null,
color: null
},
'border-left': {
width: null,
style: null,
color: null
},
outline: {
width: null,
style: null,
color: null
},
'list-style': {
type: null,
position: null,
image: null
},
transition: {
property: null,
duration: null,
'timing-function': null,
timingFunction: null, // Needed for avoiding comilation issues with jss-camel-case
delay: null
},
animation: {
name: null,
duration: null,
'timing-function': null,
timingFunction: null, // Needed to avoid compilation issues with jss-camel-case
delay: null,
'iteration-count': null,
iterationCount: null, // Needed to avoid compilation issues with jss-camel-case
direction: null,
'fill-mode': null,
fillMode: null, // Needed to avoid compilation issues with jss-camel-case
'play-state': null,
playState: null // Needed to avoid compilation issues with jss-camel-case
},
'box-shadow': {
x: 0,
y: 0,
blur: 0,
spread: 0,
color: null,
inset: null
},
'text-shadow': {
x: 0,
y: 0,
blur: null,
color: null
}
};
/**
* A scheme for converting non-standart properties inside object.
* For e.g.: include 'border-radius' property inside 'border' object.
*/
var customPropObj = exports.customPropObj = {
border: {
radius: 'border-radius'
},
background: {
size: 'background-size',
image: 'background-image'
},
font: {
style: 'font-style',
variant: 'font-variant',
weight: 'font-weight',
stretch: 'font-stretch',
size: 'font-size',
family: 'font-family',
lineHeight: 'line-height', // Needed to avoid compilation issues with jss-camel-case
'line-height': 'line-height'
},
flex: {
grow: 'flex-grow',
basis: 'flex-basis',
direction: 'flex-direction',
wrap: 'flex-wrap',
flow: 'flex-flow',
shrink: 'flex-shrink'
},
align: {
self: 'align-self',
items: 'align-items',
content: 'align-content'
}
};

View File

@@ -0,0 +1,41 @@
'use strict'
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: 'jssExpand',
libraryTarget: 'umd'
},
plugins: plugins,
module: {
loaders: [
{
loader: 'babel-loader',
test: /\.js$/,
exclude: /node_modules/
},
{
loader: 'json-loader',
test: /\.json$/
}
]
},
devtool: 'source-map'
}