view_component 4.20.0 → 4.21.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 +94 -0
- data/lib/generators/view_component/abstract_generator.rb +24 -4
- data/lib/generators/view_component/component/component_generator.rb +8 -6
- data/lib/generators/view_component/component/templates/component.rb.tt +1 -1
- data/lib/generators/view_component/erb/erb_generator.rb +2 -2
- data/lib/generators/view_component/haml/haml_generator.rb +1 -1
- data/lib/generators/view_component/locale/locale_generator.rb +2 -6
- data/lib/generators/view_component/preview/preview_generator.rb +9 -6
- data/lib/generators/view_component/preview/templates/component_preview.rb.tt +2 -2
- data/lib/generators/view_component/rspec/rspec_generator.rb +1 -1
- data/lib/generators/view_component/rspec/templates/component_spec.rb.tt +1 -1
- data/lib/generators/view_component/slim/slim_generator.rb +1 -1
- data/lib/generators/view_component/stimulus/stimulus_generator.rb +3 -7
- data/lib/generators/view_component/test_unit/templates/component_test.rb.tt +2 -2
- data/lib/generators/view_component/test_unit/test_unit_generator.rb +8 -7
- data/lib/view_component/base.rb +106 -98
- data/lib/view_component/cache_digest/dependency_tracking.rb +6 -6
- data/lib/view_component/cache_digest/digestor_lookup.rb +3 -1
- data/lib/view_component/cache_digest/resolver.rb +59 -38
- data/lib/view_component/cache_digest.rb +161 -53
- data/lib/view_component/cacheable.rb +16 -18
- data/lib/view_component/collection.rb +4 -9
- data/lib/view_component/compile_cache.rb +44 -5
- data/lib/view_component/compiler.rb +50 -2
- data/lib/view_component/config.rb +114 -8
- data/lib/view_component/engine.rb +1 -2
- data/lib/view_component/errors.rb +16 -0
- data/lib/view_component/slot.rb +12 -0
- data/lib/view_component/slotable.rb +28 -4
- data/lib/view_component/template.rb +16 -3
- data/lib/view_component/test_helpers.rb +38 -16
- data/lib/view_component/translatable.rb +34 -0
- data/lib/view_component/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 829de474217e06e2148d92de68ef3d93dd8a31e314b40073fc292440508731b8
|
|
4
|
+
data.tar.gz: 1dfb4a41b58c47814b115b72e6cfc736e3239886376632e7177cadfa024c8582
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 644364f5c6e4375b130074078de4e692dfdc4fca34ceca1bfedd307a135cfe9bd8ed81b111f08e1222af4d334afcb81fee48ee50a9b92bc21df591f783230314
|
|
7
|
+
data.tar.gz: d7902711e70321bc27f0b4b9bbf5dbd7f75864444dcaacf4bdfc762c765c87f688463b9f65edcf01656aea723fc82baf421edcf6f35989ce60c9875ebb91c699
|
data/docs/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,100 @@ nav_order: 6
|
|
|
10
10
|
|
|
11
11
|
## main
|
|
12
12
|
|
|
13
|
+
## 4.21.0
|
|
14
|
+
|
|
15
|
+
* Avoid `NameError` during eager loading when components include modules with temporary names.
|
|
16
|
+
|
|
17
|
+
*Joel Hawksley*
|
|
18
|
+
|
|
19
|
+
* Avoid repeated scanning of unterminated ERB tags during cache dependency discovery.
|
|
20
|
+
|
|
21
|
+
*Joel Hawksley*
|
|
22
|
+
|
|
23
|
+
* Skip dependency compilation for static ERB markup and literal templates while preserving helper-rendered component tracking.
|
|
24
|
+
|
|
25
|
+
*Joel Hawksley*
|
|
26
|
+
|
|
27
|
+
* Track helper-rendered component cache dependencies, enforce single-use instances on cache hits, and emit one render notification per self-cached render.
|
|
28
|
+
|
|
29
|
+
*Joel Hawksley*
|
|
30
|
+
|
|
31
|
+
* Resolve symbolic translation defaults in sidecars, restore request URL state in tests, and refresh inherited templates whenever template reloading is enabled.
|
|
32
|
+
|
|
33
|
+
*Joel Hawksley*
|
|
34
|
+
|
|
35
|
+
* Reuse existing GitHub releases when retrying a failed gem publish.
|
|
36
|
+
|
|
37
|
+
*Joel Hawksley*
|
|
38
|
+
|
|
39
|
+
* Prevent self-cache key collisions and track component references in views and format-specific partial dependencies.
|
|
40
|
+
|
|
41
|
+
*Joel Hawksley*
|
|
42
|
+
|
|
43
|
+
* Isolate preview and request parameters, honor preview locale callbacks, restore controller view contexts, and accept nil translation keys.
|
|
44
|
+
|
|
45
|
+
*Joel Hawksley*
|
|
46
|
+
|
|
47
|
+
* Honor negative generator flags and preserve pre-release versions throughout release automation. Report gem publishing failures.
|
|
48
|
+
|
|
49
|
+
*Joel Hawksley*
|
|
50
|
+
|
|
51
|
+
* Fix fragment cache collisions after `render_parent`, missing relative-partial and inherited-template dependencies, format fallback cache collisions, and stale cached output after development template edits.
|
|
52
|
+
|
|
53
|
+
*Joel Hawksley*
|
|
54
|
+
|
|
55
|
+
* Fix template method collisions between formats and variants, preserve default slot state, and copy collection spacer slots independently.
|
|
56
|
+
|
|
57
|
+
*Joel Hawksley*
|
|
58
|
+
|
|
59
|
+
* Apply `--skip-suffix` to all generated component files and restore full request URLs after `with_request_url` blocks.
|
|
60
|
+
|
|
61
|
+
*Joel Hawksley*
|
|
62
|
+
|
|
63
|
+
* Reset the assertion page when rendering a preview so assertions inspect the latest output.
|
|
64
|
+
|
|
65
|
+
*Joel Hawksley*
|
|
66
|
+
|
|
67
|
+
* Rediscover templates after development changes, including added or removed variants and parent templates.
|
|
68
|
+
|
|
69
|
+
*Joel Hawksley*
|
|
70
|
+
|
|
71
|
+
* Include all requested variants in output cache keys, preserving fallback order.
|
|
72
|
+
|
|
73
|
+
*Joel Hawksley*
|
|
74
|
+
|
|
75
|
+
* Resolve cache dependencies in their Ruby lexical namespaces and component template scopes.
|
|
76
|
+
|
|
77
|
+
*Joel Hawksley*
|
|
78
|
+
|
|
79
|
+
* Keep default slot configuration isolated between parent components and subclasses.
|
|
80
|
+
|
|
81
|
+
*Joel Hawksley*
|
|
82
|
+
|
|
83
|
+
* Preserve the calling view's translation scope when a component returns cached output or rejects content.
|
|
84
|
+
|
|
85
|
+
*Joel Hawksley*
|
|
86
|
+
|
|
87
|
+
* Reduce rendering and collection overhead, and speed up eager loading by sharing template-path parsing and avoiding redundant template and ancestor checks.
|
|
88
|
+
|
|
89
|
+
*Joel Hawksley*
|
|
90
|
+
|
|
91
|
+
* Speed up eager loading by sharing source-file reads between template compilation and cache digest precomputation, and reduce nested-render and default-slot lookup overhead.
|
|
92
|
+
|
|
93
|
+
*Joel Hawksley*
|
|
94
|
+
|
|
95
|
+
* Speed up eager loading by sharing sidecar directory listings during compilation, and reduce per-render state reset overhead.
|
|
96
|
+
|
|
97
|
+
*Joel Hawksley*
|
|
98
|
+
|
|
99
|
+
* Ignore unresolved partial dependencies inferred from dynamic renders, such as `render UI.button`, without requiring configuration for component facades. Real partials and explicit dependencies are preserved.
|
|
100
|
+
|
|
101
|
+
*Joel Hawksley*
|
|
102
|
+
|
|
103
|
+
* Raise `ViewComponent::UnknownConfigOptionError` when setting a `config.view_component` option that doesn't exist, rather than ignoring it. This includes options renamed or removed in 4.0, such as `preview_controller` (now `previews.controller`), and the error names the replacement. Replacing `previews` or `generate` with a hash preserves this validation, including through Hash mutation methods such as `merge!`, `update`, `store`, and `replace`.
|
|
104
|
+
|
|
105
|
+
*Fiona Burcombe*
|
|
106
|
+
|
|
13
107
|
## 4.20.0
|
|
14
108
|
|
|
15
109
|
* Fix `invalid byte sequence in UTF-8` errors when precomputing cache digests for components loaded from encrypted or binary source files.
|
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
module ViewComponent
|
|
4
4
|
module AbstractGenerator
|
|
5
|
+
def self.included(generator)
|
|
6
|
+
generator.class_option :skip_suffix, type: :boolean, default: false
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def initialize(...)
|
|
10
|
+
super
|
|
11
|
+
generate = ViewComponent::Base.config.generate
|
|
12
|
+
defaults = {
|
|
13
|
+
"sidecar" => generate.sidecar,
|
|
14
|
+
"stimulus" => generate.stimulus_controller,
|
|
15
|
+
"typescript" => generate.typescript
|
|
16
|
+
}.slice(*self.class.class_options.keys.map(&:to_s))
|
|
17
|
+
# Resolve defaults once so hooks inherit explicit false values as well.
|
|
18
|
+
self.options = options.class.new(defaults.merge(options)).freeze
|
|
19
|
+
end
|
|
20
|
+
|
|
5
21
|
def copy_view_file
|
|
6
22
|
template("component.html.#{engine_name}", destination) unless options["inline"] || options["call"]
|
|
7
23
|
end
|
|
@@ -21,7 +37,11 @@ module ViewComponent
|
|
|
21
37
|
end
|
|
22
38
|
|
|
23
39
|
def destination_file_name
|
|
24
|
-
"#{file_name}_component"
|
|
40
|
+
"#{file_name}#{"_component" unless options[:skip_suffix]}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def component_class_name
|
|
44
|
+
"#{class_name}#{"Component" unless options[:skip_suffix]}"
|
|
25
45
|
end
|
|
26
46
|
|
|
27
47
|
def file_name
|
|
@@ -42,15 +62,15 @@ module ViewComponent
|
|
|
42
62
|
end
|
|
43
63
|
|
|
44
64
|
def sidecar?
|
|
45
|
-
options["sidecar"]
|
|
65
|
+
options["sidecar"]
|
|
46
66
|
end
|
|
47
67
|
|
|
48
68
|
def stimulus?
|
|
49
|
-
options["stimulus"]
|
|
69
|
+
options["stimulus"]
|
|
50
70
|
end
|
|
51
71
|
|
|
52
72
|
def typescript?
|
|
53
|
-
options["typescript"]
|
|
73
|
+
options["typescript"]
|
|
54
74
|
end
|
|
55
75
|
end
|
|
56
76
|
end
|
|
@@ -10,20 +10,22 @@ module ViewComponent
|
|
|
10
10
|
source_root File.expand_path("templates", __dir__)
|
|
11
11
|
|
|
12
12
|
argument :attributes, type: :array, default: [], banner: "attribute"
|
|
13
|
-
check_class_collision suffix: "Component"
|
|
14
13
|
|
|
15
14
|
class_option :call, type: :boolean, default: false
|
|
16
15
|
class_option :inline, type: :boolean, default: false
|
|
17
16
|
class_option :locale, type: :boolean, default: ViewComponent::Base.config.generate.locale
|
|
18
17
|
class_option :parent, type: :string, desc: "The parent class for the generated component"
|
|
19
18
|
class_option :preview, type: :boolean, default: ViewComponent::Base.config.generate.preview
|
|
20
|
-
class_option :sidecar, type: :boolean
|
|
21
|
-
class_option :stimulus, type: :boolean
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
class_option :sidecar, type: :boolean
|
|
20
|
+
class_option :stimulus, type: :boolean
|
|
21
|
+
class_option :typescript, type: :boolean
|
|
22
|
+
|
|
23
|
+
def check_class_collision
|
|
24
|
+
class_collisions component_class_name
|
|
25
|
+
end
|
|
24
26
|
|
|
25
27
|
def create_component_file
|
|
26
|
-
template "component.rb", File.join(component_path, class_path, "#{
|
|
28
|
+
template "component.rb", File.join(component_path, class_path, "#{destination_file_name}.rb")
|
|
27
29
|
end
|
|
28
30
|
|
|
29
31
|
hook_for :test_framework
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
<% module_namespacing do -%>
|
|
4
|
-
class <%=
|
|
4
|
+
class <%= component_class_name %> < <%= parent_class %>
|
|
5
5
|
<%- if inline_template? -%>
|
|
6
6
|
<%= template_engine %>_template <<~<%= template_engine.upcase %>
|
|
7
7
|
<h1>Hello, World!</h1>
|
|
@@ -9,10 +9,10 @@ module ViewComponent
|
|
|
9
9
|
include ViewComponent::AbstractGenerator
|
|
10
10
|
|
|
11
11
|
source_root File.expand_path("templates", __dir__)
|
|
12
|
-
class_option :sidecar, type: :boolean
|
|
12
|
+
class_option :sidecar, type: :boolean
|
|
13
13
|
class_option :inline, type: :boolean, default: false
|
|
14
14
|
class_option :call, type: :boolean, default: false
|
|
15
|
-
class_option :stimulus, type: :boolean
|
|
15
|
+
class_option :stimulus, type: :boolean
|
|
16
16
|
|
|
17
17
|
def engine_name
|
|
18
18
|
"erb"
|
|
@@ -9,7 +9,7 @@ module ViewComponent
|
|
|
9
9
|
|
|
10
10
|
source_root File.expand_path("templates", __dir__)
|
|
11
11
|
argument :attributes, type: :array, default: [], banner: "attribute"
|
|
12
|
-
class_option :sidecar, type: :boolean
|
|
12
|
+
class_option :sidecar, type: :boolean
|
|
13
13
|
|
|
14
14
|
def create_locale_file
|
|
15
15
|
if ViewComponent::Base.config.generate.distinct_locale_files
|
|
@@ -35,11 +35,7 @@ module ViewComponent
|
|
|
35
35
|
|
|
36
36
|
def destination(locale = nil)
|
|
37
37
|
extension = ".#{locale}" if locale
|
|
38
|
-
|
|
39
|
-
File.join(component_path, class_path, "#{file_name}_component", "#{file_name}_component#{extension}.yml")
|
|
40
|
-
else
|
|
41
|
-
File.join(component_path, class_path, "#{file_name}_component#{extension}.yml")
|
|
42
|
-
end
|
|
38
|
+
File.join(destination_directory, "#{destination_file_name}#{extension}.yml")
|
|
43
39
|
end
|
|
44
40
|
end
|
|
45
41
|
end
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "generators/view_component/abstract_generator"
|
|
4
|
+
|
|
3
5
|
module ViewComponent
|
|
4
6
|
module Generators
|
|
5
7
|
class PreviewGenerator < ::Rails::Generators::NamedBase
|
|
8
|
+
include ViewComponent::AbstractGenerator
|
|
9
|
+
|
|
6
10
|
source_root File.expand_path("templates", __dir__)
|
|
7
11
|
class_option :preview_path, type: :string, desc: "Path for previews, required when multiple preview paths are configured", default: ViewComponent::Base.config.generate.preview_path
|
|
8
12
|
|
|
9
13
|
argument :attributes, type: :array, default: [], banner: "attribute"
|
|
10
|
-
|
|
14
|
+
|
|
15
|
+
def check_class_collision
|
|
16
|
+
class_collisions "#{component_class_name}Preview"
|
|
17
|
+
end
|
|
11
18
|
|
|
12
19
|
def create_preview_file
|
|
13
20
|
preview_paths = ViewComponent::Base.config.previews.paths
|
|
@@ -20,15 +27,11 @@ module ViewComponent
|
|
|
20
27
|
preview_paths.one? ? preview_paths.first : "test/components/previews"
|
|
21
28
|
end
|
|
22
29
|
|
|
23
|
-
template "component_preview.rb", File.join(path_prefix, class_path, "#{
|
|
30
|
+
template "component_preview.rb", File.join(path_prefix, class_path, "#{destination_file_name}_preview.rb")
|
|
24
31
|
end
|
|
25
32
|
|
|
26
33
|
private
|
|
27
34
|
|
|
28
|
-
def file_name
|
|
29
|
-
@_file_name ||= super.sub(/_component\z/i, "")
|
|
30
|
-
end
|
|
31
|
-
|
|
32
35
|
def render_signature
|
|
33
36
|
return if attributes.blank?
|
|
34
37
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
<% module_namespacing do -%>
|
|
4
|
-
class <%=
|
|
4
|
+
class <%= component_class_name %>Preview < ViewComponent::Preview
|
|
5
5
|
def default
|
|
6
|
-
render(<%=
|
|
6
|
+
render(<%= component_class_name %>.new<%= "(#{render_signature})" if render_signature %>)
|
|
7
7
|
end
|
|
8
8
|
end
|
|
9
9
|
<% end -%>
|
|
@@ -10,7 +10,7 @@ module ViewComponent
|
|
|
10
10
|
source_root File.expand_path("templates", __dir__)
|
|
11
11
|
|
|
12
12
|
def create_test_file
|
|
13
|
-
template "component_spec.rb", File.join(spec_component_path, class_path, "#{
|
|
13
|
+
template "component_spec.rb", File.join(spec_component_path, class_path, "#{destination_file_name}_spec.rb")
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
private
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require "rails_helper"
|
|
4
4
|
|
|
5
|
-
RSpec.describe <%= namespaced? ? "#{namespace.name}::" : '' %><%=
|
|
5
|
+
RSpec.describe <%= namespaced? ? "#{namespace.name}::" : '' %><%= component_class_name %>, type: :component do
|
|
6
6
|
pending "add some examples to (or delete) #{__FILE__}"
|
|
7
7
|
|
|
8
8
|
# it "renders something useful" do
|
|
@@ -8,8 +8,8 @@ module ViewComponent
|
|
|
8
8
|
include ViewComponent::AbstractGenerator
|
|
9
9
|
|
|
10
10
|
source_root File.expand_path("templates", __dir__)
|
|
11
|
-
class_option :sidecar, type: :boolean
|
|
12
|
-
class_option :typescript, type: :boolean
|
|
11
|
+
class_option :sidecar, type: :boolean
|
|
12
|
+
class_option :typescript, type: :boolean
|
|
13
13
|
|
|
14
14
|
def create_stimulus_controller
|
|
15
15
|
template "component_controller.#{filetype}", destination
|
|
@@ -28,11 +28,7 @@ module ViewComponent
|
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def destination
|
|
31
|
-
|
|
32
|
-
File.join(component_path, class_path, "#{file_name}_component", "#{file_name}_component_controller.#{filetype}")
|
|
33
|
-
else
|
|
34
|
-
File.join(component_path, class_path, "#{file_name}_component_controller.#{filetype}")
|
|
35
|
-
end
|
|
31
|
+
File.join(destination_directory, "#{destination_file_name}_controller.#{filetype}")
|
|
36
32
|
end
|
|
37
33
|
|
|
38
34
|
def legacy_stimulus?
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
require "test_helper"
|
|
4
4
|
|
|
5
|
-
class <%= namespaced? ? "#{namespace.name}::" : '' %><%=
|
|
5
|
+
class <%= namespaced? ? "#{namespace.name}::" : '' %><%= component_class_name %>Test < ViewComponent::TestCase
|
|
6
6
|
def test_component_renders_something_useful
|
|
7
7
|
# assert_equal(
|
|
8
8
|
# %(<span>Hello, components!</span>),
|
|
9
|
-
# render_inline(<%=
|
|
9
|
+
# render_inline(<%= component_class_name %>.new(message: "Hello, components!")).css("span").to_html
|
|
10
10
|
# )
|
|
11
11
|
end
|
|
12
12
|
end
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "generators/view_component/abstract_generator"
|
|
4
|
+
|
|
3
5
|
module ViewComponent
|
|
4
6
|
module Generators
|
|
5
7
|
class TestUnitGenerator < ::Rails::Generators::NamedBase
|
|
8
|
+
include ViewComponent::AbstractGenerator
|
|
9
|
+
|
|
6
10
|
source_root File.expand_path("templates", __dir__)
|
|
7
|
-
check_class_collision suffix: "ComponentTest"
|
|
8
11
|
|
|
9
|
-
def
|
|
10
|
-
|
|
12
|
+
def check_class_collision
|
|
13
|
+
class_collisions "#{component_class_name}Test"
|
|
11
14
|
end
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def file_name
|
|
16
|
-
@_file_name ||= super.sub(/_component\z/i, "")
|
|
16
|
+
def create_test_file
|
|
17
|
+
template "component_test.rb", File.join("test/components", class_path, "#{destination_file_name}_test.rb")
|
|
17
18
|
end
|
|
18
19
|
end
|
|
19
20
|
end
|