tag_options 0.9.0 → 0.9.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a5fb04a9c092cabe732ee9a7807861f8a2587b22e9221836d42bf9c2400856be
4
- data.tar.gz: 229782a164b543562f6f988a7afb486c26715d55f825862bd4a32b0dfd33e42c
3
+ metadata.gz: 83e261e9adfa9aeb2c3dff7ea1a96feef6b879643232d84135739204bbac2eb1
4
+ data.tar.gz: 4f5017d33651e2274f6a28200c402e840ec044c5c33e9458f73720177cbf6cc1
5
5
  SHA512:
6
- metadata.gz: 484238573bfd185df2f607efff78d33258c2dbbeff55498ebf1d5d39e9610e374676d8e0a0ebafc32b39bf942717c21e843290d724b3f3ec129a5936ccaf7bb7
7
- data.tar.gz: 5705a6389364ef3d5761e77b96d41dec2ac225f7deaefcf3995a462221f09aaf65037c3f38b7f838d42021731d1ed82630e0393326f4e023201c87755a599b16
6
+ metadata.gz: abd1baed79e11a1ecbf6bef278a4d607400e2aaedbe5b3d6d62b9b7480ff2acb4b47091f476c199cffd40ead699be7edcb18f4e5f4e68d90e2fc16e35618c073
7
+ data.tar.gz: 3606249e0673f84f8f00a407c2fe9f73eea3286e1309f10fca238ca906ff3aef8da4e20114eba04e097622317ba5cf74c534f032cb3367e8b2936ec94dac977d
data/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
- ## [0.9.0] - 2021-11-03
5
+ ## [0.9.0] - 2021-11-04
6
6
 
7
7
  - Initial release
8
+
9
+ ## [0.9.1] - 2021-11-08
10
+
11
+ - Implement property handling
data/README.md CHANGED
@@ -31,12 +31,14 @@ Would render:
31
31
  ## Table of Contents
32
32
 
