eslint-plugin-baseui
Advanced tools
Comparing version 0.0.0-next-45f4560 to 0.0.0-next-46c9467
/* | ||
Copyright (c) 2018-2020 Uber Technologies, Inc. | ||
Copyright (c) Uber Technologies, Inc. | ||
@@ -18,7 +18,5 @@ This source code is licensed under the MIT license found in the | ||
}); | ||
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); | ||
}); |
/* | ||
Copyright (c) 2018-2020 Uber Technologies, Inc. | ||
Copyright (c) Uber Technologies, Inc. | ||
@@ -10,3 +10,3 @@ This source code is licensed under the MIT license found in the | ||
const {RuleTester} = require('eslint'); | ||
const { RuleTester } = require('eslint'); | ||
const rule = require('../src/deprecated-component-api.js'); | ||
@@ -116,2 +116,22 @@ const MESSAGES = require('../src/messages.js'); | ||
}, | ||
// Should not error on ImportNamespaceSpecifiers | ||
{ | ||
code: ` | ||
import * as Typography from "baseui/typography"; | ||
const Example = () => { | ||
return <div></div> | ||
} | ||
`, | ||
}, | ||
// Should not error | ||
{ | ||
code: ` | ||
import * as Typography from "baseui/typography"; | ||
const Example = () => { | ||
const hello = {}.toString(); | ||
return <div></div> | ||
}`, | ||
}, | ||
], | ||
@@ -125,3 +145,3 @@ invalid: [ | ||
`, | ||
errors: [{messageId: MESSAGES.replace.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
@@ -140,3 +160,3 @@ import {Accordion} from "baseui/accordion"; | ||
`, | ||
errors: [{messageId: MESSAGES.replace.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
@@ -157,3 +177,3 @@ import {Accordion as Acc} from "baseui/accordion"; | ||
`, | ||
errors: [{messageId: MESSAGES.replace.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
@@ -176,3 +196,3 @@ import { Checkbox, STYLE_TYPE } from "baseui/checkbox" | ||
`, | ||
errors: [{messageId: MESSAGES.replace.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
@@ -186,15 +206,16 @@ import { Checkbox, STYLE_TYPE } from "baseui/checkbox" | ||
// Modal - autofocus | ||
// Checkbox - isError | ||
// prop as jsx identifier | ||
{ | ||
code: ` | ||
import { Modal } from "baseui/modal" | ||
import {Checkbox} from 'baseui/checkbox'; | ||
export default function() { | ||
return <Modal autofocus /> | ||
return <Checkbox isError /> | ||
} | ||
`, | ||
errors: [{messageId: MESSAGES.replace.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
import { Modal } from "baseui/modal" | ||
import {Checkbox} from 'baseui/checkbox'; | ||
export default function() { | ||
return <Modal autoFocus /> | ||
return <Checkbox error /> | ||
} | ||
@@ -204,47 +225,163 @@ `, | ||
// Modal - Backdrop | ||
// Checkbox - isError | ||
// prop as jsx expression | ||
{ | ||
code: ` | ||
import { Modal } from "baseui/modal" | ||
import {Checkbox} from 'baseui/checkbox'; | ||
export default function() { | ||
return <Modal overrides={{ Backdrop: {} }} /> | ||
return <Checkbox isError={true} /> | ||
} | ||
`, | ||
errors: [{messageId: MESSAGES.modalBackdrop.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
import {Checkbox} from 'baseui/checkbox'; | ||
export default function() { | ||
return <Checkbox error={true} /> | ||
} | ||
`, | ||
}, | ||
// Modal - Backdrop | ||
// Modal is renamed | ||
// Radio - isError | ||
// prop as jsx identifier | ||
{ | ||
code: ` | ||
import { Modal as Foo } from "baseui/modal" | ||
import {Radio} from 'baseui/radio'; | ||
export default function() { | ||
return <Foo overrides={{ Backdrop: {} }} /> | ||
return <Radio isError /> | ||
} | ||
`, | ||
errors: [{messageId: MESSAGES.modalBackdrop.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
import {Radio} from 'baseui/radio'; | ||
export default function() { | ||
return <Radio error /> | ||
} | ||
`, | ||
}, | ||
// Spinner | ||
// Radio - isError | ||
// prop as jsx expression | ||
{ | ||
code: ` | ||
import { Spinner } from "baseui/spinner" | ||
import {Radio} from 'baseui/radio'; | ||
export default function() { | ||
return <Spinner /> | ||
return <Radio isError={true} /> | ||
} | ||
`, | ||
errors: [{messageId: MESSAGES.deprecateSpinner.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
import {Radio} from 'baseui/radio'; | ||
export default function() { | ||
return <Radio error={true} /> | ||
} | ||
`, | ||
}, | ||
// Spinner renamed | ||
// RadioGroup - isError | ||
// prop as jsx identifier | ||
{ | ||
code: ` | ||
import { Spinner as BaseSpinner } from "baseui/spinner" | ||
import {Radio, RadioGroup} from 'baseui/radio'; | ||
export default function() { | ||
return <BaseSpinner /> | ||
return ( | ||
<RadioGroup isError> | ||
<Radio>one</Radio> | ||
</RadioGroup> | ||
); | ||
} | ||
`, | ||
errors: [{messageId: MESSAGES.deprecateSpinner.id}], | ||
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 | ||
{ | ||
code: ` | ||
import {Modal} from 'baseui/modal'; | ||
import Overflow from 'baseui/icon/overflow'; | ||
export default function() { | ||
return <Modal autofocus>Hello</Modal>; | ||
}`, | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
import {Modal} from 'baseui/modal'; | ||
import Overflow from 'baseui/icon/overflow'; | ||
export default function() { | ||
return <Modal autoFocus>Hello</Modal>; | ||
}`, | ||
}, | ||
// Modal - Backdrop | ||
{ | ||
code: ` | ||
import { Modal } from "baseui/modal" | ||
export default function() { | ||
return <Modal overrides={{ Backdrop: {} }} /> | ||
} | ||
`, | ||
errors: [{ messageId: MESSAGES.modalBackdrop.id }], | ||
}, | ||
// Modal - Backdrop | ||
// Modal is renamed | ||
{ | ||
code: ` | ||
import { Modal as Foo } from "baseui/modal" | ||
export default function() { | ||
return <Foo overrides={{ Backdrop: {} }} /> | ||
} | ||
`, | ||
errors: [{ messageId: MESSAGES.modalBackdrop.id }], | ||
}, | ||
// Button - minimal kind | ||
@@ -263,3 +400,3 @@ // Prop as imported constant | ||
`, | ||
errors: [{messageId: MESSAGES.buttonKindMinimal.id}], | ||
errors: [{ messageId: MESSAGES.buttonKindMinimal.id }], | ||
}, | ||
@@ -280,3 +417,3 @@ | ||
`, | ||
errors: [{messageId: MESSAGES.buttonKindMinimal.id}], | ||
errors: [{ messageId: MESSAGES.buttonKindMinimal.id }], | ||
}, | ||
@@ -297,3 +434,3 @@ | ||
`, | ||
errors: [{messageId: MESSAGES.buttonKindMinimal.id}], | ||
errors: [{ messageId: MESSAGES.buttonKindMinimal.id }], | ||
}, | ||
@@ -310,4 +447,5 @@ | ||
errors: [ | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
], | ||
@@ -330,3 +468,3 @@ output: ` | ||
`, | ||
errors: [{messageId: MESSAGES.replace.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
@@ -340,2 +478,19 @@ import { ParagraphXSmall as Foo } from "baseui/typography" | ||
// Caption1 no closing tag | ||
{ | ||
code: ` | ||
import { Caption1 } from "baseui/typography" | ||
export default () => { | ||
return <div><Caption1 /></div> | ||
} | ||
`, | ||
errors: [{ messageId: MESSAGES.replace.id }, { messageId: MESSAGES.replace.id }], | ||
output: ` | ||
import { ParagraphXSmall } from "baseui/typography" | ||
export default () => { | ||
return <div><ParagraphXSmall /></div> | ||
} | ||
`, | ||
}, | ||
// Caption2 | ||
@@ -350,4 +505,5 @@ { | ||
errors: [ | ||
{messageId: MESSAGES.replace.id}, | ||
{messageId: MESSAGES.replace.id}, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
], | ||
@@ -370,3 +526,3 @@ output: ` | ||
`, | ||
errors: [{messageId: MESSAGES.replace.id}], | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
@@ -380,22 +536,207 @@ import { LabelXSmall as Foo } from "baseui/typography" | ||
// Block - $style | ||
// Label3, styled type extension | ||
{ | ||
code: ` | ||
import {Block} from "baseui/block" | ||
export default () => { | ||
return <Block $style={{ color: "red" }} /> | ||
} | ||
import { Label3 } from "baseui/typography" | ||
const VersionHistoryLabel = styled<typeof Label3, any>(Label3, ({ $theme }: TStyledFnArgs) => ({ | ||
marginBottom: $theme.sizing.scale600, | ||
})); | ||
`, | ||
errors: [{messageId: MESSAGES.styleOnBlock.id}], | ||
errors: [ | ||
{ 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) => ({ | ||
marginBottom: $theme.sizing.scale600, | ||
})); | ||
`, | ||
}, | ||
// Block - style | ||
// Label3, styled type extension, renamed | ||
{ | ||
code: ` | ||
import {Block} from "baseui/block" | ||
import { Label3 as Foo } from "baseui/typography" | ||
const VersionHistoryLabel = styled<typeof Foo, any>(Foo, ({ $theme }: TStyledFnArgs) => ({ | ||
marginBottom: $theme.sizing.scale600, | ||
})); | ||
`, | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
import { LabelSmall as Foo } from "baseui/typography" | ||
const VersionHistoryLabel = styled<typeof Foo, any>(Foo, ({ $theme }: TStyledFnArgs) => ({ | ||
marginBottom: $theme.sizing.scale600, | ||
})); | ||
`, | ||
}, | ||
// Label3, renamed with same name import | ||
{ | ||
code: ` | ||
import { Label3 as Foo } from "baseui/typography" | ||
import { Label3 } from "hello/world" | ||
const VersionHistoryLabel = styled<typeof Label3, any>(Label3, ({ $theme }: TStyledFnArgs) => ({ | ||
marginBottom: $theme.sizing.scale600, | ||
})); | ||
`, | ||
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) => ({ | ||
marginBottom: $theme.sizing.scale600, | ||
})); | ||
`, | ||
}, | ||
// H1, renamed with a different component using same name | ||
{ | ||
code: ` | ||
import { H1 as StyledH1 } from "baseui/typography" | ||
import ReactMarkdown from 'react-markdown'; | ||
import { getOverrides } from 'baseui/helpers/overrides'; | ||
const MarkdownRender = ({ overrides = {}, text }: Props) => { | ||
const [H1, h1Props] = getOverrides(overrides.H1, StyledH1); | ||
return <ReactMarkdown | ||
components={{ | ||
h1: ({ node, ...rest }) => <H1 {...h1Props} {...rest} /> | ||
}}/>; | ||
} | ||
`, | ||
errors: [{ messageId: MESSAGES.replace.id }], | ||
output: ` | ||
import { HeadingXXLarge as StyledH1 } from "baseui/typography" | ||
import ReactMarkdown from 'react-markdown'; | ||
import { getOverrides } from 'baseui/helpers/overrides'; | ||
const MarkdownRender = ({ overrides = {}, text }: Props) => { | ||
const [H1, h1Props] = getOverrides(overrides.H1, StyledH1); | ||
return <ReactMarkdown | ||
components={{ | ||
h1: ({ node, ...rest }) => <H1 {...h1Props} {...rest} /> | ||
}}/>; | ||
} | ||
`, | ||
}, | ||
// oldName and newName imported and used | ||
{ | ||
code: ` | ||
import { HeadingXXLarge, H1 } from "baseui/typography" | ||
const MarkdownRender = () => { | ||
return <div><H1>Large</H1><HeadingXXLarge>Large</HeadingXXLarge></div> | ||
} | ||
`, | ||
errors: [ | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
], | ||
output: ` | ||
import { HeadingXXLarge } from "baseui/typography" | ||
const MarkdownRender = () => { | ||
return <div><HeadingXXLarge>Large</HeadingXXLarge><HeadingXXLarge>Large</HeadingXXLarge></div> | ||
} | ||
`, | ||
}, | ||
// oldName imported and renamed, and newName imported and used | ||
{ | ||
code: ` | ||
import { HeadingXXLarge as Hello, H1 } from "baseui/typography" | ||
const MarkdownRender = () => { | ||
return <div><H1>Large</H1><Hello>Large</Hello></div> | ||
} | ||
`, | ||
errors: [ | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
], | ||
output: ` | ||
import { HeadingXXLarge as Hello } from "baseui/typography" | ||
const MarkdownRender = () => { | ||
return <div><Hello>Large</Hello><Hello>Large</Hello></div> | ||
} | ||
`, | ||
}, | ||
// Multiple imports removed | ||
{ | ||
code: ` | ||
import { HeadingXXLarge as Hello, H1, HeadingXLarge, H2 } from "baseui/typography" | ||
const MarkdownRender = () => { | ||
return <div><H1>Large</H1><H2>H2</H2><HeadingXLarge>HeadingXLarge</HeadingXLarge><Hello>Large</Hello></div> | ||
} | ||
`, | ||
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 { HeadingXXLarge as Hello, HeadingXLarge } from "baseui/typography" | ||
const MarkdownRender = () => { | ||
return <div><Hello>Large</Hello><HeadingXLarge>H2</HeadingXLarge><HeadingXLarge>HeadingXLarge</HeadingXLarge><Hello>Large</Hello></div> | ||
} | ||
`, | ||
}, | ||
{ | ||
code: ` | ||
import { H1, HeadingXXLarge as Hello, HeadingXLarge } from "baseui/typography" | ||
const MarkdownRender = () => { | ||
return <div><H1>Large</H1><HeadingXXLarge>H2</HeadingXXLarge><HeadingXLarge>HeadingXLarge</HeadingXLarge><Hello>Large</Hello></div> | ||
} | ||
`, | ||
errors: [ | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
], | ||
output: ` | ||
import { HeadingXXLarge as Hello, HeadingXLarge } from "baseui/typography" | ||
const MarkdownRender = () => { | ||
return <div><Hello>Large</Hello><HeadingXXLarge>H2</HeadingXXLarge><HeadingXLarge>HeadingXLarge</HeadingXLarge><Hello>Large</Hello></div> | ||
} | ||
`, | ||
}, | ||
{ | ||
code: ` | ||
import { Paragraph3 } from "baseui/typography" | ||
export default () => { | ||
return <Block style={{ color: "red" }} /> | ||
return <Paragraph3><Paragraph3>Hello</Paragraph3>World</Paragraph3> | ||
} | ||
`, | ||
errors: [{messageId: MESSAGES.styleOnBlock.id}], | ||
errors: [ | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
{ messageId: MESSAGES.replace.id }, | ||
], | ||
output: ` | ||
import { ParagraphSmall } from "baseui/typography" | ||
export default () => { | ||
return <ParagraphSmall><ParagraphSmall>Hello</ParagraphSmall>World</ParagraphSmall> | ||
} | ||
`, | ||
}, | ||
@@ -409,3 +750,3 @@ ], | ||
let skipped = []; | ||
[...tests.valid, ...tests.invalid].forEach(t => { | ||
[...tests.valid, ...tests.invalid].forEach((t) => { | ||
if (t.skip) { | ||
@@ -420,3 +761,3 @@ delete t.skip; | ||
}); | ||
const predicate = t => { | ||
const predicate = (t) => { | ||
if (only.length > 0) { | ||
@@ -423,0 +764,0 @@ return only.indexOf(t) !== -1; |
/* | ||
Copyright (c) 2018-2020 Uber Technologies, Inc. | ||
Copyright (c) Uber Technologies, Inc. | ||
@@ -10,3 +10,3 @@ This source code is licensed under the MIT license found in the | ||
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; |
/* | ||
Copyright (c) 2018-2020 Uber Technologies, Inc. | ||
Copyright (c) Uber Technologies, Inc. | ||
@@ -4,0 +4,0 @@ This source code is licensed under the MIT license found in the |
/* | ||
Copyright (c) 2018-2020 Uber Technologies, Inc. | ||
Copyright (c) Uber Technologies, Inc. | ||
@@ -4,0 +4,0 @@ This source code is licensed under the MIT license found in the |
/* | ||
Copyright (c) 2018-2020 Uber Technologies, Inc. | ||
Copyright (c) Uber Technologies, Inc. | ||
@@ -4,0 +4,0 @@ This source code is licensed under the MIT license found in the |
{ | ||
"name": "eslint-plugin-baseui", | ||
"version": "0.0.0-next-45f4560", | ||
"version": "0.0.0-next-46c9467", | ||
"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 | ||
@@ -24,3 +27,3 @@ ## Installation | ||
```js | ||
```json5 | ||
{ | ||
@@ -36,2 +39,5 @@ "plugins": [ | ||
'baseui/no-deep-imports': "warn", | ||
'baseui/no-block-style': "warn", | ||
'baseui/no-component-classname': "warn", | ||
'baseui/no-shorthand-properties': "warn", | ||
} | ||
@@ -43,5 +49,5 @@ } | ||
```js | ||
```json | ||
{ | ||
"extends": ['plugin:baseui/recommended'] | ||
"extends": ["plugin:baseui/recommended"] | ||
} | ||
@@ -57,6 +63,6 @@ ``` | ||
"dependencies": { | ||
"baseui": "9.41.0", | ||
"baseui": "10.0.0" | ||
}, | ||
"devDependencies": { | ||
"eslint-plugin-baseui": "9.41.0", | ||
"eslint-plugin-baseui": "10.0.0" | ||
} | ||
@@ -66,3 +72,3 @@ } | ||
We sync the the versions for each package so you shouldn't have to worry about it. | ||
We sync the versions for each package, so you shouldn't have to worry about it. | ||
@@ -73,7 +79,10 @@ **ℹ️ Note that the first available version of this package is `9.41.0`.** | ||
| 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. | | ||
@@ -80,0 +89,0 @@ ## Contributing |
/* | ||
Copyright (c) 2018-2020 Uber Technologies, Inc. | ||
Copyright (c) Uber Technologies, Inc. | ||
@@ -7,2 +7,3 @@ This source code is licensed under the MIT license found in the | ||
*/ | ||
/* eslint-env node */ | ||
@@ -13,2 +14,37 @@ 'use strict'; | ||
const mapDeprecatedTypographyComponents = { | ||
Display: 'DisplayLarge', | ||
Display1: 'DisplayLarge', | ||
Display2: 'DisplayMedium', | ||
Display3: 'DisplaySmall', | ||
Display4: 'DisplayXSmall', | ||
H1: 'HeadingXXLarge', | ||
H2: 'HeadingXLarge', | ||
H3: 'HeadingLarge', | ||
H4: 'HeadingMedium', | ||
H5: 'HeadingSmall', | ||
H6: 'HeadingXSmall', | ||
Paragraph1: 'ParagraphLarge', | ||
Paragraph2: 'ParagraphMedium', | ||
Paragraph3: 'ParagraphSmall', | ||
Paragraph4: 'ParagraphXSmall', | ||
Label1: 'LabelLarge', | ||
Label2: 'LabelMedium', | ||
Label3: 'LabelSmall', | ||
Label4: 'LabelXSmall', | ||
Caption1: 'ParagraphXSmall', | ||
Caption2: 'LabelXSmall', | ||
}; | ||
const getOverrideIfExists = (name, node) => { | ||
// 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 | ||
); | ||
} | ||
return null; | ||
}; | ||
module.exports = { | ||
@@ -19,6 +55,5 @@ meta: { | ||
[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, | ||
}, | ||
@@ -28,9 +63,44 @@ }, | ||
let importState = {}; | ||
const identifiersToRename = {}; | ||
const fixImport = (node, oldComponent, newComponent) => { | ||
context.report({ | ||
node: node.imported, | ||
messageId: MESSAGES.replace.id, | ||
data: { | ||
old: oldComponent, | ||
new: newComponent, | ||
}, | ||
fix: function (fixer) { | ||
return [fixer.replaceText(node.imported, newComponent)]; | ||
}, | ||
}); | ||
}; | ||
const removeImport = (node, specifierIndex, oldName, newName) => { | ||
context.report({ | ||
node, | ||
messageId: MESSAGES.replace.id, | ||
data: { | ||
old: oldName, | ||
new: newName, | ||
}, | ||
fix: function (fixer) { | ||
const isAtStart = specifierIndex === 0; | ||
const startIndex = isAtStart ? specifierIndex : specifierIndex - 1; | ||
const endIndex = isAtStart ? specifierIndex + 1 : specifierIndex; | ||
return fixer.removeRange([ | ||
node.specifiers[startIndex].range[isAtStart ? 0 : 1], | ||
node.specifiers[endIndex].range[isAtStart ? 0 : 1], | ||
]); | ||
}, | ||
}); | ||
}; | ||
return { | ||
ImportSpecifier(node) { | ||
function isImporting(importName, importPath) { | ||
if ( | ||
node.imported.name === importName && | ||
node.parent.source.value === importPath | ||
) { | ||
ImportDeclaration(node) { | ||
if (!node.source.value.startsWith('baseui/')) { | ||
return; | ||
} | ||
function isImporting(node, importName, importPath) { | ||
if (node.imported.name === importName && node.parent.source.value === importPath) { | ||
importState[importName] = node.local.name; | ||
@@ -43,59 +113,67 @@ return true; | ||
// Spinner | ||
// Ex: import {Spinner} from "baseui/spinner"; | ||
// Note, we are not replacing Spinner because the new API | ||
// is not compatible. | ||
if (isImporting('Spinner', 'baseui/spinner')) { | ||
context.report({ | ||
node: node.imported, | ||
messageId: MESSAGES.deprecateSpinner.id, | ||
}); | ||
return; | ||
} | ||
for (let x = 0; x < node.specifiers.length; x++) { | ||
const specifier = node.specifiers[x]; | ||
if ( | ||
specifier.type !== 'ImportNamespaceSpecifier' && | ||
specifier.type !== 'ImportDefaultSpecifier' | ||
) { | ||
// 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, 'Checkbox', 'baseui/checkbox')) return; | ||
if (isImporting(specifier, 'Button', 'baseui/button')) return; | ||
// For Caption1 and Caption2, we want to potentially replace instances | ||
// of the component. We need to consider imports as well as instances | ||
// so that if people use the autofix flag, they don't end up with a | ||
// weird half-way fix. If we find a valid import here, we capture in | ||
// `importState` what the `new` value to use when we rename instances | ||
// later on. One consequence of this approach is that you have to fix | ||
// the import and instance separately if resolving lint warnings | ||
// manually. | ||
if (isImporting('Caption1', 'baseui/typography')) { | ||
context.report({ | ||
node: node.imported, | ||
messageId: MESSAGES.replace.id, | ||
data: { | ||
old: 'Caption1', | ||
new: 'ParagraphXSmall', | ||
}, | ||
fix: function(fixer) { | ||
return [fixer.replaceText(node.imported, 'ParagraphXSmall')]; | ||
}, | ||
}); | ||
return; | ||
// removes return statement since these can be imported together | ||
isImporting(specifier, 'Radio', 'baseui/radio'); | ||
isImporting(specifier, 'RadioGroup', 'baseui/radio'); | ||
} | ||
} | ||
if (isImporting('Caption2', 'baseui/typography')) { | ||
context.report({ | ||
node: node.imported, | ||
messageId: MESSAGES.replace.id, | ||
data: { | ||
old: 'Caption2', | ||
new: 'LabelXSmall', | ||
}, | ||
fix: function(fixer) { | ||
return [fixer.replaceText(node.imported, 'LabelXSmall')]; | ||
}, | ||
}); | ||
if (node.source.value !== 'baseui/typography') { | ||
return; | ||
} | ||
// These can be referenced later on by instances of components. | ||
if (isImporting('Accordion', 'baseui/accordion')) return; | ||
if (isImporting('Modal', 'baseui/modal')) return; | ||
if (isImporting('Block', 'baseui/block')) return; | ||
if (isImporting('Checkbox', 'baseui/checkbox')) return; | ||
if (isImporting('Button', 'baseui/button')) return; | ||
const existingImports = {}; | ||
// Map existing imports (newName: localName), preference given to first renamed import. | ||
node.specifiers.forEach((specifier) => { | ||
if (specifier.type === 'ImportNamespaceSpecifier') { | ||
return; | ||
} | ||
const currentImportedName = specifier.imported.name; | ||
if (existingImports[currentImportedName]) { | ||
if ( | ||
currentImportedName !== specifier.local.name && | ||
existingImports[currentImportedName] === currentImportedName | ||
) { | ||
existingImports[currentImportedName] = specifier.local.name; | ||
} | ||
} else { | ||
existingImports[currentImportedName] = specifier.local.name; | ||
} | ||
}); | ||
const specifiers = node.specifiers || []; | ||
specifiers.forEach((specifier, specifierIndex) => { | ||
if (specifier.type === 'ImportNamespaceSpecifier') { | ||
return; | ||
} | ||
const deprecatedComponent = specifier.imported.name; | ||
const newComponent = mapDeprecatedTypographyComponents[deprecatedComponent]; | ||
if (newComponent) { | ||
const isAlreadyImported = Boolean(existingImports[newComponent]); | ||
const isRenamed = specifier.local.name !== specifier.imported.name; | ||
if (isAlreadyImported) { | ||
removeImport(node, specifierIndex, deprecatedComponent, newComponent); | ||
identifiersToRename[specifier.local.name] = existingImports[newComponent]; | ||
} else { | ||
fixImport(specifier, deprecatedComponent, newComponent); | ||
if (!isRenamed) { | ||
identifiersToRename[specifier.local.name] = newComponent; | ||
} | ||
} | ||
} | ||
}); | ||
}, | ||
@@ -117,5 +195,4 @@ JSXIdentifier(node) { | ||
.some( | ||
ancestor => | ||
ancestor.type === 'JSXOpeningElement' && | ||
ancestor.name.name === component, | ||
(ancestor) => | ||
ancestor.type === 'JSXOpeningElement' && ancestor.name.name === component | ||
) | ||
@@ -126,6 +203,8 @@ ); | ||
// isComponent | ||
// Check if identifier is a component matching "name". | ||
// Ex: isComponent("Boo") with <Boo foo={} /> => true | ||
function isComponent(name) { | ||
return node.name === name && node.parent.type === 'JSXOpeningElement'; | ||
// Check if identifier is a component. | ||
// Ex: isComponent() with <Boo foo={} /> => true | ||
function isComponent() { | ||
return ( | ||
node.parent.type === 'JSXOpeningElement' || node.parent.type === 'JSXClosingElement' | ||
); | ||
} | ||
@@ -140,6 +219,3 @@ | ||
// Replacement: renderAll | ||
if ( | ||
importState.Accordion && | ||
isProp('renderPanelContent', importState.Accordion) | ||
) { | ||
if (importState.Accordion && isProp('renderPanelContent', importState.Accordion)) { | ||
context.report({ | ||
@@ -152,3 +228,3 @@ node, | ||
}, | ||
fix: function(fixer) { | ||
fix: function (fixer) { | ||
return fixer.replaceText(node, 'renderAll'); | ||
@@ -171,3 +247,3 @@ }, | ||
}, | ||
fix: function(fixer) { | ||
fix: function (fixer) { | ||
return fixer.replaceText(node, 'autoFocus'); | ||
@@ -179,20 +255,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, | ||
}); | ||
} | ||
// ====================== | ||
@@ -206,12 +264,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" /> | ||
@@ -225,3 +277,3 @@ context.report({ | ||
}, | ||
fix: function(fixer) { | ||
fix: function (fixer) { | ||
return fixer.replaceText(node.parent.value, `"toggle_round"`); | ||
@@ -244,7 +296,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'); | ||
}, | ||
@@ -256,2 +305,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 | ||
@@ -264,6 +367,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" /> | ||
@@ -298,19 +398,35 @@ context.report({ | ||
if (importState.Modal && isProp('overrides', importState.Modal)) { | ||
// Verify that an object is passed to overrides. | ||
if (node.parent.value.expression.type === 'ObjectExpression') { | ||
// Find object property with "Backdrop" as key. | ||
const property = node.parent.value.expression.properties.find( | ||
property => | ||
property.key && | ||
property.key.name && | ||
property.key.name === 'Backdrop', | ||
); | ||
const property = getOverrideIfExists('Backdrop', node); | ||
if (property) { | ||
context.report({ | ||
node: property, | ||
messageId: MESSAGES.modalBackdrop.id, | ||
}); | ||
return; | ||
} | ||
} | ||
// RadioGroup - All overrides are deprecated except for RadioGroupRoot | ||
// Ex: <RadioGroup overrides={{ RadioMarkInner: {}}} /> | ||
// Ex: <RadioGroup overrides={{ Description: {}}} /> | ||
// Ex: <RadioGroup overrides={{ Root: {}}} /> | ||
// Replacement: None | ||
if (importState.RadioGroup && isProp('overrides', importState.RadioGroup)) { | ||
const properties = [ | ||
'Root', | ||
'Input', | ||
'Label', | ||
'Description', | ||
'RadioMarkInner', | ||
'RadioMarkOuter', | ||
]; | ||
properties.map((val) => { | ||
const property = getOverrideIfExists(val, node); | ||
if (property) { | ||
context.report({ | ||
node: property, | ||
messageId: MESSAGES.modalBackdrop.id, | ||
messageId: MESSAGES.radioGroupOverrides.id, | ||
}); | ||
return; | ||
} | ||
} | ||
}); | ||
} | ||
@@ -325,6 +441,9 @@ | ||
// Replace deprecated component usage. | ||
// Caption1 | ||
// Ex: <Caption1 /> | ||
// Replacement: ParagraphXSmall | ||
if (importState.Caption1 && isComponent('Caption1')) { | ||
if (Object.prototype.hasOwnProperty.call(identifiersToRename, node.name) && isComponent()) { | ||
const oldName = node.name; | ||
const newName = identifiersToRename[node.name]; | ||
context.report({ | ||
@@ -334,22 +453,13 @@ node, | ||
data: { | ||
old: 'Caption1', | ||
new: 'ParagraphXSmall', | ||
old: oldName, | ||
new: newName, | ||
}, | ||
fix: function(fixer) { | ||
return [ | ||
fixer.replaceText(node, 'ParagraphXSmall'), | ||
fixer.replaceText( | ||
node.parent.parent.closingElement.name, | ||
'ParagraphXSmall', | ||
), | ||
]; | ||
fix: function (fixer) { | ||
return [fixer.replaceText(node, newName)]; | ||
}, | ||
}); | ||
return; | ||
} | ||
// Caption2 | ||
// Ex: <Caption2 /> | ||
// Replacement: LabelXSmall | ||
if (importState.Caption2 && isComponent('Caption2')) { | ||
}, | ||
Identifier(node) { | ||
const fixIdentifier = (oldComponent, newComponent) => { | ||
context.report({ | ||
@@ -359,17 +469,23 @@ node, | ||
data: { | ||
old: 'Caption2', | ||
new: 'LabelXSmall', | ||
old: oldComponent, | ||
new: newComponent, | ||
}, | ||
fix: function(fixer) { | ||
return [ | ||
fixer.replaceText(node, 'LabelXSmall'), | ||
fixer.replaceText( | ||
node.parent.parent.closingElement.name, | ||
'LabelXSmall', | ||
), | ||
]; | ||
fix: function (fixer) { | ||
return [fixer.replaceText(node, newComponent)]; | ||
}, | ||
}); | ||
return; | ||
}; | ||
function isIdentifier() { | ||
return ( | ||
node.type === 'Identifier' && | ||
!['ImportSpecifier', 'JSXIdentifier'].includes(node.parent.type) | ||
); | ||
} | ||
if ( | ||
Object.prototype.hasOwnProperty.call(identifiersToRename, node.name) && | ||
isIdentifier() | ||
) { | ||
fixIdentifier(node.name, identifiersToRename[node.name]); | ||
} | ||
}, | ||
@@ -376,0 +492,0 @@ }; |
/* | ||
Copyright (c) 2018-2020 Uber Technologies, Inc. | ||
Copyright (c) Uber Technologies, Inc. | ||
@@ -111,5 +111,2 @@ This source code is licensed under the MIT license found in the | ||
}, | ||
sliderHandleFill: { | ||
concern: 'colors', | ||
}, | ||
sliderHandleFillHover: { | ||
@@ -130,5 +127,2 @@ concern: 'colors', | ||
}, | ||
sliderHandleFillDisabled: { | ||
concern: 'colors', | ||
}, | ||
sliderBorder: { | ||
@@ -164,2 +158,8 @@ concern: 'colors', | ||
}, | ||
rating200: { | ||
concern: 'colors', | ||
}, | ||
rating400: { | ||
concern: 'colors', | ||
}, | ||
// These are marked as deprecated in baseweb:src/theme.ts. | ||
@@ -273,7 +273,5 @@ // Strangely, they are not in baseweb:src/themes/types.js, so I'm not sure where they came from. | ||
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' | ||
); | ||
@@ -283,3 +281,3 @@ | ||
importSpecifier = importDeclaration.specifiers.find( | ||
specifier => specifier.imported.name === 'createTheme', | ||
(specifier) => specifier.imported.name === 'createTheme' | ||
); | ||
@@ -330,5 +328,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'); | ||
@@ -367,5 +363,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'); | ||
@@ -379,6 +373,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 ( | ||
@@ -400,3 +391,3 @@ node.parent.type === 'MemberExpression' && | ||
const concernPropertyNode = $themeProperty.value.properties.find( | ||
property => property.key.name === themeProperty.concern, | ||
(property) => property.key.name === themeProperty.concern | ||
); | ||
@@ -420,8 +411,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 | ||
); | ||
@@ -445,4 +433,3 @@ if (deprecatedProperty) { | ||
node === deprecatedProperty.key || | ||
(node !== deprecatedProperty.value && | ||
node.parent.type !== 'MemberExpression') | ||
(node !== deprecatedProperty.value && node.parent.type !== 'MemberExpression') | ||
) { | ||
@@ -476,3 +463,3 @@ return true; | ||
const declarations = scope.block.body.body.filter( | ||
statement => statement.type === 'VariableDeclaration', | ||
(statement) => statement.type === 'VariableDeclaration' | ||
); | ||
@@ -491,9 +478,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' | ||
); | ||
@@ -506,6 +493,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. | ||
@@ -539,3 +523,3 @@ // Ex: const [css, theme] = useStyletron(); | ||
const concernPropertyNode = themeIndexNode.properties.find( | ||
property => property.key.name === themeProperty.concern, | ||
(property) => property.key.name === themeProperty.concern | ||
); | ||
@@ -559,6 +543,3 @@ | ||
if ( | ||
concernPropertyNode && | ||
concernPropertyNode.value.type === 'ObjectPattern' | ||
) { | ||
if (concernPropertyNode && concernPropertyNode.value.type === 'ObjectPattern') { | ||
// We are destructuring even further! | ||
@@ -570,3 +551,3 @@ | ||
const deprecatedProperty = concernPropertyNode.value.properties.find( | ||
property => property.key.name === node.name, | ||
(property) => property.key.name === node.name | ||
); | ||
@@ -580,4 +561,3 @@ | ||
(node === deprecatedProperty.key || | ||
(node !== deprecatedProperty.value && | ||
node.parent.type !== 'MemberExpression')) | ||
(node !== deprecatedProperty.value && node.parent.type !== 'MemberExpression')) | ||
) { | ||
@@ -599,4 +579,3 @@ return true; | ||
messages: { | ||
[MESSAGES.deprecateThemeProperty.id]: | ||
MESSAGES.deprecateThemeProperty.message, | ||
[MESSAGES.deprecateThemeProperty.id]: MESSAGES.deprecateThemeProperty.message, | ||
[MESSAGES.replaceThemeProperty.id]: MESSAGES.replaceThemeProperty.message, | ||
@@ -608,8 +587,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. | ||
@@ -622,3 +596,3 @@ const deprecatedThemeProperty = deprecatedThemeProperties[node.name]; | ||
messageId: MESSAGES.deprecateThemeProperty.id, | ||
data: {old: node.name}, | ||
data: { old: node.name }, | ||
fix: null, | ||
@@ -631,7 +605,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); | ||
}; | ||
@@ -638,0 +609,0 @@ } |
/* | ||
Copyright (c) 2018-2020 Uber Technologies, Inc. | ||
Copyright (c) Uber Technologies, Inc. | ||
@@ -13,2 +13,5 @@ This source code is licensed under the MIT license found in the | ||
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 @@ }, |
/* | ||
Copyright (c) 2018-2020 Uber Technologies, Inc. | ||
Copyright (c) Uber Technologies, Inc. | ||
@@ -23,6 +23,2 @@ This source code is licensed under the MIT license found in the | ||
}, | ||
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: { | ||
@@ -40,2 +36,26 @@ id: 'styleOnBlock', | ||
}, | ||
progressBarSuccessValue: { | ||
id: 'progressBarSuccessValue', | ||
message: | ||
'The "successValue" prop has been deprecated. The "value" prop should be normalized as though "successValue" was always set to 100.', | ||
}, | ||
selectSearchIcon: { | ||
id: 'selectSearchIcon', | ||
message: 'The "SearchIcon" override will be removed in favor of "StyledSearchIconContainer".', | ||
}, | ||
radioGroupOverrides: { | ||
id: 'radioGroupOverrides', | ||
message: | ||
'All overrides on RadioGroup except RadioGroupRoot are deprecated. Please apply overrides to individual radio buttons', | ||
}, | ||
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.', | ||
}, | ||
}; |
/* | ||
Copyright (c) 2018-2020 Uber Technologies, Inc. | ||
Copyright (c) Uber Technologies, Inc. | ||
@@ -4,0 +4,0 @@ This source code is licensed under the MIT license found in the |
104011
24
3359
89
2
6
+ Addedjsx-ast-utils@^3.2.1
+ Added@eslint-community/eslint-utils@4.4.1(transitive)
+ Added@eslint-community/regexpp@4.12.1(transitive)
+ Added@eslint/eslintrc@2.1.4(transitive)
+ Added@eslint/js@8.57.1(transitive)
+ Added@humanwhocodes/config-array@0.13.0(transitive)
+ Added@humanwhocodes/module-importer@1.0.1(transitive)
+ Added@humanwhocodes/object-schema@2.0.3(transitive)
+ Added@nodelib/fs.scandir@2.1.5(transitive)
+ Added@nodelib/fs.stat@2.0.5(transitive)
+ Added@nodelib/fs.walk@1.2.8(transitive)
+ Added@ungap/structured-clone@1.3.0(transitive)
+ Addedacorn@8.14.0(transitive)
+ Addedargparse@2.0.1(transitive)
+ Addedarray-buffer-byte-length@1.0.2(transitive)
+ Addedarray-includes@3.1.8(transitive)
+ Addedarray.prototype.flat@1.3.3(transitive)
+ Addedarraybuffer.prototype.slice@1.0.4(transitive)
+ Addedasync-function@1.0.0(transitive)
+ Addedavailable-typed-arrays@1.0.7(transitive)
+ Addedcall-bind@1.0.8(transitive)
+ Addedcall-bind-apply-helpers@1.0.1(transitive)
+ Addedcall-bound@1.0.3(transitive)
+ Addedcross-spawn@7.0.6(transitive)
+ Addeddata-view-buffer@1.0.2(transitive)
+ Addeddata-view-byte-length@1.0.2(transitive)
+ Addeddata-view-byte-offset@1.0.1(transitive)
+ Addeddefine-data-property@1.1.4(transitive)
+ Addeddefine-properties@1.2.1(transitive)
+ Addeddunder-proto@1.0.1(transitive)
+ Addedes-abstract@1.23.9(transitive)
+ Addedes-define-property@1.0.1(transitive)
+ Addedes-errors@1.3.0(transitive)
+ Addedes-object-atoms@1.1.1(transitive)
+ Addedes-set-tostringtag@2.1.0(transitive)
+ Addedes-shim-unscopables@1.0.2(transitive)
+ Addedes-to-primitive@1.3.0(transitive)
+ Addedescape-string-regexp@4.0.0(transitive)
+ Addedeslint@8.57.1(transitive)
+ Addedeslint-scope@7.2.2(transitive)
+ Addedeslint-visitor-keys@3.4.3(transitive)
+ Addedespree@9.6.1(transitive)
+ Addedfastq@1.19.0(transitive)
+ Addedfile-entry-cache@6.0.1(transitive)
+ Addedfind-up@5.0.0(transitive)
+ Addedflat-cache@3.2.0(transitive)
+ Addedflatted@3.3.2(transitive)
+ Addedfor-each@0.3.4(transitive)
+ Addedfunction-bind@1.1.2(transitive)
+ Addedfunction.prototype.name@1.1.8(transitive)
+ Addedfunctions-have-names@1.2.3(transitive)
+ Addedget-intrinsic@1.2.7(transitive)
+ Addedget-proto@1.0.1(transitive)
+ Addedget-symbol-description@1.1.0(transitive)
+ Addedglob-parent@6.0.2(transitive)
+ Addedglobals@13.24.0(transitive)
+ Addedglobalthis@1.0.4(transitive)
+ Addedgopd@1.2.0(transitive)
+ Addedgraphemer@1.4.0(transitive)
+ Addedhas-bigints@1.1.0(transitive)
+ Addedhas-property-descriptors@1.0.2(transitive)
+ Addedhas-proto@1.2.0(transitive)
+ Addedhas-symbols@1.1.0(transitive)
+ Addedhas-tostringtag@1.0.2(transitive)
+ Addedhasown@2.0.2(transitive)
+ Addedignore@5.3.2(transitive)
+ Addedinternal-slot@1.1.0(transitive)
+ Addedis-array-buffer@3.0.5(transitive)
+ Addedis-async-function@2.1.1(transitive)
+ Addedis-bigint@1.1.0(transitive)
+ Addedis-boolean-object@1.2.2(transitive)
+ Addedis-callable@1.2.7(transitive)
+ Addedis-data-view@1.0.2(transitive)
+ Addedis-date-object@1.1.0(transitive)
+ Addedis-finalizationregistry@1.1.1(transitive)
+ Addedis-generator-function@1.1.0(transitive)
+ Addedis-map@2.0.3(transitive)
+ Addedis-number-object@1.1.1(transitive)
+ Addedis-path-inside@3.0.3(transitive)
+ Addedis-regex@1.2.1(transitive)
+ Addedis-set@2.0.3(transitive)
+ Addedis-shared-array-buffer@1.0.4(transitive)
+ Addedis-string@1.1.1(transitive)
+ Addedis-symbol@1.1.1(transitive)
+ Addedis-typed-array@1.1.15(transitive)
+ Addedis-weakmap@2.0.2(transitive)
+ Addedis-weakref@1.1.1(transitive)
+ Addedis-weakset@2.0.4(transitive)
+ Addedisarray@2.0.5(transitive)
+ Addedjs-yaml@4.1.0(transitive)
+ Addedjson-buffer@3.0.1(transitive)
+ Addedjsx-ast-utils@3.3.5(transitive)
+ Addedkeyv@4.5.4(transitive)
+ Addedlevn@0.4.1(transitive)
+ Addedlocate-path@6.0.0(transitive)
+ Addedlodash.merge@4.6.2(transitive)
+ Addedmath-intrinsics@1.1.0(transitive)
+ Addedobject-inspect@1.13.4(transitive)
+ Addedobject-keys@1.1.1(transitive)
+ Addedobject.assign@4.1.7(transitive)
+ Addedobject.values@1.2.1(transitive)
+ Addedoptionator@0.9.4(transitive)
+ Addedown-keys@1.0.1(transitive)
+ Addedp-limit@3.1.0(transitive)
+ Addedp-locate@5.0.0(transitive)
+ Addedpath-exists@4.0.0(transitive)
+ Addedpath-key@3.1.1(transitive)
+ Addedpossible-typed-array-names@1.1.0(transitive)
+ Addedprelude-ls@1.2.1(transitive)
+ Addedqueue-microtask@1.2.3(transitive)
+ Addedreflect.getprototypeof@1.0.10(transitive)
+ Addedregexp.prototype.flags@1.5.4(transitive)
+ Addedreusify@1.0.4(transitive)
+ Addedrimraf@3.0.2(transitive)
+ Addedrun-parallel@1.2.0(transitive)
+ Addedsafe-array-concat@1.1.3(transitive)
+ Addedsafe-push-apply@1.0.0(transitive)
+ Addedsafe-regex-test@1.1.0(transitive)
+ Addedset-function-length@1.2.2(transitive)
+ Addedset-function-name@2.0.2(transitive)
+ Addedset-proto@1.0.0(transitive)
+ Addedshebang-command@2.0.0(transitive)
+ Addedshebang-regex@3.0.0(transitive)
+ Addedside-channel@1.1.0(transitive)
+ Addedside-channel-list@1.0.0(transitive)
+ Addedside-channel-map@1.0.1(transitive)
+ Addedside-channel-weakmap@1.0.2(transitive)
+ Addedstring.prototype.trim@1.2.10(transitive)
+ Addedstring.prototype.trimend@1.0.9(transitive)
+ Addedstring.prototype.trimstart@1.0.8(transitive)
+ Addedtype-check@0.4.0(transitive)
+ Addedtype-fest@0.20.2(transitive)
+ Addedtyped-array-buffer@1.0.3(transitive)
+ Addedtyped-array-byte-length@1.0.3(transitive)
+ Addedtyped-array-byte-offset@1.0.4(transitive)
+ Addedtyped-array-length@1.0.7(transitive)
+ Addedunbox-primitive@1.1.0(transitive)
+ Addedwhich@2.0.2(transitive)
+ Addedwhich-boxed-primitive@1.1.1(transitive)
+ Addedwhich-builtin-type@1.2.1(transitive)
+ Addedwhich-collection@1.0.2(transitive)
+ Addedwhich-typed-array@1.1.18(transitive)
+ Addedyocto-queue@0.1.0(transitive)
- Removed@babel/code-frame@7.26.2(transitive)
- Removed@babel/helper-validator-identifier@7.25.9(transitive)
- Removedacorn@7.4.1(transitive)
- Removedansi-escapes@4.3.2(transitive)
- Removedansi-regex@4.1.1(transitive)
- Removedansi-styles@3.2.1(transitive)
- Removedargparse@1.0.10(transitive)
- Removedastral-regex@1.0.0(transitive)
- Removedchalk@2.4.2(transitive)
- Removedchardet@0.7.0(transitive)
- Removedcli-cursor@3.1.0(transitive)
- Removedcli-width@3.0.0(transitive)
- Removedcolor-convert@1.9.3(transitive)
- Removedcolor-name@1.1.3(transitive)
- Removedcross-spawn@6.0.6(transitive)
- Removedemoji-regex@7.0.38.0.0(transitive)
- Removedescape-string-regexp@1.0.5(transitive)
- Removedeslint@6.8.0(transitive)
- Removedeslint-scope@5.1.1(transitive)
- Removedeslint-utils@1.4.3(transitive)
- Removedeslint-visitor-keys@1.3.0(transitive)
- Removedespree@6.2.1(transitive)
- Removedesprima@4.0.1(transitive)
- Removedestraverse@4.3.0(transitive)
- Removedexternal-editor@3.1.0(transitive)
- Removedfigures@3.2.0(transitive)
- Removedfile-entry-cache@5.0.1(transitive)
- Removedflat-cache@2.0.1(transitive)
- Removedflatted@2.0.2(transitive)
- Removedfunctional-red-black-tree@1.0.1(transitive)
- Removedglob-parent@5.1.2(transitive)
- Removedglobals@12.4.0(transitive)
- Removedhas-flag@3.0.0(transitive)
- Removediconv-lite@0.4.24(transitive)
- Removedignore@4.0.6(transitive)
- Removedinquirer@7.3.3(transitive)
- Removedis-fullwidth-code-point@2.0.03.0.0(transitive)
- Removedjs-tokens@4.0.0(transitive)
- Removedjs-yaml@3.14.1(transitive)
- Removedlevn@0.3.0(transitive)
- Removedlodash@4.17.21(transitive)
- Removedmimic-fn@2.1.0(transitive)
- Removedminimist@1.2.8(transitive)
- Removedmkdirp@0.5.6(transitive)
- Removedmute-stream@0.0.8(transitive)
- Removednice-try@1.0.5(transitive)
- Removedonetime@5.1.2(transitive)
- Removedoptionator@0.8.3(transitive)
- Removedos-tmpdir@1.0.2(transitive)
- Removedpath-key@2.0.1(transitive)
- Removedpicocolors@1.1.1(transitive)
- Removedprelude-ls@1.1.2(transitive)
- Removedprogress@2.0.3(transitive)
- Removedregexpp@2.0.1(transitive)
- Removedrestore-cursor@3.1.0(transitive)
- Removedrimraf@2.6.3(transitive)
- Removedrun-async@2.4.1(transitive)
- Removedrxjs@6.6.7(transitive)
- Removedsafer-buffer@2.1.2(transitive)
- Removedsemver@5.7.26.3.1(transitive)
- Removedshebang-command@1.2.0(transitive)
- Removedshebang-regex@1.0.0(transitive)
- Removedsignal-exit@3.0.7(transitive)
- Removedslice-ansi@2.1.0(transitive)
- Removedsprintf-js@1.0.3(transitive)
- Removedstring-width@3.1.04.2.3(transitive)
- Removedstrip-ansi@5.2.0(transitive)
- Removedsupports-color@5.5.0(transitive)
- Removedtable@5.4.6(transitive)
- Removedthrough@2.3.8(transitive)
- Removedtmp@0.0.33(transitive)
- Removedtslib@1.14.1(transitive)
- Removedtype-check@0.3.2(transitive)
- Removedtype-fest@0.21.30.8.1(transitive)
- Removedv8-compile-cache@2.4.0(transitive)
- Removedwhich@1.3.1(transitive)
- Removedwrite@1.0.3(transitive)