html_attrs 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -2
  3. data/README.md +39 -10
  4. data/lib/html_attrs.rb +63 -19
  5. metadata +2 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 81f6299891fbc21d5780803b427e30dfb8e07b6280e518ff974e1e5d9f5d5bbc
4
- data.tar.gz: 58442fc06a5a775c197aba3ad445e23f15f7f68c3a9f69a07e9900b22640193f
3
+ metadata.gz: 4e275871a3e81adcaa8d6856c397adab49166f15b6f4357ae3e3606864b1559c
4
+ data.tar.gz: 73891eb35e4a0372a31c588f016ec14b1f7a834cccebea57718503b33a63eb18
5
5
  SHA512:
6
- metadata.gz: 4cd21bb1474c4ce8be233580048c8dd604e7249ab40d84e55e4eddbda1a3f2f1a2deb9ca7ecc74e665905a61dcab2df23f76341834845ba4ed9e7a9a3ab58e6a
7
- data.tar.gz: 492c60112a6c93c069f5e93ef43203d2a0f75b61456e40714d027c9604c45dec847dd1ea4fece6b91ceb1ae6025bac1e7ea1b2c65764299897e10ec87f141762
6
+ metadata.gz: 11166749fdd6b6680acb6a07f8743ca106c76679adde0804339b2e20ed57e1896d5fa6823f25aed5b1266447feaa2b7d0abe65fadae30e00fc49e07eb6aefd90
7
+ data.tar.gz: cdc3bf3931938151fa88fcb7c1a873d81776e779ff350c7643553b9e53e88a5c1382048fb15e85cad2e85628f2cfb6d523aa5200c5920fa72bd7c01ef47c7491
data/Gemfile.lock CHANGED
@@ -1,9 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- html_attrs (0.1.0)
4
+ html_attrs (1.1.0)
5
5
  actionview (>= 6.0)
6
- activesupport (>= 6.0)
7
6
 
8
7
  GEM
9
8
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -16,7 +16,7 @@ $ bundle add html_attrs
16
16
  ```ruby
17
17
  html_attrs = {
18
18
  class: 'bg-primary-500', data: { controller: 'popover', action: 'click->popover#toggle' }
19
- }.as_html_attrs
19
+ }
20
20
 
21
21
  html_attrs = html_attrs.smart_merge(
22
22
  class: 'border border-primary-500', data: { controller: 'slideover' }, href: '#'
@@ -28,6 +28,7 @@ html_attrs = html_attrs.smart_merge(
28
28
  data: { controller: 'popover slideover', action: 'click->popover#toggle' },
29
29
  href: '#'
30
30
  }
31
+ # Note: #smart_merge returns an HtmlAttrs object which is a subclass of Hash, so you can use it just like a hash.
31
32
  ```
32
33
 
33
34
  You can use this in helpers that accept HTML attributes as a hash, e.g:
@@ -62,7 +63,35 @@ You can also use the `to_s` method to get the string representation of the HTML
62
63
  </a>
63
64
  ```
64
65
 
66
+ Merging is done recursively:
67
+ * Strings are merged by concatenating them with a space.
68
+ * Arrays are merged with simple concatenation.
69
+ * Hashes are merged recursively using the above rules.
70
+ * Everything else is merged normally, just like with `Hash#merge`.
71
+
72
+ Super simple, but super powerful.
73
+
74
+ If one hash that has a string key and the other has a symbol key or vice-versa, we'll convert everything to whatever the first hash has.
75
+
76
+ ## Configuring mergeable attributes
77
+
78
+ By default, this gem merges `class`, `style` and `data` attributes recursively. Which should usually be more than enough. You can easily customize this by specifying `mergeable_attributes:` when calling `smart_merge`. e.g:
79
+ ```ruby
80
+ HtmlAttrs.new(class: 'bg-primary-500', id: 'test', aria_label: 'Help')
81
+ .smart_merge(aria_label: 'Another', href: '/test', mergeable_attributes: [:aria_label])
82
+ # => { class: 'bg-primary-500', id: 'test', aria_label: 'Help Another', href: '/test' }
83
+ ```
84
+
85
+ You can also just set `mergeable_attributes: :all` to merge everything. Or you can just use `smart_merge_all` which merges everything by default.
65
86
 
