forked from elastic/eui
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ESLint rule to validate
css
props are declared before{...spread}
…
…props (elastic#6257) * WIP. First pass at CSS before spread child props ESLint rule. * Refactoring CSS and spread child prop index calls. * Improving the error reporting message. * Renaming file for clarity. Adding first passing unit tests. * Focused on JSXElement, added unit tests, fixed failures in local linting." * Updating unit tests to pass before renaming. * Registering ESLint rule locally before adding unit tests. * Switched to JSXElement, and array of arrays. * Simplified logic, added unit tests, fixed failures. * Renamed temp arrays and refactored early returns for clarity. * Removing contentProps.css from cssContentStyles array.
- Loading branch information
Showing
12 changed files
with
304 additions
and
10 deletions.
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
module.exports = { | ||
meta: { | ||
type: 'problem', | ||
docs: { | ||
description: 'Enforce CSS props are declared before spread props', | ||
}, | ||
}, | ||
create: function (context) { | ||
const allElementsArr = []; | ||
|
||
return { | ||
JSXElement(node) { | ||
const attributesArr = []; | ||
node.openingElement.attributes.forEach((attribute) => | ||
attributesArr.push(attribute) | ||
); | ||
allElementsArr.push(attributesArr); | ||
}, | ||
'Program:exit'() { | ||
allElementsArr.forEach((elementArr) => { | ||
const cssPropsIndex = elementArr.findIndex( | ||
(node) => node.name && node.name.name === 'css' | ||
); | ||
if (cssPropsIndex === -1) return; | ||
|
||
const spreadPropsIndex = elementArr.findIndex( | ||
(node) => node.type === 'JSXSpreadAttribute' | ||
); | ||
if (spreadPropsIndex === -1) return; | ||
|
||
if (cssPropsIndex > spreadPropsIndex) { | ||
context.report({ | ||
loc: { | ||
line: elementArr[cssPropsIndex].loc.start.line, | ||
column: elementArr[cssPropsIndex].loc.start.column, | ||
}, | ||
message: | ||
'{{ identifier }}: CSS props must be declared before spread props.', | ||
data: { | ||
identifier: elementArr[spreadPropsIndex].argument.name, | ||
}, | ||
}); | ||
} | ||
}); | ||
}, | ||
}; | ||
}, | ||
}; |
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,245 @@ | ||
import rule from './css_before_spread_props.js'; | ||
const RuleTester = require('eslint').RuleTester; | ||
|
||
const ruleTester = new RuleTester({ | ||
parser: require.resolve('babel-eslint'), | ||
}); | ||
|
||
const valid = [ | ||
{ | ||
code: `<a | ||
css={cssStyles} | ||
{...rest} | ||
> | ||
{buttonIcon} | ||
</a> | ||
`, | ||
}, | ||
{ | ||
code: `<a css={cssStyles}> | ||
{buttonIcon} | ||
</a> | ||
`, | ||
}, | ||
{ | ||
code: `<a {...rest}> | ||
{buttonIcon} | ||
</a> | ||
`, | ||
}, | ||
{ | ||
code: `<nav {...rest}> | ||
<ol | ||
className="euiBreadcrumbs__list" | ||
css={cssBreadcrumbsListStyles} | ||
> | ||
{breadcrumbChildren} | ||
</ol> | ||
</nav> | ||
`, | ||
}, | ||
{ | ||
code: `<nav {...rest}> | ||
<ol css={cssBreadcrumbsListStyles}> | ||
{breadcrumbChildren} | ||
</ol> | ||
</nav> | ||
`, | ||
}, | ||
{ | ||
code: `<nav {...rest}> | ||
<ol {...rest}> | ||
{breadcrumbChildren} | ||
</ol> | ||
</nav> | ||
`, | ||
}, | ||
{ | ||
code: `<EuiLink | ||
ref={ref} | ||
css={cssStyles} | ||
{...rest} | ||
> | ||
{text} | ||
</EuiLink> | ||
`, | ||
}, | ||
{ | ||
code: `<EuiLink | ||
ref={ref} | ||
css={cssStyles} | ||
{...rest} | ||
> | ||
Text string | ||
</EuiLink> | ||
`, | ||
}, | ||
]; | ||
|
||
const invalid = [ | ||
{ | ||
code: `<a | ||
{...rest} | ||
css={cssStyles} | ||
> | ||
{buttonIcon} | ||
</a> | ||
`, | ||
errors: [ | ||
{ | ||
message: 'rest: CSS props must be declared before spread props.', | ||
}, | ||
], | ||
}, | ||
{ | ||
code: `<nav {...rest}> | ||
<ol | ||
{...rest} | ||
css={cssBreadcrumbsListStyles} | ||
> | ||
{breadcrumbChildren} | ||
</ol> | ||
</nav> | ||
`, | ||
errors: [ | ||
{ | ||
message: 'rest: CSS props must be declared before spread props.', | ||
}, | ||
], | ||
}, | ||
{ | ||
code: `<nav> | ||
<ol | ||
{...rest} | ||
css={cssBreadcrumbsListStyles} | ||
> | ||
{breadcrumbChildren} | ||
</ol> | ||
</nav> | ||
`, | ||
errors: [ | ||
{ | ||
message: 'rest: CSS props must be declared before spread props.', | ||
}, | ||
], | ||
}, | ||
{ | ||
code: `<EuiLink | ||
ref={ref} | ||
{...rest} | ||
css={cssStyles} | ||
> | ||
{text} | ||
</EuiLink> | ||
`, | ||
errors: [ | ||
{ | ||
message: 'rest: CSS props must be declared before spread props.', | ||
}, | ||
], | ||
}, | ||
{ | ||
code: `<EuiLink | ||
ref={ref} | ||
{...rest} | ||
css={cssStyles} | ||
> | ||
Text string | ||
</EuiLink> | ||
`, | ||
errors: [ | ||
{ | ||
message: 'rest: CSS props must be declared before spread props.', | ||
}, | ||
], | ||
}, | ||
{ | ||
code: `return !href && !onClick ? ( | ||
<EuiTextColor | ||
color={highlightLastBreadcrumb ? 'default' : 'subdued'} | ||
cloneElement | ||
{...restTextColor} | ||
css={cssStyles} | ||
> | ||
<span | ||
ref={ref} | ||
title={title} | ||
aria-current={ariaCurrent} | ||
className={classes} | ||
css={cssStyles} | ||
> | ||
{text} | ||
</span> | ||
</EuiTextColor> | ||
) : ( | ||
<EuiLink | ||
{...restLink} | ||
ref={ref} | ||
title={title} | ||
aria-current={ariaCurrent} | ||
className={classes} | ||
css={cssStyles} | ||
color={color || (highlightLastBreadcrumb ? 'text' : 'subdued')} | ||
onClick={onClick} | ||
href={href} | ||
rel={rel} | ||
> | ||
{text} | ||
</EuiLink> | ||
); | ||
`, | ||
errors: [ | ||
{ | ||
message: 'restTextColor: CSS props must be declared before spread props.', | ||
}, | ||
{ | ||
message: 'restLink: CSS props must be declared before spread props.', | ||
}, | ||
], | ||
}, | ||
{ | ||
code: `return !href && !onClick ? ( | ||
<EuiTextColor | ||
color={highlightLastBreadcrumb ? 'default' : 'subdued'} | ||
cloneElement | ||
css={cssStyles} | ||
> | ||
<span | ||
ref={ref} | ||
title={title} | ||
aria-current={ariaCurrent} | ||
className={classes} | ||
{...restSpanProps} | ||
css={cssStyles} | ||
> | ||
{text} | ||
</span> | ||
</EuiTextColor> | ||
) : ( | ||
<EuiLink | ||
ref={ref} | ||
title={title} | ||
aria-current={ariaCurrent} | ||
className={classes} | ||
css={cssStyles} | ||
color={color || (highlightLastBreadcrumb ? 'text' : 'subdued')} | ||
onClick={onClick} | ||
href={href} | ||
rel={rel} | ||
> | ||
{text} | ||
</EuiLink> | ||
); | ||
`, | ||
errors: [ | ||
{ | ||
message: 'restSpanProps: CSS props must be declared before spread props.', | ||
}, | ||
], | ||
}, | ||
] | ||
|
||
ruleTester.run('css_before_spread_props', rule, { | ||
valid, | ||
invalid, | ||
}); |
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
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
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
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