Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

babel-plugin-react-cssmoduleify

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

babel-plugin-react-cssmoduleify - npm Package Compare versions

Comparing version 0.9.5 to 1.0.0-beta.4

LICENSE

482

lib/index.js

@@ -1,290 +0,249 @@

/**
* Babel plugin to transform React className property values to CSS Module style
* lookups
*/
'use strict';
"use strict";
Object.defineProperty(exports, '__esModule', {
Object.defineProperty(exports, "__esModule", {
value: true
});
exports['default'] = function (_ref) {
var Plugin = _ref.Plugin;
var parse = _ref.parse;
var t = _ref.types;
var _babelTemplate = require("babel-template");
var optionsKey = 'react-cssmoduleify';
var cssModuleId = undefined;
var _babelTemplate2 = _interopRequireDefault(_babelTemplate);
function warn() {
console.warn.apply(console, arguments);
console.warn('Please report this at https://github.com/walmartreact/' + 'babel-plugin-react-cssmoduleify/issues');
}
var _arrayFind = require("array-find");
function isValidOptions(options) {
return typeof options === 'object' && options.path && options.cssmodule;
}
var _arrayFind2 = _interopRequireDefault(_arrayFind);
/**
* Enforces plugin options to be defined and returns them.
*/
function getPluginOptions(file) {
if (!file.opts || !file.opts.extra) {
return;
}
var _path = require("path");
var pluginOptions = file.opts.extra[optionsKey];
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
if (!isValidOptions(pluginOptions)) {
throw new Error('babel-plugin-react-css-modules requires that you specify extras["' + optionsKey + '"] in .babelrc ' + 'or in your Babel Node API call ' + 'options with "path" and "cssmodule" keys.');
}
return pluginOptions;
}
/**
* TemplateElement value nodes must be of the shape {raw: string; value: string}
*/
/* eslint no-extra-parens: 0 */
var templateElementValue = function templateElementValue(value) {
return { raw: value, cooked: value };
};
/**
* Transform an AST Node representing a literal string property to an
* appropriate CSS module-style memberExpression
*
* { className: 'hello'} => className: _styles['hello'] }
* { className: 'hello world'} => className: _styles['hello'] + ' ' + _styles['world'] }
*/
var mutateStringPropertyToCSSModule = function mutateStringPropertyToCSSModule(prop) {
var parts = prop.value.value.split(' ').map(function (v) {
return t.memberExpression(cssModuleId, t.literal(v), true);
});
exports.default = function (_ref) {
var t = _ref.types;
if (parts.length === 1) {
prop.value = parts[0];
} else {
prop.value = parts.reduce(function (ast, cur, i) {
if (!ast) return cur;
var ROOT_CSSNAMES_IDENTIFIER = "cssmodule";
var BAIL_OUT = "__dontTransformMe";
return t.binaryExpression('+', t.binaryExpression('+', ast, t.literal(' ')), cur);
});
}
var matchesPatterns = function matchesPatterns(path, patterns) {
return !!(0, _arrayFind2.default)(patterns, function (pattern) {
return t.isIdentifier(path.node, { name: pattern }) || path.matchesPattern(pattern);
});
};
var isClassnames = function isClassnames(node, scope) {
var reClassnames = /classnames/i;
/**
* Updates a ConditionalExpression consequent or alternate node with the most
* appropriate CSS Module lookup.
*
* @param {Path} path consequent or alternate node of a conditional expression
* @param {Node<Identifier>} cssmodule cssmodule identifier
*/
var replaceConditionalExpression = function replaceConditionalExpression(path, cssmodule) {
return path.replaceWith(computeClassName(path, cssmodule));
};
if (node.type !== 'CallExpression') {
return false;
}
/**
* Generate the required TemplateElements for the following type of template:
* `${ slot } ${ anotherslot }`
*/
var spacedTemplateElements = function spacedTemplateElements(count) {
return Array.apply(0, Array(count)).map(function (_, i) {
return i === 0 || i === count - 1 ? t.templateElement(templateElementValue(""), i === count) : t.templateElement(templateElementValue(" "), false);
});
};
var identifierName = node.callee.type === 'Identifier' ? node.callee.name : node.callee.object ? node.callee.object.name : node.callee.type === 'SequenceExpression' ? node.callee.expressions[1].object.name : 'TODO';
if (!identifierName || identifierName === 'TODO') {
return false;
}
var definition = scope.getBinding(identifierName);
// follow the variable declaration to a require
if (definition.path.node.type === 'VariableDeclarator') {
var init = definition.path.node.init;
if (init.type !== 'CallExpression') {
return false;
var computeClassName = function computeClassName(value, cssmodule) {
if (t.isStringLiteral(value)) {
if (value.node.value === "") {
return value.node;
}
if (/require|_interopRequireDefault/.test(init.callee.name)) {
return reClassnames.test(init.arguments[0].name);
}
var values = value.node.value.split(" ");
return values.length === 1 ? t.memberExpression(cssmodule, t.stringLiteral(values[0]), true) : t.templateLiteral(spacedTemplateElements(values.length + 1), values.map(function (v) {
return t.memberExpression(cssmodule, t.stringLiteral(v), true);
}));
} else if (t.isIdentifier(value)) {
// TODO: need to validate what type of node this identifier refers to
return t.memberExpression(cssmodule, value.node, true);
} else if (t.isMemberExpression(value)) {
return t.memberExpression(cssmodule, value.node, true);
} else if (t.isConditionalExpression(value)) {
replaceConditionalExpression(value.get("consequent"), cssmodule);
replaceConditionalExpression(value.get("alternate"), cssmodule);
return value.node;
} else {
console.log("TODO(computeClassName): handle %s", value.node.type);
return value.node;
}
// TODO: track `import` statements
return false;
};
var convertStringKeysToComputedProperties = function convertStringKeysToComputedProperties(node) {
node.properties.forEach(function (p) {
// ensure we're idempotent
if (p.key.type === 'MemberExpression' && p.object === cssModuleId || !p.key.value) {
return;
}
p.key = t.memberExpression(cssModuleId, t.literal(p.key.value), true);
p.computed = true;
});
return node;
var isArrayJoin = function isArrayJoin(path) {
return t.isCallExpression(path.node) && t.isMemberExpression(path.node.callee) && t.isIdentifier(path.node.callee.property, { name: "join" }) && (t.isArrayExpression(path.node.callee.object) || t.isIdentifier(path.node.callee.object) // TODO: resolve identifier
);
};
var mutateClassnamesCall = function mutateClassnamesCall(node, scope) {
node.arguments = node.arguments.map(function (v) {
if (v.type === 'Identifier') {
var bindings = undefined;
while (!(bindings = scope.bindings[v.name]) && scope.parent) {
scope = scope.parent;
}
/**
* Resolves a path to most conservative Path to be converted. If there is only
* one reference to an Identifier we can mutate that safely, otherwise we
* return the original node to be transformed.
*
* @param {Path} path an Identifier or ArrayExpression Path
* @return {Path} the conservatively resolved path
*/
var conservativeResolve = function conservativeResolve(path) {
// if it’s not an identifier we already have what we need
if (!t.isIdentifier(path.node)) {
return path;
}
var binding = path.scope.getBinding(path.node.name);
if (!bindings) {
return t.memberExpression(cssModuleId, t.literal(v.name), true);
}
v = bindings.path.node;
if (v.type === 'VariableDeclarator') {
v = v.init;
}
// if there is only one reference, we can mutate that directly
if (binding.references === 1) {
if (t.isVariableDeclarator(binding.path)) {
return binding.path.get("init");
}
console.warn("TODO: ensure this branch is tracked");
return binding.path;
}
if (v.type === 'CallExpression') return v;
if (v.type === 'Literal' || v.type === 'BinaryExpression' || v.type === 'ConditionalExpression') {
return t.memberExpression(cssModuleId, v, true);
}
if (v.type === 'ObjectExpression') {
return convertStringKeysToComputedProperties(v);
}
if (v.type === 'MemberExpression') {
return v;
}
warn('WARNING(TODO): handle mutating classnames call for %s.', v.type);
return v;
});
// else we should probably return conservatively only the one we want and
// transform inline
return path;
};
var computedOrIdentifier = function computedOrIdentifier(node) {
return t.logicalExpression('||', t.memberExpression(cssModuleId, node, true), node);
};
var _handleBinaryExpression = function _handleBinaryExpression(node) {
if (node.value === '') return node;
if (node.type === 'MemberExpression') {
if (node.object.name === 'props' || node.object.property && node.object.property.name === 'props') {
return node;
}
return t.memberExpression(cssModuleId, node, true);
/**
* Replaces [...].join(" ") or identifier.join(" ") with the most appropriate
* cssmodule lookup hash.
*
* @param {Path<Identifier|ArrayExpression>} path an Identifier or ArrayExpression Path
* @param {Node<Identifier>} cssmodule the root identifier to the cssmodules object
*/
var replaceArrayJoinElements = function replaceArrayJoinElements(path, cssmodule) {
var arrayExpressionPath = conservativeResolve(path.get("callee").get("object"));
if (t.isIdentifier(arrayExpressionPath)) {
arrayExpressionPath.parent.object = t.callExpression(t.memberExpression(arrayExpressionPath.node, t.identifier("map"), false), [t.arrowFunctionExpression([t.identifier("i")], t.memberExpression(cssmodule, t.identifier("i"), true))]);
return;
}
if (node.type === 'ConditionalExpression') {
node.consequent = _handleBinaryExpression(node.consequent);
node.alternate = _handleBinaryExpression(node.alternate);
return node;
for (var i = 0; i < arrayExpressionPath.node.elements.length; i++) {
var element = arrayExpressionPath.get("elements", i)[i];
element.replaceWith(computeClassName(element, cssmodule));
}
};
var parts = node.value.split(' ');
if (parts.length === 1) {
return t.memberExpression(cssModuleId, t.literal(parts[0]), true);
/**
* Updates a callExpression value with the most appropriate CSS Module lookup.
*
* @param {Path} callExpression <jsx className={value()} />
* @param {Node<Identifier>} cssmodule cssmodule identifier
*/
var replaceCallExpression = function replaceCallExpression(callExpression, cssmodule) {
if (isArrayJoin(callExpression)) {
return replaceArrayJoinElements(callExpression, cssmodule);
}
return parts.reduce(function (ast, n) {
if (n === '') {
return ast;
}
if (!ast) {
return typeof n === 'object' ? n : t.binaryExpression('+', t.memberExpression(cssModuleId, t.literal(n), true), t.literal(' '));
}
return t.binaryExpression('+', t.binaryExpression('+', ast, t.literal(' ')), t.binaryExpression('+', t.literal(n), t.literal(' ')));
}, null);
// this is just mean
callExpression.replaceWith(t.callExpression(t.memberExpression(t.callExpression(t.memberExpression(t.callExpression(t.memberExpression(callExpression.node, t.identifier("split"), false), [t.stringLiteral(" ")]), t.identifier("map")), [t.arrowFunctionExpression([t.identifier("i")], t.memberExpression(cssmodule, t.identifier("i"), true))]), t.identifier("join"), false), [t.stringLiteral(" ")]));
};
var handleBinaryExpressionProp = function handleBinaryExpressionProp(prop, node, scope, file) {
if (prop.value.left.type === 'Literal' || prop.value.right.type === 'Literal') {
var left = _handleBinaryExpression(prop.value.left);
var right = _handleBinaryExpression(prop.value.right);
prop.value.left = left;
prop.value.right = right;
var updateClassName = function updateClassName(value, cssmodule) {
if (t.isStringLiteral(value)) {
value.replaceWith(computeClassName(value, cssmodule));
} else if (t.isIdentifier(value) || t.isMemberExpression(value)) {
value.replaceWith(computeClassName(value, cssmodule));
} else if (t.isCallExpression(value)) {
replaceCallExpression(value, cssmodule);
} else if (t.isObjectProperty(value)) {
updateClassName(value.get("value"), cssmodule);
} else if (t.isConditionalExpression(value)) {
updateClassName(value.get("consequent"), cssmodule);
updateClassName(value.get("alternate"), cssmodule);
} else if (t.isLogicalExpression(value)) {
updateClassName(value.get("left"), cssmodule);
updateClassName(value.get("right"), cssmodule);
} else {
warn('Unhandled BinaryExpression property at %s#%s.', file.opts.filename, prop.loc.start.row);
console.log("TODO(updateClassName): handle %s", value.type);
}
};
return prop;
if (prop.value.right.type !== 'Literal') {
prop.value.right = t.memberExpression(cssModuleId, prop.value.right, true);
} else {
prop.value.right = handleProp({ key: { name: 'className' }, value: prop.value.right }, node, scope, file).value;
/**
* Updates a JSX className value with the most appropriate CSS Module lookup.
*
* @param {Path} value <jsx className={value} />
* @param {Node<Identifier>} cssmodule cssmodule identifier
*/
var updateJSXClassName = function updateJSXClassName(value, cssmodule) {
if (!t.isJSXExpressionContainer(value)) {
value.replaceWith({
type: "JSXExpressionContainer",
expression: value.node
});
}
updateClassName(value.get("expression"), cssmodule);
};
var handleProp = function handleProp(prop, node, scope, file) {
// pick up className, activeClassName, hoverClassName, etc
if (!/classname/i.test(prop.key.name)) return prop;
var buildRequire = (0, _babelTemplate2.default)("\n const IMPORT_NAME = require(SOURCE);\n ");
if (prop.value.type === 'Identifier') {
var binding = scope.bindings[prop.value.name];
// TODO: template doesn't work for import.
var buildImport = function buildImport(_ref2) {
var IMPORT_NAME = _ref2.IMPORT_NAME;
var SOURCE = _ref2.SOURCE;
return t.importDeclaration([t.importDefaultSpecifier(IMPORT_NAME)], SOURCE);
};
if (!binding) {
prop.value = computedOrIdentifier(prop.value);
return prop;
}
return {
visitor: {
JSXAttribute: function JSXAttribute(path, state) {
if (state[BAIL_OUT]) {
return;
}
var path = binding.path;
if (path.get("name").node.name !== "className") {
return;
}
if (path.node.init.value) {
mutateStringPropertyToCSSModule(prop);
} else if (isClassnames(path.node.init, scope)) {
mutateClassnamesCall(path.node.init, scope);
}
if (!state.cssModuleId) {
state.cssModuleId = path.scope.generateUidIdentifier(ROOT_CSSNAMES_IDENTIFIER);
}
return prop;
}
updateJSXClassName(path.get("value"), state.cssModuleId);
},
CallExpression: function CallExpression(path, state) {
if (state[BAIL_OUT]) {
return;
}
if (prop.value.value) {
mutateStringPropertyToCSSModule(prop);
} else if (isClassnames(prop.value, scope)) {
mutateClassnamesCall(prop.value, scope);
} else if (prop.value.type === 'BinaryExpression') {
return handleBinaryExpressionProp(prop, node, scope, file);
} else if (prop.value.type === 'ConditionalExpression') {
prop.value.consequent = handleProp({ key: { name: 'className' },
value: prop.value.consequent
}, node, scope, file).value;
var isCreateElementCall = matchesPatterns(path.get("callee"), ["React.createElement", "_react2.default.createElement"]);
prop.value.alternate = handleProp({ key: { name: 'className' },
value: prop.value.alternate
}, node, scope, file).value;
if (!isCreateElementCall) {
return;
}
return prop;
} else if (prop.value.type === 'CallExpression') {
// simplistic `myIdentifier.join(' ')` detection
// transforms to `myIdentifier.map(a => _cssmodules[a]).join(' ')`
if (
// TODO: could lookup the callee.object value and follow the Identifier
// or ensure it is an ArrayExpresion
prop.value.callee.property.name === 'join' && prop.value.arguments[0].value === ' ') {
prop.value = t.callExpression(t.memberExpression(t.callExpression(t.memberExpression(prop.value.callee.object, t.identifier('map')), [t.arrowFunctionExpression([t.identifier('a')], t.memberExpression(cssModuleId, t.identifier('a'), true))]), prop.value.callee.property), prop.value.arguments);
}
return prop;
} else {
if (prop.value.type === 'MemberExpression' || prop.value.type === 'CallExpression' || prop.value.type === 'Literal' && prop.value.value === '') {
return prop;
}
if (!state.cssModuleId) {
state.cssModuleId = path.scope.generateUidIdentifier(ROOT_CSSNAMES_IDENTIFIER);
}
warn('\n\n' + '==================================================\n' + 'WARNING: unhandled className in %s#%s.\n', file.opts.filename, node.loc.start.line);
}
var updateProperty = function updateProperty(property) {
if (property.node.key.name === "className") {
updateClassName(property.get("value"), state.cssModuleId);
}
};
return prop;
};
return new Plugin('css-moduleify-plugin', {
visitor: {
CallExpression: function CallExpression(node, parent, scope, file) {
if (!this.state.shouldTransform) return;
if (!node.callee.property || (node.callee.property.name !== 'createElement' || node.callee.object.name === 'document')) return;
var properties = node.arguments[1].properties;
if (properties) {
node.arguments[1].properties = properties.map(function (prop) {
return handleProp(prop, node, scope, file);
var argument = path.get("arguments")[1];
if (t.isNullLiteral(argument)) {
return;
} else if (t.isCallExpression(argument)) {
argument.get("arguments").forEach(function (arg) {
if (t.isObjectExpression(arg)) {
arg.get("properties").forEach(updateProperty);
}
});
return;
} else if (t.isObjectExpression(argument)) {
argument.get("properties").forEach(updateProperty);
} else {
// an ObjectSpreadProperty was used in the source
if (node.arguments[1].type === 'CallExpression' && node.arguments[1].callee.name.indexOf('extends') !== -1) {
node.arguments[1].arguments = node.arguments[1].arguments.map(function (prop) {
if (prop.type === 'ObjectExpression') {
prop.properties = prop.properties.map(function (prop) {
return handleProp(prop, node, scope, file);
});
}
return prop;
});
}
console.log("TODO(CallExpression Visitor): handle %s", argument.node.type);
}

@@ -294,35 +253,38 @@ },

Program: {
enter: function enter(node, parent, scope, file) {
var opts = getPluginOptions(file);
if (new RegExp(opts.path).test(file.opts.filename)) {
// console.log('Program file', file.opts.filename);
this.state.shouldTransform = true;
cssModuleId = scope.generateUidIdentifier('cssmodule');
enter: function enter(path, state) {
if (!state.opts.path || new RegExp(state.opts.path).test(state.file.opts.filename)) {
// detect if this is likely compiled source
if (path.scope.getBinding("_interopRequireDefault")) {
state.transformingOutput = true;
state.cssModuleId = path.scope.generateUidIdentifier(ROOT_CSSNAMES_IDENTIFIER);
}
} else {
state[BAIL_OUT] = true;
}
},
exit: function exit(path, state) {
if (state[BAIL_OUT]) {
return;
}
exit: function exit(node, parent, scope, file) {
if (this.state.shouldTransform !== true) return;
if (state.cssModuleId) {
var importOpts = {
IMPORT_NAME: state.cssModuleId,
SOURCE: t.stringLiteral((0, _path.join)(process.env.NODE_ENV === "test" ? "" : process.cwd(), state.opts.cssmodule))
};
var _getPluginOptions = getPluginOptions(file);
var firstChild = path.get("body")[0];
var leadingComments = firstChild.node.leadingComments;
var cssmodule = _getPluginOptions.cssmodule;
delete firstChild.node.leadingComments;
var cssRequire = t.variableDeclaration('var', [t.variableDeclarator(cssModuleId, t.callExpression(t.identifier('require'), [t.literal(process.cwd() + '/' + cssmodule)]))]);
var insertIndex = undefined;
node.body.find(function (n, i) {
var result = n.type === 'VariableDeclaration' && n.declarations[0].init.type === 'CallExpression' && n.declarations[0].init.callee.name === 'require';
insertIndex = i;
return result;
});
node.body.splice(insertIndex, 0, cssRequire);
// currently we’re using the heuristic if the module system is using
// commonjs then we'll export as commonjs
path.get("body")[0].insertBefore(state.opts.modules === "commonjs" || state.transformingOutput ? buildRequire(importOpts) : buildImport(importOpts));
path.get("body")[0].node.leadingComments = leadingComments;
}
}
}
}
});
};
module.exports = exports['default'];
};
};
{
"name": "babel-plugin-react-cssmoduleify",
"version": "0.9.5",
"version": "1.0.0-beta.4",
"description": "Babel plugin to transform traditional classNames to CSS Modules",
"main": "lib/index.js",
"jsnext:main": "index.js",
"jsnext:main": "src/index.js",
"scripts": {
"build": "babel index.js -o lib/index.js",
"build": "babel src/ --out-dir lib/",
"prepublish": "npm run build",
"test": "echo \"Error: no test specified\" && exit 1"
"lint": "eslint .",
"compile-tests": "babel --presets es2015,react test/fixtures/jsx/*/ --out-dir test/fixtures/compiled",
"pretest": "npm run build && npm run compile-tests",
"test": "mocha ./test/index.js"
},
"files": [
"lib",
"index.js"
"src"
],

@@ -24,3 +27,3 @@ "repository": {

"css",
"modules"
"css-modules"
],

@@ -33,5 +36,21 @@ "author": "Dustan Kasten <dustan.kasten@gmail.com>",

"homepage": "https://github.com/walmartreact/babel-plugin-react-cssmoduleify#readme",
"dependencies": {
"array-find": "^1.0.0",
"babel-template": "^6.3.13"
},
"devDependencies": {
"babel": "^5.8.29"
"assert-transform": "github:walmartreact/assert-transform",
"babel-cli": "^6.4.0",
"babel-core": "^6.4.0",
"babel-eslint": "^4.1.6",
"babel-plugin-syntax-flow": "^6.3.13",
"babel-plugin-syntax-jsx": "^6.3.13",
"babel-plugin-transform-flow-strip-types": "^6.4.0",
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"eslint": "^1.10.3",
"eslint-config-defaults": "^7.1.1",
"eslint-plugin-filenames": "^0.2.0",
"mocha": "^2.3.4"
}
}
# babel-plugin-react-cssmoduleify
[![Build Status](https://travis-ci.org/walmartreact/babel-plugin-react-cssmoduleify.svg)](https://travis-ci.org/walmartreact/babel-plugin-react-cssmoduleify)
> **Note**: this plugin now requires Babel 6. To use the Babel 5 support ensure
> you continue using the pre 1.0 release.
For those who have tasted [CSS Modules](https://github.com/css-modules/css-modules)
it is hard to imagine life without it. At Walmart we have a large number of core
components that still use traditional CSS classNames and global CSS. To allow
for teams to take advantage of CSS Modules, this babel plugin is used to convert
all global styles into CSS Modules.
components that still use traditional CSS classNames and global CSS. This babel
plugin is used to convert all global styles into CSS Modules to allow teams to
opt-in to CSS Modules.
Please note this is a work in progress and does not account for all JavaScript
constructs yet. It is undergoing the “trial-by-fire” support methodology. If we
detect a currently-unsupported construct we will print a warning to the console
with a link to report it at our issue tracker. Please include as much code as
possible to make it easier for us to add support.
Previously this attempted to be rather aggressive in it’s resolving of className
calls. The current implementation is much simpler and therefore should also
support more use cases. Currently `classNames` must be a `string`, so we can
take any complex assignment and do the lookup on the fly.
It detects the correct `className` calls in both JSX, React.createElement, and
compiled JSX output.

@@ -25,10 +31,10 @@ ## Usage

"plugins": [
"react-cssmoduleify",
["babel-plugin-react-cssmoduleify", {
// this string is applied to the current path to transform or bail out.
// This is because this plugin is often used on external code.
"path": "node_modules/regex-path-"
"cssmodule": "client/styles/base.styl"
"modules": "es6"
}]
],
"extra": {
"react-cssmoduleify": {
"path": "node_modules/@walmart/wmreact-",
"cssmodule": "client/styles/base.styl"
}
},
}

@@ -39,162 +45,10 @@ ```

* `path`: Regex to test if a file should be transformed.
* `cssmodule`: path from `process.cwd()` to global CSS file
* `path`: `string`: string applied as a regex to each compiled file
* `cssmodule`: `string`: path from `process.cwd()` to global CSS file
* `modules`: `"es6"|"commonjs"` the type of module system cssmodule should be required as.
## Example
## Examples
This currently works on only the babel compiled JavaScript and not the original
source. Adding support the original source would likely be fairly trivial. The
following example demonstrates the modifications on the babel output of a
React component.
Look at the unit tests.
### Before
```js
"use strict";
var _react = require("react");
var _react2 = _interopRequireDefault(_react);
var MyComponent = (function (_React$Component) {
_inherits(MyComponent, _React$Component);
function MyComponent(props) {
_classCallCheck(this, MyComponent);
_get(Object.getPrototypeOf(MyComponent.prototype), "constructor", this).call(this, props);
}
_createClass(MyComponent, [{
key: "_renderFlyoutConent",
value: function _renderFlyoutConent() {
if (this.state.loading) {
return _react2["default"].createElement(
"div",
{ className: "lists-spinner" },
_react2["default"].createElement(_walmartWmreactContainers.Spinner, { loading: true })
);
}
return _react2["default"].createElement(_addToListFlyout2["default"], { lists: this.state.lists, isSignedIn: this.props.isSignedIn });
}
}, {
key: "render",
value: function render() {
var addToListTrigger = _react2["default"].createElement(
_walmartWmreactInteractive.Button,
{
className: (0, _classnames2["default"])("btn-inverse")
},
this.props.label
);
if (this.props.addToListTrigger) {
addToListTrigger = cloneElement(this.props.addToListTrigger, {});
}
return _react2["default"].createElement(
"div",
{ className: (0, _classnames2["default"])(this.props.className) },
_react2["default"].createElement(
_walmartWmreactContainers.Flyout,
{
trigger: addToListTrigger,
direction: this.props.direction,
onActiveChange: this._onAddToListClicked.bind(this)
},
this._renderFlyoutConent()
)
);
}
}]);
return MyComponent;
})(_react2["default"].Component);
MyComponent.propTypes = {
className: _react2["default"].PropTypes.string,
label: _react2["default"].PropTypes.string,
direction: _react2["default"].PropTypes.string,
isSignedIn: _react2["default"].PropTypes.bool,
addToListTrigger: _react2["default"].PropTypes.func
};
exports["default"] = MyComponent;
module.exports = exports["default"];
```
### After
```js
"use strict";
var _react = require("react");
var _cssmodules = require("/Users/dkasten/project/client/styles/base.styl");
var _react2 = _interopRequireDefault(_react);
var MyComponent = (function (_React$Component) {
_inherits(MyComponent, _React$Component);
function MyComponent(props) {
_classCallCheck(this, MyComponent);
_get(Object.getPrototypeOf(MyComponent.prototype), "constructor", this).call(this, props);
}
_createClass(MyComponent, [{
key: "_renderFlyoutConent",
value: function _renderFlyoutConent() {
if (this.state.loading) {
return _react2["default"].createElement(
"div",
{ className: _cssmodules["lists-spinner"] },
_react2["default"].createElement(_walmartWmreactContainers.Spinner, { loading: true })
);
}
return _react2["default"].createElement(_addToListFlyout2["default"], { lists: this.state.lists, isSignedIn: this.props.isSignedIn });
}
}, {
key: "render",
value: function render() {
var addToListTrigger = _react2["default"].createElement(
_walmartWmreactInteractive.Button,
{
className: (0, _classnames2["default"])(_cssmodules["btn-inverse"])
},
this.props.label
);
if (this.props.addToListTrigger) {
addToListTrigger = cloneElement(this.props.addToListTrigger, {});
}
return _react2["default"].createElement(
"div",
{ className: (0, _classnames2["default"])(this.props.className) },
_react2["default"].createElement(
_walmartWmreactContainers.Flyout,
{
trigger: addToListTrigger,
direction: this.props.direction,
onActiveChange: this._onAddToListClicked.bind(this)
},
this._renderFlyoutConent()
)
);
}
}]);
return MyComponent;
})(_react2["default"].Component);
MyComponent.propTypes = {
className: _react2["default"].PropTypes.string,
label: _react2["default"].PropTypes.string,
direction: _react2["default"].PropTypes.string,
isSignedIn: _react2["default"].PropTypes.bool,
addToListTrigger: _react2["default"].PropTypes.func
};
exports["default"] = MyComponent;
module.exports = exports["default"];
```
## Caveats

@@ -207,26 +61,5 @@

## MIT License
## License
The MIT License (MIT)
Copyright (c) 2015 Walmart Labs
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.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc