Security upgrades

This commit is contained in:
2020-07-15 19:54:48 +02:00
parent 59cc6c54cd
commit ad8ed283d2
3164 changed files with 408897 additions and 28 deletions

8
node_modules/jss-plugin-rule-value-function/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,8 @@
The MIT License (MIT)
Copyright (c) 2014-present Oleg Isonen (Slobodskoi) & contributors
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.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,71 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var warning = _interopDefault(require('tiny-warning'));
var jss = require('jss');
var now = Date.now();
var fnValuesNs = "fnValues" + now;
var fnRuleNs = "fnStyle" + ++now;
function functionPlugin() {
return {
onCreateRule: function onCreateRule(name, decl, options) {
if (typeof decl !== 'function') return null;
var rule = jss.createRule(name, {}, options);
rule[fnRuleNs] = decl;
return rule;
},
onProcessStyle: function onProcessStyle(style, rule) {
// We need to extract function values from the declaration, so that we can keep core unaware of them.
// We need to do that only once.
// We don't need to extract functions on each style update, since this can happen only once.
// We don't support function values inside of function rules.
if (fnValuesNs in rule || fnRuleNs in rule) return style;
var fnValues = {};
for (var prop in style) {
var value = style[prop];
if (typeof value !== 'function') continue;
delete style[prop];
fnValues[prop] = value;
} // $FlowFixMe
rule[fnValuesNs] = fnValues;
return style;
},
onUpdate: function onUpdate(data, rule, sheet, options) {
var styleRule = rule;
var fnRule = styleRule[fnRuleNs]; // If we have a style function, the entire rule is dynamic and style object
// will be returned from that function.
if (fnRule) {
// Empty object will remove all currently defined props
// in case function rule returns a falsy value.
styleRule.style = fnRule(data) || {};
if (process.env.NODE_ENV === 'development') {
for (var prop in styleRule.style) {
if (typeof styleRule.style[prop] === 'function') {
process.env.NODE_ENV !== "production" ? warning(false, '[JSS] Function values inside function rules are not supported.') : void 0;
break;
}
}
}
}
var fnValues = styleRule[fnValuesNs]; // If we have a fn values map, it is a rule with function values.
if (fnValues) {
for (var _prop in fnValues) {
styleRule.prop(_prop, fnValues[_prop](data), options);
}
}
}
};
}
exports.default = functionPlugin;

View File

@@ -0,0 +1,3 @@
// @flow
export * from '../src';

View File

@@ -0,0 +1,65 @@
import warning from 'tiny-warning';
import { createRule } from 'jss';
var now = Date.now();
var fnValuesNs = "fnValues" + now;
var fnRuleNs = "fnStyle" + ++now;
function functionPlugin() {
return {
onCreateRule: function onCreateRule(name, decl, options) {
if (typeof decl !== 'function') return null;
var rule = createRule(name, {}, options);
rule[fnRuleNs] = decl;
return rule;
},
onProcessStyle: function onProcessStyle(style, rule) {
// We need to extract function values from the declaration, so that we can keep core unaware of them.
// We need to do that only once.
// We don't need to extract functions on each style update, since this can happen only once.
// We don't support function values inside of function rules.
if (fnValuesNs in rule || fnRuleNs in rule) return style;
var fnValues = {};
for (var prop in style) {
var value = style[prop];
if (typeof value !== 'function') continue;
delete style[prop];
fnValues[prop] = value;
} // $FlowFixMe
rule[fnValuesNs] = fnValues;
return style;
},
onUpdate: function onUpdate(data, rule, sheet, options) {
var styleRule = rule;
var fnRule = styleRule[fnRuleNs]; // If we have a style function, the entire rule is dynamic and style object
// will be returned from that function.
if (fnRule) {
// Empty object will remove all currently defined props
// in case function rule returns a falsy value.
styleRule.style = fnRule(data) || {};
if (process.env.NODE_ENV === 'development') {
for (var prop in styleRule.style) {
if (typeof styleRule.style[prop] === 'function') {
process.env.NODE_ENV !== "production" ? warning(false, '[JSS] Function values inside function rules are not supported.') : void 0;
break;
}
}
}
}
var fnValues = styleRule[fnValuesNs]; // If we have a fn values map, it is a rule with function values.
if (fnValues) {
for (var _prop in fnValues) {
styleRule.prop(_prop, fnValues[_prop](data), options);
}
}
}
};
}
export default functionPlugin;

