Skip to content

Commit 32236ed

Browse files
committed
perf: Speeds up the performance by 2x
1 parent 2e6483f commit 32236ed

File tree

3 files changed

+26
-21
lines changed

3 files changed

+26
-21
lines changed

benchmark/run.rb

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,29 @@
1919
# puts clsx(*massive_args)
2020

2121
def clsx_optimized(*args)
22-
clsx_args_processor_optimized(*args).join(' ').presence
22+
result = clsx_args_processor_optimized(*args)
23+
result.uniq!
24+
result.join(' ').presence
2325
end
2426

2527
def clsx_args_processor_optimized(*args)
26-
result = Set.new
28+
result = []
29+
complex_keys = []
2730

31+
args.flatten!
2832
args.each do |arg|
2933
next if arg.blank? || arg.is_a?(TrueClass) || arg.is_a?(Proc)
34+
next result << arg.to_s unless arg.is_a?(Hash)
3035

31-
case arg
32-
when Array
33-
result += clsx_args_processor_optimized(*arg)
34-
when Hash
35-
arg.each { |k, v| result += clsx_args_processor_optimized(k) if v }
36-
else
37-
result << arg.to_s
38-
end
36+
arg.each { |key, value| complex_keys << key if value }
3937
end
4038

41-
result
39+
return result if complex_keys.empty?
40+
41+
result + clsx_args_processor_optimized(*complex_keys)
4242
end
4343

44-
unless clsx(*massive_args) == clsx_optimized(*massive_args)
44+
unless clsx(*massive_args).split.sort == clsx_optimized(*massive_args).split.sort
4545
puts 'The optimized version produces a different result!'
4646
puts "Original: #{clsx(*massive_args)}"
4747
puts "Optimized: #{clsx_optimized(*massive_args)}"

lib/clsx/helper.rb

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,32 @@ module Helper
2626
# <div class="<%= clsx('foo', active: @is_active, 'another-class' => @condition) %>">
2727
# <%= tag.div class: clsx(%w[foo bar], hidden: @condition) do ... end %>
2828
def clsx(*args)
29-
clsx_args_processor(*args).join(' ').presence
29+
result = clsx_args_processor(*args)
30+
result.uniq!
31+
result.join(' ').presence
3032
end
3133
alias cn clsx
3234

3335
private
3436

3537
# @param [Mixed] args
3638
#
37-
# @return [Set]
38-
def clsx_args_processor(*args) # rubocop:disable Metrics/CyclomaticComplexity
39-
result = Set.new
40-
args.flatten!
39+
# @return [Array]
40+
def clsx_args_processor(*args) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
41+
result = []
42+
complex_keys = []
4143

44+
args.flatten!
4245
args.each do |arg|
4346
next if arg.blank? || arg.is_a?(TrueClass) || arg.is_a?(Proc)
4447
next result << arg.to_s unless arg.is_a?(Hash)
4548

46-
arg.each { |k, v| result += clsx_args_processor(k) if v }
49+
arg.each { |key, value| complex_keys << key if value }
4750
end
4851

49-
result
52+
return result if complex_keys.empty?
53+
54+
result + clsx_args_processor(*complex_keys)
5055
end
5156
end
5257
end

test/clsx/helper_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def test_with_procs_and_lambdas
9292

9393
def test_with_mixed_types
9494
assert_nil clsx(nil, false, '', {}, [])
95-
assert_equal 'foo bar', clsx(nil, false, '', { foo: true }, ['bar'])
95+
assert_equal 'bar foo', clsx(nil, false, '', { foo: true }, ['bar'])
9696
end
9797

9898
# Source: https://github.com/lukeed/clsx/blob/master/test/classnames.js
@@ -104,7 +104,7 @@ def test_compatiblity_with_classnames
104104
assert_equal 'a 0 1 b', clsx('a', 0, nil, true, 1, 'b')
105105

106106
# (compat) supports heterogeneous arguments
107-
assert_equal 'a b', clsx({ a: true }, 'b', false)
107+
assert_equal 'b a', clsx({ a: true }, 'b', false)
108108

109109
# (compat) should be trimmed
110110
assert_equal 'b', clsx('', 'b', {}, '')

0 commit comments

Comments
 (0)