style_capsule 1.3.0 → 2.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.
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "digest/sha1"
4
+ require_relative "component_class_methods"
4
5
  # ActiveSupport string extensions are conditionally required in lib/style_capsule.rb
5
6
 
6
7
  module StyleCapsule
@@ -95,252 +96,7 @@ module StyleCapsule
95
96
  end
96
97
 
97
98
  module ClassMethods
98
- # Class-level cache for scoped CSS per component class
99
- def css_cache
100
- @css_cache ||= {}
101
- end
102
-
103
- # Clear the CSS cache for this component class
104
- #
105
- # Useful for testing or when you want to force CSS reprocessing.
106
- # In development, this is automatically called when classes are reloaded.
107
- #
108
- # @example
109
- # MyComponent.clear_css_cache
110
- def clear_css_cache
111
- @css_cache = {}
112
- end
113
-
114
- # Set or get a custom capsule ID for this component class (useful for testing)
115
- #
116
- # @param capsule_id [String, nil] The custom capsule ID to use (nil to get current value)
117
- # @return [String, nil] The current capsule ID if no argument provided
118
- # @example Setting a custom capsule ID
119
- # class MyComponent < ApplicationComponent
120
- # include StyleCapsule::ViewComponent
121
- # capsule_id "test-capsule-123"
122
- # end
123
- # @example Getting the current capsule ID
124
- # MyComponent.capsule_id # => "test-capsule-123" or nil
125
- def capsule_id(capsule_id = nil)
126
- if capsule_id.nil?
127
- @custom_capsule_id if defined?(@custom_capsule_id)
128
- else
129
- @custom_capsule_id = capsule_id.to_s
130
- end
131
- end
132
-
133
- # Configure stylesheet registry for head rendering
134
- #
135
- # Enables head rendering and configures namespace and cache strategy in a single call.
136
- # All parameters are optional - calling without arguments enables head rendering with defaults.
137
- #
138
- # @param namespace [Symbol, String, nil] Namespace identifier (nil/blank uses default)
139
- # @param cache_strategy [Symbol, String, Proc, nil] Cache strategy: :none (default), :time, :proc, :file
140
- # - Symbol or String: :none, :time, :proc, :file (or "none", "time", "proc", "file")
141
- # - Proc: Custom cache proc (automatically uses :proc strategy)
142
- # Proc receives: (css_content, capsule_id, namespace) and should return [cache_key, should_cache, expires_at]
143
- # @param cache_ttl [Integer, ActiveSupport::Duration, nil] Time-to-live in seconds (for :time strategy). Supports ActiveSupport::Duration (e.g., 1.hour, 30.minutes)
144
- # @param cache_proc [Proc, nil] Custom cache proc (for :proc strategy, ignored if cache_strategy is a Proc)
145
- # Proc receives: (css_content, capsule_id, namespace) and should return [cache_key, should_cache, expires_at]
146
- # @return [void]
147
- # @example Basic usage (enables head rendering with defaults)
148
- # class MyComponent < ApplicationComponent
149
- # include StyleCapsule::ViewComponent
150
- # stylesheet_registry
151
- # end
152
- # @example With namespace
153
- # class AdminComponent < ApplicationComponent
154
- # include StyleCapsule::ViewComponent
155
- # stylesheet_registry namespace: :admin
156
- # end
157
- # @example With time-based caching
158
- # class MyComponent < ApplicationComponent
159
- # include StyleCapsule::ViewComponent
160
- # stylesheet_registry cache_strategy: :time, cache_ttl: 1.hour
161
- # end
162
- # @example With custom proc caching
163
- # class MyComponent < ApplicationComponent
164
- # include StyleCapsule::ViewComponent
165
- # stylesheet_registry cache_strategy: :proc, cache_proc: ->(css, capsule_id, ns) {
166
- # cache_key = "css_#{capsule_id}_#{ns}"
167
- # should_cache = css.length > 100
168
- # expires_at = Time.now + 1800
169
- # [cache_key, should_cache, expires_at]
170
- # }
171
- # end
172
- # @example File-based caching (requires class method component_styles)
173
- # class MyComponent < ApplicationComponent
174
- # include StyleCapsule::ViewComponent
175
- # stylesheet_registry cache_strategy: :file
176
- #
177
- # def self.component_styles # Must be class method for file caching
178
- # <<~CSS
179
- # .section { color: red; }
180
- # CSS
181
- # end
182
- # end
183
- # @example All options combined
184
- # class MyComponent < ApplicationComponent
185
- # include StyleCapsule::ViewComponent
186
- # stylesheet_registry namespace: :admin, cache_strategy: :time, cache_ttl: 1.hour
187
- # end
188
- def stylesheet_registry(namespace: nil, cache_strategy: :none, cache_ttl: nil, cache_proc: nil)
189
- @head_rendering = true
190
- @stylesheet_namespace = namespace unless namespace.nil?
191
-
192
- # Normalize cache_strategy: convert strings to symbols, handle Proc
193
- normalized_strategy, normalized_proc = normalize_cache_strategy(cache_strategy, cache_proc)
194
- @inline_cache_strategy = normalized_strategy
195
- @inline_cache_ttl = cache_ttl
196
- @inline_cache_proc = normalized_proc
197
- end
198
-
199
- private
200
-
201
- # Normalize cache_strategy to handle Symbol, String, and Proc
202
- #
203
- # @param cache_strategy [Symbol, String, Proc, nil] Cache strategy
204
- # @param cache_proc [Proc, nil] Optional cache proc (ignored if cache_strategy is a Proc)
205
- # @return [Array<Symbol, Proc|nil>] Normalized strategy and proc
206
- def normalize_cache_strategy(cache_strategy, cache_proc)
207
- case cache_strategy
208
- when Proc
209
- # If cache_strategy is a Proc, use it as the proc and set strategy to :proc
210
- [:proc, cache_strategy]
211
- when String
212
- # Convert string to symbol
213
- normalized = cache_strategy.to_sym
214
- unless [:none, :time, :proc, :file].include?(normalized)
215
- raise ArgumentError, "cache_strategy must be :none, :time, :proc, or :file (got: #{cache_strategy.inspect})"
216
- end
217
- [normalized, cache_proc]
218
- when Symbol
219
- unless [:none, :time, :proc, :file].include?(cache_strategy)
220
- raise ArgumentError, "cache_strategy must be :none, :time, :proc, or :file (got: #{cache_strategy.inspect})"
221
- end
222
- [cache_strategy, cache_proc]
223
- when nil
224
- [:none, nil]
225
- else
226
- raise ArgumentError, "cache_strategy must be a Symbol, String, or Proc (got: #{cache_strategy.class})"
227
- end
228
- end
229
-
230
- # Deprecated: Use stylesheet_registry instead
231
- # @deprecated Use {#stylesheet_registry} instead
232
- def head_rendering!
233
- stylesheet_registry
234
- end
235
-
236
- # Check if component uses head rendering
237
- def head_rendering?
238
- return false unless defined?(@head_rendering)
239
- @head_rendering
240
- end
241
-
242
- public :head_rendering?
243
-
244
- # Get the namespace for stylesheet registry
245
- def stylesheet_namespace
246
- @stylesheet_namespace if defined?(@stylesheet_namespace)
247
- end
248
-
249
- # Get the custom scope ID if set (alias for capsule_id getter)
250
- def custom_capsule_id
251
- @custom_capsule_id if defined?(@custom_capsule_id)
252
- end
253
-
254
- # Get inline cache strategy
255
- def inline_cache_strategy
256
- @inline_cache_strategy if defined?(@inline_cache_strategy)
257
- end
258
-
259
- # Get inline cache TTL
260
- def inline_cache_ttl
261
- @inline_cache_ttl if defined?(@inline_cache_ttl)
262
- end
263
-
264
- # Get inline cache proc
265
- def inline_cache_proc
266
- @inline_cache_proc if defined?(@inline_cache_proc)
267
- end
268
-
269
- public :head_rendering?, :stylesheet_namespace, :custom_capsule_id, :inline_cache_strategy, :inline_cache_ttl, :inline_cache_proc
270
-
271
- # Set or get options for stylesheet_link_tag when using file-based caching
272
- #
273
- # @param options [Hash, nil] Options to pass to stylesheet_link_tag (e.g., "data-turbo-track": "reload", omit to get current value)
274
- # @return [Hash, nil] The current stylesheet link options if no argument provided
275
- # @example Setting stylesheet link options
276
- # class MyComponent < ApplicationComponent
277
- # include StyleCapsule::ViewComponent
278
- # stylesheet_registry cache_strategy: :file
279
- # stylesheet_link_options "data-turbo-track": "reload"
280
- # end
281
- # @example Getting the current options
282
- # MyComponent.stylesheet_link_options # => {"data-turbo-track" => "reload"} or nil
283
- def stylesheet_link_options(options = nil)
284
- if options.nil?
285
- @stylesheet_link_options if defined?(@stylesheet_link_options)
286
- else
287
- @stylesheet_link_options = options
288
- end
289
- end
290
-
291
- public :stylesheet_link_options
292
-
293
- # Set or get CSS scoping strategy
294
- #
295
- # @param strategy [Symbol, nil] Scoping strategy: :selector_patching (default) or :nesting (omit to get current value)
296
- # - :selector_patching: Adds [data-capsule="..."] prefix to each selector (better browser support)
297
- # - :nesting: Wraps entire CSS in [data-capsule="..."] { ... } (more performant, requires CSS nesting support)
298
- # @return [Symbol] The current scoping strategy (default: :selector_patching)
299
- # @example Using CSS nesting (requires Chrome 112+, Firefox 117+, Safari 16.5+)
300
- # class MyComponent < ApplicationComponent
301
- # include StyleCapsule::ViewComponent
302
- # css_scoping_strategy :nesting # More performant, no CSS parsing needed
303
- #
304
- # def component_styles
305
- # <<~CSS
306
- # .section { color: red; }
307
- # .heading:hover { opacity: 0.8; }
308
- # CSS
309
- # end
310
- # end
311
- # # Output: [data-capsule="abc123"] { .section { color: red; } .heading:hover { opacity: 0.8; } }
312
- # @example Using selector patching (default, better browser support)
313
- # class MyComponent < ApplicationComponent
314
- # include StyleCapsule::ViewComponent
315
- # css_scoping_strategy :selector_patching # Default
316
- #
317
- # def component_styles
318
- # <<~CSS
319
- # .section { color: red; }
320
- # CSS
321
- # end
322
- # end
323
- # # Output: [data-capsule="abc123"] .section { color: red; }
324
- def css_scoping_strategy(strategy = nil)
325
- if strategy.nil?
326
- # Check if this class has a strategy set
327
- if defined?(@css_scoping_strategy) && @css_scoping_strategy
328
- @css_scoping_strategy
329
- # Otherwise, check parent class (for inheritance)
330
- elsif superclass.respond_to?(:css_scoping_strategy, true)
331
- superclass.css_scoping_strategy
332
- else
333
- :selector_patching
334
- end
335
- else
336
- unless [:selector_patching, :nesting].include?(strategy)
337
- raise ArgumentError, "css_scoping_strategy must be :selector_patching or :nesting (got: #{strategy.inspect})"
338
- end
339
- @css_scoping_strategy = strategy
340
- end
341
- end
342
-
343
- public :css_scoping_strategy
99
+ include StyleCapsule::ComponentClassMethods
344
100
  end
