diff --git a/lesscpy/lessc/parser.py b/lesscpy/lessc/parser.py index 50358c1..60123fd 100644 --- a/lesscpy/lessc/parser.py +++ b/lesscpy/lessc/parser.py @@ -135,13 +135,13 @@ class LessParser(object): """ statement : css_charset t_ws css_string ';' | css_namespace t_ws css_string ';' """ - p[0] = Statement(list(p)[1:]) + p[0] = Statement(list(p)[1:], p.lineno(1)) p[0].parse(None) def p_statement_namespace(self, p): """ statement : css_namespace t_ws word css_string ';' """ - p[0] = Statement(list(p)[1:]) + p[0] = Statement(list(p)[1:], p.lineno(1)) p[0].parse(None) def p_statement_import(self, p): @@ -168,7 +168,7 @@ class LessParser(object): except ImportError as e: self.handle_error(e, p) else: - p[0] = Statement(list(p)[1:]) + p[0] = Statement(list(p)[1:], p.lineno(1)) p[0].parse(None) # diff --git a/lesscpy/plib/block.py b/lesscpy/plib/block.py index 7dfaee3..732c19c 100644 --- a/lesscpy/plib/block.py +++ b/lesscpy/plib/block.py @@ -9,21 +9,22 @@ class Block(Node): def parse(self, scope): """ """ - ident, inner = self.tokens - self.name = ident.parse(scope) - if not inner: inner = [] - self.parsed = [p.parse(scope) - for p in inner - if p and type(p) is not type(self)] - if not inner: - self.inner = [] - else: - self. inner = [p for p in inner - if p and type(p) is type(self)] - if self.inner: - scope = copy.deepcopy(scope) - scope.current = self.name - self.inner = [p.parse(scope) for p in self.inner] + if not self.parsed: + ident, inner = self.tokens + self.name = ident.parse(scope) + if not inner: inner = [] + self.parsed = [p.parse(scope) + for p in inner + if p and type(p) is not type(self)] + if not inner: + self.inner = [] + else: + self. inner = [p for p in inner + if p and type(p) is type(self)] + if self.inner: + scope = copy.deepcopy(scope) + scope.current = self.name + self.inner = [p.parse(scope) for p in self.inner] return self def format(self, fills): diff --git a/lesscpy/plib/node.py b/lesscpy/plib/node.py index ea7c704..ccb0eb2 100644 --- a/lesscpy/plib/node.py +++ b/lesscpy/plib/node.py @@ -5,6 +5,7 @@ class Node(object): def __init__(self, p, ln): self.tokens = p self.lineno = ln + self.parsed = False def parse(self, scope): return self diff --git a/lesscpy/plib/property.py b/lesscpy/plib/property.py index cd29144..0de98e1 100644 --- a/lesscpy/plib/property.py +++ b/lesscpy/plib/property.py @@ -3,26 +3,21 @@ from .node import Node from lesscpy.lessc import utility class Property(Node): - pass - def parse(self, scope): - if len(self.tokens) > 2: - property, style, _ = self.tokens - self.important = True - else: - property, style = self.tokens - self.important = False - self.property = ''.join(property) - self.parsed = [] - if style: - self.parsed = self.process(style, scope) -# style = self.replace_variables(style, scope) -# style = self.preprocess(style) -# self.parsed = [p.parse(scope) -# if hasattr(p, 'parse') -# else p -# for p in style] -# self.parsed = [p for p in self.parsed if p] + """ + """ + if not self.parsed: + if len(self.tokens) > 2: + property, style, _ = self.tokens + self.important = True + else: + property, style = self.tokens + self.important = False + self.property = ''.join(property) + self.parsed = [] + if style: + style = self.preprocess(style) + self.parsed = self.process(style, scope) return self def preprocess(self, style): @@ -41,12 +36,18 @@ class Property(Node): """ f = "%(tab)s%(property)s:%(ws)s%(style)s%(important)s;%(nl)s" imp = ' !important' if self.important else '' + if fills['nl']: + self.parsed = [',%s' % fills['ws'] + if p == ',' + else p + for p in self.parsed] + style = ''.join([p.format(fills) + if hasattr(p, 'format') + else str(p) + for p in self.parsed]) fills.update({ 'property': self.property, - 'style': ''.join([p.format(fills) - if hasattr(p, 'format') - else str(p) - for p in self.parsed]), + 'style': style, 'important': imp }) return f % fills diff --git a/lesscpy/test/css/variables.css b/lesscpy/test/css/variables.css new file mode 100644 index 0000000..66a0ac9 --- /dev/null +++ b/lesscpy/test/css/variables.css @@ -0,0 +1,42 @@ +.variables { + width: 14cm; +} +.variables { + height: 24px; + color: #888888; + font-family: "Trebuchet MS", Verdana, sans-serif; + quotes: "~""~"; +} +.redefinition { + three: 3; +} +.values { + font-family: 'Trebuchet', 'Trebuchet', 'Trebuchet'; + color: #888888 !important; + url: url('Trebuchet'); + multi: something 'A', B, C, 'Trebuchet'; +} +.variable-names { + name: 'hello'; +} +.alpha { + filter: alpha(opacity=42); +} +.lazy-eval { + width: 100%; +} +.scope1 { + color: blue; + border-color: black; +} +.scope2 { + color: blue; +} +.scope3 { + color: red; + border-color: black; + background-color: white; +} +.scope4 { + color: black; +} diff --git a/lesscpy/test/css/variables.min.css b/lesscpy/test/css/variables.min.css new file mode 100644 index 0000000..4b909e6 --- /dev/null +++ b/lesscpy/test/css/variables.min.css @@ -0,0 +1,11 @@ +.variables{width:14cm;} +.variables{height:24px;color:#888888;font-family:"Trebuchet MS",Verdana,sans-serif;quotes:"~""~";} +.redefinition{three:3;} +.values{font-family:'Trebuchet','Trebuchet','Trebuchet';color:#888888 !important;url:url('Trebuchet');multi:something 'A',B,C,'Trebuchet';} +.variable-names{name:'hello';} +.alpha{filter:alpha(opacity=42);} +.lazy-eval{width:100%;} +.scope1{color:blue;border-color:black;} +.scope2{color:blue;} +.scope3{color:red;border-color:black;background-color:white;} +.scope4{color:black;} diff --git a/lesscpy/test/less/expressions.less b/lesscpy/test/less/expressions.less index e69de29..2e27c59 100644 --- a/lesscpy/test/less/expressions.less +++ b/lesscpy/test/less/expressions.less @@ -0,0 +1,42 @@ +#operations { + color: #110000 + #000011 + #001100; // #111111 + height: 10px / 2px + 6px - 1px * 2; // 9px + width: 2 * 4 - 5em; // 3em + text-shadow: -1px -1px 1px red, 6px 5px 5px yellow; + .spacing { + height: 10px / 2px+6px- 1px*2; + width: 2 * 4 - 5em; + } + substraction: 20 - 10 - 5 - 5; // 0 + division: 20 / 5 / 4; // 1 +} + +@x: 4; +@y: 12em; + +.with-variables { + height: @x + @y; // 16em + width: 12 + @y; // 24em + size: 5cm - @x; // 1cm +} + +@z: -2; + +.negative { + height: 2px + @z; // 0px + width: 2px - @z; // 4px +} + +.shorthands { + padding: -1px 2px 0 -4px; // +} + +.colors { + color: #123; // #112233 + border-color: #234 + #111111; // #334455 + background-color: #222222 - #fff; // #000000 + .other { + color: 2 * #111; // #222222 + border-color: #333333 / 3 + #111; // #222222 + } +} \ No newline at end of file diff --git a/lesscpy/test/less/selectors.less b/lesscpy/test/less/selectors.less deleted file mode 100644 index e69de29..0000000 diff --git a/lesscpy/test/less/variables.less b/lesscpy/test/less/variables.less index ae785bb..551318a 100644 --- a/lesscpy/test/less/variables.less +++ b/lesscpy/test/less/variables.less @@ -1,16 +1,15 @@ +/* + Less variables +*/ @a: 2; @x: @a * @a; @y: @x + 1; @z: @x * 2 + @y; - - .variables { width: @z + 1cm; // 14cm } - @b: @a * 10; @c: #888; - @fonts: "Trebuchet MS", Verdana, sans-serif; @f: @fonts; @@ -50,10 +49,40 @@ @var: 42; filter: alpha(opacity=@var); } - +/* + Lazy eval +*/ @lazy: @j; @j: 100%; - .lazy-eval { - width: @lazy; + width: @lazy; +} +/* + Variable scoping +*/ +@x: blue; +@z: transparent; + +.scope1 { + @y: orange; + @z: black; + color: @x; // blue + border-color: @z; // black + .hidden { + @x: #131313; + } + .scope2 { + @y: red; + color: @x; // blue + .scope3 { + @local: white; + color: @y; // red + border-color: @z; // black + background-color: @local; // white + .scope4 { + @y: @z; + color: @y; + } + } + } } \ No newline at end of file