Skip to content
Permalink
Browse files

SONARPLUGINS-3000 Rule: Each 'header' tag should contain a 'favicon' …

…declaration
  • Loading branch information...
dbolkensteyn committed Jul 1, 2013
1 parent 1343265 commit a32a4f2a887487474e7e8c9d907342fb77b068ef
@@ -0,0 +1,81 @@
/*
* Sonar Web Plugin
* Copyright (C) 2010 SonarSource and Matthijs Galesloot
* dev@sonar.codehaus.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sonar.plugins.web.checks.sonar;

import org.sonar.check.Priority;
import org.sonar.check.Rule;
import org.sonar.plugins.web.checks.AbstractPageCheck;
import org.sonar.plugins.web.node.Node;
import org.sonar.plugins.web.node.TagNode;

import java.util.List;

@Rule(
key = "PageWithoutFaviconCheck",
priority = Priority.MAJOR)
public class PageWithoutFaviconCheck extends AbstractPageCheck {

private int currentHeadTagLine;
private boolean foundTitleTag;

@Override
public void startDocument(List<Node> nodes) {
currentHeadTagLine = 0;
}

@Override
public void startElement(TagNode node) {
if (isHeadTag(node)) {
currentHeadTagLine = node.getStartLinePosition();
foundTitleTag = false;
} else if (currentHeadTagLine != 0 && isFaviconTag(node)) {
foundTitleTag = true;
}
}

@Override
public void endElement(TagNode node) {
int line = 0;

if (isHeadTag(node)) {
line = currentHeadTagLine;
currentHeadTagLine = 0;
}

if (!foundTitleTag && line != 0) {
createViolation(line, "Add a favicon <link> tag to this page.");
}
}

private static boolean isHeadTag(TagNode node) {
return "HEAD".equalsIgnoreCase(node.getNodeName());
}

private static boolean isFaviconTag(TagNode node) {
String rel = node.getAttribute("rel");

return isLinkTag(node) &&
rel != null &&
("ICON".equalsIgnoreCase(rel) || "SHORTCUT ICON".equalsIgnoreCase(rel));
}

private static boolean isLinkTag(TagNode node) {
return "LINK".equalsIgnoreCase(node.getNodeName());
}

}
@@ -54,6 +54,7 @@
import org.sonar.plugins.web.checks.sonar.MetaRefreshCheck;
import org.sonar.plugins.web.checks.sonar.MouseEventWithoutKeyboardEquivalentCheck;
import org.sonar.plugins.web.checks.sonar.NonConsecutiveHeadingCheck;
import org.sonar.plugins.web.checks.sonar.PageWithoutFaviconCheck;
import org.sonar.plugins.web.checks.sonar.PageWithoutTitleCheck;
import org.sonar.plugins.web.checks.sonar.ServerSideImageMapsCheck;
import org.sonar.plugins.web.checks.sonar.TableHeaderHasIdOrScopeCheck;
@@ -135,6 +136,7 @@
TableHeaderHasIdOrScopeCheck.class,
InputWithoutLabelCheck.class,
ImgWithoutWidthOrHeightCheck.class,
PageWithoutFaviconCheck.class,
};

/**
@@ -108,6 +108,7 @@ rule.Web.DoctypePresenceCheck.name='!DOCTYPE' declarations should always appear
rule.Web.TableHeaderHasIdOrScopeCheck.name='th' table headers tags should have an 'id' or a 'scope' attribute
rule.Web.InputWithoutLabelCheck.name='input' tags should have an associated 'label' one
rule.Web.ImgWithoutWidthOrHeightCheck.name=Images tags and buttons should always have a 'width' and a 'height' attribute
rule.Web.PageWithoutFaviconCheck.name=Favicons should be used in all pages

rule.Web.HeaderCheck.name=Files should have a header comment
rule.Web.HeaderCheck.param.expression=Regular expression which header comments should match
@@ -0,0 +1,25 @@
<p>
Favicons are shown for example in the browser's address bar, bookmark list, or tabs.
They enable users to quickly identify and recognize websites.
</p>

<p>
The following code:
</p>

<pre>
&lt;head&gt; &lt;!-- Non-Compliant --&gt;
&lt;title&gt;...&lt;title&gt;
&lt;/head&gt;
</pre>

<p>
should be refactored into:
</p>

<pre>
&lt;head&gt; &lt;!-- Compliant --&gt;
&lt;title&gt;...&lt;title&gt;
&lt;link rel="shortcut icon" href="http://example.com/myicon.ico" /&gt;
&lt;/head&gt;
</pre>
@@ -0,0 +1,43 @@
/*
* Sonar Web Plugin
* Copyright (C) 2010 SonarSource and Matthijs Galesloot
* dev@sonar.codehaus.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sonar.plugins.web.checks.sonar;

import org.junit.Rule;
import org.junit.Test;
import org.sonar.plugins.web.checks.CheckMessagesVerifierRule;
import org.sonar.plugins.web.visitor.WebSourceCode;

import java.io.File;

public class PageWithoutFaviconCheckTest {

@Rule
public CheckMessagesVerifierRule checkMessagesVerifier = new CheckMessagesVerifierRule();

@Test
public void detected() throws Exception {
WebSourceCode sourceCode = TestHelper.scan(new File("src/test/resources/checks/PageWithoutFaviconCheck.html"), new PageWithoutFaviconCheck());

checkMessagesVerifier.verify(sourceCode.getViolations())
.next().atLine(5).withMessage("Add a favicon <link> tag to this page.")
.next().atLine(34)
.next().atLine(40)
.next().atLine(52);
}

}
@@ -0,0 +1,57 @@
<html> <!-- Compliant -->
</html>

<html>
<head> <!-- Non-Compliant -->
</head>
</html>

<html>
<head> <!-- Compliant -->
<link rel="shortcut icon" href="http://example.com/myicon.ico" />
</head>
</html>

<html>
<head> <!-- Compliant -->
<link rel="icon" type="image/vnd.microsoft.icon" href="http://example.com/image.ico" />
</head>
</html>

<html>
<head> <!-- Compliant -->
<link rel="icon" type="image/png" href="http://example.com/image.png" />
</head>
</html>

<html>
<head> <!-- Compliant -->
<link rel="icon" type="image/gif" href="http://example.com/image.gif" />
</head>
</html>

<html>
<head> <!-- Non-Compliant -->
<link href="http://example.com/myicon.ico" />
</head>
</html>

<html>
<head> <!-- Non-Compliant -->
<link rel="foo" href="http://example.com/myicon.ico" />
</head>
</html>

<html>
<head> <!-- Compliant -->
<link rel="ShoRtCuT IcON" href="http://example.com/myicon.ico" />
</head>
</html>

<html>
<head> <!-- Non-Compliant -->
<foo />
</head>
</html>

</head> <!-- Compliant -->

0 comments on commit a32a4f2

Please sign in to comment.
You can’t perform that action at this time.