Parse a CSS File with PHP

Parse a CSS file with PHP

Here is a quick and dirty standalone hack using regex:

$input = '
#stuff {
background-color: red;
}

#content.postclass-subcontent {
background-color: red;
}

#content2.postclass-subcontent2 {
background-color: red;
}
';

$cssClassName = 'postclass';
preg_match_all('/(#[a-z0-9]*?\.?'.addcslashes($cssClassName, '-').'.*?)\s?\{/', $input, $matches);
var_dump($matches[1]);

Results in:

array(2) {
[0]=>
string(29) "#content.postclass-subcontent"
[1]=>
string(31) "#content2.postclass-subcontent2"
}

parsing a css file with sabberworm/PHP-CSS-Parser

Use echo "<h3>".implode(', ' $w)."</h3>".

The reason is as follows: $val represents a declaration block which is a rule set with several comma-separated selectors (The key $selektor only contains the index of the declaration block which is completely arbitrary for most usages). To get the selectors, use $val->getSelectors() (which you did). This will get you an array of all selectors.

The declaration block:

h1, h2 { value: 1; }

will thus be parsed into a CSSDeclarationBlock object with the selector array ['h1', 'h2']. To get back the selectors as they were originally defined, use implode.

PHP - Parse, Regex CSS file?

Having as a base this question (posted by @skrilled in the comments) I made an example of how you can parse a css with regular expression.

We can accomplish this by doing a two steps matching of the String.

