Упаковщик CSS: зачистка css-файла

версия для печати

Упаковщик не в смысле архивации, а в смысле чистки css-файлов от пустых строк и комментариев. Слово "упаковщик" более удобно, чем "чистильщик" или т.п. Файл в итоге получается меньше без потери функциональности, поэтому так "громко" назвал :)

Проблема: на локальной копии сайта я храню файлы стилей с комментариями, а на сервере они должны быть чистыми. Перед первой загрузкой на сервер подчистил все. Теперь у меня две версии - с комментами и без них. При изменении в одной версии приходится повторять изменения в другой. Не удобно, напрягает и все такое :( Надо что-то делать.

Есть такое решение, как php-библиотека Minify. Работает с css/javascript. Размещаем библиотеку в недрах сайта, все подключения стилей/скриптов переводим на нее типа так:

<link href="http://mysite.ru/min/?f=css/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="http://mysite.ru/min/?f=js/script.js"></script>

Теперь на сервер можно все заливать, как есть, а при загрузке страниц браузеру будут отправляться очищенные файлы. Программа минимизирует, объединяет и кэширует CSS-файлы. Вообщем круто наверно :). Отказался я от этой проги потому, что:

  1. Minify - это большая библиотека php-скриптов. Черт-ее-знает, где там дыры. Перекапывать весь код для самоуспокоения мне не хочется;
  2. любой сообразительный хаЦкер сможет получить файл без компрессии, т.е. со всеми комментами и т.д. Как? Просто заменит запрос '.../min/?f=css/style.css' на 'http://mysite.ru/css/style.css'. Можно защититься от этого, разместив каталог с js-скриптами и css-файлами в админке.
Возможно это похоже на паранойю, но вдруг я прав? Вот поэтому я нашел решение по-лучше: зачем каждый раз чистить файлы перед ответом браузеру, когда их можно заливать "как есть", потом чистить, и хранить уже готовыми на сервере? Так у меня родился админский сервис по закачке css/js-файлов на свои сайты :)

Суть: в админке страница с формой по загрузке файлов. Выбираю, что грузить и еще некоторые параметры (степень очистки, резервная копия). PHP-скрипт (см. ниже) получает файл, полный комментов, чистит и ложит в нужный каталог, откуда готовый файл подключается в пользовательские шаблоны.


Мой упаковщик. Frontend

В этой статье я приведу скрипт по очистке CSS-файлов. Про скрипт для очистки js-файлов тоже напишу когда-нибудь. Пример файла ("лабораторная крыса"):

div.clear{clear:both;} /*используем пустую div-ку для отмены обтекания. Очень важная div-ка!!*/

