panda-core 0.9.0 → 0.9.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '09a8389d14bf25a5ebc6d546d1b3857b3515166393f9f5c9ba424337932b7ea5'
4
- data.tar.gz: 406ab4fe14528cf664fcffaa8a371348bb71b91a68797db02002eee69d20d8f9
3
+ metadata.gz: '08a72a419dd702e8cc8cde2bfea476a283a17280499bb16de53b554ebaf7406c'
4
+ data.tar.gz: 4cf2468a51ed77691ab280b2cfb4b0345a2449e4bb61a36560b286cecb311cac
5
5
  SHA512:
6
- metadata.gz: 663c29fcfcb8e35cb7c4c8029ab242eae56421964bb9e9acc74b6d1c1f04d5e8ae9d4bb426349f5fec6c1df5f258047c490ba85ef5f8fc4fe429689b8538dc02
7
- data.tar.gz: 22012fde38aaea3b480b31b1063515c079cc90c71e5e4a8a80428aafac457fac1a629c8b102076939bf4124ef026ae626e296d6b23b4d170b73974a62ee956bc
6
+ metadata.gz: d8ebe8e076e53a063dc0f7ab565c6b12c299a6765cdd7e9c446716a5de191070ea2da46a75167f384ab4ee5c2fa91753543625e2cbc64f58a9f962725be39042
7
+ data.tar.gz: c7d7d8932c8eea8b767343e27a4ce23ac0206c40df9acd6557b5734b2684f16080a2586fc99a63d62b0b548427dd35cf4603219e2d9938f3d704d873da818a39
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Panda
4
+ module Core
5
+ module Admin
6
+ class SettingsController < AdminController
7
+ def show
8
+ # Placeholder for site settings page
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -9,6 +9,10 @@ module Panda
9
9
  end
10
10
 
11
11
  # Include only Core JavaScript
12
+ #
13
+ # This is the single entry point for all Panda JavaScript loading.
14
+ # It automatically includes JavaScript from Core and all registered modules
15
+ # via ModuleRegistry.
12
16
  def panda_core_javascript
13
17
  # Use asset_tags for development mode (importmap) compatibility
14
18
  # In development, this will use importmap; in production/test, compiled bundles
@@ -22,20 +26,34 @@ module Panda
22
26
  javascript_include_tag(js_url, type: "module")
23
27
  end
24
28
  else
25
- # Development mode - Use the engine's importmap (loaded in initializer)
26
- # This keeps the engine's JavaScript separate from the app's importmap
27
- # Build the importmap JSON manually since paths are already absolute
28
- imports = {}
29
- Panda::Core.importmap.instance_variable_get(:@packages).each do |name, package|
30
- imports[name] = package[:path]
31
- end
29
+ # Development mode - Use ModuleRegistry to combine all Panda module importmaps
30
+ imports = Panda::Core::ModuleRegistry.combined_importmap
32
31
 
33
32
  importmap_json = JSON.generate({"imports" => imports})
34
33
 
34
+ # Generate entry point script tags for Core and all registered modules
35
+ entry_points = []
36
+
37
+ # Core entry points (always included)
38
+ entry_points << '<script type="module">import "panda/core/application"</script>'
39
+ entry_points << '<script type="module">import "panda/core/controllers/index"</script>'
40
+
41
+ # Add entry points for each registered module
42
+ Panda::Core::ModuleRegistry.modules.each do |gem_name, info|
43
+ # Extract module namespace from gem name (e.g., "panda-cms" -> "cms")
44
+ module_slug = gem_name.sub(/^panda-/, "")
45
+
46
+ # Check if the module is actually loaded
47
+ module_name = info[:engine].sub(/::Engine$/, "")
48
+ next unless Object.const_defined?(module_name)
49
+
50
+ entry_points << %(<script type="module">import "panda/#{module_slug}/application"</script>)
51
+ entry_points << %(<script type="module">import "panda/#{module_slug}/controllers/index"</script>)
52
+ end
53
+
35
54
  <<~HTML.html_safe
36
55
  <script type="importmap">#{importmap_json}</script>
37
- <script type="module">import "panda/core/application"</script>
38
- <script type="module">import "panda/core/controllers/index"</script>
56
+ #{entry_points.join("\n")}
39
57
  HTML
