Module: StyleCapsule::StandaloneHelper
- Includes:
- HelperScopeCache
- Defined in:
- lib/style_capsule/standalone_helper.rb
Overview
Standalone helper module for use without Rails
This module provides basic HTML generation and CSS scoping functionality without requiring Rails ActionView helpers. It can be included in any framework's view context or used directly.
Constant Summary collapse
- MAX_HTML_SIZE =
Maximum HTML content size (10MB) to prevent DoS attacks
10_000_000
Constants included from HelperScopeCache
HelperScopeCache::MAX_SCOPE_CACHE_ENTRIES, HelperScopeCache::STYLE_CLOSE, HelperScopeCache::STYLE_OPEN
Instance Method Summary collapse
-
#capture(&block) ⇒ String
Capture block content (simplified version without Rails).
-
#content_tag(tag, content = nil, **options, &block) ⇒ String
Generate HTML tag without Rails helpers.
-
#generate_capsule_id(css_content) ⇒ Object
Generate capsule ID based on caller location for uniqueness.
-
#html_safe(string) ⇒ String
Mark string as HTML-safe (for compatibility).
-
#raw(string) ⇒ String
Raw string (no HTML escaping).
-
#register_stylesheet(file_path, namespace: nil, **options) ⇒ void
Register a stylesheet file for head rendering.
-
#scope_css(css_content, capsule_id) ⇒ Object
Scope CSS content and return scoped CSS.
-
#style_capsule(css_content = nil, capsule_id: nil, tag: :div, &content_block) ⇒ String
ERB helper: automatically wraps content in scoped div and processes CSS.
-
#stylesheet_registry_tags(namespace: nil) ⇒ String
Render StyleCapsule registered stylesheets.
Instance Method Details
#capture(&block) ⇒ String
Capture block content (simplified version without Rails)
80 81 82 83 |
# File 'lib/style_capsule/standalone_helper.rb', line 80 def capture(&block) return "" unless block_given? block.call.to_s end |
#content_tag(tag, content = nil, **options, &block) ⇒ String
Generate HTML tag without Rails helpers
rubocop:disable Metrics/AbcSize -- serializes flat and nested HTML attributes
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/style_capsule/standalone_helper.rb', line 57 def content_tag(tag, content = nil, **, &block) tag_name = tag.to_s content = capture(&block) if block_given? && content.nil? content ||= "" attrs = .map do |k, v| if v.is_a?(Hash) # Handle nested attributes like data: { capsule: "abc" } v.map { |nk, nv| %(#{k}-#{nk}="#{escape_html_attr(nv)}") }.join(" ") else %(#{k}="#{escape_html_attr(v)}") end end.join(" ") attrs = " #{attrs}" unless attrs.empty? "<#{tag_name}#{attrs}>#{content}</#{tag_name}>" end |
#generate_capsule_id(css_content) ⇒ Object
Generate capsule ID based on caller location for uniqueness
37 38 39 40 41 42 |
# File 'lib/style_capsule/standalone_helper.rb', line 37 def generate_capsule_id(css_content) # Use caller location + CSS content for uniqueness caller_info = caller_locations(1, 1).first capsule_key = "#{caller_info.path}:#{caller_info.lineno}:#{css_content}" "a#{Digest::SHA1.hexdigest(capsule_key)}"[0, 8] end |
#html_safe(string) ⇒ String
Mark string as HTML-safe (for compatibility)
89 90 91 92 93 94 95 96 97 |
# File 'lib/style_capsule/standalone_helper.rb', line 89 def html_safe(string) # In non-Rails context, just return the string # If ActiveSupport is available, use its html_safe if string.respond_to?(:html_safe) string.html_safe else string end end |
#raw(string) ⇒ String
Raw string (no HTML escaping)
103 104 105 |
# File 'lib/style_capsule/standalone_helper.rb', line 103 def raw(string) html_safe(string.to_s) end |
#register_stylesheet(file_path, namespace: nil, **options) ⇒ void
This method returns an undefined value.
Register a stylesheet file for head rendering
163 164 165 |
# File 'lib/style_capsule/standalone_helper.rb', line 163 def register_stylesheet(file_path, namespace: nil, **) StyleCapsule::StylesheetRegistry.register(file_path, namespace: namespace, **) end |
#scope_css(css_content, capsule_id) ⇒ Object
Scope CSS content and return scoped CSS
45 46 47 |
# File 'lib/style_capsule/standalone_helper.rb', line 45 def scope_css(css_content, capsule_id) scope_css_with_bounded_cache(css_content, capsule_id) end |
#style_capsule(css_content = nil, capsule_id: nil, tag: :div, &content_block) ⇒ String
ERB helper: automatically wraps content in scoped div and processes CSS
rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity -- standalone helper mirrors Rails helper flow
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/style_capsule/standalone_helper.rb', line 114 def style_capsule(css_content = nil, capsule_id: nil, tag: :div, &content_block) html_content = nil # If CSS content is provided as argument, use it # Otherwise, extract from content block if css_content.nil? && block_given? full_content = capture(&content_block) # Validate HTML content size to prevent DoS attacks if full_content.bytesize > MAX_HTML_SIZE raise ArgumentError, "HTML content exceeds maximum size of #{MAX_HTML_SIZE} bytes (got #{full_content.bytesize} bytes)" end html_content, css_content = extract_styles_from_markup(full_content) if css_content.nil? html_content = full_content end elsif css_content && block_given? html_content = capture(&content_block) elsif css_content && !block_given? # CSS provided but no content block - just return scoped CSS capsule_id ||= generate_capsule_id(css_content) scoped_css = scope_css(css_content, capsule_id) return content_tag(:style, raw(scoped_css), type: "text/css") else return "" end # If no CSS, just return content return html_safe(html_content) if css_content.nil? || css_content.to_s.strip.empty? # Use provided capsule_id or generate one capsule_id ||= generate_capsule_id(css_content) scoped_css = scope_css(css_content, capsule_id) # Render style tag and wrapped content style_tag = content_tag(:style, raw(scoped_css), type: "text/css") wrapped_content = content_tag(tag, raw(html_content), data: {capsule: capsule_id}) html_safe(style_tag + wrapped_content) end |
#stylesheet_registry_tags(namespace: nil) ⇒ String
Render StyleCapsule registered stylesheets
171 172 173 |
# File 'lib/style_capsule/standalone_helper.rb', line 171 def (namespace: nil) StyleCapsule::StylesheetRegistry.render_head_stylesheets(self, namespace: namespace) end |