-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
87 additions
and
147 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ | |
* | ||
* Tool for sorting CSS properties in specific order | ||
* | ||
* @version 2.13 (build bb516f2-1306162139) | ||
* @version 2.14 (build 57f634a-1307080853) | ||
* @author Vyacheslav Oliyanchuk (miripiruni) <[email protected]> | ||
* @license MIT | ||
* @web http://csscomb.com/ | ||
|
@@ -30,6 +30,10 @@ class csscomb{ | |
'datauri' => null, | ||
// если найдены интерполированные переменные, то эта переменная станет массивом | ||
'interpolations' => null, | ||
// Игнорируем комментарии | ||
'comments' => null, | ||
'inlinecomments' => null, | ||
'magicComments' => null, | ||
// если найдены CSS-хаки мешающие парсить, то эта переменная станет массивом... | ||
'hacks' => null, | ||
// если найдены комментарии содержащие { или } мешающие парсить, | ||
|
@@ -908,119 +912,56 @@ function preprocess() { | |
} | ||
|
||
// 4. Interpolated variables | ||
preg_match_all('@(\#|\@){.*?}@ismx', $this->code['edited'], $this->code['interpolations']); | ||
foreach ($this->code['interpolations'][0] as $key => $value) { | ||
$pos = strpos($this->code['edited'], $value); | ||
if ($pos !== false) { | ||
$this->code['edited'] = substr_replace($this->code['edited'],"interpolation".$key.'__',$pos,strlen($value)); | ||
} | ||
preg_match_all('@(\#|\@){.*?}@ismx', $this->code['edited'], $this->code['interpolations'], PREG_SET_ORDER); | ||
foreach ($this->code['interpolations'] as $key => $value) { | ||
$this->code['edited'] = str_replace($value[0], 'interpolation'.$key.'__', $this->code['edited']); | ||
} | ||
|
||
// X. Temporally remove comments | ||
// Magic comment | ||
preg_match_all('@ | ||
(\s*\/\*\s*csscomb:\s*false\s*\*\/.*?\/\*\s*csscomb:\s*true\s*\*\/) | ||
| | ||
(\s*\/\/\s*csscomb:\s*false[\n\r].*?\/\/\s*csscomb:\s*true[^\n\S\r]*) | ||
@ismx', $this->code['edited'], | ||
$this->code['magicComments'], PREG_SET_ORDER); | ||
foreach ($this->code['magicComments'] as $key => $value) { | ||
$this->code['edited'] = str_replace($value[0], "\nmagic: comment".$key.'__;', $this->code['edited']); | ||
} | ||
// Comments | ||
preg_match_all('@ | ||
([\n\r]\s*/\*.*?\*/)+ | ||
| | ||
(^\s*/\*.*?\*/)+ | ||
| | ||
([\n\r]\s*//[^\n\r]*)+ | ||
| | ||
(^\s*//[^\n\r]*)+ | ||
@ismx', $this->code['edited'], $this->code['comments'], PREG_SET_ORDER); | ||
foreach ($this->code['comments'] as $key => $value) { | ||
$this->code['edited'] = str_replace($value[0], 'comment'.$key.'__', $this->code['edited']); | ||
} | ||
// Inline comments | ||
preg_match_all('@ | ||
[^\S\n\r]*/\*.*?\*/([^\n\S\r]*/\*.*?\*/)* | ||
| | ||
(?<!:)[^\S\n\r]*//[^\n\r]* | ||
@ismx', $this->code['edited'], $this->code['inlinecomments'], PREG_SET_ORDER); | ||
foreach ($this->code['inlinecomments'] as $key => $value) { | ||
$this->code['edited'] = str_replace($value[0], 'inlinecomment'.$key.'__', $this->code['edited']); | ||
} | ||
|
||
// 5. Закрываем сложности парсинга {} | ||
$this->code['edited'] = str_replace('{}', '{ }', $this->code['edited']); | ||
|
||
// 6. Закрываем сложности с отсутствующей последней ; перед } | ||
$this->code['edited'] = preg_replace('@(.*?[^\s;\{\}\/\*])(\s*?})@', '$1;$2', $this->code['edited']); | ||
$this->code['edited'] = preg_replace('@(.*?[^\s;\{\}\/\*_])(\s*?})@', '$1;$2', $this->code['edited']); | ||
// Убираем ; у последнего инлайнового комментария | ||
// Инлайновый комментарий может идти только после фигурной скобки или ; | ||
$this->code['edited'] = preg_replace('@([;\{\}]+\s*?//.*?);(\s*?})@', '$1$2', $this->code['edited']); | ||
// Убираем ; у интерполированных переменных | ||
$this->code['edited'] = preg_replace('/((#\{\$|\@\{).*?)[;](\s*?\})/', '$1$3', $this->code['edited']); | ||
|
||
// 7. Комментарии | ||
if (preg_match_all('@ | ||
( | ||
\s* | ||
/\* | ||
.*?[^\*/] | ||
\*/ | ||
(\s/\*\*/)? | ||
) | ||
@ismx', $this->code['edited'], $test)) { | ||
|
||
// 7.1. Закомментировано одно или несколько свойств: повторяющийся паттерн *:*; \s*? | ||
if (preg_match_all('@ | ||
(\s*) | ||
/\* | ||
(.*?[^\*/]) | ||
\*+/ | ||
(\ {0,1}/\*\*/)? | ||
@ismx', $this->code['edited'], $comments)) { | ||
|
||
$new_comments = Array(); | ||
$old_comments = $comments[0]; | ||
|
||
foreach ($comments[2] as $key => $comment) { | ||
if ( // если комментарий содержит ; и : | ||
strpos($comment, ':') !== FALSE AND | ||
strpos($comment, ';') !== FALSE | ||
|
||
) { | ||
preg_match_all('@ | ||
(\s*) | ||
( | ||
.+?[^;] | ||
; | ||
) | ||
@ismx', $comment, $properties); | ||
|
||
$new_comment = ''; | ||
foreach ($properties[2] as $property) { | ||
$new_comment .= $comments[1][$key]."commented__".$property; | ||
} | ||
$new_comments[] = $new_comment; | ||
} | ||
else { | ||
// если нет : или ;, то считаем что это текстовый комментарий | ||
// и копируем его в том виде, в каком он был. | ||
$new_comments[] = $comments[0][$key]; | ||
} | ||
|
||
|
||
} | ||
|
||
foreach ($old_comments as $key => $old_comment) { | ||
$this->code['edited'] = str_replace( | ||
$old_comments[$key], | ||
$new_comments[$key], | ||
$this->code['edited']); | ||
} | ||
} | ||
|
||
// 7.2. Обрывки закомментированных деклараций: присутствует { или } | ||
if (preg_match_all('@ | ||
\s*? | ||
/\* | ||
( | ||
.*?[^\*/] | ||
)*? | ||
\*+/ | ||
@ismx', $this->code['edited'], $comments)) { | ||
|
||
$new_comments = Array(); | ||
$old_comments = $comments[0]; | ||
|
||
foreach ($comments[0] as $key => $comment) { | ||
if (strpos($comment, '}') !== FALSE OR strpos($comment, '{') !== FALSE) { | ||
$new_comment = ''; | ||
if (strpos($comment, '}') !== FALSE) { $new_comment .= '}'; } | ||
$new_comment .= "brace__".$key; | ||
if (strpos($comment, '{') !== FALSE) { $new_comment .= '{'; } | ||
$new_comments[$key] = $new_comment; | ||
$this->code['braces'][$key] = $comment; | ||
} | ||
} | ||
|
||
foreach ($new_comments as $key => $new_comment) { | ||
if (strlen($new_comment) > 0) { | ||
$this->code['edited'] = str_replace( | ||
$old_comments[$key], | ||
$new_comment, | ||
$this->code['edited']); | ||
} | ||
} | ||
} | ||
} | ||
|
||
// 8. Entities | ||
if (preg_match_all('@ | ||
|
@@ -1181,9 +1122,9 @@ function parse_child($value = '') { | |
|
||
// 2. Выносим переменные в отдельный массив $vars | ||
preg_match_all('@ | ||
(\s*/\*[^\*/]*?\*/)? | ||
(\s*//.*?)? | ||
(comment\d*__)* | ||
\s*(\$|\@)[^;\}]+?:[^;]+?; | ||
(inlinecomment\d*__)* | ||
@ismx', $value, $vars); | ||
// Удаляем их из общей строки | ||
foreach ($vars[0] as $var) { | ||
|
@@ -1195,29 +1136,32 @@ function parse_child($value = '') { | |
|
||
// Включения, следующие сразу за { | ||
preg_match_all('@ | ||
(^\s*\@[^;]+?[;])|(^\s*\.[^;:]+?[;]) | ||
(^\s*(comment\d*__)*\s*\@[^;]+?[;](inlinecomment\d*__)*) | ||
| | ||
(^\s*(comment\d*__)*\s*\.[^;:]+?[;](inlinecomment\d*__)*) | ||
@isx', $value, $first_imports); | ||
|
||
// Все остальные | ||
preg_match_all('@ | ||
(?<=[;}])(\s*\@[^;]+?[;])|(?<=[;}])(\s*\.[^;:]+?[;]) | ||
(?<=inlinecomment\d__|[;}]) | ||
((comment\d*__)?\s*\@[^;]+?[;](inlinecomment\d*__)?) | ||
| | ||
(?<=inlinecomment\d__|[;}]) | ||
((comment\d*__)?\s*\.[^;:]+?[;](inlinecomment\d*__)?) | ||
@ismx', $value, $imports); | ||
// Удаляем их из общей строки | ||
foreach ($first_imports[0] as &$first_import) { | ||
$value = str_replace($first_import, '', $value); | ||
} | ||
foreach ($imports[1] as &$import) { | ||
$value = str_replace($import, '', $value); | ||
} | ||
foreach ($imports[2] as &$import) { | ||
foreach ($imports[0] as &$import) { | ||
$value = str_replace($import, '', $value); | ||
} | ||
|
||
// 4. Выносим простые свойства в массив $properties | ||
preg_match_all('@ | ||
(comment\d*__)? | ||
\s*[^;]+?:[^;]+?; | ||
(\s*/\*.*?[^\*/]\*/)? | ||
(\s{0,1}/\*\*/)? | ||
(inlinecomment\d*__)? | ||
@ismx', $value, $properties); | ||
// Удаляем их из общей строки | ||
foreach ($properties[0] as &$property) { | ||
|
@@ -1227,11 +1171,9 @@ function parse_child($value = '') { | |
$props = $properties[0]; | ||
$props = $this->resort_properties($props); | ||
|
||
// 5. Если осталось ещё что-то, оставляем «как есть» | ||
|
||
// 6. Склеиваем всё обратно в следующем порядке: | ||
// переменные, включения, простые свойства, вложенные {} | ||
$value = implode('', $vars[0]).implode('', $first_imports[0]).implode('', $imports[1]).implode('', $imports[2]).implode('', $block_imports).implode('', $props).$nested_string.$value; | ||
$value = implode('', $vars[0]).implode('', $first_imports[0]).implode('', $imports[0]).implode('', $block_imports).implode('', $props).$nested_string.$value; | ||
return $value; | ||
} | ||
|
||
|
@@ -1252,7 +1194,6 @@ function parse_properties($css = '') { | |
^ | ||
(.*?) | ||
( | ||
#(\s*/\*.*\*/;)*? | ||
\s*? | ||
} | ||
) | ||
|
@@ -1303,17 +1244,15 @@ function parse_properties($css = '') { | |
^ | ||
(.*?) | ||
(\s*?) | ||
(/\* .* \*/) | ||
(inlinecomment\d*__) | ||
(.*) | ||
$ | ||
@ismx', $properties, $matches); | ||
|
||
if ( | ||
count($matches) === 5 and // все распарсилось как надо | ||
strlen($matches[1]) === 0 and // комментарий действительно идет первым | ||
strpos($matches[2], "\n") !== 0 // перед комментарием нет переноса строки, следовательно предпологаем, что он относится к скобке с селектором | ||
strlen($matches[1]) === 0 // комментарий действительно идет первым | ||
) { | ||
$first_spaces = $matches[2]; | ||
$first_comment = $matches[3]; | ||
|
@@ -1330,10 +1269,7 @@ function parse_properties($css = '') { | |
.[^;]* | ||
; | ||
( # На этой же строке (после ;) может быть комментарий. Он тоже пригодится. | ||
\s* | ||
/\* | ||
.*?[^\*/] | ||
\*/ | ||
inlinecomment\d*__ | ||
) | ||
? | ||
(\s{0,1}/\*\*/)? | ||
|
@@ -1361,8 +1297,7 @@ function parse_properties($css = '') { | |
.[^;]* # все что угодно, но не ; | ||
; | ||
( # На этой же строке (после ;) может быть комментарий. Он тоже пригодится. | ||
\s* | ||
/\* .* \*/ | ||
inlinecomment\d*__ | ||
) | ||
*? | ||
) | ||
|
@@ -1406,9 +1341,7 @@ function resort_properties($prop) { | |
* Пробел в начале добавляется специально, чтобы избежать совпадений по вхождению | ||
* одной строки в другую. Например: top не должно совпадать с border-top | ||
*/ | ||
strpos(' '.trim($property), ' '.$k.':') !== FALSE OR | ||
strpos(' '.trim($property), ' commented__'.$k.':') !== FALSE | ||
|
||
strpos(' '.trim($property), ' '.$k.':') !== FALSE | ||
) { | ||
$through_number = $this->get_through_number($k); // определяем "сквозной" порядковый номер | ||
if ($through_number !== false) $index = $through_number; | ||
|
@@ -1421,8 +1354,7 @@ function resort_properties($prop) { | |
foreach ($this->sort_order as $pos => $key) { | ||
if ( | ||
// пробел в начале добавляется специально. | ||
strpos(' '.trim($property), ' '.$key.':') !== FALSE OR | ||
strpos(' '.trim($property), ' commented__'.$key.':') !== FALSE | ||
strpos(' '.trim($property), ' '.$key.':') !== FALSE | ||
) { | ||
$index = $pos; | ||
} | ||
|
@@ -1506,26 +1438,34 @@ function postprocess() { | |
} | ||
|
||
// 4. Interpolated variables | ||
preg_match_all('#interpolation(\d)__#ismx', $this->code['resorted'], $new_vars); | ||
foreach ($new_vars[1] as $key => $value) { | ||
$this->code['resorted'] = str_replace($new_vars[0][$key], $this->code['interpolations'][0][$key], $this->code['resorted']); | ||
if (is_array($this->code['interpolations'])) { // если были обнаружены и вырезаны data uri | ||
foreach ($this->code['interpolations'] as $key => $val) { | ||
$this->code['resorted'] = str_replace('interpolation'.$key.'__', $val[0], $this->code['resorted']); // заменяем значение expression обратно | ||
} | ||
} | ||
// Magic comments | ||
if (is_array($this->code['magicComments'])) { | ||
foreach ($this->code['magicComments'] as $key => $val) { | ||
$this->code['resorted'] = str_replace("\nmagic: comment".$key.'__;', $val[0], $this->code['resorted']); | ||
} | ||
} | ||
|
||
// 5. Удаляем искусственно созданные 'commented__' | ||
while(strpos($this->code['resorted'], 'commented__') !== FALSE) { | ||
$this->code['resorted'] = preg_replace( | ||
'# | ||
commented__ | ||
(.*?[^:] | ||
: | ||
.*?[^;] | ||
;) | ||
#ismx', | ||
'/*$1*/', | ||
$this->code['resorted'] | ||
); | ||
|
||
// Comments | ||
if (is_array($this->code['inlinecomments'])) { // если были обнаружены и вырезаны data uri | ||
foreach ($this->code['inlinecomments'] as $key => $val) { | ||
$this->code['resorted'] = str_replace('inlinecomment'.$key.'__', $val[0], $this->code['resorted']); // заменяем значение expression обратно | ||
} | ||
} | ||
if (is_array($this->code['comments'])) { // если были обнаружены и вырезаны data uri | ||
foreach ($this->code['comments'] as $key => $val) { | ||
if (strpos($this->code['resorted'], 'comment'.$key.'__') > -1) { | ||
$this->code['resorted'] = str_replace('comment'.$key.'__', $val[0], $this->code['resorted']); // заменяем значение expression обратно | ||
} | ||
} | ||
} | ||
|
||
|
||
// 6. Удаляем искусственно созданные 'brace__' | ||
if (is_array($this->code['braces'])) { // если были обнаружены и вырезаны хаки | ||
foreach ($this->code['braces'] as $key => $val) { | ||
|
1b1116f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the Chocolat Mixin registry.
1b1116f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@drudge, thank you!