Skip to content

Commit 34528cf

Browse files
committed
Added Squiz ShorthandSizeSniff to check that CSS sizes are using shorthand notation only when 1 or 2 values are used
1 parent ed9e033 commit 34528cf

File tree

4 files changed

+269
-0
lines changed

4 files changed

+269
-0
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
<?php
2+
/**
3+
* Squiz_Sniffs_CSS_ShorthandSizeSniff.
4+
*
5+
* PHP version 5
6+
*
7+
* @category PHP
8+
* @package PHP_CodeSniffer
9+
* @author Greg Sherwood <[email protected]>
10+
* @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
11+
* @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
12+
* @link http://pear.php.net/package/PHP_CodeSniffer
13+
*/
14+
15+
/**
16+
* Squiz_Sniffs_CSS_ShorthandSizeSniff.
17+
*
18+
* Ensure sizes are defined using shorthand notation where possible, except in the
19+
* case where shorthand becomes 3 values.
20+
*
21+
* @category PHP
22+
* @package PHP_CodeSniffer
23+
* @author Greg Sherwood <[email protected]>
24+
* @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
25+
* @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
26+
* @version Release: @package_version@
27+
* @link http://pear.php.net/package/PHP_CodeSniffer
28+
*/
29+
class Squiz_Sniffs_CSS_ShorthandSizeSniff implements PHP_CodeSniffer_Sniff
30+
{
31+
32+
/**
33+
* A list of tokenizers this sniff supports.
34+
*
35+
* @var array
36+
*/
37+
public $supportedTokenizers = array('CSS');
38+
39+
/**
40+
* A list of styles that we shouldn't check.
41+
*
42+
* These have values that looks like sizes, but are not.
43+
*
44+
* @var array
45+
*/
46+
public $excludeStyles = array(
47+
'background-position',
48+
'box-shadow',
49+
'transform-origin',
50+
'-webkit-transform-origin',
51+
'-ms-transform-origin',
52+
);
53+
54+
55+
/**
56+
* Returns the token types that this sniff is interested in.
57+
*
58+
* @return array(int)
59+
*/
60+
public function register()
61+
{
62+
return array(T_STYLE);
63+
64+
}//end register()
65+
66+
67+
/**
68+
* Processes the tokens that this sniff is interested in.
69+
*
70+
* @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
71+
* @param int $stackPtr The position in the stack where
72+
* the token was found.
73+
*
74+
* @return void
75+
*/
76+
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
77+
{
78+
$tokens = $phpcsFile->getTokens();
79+
80+
// Some styles look like shorthand but are not actually a set of 4 sizes.
81+
$style = strtolower($tokens[$stackPtr]['content']);
82+
if (in_array($style, $this->excludeStyles) === true) {
83+
return;
84+
}
85+
86+
// Get the whole style content.
87+
$end = $phpcsFile->findNext(T_SEMICOLON, ($stackPtr + 1));
88+
$content = $phpcsFile->getTokensAsString(($stackPtr + 1), ($end - $stackPtr - 1));
89+
$content = trim($content, ': ');
90+
91+
// Account for a !important annotation.
92+
if (substr($content, -10) === '!important') {
93+
$content = substr($content, 0, -10);
94+
$content = trim($content);
95+
}
96+
97+
// Check if this style value is a set of numbers with optional prefixes.
98+
$content = preg_replace('/\s+/', ' ', $content);
99+
$values = array();
100+
$num = preg_match_all(
101+
'/([0-9]+)([a-zA-Z]{2}\s+|%\s+|\s+)/',
102+
$content.' ',
103+
$values,
104+
PREG_SET_ORDER
105+
);
106+
107+
// Only interested in styles that have multiple sizes defined.
108+
if ($num < 2) {
109+
return;
110+
}
111+
112+
// Rebuild the content we matched to ensure we got everything.
113+
$matched = '';
114+
foreach ($values as $value) {
115+
$matched .= $value[0];
116+
}
117+
118+
if ($content !== trim($matched)) {
119+
return;
120+
}
121+
122+
if ($num === 3) {
123+
$expected = trim($content.' '.$values[1][1].$values[1][2]);
124+
$error = 'Shorthand syntax not allowed here; use %s instead';
125+
$data = array($expected);
126+
$phpcsFile->addError($error, $stackPtr, 'NotAllowed', $data);
127+
return;
128+
}
129+
130+
if ($num === 2) {
131+
if ($values[0][0] !== $values[1][0]) {
132+
// Both values are different, so it is already shorthand.
133+
return;
134+
}
135+
} else if ($values[0][0] !== $values[2][0] || $values[1][0] !== $values[3][0]) {
136+
// Can't shorthand this.
137+
return;
138+
}
139+
140+
if ($values[0][0] === $values[1][0]) {
141+
// All values are the same.
142+
$expected = $values[0][0];
143+
} else {
144+
$expected = $values[0][0].' '.$values[1][0];
145+
}
146+
147+
$expected = preg_replace('/\s+/', ' ', trim($expected));
148+
149+
$error = 'Size definitions must use shorthand if available; expected "%s" but found "%s"';
150+
$data = array(
151+
$expected,
152+
$content,
153+
);
154+
155+
$phpcsFile->addError($error, $stackPtr, 'NotUsed', $data);
156+
157+
}//end process()
158+
159+
160+
}//end class
161+
?>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#add-new-comment {
2+
background-color: #333333;
3+
padding: 10px;
4+
border-bottom: 1px dotted #F0F0F0;
5+
border-top: 1px dotted #FF00FF;
6+
background: #8fb7db url(diag_lines_bg.gif) top left;
7+
page-break-inside: 1;
8+
margin: 8px 8px 8px 8px;
9+
margin: 8px 8px;
10+
margin: 0 0 0 0;
11+
margin: 0 8px 0 8px;
12+
margin: 8px 4px 8px 4px;
13+
margin: 8px 4% 8px 4%;
14+
margin: 6px 2px 9px 2px;
15+
margin: 6px 2px 9px;
16+
border-radius: 2px 2px 2px 2px !important;
17+
border-width: 2px 2px 2px 2px;
18+
border-width: 1px 2px 2px 4px;
19+
margin: 97px auto 0 auto;
20+
text-shadow: 0 1px 0 #fff;
21+
22+
/* These are black-listed style names. */
23+
background-position: 0 0;
24+
box-shadow: 2px 2px 2px 2px;
25+
transform-origin: 0 110% 0;
26+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
/**
3+
* Unit test class for the ShorthandSize sniff.
4+
*
5+
* PHP version 5
6+
*
7+
* @category PHP
8+
* @package PHP_CodeSniffer
9+
* @author Greg Sherwood <[email protected]>
10+
* @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
11+
* @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
12+
* @link http://pear.php.net/package/PHP_CodeSniffer
13+
*/
14+
15+
/**
16+
* Unit test class for the ShorthandSize sniff.
17+
*
18+
* A sniff unit test checks a .inc file for expected violations of a single
19+
* coding standard. Expected errors and warnings are stored in this class.
20+
*
21+
* @category PHP
22+
* @package PHP_CodeSniffer
23+
* @author Greg Sherwood <[email protected]>
24+
* @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
25+
* @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
26+
* @version Release: @package_version@
27+
* @link http://pear.php.net/package/PHP_CodeSniffer
28+
*/
29+
class Squiz_Tests_CSS_ShorthandSizeUnitTest extends AbstractSniffUnitTest
30+
{
31+
32+
/**
33+
* Returns the lines where errors should occur.
34+
*
35+
* The key of the array should represent the line number and the value
36+
* should represent the number of errors that should occur on that line.
37+
*
38+
* @return array(int => int)
39+
*/
40+
public function getErrorList()
41+
{
42+
return array(
43+
8 => 1,
44+
9 => 1,
45+
10 => 1,
46+
11 => 1,
47+
12 => 1,
48+
13 => 1,
49+
15 => 1,
50+
16 => 1,
51+
17 => 1,
52+
);
53+
54+
}//end getErrorList()
55+
56+
57+
/**
58+
* Returns the lines where warnings should occur.
59+
*
60+
* The key of the array should represent the line number and the value
61+
* should represent the number of warnings that should occur on that line.
62+
*
63+
* @return array(int => int)
64+
*/
65+
public function getWarningList()
66+
{
67+
return array();
68+
69+
}//end getWarningList()
70+
71+
72+
}//end class
73+
74+
?>

