From 5f5982130c1a9b9adb0e294b811327ddcfbd4fef Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Tue, 5 Nov 2013 20:09:45 +0000 Subject: Improve css_loadfile() tests - use TMP_DIR constant rather than /tmp - swap order of parameters in csstest() to match reported 'expected' & 'actual' - add tests for use of 'url()' in @import - add tests for @import of '.less' files (these test will fail per FS#2875) --- _test/tests/lib/exe/css_css_loadfile.test.php | 33 +++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/_test/tests/lib/exe/css_css_loadfile.test.php b/_test/tests/lib/exe/css_css_loadfile.test.php index c89b69b2c..0aa27b0af 100644 --- a/_test/tests/lib/exe/css_css_loadfile.test.php +++ b/_test/tests/lib/exe/css_css_loadfile.test.php @@ -3,13 +3,16 @@ require_once DOKU_INC.'lib/exe/css.php'; class css_css_loadfile_test extends DokuWikiTest { + + protected $file = ''; + public function setUp() { - $this->file = tempnam('/tmp', 'css'); + $this->file = tempnam(TMP_DIR, 'css'); } private function csstest($input, $output = null, $location = 'http://www.example.com/') { io_saveFile($this->file, $input); - $this->assertEquals(css_loadfile($this->file, $location), (is_null($output) ? $input : $output)); + $this->assertEquals((is_null($output) ? $input : $output), css_loadfile($this->file, $location)); } public function test_url_relative() { @@ -32,11 +35,15 @@ class css_css_loadfile_test extends DokuWikiTest { public function test_import_relative() { $this->csstest('@import "test/test.png";', '@import "http://www.example.com/test/test.png";'); $this->csstest('@import \'test/test.png\';', '@import \'http://www.example.com/test/test.png\';'); + $this->csstest('@import url(test/test.png);', '@import url(http://www.example.com/test/test.png);'); + $this->csstest('@import url("test/test.png");', '@import url("http://www.example.com/test/test.png");'); } public function test_import_absolute() { $this->csstest('@import "/test/test.png";'); $this->csstest('@import \'/test/test.png\';'); + $this->csstest('@import url(/test/test.png);'); + $this->csstest('@import url("/test/test.png");'); } public function test_import_with_protocol() { @@ -44,6 +51,28 @@ class css_css_loadfile_test extends DokuWikiTest { $this->csstest('@import "https://www.test.com/test/test.png";'); $this->csstest('@import \'http://www.test.com/test/test.png\';'); $this->csstest('@import \'https://www.test.com/test/test.png\';'); + $this->csstest('@import url(http://www.test.com/test/test.png);'); + $this->csstest('@import url("http://www.test.com/test/test.png");'); + } + + public function test_less_basic() { + $this->csstest('@import "test.less"', '@import "/test.less"'); + $this->csstest('@import "/test.less"', '@import "/test.less"'); + $this->csstest('@import url(http://test.less)'); + } + + // more expected use, where less @import(ed) from e.g. lib/plugins/plugin_name + public function test_less_subdirectories() { + + unlink($this->file); + + $dir = TMP_DIR.'/foo/bar'; + mkdir($dir,0777,true); + $this->file = tempnam($dir, 'css'); + + $this->csstest('@import "test.less"', '@import "/foo/bar/test.less"'); + $this->csstest('@import \'test.less\'', '@import \'/foo/bar/test.less\''); + $this->csstest('@import url(test.less)', '@import url(/foo/bar/test.less)'); } public function tearDown() { -- cgit v1.2.3 From 30f686eb67205a1da8765c992e2f9ee1a158c712 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Tue, 5 Nov 2013 20:15:00 +0000 Subject: add DOKU_INC to less import directories --- lib/exe/css.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/exe/css.php b/lib/exe/css.php index f0bd24b43..bc0645400 100644 --- a/lib/exe/css.php +++ b/lib/exe/css.php @@ -173,6 +173,12 @@ function css_out(){ */ function css_parseless($css) { $less = new lessc(); + $less->importDir[] = DOKU_INC; + + if (defined('DOKU_UNITTEST')){ + $less->importDir[] = TMP_DIR; + } + try { return $less->compile($css); } catch(Exception $e) { -- cgit v1.2.3 From de737055c55e54246de5000d601a089328c1af1c Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Tue, 5 Nov 2013 20:15:39 +0000 Subject: update url/file rewriting in css_loadfile() to support @import of less files --- lib/exe/css.php | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/lib/exe/css.php b/lib/exe/css.php index bc0645400..3929b2d4b 100644 --- a/lib/exe/css.php +++ b/lib/exe/css.php @@ -403,12 +403,38 @@ function css_loadfile($file,$location=''){ $css = io_readFile($file); if(!$location) return $css; - $css = preg_replace('#(url\([ \'"]*)(?!/|data:|http://|https://| |\'|")#','\\1'.$location,$css); - $css = preg_replace('#(@import\s+[\'"])(?!/|data:|http://|https://)#', '\\1'.$location, $css); + global $css_location; + global $css_current_dir; + $css_current_dir = preg_replace('#^('.DOKU_INC.(defined('DOKU_UNITTEST')?'|'.realpath(TMP_DIR) : '').')#','',dirname($file)).'/'; + $css_location = $location; + + $css = preg_replace_callback('#(url\( *)([\'"]?)(.*?)(\2)( *\))#','css_loadfile_callback',$css); + $css = preg_replace_callback('#(@import\s+)([\'"])(.*?)(\2)#','css_loadfile_callback',$css); +# $css = preg_replace_callback('#(url\([ \'"]*)(?!/|data:|http://|https://| |\'|")#','\\1'.$location,$css); +# $css = preg_replace_callback('#(@import\s+[\'"])(?!/|data:|http://|https://)#', '\\1'.$location, $css); return $css; } +function css_loadfile_callback($match){ + global $css_location; + global $css_current_dir; + + if (preg_match('#^(/|data:|https?://)#',$match[3])) { + return $match[0]; + } + else if (substr($match[3],-5) == '.less') { + if ($match[3]{0} != '/') { + $match[3] = $css_current_dir . $match[3]; + } + } + else { + $match[3] = $css_location . $match[3]; + } + + return join('',array_slice($match,1)); +} + /** * Converte local image URLs to data URLs if the filesize is small * -- cgit v1.2.3 From 6d7e4640bed01599dac4bbf5c00b0aff8d3dd4ba Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Tue, 5 Nov 2013 20:49:53 +0000 Subject: additional tests where for relative path to @import less file --- _test/tests/lib/exe/css_css_loadfile.test.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/_test/tests/lib/exe/css_css_loadfile.test.php b/_test/tests/lib/exe/css_css_loadfile.test.php index 0aa27b0af..c336702f8 100644 --- a/_test/tests/lib/exe/css_css_loadfile.test.php +++ b/_test/tests/lib/exe/css_css_loadfile.test.php @@ -58,6 +58,7 @@ class css_css_loadfile_test extends DokuWikiTest { public function test_less_basic() { $this->csstest('@import "test.less"', '@import "/test.less"'); $this->csstest('@import "/test.less"', '@import "/test.less"'); + $this->csstest('@import "foo/test.less"', '@import "/foo/test.less"'); $this->csstest('@import url(http://test.less)'); } @@ -73,6 +74,8 @@ class css_css_loadfile_test extends DokuWikiTest { $this->csstest('@import "test.less"', '@import "/foo/bar/test.less"'); $this->csstest('@import \'test.less\'', '@import \'/foo/bar/test.less\''); $this->csstest('@import url(test.less)', '@import url(/foo/bar/test.less)'); + + $this->csstest('@import "abc/test.less"', '@import "/foo/bar/abc/test.less"'); } public function tearDown() { -- cgit v1.2.3 From ab1fef6644927b857c64c9c153915d50ef2607f1 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Tue, 5 Nov 2013 20:51:07 +0000 Subject: Test to ensure less can parse the @import rewritten by css_loadfile() This test is horrible, but I believe necessary to ensure that the @import of less files actually works. It is horrible as its not a unit test and its not a true functional test. It probably implies the code in css_out() should be refactored to make it easier to test intermediate results. --- _test/tests/lib/exe/css_at_import_less.test.php | 78 +++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 _test/tests/lib/exe/css_at_import_less.test.php diff --git a/_test/tests/lib/exe/css_at_import_less.test.php b/_test/tests/lib/exe/css_at_import_less.test.php new file mode 100644 index 000000000..4a6efcf44 --- /dev/null +++ b/_test/tests/lib/exe/css_at_import_less.test.php @@ -0,0 +1,78 @@ +markTestSkipped('Could not create directory.'); + } + + $this->file = tempnam($dir, 'css'); + + $import = ''; + do { + if ($import) unlink($import); + $import = tempnam($dir, 'less'); + $ok = rename($import, $import.'.less'); + } while (!$ok); + + $this->import = $import.'.less'; + } + + private function csstest($input, $expected_css, $expected_less) { + $location = "http://test.com/"; + io_saveFile($this->file, $input); + $css = css_loadfile($this->file, $location); + $less = css_parseless($css); + $this->assertEquals($expected_css, $css); + $this->assertEquals($expected_less, $less); + } + + public function test_basic() { + $this->setUpFiles(); + + $import = preg_replace('#(^.*[/])#','',$this->import); + $in_css = '@import "'.$import.'";'; + $in_less = '@foo: "bar"; +content: @foo;'; + + $expected_css = '@import "/'.$import.'";'; + $expected_less = 'content: "bar";'; + + io_saveFile($this->import, $in_less); + $this->csstest($in_css, $expected_css, $expected_less); + } + + public function test_subdirectory() { + $this->setUpFiles('/foo/bar'); + + $import = preg_replace('#(^.*[/])#','',$this->import); + $in_css = '@import "'.$import.'";'; + $in_less = '@foo: "bar"; +content: @foo;'; + + $expected_css = '@import "/foo/bar/'.$import.'";'; + $expected_less = 'content: "bar";'; + + io_saveFile($this->import, $in_less); + $this->csstest($in_css, $expected_css, $expected_less); + } + + public function tearDown() { + unlink($this->file); + unlink($this->import); + unset($this->file, $this->import); + } +} + +//Setup VIM: ex: et ts=4 sw=4 : -- cgit v1.2.3 From 4eb5f931edaaabdd436f4c2802d0d293f8ef76cd Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Mon, 11 Nov 2013 22:03:58 +0000 Subject: fix sp. in comment --- lib/exe/css.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/exe/css.php b/lib/exe/css.php index 3929b2d4b..948251440 100644 --- a/lib/exe/css.php +++ b/lib/exe/css.php @@ -436,7 +436,7 @@ function css_loadfile_callback($match){ } /** - * Converte local image URLs to data URLs if the filesize is small + * Convert local image URLs to data URLs if the filesize is small * * Callback for preg_replace_callback */ -- cgit v1.2.3 From 12ffbbc324be1f06ccfcff580f512990dca929b8 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Mon, 11 Nov 2013 22:31:28 +0000 Subject: refactor to improve elegance --- lib/exe/css.php | 75 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 25 deletions(-) diff --git a/lib/exe/css.php b/lib/exe/css.php index 948251440..9cde09545 100644 --- a/lib/exe/css.php +++ b/lib/exe/css.php @@ -399,40 +399,65 @@ function css_filetypes(){ * given location prefix */ function css_loadfile($file,$location=''){ - if(!@file_exists($file)) return ''; - $css = io_readFile($file); - if(!$location) return $css; + $css_file = new DokuCssFile($file); + return $css_file->load($location); +} - global $css_location; - global $css_current_dir; - $css_current_dir = preg_replace('#^('.DOKU_INC.(defined('DOKU_UNITTEST')?'|'.realpath(TMP_DIR) : '').')#','',dirname($file)).'/'; - $css_location = $location; +class DokuCssFile { - $css = preg_replace_callback('#(url\( *)([\'"]?)(.*?)(\2)( *\))#','css_loadfile_callback',$css); - $css = preg_replace_callback('#(@import\s+)([\'"])(.*?)(\2)#','css_loadfile_callback',$css); -# $css = preg_replace_callback('#(url\([ \'"]*)(?!/|data:|http://|https://| |\'|")#','\\1'.$location,$css); -# $css = preg_replace_callback('#(@import\s+[\'"])(?!/|data:|http://|https://)#', '\\1'.$location, $css); + protected $filepath; + protected $location; + private $relative_path = null; - return $css; -} + public function __construct($file) { + $this->filepath = $file; + } + + public function load($location='') { + if (!@file_exists($this->filepath)) return ''; -function css_loadfile_callback($match){ - global $css_location; - global $css_current_dir; + $css = io_readFile($this->filepath); + if (!$location) return $css; - if (preg_match('#^(/|data:|https?://)#',$match[3])) { - return $match[0]; + $this->location = $location; + + $css = preg_replace_callback('#(url\( *)([\'"]?)(.*?)(\2)( *\))#',array($this,'replacements'),$css); + $css = preg_replace_callback('#(@import\s+)([\'"])(.*?)(\2)#',array($this,'replacements'),$css); + + return $css; } - else if (substr($match[3],-5) == '.less') { - if ($match[3]{0} != '/') { - $match[3] = $css_current_dir . $match[3]; + + private function getRelativePath(){ + + if (is_null($this->relative_path)) { + $basedir = array(DOKU_INC); + if (defined('DOKU_UNITTEST')) { + $basedir[] = realpath(TMP_DIR); + } + $regex = '#^('.join('|',$basedir).')#'; + + $this->relative_path = preg_replace($regex, '', dirname($this->filepath)); } + + return $this->relative_path; } - else { - $match[3] = $css_location . $match[3]; - } - return join('',array_slice($match,1)); + public function replacements($match) { + + if (preg_match('#^(/|data:|https?://)#',$match[3])) { + return $match[0]; + } + else if (substr($match[3],-5) == '.less') { + if ($match[3]{0} != '/') { + $match[3] = $this->getRelativePath() . '/' . $match[3]; + } + } + else { + $match[3] = $this->location . $match[3]; + } + + return join('',array_slice($match,1)); + } } /** -- cgit v1.2.3