caboose-cms 0.9.175 → 0.9.176

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/caboose/block_types_controller.rb +97 -4
  3. data/app/controllers/caboose/sites_controller.rb +19 -0
  4. data/app/controllers/caboose/theme_files_controller.rb +110 -0
  5. data/app/controllers/caboose/themes_controller.rb +27 -1
  6. data/app/models/caboose/block.rb +6 -2
  7. data/app/models/caboose/block_type.rb +9 -3
  8. data/app/models/caboose/block_type_site_membership.rb +1 -1
  9. data/app/models/caboose/core_plugin.rb +2 -1
  10. data/app/models/caboose/schema.rb +18 -3
  11. data/app/models/caboose/site.rb +10 -1
  12. data/app/models/caboose/theme.rb +2 -1
  13. data/app/models/caboose/theme_file.rb +1 -1
  14. data/app/models/caboose/user.rb +2 -1
  15. data/app/views/caboose/block_types/admin_edit.html.erb +11 -4
  16. data/app/views/caboose/block_types/admin_edit_btsm_css.html.erb +147 -0
  17. data/app/views/caboose/block_types/admin_edit_btsm_html.html.erb +119 -0
  18. data/app/views/caboose/block_types/admin_edit_render_function.html.erb +119 -0
  19. data/app/views/caboose/block_types/admin_edit_sass.html.erb +118 -0
  20. data/app/views/caboose/block_types/admin_error_log.html.erb +9 -0
  21. data/app/views/caboose/block_types/admin_index.html.erb +3 -1
  22. data/app/views/caboose/blocks/_render_function.html.erb +5 -1
  23. data/app/views/caboose/events/admin_edit.html.erb +1 -1
  24. data/app/views/caboose/pages/admin_edit_css.html.erb +117 -13
  25. data/app/views/caboose/pages/admin_edit_js.html.erb +114 -14
  26. data/app/views/caboose/sites/_admin_header.html.erb +6 -1
  27. data/app/views/caboose/sites/admin_edit_block_types.html.erb +35 -8
  28. data/app/views/caboose/sites/admin_edit_contact.html.erb +41 -0
  29. data/app/views/caboose/sites/admin_edit_css.html.erb +106 -20
  30. data/app/views/caboose/sites/admin_edit_js.html.erb +107 -20
  31. data/app/views/caboose/theme_files/admin_edit.html.erb +118 -0
  32. data/app/views/caboose/theme_files/admin_index.html.erb +44 -0
  33. data/app/views/caboose/themes/admin_edit.html.erb +6 -2
  34. data/app/views/caboose/themes/admin_sass.html.erb +240 -0
  35. data/lib/caboose/version.rb +1 -1
  36. metadata +12 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9c0a529a96546461dd9dd06c99957920ef45376e
4
- data.tar.gz: 448b88d7a143789b44d6666fd91b4186c0a63518
3
+ metadata.gz: 77b7f6fbe0c4a3b8cbd71873442bb59f127d72a9
4
+ data.tar.gz: 13160daa29cfe8226439a4259b54593e54336915
5
5
  SHA512:
6
- metadata.gz: 736542cd5eefc38277124a89d7b9a9142c1631046ae8e8db711a6c5c01eafc3ceff573396899d29b74fe812e6c950d6dbe9d30964c040074425f2dc140e52133
7
- data.tar.gz: b7783da727fe6fa769a035104cb7f51492df776d30034d2de5c54281fd7ac6810a66729c44156d138f59b9d45a0d7da29bb572d41552bb30eeeddd71ba7541da
6
+ metadata.gz: 0ffe7c11ff7ad97c1d4fdc78cd33dbdf5018ad9cc17d174aefbfe30604dada4d6654ccb5ba0cfd43a4415e827e138a595731b523dde7be5c7ec06dd1cf0938bb
7
+ data.tar.gz: 6bd5e9268af909139c26ef8452bd27020a28dd613d87e7ca80289932ddeecdd00c87c72c22e45845819457e823f667eccf6596dd1687eff33f811bab371f9f20
@@ -84,6 +84,52 @@ module Caboose
84
84
  @block_type = BlockType.find(params[:id])
85
85
  render :layout => 'caboose/admin'
86
86
  end
