Skip to content

Commit

Permalink
feat(eslint-plugin): add no-restricted-eui-imports rule
Browse files Browse the repository at this point in the history
  • Loading branch information
weronikaolejniczak committed Dec 10, 2024
1 parent b937ece commit 3be0462
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 5 deletions.
18 changes: 13 additions & 5 deletions packages/eslint-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ This package contains an eslint plugin that enforces some default rules for usin

## Setup

1. install `@elastic/eslint-plugin-eui` as a dev dependency
2. extend `plugin:@elastic/eui/recommended` in your eslint config
1. Install `@elastic/eslint-plugin-eui` as a dev dependency.
2. Extend `plugin:@elastic/eui/recommended` in your eslint config.

## Rules

Expand All @@ -15,11 +15,19 @@ This package contains an eslint plugin that enforces some default rules for usin

In some cases it makes sense to disable this rule locally, such as when <kbd>cmd</kbd>+click should open the link in a new tab, but a standard click should use the `history.pushState()` API to change the URL without triggering a full page load.

### `@elastic/eui/no-restricted-eui-imports`

At times, we deprecate features that may need more highlighting and/or that are not possible to annotate with JSDoc `@deprecated`, e.g. JSON token imports: `@elastic/eui/dist/eui_theme_*.json` (for context: https://github.com/elastic/kibana/issues/199715#json-tokens).

We don't use `no-restricted-imports` because ESLint doesn't allow multiple error levels at once and it may conflict with the consumer's existing ESLint configuration for that rule. We need to assure that our rule will produce a warning (as a recommendation).

All deprecations still must follow our [deprecation process](../../wiki/eui-team-processes/deprecations.md).

## Publishing

This package is published separately from the rest of EUI, as required by eslint. The code is not transpiled, so make sure to use `require()` statements rather than `import`, and once the code is updated run:

1. `npm version patch|minor|major`
2. commit version bump
3. `npm publish` in this directory
4. push the version bump upstream
2. Commit version bump.
3. `npm publish` in this directory.
4. Push the version bump upstream.
2 changes: 2 additions & 0 deletions packages/eslint-plugin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@
module.exports = {
rules: {
'href-or-on-click': require('./rules/href_or_on_click'),
'no-restricted-eui-imports': require('./rules/no_restricted_eui_imports'),
},
configs: {
recommended: {
plugins: ['@elastic/eslint-plugin-eui'],
rules: {
'@elastic/eui/href-or-on-click': 'warn',
'@elastic/eui/no-restricted-eui-imports': 'warn',
},
},
},
Expand Down
62 changes: 62 additions & 0 deletions packages/eslint-plugin/rules/no_restricted_eui_imports.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
const DEFAULT_RESTRICTED_IMPORT_PATTERNS = [
{
pattern: '@elastic/eui/dist/eui_theme_*.json',
message:
'Please use `useEuiTheme` instead. Direct JSON token imports will be removed as per the EUI Deprecation schedule: https://github.com/elastic/eui/issues/1469.',
},
];

module.exports = {
meta: {
type: 'problem',
docs: {
description: 'Disallow deprecated EUI imports.',
category: 'Possible Errors',
recommended: false,
},
schema: [
{
type: 'object',
properties: {
patterns: {
type: 'array',
items: {
type: 'object',
properties: {
pattern: { type: 'string' },
message: { type: 'string' },
},
required: ['pattern'],
additionalProperties: false,
},
uniqueItems: true,
},
},
additionalProperties: false,
},
],
},

create(context) {
const options = context.options[0] || {};
const userPatterns = options.patterns || [];

// Combine the default patterns with the user-defined patterns
const allPatterns = [DEFAULT_RESTRICTED_IMPORT_PATTERNS, ...userPatterns];

return {
ImportDeclaration(node) {
allPatterns.forEach(({ pattern, message }) => {
const regex = new RegExp(pattern.replace('*', '.*'));
if (regex.test(node.source.value)) {
context.report({
node,
message:
message || `Importing "${node.source.value}" is restricted.`,
});
}
});
},
};
},
};
50 changes: 50 additions & 0 deletions packages/eslint-plugin/rules/no_restricted_eui_imports.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const { RuleTester } = require('eslint');
const rule = require('./no_restricted_eui_imports');

const ruleTester = new RuleTester({
parser: require.resolve('babel-eslint'),
parserOptions: {
ecmaVersion: 2018,
},
});

ruleTester.run('@elastic/eui/no-restricted-eui-imports', rule, {
valid: [
{
code: "import { EuiButton } from '@elastic/eui';",
},
{
code: "import theme from '@kbn/ui-theme';",
},
],

invalid: [
{
code: "import theme from '@elastic/eui/dist/eui_theme_light.json';",
errors: [
{
message:
'Please use `useEuiTheme` instead. Direct JSON token imports will be removed as per the EUI Deprecation schedule: https://github.com/elastic/eui/issues/1469.',
},
],
},
{
code: "import theme from '@kbn/ui-theme';",
options: [
{
patterns: [
{
pattern: '@kbn/ui-theme',
message: 'Please use `useEuiTheme` from `@elastic/eui` instead.',
},
],
},
],
errors: [
{
message: 'Please use `useEuiTheme` from `@elastic/eui` instead.',
},
],
},
],
});

0 comments on commit 3be0462

Please sign in to comment.