40
58
  end
41
59
  end
@@ -0,0 +1,10 @@
1
+ <%= render Panda::Core::Admin::ContainerComponent.new do %>
2
+ <%= render Panda::Core::Admin::HeadingComponent.new(level: 1, text: "Settings") %>
3
+
4
+ <div class="mt-6 space-y-6">
5
+ <%= render Panda::Core::Admin::PanelComponent.new do %>
6
+ <%= render Panda::Core::Admin::HeadingComponent.new(level: 2, text: "Site Settings") %>
7
+ <p class="text-sm text-gray-600 mt-2">Configure your site settings here.</p>
8
+ <% end %>
9
+ </div>
10
+ <% end %>
@@ -6,11 +6,14 @@
6
6
  <%= csp_meta_tag %>
7
7
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@7.1.0/css/all.min.css">
8
8
  <%= panda_core_stylesheet %>
9
+
10
+ <!-- ES Module Shims polyfill - must load BEFORE importmap (blocking, not async) -->
11
+ <script src="https://ga.jspm.io/npm:[email protected]/dist/es-module-shims.js" crossorigin="anonymous"></script>
12
+
13
+ <!-- Panda JavaScript (Core + all registered modules via ModuleRegistry) -->
9
14
  <%= panda_core_javascript %>
10
15
 
11
16
  <% if defined?(Panda::CMS) && controller.class.name.start_with?("Panda::CMS") %>
12
- <!-- CMS Assets -->
13
- <%= panda_cms_javascript %>
14
17
  <%= render "panda/cms/shared/favicons" %>
15
18
  <% end %>
16
19
 
data/config/routes.rb CHANGED
@@ -19,6 +19,9 @@ Panda::Core::Engine.routes.draw do
19
19
  # Profile management
20
20
  resource :my_profile, only: %i[show edit update], controller: "admin/my_profile", path: "my_profile"
21
21
 
22
+ # Settings
23
+ resource :settings, only: [:show], controller: "admin/settings"
24
+
22
25
  # Test-only authentication endpoint (available in development and test environments)
23
26
  # This bypasses OAuth for faster, more reliable test execution
24
27
  # Development: Used by Capybara system tests which run Rails server in development mode
@@ -151,8 +151,9 @@ module Panda
151
151
  version = asset_version
152
152
  "/panda-core-assets/panda-core-#{version}.js"
153
153
  else
154
- # Return importmap path
155
- "/assets/panda/core/application.js"
154
+ # Return path for development/test mode
155
+ # JavaScript is served via importmap from app/javascript
156
+ "/panda/core/application.js"
156
157
  end
157
158
  end
158
159
 
@@ -4,29 +4,13 @@ module Panda
4
4
  module Core
5
5
  class Engine < ::Rails::Engine
6
6
  # Middleware configuration for static assets
7
+ # Note: Actual middleware is registered in engine.rb initializer
8
+ # This module is kept for organizational purposes
7
9
  module MiddlewareConfig
8
10
  extend ActiveSupport::Concern
9
11
 
10
- included do
11
- # Make files in public available to the main app (e.g. /panda-core-assets/panda-logo.png)
12
- config.middleware.use Rack::Static,
13
- urls: ["/panda-core-assets"],
14
- root: Panda::Core::Engine.root.join("public"),
15
- header_rules: [
16
- # Disable caching in development for instant CSS updates
17
- [:all, {"Cache-Control" => Rails.env.development? ? "no-cache, no-store, must-revalidate" : "public, max-age=31536000"}]
18
- ]
19
-
20
- # Make JavaScript files available for importmap
21
- # Serve from app/javascript with proper MIME types
22
- config.middleware.use Rack::Static,
23
- urls: ["/panda", "/panda/core"],
24
- root: Panda::Core::Engine.root.join("app/javascript"),
25
- header_rules: [
26
- [:all, {"Cache-Control" => Rails.env.development? ? "no-cache, no-store, must-revalidate" : "public, max-age=31536000",
27
- "Content-Type" => "text/javascript; charset=utf-8"}]
28
- ]
29
- end
12
+ # Middleware configuration moved to engine.rb initializer
13
+ # See lib/panda/core/engine.rb - initializer "panda.core.static_assets"
30
14
  end
