Heute ist Developers Shame Day, eine vom PHP-Hacker ausgerufene Aktion, bei der Programmierer mit schlechtem Beispiel vorangehen. Statt sich über den WTFigen Code anderer lustig zu machen, ist heute ausnahmsweise einmal der Tag der Selbstreflektion – denn wir waren ja alle mal jung und dachten nach zwei Hallo-Welt-Tutorials, dass wir es jetzt raushaben. Da will ich nicht zurückstehen. Allerdings tendiere ich dazu, alte Sachen schnell mal wegzuwerfen und damit sind leider auch viele Jungendsünden im Orkus verschwunden. Aber dank sachdienlicher Hinweise bei Twitter habe ich noch etwas gefunden: ein klassischer Fall von „Etwas komplexes parsen? Klar, machen wir mit Regex!“
/**
* parse
* Parses some CSS into an array
* @param bool $rebuild Rebuild the array after parsing?
*/
public function parse($rebuild = true){
$css = $this->css;
// Remove CSS comments
$css = preg_replace('//*.*?*//ms', '', $css);
// Remove HTML comments
$css = preg_replace('/([^'"]+?)(<!--|-->)([^'"]+?)/ms', '$1$3', $css);
// Extract @media-blocks into $blocks
preg_match_all('/@media.+?{.*?}[s]*}/ms',$css, $blocks);
// Append the rest to $blocks
$rest = preg_replace('/@media.+?{.*?}[s]*}/ms', '', $css);
array_push($blocks[0], $rest);
$ordered = array();
$block_count = count($blocks[0]);
for($i=0; $i<$block_count; $i++){
// If @media-block, strip declaration and parenthesis
if((strlen($blocks[0][$i]) > 5) && (substr_compare($blocks[0][$i], '@media', 0, 6, FALSE) === 0)){
$ordered_key = trim(preg_replace('/^(@media[^{]+){.*}$/ms', '$1', $blocks[0][$i]));
$ordered_value = trim(preg_replace('/^@media[^{]+{(.*)}$/ms', '$1', $blocks[0][$i]));
}
else{
$ordered_key = 'css';
$ordered_value = trim($blocks[0][$i]);
}
// Split by parenthesis, ignoring those inside content-quotes
$rules = preg_split('/([^'"{}]*?['"].*?(?<!\)['"][^'"{}]*?)[{}]|([^'"{}]*?)[{}]/', trim($ordered_value," rnt"), -1, PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE);
$rules_count = count($rules);
// Group pairs of selectors and rules, split rules
for($j=0; $j<$rules_count; $j++){
$selector = trim($rules[$j]);
if(isset($rules[1+$j])){
$rule = trim($rules[++$j]);
}
if($selector && $rule){
$ordered[$ordered_key][] = array($selector => $this->split_rules($rule));
}
}
}
// Rebuild array
if($rebuild){
$this->rebuild();
}
$this->parsed = $ordered;
}
Finster. Ein paar Zeilen aus dem Ding sind vermutlich nicht von mir, aber eh … das reicht trotzdem. Wer mehr vom Developers Shame Day sehen möchte, findet die Beiträge via Twitter und Facebook.
Kommentare (2)
Cem Derin ¶
3. November 2010, 12:52 Uhr
In Puncto RegExp passt nach wie vor der Spruch: Wenn man weiß wie ein Hammer funktioniert, sieht die ganze Welt wie ein Nagel aus.
Alex ¶
3. November 2010, 22:58 Uhr
Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.