Browse Source

Added stylus plugin

main
Lakshmi Vyasarajan 14 years ago
parent
commit
b1c4c0cf08
10 changed files with 217 additions and 21 deletions
  1. +102
    -0
      hyde/ext/plugins/stylus.py
  2. +5
    -2
      hyde/plugin.py
  3. +18
    -0
      hyde/tests/ext/stylus/expected-site.css
  4. +4
    -0
      hyde/tests/ext/stylus/inc/mixin.styl
  5. +5
    -0
      hyde/tests/ext/stylus/inc/reset.css
  6. +2
    -0
      hyde/tests/ext/stylus/inc/vars.styl
  7. +14
    -0
      hyde/tests/ext/stylus/site.styl
  8. +17
    -17
      hyde/tests/ext/test_less.py
  9. +47
    -0
      hyde/tests/ext/test_stylus.py
  10. +3
    -2
      hyde/tests/ext/test_uglify.py

+ 102
- 0
hyde/ext/plugins/stylus.py View File

@@ -0,0 +1,102 @@
# -*- coding: utf-8 -*-
"""
Less css plugin
"""

from hyde.plugin import CLTransformer
from hyde.fs import File

import re
import subprocess


class StylusPlugin(CLTransformer):
"""
The plugin class for less css
"""

def __init__(self, site):
super(StylusPlugin, self).__init__(site)

def begin_text_resource(self, resource, text):
"""
Replace @import statements with {% include %} statements.
"""

if not resource.source_file.kind == 'styl':
return
import_finder = re.compile(
'^\\s*@import\s+(?:\'|\")([^\'\"]*)(?:\'|\")\s*\;?\s*$',
re.MULTILINE)

def import_to_include(match):
"""
Converts a css import statement to include statemnt.
"""
if not match.lastindex:
return ''
path = match.groups(1)[0]
afile = File(resource.source_file.parent.child(path))
if len(afile.kind.strip()) == 0:
afile = File(afile.path + '.styl')
ref = self.site.content.resource_from_path(afile.path)
if not ref:
raise self.template.exception_class(
"Cannot import from path [%s]" % afile.path)
ref.is_processable = False
return "\n" + \
self.template.get_include_statement(ref.relative_path) + \
"\n"

text = import_finder.sub(import_to_include, text)
return text

@property
def defaults(self):
"""
Returns `compress` if not in development mode.
"""
try:
mode = self.site.config.mode
except AttributeError:
mode = "production"

defaults = {"compress":""}
if mode.startswith('dev'):
defaults = {}
return defaults

@property
def plugin_name(self):
"""
The name of the plugin.
"""
return "stylus"

def text_resource_complete(self, resource, text):
"""
Save the file to a temporary place and run stylus compiler.
Read the generated file and return the text as output.
Set the target path to have a css extension.
"""
if not resource.source_file.kind == 'styl':
return
stylus = self.app
source = File.make_temp(text)
target = source
supported = [("compress", "C")]

args = [str(stylus)]
args.extend(self.process_args(supported))
args.append(str(source))
try:
self.call_app(args)
except subprocess.CalledProcessError:
raise self.template.exception_class(
"Cannot process %s. Error occurred when "
"processing [%s]" % (stylus.name, resource.source_file))
out = target.read_all()
new_name = resource.source_file.name_without_extension + ".css"
target_folder = File(resource.relative_path).parent
resource.relative_deploy_path = target_folder.child(new_name)
return out

+ 5
- 2
hyde/plugin.py View File

@@ -209,6 +209,7 @@ class CLTransformer(Plugin):


return self.__class__.__name__.replace('Plugin', '').lower() return self.__class__.__name__.replace('Plugin', '').lower()


@property
def defaults(self): def defaults(self):
""" """
Default command line options. Can be overridden Default command line options. Can be overridden
@@ -266,10 +267,12 @@ class CLTransformer(Plugin):
Given a list of supported arguments, consutructs an argument Given a list of supported arguments, consutructs an argument
list that could be passed on to the call_app function. list that could be passed on to the call_app function.
""" """
args = {}
args.update(self.defaults)
try: try:
args = getattr(self.settings, 'args').to_dict()
args.update(getattr(self.settings, 'args').to_dict())
except AttributeError: except AttributeError:
args = {}
pass


result = [] result = []
for arg in supported: for arg in supported:


+ 18
- 0
hyde/tests/ext/stylus/expected-site.css View File

@@ -0,0 +1,18 @@
* {
border: 0;
padding: 0;
margin: 0;
}
#header {
color: #333;
border-left: 1px;
border-right: 2px;
}
#footer {
color: #444;
}
#content {
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}

+ 4
- 0
hyde/tests/ext/stylus/inc/mixin.styl View File

@@ -0,0 +1,4 @@
rounded(radius = 5px)
-webkit-border-radius radius
-moz-border-radius radius
border-radius radius

+ 5
- 0
hyde/tests/ext/stylus/inc/reset.css View File

@@ -0,0 +1,5 @@
* {
border: 0;
padding: 0;
margin: 0;
}

+ 2
- 0
hyde/tests/ext/stylus/inc/vars.styl View File

@@ -0,0 +1,2 @@
the-border = 1px
base-color = #111

+ 14
- 0
hyde/tests/ext/stylus/site.styl View File

