def hsla(hue, saturation=None, lightness=None, alpha=None, evaluator=None): """Convert the given `color` to an `HSLA` node, or h,s,l,a component values. :param hue: :param saturation: :param lightness: :param alpha: :return: :class:HSLA """ # color if hue and (saturation is lightness is alpha is None): assert_color(hue) return hue.hsla() # alpha if hue and saturation and (lightness is alpha is None): assert_color(hue) color = hue.hsla() assert_type(saturation, "unit", "alpha") alpha = saturation.clone() if alpha.type == "%": alpha.value /= 100 return HSLA(color.hue, color.saturation, color.lightness, alpha.value) # color assert_type(hue, "unit", "hue") assert_type(saturation, "unit", "saturation") assert_type(lightness, "unit", "lightness") assert_type(alpha, "unit", "alpha") alpha = alpha.clone() if alpha and alpha.type == "%": alpha.value /= 100 return HSLA(hue.value, saturation.value, lightness.value, alpha.value)
def transparentify(top, bottom=None, alpha=None, evaluator=None): if isinstance(bottom, Unit): # dirty hack alpha = bottom bottom = None assert_color(top) top = top.rgba() if not bottom: bottom = RGBA(255, 255, 255, 1) if not alpha and bottom and hasattr(bottom, "rgba") and not bottom.rgba: alpha = bottom bottom = RGBA(255, 255, 255, 1) assert_color(bottom) bottom = bottom.rgba() ba = best_alpha(top, bottom) if alpha: assert_type(alpha, "unit", "aplha") if alpha.type == "%": ba = alpha.value / 100 elif not alpha.type: ba = alpha = alpha.value ba = max(min(ba, 1), 0) if ba == 0: return RGBA(bottom.r, bottom.g, bottom.b, round(ba * 100) / 100) else: return RGBA( bottom.r + (top.r - bottom.r) / ba, bottom.g + (top.g - bottom.g) / ba, bottom.b + (top.b - bottom.b) / ba, round(ba * 100) / 100, )
def lookup(name, evaluator=None): assert_type(name, "string", "name") node = evaluator.lookup(name.value) if node: return evaluator.visit(node) else: return null
def math(n: Unit, fn: String, evaluator=None): """Apply Math ``fn`` to ``n``""" assert_type(n, "unit", "n") assert_string(fn, "fn") if fn.string == "round": return Unit(int(stilus_round(n.value)), n.type) return Unit(m.__getattribute__(fn.string)(n.value), n.type)
def define(name, expr, common=None, evaluator=None): assert_type(name, "string", "name") expr = unwrap(expr) scope = evaluator.get_current_scope() if common and common.to_boolean().is_true(): scope = evaluator.common.scope() node = Ident(name.value, expr) scope.add(node) return null
def prefix_classes(prefix, block=None, evaluator=None): assert_string(prefix, "prefix") assert_type(block, "block", "block") _prefix = evaluator.prefix evaluator.options["prefix"] = evaluator.prefix = prefix.string block = evaluator.visit(block) evaluator.options["prefix"] = evaluator.prefix = _prefix return block
def substr(value, start, length=None, evaluator=None): assert_string(value, "val") assert_type(start, "unit", "start") start = int(start.value) if length: length = start + int(length.value) result = value.string[start:length] if isinstance(value, Ident): return Ident(result) else: return String(result)
def merge(dest, *args, evaluator=None): assert_present(dest, "dest") dest = unwrap(dest).first() assert_type(dest, "objectnode", "dest") last = unwrap(args[len(args) - 1]).first() deep = True is last.value for arg in args: values = unwrap(arg).first() if hasattr(values, "values"): utils.merge(dest.values, unwrap(arg).first().values, deep) return dest
def add_property(name, expr, evaluator=None): assert_type(name, "expression", "name") name = unwrap(name).first() assert_string(name, "name") assert_type(expr, "expression", "expr") prop = Property([name], expr) block = evaluator.closest_block() head = block.nodes[0:block.index] tail = block.nodes[block.index:len(block.nodes)] block.index += 1 block.mixin = True # this is a dirty hack head.append(prop) head.extend(tail) block.nodes = head return prop
def adjust(color, prop, amount, evaluator=None): assert_color(color, "color") assert_string(prop, "prop") assert_type(amount, "unit", "amount") hsl = color.hsla().clone() if not hasattr(hsl, prop.string): raise StilusError("Invalid adjustment property.") value = amount.value if amount.type == "%": if prop.string == "lightness" and value > 0: value = (100 - hsl.lightness) * value / 100 else: value = getattr(hsl, prop.string) * (value / 100) setattr(hsl, prop.string, getattr(hsl, prop.string) + value) return hsl.rgba()
def tan(angle, evaluator=None): assert_type(angle, "unit", "angle") radians = angle.value if angle.type == "deg": radians = m.radians(radians) # start of Stylus tan generation... pow = m.pow(10, 9) sin = float(stilus_round(m.sin(radians) * pow)) / pow cos = float(stilus_round(m.cos(radians) * pow)) / pow if cos == 0: tan = "Infinity" else: tan = float(stilus_round(pow * sin / cos)) / pow if tan == 0: tan = 0 # ...which in fact should be m.tan(radians) return Unit(tan, "")
def image_size(img: str, ignore_errors=False, evaluator=None): assert_type(img, "string", "img") p = Path(img.string) path = lookup(p, evaluator.paths) if p.suffix == ".svg": return _x_and_y_from_svg(path) if path: with Image.open(path) as image: x, y = image.size expression = Expression() expression.nodes = [Unit(x, "px"), Unit(y, "px")] return expression elif ignore_errors: expression = Expression() expression.nodes = [Unit(0), Unit(0)] return expression else: raise StilusError("Could not find image.")
def rgba(red, green=None, blue=None, alpha=None, evaluator=None): """Return a `RGBA` from the r,g,b,a channels. >>> rgba(255,0,0,0.5) rgba(255,0,0,0.5) >>> rgba(255,0,0,1) #ff0000 >>> rgba(#ffcc00, 50%) rgba(255,204,0,0.5) :param red: :param green: :param blue: :param alpha: :return: """ # color if red and (green is blue is alpha is None): assert_color(red) return red.rgba() # alpha if red and green and (blue is alpha is None): assert_color(red) color = red.rgba() assert_type(green, "unit", "alpha") alpha = green.clone() if alpha.type == "%": alpha.value /= 100 return RGBA(color.r, color.g, color.b, alpha.value) # color assert_type(red, "unit", "red") assert_type(green, "unit", "green") assert_type(blue, "unit", "blue") assert_type(alpha, "unit", "alpha") r = round(red.value * 2.55) if red.type == "%" else red.value g = round(green.value * 2.55) if green.type == "%" else green.value b = round(blue.value * 2.55) if blue.type == "%" else blue.value alpha = alpha.clone() if alpha and alpha.type == "%": alpha.value /= 100 return RGBA(r, g, b, alpha.value)
def visit_unaryop(self, unary): op = unary.op node = self.visit(unary.expr) if "!" != op: node = node.first().clone() utils.assert_type(node, "unit") if op == "-": node.value = -node.value elif op == "+": node.value = +node.value elif op == "~": if isinstance(node.value, float): node.value = ~int(node.value) else: node.value = ~node.value elif op == "!": return node.to_boolean().negate() return node
def range_function(start, stop, step=None, evaluator=None): assert_type(start, "unit", "start") assert_type(stop, "unit", "stop") if step: assert_type(step, "unit", "step") if step.value == 0: raise StilusError('ArgumentError: "step" argument ' "must not be zero") else: step = Unit(1) lst = Expression() i = start.value while i <= stop.value: lst.append(Unit(i, start.type)) i += step.value return lst
def base_convert(num, base, width=None, evaluator=None): if isinstance(num, Expression): num = unwrap(num).nodes[0] if isinstance(base, Expression): base = unwrap(base).nodes[0] if width and isinstance(width, Expression): width = unwrap(width).nodes[0] assert_type(num, "unit") assert_type(base, "unit") if width: assert_type(width, "unit") if width: width = width.value else: width = 2 num = int(num.value) base = int(base.value) result = _convert(num, base) while len(result) < width: result = "0" + result return Literal(result)
def error(msg, evaluator=None): assert_type(msg, "string", "msg") err = StilusError(msg.value) err.from_stilus = True raise err
def operate(op=None, left=None, right=None, evaluator=None): assert_type(op, "string", "op") assert_present(left, "left") assert_present(right, "right") return left.operate(op.value, right)
def remove(object, key, evaluator=None): assert_type(object, "objectnode", "object") assert_string(key, "key") if object.has(key.string): del object.values[key.string] return object
def match(pattern, val, flags=None, evaluator=None): assert_type(pattern, "string", "pattern") utils.assert_string(val, "val") return stilus_findall(pattern.value, val.string, flags)