Reguläre ausdrücke, css zusammenfassen mit php

Chance

Member
Ich stehe irgendwie auf dem Schlauch....
Ich habe zwei CSS Dateien. Diese möchte ich in einer zusammenfassen.
Vorlage + Änderung, also:
Code:
.test {color: green;}
.test2 {color: red;}
und
Code:
.test {color: yellow;}
.test2 {color: red;}
zu
Code:
.test {color: yellow;}
.test2 {color: red;}
.

Dazu möchte ich die CSS auseinanderpflücken und per PHP wieder zusammensetzen.
 

Nerdus

Halbgott in Schwarz
… und wo genau hängst du da jetzt fest?

Die einzelnen Selektoren stehen vor der offenen geschweiften Klammer und werden durch Kommata getrennt; die einzelnen Attribute stehen innerhalb der geschweiften Klammern und werden durch Semikola getrennt; innerhalb der Attribute werden Attributsnamen und -werte durch Doppelpunkte getrennt. Mit dem Wissen sollten sich die ersten Regeln zur “Zerlegung” doch eigentlich schon bauen lassen.
 

Chance

Member
Beide CSS Dateien in einer Zusammenzuführen.
Und die .test, test2 etc. zu beachten...

Bzw. erstmal die .test von {...} zu trennen.
 

rellek

relativ sensationell
Teammitglied
PHP:
<?php


$string = '.test {color: green;}
.test2 {color: red;}';

$res = array();

$pattern = '/([a-z0-9.#*]+) \{([a-z0-9\s,-;.%]+)\}/Uis';

preg_match_all($pattern, $string, $res);

print_r($res);

/*
Array
(
    [0] => Array
        (
            [0] => .test {color: green;}
            [1] => .test2 {color: red;}
        )

    [1] => Array
        (
            [0] => .test
            [1] => .test2
        )

    [2] => Array
        (
            [0] => color: green;
            [1] => color: red;
        )

)
*/

?>
 

Nerdus

Halbgott in Schwarz
Chance' schrieb:
Bzw. erstmal die .test von {...} zu trennen.
Na also, damit kann man arbeiten ;)

Der erste Schritt sollte eigentlich sein, die einzelnen Blöcke voneinander zu trennen, also aus
Code:
.test {color: green;}
.test2 {color: red;}
[code]einmal[code].test {color: green;}[code]und einmal[code].test2 {color: red;}[code]herauszuholen. Das geht am simpelsten mit [url='http://www.php.net/manual/de/function.preg-split.php']preg_split()[/url], als Trenner müsstest du einfach “}” angeben (und am besten zusätzlich das “PREG_SPLIT_NO_EMPTY”-flag setzen). Dann bekommst du ein Array, das ungefähr so aussehen sollte:[php]Array (
	[0] => Array (
		[0] => ".test {color: green;",
		[1] => (Zeichenzahl des Strings, bin zu faul sie zu zählen)
	),
	[1] => Array (
		[0] => ".test2 {color: red;"
		[1] => (s.o.)
	)
)[/php]

Auf die einzelnen Einträge des Arrays kannst du jetzt wieder preg_split() anwenden (diesmal mit “{”), um sie in Selektor und Anweisungen zu trennen …

[quote='rellek','index.php?page=Thread&postID=4089#post4089']…[/quote]Mmh, ohne maulen zu wollen, aber für einen Anfänger in Sachen reguläre Ausdrücke dürfte es wohl ein bisschen schwierig werden, von dem Beispiel aus weiterzuarbeiten, oder?  8o
 

rellek

relativ sensationell
Teammitglied
Nerdus' schrieb:
Mmh, ohne maulen zu wollen, aber für einen Anfänger in Sachen reguläre Ausdrücke dürfte es wohl ein bisschen schwierig werden, von dem Beispiel aus weiterzuarbeiten, oder? 8o
Und dabei ist der Ausdruck noch richtig harmlos. :D
 

Chance

Member
Danke :)