87
+
88
+ # @route GET /admin/block-types/:id/render-function
89
+ def admin_edit_render_function
90
+ return unless user_is_allowed('sites', 'edit')
91
+ @block_type = BlockType.find(params[:id])
92
+ render :layout => 'caboose/admin'
93
+ end
94
+
95
+ # @route PUT /admin/block-types/:id/render-function
96
+ def admin_update_render_function
97
+ return if !user_is_allowed('sites', 'edit')
98
+ resp = StdClass.new
99
+ @block_type = BlockType.find(params[:id])
100
+ code = params['code'].blank? ? '' : params['code'].gsub('<%==','<%= raw')
101
+ @block_type.render_function = code
102
+ @block_type.save
103
+ resp.success = true
104
+ resp.message = "Render function has been saved!"
105
+ render :json => resp
106
+ end
107
+
108
+ # @route GET /admin/block-types/:id/sass
109
+ def admin_edit_sass
110
+ return unless user_is_allowed('sites', 'edit')
111
+ @block_type = BlockType.find(params[:id])
112
+ render :layout => 'caboose/admin'
113
+ end
114
+
115
+ # @route PUT /admin/block-types/:id/sass
116
+ def admin_update_sass
117
+ return if !user_is_allowed('sites', 'edit')
118
+ resp = StdClass.new
119
+ @block_type = BlockType.find(params[:id])
120
+ @block_type.custom_sass = params['code']
121
+ @block_type.save
122
+ resp.success = true
123
+ resp.message = "Code has been saved!"
124
+ render :json => resp
125
+ end
126
+
127
+ # @route GET /admin/block-types/:id/errors
128
+ def admin_error_log
129
+ return unless user_is_allowed('sites', 'edit')
130
+ @block_type = BlockType.find(params[:id])
131
+ render :layout => 'caboose/admin'
132
+ end
87
133
 
88
134
  # @route POST /admin/block-types
89
135
  def admin_create
@@ -98,8 +144,9 @@ module Caboose
98
144
  :parent_id => params[:parent_id] ? params[:parent_id] : nil,
99
145
  :name => params[:name].downcase.gsub(' ', '_'),
100
146
  :description => params[:name],
101
- :field_type => params[:field_type],
102
- :allow_child_blocks => true
147
+ :field_type => params[:parent_id] ? 'text' : 'block',
148
+ :allow_child_blocks => false,
149
+ :icon => 'checkbox-unchecked'
103
150
  )
104
151
  bt.save
105
152
 
@@ -141,7 +188,7 @@ module Caboose
141
188
  when 'options_url' then bt.options_url = v
142
189
  when 'default_constrain' then bt.default_constrain = v
143
190
  when 'default_full_width' then bt.default_full_width = v
144
- when 'site_id' then bt.toggle_site(v[0], v[1])
191
+ when 'site_id' then resp.btsm_id = bt.toggle_site(v[0], v[1])
145
192
  end
146
193
  end
147
194
 
@@ -242,7 +289,53 @@ module Caboose
242
289
  bt.children.each do |bt2|
243
290
  admin_tree_options_helper(options, bt2, " - #{prefix}")
244
291
  end
245
- end
292
+ end
293
+
294
+ # @route GET /admin/block-type-site-memberships/:id/html
295
+ def admin_edit_btsm_html
296
+ return if !user_is_allowed_to('edit', 'sites')
297
+ @btsm = BlockTypeSiteMembership.find(params[:id])
298
+ if (@site.id != @btsm.site_id && !@site.is_master)
299
+ @error = "You are not allowed to edit this site."
300
+ render :file => 'caboose/extras/error' and return
301
+ end
302
+ render :layout => 'caboose/admin'
303
+ end
304
+
305
+ # @route PUT /admin/block-type-site-memberships/:id/html
306
+ def admin_update_btsm_html
307
+ return if !user_is_allowed_to('edit', 'sites')
308
+ resp = StdClass.new
309
+ @btsm = BlockTypeSiteMembership.find(params[:id])
310
+ @btsm.custom_html = params['code']
311
+ @btsm.save
312
+ resp.success = true
313
+ resp.message = "Code has been saved!"
314
+ render :json => resp
315
+ end
316
+
317
+ # @route GET /admin/block-type-site-memberships/:id/css
318
+ def admin_edit_btsm_css
319
+ return if !user_is_allowed_to('edit', 'sites')
320
+ @btsm = BlockTypeSiteMembership.find(params[:id])
321
+ if (@site.id != @btsm.site_id && !@site.is_master)
322
+ @error = "You are not allowed to edit this site."
323
+ render :file => 'caboose/extras/error' and return
324
+ end
325
+ render :layout => 'caboose/admin'
326
+ end
327
+
328
+ # @route PUT /admin/block-type-site-memberships/:id/css
329
+ def admin_update_btsm_css
330
+ return if !user_is_allowed_to('edit', 'sites')
331
+ resp = StdClass.new
332
+ @btsm = BlockTypeSiteMembership.find(params[:id])
333
+ @btsm.custom_css = params['code']
334
+ @btsm.save
335
+ resp.success = true
336
+ resp.message = "Code has been saved!"
337
+ render :json => resp
338
+ end
246
339
 
