Skip to content

Commit

Permalink
add rule avoid-css-animations
Browse files Browse the repository at this point in the history
  • Loading branch information
Elise DUBILLOT committed Aug 17, 2023
1 parent ea5096c commit b614205
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- [#21](https://github.com/green-code-initiative/ecoCode-javascript/pull/21) Add rule `@ecocode/avoid-css-animations`
- [#14](https://github.com/green-code-initiative/ecoCode-javascript/pull/14) Create SonarQube plugin
- [#12](https://github.com/green-code-initiative/ecoCode-javascript/issues/12) Pack ESLint plugin into SonarQube plugin
- [#16](https://github.com/green-code-initiative/ecoCode-javascript/pull/16) Use centralized rules specifications
Expand Down
1 change: 1 addition & 0 deletions eslint-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ Add `@ecocode` to the `plugins` section of your `.eslintrc`, followed by rules c

| Name | Description | ⚠️ |
| :------------------------------------------------------------------------------------- | :--------------------------------------------------------- | :- |
| [avoid-css-animations](docs/rules/avoid-css-animations.md) | Avoid usage of CSS animations ||
| [avoid-high-accuracy-geolocation](docs/rules/avoid-high-accuracy-geolocation.md) | Avoid using high accuracy geolocation in web applications. ||
| [no-import-all-from-library](docs/rules/no-import-all-from-library.md) | Should not import all from library ||
| [no-multiple-access-dom-element](docs/rules/no-multiple-access-dom-element.md) | Disallow multiple access of same DOM element. ||
Expand Down
24 changes: 24 additions & 0 deletions eslint-plugin/docs/rules/avoid-css-animations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Avoid usage of CSS animations (`@ecocode/avoid-css-animations`)

⚠️ This rule _warns_ in the ✅ `recommended` config.

<!-- end auto-generated rule header -->

## Rule Details

This rule aims to limit the usage of all types of CSS animations which can be very costly in terms of CPU and memory.
They must only be used when they are indispensable and should be limited to the CSS properties `opacity` and `transform` with it's associated functions : `translate`, `rotate` and `scale`.
You can also inform the navigator of upcoming changes with the `will-change` instruction for more optimization.

## Examples
Examples of **non compliant** code for this rule:

```js
<div style={{borderWidth:1, borderStyle: 'solid', borderColor: '#000000', transform:'translate(20px)'}}/>
```

Examples of **compliant** code for this rule:

```js
<div style={{borderWidth:1, borderStyle: 'solid', borderColor: '#000000'}}/>
```
61 changes: 61 additions & 0 deletions eslint-plugin/lib/rules/avoid-css-animations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* Copyright (C) 2023 Green Code Initiative
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "Avoid usage of CSS animations",
category: "eco-design",
recommended: "warn",
},
messages: {
AvoidCSSAnimations: "Avoid using {{attribute}} in CSS.",
},
schema: [],
},

create(context) {
return {
JSXOpeningElement(node) {
if (node.attributes.find((attr) => attr.name.name === "style")) {
const styleProp = node.attributes.find(
(attr) => attr.name.name === "style",
);

// To prevent (for example) <div style={{ transform: rotate(30deg) }}>
const transformValue = styleProp.value.expression.properties.find(
(prop) =>
prop.key.name.includes("transition") ||
prop.key.name.includes("animation"),
);
if (transformValue && transformValue.value) {
context.report({
node: transformValue,
messageId: "AvoidCSSAnimations",
data: {
attribute: transformValue.key.name,
},
});
}
}
},
};
},
};
2 changes: 1 addition & 1 deletion eslint-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@
"eslint": ">=7"
},
"packageManager": "[email protected]"
}
}
80 changes: 80 additions & 0 deletions eslint-plugin/tests/lib/rules/avoid-css-animations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* Copyright (C) 2023 Green Code Initiative
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const rule = require("../../../lib/rules/avoid-css-animations");
const RuleTester = require("eslint").RuleTester;

//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------

const ruleTester = new RuleTester({
parserOptions: {
ecmaVersion: 2021,
sourceType: "module",
ecmaFeatures: {
jsx: true,
},
},
});

ruleTester.run("avoid-css-animations", rule, {
valid: [
`
import React from 'react';
import './styles.css'; // External CSS file
const MyComponent = () => {
return <div className="my-class">This content is styled using an external CSS file.</div>;
};
export default MyComponent;
`,
],

invalid: [
{
code: "<div style={{ transition: 'width 2s' }} />",
errors: [
{
messageId: "AvoidCSSAnimations",
data: {
attribute: "transition",
},
type: "Property",
},
],
},
{
code: "<div style={{ animationName: 'example', animationDuration: '4s' }} />",
errors: [
{
messageId: "AvoidCSSAnimations",
data: {
attribute: "animationName",
},
type: "Property",
},
],
},
],
});

0 comments on commit b614205

Please sign in to comment.