@@ -0,0 +1,14 @@
@import "inc/mixin"
@import "inc/vars"
@import "inc/reset.css"

#header
color base-color * 3
border-left the-border
border-right the-border * 2

#footer
color (base-color + #111) * 1.5

#content
rounded 10px

+ 17
- 17
hyde/tests/ext/test_less.py View File

@@ -29,20 +29,20 @@ class TestLess(object):
def test_can_execute_less(self): def test_can_execute_less(self):
s = Site(TEST_SITE) s = Site(TEST_SITE)
s.config.plugins = ['hyde.ext.plugins.less.LessCSSPlugin'] s.config.plugins = ['hyde.ext.plugins.less.LessCSSPlugin']
less_paths = ['/usr/local/share/npm/bin/lessc', '~/local/bin/lessc']
for path in less_paths:
if File(path).exists:
s.config.less = Expando(dict(app=path))
source = TEST_SITE.child('content/media/css/site.less')
target = File(Folder(s.config.deploy_root_path).child('media/css/site.css'))
gen = Generator(s)
gen.generate_resource_at_path(source)
assert target.exists
text = target.read_all()
expected_text = File(LESS_SOURCE.child('expected-site.css')).read_all()
assert text == expected_text
return
assert "Cannot find the less css executable"
paths = ['/usr/local/share/npm/bin/lessc', '~/local/bin/lessc']
less = [path for path in paths if File(path).exists]
if not less:
assert False, "Cannot find the uglify executable"
less = less[0]
s.config.less = Expando(dict(app=less))
source = TEST_SITE.child('content/media/css/site.less')
target = File(Folder(s.config.deploy_root_path).child('media/css/site.css'))
gen = Generator(s)
gen.generate_resource_at_path(source)
assert target.exists
text = target.read_all()
expected_text = File(LESS_SOURCE.child('expected-site.css')).read_all()
assert text == expected_text
return

+ 47
- 0
hyde/tests/ext/test_stylus.py View File

@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
"""
Use nose
`$ pip install nose`
`$ nosetests`
"""
from hyde.fs import File, Folder
from hyde.model import Expando
from hyde.generator import Generator
from hyde.site import Site

STYLUS_SOURCE = File(__file__).parent.child_folder('stylus')
TEST_SITE = File(__file__).parent.parent.child_folder('_test')


class TestLess(object):

def setUp(self):
TEST_SITE.make()
TEST_SITE.parent.child_folder(
'sites/test_jinja').copy_contents_to(TEST_SITE)
STYLUS_SOURCE.copy_contents_to(TEST_SITE.child('content/media/css'))
File(TEST_SITE.child('content/media/css/site.css')).delete()


def tearDown(self):
TEST_SITE.delete()

def test_can_execute_stylus(self):
s = Site(TEST_SITE)
s.config.plugins = ['hyde.ext.plugins.stylus.StylusPlugin']
paths = ['/usr/local/share/npm/bin/stylus', '~/local/bin/stylus']
stylus = [path for path in paths if File(path).exists]
if not stylus:
assert False, "Cannot find the stylus executable"

stylus = stylus[0]
s.config.stylus = Expando(dict(app=stylus))
source = TEST_SITE.child('content/media/css/site.styl')
target = File(Folder(s.config.deploy_root_path).child('media/css/site.css'))
gen = Generator(s)
gen.generate_resource_at_path(source)

assert target.exists
text = target.read_all()
expected_text = File(STYLUS_SOURCE.child('expected-site.css')).read_all()
assert text.strip() == expected_text.strip()

+ 3
- 2
hyde/tests/ext/test_uglify.py View File

@@ -22,6 +22,7 @@ class TestLess(object):
JS = TEST_SITE.child_folder('content/media/js') JS = TEST_SITE.child_folder('content/media/js')
JS.make() JS.make()
UGLIFY_SOURCE.copy_contents_to(JS) UGLIFY_SOURCE.copy_contents_to(JS)


def tearDown(self): def tearDown(self):
TEST_SITE.delete() TEST_SITE.delete()
@@ -36,7 +37,7 @@ class TestLess(object):
assert False, "Cannot find the uglify executable" assert False, "Cannot find the uglify executable"


uglify = uglify[0] uglify = uglify[0]
s.config.uglify = Expando(dict(app=path))
s.config.uglify = Expando(dict(app=uglify))
source = TEST_SITE.child('content/media/js/jquery.js') source = TEST_SITE.child('content/media/js/jquery.js')
target = File(Folder(s.config.deploy_root_path).child('media/js/jquery.js')) target = File(Folder(s.config.deploy_root_path).child('media/js/jquery.js'))
gen = Generator(s) gen = Generator(s)
@@ -57,7 +58,7 @@ class TestLess(object):
assert False, "Cannot find the uglify executable" assert False, "Cannot find the uglify executable"


uglify = uglify[0] uglify = uglify[0]
s.config.uglify = Expando(dict(app=path, args={"nc":""}))
s.config.uglify = Expando(dict(app=uglify, args={"nc":""}))
source = TEST_SITE.child('content/media/js/jquery.js') source = TEST_SITE.child('content/media/js/jquery.js')
target = File(Folder(s.config.deploy_root_path).child('media/js/jquery.js')) target = File(Folder(s.config.deploy_root_path).child('media/js/jquery.js'))
gen = Generator(s) gen = Generator(s)


Loading…
Cancel
Save