345
101
 
346
102
  # Module that wraps call to add scoped wrapper
@@ -353,8 +109,11 @@ module StyleCapsule
353
109
  # Get content from original call method
354
110
  content_html = super
355
111
 
112
+ # Get wrapper tag
113
+ tag = self.class.wrapper_tag
114
+
356
115
  # Wrap content in scoped element
357
- scoped_wrapper = helpers.content_tag(:div, content_html.html_safe, data: {capsule: component_capsule})
116
+ scoped_wrapper = helpers.content_tag(tag, content_html.html_safe, data: {capsule: component_capsule})
358
117
 
359
118
  # Combine styles and wrapped content
360
119
  (styles_html + scoped_wrapper).html_safe
@@ -388,6 +147,7 @@ module StyleCapsule
388
147
  # File caching is only allowed for class method component_styles.
389
148
  #
390
149
  # @return [String] HTML string with style tag or empty string
150
+ # rubocop:disable Metrics/AbcSize -- coordinates head vs body rendering, caching, and registry
391
151
  def render_capsule_styles
392
152
  css_content = component_styles_content
393
153
  return "".html_safe if css_content.nil? || css_content.to_s.strip.empty?
@@ -433,6 +193,7 @@ module StyleCapsule
433
193
  helpers.content_tag(:style, scoped_css.html_safe, type: "text/css")
