Skip to content

Commit 2886107

Browse files
authored
Merge pull request #22 from elisecodedestrucs/no-missing-print-css
add rule provide-print-css
2 parents 88a4400 + dee4f3e commit 2886107

File tree

5 files changed

+224
-0
lines changed

5 files changed

+224
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
- [#21](https://github.com/green-code-initiative/ecoCode-javascript/pull/21) Add rule `@ecocode/avoid-css-animations`
1414
- [#18](https://github.com/green-code-initiative/ecoCode-javascript/pull/18) Add rule `@ecocode/limit-db-query-results`
1515
- [#19](https://github.com/green-code-initiative/ecoCode-javascript/pull/19) Add rule `@ecocode/no-empty-image-src-attribute`
16+
- [#22](https://github.com/green-code-initiative/ecoCode-javascript/pull/22) Add rule `@ecocode/provide-print-css`
1617
- [#207](https://github.com/green-code-initiative/ecoCode/issues/207) Add release tag analyzis on SonarCloud
1718

1819
### Changed

eslint-plugin/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ Add `@ecocode` to the `plugins` section of your `.eslintrc`, followed by rules c
6666
| [no-multiple-access-dom-element](docs/rules/no-multiple-access-dom-element.md) | Disallow multiple access of same DOM element. ||
6767
| [no-multiple-style-changes](docs/rules/no-multiple-style-changes.md) | Disallow multiple style changes at once. ||
6868
| [prefer-collections-with-pagination](docs/rules/prefer-collections-with-pagination.md) | Prefer API collections with pagination. ||
69+
| [provide-print-css](docs/rules/provide-print-css.md) | Enforce providing a print stylesheet ||
6970

7071
<!-- end auto-generated rules list -->
7172

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Enforce providing a print stylesheet (`@ecocode/provide-print-css`)
2+
3+
⚠️ This rule _warns_ in the ✅ `recommended` config.
4+
5+
<!-- end auto-generated rule header -->
6+
7+
## Rule Details
8+
9+
This rule aims to remind developers to use CSS print to limit the number of pages printed therefore indirectly reducing
10+
the impact of the web page.
11+
12+
## Examples
13+
14+
Examples of **non-compliant** code for this rule:
15+
16+
```html
17+
<head>
18+
<title>Web Page</title>
19+
<link rel="stylesheet" type="text/css" href="styles.css" />
20+
</head>
21+
```
22+
23+
Examples of **compliant** code for this rule:
24+
25+
```html
26+
<head>
27+
<title>Web Page</title>
28+
<link rel="stylesheet" media="print" type="text/css" href="print.css" />
29+
</head>
30+
```
31+
32+
```html
33+
<head>
34+
<title>Web Page</title>
35+
<style>
36+
@media print {
37+
/* Print-specific styles */
38+
}
39+
</style>
40+
</head>
41+
```
42+
43+
## Further details
44+
45+
This recommendation is made by the
46+
CNUMR: [Provide a print CSS](https://github.com/cnumr/best-practices/blob/main/chapters/BP_027_en.md)
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/**
2+
* Copyright (C) 2023 Green Code Initiative
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
"use strict";
18+
19+
/** @type {import("eslint").Rule.RuleModule} */
20+
module.exports = {
21+
meta: {
22+
type: "suggestion",
23+
docs: {
24+
description: "Enforce providing a print stylesheet",
25+
category: "eco-design",
26+
recommended: "warn",
27+
},
28+
messages: {
29+
noPrintCSSProvided: "Provide a print CSS",
30+
},
31+
schema: [],
32+
},
33+
create(context) {
34+
const isStyleWithPrintNode = (node) => {
35+
return (
36+
node.openingElement.name.name === "style" &&
37+
node.children.some((child) => {
38+
let element = null;
39+
if (child.value != null) {
40+
element = child.value;
41+
} else if (child.expression != null) {
42+
if (child.expression.value != null) {
43+
element = child.expression.value;
44+
} else if (
45+
child.expression.quasis != null &&
46+
child.expression.quasis.length > 0
47+
) {
48+
element = child.expression.quasis[0].value.cooked;
49+
}
50+
}
51+
return element != null && element.includes("@media print");
52+
})
53+
);
54+
};
55+
56+
const isLinkForPrintNode = (node) =>
57+
node.openingElement.name.name === "link" &&
58+
node.openingElement.attributes.some(
59+
(attr) => attr.name.name === "media" && attr.value.value === "print",
60+
);
61+
62+
return {
63+
JSXElement(node) {
64+
if (node.openingElement.name.name === "head") {
65+
const hasValidElement = node.children.some(
66+
(child) =>
67+
child.openingElement != null &&
68+
(isStyleWithPrintNode(child) || isLinkForPrintNode(child)),
69+
);
70+
71+
if (!hasValidElement) {
72+
context.report({
73+
node: node,
74+
messageId: "noPrintCSSProvided",
75+
});
76+
}
77+
}
78+
},
79+
};
80+
},
81+
};
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/**
2+
* Copyright (C) 2023 Green Code Initiative
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
"use strict";
18+
19+
//------------------------------------------------------------------------------
20+
// Requirements
21+
//------------------------------------------------------------------------------
22+
23+
const rule = require("../../../lib/rules/provide-print-css");
24+
const RuleTester = require("eslint").RuleTester;
25+
26+
//------------------------------------------------------------------------------
27+
// Tests
28+
//------------------------------------------------------------------------------
29+
30+
const ruleTester = new RuleTester({
31+
parserOptions: {
32+
ecmaVersion: 6,
33+
sourceType: "module",
34+
ecmaFeatures: {
35+
jsx: true,
36+
},
37+
},
38+
});
39+
40+
const expectedError = {
41+
messageId: "noPrintCSSProvided",
42+
type: "JSXElement",
43+
};
44+
45+
ruleTester.run("provide-print-css", rule, {
46+
valid: [
47+
`
48+
<head>
49+
<title>Web Page</title>
50+
<link rel="stylesheet" href="styles.css" media="print" />
51+
</head>
52+
`,
53+
`
54+
<head>
55+
<title>Web Page</title>
56+
<style>@media print {}</style>
57+
</head>
58+
`,
59+
`
60+
<head>
61+
<title>Web Page</title>
62+
<style>{'@media print {}'}</style>
63+
</head>
64+
`,
65+
`
66+
<head>
67+
<title>Web Page</title>
68+
<link rel="stylesheet" href="styles.css" media="print" />,
69+
<style>{'@media print {}'}</style>
70+
</head>
71+
`,
72+
"<head><style>{`@media print {}`}</style></head>",
73+
`<link rel="stylesheet" href="styles.css" />`,
74+
],
75+
invalid: [
76+
{
77+
code: `
78+
<head>
79+
<title>Web Page</title>
80+
<link rel="stylesheet" href="styles.css" />
81+
</head>
82+
`,
83+
errors: [expectedError],
84+
},
85+
{
86+
code: `
87+
<head>
88+
<title>Web Page</title>
89+
<style>{'@media desktop {}'}</style>
90+
</head>
91+
`,
92+
errors: [expectedError],
93+
},
94+
],
95+
});

0 commit comments

Comments
 (0)