War nah dran... irgendwie :D
Code:
([\.\#\0-9a-zA-Z]+) {(.*?)}

Habe nur immer Startschwierigkeiten ^^ .
 

Chance

Member
Ich habe es gelöst bekommen :)
Für euch und die Googelden :D:

$filecont ist der Inhalt der CSS Datei.

Der Inhalt wird aufgesplittet, in ein Array gepackt und dann wieder umgewandelt.
Das hat den Sinn, das die CSS Datei, die sonst der Browser zusammenfügt, schon zusammengefügt ist.
Das Ergebnis ist am besten zu cachen... da die Umwabndlung noch nicht optimal ist.

PHP:
preg_match_all('/([a-z0-9.#-_:,\s*]+) \{([a-z0-9.\/()_\s,#-;.%]+)\}/isU', $filecont, $Temp, PREG_SET_ORDER);

			$CSS = array();
			foreach ($Temp as $elem) {
				if (strpos($elem[1],',') === false) {
					$elem[2] = explode(';',$elem[2]);
					foreach ($elem[2] as $elem2) {
						$elem2 = explode(':',$elem2);
						if (isset($elem2[1]) === true) $CSS[trim($elem[1])][trim($elem2[0])] = trim($elem2[1]);
					}

	 			} else {

						$Temp2 = array();
						$elem[2] = explode(';',trim($elem[2]));
						foreach ($elem[2] as $elem2) {
							$elem2 = explode(':',$elem2);
							if (isset($elem2[1]) === true) $Temp2[trim($elem2[0])] = trim($elem2[1]);
						}
					if (count($Temp2) !== 0) {
						$elem[1] = explode(',',$elem[1]);
						foreach ($elem[1] as $elem3) {
							if (isset($CSS[trim($elem3)]) === false) $CSS[trim($elem3)] = $Temp2;
							else $CSS[trim($elem3)] = array_merge($CSS[trim($elem3)],$Temp2);
						}
					}
				}

			}

			$filecont = '';
			foreach ($CSS as $key => $elem) {

				$CSSItem = array();
				foreach ($elem as $CSSkey => $CSSelem) {
		 			$CSSItem[] = $CSSkey.':'.$CSSelem;
				}
				#."\n"
				$filecont .= $key.'{'.implode(';',$CSSItem).';}'."\n";
			}

			echo $filecont;
 

rellek

relativ sensationell
Teammitglied
Nicht so viel, ehrlich gesagt. Die 6 KB bekommst du bei ausreichender Grösse (und noch mehr) über GZ-Kompression und die Vererbung der CSS-Deklarationen ist Client-Sache, die man ohnehin nicht beeinflussen kann (und nebenbei bemerkt auch nicht ins Gewicht fällt).

Dafür hast du den PHP-Aufwand immer - das ist imho schmerzhafter als die 6K.

Aber RegEx halte ich für hingegen für ziemlich elementar, deshalb ist jede Beschäftigung damit goldrichtig ;)
 

Titus

Goldmember
keine Ahnung was du treibst, aber schaut lustig aus ^^

blöde Frage wozu die CSS überhaupt erst lesen?

warum schreibtst du nicht ein Styleeditor der per XML die im Style vorhanden klassen / IDs enthält kennt, dann evtl noch ein kürzel was diese Klasse macht, um eine kurze Version aller"nützlichen" CSS deklarationen darzustellen (im editor), alternativ alles was dir einfällt und somit der Editor hergibt

checkbox davor und wenn die gesetzt ist wird der Wert übernommen, das ganze packst du (irgendwie) in die DB, möglichst das due nach identischen inhalten dann auch suchen kannst für die Ausgabe UND Bearbeitung im ACP (finde alle "blue" -> liste -> alle markieren -> neue farbe Update alle markierten, so kann man den einen oder anderen weglassen)

nun kannst du für die Verwendung eine CSS ausgeben die nach deinem Bedürfnis kreiert ist, entweder sammelst du alle identischen Farbanweisungen heraus und packst das in eine Zeile, kombinirst das womöglich noch mit XY, oder was auch immer
das wäre eine art statistische auswertung die du rechenintensiv vornehmen kannst, aber z.b. so eine möglichst kompakte CSS zu schreiben

ist vermutlich einfacher als diesen kompressor zu schreiben das er sinnvoll funktioniert

man wird bei CSS zwar sicher nicht um ein wenig eigene Schreibarbeit und Spezialeinträge herum kommen, aber das wär doch ein Styleeditor der recht passabel ist?!
 

Chance

