html_attrs 1.0.0 → 1.1.1

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 +64 -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: 737a5e8f52a5be75f40e73f69c877de82a91eb1819f3df87fbe0b0132e004b03
4
+ data.tar.gz: b8e415cab20c7a73a434e6ba8097631cf423d6d2bef6b1c0032cbe4c806804e7
5
5
  SHA512:
6
- metadata.gz: 4cd21bb1474c4ce8be233580048c8dd604e7249ab40d84e55e4eddbda1a3f2f1a2deb9ca7ecc74e665905a61dcab2df23f76341834845ba4ed9e7a9a3ab58e6a
7
- data.tar.gz: 492c60112a6c93c069f5e93ef43203d2a0f75b61456e40714d027c9604c45dec847dd1ea4fece6b91ceb1ae6025bac1e7ea1b2c65764299897e10ec87f141762
6
+ metadata.gz: 712b755dc31f8af3e613b492ef999a53ba1b8c0d53f2a63b9c6c81ffbe1be63c01a6d4bd2b268b68455be9f6f7b70e13ed5a49e9ff9b4a0cbcb6598abd249d05
7
+ data.tar.gz: ed08332771a5cb04194e93b5e6c3405f3d3322c15f513d865777b172de0af1140a104e6ff0920f595aa483f8fd60c091113427952ab86f9cf781097e4f4e849d
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,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'action_view'
4
- require 'active_support/core_ext/hash/indifferent_access'
4
+ require 'bigdecimal' # tag_options references BigDecimal. Just require it here so non autoloading environments work.
5
5
 
6
- class HtmlAttrs < HashWithIndifferentAccess
7
- VERSION = '1.0.0'
6
+ class HtmlAttrs < Hash
7
+ VERSION = '1.1.1'
8
8
  DEFAULT_MERGEABLE_ATTRIBUTES = %i[class style data].to_set
9
9
 
10
- def smart_merge(other)
11
- mergeable_attributes = other.delete(:mergeable_attributes) if other.is_a?(Hash) && other.key?(:mergeable_attributes)
10
+ def initialize(constructor = nil)
11
+ if constructor.respond_to?(:to_hash)
12
+ super()
13
+ update(constructor)
14
+
15
+ hash = constructor.is_a?(Hash) ? constructor : constructor.to_hash
16
+ self.default = hash.default if hash.default
17
+ self.default_proc = hash.default_proc if hash.default_proc
18
+ elsif constructor.nil?
19
+ super()
20
+ else
21
+ super(constructor)
22
+ end
23
+ end
24
+
25
+ def smart_merge(target)
26
+ if target.is_a?(Hash) && target.key?(:mergeable_attributes)
27
+ mergeable_attributes = target.delete(:mergeable_attributes)
28
+ end
12
29
  mergeable_attributes ||= DEFAULT_MERGEABLE_ATTRIBUTES
13
- self.class.smart_merge(self, other, mergeable_attributes: mergeable_attributes)
30
+ self.class.smart_merge(self, target, mergeable_attributes: mergeable_attributes)
31
+ end
32
+
33
+ def smart_merge_all(target)
34
+ target[:mergeable_attributes] = :all if target.is_a?(Hash)
35
+ smart_merge(target)
14
36
  end
15
37
 
16
38
  def to_s
@@ -18,37 +40,48 @@ class HtmlAttrs < HashWithIndifferentAccess
18
40
  end
19
41
 
20
42
  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
43
  return other if target.nil?
25
44
  return target if other.nil?
26
45
 
27
46
  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)
47
+ raise 'Expected target to be a hash or nil' unless target.is_a?(Hash)
48
+ raise 'Expected other to be a hash or nil' unless other.is_a?(Hash)
49
+
50
+ other = other.dup
51
+ target = target.dup
30
52
 
31
53
  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)
54
+ other_type_of_key = key.is_a?(Symbol) ? key.to_s : key.to_sym
55
+
56
+ key_with_value = if other.key?(key)
57
+ key
58
+ elsif other.key?(other_type_of_key)
59
+ other_type_of_key
60
+ else
61
+ nil
62
+ end
63
+
64
+ other[key_with_value || key] =
65
+ if key_with_value && attribute_mergeable?(key, mergeable_attributes)
66
+ smart_merge(other[key_with_value], value, mergeable_attributes: :all)
35
67
  else
36
68
  value
37
69
  end
38
70
  end
71
+
39
72
  return other
40
73
  end
41
74
 
42
75
  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)
76
+ raise 'Expected target to be an array or nil' unless target.is_a?(Array)
77
+ raise 'Expected other to be an array or nil' unless other.is_a?(Array)
45
78
 
46
- return (other || []).concat(target || [])
79
+ return (other.dup || []).concat(target.dup || [])
47
80
  end
48
81
 
49
82
  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)
83
+ raise 'Expected target to be a string or nil' unless target.is_a?(String)
84
+ raise 'Expected other to be a string or nil' unless other.is_a?(String)
52
85
 
53
86
  return [other.presence, target.presence].compact.join(' ')
54
87
  end
@@ -56,6 +89,10 @@ class HtmlAttrs < HashWithIndifferentAccess
56
89
  target
57
90
  end
58
91
 
92
+ def self.smart_merge_all(other, target)
93
+ smart_merge(other, target, mergeable_attributes: :all)
94
+ end
95
+
59
96
  def self.attribute_mergeable?(attribute, mergeable_attributes)
60
97
  return true if mergeable_attributes == :all
61
98
 
@@ -75,4 +112,12 @@ class Hash
75
112
  def as_html_attrs
76
113
  HtmlAttrs.new(self)
77
114
  end
115
+
116
+ def smart_merge(target)
117
+ as_html_attrs.smart_merge(target)
118
+ end
119
+
120
+ def smart_merge_all(target)
121
+ as_html_attrs.smart_merge_all(target)
122
+ end
78
123
  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.1
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-26 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