New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

eslint-plugin-baseui

Package Overview
Dependencies
Maintainers
1
Versions
711
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-plugin-baseui - npm Package Compare versions

Comparing version 0.0.0-next-45f4560 to 0.0.0-next-46c9467

__tests__/no-block-style.test.js

6

__tests__/config.test.js
/*
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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc