babel-plugin-transform-react-styled-components-qa
Advanced tools
Comparing version 1.0.3 to 2.0.0
@@ -8,47 +8,47 @@ import pluginTester from 'babel-plugin-tester' | ||
const common = { | ||
plugin, | ||
pluginName: 'babel-plugin-transform-react-styled-components-qa', | ||
tests: [ | ||
{ | ||
fixture: path.join(__dirname, '__fixtures__', 'code'), | ||
snapshot: true | ||
} | ||
] | ||
plugin, | ||
pluginName: 'babel-plugin-transform-react-styled-components-qa', | ||
tests: [ | ||
{ | ||
fixture: path.join(__dirname, '__fixtures__', 'code'), | ||
snapshot: true, | ||
}, | ||
], | ||
} | ||
pluginTester({ | ||
...common, | ||
title: 'without plugin options' | ||
...common, | ||
title: 'without plugin options', | ||
}) | ||
pluginTester({ | ||
...common, | ||
title: 'format kebab', | ||
pluginOptions: { | ||
format: 'kebab' | ||
} | ||
...common, | ||
title: 'format kebab', | ||
pluginOptions: { | ||
format: 'kebab', | ||
}, | ||
}) | ||
pluginTester({ | ||
...common, | ||
title: 'format camel', | ||
pluginOptions: { | ||
format: 'camel' | ||
} | ||
...common, | ||
title: 'format camel', | ||
pluginOptions: { | ||
format: 'camel', | ||
}, | ||
}) | ||
pluginTester({ | ||
...common, | ||
title: 'format snake', | ||
pluginOptions: { | ||
format: 'snake' | ||
} | ||
...common, | ||
title: 'format snake', | ||
pluginOptions: { | ||
format: 'snake', | ||
}, | ||
}) | ||
pluginTester({ | ||
...common, | ||
title: 'custom attrubute', | ||
pluginOptions: { | ||
attribute: 'data-wn-qa' | ||
} | ||
...common, | ||
title: 'custom attrubute', | ||
pluginOptions: { | ||
attribute: 'data-wn-qa', | ||
}, | ||
}) |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,4 +6,19 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.default = _default; | ||
exports.default = function ({ types: t }) { | ||
var _options = require("./options"); | ||
var babelType = _interopRequireWildcard(require("@babel/types")); | ||
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; if (obj != null) { var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } | ||
/** | ||
* | ||
* @param {{ types: typeof babelType }} | ||
*/ | ||
function _default({ | ||
types: t | ||
}) { | ||
return { | ||
@@ -19,12 +34,14 @@ visitor: { | ||
const format = (0, _options.getComponentNameFormatter)(state.opts); | ||
const attributeName = (0, _options.getAttributeName)(state.opts); | ||
const attributeName = (0, _options.getAttributeName)(state.opts); // tag part of the template literal | ||
// tag part of the template literal | ||
const tag = init.tag; | ||
const tag = init.tag; // styled.div , styled.p , styled[<computed_value>], etc | ||
// styled.div , styled.p , styled[<computed_value>], etc | ||
if (t.isMemberExpression(tag)) { | ||
const { object, property } = tag; | ||
const { | ||
object, | ||
property | ||
} = tag; | ||
if (object.name === 'styled') { | ||
init.tag = t.callExpression(t.memberExpression(t.memberExpression(object, property, tag.computed), t.identifier('attrs')), [t.objectExpression([t.objectProperty(t.stringLiteral(attributeName), t.stringLiteral(format(path.node.id.name)))])]); | ||
init.tag = t.callExpression(t.memberExpression(t.memberExpression(object, property, tag.computed), t.identifier('attrs')), [t.arrowFunctionExpression([t.identifier('props')], t.blockStatement([t.returnStatement(t.objectExpression([t.objectProperty(t.stringLiteral(attributeName), t.logicalExpression('||', t.memberExpression(t.identifier('props'), t.stringLiteral(attributeName), true), t.stringLiteral(format(path.node.id.name))))]))]))]); | ||
} | ||
@@ -36,10 +53,9 @@ } | ||
if (t.isMemberExpression(tag.callee) && t.isIdentifier(tag.callee.property) && tag.callee.property.name === 'attrs' && t.isMemberExpression(tag.callee.object) && t.isIdentifier(tag.callee.object.object) && tag.callee.object.object.name === 'styled') { | ||
tag.arguments = [t.objectExpression(tag.arguments[0].properties.concat(t.objectProperty(t.stringLiteral(attributeName), t.stringLiteral(format(path.node.id.name)))))]; | ||
tag.arguments = [t.arrowFunctionExpression([t.identifier('props')], t.blockStatement([t.returnStatement(t.objectExpression(tag.arguments[0].properties.concat(t.objectProperty(t.stringLiteral(attributeName), t.logicalExpression('||', t.memberExpression(t.identifier('props'), t.stringLiteral(attributeName), true), t.stringLiteral(format(path.node.id.name)))))))]))]; | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
}; | ||
var _options = require('./options'); | ||
} |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,30 +6,25 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.getComponentNameFormatter = exports.getAttributeName = undefined; | ||
exports.getComponentNameFormatter = exports.getAttributeName = void 0; | ||
var _lodash = require('lodash.isstring'); | ||
var _lodash = _interopRequireDefault(require("lodash.isstring")); | ||
var _lodash2 = _interopRequireDefault(_lodash); | ||
var _lodash2 = _interopRequireDefault(require("lodash.camelcase")); | ||
var _lodash3 = require('lodash.camelcase'); | ||
var _lodash3 = _interopRequireDefault(require("lodash.kebabcase")); | ||
var _lodash4 = _interopRequireDefault(_lodash3); | ||
var _lodash4 = _interopRequireDefault(require("lodash.snakecase")); | ||
var _lodash5 = require('lodash.kebabcase'); | ||
var _lodash6 = _interopRequireDefault(_lodash5); | ||
var _lodash7 = require('lodash.snakecase'); | ||
var _lodash8 = _interopRequireDefault(_lodash7); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
const getAttributeName = exports.getAttributeName = opts => (0, _lodash2.default)(opts.attribute) ? opts.attribute : 'data-qa'; | ||
const getAttributeName = opts => (0, _lodash.default)(opts.attribute) ? opts.attribute : 'data-qa'; | ||
exports.getAttributeName = getAttributeName; | ||
const formattersByName = { | ||
camel: _lodash4.default, | ||
kebab: _lodash6.default, | ||
snake: _lodash8.default | ||
camel: _lodash2.default, | ||
kebab: _lodash3.default, | ||
snake: _lodash4.default | ||
}; | ||
const getComponentNameFormatter = exports.getComponentNameFormatter = opts => (0, _lodash2.default)(opts.format) && opts.format in formattersByName ? formattersByName[opts.format] : _lodash6.default; | ||
const getComponentNameFormatter = opts => (0, _lodash.default)(opts.format) && opts.format in formattersByName ? formattersByName[opts.format] : _lodash3.default; | ||
exports.getComponentNameFormatter = getComponentNameFormatter; |
{ | ||
"name": "babel-plugin-transform-react-styled-components-qa", | ||
"version": "1.0.3", | ||
"version": "2.0.0", | ||
"description": "Add data-qa property to styled-components via .attrs using the component name", | ||
@@ -28,5 +28,7 @@ "main": "lib/index.js", | ||
"devDependencies": { | ||
"babel-cli": "^6.26.0", | ||
"babel-plugin-tester": "^5.0.0", | ||
"babel-preset-env": "^1.6.1", | ||
"@babel/cli": "7.6.4", | ||
"@babel/core": "7.6.4", | ||
"@babel/types": "^7.6.3", | ||
"babel-plugin-tester": "7.0.1", | ||
"babel-preset-env": "7.0.0-beta.3", | ||
"eslint": "^4.19.0", | ||
@@ -39,3 +41,3 @@ "eslint-config-standard": "^11.0.0", | ||
"eslint-plugin-standard": "^3.0.1", | ||
"jest": "^22.4.2" | ||
"jest": "25.0.0" | ||
}, | ||
@@ -42,0 +44,0 @@ "dependencies": { |
@@ -8,54 +8,66 @@ # babel-plugin-transform-react-styled-components-qa | ||
### Standard HTML Tags | ||
In | ||
```js | ||
const Component = styled.p` | ||
color: red; | ||
` | ||
color: red; | ||
`; | ||
``` | ||
Out | ||
```js | ||
const Component = styled.p.attrs({ | ||
"data-qa": "Component" | ||
})` | ||
color: red; | ||
` | ||
const Component = styled.p.attrs(props => ({ | ||
"data-qa": props["data-qa"] || "Component" | ||
}))` | ||
color: red; | ||
`; | ||
``` | ||
### Computed Property is also supported | ||
In | ||
```js | ||
const tagName = 'h1' | ||
const tagName = "h1"; | ||
const Component = styled[tagName]` | ||
background: 'pink'; | ||
` | ||
background: "pink"; | ||
`; | ||
``` | ||
Out | ||
```js | ||
const tagName = 'h1' | ||
const Component = styled[tagName].attrs({ | ||
"data-qa": "Component" | ||
})` | ||
background: 'pink'; | ||
` | ||
const tagName = "h1"; | ||
const Component = styled[tagName].attrs(props => ({ | ||
"data-qa": props["data-qa"] || "Component" | ||
}))` | ||
background: "pink"; | ||
`; | ||
``` | ||
### `data-qa` is append after other attributes defined by users | ||
In | ||
```js | ||
const PasswordInput = styled.input.attrs({ | ||
type: 'password' | ||
type: "password" | ||
})` | ||
font-size: 14px; | ||
line-height: 2em; | ||
` | ||
font-size: 14px; | ||
line-height: 2em; | ||
`; | ||
``` | ||
Out | ||
```js | ||
const PasswordInput = styled.input.attrs({ | ||
type: 'password', | ||
"data-qa": "PasswordInput" | ||
})` | ||
font-size: 14px; | ||
line-height: 2em; | ||
` | ||
const PasswordInput = styled.input.attrs(props => ({ | ||
type: "password", | ||
"data-qa": props["data-qa"] || "PasswordInput" | ||
}))` | ||
font-size: 14px; | ||
line-height: 2em; | ||
`; | ||
``` | ||
@@ -69,2 +81,3 @@ | ||
#### .babelrc | ||
``` | ||
@@ -86,6 +99,10 @@ { | ||
## Options | ||
#### attribute : (string) | ||
The attribute name to be used instead of `data-qa`. | ||
#### format : (string) | ||
**Support values:** `kebab`, `camel`, `snake` \ | ||
**Default value:** `kebab` | ||
**Default value:** `kebab` |
149
src/index.js
import { getAttributeName, getComponentNameFormatter } from './options' | ||
export default function ({ types: t }) { | ||
return { | ||
visitor: { | ||
VariableDeclarator (path, state) { | ||
const init = path.node.init | ||
import * as babelType from '@babel/types' | ||
if (!t.isTaggedTemplateExpression(init)) { | ||
return | ||
} | ||
/** | ||
* | ||
* @param {{ types: typeof babelType }} | ||
*/ | ||
export default function({ types: t }) { | ||
return { | ||
visitor: { | ||
VariableDeclarator(path, state) { | ||
const init = path.node.init | ||
const format = getComponentNameFormatter(state.opts) | ||
const attributeName = getAttributeName(state.opts) | ||
if (!t.isTaggedTemplateExpression(init)) { | ||
return | ||
} | ||
// tag part of the template literal | ||
const tag = init.tag | ||
const format = getComponentNameFormatter(state.opts) | ||
const attributeName = getAttributeName(state.opts) | ||
// styled.div , styled.p , styled[<computed_value>], etc | ||
if (t.isMemberExpression(tag)) { | ||
const { object, property } = tag | ||
if (object.name === 'styled') { | ||
init.tag = t.callExpression( | ||
t.memberExpression( | ||
t.memberExpression(object, property, tag.computed), | ||
t.identifier('attrs') | ||
), | ||
[ | ||
t.objectExpression([ | ||
t.objectProperty( | ||
t.stringLiteral(attributeName), | ||
t.stringLiteral(format(path.node.id.name)) | ||
) | ||
]) | ||
] | ||
) | ||
} | ||
} | ||
// tag part of the template literal | ||
const tag = init.tag | ||
if (t.isCallExpression(tag)) { | ||
// styled.div.attrs({}) or styled[tag].attrs({}) | ||
if ( | ||
t.isMemberExpression(tag.callee) && | ||
t.isIdentifier(tag.callee.property) && | ||
tag.callee.property.name === 'attrs' && | ||
t.isMemberExpression(tag.callee.object) && | ||
t.isIdentifier(tag.callee.object.object) && | ||
tag.callee.object.object.name === 'styled' | ||
) { | ||
tag.arguments = [ | ||
t.objectExpression( | ||
tag.arguments[0].properties.concat( | ||
t.objectProperty( | ||
t.stringLiteral(attributeName), | ||
t.stringLiteral(format(path.node.id.name)) | ||
) | ||
) | ||
) | ||
] | ||
} | ||
} | ||
} | ||
} | ||
} | ||
// styled.div , styled.p , styled[<computed_value>], etc | ||
if (t.isMemberExpression(tag)) { | ||
const { object, property } = tag | ||
if (object.name === 'styled') { | ||
init.tag = t.callExpression( | ||
t.memberExpression( | ||
t.memberExpression(object, property, tag.computed), | ||
t.identifier('attrs'), | ||
), | ||
[ | ||
t.arrowFunctionExpression( | ||
[t.identifier('props')], | ||
t.blockStatement([ | ||
t.returnStatement( | ||
t.objectExpression([ | ||
t.objectProperty( | ||
t.stringLiteral(attributeName), | ||
t.logicalExpression( | ||
'||', | ||
t.memberExpression( | ||
t.identifier('props'), | ||
t.stringLiteral(attributeName), | ||
true, | ||
), | ||
t.stringLiteral(format(path.node.id.name)), | ||
), | ||
), | ||
]), | ||
), | ||
]), | ||
), | ||
], | ||
) | ||
} | ||
} | ||
if (t.isCallExpression(tag)) { | ||
// styled.div.attrs({}) or styled[tag].attrs({}) | ||
if ( | ||
t.isMemberExpression(tag.callee) && | ||
t.isIdentifier(tag.callee.property) && | ||
tag.callee.property.name === 'attrs' && | ||
t.isMemberExpression(tag.callee.object) && | ||
t.isIdentifier(tag.callee.object.object) && | ||
tag.callee.object.object.name === 'styled' | ||
) { | ||
tag.arguments = [ | ||
t.arrowFunctionExpression( | ||
[t.identifier('props')], | ||
t.blockStatement([ | ||
t.returnStatement( | ||
t.objectExpression( | ||
tag.arguments[0].properties.concat( | ||
t.objectProperty( | ||
t.stringLiteral(attributeName), | ||
t.logicalExpression( | ||
'||', | ||
t.memberExpression( | ||
t.identifier('props'), | ||
t.stringLiteral(attributeName), | ||
true, | ||
), | ||
t.stringLiteral(format(path.node.id.name)), | ||
), | ||
), | ||
), | ||
), | ||
), | ||
]), | ||
), | ||
] | ||
} | ||
} | ||
}, | ||
}, | ||
} | ||
} |
@@ -7,13 +7,13 @@ import isString from 'lodash.isstring' | ||
export const getAttributeName = opts => | ||
isString(opts.attribute) ? opts.attribute : 'data-qa' | ||
isString(opts.attribute) ? opts.attribute : 'data-qa' | ||
const formattersByName = { | ||
camel: camelCase, | ||
kebab: kebabCase, | ||
snake: snakeCase | ||
camel: camelCase, | ||
kebab: kebabCase, | ||
snake: snakeCase, | ||
} | ||
export const getComponentNameFormatter = opts => | ||
isString(opts.format) && opts.format in formattersByName | ||
? formattersByName[opts.format] | ||
: kebabCase | ||
isString(opts.format) && opts.format in formattersByName | ||
? formattersByName[opts.format] | ||
: kebabCase |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
22833
222
106
13