Skip to content

Commit

Permalink
chore: Code cleanup and comments
Browse files Browse the repository at this point in the history
  • Loading branch information
joshsadam committed Oct 23, 2024
1 parent ff30fb4 commit 1aea921
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 58 deletions.
2 changes: 1 addition & 1 deletion embedded_gems/flowbite/app/components/flowbite/icon.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# frozen_string_literal = true
# frozen_string_literal: true

module Flowbite
# This file defines the Flowbite::Icon component, which is responsible for
Expand Down
153 changes: 96 additions & 57 deletions embedded_gems/flowbite/lib/flowbite/classify.rb
Original file line number Diff line number Diff line change
@@ -1,96 +1,135 @@
# frozen_string_literal: true

module Flowbite
# :nodoc:
class Classify

# LOOKUP is a constant that stores utility classes for the Flowbite framework.
# It's defined in the Flowbite::Classify::Utilities module and contains
# a hash of utility classes organized by their purpose (e.g., spacing, colors, etc.).
# This constant is used throughout the Classify class to process and validate
# class names passed to components.
LOOKUP = Flowbite::Classify::Utilities::UTILITIES


class << self
# Processes the given arguments and returns a hash with class and style attributes
# @param args [Hash] The arguments to process
# @return [Hash] A hash containing :class and :style keys
def call(args = {})
style = nil
classes = [].tap do |result|
args.each do |key, val|
case key
when :classes
# insert :classes first to avoid huge doc diffs
if (class_names = validated_class_names(val))
result.unshift(class_names)
end
next
when :style
style = val
next
end

next unless LOOKUP[key]

if val.is_a?(Array)
# A while loop is ~3.5x faster than Array#each.
brk = 0
while brk < val.size
item = val[brk]

if item.nil?
brk += 1
next
end

# Believe it or not, three calls to Hash#[] and an inline rescue
# are about 30% faster than Hash#dig. It also ensures validate is
# only called when necessary, i.e. when the class can't be found
# in the lookup table.
found = (LOOKUP[key][item][brk] rescue nil) || validate(key, item, brk)
# rubocop:enable Style/RescueModifier
result << found if found
brk += 1
end
else
next if val.nil?

# rubocop:disable Style/RescueModifier
found = (LOOKUP[key][val][0] rescue nil) || validate(key, val, 0)
# rubocop:enable Style/RescueModifier
result << found if found
end
end
end.join(" ")
style, classes = process_arguments(args)

# This is much faster than Rails' presence method.
{
class: !classes || classes.empty? ? nil : classes,
style: !style || style.empty? ? nil : style
class: classes.blank? ? nil : classes.join(' '),
style: style.presence
}
# rubocop:enable Rails/Blank
end

private

# Processes the arguments and separates them into style and classes
# @param args [Hash] The arguments to process
# @return [Array] An array containing the style and classes
def process_arguments(args)
style = nil
classes = []

args.each do |key, val|
case key
when :classes
classes.unshift(validated_class_names(val)) if validated_class_names(val)
when :style
style = val
else
process_lookup(key, val, classes)
end
end

[style, classes]
end

# Processes a lookup key-value pair and adds appropriate classes
# @param key [Symbol] The lookup key
# @param val [Object] The value associated with the key
# @param classes [Array] The array to store the resulting classes
def process_lookup(key, val, classes)
return unless LOOKUP[key]

if val.is_a?(Array)
process_array_value(key, val, classes)
else
process_single_value(key, val, classes)
end
end

# Processes an array value for a given key and adds appropriate classes
# @param key [Symbol] The lookup key
# @param val [Array] The array value to process
# @param classes [Array] The array to store the resulting classes
def process_array_value(key, val, classes)
val.each_with_index do |item, index|
next if item.nil?

found = find_or_validate(key, item, index)
classes << found if found
end
end

# Processes a single value for a given key and adds the appropriate class
# @param key [Symbol] The lookup key
# @param val [Object] The value to process
# @param classes [Array] The array to store the resulting class
def process_single_value(key, val, classes)
return if val.nil?

found = find_or_validate(key, val, 0)
classes << found if found
end

# Finds a value in the LOOKUP or validates it
# @param key [Symbol] The lookup key
# @param item [Object] The item to find or validate
# @param index [Integer] The index in the breakpoints array
# @return [String, nil] The found or validated class, or nil if not found/valid
def find_or_validate(key, item, index)
LOOKUP.dig(key, item, index) || validate(key, item, index)
rescue StandardError
validate(key, item, index)
end

# Validates a value for a given key and breakpoint
# @param key [Symbol] The lookup key
# @param val [Object] The value to validate
# @param brk [Integer] The breakpoint index
# @return [String, nil] The validated class or nil if not valid
def validate(key, val, brk)
brk_str = Flowbite::Classify::Utilities::BREAKPOINTS[brk]
Flowbite::Classify::Utilities.validate(key, val, brk_str)
end

# Validates and returns the given class names
# @param classes [String] The class names to validate
# @return [String, nil] The validated class names or nil if blank
def validated_class_names(classes)
return if classes.blank?

if raise_on_invalid_options? && !ENV["FLOWBITE_WARNINGS_DISABLED"]
if raise_on_invalid_options? && !ENV['FLOWBITE_WARNINGS_DISABLED']
invalid_class_names =
classes.split.each_with_object([]) do |class_name, memo|
memo << class_name if Flowbite::Classify::Validation.invalid?(class_name)
end

# TODO: This needs to be reworked for our purposes
if invalid_class_names.any?
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."
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}. " \

Check warning on line 123 in embedded_gems/flowbite/lib/flowbite/classify.rb

View workflow job for this annotation

GitHub Actions / runner / rubocop

[rubocop] reported by reviewdog 🐶 Line is too long. [149/120] Raw Output: embedded_gems/flowbite/lib/flowbite/classify.rb:123:121: C: Layout/LineLength: Line is too long. [149/120]
'This warning will not be raised in production. Set PRIMER_WARNINGS_DISABLED=1 to disable this warning.'

Check warning on line 124 in embedded_gems/flowbite/lib/flowbite/classify.rb

View workflow job for this annotation

GitHub Actions / runner / rubocop

[rubocop] reported by reviewdog 🐶 Line is too long. [137/120] Raw Output: embedded_gems/flowbite/lib/flowbite/classify.rb:124:121: C: Layout/LineLength: Line is too long. [137/120]
end
end

classes
end

# Checks if the application is configured to raise on invalid options
# @return [Boolean] True if configured to raise on invalid options, false otherwise
def raise_on_invalid_options?
Rails.application.config.flowbite_view_components.raise_on_invalid_options
end
Expand Down

0 comments on commit 1aea921

Please sign in to comment.