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 rule no-css-animations #21

Merged
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 != null) {
// 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,
},
});
}
}
},
};
},
};
81 changes: 81 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,81 @@
/**
* 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>`,
],

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",
},
],
},
],
});