proscenium 0.14.0-x86_64-darwin → 0.15.0.beta.1-x86_64-darwin

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.
@@ -1,18 +1,70 @@
1
1
  window.Proscenium = window.Proscenium || { lazyScripts: {} };
2
+ const pathAttribute = "data-proscenium-component-path";
2
3
 
4
+ // Find lazyscripts JSON already in the DOM.
3
5
  const element = document.querySelector("#prosceniumLazyScripts");
4
6
  if (element) {
5
- const scripts = JSON.parse(element.text);
6
7
  window.Proscenium.lazyScripts = {
7
8
  ...window.Proscenium.lazyScripts,
8
- ...scripts,
9
+ ...JSON.parse(element.text),
9
10
  };
10
11
  }
11
12
 
12
- const elements = document.querySelectorAll("[data-proscenium-component-path]");
13
+ // Find components already in the DOM.
14
+ const elements = document.querySelectorAll(`[${pathAttribute}]`);
13
15
  elements.length > 0 && init(elements);
14
16
 
15
- function init() {
17
+ new MutationObserver((mutationsList) => {
18
+ for (const { addedNodes } of mutationsList) {
19
+ for (const ele of addedNodes) {
20
+ if (ele.tagName === "SCRIPT" && ele.id === "prosceniumLazyScripts") {
21
+ window.Proscenium.lazyScripts = {
22
+ ...window.Proscenium.lazyScripts,
23
+ ...JSON.parse(ele.text),
24
+ };
25
+ } else if (ele.matches(`[${pathAttribute}]`)) {
26
+ init([ele]);
27
+ }
28
+ }
29
+ }
30
+ }).observe(document, {
31
+ subtree: true,
32
+ childList: true,
33
+ });
34
+
35
+ function init(elements) {
36
+ Array.from(elements, (element) => {
37
+ const path = element.dataset.prosceniumComponentPath;
38
+ const isLazy = "prosceniumComponentLazy" in element.dataset;
39
+ const props = JSON.parse(element.dataset.prosceniumComponentProps);
40
+
41
+ if (proscenium.env.RAILS_ENV === "development") {
42
+ console.groupCollapsed(
43
+ `[proscenium/react/manager] ${isLazy ? "💤" : "⚡️"} %o`,
44
+ path
45
+ );
46
+ console.log("element: %o", element);
47
+ console.log("props: %o", props);
48
+ console.groupEnd();
49
+ }
50
+
51
+ if (isLazy) {
52
+ const observer = new IntersectionObserver((entries) => {
53
+ entries.forEach((entry) => {
54
+ if (entry.isIntersecting) {
55
+ observer.unobserve(element);
56
+
57
+ mount(element, path, props);
58
+ }
59
+ });
60
+ });
61
+
62
+ observer.observe(element);
63
+ } else {
64
+ mount(element, path, props);
65
+ }
66
+ });
67
+
16
68
  /**
17
69
  * Mounts component located at `path`, into the DOM `element`.
18
70
  *
@@ -66,36 +118,4 @@ function init() {
66
118
  console.error("[proscenium/react/manager] %o - %o", path, error);
67
119
  });
68
120
  }
69
-
70
- Array.from(elements, (element) => {
71
- const path = element.dataset.prosceniumComponentPath;
72
- const isLazy = "prosceniumComponentLazy" in element.dataset;
73
- const props = JSON.parse(element.dataset.prosceniumComponentProps);
74
-
75
- if (proscenium.env.RAILS_ENV === "development") {
76
- console.groupCollapsed(
77
- `[proscenium/react/manager] ${isLazy ? "💤" : "⚡️"} %o`,
78
- path
79
- );
80
- console.log("element: %o", element);
81
- console.log("props: %o", props);
82
- console.groupEnd();
83
- }
84
-
85
- if (isLazy) {
86
- const observer = new IntersectionObserver((entries) => {
87
- entries.forEach((entry) => {
88
- if (entry.isIntersecting) {
89
- observer.unobserve(element);
90
-
91
- mount(element, path, props);
92
- }
93
- });
94
- });
95
-
96
- observer.observe(element);
97
- } else {
98
- mount(element, path, props);
99
- }
100
- });
101
121
  }
@@ -10,12 +10,24 @@ module Proscenium
10
10
  end
11
11
  end
12
12
 
13
- def build(event)
13
+ def build_to_path(event)
14
14
  path = event.payload[:identifier]
15
+ cached = event.payload[:cached] ? ' | Cached!' : ''
15
16
  path = CGI.unescape(path) if path.start_with?(/https?%3A%2F%2F/)
16
17
 
17
18
  info do
18
- message = +"[Proscenium] Building #{path}"
19
+ message = +" #{color('[Proscenium]', nil, bold: true)} Building (to path) #{path}"
20
+ message << " (Duration: #{event.duration.round(1)}ms | " \
21
+ "Allocations: #{event.allocations}#{cached})"
22
+ end
23
+ end
24
+
25
+ def build_to_string(event)
26
+ path = event.payload[:identifier]
27
+ path = CGI.unescape(path) if path.start_with?(/https?%3A%2F%2F/)
28
+
29
+ info do
30
+ message = +" #{color('[Proscenium]', nil, bold: true)} Building #{path}"
19
31
  message << " (Duration: #{event.duration.round(1)}ms | Allocations: #{event.allocations})"
20
32
  end
21
33
  end
@@ -20,8 +20,8 @@ module Proscenium
20
20
  end
21
21
 
22
22
  def attempt
23
- render_response Builder.build(path_to_build, root: Rails.root.to_s,
24
- base_url: @request.base_url)
23
+ render_response Builder.build_to_string(path_to_build, root: Rails.root.to_s,
24
+ base_url: @request.base_url)
25
25
  rescue Builder::CompileError => e
26
26
  raise self.class::CompileError, { file: @request.fullpath, detail: e.message }, caller
27
27
  end
@@ -3,42 +3,52 @@
3
3
  module Proscenium
4
4
  # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
5
5
  module Monkey
6
- module DebugView
7
- def initialize(assigns)
8
- paths = [RESCUES_TEMPLATE_PATH, Rails.root.join('lib', 'templates').to_s]
9
- lookup_context = ActionView::LookupContext.new(paths)
10
- super(lookup_context, assigns, nil)
11
- end
12
- end
13
-
14
6
  module TemplateRenderer
15
7
  private
16
8
 
17
- def render_template(view, template, layout_name, locals)
18
- return super unless Proscenium.config.side_load
9
+ def render_template(view, template, layout_name, locals) # rubocop:disable Metrics/*
10
+ result = super
11
+ return result if !view.controller || !Proscenium.config.side_load
19
12
 
20
- layout = find_layout(layout_name, locals.keys, [formats.first])
21
13
  renderable = template.instance_variable_get(:@renderable)
22
14
 
23
- if Object.const_defined?(:ViewComponent) &&
24
- template.is_a?(ActionView::Template::Renderable) &&
25
- renderable.class < ::ViewComponent::Base && renderable.class.format == :html
26
- # Side load controller rendered ViewComponent
27
- Importer.sideload "app/views/#{layout.virtual_path}" if layout
28
- Importer.sideload "app/views/#{renderable.virtual_path}"
29
- elsif template.respond_to?(:virtual_path) &&
30
- template.respond_to?(:type) && template.type == :html
31
- Importer.sideload "app/views/#{layout.virtual_path}" if layout
32
-
33
- # Try side loading the variant template
34
- if template.respond_to?(:variant) && template.variant
35
- Importer.sideload "app/views/#{template.virtual_path}+#{template.variant}"
36
- end
37
-
38
- Importer.sideload "app/views/#{template.virtual_path}"
15
+ to_sideload = if Object.const_defined?(:ViewComponent) &&
16
+ template.is_a?(ActionView::Template::Renderable) &&
17
+ renderable.class < ::ViewComponent::Base &&
18
+ renderable.class.format == :html
19
+ renderable
20
+ elsif template.respond_to?(:virtual_path) &&
21
+ template.respond_to?(:type) && template.type == :html
22
+ template
23
+ end
24
+ if to_sideload
25
+ options = view.controller.sideload_assets_options
26
+ layout = find_layout(layout_name, locals.keys, [formats.first])
27
+ sideload_template_assets layout, view.controller, options if layout
28
+ sideload_template_assets to_sideload, view.controller, options
29
+ end
30
+
31
+ result
32
+ end
33
+
34
+ def sideload_template_assets(tpl, controller, options)
35
+ options = {} if options.nil?
36
+ options = { js: options, css: options } unless options.is_a?(Hash)
37
+
38
+ if tpl.instance_variable_defined?(:@sideload_assets_options)
39
+ tpl_options = tpl.instance_variable_get(:@sideload_assets_options)
40
+ options = case tpl_options
41
+ when Hash then options.deep_merge(tpl_options)
42
+ else
43
+ { js: tpl_options, css: tpl_options }
44
+ end
45
+ end
46
+
47
+ %i[css js].each do |k|
48
+ options[k] = controller.instance_eval(&options[k]) if options[k].is_a?(Proc)
39
49
  end
40
50
 
41
- super
51
+ Importer.sideload "app/views/#{tpl.virtual_path}", **options
42
52
  end
43
53
  end
44
54
 
@@ -46,13 +56,38 @@ module Proscenium
46
56
  private
47
57
 
48
58
  def render_partial_template(view, locals, template, layout, block)
49
- if Proscenium.config.side_load && template.respond_to?(:virtual_path) &&
59
+ result = super
60
+
61
+ return result if !view.controller || !Proscenium.config.side_load
62
+
63
+ if template.respond_to?(:virtual_path) &&
50
64
  template.respond_to?(:type) && template.type == :html
51
- Importer.sideload "app/views/#{layout.virtual_path}" if layout
52
- Importer.sideload "app/views/#{template.virtual_path}"
65
+ options = view.controller.sideload_assets_options
66
+ sideload_template_assets layout, options if layout
67
+ sideload_template_assets template, options
68
+ end
69
+
70
+ result
71
+ end
72
+
73
+ def sideload_template_assets(tpl, options)
74
+ options = {} if options.nil?
75
+ options = { js: options, css: options } unless options.is_a?(Hash)
76
+
77
+ if tpl.instance_variable_defined?(:@sideload_assets_options)
78
+ tpl_options = tpl.instance_variable_get(:@sideload_assets_options)
79
+ options = if tpl_options.is_a?(Hash)
80
+ options.deep_merge tpl_options
81
+ else
82
+ { js: tpl_options, css: tpl_options }
83
+ end
84
+ end
85
+
86
+ %i[css js].each do |k|
87
+ options[k] = controller.instance_eval(&options[k]) if options[k].is_a?(Proc)
53
88
  end
54
89
 
55
- super
90
+ Importer.sideload "app/views/#{tpl.virtual_path}", **options
56
91
  end
57
92
  end
58
93
  end
@@ -1,96 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Proscenium::Phlex::AssetInclusions
4
- include Phlex::Rails::Helpers::ContentFor
5
- include Phlex::Rails::Helpers::StyleSheetPath
6
- include Phlex::Rails::Helpers::JavaScriptPath
7
-
8
4
  def include_stylesheets
9
5
  comment { '[PROSCENIUM_STYLESHEETS]' }
10
6
  end
11
7
 
12
- def include_javascripts(defer_lazy_scripts: false)
13
- comment { '[PROSCENIUM_JAVASCRIPTS]' }
14
- !defer_lazy_scripts && include_lazy_javascripts
15
- end
16
-
17
- def include_lazy_javascripts
8
+ def include_javascripts
18
9
  comment { '[PROSCENIUM_LAZY_SCRIPTS]' }
10
+ comment { '[PROSCENIUM_JAVASCRIPTS]' }
19
11
  end
20
12
 
21
- def include_assets(defer_lazy_scripts: false)
13
+ def include_assets
22
14
  include_stylesheets
23
- include_javascripts(defer_lazy_scripts: defer_lazy_scripts)
24
- end
25
-
26
- def after_template
27
- super
28
-
29
- @_buffer.gsub! '<!-- [PROSCENIUM_STYLESHEETS] -->', capture_stylesheets!
30
- @_buffer.gsub! '<!-- [PROSCENIUM_JAVASCRIPTS] -->', capture_javascripts!
31
-
32
- if content_for?(:proscenium_lazy_scripts)
33
- flush
34
- @_buffer.gsub!('<!-- [PROSCENIUM_LAZY_SCRIPTS] -->', capture do
35
- content_for(:proscenium_lazy_scripts)
36
- end)
37
- else
38
- @_buffer.gsub! '<!-- [PROSCENIUM_LAZY_SCRIPTS] -->', ''
39
- end
40
- end
41
-
42
- private
43
-
44
- def capture_stylesheets!
45
- capture do
46
- Proscenium::Importer.each_stylesheet(delete: true) do |path, _path_options|
47
- link rel: 'stylesheet', href: stylesheet_path(path, extname: false)
48
- end
49
- end
50
- end
51
-
52
- def capture_javascripts! # rubocop:disable Metrics/*
53
- unless Rails.application.config.proscenium.code_splitting &&
54
- Proscenium::Importer.multiple_js_imported?
55
- return capture do
56
- Proscenium::Importer.each_javascript(delete: true) do |path, _|
57
- script(src: javascript_path(path, extname: false), type: :module)
58
- end
59
- end
60
- end
61
-
62
- imports = Proscenium::Importer.imported.dup
63
- paths_to_build = []
64
- Proscenium::Importer.each_javascript(delete: true) do |x, _|
65
- paths_to_build << x.delete_prefix('/')
66
- end
67
-
68
- result = Proscenium::Builder.build(paths_to_build.join(';'), base_url: helpers.request.base_url)
69
-
70
- # Remove the react components from the results, so they are not side loaded. Instead they
71
- # are lazy loaded by the component manager.
72
-
73
- capture do
74
- scripts = {}
75
- result.split(';').each do |x|
76
- inpath, outpath = x.split('::')
77
- inpath.prepend '/'
78
- outpath.delete_prefix! 'public'
79
-
80
- next unless imports.key?(inpath)
81
-
82
- if (import = imports[inpath]).delete(:lazy)
83
- scripts[inpath] = import.merge(outpath: outpath)
84
- else
85
- script(src: javascript_path(outpath, extname: false), type: :module)
86
- end
87
- end
88
-
89
- content_for :proscenium_lazy_scripts do
90
- script type: 'application/json', id: 'prosceniumLazyScripts' do
91
- unsafe_raw scripts.to_json
92
- end
93
- end
94
- end
15
+ include_javascripts
95
16
  end
96
17
  end
@@ -12,15 +12,19 @@ module Proscenium
12
12
 
13
13
  include Proscenium::SourcePath
14
14
  include CssModules
15
+ include AssetInclusions
15
16
 
16
17
  module Sideload
17
18
  def before_template
18
- Proscenium::SideLoad.sideload_inheritance_chain self
19
+ Proscenium::SideLoad.sideload_inheritance_chain self,
20
+ helpers.controller.sideload_assets_options
19
21
 
20
22
  super
21
23
  end
22
24
  end
23
25
 
26
+ class_attribute :sideload_assets_options
27
+
24
28
  class << self
25
29
  attr_accessor :abstract_class
26
30
 
@@ -29,6 +33,10 @@ module Proscenium
29
33
 
30
34
  super
31
35
  end
36
+
37
+ def sideload_assets(value)
38
+ self.sideload_assets_options = value
39
+ end
32
40
  end
33
41
  end
34
42
  end
@@ -6,12 +6,6 @@ require 'proscenium/log_subscriber'
6
6
  ENV['RAILS_ENV'] = Rails.env
7
7
 
8
8
  module Proscenium
9
- class << self
10
- def config
11
- @config ||= Railtie.config.proscenium
12
- end
13
- end
14
-
15
9
  class Railtie < ::Rails::Engine
16
10
  isolate_namespace Proscenium
17
11
 
@@ -20,6 +14,14 @@ module Proscenium
20
14
  config.proscenium.side_load = true
21
15
  config.proscenium.code_splitting = true
22
16
 
17
+ # Cache asset paths when building to path. Enabled by default in production.
18
+ # @see Proscenium::Builder#build_to_path
19
+ config.proscenium.cache = if Rails.env.local?
20
+ ActiveSupport::Cache::NullStore.new
21
+ else
22
+ ActiveSupport::Cache::MemoryStore.new
23
+ end
24
+
23
25
  # TODO: implement!
24
26
  config.proscenium.cache_query_string = Rails.env.production? && ENV.fetch('REVISION', nil)
25
27
  config.proscenium.cache_max_age = 2_592_000 # 30 days
@@ -45,6 +47,12 @@ module Proscenium
45
47
  'Proscenium::Builder::BuildError' => 'build_error'
46
48
  }
47
49
 
50
+ config.after_initialize do |_app|
51
+ ActiveSupport.on_load(:action_view) do
52
+ include Proscenium::Helper
53
+ end
54
+ end
55
+
48
56
  initializer 'proscenium.debugging' do
49
57
  if Rails.gem_version >= Gem::Version.new('7.1.0')
50
58
  tpl_path = root.join('lib', 'proscenium', 'templates').to_s
@@ -58,20 +66,17 @@ module Proscenium
58
66
  app.middleware.insert_after ActionDispatch::Static, Rack::ConditionalGet
59
67
  end
60
68
 
61
- initializer 'proscenium.monkey_patches' do
62
- ActiveSupport.on_load(:action_view) do
63
- ActionView::TemplateRenderer.prepend Monkey::TemplateRenderer
64
- ActionView::PartialRenderer.prepend Monkey::PartialRenderer
69
+ initializer 'proscenium.sideloading' do
70
+ ActiveSupport.on_load(:action_controller) do
71
+ ActionController::Base.include EnsureLoaded
72
+ ActionController::Base.include SideLoad::Controller
65
73
  end
66
74
  end
67
75
 
68
- initializer 'proscenium.helper' do
76
+ initializer 'proscenium.monkey_patches' do
69
77
  ActiveSupport.on_load(:action_view) do
70
- ActionView::Base.include Helper
71
- end
72
-
73
- ActiveSupport.on_load(:action_controller) do
74
- ActionController::Base.include EnsureLoaded
78
+ ActionView::TemplateRenderer.prepend Monkey::TemplateRenderer
79
+ ActionView::PartialRenderer.prepend Monkey::PartialRenderer
75
80
  end
76
81
  end
77
82
  end
@@ -44,9 +44,9 @@ module Proscenium
44
44
  end
45
45
 
46
46
  class_methods do
47
- def sideload
48
- Importer.import manager
49
- Importer.sideload source_path, lazy: true
47
+ def sideload(options)
48
+ Importer.import manager, **options, js: { type: 'module' }
49
+ Importer.sideload source_path, lazy: true, **options
50
50
  end
51
51
  end
52
52
 
@@ -2,21 +2,135 @@
2
2
 
3
3
  module Proscenium
4
4
  class SideLoad
5
+ module Controller
6
+ def self.included(child)
7
+ child.class_eval do
8
+ class_attribute :sideload_assets_options
9
+ child.extend ClassMethods
10
+
11
+ append_after_action :capture_and_replace_proscenium_stylesheets,
12
+ :capture_and_replace_proscenium_javascripts,
13
+ if: -> { request.format.html? && !response.redirect? }
14
+ end
15
+ end
16
+
17
+ module ClassMethods
18
+ def sideload_assets(value)
19
+ self.sideload_assets_options = value
20
+ end
21
+ end
22
+
23
+ def capture_and_replace_proscenium_stylesheets # rubocop:disable Metrics/AbcSize
24
+ return if response_body.first.blank? || !Proscenium::Importer.css_imported?
25
+ return unless response_body.first.include? '<!-- [PROSCENIUM_STYLESHEETS] -->'
26
+
27
+ imports = Proscenium::Importer.imported.dup
28
+ paths_to_build = []
29
+ Proscenium::Importer.each_stylesheet(delete: true) do |x, _|
30
+ paths_to_build << x.delete_prefix('/')
31
+ end
32
+
33
+ result = Proscenium::Builder.build_to_path(paths_to_build.join(';'),
34
+ base_url: helpers.request.base_url)
35
+
36
+ out = []
37
+ result.split(';').each do |x|
38
+ inpath, outpath = x.split('::')
39
+ inpath.prepend '/'
40
+ outpath.delete_prefix! 'public'
41
+
42
+ next unless imports.key?(inpath)
43
+
44
+ import = imports[inpath]
45
+ opts = import[:css].is_a?(Hash) ? import[:css] : {}
46
+ out << helpers.stylesheet_link_tag(outpath, extname: false, **opts)
47
+ end
48
+
49
+ response_body.first.gsub! '<!-- [PROSCENIUM_STYLESHEETS] -->', out.join.html_safe
50
+ end
51
+
52
+ def capture_and_replace_proscenium_javascripts # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/PerceivedComplexity
53
+ return if response_body.first.blank? || !Proscenium::Importer.js_imported?
54
+
55
+ imports = Proscenium::Importer.imported.dup
56
+ paths_to_build = []
57
+ Proscenium::Importer.each_javascript(delete: true) do |x, _|
58
+ paths_to_build << x.delete_prefix('/')
59
+ end
60
+
61
+ result = Proscenium::Builder.build_to_path(paths_to_build.join(';'),
62
+ base_url: helpers.request.base_url)
63
+
64
+ if response_body.first.include? '<!-- [PROSCENIUM_JAVASCRIPTS] -->'
65
+ out = []
66
+ scripts = {}
67
+ result.split(';').each do |x|
68
+ inpath, outpath = x.split('::')
69
+ inpath.prepend '/'
70
+ outpath.delete_prefix! 'public'
71
+
72
+ next unless imports.key?(inpath)
73
+
74
+ if (import = imports[inpath]).delete(:lazy)
75
+ scripts[inpath] = import.merge(outpath: outpath)
76
+ else
77
+ opts = import[:js].is_a?(Hash) ? import[:js] : {}
78
+ out << helpers.javascript_include_tag(outpath, extname: false, **opts)
79
+ end
80
+ end
81
+
82
+ response_body.first.gsub! '<!-- [PROSCENIUM_JAVASCRIPTS] -->', out.join.html_safe
83
+ end
84
+
85
+ return unless response_body.first.include? '<!-- [PROSCENIUM_LAZY_SCRIPTS] -->'
86
+
87
+ lazy_script = ''
88
+ if scripts.present?
89
+ lazy_script = helpers.content_tag 'script', type: 'application/json',
90
+ id: 'prosceniumLazyScripts' do
91
+ scripts.to_json.html_safe
92
+ end
93
+ end
94
+
95
+ response_body.first.gsub! '<!-- [PROSCENIUM_LAZY_SCRIPTS] -->', lazy_script
96
+ end
97
+ end
98
+
5
99
  class << self
6
100
  # Side loads the class, and its super classes that respond to `.source_path`.
7
101
  #
8
- # Assign the `abstract_class` class variable to any abstract class, and it will not be side
9
- # loaded. Additionally, if the class responds to `#sideload?`, and it returns false, it will
10
- # not be side loaded.
102
+ # Set the `abstract_class` class variable to true in any class, and it will not be side
103
+ # loaded.
11
104
  #
12
105
  # If the class responds to `.sideload`, it will be called instead of the regular side loading.
13
106
  # You can use this to customise what is side loaded.
14
- def sideload_inheritance_chain(obj)
15
- return if !Proscenium.config.side_load || (obj.respond_to?(:sideload?) && !obj.sideload?)
107
+ def sideload_inheritance_chain(obj, options) # rubocop:disable Metrics/*
108
+ return unless Proscenium.config.side_load
109
+
110
+ options = {} if options.nil?
111
+ options = { js: options, css: options } unless options.is_a?(Hash)
112
+
113
+ unless obj.sideload_assets_options.nil?
114
+ tpl_options = obj.sideload_assets_options
115
+ options = if tpl_options.is_a?(Hash)
116
+ options.deep_merge tpl_options
117
+ else
118
+ { js: tpl_options, css: tpl_options }
119
+ end
120
+ end
121
+
122
+ %i[css js].each do |k|
123
+ options[k] = obj.instance_eval(&options[k]) if options[k].is_a?(Proc)
124
+ end
16
125
 
17
126
  klass = obj.class
18
127
  while klass.respond_to?(:source_path) && klass.source_path && !klass.abstract_class
19
- klass.respond_to?(:sideload) ? klass.sideload : Importer.sideload(klass.source_path)
128
+ if klass.respond_to?(:sideload)
129
+ klass.sideload options
130
+ else
131
+ Importer.sideload klass.source_path, **options
132
+ end
133
+
20
134
  klass = klass.superclass
21
135
  end
22
136
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Proscenium
4
- VERSION = '0.14.0'
4
+ VERSION = '0.15.0.beta.1'
5
5
  end
@@ -14,12 +14,14 @@ class Proscenium::ViewComponent < ViewComponent::Base
14
14
 
15
15
  module Sideload
16
16
  def before_render
17
- Proscenium::SideLoad.sideload_inheritance_chain self
17
+ Proscenium::SideLoad.sideload_inheritance_chain self, controller.sideload_assets_options
18
18
 
19
19
  super
20
20
  end
21
21
  end
22
22
 
23
+ class_attribute :sideload_assets_options
24
+
23
25
  class << self
24
26
  attr_accessor :abstract_class
25
27
 
@@ -28,5 +30,9 @@ class Proscenium::ViewComponent < ViewComponent::Base
28
30
 
29
31
  super
30
32
  end
33
+
34
+ def sideload_assets(value)
35
+ self.sideload_assets_options = value
36
+ end
31
37
  end
32
38
  end
data/lib/proscenium.rb CHANGED
@@ -46,6 +46,16 @@ module Proscenium
46
46
  "Path #{@path.inspect} cannot be resolved"
47
47
  end
48
48
  end
49
+
50
+ class << self
51
+ def config
52
+ @config ||= Railtie.config.proscenium
53
+ end
54
+
55
+ def cache
56
+ @cache ||= config.cache || ActiveSupport::Cache::NullStore.new
57
+ end
58
+ end
49
59
  end
50
60
 
51
61
  require 'proscenium/railtie'