8000 Support new webpack features and internalize CSS functions. by izaakschroeder · Pull Request #17 · bootstarted/css-js-loader · GitHub
[go: up one dir, main page]

Skip to content

Support new webpack features and internalize CSS functions. #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 5, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 8 additions & 17 deletions .eslintrc
10000
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
{
"extends": [
"metalab/legacy",
"metalab/node"
],
"rules": {
"func-style": 0,
"no-extra-semi": 0,
"no-param-reassign": 0,
"vars-on-top": 0,
"max-len": 0,
"import/no-commonjs": 0,
"no-undef": 0,
"no-unused-vars": 0,
"space-before-function-paren": 0
}
}
extends:
- metalab/legacy
env:
node: true
rules:
vars-on-top: 0
no-param-reassign: 0

9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Write your styles with in JavsScript.
Install:

```sh
yarn add css-js-loader
npm install css-js-loader value-loader
```

Add to your `webpack.config.js`:
Expand All @@ -27,15 +27,17 @@ module.exports = {
loaders: ['style-loader', 'css-loader'],
}, {
test: /\.css\.js$/,
loader: 'css-js-loader',
loaders: ['css-js-loader', 'value-loader'],
}],
},
};
```

NOTE: You don't need to chain with [value-loader] per-se, but doing so gives you caching, nested dependency monitoring/reloading and the ability to use webpack's tree-shaking abilities.

## Writing JS Styles

`css-js-loader` converts JS modules to CSS markup at runtime.
`css-js-loader` converts JS modules to CSS markup at runtime.

A `.css.js` file:

Expand Down Expand Up @@ -104,3 +106,4 @@ export default () =>
```

[CSS Modules]: https://github.com/webpack-contrib/css-loader#css-modules
[value-loader]: https://www.npmjs.com/package/value-loader
24 changes: 13 additions & 11 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ var omit = require('lodash/omit');
var isString = require('lodash/isString');
var isNumber = require('lodash/isNumber');
var loaderUtils = require('loader-utils');
var dangerousStyleValue = require('react-dom/lib/dangerousStyleValue');
var dangerousStyleValue = require('./internal/dangerousStyleValue');
var hyphenateStyleName = require('fbjs/lib/hyphenateStyleName');

function indent(pretty, depth) {
return pretty ? Array(depth).join(' ') : '';
};
}

function space(pretty) {
return pretty ? ' ' : '';
};
}

