CSS minifier
Gepost door Richard van Velzen op 25-05-2010 22:38.
Jawel, een simpele, kleine, regexgebaseerd (JA!) CSS-minifier.
Uitleg is nauwelijks nodig, de code spreekt voor zich: stop er een stuk CSS in en je krijgt een sterk verkleinde string terug.
Let op(1): het haalt alleen whitespace weg, attributen zoals "margin: 1px 0 1px 0" worden niet naar "margin:1px 0" verkleind. (sinds 22-03 wel, margin: 5px 0px; margin-top: 3px; zal hij wel niks mee doen)
Let op(2): in principe zou er niks fouten moeten gaan. Er is een kleine uitzondering: commentaar binnen een url(mijnurl.png) wordt ook weggehaald. Ja, dit is volgens de standaard toegestaan maar ik ben nog geen enkel geval tegengekomen waar dit zo was. Dus dit verander ik waarschijnlijk ook niet.
Dus, brand me maar af! :-)
Update (2010-03-07): preg_replace kan ook arrays als input krijgen ja, veel handiger...
Update (2010-03-22): behoorlijk uitgebreid met veelvoorkomende dingen die kleiner kunnen.
Bestanden van dit script
index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | <?php
function minifyHelper($match) {
$entries = array_map(
'strtolower',
explode(' ', $match[0])
);
switch(count($entries)) {
case 4:
if ($entries[3] === $entries[1]) {
array_pop($entries);
} else {
break;
}
case 3:
if ($entries[2] === $entries[0]) {
array_pop($entries);
} else {
break;
}
case 2:
if ($entries[1] === $entries[0]) {
array_pop($entries);
}
}
return implode(' ', $entries);
}
function minifyCSS($input, $newlineAfterBrace = false) {
$result = trim(preg_replace_callback(
'~(?xi)
(?<!\b(?: # uitzonderingen... bah
background-position
))
:\K
(?:(?:\d*\.)?\d+ (?: [a-z]{2} | %)? | auto )
(?: \s (?:\d*\.)?\d+ (?: [a-z]{2} | %)? | auto ) {0,3}
(?= [;}] )
~S',
'minifyHelper',
preg_replace(
array(
'~(?x)
\s*
(?:
# debug-CSS weghalen
\Q/* REMOVE */\E
(?:
[\r\n]+
(?! \Q/* END REMOVE */\E )
.*
)+
[\r\n]+ \Q/* END REMOVE */\E
|
# commentaar, natuurlijk
/\* [^*]* \*+ (?: [^/] [^*]* \*+ )* /
)
\s*
~',
'~(?x)
# nietrelevante whitespace
\s+ (?! [^\'"()\r\n]* \))
~',
'@(?x)
(?<=[{};:,+>~]) \s+
| \s+ (?=[{}:,+>~;])
| ( \( [^)]* \) | " [^"]* " | \' [^\']* \' )
# een ; kan natuurlijk in een string voorkomen..
| ; (?: \s*; )* (?= \s* } )
@',
'~#(?ix)
# hex-kleuren, normaliseren naar kort formaat
([a-f\d])\1
([a-f\d])\2
([a-f\d])\3
~',
'~(?x)
# 0/0.0(px|em|etc.)? normaliseren naar 0
(?<=[:, ]) (?:0*\.)?0
(?i: [a-z]{2} | % )?
(?! \w )
~',
'@(?xm)
(?<= ^ | } )
(?:
# een selector met lege regels
(?: ^ | \s* (?: , \s*)? )
[>+~ ]?
(?: [.#]? [a-z_-]+ | \*
| \[[^]"\']*
(?:
(?: "[^"]*" | \'[^\']*\' )
[^]"\']*
)*
]
)++
)++
\s*{}\s*
@'
),
array(
' ',
' ',
'$1',
'#$1$2$3',
'0',
''
),
trim($input)
)
));
if ($newlineAfterBrace) {
$result = trim(str_replace('}', "}\n", $result));
}
return $result;
}
echo minifyCSS('
body div .class #id [attr],
body [attr] .class div
#id {
margin: 0px 5px 2px 5px; /* alleen de laatste 5px mag weg */
margin: 3px 3px 3px 3px; /* gelijke set */
margin: 0% 0 0px 0em; /* verschillende notaties van 0, moet 0 worden */
background: url(blaat;); /* ; in een url, de laatste ; moet wel weg */
}
body , html {
margin: 0px;
padding: 0;
background-color : #000;
}
body + a * > html {
color: navy ;
}
');
?> |
Commentaar
04-03-2010 10:11
ik had er al eentje in gebruik op een server, maar zoals gebruikelijk weet Richard mijn 5 of meer regels in 2 regexen te proppen.
Overigens draai ik het script server sided als rewritemap (aanroep via .htaccess), zodat op de development server ook steeds de css als style.minified.css wordt weggeschreven.
ps: ik zoek er nog eentje voor javascript files.
1 2 3 | Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding.
Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan. |
04-03-2010 10:18
Je hebt geluk, ik ben ook bezig met eentje voor JavaScript. :-)
Maar je kunt ook kijken naar JSMin+ van Tweakers: http://crisp.tweakblogs.net/blog/1856/jsmin+-version-13.html
1 2 3 | Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding.
Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan. |
04-03-2010 10:51
http://code.google.com/p/minify/
Ik gebruik deze, te minsten ik heb dingen hieruit over genomen :)
Voor mijn framework maak ik gebruik van een combinatie van Minify en CSSTidy (helaas niet langer door ontwikkeld).
04-03-2010 15:41
Netjes, korter dan die ik heb. Ik heb/had 5 expressies nodig.
Zal het eea testen morgen :)
1 2 3 | Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding.
Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan. |
07-03-2010 18:27
>> ps: ik zoek er nog eentje voor javascript files.
http://crisp.tweakblogs.net/blog/1856/jsmin+-version-13.html :-)
1 2 3 | Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding.
Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan. |
07-03-2010 18:31
Arien: volgens mij gaf ik al precies hetzelfde antwoord? :-)
Overigens vind ik het doel van hun project een beetje jammer, het ging ze voornamelijk om dingen als ; weg mogen laten, terwijl dat juist een groot minpunt van de taal is.
1 2 3 | Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding.
Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan. |
22-03-2010 11:34
Ziet er wel aardig uit. Helaas iets minder uitgebreid dan: http://csstidy.sourceforge.net/
1 2 3 4 5 6 7 8 | <?php
try {
throw new Ball('Voetbal');
}
catch(Ball $e) {
echo 'You caught the ball';
}
?> |
22-03-2010 11:45
Alle dingen die zij nog extra doen komen bij wat ik doe nauwelijks ooit voor en zijn het echt niet waard om nog bij te optimaliseren.
Daarnaast is dit een enkele functie die heel makkelijk in mijn deploymentproces past. :-)
1 2 3 | Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding.
Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan. |
22-03-2010 21:10
www.cleancss.com
1 2 3 | Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding.
Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan. |
26-05-2010 19:47
www.cleancss.com
Helemaal onderaan na al die reclame.
(based on csstidy 1.1)
Het voordeel van dit zelf doen is dat je CSS duidelijk en onderhoudbaar blijft en pas bij het aanbieden klaar word gemaakt voor snelheid.
12-10-2010 09:26
Ooit had ik eens onderstaande code gevonden om CSS te comprimeren. Heb er een kleine aanpassing in gedaan zodat alle css bestanden uit een folder werden gelezen zodat ik zelf vrij weinig eraan hoefde te doen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | <?php
ob_start('ob_gzhandler');
ob_start('cssCompress');
header('Content-type: text/css;charset: UTF-8');
header('Cache-Control: must-revalidate');
header('Expires: ' . gmdate('D, d M Y H:i:s',time() + 2419200 ) . ' GMT');
function cssCompress ( $outputBuffer )
{
$outputBuffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $outputBuffer);
$outputBuffer = str_replace(array("\r\n", "\r", "\n", "\t", ' ', ' ', ' '), '', $outputBuffer);
$outputBuffer = str_replace('{ ', '{', $outputBuffer);
$outputBuffer = str_replace(' }', '}', $outputBuffer);
$outputBuffer = str_replace('; ', ';', $outputBuffer);
$outputBuffer = str_replace(', ', ',', $outputBuffer);
$outputBuffer = str_replace(' {', '{', $outputBuffer);
$outputBuffer = str_replace('} ', '}', $outputBuffer);
$outputBuffer = str_replace(': ', ':', $outputBuffer);
$outputBuffer = str_replace(' ,', ',', $outputBuffer);
$outputBuffer = str_replace(' ;', ';', $outputBuffer);
return $outputBuffer;
}
$fileHandler = opendir('../styles/');
$fileArray = array();
while ( false !== ( $file = readdir ( $fileHandler ) ) )
{
if ( ( $file != '.' ) and ( $file != '..' ) and ( $file != 'Thumbs.db' ) )
{
$fileInfo = pathinfo($file);
if ( ( isset ( $fileInfo['extension'] ) ) and ( strtolower($fileInfo['extension']) == 'css' ) )
{
$fileArray[] = $file;
}
}
}
sort($fileArray);
closedir($fileHandler);
foreach ( $fileArray as $key => $value )
{
$fileStream = file_get_contents ( $value );
echo $fileStream;
}
?> |