html-attributes-utils 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +3 -0
  3. data/lib/html_attributes_utils.rb +132 -0
  4. metadata +108 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a383443446570cb37c2c67e608c4bcde35ecf1b255eca392cbcc263d5a36ae76
4
+ data.tar.gz: 2b81b3e7929301ee349b330dae54131b79f93afe417db7e57b934cc4c8a96615
5
+ SHA512:
6
+ metadata.gz: 9c2568b9c1a67be8cad3df9ccd4eb5f11a9e612c27da3438acddc2587eaaee2d12138adf9397aeb43bb0d05e57b3fa3735df9caf0437a8cb6d53b8eddc937e59
7
+ data.tar.gz: ce81b1c86dcbf9e464a9268d02e595a60ee6eb30ba5fd0e5fa829a5f8ed233bee252da1a06716ba9ff0a06a565a70010d71d372acc42796e7c104c6ab222d98f
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # HTML Attributes Utilities
2
+
3
+ This is a small library intended to make it easier to deal with hashes of attributes.
@@ -0,0 +1,132 @@
1
+ require "active_support/core_ext/hash/keys"
2
+
3
+ module HTMLAttributesUtils
4
+ refine Hash do
5
+ # Merge the incoming hash into the current one in a way that suits
6
+ # HTML attributes.
7
+ #
8
+ # @param custom [Hash] the incoming hash
9
+ # @param parents [Array] used to keep track of the keys that have already been
10
+ # merged, *don't supply this unless the method is called during recursion*
11
+ # @mergeable_attributes [Array<Array<Symbol>>] Mergeable attributes are
12
+ # HTML attributes can contain lists made from space-separated strings. We
13
+ # convert them to arrays so they can be cleanly merged. Rails accepts them
14
+ # as arrays so there's no need to convert back to strings.
15
+ #
16
+ # @example
17
+ # original = { class: "red", data: { size: "medium", controller: "comment" } }
18
+ # incoming = { class: "blue", data: { controller: "reply" } }
19
+ #
20
+ # original.deep_merge_html_attributes(incoming)
21
+ #
22
+ # => { class: "blue", data: { size: "medium", controller: "reply" } }
23
+ #
24
+ def deep_merge_html_attributes(custom, parents = [], mergeable_attributes: default_mergeable_attributes)
25
+ return custom unless custom.is_a?(Hash)
26
+
27
+ overrides = custom.deep_symbolize_keys
28
+
29
+ deep_symbolize_keys.each_with_object(deep_symbolize_keys) { |(key, value), merged|
30
+ next unless overrides.key?(key)
31
+
32
+ merged[key] = combine_values(
33
+ value,
34
+ overrides[key],
35
+ parents: parents << key,
36
+ mergeable_attributes: mergeable_attributes
37
+ )
38
+
39
+ overrides.delete(key)
40
+ }.merge(overrides)
41
+ end
42
+
43
+ # Remove unwanted attributes from a the hash and any values that are hashes
44
+ # recursively. In particular we don't care for empty hashes, arrays,
45
+ # strings that are empty or just contain spaces and nils.
46
+ #
47
+ # It preserves +true+ and +false+.
48
+ #
49
+ # @return [Hash] the tidied hash
50
+ # @example
51
+ # { class: "blue", title: nil, lang: "", aria: { describedby: [] } }.deep_tidy_html_attributes
52
+ #
53
+ # => { class: "blue" }
54
+ #
55
+ def deep_tidy_html_attributes
56
+ each_with_object({}) do |(key, value), tidy|
57
+ (tidy[key] = tidy_value(value)) unless skippable_value?(value)
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def tidy_value(value)
64
+ case value
65
+ when Hash
66
+ value.deep_tidy_html_attributes.presence
67
+ when Array
68
+ value.reject(&:blank?).presence
69
+ when String
70
+ value.strip.presence
71
+ else
72
+ value
73
+ end
74
+ end
75
+
76
+ # Identiy attribute values we don't care about.
77
+ #
78
+ # We can't check for this using Rails' `#presence` because we want `false` to be
79
+ # included so some HTML attributes that default to on can be disabled, like
80
+ # `autocomplete: false`
81
+ #
82
+ # FIXME: there is probably a nicer way of doing this...
83
+ def skippable_value?(value)
84
+ return false if [true, false].include?(value)
85
+
86
+ value.blank?
87
+ end
88
+
89
+ def combine_values(value, override, **kwargs)
90
+ case split_attribute_list(value, **kwargs)
91
+ when Array
92
+ combine_array(value, override, **kwargs)
93
+ when Hash
94
+ combine_hash(value, override, **kwargs)
95
+ else
96
+ split_attribute_list(override, **kwargs)
97
+ end
98
+ end
99
+
100
+ def combine_array(originals, overrides, parents:, mergeable_attributes:)
101
+ return overrides if overrides.nil?
102
+ return overrides unless mergeable_attributes.include?(parents)
103
+
104
+ (try_split(originals) + try_split(overrides)).uniq
105
+ end
106
+
107
+ def try_split(value)
108
+ value.is_a?(String) ? value.split : value
109
+ end
110
+
111
+ def combine_hash(originals, overrides, parents:, mergeable_attributes:)
112
+ originals.deep_merge_html_attributes(overrides, parents, mergeable_attributes: mergeable_attributes)
113
+ end
114
+
115
+ def split_attribute_list(value, parents:, mergeable_attributes:)
116
+ return value.split if value.is_a?(String) && mergeable_attributes.include?(parents)
117
+
118
+ value
119
+ end
120
+
121
+ def default_mergeable_attributes
122
+ [
123
+ %i(class),
124
+ %i(aria controls),
125
+ %i(aria describedby),
126
+ %i(aria flowto),
127
+ %i(aria labelledby),
128
+ %i(aria owns),
129
+ ]
130
+ end
131
+ end
132
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: html-attributes-utils
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Peter Yates
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-03-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 6.1.4.4
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 6.1.4.4
27
+ - !ruby/object:Gem::Dependency
28
+ name: debug
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.11.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.11.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop-govuk
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 4.3.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 4.3.0
69
+ description: A small collection of utilities to ease working with hashes of HTML attributes
70
+ email:
71
+ - peter.yates@graphia.co.uk
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - README.md
77
+ - lib/html_attributes_utils.rb
78
+ homepage: https://github.com/DFE-Digital/html-attributes-utils
79
+ licenses:
80
+ - MIT
81
+ metadata:
82
+ bug_tracker_uri: https://github.com/DFE-Digital/html-attributes-utils/issues
83
+ changelog_uri: https://github.com/DFE-Digital/html-attributes-utils/releases
84
+ homepage_uri: https://govuk-form-builder.netlify.app
85
+ source_code_uri: https://github.com/DFE-Digital/html-attributes-utils
86
+ github_repo: https://github.com/DFE-Digital/html-attributes-utils
87
+ documentation_uri: https://www.rubydoc.info/gems/html-attributes-utils/
88
+ rubygems_mfa_required: 'true'
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubygems_version: 3.3.7
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: HTML attribute hash utilities
108
+ test_files: []