31
15
  end
32
16
  end
@@ -57,6 +57,27 @@ module Panda
57
57
  # Configuration is already initialized with defaults in Configuration class
58
58
  end
59
59
 
60
+ # Static asset middleware for serving public files and JavaScript modules
61
+ initializer "panda.core.static_assets", before: :build_middleware_stack do |app|
62
+ # Make files in public available to the main app (e.g. /panda-core-assets/panda-logo.png)
63
+ app.config.middleware.use Rack::Static,
64
+ urls: ["/panda-core-assets"],
65
+ root: Panda::Core::Engine.root.join("public"),
66
+ header_rules: [
67
+ # Disable caching in development for instant CSS updates
68
+ [:all, {"Cache-Control" => Rails.env.development? ? "no-cache, no-store, must-revalidate" : "public, max-age=31536000"}]
69
+ ]
70
+
71
+ # Make JavaScript files available for importmap
72
+ # Serve from app/javascript with proper MIME types
73
+ app.config.middleware.use Rack::Static,
74
+ urls: ["/panda/core"],
75
+ root: Panda::Core::Engine.root.join("app/javascript"),
76
+ header_rules: [
77
+ [:all, {"Cache-Control" => Rails.env.development? ? "no-cache, no-store, must-revalidate" : "public, max-age=31536000"}]
78
+ ]
79
+ end
80
+
60
81
  # Auto-compile CSS for test/development environments
61
82
  initializer "panda_core.auto_compile_assets", after: :load_config_initializers do |app|
62
83
  # Only auto-compile in test or when explicitly requested
@@ -144,8 +144,62 @@ module Panda
144
144
  @modules.key?(gem_name)
145
145
  end
146
146
 
147
+ # Returns a combined importmap for all registered modules
148
+ #
149
+ # This merges importmaps from Core and all registered modules (CMS, CMS Pro, etc.)
150
+ # into a single hash suitable for <script type="importmap"> generation.
151
+ #
152
+ # Order matters: Core imports are added first, then modules in registration order.
153
+ # If there are conflicts, later modules override earlier ones.
154
+ #
155
+ # @return [Hash] Combined imports hash {"module/name" => "/path/to/file.js"}
156
+ def combined_importmap
157
+ imports = {}
158
+
159
+ # Add Panda Core imports first (if Core has an importmap)
160
+ if defined?(Panda::Core.importmap)
161
+ Panda::Core.importmap.instance_variable_get(:@packages).each do |name, package|
162
+ imports[name] = package.path
163
+ end
164
+ end
165
+
166
+ # Add registered modules' importmaps in registration order
167
+ @modules.each do |gem_name, info|
168
+ next unless engine_available?(info[:engine])
169
+
170
+ # Get the module's importmap constant (e.g., Panda::CMS.importmap)
171
+ module_importmap = module_importmap_for(info[:engine])
172
+ next unless module_importmap
173
+
174
+ module_importmap.instance_variable_get(:@packages).each do |name, package|
175
+ imports[name] = package.path
176
+ end
177
+ end
178
+
179
+ imports
180
+ end
181
+
147
182
  private
148
183
 
184
+ # Get the importmap for a module
185
+ #
186
+ # @param engine_name [String] Engine constant name (e.g., "Panda::CMS::Engine")
187
+ # @return [Importmap::Map, nil] Module's importmap or nil if not available
188
+ def module_importmap_for(engine_name)
189
+ # Extract module namespace from engine name (e.g., "Panda::CMS::Engine" -> "Panda::CMS")
190
+ module_name = engine_name.sub(/::Engine$/, "")
191
+ return nil unless Object.const_defined?(module_name)
192
+
193
+ mod = Object.const_get(module_name)
194
+ return nil unless mod.respond_to?(:importmap)
195
+
196
+ mod.importmap
197
+ rescue NoMethodError
198
+ nil
199
+ rescue NameError
200
+ nil
201
+ end
202
+
149
203
  # Check if an engine constant is defined and available
150
204
  #