function line(pretty) {
return pretty ? '\n' : '';
Expand Down Expand Up @@ -44,7 +44,9 @@ function format(config, value, name, level, inProp) {
// The `name` and `value` args currently represent a css property and value.
// Use React's css style processing funcs to generate css markup.

css += indent(pretty, indentLevel) + hyphenateStyleName(name) + ':' + space(pretty);
css += indent(pretty, indentLevel) +
hyphenateStyleName(name) + ':' +
space(pretty);
css += dangerousStyleValue(name, value) + ';' + line(pretty);
} else {
// The `name` and `value` args currently represent a block containing css
Expand All @@ -54,7 +56,8 @@ function format(config, value, name, level, inProp) {
if (name) {
// Unless we are in the global css scope (`name` is undefined), add a new
// block to the markup.
css += indent(pretty, indentLevel) + name + space(pretty) + '{' + line(pretty);
css += indent(pretty, indentLevel) + name + space(pretty) + '{' +
line(pretty);
indentLevel += 1;
}

Expand Down Expand Up @@ -91,14 +94,13 @@ function format(config, value, name, level, inProp) {
module.exports = function(content) {
this.cacheable();

config = defaults(
loaderUtils.getLoaderConfig(this, 'jsCssLoader'),
var config = defaults(
loaderUtils.getOptions(this),
{pretty: process.env.NODE_ENV !== 'production'}
);

var styles = this.exec(content, this.resourcePath);

var css = '';
var styles = typeof content === 'object' ? content :
this.exec(content, this.resourcePath);

if (styles.__esModule) {
// When using Babel, css classes can be defined as named es6 exports.
Expand All @@ -123,7 +125,7 @@ module.exports = function(content) {
return format(config, [
mapKeys(
omit(styles, 'default'),
function (value, key) {
function(value, key) {
return '.' + key;
}
),
Expand Down
89 changes: 89 additions & 0 deletions internal/CSSProperty.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule CSSProperty
*/

'use strict';

/**
* CSS properties which accept numbers but are not in units of "px".
*/
var isUnitlessNumber = {
animationIterationCount: true,
borderImageOutset: true,
borderImageSlice: true,
borderImageWidth: true,
boxFlex: true,
boxFlexGroup: true,
boxOrdinalGroup: true,
columnCount: true,
columns: true,
flex: true,
flexGrow: true,
flexPositive: true,
flexShrink: true,
flexNegative: true,
flexOrder: true,
gridRow: true,
gridRowEnd: true,
gridRowSpan: true,
gridRowStart: true,
gridColumn: true,
gridColumnEnd: true,
gridColumnSpan: true,
gridColumnStart: true,
fontWeight: true,
lineClamp: true,
lineHeight: true,
opacity: true,
order: true,
orphans: true,
tabSize: true,
widows: true,
zIndex: true,
zoom: true,

// SVG-related properties
fillOpacity: true,
floodOpacity: true,
stopOpacity: true,
strokeDasharray: true,
strokeDashoffset: true,
strokeMiterlimit: true,
strokeOpacity: true,
strokeWidth: true,
};

/**
* @param {string} prefix vendor-specific prefix, eg: Webkit
* @param {string} key style name, eg: transitionDuration
* @returns {string} style name prefixed with `prefix`, properly camelCased, eg:
* WebkitTransitionDuration
*/
function prefixKey(prefix, key) {
return prefix + key.charAt(0).toUpperCase() + key.substring(1);
}

/**
* Support style names that may come passed in prefixed by adding permutations
* of vendor prefixes.
*/
var prefixes = ['Webkit', 'ms', 'Moz', 'O'];

// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an
// infinite loop, because it iterates over the newly added props too.
Object.keys(isUnitlessNumber).forEach(function(prop) {
prefixes.forEach(function(prefix) {
isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
});
});

var CSSProperty = {
isUnitlessNumber: isUnitlessNumber,
};

module.exports = CSSProperty;
54 changes: 54 additions & 0 deletions internal/dangerousStyleValue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule dangerousStyleValue
*/

'use strict';

var CSSProperty = require('./CSSProperty');

var isUnitlessNumber = CSSProperty.isUnitlessNumber;

/**
* Convert a value into the proper css writable value. The style name `name`
* should be logical (no hyphens), as specified
* in `CSSProperty.isUnitlessNumber`.
*
* @param {string} name CSS property name such as `topMargin`.
* @param {*} value CSS property value such as `10px`.
* @param {boolean} isCustomProperty Is it custom
* @returns {string} Normalized style value with dimensions applied.
*/
function dangerousStyleValue(name, value, isCustomProperty) {
// Note that we've removed escapeTextForBrowser() calls here since the
// whole string will be escaped when the attribute is injected into
// the markup. If you provide unsafe user data here they can inject
// arbitrary CSS which may be problematic (I couldn't repro this):
// https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
// http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/
// This is not an XSS hole but instead a potential CSS injection issue
// which has lead to a greater discussion about how we're going to
// trust URLs moving forward. See #2115901

var isEmpty = value === null || typeof value === 'boolean' || value === '';
if (isEmpty) {
return '';
}

if (
!isCustomProperty &&
typeof value === 'number' &&
value !== 0 &&
!(isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name])
) {
return value + 'px'; // Presumes implicit 'px' suffix for unitless numbers
}

return ('' + value).trim();
}

module.exports = dangerousStyleValue;
Loading
0