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 -


here's simple example showing css.

example input:

html {   font-family: "pt sans", helvetica, arial, sans-serif;   color: #222222; } 

desired output:

html {   font-family: helvetica, arial, sans-serif;   color: #222222; } .pt-sans html {   font-family: "pt sans", helvetica, arial, sans-serif;   color: #222222; } 

i've been using https://github.com/sabberworm/php-css-parser examples not detailed enough me figure out.

this have far:

<?php $css_string = '     html {       font-family: "pt sans", helvetica, arial, sans-serif;       color: #222222;     }';  // create parser. $osettings = sabberworm\css\settings::create()->withmultibytesupport(false); $ocssparser = new sabberworm\css\parser($css_string, $osettings); $ocssdocument = $ocssparser->parse();  // font-family rules. foreach($ocssdocument->getallrulesets() $key0 => $oruleset) {   $rules = $oruleset->getrules('font-family');   if (!empty($rules)) {     foreach ($rules $key1 => $values) {       var_dump(array($key0, $key1));       var_dump($values->getvalue());     }   } } 

which outputs this

array (size=2)   0 => int 0   1 => int 0  object(sabberworm\css\value\rulevaluelist)[91]   protected 'acomponents' =>      array (size=4)       0 =>          object(sabberworm\css\value\string)[85]           private 'sstring' => string 'pt sans' (length=7)       1 => string 'helvetica' (length=9)       2 => string 'arial' (length=5)       3 => string 'sans-serif' (length=10)   protected 'sseparator' => string ',' (length=1) 

the reason why want async font loading https://www.filamentgroup.com/lab/font-events.html run js code this.

<script src="//cdn.rawgit.com/bramstein/fontfaceobserver/master/fontfaceobserver.js"></script> <script> var observer = new window.fontfaceobserver("pt sans", {}); observer.check(null, 5000).then(function () {   window.document.documentelement.classname += " pt-sans"; }); </script> 

edit: have this

$osettings = sabberworm\css\settings::create()->withmultibytesupport(false); $oparser = new sabberworm\css\parser($css_string, $osettings); $odoc = $oparser->parse();  $external_fonts_used = array(); foreach($odoc->getallrulesets() $key0 => $oruleset) {   $rules = $oruleset->getrules('font-family');   if (!empty($rules)) {     foreach ($rules $key1 => $values) {       $get_value = $values->getvalue();       if ($get_value instanceof sabberworm\css\value\rulevaluelist) {         foreach ($get_value->getlistcomponents() $key2 => $value) {           if ($value instanceof sabberworm\css\value\string) {             $external_fonts_used[$key0] = $value->getstring();           }         }       }       if ($get_value instanceof sabberworm\css\value\string) {         $external_fonts_used[$key0] = $get_value->getstring();       }     }   } } var_dump($external_fonts_used); 

which gives me

array (size=1)   0 => string 'pt sans' (length=7) 

which means can target correct css rules , read info; need modify , copy them.

ended creating own simple css parser it's lot faster.

$css_string = ' html {   font-family: "pt sans", helvetica, arial, sans-serif;   color: #222222; }';  // css contains font-family rule. $length = strlen($css_string); $porperty = 'font-family'; $replacements = array();  while (($last_position = strpos($css_string, $porperty, $last_position)) !== false) {   // closing bracket.   $end = strpos($css_string, '}', $last_position);   if ($end === false) {     $end = $length;   }   $end++;    // position of last closing bracket (start of section).   $start = strrpos($css_string, '}', - ($length - $last_position));   if ($start === false) {     $start = 0;   }   else {     $start++;   }    // closing ; in order end of declaration.   $declaration_end = strpos($css_string, ';', $last_position);    // 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 array of values.   $values_array = explode(',', $values_string);    // values array has more 1 value , first element quoted string.   if (count($values_array) > 1 && (strpos($values_array[0], '"') || strpos($values_array[0], "'"))) {     // remove first value , 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);      // selectors.     $end_of_selectors = strpos($css_string, '{', $start);     $selectors = substr($css_string, $start, $end_of_selectors - $start);      // advagg_load_stylesheet_content().     // perform safe css optimizations.     // regexp match comment blocks.     $comment     = '/\*[^*]*\*+(?:[^/*][^*]*\*+)*/';     // regexp match double quoted strings.     $double_quot = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"';     // regexp match single quoted strings.     $single_quot = "'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'";     // strip comment blocks, keep double/single quoted strings.     $selectors_stripped = preg_replace(       "<($double_quot|$single_quot)|$comment>ss",       "$1",       $selectors     );      // add css class selectors.     $selectors_array = explode(',', $selectors_stripped);     foreach ($selectors_array &$selector) {       $selector = ' .' . $removed_value . ' ' . $selector;     }     $new_selectors = implode(',', $selectors_array);      // 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 $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; } 

Comments

Popular posts from this blog

OpenCV OpenCL: Convert Mat to Bitmap in JNI Layer for Android -

android - org.xmlpull.v1.XmlPullParserException: expected: START_TAG {http://schemas.xmlsoap.org/soap/envelope/}Envelope -

python - How to remove the Xframe Options header in django? -