434
194
  end
435
195
  end
196
+ # rubocop:enable Metrics/AbcSize
436
197
 
437
198
  # Check if component should use head rendering
438
199
  #
@@ -444,11 +205,10 @@ module StyleCapsule
444
205
 
445
206
  # Scope CSS and return scoped CSS with attribute selectors
446
207
  def scope_css(css_content)
447
- # Use class-level cache to avoid reprocessing same CSS
448
- # Include capsule_id and scoping strategy in cache key
449
208
  capsule_id = component_capsule
450
209
  scoping_strategy = self.class.css_scoping_strategy
451
- cache_key = "#{self.class.name}:#{capsule_id}:#{scoping_strategy}"
210
+ css_fingerprint = Digest::SHA1.hexdigest(css_content.to_s)
211
+ cache_key = "#{self.class.name}:#{capsule_id}:#{scoping_strategy}:#{css_fingerprint}"
452
212
 
453
213
  if self.class.css_cache.key?(cache_key)
454
214
  return self.class.css_cache[cache_key]
@@ -457,15 +217,12 @@ module StyleCapsule
457
217
  # Use the configured scoping strategy
458
218
  scoped_css = case scoping_strategy
459
219
  when :nesting
460
- CssProcessor.scope_with_nesting(css_content, capsule_id)
220
+ CssProcessor.scope_with_nesting(css_content, capsule_id, component_class: self.class)
461
221
  else # :selector_patching (default)
