def old_json_function(content, local=None, name_prefix=None, evaluator=None): def convert(content, prefix=None): if prefix: prefix = prefix + "-" else: prefix = "" for key in content: val = content[key] name = prefix + key if isinstance(val, dict): convert(val, name) else: val = coerce(val, raw=False) if val.node_name == "string": val = parse_string(val.string) scope.add(Ident(name_prefix + name, val)) if name_prefix: assert_string(name_prefix, "name_prefix") name_prefix = name_prefix.value else: name_prefix = "" if local: local = local.to_boolean() else: local = Boolean(local) if local.is_true(): scope = evaluator.get_current_scope() else: scope = evaluator.common.scope() convert(content)
def selector_exists(selector, evaluator=None): assert_string(selector, "selector") visitor = Normalizer(evaluator.root.clone(), evaluator.parser, evaluator.options) visitor.visit(visitor.root) return selector.string in visitor.selector_map
def unit(unit, type=None, evaluator=None): # assert_type(unit, 'unit', 'unit') if type: assert_string(type, "type") return Unit(unit.value, type.string) else: return unit.type if hasattr(unit, "type") and unit.type else ""
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 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 split(delim, value, evaluator=None): assert_string(delim, "delimiter") assert_string(value, "val") words = value.string.split(delim.string) expr = Expression() for word in words: if isinstance(value, Ident): addition = Ident(word) else: addition = String(word) expr.append(Ident(addition)) return expr
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 component(color: Color, name: str, evaluator=None) -> Unit: """Return component `name` for a given `color`. :param color: Color :param name: str :return: Unit """ assert_color(color, "color") assert_string(name, "name") name = name.string unit = unit_map.setdefault(name, None) type = type_map[name] name = component_map[name] try: return Unit(getattr(getattr(color, type)(), name), unit) except AttributeError: raise TypeError(f'invalid color component "{name}"')
def s(fmt, *args, evaluator=None): options = evaluator.options if evaluator else {} fmt = unwrap(fmt).nodes[0] assert_string(fmt, "string") result = fmt.string results = [] for arg in args: from stilus.visitor.evaluator import Evaluator if not isinstance(arg, Evaluator): results.append(Compiler(arg, options).compile()) for r in results: result = result.replace("%s", r, 1) # add nulls for missed %s elements c = Compiler(null, options).compile() result = result.replace("%s", c) return Literal(result)
def opposite_position(positions, evaluator=None): expr = [] nodes = utils.unwrap(positions) for i, node in enumerate(nodes): utils.assert_string(node, f"position {i}") if node.string == "top": expr.append(Literal("bottom")) elif node.string == "bottom": expr.append(Literal("top")) elif node.string == "left": expr.append(Literal("right")) elif node.string == "right": expr.append(Literal("left")) elif node.string == "center": expr.append(Literal("center")) else: raise StilusError(f"invalid position {i}") return expr
def json_function(path, local=None, name_prefix=None, evaluator=None): assert_string(path, "path") def convert(content, options): ret = ObjectNode() leave_strings = options.get("leave-strings").to_boolean() for key in content: val = content[key] if isinstance(val, dict): ret.set(key, convert(val, options)) else: val = coerce(val, raw=False) if (val and val.node_name == "string" and leave_strings.is_false()): val = parse_string(val.string) ret.set(key, val) return ret # lookup path = path.string found = lookup(path, evaluator.paths, evaluator.filename) options = None if (local and hasattr(local, "node_name") and local.node_name == "objectnode"): options = local if not found: if options: optional = options.get("optional") if optional and optional.first().is_true(): return null raise StilusError(f"failed to locate .json file {path}") # read with open(found, "r") as reader: content = json.load(reader) if options: return convert(content, options) else: old_json_function(content, local, name_prefix, evaluator)
def replace(pattern, replacement, value, evaluator=None): assert_string(pattern, "pattern") assert_string(replacement, "replacement") assert_string(value, "value") result = value.string.replace(pattern.string, replacement.string) if isinstance(value, Ident): return Ident(result) else: return String(result)
def selector(*args, evaluator=None): stack = evaluator.selector_stack() if len(args) == 1: expr = unwrap(args[0]) length = len(expr.nodes) # selector .a if length == 1: assert_string(expr.first(), "selector") value = expr.first().string parsed = SelectorParser(value).parse()["value"] if parsed == value: return value stack.append(parse(value)) elif length > 1: # selector-list = '.a', '.b', '.c' # selector(selector-list) if expr.is_list: push_to_stack(expr.nodes, stack) # selector('.a' '.b' '.c') else: joined = " ".join([node.string for node in expr.nodes]) stack.append(parse(joined)) # selector('.a', '.b', '.c') elif len(args) > 1: push_to_stack(args, stack) if stack: return ",".join(compile_selectors(stack)) else: return "&"
def convert(str, evaluator=None): assert_string(str, "string") return parse_string(str.string)
def unquote(string, evaluator=None): assert_string(string, "string") return Literal(string.string)
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 basename(p, ext=None, evaluator=None): assert_string(p, "path") result = Path(p).name if ext and result.endswith(ext.name): result[: len(ext.name)] return result
def dirname(p, evaluator=None): assert_string(p, "path") return str(Path(p).parent)
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)
def push_to_stack(selectors, stack): for selector in selectors: selector = selector.first() assert_string(selector, "selector") stack.append(parse(selector.string))
def extname(p, evaluator=None): assert_string(p, "path") return Path(p.value).suffix