151
205
  # @param engine_name [String] Engine constant name
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ # CI-specific Capybara configuration
4
+ # This file configures Capybara for GitHub Actions and other CI environments
5
+ # It uses a more robust Puma setup with compatibility for Puma 6 and 7+
6
+
7
+ return unless defined?(Capybara)
8
+
9
+ ci_mode = ENV["GITHUB_ACTIONS"] == "true" || ENV["CI_SYSTEM_SPECS"] == "true"
10
+ return unless ci_mode
11
+
12
+ require "rack/handler/puma"
13
+
14
+ RSpec.configure do |config|
15
+ config.before(:suite) do
16
+ Capybara.server = :puma_ci
17
+ Capybara.default_max_wait_time = Integer(ENV.fetch("CAPYBARA_MAX_WAIT_TIME", 5))
18
+ Capybara.server_host = "127.0.0.1"
19
+ Capybara.always_include_port = true
20
+
21
+ puts "[CI Config] Capybara.server = #{Capybara.server.inspect}"
22
+ puts "[CI Config] Capybara.server_host = #{Capybara.server_host.inspect}"
23
+ puts "[CI Config] Capybara.max_wait = #{Capybara.default_max_wait_time}s"
24
+ end
25
+ end
26
+
27
+ Capybara.register_server :puma_ci do |app, port, host|
28
+ puts "[CI Config] Starting Puma (single mode) on #{host}:#{port}"
29
+
30
+ min_threads = Integer(ENV.fetch("PUMA_MIN_THREADS", "2"))
31
+ max_threads = Integer(ENV.fetch("PUMA_MAX_THREADS", "2"))
32
+
33
+ options = {
34
+ Host: host,
35
+ Port: port,
36
+ Threads: "#{min_threads}:#{max_threads}",
37
+ Workers: 0,
38
+ Silent: false,
39
+ Verbose: true,
40
+ PreloadApp: false
41
+ }
42
+
43
+ # --- Puma Compatibility Layer (supports Puma 6 AND Puma 7+) ---
44
+ puma_run = Rack::Handler::Puma.method(:run)
45
+
46
+ if puma_run.arity == 2
47
+ # Puma <= 6.x signature:
48
+ # run(app, options_hash)
49
+ puts "[CI Config] Using Puma <= 6 API (arity 2)"
50
+ Rack::Handler::Puma.run(app, options)
51
+ else
52
+ # Puma >= 7.x signature:
53
+ # run(app, **options)
54
+ puts "[CI Config] Using Puma >= 7 API (keyword args)"
55
+ Rack::Handler::Puma.run(app, **options)
56
+ end
57
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Panda
4
4
  module Core
5
- VERSION = "0.9.0"
5
+ VERSION = "0.9.2"
6
6
  end
7
7
  end
@@ -3,154 +3,136 @@
3
3
  #
4
4
  # Panda Core Asset Tasks
5
5
  #
6
- # This file contains BOTH:
7
- # 1. Engine-level CSS compilation (existing functionality)
8
- # 2. Dummy-app asset preparation for system tests (new)
9
- #
10
- # These tasks are used by:
11
- # - engine developers running local dev
12
- # - panda-cms CI preparing dummy app
13
- # - system specs that depend on Propshaft + Importmap + Cuprite
14
- #
15
6
 
16
7
  namespace :panda do
17
8
  namespace :core do
18
9
  namespace :assets do
19
- # --------------------------------------------------------------------------
20
- # 🐼 1. EXISTING TASKS ENGINE CSS COMPILATION
21
- # --------------------------------------------------------------------------
10
+ # =========================================================
11
+ # 1) ENGINE CSS COMPILATION (unchanged, just cleaned)
12
+ # =========================================================
22
13
 
23
- desc "Compile Panda Core assets for development (overwrites panda-core.css)"
14
+ desc "Compile Panda Core CSS assets (development mode)"
24
15
  task :compile do
25
- puts "🐼 Compiling Panda Core CSS assets (development mode)..."
16
+ puts "🐼 Compiling Panda Core CSS assets..."
26
17
 
27
18
  output_dir = panda_engine_root.join("public", "panda-core-assets")
28
19
  FileUtils.mkdir_p(output_dir)
29
20
 
30
21
  compile_css_development(output_dir)