462
- CssProcessor.scope_selectors(css_content, capsule_id)
222
+ CssProcessor.scope_selectors(css_content, capsule_id, component_class: self.class)
463
223
  end
464
224
 
465
- # Cache at class level (one style block per component type/scope/strategy combination)
466
- self.class.css_cache[cache_key] = scoped_css
467
-
468
- scoped_css
225
+ self.class.store_css_cache(cache_key, scoped_css)
469
226
  end
470
227
 
471
228
  # Generate a unique capsule ID based on component class name (per-component-type)
@@ -10,13 +10,17 @@ module StyleCapsule
10
10
  #
11
11
  # Usage in ViewComponent layouts:
12
12
  # def call
13
- # helpers.stylesheet_registrymap_tags
13
+ # helpers.stylesheet_registry_tags
14
14
  # end
15
15
  #
16
16
  # Usage in ViewComponent components:
17
- # def call
18
- # register_stylesheet("stylesheets/user/my_component")
19
- # content_tag(:div, "Content")
17
+ # class MyComponent < ApplicationComponent
18
+ # style_capsule namespace: :user # Set default namespace for register_stylesheet
19
+ #
20
+ # def call
21
+ # register_stylesheet("stylesheets/user/my_component") # Uses :user namespace automatically
22
+ # content_tag(:div, "Content")
23
+ # end
20
24
  # end
21
25
  module ViewComponentHelper
22
26
  # Register a stylesheet file for head rendering
@@ -28,11 +32,18 @@ module StyleCapsule
28
32
  # content_tag(:div, "Content")
29
33
  # end
30
34
  #
35
+ # If the component has a default namespace set via style_capsule or stylesheet_registry,
36
+ # it will be used automatically when namespace is not explicitly provided.
37
+ #
31
38
  # @param file_path [String] Path to stylesheet (relative to app/assets/stylesheets)
32
- # @param namespace [Symbol, String, nil] Optional namespace for separation (nil/blank uses default)
39
+ # @param namespace [Symbol, String, nil] Optional namespace for separation (nil/blank uses component's default or global default)
33
40
  # @param options [Hash] Options for stylesheet_link_tag
