proscenium 0.10.0-aarch64-linux → 0.11.0-aarch64-linux

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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +207 -45
  3. data/lib/proscenium/builder.rb +41 -19
  4. data/lib/proscenium/css_module/path.rb +31 -0
  5. data/lib/proscenium/css_module/transformer.rb +82 -0
  6. data/lib/proscenium/css_module.rb +12 -25
  7. data/lib/proscenium/ensure_loaded.rb +27 -0
  8. data/lib/proscenium/ext/proscenium +0 -0
  9. data/lib/proscenium/ext/proscenium.h +3 -2
  10. data/lib/proscenium/helper.rb +85 -0
  11. data/lib/proscenium/importer.rb +110 -0
  12. data/lib/proscenium/libs/react-manager/index.jsx +101 -0
  13. data/lib/proscenium/libs/react-manager/react.js +2 -0
  14. data/lib/proscenium/libs/test.js +1 -0
  15. data/lib/proscenium/middleware/base.rb +7 -7
  16. data/lib/proscenium/middleware/engines.rb +37 -0
  17. data/lib/proscenium/middleware/esbuild.rb +3 -5
  18. data/lib/proscenium/middleware/runtime.rb +18 -0
  19. data/lib/proscenium/middleware.rb +14 -4
  20. data/lib/proscenium/{side_load/monkey.rb → monkey.rb} +19 -15
  21. data/lib/proscenium/phlex/{resolve_css_modules.rb → css_modules.rb} +28 -16
  22. data/lib/proscenium/phlex/react_component.rb +26 -27
  23. data/lib/proscenium/phlex.rb +11 -30
  24. data/lib/proscenium/railtie.rb +44 -46
  25. data/lib/proscenium/react_componentable.rb +95 -0
  26. data/lib/proscenium/resolver.rb +37 -0
  27. data/lib/proscenium/side_load.rb +13 -73
  28. data/lib/proscenium/source_path.rb +15 -0
  29. data/lib/proscenium/templates/rescues/build_error.html.erb +30 -0
  30. data/lib/proscenium/utils.rb +13 -0
  31. data/lib/proscenium/version.rb +1 -1
  32. data/lib/proscenium/view_component/css_modules.rb +11 -0
  33. data/lib/proscenium/view_component/react_component.rb +15 -15
  34. data/lib/proscenium/view_component/sideload.rb +4 -0
  35. data/lib/proscenium/view_component.rb +8 -38
  36. data/lib/proscenium.rb +22 -68
  37. metadata +23 -30
  38. data/lib/proscenium/componentable.rb +0 -63
  39. data/lib/proscenium/css_module/class_names_resolver.rb +0 -66
  40. data/lib/proscenium/css_module/resolver.rb +0 -76
  41. data/lib/proscenium/current.rb +0 -9
  42. data/lib/proscenium/phlex/component_concerns.rb +0 -9
  43. data/lib/proscenium/phlex/page.rb +0 -62
  44. data/lib/proscenium/side_load/ensure_loaded.rb +0 -25
  45. data/lib/proscenium/side_load/helper.rb +0 -41
  46. data/lib/proscenium/view_component/tag_builder.rb +0 -23
@@ -3,41 +3,28 @@
3
3
  module Proscenium::CssModule
4
4
  extend ActiveSupport::Autoload
5
5
 
6
- class StylesheetNotFound < StandardError
7
- def initialize(pathname)
8
- @pathname = pathname
9
- super
10
- end
11
-
12
- def message
13
- "Stylesheet is required, but does not exist: #{@pathname}"
14
- end
15
- end
6
+ autoload :Path
7
+ autoload :Transformer
16
8
 
17
- autoload :ClassNamesResolver
18
- autoload :Resolver # deprecated
9
+ class TransformError < StandardError
10
+ def initialize(name, additional_msg = nil)
11
+ msg = "Failed to transform CSS module `#{name}`"
12
+ msg << ' - ' << additional_msg if additional_msg
19
13
 
20
- # Like `css_modules`, but will raise if the stylesheet cannot be found.
21
- #
22
- # @param name [Array, String]
23
- def css_module!(names)
24
- cssm.class_names!(names).join ' '
14
+ super msg
15
+ end
25
16
  end
26
17
 
27
18
  # Accepts one or more CSS class names, and transforms them into CSS module names.
28
19
  #
29
- # @param name [Array, String]
30
- def css_module(names)
31
- cssm.class_names(names).join ' '
20
+ # @param name [String,Symbol,Array<String,Symbol>]
21
+ def css_module(*names)
22
+ cssm.class_names(*names, require_prefix: false).map { |name, _| name }.join(' ')
32
23
  end