33
33
  - [Installation](#installation)
34
+ - [Configuration](#configuration)
34
35
  - [General Usage](#general-usage)
35
36
  - [combine_with!](#combinewith)
36
37
  - [override!](#override)
37
38
  - [Conditional Usage](#conditional-usage)
38
39
  - [Development](#development)
39
40
  - [Contributing](#contributing)
41
+ - [To Do](#to-do)
40
42
  - [License](#license)
41
43
 
42
44
  ## Installation
@@ -53,6 +55,14 @@ And then execute:
53
55
  bundle install
54
56
  ```
55
57
 
58
+ ## Configuration
59
+
60
+ Generate an initializer to customize the default configuration:
61
+
62
+ ```sh
63
+ rails generate arc_options:install
64
+ ```
65
+
56
66
  ## General Usage
57
67
 
58
68
  Initialize a `TagOptions::Hash` directly or by passing an existing `Hash`.
@@ -0,0 +1,9 @@
1
+ Description:
2
+ Creates a new initializer containing the default settings of the gem.
3
+
4
+ Examples:
5
+ `rails generate tag_options:install`
6
+
7
+ Creates the following:
8
+
9
+ Initializer: config/tag_options.rb
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TagOptions
4
+ class InstallGenerator < Rails::Generators::Base
5
+ source_root File.expand_path('templates', __dir__)
6
+
7
+ def copy_initializer
8
+ copy_file 'tag_options.rb', 'config/initializers/tag_options.rb'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ TagOptions.configure do |config|
4
+ # fallback_property_handler
5
+ #
6
+ # Defines the default behavior of how values are treated on HTML properties. `TagOptions::PropertyHandler::Generic`
7
+ # allows for multiple, unique, values seperated by spaces.
8
+ config.fallback_property_handler = 'TagOptions::PropertyHandler::Generic'
9
+
10
+ # property_handlers
11
+ #
12
+ # Allows of the custom handling of HTML properties that match the defined property handler. Properties are handled by
13
+ # the first matching property handler.
14
+ config.property_handlers = [
15
+ 'TagOptions::PropertyHandler::Singular',
16
+ 'TagOptions::PropertyHandler::Style'
17
+ ]
18
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TagOptions
4
+ class << self
5
+ attr_writer :configuration
6
+
7
+ def configuration
8
+ @configuration ||= TagOptions::Configuration.new
9
+ end
10
+
11
+ def configure
12
+ yield(configuration)
13
+ end
14
+ end
15
+
16
+ class Configuration
17
+ attr_writer :fallback_property_handler, :property_handlers
18
+
19
+ def fallback_property_handler
20
+ @fallback_property_handler ||= 'TagOptions::PropertyHandler::Generic'
21
+ end
22
+
23
+ def property_handlers
24
+ @property_handlers ||= [
25
+ 'TagOptions::PropertyHandler::Singular',
26
+ 'TagOptions::PropertyHandler::Style'
27
+ ]
28
+ end
29
+ end
30
+ end
@@ -2,49 +2,50 @@
2
2
 
3
3
  require 'active_support/core_ext/string'
4
4
  require 'forwardable'
5
+ require 'tag_options/property_handler/resolve_value'
5
6
 
6
7
  module TagOptions
7
8
  class Hash
8
9
  extend Forwardable
9
10
 
10
- def_delegators :@data, :inspect, :to_s, :stringify_keys, :<, :<=, :==, :>, :>=
11
+ def_delegators :@data, :inspect, :to_h, :to_hash, :to_s, :stringify_keys, :<, :<=, :==, :>, :>=
11
12
 
12
13
  # Hashes passed into the initializer are automatically flattened, with nested keys seperated by dashes. For example,
13
14
  # `data: { controller: 'dropdown' }`` becomes `'data-controller': 'dropdown'`.
14
15
  def initialize(hash={})
15
16
  @data = {}
16
- flatten_hash(hash).each do |key, value|
17
- self[key] = value
17
+ flatten_hash(hash).each do |property, value|
18
+ self[property] = value
18
19
  end
19
20
  end
20
21
 
21
22
  # []
22
- # Underscores in a key name is automatically coverted to dashes. Keys can be specified as strings or symbols, both
23
- # return the same value.
24
- def [](key)
25
- @data[normalize_key(key)]
23
+ # Underscores in a property name is automatically coverted to dashes. Properties can be specified as strings or
24
+ # symbols, both return the same value.
25
+ def [](property)
26
+ @data[normalize_property(property)]
26
27
  end
27
28
 
28
29
  # []=
29
- # Hashes assigned to a key are automatically flatten, with nested keys seperated by dashes. Underscores in a key
30
- # name is automatically converted to dashes. Keys can be specified as strings or symbols, both will assign the value
31
- # to the same key.
32
- def []=(key, value)
30
+ # Hashes assigned to a property are automatically flatten, with nested keys seperated by dashes. Underscores in a
31
+ # property name are automatically converted to dashes. Propertiess can be specified as strings or symbols, both will
32
+ # assign the value to the same property.
33
+ def []=(property, value)
33
34
  if value.is_a?(::Hash)
34
- flatten_hash({ key => value }).each do |flat_key, flat_value|
35
- @data[normalize_key(flat_key)] = flat_value
35
+ flatten_hash({ property => value }).each do |flat_property, flat_value|
36
+ store(flat_property, flat_value)
36
37
  end
37
38
  else
38
- @data[normalize_key(key)] = value
39
+ store(property, value)
39
40
  end
40
41
  end
41
42
 
42
43
  # combine_with!
43
44
  # Allows you to combine values with multiple HTML attributes in one operation. Passed keys should be the HTML
44
- # attributes to combine the values with. The values can be passed as single value (e.g. `class: 'flex'`) or as an
45
+ # property to combine the values with. The values can be specified as single string (e.g. `class: 'flex'`) or as an
45
46
  # argument array (e.g. `class: ['flex', 'mt-2', 'flex-col': layout_column?]`). Hashes in an argument array have
46
47
  # their keys combined only their value is true. Nested keys will automatically be flattened and combine with the
47
- # associated key (e.g. `data: { controller: 'dropdown' }` would be combined with `data-controller`).
48
+ # associated property (e.g. `data: { controller: 'dropdown' }` would be combined with `data-controller`).
48
49
  #
49
50
  # #combine_with!(
50
51
  # class: ['flex', 'mt-2', 'flex-col': layout_column?],
@@ -58,18 +59,18 @@ module TagOptions
58
59
  # attribute is converted to dashes, for example: `combine_with_data_controller!` will result in the argument array
59
60
  # being combined with existing values in `data-controller`.
60
61
  def combine_with!(hash={})
61
- flatten_hash(hash).each do |key, args|
62
- self[key] = combine_values(self[key], *args)
62
+ flatten_hash(hash).each do |property, args|
63
+ store(property, self[property], *args)
63
64
  end
64
65
  self
65
66
  end
66
67
 
67
68
  # override!
68
- # Allows you to override values on multiple HTML attributes in one operation. Passed keys should be the HTML
69
- # attributes to override the values of. The values can be passed as single string (e.g. `class: 'flex'`) or as an
69
+ # Allows you to override values on multiple HTML properties in one operation. Passed keys should be the HTML
70
+ # properties to override the values of. The values can be passed as single string (e.g. `class: 'flex'`) or as an
70
71
  # argument array (e.g. `class: ['flex', 'mt-2', 'flex-col': layout_column?]`). Hashes in an argument array have
71
72
  # their keys added only if their value is true. Nested keys will automatically be flattened and override the value
72
- # at the associated key (e.g. `data: { controller: 'dropdown' }` would override values at `data-controller`).
73
+ # at the associated property (e.g. `data: { controller: 'dropdown' }` would override values at `data-controller`).
73
74
  #
74
75
  # #override!(
75
76
  # class: ['flex', 'mt-2', 'flex-col': layout_column?],
@@ -83,35 +84,26 @@ module TagOptions
83
84
  # attribute is automatically nested, for example `override_data_controller!` will result in the argument array
84
85
  # overriding the existing values in `data-controller`.
85
86
  def override!(hash={})
86
- flatten_hash(hash).each do |key, args|
87
- self[key] = combine_values(*args)
87
+ flatten_hash(hash).each do |property, args|
88
+ store(property, *args)
88
89
  end
89
90
  self
90
91
  end
91
92
 
92
- def to_h
93
- @data.transform_values { |value| value.is_a?(::TagOptions::Hash) ? value.to_h : value }
94
- end
95
- alias to_hash to_h
96
-
97
93
  private
98
94
 
99
95
  def action_matcher
100
- /\A(?<action>combine_with|override)_(?<key>.*)!\z/
101
- end
102
-
103
- def combine_values(*values, **conditions)
104
- [*values, *resolve_conditions(conditions.to_h)].map { |v| v.to_s.split }.flatten.compact.uniq.join(' ')
96
+ /\A(?<action>combine_with|override)_(?<property>.*)!\z/
105
97
  end
106
98
 
107
99
  def flatten_hash(hash)
108
- hash.each_with_object({}) do |(key, value), result|
100
+ hash.each_with_object({}) do |(property, value), result|
109
101
  if value.is_a?(::Hash)
110
- flatten_hash(value).map do |nested_key, nested_value|
111
- result["#{key}-#{nested_key}".to_sym] = nested_value
102
+ flatten_hash(value).map do |nested_property, nested_value|
103
+ result["#{property}-#{nested_property}".to_sym] = nested_value
112
104
  end
113
105
  else
114
- result[key] = value
106
+ result[property] = value
115
107
  end
116
108
  end
117
109
  end
@@ -119,18 +111,24 @@ module TagOptions
119
111
  def method_missing(method_name, *args, &block)
120
112
  match_data = action_matcher.match(method_name.to_s)
121
113
  if match_data
122
- public_send("#{match_data['action']}!", { match_data['key'] => args }, &block)
114
+ public_send("#{match_data['action']}!", { match_data['property'] => args }, &block)
123
115
  else
124
116
  super
125
117
  end
126
118
  end
127
119
 
128
- def normalize_key(key)
129
- key.to_s.downcase.dasherize.to_sym
120
+ def store(property, *values, **conditions)
121
+ property = normalize_property(property)
122
+ value = resolve_value(property, *values, **conditions)
123
+ value.empty? ? @data.delete(property) : @data[property] = value
124
+ end
125
+
126
+ def resolve_value(property, *values, **conditions)
127
+ TagOptions::PropertyHandler::ResolveValue.call(property, *values, **conditions)
130
128
  end
131
129
 
132
- def resolve_conditions(conditions)
133
- conditions.select { |_key, value| value }.keys
130
+ def normalize_property(property)
131
+ property.to_s.downcase.dasherize.to_sym
134
132
  end
135
133
 
136
134
  def respond_to_missing?(method_name, include_private=false)
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TagOptions
4
+ module PropertyHandler
5
+ class Base
6
+ attr_reader :values, :conditions
7
+
8
+ def initialize(*values, **conditions)
9
+ @values = values
10
+ @conditions = conditions
11
+ end
12
+
13
+ def self.call(...)
14
+ new(...).call
15
+ end
16
+
17
+ def self.handler_for?(property_name)
18
+ self::MATCHER.match?(property_name.to_s)
19
+ end
20
+
21
+ private
22
+
23
+ def combine_values(*values, **conditions)
24
+ resolve_uniq_values(*values, **conditions).join(' ')
25
+ end
26
+
27
+ def resolve_uniq_values(*values, **conditions)
28
+ [*values, *resolve_conditions(conditions)].map { |v| v.to_s.split }.flatten.compact.uniq
29
+ end
30
+
31
+ def resolve_conditions(conditions)
32
+ conditions.select { |_key, value| value }.keys
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tag_options/property_handler/base'
4
+
5
+ module TagOptions
6
+ module PropertyHandler
7
+ class Generic < Base
8
+ MATCHER = /\A.*\z/.freeze
9
+
10
+ def call
11
+ combine_values(*values, **conditions)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tag_options/configuration'
4
+
5
+ module TagOptions
6
+ module PropertyHandler
7
+ class ResolveValue
8
+ attr_reader :property
9
+
10
+ def initialize(property)
11
+ @property = property
12
+ end
13
+
14
+ def call(...)
15
+ handler.call(...)
16
+ end
17
+
18
+ def self.call(property, *values, **conditions)
19
+ new(property).call(*values, **conditions)
20
+ end
21
+
22
+ private
23
+
24
+ def handler
25
+ TagOptions.configuration.property_handlers.each do |handler_string|
26
+ handler = handler_string.constantize
27
+ return handler if handler.handler_for?(property)
28
+ end
29
+ TagOptions.configuration.fallback_property_handler.constantize
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tag_options/property_handler/base'
4
+
5
+ module TagOptions
6
+ module PropertyHandler
7
+ class Singular < Base
8
+ MATCHER = /\Aid|role|aria-.+\z/.freeze
9
+
10
+ def call
11
+ resolve_uniq_values(*values, **conditions).last.to_s
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tag_options/property_handler/base'
4
+
5
+ module TagOptions
6
+ module PropertyHandler
7
+ class Style < Base
8
+ MATCHER = /\Astyle\z/.freeze
9
+
10
+ def call
11
+ styles.map { |p, v| "#{p}: #{v};" }.join(' ')
12
+ end
13
+
14
+ private
15
+
16
+ def styles
17
+ styles_from_values.merge(styles_from_conditions)
18
+ end
19
+
20
+ def styles_from_values
21
+ style_hash_from(values)
22
+ end
23
+
24
+ def styles_from_conditions
25
+ style_hash_from(resolve_conditions(conditions))
26
+ end
27
+
28
+ def style_hash_from(strings)
29
+ {}.tap do |result|
30
+ Array(strings).each do |string|
31
+ string.to_s.split(';').compact.each do |property_value_pair|
32
+ property, value = property_value_pair.split(':')
33
+ next unless property && value
34
+
35
+ result[property.strip.downcase.to_sym] = value.strip
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TagOptions
4
- VERSION = '0.9.0'
4
+ VERSION = '0.9.1'
5
5
  end
data/lib/tag_options.rb CHANGED
@@ -1,5 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'tag_options/property_handler/base'
4
+ require 'tag_options/property_handler/generic'
5
+ require 'tag_options/property_handler/resolve_value'
6
+ require 'tag_options/property_handler/singular'
7
+ require 'tag_options/property_handler/style'
8
+ require 'tag_options/configuration'
3
9
  require 'tag_options/hash'
4
10
  require 'tag_options/railtie'
5
11
  require 'tag_options/version'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tag_options
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Monroe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-04 00:00:00.000000000 Z
11
+ date: 2021-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: debug
@@ -161,8 +161,17 @@ files:
161
161
  - MIT-LICENSE
162
162
  - README.md
163
163
  - Rakefile
164
+ - lib/generators/tag_options/install/USAGE
165
+ - lib/generators/tag_options/install/install_generator.rb
166
+ - lib/generators/tag_options/install/templates/tag_options.rb
164
167
  - lib/tag_options.rb
168
+ - lib/tag_options/configuration.rb
165
169
  - lib/tag_options/hash.rb
170
+ - lib/tag_options/property_handler/base.rb
171
+ - lib/tag_options/property_handler/generic.rb
172
+ - lib/tag_options/property_handler/resolve_value.rb
173
+ - lib/tag_options/property_handler/singular.rb
174
+ - lib/tag_options/property_handler/style.rb
166
175
  - lib/tag_options/railtie.rb
167
176
  - lib/tag_options/version.rb
168
177
  homepage: https://github.com/wamonroe/tag_options