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

[ISSUE 113] Use unoptimized vector images #190

Merged
merged 5 commits into from
May 18, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
dedece35 marked this conversation as resolved.
Show resolved Hide resolved
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

- [#113](https://github.com/green-code-initiative/ecoCode/issues/113) new PYTHON rule : Use unoptimized vector images

### Changed

- [#19](https://github.com/green-code-initiative/ecoCode-common/issues/19) process changed for development environment installation : easier to initialize locally environment (check [`INSTALL.md`](https://github.com/green-code-initiative/ecoCode-common/blob/main/doc/INSTALL.md#howto-install-sonarqube-dev-environment) file)
Expand Down
2 changes: 1 addition & 1 deletion RULES.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Some are applicable for different technologies.
| | Non-standard fonts used | Prefer standard fonts, as they are already present on the user's computer, so they do not need to download them. This saves bandwidth, while speeding up the display of the site. | [cnumr best practices (3rd edition) BP_029](https://github.com/cnumr/best-practices/blob/main/chapters/BP_029_fr.md) | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 |
| | Non-outsourced CSS and Javascript | If you include CSS or JavaScript code in the body of the HTML file, while the HTML file is used by several pages (or even the entire site), this code must be transferred for each page requested by the user, which increases the volume of data transmitted. | [cnumr best practices (3rd edition) BP_032](https://github.com/cnumr/best-practices/blob/main/chapters/BP_032_fr.md) | 🚫 | 🚫 | 🚀 | 🚫 | 🚫 |
| | Resize images browser-side | Do not resize images using the HEIGHT and WIDTH attributes of the HTML code. This approach requires transferring these images to their original size, wasting bandwidth and CPU cycles. | [cnumr best practices (3rd edition) BP_034](https://github.com/cnumr/best-practices/blob/main/chapters/BP_034_fr.md) | 🚫 | 🚫 | 🚧 | 🚫 | 🚫 |
| EC10 | Use unoptimized vector images | Less heavy SVG images using less bandwidth | [cnumr best practices (3rd edition) BP_036](https://github.com/cnumr/best-practices/blob/main/chapters/BP_036_fr.md) | 🚧 | 🚀 | 🚀 | 🚧 | 🚀 |
| EC10 | Use unoptimized vector images | Less heavy SVG images using less bandwidth | [cnumr best practices (3rd edition) BP_036](https://github.com/cnumr/best-practices/blob/main/chapters/BP_036_fr.md) | 🚧 | 🚀 | 🚀 | | 🚀 |
| | Using too many CSS/javascript animations | JavaScript/CSS animations can be very expensive in terms of CPU cycles and memory consumption. | [cnumr best practices (3rd edition) BP_039](https://github.com/cnumr/best-practices/blob/main/chapters/BP_039_fr.md) | 🚫 | 🚫 | 🚧 | 🚫 | 🚫 |
| | Modify the DOM when traversing it | Modifying the DOM (Document Object Model) as you traverse it can lead to situations where the loop becomes very resource-intensive, especially CPU cycles. | [cnumr best practices (3rd edition) BP_041](https://github.com/cnumr/best-practices/blob/main/chapters/BP_041_fr.md) | 🚫 | 🚫 | 🚧 | 🚫 | 🚫 |
| | Edit DOM elements to make it invisible | When an element of the Document Object Model (DOM) needs to be modified by several properties, each change in style or content will generate a repaint or reflow. | [cnumr best practices (3rd edition) BP_042](https://github.com/cnumr/best-practices/blob/main/chapters/BP_042_fr.md) | 🚫 | 🚫 | 🚀 | 🚫 | 🚫 |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,7 @@
import java.util.List;
import java.util.Map;

import fr.greencodeinitiative.python.checks.AvoidFullSQLRequest;
import fr.greencodeinitiative.python.checks.AvoidGettersAndSetters;
import fr.greencodeinitiative.python.checks.AvoidGlobalVariableInFunctionCheck;
import fr.greencodeinitiative.python.checks.AvoidSQLRequestInLoop;
import fr.greencodeinitiative.python.checks.AvoidTryCatchFinallyCheck;
import fr.greencodeinitiative.python.checks.NoFunctionCallWhenDeclaringForLoop;
import fr.greencodeinitiative.python.checks.*;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.rules.RuleType;
import org.sonar.api.server.rule.RulesDefinition;
Expand Down Expand Up @@ -93,6 +88,7 @@ public List<Class> checkClasses() {
AvoidGlobalVariableInFunctionCheck.class,
AvoidSQLRequestInLoop.class,
AvoidTryCatchFinallyCheck.class,
AvoidUnoptimizedVectorImagesCheck.class,
NoFunctionCallWhenDeclaringForLoop.class,
AvoidFullSQLRequest.class
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package fr.greencodeinitiative.python.checks;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.sonar.check.Priority;
import org.sonar.check.Rule;
import org.sonar.plugins.python.api.PythonSubscriptionCheck;
import org.sonar.plugins.python.api.SubscriptionContext;
import org.sonar.plugins.python.api.tree.*;

@Rule(
key = AvoidUnoptimizedVectorImagesCheck.RULE_KEY,
name = AvoidUnoptimizedVectorImagesCheck.DESCRIPTION,
description = AvoidUnoptimizedVectorImagesCheck.DESCRIPTION,
priority = Priority.MINOR,
tags = {"eco-design", "ecocode"})
public class AvoidUnoptimizedVectorImagesCheck extends PythonSubscriptionCheck {

public static final String RULE_KEY = "EC10";
public static final String DESCRIPTION = "Avoid using unoptimized vector images";
private static final Pattern COMMENT_PATTERN = Pattern.compile("(<!--|-->)");
private static final Pattern LAYERS_PATTERN = Pattern.compile("</g>");
private static final Pattern NAMESPACE_PATTERN = Pattern.compile("xmlns:(?!svg)[a-z0-9]+");
private static final String STRING_TAG_TO_DETECT = "</svg>";

@Override
public void initialize(Context ctx) {
ctx.registerSyntaxNodeConsumer(Tree.Kind.STRING_ELEMENT, this::checkSVG);
}

private void checkSVG(SubscriptionContext ctx) {
StringElement stringLiteral = (StringElement) ctx.syntaxNode();
checkComments(stringLiteral, ctx);
checkLayers(stringLiteral, ctx);
checkNamespaces(stringLiteral, ctx);
checkMetadata(stringLiteral, ctx);
}

private void checkComments(StringElement str, SubscriptionContext ctx) {
if (isSvgTagNotDetected(str))
return;

if (COMMENT_PATTERN.matcher(str.value()).find()) {
ctx.addIssue(str, DESCRIPTION);
}
}

private void checkLayers(StringElement str, SubscriptionContext ctx) {
if (isSvgTagNotDetected(str))
return;

Matcher matcher = LAYERS_PATTERN.matcher(str.value());
int matches = 0;
while (matcher.find()) matches++;
if (matches > 1) {
ctx.addIssue(str, DESCRIPTION);
}
}

private void checkNamespaces(StringElement str, SubscriptionContext ctx) {
if (isSvgTagNotDetected(str))
return;

if (NAMESPACE_PATTERN.matcher(str.value()).find()) {
ctx.addIssue(str, DESCRIPTION);
}
}

private void checkMetadata(StringElement str, SubscriptionContext ctx) {
if (isSvgTagNotDetected(str))
return;

if (str.value().contains("</metadata>")) {
ctx.addIssue(str, DESCRIPTION);
}
}

private boolean isSvgTagNotDetected(StringElement str) {
return !str.value().contains(AvoidUnoptimizedVectorImagesCheck.STRING_TAG_TO_DETECT);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<p>SVG images generated by common drawing softwares contains unnecessary data : calc layer, metadata, namespaces and comments.</p>
<h2>Noncompliant Code Example</h2>
<pre>
&lt;!-- Created with Inkscape (http://www.inkscape.org/) --&gt;
&lt;svg
width="210mm"
height="297mm"
viewBox="0 0 210 297"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
sodipodi:docname="dessin2.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"&gt;
&lt;g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1"&gt;
&lt;circle
style="fill:#ff00ff;stroke-width:0.264583"
id="path111"
cx="104.02724"
cy="152.19028"
r="73.177132" /&gt;
&lt;/g&gt;
&lt;/svg&gt;
</pre>
<h2>Compliant Solution</h2>
<pre>
&lt;svg
width="210mm"
height="297mm"
viewBox="0 0 210 297"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"&gt;
&lt;g&gt;
&lt;circle
style="fill:#ff00ff;stroke-width:0.264583"
id="path111"
cx="104.02724"
cy="152.19028"
r="73.177132" /&gt;
&lt;/g&gt;
&lt;/svg&gt;
</pre>
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ public void init() {
public void test() {
assertThat(pythonRuleRepository.repositoryKey()).isEqualTo(PythonRuleRepository.REPOSITORY_KEY);
assertThat(context.repositories()).hasSize(1).extracting("key").containsExactly(pythonRuleRepository.repositoryKey());
assertThat(context.repositories().get(0).rules()).hasSize(6);
assertThat(pythonRuleRepository.checkClasses()).hasSize(6);
assertThat(context.repositories().get(0).rules()).hasSize(7);
assertThat(pythonRuleRepository.checkClasses()).hasSize(7);
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package fr.greencodeinitiative.python.checks;

import org.junit.Test;
import org.sonar.python.checks.utils.PythonCheckVerifier;

public class AvoidUnoptimizedVectorImagesTest {

@Test
public void test() {
PythonCheckVerifier.verify("src/test/resources/checks/avoidUnoptimizedVectorImages.py", new AvoidUnoptimizedVectorImagesCheck());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
image0 = """<svg xmlns:svg="http://www.w3.org/2000/svg"><g></g></svg>"""
image1 = """<svg xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"></svg>""" # Noncompliant {{Avoid using unoptimized vector images}}
image2 = "<svg><!-- Hello world --></svg>" # Noncompliant {{Avoid using unoptimized vector images}}
image3 = "<svg><g>...</g><g>...</g></svg>" # Noncompliant {{Avoid using unoptimized vector images}}
image4 = "<svg><metadata></metadata></svg>" # Noncompliant {{Avoid using unoptimized vector images}}
dedece35 marked this conversation as resolved.
Show resolved Hide resolved