public function __construct($selector_string = null, $declarations_string) { $regex = CssCrush::$regex; // Parse the selectors chunk if (!empty($selector_string)) { $selector_adjustments = array('!:hocus([^a-z0-9_-])!' => ':any(:hover,:focus)$1', '!:pocus([^a-z0-9_-])!' => ':any(:hover,:focus,:active)$1', '!::(after|before|first-letter|first-line)!' => ':$1'); $selector_string = preg_replace(array_keys($selector_adjustments), array_values($selector_adjustments), $selector_string); $selectors_match = CssCrush::splitDelimList($selector_string, ','); $this->parens += $selectors_match->matches; // Remove and store comments that sit above the first selector // remove all comments between the other selectors preg_match_all($regex->token->comment, $selectors_match->list[0], $m); $this->comments = $m[0]; foreach ($selectors_match->list as &$selector) { $selector = preg_replace($regex->token->comment, '', $selector); $selector = trim($selector); } $this->selectors = $selectors_match->list; } // Parse the declarations chunk $declarations_match = CssCrush::splitDelimList($declarations_string, ';'); $this->parens += $declarations_match->matches; // Parse declarations in to property/value pairs foreach ($declarations_match->list as $declaration) { // Strip comments around the property $declaration = preg_replace($regex->token->comment, '', $declaration); // Store the property $colonPos = strpos($declaration, ':'); if ($colonPos === false) { // If there is no colon it's malformed continue; } else { $prop = trim(substr($declaration, 0, $colonPos)); // Store the property name $this->addProperty($prop); } // Extract the value part of the declaration $value = substr($declaration, $colonPos + 1); $value = $value !== false ? trim($value) : $value; if ($value === false or $value === '') { // We'll ignore declarations with empty values continue; } // If are parenthesised expressions in the value // Search for any custom functions so we can apply them if (count($declarations_match->matches)) { CssCrush::$storage->tmpParens = $declarations_match->matches; $value = preg_replace_callback($regex->function->custom, array('CssCrush_Function', 'css_fn'), $value); } // Store the property family // Store the vendor id, if one is present if (preg_match($regex->vendorPrefix, $prop, $vendor)) { $family = $vendor[2]; $vendor = $vendor[1]; } else { $vendor = null; $family = $prop; } // Create an index of all functions in the current declaration if (preg_match_all($regex->function->match, $value, $functions) > 0) { $out = array(); foreach ($functions[2] as $index => $fn_name) { $out[] = $fn_name; } $functions = array_unique($out); } else { $functions = array(); } // Store the declaration $_declaration = (object) array('property' => $prop, 'family' => $family, 'vendor' => $vendor, 'functions' => $functions, 'value' => $value); $this->declarations[] = $_declaration; } }
protected static function parseArgs($input, $argCount = null) { $args = CssCrush::splitDelimList($input, ',', true, true); return array_map('trim', $args->list); }