stimulus_tag_helper 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b6abf8489a80e3128ea3a0d0a81b935e5b1b2303e0e911af50069ddaad5d84d8
4
- data.tar.gz: 45e22a4a2b76553502ffdf0cca5b49b24f59c3e6f8139f57052b159a0e3a45b0
3
+ metadata.gz: 1e14706b60764f1c964d28e6aee33ccbd1bd0ae37276f54551c2cef6382c3043
4
+ data.tar.gz: b2d6259c7ad45568e8b38fd2410a5cb4f7a2a2624d82fbd98ca9c1f638735f5f
5
5
  SHA512:
6
- metadata.gz: 72427f49698c21330c73061f040fdd1c4eb7a630dd41b15555dc703234771dd614a00d9ade29258d88d4ffc74b33fa4f23c88d24230d62dc2daaa7770440f58e
7
- data.tar.gz: 06c29df33bf224027b006d059ef0631693d7be19a92dddba137a004c774ebb8a91c2408d90a5f5061ba1130f2b700109b2997de8c2d9fe80077d2811332396c7
6
+ metadata.gz: 30df03a48c9a2b28c8fdd84192c175756bcca535d14c4dc737b32e9afae027a8c95cbc110728e3a828466fe840894675e76937bdb24dedf57236017fc94a0b5e
7
+ data.tar.gz: 7270c3d1959724d3a481d805f0bdd87f4243f525c18ac01298b71fe7c89521453945e0d13d830afd71513b3a5fcbad6967750b6097ad5fa0dce19b264847792e
data/README.md CHANGED
@@ -1,19 +1,29 @@
1
1
  # stimulus_tag_helper
2
2
 