247
340
  #===========================================================================
248
341
  # Public Repo Actions
@@ -111,6 +111,16 @@ module Caboose
111
111
  end
112
112
  @site = Site.find(params[:id])
113
113
  end
114
+
115
+ # @route GET /admin/sites/:id/contact
116
+ def admin_edit_contact
117
+ return if !user_is_allowed('sites', 'edit')
118
+ if (@site.id.to_s != params[:id] && !@site.is_master)
119
+ @error = "You are not allowed to edit this site."
120
+ render :file => 'caboose/extras/error' and return
121
+ end
122
+ @site = Site.find(params[:id])
123
+ end
114
124
 
115
125
  # @route GET /admin/sites/:id/delete
116
126
  def admin_delete_form
@@ -186,6 +196,15 @@ module Caboose
186
196
  when 'allow_self_registration' then site.allow_self_registration = value
187
197
  when 'theme_color' then site.theme_color = value
188
198
  when 'assets_url' then site.assets_url = value
199
+ when 'main_phone' then site.main_phone = value
200
+ when 'alt_phone' then site.alt_phone = value
201
+ when 'address1' then site.address1 = value
202
+ when 'address2' then site.address2 = value
203
+ when 'city' then site.city = value
204
+ when 'state' then site.state = value
205
+ when 'zip' then site.zip = value
206
+ when 'fax' then site.fax = value
207
+ when 'contact_email' then site.contact_email = value
189
208
  end
190
209
  end
191
210
  resp.success = save && site.save
@@ -0,0 +1,110 @@
1
+ module Caboose
2
+ class ThemeFilesController < ApplicationController
3
+ layout 'caboose/admin'
4
+
5
+ # @route GET /admin/theme-files
6
+ def admin_index
7
+ return unless (user_is_allowed_to 'view', 'theme_files')
8
+ end
9
+
10
+ # @route POST /admin/theme-files
11
+ def admin_add
12
+ return unless (user_is_allowed_to 'edit', 'theme_files')
13
+ resp = Caboose::StdClass.new
14
+ c = Caboose::ThemeFile.new
15
+ c.nice_name = params[:nice_name]
16
+ c.save
17
+ resp.redirect = "/admin/theme-files/#{c.id}"
18
+ render :json => resp
19
+ end
20
+
21
+ # @route GET /admin/theme-files/json
22
+ def admin_json
23
+ render :json => false and return if !user_is_allowed_to 'view', 'theme_files'
24
+ pager = Caboose::Pager.new(params, {
25
+ 'nice_name_like' => ''
26
+ }, {
27
+ 'model' => 'Caboose::ThemeFile',
28
+ 'sort' => 'nice_name',
29
+ 'desc' => 'false',
30
+ 'base_url' => '/admin/theme-files',
31
+ 'items_per_page' => 50
32
+ })
33
+ render :json => {
34
+ :pager => pager,
35
+ :models => pager.items
36
+ }
37
+ end
38
+
39
+ # @route GET /admin/theme-files/:id/json
40
+ def admin_json_single
41
+ render :json => false and return if !user_is_allowed_to 'edit', 'theme_files'
42
+ prop = Caboose::ThemeFile.find(params[:id])
43
+ render :json => prop
44
+ end
45
+
46
+ # @route GET /admin/theme-files/:id
47
+ def admin_edit
48
+ if !user_is_allowed_to 'edit', 'theme_files'
49
+ Caboose.log("invalid permissions")
50
+ else
51
+ @themefile = Caboose::ThemeFile.where(:id => params[:id]).first
52
+ end
53
+ end
54
+
55
+ # @route PUT /admin/theme-files/:id/sass
56
+ def admin_update_sass
57
+ return if !user_is_allowed('edit', 'theme_files')
58
+ resp = StdClass.new
59
+ @themefile = ThemeFile.find(params[:id])
60
+ @themefile.code = params['code']
61
+ @themefile.save
62
+ resp.success = true
63
+ resp.message = "Code has been saved!"
64
+ render :json => resp
65
+ end
66
+
67
+ # @route PUT /admin/theme-files/:id
68
+ def admin_update
69
+ return unless (user_is_allowed_to 'edit', 'theme_files')
70
+ resp = Caboose::StdClass.new
71
+ theme_files = params[:id] == 'bulk' ? params[:model_ids].collect{ |rid| Caboose::ThemeFile.find(rid) } : [Caboose::ThemeFile.find(params[:id])]
72
+ user = logged_in_user
73
+ if user
74
+ params.each do |k,v|
75
+ case k
76
+ when "filename" then theme_files.each { |r| r.filename = v }
77
+ when "nice_name" then theme_files.each { |r| r.nice_name = v }
78
+ when "default_included" then theme_files.each { |r| r.default_included = v }
79
+ end
80
+ end
81
+ theme_files.each do |r|
82
+ r.save
83
+ end
84
+ resp.success = true
85
+ end
86
+ render :json => resp
87
+ end
88
+
89
+ # @route DELETE /admin/theme-files/bulk
90
+ def admin_bulk_delete
91
+ return unless user_is_allowed_to 'delete', 'theme_files'
92
+ params[:model_ids].each do |rc_id|
93
+ prop = Caboose::ThemeFile.where(:id => rc_id).first
94
+ prop.destroy
95
+ end
96
+ resp = Caboose::StdClass.new('success' => true)
97
+ render :json => resp
98
+ end
99
+
100
+ # @route DELETE /admin/theme-files/:id
101
+ def admin_delete
102
+ return unless user_is_allowed_to 'delete', 'theme_files'
103
+ prop = Caboose::ThemeFile.find(params[:id])
104
+ resp = Caboose::StdClass.new('redirect' => "/admin/theme-files")
105
+ prop.destroy
106
+ render :json => resp
107
+ end
108
+
109
+ end
110
+ end
@@ -87,11 +87,19 @@ module Caboose
87
87
  render :json => resp
88
88
  end
89
89
 
90
- # @route GET /admin/themes/:id/compile
90
+ # @route PUT /admin/themes/:id/compile
91
91
  def admin_compile
92
92
  return if !user_is_allowed('theme', 'edit')
93
93
  resp = StdClass.new
94
94
  theme = @site.theme
95
+ if params['code']
96
+ theme.custom_sass = params['code']
97
+ theme.save
98
+ elsif params['btsm_id']
99
+ btsm = Caboose::BlockTypeSiteMembership.find(params['btsm_id'])
100
+ btsm.custom_css = params['custom_css']
101
+ btsm.save
102
+ end
95
103
  theme.compile(@site.id) if Rails.env.development?
96
104
  theme.delay(:queue => 'general', :priority => 5).compile(@site.id) if Rails.env.production?
97
105
  resp.success = true
@@ -99,6 +107,24 @@ module Caboose
99
107
  render :json => resp
100
108
  end
101
109
 
110
+ # @route GET /admin/theme/sass
111
+ def admin_sass
112
+ return if !user_is_allowed('theme', 'edit')
113
+ @theme = @site.theme
114
+ end
115
+
116
+ # @route PUT /admin/theme/sass
117
+ def admin_update_sass
118
+ return if !user_is_allowed('theme', 'edit')
119
+ resp = StdClass.new
120
+ @theme = @site.theme
121
+ @theme.custom_sass = params['code']
122
+ @theme.save
123
+ resp.success = true
124
+ resp.message = "Theme has been saved!"
125
+ render :json => resp
126
+ end
127
+
102
128
  # @route POST /admin/themes/:id/default-banner-image
103
129
  def admin_update_default_banner_image
104
130
  return if !user_is_allowed('theme', 'edit')
@@ -213,13 +213,17 @@ class Caboose::Block < ActiveRecord::Base
213
213
  view = options2[:view]
214
214
  view = ActionView::Base.new(ActionController::Base.view_paths) if view.nil?
215
215
 
216
- if block.block_type.use_render_function && block.block_type.render_function
216
+ if (block.block_type.use_render_function && block.block_type.render_function) || Caboose::BlockTypeSiteMembership.where(:site_id => options2[:site].id, :block_type_id => block.block_type.id).where('custom_html IS NOT NULL and custom_html != ?', '').exists?
217
217
  begin
218
218
  str = view.render(:partial => "caboose/blocks/render_function", :locals => options2)
219
219
  rescue Exception => ex
220
220
  msg = block ? (block.block_type ? "Error with #{block.block_type.name} block (block_type_id #{block.block_type.id}, block_id #{block.id})\n" : "Error with block (block_id #{block.id})\n") : ''
221
221
  Caboose.log("#{msg}#{ex.message}\n#{ex.backtrace.join("\n")}")
222
222
  str = "<p class='note error'>#{msg}</p>"
223
+ if block && block.block_type
224
+ block.block_type.latest_error = "#{msg}#{ex.message}\n#{ex.backtrace.join("\n")}"
225
+ block.block_type.save
226
+ end
223
227
  end
224
228
  else
225
229
 
@@ -233,7 +237,7 @@ class Caboose::Block < ActiveRecord::Base
233
237
  end
234
238
 
235
239
  #begin str = view.render(:partial => "../../sites/#{site.name}/blocks/#{full_name}", :locals => options2)
236
- #rescue ActionView::MissingTemplate => ex
240
+ #rescue ActionView::MissingTemplate => ex
237
241
  # begin str = view.render(:partial => "../../sites/#{site.name}/blocks/#{block.block_type.name}", :locals => options2)
238
242
  # rescue ActionView::MissingTemplate => ex
239
243
  # begin str = view.render(:partial => "../../sites/#{site.name}/blocks/#{block.block_type.field_type}", :locals => options2)
@@ -29,6 +29,8 @@ class Caboose::BlockType < ActiveRecord::Base
29
29
  :options_url,
30
30
  :icon,
31
31
  :default_constrain,
32
+ :custom_sass,
33
+ :latest_error,
32
34
  :share, # Whether or not to share the block type in the existing block store.
33
35
  :downloaded # Whether the full block type has been download or just the name and description.
34
36
 
@@ -112,9 +114,9 @@ class Caboose::BlockType < ActiveRecord::Base
112
114
 
113
115
  def toggle_site(site_id, value)
114
116
  if value.to_i > 0
115
- self.add_to_site(site_id)
117
+ return self.add_to_site(site_id)
116
118
  else
117
- self.remove_from_site(site_id)
119
+ return self.remove_from_site(site_id)
118
120
  end
119
121
  end
120
122
 
@@ -126,7 +128,11 @@ class Caboose::BlockType < ActiveRecord::Base
126
128
  end
127
129
  else
128
130
  if !Caboose::BlockTypeSiteMembership.where(:block_type_id => self.id, :site_id => site_id.to_i).exists?
129
- Caboose::BlockTypeSiteMembership.create(:block_type_id => self.id, :site_id => site_id.to_i)
131
+ btsm = Caboose::BlockTypeSiteMembership.new
132
+ btsm.block_type_id = self.id
133
+ btsm.site_id = site_id.to_i
134
+ btsm.save
135
+ return btsm.id
130
136
  end
131
137
  end
132
138
  end
@@ -2,5 +2,5 @@ class Caboose::BlockTypeSiteMembership < ActiveRecord::Base
2
2
  self.table_name = "block_type_site_memberships"
3
3
  belongs_to :site
4
4
  belongs_to :block_type
5
- attr_accessible :id, :site_id, :block_type_id
5
+ attr_accessible :id, :site_id, :block_type_id, :custom_css, :custom_html
6
6
  end
