这是一个简单的例子,展示了我想用CSS做什么。
示例输入:
html {
font-family: "PT Sans", Helvetica, Arial, sans-serif;
color: #222222;
}
期望的输出:
html {
font-family: Helvetica, Arial, sans-serif;
color: #222222;
}
.pt-sans html {
font-family: "PT Sans", Helvetica, Arial, sans-serif;
color: #222222;
}
我一直在使用https://github.com/sabberworm/PHP-CSS-Parser,但这些例子对我来说还不够详细。
这是我到目前为止所做的:
<?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();
// Get font-family rules.
foreach($oCssDocument->getAllRuleSets() as $key0 => $oRuleSet) {
$rules = $oRuleSet->getRules('font-family');
if (!empty($rules)) {
foreach ($rules as $key1 => $values) {
var_dump(array($key0, $key1));
var_dump($values->getValue());
}
}
}
哪个输出
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)
我想要这样做的原因是异步字体加载https://www.filamentgroup.com/lab/font-events.html我会在这里运行一些js代码。
<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>
编辑: 我现在有了这个
$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() as $key0 => $oRuleSet) {
$rules = $oRuleSet->getRules('font-family');
if (!empty($rules)) {
foreach ($rules as $key1 => $values) {
$get_value = $values->getValue();
if ($get_value instanceof Sabberworm\CSS\Value\RuleValueList) {
foreach ($get_value->getListComponents() as $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);
哪个给了我
array (size=1)
0 => string 'PT Sans' (length=7)
这意味着我可以定位正确的CSS规则并阅读信息;现在我需要修改和复制它们。
答案 0 :(得分:0)
结束创建我自己的简单css解析器,因为它的速度要快得多。
$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);
}
输出:
html {
font-family: "PT Sans", Helvetica, Arial, sans-serif;
color: #222222;
} .pt-sans
html {
font-family: Helvetica, Arial, sans-serif;
color: #222222;
}