1) Firstly we retrieve the class (or id name) and the abstraction of the attributes in a string (I mean, all the attributes in one string).
This regex fulfills pretty well the task: ([#\.][a-z0-9]*?\.?.*?)\s?\{([^\{\}]*)\}

2) Had the attributes string, we can now spend a regex to parse it and create a new array. Using this simple regex we can retrieve the second part: ([^\;]*);

In the code this would be something like:

function parseCss($cssString){
//Parsing the class or id name + the attributes
$regex = "/([#\.][a-z0-9]*?\.?.*?)\s?\{([^\{\}]*)\}/m";
preg_match_all($regex, $cssString, $classes, PREG_PATTERN_ORDER);

if(sizeof($classes[1]) > 0){
//organize a new proper array "$parsedCss"
foreach($classes[1] as $index => $value){
$parsedCss[$index][0] = $value; //class or id name
}

foreach($classes[2] as $index => $value){
//Parsing the attributes string
$regex = "/([^\;]*);/m";
preg_match_all($regex, $value, $returned_attributes, PREG_PATTERN_ORDER);

if(sizeof($returned_attributes[1]) > 0){
$parsedCss[$index][1] = $returned_attributes[1]; // array of attributes
}
}
}
return $parsedCss;
}

Then you can just print:

echo '<pre>';
$css = "#header { background: red; font-size: 14px; color:white; }#header { background: red; font-size: 14px; color:white; }";
print_r(parseCss($css));

And the result would be:

Array
(
[0] => Array
(
[0] => #header
[1] => Array
(
[0] => background: red
[1] => font-size: 14px
[2] => color:white
)

)

[1] => Array
(
[0] => #header
[1] => Array
(
[0] => background: red
[1] => font-size: 14px
[2] => color:white
)

)

)

PHP: Parse CSS file, find quoted font-family value, copy rules/selectors without that quoted font, add class to all selectors with that font name

Ended up creating my own simple css parser to do this as it's a lot faster.

$css_string = '
html {
font-family: "PT Sans", Helvetica, Arial, sans-serif;
color: #222222;
}';

// Get the CSS that contains a font-family rule.
$length = strlen($css_string);
$porperty = 'font-family';
$replacements = array();

while (($last_position = strpos($css_string, $porperty, $last_position)) !== FALSE) {
// Get closing bracket.
$end = strpos($css_string, '}', $last_position);
if ($end === FALSE) {
$end = $length;
}
$end++;

// Get position of the last closing bracket (start of this section).
$start = strrpos($css_string, '}', - ($length - $last_position));
if ($start === FALSE) {
$start = 0;
}
else {
$start++;
}

// Get closing ; in order to get the end of the declaration.
$declaration_end = strpos($css_string, ';', $last_position);

// Get values.
$start_of_values = strpos($css_string, ':', $last_position);
$values_string = substr($css_string, $start_of_values + 1, $declaration_end - ($start_of_values + 1));
// Parse values string into an array of values.
$values_array = explode(',', $values_string);

// Values array has more than 1 value and first element is a quoted string.
if (count($values_array) > 1 && (strpos($values_array[0], '"') || strpos($values_array[0], "'"))) {
// Remove first value and render css rule.
$removed_value = strtolower(trim(str_replace(array('"', "'"), '', $values_array[0])));
$removed_value = str_replace(' ', '-', $removed_value);
unset($values_array[0]);
$new_values_array = implode(',', $values_array);

// Get all selectors.
$end_of_selectors = strpos($css_string, '{', $start);
$selectors = substr($css_string, $start, $end_of_selectors - $start);

// From advagg_load_stylesheet_content().
// Perform some safe CSS optimizations.
// Regexp to match comment blocks.
$comment = '/\*[^*]*\*+(?:[^/*][^*]*\*+)*/';
// Regexp to match double quoted strings.
$double_quot = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"';
// Regexp to match single quoted strings.
$single_quot = "'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'";
// Strip all comment blocks, but keep double/single quoted strings.
$selectors_stripped = preg_replace(
"<($double_quot|$single_quot)|$comment>Ss",
"$1",
$selectors
);

// Add css class to all the selectors.
$selectors_array = explode(',', $selectors_stripped);
foreach ($selectors_array as &$selector) {
$selector = ' .' . $removed_value . ' ' . $selector;
}
$new_selectors = implode(',', $selectors_array);

// Get full rule set.
$full_rule_set = substr($css_string, $start, $end - $start);
// Replace values.
$new_full_rule_set = str_replace($values_string, $new_values_array, $full_rule_set);
// Replace selectors.
$new_full_rule_set = str_replace($selectors, $new_selectors, $new_full_rule_set);

// Record info.
$replacements[] = array($full_rule_set, $new_full_rule_set, $removed_value);
}

// Advance position.
$last_position = $end;
}

foreach ($replacements as $replace) {
$css_string = str_replace($replace[0], $replace[0] . $replace[1], $css_string);
}

output:

html {
font-family: "PT Sans", Helvetica, Arial, sans-serif;
color: #222222;
} .pt-sans
html {
font-family: Helvetica, Arial, sans-serif;
color: #222222;
}

PHP CSS Parser - Selector Declarations to String

I came up with my own crude solution and created a class to do what I was looking for. My sources are referenced at the bottom.

class css2string {
var $css;

function parseStr($string) {
preg_match_all( '/(?ims)([a-z0-9, \s\.\:#_\-@]+)\{([^\}]*)\}/', $string, $arr);
$this->css = array();
foreach ($arr[0] as $i => $x)
{
$selector = trim($arr[1][$i]);
$rules = explode(';', trim($arr[2][$i]));
$this->css[$selector] = array();
foreach ($rules as $strRule)
{
if (!empty($strRule))
{
$rule = explode(":", $strRule);
$this->css[$selector][trim($rule[0])] = trim($rule[1]);
}
}
}
}

function arrayImplode($glue,$separator,$array) {
if (!is_array($array)) return $array;
$styleString = array();
foreach ($array as $key => $val) {
if (is_array($val))
$val = implode(',',$val);
$styleString[] = "{$key}{$glue}{$val}";

}
return implode($separator,$styleString);
}

function getSelector($selectorName) {
return $this->arrayImplode(":",";",$this->css[$selectorName]);
}

}

You can run it as follows:

$cssString = "
h1 {
font-size: 15px;
font-weight: bold;
font-style: italic;
font-family: Verdana, Arial, Helvetica, sans-serif;
}

div.item {
font-size: 12px;
border:1px solid #EEE;
}";

$getStyle = new css2string();
$getStyle->parseStr(cssString);
echo $getStyle->getSelector("div.item");

The output would be as follows:

font-size:12px;border:1px solid #EEE

This solution works even with comments within your CSS file, as long as the comments are not inside selectors.

References:
http://www.php.net/manual/en/function.implode.php#106085
http://stackoverflow.com/questions/1215074/break-a-css-file-into-an-array-with-php

parsing CSS in PHP with global variables. Wordpress

The problem is, your CSS file containing PHP is loaded outside of WordPress, and thus knows nothing about your global variable declared inside of WordPress.

One common technique, is to simply output the customized properties in the head of the page using wp_head

function my_style() {
?><style type="text/css"><?php
//Output CSS.
?></style><?php
}
add_action( 'wp_head', 'my_style' );

Another technique would be to use the AJAX URL, and register an action that will respond with the dynamic CSS.

$style_url = add_query_arg( array( 'action' => 'my-style' ), admin_url( 'admin-ajax.php' ) );
wp_enqueue_styles( 'my-style', $style_url );

function my_style() {
header( 'Content-type: text/css; charset: UTF-8' );
//Output CSS.
}
add_action( 'wp_ajax_my-style', 'my_style' );
add_action( 'wp_ajax_nopriv_my-style', 'my_style' );

In either case, I strongly recommend separating out the dynamic styles from the static CSS. Parsing the entire CSS file though PHP adds unnecessary load to the server. Also .htaccess-based tricks for parsing CSS as PHP will only work with Apache servers.



Related Topics



Leave a reply



Submit