html-attributes-utils 0.9.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 (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: []