Class: Panda::Core::ModuleRegistry
- Inherits:
-
Object
- Object
- Panda::Core::ModuleRegistry
- Defined in:
- lib/panda/core/module_registry.rb
Overview
Module registry for Panda ecosystem components
This class maintains a registry of all Panda modules (CMS, CMS Pro, Community, etc.) and their asset paths. Each module self-registers during engine initialization.
Benefits:
-
Core doesn’t need hardcoded knowledge of other modules
-
Supports private modules (e.g., panda-community in development)
-
Single source of truth for asset compilation
-
Scales automatically to future modules
Usage:
# In module's engine.rb (after class definition):
Panda::Core::ModuleRegistry.register(
gem_name: 'panda-cms',
engine: 'Panda::CMS::Engine',
paths: {
views: 'app/views/panda/cms/**/*.erb',
components: 'app/components/panda/cms/**/*.rb',
stylesheets: 'app/assets/stylesheets/panda/cms/**/*.css'
}
)
Defined Under Namespace
Classes: JavaScriptMiddleware
Class Attribute Summary collapse
-
.modules ⇒ Hash
readonly
Returns all registered modules.
Class Method Summary collapse
-
.combined_importmap ⇒ Hash
Returns a combined importmap for all registered modules.
-
.javascript_sources ⇒ Array<String>
Returns JavaScript source files by introspecting importmaps.
-
.register(gem_name:, engine:, paths:) ⇒ Object
Register a Panda module with its asset paths.
-
.registered?(gem_name) ⇒ Boolean
Check if a specific module is registered.
-
.registered_modules ⇒ Array<String>
Returns registered module names.
-
.tailwind_content_paths ⇒ Array<String>
Returns content paths for Tailwind CSS scanning.
Class Attribute Details
.modules ⇒ Hash (readonly)
Returns all registered modules
50 51 52 |
# File 'lib/panda/core/module_registry.rb', line 50 def modules @modules end |
Class Method Details
.combined_importmap ⇒ Hash
Returns a combined importmap for all registered modules
This merges importmaps from Core and all registered modules (CMS, CMS Pro, etc.) into a single hash suitable for <script type=“importmap”> generation.
Order matters: Core imports are added first, then modules in registration order. If there are conflicts, later modules override earlier ones.
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/panda/core/module_registry.rb', line 156 def combined_importmap imports = {} # Add Panda Core imports first (if Core has an importmap) if defined?(Panda::Core.importmap) Panda::Core.importmap.instance_variable_get(:@packages).each do |name, package| imports[name] = package.path end end # Add registered modules' importmaps in registration order @modules.each do |gem_name, info| next unless engine_available?(info[:engine]) # Get the module's importmap constant (e.g., Panda::CMS.importmap) module_importmap = module_importmap_for(info[:engine]) next unless module_importmap module_importmap.instance_variable_get(:@packages).each do |name, package| imports[name] = package.path end end imports end |
.javascript_sources ⇒ Array<String>
Returns JavaScript source files by introspecting importmaps
Instead of duplicating file lists, we read the importmap configuration that each engine already maintains. This provides a single source of truth.
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/panda/core/module_registry.rb', line 104 def javascript_sources return [] unless defined?(Rails.application&.importmap) sources = [] # Detect importmap-rails version and use appropriate API importmap = Rails.application.importmap entries = if importmap.respond_to?(:packages) # importmap-rails 2.x - packages is a hash importmap.packages elsif importmap.respond_to?(:entries) # importmap-rails 1.x - entries is an array importmap.entries.map { |e| [e.name, e] }.to_h else {} end # Find all Panda-namespaced imports and resolve to file paths entries.each do |name, config| next unless name.to_s.match?(/^panda-/) path = resolve_importmap_to_path(name, config) sources << path if path end sources.compact.uniq end |
.register(gem_name:, engine:, paths:) ⇒ Object
Register a Panda module with its asset paths
40 41 42 43 44 45 |
# File 'lib/panda/core/module_registry.rb', line 40 def register(gem_name:, engine:, paths:) @modules[gem_name] = { engine: engine, paths: paths } end |
.registered?(gem_name) ⇒ Boolean
Check if a specific module is registered
143 144 145 |
# File 'lib/panda/core/module_registry.rb', line 143 def registered?(gem_name) @modules.key?(gem_name) end |
.registered_modules ⇒ Array<String>
Returns registered module names
135 136 137 |
# File 'lib/panda/core/module_registry.rb', line 135 def registered_modules @modules.keys end |
.tailwind_content_paths ⇒ Array<String>
Returns content paths for Tailwind CSS scanning
Tailwind needs to scan all files that might contain utility classes:
-
Views (ERB templates)
-
Components (ViewComponent classes)
-
JavaScript (Stimulus controllers, etc.)
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/panda/core/module_registry.rb', line 60 def tailwind_content_paths paths = [] # Core's own content (always included) core_root = Panda::Core::Engine.root paths << "#{core_root}/app/views/panda/core/**/*.erb" paths << "#{core_root}/app/components/panda/core/**/*.rb" # Registered modules (only if engine is loaded) @modules.each do |gem_name, info| next unless engine_available?(info[:engine]) root = engine_root(info[:engine]) next unless root # Add configured path types paths << "#{root}/#{info[:paths][:views]}" if info[:paths][:views] paths << "#{root}/#{info[:paths][:components]}" if info[:paths][:components] # For Tailwind scanning, we also need to scan JavaScript for utility classes # Check if module has JavaScript (via importmap or direct paths) js_root = root.join("app/javascript") if js_root.directory? paths << "#{js_root}/**/*.js" end end # Host application Panda overrides # Applications can override any Panda views/components if defined?(Rails.root) paths << "#{Rails.root}/app/views/panda/**/*.erb" paths << "#{Rails.root}/app/components/panda/**/*.rb" paths << "#{Rails.root}/app/javascript/panda/**/*.js" end paths.compact end |