34
41
  # @return [void]
35
42
  def register_stylesheet(file_path, namespace: nil, **options)
43
+ # Use component's default namespace if not explicitly provided
44
+ if namespace.nil? && respond_to?(:class) && self.class.respond_to?(:stylesheet_namespace)
45
+ namespace = self.class.stylesheet_namespace
46
+ end
36
47
  StyleCapsule::StylesheetRegistry.register(file_path, namespace: namespace, **options)
37
48
  end
38
49
 
@@ -49,9 +60,5 @@ module StyleCapsule
49
60
  def stylesheet_registry_tags(namespace: nil)
50
61
  StyleCapsule::StylesheetRegistry.render_head_stylesheets(helpers, namespace: namespace)
51
62
  end
52
-
53
- # @deprecated Use {#stylesheet_registry_tags} instead.
54
- # This method name will be removed in a future version.
55
- alias_method :stylesheet_registrymap_tags, :stylesheet_registry_tags
56
63
  end
57
64
  end
data/lib/style_capsule.rb CHANGED
@@ -18,6 +18,7 @@ end
18
18
  # @example Phlex Component Usage
19
19
  # class MyComponent < ApplicationComponent
20
20
  # include StyleCapsule::Component
21
+ # style_capsule namespace: :user # Configure namespace and other settings
21
22
  #
22
23
  # def component_styles
23
24
  # <<~CSS
@@ -29,6 +30,7 @@ end
29
30
  # @example ViewComponent Encapsulation Usage
30
31
  # class MyComponent < ApplicationComponent
31
32
  # include StyleCapsule::ViewComponent
33
+ # style_capsule namespace: :admin # Configure namespace and other settings
32
34
  #
33
35
  # def component_styles
34
36
  # <<~CSS
@@ -51,8 +53,10 @@ end
51
53
  # end
52
54
  #
53
55
  # class MyComponent < ApplicationComponent
56
+ # style_capsule namespace: :user # Configure namespace
57
+ #
54
58
  # def call
55
- # register_stylesheet("stylesheets/user/my_component")
59
+ # register_stylesheet("stylesheets/user/my_component") # Uses :user namespace automatically
56
60
  # content_tag(:div, "Content", class: "section")
57
61
  # end
58
62
  # end
@@ -68,9 +72,12 @@ end
68
72
  # <%= stylesheet_registry_tags(namespace: :admin) %>
69
73
  #
70
74
  # @example Namespace Support
71
- # # Register stylesheets with namespaces
72
- # StyleCapsule::StylesheetRegistry.register('stylesheets/admin/dashboard', namespace: :admin)
73
- # StyleCapsule::StylesheetRegistry.register('stylesheets/user/profile', namespace: :user)
75
+ # # Eager registrations (boot / class load; process-wide manifest)
76
+ # StyleCapsule::StylesheetRegistry.register_eager('stylesheets/admin/dashboard', namespace: :admin)
77
+ # StyleCapsule::StylesheetRegistry.register_eager('stylesheets/user/profile', namespace: :user)
78
+ #
79
+ # # Render-time registrations (request-scoped; also picked up by HeadInjectionMiddleware)
80
+ # StyleCapsule::StylesheetRegistry.register('stylesheets/page', namespace: :user)
74
81
  #
75
82
  # # Render all namespaces (default)
76
83
  # <%= stylesheet_registry_tags %>
@@ -81,7 +88,7 @@ end
81
88
  # @example File-Based Caching (HTTP Caching)
82
89
  # class MyComponent < ApplicationComponent
83
90
  # include StyleCapsule::Component
84
- # stylesheet_registry cache_strategy: :file # Writes CSS to files for HTTP caching
91
+ # style_capsule cache_strategy: :file # Writes CSS to files for HTTP caching
85
92
  # end
86
93
  #
87
94
  # # CSS files are written to app/assets/builds/capsules/
@@ -90,6 +97,8 @@ end
90
97
  module StyleCapsule