31
22
 
32
- puts "🎉 Asset compilation complete!"
33
- puts "📁 Output directory: #{output_dir}"
34
- puts ""
23
+ puts "🎉 CSS compiled → #{output_dir}"
35
24
  end
36
25
 
37
26
  desc "Compile and version Panda Core CSS assets for release"
38
27
  task :release do
39
- puts "🐼 Compiling Panda Core CSS assets for release..."
40
-
41
28
  require_relative "../../panda/core/version"
42
- version = Panda::Core::VERSION
43
29
 
30
+ version = Panda::Core::VERSION
44
31
  output_dir = panda_engine_root.join("public", "panda-core-assets")
45
32
  FileUtils.mkdir_p(output_dir)
46
33
 
47
34
  compile_css_release(output_dir, version)
48
35
 
49
- puts "🎉 Release asset compilation complete!"
50
- puts "📁 Output directory: #{output_dir}"
51
- puts "📦 Versioned: panda-core-#{version}.css"
36
+ puts "🎉 Release assets compiled"
52
37
  end
53
38
 
54
- # --------------------------------------------------------------------------
55
- # 🧩 INTERNAL HELPERS (CSS)
56
- # --------------------------------------------------------------------------
39
+ # =========================================================
40
+ # CSS INTERNAL HELPERS
41
+ # =========================================================
57
42
 
58
43
  def panda_engine_root
59
44
  Panda::Core::Engine.root
60
45
  end
61
46
 
62
47
  def compile_css_development(output_dir)
63
- engine_root = panda_engine_root
64
- input_file = engine_root.join("app/assets/tailwind/application.css")
65
- output_file = output_dir.join("panda-core.css")
66
-
67
- content_paths = Panda::Core::ModuleRegistry.tailwind_content_paths
68
- content_flags = content_paths.map { |p| "--content '#{p}'" }.join(" ")
48
+ input = panda_engine_root.join("app/assets/tailwind/application.css")
49
+ output = output_dir.join("panda-core.css")
69
50
 
70
- cmd = "bundle exec tailwindcss -i #{input_file} -o #{output_file} #{content_flags} --minify"
51
+ content = Panda::Core::ModuleRegistry.tailwind_content_paths
52
+ flags = content.map { |p| "--content '#{p}'" }.join(" ")
71
53
 
72
- unless system(cmd)
73
- abort("❌ CSS compilation failed")
74
- end
54
+ cmd = "bundle exec tailwindcss -i #{input} -o #{output} #{flags} --minify"
55
+ abort("❌ CSS compile failed") unless system(cmd)
75
56
 
76
- puts " CSS compiled: #{output_file} (#{File.size(output_file)} bytes)"
57
+ puts " #{output.basename} (#{File.size(output)} bytes)"
77
58
  end
78
59
 
79
60
  def compile_css_release(output_dir, version)
80
- engine_root = panda_engine_root
81
- input_file = engine_root.join("app/assets/tailwind/application.css")
82
- versioned_file = output_dir.join("panda-core-#{version}.css")
61
+ input = panda_engine_root.join("app/assets/tailwind/application.css")
62
+ file = output_dir.join("panda-core-#{version}.css")
83
63
 
84
- content_paths = Panda::Core::ModuleRegistry.tailwind_content_paths
85
- content_flags = content_paths.map { |p| "--content '#{p}'" }.join(" ")
64
+ content = Panda::Core::ModuleRegistry.tailwind_content_paths
65
+ flags = content.map { |p| "--content '#{p}'" }.join(" ")
86
66
 
87
- cmd = "bundle exec tailwindcss -i #{input_file} -o #{versioned_file} #{content_flags} --minify"
88
-
89
- unless system(cmd)
90
- abort("❌ CSS compilation failed")
91
- end
67
+ cmd = "bundle exec tailwindcss -i #{input} -o #{file} #{flags} --minify"
68
+ abort("❌ CSS release compile failed") unless system(cmd)
92
69
 
93
70
  symlink = output_dir.join("panda-core.css")
94
71
  FileUtils.rm_f(symlink)
95
- FileUtils.ln_sf(File.basename(versioned_file), symlink)
72
+ FileUtils.ln_sf(file.basename, symlink)
96
73
 
