tag_options 0.9.1 → 1.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -3
- data/README.md +87 -70
- data/Rakefile +5 -5
- data/lib/tag_options/configuration.rb +16 -9
- data/lib/tag_options/error.rb +4 -0
- data/lib/tag_options/errors/not_hash_error.rb +12 -0
- data/lib/tag_options/errors/resolver_error.rb +11 -0
- data/lib/tag_options/hash.rb +19 -124
- data/lib/tag_options/hash_at.rb +30 -0
- data/lib/tag_options/resolver.rb +17 -0
- data/lib/tag_options/resolvers/default.rb +11 -0
- data/lib/tag_options/resolvers/style.rb +26 -0
- data/lib/tag_options/version.rb +1 -3
- data/lib/tag_options.rb +7 -10
- metadata +11 -139
- data/lib/generators/tag_options/install/USAGE +0 -9
- data/lib/generators/tag_options/install/install_generator.rb +0 -11
- data/lib/generators/tag_options/install/templates/tag_options.rb +0 -18
- data/lib/tag_options/property_handler/base.rb +0 -36
- data/lib/tag_options/property_handler/generic.rb +0 -15
- data/lib/tag_options/property_handler/resolve_value.rb +0 -33
- data/lib/tag_options/property_handler/singular.rb +0 -15
- data/lib/tag_options/property_handler/style.rb +0 -42
- data/lib/tag_options/railtie.rb +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 900cd0b42ae1f34b69b7cf227cb4f6bc91cb560f3b04424cdf3e2fd41e5d3f61
|
4
|
+
data.tar.gz: b4af6738e8d551d795bab1ef057bb47f49de8d73ba32068c839d04bf50e78a43
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3322cbce916927b777b7e915e181102cdbc7497c42095edc0e11f009d9a6a3884e8649ce6826d0199ba0ac3e9fe1a8c039bc5bd8c490a6db027714f08e6d88c4
|
7
|
+
data.tar.gz: 0d1ebc95b92d489d19c49b33acead9abe88a9fc5932865941454100e11bb877db6baacf7380a85f0495c3d47d3807d02e6d8bbfe08d654dbfb6b17a2940c8393
|
data/CHANGELOG.md
CHANGED
@@ -2,10 +2,24 @@
|
|
2
2
|
|
3
3
|
## [Unreleased]
|
4
4
|
|
5
|
-
## [0.
|
5
|
+
## [1.0.0] - 2022-06-14
|
6
6
|
|
7
|
-
-
|
7
|
+
- Rewrote and simplified TagOptions::Hash and supporting classes.
|
8
|
+
- BREAKING CHANGES, read documentation for updated usage before updating
|
9
|
+
|
10
|
+
## [0.9.3] - 2021-11-11
|
11
|
+
|
12
|
+
- Added TagOptions::Hash() ease-of-use method
|
13
|
+
- Bug fixes for Ruby 3.0
|
14
|
+
|
15
|
+
## [0.9.2] - 2021-11-09
|
16
|
+
|
17
|
+
- Added optional TailwindCSS property handler
|
8
18
|
|
9
19
|
## [0.9.1] - 2021-11-08
|
10
20
|
|
11
|
-
-
|
21
|
+
- Implemented property handling
|
22
|
+
|
23
|
+
## [0.9.0] - 2021-11-04
|
24
|
+
|
25
|
+
- Initial release
|
data/README.md
CHANGED
@@ -1,17 +1,20 @@
|
|
1
1
|
# Tag Options
|
2
2
|
|
3
|
-
Simple library for manipulating options passed to the Rails `tag`,
|
3
|
+
Simple library for manipulating options passed to the Rails `tag`,
|
4
|
+
`content_tag`, and other tag helpers.
|
4
5
|
|
5
|
-
This library provides a simple class to make authoring resuable helpers and
|
6
|
-
easier when you want to allow for
|
6
|
+
This library provides a simple class to make authoring resuable helpers and
|
7
|
+
[View Components](https://viewcomponent.org) easier when you want to allow for
|
8
|
+
the input of properties on HTML elements, but also need to add/set your own.
|
7
9
|
|
8
|
-
`TagOptions::Hash` is an object that normalizes the options passed to Rails
|
9
|
-
to manipulate the values of HTML
|
10
|
+
`TagOptions::Hash` is an object that normalizes the options passed to Rails
|
11
|
+
helper, while providing helpful methods to manipulate the values of HTML
|
12
|
+
properties:
|
10
13
|
|
11
14
|
```ruby
|
12
15
|
def external_link_to(name, url, options={})
|
13
16
|
options = TagOptions::Hash.new(options)
|
14
|
-
options.
|
17
|
+
options.at(:class).combine!("external-link")
|
15
18
|
link_to(name, url, options)
|
16
19
|
end
|
17
20
|
```
|
@@ -19,7 +22,7 @@ end
|
|
19
22
|
Called with:
|
20
23
|
|
21
24
|
```ruby
|
22
|
-
external_link_to(
|
25
|
+
external_link_to("Example", "https://example.com", class: "ml-2")
|
23
26
|
```
|
24
27
|
|
25
28
|
Would render:
|
@@ -31,11 +34,11 @@ Would render:
|
|
31
34
|
## Table of Contents
|
32
35
|
|
33
36
|
- [Installation](#installation)
|
34
|
-
- [Configuration](#configuration)
|
35
37
|
- [General Usage](#general-usage)
|
36
|
-
- [
|
37
|
-
- [
|
38
|
+
- [combine!](#combine)
|
39
|
+
- [set!](#set)
|
38
40
|
- [Conditional Usage](#conditional-usage)
|
41
|
+
- [Property Resolvers](#property-resolvers)
|
39
42
|
- [Development](#development)
|
40
43
|
- [Contributing](#contributing)
|
41
44
|
- [To Do](#to-do)
|
@@ -46,7 +49,7 @@ Would render:
|
|
46
49
|
Add this line to your application's Gemfile:
|
47
50
|
|
48
51
|
```ruby
|
49
|
-
gem
|
52
|
+
gem "tag_options"
|
50
53
|
```
|
51
54
|
|
52
55
|
And then execute:
|
@@ -55,14 +58,6 @@ And then execute:
|
|
55
58
|
bundle install
|
56
59
|
```
|
57
60
|
|
58
|
-
## Configuration
|
59
|
-
|
60
|
-
Generate an initializer to customize the default configuration:
|
61
|
-
|
62
|
-
```sh
|
63
|
-
rails generate arc_options:install
|
64
|
-
```
|
65
|
-
|
66
61
|
## General Usage
|
67
62
|
|
68
63
|
Initialize a `TagOptions::Hash` directly or by passing an existing `Hash`.
|
@@ -71,115 +66,137 @@ Initialize a `TagOptions::Hash` directly or by passing an existing `Hash`.
|
|
71
66
|
TagOptions::Hash.new
|
72
67
|
=> {}
|
73
68
|
|
74
|
-
hash = {class:
|
69
|
+
hash = {class: "flex"}
|
75
70
|
TagOptions::Hash.new(hash)
|
76
71
|
=> {:class=>"flex"}
|
77
72
|
```
|
78
73
|
|
79
|
-
###
|
74
|
+
### combine!
|
80
75
|
|
81
|
-
Combine HTML attributes with an existing `TagOptions::Hash`
|
76
|
+
Combine HTML attributes with an existing `TagOptions::Hash` by chaining `at` and
|
77
|
+
`combine!`
|
82
78
|
|
83
79
|
```ruby
|
84
|
-
options = TagOptions::Hash.new(class:
|
85
|
-
options.
|
80
|
+
options = TagOptions::Hash.new(class: "flex")
|
81
|
+
options.at(:class).combine!("mt-1")
|
86
82
|
=> {:class=>"flex mt-1"}
|
87
83
|
```
|
88
84
|
|
89
85
|
Values can also be specified as arrays.
|
90
86
|
|
91
87
|
```ruby
|
92
|
-
options = TagOptions::Hash.new(class:
|
93
|
-
options.
|
88
|
+
options = TagOptions::Hash.new(class: "flex")
|
89
|
+
options.at(:class).combine!(["mt-1", "mx-2"])
|
94
90
|
=> {:class=>"flex mt-1 mx-2"}
|
95
91
|
```
|
96
92
|
|
97
93
|
HTML attributes are only added if they don't already exist.
|
98
94
|
|
99
95
|
```ruby
|
100
|
-
options = TagOptions::Hash.new(class:
|
101
|
-
options.
|
96
|
+
options = TagOptions::Hash.new(class: "flex")
|
97
|
+
options.at(:class).combine!("flex flex-col")
|
102
98
|
=> {:class=>"flex flex-col"}
|
103
99
|
```
|
104
100
|
|
105
|
-
You can also combine
|
101
|
+
You can also combine values on nested hashes.
|
106
102
|
|
107
103
|
```ruby
|
108
|
-
options = TagOptions::Hash.new(class:
|
109
|
-
options.
|
110
|
-
=> {:class=>"flex
|
104
|
+
options = TagOptions::Hash.new(class: "flex", data: {controller: "dropdown"})
|
105
|
+
options.at(:data, :controller).combine!("toggle")
|
106
|
+
=> {:class=>"flex", :data=>{:controller=>"dropdown toggle"}
|
111
107
|
```
|
112
108
|
|
113
|
-
|
109
|
+
If a nested hash doesn't already exist it will be automatically added.
|
114
110
|
|
115
111
|
```ruby
|
116
|
-
options = TagOptions::Hash.new(class:
|
117
|
-
options.
|
118
|
-
=> {:class=>"flex
|
112
|
+
options = TagOptions::Hash.new(class: "flex")
|
113
|
+
options.at(:data, :controller).combine!("dropdown")
|
114
|
+
=> {:class=>"flex", :data=>{:controller=>"dropdown"}
|
119
115
|
```
|
120
116
|
|
121
|
-
|
117
|
+
### set!
|
118
|
+
|
119
|
+
Chaining `at` and `set!` functions nearly the same as `combine!` with all same
|
120
|
+
usage patterns. The major difference is that the set method will override any
|
121
|
+
existing values.
|
122
122
|
|
123
123
|
```ruby
|
124
|
-
options = TagOptions::Hash.new(class:
|
125
|
-
options.
|
126
|
-
=> {:class=>"
|
124
|
+
options = TagOptions::Hash.new(class: "flex")
|
125
|
+
options.at(:class).set!("block")
|
126
|
+
=> {:class=>"block"}
|
127
127
|
```
|
128
128
|
|
129
|
-
|
130
|
-
|
129
|
+
## Conditional Usage
|
130
|
+
|
131
|
+
Both the `combine!` and `set!` allow for values to be conditionally added to
|
132
|
+
HTML attributes using an argument array. Where the values are added
|
133
|
+
unconditionally and key/value pairs have their key added _IF_ the value is true.
|
131
134
|
|
132
135
|
```ruby
|
133
|
-
|
134
|
-
options.
|
135
|
-
options.
|
136
|
-
=> {:class=>"flex mt-1
|
136
|
+
# assuming `centered?` returns `true`
|
137
|
+
options = TagOptions::Hash.new(class: "flex")
|
138
|
+
options.at(:class).combine!("mt-1", "mx-auto": centered?, "mx-2": !centered?)
|
139
|
+
=> {:class=>"flex mt-1 mx-auto"}
|
137
140
|
```
|
138
141
|
|
139
|
-
|
142
|
+
## Custom Property Resolvers
|
140
143
|
|
141
|
-
|
142
|
-
|
143
|
-
values with existing values. Any specified values will override any existing values.
|
144
|
+
Chaining `at` to `combine!` or `set!` processes HTML properties similar to
|
145
|
+
`class`.
|
144
146
|
|
145
|
-
|
147
|
+
- Multiple are allowed
|
148
|
+
- Multiple values are seperated by a space
|
149
|
+
- Duplicate values are not added
|
150
|
+
|
151
|
+
Tag Options also ships with a special `style` resolver, which can be used by
|
152
|
+
pass `as: :style` to `at`.
|
146
153
|
|
147
|
-
|
148
|
-
|
154
|
+
- Multiple values are allowed
|
155
|
+
- Values must be specified as `property: value;`
|
156
|
+
- Duplicate `property: value;` pairs are not added
|
157
|
+
- The `combine!` method will overwrite an existing style property if it exists,
|
158
|
+
add properties that don't exist, and leave the remaining properties untouched.
|
159
|
+
- The `set!` method will overwrite all existing style properties.
|
149
160
|
|
150
161
|
```ruby
|
151
|
-
|
152
|
-
options
|
153
|
-
|
154
|
-
=> {:class=>"flex mt-1 mx-auto"}
|
162
|
+
options = TagOptions::Hash.new(style: "display: block; margin-left: 0;")
|
163
|
+
options.at(:style, as: :style).combine!("display: flex; margin-right: 0;")
|
164
|
+
=> {:style=>"display: flex; margin-left: 0; margin-right: 0;"}
|
155
165
|
```
|
156
166
|
|
157
|
-
|
158
|
-
|
167
|
+
A `TagOptions::Resolver` class is available if you wish to implement your own
|
168
|
+
custom handlers. For examples on doing so, see the [built-in
|
169
|
+
handlers](https://github.com/wamonroe/tag_options/tree/main/lib/tag_options/resolvers).
|
170
|
+
|
171
|
+
To register a custom handler:
|
159
172
|
|
160
173
|
```ruby
|
161
|
-
#
|
162
|
-
|
163
|
-
|
164
|
-
|
174
|
+
# config/initializers/tag_options.rb
|
175
|
+
TagOptions.configure do |config|
|
176
|
+
config.register_resolver :custom, "MyCustomResolver"
|
177
|
+
end
|
165
178
|
```
|
166
179
|
|
167
180
|
## Development
|
168
181
|
|
169
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
170
|
-
also run:
|
182
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
183
|
+
`bin/rspec` to run the tests. You can also run:
|
171
184
|
|
172
185
|
- `bin/console` for an interactive prompt that will allow you to experiment
|
173
186
|
- `bin/rubocop` to run RuboCop to check the code style and formatting
|
174
187
|
|
175
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To
|
176
|
-
version number in `version.rb`, and then run
|
177
|
-
|
188
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To
|
189
|
+
release a new version, update the version number in `version.rb`, and then run
|
190
|
+
`bundle exec rake release`, which will create a git tag for the version, push
|
191
|
+
git commits and the created tag, and push the `.gem` file to
|
192
|
+
[rubygems.org](https://rubygems.org).
|
178
193
|
|
179
194
|
## Contributing
|
180
195
|
|
181
|
-
Bug reports and pull requests are welcome on GitHub at
|
196
|
+
Bug reports and pull requests are welcome on GitHub at
|
197
|
+
https://github.com/wamonroe/tag_options.
|
182
198
|
|
183
199
|
## License
|
184
200
|
|
185
|
-
The gem is available as open source under the terms of the [MIT
|
201
|
+
The gem is available as open source under the terms of the [MIT
|
202
|
+
License](https://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "bundler/setup"
|
4
4
|
|
5
|
-
require
|
6
|
-
require
|
5
|
+
require "bundler/gem_tasks"
|
6
|
+
require "rake/testtask"
|
7
7
|
|
8
8
|
Rake::TestTask.new(:test) do |t|
|
9
|
-
t.libs <<
|
10
|
-
t.pattern =
|
9
|
+
t.libs << "test"
|
10
|
+
t.pattern = "test/**/*_test.rb"
|
11
11
|
t.verbose = false
|
12
12
|
end
|
13
13
|
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
require "tag_options/resolvers/default"
|
2
|
+
require "tag_options/resolvers/style"
|
3
|
+
require "tag_options/errors/resolver_error"
|
2
4
|
|
3
5
|
module TagOptions
|
4
6
|
class << self
|
@@ -14,17 +16,22 @@ module TagOptions
|
|
14
16
|
end
|
15
17
|
|
16
18
|
class Configuration
|
17
|
-
|
19
|
+
def initialize
|
20
|
+
@resolvers = {
|
21
|
+
default: "TagOptions::Resolvers::Default",
|
22
|
+
style: "TagOptions::Resolvers::Style"
|
23
|
+
}
|
24
|
+
end
|
18
25
|
|
19
|
-
def
|
20
|
-
|
26
|
+
def resolver(name)
|
27
|
+
unless (resolver_name = @resolvers[name])
|
28
|
+
raise TagOptions::Errors::ResolverError, name
|
29
|
+
end
|
30
|
+
Object.const_get(resolver_name)
|
21
31
|
end
|
22
32
|
|
23
|
-
def
|
24
|
-
@
|
25
|
-
'TagOptions::PropertyHandler::Singular',
|
26
|
-
'TagOptions::PropertyHandler::Style'
|
27
|
-
]
|
33
|
+
def register_resolver(name, class_name)
|
34
|
+
@resolvers[name] = class_name
|
28
35
|
end
|
29
36
|
end
|
30
37
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "tag_options/error"
|
2
|
+
|
3
|
+
module TagOptions
|
4
|
+
module Errors
|
5
|
+
class NotHashError < Error
|
6
|
+
def initialize(key, *keys, type:)
|
7
|
+
hash_path = [key, *keys].join("=>")
|
8
|
+
super("unsupport type `#{type}` is already located at #{hash_path}")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/tag_options/hash.rb
CHANGED
@@ -1,138 +1,33 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'active_support/core_ext/string'
|
4
|
-
require 'forwardable'
|
5
|
-
require 'tag_options/property_handler/resolve_value'
|
1
|
+
require "tag_options/hash_at"
|
2
|
+
require "tag_options/errors/not_hash_error"
|
6
3
|
|
7
4
|
module TagOptions
|
8
|
-
class Hash
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
# Hashes passed into the initializer are automatically flattened, with nested keys seperated by dashes. For example,
|
14
|
-
# `data: { controller: 'dropdown' }`` becomes `'data-controller': 'dropdown'`.
|
15
|
-
def initialize(hash={})
|
16
|
-
@data = {}
|
17
|
-
flatten_hash(hash).each do |property, value|
|
18
|
-
self[property] = value
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# []
|
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)]
|
27
|
-
end
|
28
|
-
|
29
|
-
# []=
|
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)
|
34
|
-
if value.is_a?(::Hash)
|
35
|
-
flatten_hash({ property => value }).each do |flat_property, flat_value|
|
36
|
-
store(flat_property, flat_value)
|
37
|
-
end
|
38
|
-
else
|
39
|
-
store(property, value)
|
5
|
+
class Hash < ::Hash
|
6
|
+
def initialize(hash = {})
|
7
|
+
hash.each do |key, value|
|
8
|
+
self[key] = value.is_a?(::Hash) ? TagOptions::Hash.new(value) : value
|
40
9
|
end
|
41
10
|
end
|
42
11
|
|
43
|
-
|
44
|
-
|
45
|
-
# property to combine the values with. The values can be specified as single string (e.g. `class: 'flex'`) or as an
|
46
|
-
# argument array (e.g. `class: ['flex', 'mt-2', 'flex-col': layout_column?]`). Hashes in an argument array have
|
47
|
-
# their keys combined only their value is true. Nested keys will automatically be flattened and combine with the
|
48
|
-
# associated property (e.g. `data: { controller: 'dropdown' }` would be combined with `data-controller`).
|
49
|
-
#
|
50
|
-
# #combine_with!(
|
51
|
-
# class: ['flex', 'mt-2', 'flex-col': layout_column?],
|
52
|
-
# data: {
|
53
|
-
# controller: ['dropdown', 'navbar': navbar?]
|
54
|
-
# }
|
55
|
-
# )
|
56
|
-
#
|
57
|
-
# TagOptions::Hash also responses to combine_with_<name>!, where `<name>` is the name of the HTML attribute to
|
58
|
-
# combine the passed argument array with. If `<name>` is specified with a value containing underscores, the HTML
|
59
|
-
# attribute is converted to dashes, for example: `combine_with_data_controller!` will result in the argument array
|
60
|
-
# being combined with existing values in `data-controller`.
|
61
|
-
def combine_with!(hash={})
|
62
|
-
flatten_hash(hash).each do |property, args|
|
63
|
-
store(property, self[property], *args)
|
64
|
-
end
|
65
|
-
self
|
66
|
-
end
|
67
|
-
|
68
|
-
# override!
|
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
|
71
|
-
# argument array (e.g. `class: ['flex', 'mt-2', 'flex-col': layout_column?]`). Hashes in an argument array have
|
72
|
-
# their keys added only if their value is true. Nested keys will automatically be flattened and override the value
|
73
|
-
# at the associated property (e.g. `data: { controller: 'dropdown' }` would override values at `data-controller`).
|
74
|
-
#
|
75
|
-
# #override!(
|
76
|
-
# class: ['flex', 'mt-2', 'flex-col': layout_column?],
|
77
|
-
# data: {
|
78
|
-
# controller: ['dropdown', 'navbar': navbar?]
|
79
|
-
# }
|
80
|
-
# )
|
81
|
-
#
|
82
|
-
# TagOptions::Hash also responses to override_<name>!, where `<name>` is the name of the HTML attribute to override
|
83
|
-
# the passed argument array on. If `<name>` is specified with a value containing underscores, the resulting HTML
|
84
|
-
# attribute is automatically nested, for example `override_data_controller!` will result in the argument array
|
85
|
-
# overriding the existing values in `data-controller`.
|
86
|
-
def override!(hash={})
|
87
|
-
flatten_hash(hash).each do |property, args|
|
88
|
-
store(property, *args)
|
89
|
-
end
|
90
|
-
self
|
12
|
+
def at(key, *nested_keys, as: :default)
|
13
|
+
TagOptions::HashAt.new(opt_hash: self, keys: [key, *nested_keys], as: as)
|
91
14
|
end
|
92
15
|
|
93
|
-
|
94
|
-
|
95
|
-
def action_matcher
|
96
|
-
/\A(?<action>combine_with|override)_(?<property>.*)!\z/
|
16
|
+
def dig(*keys)
|
17
|
+
keys.size.zero? ? self : super
|
97
18
|
end
|
98
19
|
|
99
|
-
def
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
20
|
+
def populate!(*keys)
|
21
|
+
populated_keys = []
|
22
|
+
data = self
|
23
|
+
keys.each do |key|
|
24
|
+
data[key] ||= TagOptions::Hash.new
|
25
|
+
data = data[key]
|
26
|
+
unless data.is_a?(TagOptions::Hash)
|
27
|
+
raise TagOptions::Errors::NotHashError.new(populated_keys, type: data.class)
|
107
28
|
end
|
108
29
|
end
|
109
|
-
|
110
|
-
|
111
|
-
def method_missing(method_name, *args, &block)
|
112
|
-
match_data = action_matcher.match(method_name.to_s)
|
113
|
-
if match_data
|
114
|
-
public_send("#{match_data['action']}!", { match_data['property'] => args }, &block)
|
115
|
-
else
|
116
|
-
super
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
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)
|
128
|
-
end
|
129
|
-
|
130
|
-
def normalize_property(property)
|
131
|
-
property.to_s.downcase.dasherize.to_sym
|
132
|
-
end
|
133
|
-
|
134
|
-
def respond_to_missing?(method_name, include_private=false)
|
135
|
-
action_matcher.match?(method_name.to_s) || super
|
30
|
+
self
|
136
31
|
end
|
137
32
|
end
|
138
33
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "tag_options/configuration"
|
2
|
+
|
3
|
+
module TagOptions
|
4
|
+
class HashAt
|
5
|
+
def initialize(opt_hash:, keys:, as:)
|
6
|
+
@opt_hash = opt_hash
|
7
|
+
@keys = keys[..-2]
|
8
|
+
@value_key = keys[-1]
|
9
|
+
@resolver = TagOptions.configuration.resolver(as)
|
10
|
+
end
|
11
|
+
|
12
|
+
def combine!(*values, **conditions)
|
13
|
+
@opt_hash.populate!(*@keys)
|
14
|
+
current_value = @opt_hash.dig(*@keys, @value_key)
|
15
|
+
set_value! @resolver.call(current_value, *values, **conditions)
|
16
|
+
end
|
17
|
+
|
18
|
+
def set!(*values, **conditions)
|
19
|
+
@opt_hash.populate!(*@keys)
|
20
|
+
set_value! @resolver.call(*values, **conditions)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def set_value!(value)
|
26
|
+
@opt_hash.dig(*@keys)[@value_key] = value
|
27
|
+
@opt_hash
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module TagOptions
|
2
|
+
class Resolver
|
3
|
+
def initialize(*values, **conditional_values)
|
4
|
+
@values = [*values, *resolve_conditional_values(conditional_values)]
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.call(...)
|
8
|
+
new(...).call
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def resolve_conditional_values(conditional_values)
|
14
|
+
conditional_values.select { |_key, value| value }.keys
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "tag_options/resolver"
|
2
|
+
|
3
|
+
module TagOptions
|
4
|
+
module Resolvers
|
5
|
+
class Style < Resolver
|
6
|
+
def call
|
7
|
+
styles.map { |p, v| "#{p}: #{v};" }.join(" ")
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def styles
|
13
|
+
{}.tap do |result|
|
14
|
+
@values.each do |string|
|
15
|
+
string.to_s.split(";").compact.each do |property_value_pair|
|
16
|
+
property, value = property_value_pair.split(":")
|
17
|
+
next unless property && value
|
18
|
+
|
19
|
+
result[property.strip.downcase.to_sym] = value.strip
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/tag_options/version.rb
CHANGED
data/lib/tag_options.rb
CHANGED
@@ -1,11 +1,8 @@
|
|
1
|
-
|
1
|
+
require "tag_options/hash"
|
2
|
+
require "tag_options/version"
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
require 'tag_options/configuration'
|
9
|
-
require 'tag_options/hash'
|
10
|
-
require 'tag_options/railtie'
|
11
|
-
require 'tag_options/version'
|
4
|
+
module TagOptions
|
5
|
+
def self.Hash(hash = {})
|
6
|
+
TagOptions::Hash.new(hash)
|
7
|
+
end
|
8
|
+
end
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tag_options
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Monroe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-06-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: rspec
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
@@ -24,132 +24,6 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: minitest
|
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: mocha
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: rubocop
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: rubocop-minitest
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: rubocop-performance
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - ">="
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: rubocop-rake
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - ">="
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: shoulda
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - ">="
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - ">="
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: '0'
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: simplecov
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - ">="
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '0'
|
132
|
-
type: :development
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - ">="
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: '0'
|
139
|
-
- !ruby/object:Gem::Dependency
|
140
|
-
name: rails
|
141
|
-
requirement: !ruby/object:Gem::Requirement
|
142
|
-
requirements:
|
143
|
-
- - ">="
|
144
|
-
- !ruby/object:Gem::Version
|
145
|
-
version: 5.2.0
|
146
|
-
type: :runtime
|
147
|
-
prerelease: false
|
148
|
-
version_requirements: !ruby/object:Gem::Requirement
|
149
|
-
requirements:
|
150
|
-
- - ">="
|
151
|
-
- !ruby/object:Gem::Version
|
152
|
-
version: 5.2.0
|
153
27
|
description: Simple library for manipulating options passed to various Rails tag helpers.
|
154
28
|
email:
|
155
29
|
- alex@monroepost.com
|
@@ -161,18 +35,16 @@ files:
|
|
161
35
|
- MIT-LICENSE
|
162
36
|
- README.md
|
163
37
|
- 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
|
167
38
|
- lib/tag_options.rb
|
168
39
|
- lib/tag_options/configuration.rb
|
40
|
+
- lib/tag_options/error.rb
|
41
|
+
- lib/tag_options/errors/not_hash_error.rb
|
42
|
+
- lib/tag_options/errors/resolver_error.rb
|
169
43
|
- lib/tag_options/hash.rb
|
170
|
-
- lib/tag_options/
|
171
|
-
- lib/tag_options/
|
172
|
-
- lib/tag_options/
|
173
|
-
- lib/tag_options/
|
174
|
-
- lib/tag_options/property_handler/style.rb
|
175
|
-
- lib/tag_options/railtie.rb
|
44
|
+
- lib/tag_options/hash_at.rb
|
45
|
+
- lib/tag_options/resolver.rb
|
46
|
+
- lib/tag_options/resolvers/default.rb
|
47
|
+
- lib/tag_options/resolvers/style.rb
|
176
48
|
- lib/tag_options/version.rb
|
177
49
|
homepage: https://github.com/wamonroe/tag_options
|
178
50
|
licenses:
|
@@ -196,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
196
68
|
- !ruby/object:Gem::Version
|
197
69
|
version: '0'
|
198
70
|
requirements: []
|
199
|
-
rubygems_version: 3.
|
71
|
+
rubygems_version: 3.3.7
|
200
72
|
signing_key:
|
201
73
|
specification_version: 4
|
202
74
|
summary: Simple library for manipulating options passed to various Rails tag helpers.
|
@@ -1,11 +0,0 @@
|
|
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
|
@@ -1,18 +0,0 @@
|
|
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
|
@@ -1,36 +0,0 @@
|
|
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
|
@@ -1,15 +0,0 @@
|
|
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
|
@@ -1,33 +0,0 @@
|
|
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
|
@@ -1,15 +0,0 @@
|
|
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
|
@@ -1,42 +0,0 @@
|
|
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
|