Skip to content

Instantly share code, notes, and snippets.

@jaikdean
Created March 14, 2012 14:52
Show Gist options
  • Save jaikdean/2037007 to your computer and use it in GitHub Desktop.
Save jaikdean/2037007 to your computer and use it in GitHub Desktop.
PHP_CodeSniffer sniff for CSS to find box model styles which can be optimised using shorthand
<?php
/**
* Shorthand box model value sniffer
*
* @package SkylabCodeSniffer
* @author Jaik Dean
**/
/**
* Shorthand box model value sniffer
*
* @author Jaik Dean
**/
class Skylab_Sniffs_CSS_ShorthandBoxModelSniff implements PHP_CodeSniffer_Sniff
{
/**
* A list of tokenizers this sniff supports.
*
* @var array
**/
public $supportedTokenizers = array('CSS');
/**
* A list of styles this rule applies to
*
* @var array
**/
protected $applicableStyles = array(
'margin',
'padding',
'border-width',
'border-color',
'border-style',
);
/**
* Returns the token types that this sniff is interested in.
*
* @return array(int)
**/
public function register()
{
return array(T_STYLE);
}
/**
* Processes the tokens that this sniff is interested in.
*
* @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
* @param int $stackPtr The position in the stack where
* the token was found.
*
* @return void
**/
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
// only apply to margin, padding and borders
if (!in_array($tokens[$stackPtr]['content'], $this->applicableStyles)) {
return;
}
// find the start and end of the value
$valueStart = $phpcsFile->findNext(array(T_COLON, T_WHITESPACE), ($stackPtr + 1), null, true);
$valueEnd = $phpcsFile->findNext(array(T_SEMICOLON), ($valueStart + 1));
// concatenate the value into a string
$value = '';
for ($i = $valueStart; $i < $valueEnd; $i++) {
$value .= $tokens[$i]['content'];
}
$value = trim($value);
// exit if we don't have any whitespace to avoid expensive preg_match()ing
if (!preg_match('/\\s/', $value)) {
return;
}
// check if we aren't using the most compact shorthand
$errorData = false;
if (preg_match('/^([^\\s]+)(?:\\s+\\1){1,3}$/', $value, $matches)) {
// one unique value
$errorData = array(
$matches[1],
$value,
$tokens[$stackPtr]['content'],
);
} elseif (preg_match('/^([^\\s]+)\\s+([^\\s]+)\\s+\\1(?:\\s+\\2)?$/', $value, $matches)) {
// two unique values
$errorData = array(
$matches[1] . ' ' . $matches[2],
$value,
$tokens[$stackPtr]['content'],
);
} elseif (preg_match('/^([^\\s]+)\\s+([^\\s]+)\\s+([^\\s]+)\\s+\\2$/', $value, $matches)) {
// three unique values
$errorData = array(
$matches[1] . ' ' . $matches[2] . ' ' . $matches[3],
$value,
$tokens[$stackPtr]['content'],
);
}
if ($errorData !== false) {
$phpcsFile->addError('Box model styles must be shorthand; expected "%s" but found "%s" (%s)', $i, 'Found', $errorData);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment