lib/phlex/helpers.rb
# frozen_string_literal: true require "set" module Phlex::Helpers private # Tokens # @return [String] # @example With Proc conditions # tokens( # -> { true } => "a", # -> { false } => "b" # ) # @example With method conditions # tokens( # active?: "active" # ) # @example With else condition # tokens( # active?: { then: "active", else: "inactive" } # ) def tokens(*tokens, **conditional_tokens) conditional_tokens.each do |condition, token| truthy = case condition when Symbol then send(condition) when Proc then condition.call else raise ArgumentError, "The class condition must be a Symbol or a Proc." end if truthy case token when Hash then __append_token__(tokens, token[:then]) else __append_token__(tokens, token) end else case token when Hash then __append_token__(tokens, token[:else]) end end end tokens = tokens.select(&:itself).join(" ") tokens.strip! tokens.gsub!(/\s+/, " ") tokens end # @api private def __append_token__(tokens, token) case token when nil then nil when String then tokens << token when Symbol then tokens << token.name when Array then tokens.concat(token) else raise ArgumentError, "Conditional classes must be Symbols, Strings, or Arrays of Symbols or Strings." end end # Like {#tokens} but returns a {Hash} where the tokens are the value for `:class`. # @return [Hash] def classes(*tokens, **conditional_tokens) tokens = self.tokens(*tokens, **conditional_tokens) if tokens.empty? {} else { class: tokens } end end # @return [Hash] def mix(*args) args.each_with_object({}) do |object, result| result.merge!(object) do |_key, old, new| next new if old.nil? case new when Hash old.is_a?(Hash) ? mix(old, new) : new when Array case old when Array then old + new when Set then old.to_a + new when Hash then new else [old] + new end when Set case old when Set then old + new when Array then old + new.to_a when Hash then new else new + [old] end when String old.is_a?(String) ? "#{old} #{new}" : old + old.class[new] when nil old else new end end result.transform_keys! do |key| key.end_with?("!") ? key.name.chop.to_sym : key end end end end