Commits

Jan-Jaap Driessen committed 3499c24

Add lesscss compiler based on node.js

  • Participants
  • Parent commits 6198143
  • Branches compilers-n-compressors

Comments (0)

Files changed (4)

   and the name of the compiler.In non-development mode, the filesystem is
   used to find a compiled version of a resource. 
 
-- Implemented a CoffeeScript and SCSS compiler. The optional dependencies
+- Implemented a CoffeeScript, LessCSS and SCSS compiler. The optional dependencies
   can be installed using the 'fanstatic[compilers]' requirement.
   Base functionality of these compilers is shared in a baseclass. 
   Compilers do not know about Resources or Library, only about filenames.

fanstatic/compiler.py

     def __call__(self, path):
         raise NotImplementedError
 
+class CoffeeScriptCompiler(CompilerBase):
+    source_extension = 'coffee'
+    target_extension = 'js'
+    name = 'coffeescript'
+
+    @staticmethod
+    def available():
+        try:
+            check = subprocess.check_call('which coffee', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        except subprocess.CalledProcessError:
+            return False
+        if check == 0:
+            return True
+        return False
+
+    def __call__(self, path):
+        cmd = 'coffee --bare --compile --print %s' % path
+        
+        p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        p.wait()
+        if p.returncode != 0:
+            raise CompilerException(p.stderr.read())
+
+        f = open(self.target_path(path), 'wb')
+        try:
+            f.write(p.stdout.read())
+        finally:
+            f.close()
+
+class LessCSSCompiler(CompilerBase):
+    source_extension = 'less'
+    target_extension = 'css'
+    name = 'lesscss'
+
+    @staticmethod
+    def available():
+        try:
+            check = subprocess.check_call('which lessc', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        except subprocess.CalledProcessError:
+            return False
+        if check == 0:
+            return True
+        return False
+
+    def __call__(self, path):
+        cmd = 'lessc %s' % path
+        
+        p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        p.wait()
+        if p.returncode != 0:
+            raise CompilerException(p.stderr.read())
+
+        f = open(self.target_path(path), 'wb')
+        try:
+            f.write(p.stdout.read())
+        finally:
+            f.close()
+
 try:
     import scss
 except ImportError:
     scss = None
 
-
 @contextmanager
 def stderr_redirect(stream):
    orig_err = sys.stderr
    finally:
        sys.stderr = orig_err
 
-
 class SCSSCompiler(CompilerBase):
     source_extension = 'scss'
     target_extension = 'css'
         finally:
             f.close()
 
-class CoffeeScriptCompiler(CompilerBase):
-    source_extension = 'coffee'
-    target_extension = 'js'
-    name = 'coffeescript'
-
-    @staticmethod
-    def available():
-        try:
-            check = subprocess.check_call('which coffee', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-        except subprocess.CalledProcessError:
-            return False
-        if check == 0:
-            return True
-        return False
-
-    def __call__(self, path):
-        cmd = 'coffee --bare --compile --print %s' % path
-        
-        p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-        p.wait()
-        if p.returncode != 0:
-            raise CompilerException(p.stderr.read())
-
-        f = open(self.target_path(path), 'wb')
-        try:
-            f.write(p.stdout.read())
-        finally:
-            f.close()

fanstatic/test_compile.py

 from fanstatic import Library, Resource, NeededResources, LibraryRegistry, Publisher
 from fanstatic.core import CompiledNotFoundError, TooManyCompiledFoundError
 from fanstatic.core import UnknownCompilerExtensionError
-from fanstatic.compiler import CompilerBase, CoffeeScriptCompiler, SCSSCompiler
-from fanstatic.compiler import CompilerException
+from fanstatic.compiler import CompilerBase, CompilerException
+from fanstatic.compiler import CoffeeScriptCompiler, LessCSSCompiler, SCSSCompiler
 import fanstatic.registry
 
 
 '''
 
 
+@pytest.mark.skipif('not LessCSSCompiler.available()')
+def test_lesscsscompiler(tmpdir):
+    style = tmpdir.join('style.less')
+    # from http://lesscss.org :
+    style.write('''\
+@color: #4D926F;
+
+#header {
+  color: @color;
+}
+h2 {
+  color: @color;
+}''')
+
+    compiler = LessCSSCompiler()
+    compiler(str(style))
+    assert open(compiler.target_path(str(style))).read() == '''\
+#header {
+  color: #4d926f;
+}
+h2 {
+  color: #4d926f;
+}
+'''
+    with_syntax_error = tmpdir.join('error.less')
+    with_syntax_error.write('.frop {')
+    # If the input is invalid, should raise a compiler error.
+    with pytest.raises(CompilerException):
+        compiler(str(with_syntax_error))
+
 @pytest.mark.skipif('not SCSSCompiler.available()')
 def test_scsscompiler(tmpdir):
     # from http://sass-lang.com/tutorial.html :
             'fanstatic = fanstatic.scripts:main',
             ],
         'fanstatic.compilers': [
+            'coffeescript = fanstatic.compiler:CoffeeScriptCompiler',
+            'lesscss = fanstatic.compiler:LessCSSCompiler',
             'scss = fanstatic.compiler:SCSSCompiler',
-            'coffeescript = fanstatic.compiler:CoffeeScriptCompiler',
             ],
     })