View File

@@ -0,0 +1,91 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('jss')) :
typeof define === 'function' && define.amd ? define(['exports', 'jss'], factory) :
(global = global || self, factory(global.jssPluginRuleValueFunction = {}, global.jss));
}(this, (function (exports, jss) { 'use strict';
function warning(condition, message) {
{
if (condition) {
return;
}
var text = "Warning: " + message;
if (typeof console !== 'undefined') {
console.warn(text);
}
try {
throw Error(text);
} catch (x) {}
}
}
var now = Date.now();
var fnValuesNs = "fnValues" + now;
var fnRuleNs = "fnStyle" + ++now;
function functionPlugin() {
return {
onCreateRule: function onCreateRule(name, decl, options) {
if (typeof decl !== 'function') return null;
var rule = jss.createRule(name, {}, options);
rule[fnRuleNs] = decl;
return rule;
},
onProcessStyle: function onProcessStyle(style, rule) {
// We need to extract function values from the declaration, so that we can keep core unaware of them.
// We need to do that only once.
// We don't need to extract functions on each style update, since this can happen only once.
// We don't support function values inside of function rules.
if (fnValuesNs in rule || fnRuleNs in rule) return style;
var fnValues = {};
for (var prop in style) {
var value = style[prop];
if (typeof value !== 'function') continue;
delete style[prop];
fnValues[prop] = value;
} // $FlowFixMe
rule[fnValuesNs] = fnValues;
return style;
},
onUpdate: function onUpdate(data, rule, sheet, options) {
var styleRule = rule;
var fnRule = styleRule[fnRuleNs]; // If we have a style function, the entire rule is dynamic and style object
// will be returned from that function.
if (fnRule) {
// Empty object will remove all currently defined props
// in case function rule returns a falsy value.
styleRule.style = fnRule(data) || {};
{
for (var prop in styleRule.style) {
if (typeof styleRule.style[prop] === 'function') {
warning(false, '[JSS] Function values inside function rules are not supported.') ;
break;
}
}
}
}
var fnValues = styleRule[fnValuesNs]; // If we have a fn values map, it is a rule with function values.
if (fnValues) {
for (var _prop in fnValues) {
styleRule.prop(_prop, fnValues[_prop](data), options);
}
}
}
};
}
exports.default = functionPlugin;
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=jss-plugin-rule-value-function.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports,require("jss")):"function"==typeof define&&define.amd?define(["exports","jss"],n):n((e=e||self).jssPluginRuleValueFunction={},e.jss)}(this,function(e,n){"use strict";var t=Date.now(),r="fnValues"+t,o="fnStyle"+ ++t;e.default=function(){return{onCreateRule:function(e,t,r){if("function"!=typeof t)return null;var u=n.createRule(e,{},r);return u[o]=t,u},onProcessStyle:function(e,n){if(r in n||o in n)return e;var t={};for(var u in e){var f=e[u];"function"==typeof f&&(delete e[u],t[u]=f)}return n[r]=t,e},onUpdate:function(e,n,t,u){var f=n,i=f[o];i&&(f.style=i(e)||{});var s=f[r];if(s)for(var a in s)f.prop(a,s[a](e),u)}}},Object.defineProperty(e,"__esModule",{value:!0})});

View File

@@ -0,0 +1,76 @@
{
"_from": "jss-plugin-rule-value-function@^10.0.3",
"_id": "jss-plugin-rule-value-function@10.3.0",
"_inBundle": false,
"_integrity": "sha512-7WiMrKIHH3rwxTuJki9+7nY11r1UXqaUZRhHvqTD4/ZE+SVhvtD5Tx21ivNxotwUSleucA/8boX+NF21oXzr5Q==",
"_location": "/jss-plugin-rule-value-function",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "jss-plugin-rule-value-function@^10.0.3",
"name": "jss-plugin-rule-value-function",
"escapedName": "jss-plugin-rule-value-function",
"rawSpec": "^10.0.3",
"saveSpec": null,
"fetchSpec": "^10.0.3"
},
"_requiredBy": [
"/@material-ui/styles"
],
"_resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.3.0.tgz",
"_shasum": "498b0e2bae16cb316a6bdb73fd783cf9604ba747",
"_spec": "jss-plugin-rule-value-function@^10.0.3",
"_where": "D:\\WORK\\Menui\\menui_backend\\node_modules\\@material-ui\\styles",
"author": {
"name": "JSS Team"
},
"bugs": {
"url": "https://github.com/cssinjs/jss/issues/new?title=[jss-plugin-rule-value-function]"
},
"bundleDependencies": false,
"dependencies": {
"@babel/runtime": "^7.3.1",
"jss": "^10.3.0",
"tiny-warning": "^1.0.2"
},
"deprecated": false,
"description": "JSS plugin for function value and rule syntax",
"files": [
"dist",
"src",
"LICENSE"
],
"gitHead": "4094410d82dfdae772e1c09f0cd187cb48fa1cdc",
"homepage": "https://cssinjs.org/",
"keywords": [
"jss",
"style",
"sheet",
"stylesheet",
"css",
"components",
"composable",
"css in js",
"css-in-js",
"dynamic",
"function",
"reactive",
"animation"
],
"license": "MIT",
"main": "dist/jss-plugin-rule-value-function.cjs.js",
"module": "dist/jss-plugin-rule-value-function.esm.js",
"name": "jss-plugin-rule-value-function",
"repository": {
"type": "git",
"url": "git+https://github.com/cssinjs/jss.git"
},
"scripts": {
"build": "node ../../scripts/build.js",
"check-snapshot": "node ../../scripts/match-snapshot.js"
},
"typings": "./src/index.d.ts",
"unpkg": "dist/jss-plugin-rule-value-function.bundle.js",
"version": "10.3.0"
}

