
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.
110 lines
3.5 KiB
Python
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
|