Class: Panda::Core::ModuleRegistry

Inherits:
Object
  • Object
show all
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

Class Method Summary collapse

Class Attribute Details

.modulesHash (readonly)

Returns all registered modules

Returns:

  • (Hash)

    Module registry



50
51
52
# File 'lib/panda/core/module_registry.rb', line 50

def modules
  @modules
end

Class Method Details

.combined_importmapHash

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

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.

Returns:

  • (Array<String>)

    Full paths to JavaScript source files



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

Parameters:

  • gem_name (String)

    Gem name (e.g., 'panda-cms')

  • engine (String)

    Engine constant name (e.g., 'Panda::CMS::Engine')

  • paths (Hash)

    Asset path patterns relative to engine root

Options Hash (paths:):

  • :views (String)

    View template paths

  • :components (String)

    ViewComponent paths

  • :stylesheets (String)

    Stylesheet paths (optional)



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

Parameters:

  • gem_name (String)

    Gem name to check

Returns:

  • (Boolean)

    True if 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_modulesArray<String>

Returns registered module names

Returns:

  • (Array<String>)

    List of registered gem names



135
136
137
# File 'lib/panda/core/module_registry.rb', line 135

def registered_modules
  @modules.keys
end

.tailwind_content_pathsArray<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.)

Returns:

  • (Array<String>)

    Full paths for Tailwind --content flags



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