Added logging, changed some directory structure

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

View File

@@ -0,0 +1,8 @@
The MIT License (MIT)
Copyright (c) 2014-present Oleg Slobodskoi
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,531 @@
## 8.1.0 / 2017-067-12
- Added webpackbin examples
- Added size-limit tool
- Added SheetsManager
## 8.0.0 / 2017-06-20
- Option `insertionPoint` can now accept a DOM node
- DOM node provided in `insertionPoint` can be inside of an iframe.
- Warn when an `insertionPoint` was specified but not found in the DOM.
### Breaking changes for users
- Option `generateClassName` which was used in Jss constructor and `Jss.setup` has been removed. A new option is called `createGenerateClassName` which is a factory that returns the old `generateClassName`. We need this to reset counters on SSR for each request.
- Removed default `insertionPoint` value ("jss") in order to have warnings when insertionPoint is not found in the DOM. With the default one we simply don't know when to warn.
### Potentially breaking changes for plugins
- KeyframeRule has been renamed to KeyframesRule.
- KeyframeRule.type === 'keyframe' => KeyFrames.type === 'keyframes'.
- RegularRule has been renamed to StyleRule
- RegularRule.type === 'regular' => StyleRule.type === 'style'.
- RegularRule.name => RegularRule.key
- ConditionalRule.selector => ConditionalRule.key
- FontFaceRule.selector => FontFaceRule.key
- SimpleRule.name => SimpleRule.key
- ViewportRule.name => ViewportRule.key
- RulesContainer => RuleList
## 7.1.7 / 2017-06-15
- Fix CSS flow types
## 7.1.6 / 2017-06-14
- Fix dynamic values for conditional and keyframe rules
## 7.1.5 / 2017-05-28
- Prevent duplicates in the sheets registry (#504)
- Optimize `sheets.add` for a big registry
## 7.1.4 / 2017-05-27
- Fixed undefined rule support (#489)
## 7.1.3 / 2017-05-26
- Fixes flow error when updating to the latest version (#507)
- Fixes createStyleSheet type definitions error (#495)
- Fixes function values for for nested rules (#500)
## 7.1.2 / 2017-05-12
- Fixes function values within keyframes (#471)
## 7.1.1 / 2017-04-26
- Fixes rendering rules with function values only (#475)
## 7.1.0 / 2017-04-21
- Support updating specific rule in `sheet.update(name, data)`
## 7.0.3 / 2017-04-14
- Fix a bug when dynamically inserted rules disapeared after reattaching the sheet (#438)
## 7.0.2 / 2017-04-14
- Remove temporarily jss-isolate from the tests
## 7.0.1 / 2017-04-14
- Fix `getDynamicStyles` when nested object is in the same styles object (#467)
## 7.0.0 / 2017-04-10
- Perf improvement through removing of JSON.parse(JSON.stringify(style))
- New hook `onProcessStyle`
- New hook `onChangeValue`
### Bugfixes
- Run plugins over property names with function values (#441)
- Function values inside of nested rules (#445)
### Breaking changes
- New signature of `generateClassName(rule, sheet)` option.
- Property `rule.originalStyle` is now available through `rule.options.parent.rules.raw[rule.name]`. It is longer but its a better place and is used in plugins only.
- Plugin signature for the hook `onProcessRule` shortcut `jss.use((rule) => {})` is not supported any more. Instead this hook is supported using its full name: `jss.use({onProcessRule: () => {}})`
## 6.5.0 / 2017-03-14
- Dynamic Sheets for theming and animations. #356
## 6.4.0 / 2017-03-10
- Reintroduced counter based class generation algorithm. #432
## 6.3.0 / 2017-02-16
- Introduced new option `insertionPoint`.
- Reduced amount of files in the package, dropped .npmignore file.
- Removed babel-runtime from the build.
- Added a new hook `onProcessSheet`.
- Started a list of companies/products using JSS, see docs/users.md
## 6.2.0 / 2017-01-15
- Added @viewport and @-ms-viewport support (used in bootstrap).
## 6.1.1 / 2017-01-04
- Allow sheet.link() call when VirtualRenderer is used.
## 6.1.0 / 2016-12-26
- Add jss-cache to the tests suit.
- Don't run processors on a rule which has been processed already.
- Add test for onCreateRule arguments.
- Add sheet as a second argument to the onProcessRule hook.
## 6.0.2 / 2016-12-23
- Call `onCreateRule` for every rule type.
- RulesContainer is now exported for the plugins.
- Using babel-runtime for the lib build now.
- Using webpack 2 now.
- Preparation for the bugfix - nesting within @global (#380)
- Preparation for the bugfix - nested @media inside of a rule inside of @global (#387).
## 6.0.1 / 2016-12-10
- Don't insert empty rules #363.
## 6.0.0 / 2016-12-09
- Added flow types.
- Added a new plugins API. It is backwards compatible. See plugins section.
- Perf improvements.
### Breaking changes
- Option "named" has been removed from JSS core and replaced by a jss-global plugin. From now on global styles are only possible using that plugin.
- Sheets are not added to the sheets registry automatically server-side any more. In order to prevent leaking styles between requests, you now need to create your own SheetsRegistry instance and add sheets to it manually. Make sure to create a new instance for each request. On the client, sheets are still automatically added to the registry.
## 5.5.6 / 2016-11-03
- test suite
- new is-in-browser detection #305
- warning when using an unknown at-rule
- start using flow #296
## 5.5.5 / 2016-09-23
- remove rewire from build
- update roadmap
## 5.5.4 / 2016-09-19
- always use `cssRules.insertRule` when using addRule on attached sheet, mixing them results in weird overwrite of a rule added by insertRule by a media query rendered using text node.
- catch errors from `cssRules.insertRule` and use a warning in development
## 5.5.3 / 2016-09-19
- add edge browser for browserstack
- fix addRule insertion order from plugins when sheet is attached
- fix @media insertion in IE
## 5.5.2 / 2016-09-9
- Skip empty values #307
## 5.5.1 / 2016-09-6
- Fix adding rules during the plugins loop
## 5.5.0 / 2016-09-6
- Fix wrong order of nested rules #285
- Add `index` option to `sheet.addRule` which allows to specify the order or added rules
- Add `<style>` node position control option `index` and insertion point comment
- Better browser detection by using `is-browser` package
## 5.4.0 / 2016-08-15
- More docs
- More benchmarks
- Make sheet.addRule accept options
## 5.3.0 / 2016-08-06
- Added `jss.setup` method which accepts options like the contructor and can be used for presets
- Docs
- Create Rodamap
- Cleanup DomRenderer from IE8 code.
- Fix benchmark, use a new jss instance, because there is sheets registry
## 5.2.0 / 2016-07-27
- Added `sheet.deleteRule` #266
## 5.1.0 / 2016-07-13
- alternative syntax for space and comma separated values #264
## 5.0.0 / 2016-07-10
- new fallbacks api #256
- rule.applyTo doesn't support fallbacks any more
- support conditionals overwrite upfront #259, #180
- remove compatibility fix for babel 5, now you need to use `var jss = require('jss').default` in ES5
## 4.0.3 / 2016-07-05
- fixed bug when plugins called twice on createStyleSheet #258
- enable node 7 #248
## 4.0.2 / 2016-06-28
- allow adding rules to a detached sheet #253
## 4.0.1 / 2016-06-23
- fix jss.version in lib
## 4.0.0 / 2016-06-23
- user defined classname generation function
- deterministic class names generation
- run plugins separately when creating rules in a batch
## 3.11.1 / 2016-05-11
- register children of a conditional in sheet.classes #81
## 3.11.0 / 2016-05-06
- added option element to .createStyleSheet #231
## 3.10.0 / 2016-05-02
- fix multiple @imports
- added benchmarks
- rewrote all tests with mocha
## 3.9.1 / 2016-04-26
- fix multiple @media in one sheet
## 3.9.0 / 2016-04-24
- update linter eslint-config-jss@1.0.0
## 3.8.0 / 2016-04-24
- added jss.version to the build (Daijiro Wachi)
## 3.7.0 / 2016-04-21
- docs
- font-face rule can now handle array of font-faces (Ken Carpenter)
## 3.6.3 / 2016-03-12
- fix rule registration in style sheet, previous commits resulted in a selector instead of class nem within sheet.classes map.
## 3.6.2 / 2016-04-12
- register rule when changed worked by setting selector
## 3.6.1 / 2016-03-11
- Update StyleSheet#rules when modifying selector
## 3.6.0 / 2016-04-08
- implement selector setter, now Rule#selector can be set, due to the fact not every browser implements selectorText setter, the entire sheet will be rerendered in such browsers. Should be used with caution.
## 3.5.0 / 2016-04-04
- fixed breaking change, which made exports of 3.4.0 incompatible with 3.3.0
- fix font-face rule type
## 3.4.0 / 2016-04-03
- added style sheets registry accesible via jss.sheets
- updated babel to version 6
## 3.3.0 / 2016-01-31
- fixed bug: nested rule inside of a @media conditional
- new docs
- trim empty rules (@wldcordeiro)
- support node 5 (@nikgraf)
## 3.2.0 / 2015-11-27
- jss-debug is deprecated, rule name is inside of generated class name now
- no more "type" option for style sheet, its always set to text/css
- no more "title" option for style sheet, its not a part of the spec http://www.w3.org/TR/html-markup/style.html
- added meta option, now you can for e.g. set the name of your component and find it on style element.
- fixed bug when multiple conditionals used in one sheet
## 3.1.1 / 2015-11-14
- added Rule#originalStyle property to access original style object from a plugin
## 3.1.0 / 2015-11-12
- new testing infrastructure with browserstack and codeship
## 3.0.0 / 2015-10-19
- internal rewrite for cleaner code (ConditionalRule, KeyframeRule, SimpleRule)
- moved all DOM related methods to dom.js module
- now child rules exist only in ConditionalRule, simplified Rule and StyleSheet logic
- fixed Named rules not generating when using @media only #81
- added support for @charset, @import, @namespace, @supports
- removed jss.Rule from public access, use jss.createRule() instead
- removed jss.Jss from public access, use jss.create() instead
- removed jss.StyleSheet from public access, use jss.createStyleSheet() instead
## 2.3.4 / 2015-09-21
- remove bower.json
- remove dist from repository
- add dist to npm package
- add cdnjs support
## 2.3.3 / 2015-09-20
- remove xpkg, update npmignore and ingore list for bower
## 2.3.2 / 2015-09-19
- reference rule name on the rule instance to fix jss-debug
## 2.3.1 / 2015-09-15
- use eslint-config-jss
## 2.3.0 / 2015-09-10
- migrate to es6
- move examples to jss-examples repository
## 2.2.1 / 2015-09-6
- remove @media from classes hash
## 2.2.0 / 2015-09-6
- added support for named at-rules e.g. @media
## 2.1.6 / 2015-09-2
- removed invalid characters
## 2.1.5 / 2015-08-20
- stop mutating original rules passed by user. expecting style to be a plaing object.
## 2.1.4 / 2015-07-31
- add internal method uid.reset() for testing
## 2.1.3 / 2015-07-31
- rename global reference to globalReference
## 2.1.2 / 2015-07-28
- avoid conflicts of jss ids when multiple jss versions are used on the same page
## 2.1.1 / 2015-07-20
- remove browser field from package.json, it makes webpack use dist version instead of src.
## 2.1.0 / 2015-07-18
- create Jss constructor so that we can have multiple jss instances with different plugins, needed when you want to reuse jss lib from different standalone components which have own jss configuration and should not clash.
## 2.0.0 / 2015-06-17
- create jss-cli package, remove bin script from jss
## 1.0.8 / 2015-03-16
- fix bower package name
- make change condition to include any non-null value in Rule#prop (Stephen Saunders)
## 1.0.7 / 2015-02-26
- remove NO-BREAK SPACE chars
## 1.0.6 / 2015-02-24
- add rule.toJSON()
## 1.0.5 / 2015-02-17
- support any node version above 0.8
## 1.0.4 / 2015-02-6
- allow rule options to be passed in internal rule#addRule method to allow nested rules to have different options than parent one (for now just "named")
## 1.0.3 / 2015-01-31
- pass rule name to make debug plugin possible
## 1.0.2 / 2015-01-31
- fix duplicated rule rendering
## 1.0.1 / 2015-01-31
- run plugins on inner rules of at-rules
## 1.0.0 / 2015-01-31
- styles have named: true option by default, this is backwards incompatible
- at-rules like @media can now also have named rules
## 0.10.2 / 2015-01-31
- fixed #40 there is no colons in all at-rules with nested declarations
## 0.10.1 / 2014-12-21
- fixed firefox issues
## 0.10.0 / 2014-12-21
- added rule.prop() for dynamic rule properties #15
## 0.9.0 / 2014-12-21
- added Rule#prop() for setting and getting rule props dynamically
- added `link` option in order to make .prop() work but still without to add perf overhead by default.
- added example for .prop()
## 0.8.2 / 2014-12-17
- added build for "support non browser env #12"
- added calendar example
## 0.8.1 / 2014-11-29
- supported non browser env #12
## 0.8.0 / 2014-11-29
- renamed Stylesheet to StyleSheet because its wrong.
## 0.7.0 / 2014-11-29
- moved jss to separate github organization
- moved all plugins to separate repositories (don't force people use plugins they don't need)
## 0.6.0 / 2014-11-28
- renamed processors to plugins
- added public .use function for registering plugins
## 0.5.0 / 2014-11-27
- supported multiple declarations with identical property names #22
## 0.4.0 / 2014-11-23
- supported nested rules when using .addRule method #20
## 0.3.2 / 2014-11-19
- rewrittn prefixer for feature testing using camel cased version because of firefox
## 0.3.0 / 2014-11-19
- added vendor prefixes plugin for properties #21
## 0.2.10 / 2014-11-10
- supported nested extend
- added more complex topcoat example
## 0.2.9 / 2014-11-03
- added @keyframes and @media support #16
## 0.2.8 / 2014-11-02
- added possibility write multi nested selector in one line #18
## 0.2.7 / 2014-11-02
- added @font-face to cli converter
- added @keyframes to cli converter
## 0.2.6 / 2014-11-02
- createed perf comparence for bootstrap #13
## 0.2.5 / 2014-11-02
- createed css->jss converter #11
## 0.2.4 / 2014-11-01
- made tests runnable from githubs gh-pages http://jsstyles.github.io/jss/test/
## 0.2.3 / 2014-11-01
- fixed test failing in firefox #14
## 0.2.2 / 2014-11-01
- Renamed param "generateClasses" to "named" in createStyleSheet
- If `named` is true, ss.rules[name] is accessible using the name.
- ss.addRules will render new rules after style element has been rendered too.
- document ss.addRules
## 0.2.1 / 2014-10-29
First official release.

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,72 @@
declare type DOMString = string
declare interface CSSRuleBase<T> {
+type: $PropertyType<T, 'type'>;
+CSSRule: ?CSSRule;
+CSSStyleSheet: ?CSSStyleSheet;
cssText: DOMString;
static STYLE_RULE: 1;
static CHARSET_RULE: 2; // deprecated
static IMPORT_RULE: 3;
static MEDIA_RULE: 4;
static FONT_FACE_RULE: 5;
static PAGE_RULE: 6;
static KEYFRAMES_RULE: 7;
static KEYFRAME_RULE: 8;
static NAMESPACE_RULE: 10;
static COUNTER_STYLE_RULE: 11;
static SUPPORTS_RULE: 12;
static DOCUMENT_RULE: 13;
static FONT_FEATURE_VALUES_RULE: 14;
static VIEWPORT_RULE: 15;
static REGION_STYLE_RULE: 16;
}
declare interface CSSStyleRule extends CSSRuleBase<{type: 1|1}> {
+type: 1;
+style: CSSStyleDeclaration;
selectorText: DOMString;
}
declare interface CSSRuleList {
length: number;
[index: number]: CSSStyleRule;
}
declare interface CSSGroupingRule<T> extends CSSRuleBase<T> {
+cssRules: CSSRuleList;
insertRule(rule: DOMString, index: number): number;
deleteRule(index: number): void;
}
declare interface CSSKeyframeRule extends CSSRuleBase<{type: 8|8}> {
+type: 8;
+style: CSSStyleDeclaration;
keyText: DOMString;
}
declare interface CSSKeyframesRule extends CSSRuleBase<{type: 7|7}> {
+type: 7;
+cssRules: CSSRuleList;
name: DOMString;
appendRule(rule: DOMString): void;
deleteRule(key: DOMString): void;
findRule(key: DOMString): CSSKeyframeRule;
}
declare interface CSSMediaRule extends CSSGroupingRule<{type: 4|4}> {
+type: 4;
+mediaList: {
+mediaText: DOMString,
length: number,
item?: DOMString,
appendMedium(medium: DOMString): void,
deleteMedium(medium: DOMString): void
}
}
declare type CSSOMRule =
| CSSStyleRule
| CSSMediaRule
| CSSKeyframesRule

View File

@@ -0,0 +1,162 @@
'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; };
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _StyleSheet = require('./StyleSheet');
var _StyleSheet2 = _interopRequireDefault(_StyleSheet);
var _PluginsRegistry = require('./PluginsRegistry');
var _PluginsRegistry2 = _interopRequireDefault(_PluginsRegistry);
var _rules = require('./plugins/rules');
var _rules2 = _interopRequireDefault(_rules);
var _sheets = require('./sheets');
var _sheets2 = _interopRequireDefault(_sheets);
var _createGenerateClassName = require('./utils/createGenerateClassName');
var _createGenerateClassName2 = _interopRequireDefault(_createGenerateClassName);
var _createRule2 = require('./utils/createRule');
var _createRule3 = _interopRequireDefault(_createRule2);
var _findRenderer = require('./utils/findRenderer');
var _findRenderer2 = _interopRequireDefault(_findRenderer);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Jss = function () {
function Jss(options) {
_classCallCheck(this, Jss);
this.version = "8.1.0";
this.plugins = new _PluginsRegistry2['default']();
// eslint-disable-next-line prefer-spread
this.use.apply(this, _rules2['default']);
this.setup(options);
}
_createClass(Jss, [{
key: 'setup',
value: function setup() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var createGenerateClassName = options.createGenerateClassName || _createGenerateClassName2['default'];
this.generateClassName = createGenerateClassName();
this.options = _extends({}, options, {
createGenerateClassName: createGenerateClassName,
Renderer: (0, _findRenderer2['default'])(options)
// eslint-disable-next-line prefer-spread
});if (options.plugins) this.use.apply(this, options.plugins);
return this;
}
/**
* Create a Style Sheet.
*/
}, {
key: 'createStyleSheet',
value: function createStyleSheet(styles) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var index = options.index;
if (typeof index !== 'number') {
index = _sheets2['default'].index === 0 ? 0 : _sheets2['default'].index + 1;
}
var sheet = new _StyleSheet2['default'](styles, _extends({}, options, {
jss: this,
generateClassName: options.generateClassName || this.generateClassName,
insertionPoint: this.options.insertionPoint,
Renderer: this.options.Renderer,
index: index
}));
this.plugins.onProcessSheet(sheet);
return sheet;
}
/**
* Detach the Style Sheet and remove it from the registry.
*/
}, {
key: 'removeStyleSheet',
value: function removeStyleSheet(sheet) {
sheet.detach();
_sheets2['default'].remove(sheet);
return this;
}
/**
* Create a rule without a Style Sheet.
*/
}, {
key: 'createRule',
value: function createRule(name) {
var style = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
// Enable rule without name for inline styles.
if ((typeof name === 'undefined' ? 'undefined' : _typeof(name)) === 'object') {
options = style;
style = name;
name = undefined;
}
// Cast from RuleFactoryOptions to RuleOptions
// https://stackoverflow.com/questions/41328728/force-casting-in-flow
var ruleOptions = options;
ruleOptions.jss = this;
ruleOptions.Renderer = this.options.Renderer;
if (!ruleOptions.generateClassName) ruleOptions.generateClassName = this.generateClassName;
if (!ruleOptions.classes) ruleOptions.classes = {};
var rule = (0, _createRule3['default'])(name, style, ruleOptions);
this.plugins.onProcessRule(rule);
return rule;
}
/**
* Register plugin. Passed function will be invoked with a rule instance.
*/
}, {
key: 'use',
value: function use() {
var _this = this;
for (var _len = arguments.length, plugins = Array(_len), _key = 0; _key < _len; _key++) {
plugins[_key] = arguments[_key];
}
plugins.forEach(function (plugin) {
return _this.plugins.use(plugin);
});
return this;
}
}]);
return Jss;
}();
exports['default'] = Jss;

View File

@@ -0,0 +1,114 @@
/* @flow */
import StyleSheet from './StyleSheet'
import PluginsRegistry from './PluginsRegistry'
import rulesPlugins from './plugins/rules'
import sheets from './sheets'
import createGenerateClassNameDefault from './utils/createGenerateClassName'
import createRule from './utils/createRule'
import findRenderer from './utils/findRenderer'
import type {
Rule,
RuleFactoryOptions,
RuleOptions,
StyleSheetFactoryOptions,
Plugin,
JssOptions,
InternalJssOptions,
JssStyle,
generateClassName
} from './types'
declare var __VERSION__: string
export default class Jss {
version = __VERSION__
plugins = new PluginsRegistry()
options: InternalJssOptions
generateClassName: generateClassName
constructor(options?: JssOptions) {
// eslint-disable-next-line prefer-spread
this.use.apply(this, rulesPlugins)
this.setup(options)
}
setup(options?: JssOptions = {}): this {
const createGenerateClassName =
options.createGenerateClassName ||
createGenerateClassNameDefault
this.generateClassName = createGenerateClassName()
this.options = {
...options,
createGenerateClassName,
Renderer: findRenderer(options)
}
// eslint-disable-next-line prefer-spread
if (options.plugins) this.use.apply(this, options.plugins)
return this
}
/**
* Create a Style Sheet.
*/
createStyleSheet(styles: Object, options: StyleSheetFactoryOptions = {}): StyleSheet {
let index = options.index
if (typeof index !== 'number') {
index = sheets.index === 0 ? 0 : sheets.index + 1
}
const sheet = new StyleSheet(styles, {
...options,
jss: (this: Jss),
generateClassName: options.generateClassName || this.generateClassName,
insertionPoint: this.options.insertionPoint,
Renderer: this.options.Renderer,
index
})
this.plugins.onProcessSheet(sheet)
return sheet
}
/**
* Detach the Style Sheet and remove it from the registry.
*/
removeStyleSheet(sheet: StyleSheet): this {
sheet.detach()
sheets.remove(sheet)
return this
}
/**
* Create a rule without a Style Sheet.
*/
createRule(name?: string, style?: JssStyle = {}, options?: RuleFactoryOptions = {}): Rule {
// Enable rule without name for inline styles.
if (typeof name === 'object') {
options = style
style = name
name = undefined
}
// Cast from RuleFactoryOptions to RuleOptions
// https://stackoverflow.com/questions/41328728/force-casting-in-flow
const ruleOptions: RuleOptions = (options: any)
ruleOptions.jss = this
ruleOptions.Renderer = this.options.Renderer
if (!ruleOptions.generateClassName) ruleOptions.generateClassName = this.generateClassName
if (!ruleOptions.classes) ruleOptions.classes = {}
const rule = createRule(name, style, ruleOptions)
this.plugins.onProcessRule(rule)
return rule
}
/**
* Register plugin. Passed function will be invoked with a rule instance.
*/
use(...plugins: Array<Plugin>): this {
plugins.forEach(plugin => this.plugins.use(plugin))
return this
}
}

View File

@@ -0,0 +1,123 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _warning = require('warning');
var _warning2 = _interopRequireDefault(_warning);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var PluginsRegistry = function () {
function PluginsRegistry() {
_classCallCheck(this, PluginsRegistry);
this.hooks = {
onCreateRule: [],
onProcessRule: [],
onProcessStyle: [],
onProcessSheet: [],
onChangeValue: []
/**
* Call `onCreateRule` hooks and return an object if returned by a hook.
*/
};
}
_createClass(PluginsRegistry, [{
key: 'onCreateRule',
value: function onCreateRule(name, decl, options) {
for (var i = 0; i < this.hooks.onCreateRule.length; i++) {
var rule = this.hooks.onCreateRule[i](name, decl, options);
if (rule) return rule;
}
return null;
}
/**
* Call `onProcessRule` hooks.
*/
}, {
key: 'onProcessRule',
value: function onProcessRule(rule) {
if (rule.isProcessed) return;
var sheet = rule.options.sheet;
for (var i = 0; i < this.hooks.onProcessRule.length; i++) {
this.hooks.onProcessRule[i](rule, sheet);
}
// $FlowFixMe
if (rule.style) this.onProcessStyle(rule.style, rule, sheet);
rule.isProcessed = true;
}
/**
* Call `onProcessStyle` hooks.
*/
}, {
key: 'onProcessStyle',
value: function onProcessStyle(style, rule, sheet) {
var nextStyle = style;
for (var i = 0; i < this.hooks.onProcessStyle.length; i++) {
nextStyle = this.hooks.onProcessStyle[i](nextStyle, rule, sheet);
// $FlowFixMe
rule.style = nextStyle;
}
}
/**
* Call `onProcessSheet` hooks.
*/
}, {
key: 'onProcessSheet',
value: function onProcessSheet(sheet) {
for (var i = 0; i < this.hooks.onProcessSheet.length; i++) {
this.hooks.onProcessSheet[i](sheet);
}
}
/**
* Call `onChangeValue` hooks.
*/
}, {
key: 'onChangeValue',
value: function onChangeValue(value, prop, rule) {
var processedValue = value;
for (var i = 0; i < this.hooks.onChangeValue.length; i++) {
processedValue = this.hooks.onChangeValue[i](processedValue, prop, rule);
}
return processedValue;
}
/**
* Register a plugin.
* If function is passed, it is a shortcut for `{onProcessRule}`.
*/
}, {
key: 'use',
value: function use(plugin) {
for (var name in plugin) {
if (this.hooks[name]) this.hooks[name].push(plugin[name]);else (0, _warning2['default'])(false, '[JSS] Unknown hook "%s".', name);
}
}
}]);
return PluginsRegistry;
}();
exports['default'] = PluginsRegistry;

View File

@@ -0,0 +1,85 @@
/* @flow */
import warning from 'warning'
import type StyleSheet from './StyleSheet'
import type {Plugin, Rule, RuleOptions, JssStyle} from './types'
export default class PluginsRegistry {
hooks: {[key: string]: Array<Function>} = {
onCreateRule: [],
onProcessRule: [],
onProcessStyle: [],
onProcessSheet: [],
onChangeValue: []
}
/**
* Call `onCreateRule` hooks and return an object if returned by a hook.
*/
onCreateRule(name?: string, decl: JssStyle, options: RuleOptions): Rule|null {
for (let i = 0; i < this.hooks.onCreateRule.length; i++) {
const rule = this.hooks.onCreateRule[i](name, decl, options)
if (rule) return rule
}
return null
}
/**
* Call `onProcessRule` hooks.
*/
onProcessRule(rule: Rule): void {
if (rule.isProcessed) return
const {sheet} = rule.options
for (let i = 0; i < this.hooks.onProcessRule.length; i++) {
this.hooks.onProcessRule[i](rule, sheet)
}
// $FlowFixMe
if (rule.style) this.onProcessStyle(rule.style, rule, sheet)
rule.isProcessed = true
}
/**
* Call `onProcessStyle` hooks.
*/
onProcessStyle(style: JssStyle, rule: Rule, sheet?: StyleSheet): void {
let nextStyle = style
for (let i = 0; i < this.hooks.onProcessStyle.length; i++) {
nextStyle = this.hooks.onProcessStyle[i](nextStyle, rule, sheet)
// $FlowFixMe
rule.style = nextStyle
}
}
/**
* Call `onProcessSheet` hooks.
*/
onProcessSheet(sheet: StyleSheet): void {
for (let i = 0; i < this.hooks.onProcessSheet.length; i++) {
this.hooks.onProcessSheet[i](sheet)
}
}
/**
* Call `onChangeValue` hooks.
*/
onChangeValue(value: string, prop: string, rule: Rule): string {
let processedValue = value
for (let i = 0; i < this.hooks.onChangeValue.length; i++) {
processedValue = this.hooks.onChangeValue[i](processedValue, prop, rule)
}
return processedValue
}
/**
* Register a plugin.
* If function is passed, it is a shortcut for `{onProcessRule}`.
*/
use(plugin: Plugin): void {
for (const name in plugin) {
if (this.hooks[name]) this.hooks[name].push(plugin[name])
else warning(false, '[JSS] Unknown hook "%s".', name)
}
}
}

View File

@@ -0,0 +1,224 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _createRule = require('./utils/createRule');
var _createRule2 = _interopRequireDefault(_createRule);
var _updateRule = require('./utils/updateRule');
var _updateRule2 = _interopRequireDefault(_updateRule);
var _linkRule = require('./utils/linkRule');
var _linkRule2 = _interopRequireDefault(_linkRule);
var _StyleRule = require('./rules/StyleRule');
var _StyleRule2 = _interopRequireDefault(_StyleRule);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Contains rules objects and allows adding/removing etc.
* Is used for e.g. by `StyleSheet` or `ConditionalRule`.
*/
var RuleList = function () {
// Original styles object.
function RuleList(options) {
_classCallCheck(this, RuleList);
this.map = {};
this.raw = {};
this.index = [];
this.options = options;
this.classes = options.classes;
}
/**
* Create and register rule.
*
* Will not render after Style Sheet was rendered the first time.
*/
// Used to ensure correct rules order.
// Rules registry for access by .get() method.
// It contains the same rule registered by name and by selector.
_createClass(RuleList, [{
key: 'add',
value: function add(name, decl, options) {
var _options = this.options,
parent = _options.parent,
sheet = _options.sheet,
jss = _options.jss,
Renderer = _options.Renderer,
generateClassName = _options.generateClassName;
options = _extends({
classes: this.classes,
parent: parent,
sheet: sheet,
jss: jss,
Renderer: Renderer,
generateClassName: generateClassName
}, options);
if (!options.selector && this.classes[name]) options.selector = '.' + this.classes[name];
this.raw[name] = decl;
var rule = (0, _createRule2['default'])(name, decl, options);
this.register(rule);
var index = options.index === undefined ? this.index.length : options.index;
this.index.splice(index, 0, rule);
return rule;
}
/**
* Get a rule.
*/
}, {
key: 'get',
value: function get(name) {
return this.map[name];
}
/**
* Delete a rule.
*/
}, {
key: 'remove',
value: function remove(rule) {
this.unregister(rule);
this.index.splice(this.indexOf(rule), 1);
}
/**
* Get index of a rule.
*/
}, {
key: 'indexOf',
value: function indexOf(rule) {
return this.index.indexOf(rule);
}
/**
* Run `onProcessRule()` plugins on every rule.
*/
}, {
key: 'process',
value: function process() {
var plugins = this.options.jss.plugins;
// We need to clone array because if we modify the index somewhere else during a loop
// we end up with very hard-to-track-down side effects.
this.index.slice(0).forEach(plugins.onProcessRule, plugins);
}
/**
* Register a rule in `.map` and `.classes` maps.
*/
}, {
key: 'register',
value: function register(rule) {
this.map[rule.key] = rule;
if (rule instanceof _StyleRule2['default']) {
this.map[rule.selector] = rule;
this.classes[rule.key] = rule.selector.substr(1);
}
}
/**
* Unregister a rule.
*/
}, {
key: 'unregister',
value: function unregister(rule) {
delete this.map[rule.key];
delete this.classes[rule.key];
if (rule instanceof _StyleRule2['default']) delete this.map[rule.selector];
}
/**
* Update the function values with a new data.
*/
}, {
key: 'update',
value: function update(name, data) {
if (typeof name === 'string') {
(0, _updateRule2['default'])(this.get(name), data, RuleList);
return;
}
for (var index = 0; index < this.index.length; index++) {
(0, _updateRule2['default'])(this.index[index], name, RuleList);
}
}
/**
* Link renderable rules with CSSRuleList.
*/
}, {
key: 'link',
value: function link(cssRules) {
for (var i = 0; i < cssRules.length; i++) {
var cssRule = cssRules[i];
var rule = this.get(this.options.sheet.renderer.getSelector(cssRule));
if (rule) (0, _linkRule2['default'])(rule, cssRule);
}
}
/**
* Convert rules to a CSS string.
*/
}, {
key: 'toString',
value: function toString(options) {
var str = '';
for (var index = 0; index < this.index.length; index++) {
var rule = this.index[index];
var css = rule.toString(options);
// No need to render an empty rule.
if (!css) continue;
if (str) str += '\n';
str += css;
}
return str;
}
}]);
return RuleList;
}();
exports['default'] = RuleList;

View File

@@ -0,0 +1,165 @@
/* @flow */
import createRule from './utils/createRule'
import updateRule from './utils/updateRule'
import linkRule from './utils/linkRule'
import StyleRule from './rules/StyleRule'
import type {
RuleListOptions,
ToCssOptions,
Rule,
RuleOptions,
JssStyle
} from './types'
/**
* Contains rules objects and allows adding/removing etc.
* Is used for e.g. by `StyleSheet` or `ConditionalRule`.
*/
export default class RuleList {
// Rules registry for access by .get() method.
// It contains the same rule registered by name and by selector.
map: {[key: string]: Rule} = {}
// Original styles object.
raw: {[key: string]: JssStyle} = {}
// Used to ensure correct rules order.
index: Array<Rule> = []
options: RuleListOptions
classes: Object
constructor(options: RuleListOptions) {
this.options = options
this.classes = options.classes
}
/**
* Create and register rule.
*
* Will not render after Style Sheet was rendered the first time.
*/
add(name: string, decl: JssStyle, options?: RuleOptions): Rule {
const {parent, sheet, jss, Renderer, generateClassName} = this.options
options = {
classes: this.classes,
parent,
sheet,
jss,
Renderer,
generateClassName,
...options
}
if (!options.selector && this.classes[name]) options.selector = `.${this.classes[name]}`
this.raw[name] = decl
const rule = createRule(name, decl, options)
this.register(rule)
const index = options.index === undefined ? this.index.length : options.index
this.index.splice(index, 0, rule)
return rule
}
/**
* Get a rule.
*/
get(name: string): Rule {
return this.map[name]
}
/**
* Delete a rule.
*/
remove(rule: Rule): void {
this.unregister(rule)
this.index.splice(this.indexOf(rule), 1)
}
/**
* Get index of a rule.
*/
indexOf(rule: Rule): number {
return this.index.indexOf(rule)
}
/**
* Run `onProcessRule()` plugins on every rule.
*/
process(): void {
const {plugins} = this.options.jss
// We need to clone array because if we modify the index somewhere else during a loop
// we end up with very hard-to-track-down side effects.
this.index.slice(0).forEach(plugins.onProcessRule, plugins)
}
/**
* Register a rule in `.map` and `.classes` maps.
*/
register(rule: Rule): void {
this.map[rule.key] = rule
if (rule instanceof StyleRule) {
this.map[rule.selector] = rule
this.classes[rule.key] = rule.selector.substr(1)
}
}
/**
* Unregister a rule.
*/
unregister(rule: Rule): void {
delete this.map[rule.key]
delete this.classes[rule.key]
if (rule instanceof StyleRule) delete this.map[rule.selector]
}
/**
* Update the function values with a new data.
*/
update(name?: string, data?: Object): void {
if (typeof name === 'string') {
updateRule(this.get(name), data, RuleList)
return
}
for (let index = 0; index < this.index.length; index++) {
updateRule(this.index[index], name, RuleList)
}
}
/**
* Link renderable rules with CSSRuleList.
*/
link(cssRules: CSSRuleList): void {
for (let i = 0; i < cssRules.length; i++) {
const cssRule = cssRules[i]
const rule = this.get(this.options.sheet.renderer.getSelector(cssRule))
if (rule) linkRule(rule, cssRule)
}
}
/**
* Convert rules to a CSS string.
*/
toString(options?: ToCssOptions): string {
let str = ''
for (let index = 0; index < this.index.length; index++) {
const rule = this.index[index]
const css = rule.toString(options)
// No need to render an empty rule.
if (!css) continue
if (str) str += '\n'
str += css
}
return str
}
}

View File

@@ -0,0 +1,82 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _warning = require('warning');
var _warning2 = _interopRequireDefault(_warning);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* SheetsManager is like a WeakMap which is designed to count StyleSheet
* instances and attach/detach automatically.
*/
var SheetsManager = function () {
function SheetsManager() {
_classCallCheck(this, SheetsManager);
this.sheets = [];
this.refs = [];
this.keys = [];
}
_createClass(SheetsManager, [{
key: 'get',
value: function get(key) {
var index = this.keys.indexOf(key);
return this.sheets[index];
}
}, {
key: 'add',
value: function add(key, sheet) {
var sheets = this.sheets,
refs = this.refs,
keys = this.keys;
var index = sheets.indexOf(sheet);
if (index !== -1) return index;
sheets.push(sheet);
refs.push(0);
keys.push(key);
return sheets.length - 1;
}
}, {
key: 'manage',
value: function manage(key) {
var index = this.keys.indexOf(key);
var sheet = this.sheets[index];
if (this.refs[index] === 0) sheet.attach();
this.refs[index]++;
if (!this.keys[index]) this.keys.splice(index, 0, key);
return sheet;
}
}, {
key: 'unmanage',
value: function unmanage(key) {
var index = this.keys.indexOf(key);
if (index === -1) {
// eslint-ignore-next-line no-console
(0, _warning2['default'])('SheetsManager: can\'t find sheet to unmanage');
return;
}
if (this.refs[index] > 0) {
this.refs[index]--;
if (this.refs[index] === 0) this.sheets[index].detach();
}
}
}]);
return SheetsManager;
}();
exports['default'] = SheetsManager;

View File

@@ -0,0 +1,55 @@
/* @flow */
import warn from 'warning'
import type StyleSheet from './StyleSheet'
/**
* SheetsManager is like a WeakMap which is designed to count StyleSheet
* instances and attach/detach automatically.
*/
export default class SheetsManager {
sheets: Array<StyleSheet> = []
refs: Array<number> = []
keys: Array<Object> = []
get(key: Object): StyleSheet {
const index = this.keys.indexOf(key)
return this.sheets[index]
}
add(key: Object, sheet: StyleSheet): number {
const {sheets, refs, keys} = this
const index = sheets.indexOf(sheet)
if (index !== -1) return index
sheets.push(sheet)
refs.push(0)
keys.push(key)
return sheets.length - 1
}
manage(key: Object): StyleSheet {
const index = this.keys.indexOf(key)
const sheet = this.sheets[index]
if (this.refs[index] === 0) sheet.attach()
this.refs[index]++
if (!this.keys[index]) this.keys.splice(index, 0, key)
return sheet
}
unmanage(key: Object): void {
const index = this.keys.indexOf(key)
if (index === -1) {
// eslint-ignore-next-line no-console
warn('SheetsManager: can\'t find sheet to unmanage')
return
}
if (this.refs[index] > 0) {
this.refs[index]--
if (this.refs[index] === 0) this.sheets[index].detach()
}
}
}

View File

@@ -0,0 +1,98 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Sheets registry to access them all at one place.
*/
var SheetsRegistry = function () {
function SheetsRegistry() {
_classCallCheck(this, SheetsRegistry);
this.registry = [];
}
_createClass(SheetsRegistry, [{
key: 'add',
/**
* Register a Style Sheet.
*/
value: function add(sheet) {
var registry = this.registry;
var index = sheet.options.index;
if (registry.indexOf(sheet) !== -1) return;
if (registry.length === 0 || index >= this.index) {
registry.push(sheet);
return;
}
// Find a position.
for (var i = 0; i < registry.length; i++) {
if (registry[i].options.index > index) {
registry.splice(i, 0, sheet);
return;
}
}
}
/**
* Reset the registry.
*/
}, {
key: 'reset',
value: function reset() {
this.registry = [];
}
/**
* Remove a Style Sheet.
*/
}, {
key: 'remove',
value: function remove(sheet) {
var index = this.registry.indexOf(sheet);
this.registry.splice(index, 1);
}
/**
* Convert all attached sheets to a CSS string.
*/
}, {
key: 'toString',
value: function toString(options) {
return this.registry.filter(function (sheet) {
return sheet.attached;
}).map(function (sheet) {
return sheet.toString(options);
}).join('\n');
}
}, {
key: 'index',
/**
* Current highest index number.
*/
get: function get() {
return this.registry.length === 0 ? 0 : this.registry[this.registry.length - 1].options.index;
}
}]);
return SheetsRegistry;
}();
exports['default'] = SheetsRegistry;

View File

@@ -0,0 +1,65 @@
/* @flow */
import type {ToCssOptions} from './types'
import type StyleSheet from './StyleSheet'
/**
* Sheets registry to access them all at one place.
*/
export default class SheetsRegistry {
registry: Array<StyleSheet> = []
/**
* Current highest index number.
*/
get index(): number {
return this.registry.length === 0 ? 0 : this.registry[this.registry.length - 1].options.index
}
/**
* Register a Style Sheet.
*/
add(sheet: StyleSheet): void {
const {registry} = this
const {index} = sheet.options
if (registry.indexOf(sheet) !== -1) return
if (registry.length === 0 || index >= this.index) {
registry.push(sheet)
return
}
// Find a position.
for (let i = 0; i < registry.length; i++) {
if (registry[i].options.index > index) {
registry.splice(i, 0, sheet)
return
}
}
}
/**
* Reset the registry.
*/
reset(): void {
this.registry = []
}
/**
* Remove a Style Sheet.
*/
remove(sheet: StyleSheet): void {
const index = this.registry.indexOf(sheet)
this.registry.splice(index, 1)
}
/**
* Convert all attached sheets to a CSS string.
*/
toString(options?: ToCssOptions): string {
return this.registry
.filter(sheet => sheet.attached)
.map(sheet => sheet.toString(options))
.join('\n')
}
}

View File

@@ -0,0 +1,234 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _linkRule = require('./utils/linkRule');
var _linkRule2 = _interopRequireDefault(_linkRule);
var _RuleList = require('./RuleList');
var _RuleList2 = _interopRequireDefault(_RuleList);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var StyleSheet = function () {
function StyleSheet(styles, options) {
_classCallCheck(this, StyleSheet);
this.attached = false;
this.deployed = false;
this.linked = false;
this.classes = {};
this.options = _extends({}, options, {
sheet: this,
parent: this,
classes: this.classes
});
this.renderer = new options.Renderer(this);
this.rules = new _RuleList2['default'](this.options);
for (var name in styles) {
this.rules.add(name, styles[name]);
}
this.rules.process();
}
/**
* Attach renderable to the render tree.
*/
_createClass(StyleSheet, [{
key: 'attach',
value: function attach() {
if (this.attached) return this;
if (!this.deployed) this.deploy();
this.renderer.attach();
if (!this.linked && this.options.link) this.link();
this.attached = true;
return this;
}
/**
* Remove renderable from render tree.
*/
}, {
key: 'detach',
value: function detach() {
if (!this.attached) return this;
this.renderer.detach();
this.attached = false;
return this;
}
/**
* Add a rule to the current stylesheet.
* Will insert a rule also after the stylesheet has been rendered first time.
*/
}, {
key: 'addRule',
value: function addRule(name, decl, options) {
var queue = this.queue;
// Plugins can create rules.
// In order to preserve the right order, we need to queue all `.addRule` calls,
// which happen after the first `rules.add()` call.
if (this.attached && !queue) this.queue = [];
var rule = this.rules.add(name, decl, options);
this.options.jss.plugins.onProcessRule(rule);
if (this.attached) {
if (!this.deployed) return rule;
// Don't insert rule directly if there is no stringified version yet.
// It will be inserted all together when .attach is called.
if (queue) queue.push(rule);else {
this.insertRule(rule);
if (this.queue) {
this.queue.forEach(this.insertRule, this);
this.queue = undefined;
}
}
return rule;
}
// We can't add rules to a detached style node.
// We will redeploy the sheet once user will attach it.
this.deployed = false;
return rule;
}
/**
* Insert rule into the StyleSheet
*/
}, {
key: 'insertRule',
value: function insertRule(rule) {
var renderable = this.renderer.insertRule(rule);
if (renderable && this.options.link) (0, _linkRule2['default'])(rule, renderable);
}
/**
* Create and add rules.
* Will render also after Style Sheet was rendered the first time.
*/
}, {
key: 'addRules',
value: function addRules(styles, options) {
var added = [];
for (var name in styles) {
added.push(this.addRule(name, styles[name], options));
}
return added;
}
/**
* Get a rule by name.
*/
}, {
key: 'getRule',
value: function getRule(name) {
return this.rules.get(name);
}
/**
* Delete a rule by name.
* Returns `true`: if rule has been deleted from the DOM.
*/
}, {
key: 'deleteRule',
value: function deleteRule(name) {
var rule = this.rules.get(name);
if (!rule) return false;
this.rules.remove(rule);
if (this.attached && rule.renderable) {
return this.renderer.deleteRule(rule.renderable);
}
return true;
}
/**
* Get index of a rule.
*/
}, {
key: 'indexOf',
value: function indexOf(rule) {
return this.rules.indexOf(rule);
}
/**
* Deploy pure CSS string to a renderable.
*/
}, {
key: 'deploy',
value: function deploy() {
this.renderer.deploy();
this.deployed = true;
return this;
}
/**
* Link renderable CSS rules from sheet with their corresponding models.
*/
}, {
key: 'link',
value: function link() {
var cssRules = this.renderer.getRules();
// Is undefined when VirtualRenderer is used.
if (cssRules) this.rules.link(cssRules);
this.linked = true;
return this;
}
/**
* Update the function values with a new data.
*/
}, {
key: 'update',
value: function update(name, data) {
this.rules.update(name, data);
return this;
}
/**
* Convert rules to a CSS string.
*/
}, {
key: 'toString',
value: function toString(options) {
return this.rules.toString(options);
}
}]);
return StyleSheet;
}();
exports['default'] = StyleSheet;

View File

@@ -0,0 +1,197 @@
/* @flow */
import linkRule from './utils/linkRule'
import RuleList from './RuleList'
import type {
InternalStyleSheetOptions,
Rule,
ToCssOptions,
RuleOptions,
StyleSheetOptions,
JssStyle
} from './types'
export default class StyleSheet {
options: InternalStyleSheetOptions
linked: boolean
deployed: boolean
attached: boolean
rules: RuleList
renderer: Object
classes: Object
queue: ?Array<Rule>
constructor(styles: Object, options: StyleSheetOptions) {
this.attached = false
this.deployed = false
this.linked = false
this.classes = {}
this.options = {
...options,
sheet: this,
parent: this,
classes: this.classes
}
this.renderer = new options.Renderer(this)
this.rules = new RuleList(this.options)
for (const name in styles) {
this.rules.add(name, styles[name])
}
this.rules.process()
}
/**
* Attach renderable to the render tree.
*/
attach(): this {
if (this.attached) return this
if (!this.deployed) this.deploy()
this.renderer.attach()
if (!this.linked && this.options.link) this.link()
this.attached = true
return this
}
/**
* Remove renderable from render tree.
*/
detach(): this {
if (!this.attached) return this
this.renderer.detach()
this.attached = false
return this
}
/**
* Add a rule to the current stylesheet.
* Will insert a rule also after the stylesheet has been rendered first time.
*/
addRule(name: string, decl: JssStyle, options?: RuleOptions): Rule {
const {queue} = this
// Plugins can create rules.
// In order to preserve the right order, we need to queue all `.addRule` calls,
// which happen after the first `rules.add()` call.
if (this.attached && !queue) this.queue = []
const rule = this.rules.add(name, decl, options)
this.options.jss.plugins.onProcessRule(rule)
if (this.attached) {
if (!this.deployed) return rule
// Don't insert rule directly if there is no stringified version yet.
// It will be inserted all together when .attach is called.
if (queue) queue.push(rule)
else {
this.insertRule(rule)
if (this.queue) {
this.queue.forEach(this.insertRule, this)
this.queue = undefined
}
}
return rule
}
// We can't add rules to a detached style node.
// We will redeploy the sheet once user will attach it.
this.deployed = false
return rule
}
/**
* Insert rule into the StyleSheet
*/
insertRule(rule: Rule) {
const renderable = this.renderer.insertRule(rule)
if (renderable && this.options.link) linkRule(rule, renderable)
}
/**
* Create and add rules.
* Will render also after Style Sheet was rendered the first time.
*/
addRules(styles: Object, options?: RuleOptions): Array<Rule> {
const added = []
for (const name in styles) {
added.push(this.addRule(name, styles[name], options))
}
return added
}
/**
* Get a rule by name.
*/
getRule(name: string): Rule {
return this.rules.get(name)
}
/**
* Delete a rule by name.
* Returns `true`: if rule has been deleted from the DOM.
*/
deleteRule(name: string): boolean {
const rule = this.rules.get(name)
if (!rule) return false
this.rules.remove(rule)
if (this.attached && rule.renderable) {
return this.renderer.deleteRule(rule.renderable)
}
return true
}
/**
* Get index of a rule.
*/
indexOf(rule: Rule): number {
return this.rules.indexOf(rule)
}
/**
* Deploy pure CSS string to a renderable.
*/
deploy(): this {
this.renderer.deploy()
this.deployed = true
return this
}
/**
* Link renderable CSS rules from sheet with their corresponding models.
*/
link(): this {
const cssRules = this.renderer.getRules()
// Is undefined when VirtualRenderer is used.
if (cssRules) this.rules.link(cssRules)
this.linked = true
return this
}
/**
* Update the function values with a new data.
*/
update(name?: string, data?: Object): this {
this.rules.update(name, data)
return this
}
/**
* Convert rules to a CSS string.
*/
toString(options?: ToCssOptions): string {
return this.rules.toString(options)
}
}

View File

@@ -0,0 +1,69 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.create = exports.sheets = exports.RuleList = exports.SheetsManager = exports.SheetsRegistry = exports.getDynamicStyles = undefined;
var _getDynamicStyles = require('./utils/getDynamicStyles');
Object.defineProperty(exports, 'getDynamicStyles', {
enumerable: true,
get: function get() {
return _interopRequireDefault(_getDynamicStyles)['default'];
}
});
var _SheetsRegistry = require('./SheetsRegistry');
Object.defineProperty(exports, 'SheetsRegistry', {
enumerable: true,
get: function get() {
return _interopRequireDefault(_SheetsRegistry)['default'];
}
});
var _SheetsManager = require('./SheetsManager');
Object.defineProperty(exports, 'SheetsManager', {
enumerable: true,
get: function get() {
return _interopRequireDefault(_SheetsManager)['default'];
}
});
var _RuleList = require('./RuleList');
Object.defineProperty(exports, 'RuleList', {
enumerable: true,
get: function get() {
return _interopRequireDefault(_RuleList)['default'];
}
});
var _sheets = require('./sheets');
Object.defineProperty(exports, 'sheets', {
enumerable: true,
get: function get() {
return _interopRequireDefault(_sheets)['default'];
}
});
var _Jss = require('./Jss');
var _Jss2 = _interopRequireDefault(_Jss);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
/**
* Creates a new instance of Jss.
*/
var create = exports.create = function create(options) {
return new _Jss2['default'](options);
};
/**
* A global Jss instance.
*/
exports['default'] = create();

View File

@@ -0,0 +1,45 @@
/* @flow */
/**
* A better abstraction over CSS.
*
* @copyright Oleg Slobodskoi 2014-present
* @website https://github.com/cssinjs/jss
* @license MIT
*/
import Jss from './Jss'
import type {JssOptions} from './types'
/**
* Extracts a styles object with only rules that contain function values.
*/
export {default as getDynamicStyles} from './utils/getDynamicStyles'
/**
* SheetsRegistry for SSR.
*/
export {default as SheetsRegistry} from './SheetsRegistry'
/**
* SheetsManager for react-jss and co.
*/
export {default as SheetsManager} from './SheetsManager'
/**
* RuleList for plugins.
*/
export {default as RuleList} from './RuleList'
/**
* Default global SheetsRegistry instance.
*/
export {default as sheets} from './sheets'
/**
* Creates a new instance of Jss.
*/
export const create = (options?: JssOptions): Jss => new Jss(options)
/**
* A global Jss instance.
*/
export default create()

View File

@@ -0,0 +1,51 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _SimpleRule = require('../rules/SimpleRule');
var _SimpleRule2 = _interopRequireDefault(_SimpleRule);
var _KeyframesRule = require('../rules/KeyframesRule');
var _KeyframesRule2 = _interopRequireDefault(_KeyframesRule);
var _ConditionalRule = require('../rules/ConditionalRule');
var _ConditionalRule2 = _interopRequireDefault(_ConditionalRule);
var _FontFaceRule = require('../rules/FontFaceRule');
var _FontFaceRule2 = _interopRequireDefault(_FontFaceRule);
var _ViewportRule = require('../rules/ViewportRule');
var _ViewportRule2 = _interopRequireDefault(_ViewportRule);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var classes = {
'@charset': _SimpleRule2['default'],
'@import': _SimpleRule2['default'],
'@namespace': _SimpleRule2['default'],
'@keyframes': _KeyframesRule2['default'],
'@media': _ConditionalRule2['default'],
'@supports': _ConditionalRule2['default'],
'@font-face': _FontFaceRule2['default'],
'@viewport': _ViewportRule2['default'],
'@-ms-viewport': _ViewportRule2['default']
/**
* Generate plugins which will register all rules.
*/
};
exports['default'] = Object.keys(classes).map(function (key) {
// https://jsperf.com/indexof-vs-substr-vs-regex-at-the-beginning-3
var re = new RegExp('^' + key);
var onCreateRule = function onCreateRule(name, decl, options) {
return re.test(name) ? new classes[key](name, decl, options) : null;
};
return { onCreateRule: onCreateRule };
});

View File

@@ -0,0 +1,31 @@
/* @flow */
import SimpleRule from '../rules/SimpleRule'
import KeyframesRule from '../rules/KeyframesRule'
import ConditionalRule from '../rules/ConditionalRule'
import FontFaceRule from '../rules/FontFaceRule'
import ViewportRule from '../rules/ViewportRule'
import type {Plugin, RuleOptions, Rule, JssStyle} from '../types'
const classes = {
'@charset': SimpleRule,
'@import': SimpleRule,
'@namespace': SimpleRule,
'@keyframes': KeyframesRule,
'@media': ConditionalRule,
'@supports': ConditionalRule,
'@font-face': FontFaceRule,
'@viewport': ViewportRule,
'@-ms-viewport': ViewportRule
}
/**
* Generate plugins which will register all rules.
*/
export default Object.keys(classes).map((key: string): Plugin => {
// https://jsperf.com/indexof-vs-substr-vs-regex-at-the-beginning-3
const re = new RegExp(`^${key}`)
const onCreateRule = (name: string, decl: JssStyle, options: RuleOptions): Rule|null => (
re.test(name) ? new classes[key](name, decl, options) : null
)
return {onCreateRule}
})

View File

@@ -0,0 +1,333 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _warning = require('warning');
var _warning2 = _interopRequireDefault(_warning);
var _sheets = require('../sheets');
var _sheets2 = _interopRequireDefault(_sheets);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Get a style property.
*/
function getStyle(rule, prop) {
try {
return rule.style.getPropertyValue(prop);
} catch (err) {
// IE may throw if property is unknown.
return '';
}
}
/**
* Set a style property.
*/
function setStyle(rule, prop, value) {
try {
rule.style.setProperty(prop, value);
} catch (err) {
// IE may throw if property is unknown.
return false;
}
return true;
}
function extractSelector(cssText) {
var from = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
return cssText.substr(from, cssText.indexOf('{') - 1);
}
var CSSRuleTypes = {
STYLE_RULE: 1,
KEYFRAMES_RULE: 7
/**
* Get the selector.
*/
};function getSelector(rule) {
if (rule.type === CSSRuleTypes.STYLE_RULE) return rule.selectorText;
if (rule.type === CSSRuleTypes.KEYFRAMES_RULE) {
var name = rule.name;
if (name) return '@keyframes ' + name;
// There is no rule.name in the following browsers:
// - IE 9
// - Safari 7.1.8
// - Mobile Safari 9.0.0
var cssText = rule.cssText;
return '@' + extractSelector(cssText, cssText.indexOf('keyframes'));
}
return extractSelector(rule.cssText);
}
/**
* Set the selector.
*/
function setSelector(rule, selectorText) {
rule.selectorText = selectorText;
// Return false if setter was not successful.
// Currently works in chrome only.
return rule.selectorText === selectorText;
}
/**
* Gets the `head` element upon the first call and caches it.
*/
var getHead = function () {
var head = void 0;
return function () {
if (!head) head = document.head || document.getElementsByTagName('head')[0];
return head;
};
}();
/**
* Find attached sheet with an index higher than the passed one.
*/
function findHigherSheet(registry, options) {
for (var i = 0; i < registry.length; i++) {
var sheet = registry[i];
if (sheet.attached && sheet.options.index > options.index && sheet.options.insertionPoint === options.insertionPoint) {
return sheet;
}
}
return null;
}
/**
* Find attached sheet with the highest index.
*/
function findHighestSheet(registry, options) {
for (var i = registry.length - 1; i >= 0; i--) {
var sheet = registry[i];
if (sheet.attached && sheet.options.insertionPoint === options.insertionPoint) {
return sheet;
}
}
return null;
}
/**
* Find a comment with "jss" inside.
*/
function findCommentNode(text) {
var head = getHead();
for (var i = 0; i < head.childNodes.length; i++) {
var node = head.childNodes[i];
if (node.nodeType === 8 && node.nodeValue.trim() === text) {
return node;
}
}
return null;
}
/**
* Find a node before which we can insert the sheet.
*/
function findPrevNode(options) {
var registry = _sheets2['default'].registry;
if (registry.length > 0) {
// Try to insert before the next higher sheet.
var sheet = findHigherSheet(registry, options);
if (sheet) return sheet.renderer.element;
// Otherwise insert after the last attached.
sheet = findHighestSheet(registry, options);
if (sheet) return sheet.renderer.element.nextElementSibling;
}
// Try to find a comment placeholder if registry is empty.
var insertionPoint = options.insertionPoint;
if (insertionPoint && typeof insertionPoint === 'string') {
var comment = findCommentNode(insertionPoint);
if (comment) return comment.nextSibling;
// If user specifies an insertion point and it can't be found in the document -
// bad specificity issues may appear.
(0, _warning2['default'])(insertionPoint === 'jss', '[JSS] Insertion point "%s" not found.', insertionPoint);
}
return null;
}
/**
* Insert style element into the DOM.
*/
function insertStyle(style, options) {
var insertionPoint = options.insertionPoint;
var prevNode = findPrevNode(options);
if (prevNode) {
var parentNode = prevNode.parentNode;
if (parentNode) parentNode.insertBefore(style, prevNode);
return;
}
// Works with iframes and any node types.
if (insertionPoint && typeof insertionPoint.nodeType === 'number') {
// https://stackoverflow.com/questions/41328728/force-casting-in-flow
var insertionPointElement = insertionPoint;
var _parentNode = insertionPointElement.parentNode;
if (_parentNode) _parentNode.insertBefore(style, insertionPointElement.nextSibling);else (0, _warning2['default'])(false, '[JSS] Insertion point is not in the DOM.');
return;
}
getHead().insertBefore(style, prevNode);
}
var DomRenderer = function () {
function DomRenderer(sheet) {
_classCallCheck(this, DomRenderer);
this.getStyle = getStyle;
this.setStyle = setStyle;
this.setSelector = setSelector;
this.getSelector = getSelector;
this.hasInsertedRules = false;
// There is no sheet when the renderer is used from a standalone StyleRule.
if (sheet) _sheets2['default'].add(sheet);
this.sheet = sheet;
var _ref = this.sheet ? this.sheet.options : {},
media = _ref.media,
meta = _ref.meta,
element = _ref.element;
this.element = element || document.createElement('style');
this.element.type = 'text/css';
this.element.setAttribute('data-jss', '');
if (media) this.element.setAttribute('media', media);
if (meta) this.element.setAttribute('data-meta', meta);
}
/**
* Insert style element into render tree.
*/
// HTMLStyleElement needs fixing https://github.com/facebook/flow/issues/2696
_createClass(DomRenderer, [{
key: 'attach',
value: function attach() {
// In the case the element node is external and it is already in the DOM.
if (this.element.parentNode || !this.sheet) return;
// When rules are inserted using `insertRule` API, after `sheet.detach().attach()`
// browsers remove those rules.
// TODO figure out if its a bug and if it is known.
// Workaround is to redeploy the sheet before attaching as a string.
if (this.hasInsertedRules) {
this.deploy();
this.hasInsertedRules = false;
}
insertStyle(this.element, this.sheet.options);
}
/**
* Remove style element from render tree.
*/
}, {
key: 'detach',
value: function detach() {
this.element.parentNode.removeChild(this.element);
}
/**
* Inject CSS string into element.
*/
}, {
key: 'deploy',
value: function deploy() {
if (!this.sheet) return;
this.element.textContent = '\n' + this.sheet.toString() + '\n';
}
/**
* Insert a rule into element.
*/
}, {
key: 'insertRule',
value: function insertRule(rule) {
var sheet = this.element.sheet;
var cssRules = sheet.cssRules;
var index = cssRules.length;
var str = rule.toString();
if (!str) return false;
try {
sheet.insertRule(str, index);
} catch (err) {
(0, _warning2['default'])(false, '[JSS] Can not insert an unsupported rule \n\r%s', rule);
return false;
}
this.hasInsertedRules = true;
return cssRules[index];
}
/**
* Delete a rule.
*/
}, {
key: 'deleteRule',
value: function deleteRule(rule) {
var sheet = this.element.sheet;
var cssRules = sheet.cssRules;
for (var _index = 0; _index < cssRules.length; _index++) {
if (rule === cssRules[_index]) {
sheet.deleteRule(_index);
return true;
}
}
return false;
}
/**
* Get all rules elements.
*/
}, {
key: 'getRules',
value: function getRules() {
return this.element.sheet.cssRules;
}
}]);
return DomRenderer;
}();
exports['default'] = DomRenderer;

View File

@@ -0,0 +1,297 @@
/* @flow */
import warning from 'warning'
import sheets from '../sheets'
import type StyleSheet from '../StyleSheet'
import type {Rule, InsertionPoint} from '../types'
type PriorityOptions = {
index: number,
insertionPoint?: InsertionPoint
}
/**
* Get a style property.
*/
function getStyle(rule: HTMLElement|CSSStyleRule, prop: string): string {
try {
return rule.style.getPropertyValue(prop)
}
catch (err) {
// IE may throw if property is unknown.
return ''
}
}
/**
* Set a style property.
*/
function setStyle(rule: HTMLElement|CSSStyleRule, prop: string, value: string): boolean {
try {
rule.style.setProperty(prop, value)
}
catch (err) {
// IE may throw if property is unknown.
return false
}
return true
}
function extractSelector(cssText: string, from: number = 0) {
return cssText.substr(from, cssText.indexOf('{') - 1)
}
const CSSRuleTypes = {
STYLE_RULE: 1,
KEYFRAMES_RULE: 7
}
/**
* Get the selector.
*/
function getSelector(rule: CSSOMRule): string {
if (rule.type === CSSRuleTypes.STYLE_RULE) return rule.selectorText
if (rule.type === CSSRuleTypes.KEYFRAMES_RULE) {
const {name} = rule
if (name) return `@keyframes ${name}`
// There is no rule.name in the following browsers:
// - IE 9
// - Safari 7.1.8
// - Mobile Safari 9.0.0
const {cssText} = rule
return `@${extractSelector(cssText, cssText.indexOf('keyframes'))}`
}
return extractSelector(rule.cssText)
}
/**
* Set the selector.
*/
function setSelector(rule: CSSStyleRule, selectorText: string): boolean {
rule.selectorText = selectorText
// Return false if setter was not successful.
// Currently works in chrome only.
return rule.selectorText === selectorText
}
/**
* Gets the `head` element upon the first call and caches it.
*/
const getHead = (() => {
let head
return (): HTMLElement => {
if (!head) head = document.head || document.getElementsByTagName('head')[0]
return head
}
})()
/**
* Find attached sheet with an index higher than the passed one.
*/
function findHigherSheet(registry: Array<StyleSheet>, options: PriorityOptions): StyleSheet|null {
for (let i = 0; i < registry.length; i++) {
const sheet = registry[i]
if (
sheet.attached &&
sheet.options.index > options.index &&
sheet.options.insertionPoint === options.insertionPoint
) {
return sheet
}
}
return null
}
/**
* Find attached sheet with the highest index.
*/
function findHighestSheet(registry: Array<StyleSheet>, options: PriorityOptions): StyleSheet|null {
for (let i = registry.length - 1; i >= 0; i--) {
const sheet = registry[i]
if (sheet.attached && sheet.options.insertionPoint === options.insertionPoint) {
return sheet
}
}
return null
}
/**
* Find a comment with "jss" inside.
*/
function findCommentNode(text: string): Comment|null {
const head = getHead()
for (let i = 0; i < head.childNodes.length; i++) {
const node = head.childNodes[i]
if (node.nodeType === 8 && node.nodeValue.trim() === text) {
return node
}
}
return null
}
/**
* Find a node before which we can insert the sheet.
*/
function findPrevNode(options: PriorityOptions): ?Node|null {
const {registry} = sheets
if (registry.length > 0) {
// Try to insert before the next higher sheet.
let sheet = findHigherSheet(registry, options)
if (sheet) return sheet.renderer.element
// Otherwise insert after the last attached.
sheet = findHighestSheet(registry, options)
if (sheet) return sheet.renderer.element.nextElementSibling
}
// Try to find a comment placeholder if registry is empty.
const {insertionPoint} = options
if (insertionPoint && typeof insertionPoint === 'string') {
const comment = findCommentNode(insertionPoint)
if (comment) return comment.nextSibling
// If user specifies an insertion point and it can't be found in the document -
// bad specificity issues may appear.
warning(insertionPoint === 'jss', '[JSS] Insertion point "%s" not found.', insertionPoint)
}
return null
}
/**
* Insert style element into the DOM.
*/
function insertStyle(style: HTMLElement, options: PriorityOptions) {
const {insertionPoint} = options
const prevNode = findPrevNode(options)
if (prevNode) {
const {parentNode} = prevNode
if (parentNode) parentNode.insertBefore(style, prevNode)
return
}
// Works with iframes and any node types.
if (insertionPoint && typeof insertionPoint.nodeType === 'number') {
// https://stackoverflow.com/questions/41328728/force-casting-in-flow
const insertionPointElement: HTMLElement = (insertionPoint: any)
const {parentNode} = insertionPointElement
if (parentNode) parentNode.insertBefore(style, insertionPointElement.nextSibling)
else warning(false, '[JSS] Insertion point is not in the DOM.')
return
}
getHead().insertBefore(style, prevNode)
}
export default class DomRenderer {
getStyle = getStyle
setStyle = setStyle
setSelector = setSelector
getSelector = getSelector
// HTMLStyleElement needs fixing https://github.com/facebook/flow/issues/2696
element: any
sheet: ?StyleSheet
hasInsertedRules: boolean = false
constructor(sheet?: StyleSheet) {
// There is no sheet when the renderer is used from a standalone StyleRule.
if (sheet) sheets.add(sheet)
this.sheet = sheet
const {media, meta, element} = (this.sheet ? this.sheet.options : {})
this.element = element || document.createElement('style')
this.element.type = 'text/css'
this.element.setAttribute('data-jss', '')
if (media) this.element.setAttribute('media', media)
if (meta) this.element.setAttribute('data-meta', meta)
}
/**
* Insert style element into render tree.
*/
attach(): void {
// In the case the element node is external and it is already in the DOM.
if (this.element.parentNode || !this.sheet) return
// When rules are inserted using `insertRule` API, after `sheet.detach().attach()`
// browsers remove those rules.
// TODO figure out if its a bug and if it is known.
// Workaround is to redeploy the sheet before attaching as a string.
if (this.hasInsertedRules) {
this.deploy()
this.hasInsertedRules = false
}
insertStyle(this.element, this.sheet.options)
}
/**
* Remove style element from render tree.
*/
detach(): void {
this.element.parentNode.removeChild(this.element)
}
/**
* Inject CSS string into element.
*/
deploy(): void {
if (!this.sheet) return
this.element.textContent = `\n${this.sheet.toString()}\n`
}
/**
* Insert a rule into element.
*/
insertRule(rule: Rule): false|CSSStyleRule {
const {sheet} = this.element
const {cssRules} = sheet
const index = cssRules.length
const str = rule.toString()
if (!str) return false
try {
sheet.insertRule(str, index)
}
catch (err) {
warning(false, '[JSS] Can not insert an unsupported rule \n\r%s', rule)
return false
}
this.hasInsertedRules = true
return cssRules[index]
}
/**
* Delete a rule.
*/
deleteRule(rule: CSSStyleRule): boolean {
const {sheet} = this.element
const {cssRules} = sheet
for (let index = 0; index < cssRules.length; index++) {
if (rule === cssRules[index]) {
sheet.deleteRule(index)
return true
}
}
return false
}
/**
* Get all rules elements.
*/
getRules(): CSSRuleList {
return this.element.sheet.cssRules
}
}

View File

@@ -0,0 +1,68 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/* eslint-disable class-methods-use-this */
/**
* Rendering backend to do nothing in nodejs.
*/
var VirtualRenderer = function () {
function VirtualRenderer() {
_classCallCheck(this, VirtualRenderer);
}
_createClass(VirtualRenderer, [{
key: 'setStyle',
value: function setStyle() {
return true;
}
}, {
key: 'getStyle',
value: function getStyle() {
return '';
}
}, {
key: 'setSelector',
value: function setSelector() {
return true;
}
}, {
key: 'getSelector',
value: function getSelector() {
return '';
}
}, {
key: 'attach',
value: function attach() {}
}, {
key: 'detach',
value: function detach() {}
}, {
key: 'deploy',
value: function deploy() {}
}, {
key: 'insertRule',
value: function insertRule() {
return false;
}
}, {
key: 'deleteRule',
value: function deleteRule() {
return true;
}
}, {
key: 'getRules',
value: function getRules() {}
}]);
return VirtualRenderer;
}();
exports['default'] = VirtualRenderer;

View File

@@ -0,0 +1,30 @@
/* @flow */
/* eslint-disable class-methods-use-this */
/**
* Rendering backend to do nothing in nodejs.
*/
export default class VirtualRenderer {
setStyle() {
return true
}
getStyle() {
return ''
}
setSelector() {
return true
}
getSelector() {
return ''
}
attach() {}
detach() {}
deploy() {}
insertRule() {
return false
}
deleteRule() {
return true
}
getRules() {}
}

View File

@@ -0,0 +1,90 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _RuleList = require('../RuleList');
var _RuleList2 = _interopRequireDefault(_RuleList);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Conditional rule for @media, @supports
*/
var ConditionalRule = function () {
function ConditionalRule(key, styles, options) {
_classCallCheck(this, ConditionalRule);
this.type = 'conditional';
this.isProcessed = false;
this.key = key;
this.options = options;
this.rules = new _RuleList2['default'](_extends({}, options, { parent: this }));
for (var name in styles) {
this.rules.add(name, styles[name]);
}
this.rules.process();
}
/**
* Get a rule.
*/
_createClass(ConditionalRule, [{
key: 'getRule',
value: function getRule(name) {
return this.rules.get(name);
}
/**
* Get index of a rule.
*/
}, {
key: 'indexOf',
value: function indexOf(rule) {
return this.rules.indexOf(rule);
}
/**
* Create and register rule, run plugins.
*/
}, {
key: 'addRule',
value: function addRule(name, style, options) {
var rule = this.rules.add(name, style, options);
this.options.jss.plugins.onProcessRule(rule);
return rule;
}
/**
* Generates a CSS string.
*/
}, {
key: 'toString',
value: function toString() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { indent: 1 };
var inner = this.rules.toString(options);
return inner ? this.key + ' {\n' + inner + '\n}' : '';
}
}]);
return ConditionalRule;
}();
exports['default'] = ConditionalRule;

View File

@@ -0,0 +1,63 @@
/* @flow */
import RuleList from '../RuleList'
import type {Rule, RuleOptions, ToCssOptions, JssStyle, BaseRule} from '../types'
/**
* Conditional rule for @media, @supports
*/
export default class ConditionalRule implements BaseRule {
type = 'conditional'
key: string
rules: RuleList
options: RuleOptions
isProcessed: boolean = false
renderable: ?CSSStyleRule
constructor(key: string, styles: Object, options: RuleOptions) {
this.key = key
this.options = options
this.rules = new RuleList({...options, parent: this})
for (const name in styles) {
this.rules.add(name, styles[name])
}
this.rules.process()
}
/**
* Get a rule.
*/
getRule(name: string): Rule {
return this.rules.get(name)
}
/**
* Get index of a rule.
*/
indexOf(rule: Rule): number {
return this.rules.indexOf(rule)
}
/**
* Create and register rule, run plugins.
*/
addRule(name: string, style: JssStyle, options?: RuleOptions): Rule {
const rule = this.rules.add(name, style, options)
this.options.jss.plugins.onProcessRule(rule)
return rule
}
/**
* Generates a CSS string.
*/
toString(options?: ToCssOptions = {indent: 1}): string {
const inner = this.rules.toString(options)
return inner ? `${this.key} {\n${inner}\n}` : ''
}
}

View File

@@ -0,0 +1,53 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _toCss = require('../utils/toCss');
var _toCss2 = _interopRequireDefault(_toCss);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var FontFaceRule = function () {
function FontFaceRule(key, style, options) {
_classCallCheck(this, FontFaceRule);
this.type = 'font-face';
this.isProcessed = false;
this.key = key;
this.style = style;
this.options = options;
}
/**
* Generates a CSS string.
*/
_createClass(FontFaceRule, [{
key: 'toString',
value: function toString(options) {
if (Array.isArray(this.style)) {
var str = '';
for (var index = 0; index < this.style.length; index++) {
str += (0, _toCss2['default'])(this.key, this.style[index]);
if (this.style[index + 1]) str += '\n';
}
return str;
}
return (0, _toCss2['default'])(this.key, this.style, options);
}
}]);
return FontFaceRule;
}();
exports['default'] = FontFaceRule;

View File

@@ -0,0 +1,39 @@
/* @flow */
import toCss from '../utils/toCss'
import type {RuleOptions, JssStyle, ToCssOptions, BaseRule} from '../types'
export default class FontFaceRule implements BaseRule {
type = 'font-face'
key: string
style: JssStyle
options: RuleOptions
isProcessed: boolean = false
renderable: ?CSSStyleRule
constructor(key: string, style: JssStyle, options: RuleOptions) {
this.key = key
this.style = style
this.options = options
}
/**
* Generates a CSS string.
*/
toString(options?: ToCssOptions): string {
if (Array.isArray(this.style)) {
let str = ''
for (let index = 0; index < this.style.length; index++) {
str += toCss(this.key, this.style[index])
if (this.style[index + 1]) str += '\n'
}
return str
}
return toCss(this.key, this.style, options)
}
}

View File

@@ -0,0 +1,62 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _RuleList = require('../RuleList');
var _RuleList2 = _interopRequireDefault(_RuleList);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Rule for @keyframes
*/
var KeyframesRule = function () {
function KeyframesRule(key, frames, options) {
_classCallCheck(this, KeyframesRule);
this.type = 'keyframes';
this.isProcessed = false;
this.key = key;
this.options = options;
this.rules = new _RuleList2['default'](_extends({}, options, { parent: this }));
for (var name in frames) {
this.rules.add(name, frames[name], _extends({}, this.options, {
parent: this,
selector: name
}));
}
this.rules.process();
}
/**
* Generates a CSS string.
*/
_createClass(KeyframesRule, [{
key: 'toString',
value: function toString() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { indent: 1 };
var inner = this.rules.toString(options);
if (inner) inner += '\n';
return this.key + ' {\n' + inner + '}';
}
}]);
return KeyframesRule;
}();
exports['default'] = KeyframesRule;

View File

@@ -0,0 +1,45 @@
/* @flow */
import RuleList from '../RuleList'
import type {RuleOptions, ToCssOptions, BaseRule} from '../types'
/**
* Rule for @keyframes
*/
export default class KeyframesRule implements BaseRule {
type = 'keyframes'
key: string
rules: RuleList
options: RuleOptions
isProcessed: boolean = false
renderable: ?CSSStyleRule
constructor(key: string, frames: Object, options: RuleOptions) {
this.key = key
this.options = options
this.rules = new RuleList({...options, parent: this})
for (const name in frames) {
this.rules.add(name, frames[name], {
...this.options,
parent: this,
selector: name
})
}
this.rules.process()
}
/**
* Generates a CSS string.
*/
toString(options?: ToCssOptions = {indent: 1}): string {
let inner = this.rules.toString(options)
if (inner) inner += '\n'
return `${this.key} {\n${inner}}`
}
}

View File

@@ -0,0 +1,48 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var SimpleRule = function () {
function SimpleRule(key, value, options) {
_classCallCheck(this, SimpleRule);
this.type = 'simple';
this.isProcessed = false;
this.key = key;
this.value = value;
this.options = options;
}
/**
* Generates a CSS string.
*/
// eslint-disable-next-line no-unused-vars
_createClass(SimpleRule, [{
key: 'toString',
value: function toString(options) {
if (Array.isArray(this.value)) {
var str = '';
for (var index = 0; index < this.value.length; index++) {
str += this.key + ' ' + this.value[index] + ';';
if (this.value[index + 1]) str += '\n';
}
return str;
}
return this.key + ' ' + this.value + ';';
}
}]);
return SimpleRule;
}();
exports['default'] = SimpleRule;

View File

@@ -0,0 +1,39 @@
/* @flow */
import type {RuleOptions, ToCssOptions, BaseRule} from '../types'
export default class SimpleRule implements BaseRule {
type = 'simple'
key: string
value: string
options: RuleOptions
isProcessed: boolean = false
renderable: ?CSSStyleRule
constructor(key: string, value: string, options: RuleOptions) {
this.key = key
this.value = value
this.options = options
}
/**
* Generates a CSS string.
*/
// eslint-disable-next-line no-unused-vars
toString(options?: ToCssOptions): string {
if (Array.isArray(this.value)) {
let str = ''
for (let index = 0; index < this.value.length; index++) {
str += `${this.key} ${this.value[index]};`
if (this.value[index + 1]) str += '\n'
}
return str
}
return `${this.key} ${this.value};`
}
}

View File

@@ -0,0 +1,177 @@
'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; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _toCss = require('../utils/toCss');
var _toCss2 = _interopRequireDefault(_toCss);
var _toCssValue = require('../utils/toCssValue');
var _toCssValue2 = _interopRequireDefault(_toCssValue);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var StyleRule = function () {
function StyleRule(key, style, options) {
_classCallCheck(this, StyleRule);
this.type = 'style';
this.isProcessed = false;
var generateClassName = options.generateClassName,
sheet = options.sheet,
Renderer = options.Renderer,
selector = options.selector;
this.key = key;
this.options = options;
this.style = style;
this.selectorText = selector || '.' + generateClassName(this, sheet);
this.renderer = sheet ? sheet.renderer : new Renderer();
}
/**
* Set selector string.
* TODO rewrite this #419
* Attention: use this with caution. Most browsers didn't implement
* selectorText setter, so this may result in rerendering of entire Style Sheet.
*/
_createClass(StyleRule, [{
key: 'prop',
/**
* Get or set a style property.
*/
value: function prop(name, nextValue) {
var $name = typeof this.style[name] === 'function' ? '$' + name : name;
var currValue = this.style[$name];
// Its a setter.
if (nextValue != null) {
// Don't do anything if the value has not changed.
if (currValue !== nextValue) {
nextValue = this.options.jss.plugins.onChangeValue(nextValue, name, this);
Object.defineProperty(this.style, $name, {
value: nextValue,
writable: true
});
// Defined if StyleSheet option `link` is true.
if (this.renderable) this.renderer.setStyle(this.renderable, name, nextValue);
}
return this;
}
// Its a getter, read the value from the DOM if its not cached.
if (this.renderable && currValue == null) {
// Cache the value after we have got it from the DOM first time.
Object.defineProperty(this.style, $name, {
value: this.renderer.getStyle(this.renderable, name),
writable: true
});
}
return this.style[$name];
}
/**
* Apply rule to an element inline.
*/
}, {
key: 'applyTo',
value: function applyTo(renderable) {
var json = this.toJSON();
for (var prop in json) {
this.renderer.setStyle(renderable, prop, json[prop]);
}return this;
}
/**
* Returns JSON representation of the rule.
* Fallbacks are not supported.
* Useful for inline styles.
*/
}, {
key: 'toJSON',
value: function toJSON() {
var json = {};
for (var prop in this.style) {
var value = this.style[prop];
var type = typeof value === 'undefined' ? 'undefined' : _typeof(value);
if (type === 'function') json[prop] = this.style['$' + prop];else if (type !== 'object') json[prop] = value;else if (Array.isArray(value)) json[prop] = (0, _toCssValue2['default'])(value);
}
return json;
}
/**
* Generates a CSS string.
*/
}, {
key: 'toString',
value: function toString(options) {
return (0, _toCss2['default'])(this.selector, this.style, options);
}
}, {
key: 'selector',
set: function set(selector) {
var sheet = this.options.sheet;
// After we modify a selector, ref by old selector needs to be removed.
if (sheet) sheet.rules.unregister(this);
this.selectorText = selector;
if (!this.renderable) {
// Register the rule with new selector.
if (sheet) sheet.rules.register(this);
return;
}
var changed = this.renderer.setSelector(this.renderable, selector);
if (changed && sheet) {
sheet.rules.register(this);
return;
}
// If selector setter is not implemented, rerender the sheet.
// We need to delete renderable from the rule, because when sheet.deploy()
// calls rule.toString, it will get the old selector.
delete this.renderable;
if (sheet) {
sheet.rules.register(this);
sheet.deploy().link();
}
}
/**
* Get selector string.
*/
,
get: function get() {
if (this.renderable) {
return this.renderer.getSelector(this.renderable);
}
return this.selectorText;
}
}]);
return StyleRule;
}();
exports['default'] = StyleRule;

View File

@@ -0,0 +1,148 @@
/* @flow */
import toCss from '../utils/toCss'
import toCssValue from '../utils/toCssValue'
import type {ToCssOptions, RuleOptions, Renderer as RendererInterface, JssStyle, BaseRule} from '../types'
export default class StyleRule implements BaseRule {
type = 'style'
key: string
isProcessed: boolean = false
style: JssStyle
selectorText: string
renderer: RendererInterface
renderable: ?CSSStyleRule
options: RuleOptions
constructor(key: string, style: JssStyle, options: RuleOptions) {
const {generateClassName, sheet, Renderer, selector} = options
this.key = key
this.options = options
this.style = style
this.selectorText = selector || `.${generateClassName(this, sheet)}`
this.renderer = sheet ? sheet.renderer : new Renderer()
}
/**
* Set selector string.
* TODO rewrite this #419
* Attention: use this with caution. Most browsers didn't implement
* selectorText setter, so this may result in rerendering of entire Style Sheet.
*/
set selector(selector: string): void {
const {sheet} = this.options
// After we modify a selector, ref by old selector needs to be removed.
if (sheet) sheet.rules.unregister(this)
this.selectorText = selector
if (!this.renderable) {
// Register the rule with new selector.
if (sheet) sheet.rules.register(this)
return
}
const changed = this.renderer.setSelector(this.renderable, selector)
if (changed && sheet) {
sheet.rules.register(this)
return
}
// If selector setter is not implemented, rerender the sheet.
// We need to delete renderable from the rule, because when sheet.deploy()
// calls rule.toString, it will get the old selector.
delete this.renderable
if (sheet) {
sheet.rules.register(this)
sheet
.deploy()
.link()
}
}
/**
* Get selector string.
*/
get selector(): string {
if (this.renderable) {
return this.renderer.getSelector(this.renderable)
}
return this.selectorText
}
/**
* Get or set a style property.
*/
prop(name: string, nextValue?: string): StyleRule|string {
const $name = typeof this.style[name] === 'function' ? `$${name}` : name
const currValue = this.style[$name]
// Its a setter.
if (nextValue != null) {
// Don't do anything if the value has not changed.
if (currValue !== nextValue) {
nextValue = this.options.jss.plugins.onChangeValue(nextValue, name, this)
Object.defineProperty(this.style, $name, {
value: nextValue,
writable: true
})
// Defined if StyleSheet option `link` is true.
if (this.renderable) this.renderer.setStyle(this.renderable, name, nextValue)
}
return this
}
// Its a getter, read the value from the DOM if its not cached.
if (this.renderable && currValue == null) {
// Cache the value after we have got it from the DOM first time.
Object.defineProperty(this.style, $name, {
value: this.renderer.getStyle(this.renderable, name),
writable: true
})
}
return this.style[$name]
}
/**
* Apply rule to an element inline.
*/
applyTo(renderable: HTMLElement): this {
const json = this.toJSON()
for (const prop in json) this.renderer.setStyle(renderable, prop, json[prop])
return this
}
/**
* Returns JSON representation of the rule.
* Fallbacks are not supported.
* Useful for inline styles.
*/
toJSON(): Object {
const json = {}
for (const prop in this.style) {
const value = this.style[prop]
const type = typeof value
if (type === 'function') json[prop] = this.style[`$${prop}`]
else if (type !== 'object') json[prop] = value
else if (Array.isArray(value)) json[prop] = toCssValue(value)
}
return json
}
/**
* Generates a CSS string.
*/
toString(options?: ToCssOptions): string {
return toCss(this.selector, this.style, options)
}
}

View File

@@ -0,0 +1,44 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _toCss = require('../utils/toCss');
var _toCss2 = _interopRequireDefault(_toCss);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var ViewportRule = function () {
function ViewportRule(key, style, options) {
_classCallCheck(this, ViewportRule);
this.type = 'viewport';
this.isProcessed = false;
this.key = key;
this.style = style;
this.options = options;
}
/**
* Generates a CSS string.
*/
_createClass(ViewportRule, [{
key: 'toString',
value: function toString(options) {
return (0, _toCss2['default'])(this.key, this.style, options);
}
}]);
return ViewportRule;
}();
exports['default'] = ViewportRule;

View File

@@ -0,0 +1,30 @@
/* @flow */
import toCss from '../utils/toCss'
import type {RuleOptions, JssStyle, ToCssOptions, BaseRule} from '../types'
export default class ViewportRule implements BaseRule {
type = 'viewport'
key: string
style: JssStyle
options: RuleOptions
isProcessed: boolean = false
renderable: ?CSSStyleRule
constructor(key: string, style: JssStyle, options: RuleOptions) {
this.key = key
this.style = style
this.options = options
}
/**
* Generates a CSS string.
*/
toString(options?: ToCssOptions): string {
return toCss(this.key, this.style, options)
}
}

View File

@@ -0,0 +1,19 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _SheetsRegistry = require('./SheetsRegistry');
var _SheetsRegistry2 = _interopRequireDefault(_SheetsRegistry);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
/**
* This is a global sheets registry. Only DomRenderer will add sheets to it.
* On the server one should use an own SheetsRegistry instance and add the
* sheets to it, because you need to make sure to create a new registry for
* each request in order to not leak sheets across requests.
*/
exports['default'] = new _SheetsRegistry2['default']();

View File

@@ -0,0 +1,10 @@
/* @flow */
import SheetsRegistry from './SheetsRegistry'
/**
* This is a global sheets registry. Only DomRenderer will add sheets to it.
* On the server one should use an own SheetsRegistry instance and add the
* sheets to it, because you need to make sure to create a new registry for
* each request in order to not leak sheets across requests.
*/
export default new SheetsRegistry()

View File

@@ -0,0 +1,35 @@
'use strict';
var _Jss = require('./Jss');
var _Jss2 = _interopRequireDefault(_Jss);
var _StyleSheet = require('./StyleSheet');
var _StyleSheet2 = _interopRequireDefault(_StyleSheet);
var _ConditionalRule = require('./rules/ConditionalRule');
var _ConditionalRule2 = _interopRequireDefault(_ConditionalRule);
var _KeyframesRule = require('./rules/KeyframesRule');
var _KeyframesRule2 = _interopRequireDefault(_KeyframesRule);
var _StyleRule = require('./rules/StyleRule');
var _StyleRule2 = _interopRequireDefault(_StyleRule);
var _ViewportRule = require('./rules/ViewportRule');
var _ViewportRule2 = _interopRequireDefault(_ViewportRule);
var _SimpleRule = require('./rules/SimpleRule');
var _SimpleRule2 = _interopRequireDefault(_SimpleRule);
var _FontFaceRule = require('./rules/FontFaceRule');
var _FontFaceRule2 = _interopRequireDefault(_FontFaceRule);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

View File

@@ -0,0 +1,136 @@
/* @flow */
import Jss from './Jss'
import StyleSheet from './StyleSheet'
import ConditionalRule from './rules/ConditionalRule'
import KeyframesRule from './rules/KeyframesRule'
import StyleRule from './rules/StyleRule'
import ViewportRule from './rules/ViewportRule'
import SimpleRule from './rules/SimpleRule'
import FontFaceRule from './rules/FontFaceRule'
export type ToCssOptions = {
indent?: number
}
export type Rule = StyleRule|ConditionalRule|FontFaceRule|KeyframesRule|SimpleRule|ViewportRule
export type generateClassName = (rule: Rule, sheet?: StyleSheet) => string
// TODO
// Find a way to declare all types: Object|string|Array<Object>
export type JssStyle = Object
export interface Renderer {
constructor(sheet?: StyleSheet): Renderer;
setStyle(rule: HTMLElement|CSSStyleRule, prop: string, value: string): boolean;
getStyle(rule: HTMLElement|CSSStyleRule, prop: string): string;
setSelector(rule: CSSStyleRule, selectorText: string): boolean;
getSelector(rule: CSSStyleRule): string;
attach(): void;
detach(): void;
deploy(sheet: StyleSheet): void;
insertRule(rule: Rule): false|CSSStyleRule;
deleteRule(rule: CSSStyleRule): boolean;
getRules(): CSSRuleList|void;
}
export type RuleFactoryOptions = {
selector?: string,
classes?: Object,
sheet?: StyleSheet,
index?: number,
jss?: Jss,
generateClassName?: generateClassName,
Renderer?: Class<Renderer>
}
export type RuleOptions = {
selector?: string,
sheet?: StyleSheet,
index?: number,
classes: Object,
jss: Jss,
generateClassName: generateClassName,
Renderer: Class<Renderer>
}
export type RuleListOptions = {
classes: Object,
generateClassName: generateClassName,
Renderer: Class<Renderer>,
jss: Jss,
sheet: StyleSheet,
parent: ConditionalRule|KeyframesRule|StyleSheet
}
export interface BaseRule {
type: string;
key: string;
isProcessed: boolean;
options: RuleOptions;
toString(options?: ToCssOptions): string;
}
export type Plugin = {
onCreateRule?: (name: string, decl: JssStyle, options: RuleOptions) => Rule|null,
onProcessRule?: (rule: Rule, sheet?: StyleSheet) => void,
onProcessStyle?: (style: JssStyle, rule: Rule, sheet?: StyleSheet) => JssStyle,
onProcessSheet?: (sheet?: StyleSheet) => void,
onChangeValue?: (value: string, prop: string, rule: Rule) => string
}
export type InsertionPoint = string|HTMLElement
type createGenerateClassName = () => generateClassName
export type JssOptions = {
createGenerateClassName?: createGenerateClassName,
plugins?: Array<Plugin>,
insertionPoint?: InsertionPoint,
Renderer?: Class<Renderer>,
virtual?: Boolean
}
export type InternalJssOptions = {
createGenerateClassName: createGenerateClassName,
plugins?: Array<Plugin>,
insertionPoint?: InsertionPoint,
Renderer: Class<Renderer>
}
export type StyleSheetFactoryOptions = {
media?: string,
meta?: string,
index?: number,
link?: boolean,
element?: HTMLStyleElement,
generateClassName?: generateClassName
}
export type StyleSheetOptions = {
media?: string,
meta?: string,
link?: boolean,
element?: HTMLStyleElement,
index: number,
generateClassName: generateClassName,
Renderer: Class<Renderer>,
insertionPoint?: InsertionPoint,
jss: Jss
}
export type InternalStyleSheetOptions = {
media?: string,
meta?: string,
link?: boolean,
element?: HTMLStyleElement,
index: number,
insertionPoint?: InsertionPoint,
Renderer: Class<Renderer>,
generateClassName: generateClassName,
jss: Jss,
sheet: StyleSheet,
parent: ConditionalRule|KeyframesRule|StyleSheet,
classes: Object
}

View File

@@ -0,0 +1,33 @@
'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 = cloneStyle;
var isArray = Array.isArray;
function cloneStyle(style) {
// Support empty values in case user ends up with them by accident.
if (style == null) return style;
// Support string value for SimpleRule.
var typeOfStyle = typeof style === 'undefined' ? 'undefined' : _typeof(style);
if (typeOfStyle === 'string' || typeOfStyle === 'number') return style;
// Support array for FontFaceRule.
if (isArray(style)) return style.map(cloneStyle);
var newStyle = {};
for (var name in style) {
var value = style[name];
if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object') {
newStyle[name] = cloneStyle(value);
continue;
}
newStyle[name] = value;
}
return newStyle;
}

View File

@@ -0,0 +1,27 @@
import type {JssStyle} from '../types'
const {isArray} = Array
export default function cloneStyle(style: JssStyle): JssStyle {
// Support empty values in case user ends up with them by accident.
if (style == null) return style
// Support string value for SimpleRule.
const typeOfStyle = typeof style
if (typeOfStyle === 'string' || typeOfStyle === 'number') return style
// Support array for FontFaceRule.
if (isArray(style)) return style.map(cloneStyle)
const newStyle = {}
for (const name in style) {
const value = style[name]
if (typeof value === 'object') {
newStyle[name] = cloneStyle(value)
continue
}
newStyle[name] = value
}
return newStyle
}

View File

@@ -0,0 +1,27 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var globalRef = typeof window === 'undefined' ? global : window;
var namespace = '__JSS_VERSION_COUNTER__';
if (globalRef[namespace] == null) globalRef[namespace] = 0;
// In case we have more than one JSS version.
var jssCounter = globalRef[namespace]++;
/**
* Returns a function which generates unique class names based on counters.
* When new generator function is created, rule counter is reseted.
* We need to reset the rule counter for SSR for each request.
*/
exports['default'] = function () {
var ruleCounter = 0;
return function (rule) {
return rule.key + '-' + jssCounter + '-' + ruleCounter++;
};
};

View File

@@ -0,0 +1,19 @@
/* @flow */
import type {Rule, generateClassName} from '../types'
const globalRef = typeof window === 'undefined' ? global : window
const namespace = '__JSS_VERSION_COUNTER__'
if (globalRef[namespace] == null) globalRef[namespace] = 0
// In case we have more than one JSS version.
const jssCounter = globalRef[namespace]++
/**
* Returns a function which generates unique class names based on counters.
* When new generator function is created, rule counter is reseted.
* We need to reset the rule counter for SSR for each request.
*/
export default (): generateClassName => {
let ruleCounter = 0
return (rule: Rule): string => `${rule.key}-${jssCounter}-${ruleCounter++}`
}

View File

@@ -0,0 +1,42 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports['default'] = createRule;
var _warning = require('warning');
var _warning2 = _interopRequireDefault(_warning);
var _StyleRule = require('../rules/StyleRule');
var _StyleRule2 = _interopRequireDefault(_StyleRule);
var _cloneStyle = require('../utils/cloneStyle');
var _cloneStyle2 = _interopRequireDefault(_cloneStyle);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
/**
* Create a rule instance.
*/
function createRule() {
var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'unnamed';
var decl = arguments[1];
var options = arguments[2];
var jss = options.jss;
var declCopy = (0, _cloneStyle2['default'])(decl);
var rule = jss.plugins.onCreateRule(name, declCopy, options);
if (rule) return rule;
// It is an at-rule and it has no instance.
if (name[0] === '@') {
(0, _warning2['default'])(false, '[JSS] Unknown at-rule %s', name);
}
return new _StyleRule2['default'](name, declCopy, options);
}

View File

@@ -0,0 +1,23 @@
/* @flow */
import warning from 'warning'
import StyleRule from '../rules/StyleRule'
import type {Rule, RuleOptions, JssStyle} from '../types'
import cloneStyle from '../utils/cloneStyle'
/**
* Create a rule instance.
*/
export default function createRule(name: string = 'unnamed', decl: JssStyle, options: RuleOptions): Rule {
const {jss} = options
const declCopy = cloneStyle(decl)
const rule = jss.plugins.onCreateRule(name, declCopy, options)
if (rule) return rule
// It is an at-rule and it has no instance.
if (name[0] === '@') {
warning(false, '[JSS] Unknown at-rule %s', name)
}
return new StyleRule(name, declCopy, options)
}

View File

@@ -0,0 +1,19 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports['default'] = findClassNames;
var dotsRegExp = /[.]/g;
var classesRegExp = /[.][^ ,]+/g;
/**
* Get class names from a selector.
*/
function findClassNames(selector) {
var classes = selector.match(classesRegExp);
if (!classes) return '';
return classes.join(' ').replace(dotsRegExp, '');
}

View File

@@ -0,0 +1,16 @@
/* @flow */
const dotsRegExp = /[.]/g
const classesRegExp = /[.][^ ,]+/g
/**
* Get class names from a selector.
*/
export default function findClassNames(selector: string): string {
const classes = selector.match(classesRegExp)
if (!classes) return ''
return classes
.join(' ')
.replace(dotsRegExp, '')
}

View File

@@ -0,0 +1,33 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports['default'] = findRenderer;
var _isInBrowser = require('is-in-browser');
var _isInBrowser2 = _interopRequireDefault(_isInBrowser);
var _DomRenderer = require('../renderers/DomRenderer');
var _DomRenderer2 = _interopRequireDefault(_DomRenderer);
var _VirtualRenderer = require('../renderers/VirtualRenderer');
var _VirtualRenderer2 = _interopRequireDefault(_VirtualRenderer);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
/**
* Find proper renderer.
* Option `virtual` is used to force use of VirtualRenderer even if DOM is
* detected, used for testing only.
*/
function findRenderer() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
if (options.Renderer) return options.Renderer;
var useVirtual = options.virtual || !_isInBrowser2['default'];
return useVirtual ? _VirtualRenderer2['default'] : _DomRenderer2['default'];
}

View File

@@ -0,0 +1,16 @@
/* @flow */
import isInBrowser from 'is-in-browser'
import DomRenderer from '../renderers/DomRenderer'
import VirtualRenderer from '../renderers/VirtualRenderer'
import type {JssOptions, Renderer} from '../types'
/**
* Find proper renderer.
* Option `virtual` is used to force use of VirtualRenderer even if DOM is
* detected, used for testing only.
*/
export default function findRenderer(options: JssOptions = {}): Class<Renderer> {
if (options.Renderer) return options.Renderer
const useVirtual = options.virtual || !isInBrowser
return useVirtual ? VirtualRenderer : DomRenderer
}

View File

@@ -0,0 +1,37 @@
'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; };
/**
* Extracts a styles object with only props that contain function values.
*/
exports['default'] = function (styles) {
// eslint-disable-next-line no-shadow
function extract(styles) {
var to = null;
for (var key in styles) {
var value = styles[key];
var type = typeof value === 'undefined' ? 'undefined' : _typeof(value);
if (type === 'function') {
if (!to) to = {};
to[key] = value;
} else if (type === 'object' && value !== null && !Array.isArray(value)) {
var extracted = extract(value);
if (extracted) {
if (!to) to = {};
to[key] = extracted;
}
}
}
return to;
}
return extract(styles);
};

View File

@@ -0,0 +1,30 @@
/**
* Extracts a styles object with only props that contain function values.
*/
export default (styles: Object): Object|null => {
// eslint-disable-next-line no-shadow
function extract(styles: Object): Object {
let to = null
for (const key in styles) {
const value = styles[key]
const type = typeof value
if (type === 'function') {
if (!to) to = {}
to[key] = value
}
else if (type === 'object' && value !== null && !Array.isArray(value)) {
const extracted = extract(value)
if (extracted) {
if (!to) to = {}
to[key] = extracted
}
}
}
return to
}
return extract(styles)
}

View File

@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = linkRule;
/**
* Link rule with CSSStyleRule and nested rules with corresponding nested cssRules if both exists.
*/
function linkRule(rule, cssRule) {
rule.renderable = cssRule;
if (rule.rules && cssRule.cssRules) rule.rules.link(cssRule.cssRules);
}

View File

@@ -0,0 +1,7 @@
/**
* Link rule with CSSStyleRule and nested rules with corresponding nested cssRules if both exists.
*/
export default function linkRule(rule: Rule, cssRule: CSSOMRule): void {
rule.renderable = cssRule
if (rule.rules && cssRule.cssRules) rule.rules.link(cssRule.cssRules)
}

View File

@@ -0,0 +1,87 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports['default'] = toCss;
var _toCssValue = require('./toCssValue');
var _toCssValue2 = _interopRequireDefault(_toCssValue);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
/**
* Indent a string.
* http://jsperf.com/array-join-vs-for
*/
function indentStr(str, indent) {
var result = '';
for (var index = 0; index < indent; index++) {
result += ' ';
}return result + str;
}
/**
* Converts a Rule to CSS string.
*/
function toCss(selector, style) {
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var result = '';
if (!style) return result;
var _options$indent = options.indent,
indent = _options$indent === undefined ? 0 : _options$indent;
var fallbacks = style.fallbacks;
indent++;
// Apply fallbacks first.
if (fallbacks) {
// Array syntax {fallbacks: [{prop: value}]}
if (Array.isArray(fallbacks)) {
for (var index = 0; index < fallbacks.length; index++) {
var fallback = fallbacks[index];
for (var prop in fallback) {
var value = fallback[prop];
if (value != null) {
result += '\n' + indentStr(prop + ': ' + (0, _toCssValue2['default'])(value) + ';', indent);
}
}
}
}
// Object syntax {fallbacks: {prop: value}}
else {
for (var _prop in fallbacks) {
var _value = fallbacks[_prop];
if (_value != null) {
result += '\n' + indentStr(_prop + ': ' + (0, _toCssValue2['default'])(_value) + ';', indent);
}
}
}
}
var hasFunctionValue = false;
for (var _prop2 in style) {
var _value2 = style[_prop2];
if (typeof _value2 === 'function') {
_value2 = style['$' + _prop2];
hasFunctionValue = true;
}
if (_value2 != null && _prop2 !== 'fallbacks') {
result += '\n' + indentStr(_prop2 + ': ' + (0, _toCssValue2['default'])(_value2) + ';', indent);
}
}
if (!result && !hasFunctionValue) return result;
indent--;
result = indentStr(selector + ' {' + result + '\n', indent) + indentStr('}', indent);
return result;
}

View File

@@ -0,0 +1,72 @@
/* @flow */
import toCssValue from './toCssValue'
import type {ToCssOptions as Options, JssStyle} from '../types'
/**
* Indent a string.
* http://jsperf.com/array-join-vs-for
*/
function indentStr(str: string, indent: number): string {
let result = ''
for (let index = 0; index < indent; index++) result += ' '
return result + str
}
/**
* Converts a Rule to CSS string.
*/
export default function toCss(selector: string, style: JssStyle, options: Options = {}): string {
let result = ''
if (!style) return result
let {indent = 0} = options
const {fallbacks} = style
indent++
// Apply fallbacks first.
if (fallbacks) {
// Array syntax {fallbacks: [{prop: value}]}
if (Array.isArray(fallbacks)) {
for (let index = 0; index < fallbacks.length; index++) {
const fallback = fallbacks[index]
for (const prop in fallback) {
const value = fallback[prop]
if (value != null) {
result += `\n${indentStr(`${prop}: ${toCssValue(value)};`, indent)}`
}
}
}
}
// Object syntax {fallbacks: {prop: value}}
else {
for (const prop in fallbacks) {
const value = fallbacks[prop]
if (value != null) {
result += `\n${indentStr(`${prop}: ${toCssValue(value)};`, indent)}`
}
}
}
}
let hasFunctionValue = false
for (const prop in style) {
let value = style[prop]
if (typeof value === 'function') {
value = style[`$${prop}`]
hasFunctionValue = true
}
if (value != null && prop !== 'fallbacks') {
result += `\n${indentStr(`${prop}: ${toCssValue(value)};`, indent)}`
}
}
if (!result && !hasFunctionValue) return result
indent--
result = indentStr(`${selector} {${result}\n`, indent) + indentStr('}', indent)
return result
}

View File

@@ -0,0 +1,26 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports['default'] = toCssValue;
var joinWithSpace = function joinWithSpace(value) {
return value.join(' ');
};
/**
* Converts array values to string.
*
* `margin: [['5px', '10px']]` > `margin: 5px 10px;`
* `border: ['1px', '2px']` > `border: 1px, 2px;`
*/
function toCssValue(value) {
if (!Array.isArray(value)) return value;
// Support space separated values.
if (Array.isArray(value[0])) {
return toCssValue(value.map(joinWithSpace));
}
return value.join(', ');
}

View File

@@ -0,0 +1,19 @@
/* @flow */
const joinWithSpace = (value: Array<string|number>): string => value.join(' ')
/**
* Converts array values to string.
*
* `margin: [['5px', '10px']]` > `margin: 5px 10px;`
* `border: ['1px', '2px']` > `border: 1px, 2px;`
*/
export default function toCssValue(value: any) {
if (!Array.isArray(value)) return value
// Support space separated values.
if (Array.isArray(value[0])) {
return toCssValue(value.map(joinWithSpace))
}
return value.join(', ')
}

View File

@@ -0,0 +1,18 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports['default'] = function (rule, data, RuleList) {
if (rule.type === 'style') {
for (var prop in rule.style) {
var value = rule.style[prop];
if (typeof value === 'function') {
rule.prop(prop, value(data));
}
}
} else if (rule.rules instanceof RuleList) {
rule.rules.update(data);
}
};

View File

@@ -0,0 +1,16 @@
import type RuleListType from '../RuleList'
import type {Rule} from './types'
export default (rule: Rule, data: Object, RuleList: RuleListType): void => {
if (rule.type === 'style') {
for (const prop in rule.style) {
const value = rule.style[prop]
if (typeof value === 'function') {
rule.prop(prop, value(data))
}
}
}
else if (rule.rules instanceof RuleList) {
rule.rules.update(data)
}
}

View File

@@ -0,0 +1,159 @@
{
"_args": [
[
"jss@8.1.0",
"C:\\Users\\deranjer\\go\\src\\github.com\\deranjer\\goTorrent\\torrent-project"
]
],
"_from": "jss@8.1.0",
"_id": "jss@8.1.0",
"_inBundle": false,
"_integrity": "sha512-NZ4CNAoPaPlM2rqHxPG5uGQbQEFZ9n1PITn0+wGIdAk2ZtA/F6el0SphLHf8So1Sx6N34hnVFFIuc32/hdsEzw==",
"_location": "/material-ui/jss",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "jss@8.1.0",
"name": "jss",
"escapedName": "jss",
"rawSpec": "8.1.0",
"saveSpec": null,
"fetchSpec": "8.1.0"
},
"_requiredBy": [
"/material-ui",
"/material-ui/react-jss"
],
"_resolved": "https://registry.npmjs.org/jss/-/jss-8.1.0.tgz",
"_spec": "8.1.0",
"_where": "C:\\Users\\deranjer\\go\\src\\github.com\\deranjer\\goTorrent\\torrent-project",
"author": {
"name": "Oleg Slobodskoi",
"email": "oleg008@gmail.com"
},
"bugs": {
"url": "https://github.com/cssinjs/jss/issues"
},
"dependencies": {
"is-in-browser": "^1.0.2",
"warning": "^3.0.0"
},
"description": "A lib for generating Style Sheets with JavaScript.",
"devDependencies": {
"babel-cli": "^6.18.0",
"babel-core": "^6.20.0",
"babel-eslint": "^7.1.1",
"babel-loader": "^6.2.9",
"babel-plugin-inline-version": "^1.0.2",
"babel-plugin-rewire": "^1.0.0",
"babel-plugin-transform-es3-member-expression-literals": "^6.8.0",
"babel-plugin-transform-es3-property-literals": "^6.8.0",
"babel-plugin-transform-flow-strip-types": "^6.18.0",
"babel-plugin-transform-inline-environment-variables": "^6.8.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015": "^6.18.0",
"babel-preset-stage-0": "^6.16.0",
"codecov": "^1.0.1",
"common-tags": "^1.4.0",
"cross-env": "^3.1.3",
"detect-browser": "^1.5.0",
"es5-shim": "^4.5.9",
"eslint": "^3.11.1",
"eslint-config-airbnb": "^13.0.0",
"eslint-config-jss": "^3.0.0",
"eslint-plugin-flowtype": "^2.29.1",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-jsx-a11y": "^2.2.3",
"eslint-plugin-react": "^6.5.0",
"expect.js": "^0.3.1",
"flow-bin": "^0.47.0",
"flow-copy-source": "^1.1.0",
"json-loader": "^0.5.4",
"jss-cache": "^2.0.0",
"jss-camel-case": "^5.0.0",
"jss-compose": "^4.0.0",
"jss-default-unit": "^7.0.0",
"jss-expand": "^4.0.0",
"jss-extend": "^5.0.0",
"jss-global": "^2.0.0",
"jss-isolate": "^4.0.0",
"jss-nested": "^5.0.0",
"jss-props-sort": "^5.0.0",
"jss-vendor-prefixer": "^6.0.0",
"karma": "^1.3.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-mocha": "^1.3.0",
"karma-mocha-reporter": "^2.2.1",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^1.8.0",
"lint-staged": "^3.2.2",
"mocha": "^3.2.0",
"pre-commit": "^1.1.3",
"rimraf": "^2.5.4",
"size-limit": "^0.2.0",
"webpack": "^2.3.3"
},
"engines": {
"node": ">=4"
},
"files": [
"dist",
"lib",
"flow-typed",
"readme.md",
"changelog.md",
"LICENSE"
],
"homepage": "https://github.com/cssinjs/jss#readme",
"keywords": [
"jss",
"style",
"sheet",
"stylesheet",
"css",
"components",
"composable",
"css in js",
"css-in-js"
],
"license": "MIT",
"lint-staged": {
"./src ./tests ./benchmark ./*.js": [
"eslint",
"git add"
]
},
"main": "./lib/index.js",
"name": "jss",
"pre-commit": "lint:staged",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/cssinjs/jss.git"
},
"scripts": {
"all": "npm run lint && npm run flow && npm run test && npm run build && npm run size",
"bench": "cross-env BENCHMARK=true karma start --single-run",
"build": "npm run clean && npm run build:lib && npm run build:max && npm run build:min && npm run build:tests",
"build:lib": "babel src --out-dir lib && npm run flow:copy-src",
"build:max": "cross-env NODE_ENV=development webpack src/index.js dist/jss.js",
"build:min": "cross-env NODE_ENV=production webpack src/index.js dist/jss.min.js",
"build:tests": "cross-env NODE_ENV=test webpack tests/index.js tmp/tests.js",
"clean": "rimraf '{lib,dist,tmp}/*'",
"codecov": "codecov",
"flow": "flow --show-all-errors",
"flow:copy-src": "flow-copy-source -i './src/**' src lib",
"lint": "eslint ./src ./tests ./benchmark ./*.js && npm run flow",
"lint:staged": "lint-staged && npm run flow",
"posttest": "[ -z \"$TRAVIS\" ] || codecov",
"prepublishOnly": "npm run all",
"size": "size-limit 5.8KB dist/jss.js",
"test": "cross-env NODE_ENV=test karma start --single-run",
"test:watch": "cross-env NODE_ENV=test karma start"
},
"version": "8.1.0"
}

View File

@@ -0,0 +1,218 @@
# JSS
[![Gitter](https://badges.gitter.im/JoinChat.svg)](https://gitter.im/cssinjs/lobby)
[![Build Status](https://travis-ci.org/cssinjs/jss.svg?branch=master)](https://travis-ci.org/cssinjs/jss)
[![codecov](https://codecov.io/gh/cssinjs/jss/branch/master/graph/badge.svg)](https://codecov.io/gh/cssinjs/jss)
[![bitHound Score](https://www.bithound.io/cssinjs/jss/badges/score.svg)](https://www.bithound.io/cssinjs/jss)
[![OpenCollective](https://opencollective.com/jss/backers/badge.svg)](#backers)
[![OpenCollective](https://opencollective.com/jss/sponsors/badge.svg)](#sponsors)
[JSS is a better abstraction](https://medium.com/@oleg008/jss-is-css-d7d41400b635) over CSS. It uses JavaScript as a language to describe styles in a declarative and maintainable way. It is a [high performance](https://github.com/cssinjs/jss/blob/master/docs/performance.md) JS to CSS compiler which works at runtime and server-side. You can use it with [React](https://github.com/cssinjs/react-jss) or with any other library. It is about 5KB (minified and gzipped) and is extensible via [plugins](./docs/plugins.md) API.
## Integrations
### Official
- [React-JSS](https://github.com/cssinjs/react-jss) - HOC interface for React, try it on [webpackbin](https://www.webpackbin.com/bins/-Kn90iijPuAJO48ItgF-).
- [Styled-JSS](https://github.com/cssinjs/styled-jss) - styled components interface for React, try it on [webpackbin](https://www.webpackbin.com/bins/-KlrbQuwAZSK5eSzpCSy).
- [Aphrodite-JSS](https://github.com/cssinjs/aphrodite-jss) - aphrodite like API.
### External
- [Theme Reactor](https://github.com/nathanmarks/jss-theme-reactor) - experimental React integration with theming.
- [Aesthetic](https://github.com/milesj/aesthetic/tree/master/packages/aesthetic) - a React style abstraction layer with theme support.
## TOC
1. [Live examples](https://github.com/cssinjs/examples).
1. [Benefits](./docs/benefits.md)
1. [Setup](./docs/setup.md)
1. [JSON API (JSS Syntax)](./docs/json-api.md)
1. [JavaScript API](./docs/js-api.md)
1. [Server-side rendering](./docs/ssr.md)
1. [Performance](./docs/performance.md)
1. [Plugins API](./docs/plugins.md)
1. [Official plugins](https://github.com/cssinjs?q=plugin)
1. [All related projects](./docs/projects.md)
1. [CLI Converter](https://github.com/cssinjs/cli)
1. [Contributing](./contributing.md)
## Example
Try it out on [webpackbin](https://www.webpackbin.com/bins/-KlrNqkpZZmKIz0eYwIk).
You need to [setup plugins](./docs/setup.md#setup-with-plugins) before.
You can use a [preset](https://github.com/cssinjs/jss-preset-default) for a quick setup with default plugins.
```javascript
import jss from 'jss'
import preset from 'jss-preset-default'
import color from 'color'
// One time setup with default plugins and settings.
jss.setup(preset())
const styles = {
button: {
fontSize: 12,
'&:hover': {
background: 'blue'
}
},
ctaButton: {
extend: 'button',
'&:hover': {
background: color('blue').darken(0.3).hex()
}
},
'@media (min-width: 1024px)': {
button: {
width: 200
}
}
}
const {classes} = jss.createStyleSheet(styles).attach()
document.body.innerHTML = `
<button class="${classes.button}">Button</button>
<button class="${classes.ctaButton}">CTA Button</button>
`
```
Result
```html
<head>
<style type="text/css">
.button-123456 {
font-size: 12px;
}
.button-123456:hover {
background: blue;
}
.ctaButton-789012 {
font-size: 12px;
}
.ctaButton-789012:hover {
background: red;
}
@media (min-width: 1024px) {
.button-123456 {
min-width: 200px;
}
}
</style>
</head>
<body>
<button class="button-123456">Button</button>
<button class="ctaButton-789012">CTA Button</button>
</body>
```
## When should I use it?
- You build a JavaScript heavy application.
- You use components based architecture.
- You build a reusable UI library.
- You need a collision free CSS (external content, third-party UI components ...).
- You need code sharing between js and css.
- Minimal download size is important to you.
- Robustness and code reuse is important to you.
- Ease of maintenance is important to you.
- You just want to use any of its [benefits](./docs/benefits.md)
## Roadmap
- ~~Make it easier for newcomers to setup jss with plugins (like presets).~~
- ~~Make JSON DSL even better, for e.g. [jss-expand](https://github.com/typical000/jss-expand).~~
- ~~Make it easy to see when changes in the core break plugins (integrate plugins test suite).~~
- Make community create plugins (better plugins API documentation, infrastructure).
- Do more benchmarking, include plugins, always track perf regressions.
- Introduce a way for theming with react-jss or replace it by [jss-theme-reactor](https://github.com/nathanmarks/jss-theme-reactor)
- Make SSR even better (vendor prefixer, smaller critical CSS)
- Make CLI tool better, allow integration of styles written in various preprocessing languages as well as pure css.
- React Native support.
- Add converters stylus, sass and co. to [cli](https://github.com/cssinjs/cli) with constants reuse.
## Browsers Support
We have automated tests running in [real browsers](./browsers.json).
## License
MIT
## Thanks
Thanks to [BrowserStack](https://www.browserstack.com) for providing the infrastructure that allows us to run our tests in real browsers and to all awesome [contributors](https://github.com/cssinjs/jss/graphs/contributors).
### Backers
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/jss#backer)]
<a href="https://opencollective.com/jss/backer/0/website" target="_blank"><img src="https://opencollective.com/jss/backer/0/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/1/website" target="_blank"><img src="https://opencollective.com/jss/backer/1/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/2/website" target="_blank"><img src="https://opencollective.com/jss/backer/2/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/3/website" target="_blank"><img src="https://opencollective.com/jss/backer/3/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/4/website" target="_blank"><img src="https://opencollective.com/jss/backer/4/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/5/website" target="_blank"><img src="https://opencollective.com/jss/backer/5/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/6/website" target="_blank"><img src="https://opencollective.com/jss/backer/6/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/7/website" target="_blank"><img src="https://opencollective.com/jss/backer/7/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/8/website" target="_blank"><img src="https://opencollective.com/jss/backer/8/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/9/website" target="_blank"><img src="https://opencollective.com/jss/backer/9/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/10/website" target="_blank"><img src="https://opencollective.com/jss/backer/10/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/11/website" target="_blank"><img src="https://opencollective.com/jss/backer/11/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/12/website" target="_blank"><img src="https://opencollective.com/jss/backer/12/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/13/website" target="_blank"><img src="https://opencollective.com/jss/backer/13/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/14/website" target="_blank"><img src="https://opencollective.com/jss/backer/14/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/15/website" target="_blank"><img src="https://opencollective.com/jss/backer/15/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/16/website" target="_blank"><img src="https://opencollective.com/jss/backer/16/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/17/website" target="_blank"><img src="https://opencollective.com/jss/backer/17/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/18/website" target="_blank"><img src="https://opencollective.com/jss/backer/18/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/19/website" target="_blank"><img src="https://opencollective.com/jss/backer/19/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/20/website" target="_blank"><img src="https://opencollective.com/jss/backer/20/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/21/website" target="_blank"><img src="https://opencollective.com/jss/backer/21/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/22/website" target="_blank"><img src="https://opencollective.com/jss/backer/22/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/23/website" target="_blank"><img src="https://opencollective.com/jss/backer/23/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/24/website" target="_blank"><img src="https://opencollective.com/jss/backer/24/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/25/website" target="_blank"><img src="https://opencollective.com/jss/backer/25/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/26/website" target="_blank"><img src="https://opencollective.com/jss/backer/26/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/27/website" target="_blank"><img src="https://opencollective.com/jss/backer/27/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/28/website" target="_blank"><img src="https://opencollective.com/jss/backer/28/avatar.svg"></a>
<a href="https://opencollective.com/jss/backer/29/website" target="_blank"><img src="https://opencollective.com/jss/backer/29/avatar.svg"></a>
### Sponsors
Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/jss#sponsor)]
<a href="https://opencollective.com/jss/sponsor/0/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/1/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/2/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/3/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/4/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/5/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/6/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/7/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/8/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/9/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/9/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/10/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/10/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/11/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/11/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/12/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/12/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/13/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/13/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/14/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/14/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/15/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/15/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/16/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/16/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/17/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/17/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/18/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/18/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/19/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/19/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/20/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/20/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/21/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/21/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/22/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/22/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/23/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/23/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/24/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/24/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/25/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/25/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/26/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/26/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/27/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/27/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/28/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/28/avatar.svg"></a>
<a href="https://opencollective.com/jss/sponsor/29/website" target="_blank"><img src="https://opencollective.com/jss/sponsor/29/avatar.svg"></a>