97
- puts " Release CSS compiled + symlink generated"
74
+ puts " Versioned file + symlink created"
98
75
  end
99
76
 
100
- # --------------------------------------------------------------------------
101
- # 🚂 2. NEW TASKS — DUMMY APP ASSET PREPARATION (FOR CI + SYSTEM TESTS)
102
- # --------------------------------------------------------------------------
77
+ # =========================================================
78
+ # 2) DUMMY APP PREP (FOR SYSTEM TESTS + CI)
79
+ # =========================================================
103
80
 
104
- desc "Compile Panda Core + host app assets into spec/dummy/public/assets (CI)"
81
+ desc "Compile Panda Core + dummy app assets into spec/dummy/public/assets"
105
82
  task compile_dummy: :environment do
106
83
  dummy_root = find_dummy_root
107
84
  assets_root = dummy_root.join("public/assets")
108
85
 
109
- puts "🚧 Compiling assets into dummy app:"
110
- puts "👉 #{assets_root}"
111
-
86
+ puts "🚧 Compiling dummy assets..."
87
+ puts " #{assets_root}"
112
88
  FileUtils.mkdir_p(assets_root)
113
89
 
114
90
  Dir.chdir(dummy_root) do
115
- # Runs the engine's asset compile pipeline in the dummy app context
116
- unless system("bundle exec rake app:panda:core:assets:compile")
117
- abort("❌ Failed to compile Panda Core assets in dummy app")
91
+ # IMPORTANT: this is now the correct task name
92
+ unless system("bundle exec rake panda:core:assets:compile")
93
+ abort("❌ panda:core:assets:compile failed in dummy app")
118
94
  end
95
+
96
+ # Propshaft (Rails 8)
97
+ abort("❌ assets:precompile failed") \
98
+ unless system("bundle exec rake assets:precompile RAILS_ENV=#{Rails.env}")
119
99
  end
120
100
 
121
101
  puts "✅ Dummy assets compiled"
122
102
  end
123
103
 
124
- desc "Generate importmap.json for Rails 8 dummy app"
104
+ desc "Generate importmap.json for the dummy app"
125
105
  task generate_dummy_importmap: :environment do
126
106
  dummy_root = find_dummy_root
127
- importmap_out = dummy_root.join("public/assets/importmap.json")
107
+ output = dummy_root.join("public/assets/importmap.json")
128
108
 
129
- puts "🗺️ Generating importmap.json..."
130
- FileUtils.mkdir_p(importmap_out.dirname)
109
+ puts "🗺️ Generating importmap.json..."
110
+ FileUtils.mkdir_p(output.dirname)
131
111
 
132
112
  Dir.chdir(dummy_root) do
133
- map = Rails.application.importmap
134
- File.write(importmap_out, JSON.pretty_generate(map.to_json))
113
+ json = Rails.application.importmap.to_json(
114
+ resolver: ActionController::Base.helpers
115
+ )
116
+ File.write(output, JSON.pretty_generate(json))
135
117
  end
136
118
 
137
- puts " importmap.json written to #{importmap_out}"
119
+ puts " importmap.json written"
138
120
  end
139
121
 
140
- desc "Verify dummy app asset readiness (fail-fast for CI)"
122
+ desc "Verify dummy assets for CI (fail-fast)"
141
123
  task verify_dummy: :environment do
142
124
  dummy_root = find_dummy_root
143
- assets_root = dummy_root.join("public/assets")
144
- manifest = assets_root.join(".manifest.json")
145
- importmap = assets_root.join("importmap.json")
125
+ assets = dummy_root.join("public/assets")
126
+ manifest = assets.join(".manifest.json")
127
+ importmap = assets.join("importmap.json")
146
128
 
147
- abort("❌ Missing directory: #{assets_root}") unless Dir.exist?(assets_root)
148
- abort("❌ Missing #{manifest}") unless File.exist?(manifest)
149
- abort("❌ Missing #{importmap}") unless File.exist?(importmap)
129
+ abort("❌ Missing #{assets}") unless assets.exist?
130
+ abort("❌ Missing #{manifest}") unless manifest.exist?
131
+ abort("❌ Missing #{importmap}") unless importmap.exist?
150
132
 