Member
rellek' schrieb:
Nicht so viel, ehrlich gesagt. Die 6 KB bekommst du bei ausreichender Grösse (und noch mehr) über GZ-Kompression und die Vererbung der CSS-Deklarationen ist Client-Sache, die man ohnehin nicht beeinflussen kann (und nebenbei bemerkt auch nicht ins Gewicht fällt).

Dafür hast du den PHP-Aufwand immer - das ist imho schmerzhafter als die 6K.

Aber RegEx halte ich für hingegen für ziemlich elementar, deshalb ist jede Beschäftigung damit goldrichtig ;)

GZ Kompression ist auch aktiviert etc.
Mir kommt es auf jedes Quentchen an.

@Titus:
Wäre dann Admin abhängig, oder ?
 

Nerdus

Halbgott in Schwarz
rellek' schrieb:
Nicht so viel, ehrlich gesagt. Die 6 KB bekommst du bei ausreichender Grösse (und noch mehr) über GZ-Kompression und die Vererbung der CSS-Deklarationen ist Client-Sache, die man ohnehin nicht beeinflussen kann (und nebenbei bemerkt auch nicht ins Gewicht fällt).

Dafür hast du den PHP-Aufwand immer - das ist imho schmerzhafter als die 6K.
Ich finde die Idee nicht soo uninteressant, aber natürlich muss die Umsetzung entsprechend gut sein und man braucht eine Umgebung, in der so eine Spielerei auch tatsächlich sinnvoll ist. Wenn es sowieso nur eine einzelne CSS-Datei ist, die man damit ein bisschen “umsortiert”, dann ist der Effekt natürlich kaum der Rede wert. Wenn man aber zum Beispiel ein Dutzend CSS-Dateien hat, die man durch so eine (oder eine ähnliche) Funktion zu einer einzigen Datei zusammenfasst und den Inhalt so weit wie möglich komprimiert … Dann wird es schon interessanter, weil es nicht nur die Datenmenge deutlich reduzieren dürfte, sondern vor allem auch die Anzahl der Dateien, die überhaupt angefordert werden. Die Ergebnisse zu cachen sollte ja nicht so das große Problem sein, da sich die Inhalte von CSS-Dateien nicht am laufenden Band ändern.

Dass das natürlich trotzdem eine Verbesserung ist, die hauptsächlich auf dem Papier besteht und in der Praxis kaum einen Unterschied darstellt, sollte eh klar sein.

rellek' schrieb:
Aber RegEx halte ich für hingegen für ziemlich elementar, deshalb ist jede Beschäftigung damit goldrichtig ;)
Sehr richtig :D
 

Titus

Goldmember
Chance' schrieb:
@Titus:
Wäre dann Admin abhängig, oder ?
jein, wenn du es als eigenständige Anwendung erstellst ist das prinzipiell sogar auf einer HTML-Dateien basierten Website verwendbar, man bindet dann ja nur das Endprodukt, die CSS-Datei ein

ich dachte du hast das für dein CMS gedacht, daher die IDee das gleich "richtig" zu machen statt diese komrimierungsspielerei

die Verwaltung unterschiedlicher Stile könnte man auch in ebnen organisieren und bei der Auswertung nur bestimmte definitionen herausgeben, bzw Unterschiedliche CSS mit lediglich den Unterschieden zur BasisCSS
was sicher hilfreich ist wenn man verschiedene Layouts verwendet - der Eingangsstil ist ja meist schon geladen, man bräuchte also nur die differenzwerte (ähnlich man beim vB ja auch unterstyles erstellen kann, mit dem Unterschied das man nicht das Ganze sondern nur die Unterschiede ausgibt)

Nerdus' schrieb:
Wenn es sowieso nur eine einzelne CSS-Datei ist, die man damit ein bisschen “umsortiert”, dann ist der Effekt natürlich kaum der Rede wert. Wenn man aber zum Beispiel ein Dutzend CSS-Dateien hat, die man durch so eine (oder eine ähnliche) Funktion zu einer einzigen Datei zusammenfasst und den Inhalt so weit wie möglich komprimiert … Dann wird es schon interessanter

wobei dann immer zu beachten ist welche Hierarchie einzuhalten ist, wenn eine Optionenbox auf der Startseite anders aussieht als auf der Unterseite wäre nicht so prall das zusammen zu fügen
 
Oben