package.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
4141
-- Thanks to Spencer Rinehart for the contribution
4242
- Generated HTML docs now correctly show the open PHP tag in code comparison blocks
4343
- Added Generic InlineHTMLSniff to ensure a file only contains PHP code
44+
- Added Squiz ShorthandSizeSniff to check that CSS sizes are using shorthand notation only when 1 or 2 values are used
4445
- PSR2 standard no longer enforces no whitespace between the closing parenthesis of a function call and the semicolon
4546
- PSR2 ClassDeclarationSniff now ignores empty classes when checking the end brace position
4647
- PSR2 SwitchDeclarationSniff no longer reports errors for empty lines between CASE statements
@@ -1465,6 +1466,9 @@ http://pear.php.net/dtd/package-2.0.xsd">
14651466
<file baseinstalldir="PHP" name="SemicolonSpacingSniff.php" role="php">
14661467
<tasks:replace from="@package_version@" to="version" type="package-info" />
14671468
</file>
1469+
<file baseinstalldir="PHP" name="ShorthandSizeSniff.php" role="php">
1470+
<tasks:replace from="@package_version@" to="version" type="package-info" />
1471+
</file>
14681472
</dir>
14691473
<dir name="Debug">
14701474
<file baseinstalldir="PHP" name="JavaScriptLintSniff.php" role="php">
@@ -1845,6 +1849,10 @@ http://pear.php.net/dtd/package-2.0.xsd">
18451849
<file baseinstalldir="PHP" name="SemicolonSpacingUnitTest.php" role="test">
18461850
<tasks:replace from="@package_version@" to="version" type="package-info" />
18471851
</file>
1852+
<file baseinstalldir="PHP" name="ShorthandSizeUnitTest.css" role="test" />
1853+
<file baseinstalldir="PHP" name="ShorthandSizeUnitTest.php" role="test">
1854+
<tasks:replace from="@package_version@" to="version" type="package-info" />
1855+
</file>
18481856
</dir>
18491857
<dir name="Debug">
18501858
<file baseinstalldir="PHP" name="JavaScriptLintUnitTest.js" role="test" />

0 commit comments

Comments
 (0)