Skip to content

Commit

Permalink
Merge pull request #21 from elisecodedestrucs/no-css-animation
Browse files Browse the repository at this point in the history
add rule no-css-animations
  • Loading branch information
utarwyn authored Aug 17, 2023
2 parents 72dfdf4 + 2879047 commit 1b0cd07
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ 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`
- [#19](https://github.com/green-code-initiative/ecoCode-javascript/pull/19) add rule `@ecocode/no-empty-image-src-attribute`
- [#18](https://github.com/green-code-initiative/ecoCode-javascript/pull/18) add rule `@ecocode/limit-db-query-results`
- [#14](https://github.com/green-code-initiative/ecoCode-javascript/pull/14) Create SonarQube plugin
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. ||
| [limit-db-query-results](docs/rules/limit-db-query-results.md) | Should limit the number of returns for a SQL query ||
| [no-empty-image-src-attribute](docs/rules/no-empty-image-src-attribute.md) | Disallow usage of image with empty source attribute ||
Expand Down
31 changes: 31 additions & 0 deletions eslint-plugin/docs/rules/avoid-css-animations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# 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={{ border: "1px solid black", transition: "border 2s ease" }}/>
```

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

```js
<div style={{ border: "1px solid black" }}/>
```

## Further details

This recommendation is made by the
CNUMR: [Avoid JavaScript / CSS animations](https://github.com/cnumr/best-practices/blob/main/chapters/BP_039_en.md)
62 changes: 62 additions & 0 deletions eslint-plugin/lib/rules/avoid-css-animations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* 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) {
const forbiddenProperties = ["transition", "animation"];
return {
JSXOpeningElement(node) {
const styleAttribute = node.attributes.find(
(attribute) => attribute.name.name === "style",
);

if (styleAttribute && styleAttribute.value.expression) {
// To prevent (for example) <div style={{ animate: 'width 2s' }}>
const property = styleAttribute.value.expression.properties.find(
(prop) =>
forbiddenProperties.some((forbidProp) =>
prop.key.name.includes(forbidProp),
),
);
if (property != null) {
context.report({
node: property,
messageId: "AvoidCSSAnimations",
data: {
attribute: property.key.name,
},
});
}
}
},
};
},
};
82 changes: 82 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,82 @@
/**
* 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;
`,
`<div style={{ width: '100px', height: '100px' }}>Hello world</div>`,
`<div style="border: 2px solid red">My red element</div>`,
],

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 1b0cd07

Please sign in to comment.