/** * Parses the css code converting to a Css object with all selectors, properties and values. * * @param string $string_code The css code to parse * * @return Stylecow\Css The parsed css code */ private static function parse($string_code) { $Css = new Css(); while ($string_code) { $pos = strpos($string_code, '{'); $pos2 = strpos($string_code, ';'); if ($pos2 !== false && $pos2 < $pos) { $Css->addChild(new Css(Selector::createFromString(substr($string_code, 0, $pos2)))); $string_code = trim(substr($string_code, $pos2 + 1)); continue; } if ($pos === false) { break; } $selector = substr($string_code, 0, $pos); $string_code = trim(substr($string_code, $pos + 1)); $length = strlen($string_code); $in = 1; for ($n = 0; $n <= $length; $n++) { $letter = $string_code[$n]; if ($letter === '{') { $in++; continue; } if ($letter !== '}' || --$in) { continue; } $Child = $Css->addChild(new Css(Selector::createFromString($selector))); $string_piece = $n === 0 ? '' : trim(substr($string_code, 0, $n - 1)); $string_code = trim(substr($string_code, $n + 1)); $pos = strpos($string_piece, '{'); if ($pos === false) { $properties_string = $string_piece; $content_string = ''; } else { $pos = strrpos(substr($string_piece, 0, $pos), ';'); if ($pos !== false) { $properties_string = trim(substr($string_piece, 0, $pos + 1)); $content_string = trim(substr($string_piece, $pos + 1)); } else { $properties_string = ''; $content_string = $string_piece; } } if ($properties_string) { foreach (self::explodeTrim(';', $properties_string) as $property) { $Child->addProperty(Property::createFromString($property)); } } if ($content_string) { foreach (self::parse($content_string) as $child) { $Child->addChild($child); } } break; } } return $Css; }
/** * Parses the css code converting to a Css object with all selectors, properties and values. * * @param string $string_code The css code to parse * @param string $filename The original filename (used to import relative files) * * @return Stylecow\Css The parsed css code */ private static function parse($string_code, $filename = null, $contextFile = null) { if ($filename) { $relativePath = $contextFile ? substr($filename, strlen($contextFile)) : pathinfo($filename, PATHINFO_BASENAME); } else { $relativePath = ''; } $Css = $Child = new Css(); $status = array('selector'); $buffer = ''; $code = explode("\n", str_replace("\n\r", "\n", $string_code)); array_unshift($code, ''); foreach ($code as $line => $string_line) { if (empty($string_line)) { continue; } $col = 0; $length = strlen($string_line); $char = $previousChar = null; $nextChar = $string_line[$col]; while ($col < $length) { $previousChar = $char; $char = $nextChar; $col++; $nextChar = $col === $length ? null : $string_line[$col]; switch ($char) { case '"': switch ($status[0]) { case 'doubleQuote': $buffer .= $char; if ($previousChar !== '\\') { array_shift($status); } break; case 'simpleQuote': $buffer .= $char; break; case 'selector': case 'properties': $buffer .= $char; array_unshift($status, 'doubleQuote'); } break; case "'": switch ($status[0]) { case 'simpleQuote': $buffer .= $char; if ($previousChar !== '\\') { array_shift($status); } break; case 'doubleQuote': $buffer .= $char; break; case 'selector': case 'properties': $buffer .= $char; array_unshift($status, 'simpleQuote'); } break; case '{': switch ($status[0]) { case 'selector': case 'properties': $Child = $Child->addChild(new Css(Selector::createFromString($buffer)))->setSourceMap($line, $col, $relativePath); array_unshift($status, 'properties'); $buffer = ''; break; } break; case '}': switch ($status[0]) { case 'properties': if (trim($buffer)) { $Child->addProperty(Property::createFromString($buffer))->setSourceMap($line, $col, $relativePath); } $buffer = ''; array_shift($status); $Child = $Child->parent; break; } break; case ';': switch ($status[0]) { case 'selector': if (strpos($buffer, '@import') === false || !is_object($Children = self::parseImport($buffer, $filename, $contextFile))) { $Child->addChild(new Css(Selector::createFromString($buffer)))->setSourceMap($line, $col, $relativePath); } else { foreach ($Children->getChildren() as $Each) { $Child->addChild($Each); } } $buffer = ''; break; case 'properties': if (!empty($buffer)) { $Child->addProperty(Property::createFromString($buffer))->setSourceMap($line, $col, $relativePath); } $buffer = ''; break; } break; case '/': if ($status[0] !== 'comment') { if ($nextChar === '*') { array_unshift($status, 'comment'); $col++; $nextNextChar = $col === $length ? null : $string_line[$col]; if ($nextNextChar === '/') { $col++; } } else { $buffer .= $char; } } else { if ($previousChar === '*') { array_shift($status); } } break; default: if (!isset($status[0])) { $status = array('selector'); } if ($status[0] !== 'comment') { $buffer .= $char; } } } } return $Css; }