87
+ ```ruby
88
+ { class: 'bg-primary-500', id: 'test', aria_label: 'Help' }
89
+ .smart_merge_all(class: 'text-red-500', aria_label: 'Another', href: '/test')
90
+ # => { class: 'bg-primary-500 text-red-500', id: 'test', aria_label: 'Help Another', href: '/test' }
91
+ ```
92
+
93
+
94
+ ## Other ways to use
66
95
  Alternative, you can use the `HtmlAttrs` class directly, e.g:
67
96
  ```ruby
68
97
  HtmlAttrs.smart_merge(
@@ -81,18 +110,18 @@ html_attrs.smart_merge( id: 'test', class: 'border')
81
110
  # => { class: 'bg-primary-500 border', data: { controller: 'popover' }, id: 'test' }
82
111
  ```
83
112
 
84
- Under the hood, `HtmlAttrs` is a simple wrapper around `ActiveSupport::HashWithIndifferentAccess`, so you can use it just like any other hash. The only difference is `#smart_merge` and `to_s`.
113
+ Under the hood, `HtmlAttrs` is a simple wrapper around `Hash`, so you can use it just like any other hash. The only difference is `#smart_merge`, `#smart_merge_all` and `to_s`.
85
114
 
86
- Merging is done recursively. Strings are merged by concatenating them with a space. Arrays are merged with simple concatenation. Hashes are merged recursively using the above rules. Everything else is merged normally, just like with `Hash#merge`. Super simple, but super powerful.
115
+ <br/>
87
116
 
88
- ## Configuring mergeable attributes
117
+ ## Interested in a powerful Rails UI library?
89
118
 