91
98
  require_relative "style_capsule/version"
92
99
  require_relative "style_capsule/instrumentation"
100
+ require_relative "style_capsule/asset_path"
101
+ require_relative "style_capsule/helper_scope_cache"
93
102
  require_relative "style_capsule/css_processor"
94
103
  require_relative "style_capsule/css_file_writer"
95
104
  require_relative "style_capsule/stylesheet_registry"
@@ -16,7 +16,20 @@ namespace :style_capsule do
16
16
  end
17
17
  end
18
18
 
19
- # Hook into Rails asset precompilation (similar to Tailwind CSS)
19
+ # Hook into Rails asset precompilation (similar to Tailwind CSS).
20
+ # Set `config.style_capsule.run_on_precompile = false` to skip.
21
+ task "style_capsule:precompile_hook" => :environment do
22
+ cfg = Rails.application.config
23
+ run = if cfg.respond_to?(:style_capsule) && cfg.style_capsule
24
+ cfg.style_capsule.run_on_precompile != false
25
+ else
26
+ true
27
+ end
28
+ next unless run
29
+
30
+ Rake::Task["style_capsule:build"].invoke
31
+ end
32
+
20
33
  if defined?(Rails)
21
- Rake::Task["assets:precompile"].enhance(["style_capsule:build"]) if Rake::Task.task_defined?("assets:precompile")
34
+ Rake::Task["assets:precompile"].enhance(["style_capsule:precompile_hook"]) if Rake::Task.task_defined?("assets:precompile")
22
35
  end
@@ -1,9 +1,13 @@
1
1
  module StyleCapsule
2
2
  VERSION: String
3
3
 
4
+ module AssetPath
5
+ def self.validate_logical_path!: (String path) -> String
6
+ end
7
+
4
8
  module CssProcessor
5
- def self.scope_selectors: (String css_string, String capsule_id) -> String
6
- def self.scope_with_nesting: (String css_string, String capsule_id) -> String
9
+ def self.scope_selectors: (String css_string, String capsule_id, ?component_class: Class | String | nil) -> String
10
+ def self.scope_with_nesting: (String css_string, String capsule_id, ?component_class: Class | String | nil) -> String
7
11
  def self.strip_comments: (String css) -> String
8
12
  end
9
13
 
@@ -17,44 +21,59 @@ module StyleCapsule
17
21
  def self.enabled?: () -> bool
18
22
  end
19
23
 
20
- class StylesheetRegistry < ActiveSupport::CurrentAttributes
24
+ # At runtime inherits Object when ActiveSupport::CurrentAttributes is unavailable.
25
+ class StylesheetRegistry
21
26
  DEFAULT_NAMESPACE: Symbol
22
27
 
23
28
  def self.normalize_namespace: (Symbol | String | nil namespace) -> Symbol
24
29
  def self.register: (String file_path, ?namespace: Symbol | String | nil, **Hash[untyped, untyped] options) -> void
30
+ def self.register_eager: (String file_path, ?namespace: Symbol | String | nil, **Hash[untyped, untyped] options) -> void
25
31
  def self.register_inline: (String css_content, ?namespace: Symbol | String | nil, ?capsule_id: String | nil, ?cache_key: String | nil, ?cache_strategy: Symbol, ?cache_ttl: Integer | ActiveSupport::Duration | nil, ?cache_proc: Proc | nil, ?component_class: Class | nil, ?stylesheet_link_options: Hash[untyped, untyped] | nil) -> void
26
32
  def self.cached_inline: (String cache_key, cache_strategy: Symbol, ?cache_ttl: Integer | ActiveSupport::Duration | nil, ?cache_proc: Proc | nil, ?css_content: String | nil, ?capsule_id: String | nil, ?namespace: Symbol | nil) -> String | nil
27
33
  def self.cache_inline_css: (String cache_key, String css_content, cache_strategy: Symbol, ?cache_ttl: Integer | ActiveSupport::Duration | nil, ?cache_proc: Proc | nil, ?capsule_id: String | nil, ?namespace: Symbol | nil) -> void
28
34
  def self.clear_inline_cache: (?String cache_key) -> void
