tailwind_merge 1.5.1 → 1.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- data/benchmark/benchmark.rb +75 -0
- data/lib/tailwind_merge/class_group_utils.rb +8 -7
- data/lib/tailwind_merge/config.rb +17 -1
- data/lib/tailwind_merge/parse_class_name.rb +36 -12
- data/lib/tailwind_merge/validators.rb +2 -2
- data/lib/tailwind_merge/version.rb +1 -1
- data/lib/tailwind_merge.rb +14 -11
- metadata +7 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '059b8e52b3a7bc182e6cae5db2a2c8dee46aa1d1176b6b7d26dd7f2313f566cc'
|
|
4
|
+
data.tar.gz: c94346250084798c59da34357f9e16acc058943eb5e64f759f87b06701adac7c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 61dc28329c357f7b1bb060b499c56d6d419672f2ccade9a3cb8442ae1c77da2f3c9c9526894c836294ef6128a78041adbd1b0c291b9c6b7fa33ef34b527400f1
|
|
7
|
+
data.tar.gz: 76ea9d360488b4945ce4b2a3ac642fdd20a0cd0eee20b85a3baec2f363ce3dcddbbd3dc9a6be2f7207d30a5776aeff328df792b742770e5b2d1c63867a076eac
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
## [1.5.3](https://github.com/gjtorikian/tailwind_merge/compare/v1.5.2...v1.5.3) (2026-08-11)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
* **config:** classify shadow-inner into the shadow class group ([99bccc2](https://github.com/gjtorikian/tailwind_merge/commit/99bccc2b66d5a6e94735515676102534a3f29e37))
|
|
6
|
+
|
|
7
|
+
### Performance Improvements
|
|
8
|
+
|
|
9
|
+
* **parse:** skip modifiers array alloc for no-modifier classes ([0ee620e](https://github.com/gjtorikian/tailwind_merge/commit/0ee620e7e464074fb490fd363afaa5b404a4faf4))
|
|
10
|
+
|
|
11
|
+
### Miscellaneous Chores
|
|
12
|
+
|
|
13
|
+
* trigger release-please run ([65e80ae](https://github.com/gjtorikian/tailwind_merge/commit/65e80ae41d08e813c0d6ce9317aa235454bfc935))
|
|
14
|
+
* **config:** deep-freeze DEFAULTS to prevent global-state mutation ([9bf4778](https://github.com/gjtorikian/tailwind_merge/commit/9bf47789b778b4d1e0503e9b69ce30d407826483))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# [v1.5.2] - 06-07-2026
|
|
18
|
+
## What's Changed
|
|
19
|
+
* fix: thread-safety of Merger's internal LRU cache by @svyatov in https://github.com/gjtorikian/tailwind_merge/pull/79
|
|
20
|
+
* perf: reduce allocations in merge hot path (~35% faster, ~56% fewer allocations) by @svyatov in https://github.com/gjtorikian/tailwind_merge/pull/80
|
|
21
|
+
|
|
22
|
+
## New Contributors
|
|
23
|
+
* @svyatov made their first contribution in https://github.com/gjtorikian/tailwind_merge/pull/79
|
|
24
|
+
|
|
25
|
+
**Full Changelog**: https://github.com/gjtorikian/tailwind_merge/compare/v1.5.1...v1.5.2
|
|
1
26
|
# [v1.5.1] - 18-05-2026
|
|
2
27
|
## What's Changed
|
|
3
28
|
* Fix memory leak when passing in config by @ibrahima in https://github.com/gjtorikian/tailwind_merge/pull/77
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Benchmark for the cache-miss merge path.
|
|
4
|
+
#
|
|
5
|
+
# Usage: ruby benchmark/benchmark.rb
|
|
6
|
+
#
|
|
7
|
+
# Measures `merge_class_list` directly: `merge` memoizes whole input strings
|
|
8
|
+
# in an LRU cache, so benchmarking it with a fixed corpus would mostly
|
|
9
|
+
# measure a Hash lookup. The uncached path is what runs for every
|
|
10
|
+
# first-seen class string in a real app.
|
|
11
|
+
|
|
12
|
+
require "bundler/inline"
|
|
13
|
+
|
|
14
|
+
gemfile do
|
|
15
|
+
source "https://rubygems.org"
|
|
16
|
+
gem "benchmark-ips"
|
|
17
|
+
gem "memory_profiler"
|
|
18
|
+
gem "sin_lru_redux"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
require_relative "../lib/tailwind_merge"
|
|
22
|
+
|
|
23
|
+
CORPUS = [
|
|
24
|
+
# simple conflicts
|
|
25
|
+
"px-2 px-4",
|
|
26
|
+
"text-sm text-lg font-bold",
|
|
27
|
+
"block inline flex",
|
|
28
|
+
# modifiers
|
|
29
|
+
"hover:focus:!bg-red-500 hover:focus:!bg-blue-600",
|
|
30
|
+
"md:hover:underline md:hover:no-underline",
|
|
31
|
+
"dark:sm:hover:bg-gray-800 dark:sm:hover:bg-gray-900",
|
|
32
|
+
# postfix modifiers
|
|
33
|
+
"bg-red-500/50 bg-red-500/75",
|
|
34
|
+
"text-white/90 leading-7",
|
|
35
|
+
# arbitrary values / properties / variables
|
|
36
|
+
"p-[2px] p-[4px]",
|
|
37
|
+
"[mask-type:luminance] [mask-type:alpha]",
|
|
38
|
+
"bg-(--brand-color) bg-red-500",
|
|
39
|
+
"content-['hello'] content-['world']",
|
|
40
|
+
# non-tailwind classes mixed in
|
|
41
|
+
"my-custom-class px-2 another-class px-4",
|
|
42
|
+
# long realistic string (shadcn-style button + overrides)
|
|
43
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md " \
|
|
44
|
+
"text-sm font-medium transition-colors focus-visible:outline-none " \
|
|
45
|
+
"focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none " \
|
|
46
|
+
"disabled:opacity-50 bg-primary text-primary-foreground shadow " \
|
|
47
|
+
"hover:bg-primary/90 h-9 px-4 py-2 rounded-lg px-6 text-base w-full",
|
|
48
|
+
].freeze
|
|
49
|
+
|
|
50
|
+
merger = TailwindMerge::Merger.new
|
|
51
|
+
|
|
52
|
+
# sanity check: outputs must be non-empty
|
|
53
|
+
CORPUS.each do |s|
|
|
54
|
+
result = merger.send(:merge_class_list, s)
|
|
55
|
+
raise "unexpected empty result for #{s.inspect}" if result.empty?
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
puts "ruby #{RUBY_VERSION} (#{RUBY_ENGINE}), tailwind_merge #{TailwindMerge::VERSION}"
|
|
59
|
+
puts
|
|
60
|
+
|
|
61
|
+
Benchmark.ips do |x|
|
|
62
|
+
x.report("merge_class_list (corpus of #{CORPUS.size})") do
|
|
63
|
+
CORPUS.each { |s| merger.send(:merge_class_list, s) }
|
|
64
|
+
end
|
|
65
|
+
x.report("merge_class_list (long string)") do
|
|
66
|
+
merger.send(:merge_class_list, CORPUS.last)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
puts
|
|
71
|
+
report = MemoryProfiler.report do
|
|
72
|
+
CORPUS.each { |s| merger.send(:merge_class_list, s) }
|
|
73
|
+
end
|
|
74
|
+
puts "allocations for one corpus pass: " \
|
|
75
|
+
"#{report.total_allocated} objects, #{report.total_allocated_memsize} bytes"
|
|
@@ -23,25 +23,26 @@ module TailwindMerge
|
|
|
23
23
|
get_group_recursive(class_parts, @class_map) || get_group_id_for_arbitrary_property(class_name)
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
def get_group_recursive(class_parts, class_part_object)
|
|
27
|
-
return class_part_object[:class_group_id] if class_parts.
|
|
26
|
+
def get_group_recursive(class_parts, class_part_object, index = 0)
|
|
27
|
+
return class_part_object[:class_group_id] if index == class_parts.length
|
|
28
28
|
|
|
29
|
-
current_class_part = class_parts
|
|
29
|
+
current_class_part = class_parts[index]
|
|
30
30
|
|
|
31
31
|
next_class_part_object = class_part_object[:next_part][current_class_part]
|
|
32
32
|
|
|
33
33
|
if next_class_part_object
|
|
34
|
-
class_group_from_next_class_part = get_group_recursive(class_parts
|
|
34
|
+
class_group_from_next_class_part = get_group_recursive(class_parts, next_class_part_object, index + 1)
|
|
35
35
|
return class_group_from_next_class_part if class_group_from_next_class_part
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
return if class_part_object[:validators].empty?
|
|
39
39
|
|
|
40
|
-
class_rest = class_parts.join(CLASS_PART_SEPARATOR)
|
|
40
|
+
class_rest = index.zero? ? class_parts.join(CLASS_PART_SEPARATOR) : class_parts[index..].join(CLASS_PART_SEPARATOR)
|
|
41
41
|
|
|
42
|
+
# Theme procs are expanded at trie-build time (see process_classes_recursively),
|
|
43
|
+
# so validators here are always plain value validators.
|
|
42
44
|
result = class_part_object[:validators].find do |v|
|
|
43
|
-
|
|
44
|
-
from_theme?(validator) ? validator.call(@config) : validator.call(class_rest)
|
|
45
|
+
v[:validator].call(class_rest)
|
|
45
46
|
end
|
|
46
47
|
|
|
47
48
|
result&.fetch(:class_group_id, nil)
|
|
@@ -6,6 +6,19 @@ module TailwindMerge
|
|
|
6
6
|
module Config
|
|
7
7
|
include Validators
|
|
8
8
|
|
|
9
|
+
class << self
|
|
10
|
+
# Recursively freezes nested Hash/Array structures so shared config
|
|
11
|
+
# constants can't be mutated in place. Keys are strings/symbols and are
|
|
12
|
+
# already immutable, so only values need walking.
|
|
13
|
+
private def deep_freeze(object)
|
|
14
|
+
case object
|
|
15
|
+
when Hash then object.each_value { |value| deep_freeze(value) }
|
|
16
|
+
when Array then object.each { |value| deep_freeze(value) }
|
|
17
|
+
end
|
|
18
|
+
object.freeze
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
9
22
|
THEME_KEYS = [
|
|
10
23
|
"color",
|
|
11
24
|
"font",
|
|
@@ -1432,6 +1445,8 @@ module TailwindMerge
|
|
|
1432
1445
|
"shadow" => [
|
|
1433
1446
|
# Deprecated since Tailwind CSS v4.0.0
|
|
1434
1447
|
"",
|
|
1448
|
+
# Deprecated since Tailwind CSS v4.0.0
|
|
1449
|
+
"inner",
|
|
1435
1450
|
"none",
|
|
1436
1451
|
THEME_SHADOW,
|
|
1437
1452
|
IS_ARBITRARY_VARIABLE_SHADOW,
|
|
@@ -2441,7 +2456,8 @@ module TailwindMerge
|
|
|
2441
2456
|
"placeholder",
|
|
2442
2457
|
"selection",
|
|
2443
2458
|
],
|
|
2444
|
-
}
|
|
2459
|
+
}
|
|
2460
|
+
deep_freeze(DEFAULTS)
|
|
2445
2461
|
|
|
2446
2462
|
def merge_config(incoming_config)
|
|
2447
2463
|
extended_config = TailwindMerge::Config::DEFAULTS.dup
|
|
@@ -6,9 +6,17 @@ module TailwindMerge
|
|
|
6
6
|
|
|
7
7
|
module ParseClassName
|
|
8
8
|
IMPORTANT_MODIFIER = "!"
|
|
9
|
+
EMPTY_MODIFIERS = [].freeze
|
|
9
10
|
MODIFIER_SEPARATOR = ":"
|
|
10
11
|
MODIFIER_SEPARATOR_LENGTH = MODIFIER_SEPARATOR.length
|
|
11
12
|
|
|
13
|
+
MODIFIER_SEPARATOR_BYTE = MODIFIER_SEPARATOR.ord
|
|
14
|
+
POSTFIX_SEPARATOR_BYTE = "/".ord
|
|
15
|
+
OPEN_BRACKET_BYTE = "[".ord
|
|
16
|
+
CLOSE_BRACKET_BYTE = "]".ord
|
|
17
|
+
OPEN_PAREN_BYTE = "(".ord
|
|
18
|
+
CLOSE_PAREN_BYTE = ")".ord
|
|
19
|
+
|
|
12
20
|
##
|
|
13
21
|
# Parse class name into parts.
|
|
14
22
|
#
|
|
@@ -22,7 +30,7 @@ module TailwindMerge
|
|
|
22
30
|
else
|
|
23
31
|
return TailwindClass.new(
|
|
24
32
|
is_external: true,
|
|
25
|
-
modifiers:
|
|
33
|
+
modifiers: EMPTY_MODIFIERS,
|
|
26
34
|
has_important_modifier: false,
|
|
27
35
|
base_class_name: class_name,
|
|
28
36
|
maybe_postfix_modifier_position: nil,
|
|
@@ -30,32 +38,48 @@ module TailwindMerge
|
|
|
30
38
|
end
|
|
31
39
|
end
|
|
32
40
|
|
|
33
|
-
|
|
41
|
+
# Stays nil until the first modifier separator, so the common no-modifier
|
|
42
|
+
# class (`px-2`, `block`) never allocates an array.
|
|
43
|
+
modifiers = nil
|
|
34
44
|
|
|
35
45
|
bracket_depth = 0
|
|
36
46
|
paren_depth = 0
|
|
37
47
|
modifier_start = 0
|
|
38
48
|
postfix_modifier_position = nil
|
|
39
49
|
|
|
40
|
-
|
|
50
|
+
# Byte-wise scan: all separators are ASCII, so byte positions are safe
|
|
51
|
+
# for multibyte class names (UTF-8 continuation bytes never match ASCII).
|
|
52
|
+
# Positions produced here (including maybe_postfix_modifier_position)
|
|
53
|
+
# are byte offsets and must be consumed with String#byteslice.
|
|
54
|
+
index = 0
|
|
55
|
+
size = class_name.bytesize
|
|
56
|
+
while index < size
|
|
57
|
+
byte = class_name.getbyte(index)
|
|
58
|
+
|
|
41
59
|
if bracket_depth.zero? && paren_depth.zero?
|
|
42
|
-
if
|
|
43
|
-
modifiers << class_name
|
|
60
|
+
if byte == MODIFIER_SEPARATOR_BYTE
|
|
61
|
+
(modifiers ||= []) << class_name.byteslice(modifier_start, index - modifier_start)
|
|
44
62
|
modifier_start = index + MODIFIER_SEPARATOR_LENGTH
|
|
63
|
+
index += 1
|
|
45
64
|
next
|
|
46
|
-
elsif
|
|
65
|
+
elsif byte == POSTFIX_SEPARATOR_BYTE
|
|
47
66
|
postfix_modifier_position = index
|
|
67
|
+
index += 1
|
|
48
68
|
next
|
|
49
69
|
end
|
|
50
70
|
end
|
|
51
71
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
72
|
+
case byte
|
|
73
|
+
when OPEN_BRACKET_BYTE then bracket_depth += 1
|
|
74
|
+
when CLOSE_BRACKET_BYTE then bracket_depth -= 1
|
|
75
|
+
when OPEN_PAREN_BYTE then paren_depth += 1
|
|
76
|
+
when CLOSE_PAREN_BYTE then paren_depth -= 1
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
index += 1
|
|
56
80
|
end
|
|
57
81
|
|
|
58
|
-
base_class_name_with_important_modifier = modifiers
|
|
82
|
+
base_class_name_with_important_modifier = modifiers ? class_name.byteslice(modifier_start, size - modifier_start) : class_name
|
|
59
83
|
|
|
60
84
|
base_class_name, has_important_modifier = strip_important_modifier(base_class_name_with_important_modifier)
|
|
61
85
|
|
|
@@ -65,7 +89,7 @@ module TailwindMerge
|
|
|
65
89
|
|
|
66
90
|
TailwindClass.new(
|
|
67
91
|
is_external: false,
|
|
68
|
-
modifiers
|
|
92
|
+
modifiers: modifiers || EMPTY_MODIFIERS,
|
|
69
93
|
has_important_modifier:,
|
|
70
94
|
base_class_name: base_class_name,
|
|
71
95
|
maybe_postfix_modifier_position:,
|
|
@@ -97,7 +97,7 @@ module TailwindMerge
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
IS_ARBITRARY_VALUE = ->(value) {
|
|
100
|
-
ARBITRARY_VALUE_REGEX.match(value)
|
|
100
|
+
ARBITRARY_VALUE_REGEX.match?(value)
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
IS_ARBITRARY_LENGTH = ->(value) {
|
|
@@ -129,7 +129,7 @@ module TailwindMerge
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
IS_ARBITRARY_VARIABLE = ->(value) {
|
|
132
|
-
ARBITRARY_VARIABLE_REGEX.match(value)
|
|
132
|
+
ARBITRARY_VARIABLE_REGEX.match?(value)
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
IS_ARBITRARY_VARIABLE_LENGTH = ->(value) {
|
data/lib/tailwind_merge.rb
CHANGED
|
@@ -18,14 +18,13 @@ module TailwindMerge
|
|
|
18
18
|
include ParseClassName
|
|
19
19
|
include SortModifiers
|
|
20
20
|
|
|
21
|
-
SPLIT_CLASSES_REGEX = /\s+/
|
|
22
|
-
|
|
23
21
|
def initialize(config: {})
|
|
24
22
|
@config = merge_config(config)
|
|
25
23
|
@config[:important_modifier] = @config[:important_modifier].to_s
|
|
26
24
|
@class_utils = TailwindMerge::ClassGroupUtils.new(@config)
|
|
27
|
-
@cache = LruRedux::
|
|
25
|
+
@cache = LruRedux::ThreadSafeCache.new(@config[:cache_size], @config[:ignore_empty_cache])
|
|
28
26
|
@postfix_lookup_class_group_ids = build_postfix_lookup_class_group_ids(@config[:postfix_lookup_class_groups])
|
|
27
|
+
@order_sensitive_modifiers = Set.new(@config[:order_sensitive_modifiers]).freeze
|
|
29
28
|
end
|
|
30
29
|
|
|
31
30
|
def merge(classes)
|
|
@@ -42,14 +41,14 @@ module TailwindMerge
|
|
|
42
41
|
# @example 'float'
|
|
43
42
|
# @example 'hover:focus:bg-color'
|
|
44
43
|
# @example 'md:!pr'
|
|
45
|
-
|
|
46
|
-
return "" if
|
|
44
|
+
class_names = class_list.split
|
|
45
|
+
return "" if class_names.empty?
|
|
47
46
|
|
|
48
47
|
class_groups_in_conflict = Set.new
|
|
49
48
|
|
|
50
49
|
merged_classes = []
|
|
51
50
|
|
|
52
|
-
|
|
51
|
+
class_names.reverse_each do |original_class_name|
|
|
53
52
|
result = parse_class_name(original_class_name, prefix: @config[:prefix])
|
|
54
53
|
is_external = result.is_external
|
|
55
54
|
modifiers = result.modifiers
|
|
@@ -65,7 +64,8 @@ module TailwindMerge
|
|
|
65
64
|
has_postfix_modifier = maybe_postfix_modifier_position ? true : false
|
|
66
65
|
|
|
67
66
|
if has_postfix_modifier
|
|
68
|
-
|
|
67
|
+
# maybe_postfix_modifier_position is a byte offset (see ParseClassName)
|
|
68
|
+
base_class_name_without_postfix = base_class_name.byteslice(0, maybe_postfix_modifier_position)
|
|
69
69
|
class_group_id = @class_utils.class_group_id(base_class_name_without_postfix)
|
|
70
70
|
|
|
71
71
|
if class_group_id && @postfix_lookup_class_group_ids[class_group_id]
|
|
@@ -97,10 +97,13 @@ module TailwindMerge
|
|
|
97
97
|
has_postfix_modifier = false
|
|
98
98
|
end
|
|
99
99
|
|
|
100
|
-
variant_modifier = sort_modifiers(modifiers, @
|
|
100
|
+
variant_modifier = sort_modifiers(modifiers, @order_sensitive_modifiers).join(":")
|
|
101
101
|
|
|
102
102
|
modifier_id = has_important_modifier ? "#{variant_modifier}#{IMPORTANT_MODIFIER}" : variant_modifier
|
|
103
|
-
|
|
103
|
+
has_modifier_id = !modifier_id.empty?
|
|
104
|
+
# `to_s` matches the previous interpolation behavior: group ids may be
|
|
105
|
+
# Symbols (custom configs) or Strings (defaults, where to_s is free)
|
|
106
|
+
class_id = has_modifier_id ? "#{modifier_id}#{class_group_id}" : class_group_id.to_s
|
|
104
107
|
|
|
105
108
|
# Tailwind class omitted due to conflict
|
|
106
109
|
next if class_groups_in_conflict.include?(class_id)
|
|
@@ -108,14 +111,14 @@ module TailwindMerge
|
|
|
108
111
|
class_groups_in_conflict << class_id
|
|
109
112
|
|
|
110
113
|
@class_utils.get_conflicting_class_group_ids(class_group_id, has_postfix_modifier).each do |conflicting_id|
|
|
111
|
-
class_groups_in_conflict << "#{modifier_id}#{conflicting_id}"
|
|
114
|
+
class_groups_in_conflict << (has_modifier_id ? "#{modifier_id}#{conflicting_id}" : conflicting_id.to_s)
|
|
112
115
|
end
|
|
113
116
|
|
|
114
117
|
# Tailwind class not in conflict
|
|
115
118
|
merged_classes << original_class_name
|
|
116
119
|
end
|
|
117
120
|
|
|
118
|
-
merged_classes.reverse
|
|
121
|
+
merged_classes.reverse!.join(" ")
|
|
119
122
|
end
|
|
120
123
|
|
|
121
124
|
private def build_postfix_lookup_class_group_ids(class_group_ids)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tailwind_merge
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.5.
|
|
4
|
+
version: 1.5.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Garen J. Torikian
|
|
@@ -64,6 +64,7 @@ files:
|
|
|
64
64
|
- LICENSE.txt
|
|
65
65
|
- README.md
|
|
66
66
|
- Rakefile
|
|
67
|
+
- benchmark/benchmark.rb
|
|
67
68
|
- lib/tailwind_merge.rb
|
|
68
69
|
- lib/tailwind_merge/class_group_utils.rb
|
|
69
70
|
- lib/tailwind_merge/config.rb
|
|
@@ -73,15 +74,15 @@ files:
|
|
|
73
74
|
- lib/tailwind_merge/version.rb
|
|
74
75
|
- script/test
|
|
75
76
|
- tailwind_merge.gemspec
|
|
76
|
-
homepage: https://github.com/gjtorikian/tailwind_merge/tree/v1.5.
|
|
77
|
+
homepage: https://github.com/gjtorikian/tailwind_merge/tree/v1.5.3
|
|
77
78
|
licenses:
|
|
78
79
|
- MIT
|
|
79
80
|
metadata:
|
|
80
|
-
homepage_uri: https://github.com/gjtorikian/tailwind_merge/tree/v1.5.
|
|
81
|
-
source_code_uri: https://github.com/gjtorikian/tailwind_merge/tree/v1.5.
|
|
82
|
-
changelog_uri: https://github.com/gjtorikian/tailwind_merge/blob/v1.5.
|
|
81
|
+
homepage_uri: https://github.com/gjtorikian/tailwind_merge/tree/v1.5.3
|
|
82
|
+
source_code_uri: https://github.com/gjtorikian/tailwind_merge/tree/v1.5.3
|
|
83
|
+
changelog_uri: https://github.com/gjtorikian/tailwind_merge/blob/v1.5.3/CHANGELOG.md
|
|
83
84
|
bug_tracker_uri: https://github.com/gjtorikian/tailwind_merge/issues
|
|
84
|
-
documentation_uri: https://rubydoc.info/gems/tailwind_merge/1.5.
|
|
85
|
+
documentation_uri: https://rubydoc.info/gems/tailwind_merge/1.5.3
|
|
85
86
|
funding_uri: https://github.com/sponsors/gjtorikian
|
|
86
87
|
rubygems_mfa_required: 'true'
|
|
87
88
|
rdoc_options: []
|