90
- By default, this gem merges `class`, `style` and `data` attributes recursively. Which should usually be more than enough. You can easily customize this by specifying `mergeable_attributes:` when calling `smart_merge`. e.g:
91
- ```ruby
92
- HtmlAttrs.new(class: 'bg-primary-500', id: 'test', aria_label: 'Help')
93
- .smart_merge(aria_label: 'Another', href: '/test', mergeable_attributes: [:aria_label])
94
- # => { class: 'bg-primary-500', id: 'test', aria_label: 'Help Another', href: '/test' }
95
- ```
119
+ I am working on a super-powerful Rails UI library - components as well as templates & patterns.
120
+
121
+ [Please check this out if you're interested](https://owaiskhan.me/rails-ui-library).
122
+ <br/>
123
+ <br/>
124
+ <br/>
96
125
 
97
126
  ## Development
98
127
 
data/lib/html_attrs.rb CHANGED
@@ -1,16 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'action_view'
4
- require 'active_support/core_ext/hash/indifferent_access'
5
4
 
6
- class HtmlAttrs < HashWithIndifferentAccess
7
- VERSION = '1.0.0'
5
+ class HtmlAttrs < Hash
6
+ VERSION = '1.1.0'
8
7
  DEFAULT_MERGEABLE_ATTRIBUTES = %i[class style data].to_set
9
8
 
10
- def smart_merge(other)
11
- mergeable_attributes = other.delete(:mergeable_attributes) if other.is_a?(Hash) && other.key?(:mergeable_attributes)
9
+ def initialize(constructor = nil)
10
+ if constructor.respond_to?(:to_hash)
11
+ super()
12
+ update(constructor)
13
+
14
+ hash = constructor.is_a?(Hash) ? constructor : constructor.to_hash
15
+ self.default = hash.default if hash.default
16
+ self.default_proc = hash.default_proc if hash.default_proc
17
+ elsif constructor.nil?
18
+ super()
19
+ else
20
+ super(constructor)
21
+ end
22
+ end
23
+
24
+ def smart_merge(target)
25
+ if target.is_a?(Hash) && target.key?(:mergeable_attributes)
26
+ mergeable_attributes = target.delete(:mergeable_attributes)
27
+ end
12
28
  mergeable_attributes ||= DEFAULT_MERGEABLE_ATTRIBUTES
13
- self.class.smart_merge(self, other, mergeable_attributes: mergeable_attributes)
29
+ self.class.smart_merge(self, target, mergeable_attributes: mergeable_attributes)
30
+ end
31
+
32
+ def smart_merge_all(target)
33
+ target[:mergeable_attributes] = :all if target.is_a?(Hash)
34
+ smart_merge(target)
14
35
  end
15
36
 
16
37
  def to_s
@@ -18,37 +39,48 @@ class HtmlAttrs < HashWithIndifferentAccess
18
39
  end
19
40
 
20
41
  def self.smart_merge(other, target, mergeable_attributes: DEFAULT_MERGEABLE_ATTRIBUTES)
21
- other = other.with_indifferent_access if other.is_a?(Hash) && !other.is_a?(HashWithIndifferentAccess)
22
- target = target.with_indifferent_access if target.is_a?(Hash) && !target.is_a?(HashWithIndifferentAccess)
23
-
24
42
  return other if target.nil?
25
43
  return target if other.nil?
26
44
 
27
45
  if target.is_a?(Hash) || other.is_a?(Hash)
28
- raise 'Expected target to be a hash or nil' if !target.nil? && !target.is_a?(Hash)
29
- raise 'Expected other to be a hash or nil' if !other.nil? && !other.is_a?(Hash)
46
+ raise 'Expected target to be a hash or nil' unless target.is_a?(Hash)
47
+ raise 'Expected other to be a hash or nil' unless other.is_a?(Hash)
48
+
49
+ other = other.dup
50
+ target = target.dup
30
51
 
31
52
  target.each do |key, value|
32
- other[key] =
33
- if other.key?(key) && attribute_mergeable?(key, mergeable_attributes)
34
- smart_merge(other[key], value, mergeable_attributes: :all)
53
+ other_type_of_key = key.is_a?(Symbol) ? key.to_s : key.to_sym
54
+
55
+ key_with_value = if other.key?(key)
56
+ key
57
+ elsif other.key?(other_type_of_key)
58
+ other_type_of_key
59
+ else
60
+ nil
61
+ end
62
+
63
+ other[key_with_value || key] =
64
+ if key_with_value && attribute_mergeable?(key, mergeable_attributes)
65
+ smart_merge(other[key_with_value], value, mergeable_attributes: :all)
35
66
  else
36
67
  value
37
68
  end
38
69
  end
70
+
39
71
  return other
40
72
  end
41
73
 
42
74
  if target.is_a?(Array) || other.is_a?(Array)
43
- raise 'Expected target to be an array or nil' if !target.nil? && !target.is_a?(Array)
44
- raise 'Expected other to be an array or nil' if !other.nil? && !other.is_a?(Array)
75
+ raise 'Expected target to be an array or nil' unless target.is_a?(Array)
76
+ raise 'Expected other to be an array or nil' unless other.is_a?(Array)
45
77
 
46
- return (other || []).concat(target || [])
78
+ return (other.dup || []).concat(target.dup || [])
47
79
  end
48
80
 
49
81
  if target.is_a?(String) || other.is_a?(String)
50
- raise 'Expected target to be a string or nil' if !target.nil? && !target.is_a?(String)
51
- raise 'Expected other to be a string or nil' if !other.nil? && !other.is_a?(String)
82
+ raise 'Expected target to be a string or nil' unless target.is_a?(String)
83
+ raise 'Expected other to be a string or nil' unless other.is_a?(String)
52
84
 
53
85
  return [other.presence, target.presence].compact.join(' ')
54
86
  end
@@ -56,6 +88,10 @@ class HtmlAttrs < HashWithIndifferentAccess
56
88
  target
57
89
  end
58
90
 
91
+ def self.smart_merge_all(other, target)
92
+ smart_merge(other, target, mergeable_attributes: :all)
93
+ end
94
+
59
95
  def self.attribute_mergeable?(attribute, mergeable_attributes)
60
96
  return true if mergeable_attributes == :all
61
97
 
@@ -75,4 +111,12 @@ class Hash
75
111
  def as_html_attrs
76
112
  HtmlAttrs.new(self)
77
113
  end
114
+
115
+ def smart_merge(target)
116
+ as_html_attrs.smart_merge(target)
117
+ end
118
+
119
+ def smart_merge_all(target)
120
+ as_html_attrs.smart_merge_all(target)
121
+ end
78
122
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: html_attrs
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Owais
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-03-16 00:00:00.000000000 Z
11
+ date: 2024-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionview
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '6.0'
27
- - !ruby/object:Gem::Dependency
28
- name: activesupport
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '6.0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '6.0'
41
27
  description: A gem that provides a way to smartly merge HTML attributes
42
28
  email:
43
29
  - owaiswiz@gmail.com