html_attrs 1.0.0 → 1.1.0

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.
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