eslint-plugin-baseui
Advanced tools
Comparing version
@@ -18,7 +18,5 @@ /* | ||
}); | ||
const config = cli.getConfigForFile( | ||
path.resolve(__dirname, 'example-config/fixture.js'), | ||
); | ||
const config = cli.getConfigForFile(path.resolve(__dirname, 'example-config/fixture.js')); | ||
expect(config.rules).toMatchObject(Plugin.configs.recommended.rules); | ||
expect(config.plugins).toMatchObject(Plugin.configs.recommended.plugins); | ||
}); |
@@ -10,3 +10,3 @@ /* | ||
const {RuleTester} = require('eslint'); | ||
const { RuleTester } = require('eslint'); | ||
const rule = require('../src/deprecated-component-api.js'); | ||
@@ -120,3 +120,3 @@ const MESSAGES = require('../src/messages.js'); | ||
import * as Typography from "baseui/typography"; | ||
const Example = () => { | ||
@@ -145,3 +145,3 @@ return <div></div> | ||
`, | ||
errors: [{messageId: MESSAGES.replace.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
@@ -160,3 +160,3 @@ import {Accordion} from "baseui/accordion"; | ||
`, | ||
errors: [{messageId: MESSAGES.replace.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
@@ -177,3 +177,3 @@ import {Accordion as Acc} from "baseui/accordion"; | ||
`, | ||
errors: [{messageId: MESSAGES.replace.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
@@ -196,3 +196,3 @@ import { Checkbox, STYLE_TYPE } from "baseui/checkbox" | ||
`, | ||
errors: [{messageId: MESSAGES.replace.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
@@ -206,2 +206,141 @@ import { Checkbox, STYLE_TYPE } from "baseui/checkbox" | ||
// Checkbox - isError | ||
// prop as jsx identifier | ||
{ | ||
code: ` | ||
import {Checkbox} from 'baseui/checkbox'; | ||
export default function() { | ||
return <Checkbox isError /> | ||
} | ||
`, | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
import {Checkbox} from 'baseui/checkbox'; | ||
export default function() { | ||
return <Checkbox error /> | ||
} | ||
`, | ||
}, | ||
// Checkbox - isError | ||
// prop as jsx expression | ||
{ | ||
code: ` | ||
import {Checkbox} from 'baseui/checkbox'; | ||
export default function() { | ||
return <Checkbox isError={true} /> | ||
} | ||
`, | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
import {Checkbox} from 'baseui/checkbox'; | ||
export default function() { | ||
return <Checkbox error={true} /> | ||
} | ||
`, | ||
}, | ||
// Radio - isError | ||
// prop as jsx identifier | ||
{ | ||
code: ` | ||
import {Radio} from 'baseui/radio'; | ||
export default function() { | ||
return <Radio isError /> | ||
} | ||
`, | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
import {Radio} from 'baseui/radio'; | ||
export default function() { | ||
return <Radio error /> | ||
} | ||
`, | ||
}, | ||
// Radio - isError | ||
// prop as jsx expression | ||
{ | ||
code: ` | ||
import {Radio} from 'baseui/radio'; | ||
export default function() { | ||
return <Radio isError={true} /> | ||
} | ||
`, | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
import {Radio} from 'baseui/radio'; | ||
export default function() { | ||
return <Radio error={true} /> | ||
} | ||
`, | ||
}, | ||
// RadioGroup - isError | ||
// prop as jsx identifier | ||
{ | ||
code: ` | ||
import {Radio, RadioGroup} from 'baseui/radio'; | ||
export default function() { | ||
return ( | ||
<RadioGroup isError> | ||
<Radio>one</Radio> | ||
</RadioGroup> | ||
); | ||
} | ||
`, | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
import {Radio, RadioGroup} from 'baseui/radio'; | ||
export default function() { | ||
return ( | ||
<RadioGroup error> | ||
<Radio>one</Radio> | ||
</RadioGroup> | ||
); | ||
} | ||
`, | ||
}, | ||
// RadioGroup - isError | ||
// prop as jsx expression | ||
{ | ||
code: ` | ||
import {Radio, RadioGroup} from 'baseui/radio'; | ||
export default function() { | ||
return ( | ||
<RadioGroup isError> | ||
<Radio>one</Radio> | ||
</RadioGroup> | ||
); | ||
} | ||
`, | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
import {Radio, RadioGroup} from 'baseui/radio'; | ||
export default function() { | ||
return ( | ||
<RadioGroup error> | ||
<Radio>one</Radio> | ||
</RadioGroup> | ||
); | ||
} | ||
`, | ||
}, | ||
// RadioGroup - deprecated overrides | ||
{ | ||
code: ` | ||
import {Radio, RadioGroup} from 'baseui/radio'; | ||
export default function() { | ||
return ( | ||
<RadioGroup overrides={{Label: {style: {marginRight: 0}}}}> | ||
<Radio>hello</Radio> | ||
</RadioGroup> | ||
); | ||
} | ||
`, | ||
errors: [{ messageId: MESSAGES.radioGroupOverrides.id }], | ||
}, | ||
// Modal - autofocus | ||
@@ -215,3 +354,3 @@ { | ||
}`, | ||
errors: [{messageId: MESSAGES.replace.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
@@ -233,3 +372,3 @@ import {Modal} from 'baseui/modal'; | ||
`, | ||
errors: [{messageId: MESSAGES.modalBackdrop.id}], | ||
errors: [{ messageId: MESSAGES.modalBackdrop.id }], | ||
}, | ||
@@ -246,27 +385,5 @@ | ||
`, | ||
errors: [{messageId: MESSAGES.modalBackdrop.id}], | ||
errors: [{ messageId: MESSAGES.modalBackdrop.id }], | ||
}, | ||
// Spinner | ||
{ | ||
code: ` | ||
import { Spinner } from "baseui/spinner" | ||
export default function() { | ||
return <Spinner /> | ||
} | ||
`, | ||
errors: [{messageId: MESSAGES.deprecateSpinner.id}], | ||
}, | ||
// Spinner renamed | ||
{ | ||
code: ` | ||
import { Spinner as BaseSpinner } from "baseui/spinner" | ||
export default function() { | ||
return <BaseSpinner /> | ||
} | ||
`, | ||
errors: [{messageId: MESSAGES.deprecateSpinner.id}], | ||
}, | ||
// Button - minimal kind | ||
@@ -285,3 +402,3 @@ // Prop as imported constant | ||
`, | ||
errors: [{messageId: MESSAGES.buttonKindMinimal.id}], | ||
errors: [{ messageId: MESSAGES.buttonKindMinimal.id }], | ||
}, | ||
@@ -302,3 +419,3 @@ | ||
`, | ||
errors: [{messageId: MESSAGES.buttonKindMinimal.id}], | ||
errors: [{ messageId: MESSAGES.buttonKindMinimal.id }], | ||
}, | ||
@@ -319,3 +436,3 @@ | ||
`, | ||
errors: [{messageId: MESSAGES.buttonKindMinimal.id}], | ||
errors: [{ messageId: MESSAGES.buttonKindMinimal.id }], | ||
}, | ||
@@ -332,5 +449,5 @@ | ||
errors: [ | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
], | ||
@@ -353,3 +470,3 @@ output: ` | ||
`, | ||
errors: [{messageId: MESSAGES.replace.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
@@ -371,6 +488,3 @@ import { ParagraphXSmall as Foo } from "baseui/typography" | ||
`, | ||
errors: [ | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
], | ||
errors: [{ messageId: MESSAGES.replace.id }, { messageId: MESSAGES.replace.id }], | ||
output: ` | ||
@@ -393,5 +507,5 @@ import { ParagraphXSmall } from "baseui/typography" | ||
errors: [ | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
], | ||
@@ -414,3 +528,3 @@ output: ` | ||
`, | ||
errors: [{messageId: MESSAGES.replace.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
@@ -428,3 +542,3 @@ import { LabelXSmall as Foo } from "baseui/typography" | ||
import { Label3 } from "baseui/typography" | ||
const VersionHistoryLabel = styled<typeof Label3, any>(Label3, ({ $theme }: TStyledFnArgs) => ({ | ||
@@ -435,9 +549,9 @@ marginBottom: $theme.sizing.scale600, | ||
errors: [ | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
], | ||
output: ` | ||
import { LabelSmall } from "baseui/typography" | ||
const VersionHistoryLabel = styled<typeof LabelSmall, any>(LabelSmall, ({ $theme }: TStyledFnArgs) => ({ | ||
@@ -453,3 +567,3 @@ marginBottom: $theme.sizing.scale600, | ||
import { Label3 as Foo } from "baseui/typography" | ||
const VersionHistoryLabel = styled<typeof Foo, any>(Foo, ({ $theme }: TStyledFnArgs) => ({ | ||
@@ -459,6 +573,6 @@ marginBottom: $theme.sizing.scale600, | ||
`, | ||
errors: [{messageId: MESSAGES.replace.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
import { LabelSmall as Foo } from "baseui/typography" | ||
const VersionHistoryLabel = styled<typeof Foo, any>(Foo, ({ $theme }: TStyledFnArgs) => ({ | ||
@@ -474,3 +588,3 @@ marginBottom: $theme.sizing.scale600, | ||
import { Label3 } from "hello/world" | ||
const VersionHistoryLabel = styled<typeof Label3, any>(Label3, ({ $theme }: TStyledFnArgs) => ({ | ||
@@ -480,7 +594,7 @@ marginBottom: $theme.sizing.scale600, | ||
`, | ||
errors: [{messageId: MESSAGES.replace.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
import { LabelSmall as Foo } from "baseui/typography" | ||
import { Label3 } from "hello/world" | ||
const VersionHistoryLabel = styled<typeof Label3, any>(Label3, ({ $theme }: TStyledFnArgs) => ({ | ||
@@ -500,3 +614,3 @@ marginBottom: $theme.sizing.scale600, | ||
const [H1, h1Props] = getOverrides(overrides.H1, StyledH1); | ||
return <ReactMarkdown | ||
@@ -508,3 +622,3 @@ components={{ | ||
`, | ||
errors: [{messageId: MESSAGES.replace.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
@@ -517,3 +631,3 @@ import { HeadingXXLarge as StyledH1 } from "baseui/typography" | ||
const [H1, h1Props] = getOverrides(overrides.H1, StyledH1); | ||
return <ReactMarkdown | ||
@@ -537,5 +651,5 @@ components={{ | ||
errors: [ | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
], | ||
@@ -560,5 +674,5 @@ output: ` | ||
errors: [ | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
], | ||
@@ -583,8 +697,8 @@ output: ` | ||
errors: [ | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
], | ||
@@ -608,5 +722,5 @@ output: ` | ||
errors: [ | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
], | ||
@@ -622,25 +736,4 @@ output: ` | ||
// Block - $style | ||
{ | ||
code: ` | ||
import {Block} from "baseui/block" | ||
export default () => { | ||
return <Block $style={{ color: "red" }} /> | ||
} | ||
`, | ||
errors: [{messageId: MESSAGES.styleOnBlock.id}], | ||
}, | ||
// Block - style | ||
{ | ||
code: ` | ||
import {Block} from "baseui/block" | ||
export default () => { | ||
return <Block style={{ color: "red" }} /> | ||
} | ||
`, | ||
errors: [{messageId: MESSAGES.styleOnBlock.id}], | ||
}, | ||
{ | ||
code: ` | ||
import { Paragraph3 } from "baseui/typography" | ||
@@ -652,7 +745,7 @@ export default () => { | ||
errors: [ | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
], | ||
@@ -673,3 +766,3 @@ output: ` | ||
let skipped = []; | ||
[...tests.valid, ...tests.invalid].forEach(t => { | ||
[...tests.valid, ...tests.invalid].forEach((t) => { | ||
if (t.skip) { | ||
@@ -684,3 +777,3 @@ delete t.skip; | ||
}); | ||
const predicate = t => { | ||
const predicate = (t) => { | ||
if (only.length > 0) { | ||
@@ -687,0 +780,0 @@ return only.indexOf(t) !== -1; |
@@ -10,3 +10,3 @@ /* | ||
const {RuleTester} = require('eslint'); | ||
const { RuleTester } = require('eslint'); | ||
const rule = require('../src/deprecated-theme-api.js'); | ||
@@ -839,3 +839,3 @@ const MESSAGES = require('../src/messages.js'); | ||
let skipped = []; | ||
[...tests.valid, ...tests.invalid].forEach(t => { | ||
[...tests.valid, ...tests.invalid].forEach((t) => { | ||
if (t.skip) { | ||
@@ -850,3 +850,3 @@ delete t.skip; | ||
}); | ||
const predicate = t => { | ||
const predicate = (t) => { | ||
if (only.length > 0) { | ||
@@ -853,0 +853,0 @@ return only.indexOf(t) !== -1; |
@@ -10,3 +10,3 @@ /* | ||
const {RuleTester} = require('eslint'); | ||
const { RuleTester } = require('eslint'); | ||
const rule = require('../src/no-deep-imports.js'); | ||
@@ -50,3 +50,3 @@ | ||
let skipped = []; | ||
[...tests.valid, ...tests.invalid].forEach(t => { | ||
[...tests.valid, ...tests.invalid].forEach((t) => { | ||
if (t.skip) { | ||
@@ -61,3 +61,3 @@ delete t.skip; | ||
}); | ||
const predicate = t => { | ||
const predicate = (t) => { | ||
if (only.length > 0) { | ||
@@ -64,0 +64,0 @@ return only.indexOf(t) !== -1; |
{ | ||
"name": "eslint-plugin-baseui", | ||
"version": "0.0.0-next-aad65df", | ||
"version": "0.0.0-next-aadc4ef", | ||
"description": "ESLint rules for Base Web", | ||
@@ -12,3 +12,3 @@ "main": "index.js", | ||
"peerDependencies": { | ||
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" | ||
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" | ||
}, | ||
@@ -34,3 +34,6 @@ "devDependencies": { | ||
"url": "https://github.com/uber/baseweb/issues" | ||
}, | ||
"dependencies": { | ||
"jsx-ast-utils": "^3.2.1" | ||
} | ||
} |
@@ -8,2 +8,5 @@ # `eslint-plugin-baseui` | ||
- Identify improper usage of components | ||
- Identify improper styling on Block elements | ||
- Identify improper styling on baseui components | ||
- Identify shorthand properties in baseui overrides | ||
@@ -35,2 +38,5 @@ ## Installation | ||
'baseui/no-deep-imports': "warn", | ||
'baseui/no-block-style': "warn", | ||
'baseui/no-component-classname': "warn", | ||
'baseui/no-shorthand-properties': "warn", | ||
} | ||
@@ -69,7 +75,10 @@ } | ||
| Rule | Responsibility | | ||
| --- | --- | | ||
| `deprecated-theme-api` | Identify theme properties that are deprecated. | | ||
| `deprecated-component-api` | Identify components and props that are deprecated. | | ||
| `no-deep-imports` | Identify importing unsupported modules from `baseui` source code. | | ||
| Rule | Responsibility | | ||
|----------------------------|------------------------------------------------------------------------------------------------| | ||
| `deprecated-theme-api` | Identify theme properties that are deprecated. | | ||
| `deprecated-component-api` | Identify components and props that are deprecated. | | ||
| `no-deep-imports` | Identify importing unsupported modules from `baseui` source code. | | ||
| `no-block-style` | Identify instances of Block being used with style/$style instead of overrides. (not supported) | | ||
| `no-component-classname` | Identify instances of components being styled using className. (not supported) | | ||
| `no-shorthand-properties` | Identify instances of component overrides using shorthand css properties. | | ||
@@ -76,0 +85,0 @@ ## Contributing |
@@ -7,2 +7,3 @@ /* | ||
*/ | ||
/* eslint-env node */ | ||
@@ -38,8 +39,7 @@ 'use strict'; | ||
const getOverrideIfExists = (name, node) => { | ||
// Verify that an object is passed to overrides. | ||
// Verify that an object is passed into overrides. | ||
if (node.parent.value.expression.type === 'ObjectExpression') { | ||
// Find property name | ||
return node.parent.value.expression.properties.find( | ||
property => | ||
property.key && property.key.name && property.key.name === name, | ||
(property) => property.key && property.key.name && property.key.name === name | ||
); | ||
@@ -55,6 +55,5 @@ } | ||
[MESSAGES.replace.id]: MESSAGES.replace.message, | ||
[MESSAGES.deprecateSpinner.id]: MESSAGES.deprecateSpinner.message, | ||
[MESSAGES.styleOnBlock.id]: MESSAGES.styleOnBlock.message, | ||
[MESSAGES.buttonKindMinimal.id]: MESSAGES.buttonKindMinimal.message, | ||
[MESSAGES.modalBackdrop.id]: MESSAGES.modalBackdrop.message, | ||
[MESSAGES.radioGroupOverrides.id]: MESSAGES.radioGroupOverrides.message, | ||
}, | ||
@@ -73,3 +72,3 @@ }, | ||
}, | ||
fix: function(fixer) { | ||
fix: function (fixer) { | ||
return [fixer.replaceText(node.imported, newComponent)]; | ||
@@ -87,3 +86,3 @@ }, | ||
}, | ||
fix: function(fixer) { | ||
fix: function (fixer) { | ||
const isAtStart = specifierIndex === 0; | ||
@@ -107,6 +106,3 @@ const startIndex = isAtStart ? specifierIndex : specifierIndex - 1; | ||
function isImporting(node, importName, importPath) { | ||
if ( | ||
node.imported.name === importName && | ||
node.parent.source.value === importPath | ||
) { | ||
if (node.imported.name === importName && node.parent.source.value === importPath) { | ||
importState[importName] = node.local.name; | ||
@@ -125,20 +121,11 @@ return true; | ||
) { | ||
// Spinner | ||
// Ex: import {Spinner} from "baseui/spinner"; | ||
// Note, we are not replacing Spinner because the new API | ||
// is not compatible. | ||
if (isImporting(specifier, 'Spinner', 'baseui/spinner')) { | ||
context.report({ | ||
node: specifier.imported, | ||
messageId: MESSAGES.deprecateSpinner.id, | ||
}); | ||
return; | ||
} | ||
// These can be referenced later on by instances of components. | ||
if (isImporting(specifier, 'Accordion', 'baseui/accordion')) return; | ||
if (isImporting(specifier, 'Modal', 'baseui/modal')) return; | ||
if (isImporting(specifier, 'Block', 'baseui/block')) return; | ||
if (isImporting(specifier, 'Checkbox', 'baseui/checkbox')) return; | ||
if (isImporting(specifier, 'Button', 'baseui/button')) return; | ||
// removes return statement since these can be imported together | ||
isImporting(specifier, 'Radio', 'baseui/radio'); | ||
isImporting(specifier, 'RadioGroup', 'baseui/radio'); | ||
} | ||
@@ -154,3 +141,3 @@ } | ||
// Map existing imports (newName: localName), preference given to first renamed import. | ||
node.specifiers.forEach(specifier => { | ||
node.specifiers.forEach((specifier) => { | ||
if (specifier.type === 'ImportNamespaceSpecifier') { | ||
@@ -178,4 +165,3 @@ return; | ||
const deprecatedComponent = specifier.imported.name; | ||
const newComponent = | ||
mapDeprecatedTypographyComponents[deprecatedComponent]; | ||
const newComponent = mapDeprecatedTypographyComponents[deprecatedComponent]; | ||
@@ -187,10 +173,4 @@ if (newComponent) { | ||
if (isAlreadyImported) { | ||
removeImport( | ||
node, | ||
specifierIndex, | ||
deprecatedComponent, | ||
newComponent, | ||
); | ||
identifiersToRename[specifier.local.name] = | ||
existingImports[newComponent]; | ||
removeImport(node, specifierIndex, deprecatedComponent, newComponent); | ||
identifiersToRename[specifier.local.name] = existingImports[newComponent]; | ||
} else { | ||
@@ -220,5 +200,4 @@ fixImport(specifier, deprecatedComponent, newComponent); | ||
.some( | ||
ancestor => | ||
ancestor.type === 'JSXOpeningElement' && | ||
ancestor.name.name === component, | ||
(ancestor) => | ||
ancestor.type === 'JSXOpeningElement' && ancestor.name.name === component | ||
) | ||
@@ -233,4 +212,3 @@ ); | ||
return ( | ||
node.parent.type === 'JSXOpeningElement' || | ||
node.parent.type === 'JSXClosingElement' | ||
node.parent.type === 'JSXOpeningElement' || node.parent.type === 'JSXClosingElement' | ||
); | ||
@@ -246,6 +224,3 @@ } | ||
// Replacement: renderAll | ||
if ( | ||
importState.Accordion && | ||
isProp('renderPanelContent', importState.Accordion) | ||
) { | ||
if (importState.Accordion && isProp('renderPanelContent', importState.Accordion)) { | ||
context.report({ | ||
@@ -258,3 +233,3 @@ node, | ||
}, | ||
fix: function(fixer) { | ||
fix: function (fixer) { | ||
return fixer.replaceText(node, 'renderAll'); | ||
@@ -277,3 +252,3 @@ }, | ||
}, | ||
fix: function(fixer) { | ||
fix: function (fixer) { | ||
return fixer.replaceText(node, 'autoFocus'); | ||
@@ -285,36 +260,2 @@ }, | ||
// style and $style | ||
// Ex: <Block style={{ ... }} /> | ||
// Ex: <Block $style={{ ... }} /> | ||
// The "$style" and "style" props are not supported. | ||
// It works because Block spreads props down to the base | ||
// styled component, but styles are not guaranteed to be applied | ||
// as expected. | ||
if ( | ||
importState.Block && | ||
(isProp('$style', importState.Block) || | ||
isProp('style', importState.Block)) | ||
) { | ||
context.report({ | ||
node, | ||
messageId: MESSAGES.styleOnBlock.id, | ||
}); | ||
return; | ||
} | ||
// successValue | ||
// Ex: <Checkbox successValue={1} /> | ||
// Replacement: None | ||
if ( | ||
importState.ProgressBar && | ||
isProp('successValue', importState.ProgressBar) | ||
) { | ||
// The prop will be completely removed. | ||
context.report({ | ||
node: node.parent.value.expression.property, | ||
messageId: MESSAGES.progressBarSuccessValue.id, | ||
}); | ||
return; | ||
} | ||
// ====================== | ||
@@ -328,12 +269,6 @@ // Deprecated Prop Values | ||
// Replacement: toggle_round | ||
if ( | ||
importState.Checkbox && | ||
isProp('checkmarkType', importState.Checkbox) | ||
) { | ||
if (importState.Checkbox && isProp('checkmarkType', importState.Checkbox)) { | ||
// The value can be a constant or a string literal. | ||
// We need to handle each a little differently. | ||
if ( | ||
node.parent.value.type === 'Literal' && | ||
node.parent.value.value === 'toggle' | ||
) { | ||
if (node.parent.value.type === 'Literal' && node.parent.value.value === 'toggle') { | ||
// Ex: <Checkmark checkmarkType="toggle" /> | ||
@@ -347,3 +282,3 @@ context.report({ | ||
}, | ||
fix: function(fixer) { | ||
fix: function (fixer) { | ||
return fixer.replaceText(node.parent.value, `"toggle_round"`); | ||
@@ -366,7 +301,4 @@ }, | ||
}, | ||
fix: function(fixer) { | ||
return fixer.replaceText( | ||
node.parent.value.expression.property, | ||
'toggle_round', | ||
); | ||
fix: function (fixer) { | ||
return fixer.replaceText(node.parent.value.expression.property, 'toggle_round'); | ||
}, | ||
@@ -378,2 +310,56 @@ }); | ||
// Checkbox - isError | ||
// Ex: <Checkbox isError /> | ||
// Replacement: error | ||
if (importState.Checkbox && isProp('isError', importState.Checkbox)) { | ||
context.report({ | ||
node: node, | ||
messageId: MESSAGES.replace.id, | ||
data: { | ||
old: `isError`, | ||
new: `error`, | ||
}, | ||
fix: function (fixer) { | ||
return fixer.replaceText(node, 'error'); | ||
}, | ||
}); | ||
return; | ||
} | ||
// Radio - isError | ||
// Ex: <Radio isError /> | ||
// Replacement: error | ||
if (importState.Radio && isProp('isError', importState.Radio)) { | ||
context.report({ | ||
node: node, | ||
messageId: MESSAGES.replace.id, | ||
data: { | ||
old: `isError`, | ||
new: `error`, | ||
}, | ||
fix: function (fixer) { | ||
return fixer.replaceText(node, 'error'); | ||
}, | ||
}); | ||
return; | ||
} | ||
// RadioGroup - isError | ||
// Ex: <RadioGroup isError /> | ||
// Replacement: error | ||
if (importState.RadioGroup && isProp('isError', importState.RadioGroup)) { | ||
context.report({ | ||
node: node, | ||
messageId: MESSAGES.replace.id, | ||
data: { | ||
old: `isError`, | ||
new: `error`, | ||
}, | ||
fix: function (fixer) { | ||
return fixer.replaceText(node, 'error'); | ||
}, | ||
}); | ||
return; | ||
} | ||
// kind | ||
@@ -386,6 +372,3 @@ // Ex: <Button kind="minimal" /> | ||
// We need to handle each a little differently. | ||
if ( | ||
node.parent.value.type === 'Literal' && | ||
node.parent.value.value === 'minimal' | ||
) { | ||
if (node.parent.value.type === 'Literal' && node.parent.value.value === 'minimal') { | ||
// Ex: <Button kind="minimal" /> | ||
@@ -430,16 +413,2 @@ context.report({ | ||
// Select | ||
// Ex: <Select overrides={{ SearchIcon: {}}} /> | ||
// Replacement: SearchIconContainer | ||
if (importState.Select && isProp('overrides', importState.Select)) { | ||
const property = getOverrideIfExists('SearchIcon', node); | ||
if (property) { | ||
context.report({ | ||
node: property, | ||
messageId: MESSAGES.selectSearchIcon.id, | ||
}); | ||
return; | ||
} | ||
} | ||
// RadioGroup - All overrides are deprecated except for RadioGroupRoot | ||
@@ -450,6 +419,3 @@ // Ex: <RadioGroup overrides={{ RadioMarkInner: {}}} /> | ||
// Replacement: None | ||
if ( | ||
importState.RadioGroup && | ||
isProp('overrides', importState.RadioGroup) | ||
) { | ||
if (importState.RadioGroup && isProp('overrides', importState.RadioGroup)) { | ||
const properties = [ | ||
@@ -463,3 +429,3 @@ 'Root', | ||
]; | ||
properties.map(val => { | ||
properties.map((val) => { | ||
const property = getOverrideIfExists(val, node); | ||
@@ -486,9 +452,3 @@ if (property) { | ||
// Replacement: ParagraphXSmall | ||
if ( | ||
Object.prototype.hasOwnProperty.call( | ||
identifiersToRename, | ||
node.name, | ||
) && | ||
isComponent() | ||
) { | ||
if (Object.prototype.hasOwnProperty.call(identifiersToRename, node.name) && isComponent()) { | ||
const oldName = node.name; | ||
@@ -503,3 +463,3 @@ const newName = identifiersToRename[node.name]; | ||
}, | ||
fix: function(fixer) { | ||
fix: function (fixer) { | ||
return [fixer.replaceText(node, newName)]; | ||
@@ -519,3 +479,3 @@ }, | ||
}, | ||
fix: function(fixer) { | ||
fix: function (fixer) { | ||
return [fixer.replaceText(node, newComponent)]; | ||
@@ -533,6 +493,3 @@ }, | ||
if ( | ||
Object.prototype.hasOwnProperty.call( | ||
identifiersToRename, | ||
node.name, | ||
) && | ||
Object.prototype.hasOwnProperty.call(identifiersToRename, node.name) && | ||
isIdentifier() | ||
@@ -539,0 +496,0 @@ ) { |
@@ -270,7 +270,5 @@ /* | ||
const program = context | ||
.getAncestors(node) | ||
.find(node => node.type === 'Program'); | ||
const program = context.getAncestors(node).find((node) => node.type === 'Program'); | ||
const importDeclaration = program.body.find( | ||
node => node.type === 'ImportDeclaration' && node.source.value === 'baseui', | ||
(node) => node.type === 'ImportDeclaration' && node.source.value === 'baseui' | ||
); | ||
@@ -280,3 +278,3 @@ | ||
importSpecifier = importDeclaration.specifiers.find( | ||
specifier => specifier.imported.name === 'createTheme', | ||
(specifier) => specifier.imported.name === 'createTheme' | ||
); | ||
@@ -327,5 +325,3 @@ } | ||
scope.block.parent.key.name === 'style' && | ||
ancestors.some( | ||
node => node.type === 'JSXAttribute' && node.name.name === 'overrides', | ||
); | ||
ancestors.some((node) => node.type === 'JSXAttribute' && node.name.name === 'overrides'); | ||
@@ -364,5 +360,3 @@ if (!passedToStyledOrWithStyle && !passedToOverrides) { | ||
// Our parameter is being destructured. | ||
const $themeProperty = parameter.properties.find( | ||
property => property.key.name === '$theme', | ||
); | ||
const $themeProperty = parameter.properties.find((property) => property.key.name === '$theme'); | ||
@@ -376,6 +370,3 @@ // the styled function is not using the theme | ||
// ({$theme}) => ({ color: $theme.colors.foreground }) | ||
if ( | ||
$themeProperty.value.type === 'Identifier' && | ||
$themeProperty.value.name === '$theme' | ||
) { | ||
if ($themeProperty.value.type === 'Identifier' && $themeProperty.value.name === '$theme') { | ||
if ( | ||
@@ -397,3 +388,3 @@ node.parent.type === 'MemberExpression' && | ||
const concernPropertyNode = $themeProperty.value.properties.find( | ||
property => property.key.name === themeProperty.concern, | ||
(property) => property.key.name === themeProperty.concern | ||
); | ||
@@ -417,8 +408,5 @@ | ||
// ({$theme: {colors: {foreground}}}) => ({ color: foreground }) | ||
if ( | ||
concernPropertyNode && | ||
concernPropertyNode.value.type === 'ObjectPattern' | ||
) { | ||
if (concernPropertyNode && concernPropertyNode.value.type === 'ObjectPattern') { | ||
const deprecatedProperty = concernPropertyNode.value.properties.find( | ||
property => property.key.name === node.name, | ||
(property) => property.key.name === node.name | ||
); | ||
@@ -442,4 +430,3 @@ if (deprecatedProperty) { | ||
node === deprecatedProperty.key || | ||
(node !== deprecatedProperty.value && | ||
node.parent.type !== 'MemberExpression') | ||
(node !== deprecatedProperty.value && node.parent.type !== 'MemberExpression') | ||
) { | ||
@@ -473,3 +460,3 @@ return true; | ||
const declarations = scope.block.body.body.filter( | ||
statement => statement.type === 'VariableDeclaration', | ||
(statement) => statement.type === 'VariableDeclaration' | ||
); | ||
@@ -488,9 +475,9 @@ | ||
let declarator; | ||
declarations.forEach(declaration => { | ||
declarations.forEach((declaration) => { | ||
declarator = declaration.declarations.find( | ||
declarator => | ||
(declarator) => | ||
declarator.type === 'VariableDeclarator' && | ||
declarator.init && | ||
declarator.init.type === 'CallExpression' && | ||
declarator.init.callee.name === 'useStyletron', | ||
declarator.init.callee.name === 'useStyletron' | ||
); | ||
@@ -503,6 +490,3 @@ }); | ||
if ( | ||
declarator.id.type === 'ArrayPattern' && | ||
declarator.id.elements.length === 2 | ||
) { | ||
if (declarator.id.type === 'ArrayPattern' && declarator.id.elements.length === 2) { | ||
// Confirm we are accessing the theme index in the returned array. | ||
@@ -536,3 +520,3 @@ // Ex: const [css, theme] = useStyletron(); | ||
const concernPropertyNode = themeIndexNode.properties.find( | ||
property => property.key.name === themeProperty.concern, | ||
(property) => property.key.name === themeProperty.concern | ||
); | ||
@@ -556,6 +540,3 @@ | ||
if ( | ||
concernPropertyNode && | ||
concernPropertyNode.value.type === 'ObjectPattern' | ||
) { | ||
if (concernPropertyNode && concernPropertyNode.value.type === 'ObjectPattern') { | ||
// We are destructuring even further! | ||
@@ -567,3 +548,3 @@ | ||
const deprecatedProperty = concernPropertyNode.value.properties.find( | ||
property => property.key.name === node.name, | ||
(property) => property.key.name === node.name | ||
); | ||
@@ -577,4 +558,3 @@ | ||
(node === deprecatedProperty.key || | ||
(node !== deprecatedProperty.value && | ||
node.parent.type !== 'MemberExpression')) | ||
(node !== deprecatedProperty.value && node.parent.type !== 'MemberExpression')) | ||
) { | ||
@@ -596,4 +576,3 @@ return true; | ||
messages: { | ||
[MESSAGES.deprecateThemeProperty.id]: | ||
MESSAGES.deprecateThemeProperty.message, | ||
[MESSAGES.deprecateThemeProperty.id]: MESSAGES.deprecateThemeProperty.message, | ||
[MESSAGES.replaceThemeProperty.id]: MESSAGES.replaceThemeProperty.message, | ||
@@ -605,8 +584,3 @@ }, | ||
Identifier(node) { | ||
if ( | ||
Object.prototype.hasOwnProperty.call( | ||
deprecatedThemeProperties, | ||
node.name, | ||
) | ||
) { | ||
if (Object.prototype.hasOwnProperty.call(deprecatedThemeProperties, node.name)) { | ||
// We have matched a possible deprecated theme property. | ||
@@ -619,3 +593,3 @@ const deprecatedThemeProperty = deprecatedThemeProperties[node.name]; | ||
messageId: MESSAGES.deprecateThemeProperty.id, | ||
data: {old: node.name}, | ||
data: { old: node.name }, | ||
fix: null, | ||
@@ -628,7 +602,4 @@ }; | ||
reportOptions.data.new = deprecatedThemeProperty.replacement; | ||
reportOptions.fix = function(fixer) { | ||
return fixer.replaceText( | ||
node, | ||
deprecatedThemeProperty.replacement, | ||
); | ||
reportOptions.fix = function (fixer) { | ||
return fixer.replaceText(node, deprecatedThemeProperty.replacement); | ||
}; | ||
@@ -635,0 +606,0 @@ } |
@@ -13,2 +13,5 @@ /* | ||
const NoDeepImports = require('./no-deep-imports.js'); | ||
const NoBlockStyle = require('./no-block-style.js'); | ||
const NoComponentClassname = require('./no-component-classname.js'); | ||
const NoShorthandProperties = require('./no-shorthand-properties.js'); | ||
@@ -20,2 +23,5 @@ module.exports = { | ||
'no-deep-imports': NoDeepImports, | ||
'no-block-style': NoBlockStyle, | ||
'no-component-classname': NoComponentClassname, | ||
'no-shorthand-properties': NoShorthandProperties, | ||
}, | ||
@@ -29,2 +35,5 @@ configs: { | ||
'baseui/no-deep-imports': ['warn'], | ||
'baseui/no-block-style': ['warn'], | ||
'baseui/no-component-classname': ['warn'], | ||
'baseui/no-shorthand-properties': ['warn'], | ||
}, | ||
@@ -31,0 +40,0 @@ }, |
@@ -23,6 +23,2 @@ /* | ||
}, | ||
deprecateSpinner: { | ||
id: 'deprecateSpinner', | ||
message: `The "Spinner" component has been deprecated in favor of "StyledSpinnerNext". In v11 of baseui, "Spinner" will be removed and "StyledSpinnerNext" will be renamed to "Spinner".`, | ||
}, | ||
styleOnBlock: { | ||
@@ -47,4 +43,3 @@ id: 'styleOnBlock', | ||
id: 'selectSearchIcon', | ||
message: | ||
'The "SearchIcon" override will be removed in favor of "StyledSearchIconContainer".', | ||
message: 'The "SearchIcon" override will be removed in favor of "StyledSearchIconContainer".', | ||
}, | ||
@@ -56,2 +51,12 @@ radioGroupOverrides: { | ||
}, | ||
noClassName: { | ||
id: 'noClassName', | ||
message: | ||
'Base web components should only be styled using `styled`, `withStyle`, or `overrides`. {{ component }} is using className, which can cause unintended styling issues. See https://baseweb.design/guides/styling/ for recommended styling patterns.', | ||
}, | ||
noShorthandProperties: { | ||
id: 'noShorthandProperties', | ||
message: | ||
'Shorthand properties should not be used with baseui component overrides. See https://baseweb.design/guides/styling/ for recommended styling patterns.', | ||
}, | ||
}; |
104011
22.5%24
33.33%3359
21.31%89
11.25%2
100%6
100%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed