Sascha Peilicke dc4196cf6d Fix block fills generation with only variables.
If the parsed block contents contains only LESS variable definitions,
the block should not be renderend. Previously this was implemented by
not returning self from Variable.parse() (contrary to it's docstring and
other plib classes). The real fix is to just check for the above
condition and return self again.
2013-12-20 11:14:03 +01:00

110 lines
3.5 KiB
Python

# -*- coding: utf8 -*-
"""
.. module:: lesscpy.plib.deferred
:synopsis: Deferred mixin call.
Copyright (c)
See LICENSE for details.
.. moduleauthor:: Johann T. Mariusson <jtm@robot.is>
"""
from .node import Node
from lesscpy.lessc import utility
class Deferred(Node):
def __init__(self, mixin, args, lineno=0):
"""This node represents mixin calls. The calls
to these mixins are deferred until the second
parse cycle. lessc.js allows calls to mixins not
yet defined or known.
args:
mixin (Mixin): Mixin object
args (list): Call arguments
"""
self.tokens = [mixin, args]
self.lineno = lineno
def parse(self, scope, error=False):
""" Parse function. We search for mixins
first within current scope then fallback
to global scope. The special scope.deferred
is used when local scope mixins are called
within parent mixins.
If nothing is found we fallback to block-mixin
as lessc.js allows calls to blocks and mixins to
be inter-changable.
clx: This method is a HACK that stems from
poor design elsewhere. I will fix it
when I have more time.
args:
scope (Scope): Current scope
returns:
mixed
"""
res = False
ident, args = self.tokens
ident.parse(scope)
mixins = scope.mixins(ident.raw())
if not mixins:
ident.parse(None)
mixins = scope.mixins(ident.raw())
if not mixins:
if scope.deferred:
store = [t for t in scope.deferred.parsed[-1]]
i = 0
while scope.deferred.parsed[-1]:
scope.current = scope.deferred
ident.parse(scope)
mixins = scope.mixins(ident.raw())
scope.current = None
if mixins or i > 64:
break
scope.deferred.parsed[-1].pop()
i += 1
scope.deferred.parsed[-1] = store
if not mixins:
# Fallback to blocks
block = scope.blocks(ident.raw())
if not block:
ident.parse(None)
block = scope.blocks(ident.raw())
if block:
scope.current = scope.real[-1] if scope.real else None
res = block.copy_inner(scope)
scope.current = None
if mixins:
for mixin in mixins:
scope.current = scope.real[-1] if scope.real else None
res = mixin.call(scope, args)
if res:
# Add variables to scope to support
# closures
[scope.add_variable(v) for v in mixin.vars]
scope.deferred = ident
break
if res:
store = [t for t in scope.deferred.parsed[
-1]] if scope.deferred else False
res = [p.parse(scope) for p in res if p]
while(any(t for t in res if isinstance(t, Deferred))):
res = [p.parse(scope) for p in res if p]
if store:
scope.deferred.parsed[-1] = store
if error and not res:
raise SyntaxError('NameError `%s`' % ident.raw(True))
return res
def copy(self):
""" Returns self (used when Block objects are copy'd)
returns:
self
"""
return self