33
24
 
34
25
  private
35
26
 
36
- def path
37
- self.class.path
38
- end
39
-
40
27
  def cssm
41
- @cssm ||= Resolver.new(path)
28
+ @cssm ||= Transformer.new(self.class.css_module_path)
42
29
  end
43
30
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Proscenium
4
+ NotIncludedError = Class.new(StandardError)
5
+
6
+ module EnsureLoaded
7
+ def self.included(child)
8
+ child.class_eval do
9
+ append_after_action do
10
+ if request.format.html? && Importer.imported?
11
+ if Importer.js_imported?
12
+ raise NotIncludedError, 'There are javascripts to be included, but they have ' \
13
+ 'not been included in the page. Did you forget to add the ' \
14
+ '`#include_javascripts` helper in your views?'
15
+ end
16
+
17
+ if Importer.css_imported?
18
+ raise NotIncludedError, 'There are stylesheets to be included, but they have ' \
19
+ 'not been included in the page. Did you forget to add the ' \
20
+ '`#include_stylesheets` helper in your views?'
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
Binary file
@@ -97,7 +97,7 @@ extern "C" {
97
97
  // - codeSpitting?
98
98
  // - debug?
99
99
  //
100
- extern struct Result build(char* filepath, char* baseUrl, char* importMap, char* envVars, char* root, unsigned int env, GoUint8 codeSplitting, GoUint8 debug);
100
+ extern struct Result build(char* filepath, char* baseUrl, char* importMap, char* envVars, char* appRoot, char* gemPath, unsigned int env, GoUint8 codeSplitting, char* engines, GoUint8 debug);
101
101
 
102
102
  // Resolve the given `path` relative to the `root`.
103
103
  //
@@ -107,8 +107,9 @@ extern struct Result build(char* filepath, char* baseUrl, char* importMap, char*
107
107
  // Config
108
108
  // - root - The working directory.
109
109
  // - env - The environment (1 = development, 2 = test, 3 = production)
110
+ // - debug?
110
111
  //
111
- extern struct Result resolve(char* path, char* importMap, char* root, unsigned int env);
112
+ extern struct Result resolve(char* path, char* importMap, char* appRoot, char* gemPath, unsigned int env, GoUint8 debug);
112
113
 
113
114
  #ifdef __cplusplus
114
115
  }
@@ -15,5 +15,90 @@ module Proscenium
15
15
 
16
16
  super
17
17
  end
18
+
19
+ # Accepts one or more CSS class names, and transforms them into CSS module names.
20
+ #
21
+ # @see CssModule::Transformer#class_names
22
+ # @param name [String,Symbol,Array<String,Symbol>]
23
+ def css_module(*names)
24
+ path = Pathname.new(@lookup_context.find(@virtual_path).identifier).sub_ext('')
25
+ CssModule::Transformer.new(path).class_names(*names, require_prefix: false).map do |name, _|
26
+ name
27
+ end.join(' ')
28
+ end
29
+
30
+ def include_stylesheets(**options)
31
+ out = []
32
+ Importer.each_stylesheet(delete: true) do |path, _path_options|
33
+ out << stylesheet_link_tag(path, extname: false, **options)
34
+ end
35
+ out.join("\n").html_safe
36
+ end
37
+ alias side_load_stylesheets include_stylesheets
38
+ deprecate side_load_stylesheets: 'Use `include_stylesheets` instead', deprecator: Deprecator.new
39
+
40
+ # Includes all javascripts that have been imported and side loaded.
41
+ #
42
+ # @param extract_lazy_scripts [Boolean] if true, any lazy scripts will be extracted using
43
+ # `content_for` to `:proscenium_lazy_scripts` for later use. Be sure to include this in your
44
+ # page with the `declare_lazy_scripts` helper, or simply
45
+ # `content_for :proscenium_lazy_scripts`.
46
+ # @return [String] the HTML tags for the javascripts.
47
+ def include_javascripts(extract_lazy_scripts: false, **options) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
48
+ out = []
49
+
50
+ if Rails.application.config.proscenium.code_splitting && Importer.multiple_js_imported?
51
+ imports = Importer.imported.dup
52
+
53
+ paths_to_build = []
54
+ Importer.each_javascript(delete: true) do |x, _|
55
+ paths_to_build << x.delete_prefix('/')
56
+ end
57
+
58
+ result = Builder.build(paths_to_build.join(';'), base_url: request.base_url)
59
+
60
+ # Remove the react components from the results, so they are not side loaded. Instead they
61
+ # are lazy loaded by the component manager.
62
+
63
+ scripts = {}
64
+ result.split(';').each do |x|
65
+ inpath, outpath = x.split('::')
66
+ inpath.prepend '/'
67
+ outpath.delete_prefix! 'public'
68
+
69
+ next unless imports.key?(inpath)
70
+
71
+ if (import = imports[inpath]).delete(:lazy)
72
+ scripts[inpath] = import.merge(outpath: outpath)
73
+ else
74
+ out << javascript_include_tag(outpath, extname: false, **options)
75
+ end
76
+ end
77
+
78
+ if extract_lazy_scripts
79
+ content_for :proscenium_lazy_scripts do
80
+ tag.script type: 'application/json', id: 'prosceniumLazyScripts' do
81
+ raw scripts.to_json
82
+ end
83
+ end
84
+ else
85
+ out << tag.script(type: 'application/json', id: 'prosceniumLazyScripts') do
86
+ raw scripts.to_json
87
+ end
88
+ end
89
+ else
90
+ Importer.each_javascript(delete: true) do |path, _|
91
+ out << javascript_include_tag(path, extname: false, **options)
92
+ end
93
+ end
94
+
95
+ out.join("\n").html_safe
96
+ end
97
+ alias side_load_javascripts include_javascripts
98
+ deprecate side_load_javascripts: 'Use `include_javascripts` instead', deprecator: Deprecator.new
99
+
100
+ def declare_lazy_scripts
101
+ content_for :proscenium_lazy_scripts
102
+ end
18
103
  end
19
104
  end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/current_attributes'
4
+
5
+ module Proscenium
6
+ class Importer < ActiveSupport::CurrentAttributes
7
+ JS_EXTENSIONS = %w[.tsx .ts .jsx .js].freeze
8
+ CSS_EXTENSIONS = %w[.module.css .css].freeze
9
+
10
+ # Holds the JS and CSS files to include in the current request.
11
+ #
12
+ # Example:
13
+ # {
14
+ # '/path/to/input/file.js': {
15
+ # output: '/path/to/compiled/file.js',
16
+ # **options
17
+ # }
18
+ # }
19
+ attribute :imported
20
+
21
+ class << self
22
+ # Import the given `filepath`. This is idempotent - it will never include duplicates.
23
+ #
24
+ # @param filepath [String] Absolute URL path (relative to Rails root) of the file to import.
25
+ # Should be the actual asset file, eg. app.css, some/component.js.
26
+ # @param resolve [String] description of the file to resolve and import.
27
+ # @return [String] the digest of the imported file path if a css module (*.module.css).
28
+ def import(filepath = nil, resolve: nil, **options)
29
+ self.imported ||= {}
30
+
31
+ filepath = Resolver.resolve(resolve) if !filepath && resolve
32
+ css_module = filepath.end_with?('.module.css')
33
+
34
+ unless self.imported.key?(filepath)
35
+ # ActiveSupport::Notifications.instrument('sideload.proscenium', identifier: value)
36
+
37
+ self.imported[filepath] = { **options }
38
+ self.imported[filepath][:digest] = Utils.digest(filepath) if css_module
39
+ end
40
+
41
+ css_module ? self.imported[filepath][:digest] : nil
42
+ end
43
+
44
+ # Sideloads JS and CSS assets for the given Ruby filepath.
45
+ #
46
+ # Any files with the same base name and matching a supported extension will be sideloaded.
47
+ # Only one JS and one CSS file will be sideloaded, with the first match used in the following
48
+ # order:
49
+ # - JS extensions: .tsx, .ts, .jsx, and .js.
50
+ # - CSS extensions: .css.module, and .css.
51
+ #
52
+ # Example:
53
+ # - `app/views/layouts/application.rb`
54
+ # - `app/views/layouts/application.css`
55
+ # - `app/views/layouts/application.js`
56
+ # - `app/views/layouts/application.tsx`
57
+ #
58
+ # A request to sideload `app/views/layouts/application.rb` will result in `application.css`
59
+ # and `application.tsx` being sideloaded. `application.js` will not be sideloaded because the
60
+ # `.tsx` extension is matched first.
61
+ #
62
+ # @param filepath [Pathname] Absolute file system path of the Ruby file to sideload.
63
+ def sideload(filepath, **options)
64
+ return unless Proscenium.config.side_load
65
+
66
+ filepath = Rails.root.join(filepath) unless filepath.is_a?(Pathname)
67
+ filepath = filepath.sub_ext('')
68
+
69
+ import_if_exists = lambda do |x|
70
+ if (fp = filepath.sub_ext(x)).exist?
71
+ import(Resolver.resolve(fp.to_s), sideloaded: true, **options)
72
+ end
73
+ end
74
+
75
+ JS_EXTENSIONS.find(&import_if_exists)
76
+ CSS_EXTENSIONS.find(&import_if_exists)
77
+ end
78
+
79
+ def each_stylesheet(delete: false)
80
+ return if imported.blank?
81
+
82
+ blk = proc { |key, options| key.end_with?(*CSS_EXTENSIONS) && yield(key, options) }
83
+ delete ? imported.delete_if(&blk) : imported.each(&blk)
84
+ end
85
+
86
+ def each_javascript(delete: false)
87
+ return if imported.blank?
88
+
89
+ blk = proc { |key, options| key.end_with?(*JS_EXTENSIONS) && yield(key, options) }
90
+ delete ? imported.delete_if(&blk) : imported.each(&blk)
91
+ end
92
+
93
+ def css_imported?
94
+ imported&.keys&.any? { |x| x.end_with?(*CSS_EXTENSIONS) }
95
+ end
96
+
97
+ def js_imported?
98
+ imported&.keys&.any? { |x| x.end_with?(*JS_EXTENSIONS) }
99
+ end
100
+
101
+ def multiple_js_imported?
102
+ imported&.keys&.many? { |x| x.end_with?(*JS_EXTENSIONS) }
103
+ end
104
+
105
+ def imported?(filepath = nil)
106
+ filepath ? imported&.key?(filepath) : !imported.blank?
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,101 @@
1
+ window.Proscenium = window.Proscenium || { lazyScripts: {} };
2
+
3
+ const element = document.querySelector("#prosceniumLazyScripts");
4
+ if (element) {
5
+ const scripts = JSON.parse(element.text);
6
+ window.Proscenium.lazyScripts = {
7
+ ...window.Proscenium.lazyScripts,
8
+ ...scripts,
9
+ };
10
+ }
11
+
12
+ const elements = document.querySelectorAll("[data-proscenium-component-path]");
13
+ elements.length > 0 && init(elements);
14
+
15
+ function init() {
16
+ /**
17
+ * Mounts component located at `path`, into the DOM `element`.
18
+ *
19
+ * The element at which the component is mounted must have the following data attributes:
20
+ *
21
+ * - `data-proscenium-component-path`: The URL path to the component's source file.
22
+ * - `data-proscenium-component-props`: JSON object of props to pass to the component.
23
+ * - `data-proscenium-component-lazy`: If present, will lazily load the component when in view
24
+ * using IntersectionObserver.
25
+ * - `data-proscenium-component-forward-children`: If the element should forward its `innerHTML`
26
+ * as the component's children prop.
27
+ */
28
+ function mount(element, path, { children, ...props }) {
29
+ // For testing and simulation of slow connections.
30
+ // const sim = new Promise((resolve) => setTimeout(resolve, 5000));
31
+
32
+ if (!window.Proscenium.lazyScripts[path]) {
33
+ throw `[proscenium/react/manager] Cannot load component ${path} (not found in Proscenium.lazyScripts)`;
34
+ }
35
+
36
+ const react = import("@proscenium/react-manager/react");
37
+ const Component = import(window.Proscenium.lazyScripts[path].outpath);
38
+
39
+ const forwardChildren =
40
+ "prosceniumComponentForwardChildren" in element.dataset &&
41
+ element.innerHTML !== "";
42
+
43
+ Promise.all([react, Component])
44
+ .then(([r, c]) => {
45
+ if (proscenium.env.RAILS_ENV === "development") {
46
+ console.groupCollapsed(
47
+ `[proscenium/react/manager] 🔥 %o mounted!`,
48
+ path
49
+ );
50
+ console.log("props: %o", props);
51
+ console.groupEnd();
52
+ }
53
+
54
+ let component;
55
+ if (forwardChildren) {
56
+ component = r.createElement(c.default, props, element.innerHTML);
57
+ } else if (children) {
58
+ component = r.createElement(c.default, props, children);
59
+ } else {
60
+ component = r.createElement(c.default, props);
61
+ }
62
+
63
+ r.createRoot(element).render(component);
64
+ })
65
+ .catch((error) => {
66
+ console.error("[proscenium/react/manager] %o - %o", path, error);
67
+ });
68
+ }
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
+ }
@@ -0,0 +1,2 @@
1
+ export { createElement } from "react";
2
+ export { createRoot } from "react-dom/client";
@@ -0,0 +1 @@
1
+ console.log("/@proscenium/test.js");
@@ -34,12 +34,12 @@ module Proscenium
34
34
  private
35
35
 
36
36
  def real_path
37
- @request.path
37
+ @real_path ||= @request.path
38
38
  end
39
39
 
40
40
  # @return [String] the path to the file without the leading slash which will be built.
41
41
  def path_to_build
42
- @request.path[1..]
42
+ @path_to_build ||= @request.path[1..]
43
43
  end
44
44
 
45
45
  def sourcemap?
@@ -53,22 +53,22 @@ module Proscenium
53
53
  def file_readable?
54
54
  return false unless (path = clean_path(sourcemap? ? real_path[0...-4] : real_path))
55
55
 
56
- file_stat = File.stat(Pathname(root).join(path.delete_prefix('/').b).to_s)
56
+ file_stat = File.stat(root_for_readable.join(path.delete_prefix('/').b).to_s)
57
57
  rescue SystemCallError
58
58
  false
59
59
  else
60
60
  file_stat.file? && file_stat.readable?
61
61
  end
62
62
 
63
+ def root_for_readable
64
+ Rails.root
65
+ end
66
+
63
67
  def clean_path(file)
64
68
  path = Rack::Utils.unescape_path file.chomp('/').delete_prefix('/')
65
69
  Rack::Utils.clean_path_info path if Rack::Utils.valid_path? path
66
70
  end
67
71
 
68
- def root
69
- @root ||= Rails.root.to_s
70
- end
71
-
72
72
  def content_type
73
73
  case ::File.extname(path_to_build)
74
74
  when '.js', '.mjs', '.ts', '.tsx', '.jsx' then 'application/javascript'
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Proscenium
4
+ class Middleware
5
+ # This middleware handles requests for assets in Rails engines. An engine that wants to expose
6
+ # its assets via Proscenium to the application must add itself to the list of engines in the
7
+ # Proscenium config options `Proscenium.config.engines`.
8
+ #
9
+ # For example, we have a gem that exposes a Rails engine.
10
+ #
11
+ # module Gem1
12
+ # class Engine < ::Rails::Engine
13
+ # config.proscenium.engines << self
14
+ # end
15
+ # end
16
+ #
17
+ # When this gem is installed in any Rails application, its assets will be available at the URL
18
+ # `/gem1/...`. For example, if the gem has a file `lib/styles.css`, it can be requested at
19
+ # `/gem1/lib/styles.css`.
20
+ #
21
+ class Engines < Esbuild
22
+ def real_path
23
+ @real_path ||= Pathname.new(@request.path.delete_prefix("/#{engine.engine_name}")).to_s
24
+ end
25
+
26
+ def root_for_readable
27
+ engine.root
28
+ end
29
+
30
+ def engine
31
+ @engine ||= Proscenium.config.engines.find do |engine|
32
+ @request.path.start_with?("/#{engine.engine_name}")
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -20,11 +20,9 @@ module Proscenium
20
20
  end
21
21
 
22
22
  def attempt
23
- ActiveSupport::Notifications.instrument('build.proscenium', identifier: path_to_build) do
24
- render_response Proscenium::Builder.build(path_to_build, root: root,
25
- base_url: @request.base_url)
26
- end
27
- rescue Proscenium::Builder::CompileError => e
23
+ render_response Builder.build(path_to_build, root: Rails.root.to_s,
24
+ base_url: @request.base_url)
25
+ rescue Builder::CompileError => e
28
26
  raise self.class::CompileError, { file: @request.fullpath, detail: e.message }, caller
29
27
  end
30
28
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Proscenium
4
+ class Middleware
5
+ class Runtime < Esbuild
6
+ private
7
+
8
+ def real_path
9
+ @real_path ||= Pathname.new(@request.path.sub(%r{^/@proscenium},
10
+ '/lib/proscenium/libs')).to_s
11
+ end
12
+
13
+ def root_for_readable
14
+ Proscenium::Railtie.root
15
+ end
16
+ end
17
+ end
18
+ end
@@ -9,6 +9,8 @@ module Proscenium
9
9
 
10
10
  autoload :Base
11
11
  autoload :Esbuild
12
+ autoload :Engines
13
+ autoload :Runtime
12
14
  autoload :Url
13
15
 
14
16
  def initialize(app)
@@ -40,12 +42,20 @@ module Proscenium
40
42
 
41
43
  def find_type(request)
42
44
  return Url if request.path.match?(%r{^/https?%3A%2F%2F})
43
- return Esbuild if Pathname.new(request.path).fnmatch?(path_glob, File::FNM_EXTGLOB)
45
+ return Runtime if request.path.match?(%r{^/@proscenium/})
46
+ return Esbuild if Pathname.new(request.path).fnmatch?(app_path_glob, File::FNM_EXTGLOB)
47
+
48
+ Engines if Pathname.new(request.path).fnmatch?(engines_path_glob, File::FNM_EXTGLOB)
49
+ end
50
+
51
+ def app_path_glob
52
+ "/{#{Proscenium::ALLOWED_DIRECTORIES}}/**.{#{FILE_EXTENSIONS.join(',')}}"
44
53
  end
45
54
 
46
- def path_glob
47
- paths = Rails.application.config.proscenium.include_paths.join(',')
48
- "/{#{paths}}/**.{#{FILE_EXTENSIONS.join(',')}}"
55
+ def engines_path_glob
56
+ names = Proscenium.config.engines.map(&:engine_name)
57
+
58
+ "/{#{names.join(',')}}/{#{Proscenium::ALLOWED_DIRECTORIES}}/**.{#{FILE_EXTENSIONS.join(',')}}"
49
59
  end
50
60
 
51
61
  # TODO: handle precompiled assets
@@ -1,12 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Proscenium::SideLoad
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
+
6
14
  module TemplateRenderer
7
15
  private
8
16
 
9
17
  def render_template(view, template, layout_name, locals)
18
+ return super unless Proscenium.config.side_load
19
+
10
20
  layout = find_layout(layout_name, locals.keys, [formats.first])
11
21
  renderable = template.instance_variable_get(:@renderable)
12
22
 
@@ -14,18 +24,18 @@ class Proscenium::SideLoad
14
24
  template.is_a?(ActionView::Template::Renderable) &&
15
25
  renderable.class < ::ViewComponent::Base && renderable.class.format == :html
16
26
  # Side load controller rendered ViewComponent
17
- Proscenium::SideLoad.append "app/views/#{layout.virtual_path}" if layout
18
- Proscenium::SideLoad.append "app/views/#{renderable.virtual_path}"
27
+ Importer.sideload "app/views/#{layout.virtual_path}" if layout
28
+ Importer.sideload "app/views/#{renderable.virtual_path}"
19
29
  elsif template.respond_to?(:virtual_path) &&
20
30
  template.respond_to?(:type) && template.type == :html
21
- Proscenium::SideLoad.append "app/views/#{layout.virtual_path}" if layout
31
+ Importer.sideload "app/views/#{layout.virtual_path}" if layout
22
32
 
23
33
  # Try side loading the variant template
24
34
  if template.respond_to?(:variant) && template.variant
25
- Proscenium::SideLoad.append "app/views/#{template.virtual_path}+#{template.variant}"
35
+ Importer.sideload "app/views/#{template.virtual_path}+#{template.variant}"
26
36
  end
27
37
 
28
- Proscenium::SideLoad.append "app/views/#{template.virtual_path}"
38
+ Importer.sideload "app/views/#{template.virtual_path}"
29
39
  end
30
40
 
31
41
  super
@@ -36,20 +46,14 @@ class Proscenium::SideLoad
36
46
  private
37
47
 
38
48
  def render_partial_template(view, locals, template, layout, block)
39
- if template.respond_to?(:virtual_path) &&
49
+ if Proscenium.config.side_load && template.respond_to?(:virtual_path) &&
40
50
  template.respond_to?(:type) && template.type == :html
41
- Proscenium::SideLoad.append "app/views/#{layout.virtual_path}" if layout
42
- Proscenium::SideLoad.append "app/views/#{template.virtual_path}"
51
+ Importer.sideload "app/views/#{layout.virtual_path}" if layout
52
+ Importer.sideload "app/views/#{template.virtual_path}"
43
53
  end
44
54
 
45
55
  super
46
56
  end
47
-
48
- def build_rendered_template(content, template)
49
- path = Rails.root.join('app', 'views', template.virtual_path)
50
- cssm = Proscenium::CssModule::Resolver.new(path)
51
- super cssm.compile_class_names(content), template
52
- end
53
57
  end
54
58
  end
55
59
  # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity