panda-core 0.10.6 → 0.11.0

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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +26 -46
  3. data/app/assets/tailwind/application.css +6 -8
  4. data/app/models/concerns/panda/core/has_uuid.rb +24 -0
  5. data/app/models/panda/core/user.rb +2 -8
  6. data/db/migrate/20250809000001_create_panda_core_users.rb +14 -9
  7. data/lib/panda/core/engine.rb +4 -2
  8. data/lib/panda/core/shared/inflections_config.rb +1 -0
  9. data/lib/panda/core/version.rb +1 -1
  10. data/lib/tasks/panda/core/ci_tasks.rake +38 -0
  11. data/lib/tasks/panda/core/migrations.rake +0 -1
  12. data/lib/tasks/panda/shared.rake +83 -0
  13. data/public/panda-core-assets/favicons/android-chrome-192x192.png +0 -0
  14. data/public/panda-core-assets/favicons/android-chrome-512x512.png +0 -0
  15. data/public/panda-core-assets/favicons/apple-touch-icon.png +0 -0
  16. data/public/panda-core-assets/favicons/browserconfig.xml +9 -0
  17. data/public/panda-core-assets/favicons/favicon-16x16.png +0 -0
  18. data/public/panda-core-assets/favicons/favicon-32x32.png +0 -0
  19. data/public/panda-core-assets/favicons/favicon.ico +0 -0
  20. data/public/panda-core-assets/favicons/mstile-150x150.png +0 -0
  21. data/public/panda-core-assets/favicons/safari-pinned-tab.svg +61 -0
  22. data/public/panda-core-assets/favicons/site.webmanifest +14 -0
  23. data/public/panda-core-assets/panda-core-0.10.6.css +2 -2
  24. data/public/panda-core-assets/panda-core-0.10.7.css +2 -0
  25. data/public/panda-core-assets/panda-core.css +1 -1
  26. data/public/panda-core-assets/panda-logo-screenprint.png +0 -0
  27. data/public/panda-core-assets/panda-nav.png +0 -0
  28. metadata +32 -22
  29. data/app/assets/tailwind/tailwind.config.js +0 -29
  30. data/db/migrate/20250810120000_add_current_theme_to_panda_core_users.rb +0 -7
  31. data/db/migrate/20250811120000_add_oauth_avatar_url_to_panda_core_users.rb +0 -7
  32. data/lib/tasks/panda_core.rake +0 -52
  33. data/lib/tasks/panda_core_tasks.rake +0 -16
  34. data/public/panda-core-assets/panda-core-0.8.0.css +0 -2
  35. /data/lib/tasks/{panda_core_users.rake → panda/core/users.rake} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d19f2a3ddaf8824cf777911ccd3f763d705088ab6af1b42b0bbf25d27ef47813
4
- data.tar.gz: 8670e719ed3e22b8eb3fc4c846b18b0714096989adcfa975859015c4c95ccb66
3
+ metadata.gz: ecbb8f9e4f925e37db74cbb9bec9b45277feceafc990fbab333433adf86e8e36
4
+ data.tar.gz: ab419ee62bb77a3c382b462997439853ec07e438a37ea0d02935eb52d69d7169
5
5
  SHA512:
