view_component 3.16.0 → 3.17.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/docs/CHANGELOG.md +22 -0
- data/lib/rails/generators/abstract_generator.rb +9 -1
- data/lib/rails/generators/erb/component_generator.rb +1 -1
- data/lib/rails/generators/stimulus/component_generator.rb +8 -3
- data/lib/rails/generators/stimulus/templates/component_controller.ts.tt +9 -0
- data/lib/view_component/base.rb +8 -0
- data/lib/view_component/compiler.rb +58 -53
- data/lib/view_component/config.rb +6 -0
- data/lib/view_component/errors.rb +0 -6
- data/lib/view_component/template.rb +6 -3
- data/lib/view_component/version.rb +1 -1
- metadata +59 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5f95cb571165fe8ad9d61f6236c5104ca6b9becec9c45e1f5bbb93f2e8bad487
|
|
4
|
+
data.tar.gz: 2f547097278242f1b1c945341b0cbcefd455ce93d2ed61145209f92a7acd5c2b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 51f0cbc8e8794c383cc2bbb97736e7be0da272c340c94ef9cf3927dd4526b58f73566aec5e1e37f0ee2a302fb99f0fec9a7f058620e6c051339db83426c8c852
|
|
7
|
+
data.tar.gz: 8484fa046329adf95fd78946ad5ce4b1ab647d9f6e7546da4bee02fe56fb74f25b8ad35cffee4afdae726d99832ebbcfae47a056603c6cfa1c9df7ef1e6476f4
|
data/docs/CHANGELOG.md
CHANGED
|
@@ -10,8 +10,30 @@ nav_order: 5
|
|
|
10
10
|
|
|
11
11
|
## main
|
|
12
12
|
|
|
13
|
+
## 3.17.0
|
|
14
|
+
|
|
15
|
+
* Use struct instead openstruct in lib code.
|
|
16
|
+
|
|
17
|
+
*Oleksii Vasyliev*
|
|
18
|
+
|
|
19
|
+
* Fix bug where stimulus controller was not added to ERB when stimulus was activated by default.
|
|
20
|
+
|
|
21
|
+
*Denis Pasin*
|
|
22
|
+
|
|
23
|
+
* Add typescript support to stimulus generator.
|
|
24
|
+
|
|
25
|
+
*Denis Pasin*
|
|
26
|
+
|
|
27
|
+
* Fix the example of #vc_test_request in the API reference to use the correct method name.
|
|
28
|
+
|
|
29
|
+
*Alberto Rocha*
|
|
30
|
+
|
|
13
31
|
## 3.16.0
|
|
14
32
|
|
|
33
|
+
* Fix development mode race condition that caused an invalid duplicate template error.
|
|
34
|
+
|
|
35
|
+
*Blake Williams*
|
|
36
|
+
|
|
15
37
|
* Add template information to multiple template error messages.
|
|
16
38
|
|
|
17
39
|
*Joel Hawksley*
|
|
@@ -33,7 +33,7 @@ module ViewComponent
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def stimulus_controller
|
|
36
|
-
if
|
|
36
|
+
if stimulus?
|
|
37
37
|
File.join(destination_directory, destination_file_name)
|
|
38
38
|
.sub("#{component_path}/", "")
|
|
39
39
|
.tr("_", "-")
|
|
@@ -44,5 +44,13 @@ module ViewComponent
|
|
|
44
44
|
def sidecar?
|
|
45
45
|
options["sidecar"] || ViewComponent::Base.config.generate.sidecar
|
|
46
46
|
end
|
|
47
|
+
|
|
48
|
+
def stimulus?
|
|
49
|
+
options["stimulus"] || ViewComponent::Base.config.generate.stimulus_controller
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def typescript?
|
|
53
|
+
options["typescript"] || ViewComponent::Base.config.generate.typescript
|
|
54
|
+
end
|
|
47
55
|
end
|
|
48
56
|
end
|
|
@@ -9,9 +9,10 @@ module Stimulus
|
|
|
9
9
|
|
|
10
10
|
source_root File.expand_path("templates", __dir__)
|
|
11
11
|
class_option :sidecar, type: :boolean, default: false
|
|
12
|
+
class_option :typescript, type: :boolean, default: false
|
|
12
13
|
|
|
13
14
|
def create_stimulus_controller
|
|
14
|
-
template "component_controller
|
|
15
|
+
template "component_controller.#{filetype}", destination
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
def stimulus_module
|
|
@@ -22,11 +23,15 @@ module Stimulus
|
|
|
22
23
|
|
|
23
24
|
private
|
|
24
25
|
|
|
26
|
+
def filetype
|
|
27
|
+
typescript? ? "ts" : "js"
|
|
28
|
+
end
|
|
29
|
+
|
|
25
30
|
def destination
|
|
26
31
|
if sidecar?
|
|
27
|
-
File.join(component_path, class_path, "#{file_name}_component", "#{file_name}_component_controller
|
|
32
|
+
File.join(component_path, class_path, "#{file_name}_component", "#{file_name}_component_controller.#{filetype}")
|
|
28
33
|
else
|
|
29
|
-
File.join(component_path, class_path, "#{file_name}_component_controller
|
|
34
|
+
File.join(component_path, class_path, "#{file_name}_component_controller.#{filetype}")
|
|
30
35
|
end
|
|
31
36
|
end
|
|
32
37
|
|
data/lib/view_component/base.rb
CHANGED
|
@@ -412,6 +412,14 @@ module ViewComponent
|
|
|
412
412
|
# config.view_component.generate.stimulus_controller = true
|
|
413
413
|
# ```
|
|
414
414
|
#
|
|
415
|
+
# #### `#typescript`
|
|
416
|
+
#
|
|
417
|
+
# Generate TypeScript files instead of JavaScript files:
|
|
418
|
+
#
|
|
419
|
+
# ```ruby
|
|
420
|
+
# config.view_component.generate.typescript = true
|
|
421
|
+
# ```
|
|
422
|
+
#
|
|
415
423
|
# #### #locale
|
|
416
424
|
#
|
|
417
425
|
# Always generate translations file alongside the component:
|
|
@@ -30,7 +30,12 @@ module ViewComponent
|
|
|
30
30
|
@component.superclass.compile(raise_errors: raise_errors)
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
if template_errors.present?
|
|
34
|
+
raise TemplateError.new(template_errors) if raise_errors
|
|
35
|
+
|
|
36
|
+
# this return is load bearing, and prevents the component from being considered "compiled?"
|
|
37
|
+
return false
|
|
38
|
+
end
|
|
34
39
|
|
|
35
40
|
if raise_errors
|
|
36
41
|
@component.validate_initialization_parameters!
|
|
@@ -98,70 +103,70 @@ module ViewComponent
|
|
|
98
103
|
end
|
|
99
104
|
end
|
|
100
105
|
|
|
101
|
-
def
|
|
102
|
-
|
|
106
|
+
def template_errors
|
|
107
|
+
@_template_errors ||= begin
|
|
108
|
+
errors = []
|
|
103
109
|
|
|
104
|
-
|
|
110
|
+
errors << "Couldn't find a template file or inline render method for #{@component}." if @templates.empty?
|
|
105
111
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
# We currently allow components to have both an inline call method and a template for a variant, with the
|
|
113
|
+
# inline call method overriding the template. We should aim to change this in v4 to instead
|
|
114
|
+
# raise an error.
|
|
115
|
+
@templates.reject(&:inline_call?)
|
|
116
|
+
.map { |template| [template.variant, template.format] }
|
|
117
|
+
.tally
|
|
118
|
+
.select { |_, count| count > 1 }
|
|
119
|
+
.each do |tally|
|
|
120
|
+
variant, this_format = tally.first
|
|
115
121
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
errors << "More than one #{this_format.upcase} template found#{variant_string} for #{@component}. "
|
|
119
|
-
end
|
|
122
|
+
variant_string = " for variant `#{variant}`" if variant.present?
|
|
120
123
|
|
|
121
|
-
|
|
122
|
-
|
|
124
|
+
errors << "More than one #{this_format.upcase} template found#{variant_string} for #{@component}. "
|
|
125
|
+
end
|
|
123
126
|
|
|
124
|
-
|
|
125
|
-
|
|
127
|
+
default_template_types = @templates.each_with_object(Set.new) do |template, memo|
|
|
128
|
+
next if template.variant
|
|
126
129
|
|
|
127
|
-
|
|
128
|
-
|
|
130
|
+
memo << :template_file if !template.inline_call?
|
|
131
|
+
memo << :inline_render if template.inline_call? && template.defined_on_self?
|
|
129
132
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
"Template file and inline render method found for #{@component}. " \
|
|
133
|
-
"There can only be a template file or inline render method per component."
|
|
134
|
-
end
|
|
133
|
+
memo
|
|
134
|
+
end
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
@templates.select { _1.inline_call? && _1.defined_on_self? }.map(&:variant)
|
|
142
|
-
|
|
143
|
-
unless duplicate_template_file_and_inline_call_variants.empty?
|
|
144
|
-
count = duplicate_template_file_and_inline_call_variants.count
|
|
145
|
-
|
|
146
|
-
errors <<
|
|
147
|
-
"Template #{"file".pluralize(count)} and inline render #{"method".pluralize(count)} " \
|
|
148
|
-
"found for #{"variant".pluralize(count)} " \
|
|
149
|
-
"#{duplicate_template_file_and_inline_call_variants.map { |v| "'#{v}'" }.to_sentence} " \
|
|
150
|
-
"in #{@component}. There can only be a template file or inline render method per variant."
|
|
151
|
-
end
|
|
136
|
+
if default_template_types.length > 1
|
|
137
|
+
errors <<
|
|
138
|
+
"Template file and inline render method found for #{@component}. " \
|
|
139
|
+
"There can only be a template file or inline render method per component."
|
|
140
|
+
end
|
|
152
141
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
142
|
+
# If a template has inline calls, they can conflict with template files the component may use
|
|
143
|
+
# to render. This attempts to catch and raise that issue before run time. For example,
|
|
144
|
+
# `def render_mobile` would conflict with a sidecar template of `component.html+mobile.erb`
|
|
145
|
+
duplicate_template_file_and_inline_call_variants =
|
|
146
|
+
@templates.reject(&:inline_call?).map(&:variant) &
|
|
147
|
+
@templates.select { _1.inline_call? && _1.defined_on_self? }.map(&:variant)
|
|
148
|
+
|
|
149
|
+
unless duplicate_template_file_and_inline_call_variants.empty?
|
|
150
|
+
count = duplicate_template_file_and_inline_call_variants.count
|
|
151
|
+
|
|
152
|
+
errors <<
|
|
153
|
+
"Template #{"file".pluralize(count)} and inline render #{"method".pluralize(count)} " \
|
|
154
|
+
"found for #{"variant".pluralize(count)} " \
|
|
155
|
+
"#{duplicate_template_file_and_inline_call_variants.map { |v| "'#{v}'" }.to_sentence} " \
|
|
156
|
+
"in #{@component}. There can only be a template file or inline render method per variant."
|
|
157
|
+
end
|
|
158
158
|
|
|
159
|
-
|
|
160
|
-
|
|
159
|
+
@templates.select(&:variant).each_with_object(Hash.new { |h, k| h[k] = Set.new }) do |template, memo|
|
|
160
|
+
memo[template.normalized_variant_name] << template.variant
|
|
161
|
+
memo
|
|
162
|
+
end.each do |_, variant_names|
|
|
163
|
+
next unless variant_names.length > 1
|
|
161
164
|
|
|
162
|
-
|
|
165
|
+
errors << "Colliding templates #{variant_names.sort.map { |v| "'#{v}'" }.to_sentence} found in #{@component}."
|
|
166
|
+
end
|
|
163
167
|
|
|
164
|
-
|
|
168
|
+
errors
|
|
169
|
+
end
|
|
165
170
|
end
|
|
166
171
|
|
|
167
172
|
def gather_templates
|
|
@@ -48,6 +48,12 @@ module ViewComponent
|
|
|
48
48
|
#
|
|
49
49
|
# config.view_component.generate.stimulus_controller = true
|
|
50
50
|
#
|
|
51
|
+
# #### `#typescript`
|
|
52
|
+
#
|
|
53
|
+
# Generate TypeScript files instead of JavaScript files:
|
|
54
|
+
#
|
|
55
|
+
# config.view_component.generate.typescript = true
|
|
56
|
+
#
|
|
51
57
|
# #### `#locale`
|
|
52
58
|
#
|
|
53
59
|
# Always generate translations file alongside the component:
|
|
@@ -20,12 +20,6 @@ module ViewComponent
|
|
|
20
20
|
def initialize(errors, templates = nil)
|
|
21
21
|
message = errors.join("\n")
|
|
22
22
|
|
|
23
|
-
if templates
|
|
24
|
-
message << "\n"
|
|
25
|
-
message << "Templates:\n"
|
|
26
|
-
message << templates.map(&:inspect).join("\n")
|
|
27
|
-
end
|
|
28
|
-
|
|
29
23
|
super(message)
|
|
30
24
|
end
|
|
31
25
|
end
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module ViewComponent
|
|
4
4
|
class Template
|
|
5
|
+
DataWithSource = Struct.new(:format, :identifier, :short_identifier, :type, keyword_init: true)
|
|
6
|
+
DataNoSource = Struct.new(:source, :identifier, :type, keyword_init: true)
|
|
7
|
+
|
|
5
8
|
attr_reader :variant, :this_format, :type
|
|
6
9
|
|
|
7
10
|
def initialize(
|
|
@@ -109,13 +112,13 @@ module ViewComponent
|
|
|
109
112
|
|
|
110
113
|
if handler.method(:call).parameters.length > 1
|
|
111
114
|
handler.call(
|
|
112
|
-
|
|
115
|
+
DataWithSource.new(format: @this_format, identifier: @path, short_identifier: short_identifier, type: type),
|
|
113
116
|
this_source
|
|
114
117
|
)
|
|
115
118
|
# :nocov:
|
|
116
119
|
# TODO: Remove in v4
|
|
117
120
|
else
|
|
118
|
-
handler.call(
|
|
121
|
+
handler.call(DataNoSource.new(source: this_source, identifier: @path, type: type))
|
|
119
122
|
end
|
|
120
123
|
# :nocov:
|
|
121
124
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: view_component
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.17.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ViewComponent Team
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-10-
|
|
11
|
+
date: 2024-10-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -492,6 +492,62 @@ dependencies:
|
|
|
492
492
|
- - ">="
|
|
493
493
|
- !ruby/object:Gem::Version
|
|
494
494
|
version: '0'
|
|
495
|
+
- !ruby/object:Gem::Dependency
|
|
496
|
+
name: base64
|
|
497
|
+
requirement: !ruby/object:Gem::Requirement
|
|
498
|
+
requirements:
|
|
499
|
+
- - ">="
|
|
500
|
+
- !ruby/object:Gem::Version
|
|
501
|
+
version: '0'
|
|
502
|
+
type: :development
|
|
503
|
+
prerelease: false
|
|
504
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
505
|
+
requirements:
|
|
506
|
+
- - ">="
|
|
507
|
+
- !ruby/object:Gem::Version
|
|
508
|
+
version: '0'
|
|
509
|
+
- !ruby/object:Gem::Dependency
|
|
510
|
+
name: bigdecimal
|
|
511
|
+
requirement: !ruby/object:Gem::Requirement
|
|
512
|
+
requirements:
|
|
513
|
+
- - ">="
|
|
514
|
+
- !ruby/object:Gem::Version
|
|
515
|
+
version: '0'
|
|
516
|
+
type: :development
|
|
517
|
+
prerelease: false
|
|
518
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
519
|
+
requirements:
|
|
520
|
+
- - ">="
|
|
521
|
+
- !ruby/object:Gem::Version
|
|
522
|
+
version: '0'
|
|
523
|
+
- !ruby/object:Gem::Dependency
|
|
524
|
+
name: drb
|
|
525
|
+
requirement: !ruby/object:Gem::Requirement
|
|
526
|
+
requirements:
|
|
527
|
+
- - ">="
|
|
528
|
+
- !ruby/object:Gem::Version
|
|
529
|
+
version: '0'
|
|
530
|
+
type: :development
|
|
531
|
+
prerelease: false
|
|
532
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
533
|
+
requirements:
|
|
534
|
+
- - ">="
|
|
535
|
+
- !ruby/object:Gem::Version
|
|
536
|
+
version: '0'
|
|
537
|
+
- !ruby/object:Gem::Dependency
|
|
538
|
+
name: mutex_m
|
|
539
|
+
requirement: !ruby/object:Gem::Requirement
|
|
540
|
+
requirements:
|
|
541
|
+
- - ">="
|
|
542
|
+
- !ruby/object:Gem::Version
|
|
543
|
+
version: '0'
|
|
544
|
+
type: :development
|
|
545
|
+
prerelease: false
|
|
546
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
547
|
+
requirements:
|
|
548
|
+
- - ">="
|
|
549
|
+
- !ruby/object:Gem::Version
|
|
550
|
+
version: '0'
|
|
495
551
|
- !ruby/object:Gem::Dependency
|
|
496
552
|
name: ostruct
|
|
497
553
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -543,6 +599,7 @@ files:
|
|
|
543
599
|
- lib/rails/generators/slim/templates/component.html.slim.tt
|
|
544
600
|
- lib/rails/generators/stimulus/component_generator.rb
|
|
545
601
|
- lib/rails/generators/stimulus/templates/component_controller.js.tt
|
|
602
|
+
- lib/rails/generators/stimulus/templates/component_controller.ts.tt
|
|
546
603
|
- lib/rails/generators/tailwindcss/component_generator.rb
|
|
547
604
|
- lib/rails/generators/tailwindcss/templates/component.html.erb.tt
|
|
548
605
|
- lib/rails/generators/test_unit/component_generator.rb
|