-
-
Notifications
You must be signed in to change notification settings - Fork 162
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* fix: handle spread * test: handle spread * test: add test case for spread * spread: remove keys exclusion, avoid falsy values * refactor: handle spread separated in another file
- Loading branch information
1 parent
70550bc
commit 05c2683
Showing
8 changed files
with
191 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// @flow | ||
|
||
import { | ||
Expression, | ||
memberExpression, | ||
binaryExpression, | ||
stringLiteral, | ||
logicalExpression, | ||
identifier | ||
} from '@babel/types'; | ||
import optionsDefaults from './schemas/optionsDefaults'; | ||
|
||
const createSpreadMapper = (path: *, stats: *): { [destinationName: string]: Expression } => { | ||
const result = {}; | ||
|
||
let {attributeNames} = optionsDefaults; | ||
|
||
if (stats.opts && stats.opts.attributeNames) { | ||
attributeNames = Object.assign({}, attributeNames, stats.opts.attributeNames); | ||
} | ||
|
||
const attributes = Object | ||
.entries(attributeNames) | ||
.filter((pair) => { | ||
return pair[1]; | ||
}); | ||
|
||
const attributeKeys = attributes.map((pair) => { | ||
return pair[0]; | ||
}); | ||
|
||
path.traverse({ | ||
JSXSpreadAttribute (spreadPath: *) { | ||
const spread = spreadPath.node; | ||
|
||
for (const attributeKey of attributeKeys) { | ||
const destinationName = attributeNames[attributeKey]; | ||
|
||
if (result[destinationName]) { | ||
result[destinationName] = binaryExpression( | ||
'+', | ||
result[destinationName], | ||
binaryExpression( | ||
'+', | ||
stringLiteral(' '), | ||
logicalExpression( | ||
'||', | ||
memberExpression( | ||
spread.argument, | ||
identifier(destinationName), | ||
), | ||
stringLiteral('') | ||
) | ||
), | ||
); | ||
} else { | ||
result[destinationName] = logicalExpression( | ||
'||', | ||
memberExpression( | ||
spread.argument, | ||
identifier(destinationName), | ||
), | ||
stringLiteral('') | ||
); | ||
} | ||
} | ||
} | ||
}); | ||
|
||
return result; | ||
}; | ||
|
||
export default createSpreadMapper; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// @flow | ||
|
||
import { | ||
Expression, | ||
isStringLiteral, | ||
isJSXExpressionContainer, | ||
jsxExpressionContainer, | ||
binaryExpression, | ||
stringLiteral | ||
} from '@babel/types'; | ||
|
||
const handleSpreadClassName = ( | ||
path: *, | ||
destinationName: string, | ||
classNamesFromSpread: Expression | ||
) => { | ||
const destinationAttribute = path.node.openingElement.attributes | ||
.find((attribute) => { | ||
return typeof attribute.name !== 'undefined' && attribute.name.name === destinationName; | ||
}); | ||
|
||
if (!destinationAttribute) { | ||
return; | ||
} | ||
|
||
if (isStringLiteral(destinationAttribute.value)) { | ||
destinationAttribute.value = jsxExpressionContainer( | ||
binaryExpression( | ||
'+', | ||
destinationAttribute.value, | ||
binaryExpression( | ||
'+', | ||
stringLiteral(' '), | ||
classNamesFromSpread, | ||
) | ||
) | ||
); | ||
} else if (isJSXExpressionContainer(destinationAttribute.value)) { | ||
destinationAttribute.value = jsxExpressionContainer( | ||
binaryExpression( | ||
'+', | ||
destinationAttribute.value.expression, | ||
binaryExpression( | ||
'+', | ||
stringLiteral(' '), | ||
classNamesFromSpread | ||
) | ||
) | ||
); | ||
} | ||
}; | ||
|
||
export default handleSpreadClassName; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
test/fixtures/react-css-modules/handle spread attributes/foo.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.a {} |
22 changes: 22 additions & 0 deletions
22
test/fixtures/react-css-modules/handle spread attributes/input.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import './foo.css'; | ||
|
||
const rest = {}; | ||
|
||
<div {...rest} styleName="a" className="b"></div>; | ||
|
||
<div {...rest} styleName="a"></div>; | ||
|
||
<div {...rest} activeClassName={this.props.activeClassName} activeStyleName="a" styleName="a"></div>; | ||
|
||
<div {...rest} activeStyleName="a" activeClassName="b"></div>; | ||
|
||
// Should be okay if rest is put on last | ||
<div styleName="a" {...rest}></div>; | ||
|
||
const rest2 = {}; | ||
|
||
<div {...rest} {...rest2} styleName="a"></div>; | ||
|
||
// Should not do anything | ||
<div {...rest} {...rest2}></div>; | ||
<div {...rest} {...rest2} className="b"></div>; |
13 changes: 13 additions & 0 deletions
13
test/fixtures/react-css-modules/handle spread attributes/options.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"plugins": [ | ||
[ | ||
"../../../../src", | ||
{ | ||
"generateScopedName": "[name]__[local]", | ||
"attributeNames": { | ||
"activeStyleName": "activeClassName" | ||
} | ||
} | ||
] | ||
] | ||
} |
16 changes: 16 additions & 0 deletions
16
test/fixtures/react-css-modules/handle spread attributes/output.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
"use strict"; | ||
|
||
require("./foo.css"); | ||
|
||
const rest = {}; | ||
<div {...rest} className={"b foo__a" + (" " + (rest.className || ""))}></div>; | ||
<div {...rest} className={"foo__a" + (" " + (rest.className || ""))}></div>; | ||
<div {...rest} activeClassName={((void 0).props.activeClassName ? (void 0).props.activeClassName + " " : "") + "foo__a" + (" " + (rest.activeClassName || ""))} className={"foo__a" + (" " + (rest.className || ""))}></div>; | ||
<div {...rest} activeClassName={"b foo__a" + (" " + (rest.activeClassName || ""))}></div>; // Should be okay if rest is put on last | ||
|
||
<div className={"foo__a" + (" " + (rest.className || ""))} {...rest}></div>; | ||
const rest2 = {}; | ||
<div {...rest} {...rest2} className={"foo__a" + (" " + ((rest.className || "") + (" " + (rest2.className || ""))))}></div>; // Should not do anything | ||
|
||
<div {...rest} {...rest2}></div>; | ||
<div {...rest} {...rest2} className="b"></div>; |