6
- metadata.gz: a4d9001b13004fc24c8f19a7d770509293ed9908d77baef27f34f72688a9519dd26fc9a99d3310259bd25f60e888be4866c9a13369c4d674e57c3962932c0f30
7
- data.tar.gz: 1ed6107145993f8cf0eb0bc1576d2f31e310be2a51a45170ea25b2556b2301f3b470680a004d200f14a088f88e5cc37571371b3b9611c345f19ffbc9b9a12ee2
6
+ metadata.gz: 79f71a37792d0c3b85edb9d211459e2b1433c3fab96bc8adfa707bb8ce443f11c80cdb12c05a75a03154912908c1bb759fdc2031b3ae1840a045f1629d3f0d14
7
+ data.tar.gz: 1d4f21c85d14ee7a474d8a83f1d99bccac31761a2803372a9d10d49156618cc40331d598ea805273040f8b56b5f4562bd873765bde423c76e358a76aab8ca56a
data/README.md CHANGED
@@ -5,6 +5,26 @@ Core functionality shared between Panda Software gems:
5
5
  - [Panda CMS](https://github.com/tastybamboo/panda-cms)
6
6
  - [Panda Editor](https://github.com/tastybamboo/panda-editor)
7
7
 
8
+ ## Requirements
9
+
10
+ ### Database Support
11
+
12
+ Panda Core supports both PostgreSQL and SQLite3 databases:
13
+
14
+ **PostgreSQL** (recommended for production):
15
+
16
+ - PostgreSQL 12, 15, 17, 18
17
+ - Tested against all versions in CI
18
+ - Uses native UUID generation (`gen_random_uuid()`)
19
+
20
+ **SQLite3** (development/testing):
21
+
22
+ - SQLite 3.x
23
+ - Uses application-level UUID generation
24
+ - Ideal for local development and testing
25
+
26
+ Both databases are tested extensively in CI across multiple Ruby and Rails versions to ensure cross-database compatibility.
27
+
8
28
  ## Installation
9
29
 
10
30
  Add this line to your application's Gemfile:
@@ -144,33 +164,6 @@ Panda Core uses Tailwind CSS v4 to compile all admin interface styling.
144
164
 
145
165
  **Quick Start** - Compile full CSS (Core + CMS):
146
166
 
147
- ```bash
148
- cd /path/to/panda-core
149
-
150
- bundle exec tailwindcss -i app/assets/tailwind/application.css \
151
- -o public/panda-core-assets/panda-core.css \
152
- --content '../cms/app/views/**/*.erb' \
153
- --content '../cms/app/components/**/*.rb' \
154
- --content '../cms/app/javascript/**/*.js' \
155
- --content 'app/views/**/*.erb' \
156
- --content 'app/components/**/*.rb' \
157
- --minify
158
- ```
159
-
160
- **Result**: `panda-core.css` (~37KB) with all utility classes
161
-
162
- **Important**: Always compile with full content before committing!
163
-
164
- For complete documentation on:
165
- - Development workflows (Core-only vs full stack)
166
- - Release processes
167
- - Troubleshooting
168
- - Best practices
169
-
170
- See **[docs/ASSET_COMPILATION.md](docs/ASSET_COMPILATION.md)**
171
-
172
- **How Asset Serving Works:**
173
-
174
167
  Core's Rack middleware serves `/panda-core-assets/` from the gem's `public/` directory:
175
168
 
176
169
  ```ruby
@@ -190,7 +183,7 @@ This means:
190
183
  **What Gets Compiled:**
191
184
 
192
185
  The compilation process:
193
- - Scans all Core and CMS views/components for Tailwind classes (via `tailwind.config.js`)
186
+ - Scans all Core and registered modules' views/components for Tailwind classes
194
187
  - Includes EditorJS content styles for rich text editing
195
188
  - Applies theme variables for default and sky themes
196
189
  - Outputs a single minified CSS file (~37KB)
@@ -208,28 +201,15 @@ Panda CMS depends on Panda Core and loads its CSS automatically:
208
201
  <link rel="stylesheet" href="/panda-core-assets/panda-core.css">
209
202
  ```
210
203
 
211
- CMS no longer compiles its own CSS - all styling comes from Core.
212
-
213
- **Content Scanning**
214
-
215
- The `tailwind.config.js` file configures content scanning to include:
216
- - Core views: `../../app/views/**/*.html.erb`
217
- - Core components: `../../app/components/**/*.rb`
218
- - CMS views: `../../../cms/app/views/**/*.html.erb`
219
- - CMS components: `../../../cms/app/components/**/*.rb`
220
- - CMS JavaScript: `../../../cms/app/javascript/**/*.js`
221
-
222
204
  This ensures all Tailwind classes used across the Panda ecosystem are included in the compiled CSS.
223
205
 
224
- **Customizing Styles**
206
+ To regenerate CSS, run (from inside `panda-core` or another engine):
225
207
 
226
- To customize the admin interface styles:
208
+ ```
209
+ bundle exec rake app:panda:compile_css
210
+ ```
227
211
 
228
- 1. Edit `app/assets/tailwind/application.css` in panda-core
229
- 2. Add custom CSS in the appropriate `@layer` (base, components, or utilities)
230
- 3. Recompile: `bundle exec tailwindcss -i app/assets/tailwind/application.css -o public/panda-core-assets/panda-core.css --minify`
231
- 4. Copy the updated CSS to test locations if needed
232
- 5. Restart your Rails server to see changes
212
+ You should run this from the top-most or last registered engine in your application.
233
213
 
234
214
  **Theme System**
235
215
 
@@ -1,13 +1,5 @@
1
1
  @import 'tailwindcss';
2
2
 
3
- @source "../../app/views/**/*.html.erb";
4
- @source "../../app/components/**/*.html.erb";
5
- @source "../../app/components/**/*.rb";
6
- @source "../../app/helpers/**/*.rb";
7
- @source "../../../cms/app/views/**/*.html.erb";
8
- @source "../../../cms/app/components/**/*.html.erb";
9
- @source "../../../cms/app/components/**/*.rb";
10
-
11
3
  @theme {
12
4
  /* Legacy colors */
13
5
  --color-white: var(--color-white);
@@ -250,6 +242,12 @@
250
242
  .btn-danger {
251
243
  @apply bg-red-600 text-white hover:bg-red-700 focus:ring-red-500;
252
244
  }
245
+
246
+ a.block-link:after {
247
+ position: absolute;
248
+ content: '';
249
+ inset: 0;
250
+ }
253
251
  }
254
252
 
255
253
  /* EditorJS content styles */
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Panda
4
+ module Core
5
+ # Concern for models using UUIDs as primary keys
6
+ # Ensures UUID generation works across all database adapters
7
+ module HasUUID
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ # Generate UUID before creation if not already set
12
+ # PostgreSQL uses gen_random_uuid() natively
13
+ # SQLite and other databases use SecureRandom.uuid
14
+ before_create :generate_uuid_if_blank
15
+ end
16
+
17
+ private
18
+
19
+ def generate_uuid_if_blank
20
+ self.id ||= SecureRandom.uuid if id.blank?
21
+ end
22
+ end
23
+ end
24
+ end
@@ -3,6 +3,8 @@
3
3
  module Panda
4
4
  module Core
5
5
  class User < ApplicationRecord
6
+ include HasUUID
7
+
6
8
  self.table_name = "panda_core_users"
7
9
 
8
10
  # Active Storage attachment for avatar with variants
@@ -69,14 +71,6 @@ module Panda
69
71
  true
70
72
  end
71
73
 
72
- def name
73
- if self[:name].present?
74
- self[:name]
75
- else
76
- email&.split("@")&.first || "Unknown User"
77
- end
78
- end
79
-
80
74
  # Returns the URL for the user's avatar
81
75
  # Prefers Active Storage attachment over OAuth provider URL
82
76
  # @param size [Symbol] The variant size (:thumb, :small, :medium, :large, or nil for original)
@@ -2,16 +2,21 @@
2
2
 
3
3
  class CreatePandaCoreUsers < ActiveRecord::Migration[7.1]
4
4
  def change
5
- unless table_exists?(:panda_core_users)
6
- create_table :panda_core_users, id: :uuid do |t|
7
- t.string :name
8
- t.string :email, null: false
9
- t.string :image_url
10
- t.boolean :is_admin, default: false, null: false
11
- t.timestamps
12
- end
5
+ # Enable pgcrypto extension for PostgreSQL UUID generation
6
+ enable_extension "pgcrypto" if ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
13
7
 
14
- add_index :panda_core_users, :email, unique: true
8
+ # Rails 7.1+ supports id: :uuid across databases
9
+ # PostgreSQL uses gen_random_uuid(), SQLite uses application-generated UUIDs
10
+ create_table :panda_core_users, id: :uuid do |t|
11
+ t.string :name
12
+ t.string :email, null: false
13
+ t.string :image_url
14
+ t.boolean :is_admin, default: false, null: false
15
+ t.string :current_theme
16
+ t.string :oauth_avatar_url
17
+ t.timestamps
15
18
  end
19
+
20
+ add_index :panda_core_users, :email, unique: true
16
21
  end
17
22
  end
@@ -81,8 +81,10 @@ Panda::Core::ModuleRegistry.register(
81
81
  gem_name: "panda-core",
82
82
  engine: "Panda::Core::Engine",
83
83
  paths: {
84
+ builders: "app/builders/panda/core/**/*.rb",
85
+ components: "app/components/panda/core/**/*.rb",
86
+ helpers: "app/helpers/panda/core/**/*.rb",
84
87
  views: "app/views/panda/core/**/*.erb",
85
- components: "app/components/panda/core/**/*.rb"
86
- # JavaScript paths are auto-discovered from config/importmap.rb
88
+ javascripts: "app/assets/javascript/panda/core/**/*.js"
87
89
  }
88
90
  )
@@ -15,6 +15,7 @@ module Panda
15
15
  inflect.acronym "CMS"
16
16
  inflect.acronym "SEO"
17
17
  inflect.acronym "AI"
18
+ inflect.acronym "UUID"
18
19
  end
19
20
  end
20
21
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Panda
4
4
  module Core
5
- VERSION = "0.10.6"
5
+ VERSION = "0.11.0"
6
6
  end
7
7
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ # TODO: These should ideally move to the panda: namespace and lint across all loaded modules
4
+
5
+ namespace :panda do
6
+ namespace :core do
7
+ desc "Run all linters"
8
+ task :lint do
9
+ puts "Running Ruby linter..."
10
+ sh "bundle exec standardrb"
11
+ puts "Running YAML linter..."
12
+ sh "yamllint -c .yamllint ."
13
+ end
14
+
15
+ namespace :lint do
16
+ desc "Run Ruby linter"
17
+ task :ruby do
18
+ sh "bundle exec standardrb"
19
+ end
20
+
21
+ desc "Run YAML linter"
22
+ task :yaml do
23
+ sh "yamllint -c .yamllint ."
24
+ end
25
+ end
26
+
27
+ desc "Run security checks"
28
+ task :security do
29
+ puts "Running Brakeman..."
30
+ sh "bundle exec brakeman --quiet"
31
+ puts "Running Bundler Audit..."
32
+ sh "bundle exec bundle-audit --update"
33
+ end
34
+
35
+ desc "Run all quality checks"
36
+ task quality: [:lint, :security]
37
+ end
38
+ end
@@ -3,7 +3,6 @@
3
3
  namespace :panda do
4
4
  namespace :core do
5
5
  namespace :install do
6
- desc "Copy migrations from panda_core to application"
7
6
  task :migrations do
8
7
  # Delegate to the auto-generated task
9
8
  Rake::Task["panda_core:install:migrations"].invoke
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :panda do
4
+ desc "Show all registered modules"
5
+ task registered_modules: :environment do
6
+ Panda::Core::ModuleRegistry.modules(&:map).each do |registered_module, module_attrs|
7
+ puts registered_modules
8
+ end
9
+ end
10
+
11
+ desc "Compile the Panda CSS"
12
+ task compile_css: :environment do
13
+ Rails.logger = Logger.new($stdout) if Rails.env.development? || Rails.env.test?
14
+
15
+ core_gemspec = Gem::Specification.find_by_name("panda-core")
16
+ output_dir = "#{core_gemspec.full_gem_path}/public/panda-core-assets"
17
+
18
+ puts "\n" + ("=" * 80)
19
+ puts "Panda CSS Compilation"
20
+ puts "=" * 80
21
+
22
+ registered_modules = Panda::Core::ModuleRegistry.modules(&:map)
23
+
24
+ puts "\n📦 Found #{registered_modules.length} registered Panda module(s):"
25
+ registered_modules.each do |gem_name, _info|
26
+ puts " • #{gem_name}"
27
+ end
28
+
29
+ if registered_modules.length == 1
30
+ puts "\n⚠️ Warning: Only compiling CSS for panda-core (no other modules loaded)"
31
+ end
32
+
33
+ puts "\n🎨 Output: #{output_dir}/panda-core.css"
34
+ puts ""
35
+
36
+ command = ["bundle exec tailwindcss",
37
+ "-i #{core_gemspec.full_gem_path}/app/assets/tailwind/application.css",
38
+ "-o #{output_dir}/panda-core.css"]
39
+
40
+ content_paths_count = 0
41
+ registered_modules.each do |gem_name, info|
42
+ gem_path = begin
43
+ gem_spec = Gem::Specification.find_by_name(gem_name)
44
+ gem_spec.full_gem_path
45
+ rescue Gem::LoadError
46
+ Rails.logger.error { "Gem '#{gem_name}' not installed; can't compile panda-core CSS for it" }
47
+ next
48
+ end
49
+
50
+ info[:paths].each do |asset_type, path|
51
+ command << "--content '#{gem_path}/#{path}'"
52
+ content_paths_count += 1
53
+ end
54
+ end
55
+
56
+ puts "📂 Scanning #{content_paths_count} content path(s) for Tailwind classes..."
57
+ puts ""
58
+
59
+ command << "--minify"
60
+ command << "--verbose"
61
+
62
+ system(command.join(" "))
63
+
64
+ puts "\n" + ("=" * 80)
65
+ if File.exist?("#{output_dir}/panda-core.css")
66
+ filesize = File.size("#{output_dir}/panda-core.css").to_fs(:human_size)
67
+ puts "✅ CSS compilation successful!"
68
+ puts ""
69
+ puts " Main file: #{output_dir}/panda-core.css (#{filesize})"
70
+
71
+ # Create versioned CSS file
72
+ versioned_css_file = "#{output_dir}/panda-core-#{core_gemspec.version}.css"
73
+ File.copy_stream("#{output_dir}/panda-core.css", versioned_css_file)
74
+ if File.exist?(versioned_css_file)
75
+ puts " Versioned copy: #{versioned_css_file}"
76
+ end
77
+ else
78
+ puts "❌ CSS compilation failed!"
79
+ end
80
+ puts "=" * 80
81
+ puts ""
82
+ end
83
+ end
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <browserconfig>
3
+ <msapplication>
4
+ <tile>
5
+ <square150x150logo src="/panda-cms-assets/mstile-150x150.png"/>
6
+ <TileColor>#b91d47</TileColor>
7
+ </tile>
8
+ </msapplication>
9
+ </browserconfig>
@@ -0,0 +1,61 @@
1
+ <?xml version="1.0" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
3
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
4
+ <svg version="1.0" xmlns="http://www.w3.org/2000/svg"
5
+ width="200.000000pt" height="200.000000pt" viewBox="0 0 200.000000 200.000000"
6
+ preserveAspectRatio="xMidYMid meet">
7
+ <metadata>
8
+ Created by potrace 1.14, written by Peter Selinger 2001-2017
9
+ </metadata>
10
+ <g transform="translate(0.000000,200.000000) scale(0.100000,-0.100000)"
11
+ fill="#000000" stroke="none">
12
+ <path d="M565 1803 c-42 -22 -65 -43 -83 -78 -42 -82 -32 -165 29 -226 36 -36
13
+ 39 -43 33 -75 l-6 -34 -28 42 c-49 77 -190 192 -210 172 -5 -5 -17 -38 -26
14
+ -74 -26 -102 -3 -238 55 -319 l19 -26 -61 3 c-67 4 -137 -12 -137 -31 0 -24
15
+ 56 -102 100 -139 46 -40 115 -68 166 -68 32 0 32 -1 23 -32 -21 -74 -7 -156
16
+ 37 -215 29 -39 33 -89 7 -78 -59 25 -73 27 -105 21 -24 -4 -47 -19 -67 -42
17
+ -26 -29 -31 -43 -31 -87 0 -63 25 -120 76 -176 84 -93 183 -120 272 -73 44 23
18
+ 78 26 156 16 35 -5 46 -11 46 -25 0 -19 44 -59 65 -59 7 0 23 8 36 19 18 14
19
+ 46 19 110 23 65 3 95 10 123 26 50 30 164 31 227 2 118 -53 240 5 305 144 15
20
+ 33 24 70 24 103 0 44 -5 58 -31 87 -45 51 -85 56 -171 21 -29 -12 -22 38 12
21
+ 87 67 96 53 232 -35 353 -13 19 -8 30 72 150 75 113 90 143 114 230 33 117 36
22
+ 145 13 145 -23 0 -185 -155 -208 -199 l-20 -36 -11 50 c-11 50 -11 50 22 81
23
+ 125 119 48 334 -120 334 -55 0 -79 -10 -122 -51 l-31 -29 -59 22 c-83 30 -208
24
+ 29 -288 -2 l-59 -22 -31 30 c-18 17 -45 36 -60 41 -41 16 -107 13 -142 -6z
25
+ m557 -83 c74 -23 159 -80 206 -139 42 -52 92 -158 92 -194 0 -33 -41 -161 -70
26
+ -217 -39 -77 -217 -136 -385 -127 -188 10 -313 97 -375 263 -19 53 -19 54 0
27
+ 116 73 236 308 367 532 298z m-437 -49 c3 -5 -4 -12 -14 -16 -11 -3 -32 -20
28
+ -46 -36 l-25 -31 0 36 c0 23 6 39 18 45 22 13 59 14 67 2z m698 -3 c16 -13 35
29
+ -68 22 -68 -16 0 -95 62 -90 71 9 13 48 11 68 -3z m66 -442 c-50 -81 -93 -145
30
+ -96 -142 -5 4 22 49 154 259 14 22 26 37 29 34 3 -2 -37 -70 -87 -151z m-171
31
+ -273 c-74 -117 -67 -107 -72 -102 -7 7 114 199 124 199 5 0 -18 -44 -52 -97z
32
+ m-378 -72 c63 -15 156 -13 218 3 29 7 52 9 52 4 0 -21 -21 -46 -44 -52 -13 -3
33
+ -38 -22 -56 -43 -30 -34 -32 -40 -27 -91 6 -54 5 -56 -53 -143 -33 -48 -69
34
+ -90 -80 -94 -11 -3 -25 -15 -30 -26 -11 -19 -11 -19 -53 2 -54 27 -144 94
35
+ -156 117 -8 16 -1 17 82 17 75 0 99 4 127 21 48 28 80 78 80 127 0 53 -56 111
36
+ -117 121 -40 7 -41 9 -31 32 7 15 17 23 27 20 9 -3 36 -10 61 -15z m174 -288
37
+ c-64 -99 -87 -133 -91 -129 -6 5 91 156 101 156 4 0 0 -12 -10 -27z m235 -45
38
+ c-32 -44 -90 -87 -148 -109 -30 -11 -58 -18 -62 -17 -5 2 13 37 39 78 l48 75
39
+ 71 0 71 0 -19 -27z m-864 -22 c67 -28 119 -138 83 -174 -34 -34 -124 11 -159
40
+ 79 -29 58 -16 96 39 108 1 1 18 -5 37 -13z m1199 -28 c13 -36 -24 -112 -66
41
+ -138 -46 -28 -82 -26 -107 6 l-21 27 27 49 c51 93 142 124 167 56z m-649 -93
42
+ c14 -13 25 -34 25 -47 0 -19 -3 -18 -18 12 -11 24 -28 39 -52 47 -34 11 -34
43
+ 12 -7 12 17 1 38 -9 52 -24z"/>
44
+ <path d="M765 1496 c-71 -31 -115 -122 -95 -198 23 -83 91 -119 158 -84 57 30
45
+ 122 119 122 168 0 37 -34 90 -71 110 -40 21 -72 22 -114 4z m121 -98 c19 -23
46
+ 19 -23 -2 -5 -11 9 -29 17 -39 17 -27 0 -55 -30 -55 -59 0 -31 8 -44 35 -59
47
+ 11 -6 15 -12 9 -12 -26 0 -57 37 -57 68 0 65 70 96 109 50z m-31 -26 c0 -18
48
+ -20 -15 -23 4 -3 10 1 15 10 12 7 -3 13 -10 13 -16z"/>
49
+ <path d="M1119 1487 c-94 -63 -83 -180 24 -258 75 -54 149 -32 182 56 31 80
50
+ -5 172 -79 206 -54 25 -86 24 -127 -4z m84 -79 c9 -7 20 -27 23 -45 5 -26 1
51
+ -37 -19 -57 -15 -14 -34 -26 -44 -26 -11 1 -6 6 14 15 36 15 48 42 34 78 -14
52
+ 35 -53 45 -89 22 l-27 -18 19 21 c21 24 63 29 89 10z m-23 -38 c0 -11 -4 -20
53
+ -10 -20 -5 0 -10 9 -10 20 0 11 5 20 10 20 6 0 10 -9 10 -20z"/>
54
+ <path d="M948 1249 c-14 -6 -29 -16 -32 -24 -6 -18 40 -75 61 -75 13 0 13 -3
55
+ 3 -15 -17 -21 -48 -19 -62 5 -17 26 -30 26 -26 -1 2 -12 15 -31 30 -42 23 -17
56
+ 31 -19 53 -9 19 9 32 9 47 1 28 -15 65 -3 84 27 13 19 14 28 5 37 -8 8 -15 6
57
+ -27 -11 -17 -24 -46 -29 -62 -9 -8 10 -4 16 19 26 57 25 61 72 7 90 -37 13
58
+ -64 13 -100 0z m42 -23 c0 -2 -9 -6 -20 -9 -11 -3 -20 -1 -20 4 0 5 9 9 20 9
59
+ 11 0 20 -2 20 -4z"/>
60
+ </g>
61
+ </svg>
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "",
3
+ "short_name": "",
4
+ "icons": [
5
+ {
6
+ "src": "/panda-cms-assets/favicons/android-chrome-192x192.png",
7
+ "sizes": "192x192",
8
+ "type": "image/png"
9
+ }
10
+ ],
11
+ "theme_color": "#ffffff",
12
+ "background_color": "#ffffff",
13
+ "display": "standalone"
14
+ }