/*------Ярлычки, общий вид вкладок----------*/
.tab{background-color: #DDECFF; }                  /* <----- цвет ярлычка */
.menucontent, .onepost{
    border:1px solid #81A8FF;
/* table-layout: fixed; это нельзя делать, иначе придется контролировать ширину ячейки. 
При увеличении разряда счетчика ячейку нужно уменьшать. Ширина прям в html установлена.*/
  }
div.post_tab{background-color:white;/*#FFF8F2*/ /*#81A8FF*/} /*Ярлычки на одной записи*/
div.hidden{background-color:#FFA500;/*#FFF8F2*/ /*#81A8FF*/}
/*------------------------------------------*/

table.label td{padding:0 5px 2px 0; vertical-align: middle !important;}

Что имеем: пустые строки, обычный комментарий в конце строки (1), многострочный комментарий (7, 8) и вставки комментов прям в описании свойств селектора (10, 11). Более того, я для себя принял такое соглашение: отдельные смысловые блоки отмечаю комментариями, в которых пишу только по-русски и еще использую знак '-' (3, 12).

Если нужно вычищать все комментарии, то код получается совсем простой:

$fn='/home/site/css/style.css'
$text=file_get_contents($fn);
$text=preg_replace('#\/\*.*\*\/#Us','',$text);       //Вырезаем комменты, заключенные в "/*...*/"
$text=preg_replace("#\s+[\n|\r|\r\n]+#","\n",$text); //Заменяем все пробелы в конце строки и любые окончания строк на Linux-окончание строки.
file_put_contents($fn,$text);

Результат применения к подопытному файлу выглядит так:

div.clear{clear:both;}
.tab{background-color: #DDECFF; }
.menucontent, .onepost{
   border:1px solid #81A8FF;
   }
div.post_tab{background-color:white; }
div.hidden{background-color:#FFA500; }
table.label td{padding:0 5px 2px 0; vertical-align: middle !important;}

На этом можно было бы закончить статью. Остается только прикрутить скрипт к обрабочику формы, эта часть работы остается за вами. Важно понимать, что загрузка файлов по HTTP сильно уступает FTP, но в моем случае файлики не большие, так-что вполне хватает метода POST. Еще один вероятный минус (на деле у меня так не было): представьте, пока вы методами POST/GET заливаете обновки на сервер, кому-то формируется ответ в браузер. Я думаю, у пользователя есть вероятность получения битого css/js-файла. Но поскольку это не критично к работе сайта, я иду на такой риск.

В качестве post scriptum приведу код функции, которая аккуратно вычищает все комментарии кроме "смысловой разметки" (см. пример выше, строки 3, 12):

//Умный css-упаковщик. Оставляет однострочные комменты  при условии, 
//что в строке только русские буквы и "-" (разметка блока).
$fn='/home/site/css/style.css'
$text=file_get_contents($fn);
$text=preg_replace("#\r\n|\r#","\n",$text);
$arr=explode("\n",$text);
$flgMulti=false;//Поднимаем флаг, когда попадется многострочный комментарий.
                //Сбрасываем, когда такой коммент заканчивается.
foreach($arr as $str)
{
  //Текущая строка - часть многострочного коммента 
  if($flgMulti) 
  { if(preg_match("#\*\/#U",$str))             //если в строке есть закрывающие коммент символы..
    { $str=preg_replace("#.*\*\/#U",'',$str,1);//..вырезаем конец комментария. Только первое совпадение. Эт правильно, иначе может быть вырезано лишнее ;)
      $flgMulti=false; }                       //Cбрасываем флаг.
  else continue; }

  //Если в строке не [только русский текст или "-" (разметка блока)], то чистим строку..
  if (!$flgMulti && !preg_match('#^\/\*[а-яА-Я\s-,\.]+\*\/$#U',$str))
  {  $str=preg_replace('#\/\*.*\*\/#U','',$str);//Вырезаем комменты, заключенные в "/*...*/"
     $str=rtrim($str); }                        //Убираем пробелы в конце строки

  //Если нашли начало многострочного коммента (есть открывающие символы, но нет закрывающих),..
  if (preg_match("#\/\*#",$str) && !preg_match("#\*\/#",$str))
  { $str=preg_replace("#\/\*.*#",'',$str);      //..то вырезаем текущую часть коммента
    $flgMulti=true; }                           //и поднимаем флаг.

  if(!$str) continue;
  $str=preg_replace('#(\S+)\s+\}#',"\\1}",$str);//Последний штрих - убираем пробелы типа "..10px;[пробелы]}". Они могли остаться после вырезки коммента.
  $new[]=$str;
}
$text=implode("\n",$new);
file_put_contents($fn,$text);

Думаю, из комментариев в коде понятно, что к чему. Результат работы такого упаковщика выглядит так:

div.clear{clear:both;}
/*------Ярлычки, общий вид вкладок----------*/
.tab{background-color: #DDECFF;}
.menucontent, .onepost{
   border:1px solid #81A8FF;
   }
div.post_tab{background-color:white;}
div.hidden{background-color:#FFA500;}
/*---------------------------------
---------*/
table.label td{padding:0 5px 2px 0; vertical-align: middle !important;}
[1oo%, EoF]


Похожие материалы: Упаковщик Javascript: зачистка js-файла
Понравилась статья? Расскажите о ней друзьям:

Метки: CSS, PHP, кодинг

Комментарии
Для работы модуля комментариев включите javaScript


Показать/скрыть правила
Имя
[i] [b] [u] [s] [url]
:-) ;-) :D *lol* 8-) :-* :-| :-( *cry* :o :-? *unsure* *oops* :-x *shocked* *zzz* :P *evil*

Осталось 1000 символов.
Код защиты от спама Обновить код
Каждый комментарий проходит ручную модерацию. 100% фильтрация спама.
Продвижение
Время
Метки
Щелкни мышей, чтобы закрыть