view_component_css_dsl 0.1.0 → 0.1.2
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 +13 -3
- data/README.md +120 -0
- data/lib/view_component_css_dsl/version.rb +1 -1
- data/lib/view_component_css_dsl.rb +182 -25
- metadata +17 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: eba29c79b834ffc0651fc3ff6b244e860de04218b6b29ca31df90634211fc6a6
|
|
4
|
+
data.tar.gz: fb7183fa91dc0bb773d61dc0953df0cf17fed601d39609cc1b2e2d44da725f51
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d28bfc76e89df1e4899fa396f0d45be296bbef32bed288d4893f908ad9038f28bc3f3e444675acf1408e01859f2cd6b007cb4fc346bad8389377765768952ff9
|
|
7
|
+
data.tar.gz: 9353657fc812e95881ec400152852886d05f2292f978d590dc0475abb64cb87dfe61ba38c1cde972d8c2c6f22eb74d0e88bd2f2c632455d1caa5d368f6d230e4
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## [Unreleased]
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
|
|
5
|
+
## [0.1.2] - 2026-05-15
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- data, aria, and attribute DSL declarators for first-class HTML attribute declarations (cf37050)
|
|
10
|
+
|
|
11
|
+
## [0.1.1] - 2026-05-15
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- `view_component` dependency pinned to `~> 4.0` (was `>= 4.0`) — RubyGems-recommended SemVer-aware constraint
|
|
16
|
+
- Minimum Ruby version raised to 3.2 (was 3.1), matching the floor for `view_component >= 4.0`
|
data/README.md
CHANGED
|
@@ -237,6 +237,124 @@ css -> { "pl-#{@indent * 4}" }
|
|
|
237
237
|
|
|
238
238
|
Procs returning `nil` are dropped. Procs participate in smart_merge.
|
|
239
239
|
|
|
240
|
+
## Declaring `data`, `aria`, and HTML attributes
|
|
241
|
+
|
|
242
|
+
The gem provides three sibling declarators that mirror `css`'s shape: `data`, `aria`, and `attribute`. Use them to declare attributes alongside your styles instead of overriding methods.
|
|
243
|
+
|
|
244
|
+
```ruby
|
|
245
|
+
class ButtonComponent < ApplicationComponent
|
|
246
|
+
css "rounded px-4 py-2 bg-blue-500 text-white"
|
|
247
|
+
|
|
248
|
+
data variant: :variant, size: :size
|
|
249
|
+
aria label: "Submit"
|
|
250
|
+
attribute target: "_blank"
|
|
251
|
+
|
|
252
|
+
def initialize(variant: :primary, size: :default)
|
|
253
|
+
@variant = variant
|
|
254
|
+
@size = size
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
attr_reader :variant, :size
|
|
258
|
+
end
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
All three declarators share the same patterns. The only difference is *where* the attribute lands in the rendered HTML — `data` produces `data-*`, `aria` produces `aria-*`, and `attribute` produces a top-level attribute.
|
|
262
|
+
|
|
263
|
+
### Static values
|
|
264
|
+
|
|
265
|
+
Always emitted. Stringified at render time (booleans, integers, etc. all become strings; `nil` drops the attribute).
|
|
266
|
+
|
|
267
|
+
```ruby
|
|
268
|
+
data controller: "modal"
|
|
269
|
+
aria label: "Close dialog"
|
|
270
|
+
attribute target: "_blank"
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Symbol values — call an instance method
|
|
274
|
+
|
|
275
|
+
When the value is a Symbol, the DSL calls that instance method at render time and uses the result. Standard pattern for streaming an ivar or computed value into a data attribute.
|
|
276
|
+
|
|
277
|
+
```ruby
|
|
278
|
+
data variant: :variant # calls #variant; renders as data-variant="<value>"
|
|
279
|
+
attribute tabindex: :tab_index
|
|
280
|
+
|
|
281
|
+
def tab_index
|
|
282
|
+
focusable? ? 0 : -1
|
|
283
|
+
end
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
If the method returns `nil`, the attribute is dropped.
|
|
287
|
+
|
|
288
|
+
### Proc values — inline computation
|
|
289
|
+
|
|
290
|
+
For one-off computed values that don't deserve a named method:
|
|
291
|
+
|
|
292
|
+
```ruby
|
|
293
|
+
aria label: -> { "#{@variant} Notification".titleize }
|
|
294
|
+
data turbo_permanent: -> { true if turbo_permanent? }
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Procs are `instance_exec`'d at render time, so they see instance state. Procs returning `nil` drop the attribute.
|
|
298
|
+
|
|
299
|
+
### Conditional inclusion via positional predicate
|
|
300
|
+
|
|
301
|
+
Mirrors the `css :method?, style: "..."` pattern — a positional Symbol or Proc as the first argument acts as a predicate. When truthy, the declaration applies; when falsy, it's skipped entirely.
|
|
302
|
+
|
|
303
|
+
```ruby
|
|
304
|
+
data :auto_dismiss?, timeout: "5000", animation: "fade"
|
|
305
|
+
aria :loud?, label: "Important"
|
|
306
|
+
attribute -> { @disabled }, disabled: true
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
The Symbol form calls the named instance method; the Proc form is `instance_exec`'d.
|
|
310
|
+
|
|
311
|
+
### Multiple attributes per declaration
|
|
312
|
+
|
|
313
|
+
Each declaration accepts a hash of attributes. All share the same predicate (if any).
|
|
314
|
+
|
|
315
|
+
```ruby
|
|
316
|
+
data controller: "modal",
|
|
317
|
+
modal_dismiss_action: "click->modal#dismiss"
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Multiple declarations: how they compose
|
|
321
|
+
|
|
322
|
+
For `aria` and `attribute`, repeated keys across declarations *replace* — the last declaration wins.
|
|
323
|
+
|
|
324
|
+
For `data`, **the keys `:controller` and `:action` accumulate** (they're space-separated lists in HTML), and everything else replaces. This matches how the gem already merges component defaults with caller-passed values.
|
|
325
|
+
|
|
326
|
+
```ruby
|
|
327
|
+
data :modal?, controller: "modal"
|
|
328
|
+
data :trap_focus?, controller: "trap-focus"
|
|
329
|
+
# Both predicates true → data-controller="modal trap-focus"
|
|
330
|
+
# Only :modal? true → data-controller="modal"
|
|
331
|
+
# Neither true → data-controller attribute is omitted
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Caller customization
|
|
335
|
+
|
|
336
|
+
Whatever a caller passes for `class:`, `data:`, `aria:`, or any HTML attribute layers on top of your declarations using the same rules:
|
|
337
|
+
|
|
338
|
+
- `class:` smart-merged (see Smart merge behavior below)
|
|
339
|
+
- `data:` controller/action keys concatenate, others replace
|
|
340
|
+
- `aria:` and other attrs: caller wins
|
|
341
|
+
|
|
342
|
+
### Inheritance
|
|
343
|
+
|
|
344
|
+
Subclass declarations stack on top of parent declarations using the same rules. `data controller:` declarations in a child class concatenate with the parent's; `data role:` in a child class replaces the parent's. `aria` and `attribute` keys in a child class replace the parent's.
|
|
345
|
+
|
|
346
|
+
```ruby
|
|
347
|
+
class CardComponent < ApplicationComponent
|
|
348
|
+
data controller: "card"
|
|
349
|
+
data role: "region"
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
class HighlightedCardComponent < CardComponent
|
|
353
|
+
data controller: "highlighted" # appends → data-controller="card highlighted"
|
|
354
|
+
data role: "alert" # replaces → data-role="alert"
|
|
355
|
+
end
|
|
356
|
+
```
|
|
357
|
+
|
|
240
358
|
## Caller customization
|
|
241
359
|
|
|
242
360
|
Callers can pass `class:` (smart-merged with the component's defaults), plus any other HTML attribute (`data:`, `id:`, `aria:`, etc.) — they all land on the top-level element without the component having to opt each one in.
|
|
@@ -327,6 +445,8 @@ bundle exec rspec
|
|
|
327
445
|
bundle exec standardrb
|
|
328
446
|
```
|
|
329
447
|
|
|
448
|
+
Releases are managed by [reissue](https://github.com/SOFware/reissue). When committing, add Keep-a-Changelog trailers (`Added:`, `Changed:`, `Fixed:`, etc.) and reissue will collate them into `CHANGELOG.md` at release time. To publish a new version, run the "Release gem to RubyGems.org" workflow from GitHub Actions.
|
|
449
|
+
|
|
330
450
|
## License
|
|
331
451
|
|
|
332
452
|
MIT. See [LICENSE.txt](LICENSE.txt).
|
|
@@ -12,11 +12,6 @@ require_relative "view_component_css_dsl/version"
|
|
|
12
12
|
module ViewComponentCssDsl
|
|
13
13
|
extend ActiveSupport::Concern
|
|
14
14
|
|
|
15
|
-
# HTML attributes auto-extracted from kwargs at construction time. Anything in
|
|
16
|
-
# this set is captured into @html_attrs instead of being passed to initialize,
|
|
17
|
-
# so callers can pass `class:`, `data:`, `aria:`, etc. without the component
|
|
18
|
-
# declaring them. To opt out, accept a kwarg with the same name in initialize
|
|
19
|
-
# (e.g. `def initialize(class:)`) or use a keyrest name other than html_attrs.
|
|
20
15
|
HTML_ATTR_KEYS = Set[
|
|
21
16
|
:alt, :aria, :autofocus,
|
|
22
17
|
:class, :colspan, :contenteditable,
|
|
@@ -138,6 +133,10 @@ module ViewComponentCssDsl
|
|
|
138
133
|
class_attribute :_css_cache, instance_writer: false, default: nil
|
|
139
134
|
# Memoization cache for smart_merge results (axis + method + proc combinations)
|
|
140
135
|
class_attribute :_css_merge_cache, instance_writer: false, default: nil
|
|
136
|
+
# Rules for the data/aria/attribute DSLs. Each entry: {predicate:, attrs:}
|
|
137
|
+
class_attribute :_data_rules, instance_writer: false, default: []
|
|
138
|
+
class_attribute :_aria_rules, instance_writer: false, default: []
|
|
139
|
+
class_attribute :_attribute_rules, instance_writer: false, default: []
|
|
141
140
|
end
|
|
142
141
|
|
|
143
142
|
class_methods do
|
|
@@ -203,23 +202,117 @@ module ViewComponentCssDsl
|
|
|
203
202
|
end
|
|
204
203
|
end
|
|
205
204
|
|
|
205
|
+
# Declares one or more `data-*` attributes on the top-level element.
|
|
206
|
+
#
|
|
207
|
+
# data controller: "modal" # static
|
|
208
|
+
# data variant: :variant # Symbol value -> calls instance method
|
|
209
|
+
# data foo: -> { computed_value } # Proc value -> instance_exec'd
|
|
210
|
+
# data :auto_dismiss?, timeout_value: "5000" # Symbol predicate
|
|
211
|
+
# data -> { complex_check? }, foo: "bar" # Proc predicate
|
|
212
|
+
def data(*args, **kwargs)
|
|
213
|
+
self._data_rules = _data_rules.dup
|
|
214
|
+
_data_rules << _build_attr_rule(:data, *args, **kwargs)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# Declares one or more `aria-*` attributes on the top-level element.
|
|
218
|
+
# See `data` for the full pattern.
|
|
219
|
+
def aria(*args, **kwargs)
|
|
220
|
+
self._aria_rules = _aria_rules.dup
|
|
221
|
+
_aria_rules << _build_attr_rule(:aria, *args, **kwargs)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# Declares one or more top-level HTML attributes (`target`, `role`, `tabindex`,
|
|
225
|
+
# etc.) on the rendered element. See `data` for the full pattern.
|
|
226
|
+
def attribute(*args, **kwargs)
|
|
227
|
+
self._attribute_rules = _attribute_rules.dup
|
|
228
|
+
_attribute_rules << _build_attr_rule(:attribute, *args, **kwargs)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
private
|
|
232
|
+
|
|
233
|
+
# Builds the rule entry used by `data`, `aria`, and `attribute`.
|
|
234
|
+
# Returns {predicate:, attrs:} where predicate is nil, Symbol, or Proc and
|
|
235
|
+
# attrs is the hash of attribute key -> (literal | Symbol | Proc).
|
|
236
|
+
def _build_attr_rule(namespace, *args, **kwargs)
|
|
237
|
+
if args.size > 1
|
|
238
|
+
raise ArgumentError,
|
|
239
|
+
"#{namespace} accepts at most one positional arg (a predicate Symbol or Proc)"
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
predicate = args.first
|
|
243
|
+
if predicate && !predicate.is_a?(Symbol) && !predicate.is_a?(Proc)
|
|
244
|
+
raise ArgumentError,
|
|
245
|
+
"#{namespace} positional predicate must be a Symbol or Proc " \
|
|
246
|
+
"(got #{predicate.class})"
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
if kwargs.empty?
|
|
250
|
+
raise ArgumentError,
|
|
251
|
+
"#{namespace} requires at least one attribute kwarg"
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
{predicate:, attrs: kwargs}
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
public
|
|
258
|
+
|
|
206
259
|
# Override `new` to auto-extract HTML attributes from kwargs into @html_attrs,
|
|
207
260
|
# so components don't need to declare **html_attrs in their initialize signature.
|
|
208
261
|
# Anything in HTML_ATTR_KEYS that wasn't declared as a kwarg is captured.
|
|
262
|
+
#
|
|
263
|
+
# These can then be referenced in the component's template as `html_attrs`.
|
|
264
|
+
#
|
|
265
|
+
# Why?
|
|
266
|
+
# - DX: All components can accept arbitrary html attrs for free. Dev can pass
|
|
267
|
+
# arbitrary html attrs in at any caller and have it output at the component's
|
|
268
|
+
# top-level element.
|
|
269
|
+
# - Removes boilerplate of putting `**html_attrs` as the last argument in every
|
|
270
|
+
# single component's initialize signature, and then having to set the same as an
|
|
271
|
+
# ivar within the initialize body.
|
|
272
|
+
# - Requires following a pattern of declaring `**html_attrs` in the top level
|
|
273
|
+
# element of every single component's template.
|
|
274
|
+
# - Example template definition:
|
|
275
|
+
#
|
|
276
|
+
# # html_attrs contains :class, :data, etc defined either in the component
|
|
277
|
+
# # or passed in by the caller.
|
|
278
|
+
# <%= tag.my_component **html_attrs do %>
|
|
279
|
+
# <%= content %>
|
|
280
|
+
# <% end %>
|
|
281
|
+
#
|
|
282
|
+
# Example caller:
|
|
283
|
+
#
|
|
284
|
+
# render MyComponent.new(text: "Hello", class: "custom", data: {foo: "bar"})
|
|
285
|
+
#
|
|
286
|
+
# - :text goes to component's #initialize method, as normal
|
|
287
|
+
# - :class, :data, etc are captured and merged into @html_attrs automatically
|
|
288
|
+
# - The component's initialize method will look like:
|
|
289
|
+
#
|
|
290
|
+
# def initialize(text)
|
|
291
|
+
# @text = text
|
|
292
|
+
# end
|
|
293
|
+
#
|
|
294
|
+
# To opt out of this behavior, inherit from ViewComponent::Base directly instead of
|
|
295
|
+
# ApplicationComponent.
|
|
296
|
+
#
|
|
209
297
|
def new(*args, **kwargs, &block)
|
|
210
298
|
info = initialize_params_info
|
|
211
299
|
html_attrs = {}
|
|
300
|
+
|
|
301
|
+
# Only extract HTML attrs if the component uses **html_attrs pattern.
|
|
302
|
+
# Components with other keyrest names (like **options) should receive all kwargs.
|
|
212
303
|
if info[:uses_html_attrs_keyrest]
|
|
304
|
+
# Extract HTML attrs, but NOT if they're declared component params
|
|
213
305
|
extractable = HTML_ATTR_KEYS.intersection(kwargs.keys) - info[:declared_kwargs]
|
|
214
306
|
html_attrs = kwargs.extract!(*extractable)
|
|
215
307
|
end
|
|
216
308
|
|
|
217
309
|
instance = allocate
|
|
310
|
+
# Set @html_attrs BEFORE initialize so components can access it there
|
|
218
311
|
instance.instance_variable_set(:@html_attrs, html_attrs)
|
|
219
312
|
instance.send(:initialize, *args, **kwargs, &block)
|
|
220
313
|
|
|
221
|
-
# Merge with any @html_attrs
|
|
222
|
-
#
|
|
314
|
+
# Merge with any @html_attrs set by initialize (old pattern components).
|
|
315
|
+
# Caller-provided values (html_attrs) take precedence over component defaults.
|
|
223
316
|
existing = instance.instance_variable_get(:@html_attrs) || {}
|
|
224
317
|
instance.instance_variable_set(:@html_attrs, existing.merge(html_attrs))
|
|
225
318
|
instance
|
|
@@ -234,12 +327,17 @@ module ViewComponentCssDsl
|
|
|
234
327
|
keyrest_name = nil
|
|
235
328
|
instance_method(:initialize).parameters.each do |type, name|
|
|
236
329
|
case type
|
|
237
|
-
when :key, :keyreq
|
|
238
|
-
|
|
330
|
+
when :key, :keyreq
|
|
331
|
+
declared_kwargs << name
|
|
332
|
+
when :keyrest
|
|
333
|
+
keyrest_name = name
|
|
239
334
|
end
|
|
240
335
|
end
|
|
241
|
-
|
|
242
|
-
{
|
|
336
|
+
|
|
337
|
+
{
|
|
338
|
+
declared_kwargs:,
|
|
339
|
+
uses_html_attrs_keyrest: keyrest_name == :html_attrs || keyrest_name.nil?
|
|
340
|
+
}
|
|
243
341
|
end
|
|
244
342
|
end
|
|
245
343
|
|
|
@@ -361,7 +459,10 @@ module ViewComponentCssDsl
|
|
|
361
459
|
def html_attrs
|
|
362
460
|
return {} unless @html_attrs
|
|
363
461
|
|
|
364
|
-
|
|
462
|
+
# Start with DSL-declared top-level attrs; caller's html_attrs layer on top
|
|
463
|
+
# (caller wins on collision, mirroring the css behavior).
|
|
464
|
+
dsl_attrs = resolved_attr_rules(:attribute)
|
|
465
|
+
result = dsl_attrs.merge(@html_attrs.except(:aria, :class, :data))
|
|
365
466
|
|
|
366
467
|
# Only include aria/data if they have content, otherwise they'd override
|
|
367
468
|
# inline attrs in templates like: tag.div data: {foo: "bar"}, **html_attrs
|
|
@@ -422,16 +523,11 @@ module ViewComponentCssDsl
|
|
|
422
523
|
# - In contrast, data-label from the caller overwrites the default
|
|
423
524
|
#
|
|
424
525
|
def final_data_attrs
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
value
|
|
431
|
-
end
|
|
432
|
-
|
|
433
|
-
final_data[key] = final_value
|
|
434
|
-
end
|
|
526
|
+
# Merge in order: DSL declarations -> method override -> caller's :data.
|
|
527
|
+
# Each layer uses DATA_MERGE_KEYS semantics (controller/action concatenate,
|
|
528
|
+
# everything else replaces).
|
|
529
|
+
combined = merge_data_layer(resolved_attr_rules(:data), data_attrs)
|
|
530
|
+
merge_data_layer(combined, @html_attrs.fetch(:data, {}))
|
|
435
531
|
end
|
|
436
532
|
|
|
437
533
|
# Overwrite in subclass to define default aria-attrs
|
|
@@ -439,14 +535,75 @@ module ViewComponentCssDsl
|
|
|
439
535
|
{}
|
|
440
536
|
end
|
|
441
537
|
|
|
442
|
-
#
|
|
443
|
-
#
|
|
538
|
+
# Merge in order: DSL declarations -> method override -> caller's :aria.
|
|
539
|
+
# Hash#merge throughout — caller wins on collision (no additive semantics).
|
|
444
540
|
def final_aria_attrs
|
|
445
|
-
aria_attrs.merge(@html_attrs.fetch(:aria, {}))
|
|
541
|
+
resolved_attr_rules(:aria).merge(aria_attrs).merge(@html_attrs.fetch(:aria, {}))
|
|
446
542
|
end
|
|
447
543
|
|
|
448
544
|
private
|
|
449
545
|
|
|
546
|
+
# Walks the DSL rules for the given namespace (:data, :aria, :attribute),
|
|
547
|
+
# evaluates each predicate, resolves each value, and returns a hash. For
|
|
548
|
+
# the :data namespace, DATA_MERGE_KEYS keys accumulate space-separated when
|
|
549
|
+
# the same key appears in multiple included rules.
|
|
550
|
+
def resolved_attr_rules(namespace)
|
|
551
|
+
rules = case namespace
|
|
552
|
+
when :data then self.class._data_rules
|
|
553
|
+
when :aria then self.class._aria_rules
|
|
554
|
+
when :attribute then self.class._attribute_rules
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
rules.each_with_object({}) do |rule, result|
|
|
558
|
+
next unless predicate_met?(rule[:predicate])
|
|
559
|
+
|
|
560
|
+
rule[:attrs].each do |key, value|
|
|
561
|
+
resolved = resolve_attr_value(value)
|
|
562
|
+
next if resolved.nil?
|
|
563
|
+
|
|
564
|
+
result[key] = if namespace == :data && DATA_MERGE_KEYS.include?(key) && result.key?(key)
|
|
565
|
+
"#{result[key]} #{resolved}"
|
|
566
|
+
else
|
|
567
|
+
resolved
|
|
568
|
+
end
|
|
569
|
+
end
|
|
570
|
+
end
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
# Layers `addition` on top of `base` using DATA_MERGE_KEYS semantics: keys
|
|
574
|
+
# in DATA_MERGE_KEYS concatenate space-separated, every other key replaces.
|
|
575
|
+
def merge_data_layer(base, addition)
|
|
576
|
+
addition.each_with_object(base.dup) do |(key, value), result|
|
|
577
|
+
result[key] = if DATA_MERGE_KEYS.include?(key)
|
|
578
|
+
[result[key], value].compact.join(" ")
|
|
579
|
+
else
|
|
580
|
+
value
|
|
581
|
+
end
|
|
582
|
+
end
|
|
583
|
+
end
|
|
584
|
+
|
|
585
|
+
# Resolves a predicate. nil predicate -> always true. Symbol -> call instance
|
|
586
|
+
# method. Proc -> instance_exec.
|
|
587
|
+
def predicate_met?(predicate)
|
|
588
|
+
case predicate
|
|
589
|
+
when nil then true
|
|
590
|
+
when Symbol then send(predicate)
|
|
591
|
+
when Proc then instance_exec(&predicate)
|
|
592
|
+
end
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
# Resolves a value for a DSL-declared attribute. Symbols become method calls
|
|
596
|
+
# on the instance; Procs are instance_exec'd; literals pass through. Result
|
|
597
|
+
# is stringified unless nil (which drops the attribute).
|
|
598
|
+
def resolve_attr_value(value)
|
|
599
|
+
resolved = case value
|
|
600
|
+
when Symbol then send(value)
|
|
601
|
+
when Proc then instance_exec(&value)
|
|
602
|
+
else value
|
|
603
|
+
end
|
|
604
|
+
resolved&.to_s
|
|
605
|
+
end
|
|
606
|
+
|
|
450
607
|
def build_classes
|
|
451
608
|
validate_axes!
|
|
452
609
|
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: view_component_css_dsl
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jeff Lange
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: activesupport
|
|
@@ -44,6 +43,20 @@ dependencies:
|
|
|
44
43
|
- - "~>"
|
|
45
44
|
- !ruby/object:Gem::Version
|
|
46
45
|
version: '4.0'
|
|
46
|
+
- !ruby/object:Gem::Dependency
|
|
47
|
+
name: reissue
|
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
|
49
|
+
requirements:
|
|
50
|
+
- - "~>"
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: '0.4'
|
|
53
|
+
type: :development
|
|
54
|
+
prerelease: false
|
|
55
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
56
|
+
requirements:
|
|
57
|
+
- - "~>"
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '0.4'
|
|
47
60
|
- !ruby/object:Gem::Dependency
|
|
48
61
|
name: rspec
|
|
49
62
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -95,7 +108,6 @@ metadata:
|
|
|
95
108
|
source_code_uri: https://github.com/SOFware/view_component_css_dsl
|
|
96
109
|
changelog_uri: https://github.com/SOFware/view_component_css_dsl/blob/main/CHANGELOG.md
|
|
97
110
|
rubygems_mfa_required: 'true'
|
|
98
|
-
post_install_message:
|
|
99
111
|
rdoc_options: []
|
|
100
112
|
require_paths:
|
|
101
113
|
- lib
|
|
@@ -110,8 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
110
122
|
- !ruby/object:Gem::Version
|
|
111
123
|
version: '0'
|
|
112
124
|
requirements: []
|
|
113
|
-
rubygems_version:
|
|
114
|
-
signing_key:
|
|
125
|
+
rubygems_version: 4.0.3
|
|
115
126
|
specification_version: 4
|
|
116
127
|
summary: Declarative CSS class DSL for ViewComponent + Tailwind
|
|
117
128
|
test_files: []
|