3
- [![Rubocop](https://github.com/crawler/stimulus_tag_helper/workflows/Rubocop/badge.svg)](https://github.com/crawler/stimulus_tag_helper/actions)
4
-
3
+ [![Rubocop](https://github.com/crawler/stimulus_tag_helper/actions/workflows/rubocop.yml/badge.svg)](https://github.com/crawler/stimulus_tag_helper/actions/workflows/rubocop.yml)
4
+ [![Tests](https://github.com/crawler/stimulus_tag_helper/actions/workflows/test.yml/badge.svg)](https://github.com/crawler/stimulus_tag_helper/actions/workflows/test.yml)
5
+ [![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
5
6
  [![Gem](https://img.shields.io/gem/v/stimulus_tag_helper.svg)](https://rubygems.org/gems/stimulus_tag_helper)
6
7
 
7
- ## WARING!
8
+ ## ~~WARING!~~
9
+
10
+ ~~This gem is in the proof of concept stage. I made it for myself, and it is not yet covered with tests and documentation.~~
8
11
 
9
- This gem is in the proof of concept stage. I made it for myself, and it is not yet covered with tests and the documentation.
12
+ 🎉 After around a year from initial publication, the helper is pretty useful and simple enough to be stable and compatible with different Ruby/Rails versions. So I decided to cover it with tests and add fancy badges.
13
+
14
+ If Russia has not dropped a nuclear bomb on Kyiv then the repo is still maintained by me.
10
15
 
11
16
  ## Description
12
17
 
13
- The stimulusjs is a great js framework for the HTML that you already have, but once u start using it the HTML becomes pretty big as you need to extend it with the attributes that your required to tight it with controllers. So I made this modest (even more modest than the stimulus itself) helper. Currently, I use it with the Slim(http://slim-lang.com/). So for now examples will be in it.
18
+ The stimulusjs is a great js framework for the HTML that you already have, but once you start using it the HTML became wordier, as you need to extend it with more attributes that you already have. So I made this even more modest than the stimulus helper.
19
+
20
+ Sometimes it makes the template cleaner, sometimes it is not. It's up to you when to use it.
21
+
22
+ Helper matches Stimulus 2.0+ requirements. You can mix attributes of multiple controllers in a single element or the tag helper. In the end, the stimulus helpers return is a simple Hash.
14
23
 
15
24
  ---
16
25
 
26
+ - [Compatibility](#compatibility)
17
27
  - [Quick start](#quick-start)
18
28
  - [Examples](#examples)
19
29
  - [Support](#support)
@@ -21,13 +31,17 @@ The stimulusjs is a great js framework for the HTML that you already have, but o
21
31
  - [Code of conduct](#code-of-conduct)
22
32
  - [Contribution guide](#contribution-guide)
23
33
 
34
+ ## Compatibility
35
+
36
+ **Ruby:** 3.1, 3.0, 2.7; **Rails:** edge, 7.0, 6.1, 6.0
37
+
24
38
  ## Quick start
25
39
 
26
40
  ```ruby
27
- gem 'stimulus_tag_helper', github: 'crawler/stimulus_tag_helper'
41
+ gem `stimulus_tag_helper`
28
42
  ```
29
43
 
30
- ### In the rails Controller
44
+ ### In the Rails Controller
31
45
 
32
46
  ```ruby
33
47
  helper StimulusTagHelper
@@ -41,10 +55,9 @@ include StimulusTagHelper
41
55
 
42
56
  ## Examples
43
57
 
44
- Some examples is taken from the real app so may be not very)
45
-
46
- ### "Hello, Stimulus" controller from the stimulusjs homepage
58
+ ### The controller from the stimulusjs homepage
47
59
 
60
+ **Slim Lang:**
48
61
  ```slim
49
62
  = stimulus_controller("hello", tag: "div") do |sc|
50
63
  = text_field_tag('', '', **sc.target("name"))
@@ -52,9 +65,7 @@ Some examples is taken from the real app so may be not very)
52
65
  span[*sc.target("output")]
53
66
  ```
54
67
 
55
- Please note that to support nesting, and the stimulus 2.0 attributes notation, the actions and the targets will be prefixed with controller name
56
-
57
- So example above will became:
68
+ **Output:**
58
69
 
59
70
  ```html
60
71
  <div data-controller="hello">
@@ -64,29 +75,30 @@ So example above will became:
64
75
  </div>
65
76
  ```
66
77
 
78
+ *To support nesting, and the stimulus 2.0 attributes notation, the actions, and the targets are prefixed with the controller name*
79
+
67
80
 
68
- ## "Slideshow" define controller without tag rendering
81
+ ### Initialize the builder and use the controller attribute later
69
82
 
70
- (buttons messed up for the demonstation purposes)
83
+ **Slim Lang**
71
84
 
72
85
  ```slim
73
86
  = stimulus_controller("slideshow") do |sc|
74
87
  div[*sc.controller_attribute]
75
88
  = button_tag ' ← ', type: 'button', **sc.action("previous")
76
- button[*sc.action("next")]
77
- ' →
89
+ = button_tag ' → ', type: 'button', **sc.action("next")
78
90
  div[*sc.target("slide")] 🐵
79
91
  div[*sc.target("slide")] 🙈
80
92
  div[*sc.target("slide")] 🙉
81
93
  div[*sc.target("slide")] 🙊
82
94
  ```
83
95
 
84
- Became:
96
+ **Output:**
85
97
 
86
98
  ```html
87
99
  <div data-controller="slideshow">
88
100
  <button name="button" type="button" data-action="slideshow#previous"> ← </button>
89
- <button data-action="slideshow#next"> → </button>
101
+ <button name="button" type="button" data-action="slideshow#next"> → </button>
90
102
  <div data-slideshow-target="slide">🐵</div>
91
103
  <div data-slideshow-target="slide">🙈</div>
92
104
  <div data-slideshow-target="slide">🙉</div>
@@ -94,39 +106,45 @@ Became:
94
106
  </div>
95
107
  ```
96
108
 
97
- ### Nested controllers
109
+ ### Nested controllers example
98
110
 
99
- ```slim
100
- = stimulus_controller( \
101
- "flash", tag: "div", class: "flash flash_global", values: { "page-cached" => page_will_be_cached?, src: flash_path },
102
- actions: %w[flash-message:connect->registerMessage flash-message:disconnect->removeMessage] \
103
- ) do |fc|
104
- - unless page_will_be_cached?
105
- - flash.keys.each do |type|
106
- .flash__message
107
- = stimulus_controller( \
108
- "flash-message",
109
- tag: "div", class: "flash-message flash-message_type_#{type}",
110
- actions: %w[animationend->next click->hide] \
111
- ) do |fmc|
112
- .flash-message__text = flash[type]
113
- button.flash-message__dismiss-button[aria-label="Close flash message" *fmc.action("dismiss")]
114
- = svg_sprite "icons/common.svg#common-times", class: "icon"
111
+ **Plain Ruby:**
115
112
 
113
+ ```ruby
114
+ stimulus_controller(:effects) do |ec|
115
+ stimulus_controller(
116
+ :clipboard, tag: :div, **ec.controller_property.merge(ec.action_property("clipboard:copy->flash"))
117
+ ) do |cc|
118
+ safe_join([
119
+ "PIN: ",
120
+ tag.input(**cc.attributes(target: "source"), type: "text", value: "1234", readonly: true),
121
+ tag.button(**cc.action("copy")) { "Copy to Clipboard" }
122
+ ])
123
+ end
124
+ end
116
125
  ```
117
126
 
127
+ **Output:**
128
+
129
+ ```html
130
+ <div data-controller="clipboard effects" data-action="clipboard:copy->effects#flash">
131
+ PIN: <input data-clipboard-target="source" type="text" value="1234" readonly="readonly">
132
+ <button data-action="clipboard#copy">Copy to Clipboard</button>
133
+ </div>
134
+ ```
118
135
 
119
136
  ## Support
120
137
 
121
- If you want to report a bug, or have ideas, feedback or questions about the gem, [let me know via GitHub issues](https://github.com/crawler/stimulus_tag_helper/issues/new) and I will do my best to provide a helpful answer. Happy hacking!
138
+ If you want to report a bug or have ideas, feedback, or questions about the gem, [let me know via GitHub issues](https://github.com/crawler/stimulus_tag_helper/issues/new) and I will do my best to provide a helpful answer. Happy hacking!
122
139
 
123
140
  ## License
124
141
 
125
- The gem is available as open source under the terms of the [MIT License](LICENSE.txt).
142
+ The gem is available as open-source under the terms of the [MIT License](LICENSE.txt).
126
143
 
127
144
  ## Code of conduct
128
145
 
129
- Everyone interacting in this project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](CODE_OF_CONDUCT.md).
146
+ Everyone interacting in this project’s codebases, issue trackers, chat rooms, and mailing lists is expected to follow
147
+ the [code of conduct](CODE_OF_CONDUCT.md).
130
148
 
131
149
  ## Contribution guide
132
150
 
@@ -3,19 +3,30 @@
3
3
  module StimulusTagHelper
4
4
  class StimulusAction
5
5
  STANDARD_PARSER =
6
- /^(?<void>(?<event>.+?)(?<void>@(?<target>window|document))?->)?(?<identifier>.+?)(?<void>#(?<method>[^:]+?))(?<void>:(?<options>.+))?$/.freeze
6
+ /^(?<void>(?<event>.+?)(?<void>@(?<target>window|document))?->)?(?<identifier>.+?)(?<void>#(?<method>[^:]+?))(?<void>:(?<options>.+))?$/
7
7
  NO_CONTROLLER_PARSER =
8
- /^(?<void>(?<event>.+?)?(?<void>@(?<target>window|document))?->)?(?<method>[^#:]+?)(?<void>:(?<options>.+))?$/.freeze
9
- class_attribute :parts, default: %i[identifier method event target options]
10
- attr_reader(*parts)
8
+ /^(?<void>(?<event>.+?)?(?<void>@(?<target>window|document))?->)?(?<method>[^#:]+?)(?<void>:(?<options>.+))?$/
9
+ PARTS = %i[identifier method event target options]
11
10
 
12
- # event is nil to let stimulusjs decide default event for the element
11
+ # event is nil to let stimulus.js decide default event for the element
13
12
  def initialize(identifier:, method:, event: nil, target: nil, options: nil)
14
- parts.each do |part|
13
+ PARTS.each do |part|
15
14
  instance_variable_set(:"@#{part}", binding.local_variable_get(part))
16
15
  end
17
16
  end
18
17
 
18
+ def to_s
19
+ "#{event_part.presence&.+("->")}#{handler_part}"
20
+ end
21
+
22
+ def ==(other)
23
+ other.is_a?(StimulusAction) && other.to_s == to_s
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader(*PARTS) # define attr readers for each part
29
+
19
30
  def event_part
20
31
  "#{event}#{"@#{target}" if target}"
21
32
  end
@@ -24,16 +35,15 @@ module StimulusTagHelper
24
35
  "#{identifier}##{method}#{":#{options}" if options}"
25
36
  end
26
37
 
27
- def to_s
28
- "#{event_part.presence&.+'->'}#{handler_part}".html_safe
29
- end
38
+ class << self
39
+ def parse(string, **defaults)
40
+ to_parse = string.to_s
41
+ parsed =
42
+ to_parse.include?("#") ? STANDARD_PARSER.match(to_parse) : NO_CONTROLLER_PARSER.match(to_parse)
43
+ raise(ArgumentError, "Can't parse stimulus action #{string.inspect}") unless parsed
30
44
 
31
- def self.parse(str)
32
- parsed =
33
- str.include?("#") ? STANDARD_PARSER.match(str) : NO_CONTROLLER_PARSER.match(str)
34
- raise(ArgumentError, "can't parse action string #{str}") unless parsed
35
-
36
- parsed.named_captures.except("void").symbolize_keys
45
+ new(**defaults.merge(parsed.named_captures.except("void").transform_keys(&:to_sym)))
46
+ end
37
47
  end
38
48
  end
39
49
  end
@@ -2,30 +2,56 @@
2
2
 
3
3
  module StimulusTagHelper
4
4
  class StimulusControllerBuilder
5
- def initialize(identifier:, template:)
5
+ class << self
6
+ delegate :properties, :aliases, :attribute_method_name_for, :property_method_name_for, to: StimulusTagHelper
7
+ end
8
+
9
+ attr_reader :identifier, :template, :tag, :tag_options
10
+
11
+ # all the options are tag options of now
12
+ def initialize(identifier:, template:, tag: nil, **tag_options)
6
13
  @identifier = identifier
7
14
  @template = template
15
+ @tag = tag
16
+ @tag_options = tag_options
8
17
  end
9
18
 
10
- StimulusTagHelper.property_names.each do |name|
11
- name = name.to_s
12
- attribute, property = name.pluralize == name ? %w[attributes properties] : %w[attribute property]
19
+ properties.each do |name|
20
+ attribute_method_name = attribute_method_name_for(name)
21
+ property_method_name = property_method_name_for(name)
22
+ alias_name = aliases[name]
13
23
 
14
24
  class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
15
- def #{name}_#{attribute}(...) # def value_attribute(...)
16
- { data: #{name}_#{property}(...) } # { data: value_property(...) }
17
- end # end
25
+ def #{name}(*args, **kwargs) # def values(*args, **kwargs)
26
+ template.stimulus_#{attribute_method_name}(*args.unshift(identifier), **kwargs) # template.stimulus_values_attributes(*args.unshift(identifier), **kwargs)
27
+ end # end
18
28
 
19
- alias #{name} #{name}_#{attribute} # alias value value_attribute
29
+ alias_method :#{alias_name}, :#{name} # alias_method :value, :values
30
+ alias_method :#{attribute_method_name}, :#{name} # alias_method :values_attributes, :values
31
+ alias_method :#{alias_name}_attribute, :#{name} # alias_method :value_attribute, :values
20
32
 
21
- def #{name}_#{property}(*args, **kws) # def value_property(*args, **kws)
22
- @template.stimulus_#{name}_#{property}(*args.unshift(@identifier), **kws) # stimulus_value_property(@identifier, *args, **kws)
23
- end # end
33
+ def #{property_method_name}(*args, **kwargs) # def values_properties(*args, **kwargs)
34
+ template.stimulus_#{property_method_name}(*args.unshift(identifier), **kwargs) # template.stimulus_values_properties(*args.unshift(identifier), **kwargs)
35
+ end # end
36
+
37
+ alias_method :#{alias_name}_property, :#{property_method_name} # alias_method :value_property, :values_properties
24
38
  RUBY
25
39
  end
26
40
 
27
- def attributes(props)
28
- { data: @template.stimulus_properties(@identifier, props) }
41
+ def attributes(**attributes)
42
+ template.stimulus_attributes(identifier, **attributes)
43
+ end
44
+
45
+ def properties(**properties)
46
+ template.stimulus_properties(identifier, **properties)
47
+ end
48
+
49
+ def capture(&block)
50
+ return template.capture(self, &block) unless tag
51
+
52
+ template.stimulus_controller_tag(identifier, tag: tag, **tag_options) do
53
+ template.capture(self, &block)
54
+ end
29
55
  end
30
56
  end
31
57
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StimulusTagHelper
4
- VERSION = "0.1.0"
4
+ VERSION = "0.3.0"
5
5
  end
@@ -1,74 +1,108 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/all"
4
+ require "zeitwerk"
5
+ Zeitwerk::Loader.for_gem.setup
6
+
3
7
  module StimulusTagHelper
4
- autoload :VERSION, "stimulus_tag_helper/version"
5
- autoload :StimulusAction, "stimulus_tag_helper/stimulus_action"
6
- autoload :StimulusControllerBuilder, "stimulus_tag_helper/stimulus_controller_builder"
8
+ def self.properties
9
+ %i[controllers values classes targets actions].freeze
10
+ end
11
+
12
+ def self.aliases
13
+ @aliases ||=
14
+ properties.map { |property| [property.to_s.singularize.to_sym, property] }.to_h.tap do |aliases|
15
+ aliases.dup.each { |key, value| aliases[value] = key }
16
+ end.freeze
17
+ end
7
18
 
8
- def self.base_properties
9
- %i[controller values classes targets target actions]
19
+ def self.all_possible_properties_names
20
+ @all_possible_properties_names ||= aliases.keys
10
21
  end
11
22
 
12
- def self.aliases_map
13
- { values: :value, classes: :class, actions: :action }
23
+ def self.property_method_name_for(property)
24
+ property = aliases[property] if properties.exclude?(property)
25
+ "#{property}_#{rendered_as(property) == :one ? "property" : "properties"}"
14
26
  end
15
27
 
16
- def self.alias_properties
17
- @alias_properties ||= aliases_map.values
28
+ def self.attribute_method_name_for(property)
29
+ property = aliases[property] if properties.exclude?(property)
30
+ "#{property}_#{rendered_as(property) == :one ? "attribute" : "attributes"}"
18
31
  end
19
32
 
20
- def self.property_names
21
- @property_names ||= base_properties + alias_properties
33
+ def self.rendered_as(property)
34
+ {controllers: :one, values: :many, classes: :many, targets: :many, actions: :one} \
35
+ [property] || raise(ArgumentError, "Unknown property: #{property.inspect}")
22
36
  end
23
37
 
24
38
  def self.prevent_duplicates(properties_set, name)
25
- alias_name = StimulusTagHelper.aliases_map[name]
39
+ alias_name = StimulusTagHelper.aliases[name]
26
40
  return unless alias_name && (properties_set[alias_name])
27
41
 
28
42
  raise(ArgumentError, <<~STRING)
29
- "#{name} and #{alias_name} can't be passed at same time"
43
+ "#{name} and #{alias_name} should not be passed at the same time"
30
44
  STRING
31
45
  end
32
46
 
33
- def stimulus_controller(identifier, tag: nil, **args, &block)
34
- raise(ArgumentError, "Missing block") unless block
35
-
36
- builder = StimulusControllerBuilder.new(identifier: identifier, template: self)
47
+ def stimulus_controller(identifier, tag: nil, **options, &block)
48
+ builder = StimulusControllerBuilder.new(identifier: identifier, tag: tag, template: self, **options)
49
+ return builder unless block
50
+ builder.capture(&block)
51
+ end
37
52
 
38
- return capture(builder, &block) unless tag
53
+ # controller arg is used to add additional stimulus controllers to the element
54
+ def stimulus_controller_tag(identifier, tag:, data: {}, controller: nil, **args, &block)
55
+ # class class interpreted as class attribute, not a stimulus class
56
+ # what about value and action action? maybe here should be warning
39
57
 
40
- stimulus_controller_tag(identifier, tag: tag, **args) do
41
- capture(builder, &block)
42
- end
58
+ # maybe data should be merged in args?
59
+ data.merge!(stimulus_properties(
60
+ identifier,
61
+ controller: data[:controller] || controller, # nil is allowed, because the args will be prepended by the identifier
62
+ **args.extract!(*StimulusTagHelper.all_possible_properties_names - %i[class])
63
+ ))
64
+ tag_builder.tag_string(tag, **args.merge(data: data), &block)
43
65
  end
44
66
 
45
- def stimulus_controller_tag(identifier, tag:, data: {}, **args, &block)
46
- data.merge!(stimulus_controllers_property(identifier))
47
- # class option goes to the tag
48
- data.merge!(stimulus_properties(identifier, args.extract!(*StimulusTagHelper.property_names - %i[class])))
49
- tag_builder.tag_string(tag, **args.merge(data: data), &block)
67
+ def stimulus_attributes(...)
68
+ {data: stimulus_properties(...)}
50
69
  end
51
70
 
52
- def stimulus_properties(identifier, props)
71
+ alias_method :stimulus_attribute, :stimulus_attributes
72
+
73
+ def stimulus_properties(identifier, **props)
74
+ props = props.symbolize_keys
53
75
  {}.tap do |data|
54
- StimulusTagHelper.property_names.each do |name|
55
- next unless props[name]
76
+ StimulusTagHelper.all_possible_properties_names.each do |name|
77
+ next unless props.key?(name)
56
78
 
57
- params = Array.wrap(props[name]).unshift(identifier)
58
- kwparams = params.last.is_a?(Hash) ? params.pop : {}
79
+ args = Array.wrap(props[name]).unshift(identifier)
80
+ kwargs = args.last.is_a?(Hash) ? args.pop : {}
59
81
  StimulusTagHelper.prevent_duplicates(props, name)
60
- name = name.to_s
61
- property = name.pluralize == name ? "properties" : "property"
62
- data.merge!(public_send("stimulus_#{name}_#{property}", *params, **kwparams))
82
+ data.merge!(
83
+ public_send("stimulus_#{StimulusTagHelper.property_method_name_for(name)}", *args, **kwargs)
84
+ )
63
85
  end
64
86
  end
65
87
  end
66
88
 
89
+ def stimulus_controllers_attribute(...)
90
+ {data: stimulus_controllers_properties(...)}
91
+ end
92
+
93
+ alias_method :stimulus_controller_attribute, :stimulus_controllers_attribute
94
+
67
95
  def stimulus_controllers_property(*identifiers)
68
- { controller: Array.wrap(identifiers).join(" ") }
96
+ {controller: identifiers.flatten.compact.uniq.join(" ")}
97
+ end
98
+
99
+ alias_method :stimulus_controller_property, :stimulus_controllers_property
100
+
101
+ def stimulus_values_attributes(...)
102
+ {data: stimulus_values_properties(...)}
69
103
  end
70
104
 
71
- alias stimulus_controller_property stimulus_controllers_property
105
+ alias_method :stimulus_value_attribute, :stimulus_values_attributes
72
106
 
73
107
  def stimulus_values_properties(identifier, **values)
74
108
  {}.tap do |properties|
@@ -78,7 +112,13 @@ module StimulusTagHelper
78
112
  end
79
113
  end
80
114
 
81
- alias stimulus_value_property stimulus_values_properties
115
+ alias_method :stimulus_value_property, :stimulus_values_properties
116
+
117
+ def stimulus_classes_attributes(...)
118
+ {data: stimulus_classes_properties(...)}
119
+ end
120
+
121
+ alias_method :stimulus_class_attribute, :stimulus_classes_attributes
82
122
 
83
123
  def stimulus_classes_properties(identifier, **classes)
84
124
  {}.tap do |properties|
@@ -88,47 +128,39 @@ module StimulusTagHelper
88
128
  end
89
129
  end
90
130
 
91
- alias stimulus_class_property stimulus_classes_properties
131
+ alias_method :stimulus_class_property, :stimulus_classes_properties
92
132
 
93
- def stimulus_targets_properties(identifier, *targets)
94
- {}.tap do |properties|
95
- targets.each do |target|
96
- properties.merge!(stimulus_target_property(identifier, target))
97
- end
98
- end
133
+ def stimulus_targets_attributes(...)
134
+ {data: stimulus_targets_properties(...)}
99
135
  end
100
136
 
101
- def stimulus_target_property(identifier, name)
102
- { "#{identifier}-target" => name }
137
+ alias_method :stimulus_target_attribute, :stimulus_targets_attributes
138
+
139
+ def stimulus_targets_properties(identifier, *targets)
140
+ {"#{identifier}-target" => targets.join(" ")}
103
141
  end
104
142
 
105
- def stimulus_actions_properties(identifier, *actions_params)
143
+ alias_method :stimulus_target_property, :stimulus_targets_properties
144
+
145
+ def stimulus_actions_property(identifier, *actions_params)
106
146
  {
107
- "action" => actions_params.map { |action_params| stimulus_action_value(identifier, action_params) }.join(" ")
147
+ action: actions_params.flatten.map { |action_params| stimulus_action_value(identifier, action_params) }.join(" ").html_safe
108
148
  }
109
149
  end
110
150
 
111
- alias stimulus_action_property stimulus_actions_properties
151
+ alias_method :stimulus_action_property, :stimulus_actions_property
112
152
 
113
- def stimulus_action_value(identifier, action_params_or_action_str)
114
- if action_params_or_action_str.is_a?(String)
115
- action_params_or_action_str = StimulusAction.parse(action_params_or_action_str)
116
- end
117
-
118
- StimulusAction.new(identifier: identifier, **action_params_or_action_str).to_s
153
+ def stimulus_actions_attribute(...)
154
+ {data: stimulus_actions_property(...)}
119
155
  end
120
156
 
121
- property_names.each do |name|
122
- name = name.to_s
123
- attribute, property = name.pluralize == name ? %w[attributes properties] : %w[attribute property]
124
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
125
- def stimulus_#{name}_#{attribute}(...) # def stimulus_value_attribute(...)
126
- { data: stimulus_#{name}_#{property}(...) } # { data: stimulus_value_property(...) }
127
- end # end
128
- RUBY
129
- end
157
+ alias_method :stimulus_action_attribute, :stimulus_actions_attribute
158
+
159
+ def stimulus_action_value(identifier, args_or_string) # :nodoc:
160
+ return StimulusAction.parse(args_or_string, identifier: identifier) if args_or_string.is_a?(String)
130
161
 
131
- def stimulus_attribute(...)
132
- { data: stimulus_properties(...) }
162
+ # WARNING: this is unsafe for public use by unexpired developers.
163
+ # TODO: find a elegant way to escape -> splitter escaping &gt; back and forth.
164
+ StimulusAction.new(identifier: identifier, **args_or_string).to_s.html_safe
133
165
  end
134
166
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stimulus_tag_helper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anton Topchii
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-23 00:00:00.000000000 Z
11
+ date: 2022-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 6.0.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.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.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: zeitwerk
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 2.5.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 2.5.0
27
55
  description:
28
56
  email:
29
57
  - player1@infinitevoid.net
@@ -60,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
60
88
  - !ruby/object:Gem::Version
61
89
  version: '0'
62
90
  requirements: []
63
- rubygems_version: 3.2.15
91
+ rubygems_version: 3.3.7
64
92
  signing_key:
65
93
  specification_version: 4
66
94
  summary: A form_for like, compact and elegant way to define stimulus attributes in