151
133
  begin
152
134
  parsed = JSON.parse(File.read(manifest))
153
- abort("❌ Empty manifest!") if parsed.empty?
135
+ abort("❌ Empty .manifest.json") if parsed.empty?
154
136
  rescue
155
137
  abort("❌ Invalid .manifest.json")
156
138
  end
@@ -158,20 +140,19 @@ namespace :panda do
158
140
  puts "✅ Dummy assets verified"
159
141
  end
160
142
 
161
- # --------------------------------------------------------------------------
162
- # 🧩 INTERNAL HELPERS (DUMMY APP)
163
- # --------------------------------------------------------------------------
143
+ # =========================================================
144
+ # INTERNAL UTILITIES
145
+ # =========================================================
164
146
 
165
147
  def find_dummy_root
166
148
  root = Rails.root
149
+
167
150
  return root if root.basename.to_s == "dummy"
168
151
 
169
- # For engines, Rails.root will be e.g. panda-cms/
170
- # In CI we want panda-cms/spec/dummy/
171
- possible = root.join("spec/dummy")
172
- return possible if possible.exist?
152
+ candidate = root.join("spec/dummy")
153
+ return candidate if candidate.exist?
173
154
 
174
- abort("❌ Cannot find dummy root at #{possible}")
155
+ abort("❌ Cannot find dummy root expected #{candidate}")
175
156
  end
176
157
  end
177
158
  end
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: panda-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Otaina Limited
8
8
  - James Inman
9
- autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2025-11-12 00:00:00.000000000 Z
11
+ date: 1980-01-02 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: image_processing
@@ -430,6 +429,7 @@ files:
430
429
  - app/controllers/panda/core/admin/dashboard_controller.rb
431
430
  - app/controllers/panda/core/admin/my_profile_controller.rb
432
431
  - app/controllers/panda/core/admin/sessions_controller.rb
432
+ - app/controllers/panda/core/admin/settings_controller.rb
433
433
  - app/controllers/panda/core/admin/test_sessions_controller.rb
434
434
  - app/controllers/panda/core/application_controller.rb
435
435
  - app/helpers/panda/core/asset_helper.rb
@@ -457,6 +457,7 @@ files:
457
457
  - app/views/panda/core/admin/dashboard/show.html.erb
458
458
  - app/views/panda/core/admin/my_profile/edit.html.erb
459
459
  - app/views/panda/core/admin/sessions/new.html.erb
460
+ - app/views/panda/core/admin/settings/show.html.erb
460
461
  - app/views/panda/core/admin/shared/_breadcrumbs.html.erb
461
462
  - app/views/panda/core/admin/shared/_flash.html.erb
462
463
  - app/views/panda/core/admin/shared/_sidebar.html.erb
@@ -507,6 +508,7 @@ files:
507
508
  - lib/panda/core/testing/support/setup.rb
508
509
  - lib/panda/core/testing/support/system/better_system_tests.rb
509
510
  - lib/panda/core/testing/support/system/capybara_setup.rb
511
+ - lib/panda/core/testing/support/system/ci_capybara_config.rb
510
512
  - lib/panda/core/testing/support/system/cuprite_helpers.rb
511
513
  - lib/panda/core/testing/support/system/cuprite_setup.rb
512
514
  - lib/panda/core/testing/support/system/database_connection_helpers.rb
@@ -527,7 +529,6 @@ metadata:
527
529
  homepage_uri: https://github.com/tastybamboo/panda-core
528
530
  source_code_uri: https://github.com/tastybamboo/panda-core
529
531
  changelog_uri: https://github.com/tastybamboo/panda-core/blob/main/CHANGELOG.md
530
- post_install_message:
531
532
  rdoc_options: []
532
533
  require_paths:
533
534
  - lib
@@ -542,8 +543,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
542
543
  - !ruby/object:Gem::Version
543
544
  version: '0'
544
545
  requirements: []
545
- rubygems_version: 3.5.22
546
- signing_key:
546
+ rubygems_version: 3.6.9
547
547
  specification_version: 4
548
548
  summary: Core libraries and development tools for Tasty Bamboo projects
549
549
  test_files: []