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
Post a Comment