Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add no-deprecated-props rule #156

Merged
merged 9 commits into from
Apr 22, 2024
94 changes: 94 additions & 0 deletions src/rules/__tests__/no-deprecated-props.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
'use strict'

const {RuleTester} = require('eslint')
const rule = require('../no-deprecated-props')

const ruleTester = new RuleTester({
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
ecmaFeatures: {
jsx: true,
},
},
})

ruleTester.run('no-deprecated-props', rule, {
valid: [
`import {ActionList} from '@primer/react';
<ActionList>
<ActionList.Group>
<ActionList.GroupHeading as="h3">Group heading 1</ActionList.GroupHeading>
<ActionList.Item>Item</ActionList.Item>
</ActionList.Group>
<ActionList.Group>
<ActionList.GroupHeading as="h3">Group heading 2</ActionList.GroupHeading>
<ActionList.Item>Item 2</ActionList.Item>
</ActionList.Group>
</ActionList>`,
`import {ActionList} from '@primer/react';
<ActionList>
<ActionList.Group>
<ActionList.GroupHeading>Group heading 1</ActionList.GroupHeading>
<ActionList.Item>Item</ActionList.Item>
</ActionList.Group>
<ActionList.Group>
<ActionList.GroupHeading>Group heading 2</ActionList.GroupHeading>
<ActionList.Item>Item 2</ActionList.Item>
</ActionList.Group>
</ActionList>`,
`import {ActionList} from '@primer/react';
<ActionList>
<ActionList.Group>
<ActionList.GroupHeading as="h3">Group heading</ActionList.GroupHeading>
<ActionList.Item>Item</ActionList.Item>
</ActionList.Group>
<ActionList.Item>Item 2</ActionList.Item>
</ActionList>`,
`import {ActionList} from '@primer/react';
<ActionList role="listbox">
<ActionList.Group>
<ActionList.GroupHeading>Group heading</ActionList.GroupHeading>
<ActionList.Item>Item</ActionList.Item>
</ActionList.Group>
<ActionList.Item>Item 2</ActionList.Item>
</ActionList>`,
`import {ActionList} from '@primer/react';
<ActionList role="menu">
<ActionList.Item>Item</ActionList.Item>
<ActionList.Group>
<ActionList.GroupHeading>Group heading</ActionList.GroupHeading>
<ActionList.Item>Group item</ActionList.Item>
</ActionList.Group>
</ActionList>`,
],
invalid: [
{
code: `<ActionList.Group title="Group heading 1"></ActionList.Group>`,
output: `<ActionList.Group><ActionList.GroupHeading>Group heading 1</ActionList.GroupHeading></ActionList.Group>`,
errors: [
{
messageId: 'titlePropDeprecated',
},
],
},
{
code: `<ActionList.Group title="Group heading 1" sx={{padding: 2}}></ActionList.Group>`,
output: `<ActionList.Group sx={{padding: 2}}><ActionList.GroupHeading>Group heading 1</ActionList.GroupHeading></ActionList.Group>`,
errors: [
{
messageId: 'titlePropDeprecated',
},
],
},
{
code: `<ActionList.Group variant="filled" title="Group heading 1"></ActionList.Group>`,
output: `<ActionList.Group variant="filled"><ActionList.GroupHeading>Group heading 1</ActionList.GroupHeading></ActionList.Group>`,
errors: [
{
messageId: 'titlePropDeprecated',
},
],
},
],
})
54 changes: 54 additions & 0 deletions src/rules/no-deprecated-props.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
'use strict'
const {getJSXOpeningElementAttribute} = require('../utils/get-jsx-opening-element-attribute')
const {getJSXOpeningElementName} = require('../utils/get-jsx-opening-element-name')

const url = require('../url')

/**
* @type {import('eslint').Rule.RuleModule}
*/
module.exports = {
meta: {
type: 'problem',
docs: {
description: 'Avoid using deprecated props from @primer/react',
recommended: true,
url: url(module),
},
fixable: true,
schema: [],
messages: {
titlePropDeprecated: 'The `title` prop is deprecated. Please use `ActionList.GroupHeading` instead.',
},
},
create(context) {
return {
JSXOpeningElement(node) {
const openingElName = getJSXOpeningElementName(node)
if (openingElName !== 'ActionList.Group') {
return
}
const title = getJSXOpeningElementAttribute(node, 'title')

if (title !== undefined) {
context.report({
node,
messageId: 'titlePropDeprecated',
fix(fixer) {
const groupTitle = title.value.value
const start = title.range[0]
const end = title.range[1]
return [
fixer.removeRange([start - 1, end]), // remove the space before the title as well
fixer.insertTextAfterRange(
[node.range[1], node.range[1]],
`<ActionList.GroupHeading>${groupTitle}</ActionList.GroupHeading>`,
),
]
},
})
}
},
}
},
}