29
35
  def self.cleanup_expired_cache: () -> Integer
30
- def self.manifest_files: () -> Hash[Symbol, Set[Hash[Symbol, untyped]]]
36
+ def self.manifest_files: () -> Hash[Symbol, Array[Hash[Symbol, untyped]]]
31
37
  def self.request_inline_stylesheets: () -> Hash[Symbol, Array[Hash[Symbol, untyped]]]
38
+ def self.request_stylesheet_files: () -> Hash[Symbol, Hash[String, Hash[Symbol, untyped]]]
32
39
  def self.stylesheets_for: (?namespace: Symbol | String | nil) -> Array[Hash[Symbol, untyped]]
33
40
  def self.clear: (?namespace: Symbol | String | nil) -> void
34
41
  def self.clear_manifest: (?namespace: Symbol | String | nil) -> void
35
42
  def self.render_head_stylesheets: (?ActionView::Base | nil view_context, ?namespace: Symbol | String | nil) -> String
43
+ def self.inject_pending_head_stylesheets: (String html, ?ActionView::Base | nil view_context) -> String
44
+ def self.pending_head_stylesheets?: () -> bool
36
45
  def self.any?: (?namespace: Symbol | String | nil) -> bool
37
46
  end
38
47
 
48
+ class HeadInjectionMiddleware
49
+ def initialize: (untyped app) -> void
50
+ def call: (Hash[Symbol, untyped] env) -> [Integer, Hash[String, String], untyped]
51
+ end
52
+
53
+ module ComponentClassMethods
54
+ MAX_CSS_CACHE_ENTRIES: Integer
55
+ def css_cache: () -> Hash[String, String]
56
+ def store_css_cache: (String cache_key, String scoped_css) -> String
57
+ def clear_css_cache: () -> void
58
+ def capsule_id: () -> String | nil
59
+ def capsule_id: (String capsule_id) -> String
60
+ def stylesheet_registry: (?namespace: Symbol | String | nil, ?cache_strategy: Symbol, ?cache_ttl: Integer | ActiveSupport::Duration | nil, ?cache_proc: Proc | nil) -> void
61
+ def style_capsule: (?namespace: Symbol | String | nil, ?cache_strategy: Symbol | String | Proc | nil, ?cache_ttl: Integer | ActiveSupport::Duration | nil, ?cache_proc: Proc | nil, ?scoping_strategy: Symbol | nil, ?head_rendering: bool | nil, ?tag: Symbol | String | nil) -> void
62
+ def head_rendering?: () -> bool
63
+ def stylesheet_namespace: () -> Symbol | String | nil
64
+ def custom_capsule_id: () -> String | nil
65
+ def inline_cache_strategy: () -> Symbol | nil
66
+ def inline_cache_strategy: (Symbol strategy, ?ttl: Integer | nil, ?cache_proc: Proc | nil) -> Symbol
67
+ def inline_cache_ttl: () -> Integer | ActiveSupport::Duration | nil
68
+ def inline_cache_proc: () -> Proc | nil
69
+ def stylesheet_link_options: () -> Hash[untyped, untyped] | nil
70
+ def stylesheet_link_options: (Hash[untyped, untyped] options) -> Hash[untyped, untyped]
71
+ def css_scoping_strategy: () -> Symbol
72
+ end
73
+
39
74
  module Component
40
75
  module ClassMethods
41
- def css_cache: () -> Hash[String, String]
42
- def clear_css_cache: () -> void
43
- def capsule_id: () -> String | nil
44
- def capsule_id: (String capsule_id) -> String
45
- def stylesheet_registry: (?namespace: Symbol | String | nil, ?cache_strategy: Symbol, ?cache_ttl: Integer | ActiveSupport::Duration | nil, ?cache_proc: Proc | nil) -> void
46
- def head_rendering!: () -> void # deprecated
47
- def head_rendering?: () -> bool
48
- def stylesheet_namespace: () -> Symbol | String | nil
49
- def custom_capsule_id: () -> String | nil
50
- def inline_cache_strategy: () -> Symbol | nil
51
- def inline_cache_strategy: (Symbol strategy, ?ttl: Integer | nil, ?cache_proc: Proc | nil) -> Symbol
52
- def inline_cache_ttl: () -> Integer | ActiveSupport::Duration | nil
53
- def inline_cache_proc: () -> Proc | nil
54
- def stylesheet_link_options: () -> Hash[untyped, untyped] | nil
55
- def stylesheet_link_options: (Hash[untyped, untyped] options) -> Hash[untyped, untyped]
56
- def css_scoping_strategy: () -> Symbol
57
- def css_scoping_strategy: (Symbol strategy) -> Symbol
76
+ include ComponentClassMethods
58
77
  end
