class Primer::Classify

Constants

BG_KEY
BOOLEAN_MAPPINGS
BORDER_COLOR_KEY
BORDER_KEY
BORDER_MARGIN_KEYS
BORDER_RADIUS_KEY
BOX_SHADOW_KEY
BREAKPOINTS
CONCAT_KEYS

Keys where we can simply translate { key: value } into “.key-value”

CONTAINER_KEY
RESPONSIVE_KEYS
TEXT_KEYS
TYPOGRAPHY_KEYS
VALID_KEYS

Public Class Methods

call(classes: "", style: nil, **args) click to toggle source
# File lib/primer/classify.rb, line 96
def call(classes: "", style: nil, **args)
  extracted_results = extract_hash(args)

  extracted_results[:class] = [
    validated_class_names(classes),
    extracted_results.delete(:classes)
  ].compact.join(" ").strip.presence

  extracted_results[:style] = [
    extracted_results.delete(:styles),
    style
  ].compact.join.presence

  extracted_results
end

Private Class Methods

extract_hash(styles_hash) click to toggle source

NOTE: This is a fairly naive implementation that we're building as we go. Feel free to refactor as this is thoroughly tested.

Utility for mapping component configuration into Primer CSS class names

styles_hash - A hash with utility keys that mimic the interface used by github.com/primer/components

Returns a string of Primer CSS class names to be added to an HTML class attribute

Example usage: extract_hash({ mt: 4, py: 2 }) => “mt-4 py-2”

# File lib/primer/classify.rb, line 140
def extract_hash(styles_hash)
  memo = { classes: [], styles: +"" }
  styles_hash.each do |key, value|
    next unless VALID_KEYS.include?(key)

    if value.is_a?(Array)
      raise ArgumentError, "#{key} does not support responsive values" unless RESPONSIVE_KEYS.include?(key) || Primer::Classify::Utilities.supported_key?(key)

      value.each_with_index do |val, index|
        Primer::Classify::Cache.read(memo, key, val, BREAKPOINTS[index]) || extract_value(memo, key, val, BREAKPOINTS[index])
      end
    else
      Primer::Classify::Cache.read(memo, key, value, BREAKPOINTS[0]) || extract_value(memo, key, value, BREAKPOINTS[0])
    end
  end

  memo[:classes] = memo[:classes].join(" ")

  memo
end
extract_value(memo, key, val, breakpoint) click to toggle source
# File lib/primer/classify.rb, line 161
def extract_value(memo, key, val, breakpoint)
  return if val.nil? || val == ""

  if Primer::Classify::Utilities.supported_key?(key)
    memo[:classes] << Primer::Classify::Utilities.classname(key, val, breakpoint)
  elsif BOOLEAN_MAPPINGS.key?(key)
    BOOLEAN_MAPPINGS[key][:mappings].each do |m|
      memo[:classes] << m[:css_class] if m[:value] == val && m[:css_class].present?
    end
  elsif key == BG_KEY
    if val.to_s.start_with?("#")
      memo[:styles] << "background-color: #{val};"
    else
      memo[:classes] << Primer::Classify::FunctionalBackgroundColors.color(val)
    end
  elsif key == BORDER_KEY
    border_value = if val == true
                     "border"
                   else
                     "border-#{val.to_s.dasherize}"
                   end

    memo[:classes] << border_value
  elsif key == BORDER_COLOR_KEY
    memo[:classes] << Primer::Classify::FunctionalBorderColors.color(val)
  elsif BORDER_MARGIN_KEYS.include?(key)
    memo[:classes] << "#{key.to_s.dasherize}-#{val}"
  elsif key == BORDER_RADIUS_KEY
    memo[:classes] << "rounded-#{val}"
  elsif Primer::Classify::Flex::KEYS.include?(key)
    memo[:classes] << Primer::Classify::Flex.classes(key, val, breakpoint)
  elsif Primer::Classify::Grid::KEYS.include?(key)
    memo[:classes] << Primer::Classify::Grid.classes(key, val, breakpoint)
  elsif TEXT_KEYS.include?(key)
    memo[:classes] << "text-#{val.to_s.dasherize}"
  elsif TYPOGRAPHY_KEYS.include?(key)
    memo[:classes] << if val == :small || val == :normal
                        "text-#{val.to_s.dasherize}"
                      else
                        "f#{val.to_s.dasherize}"
                      end
  elsif key == BOX_SHADOW_KEY
    memo[:classes] << if val == true
                        "color-shadow-small"
                      elsif val == :none || val.blank?
                        "box-shadow-none"
                      else
                        "color-shadow-#{val.to_s.dasherize}"
                      end
  end
end
force_system_arguments?() click to toggle source
# File lib/primer/classify.rb, line 213
def force_system_arguments?
  Rails.application.config.primer_view_components.force_system_arguments
end
validated_class_names(classes) click to toggle source
# File lib/primer/classify.rb, line 114
def validated_class_names(classes)
  return if classes.blank?

  if force_system_arguments? && !ENV["PRIMER_WARNINGS_DISABLED"]
    invalid_class_names =
      classes.split.each_with_object([]) do |class_name, memo|
        memo << class_name if Primer::Classify::Validation.invalid?(class_name)
      end

    raise ArgumentError, "Use System Arguments (https://primer.style/view-components/system-arguments) instead of Primer CSS class #{'name'.pluralize(invalid_class_names.length)} #{invalid_class_names.to_sentence}. This warning will not be raised in production. Set PRIMER_WARNINGS_DISABLED=1 to disable this warning." if invalid_class_names.any?
  end

  classes
end