Selector-Scope
Hier muss ich wahrscheinlich erst einmal klären, was ich genau damit meine:
Meine CSS-Dateien sehen oft folgendermaßen aus:
Code:
Man sieht, dass sich "#hauptID" oft wiederholt und nun habe ich mir gedacht: #hauptID { ... }
#hauptID .subClass { ... }
#hauptID h1 { ... }Hey, du bist doch faul... warum kann man diese Regeln nicht einfach zusammenfassen und nur einmal "#hauptID" schreiben?Gedacht - getan:
Syntax
Hier habe ich nicht lange überlegen müssen - geschweifte Klammern zum Zusammenfassen sind schon im CSS vorhanden... übernehmen wir das. So würde das obige Beispiel folgendermaßen aussehen:
Code:
Jetzt haben wir aber in CSS natürlich noch die Unterscheidung zwischen "#ID .class" und "#ID.class" - also der Tatsache ob zwischen den einzelnen Selectoren ein Leerzeichen ist oder nicht. Wie kommt das hier zum Tragen?@parser scope #hauptID {
{ ... }
.subClass { ... }
h1 { ... }
}Realtiv einfach - ABER leider nicht ganz intuitiv:
Wenn am Ende des Selektors das ansonsten verbotene Zeichen "|" (Pipe) steht wird der Inhalt des Scopes direkt an den Selektor angehängt. D.h. die beiden Beispiele von oben würde so aussehen:
Code:
@parser scope #ID {
.class { ... }
}
/* und */
@parser scope #ID|{
.class { ... }
}
Natürlich kann man das Ganze auch schachteln und auch komplette Dateien in einen Scope packen:
Code:
- dafür müssen wir nur in unserer $this->parse-Funktion das Einfügen der Dateien vor dem Auflösen des Scopes machen.@parser scope #hauptID {
@parser include(dateiname);
}Realisierung
Dieses Problem hat mich völlig überrascht: es ging so einfach:
Code:
private function resolveScope($content){
return preg_replace_callback('/(?:\r?\n)?[ \t]*@parser\s+scope\s+([^{}]+)({(?:[^{}"\']+|' . self::$strRegExp . '|(?2))*})[ \t]*(?:\r?\n)?/', array($this, "parseScopeRegExpWrapper"), $content);
}
private function parseScopeRegExpWrapper($match){
$name = preg_replace('/\s+$/', "", $match[1]);
if ($name{strlen($name) - 1} == "|") $name = substr($name, 0, -1);
else $name .= " ";
// hier war in der letzten Version ein Fehler: mit "," separierte Werte wurden nicht beachtet
$content = preg_replace('/[ \t]*([^{}\n\r,]*)({(?:[^{}"\']+|' . self::$strRegExp . ')*}|,\s*)/', $name . "$1$2",
$this->resolveScope(
preg_replace('/^{|[ \t]*}$/', "", $match[2])
)
);
return $content;
}