59
78
 
60
79
  def component_capsule: () -> String
@@ -63,23 +82,7 @@ module StyleCapsule
63
82
 
64
83
  module ViewComponent
65
84
  module ClassMethods
66
- def css_cache: () -> Hash[String, String]
67
- def clear_css_cache: () -> void
68
- def capsule_id: () -> String | nil
69
- def capsule_id: (String capsule_id) -> String
70
- def stylesheet_registry: (?namespace: Symbol | String | nil, ?cache_strategy: Symbol, ?cache_ttl: Integer | ActiveSupport::Duration | nil, ?cache_proc: Proc | nil) -> void
71
- def head_rendering!: () -> void # deprecated
72
- def head_rendering?: () -> bool
73
- def stylesheet_namespace: () -> Symbol | String | nil
74
- def custom_capsule_id: () -> String | nil
75
- def inline_cache_strategy: () -> Symbol | nil
76
- def inline_cache_strategy: (Symbol strategy, ?ttl: Integer | nil, ?cache_proc: Proc | nil) -> Symbol
77
- def inline_cache_ttl: () -> Integer | ActiveSupport::Duration | nil
78
- def inline_cache_proc: () -> Proc | nil
79
- def stylesheet_link_options: () -> Hash[untyped, untyped] | nil
80
- def stylesheet_link_options: (Hash[untyped, untyped] options) -> Hash[untyped, untyped]
81
- def css_scoping_strategy: () -> Symbol
82
- def css_scoping_strategy: (Symbol strategy) -> Symbol
85
+ include ComponentClassMethods
83
86
  end
84
87
 
85
88
  def component_capsule: () -> String
@@ -89,25 +92,21 @@ module StyleCapsule
89
92
  module ViewComponentHelper
90
93
  def register_stylesheet: (String file_path, ?namespace: Symbol | String | nil, **Hash[untyped, untyped] options) -> void
91
94
  def stylesheet_registry_tags: (?namespace: Symbol | String | nil) -> String
92
- def stylesheet_registrymap_tags: (?namespace: Symbol | String | nil) -> String # deprecated
93
95
  end
94
96
 
95
97
  module Helper
96
98
  def generate_capsule_id: (String css_content) -> String
97
99
  def scope_css: (String css_content, String capsule_id) -> String
98
- def style_capsule: (?String css_content, ?capsule_id: String | nil) { () -> String } -> String
100
+ def style_capsule: (?String css_content, ?capsule_id: String | nil, ?tag: Symbol | String) { () -> String } -> String
99
101
  def register_stylesheet: (String file_path, ?namespace: Symbol | String | nil, **Hash[untyped, untyped] options) -> void
100
102
  def stylesheet_registry_tags: (?namespace: Symbol | String | nil) -> String
101
- def stylesheet_registrymap_tags: (?namespace: Symbol | String | nil) -> String # deprecated
102
103
  end
103
104
 
104
105
  module PhlexHelper
105
106
  def register_stylesheet: (String file_path, ?namespace: Symbol | String | nil, **Hash[untyped, untyped] options) -> void
106
- def stylesheet_registry_tags: (?namespace: Symbol | String | nil) -> void
107
- def stylesheet_registrymap_tags: (?namespace: Symbol | String | nil) -> void # deprecated
107
+ def stylesheet_registry_tags: (?namespace: Symbol | String | nil) -> String
108
108
  end
109
109
 
110
110
  class Railtie < Rails::Railtie
111
111
  end
112
112
  end
113
-