diff --git a/.gitignore b/.gitignore index c49ca6eb..7d30ec59 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,9 @@ +*~ +.*.swp *.pyc *.pyo *.so *.o +*.egg-info/ +build/ +dist/ diff --git a/CHANGELOG b/CHANGELOG index 2333b775..9b740090 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,6 +5,13 @@ Changelog + Added ``--debug-info`` command line option (for *FireSass* output). + Added compass helper function ``reject()``. + Added ``undefined`` keyword for undefined variables. + + Added function ``index()``. + + Fixed ``append()`` and ``join()`` when called with a separator. + + Fixed incorrect exception when a file is not found. + + Fixed incorrect exceptions when a token is not in the expected number format. + + Fix parsing of gradients. + + Fix bug in the ``-compass-list()`` function. + + Show a better error if no color stops given to ``*-gradient`` functions. 1.1.3 Jan 9, 2012 + Support for the new Sass 3.2.0 features (``@content`` and placeholder selectors) diff --git a/README.rst b/README.rst index 0475cd6a..56e5abc9 100644 --- a/README.rst +++ b/README.rst @@ -357,6 +357,13 @@ Changelog + Added ``--debug-info`` command line option (for *FireSass* output). + Added compass helper function ``reject()``. + Added ``undefined`` keyword for undefined variables. + + Added function ``index()``. + + Fixed ``append()`` and ``join()`` when called with a separator. + + Fixed incorrect exception when a file is not found. + + Fixed incorrect exceptions when a token is not in the expected number format. + + Fix parsing of gradients. + + Fix bug in the ``-compass-list()`` function. + + Show a better error if no color stops given to ``*-gradient`` functions. 1.1.3 Jan 9, 2012 + Support for the new Sass 3.2.0 features (``@content`` and placeholder selectors) diff --git a/pyScss.egg-info/PKG-INFO b/pyScss.egg-info/PKG-INFO deleted file mode 100644 index 49f191c9..00000000 --- a/pyScss.egg-info/PKG-INFO +++ /dev/null @@ -1,314 +0,0 @@ -Metadata-Version: 1.0 -Name: pyScss -Version: 1.1.3 -Summary: pyScss, a Scss compiler for Python -Home-page: http://github.com/Kronuz/pyScss -Author: German M. Bravo (Kronuz) -Author-email: german.mb@gmail.com -License: MIT -Download-URL: http://github.com/Kronuz/pyScss/tarball/v1.1.3 -Description: pyScss, a Scss compiler for Python - ================================== - :Author: - German M. Bravo (Kronuz) - - About - ===== - pyScss compiles Scss (Sass), a superset of CSS that is more powerful, elegant - and easier to maintain than plain-vanilla CSS. The library acts as a CSS source - code preprocesor which allows you to use variables, nested rules, mixins, and - have inheritance of rules, all with a CSS-compatible syntax which the - preprocessor then compiles to standard CSS. - - Scss, as an extension of CSS, helps keep large stylesheets well-organized. It - borrows concepts and functionality from projects such as OOCSS and other similar - frameworks like as Sass. It's build on top of the original PHP xCSS codebase - structure but it's been completely rewritten, many bugs have been fixed and it - has been extensively extended to support almost the full range of Sass' Scss - syntax and functionality. - - .. image:: http://pledgie.com/campaigns/16513.png?skin_name=chrome - :alt: Click here to lend your support to pyScss and make a donation at pledgie.com! - :target: http://pledgie.com/campaigns/16513 - - Support - ======== - pyScss is fully compatible with SCSS (Sass) 3.2 ...it has: - - * **Compass**: Compass 0.11 Support - * **Nested rules** - * **Keyword arguments** - * **Mixins**: `@mixin`, `@include` - * **Functions**: `@function`, `@return` - * **Inheritance**: `@extend` - * **Conditions**: `@if`, `@else if`, `@else` - * **Loops**: `@for`, `@each` - * **Variables**: `$`, `@variables`, `@vars` - * **Sprites**: `sprite-map()`, `sprite()`, `sprite-position()`, `sprite-url()`, ... - * **Images**: `image-url()`, `image-width()`, `image-height()`, ... - * **Embedded (inline) images**: `inline-image()` - * **Colors handling**: `adjust-color()`, `scale-color()`, `opacify()`/`transparentize()`, `lighten()`/`darken()`, `mix()`, ... - * **Math functions**: `sin()`, `cos()`, `tan()`, `round()`, `ceil()`, `floor()`, `pi()`, ... - * **CSS Compression**: `@option compress:yes;` - - Requirements - ============ - * python >= 2.5 - - Installation - ============ - pyScss should be installed using pip or setuptools:: - - pip install pyScss - - easy_install pyScss - - Usage - ===== - Usage example:: - - from scss import Scss - css = Scss() - css.compile("a { color: red + green; }") - - Or compile from the command line:: - - python scss.py < file.scss - - Interactive mode:: - - python scss.py --interactive - - Examples - ======== - #. **Nested Rules** - Example:: - - @option compress: no; - .selector { - a { - display: block; - } - strong { - color: blue; - } - } - - ...produces:: - - .selector a { - display: block; - } - .selector strong { - color: #00f; - } - - #. **Variables** - Example:: - - @option compress: no; - $main-color: #ce4dd6; - $style: solid; - $side: bottom; - #navbar { - border-#{$side}: { - color: $main-color; - style: $style; - } - } - - ...produces:: - - #navbar { - border-bottom-color: #ce4dd6; - border-bottom-style: solid; - } - - #. **Mixins** - Example:: - - @option compress: no; - @mixin rounded($side, $radius: 10px) { - border-#{$side}-radius: $radius; - -moz-border-radius-#{$side}: $radius; - -webkit-border-#{$side}-radius: $radius; - } - #navbar li { @include rounded(top); } - #footer { @include rounded(top, 5px); } - #sidebar { @include rounded(left, 8px); } - - ...produces:: - - #navbar li { - border-top-radius: 10px; - -moz-border-radius-top: 10px; - -webkit-border-top-radius: 10px; - } - #footer { - border-top-radius: 5px; - -moz-border-radius-top: 5px; - -webkit-border-top-radius: 5px; - } - #sidebar { - border-left-radius: 8px; - -moz-border-radius-left: 8px; - -webkit-border-left-radius: 8px; - } - - #. **Extend** (using `@extend`) - Example:: - - @option compress: no; - .error { - border: 1px #f00; - background-color: #fdd; - } - .error.intrusion { - background-image: url("/image/hacked.png"); - } - .seriousError { - @extend .error; - border-width: 3px; - } - - ...produces:: - - .error, - .seriousError { - border: 1px red; - background-color: #fdd; - } - .error.intrusion, - .seriousError.intrusion { - background-image: url("/image/hacked.png"); - } - .seriousError { - border-width: 3px; - } - - #. **Sprites** (using `sprite-map()`) - Example:: - - @option compress: no; - $icons: sprite-map("sociable/*.png"); // contains sociable/facebook.png among others. - div { - background: $icons; - } - @each $icon in sprites($icons) { - div .#{$icon} { - width: image-width(sprite-file($icons, $icon)); - height: image-height(sprite-file($icons, $icon)); - background-position: sprite-position($icons, $icon); - } - } - - ...generates a new sprite file and produces something like:: - - div { - background: url("/static/assets/u8Y7yEQL0UffAVw5rX7yhw.png?_=1298240989") 0px 0px no-repeat; - } - div .facebook { - width: 32px; - height: 32px; - background-position: 0px 0px; - } - div .twitter { - width: 32px; - height: 32px; - background-position: 0px -32px; - } - ... - - #. **Interactive mode** - Example:: - - $ python scss.py --interactive - >>> @import "compass/css3" - >>> show() - ['functions', 'mixins', 'options', 'vars'] - >>> show(mixins) - ['apply-origin', - 'apply-transform', - ... - 'transparent'] - >>> show(mixins, transparent) - @mixin transparent() { - @include opacity(0); - } - >>> 1px + 5px - 6px - >>> _ - - Sass Sassy CSS - ============== - pyScss is a Scss (Sass) implementation for Python. - Currently it implements @mixin, @include, @if, @else, @for, and @import... it - also implements many of the Sass functions including color functions like - hsla(), hsl(), darken(), lighten(), mix(), opacify(), transparentize(), - saturate(), desaturate(), etc.) as well as sprite-map(), sprite-file(), - image-width(), image-height() and the others. - - In the file `scss.py`, by the top, you can configure the LOAD_PATHS to point to - your Sass frameworks path (I have `sass/frameworks/compass/*.scss` and - `sass/framework/blueprint/*.scss` files in my project directory: - `/usr/local/www/project/`, where `scss.py` lives, so it defaults to use the - `sass/framework/` path, relative to the `scss.py` file) or configure using the - command line `--load-path` option, see `python scss.py --help`. - - I have succesfully compiled some Compass using `python scss.py < myfile.css` the - following `myfile.css`:: - - @option compress: no; - - $blueprint-grid-columns : 24; - $blueprint-grid-width : 30px; - $blueprint-grid-margin : 10px; - $font-color : #333; - - @import "compass/reset"; - @import "compass/utilities"; - @import "blueprint"; - - // Stuff goes here... - - - Bug tracker - =========== - If you have any suggestions, bug reports or annoyances please report them to the - issue tracker at http://github.com/Kronuz/pyScss/issues - - - Contributing - ============ - Development of pyScss happens at github: https://github.com/Kronuz/pyScss - - License - ======= - MIT License. See *LICENSE* for details. - http://www.opensource.org/licenses/mit-license.php - - Copyright - ========= - Copyright (c) 2012 German M. Bravo (Kronuz) - *Bits of code in pyScss come from various projects:* - - Compass: - (c) 2009 Christopher M. Eppstein - http://compass-style.org/ - Sass: - (c) 2006-2009 Hampton Catlin and Nathan Weizenbaum - http://sass-lang.com/ - xCSS: - (c) 2010 Anton Pawlik - http://xcss.antpaw.org/docs/ -Keywords: css oocss xcss sass scss less precompiler -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Topic :: Software Development :: Code Generators -Classifier: Topic :: Text Processing :: Markup -Classifier: Topic :: Software Development :: Libraries :: Python Modules diff --git a/pyScss.egg-info/SOURCES.txt b/pyScss.egg-info/SOURCES.txt deleted file mode 100644 index 1dc63e89..00000000 --- a/pyScss.egg-info/SOURCES.txt +++ /dev/null @@ -1,33 +0,0 @@ -CHANGELOG -DESCRIPTION -LICENSE -MANIFEST.in -README.rst -setup.py -pyScss.egg-info/PKG-INFO -pyScss.egg-info/SOURCES.txt -pyScss.egg-info/dependency_links.txt -pyScss.egg-info/entry_points.txt -pyScss.egg-info/top_level.txt -scss/__init__.py -scss/__init__.pyc -scss/scss_meta.py -scss/scss_meta.pyc -scss/setup.py -scss/tests.rst -scss/src/_speedups.c -scss/src/block_locator.c -scss/src/block_locator.h -scss/src/block_locator.py -scss/src/build.py -scss/src/scanner.c -scss/src/scanner.h -scss/src/scanner.py -scss/src/utils.h -scss/src/grammar/LICENSE -scss/src/grammar/README -scss/src/grammar/grammar.g -scss/src/grammar/grammar.py -scss/src/grammar/yapps2.py -scss/src/grammar/yappsrt.py -scss/src/grammar/yappsrt.pyc \ No newline at end of file diff --git a/pyScss.egg-info/dependency_links.txt b/pyScss.egg-info/dependency_links.txt deleted file mode 100644 index 8b137891..00000000 --- a/pyScss.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/pyScss.egg-info/entry_points.txt b/pyScss.egg-info/entry_points.txt deleted file mode 100644 index 0600609b..00000000 --- a/pyScss.egg-info/entry_points.txt +++ /dev/null @@ -1,4 +0,0 @@ - - [console_scripts] - pyscss = scss:main - \ No newline at end of file diff --git a/pyScss.egg-info/top_level.txt b/pyScss.egg-info/top_level.txt deleted file mode 100644 index a419809a..00000000 --- a/pyScss.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -scss diff --git a/scss/__init__.py b/scss/__init__.py index d94cf568..16b701c8 100644 --- a/scss/__init__.py +++ b/scss/__init__.py @@ -4,7 +4,7 @@ pyScss, a Scss compiler for Python @author German M. Bravo (Kronuz) -@version 1.1.3 +@version 1.1.4 @see https://github.com/Kronuz/pyScss @copyright (c) 2012 German M. Bravo (Kronuz) @license MIT License @@ -414,7 +414,7 @@ 'scaleX scaleY rotate skewX skewY' # http://www.w3.org/TR/css3-3d-transforms/ FUNCTIONS_3D = 'matrix3d translate3d translateZ scale3d scaleZ rotate3d '\ - 'rotateX rotateY rotateZ perspective' + 'rotateX rotateY rotateZ skew perspective' # http://www.w3.org/TR/css3-transitions/ FUNCTIONS_TRANSITIONS = 'cubic-bezier' # http://www.w3.org/TR/css3-animations/ @@ -540,7 +540,8 @@ def split_params(params): param = params.pop(0) try: while True: - while param.count('(') != param.count(')'): + while param.count('(') != param.count(')') or \ + param.count('"') % 2 == 1: try: param = param + ',' + params.pop(0) except IndexError: @@ -1270,7 +1271,7 @@ def _do_import(self, rule, p_selectors, p_parents, p_children, scope, media, c_l if i_codestr is None: load_paths = load_paths and "\nLoad paths:\n\t%s" % "\n\t".join(load_paths) or '' unsupported = unsupported and "\nPossible matches (for unsupported file format SASS):\n\t%s" % "\n\t".join(unsupported) or '' - log.warn("File to import not found or unreadable: '%s' (%s)%s%s", filename, rule[INDEX][rule[LINENO]], load_paths, unsupported) + log.warn("File to import not found or unreadable: '%s' (%s)%s%s", name, rule[INDEX][rule[LINENO]], load_paths, unsupported) else: _rule = spawn_rule(rule, codestr=i_codestr, path=full_filename, lineno=c_lineno) self.manage_children(_rule, p_selectors, p_parents, p_children, scope, media) @@ -2404,7 +2405,7 @@ def _get_gradient_position_and_angle(args): skip = True break elif isinstance(a, NumberValue): - ret = arg + ret = _arg if skip: continue if ret is not None: @@ -2415,7 +2416,7 @@ def _get_gradient_position_and_angle(args): 'left', 'right', ): if seek in _arg: - return arg + return _arg return None @@ -2458,6 +2459,8 @@ def _radial_gradient(*args): position_and_angle = _get_gradient_position_and_angle(args) shape_and_size = _get_gradient_shape_and_size(args) color_stops = _get_gradient_color_stops(args) + if color_stops is None: + raise Exception('No color stops provided to radial-gradient function') color_stops = __color_stops(False, *color_stops) args = [ @@ -2512,6 +2515,8 @@ def _linear_gradient(*args): position_and_angle = _get_gradient_position_and_angle(args) color_stops = _get_gradient_color_stops(args) + if color_stops is None: + raise Exception('No color stops provided to linear-gradient function') color_stops = __color_stops(False, *color_stops) args = [ @@ -3508,6 +3513,20 @@ def _grad_point(*p): ################################################################################ +def __parse_separator(sep): + if sep is None: + return None + sep = StringValue(sep).value + if sep == 'comma': + return ',' + elif sep == 'space': + return ' ' + elif sep == 'auto': + return None + else: + raise ValueError('Separator must be auto, comma, or space') + + def __compass_list(*args): separator = None if len(args) == 1 and isinstance(args[0], (list, tuple, ListValue)): @@ -3516,7 +3535,7 @@ def __compass_list(*args): separator = ',' ret = ListValue(args) if separator: - ret['_'] = separator + ret.value['_'] = separator return ret @@ -3575,6 +3594,8 @@ def _reject(lst, *values): values = values[0] if isinstance(values, ListValue): values = values.value.values() + elif not isinstance(values, (list, tuple)): + values = list(values) for i, item in lst.items(): if item not in values: ret[i] = item @@ -3635,10 +3656,9 @@ def _join(lst1, lst2, separator=None): lst2 = ListValue(lst2).value lst_len = len(ret.value) ret.value.update((k + lst_len if isinstance(k, int) else k, v) for k, v in lst2.items()) + separator = __parse_separator(separator) if separator is not None: - separator = StringValue(separator).value - if separator: - ret.value['_'] = separator + ret.value['_'] = separator return ret @@ -3664,14 +3684,19 @@ def _min(*lst): def _append(lst, val, separator=None): - separator = separator and StringValue(separator).value + separator = __parse_separator(separator) ret = ListValue(lst, separator) - val = ListValue(val) - for v in val: - ret.value[len(ret)] = v + ret.value[len(ret)] = val return ret +def _index(lst, val): + for i in xrange(len(lst)): + if lst.value[i] == val: + return NumberValue(i + 1) + return BooleanValue(False) + + ################################################################################ @@ -4187,11 +4212,11 @@ def __init__(self, tokens, type=None): elif isinstance(tokens, (int, float)): self.value = float(tokens) elif isinstance(tokens, (list, tuple)): - raise ValueError("Value is not a Number! (%r)" % list(tokens)) + raise ValueError("Value is not a Number! (%r)" % (tokens,)) elif isinstance(tokens, (dict, ListValue)): - raise ValueError("Value is not a Number! (%r)" % tokens.values()) + raise ValueError("Value is not a Number! (%r)" % (tokens.values(),)) else: - raise ValueError("Value is not a Number! (%s)" % tokens) + raise ValueError("Value is not a Number! (%r)" % (tokens,)) if type is not None: self.units = {type: _units_weights.get(type, 1), '_': type} @@ -4419,7 +4444,7 @@ def values(self): return zip(*self.items())[1] def keys(self): - return zip(*self.items())[1] + return zip(*self.items())[0] def items(self): return sorted((k, v) for k, v in self.value.items() if k != '_') @@ -4813,6 +4838,7 @@ def __radd__(self, other): '-compass-list-size:n': _length, 'append:2': _append, 'append:3': _append, + 'index:2': _index, 'nest:n': _nest, 'append-selector:2': _append_selector, diff --git a/scss/scss_meta.py b/scss/scss_meta.py index 6de98a87..df6b5aa4 100644 --- a/scss/scss_meta.py +++ b/scss/scss_meta.py @@ -4,7 +4,7 @@ pyScss, a Scss compiler for Python @author German M. Bravo (Kronuz) -@version 1.1.3 +@version 1.1.4 @see https://github.com/Kronuz/pyScss @copyright (c) 2012 German M. Bravo (Kronuz) @license MIT License @@ -44,7 +44,7 @@ """ -VERSION_INFO = (1, 1, 3) +VERSION_INFO = (1, 1, 4) DATE_INFO = (2012, 1, 9) # YEAR, MONTH, DAY VERSION = '.'.join(str(i) for i in VERSION_INFO) REVISION = '%04d%02d%02d' % DATE_INFO diff --git a/scss/setup.py b/scss/setup.py deleted file mode 100644 index 7112a187..00000000 --- a/scss/setup.py +++ /dev/null @@ -1,14 +0,0 @@ -from distutils.core import setup, Extension - -setup(name='pyScss', - version='1.1.1', - description='pyScss', - ext_modules=[ - Extension( - '_scss', - sources=['src/_scss.c', 'src/block_locator.c', 'src/scanner.c'], - libraries=['pcre'], - optional=True - ) - ] -)