style_capsule 2.0.1 → 2.0.3
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 +20 -1
- data/README.md +44 -29
- data/SECURITY.md +11 -14
- data/docs/changelogs/20260904180000_audit-fixes.md +33 -0
- data/docs/changelogs/20260925094000_head-injection-bufferable-chunked.md +25 -0
- data/docs/changelogs/20260928193000_sync-appraisal-locks-after-version-bump.md +19 -0
- data/docs/dependencies/20260904174500_json-cve-2026-71847.md +37 -0
- data/docs/issues/20260904174500_engineering-and-dependency-audit.md +51 -0
- data/docs/issues/20260917123253_ci-drop-automatic-dependency-audit.md +28 -0
- data/docs/issues/20261103150931_engineering-prose-release-audit.md +40 -0
- data/docs/non_rails_support.md +2 -2
- data/docs/reviews/20261028_engineering-audit-release-preparation.md +25 -0
- data/docs/reviews/20261103150931_engineering-prose-release-audit.md +42 -0
- data/lib/style_capsule/component.rb +1 -1
- data/lib/style_capsule/component_builder.rb +1 -1
- data/lib/style_capsule/component_styles_support.rb +10 -0
- data/lib/style_capsule/css_file_writer.rb +5 -4
- data/lib/style_capsule/css_processor.rb +220 -83
- data/lib/style_capsule/head_injection_middleware.rb +22 -7
- data/lib/style_capsule/stylesheet_registry.rb +93 -62
- data/lib/style_capsule/version.rb +1 -1
- data/lib/style_capsule/view_component.rb +1 -1
- data/sig/style_capsule.rbs +6 -1
- metadata +22 -72
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "cgi"
|
|
3
4
|
require_relative "instrumentation"
|
|
4
5
|
require_relative "asset_path"
|
|
6
|
+
require_relative "css_processor"
|
|
5
7
|
|
|
6
8
|
module StyleCapsule
|
|
7
9
|
# Helper to determine the parent class for StylesheetRegistry
|
|
@@ -72,14 +74,18 @@ module StyleCapsule
|
|
|
72
74
|
class StylesheetRegistry < StyleCapsule.stylesheet_registry_parent_class
|
|
73
75
|
# Default namespace for backward compatibility
|
|
74
76
|
DEFAULT_NAMESPACE = :default
|
|
77
|
+
MAX_INLINE_CACHE_ENTRIES = 256
|
|
78
|
+
FALLBACK_LINK_OPTION_NAME = /\A(?:media|title|crossorigin|integrity|nonce|type|id|class|data-[a-zA-Z0-9_-]+)\z/
|
|
75
79
|
|
|
76
80
|
# Process-wide manifest for static file paths (like Propshaft)
|
|
77
81
|
# Organized by namespace: { namespace => { logical_path => { file_path:, options: } } }
|
|
78
82
|
@manifest = {} # rubocop:disable Style/ClassVars, ThreadSafety/MutableClassInstanceVariable
|
|
83
|
+
@manifest_mutex = Mutex.new
|
|
79
84
|
|
|
80
85
|
# Process-wide cache for inline CSS (with expiration support)
|
|
81
86
|
# Structure: { cache_key => { css_content: String, cached_at: Time, expires_at: Time } }
|
|
82
87
|
@inline_cache = {} # rubocop:disable Style/ClassVars, ThreadSafety/MutableClassInstanceVariable
|
|
88
|
+
@inline_cache_mutex = Mutex.new
|
|
83
89
|
|
|
84
90
|
# Track last cleanup time for lazy cleanup (prevents excessive cleanup calls)
|
|
85
91
|
@last_cleanup_time = nil # rubocop:disable Style/ClassVars
|
|
@@ -222,8 +228,10 @@ module StyleCapsule
|
|
|
222
228
|
inline_size: nil,
|
|
223
229
|
cache_strategy: :none
|
|
224
230
|
) do
|
|
225
|
-
|
|
226
|
-
|
|
231
|
+
with_manifest do
|
|
232
|
+
@manifest[ns] ||= {}
|
|
233
|
+
@manifest[ns][path] = {file_path: path, options: options}
|
|
234
|
+
end
|
|
227
235
|
end
|
|
228
236
|
end
|
|
229
237
|
|
|
@@ -350,11 +358,10 @@ module StyleCapsule
|
|
|
350
358
|
# @param namespace [Symbol] Namespace (for proc strategy)
|
|
351
359
|
# @return [String, nil] Cached CSS content or nil if not cached/expired
|
|
352
360
|
def self.cached_inline(cache_key, cache_strategy:, cache_ttl: nil, cache_proc: nil, css_content: nil, capsule_id: nil, namespace: nil)
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
cached_entry = @inline_cache[cache_key]
|
|
361
|
+
cached_entry = with_inline_cache do
|
|
362
|
+
cleanup_expired_cache_unlocked_if_needed
|
|
363
|
+
@inline_cache[cache_key]
|
|
364
|
+
end
|
|
358
365
|
return nil unless cached_entry
|
|
359
366
|
|
|
360
367
|
# Check expiration based on strategy
|
|
@@ -402,11 +409,16 @@ module StyleCapsule
|
|
|
402
409
|
end
|
|
403
410
|
end
|
|
404
411
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
412
|
+
with_inline_cache do
|
|
413
|
+
unless @inline_cache.key?(cache_key)
|
|
414
|
+
@inline_cache.shift while @inline_cache.size >= MAX_INLINE_CACHE_ENTRIES
|
|
415
|
+
end
|
|
416
|
+
@inline_cache[cache_key] = {
|
|
417
|
+
css_content: css_content,
|
|
418
|
+
cached_at: current_time,
|
|
419
|
+
expires_at: expires_at
|
|
420
|
+
}
|
|
421
|
+
end
|
|
410
422
|
end
|
|
411
423
|
|
|
412
424
|
# Clear inline CSS cache
|
|
@@ -414,10 +426,12 @@ module StyleCapsule
|
|
|
414
426
|
# @param cache_key [String, nil] Specific cache key to clear (nil clears all)
|
|
415
427
|
# @return [void]
|
|
416
428
|
def self.clear_inline_cache(cache_key = nil)
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
429
|
+
with_inline_cache do
|
|
430
|
+
if cache_key
|
|
431
|
+
@inline_cache.delete(cache_key)
|
|
432
|
+
else
|
|
433
|
+
@inline_cache.clear
|
|
434
|
+
end
|
|
421
435
|
end
|
|
422
436
|
end
|
|
423
437
|
|
|
@@ -437,13 +451,16 @@ module StyleCapsule
|
|
|
437
451
|
# # In a scheduled job or initializer
|
|
438
452
|
# StyleCapsule::StylesheetRegistry.cleanup_expired_cache
|
|
439
453
|
def self.cleanup_expired_cache
|
|
454
|
+
with_inline_cache { cleanup_expired_cache_unlocked }
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
def self.cleanup_expired_cache_unlocked
|
|
440
458
|
return 0 if @inline_cache.empty?
|
|
441
459
|
|
|
442
460
|
now = current_time
|
|
443
461
|
expired_keys = []
|
|
444
462
|
|
|
445
463
|
@inline_cache.each do |cache_key, entry|
|
|
446
|
-
# Remove entries that have an expires_at time and it's in the past
|
|
447
464
|
if entry[:expires_at] && now > entry[:expires_at]
|
|
448
465
|
expired_keys << cache_key
|
|
449
466
|
end
|
|
@@ -455,23 +472,24 @@ module StyleCapsule
|
|
|
455
472
|
expired_keys.size
|
|
456
473
|
end
|
|
457
474
|
|
|
458
|
-
|
|
459
|
-
#
|
|
460
|
-
# Only performs cleanup if it's been more than 5 minutes since the last cleanup.
|
|
461
|
-
# This prevents excessive cleanup calls while still preventing memory leaks.
|
|
462
|
-
#
|
|
463
|
-
# @return [void]
|
|
464
|
-
# @api private
|
|
465
|
-
def self.cleanup_expired_cache_if_needed
|
|
466
|
-
# Cleanup every 5 minutes (300 seconds) to balance memory usage and performance
|
|
475
|
+
def self.cleanup_expired_cache_unlocked_if_needed
|
|
467
476
|
cleanup_interval = 300
|
|
468
477
|
|
|
469
478
|
if @last_cleanup_time.nil? || (current_time - @last_cleanup_time) > cleanup_interval
|
|
470
|
-
|
|
479
|
+
cleanup_expired_cache_unlocked
|
|
471
480
|
end
|
|
472
481
|
end
|
|
473
482
|
|
|
474
|
-
|
|
483
|
+
def self.with_inline_cache
|
|
484
|
+
@inline_cache_mutex.synchronize { yield }
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
def self.with_manifest
|
|
488
|
+
@manifest_mutex.synchronize { yield }
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
private_class_method :cleanup_expired_cache_unlocked, :cleanup_expired_cache_unlocked_if_needed,
|
|
492
|
+
:with_inline_cache, :with_manifest
|
|
475
493
|
|
|
476
494
|
# Get all registered file paths from process-wide manifest (organized by namespace)
|
|
477
495
|
#
|
|
@@ -540,11 +558,13 @@ module StyleCapsule
|
|
|
540
558
|
# @param namespace [Symbol, String, nil] Optional namespace to clear (nil clears all)
|
|
541
559
|
# @return [void]
|
|
542
560
|
def self.clear_manifest(namespace: nil)
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
561
|
+
with_manifest do
|
|
562
|
+
if namespace.nil?
|
|
563
|
+
@manifest = {}
|
|
564
|
+
else
|
|
565
|
+
ns = normalize_namespace(namespace)
|
|
566
|
+
@manifest.delete(ns)
|
|
567
|
+
end
|
|
548
568
|
end
|
|
549
569
|
end
|
|
550
570
|
|
|
@@ -564,7 +584,17 @@ module StyleCapsule
|
|
|
564
584
|
# If nil, falls back to basic HTML generation
|
|
565
585
|
# @param namespace [Symbol, String, nil] Optional namespace to render (nil/blank renders all namespaces)
|
|
566
586
|
# @return [String] HTML-safe string with stylesheet tags
|
|
567
|
-
|
|
587
|
+
def self.render_stylesheet_entries(stylesheets, view_context)
|
|
588
|
+
stylesheets.map do |stylesheet|
|
|
589
|
+
if stylesheet[:type] == :inline
|
|
590
|
+
render_inline_stylesheet(stylesheet, view_context)
|
|
591
|
+
else
|
|
592
|
+
render_file_stylesheet(stylesheet, view_context)
|
|
593
|
+
end
|
|
594
|
+
end.join("\n").then { |s| safe_string(s) }
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity -- renders mixed inline and file registrations
|
|
568
598
|
def self.render_head_stylesheets(view_context = nil, namespace: nil)
|
|
569
599
|
if namespace.nil? || namespace.to_s.strip.empty?
|
|
570
600
|
request_files_snapshot = request_file_stylesheets.transform_values { |files| files.keys.dup }
|
|
@@ -578,16 +608,9 @@ module StyleCapsule
|
|
|
578
608
|
|
|
579
609
|
return safe_string("") if all_stylesheets.empty?
|
|
580
610
|
|
|
581
|
-
rendered = all_stylesheets
|
|
582
|
-
if stylesheet[:type] == :inline
|
|
583
|
-
render_inline_stylesheet(stylesheet, view_context)
|
|
584
|
-
else
|
|
585
|
-
render_file_stylesheet(stylesheet, view_context)
|
|
586
|
-
end
|
|
587
|
-
end.join("\n").then { |s| safe_string(s) }
|
|
611
|
+
rendered = render_stylesheet_entries(all_stylesheets, view_context)
|
|
588
612
|
|
|
589
613
|
clear_snapshotted_request_registrations(request_files_snapshot, request_inline_snapshot)
|
|
590
|
-
rendered
|
|
591
614
|
|
|
592
615
|
else
|
|
593
616
|
# Render specific namespace
|
|
@@ -598,24 +621,19 @@ module StyleCapsule
|
|
|
598
621
|
|
|
599
622
|
return safe_string("") if stylesheets.empty?
|
|
600
623
|
|
|
601
|
-
rendered = stylesheets
|
|
602
|
-
if stylesheet[:type] == :inline
|
|
603
|
-
render_inline_stylesheet(stylesheet, view_context)
|
|
604
|
-
else
|
|
605
|
-
render_file_stylesheet(stylesheet, view_context)
|
|
606
|
-
end
|
|
607
|
-
end.join("\n").then { |s| safe_string(s) }
|
|
624
|
+
rendered = render_stylesheet_entries(stylesheets, view_context)
|
|
608
625
|
|
|
609
626
|
clear_snapshotted_request_registrations_for_namespace(
|
|
610
627
|
ns,
|
|
611
628
|
file_paths: snapshotted_file_paths,
|
|
612
629
|
snapshotted_inline_stylesheets: snapshotted_inline
|
|
613
630
|
)
|
|
614
|
-
rendered
|
|
615
631
|
|
|
616
632
|
end
|
|
633
|
+
|
|
634
|
+
rendered
|
|
617
635
|
end
|
|
618
|
-
# rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity
|
|
636
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
619
637
|
|
|
620
638
|
# Check if there are any registered stylesheets
|
|
621
639
|
#
|
|
@@ -668,6 +686,7 @@ module StyleCapsule
|
|
|
668
686
|
end
|
|
669
687
|
|
|
670
688
|
# @api private
|
|
689
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity -- clears snapshotted request registries per namespace
|
|
671
690
|
def self.clear_snapshotted_request_registrations_for_namespace(namespace, file_paths:, snapshotted_inline_stylesheets:)
|
|
672
691
|
ns = normalize_namespace(namespace)
|
|
673
692
|
|
|
@@ -694,6 +713,7 @@ module StyleCapsule
|
|
|
694
713
|
|
|
695
714
|
self.inline_stylesheets = inline_registry
|
|
696
715
|
end
|
|
716
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
697
717
|
|
|
698
718
|
# Inject pending request-scoped stylesheets into an HTML document before +</head>+.
|
|
699
719
|
#
|
|
@@ -708,10 +728,16 @@ module StyleCapsule
|
|
|
708
728
|
return html if pending_stylesheets.empty?
|
|
709
729
|
|
|
710
730
|
closing_head_index = html.match(%r{</head>}i)&.begin(0)
|
|
711
|
-
|
|
731
|
+
unless closing_head_index
|
|
732
|
+
clear
|
|
733
|
+
return html
|
|
734
|
+
end
|
|
712
735
|
|
|
713
736
|
tags = render_stylesheet_tags(pending_stylesheets, view_context)
|
|
714
|
-
|
|
737
|
+
if tags.empty?
|
|
738
|
+
clear
|
|
739
|
+
return html
|
|
740
|
+
end
|
|
715
741
|
|
|
716
742
|
injected = html.dup
|
|
717
743
|
injected.insert(closing_head_index, "#{tags}\n")
|
|
@@ -793,20 +819,24 @@ module StyleCapsule
|
|
|
793
819
|
else
|
|
794
820
|
# Fallback if no view context (logical path validated in .register)
|
|
795
821
|
href = "/assets/#{file_path}.css"
|
|
796
|
-
tag_options = options
|
|
822
|
+
tag_options = fallback_link_option_attributes(options)
|
|
797
823
|
safe_string(%(<link rel="stylesheet" href="#{href}"#{" #{tag_options}" unless tag_options.empty?}>))
|
|
798
824
|
end
|
|
799
825
|
end
|
|
800
826
|
|
|
827
|
+
def self.fallback_link_option_attributes(options)
|
|
828
|
+
options.filter_map do |key, value|
|
|
829
|
+
name = key.to_s
|
|
830
|
+
next unless name.match?(FALLBACK_LINK_OPTION_NAME)
|
|
831
|
+
|
|
832
|
+
%(#{name}="#{CGI.escapeHTML(value.to_s)}")
|
|
833
|
+
end.join(" ")
|
|
834
|
+
end
|
|
835
|
+
|
|
801
836
|
# Render an inline stylesheet
|
|
802
|
-
def self.render_inline_stylesheet(stylesheet,
|
|
803
|
-
# CSS content is already scoped when registered from components
|
|
804
|
-
# capsule_id is stored for reference but CSS is pre-processed
|
|
837
|
+
def self.render_inline_stylesheet(stylesheet, _view_context)
|
|
805
838
|
css_content = stylesheet[:css_content]
|
|
806
|
-
|
|
807
|
-
# Construct HTML manually to avoid any HTML escaping issues
|
|
808
|
-
# CSS content should not be HTML-escaped as it's inside a <style> tag
|
|
809
|
-
# Using string interpolation with html_safe ensures CSS is not escaped
|
|
839
|
+
CssProcessor.reject_style_element_breakout!(css_content)
|
|
810
840
|
safe_string(%(<style type="text/css">#{css_content}</style>))
|
|
811
841
|
end
|
|
812
842
|
|
|
@@ -822,6 +852,7 @@ module StyleCapsule
|
|
|
822
852
|
end
|
|
823
853
|
end
|
|
824
854
|
|
|
825
|
-
private_class_method :render_file_stylesheet, :render_inline_stylesheet, :safe_string
|
|
855
|
+
private_class_method :render_file_stylesheet, :render_inline_stylesheet, :safe_string,
|
|
856
|
+
:fallback_link_option_attributes
|
|
826
857
|
end
|
|
827
858
|
end
|
|
@@ -167,7 +167,7 @@ module StyleCapsule
|
|
|
167
167
|
|
|
168
168
|
# File caching is only allowed for class method component_styles
|
|
169
169
|
if cache_strategy == :file && !file_caching_allowed?
|
|
170
|
-
|
|
170
|
+
warn_file_cache_fallback(self.class)
|
|
171
171
|
cache_strategy = :none
|
|
172
172
|
cache_ttl = nil
|
|
173
173
|
cache_proc = nil
|
data/sig/style_capsule.rbs
CHANGED
|
@@ -6,9 +6,13 @@ module StyleCapsule
|
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
module CssProcessor
|
|
9
|
+
MAX_CSS_SIZE: Integer
|
|
10
|
+
NON_SCOPING_AT_RULES: Array[String]
|
|
11
|
+
HOISTABLE_AT_RULES: Array[String]
|
|
12
|
+
|
|
9
13
|
def self.scope_selectors: (String css_string, String capsule_id, ?component_class: Class | String | nil) -> String
|
|
10
14
|
def self.scope_with_nesting: (String css_string, String capsule_id, ?component_class: Class | String | nil) -> String
|
|
11
|
-
def self.
|
|
15
|
+
def self.reject_style_element_breakout!: (String | nil css_string) -> void
|
|
12
16
|
end
|
|
13
17
|
|
|
14
18
|
class CssFileWriter
|
|
@@ -24,6 +28,7 @@ module StyleCapsule
|
|
|
24
28
|
# At runtime inherits Object when ActiveSupport::CurrentAttributes is unavailable.
|
|
25
29
|
class StylesheetRegistry
|
|
26
30
|
DEFAULT_NAMESPACE: Symbol
|
|
31
|
+
MAX_INLINE_CACHE_ENTRIES: Integer
|
|
27
32
|
|
|
28
33
|
def self.normalize_namespace: (Symbol | String | nil namespace) -> Symbol
|
|
29
34
|
def self.register: (String file_path, ?namespace: Symbol | String | nil, **Hash[untyped, untyped] options) -> void
|
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: 2.0.
|
|
4
|
+
version: 2.0.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrei Makarov
|
|
@@ -15,7 +15,7 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: '
|
|
18
|
+
version: '7.0'
|
|
19
19
|
- - "<"
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
21
|
version: '9.0'
|
|
@@ -25,7 +25,7 @@ dependencies:
|
|
|
25
25
|
requirements:
|
|
26
26
|
- - ">="
|
|
27
27
|
- !ruby/object:Gem::Version
|
|
28
|
-
version: '
|
|
28
|
+
version: '7.0'
|
|
29
29
|
- - "<"
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
31
|
version: '9.0'
|
|
@@ -35,7 +35,7 @@ dependencies:
|
|
|
35
35
|
requirements:
|
|
36
36
|
- - ">="
|
|
37
37
|
- !ruby/object:Gem::Version
|
|
38
|
-
version: '
|
|
38
|
+
version: '7.0'
|
|
39
39
|
- - "<"
|
|
40
40
|
- !ruby/object:Gem::Version
|
|
41
41
|
version: '9.0'
|
|
@@ -45,7 +45,7 @@ dependencies:
|
|
|
45
45
|
requirements:
|
|
46
46
|
- - ">="
|
|
47
47
|
- !ruby/object:Gem::Version
|
|
48
|
-
version: '
|
|
48
|
+
version: '7.0'
|
|
49
49
|
- - "<"
|
|
50
50
|
- !ruby/object:Gem::Version
|
|
51
51
|
version: '9.0'
|
|
@@ -67,16 +67,16 @@ dependencies:
|
|
|
67
67
|
name: polyrun
|
|
68
68
|
requirement: !ruby/object:Gem::Requirement
|
|
69
69
|
requirements:
|
|
70
|
-
- - "
|
|
70
|
+
- - ">="
|
|
71
71
|
- !ruby/object:Gem::Version
|
|
72
|
-
version:
|
|
72
|
+
version: 2.2.0
|
|
73
73
|
type: :development
|
|
74
74
|
prerelease: false
|
|
75
75
|
version_requirements: !ruby/object:Gem::Requirement
|
|
76
76
|
requirements:
|
|
77
|
-
- - "
|
|
77
|
+
- - ">="
|
|
78
78
|
- !ruby/object:Gem::Version
|
|
79
|
-
version:
|
|
79
|
+
version: 2.2.0
|
|
80
80
|
- !ruby/object:Gem::Dependency
|
|
81
81
|
name: webmock
|
|
82
82
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -105,48 +105,6 @@ dependencies:
|
|
|
105
105
|
- - "~>"
|
|
106
106
|
- !ruby/object:Gem::Version
|
|
107
107
|
version: '13'
|
|
108
|
-
- !ruby/object:Gem::Dependency
|
|
109
|
-
name: simplecov
|
|
110
|
-
requirement: !ruby/object:Gem::Requirement
|
|
111
|
-
requirements:
|
|
112
|
-
- - "~>"
|
|
113
|
-
- !ruby/object:Gem::Version
|
|
114
|
-
version: '0.22'
|
|
115
|
-
type: :development
|
|
116
|
-
prerelease: false
|
|
117
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
118
|
-
requirements:
|
|
119
|
-
- - "~>"
|
|
120
|
-
- !ruby/object:Gem::Version
|
|
121
|
-
version: '0.22'
|
|
122
|
-
- !ruby/object:Gem::Dependency
|
|
123
|
-
name: rspec_junit_formatter
|
|
124
|
-
requirement: !ruby/object:Gem::Requirement
|
|
125
|
-
requirements:
|
|
126
|
-
- - "~>"
|
|
127
|
-
- !ruby/object:Gem::Version
|
|
128
|
-
version: '0.6'
|
|
129
|
-
type: :development
|
|
130
|
-
prerelease: false
|
|
131
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
132
|
-
requirements:
|
|
133
|
-
- - "~>"
|
|
134
|
-
- !ruby/object:Gem::Version
|
|
135
|
-
version: '0.6'
|
|
136
|
-
- !ruby/object:Gem::Dependency
|
|
137
|
-
name: simplecov-cobertura
|
|
138
|
-
requirement: !ruby/object:Gem::Requirement
|
|
139
|
-
requirements:
|
|
140
|
-
- - "~>"
|
|
141
|
-
- !ruby/object:Gem::Version
|
|
142
|
-
version: '3'
|
|
143
|
-
type: :development
|
|
144
|
-
prerelease: false
|
|
145
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
146
|
-
requirements:
|
|
147
|
-
- - "~>"
|
|
148
|
-
- !ruby/object:Gem::Version
|
|
149
|
-
version: '3'
|
|
150
108
|
- !ruby/object:Gem::Dependency
|
|
151
109
|
name: standard
|
|
152
110
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -273,20 +231,6 @@ dependencies:
|
|
|
273
231
|
- - "~>"
|
|
274
232
|
- !ruby/object:Gem::Version
|
|
275
233
|
version: '2'
|
|
276
|
-
- !ruby/object:Gem::Dependency
|
|
277
|
-
name: memory_profiler
|
|
278
|
-
requirement: !ruby/object:Gem::Requirement
|
|
279
|
-
requirements:
|
|
280
|
-
- - "~>"
|
|
281
|
-
- !ruby/object:Gem::Version
|
|
282
|
-
version: '1'
|
|
283
|
-
type: :development
|
|
284
|
-
prerelease: false
|
|
285
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
286
|
-
requirements:
|
|
287
|
-
- - "~>"
|
|
288
|
-
- !ruby/object:Gem::Version
|
|
289
|
-
version: '1'
|
|
290
234
|
- !ruby/object:Gem::Dependency
|
|
291
235
|
name: rbs
|
|
292
236
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -329,11 +273,8 @@ dependencies:
|
|
|
329
273
|
- - "~>"
|
|
330
274
|
- !ruby/object:Gem::Version
|
|
331
275
|
version: '4.0'
|
|
332
|
-
description:
|
|
333
|
-
|
|
334
|
-
scoped to prevent leakage between components. Inspired by component-based CSS approaches
|
|
335
|
-
like Angular's view encapsulation and CSS modules. Works with Rails and can be used
|
|
336
|
-
standalone in other Ruby frameworks (Sinatra, Hanami, etc.) or plain Ruby scripts.
|
|
276
|
+
description: Attribute-based CSS scoping via [data-capsule] for Phlex, ViewComponent,
|
|
277
|
+
and ERB. Works with Rails and standalone in other Ruby frameworks or plain Ruby.
|
|
337
278
|
email:
|
|
338
279
|
- contact@kiskolabs.com
|
|
339
280
|
executables: []
|
|
@@ -344,7 +285,16 @@ files:
|
|
|
344
285
|
- LICENSE.md
|
|
345
286
|
- README.md
|
|
346
287
|
- SECURITY.md
|
|
288
|
+
- docs/changelogs/20260904180000_audit-fixes.md
|
|
289
|
+
- docs/changelogs/20260925094000_head-injection-bufferable-chunked.md
|
|
290
|
+
- docs/changelogs/20260928193000_sync-appraisal-locks-after-version-bump.md
|
|
291
|
+
- docs/dependencies/20260904174500_json-cve-2026-71847.md
|
|
292
|
+
- docs/issues/20260904174500_engineering-and-dependency-audit.md
|
|
293
|
+
- docs/issues/20260917123253_ci-drop-automatic-dependency-audit.md
|
|
294
|
+
- docs/issues/20261103150931_engineering-prose-release-audit.md
|
|
347
295
|
- docs/non_rails_support.md
|
|
296
|
+
- docs/reviews/20261028_engineering-audit-release-preparation.md
|
|
297
|
+
- docs/reviews/20261103150931_engineering-prose-release-audit.md
|
|
348
298
|
- lib/style_capsule.rb
|
|
349
299
|
- lib/style_capsule/asset_path.rb
|
|
350
300
|
- lib/style_capsule/class_registry.rb
|
|
@@ -383,14 +333,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
383
333
|
requirements:
|
|
384
334
|
- - ">="
|
|
385
335
|
- !ruby/object:Gem::Version
|
|
386
|
-
version: '3.
|
|
336
|
+
version: '3.4'
|
|
387
337
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
388
338
|
requirements:
|
|
389
339
|
- - ">="
|
|
390
340
|
- !ruby/object:Gem::Version
|
|
391
341
|
version: '0'
|
|
392
342
|
requirements: []
|
|
393
|
-
rubygems_version: 4.0.
|
|
343
|
+
rubygems_version: 4.0.6
|
|
394
344
|
specification_version: 4
|
|
395
345
|
summary: Attribute-based CSS scoping for Phlex, ViewComponent, and ERB templates.
|
|
396
346
|
test_files: []
|