@@ -15,7 +15,8 @@ class Caboose::CorePlugin < Caboose::CaboosePlugin
15
15
  nav << item if item['children'].count > 0
16
16
 
17
17
  item = { 'id' => 'core', 'text' => 'Settings', 'children' => [] }
18
- item['children'] << { 'id' => 'settings' , 'icon' => 'settings', 'text' => 'Site Settings' , 'href' => "/admin/sites/#{site.id}" , 'modal' => false } if user.is_super_admin?
18
+ item['children'] << { 'id' => 'settings' , 'icon' => 'settings', 'text' => 'Site Settings' , 'href' => "/admin/sites/#{site.id}" , 'modal' => false } if user.is_super_admin?
19
+ item['children'] << { 'id' => 'theme-files' , 'icon' => 'custom', 'text' => 'Theme Files' , 'href' => '/admin/theme-files' , 'modal' => false } if user.is_super_admin? && site.is_master == true
19
20
  item['children'] << { 'id' => 'blocktypes' , 'text' => 'Block Types' , 'href' => '/admin/block-types' , 'modal' => false } if user.is_allowed('blocktypes' , 'view') && site.is_master == true
20
21
  item['children'] << { 'icon' => 'star', 'id' => 'fonts' , 'text' => 'Fonts' , 'href' => '/admin/fonts' , 'modal' => false } if user.is_allowed('fonts' , 'view') && site.use_fonts == true
21
22
  item['children'] << { 'id' => 'redirects' , 'text' => 'Permanent Redirects' , 'href' => '/admin/redirects' , 'modal' => false } if user.is_allowed('redirects' , 'view')
@@ -197,7 +197,9 @@ class Caboose::Schema < Caboose::Utilities::Schema
197
197
  [ :fixed_placeholder , :boolean ],
198
198
  [ :options , :text ],
199
199
  [ :options_function , :text ],
200
+ [ :custom_sass , :text ],
200
201
  [ :options_url , :string ],
202
+ [ :latest_error , :text ],
201
203
  [ :default_constrain , :boolean , { :default => false }],
202
204
  [ :default_full_width , :boolean , { :default => false }],
203
205
  [ :share , :boolean , { :default => true }],
@@ -205,7 +207,9 @@ class Caboose::Schema < Caboose::Utilities::Schema
205
207
  ],
206
208
  Caboose::BlockTypeSiteMembership => [
207
209
  [ :site_id , :integer ],
208
- [ :block_type_id , :integer ]
210
+ [ :block_type_id , :integer ],
211
+ [ :custom_css, :text ],
212
+ [ :custom_html, :text ]
209
213
  ],
210
214
  Caboose::BlockTypeCategory => [
211
215
  [ :parent_id , :integer ],
@@ -810,7 +814,16 @@ class Caboose::Schema < Caboose::Utilities::Schema
810
814
  [ :theme_id, :integer ],
811
815
  [ :favicon, :attachment ],
812
816
  [ :cl_logo_version , :string ],
813
- [ :cl_favicon_version , :string ]
817
+ [ :cl_favicon_version , :string ],
818
+ [ :main_phone, :string ],
819
+ [ :alt_phone, :string ],
820
+ [ :address1, :string ],
821
+ [ :address2, :string ],
822
+ [ :city, :string ],
823
+ [ :state, :string ],
824
+ [ :zip, :string ],
825
+ [ :fax, :string ],
826
+ [ :contact_email, :string ]
814
827
  ],
815
828
  Caboose::SiteMembership => [
816
829
  [ :site_id , :integer ],
@@ -985,11 +998,13 @@ class Caboose::Schema < Caboose::Utilities::Schema
985
998
  [ :footer_hover_color, :string ],
986
999
  [ :actual_footer_height, :string ],
987
1000
  [ :actual_banner_height, :string ],
988
- [ :dropdown_nav_padding, :string ]
1001
+ [ :dropdown_nav_padding, :string ],
1002
+ [ :custom_sass, :text ]
989
1003
  ],
990
1004
  Caboose::ThemeFile => [
991
1005
  [ :filename, :string ],
992
1006
  [ :nice_name, :string ],
1007
+ [ :code, :text ],
993
1008
  [ :default_included, :boolean , { :default => false }]
994
1009
  ],
995
1010
  Caboose::ThemeFileMembership => [