26
node_modules/jss-plugin-rule-value-function/readme.md generated vendored Normal file
View File

@@ -0,0 +1,26 @@
# jss-plugin-rule-value-function
[![Version](https://img.shields.io/npm/v/jss-plugin-rule-value-function.svg?style=flat)](https://npmjs.org/package/jss-plugin-rule-value-function)
[![License](https://img.shields.io/npm/l/jss-plugin-rule-value-function.svg?style=flat)](https://github.com/cssinjs/jss/blob/master/LICENSE)
[![Downlodas](https://img.shields.io/npm/dm/jss-plugin-rule-value-function.svg?style=flat)](https://npmjs.org/package/jss-plugin-rule-value-function)
[![Size](https://img.shields.io/bundlephobia/minzip/jss-plugin-rule-value-function.svg?style=flat)](https://npmjs.org/package/jss-plugin-rule-value-function)
[![Dependencies](https://img.shields.io/david/cssinjs/jss.svg?path=packages%2Fjss-plugin-rule-value-function&style=flat)](https://npmjs.org/package/jss-plugin-rule-value-function)
[![Gitter](https://badges.gitter.im/JoinChat.svg)](https://gitter.im/cssinjs/lobby)
> JSS plugin for function value and rule syntax
See our website [jss-plugin-rule-value-function](https://cssinjs.org/jss-plugin-rule-value-function?v=v10.3.0) for more information.
## Install
Using npm:
```sh
npm install jss-plugin-rule-value-function
```
or using yarn:
```sh
yarn add jss-plugin-rule-value-function
```

View File

@@ -0,0 +1,274 @@
import expect from 'expect.js'
import {stripIndent} from 'common-tags'
import {create} from 'jss'
import sinon from 'sinon'
import functionPlugin from '.'
const settings = {createGenerateId: () => rule => `${rule.key}-id`}
describe('jss-plugin-rule-value-function: Function rules', () => {
let jss
beforeEach(() => {
jss = create(settings).use(functionPlugin())
})
describe('basic', () => {
let sheet
beforeEach(() => {
sheet = jss
.createStyleSheet(
{
a: data => ({
color: data.color,
display: 'block'
})
},
{link: true}
)
.attach()
})
afterEach(() => {
sheet.detach()
})
it('should compile correctly', () => {
sheet.update({color: 'red'})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: red;
display: block;
}
`)
})
})
describe('remove props', () => {
let sheet
beforeEach(() => {
sheet = jss
.createStyleSheet(
{
a: data => {
if (data.removeAll) {
return null
}
if (data.noDisplay) {
return {color: data.color}
}
return {
color: data.color,
display: 'block'
}
}
},
{link: true}
)
.attach()
})
afterEach(() => {
sheet.detach()
})
it('should compile with color and display', () => {
sheet.update({color: 'red'})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: red;
display: block;
}
`)
})
it('should compile with color', () => {
sheet.update({color: 'red'})
sheet.update({color: 'red', noDisplay: true})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: red;
}
`)
})
it('should remove all props', () => {
sheet.update({color: 'red'})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: red;
display: block;
}
`)
sheet.update({removeAll: true})
expect(sheet.toString()).to.be('.a-id {}')
})
})
describe('fallbacks inside', () => {
let sheet
beforeEach(() => {
sheet = jss
.createStyleSheet(
{
a: data => ({
color: data.color,
fallbacks: {
color: 'green'
}
})
},
{link: true}
)
.attach()
})
afterEach(() => {
sheet.detach()
})
it('should output with fallbacks', () => {
sheet.update({color: 'red'})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: green;
color: red;
}
`)
})
})
describe('@media with fn values', () => {
let sheet
beforeEach(() => {
sheet = jss
.createStyleSheet(
{
'@media all': {
a: {
color: ({color}) => color
}
}
},
{link: true}
)
.attach()
})
afterEach(() => {
sheet.detach()
})
it('should return correct .toString()', () => {
sheet.update({color: 'red'})
expect(sheet.toString()).to.be(stripIndent`
@media all {
.a-id {
color: red;
}
}
`)
})
})
describe('.addRule() with style rule', () => {
let sheet
beforeEach(() => {
sheet = jss.createStyleSheet(null, {link: true}).attach()
sheet.addRule('a', data => ({
color: data.primary ? 'black' : 'white'
}))
})
afterEach(() => {
sheet.detach()
})
it('should compile correct CSS', () => {
sheet.update({primary: true})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: black;
}
`)
})
it('should return correct .toString()', () => {
sheet.update({primary: false})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: white;
}
`)
})
})
describe('.addRule() with @media', () => {
let sheet
beforeEach(() => {
sheet = jss.createStyleSheet({}, {link: true}).attach()
sheet.addRule('@media screen', {
b: data => ({
color: data.primary ? 'black' : 'white'
})
})
})
afterEach(() => {
sheet.detach()
})
it('should return correct .toString()', () => {
sheet.update({primary: true})
expect(sheet.toString()).to.be(stripIndent`
@media screen {
.b-id {
color: black;
}
}
`)
})
})
describe('function value inside', () => {
let sheet
let spy
beforeEach(() => {
sheet = jss
.createStyleSheet(
{
a: data => ({
color: () => data.color,
background: () => data.background
})
},
{link: true}
)
.attach()
spy = sinon.spy(console, 'warn')
})
afterEach(() => {
sheet.detach()
console.warn.restore()
})
it('should warn when a function value is inside a function rule', () => {
sheet.update({color: 'blue', background: 'green'})
expect(spy.callCount).to.be(1)
expect(
spy.calledWithExactly(
'Warning: [JSS] Function values inside function rules are not supported.'
)
).to.be(true)
})
})
})

View File

@@ -0,0 +1,434 @@
/* eslint-disable no-underscore-dangle */
import {stripIndent} from 'common-tags'
import expect from 'expect.js'
import {create} from 'jss'
import functionPlugin from '.'
const settings = {createGenerateId: () => rule => `${rule.key}-id`}
describe('jss-plugin-rule-value-function: Function values', () => {
let jss
beforeEach(() => {
jss = create(settings).use(functionPlugin())
})
describe('.addRule() with @media with function values', () => {
let sheet
beforeEach(() => {
sheet = jss.createStyleSheet({}, {link: true}).attach()
sheet.addRule('@media screen', {
b: {
color: props => (props.primary ? 'black' : 'white')
}
})
})
afterEach(() => {
sheet.detach()
})
})
describe('.addRule() with function values and attached sheet', () => {
let sheet
beforeEach(() => {
sheet = jss.createStyleSheet(null, {link: true}).attach()
sheet.addRule('a', {color: ({color}) => color})
})
afterEach(() => {
sheet.detach()
})
it('should render an empty rule', () => {
expect(sheet.toString()).to.be(stripIndent`
.a-id {}
`)
})
it('should render rule with updated color', () => {
sheet.update({color: 'red'})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: red;
}
`)
})
})
describe('.addRule() with function values for rules from plugins queue', () => {
let sheet
beforeEach(() => {
jss.use({
onProcessRule(rule, ruleSheet) {
const ruleName = 'plugin-rule'
if (rule.key === ruleName) return
ruleSheet.addRule(ruleName, {
color: props => props.color
})
}
})
sheet = jss.createStyleSheet({}, {link: true}).attach()
})
afterEach(() => {
sheet.detach()
})
it('should render color for rule by plugin', () => {
sheet.addRule('rule', {
color: props => props.color
})
sheet.update({color: 'red'})
expect(sheet.toString()).to.be(stripIndent`
.rule-id {
color: red;
}
.plugin-rule-id {
color: red;
}
`)
})
})
describe('.addRule() with arrays returned from function values', () => {
let sheet
beforeEach(() => {
sheet = jss.createStyleSheet(null, {link: true}).attach()
sheet.addRule('a', {color: ({color}) => color})
})
afterEach(() => {
sheet.detach()
})
it('should render an empty rule', () => {
expect(sheet.toString()).to.be(stripIndent`
.a-id {}
`)
})
it('should return correct CSS from an array with a single value', () => {
sheet.update({color: ['blue']})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: blue;
}
`)
})
it('should return correct CSS from a double array with !important', () => {
sheet.update({color: [['blue'], '!important']})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: blue !important;
}
`)
})
it('should return correct CSS from an array with !important', () => {
sheet.update({color: ['blue', '!important']})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: blue !important;
}
`)
})
it('should return a property value from the CSSOM getPropertyValue function of "green" with important', () => {
sheet.update({color: [['green'], '!important']})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: green !important;
}
`)
})
it('should return a property value from the CSSOM getPropertyValue function of "green"', () => {
sheet.update({color: ['green']})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: green;
}
`)
})
it('should return a correct priority', () => {
sheet.update({color: [['red'], '!important']})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: red !important;
}
`)
})
})
describe('sheet.update()', () => {
let sheet
const styles = {
a: {
color: theme => theme.color
},
'@media all': {
b: {
color: theme => theme.color
}
},
'@keyframes a': {
'0%': {
color: theme => theme.color
}
}
}
beforeEach(() => {
sheet = jss.createStyleSheet(styles, {link: true})
})
afterEach(() => {
sheet.detach()
})
describe('.toString()', () => {
it('should return correct .toString() before .update()', () => {
expect(sheet.toString()).to.be(stripIndent`
.a-id {}
@media all {
.b-id { }
}
@keyframes keyframes-a-id {
0% { }
}
`)
})
it('should return correct .toString() after single .update()', () => {
sheet.update({
color: 'green'
})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: green;
}
@media all {
.b-id {
color: green;
}
}
@keyframes keyframes-a-id {
0% {
color: green;
}
}
`)
})
it('should return correct .toString() after double .update()', () => {
sheet.update({
color: 'green'
})
sheet.update({
color: 'yellow'
})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: yellow;
}
@media all {
.b-id {
color: yellow;
}
}
@keyframes keyframes-a-id {
0% {
color: yellow;
}
}
`)
})
it('should update specific rule', () => {
sheet.update({color: 'yellow'})
sheet.update('a', {color: 'green'})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: green;
}
@media all {
.b-id {
color: yellow;
}
}
@keyframes keyframes-a-id {
0% {
color: yellow;
}
}
`)
})
it('should remove declarations when value is null', () => {
sheet.update({color: null})
expect(sheet.toString()).to.be(stripIndent`
.a-id {}
@media all {
.b-id { }
}
@keyframes keyframes-a-id {
0% { }
}
`)
})
it('should remove declarations when value is undefined', () => {
sheet.update({color: undefined})
expect(sheet.toString()).to.be(stripIndent`
.a-id {}
@media all {
.b-id { }
}
@keyframes keyframes-a-id {
0% { }
}
`)
})
it('should remove declarations when value is false', () => {
sheet.update({color: false})
expect(sheet.toString()).to.be(stripIndent`
.a-id {}
@media all {
.b-id { }
}
@keyframes keyframes-a-id {
0% { }
}
`)
})
})
describe('sheet.update() after attach', () => {
beforeEach(() => {
sheet = jss.createStyleSheet(
{
a: {
color: theme => theme.color
}
},
{link: true}
)
})
it('should render sheet with updated props after attach', () => {
sheet.attach().update({color: 'green'})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: green;
}
`)
})
it('should render updated rule after attach', () => {
sheet.attach().update('a', {color: 'green'})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: green;
}
`)
})
})
})
describe('keyframe names', () => {
it('should work with animation-name', () => {
const sheet = jss.createStyleSheet({
'@keyframes animateIn': {},
'@keyframes animateOut': {},
a: {'animation-name': ({name}) => name}
})
sheet.update({name: '$animateIn'})
expect(sheet.toString()).to.be(stripIndent`
@keyframes keyframes-animateIn-id {}
@keyframes keyframes-animateOut-id {}
.a-id {
animation-name: keyframes-animateIn-id;
}
`)
sheet.update({name: '$animateOut'})
expect(sheet.toString()).to.be(stripIndent`
@keyframes keyframes-animateIn-id {}
@keyframes keyframes-animateOut-id {}
.a-id {
animation-name: keyframes-animateOut-id;
}
`)
})
it('should work with animation prop', () => {
const sheet = jss.createStyleSheet({
'@keyframes animateIn': {},
'@keyframes animateOut': {},
a: {animation: ({name}) => `${name} 5s`}
})
sheet.update({name: '$animateIn'})
expect(sheet.toString()).to.be(stripIndent`
@keyframes keyframes-animateIn-id {}
@keyframes keyframes-animateOut-id {}
.a-id {
animation: keyframes-animateIn-id 5s;
}
`)
sheet.update({name: '$animateOut'})
expect(sheet.toString()).to.be(stripIndent`
@keyframes keyframes-animateIn-id {}
@keyframes keyframes-animateOut-id {}
.a-id {
animation: keyframes-animateOut-id 5s;
}
`)
})
})
describe('rule.toJSON()', () => {
it('should handle function values', () => {
const sheet = jss.createStyleSheet({
a: {color: () => 'red'}
})
sheet.update()
expect(sheet.getRule('a').toJSON()).to.eql({color: 'red'})
})
})
})

View File

@@ -0,0 +1,3 @@
import {Plugin} from 'jss'
export default function jssPluginSyntaxRuleValueFunction(): Plugin

View File

@@ -0,0 +1,80 @@
/* @flow */
import warning from 'tiny-warning'
import {
createRule,
type Rule,
type JssStyle,
type RuleOptions,
type UpdateOptions,
type StyleRule,
type StyleSheet
} from 'jss'
// A symbol replacement.
let now = Date.now()
const fnValuesNs = `fnValues${now}`
const fnRuleNs = `fnStyle${++now}`
type StyleRuleWithRuleFunction = StyleRule & {[key: string]: Function}
export default function functionPlugin() {
return {
onCreateRule(name?: string, decl: JssStyle, options: RuleOptions): Rule | null {
if (typeof decl !== 'function') return null
const rule: StyleRuleWithRuleFunction = (createRule(name, {}, options): any)
rule[fnRuleNs] = decl
return rule
},
onProcessStyle(style: JssStyle, rule: Rule): JssStyle {
// We need to extract function values from the declaration, so that we can keep core unaware of them.
// We need to do that only once.
// We don't need to extract functions on each style update, since this can happen only once.
// We don't support function values inside of function rules.
if (fnValuesNs in rule || fnRuleNs in rule) return style
const fnValues = {}
for (const prop in style) {
const value = style[prop]
if (typeof value !== 'function') continue
delete style[prop]
fnValues[prop] = value
}
// $FlowFixMe
rule[fnValuesNs] = fnValues
return style
},
onUpdate(data: Object, rule: Rule, sheet: StyleSheet, options: UpdateOptions) {
const styleRule: StyleRule = (rule: any)
const fnRule = styleRule[fnRuleNs]
// If we have a style function, the entire rule is dynamic and style object
// will be returned from that function.
if (fnRule) {
// Empty object will remove all currently defined props
// in case function rule returns a falsy value.
styleRule.style = fnRule(data) || {}
if (process.env.NODE_ENV === 'development') {
for (const prop in styleRule.style) {
if (typeof styleRule.style[prop] === 'function') {
warning(false, '[JSS] Function values inside function rules are not supported.')
break
}
}
}
}
const fnValues = styleRule[fnValuesNs]
// If we have a fn values map, it is a rule with function values.
if (fnValues) {
for (const prop in fnValues) {
styleRule.prop(prop, fnValues[prop](data), options)
}
}
}
}
}

View File

@@ -0,0 +1,6 @@
import './function-rules.test'
import './function-values.test'
import './plugin-expand.test'
import './plugin-nested.test'
import './plugin-global.test'
import './plugin-compose.test'

View File

@@ -0,0 +1,97 @@
import expect from 'expect.js'
import {stripIndent} from 'common-tags'
import {create} from 'jss'
import pluginCompose from 'jss-plugin-compose'
import pluginFunction from '.'
const settings = {createGenerateId: () => rule => `${rule.key}-id`}
describe('jss-plugin-rule-value-function: plugin-compose', () => {
let jss
beforeEach(() => {
jss = create(settings).use(pluginFunction(), pluginCompose())
})
describe('composing fn value', () => {
let sheet
beforeEach(() => {
sheet = jss
.createStyleSheet(
{
a: {
color: () => 'red'
},
b: {
color: 'green',
composes: '$a'
}
},
{link: true}
)
.attach()
})
afterEach(() => {
sheet.detach()
})
it('should return correct .toString()', () => {
sheet.update()
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: red;
}
.b-id {
color: green;
}
`)
})
it('should have composed class names', () => {
expect(sheet.classes).to.eql({a: 'a-id', b: 'b-id a-id'})
})
})
describe('composing fn rule', () => {
let sheet
beforeEach(() => {
sheet = jss
.createStyleSheet(
{
a: () => ({
color: 'red'
}),
b: {
color: 'green',
composes: '$a'
}
},
{link: true}
)
.attach()
})
afterEach(() => {
sheet.detach()
})
it('should return correct .toString()', () => {
sheet.update()
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: red;
}
.b-id {
color: green;
}
`)
})
it('should have composed class names', () => {
expect(sheet.classes).to.eql({a: 'a-id', b: 'b-id a-id'})
})
})
})

View File

@@ -0,0 +1,111 @@
import expect from 'expect.js'
import {stripIndent} from 'common-tags'
import {create} from 'jss'
import pluginExpand from '../../jss-plugin-expand'
import pluginFunction from '.'
const settings = {createGenerateId: () => rule => `${rule.key}-id`}
describe('jss-plugin-rule-value-function: plugin-expand', () => {
let jss
beforeEach(() => {
jss = create(settings).use(pluginFunction(), pluginExpand())
})
describe('expanding in fn values', () => {
let sheet
beforeEach(() => {
sheet = jss
.createStyleSheet(
{
a: {
border: props => ({
top: props.border,
bottom: props.border
})
}
},
{link: true}
)
.attach()
})
afterEach(() => {
sheet.detach()
})
it.skip('should return correct .toString()', () => {
sheet.update({border: '1px'})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
border-top: 1px;
border-bottom: 1px;
}
`)
})
it.skip('should handle when updating multiple times', () => {
sheet.update({border: '1px'})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
border-top: 1px;
border-bottom: 1px;
}
`)
sheet.update({border: '5px'})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
border-top: 5px;
border-bottom: 5px;
}
`)
})
})
describe('expanding in fn rules', () => {
let sheet
beforeEach(() => {
sheet = jss
.createStyleSheet(
{
a: props => ({border: {color: props.color}})
},
{link: true}
)
.attach()
})
afterEach(() => {
sheet.detach()
})
it('should return correct .toString()', () => {
sheet.update({color: 'red'})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
border-color: red;
}
`)
})
it('should handle updating multiple times', () => {
sheet.update({color: 'red'})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
border-color: red;
}
`)
sheet.update({color: 'blue'})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
border-color: blue;
}
`)
})
})
})

View File

@@ -0,0 +1,89 @@
import expect from 'expect.js'
import {stripIndent} from 'common-tags'
import {create} from 'jss'
import pluginGlobal from 'jss-plugin-global'
import pluginFunction from '.'
const settings = {createGenerateId: () => rule => `${rule.key}-id`}
describe('jss-plugin-rule-value-function: plugin-global', () => {
let jss
beforeEach(() => {
jss = create(settings).use(pluginGlobal(), pluginFunction())
})
describe('fn rule', () => {
let sheet
beforeEach(() => {
sheet = jss
.createStyleSheet(
{
'@global': {
a: data => ({
color: data.color
}),
'@media all': {
a: {
color: 'green'
}
}
}
},
{link: true}
)
.attach()
})
afterEach(() => {
sheet.detach()
})
it('should return correct .toString()', () => {
sheet.update({color: 'red'})
expect(sheet.toString()).to.be(stripIndent`
a {
color: red;
}
@media all {
a {
color: green;
}
}
`)
})
})
describe('fn value', () => {
let sheet
beforeEach(() => {
sheet = jss
.createStyleSheet(
{
'@global': {
a: {
color: data => data.color
}
}
},
{link: true}
)
.attach()
})
afterEach(() => {
sheet.detach()
})
it('should return correct .toString()', () => {
sheet.update({color: 'red'})
expect(sheet.toString()).to.be(stripIndent`
a {
color: red;
}
`)
})
})
})

View File

@@ -0,0 +1,211 @@
import expect from 'expect.js'
import {stripIndent} from 'common-tags'
import {create} from 'jss'
import pluginNested from '../../jss-plugin-nested'
import pluginFunction from '.'
const settings = {createGenerateId: () => rule => `${rule.key}-id`}
describe('jss-plugin-rule-value-function: plugin-nested', () => {
let jss
beforeEach(() => {
jss = create(settings).use(pluginNested(), pluginFunction())
})
describe('@media nested in fn rule', () => {
let sheet
beforeEach(() => {
sheet = jss
.createStyleSheet(
{
a: data => ({
color: data.color,
'@media all': {
color: 'green'
}
})
},
{link: true}
)
.attach()
})
afterEach(() => {
sheet.detach()
})
it('should return correct .toString()', () => {
sheet.update({color: 'red'})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: red;
}
@media all {
.a-id {
color: green;
}
}
`)
})
})
describe('@media nested as a fn rule', () => {
let sheet
beforeEach(() => {
sheet = jss
.createStyleSheet(
{
a: {
color: 'red',
'@media all': data => ({
color: data.color
})
}
},
{link: true}
)
.attach()
})
afterEach(() => {
sheet.detach()
})
it('should return correct .toString()', () => {
sheet.update({color: 'green'})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: red;
}
@media all {
.a-id {
color: green;
}
}
`)
})
})
describe('nested selector inside of a fn rule', () => {
let sheet
beforeEach(() => {
sheet = jss
.createStyleSheet(
{
a: ({color}) => ({
color: 'red',
'& a': {
color
}
})
},
{link: true}
)
.attach()
})
afterEach(() => {
sheet.detach()
})
it('should return correct .toString()', () => {
sheet.update({color: 'green'})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: red;
}
.a-id a {
color: green;
}
`)
})
})
describe('nested selector as a fn rule', () => {
let sheet
beforeEach(() => {
sheet = jss
.createStyleSheet(
{
a: {
color: 'red',
'& a': ({color}) => ({
color
})
}
},
{link: true}
)
.attach()
})
afterEach(() => {
sheet.detach()
})
it('should return correct .toString()', () => {
sheet.update({color: 'green'})
expect(sheet.toString()).to.be(stripIndent`
.a-id {
color: red;
}
.a-id a {
color: green;
}
`)
})
})
describe('deeply nested selector as a fn value', () => {
let sheet
beforeEach(() => {
sheet = jss
.createStyleSheet(
{
a: {
padding: '5px'
},
b: {
background: 'blue'
},
c: {
'&$a': {
'& $b': {
margin: () => '10px'
}
}
}
},
{link: true}
)
.attach()
})
afterEach(() => {
sheet.detach()
})
it('should return correct .toString()', () => {
sheet.update()
expect(sheet.toString()).to.be(stripIndent`
.a-id {
padding: 5px;
}
.b-id {
background: blue;
}
.c-id {}
.c-id.a-id {}
.c-id.a-id .b-id {
margin: 10px;
}
`)
})
})
})