Commits

Gael Pasgrimaud committed d01f83f

Add LessResource. Self compiled resource using lessc

Comments (0)

Files changed (8)

 .installed.cfg
 *.egg-info
 *.pyc
+*.swp
 *~
 develop-eggs
 dist
+node_modules
+js/lesscss/resources/my.*
File contents unchanged.
 [buildout]
 develop = .
-parts = py.test
+parts = eggs
 
-[py.test]
+[eggs]
 recipe = z3c.recipe.scripts
-# Need exit status code for buildbot.
-# See https://bugs.launchpad.net/zc.buildout/+bug/164629
-script-initialization =
-  import pytest
-  if __name__ == '__main__': sys.exit(pytest.main())
 eggs = js.lesscss
-       pytest
+       nose

js/lesscss/__init__.py

+from fanstatic.core import register_inclusion_renderer
 from fanstatic import Library, Resource
+from os.path import isfile
+from os.path import join
+import subprocess
+import logging
+import shutil
+import os
+
+def render_less(url):
+    if url.endswith('.css'):
+        return ('<link rel="stylesheet" type="text/css" href="%s" />' % url)
+    else:
+        return ('<link rel="stylesheet" type="text/x-less" href="%s" />' % url)
+
+register_inclusion_renderer('.less', render_less, 25)
 
 library = Library('less', 'resources')
 
 lesscss_js = Resource(library, 'less.min.js', bottom=True)
 lesscss = lesscss_js
+
+class LessResource(Resource):
+
+    def __init__(self, library, relpath, **kwargs):
+        fullpath = os.path.join(library.path, relpath)
+        if 'LESSC' in os.environ:
+            lessc(fullpath)
+            depends = kwargs.get('depends', [])
+            if lesscss_js not in depends:
+                depends.insert(0, lesscss_js)
+            kwargs['depends'] = depends
+            kwargs['debug'] = relpath
+        else:
+            # avoid failure
+            fullpath += '.min.css'
+            if not isfile(fullpath):
+                fd = open(fullpath, 'w')
+                fd.write('// Not compiled yet\n')
+                fd.write('// set the LESSC environ variable ')
+                fd.write('to a valid lessc binary and relaunch your application\n')
+                fd.close()
+        relpath += '.min.css'
+        super(LessResource, self).__init__(library, relpath, **kwargs)
+
+def lessc(in_path, *args):
+
+    lessc = None
+    if 'LESSC' in os.environ:
+        lessc = os.environ['LESSC']
+    if lessc is None or not isfile(lessc):
+        for path in (('node_modules', os.path.expanduser('~/.node_modules'))):
+            path = os.path.join(path, 'less', 'bin', 'lessc')
+            if isfile(path):
+                lessc = path
+    if not lessc:
+        lessc = 'less'
+
+    args = list(args)
+    if not args:
+        args = ['-x']
+
+    cmd = [lessc]+list(args)+[in_path]
+    print cmd
+    p = subprocess.Popen(cmd,
+                         stdout=subprocess.PIPE,
+                         stderr=subprocess.PIPE)
+    p.wait()
+
+    err = p.stderr.read()
+    if err.strip():
+        msg = 'Error while compiling %s:\n%s' % (in_path, err)
+        raise RuntimeError(msg)
+
+    out_path = in_path + '.min.css'
+    fd = open(out_path, 'w')
+    shutil.copyfileobj(p.stdout, fd)
+    fd.close()
+    return out_path
+
+def main():
+    from optparse import OptionParser
+    parser = OptionParser()
+    options, args = parser.parse_args()
+
+    if not args:
+        args = ['.']
+
+    for arg in args:
+        for root, dirnames, filenames in os.walk(arg):
+            for filename in filenames:
+                if filename.endswith('.less'):
+                    in_path = os.path.join(root, filename)
+                    print in_path
+                    out_path = lessc(in_path, '-x')
+                    print in_path, '->' , out_path

js/lesscss/script.py

+# -*- coding: utf-8 -*-
+import subprocess
+import shutil
+import os
+

js/lesscss/tests.py

+# -*- coding: utf-8 -*-
+import os
+import sys
+from js.lesscss import library, LessResource
+from fanstatic.core import NeededResources
+
+stderr = sys.stderr
+
+def test_resource():
+
+    resource = LessResource(library, 'my.less')
+
+    if 'LESSC' not in os.environ:
+        stderr.write(('WARN: Please export a LESSC variable. '
+                      'Test skipped...'))
+        return
+
+    nr = NeededResources(resources=[resource], debug=True)
+    assert len(nr.resources()) > 1, nr.resources()
+    tag = nr.render()
+    assert 'less.min.js"' in tag, tag
+    assert 'type="text/x-less" href="/fanstatic/less/my.less"' in tag, tag
+
+    nr = NeededResources(resources=[resource], minified=True)
+    tag = nr.render()
+    assert 'less.min.js"' in tag, tag
+    assert 'type="text/css" href="/fanstatic/less/my.less.min.css"' in tag, tag
+
+    nr = NeededResources(resources=[resource])
+    tag = nr.render()
+    assert 'less.min.js"' in tag, tag
+    assert 'type="text/css" href="/fanstatic/less/my.less.min.css"' in tag, tag
+
+[nosetests]
+with-doctest=true
+doctest-extension=.txt
+verbosity=2
         'fanstatic.libraries': [
             'less = js.lesscss:library',
             ],
+        'console_scripts': [
+            'jslessc = js.lesscss:main',
+            ],
         },
     )