style_capsule 1.1.0 → 1.2.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/CHANGELOG.md +9 -0
- data/README.md +1 -1
- data/lib/style_capsule/class_registry.rb +101 -0
- data/lib/style_capsule/component.rb +3 -0
- data/lib/style_capsule/component_builder.rb +18 -4
- data/lib/style_capsule/railtie.rb +9 -19
- data/lib/style_capsule/version.rb +1 -1
- data/lib/style_capsule/view_component.rb +3 -0
- data/lib/style_capsule.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d1fcbe6c03f9675593d6dca7b3d7d70de2b7d471d2d938993b59877614332ff4
|
|
4
|
+
data.tar.gz: 6aa5feb7ff25ef755084e7754f328e4340a0d4dc620e1ea8298badbb0387f254
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f06af1e47282aa0220b5ff28e5e0a197a8d76eaa9f3c00639958ca1f9d672c7ad1dd4f672b9de83cc7c521af6a49b9c9f9c9bd0ce476575211b1fc7a7aeb1da2
|
|
7
|
+
data.tar.gz: 3844dd9da6608b1eff6e495e19b92e3f90d4b41df323118f5fa7c6216603d3b33620c80df8aeb13c2e2506e133e3ab6e424c3dfd76feb16dbbc68b37fac72636
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 1.2.0 (2025-11-24)
|
|
4
|
+
|
|
5
|
+
- Added `StyleCapsule::ClassRegistry` for Rails-friendly class tracking without ObjectSpace iteration
|
|
6
|
+
- Fixed development environment bug where `ObjectSpace.each_object(Class)` could trigger errors with gems that override `Class#name` (e.g., Faker)
|
|
7
|
+
- Improved `ComponentBuilder` to use ClassRegistry first, with ObjectSpace fallback for compatibility
|
|
8
|
+
- Classes are now automatically registered when including `StyleCapsule::Component` or `StyleCapsule::ViewComponent`
|
|
9
|
+
- Better performance in development mode by tracking only relevant classes instead of iterating all classes
|
|
10
|
+
- Enhanced error handling for classes that cause issues during iteration
|
|
11
|
+
|
|
3
12
|
## 1.1.0 (2025-11-21)
|
|
4
13
|
|
|
5
14
|
- Made Rails dependencies optional: `railties` and `activesupport` moved to development dependencies
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# style_capsule
|
|
2
2
|
|
|
3
|
-
[](https://badge.fury.io/rb/style_capsule) [](https://github.com/amkisko/style_capsule.rb/actions/workflows/test.yml) [](https://codecov.io/gh/amkisko/style_capsule.rb)
|
|
4
4
|
|
|
5
5
|
CSS scoping extension for Ruby components. Provides attribute-based style encapsulation for Phlex, ViewComponent, and ERB templates to prevent style leakage between components. Works with Rails and can be used standalone in other Ruby frameworks (Sinatra, Hanami, etc.) or plain Ruby scripts. Includes configurable caching strategies for optimal performance.
|
|
6
6
|
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module StyleCapsule
|
|
4
|
+
# Registry for tracking classes that include StyleCapsule modules
|
|
5
|
+
#
|
|
6
|
+
# This provides a Rails-friendly way to track classes without using ObjectSpace,
|
|
7
|
+
# which can be problematic with certain gems (e.g., Faker) that override Class#name.
|
|
8
|
+
#
|
|
9
|
+
# Classes are automatically registered when they include StyleCapsule::Component
|
|
10
|
+
# or StyleCapsule::ViewComponent.
|
|
11
|
+
#
|
|
12
|
+
# @example
|
|
13
|
+
# # Classes are automatically registered when they include modules
|
|
14
|
+
# class MyComponent < ApplicationComponent
|
|
15
|
+
# include StyleCapsule::Component # Automatically registered
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
# # Iterate over registered classes
|
|
19
|
+
# StyleCapsule::ClassRegistry.each do |klass|
|
|
20
|
+
# klass.clear_css_cache if klass.respond_to?(:clear_css_cache)
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
23
|
+
# # Clear registry (useful in development when classes are reloaded)
|
|
24
|
+
# StyleCapsule::ClassRegistry.clear
|
|
25
|
+
class ClassRegistry
|
|
26
|
+
# Use Set for O(1) lookups instead of O(n) with Array#include?
|
|
27
|
+
@classes = Set.new
|
|
28
|
+
|
|
29
|
+
class << self
|
|
30
|
+
# Register a class that includes a StyleCapsule module
|
|
31
|
+
#
|
|
32
|
+
# @param klass [Class] The class to register
|
|
33
|
+
# @return [void]
|
|
34
|
+
def register(klass)
|
|
35
|
+
return if klass.nil?
|
|
36
|
+
return if klass.singleton_class?
|
|
37
|
+
|
|
38
|
+
# Only register classes with names (skip anonymous classes)
|
|
39
|
+
begin
|
|
40
|
+
name = klass.name
|
|
41
|
+
return if name.nil? || name.to_s.strip.empty?
|
|
42
|
+
rescue
|
|
43
|
+
# Skip classes that cause errors when calling name (e.g., ArgumentError, NoMethodError, NameError)
|
|
44
|
+
return
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
@classes.add(klass)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Remove a class from the registry
|
|
51
|
+
#
|
|
52
|
+
# @param klass [Class] The class to unregister
|
|
53
|
+
# @return [void]
|
|
54
|
+
def unregister(klass)
|
|
55
|
+
@classes.delete(klass)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Iterate over all registered classes
|
|
59
|
+
#
|
|
60
|
+
# @yield [Class] Each registered class
|
|
61
|
+
# @return [void]
|
|
62
|
+
def each(&block)
|
|
63
|
+
# Filter out classes that no longer exist or have been unloaded
|
|
64
|
+
# Use delete_if for Set (equivalent to reject! for Array)
|
|
65
|
+
@classes.delete_if do |klass|
|
|
66
|
+
# Check if class still exists and is valid
|
|
67
|
+
klass.name.nil? || klass.singleton_class?
|
|
68
|
+
rescue
|
|
69
|
+
# Class has been unloaded or causes errors - remove from registry
|
|
70
|
+
true
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
@classes.each(&block)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Get all registered classes
|
|
77
|
+
#
|
|
78
|
+
# @return [Array<Class>] Array of registered classes
|
|
79
|
+
def all
|
|
80
|
+
# Filter out invalid classes
|
|
81
|
+
each.to_a
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Clear the registry
|
|
85
|
+
#
|
|
86
|
+
# Useful in development when classes are reloaded.
|
|
87
|
+
#
|
|
88
|
+
# @return [void]
|
|
89
|
+
def clear
|
|
90
|
+
@classes.clear
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Get the number of registered classes
|
|
94
|
+
#
|
|
95
|
+
# @return [Integer]
|
|
96
|
+
def count
|
|
97
|
+
each.count
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -21,34 +21,47 @@ module StyleCapsule
|
|
|
21
21
|
|
|
22
22
|
# Find all Phlex components that use StyleCapsule
|
|
23
23
|
#
|
|
24
|
+
# Uses ClassRegistry to find registered components (Rails-friendly, avoids expensive ObjectSpace scanning).
|
|
25
|
+
# Classes are automatically registered when they include StyleCapsule::Component.
|
|
26
|
+
#
|
|
24
27
|
# @return [Array<Class>] Array of component classes
|
|
25
28
|
def find_phlex_components
|
|
26
29
|
return [] unless phlex_available?
|
|
27
30
|
|
|
28
31
|
components = []
|
|
29
|
-
|
|
32
|
+
|
|
33
|
+
# Use the registry (Rails-friendly, avoids expensive ObjectSpace scanning)
|
|
34
|
+
ClassRegistry.each do |klass|
|
|
30
35
|
if klass < Phlex::HTML && klass.included_modules.include?(StyleCapsule::Component)
|
|
31
36
|
components << klass
|
|
32
37
|
end
|
|
38
|
+
rescue
|
|
39
|
+
# Skip classes that cause errors (inheritance checks, etc.)
|
|
40
|
+
next
|
|
33
41
|
end
|
|
42
|
+
|
|
34
43
|
components
|
|
35
44
|
end
|
|
36
45
|
|
|
37
46
|
# Find all ViewComponent components that use StyleCapsule
|
|
38
47
|
#
|
|
48
|
+
# Uses ClassRegistry to find registered components (Rails-friendly, avoids expensive ObjectSpace scanning).
|
|
49
|
+
# Classes are automatically registered when they include StyleCapsule::ViewComponent.
|
|
50
|
+
#
|
|
39
51
|
# @return [Array<Class>] Array of component classes
|
|
40
52
|
def find_view_components
|
|
41
53
|
return [] unless view_component_available?
|
|
42
54
|
|
|
43
55
|
components = []
|
|
56
|
+
|
|
44
57
|
begin
|
|
45
|
-
|
|
58
|
+
# Use the registry (Rails-friendly, avoids expensive ObjectSpace scanning)
|
|
59
|
+
ClassRegistry.each do |klass|
|
|
46
60
|
if klass < ViewComponent::Base && klass.included_modules.include?(StyleCapsule::ViewComponent)
|
|
47
61
|
components << klass
|
|
48
62
|
end
|
|
49
63
|
rescue
|
|
50
|
-
# Skip
|
|
51
|
-
# (e.g., ViewComponent 2.83.0 has a bug with Gem::Version#to_f)
|
|
64
|
+
# Skip classes that cause errors (inheritance checks, etc.)
|
|
52
65
|
next
|
|
53
66
|
end
|
|
54
67
|
rescue
|
|
@@ -56,6 +69,7 @@ module StyleCapsule
|
|
|
56
69
|
# Silently skip ViewComponent components if there's an error
|
|
57
70
|
# This allows the rake task to continue with Phlex components
|
|
58
71
|
end
|
|
72
|
+
|
|
59
73
|
components
|
|
60
74
|
end
|
|
61
75
|
|
|
@@ -31,26 +31,16 @@ module StyleCapsule
|
|
|
31
31
|
# This prevents memory leaks from stale cache entries during code reloading
|
|
32
32
|
if Rails.env.development?
|
|
33
33
|
config.to_prepare do
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
|
|
37
|
-
#
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
name = klass.name
|
|
41
|
-
next if name.nil? || (name.respond_to?(:blank?) ? name.blank? : name.to_s.strip.empty?)
|
|
42
|
-
next if klass.singleton_class?
|
|
43
|
-
|
|
44
|
-
# Use method_defined? instead of respond_to? to avoid triggering delegation
|
|
45
|
-
# that might cause errors with singleton classes or other edge cases
|
|
46
|
-
begin
|
|
47
|
-
if klass.method_defined?(:clear_css_cache, false) || klass.private_method_defined?(:clear_css_cache)
|
|
48
|
-
klass.clear_css_cache
|
|
49
|
-
end
|
|
50
|
-
rescue
|
|
51
|
-
# Skip classes that cause errors (singleton classes, delegation issues, etc.)
|
|
52
|
-
next
|
|
34
|
+
# Use Rails-friendly class registry instead of ObjectSpace iteration
|
|
35
|
+
# This avoids issues with gems that override Class#name (e.g., Faker)
|
|
36
|
+
StyleCapsule::ClassRegistry.each do |klass|
|
|
37
|
+
# Clear CSS cache if the class has this method
|
|
38
|
+
if klass.method_defined?(:clear_css_cache, false) || klass.private_method_defined?(:clear_css_cache)
|
|
39
|
+
klass.clear_css_cache
|
|
53
40
|
end
|
|
41
|
+
rescue
|
|
42
|
+
# Skip classes that cause errors (unloaded classes, etc.)
|
|
43
|
+
next
|
|
54
44
|
end
|
|
55
45
|
|
|
56
46
|
# Clear stylesheet manifest to allow re-registration during code reload
|
data/lib/style_capsule.rb
CHANGED
|
@@ -92,6 +92,7 @@ module StyleCapsule
|
|
|
92
92
|
require_relative "style_capsule/css_processor"
|
|
93
93
|
require_relative "style_capsule/css_file_writer"
|
|
94
94
|
require_relative "style_capsule/stylesheet_registry"
|
|
95
|
+
require_relative "style_capsule/class_registry"
|
|
95
96
|
require_relative "style_capsule/component_styles_support"
|
|
96
97
|
require_relative "style_capsule/component"
|
|
97
98
|
require_relative "style_capsule/standalone_helper"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: style_capsule
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrei Makarov
|
|
@@ -261,6 +261,7 @@ files:
|
|
|
261
261
|
- README.md
|
|
262
262
|
- SECURITY.md
|
|
263
263
|
- lib/style_capsule.rb
|
|
264
|
+
- lib/style_capsule/class_registry.rb
|
|
264
265
|
- lib/style_capsule/component.rb
|
|
265
266
|
- lib/style_capsule/component_builder.rb
|
|
266
267
|
- lib/style_capsule/component_styles_support.rb
|