diff --git a/common/framework/formatter.php b/common/framework/formatter.php index 1e9c2857a..8bda5dbe0 100644 --- a/common/framework/formatter.php +++ b/common/framework/formatter.php @@ -337,9 +337,109 @@ class Formatter { $content = "@media $media {\n\n$content\n\n}"; } - $result .= trim($content) . "\n\n"; + $original_filename = starts_with(\RX_BASEDIR, $filename) ? substr($filename, strlen(\RX_BASEDIR)) : $filename; + $result .= '/* Original file: ' . $original_filename . ' */' . "\n\n" . trim($content) . "\n\n"; } return $result; } + + /** + * JS concatenation subroutine. + * + * @param string|array $source_filename + * @param string $target_filename + * @return string + */ + public static function concatJS($source_filename, $target_filename) + { + $result = ''; + + if (!is_array($source_filename)) + { + $source_filename = array($source_filename); + } + foreach ($source_filename as $filename) + { + if (is_array($filename) && count($filename) >= 2) + { + list($filename, $targetie) = $filename; + } + else + { + $targetie = null; + } + $content = utf8_clean(file_get_contents($filename)); + if ($targetie !== null) + { + $content = 'if (' . self::convertIECondition($targetie) . ') {' . "\n\n" . $content . "\n\n" . '}'; + } + $original_filename = starts_with(\RX_BASEDIR, $filename) ? substr($filename, strlen(\RX_BASEDIR)) : $filename; + $result .= '/* Original file: ' . $original_filename . ' */' . "\n\n" . trim($content) . "\n\n"; + } + + return $result; + } + + /** + * Convert IE conditional comments to JS conditions. + * + * @param string $condition + * @return string + */ + public static function convertIECondition($condition) + { + $conversions = array( + '/^true$/i' => 'true', + '/^false$/i' => 'false', + '/^IE$/i' => 'window.navigator.userAgent.match(/MSIE\s/)', + '/^IE\s*(\d+)$/i' => '(/MSIE (\d+)/.exec(window.navigator.userAgent) && /MSIE (\d+)/.exec(window.navigator.userAgent)[1] == %d)', + '/^gt IE\s*(\d+)$/i' => '(/MSIE (\d+)/.exec(window.navigator.userAgent) && /MSIE (\d+)/.exec(window.navigator.userAgent)[1] > %d)', + '/^gte IE\s*(\d+)$/i' => '(/MSIE (\d+)/.exec(window.navigator.userAgent) && /MSIE (\d+)/.exec(window.navigator.userAgent)[1] >= %d)', + '/^lt IE\s*(\d+)$/i' => '(/MSIE (\d+)/.exec(window.navigator.userAgent) && /MSIE (\d+)/.exec(window.navigator.userAgent)[1] < %d)', + '/^lte IE\s*(\d+)$/i' => '(/MSIE (\d+)/.exec(window.navigator.userAgent) && /MSIE (\d+)/.exec(window.navigator.userAgent)[1] <= %d)', + ); + + $result = array(); + $conditions = preg_split('/([\&\|])/', $condition, -1, \PREG_SPLIT_NO_EMPTY | \PREG_SPLIT_DELIM_CAPTURE); + foreach ($conditions as $condition) + { + $condition = trim(preg_replace('/[\(\)]/', '', $condition)); + if ($condition === '') + { + continue; + } + + if ($condition === '&' || $condition === '|') + { + $result[] = $condition . $condition; + continue; + } + + $negation = $condition[0] === '!'; + if ($negation) + { + $condition = trim(substr($condition, 1)); + } + + foreach ($conversions as $regexp => $replacement) + { + if (preg_match($regexp, $condition, $matches)) + { + if (count($matches) > 1) + { + array_shift($matches); + $result[] = ($negation ? '!' : '') . vsprintf($replacement, $matches); + } + else + { + $result[] = ($negation ? '!' : '') . $replacement; + } + break; + } + } + } + + return count($result) ? implode(' ', $result) : 'false'; + } } diff --git a/tests/_data/formatter/scss.target1.css b/tests/_data/formatter/scss.target1.css index 8e961b07d..2d78eacef 100644 --- a/tests/_data/formatter/scss.target1.css +++ b/tests/_data/formatter/scss.target1.css @@ -1,4 +1,6 @@ @charset "UTF-8"; +/* Original file: tests/_data/formatter/scss.source1.scss */ +/* Original file: tests/_data/formatter/scss.source2.scss */ .rhymix { color: #123456; background: url("../_data/formatter/foo/bar.jpg"); diff --git a/tests/unit/framework/FormatterTest.php b/tests/unit/framework/FormatterTest.php index b90d16fb4..8c034b6a4 100644 --- a/tests/unit/framework/FormatterTest.php +++ b/tests/unit/framework/FormatterTest.php @@ -131,4 +131,33 @@ class FormatterTest extends \Codeception\TestCase\Test unlink($test_target); } + + public function testConvertIECondition() + { + $this->assertEquals('window.navigator.userAgent.match(/MSIE\s/)', Rhymix\Framework\Formatter::convertIECondition('IE')); + $this->assertEquals('!window.navigator.userAgent.match(/MSIE\s/)', Rhymix\Framework\Formatter::convertIECondition('!IE')); + $this->assertEquals('!window.navigator.userAgent.match(/MSIE\s/)', Rhymix\Framework\Formatter::convertIECondition('!(IE)')); + $this->assertEquals('true && false', Rhymix\Framework\Formatter::convertIECondition('true&false')); + $this->assertEquals('false', Rhymix\Framework\Formatter::convertIECondition('gobbledygook')); + + $source = 'gt IE 7'; + $target = '(/MSIE (\d+)/.exec(window.navigator.userAgent) && /MSIE (\d+)/.exec(window.navigator.userAgent)[1] > 7)'; + $this->assertEquals($target, Rhymix\Framework\Formatter::convertIECondition($source)); + + $source = 'lte IE 8'; + $target = '(/MSIE (\d+)/.exec(window.navigator.userAgent) && /MSIE (\d+)/.exec(window.navigator.userAgent)[1] <= 8)'; + $this->assertEquals($target, Rhymix\Framework\Formatter::convertIECondition($source)); + + $source = '(gte IE 6) & (lt IE 8)'; + $target = '(/MSIE (\d+)/.exec(window.navigator.userAgent) && /MSIE (\d+)/.exec(window.navigator.userAgent)[1] >= 6) && (/MSIE (\d+)/.exec(window.navigator.userAgent) && /MSIE (\d+)/.exec(window.navigator.userAgent)[1] < 8)'; + $this->assertEquals($target, Rhymix\Framework\Formatter::convertIECondition($source)); + + $source = '!(gt IE 9)'; + $target = '!(/MSIE (\d+)/.exec(window.navigator.userAgent) && /MSIE (\d+)/.exec(window.navigator.userAgent)[1] > 9)'; + $this->assertEquals($target, Rhymix\Framework\Formatter::convertIECondition($source)); + + $source = '!lt IE 8|lt IE 6'; + $target = '!(/MSIE (\d+)/.exec(window.navigator.userAgent) && /MSIE (\d+)/.exec(window.navigator.userAgent)[1] < 8) || (/MSIE (\d+)/.exec(window.navigator.userAgent) && /MSIE (\d+)/.exec(window.navigator.userAgent)[1] < 6)'; + $this->assertEquals($target, Rhymix\Framework\Formatter::convertIECondition($source)); + } }