Skip to content

Commit 166d1ad

Browse files
committed
[ec36-avoid-autoplay] implement rule autoplay and preload
1 parent b80b84e commit 166d1ad

File tree

3 files changed

+204
-0
lines changed

3 files changed

+204
-0
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Disallow usage of image with empty source attribute (`@ecocode/no-empty-image-src-attribute`)
2+
3+
⚠️ This rule _warns_ in the ✅ `recommended` config.
4+
5+
<!-- end auto-generated rule header -->
6+
7+
## Why is this an issue?
8+
9+
Automatic videos and audio files activation (autoplay) during web pages loading uses resources on each tier (device,
10+
network, data center). In many cases, automatic playback is not necessary. Moreover, it can draw users' attention and
11+
distract them from the initially requested service. Therefore, whenever possible, these playbacks should be initiated by
12+
the users and by not using the autoplay attributes in the `<audio>` and `<video>` elements.
13+
14+
Nevertheless, some parts of the video or audio files may be downloaded even if autoplay is not activated. Moreover, data
15+
will be unnecessarily downloaded even if users do not start the video playback. It is therefore necessary to force
16+
browsers not to preload anything by setting the `preload` attribute to `none`.
17+
18+
```jsx
19+
return (
20+
<>
21+
<video src="video.mp4" autoplay/> // Non-compliant
22+
<video src="video.mp4" preload="auto"/> // Non-compliant
23+
<video src="video.mp4" autoplay preload="auto"/> // Non-compliant
24+
<video src="video.mp4" preload="none"/> // Compliant
25+
</>
26+
)
27+
```
28+
29+
This rule is build for [React](https://react.dev/) and JSX.
30+
31+
## Resources
32+
33+
### Documentation
34+
35+
- [Mozilla Web Technology for Developers](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/autoplay) -
36+
Autoplay in HTML
37+
- [Mozilla Web Technology for Developers](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video) - Video and
38+
audio content
39+
- [Mozilla Web Technology for Developers](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video#attr-preload) -
40+
Preload in HTML
41+
42+
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* ecoCode JavaScript plugin - Provides rules to reduce the environmental footprint of your JavaScript programs
3+
* Copyright © 2023 Green Code Initiative (https://www.ecocode.io)
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
"use strict";
20+
21+
/** @type {import('eslint').Rule.RuleModule} */
22+
module.exports = {
23+
meta: {
24+
type: "suggestion",
25+
docs: {
26+
description: "Disallow autoplay and enforce preload='none' for video and audio elements",
27+
category: "eco-design",
28+
recommended: "warn",
29+
},
30+
messages: {
31+
NoAutoplay: "Avoid using autoplay attribute for <video> and <audio> elements.",
32+
EnforcePreloadNone: "Set preload='none' for <video> and <audio> elements.",
33+
NoAutoplay_EnforcePreloadNone: "Avoid using autoplay attribute and set preload='none' for <video> and <audio> elements.",
34+
},
35+
schema: [],
36+
},
37+
create(context) {
38+
return {
39+
JSXOpeningElement(node) {
40+
if (node.name.name === "video" || node.name.name === "audio") {
41+
const autoplayAttr = node.attributes.find(
42+
(attr) => attr.name.name === "autoplay",
43+
);
44+
const preloadAttr = node.attributes.find(
45+
(attr) => attr.name.name === "preload",
46+
);
47+
if(autoplayAttr && (!preloadAttr || preloadAttr.value.value !== "none")) {
48+
// console.log("NoAutoplay_EnforcePreloadNone")
49+
context.report({
50+
node: autoplayAttr||preloadAttr,
51+
messageId: "NoAutoplay_EnforcePreloadNone",
52+
});
53+
}
54+
else {
55+
if (autoplayAttr) {
56+
//console.log("NoAutoplay", autoplayAttr)
57+
context.report({
58+
node: autoplayAttr,
59+
messageId: "NoAutoplay",
60+
});
61+
}
62+
63+
if (!preloadAttr || preloadAttr.value.value !== "none") {
64+
context.report({
65+
node: preloadAttr || node,
66+
messageId: "EnforcePreloadNone",
67+
});
68+
}
69+
}
70+
}
71+
},
72+
};
73+
},
74+
};
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* ecoCode JavaScript plugin - Provides rules to reduce the environmental footprint of your JavaScript programs
3+
* Copyright © 2023 Green Code Initiative (https://www.ecocode.io)
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
"use strict";
20+
21+
//------------------------------------------------------------------------------
22+
// Requirements
23+
//------------------------------------------------------------------------------
24+
25+
const rule = require("../../../lib/rules/avoid-autoplay");
26+
const RuleTester = require("eslint").RuleTester;
27+
28+
//------------------------------------------------------------------------------
29+
// Tests
30+
//------------------------------------------------------------------------------
31+
32+
const ruleTester = new RuleTester({
33+
parserOptions: {
34+
ecmaVersion: 2021,
35+
sourceType: "module",
36+
ecmaFeatures: {
37+
jsx: true,
38+
},
39+
},
40+
});
41+
const expectedError1 = {
42+
messageId: "NoAutoplay",
43+
type: "JSXAttribute",
44+
};
45+
const expectedError2 = {
46+
messageId: "EnforcePreloadNone",
47+
type: "JSXAttribute",
48+
};
49+
const expectedError3 = {
50+
messageId: "NoAutoplay_EnforcePreloadNone",
51+
type: "JSXAttribute",
52+
};
53+
54+
55+
ruleTester.run("autoplay-audio-video-attribute-not-present", rule, {
56+
valid: [
57+
`
58+
<audio preload="none"></audio>
59+
`,
60+
'<video preload="none"></video>',
61+
],
62+
63+
invalid: [
64+
{
65+
code: `
66+
<audio autoplay></audio>
67+
`,
68+
errors: [expectedError3],
69+
},
70+
{
71+
code: `
72+
<video autoplay preload="auto"></video>
73+
`,
74+
errors: [expectedError3],
75+
}
76+
,
77+
{
78+
code:'<video autoplay preload="none"></video>',
79+
errors: [expectedError1],
80+
}
81+
,
82+
{
83+
code:'<audio preload="auto"></audio>',
84+
errors: [expectedError2],
85+
}
86+
87+
],
88+
});

0 commit comments

Comments
 (0)