proscenium 0.18.0-arm64-darwin → 0.19.0-arm64-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.
- checksums.yaml +4 -4
- data/README.md +25 -174
- data/lib/proscenium/builder.rb +36 -100
- data/lib/proscenium/bundled_gems.rb +37 -0
- data/lib/proscenium/css_module/path.rb +2 -1
- data/lib/proscenium/css_module/transformer.rb +1 -1
- data/lib/proscenium/css_module.rb +16 -9
- data/lib/proscenium/ensure_loaded.rb +14 -10
- data/lib/proscenium/ext/proscenium +0 -0
- data/lib/proscenium/ext/proscenium.h +9 -36
- data/lib/proscenium/helper.rb +4 -22
- data/lib/proscenium/importer.rb +39 -21
- data/lib/proscenium/log_subscriber.rb +11 -10
- data/lib/proscenium/middleware/base.rb +11 -6
- data/lib/proscenium/middleware/esbuild.rb +8 -9
- data/lib/proscenium/middleware/ruby_gems.rb +23 -0
- data/lib/proscenium/middleware.rb +26 -24
- data/lib/proscenium/monkey.rb +5 -14
- data/lib/proscenium/railtie.rb +11 -53
- data/lib/proscenium/{libs/react-manager → react-manager}/index.jsx +3 -22
- data/lib/proscenium/react_componentable.rb +2 -3
- data/lib/proscenium/resolver.rb +14 -23
- data/lib/proscenium/side_load.rb +41 -74
- data/lib/proscenium/utils.rb +33 -0
- data/lib/proscenium/version.rb +1 -1
- data/lib/proscenium.rb +2 -12
- metadata +11 -99
- data/lib/proscenium/core_ext/object/css_module_ivars.rb +0 -19
- data/lib/proscenium/css_module/rewriter.rb +0 -44
- data/lib/proscenium/libs/custom_element.js +0 -54
- data/lib/proscenium/libs/stimulus-loading.js +0 -65
- data/lib/proscenium/libs/test.js +0 -1
- data/lib/proscenium/libs/ujs/class.js +0 -15
- data/lib/proscenium/libs/ujs/data_confirm.js +0 -23
- data/lib/proscenium/libs/ujs/data_disable_with.js +0 -68
- data/lib/proscenium/libs/ujs/index.js +0 -9
- data/lib/proscenium/middleware/engines.rb +0 -45
- data/lib/proscenium/middleware/runtime.rb +0 -18
- data/lib/proscenium/phlex/asset_inclusions.rb +0 -17
- data/lib/proscenium/phlex/css_modules.rb +0 -79
- data/lib/proscenium/phlex/react_component.rb +0 -32
- data/lib/proscenium/phlex.rb +0 -42
- data/lib/proscenium/ui/breadcrumbs/component.module.css +0 -14
- data/lib/proscenium/ui/breadcrumbs/component.rb +0 -73
- data/lib/proscenium/ui/breadcrumbs/computed_element.rb +0 -69
- data/lib/proscenium/ui/breadcrumbs/control.rb +0 -95
- data/lib/proscenium/ui/breadcrumbs/mixins.css +0 -83
- data/lib/proscenium/ui/breadcrumbs.rb +0 -72
- data/lib/proscenium/ui/component.rb +0 -7
- data/lib/proscenium/ui/test.js +0 -1
- data/lib/proscenium/ui.rb +0 -8
- data/lib/proscenium/view_component/css_modules.rb +0 -11
- data/lib/proscenium/view_component/react_component.rb +0 -22
- data/lib/proscenium/view_component/sideload.rb +0 -4
- data/lib/proscenium/view_component.rb +0 -38
- /data/lib/proscenium/{libs/react-manager → react-manager}/react.js +0 -0
@@ -24,6 +24,7 @@ typedef struct { const char *p; ptrdiff_t n; } _GoString_;
|
|
24
24
|
struct Result {
|
25
25
|
int success;
|
26
26
|
char* response;
|
27
|
+
char* contentHash;
|
27
28
|
};
|
28
29
|
|
29
30
|
#line 1 "cgo-generated-wrapper"
|
@@ -82,49 +83,21 @@ typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
|
|
82
83
|
extern "C" {
|
83
84
|
#endif
|
84
85
|
|
86
|
+
extern void reset_config();
|
85
87
|
|
86
|
-
// Build the given `path`
|
88
|
+
// Build the given `path` using the `config`.
|
87
89
|
//
|
88
|
-
//
|
89
|
-
//
|
90
|
-
// - baseUrl - base URL of the Rails app. eg. https://example.com
|
91
|
-
// - importMap - Path to the import map relative to `root`.
|
92
|
-
// - envVars - JSON string of environment variables.
|
93
|
-
// Config:
|
94
|
-
// - root - The working directory.
|
95
|
-
// - env - The environment (1 = development, 2 = test, 3 = production)
|
96
|
-
// - codeSpitting?
|
97
|
-
// - debug?
|
90
|
+
// - path - The path to build relative to `root`.
|
91
|
+
// - config
|
98
92
|
//
|
99
|
-
extern struct Result build_to_string(char*
|
100
|
-
|
101
|
-
// Build the given `path` in the `root`.
|
102
|
-
//
|
103
|
-
// BuildOptions
|
104
|
-
// - path - The path to build relative to `root`. Multiple paths can be given by separating them
|
105
|
-
// with a semi-colon.
|
106
|
-
// - baseUrl - base URL of the Rails app. eg. https://example.com
|
107
|
-
// - importMap - Path to the import map relative to `root`.
|
108
|
-
// - envVars - JSON string of environment variables.
|
109
|
-
// Config:
|
110
|
-
// - root - The working directory.
|
111
|
-
// - env - The environment (1 = development, 2 = test, 3 = production)
|
112
|
-
// - codeSpitting?
|
113
|
-
// - debug?
|
114
|
-
//
|
115
|
-
extern struct Result build_to_path(char* filepath, char* baseUrl, char* importMap, char* envVars, char* appRoot, char* gemPath, unsigned int env, GoUint8 codeSplitting, char* engines, GoUint8 debug);
|
93
|
+
extern struct Result build_to_string(char* filePath, char* configJson);
|
116
94
|
|
117
95
|
// Resolve the given `path` relative to the `root`.
|
118
96
|
//
|
119
|
-
//
|
120
|
-
//
|
121
|
-
// - importMap - Path to the import map relative to `root`.
|
122
|
-
// Config
|
123
|
-
// - root - The working directory.
|
124
|
-
// - env - The environment (1 = development, 2 = test, 3 = production)
|
125
|
-
// - debug?
|
97
|
+
// - path - The path to build relative to `root`.
|
98
|
+
// - config
|
126
99
|
//
|
127
|
-
extern struct Result resolve(char*
|
100
|
+
extern struct Result resolve(char* filePath, char* configJson);
|
128
101
|
|
129
102
|
#ifdef __cplusplus
|
130
103
|
}
|
data/lib/proscenium/helper.rb
CHANGED
@@ -16,15 +16,13 @@ module Proscenium
|
|
16
16
|
# those asset paths all begin with a slash, which the Rails asset helpers do not pass through to
|
17
17
|
# here.
|
18
18
|
#
|
19
|
-
# If the given `path` is a bare path (does not start with
|
19
|
+
# If the given `path` is a bare path (does not start with `./` or `../`), then we use
|
20
20
|
# Rails default conventions, and serve CSS from /app/assets/stylesheets and JS from
|
21
21
|
# /app/javascript.
|
22
22
|
def compute_asset_path(path, options = {})
|
23
23
|
if %i[javascript stylesheet].include?(options[:type])
|
24
|
-
path.prepend DEFAULT_RAILS_ASSET_PATHS[options[:type]]
|
25
|
-
|
26
|
-
result = Proscenium::Builder.build_to_path(path, base_url: request.base_url)
|
27
|
-
return result.split('::').last.delete_prefix 'public'
|
24
|
+
path.prepend DEFAULT_RAILS_ASSET_PATHS[options[:type]] if !path.start_with?('./', '../')
|
25
|
+
return path
|
28
26
|
end
|
29
27
|
|
30
28
|
super
|
@@ -42,18 +40,6 @@ module Proscenium
|
|
42
40
|
.map { |name, _| name }.join(' ')
|
43
41
|
end
|
44
42
|
|
45
|
-
# @param name [String,Symbol,Array<String,Symbol>]
|
46
|
-
# @param path [Pathname] the path to the CSS file to use for the transformation.
|
47
|
-
# @return [String] the transformed CSS module names concatenated as a string.
|
48
|
-
def class_names(*names, path: nil)
|
49
|
-
names = names.flatten.compact
|
50
|
-
|
51
|
-
return if names.empty?
|
52
|
-
|
53
|
-
path ||= Pathname.new(@lookup_context.find(@virtual_path).identifier).sub_ext('')
|
54
|
-
CssModule::Transformer.new(path).class_names(*names).map { |name, _| name }.join(' ')
|
55
|
-
end
|
56
|
-
|
57
43
|
def include_assets
|
58
44
|
include_stylesheets + include_javascripts
|
59
45
|
end
|
@@ -61,16 +47,12 @@ module Proscenium
|
|
61
47
|
def include_stylesheets
|
62
48
|
SideLoad::CSS_COMMENT.html_safe
|
63
49
|
end
|
64
|
-
alias side_load_stylesheets include_stylesheets
|
65
|
-
deprecate side_load_stylesheets: 'Use `include_stylesheets` instead', deprecator: Deprecator.new
|
66
50
|
|
67
51
|
# Includes all javascripts that have been imported and side loaded.
|
68
52
|
#
|
69
53
|
# @return [String] the HTML tags for the javascripts.
|
70
54
|
def include_javascripts
|
71
|
-
|
55
|
+
SideLoad::JS_COMMENT.html_safe
|
72
56
|
end
|
73
|
-
alias side_load_javascripts include_javascripts
|
74
|
-
deprecate side_load_javascripts: 'Use `include_javascripts` instead', deprecator: Deprecator.new
|
75
57
|
end
|
76
58
|
end
|
data/lib/proscenium/importer.rb
CHANGED
@@ -23,19 +23,24 @@ module Proscenium
|
|
23
23
|
#
|
24
24
|
# @param filepath [String] Absolute URL path (relative to Rails root) of the file to import.
|
25
25
|
# Should be the actual asset file, eg. app.css, some/component.js.
|
26
|
-
# @
|
27
|
-
|
28
|
-
def import(filepath = nil, resolve: nil, **)
|
26
|
+
# @return [String|nil] the digest of the imported file path if a css module (*.module.css).
|
27
|
+
def import(filepath = nil, sideloaded: false, **)
|
29
28
|
self.imported ||= {}
|
30
29
|
|
31
|
-
filepath =
|
30
|
+
filepath = "/node_modules/#{filepath}" if filepath.start_with?('@rubygems/')
|
32
31
|
css_module = filepath.end_with?('.module.css')
|
33
32
|
|
34
33
|
unless self.imported.key?(filepath)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
34
|
+
if sideloaded
|
35
|
+
ActiveSupport::Notifications.instrument 'sideload.proscenium', identifier: filepath,
|
36
|
+
sideloaded: do
|
37
|
+
self.imported[filepath] = { ** }
|
38
|
+
self.imported[filepath][:digest] = Utils.digest(filepath) if css_module
|
39
|
+
end
|
40
|
+
else
|
41
|
+
self.imported[filepath] = { ** }
|
42
|
+
self.imported[filepath][:digest] = Utils.digest(filepath) if css_module
|
43
|
+
end
|
39
44
|
end
|
40
45
|
|
41
46
|
css_module ? self.imported[filepath][:digest] : nil
|
@@ -60,6 +65,7 @@ module Proscenium
|
|
60
65
|
# `.tsx` extension is matched first.
|
61
66
|
#
|
62
67
|
# @param filepath [Pathname] Absolute file system path of the Ruby file to sideload.
|
68
|
+
# @param options [Hash] Options to pass to `import`.
|
63
69
|
def sideload(filepath, **options)
|
64
70
|
return if !Proscenium.config.side_load || (options[:js] == false && options[:css] == false)
|
65
71
|
|
@@ -67,30 +73,42 @@ module Proscenium
|
|
67
73
|
sideload_css(filepath, **options) unless options[:css] == false
|
68
74
|
end
|
69
75
|
|
70
|
-
def sideload_js(filepath, **
|
71
|
-
|
76
|
+
def sideload_js(filepath, **)
|
77
|
+
_sideload(filepath, JS_EXTENSIONS, **)
|
78
|
+
end
|
72
79
|
|
73
|
-
|
74
|
-
filepath
|
80
|
+
def sideload_css(filepath, **)
|
81
|
+
_sideload(filepath, ['.css'], **)
|
82
|
+
end
|
75
83
|
|
76
|
-
|
77
|
-
|
78
|
-
import(Resolver.resolve(fp.to_s), sideloaded: true, **options)
|
79
|
-
end
|
80
|
-
end
|
84
|
+
def sideload_css_module(filepath, **)
|
85
|
+
_sideload(filepath, ['.module.css'], **)
|
81
86
|
end
|
82
87
|
|
83
|
-
|
88
|
+
# @param filepath [Pathname] Absolute file system path of the Ruby file to sideload.
|
89
|
+
# @param extensions [Array<String>] Supported file extensions to sideload.
|
90
|
+
# @param options [Hash] Options to pass to `import`.
|
91
|
+
# @return [Array<String>] The imported file paths.
|
92
|
+
# @raise [ArgumentError] if `filepath` is not an absolute file system path.
|
93
|
+
private def _sideload(filepath, extensions, **options) # rubocop:disable Style/AccessModifierDeclarations
|
84
94
|
return unless Proscenium.config.side_load
|
85
95
|
|
86
|
-
filepath
|
96
|
+
if !filepath.is_a?(Pathname) || !filepath.absolute?
|
97
|
+
raise ArgumentError, "`filepath` (#{filepath}) must be a `Pathname`, and an absolute path"
|
98
|
+
end
|
99
|
+
|
100
|
+
# Ensures extensions with more than one dot are handled correctly.
|
87
101
|
filepath = filepath.sub_ext('')
|
88
102
|
|
89
|
-
|
103
|
+
sideloaded = []
|
104
|
+
|
105
|
+
extensions.find do |x|
|
90
106
|
if (fp = filepath.sub_ext(x)).exist?
|
91
|
-
import(Resolver.resolve(fp.to_s), sideloaded:
|
107
|
+
sideloaded << import(Resolver.resolve(fp.to_s), sideloaded: filepath, **options)
|
92
108
|
end
|
93
109
|
end
|
110
|
+
|
111
|
+
sideloaded
|
94
112
|
end
|
95
113
|
|
96
114
|
def each_stylesheet(delete: false)
|
@@ -5,33 +5,34 @@ require 'active_support/log_subscriber'
|
|
5
5
|
module Proscenium
|
6
6
|
class LogSubscriber < ActiveSupport::LogSubscriber
|
7
7
|
def sideload(event)
|
8
|
+
path = event.payload[:identifier]
|
9
|
+
sideloaded = event.payload[:sideloaded]
|
10
|
+
sideloaded = sideloaded.relative_path_from(Rails.root) if sideloaded.is_a?(Pathname)
|
11
|
+
|
8
12
|
info do
|
9
|
-
" [Proscenium]
|
13
|
+
msg = " #{color('[Proscenium]', nil, bold: true)} Sideloading #{path}"
|
14
|
+
sideloaded.is_a?(Pathname) ? msg << " from #{sideloaded}" : msg
|
10
15
|
end
|
11
16
|
end
|
12
17
|
|
13
|
-
def
|
18
|
+
def build(event)
|
14
19
|
path = event.payload[:identifier]
|
15
|
-
cached = event.payload[:cached] ? ' | Cached!' : ''
|
16
20
|
path = CGI.unescape(path) if path.start_with?(/https?%3A%2F%2F/)
|
17
21
|
|
18
22
|
info do
|
19
|
-
message = "
|
20
|
-
message << " (Duration: #{event.duration.round(1)}ms | "
|
21
|
-
"Allocations: #{event.allocations}#{cached})"
|
23
|
+
message = "#{color('[Proscenium]', nil, bold: true)} Building /#{path}"
|
24
|
+
message << " (Duration: #{event.duration.round(1)}ms | Allocations: #{event.allocations})"
|
22
25
|
end
|
23
26
|
end
|
24
27
|
|
25
|
-
def
|
28
|
+
def resolve(event)
|
26
29
|
path = event.payload[:identifier]
|
27
30
|
path = CGI.unescape(path) if path.start_with?(/https?%3A%2F%2F/)
|
28
31
|
|
29
32
|
info do
|
30
|
-
message = " #{color('[Proscenium]', nil, bold: true)}
|
33
|
+
message = " #{color('[Proscenium]', nil, bold: true)} Resolving #{path}"
|
31
34
|
message << " (Duration: #{event.duration.round(1)}ms | Allocations: #{event.allocations})"
|
32
35
|
end
|
33
36
|
end
|
34
37
|
end
|
35
38
|
end
|
36
|
-
|
37
|
-
Proscenium::LogSubscriber.attach_to :proscenium
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'oj'
|
4
|
-
|
5
3
|
module Proscenium
|
6
4
|
class Middleware
|
7
5
|
class Base
|
@@ -79,18 +77,25 @@ module Proscenium
|
|
79
77
|
end
|
80
78
|
end
|
81
79
|
|
82
|
-
def render_response(
|
80
|
+
def render_response(result)
|
81
|
+
content = result[:response]
|
82
|
+
|
83
83
|
response = Rack::Response.new
|
84
|
-
response.write content
|
85
|
-
response.content_type = content_type
|
86
84
|
response['X-Proscenium-Middleware'] = name
|
87
85
|
response.set_header 'SourceMap', "#{@request.path_info}.map"
|
86
|
+
response.content_type = content_type
|
87
|
+
response.etag = result[:content_hash]
|
88
88
|
|
89
89
|
if Proscenium.config.cache_query_string && Proscenium.config.cache_max_age
|
90
90
|
response.cache! Proscenium.config.cache_max_age
|
91
91
|
end
|
92
92
|
|
93
|
-
|
93
|
+
if @request.fresh?(response)
|
94
|
+
response.status = 304
|
95
|
+
response.body = []
|
96
|
+
else
|
97
|
+
response.write content
|
98
|
+
end
|
94
99
|
|
95
100
|
response.finish
|
96
101
|
end
|
@@ -6,22 +6,21 @@ module Proscenium
|
|
6
6
|
class CompileError < Base::CompileError
|
7
7
|
def initialize(args)
|
8
8
|
detail = args[:detail]
|
9
|
-
detail =
|
9
|
+
detail = JSON.parse(detail, mode: :strict)
|
10
10
|
|
11
|
-
args[
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
args['detail'] = if detail['location']
|
12
|
+
"#{detail['text']} in #{detail['location']['file']}:" +
|
13
|
+
detail['location']['line'].to_s
|
14
|
+
else
|
15
|
+
detail['text']
|
16
|
+
end
|
17
17
|
|
18
18
|
super
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
22
|
def attempt
|
23
|
-
render_response Builder.build_to_string(path_to_build
|
24
|
-
base_url: @request.base_url)
|
23
|
+
render_response Builder.build_to_string(path_to_build)
|
25
24
|
rescue Builder::CompileError => e
|
26
25
|
raise self.class::CompileError, { file: @request.fullpath, detail: e.message }, caller
|
27
26
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Proscenium
|
4
|
+
class Middleware
|
5
|
+
class RubyGems < Esbuild
|
6
|
+
def real_path
|
7
|
+
@real_path ||= Pathname.new(gem_request_path.delete_prefix("#{gem_name}/")).to_s
|
8
|
+
end
|
9
|
+
|
10
|
+
def root_for_readable
|
11
|
+
BundledGems.pathname_for!(gem_name)
|
12
|
+
end
|
13
|
+
|
14
|
+
def gem_name
|
15
|
+
@gem_name ||= gem_request_path.split('/').first
|
16
|
+
end
|
17
|
+
|
18
|
+
def gem_request_path
|
19
|
+
@gem_request_path ||= @request.path.delete_prefix('/node_modules/@rubygems/')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -9,8 +9,7 @@ module Proscenium
|
|
9
9
|
|
10
10
|
autoload :Base
|
11
11
|
autoload :Esbuild
|
12
|
-
autoload :
|
13
|
-
autoload :Runtime
|
12
|
+
autoload :RubyGems
|
14
13
|
|
15
14
|
def initialize(app)
|
16
15
|
@app = app
|
@@ -21,10 +20,25 @@ module Proscenium
|
|
21
20
|
end
|
22
21
|
|
23
22
|
def call(env)
|
24
|
-
request =
|
23
|
+
request = ActionDispatch::Request.new(env)
|
25
24
|
|
26
25
|
return @app.call(env) if !request.get? && !request.head?
|
27
|
-
|
26
|
+
|
27
|
+
if request.path.match?(%r{^/_asset_chunks/})
|
28
|
+
response = Rack::Response[*@chunk_handler.attempt(request.env)]
|
29
|
+
response.etag = request.path.match(/-\$([a-z0-9]+)\$/i)[1]
|
30
|
+
|
31
|
+
if Proscenium.config.cache_query_string && Proscenium.config.cache_max_age
|
32
|
+
response.cache! Proscenium.config.cache_max_age
|
33
|
+
end
|
34
|
+
|
35
|
+
if request.fresh?(response)
|
36
|
+
response.status = 304
|
37
|
+
response.body = []
|
38
|
+
end
|
39
|
+
|
40
|
+
return response.finish
|
41
|
+
end
|
28
42
|
|
29
43
|
attempt(request) || @app.call(env)
|
30
44
|
end
|
@@ -34,41 +48,29 @@ module Proscenium
|
|
34
48
|
def attempt(request)
|
35
49
|
return unless (type = find_type(request))
|
36
50
|
|
37
|
-
# file_handler.attempt(request.env) || type.attempt(request)
|
38
|
-
|
39
51
|
type.attempt request
|
40
52
|
end
|
41
53
|
|
42
54
|
def find_type(request)
|
43
|
-
return Runtime if request.path.match?(%r{^/@proscenium/})
|
44
|
-
return Esbuild if Pathname.new(request.path).fnmatch?(app_path_glob, File::FNM_EXTGLOB)
|
45
|
-
|
46
55
|
pathname = Pathname.new(request.path)
|
47
|
-
|
48
|
-
|
56
|
+
|
57
|
+
if pathname.fnmatch?(gems_path_glob, File::FNM_EXTGLOB)
|
58
|
+
RubyGems
|
59
|
+
elsif pathname.fnmatch?(app_path_glob, File::FNM_EXTGLOB)
|
60
|
+
Esbuild
|
61
|
+
end
|
49
62
|
end
|
50
63
|
|
51
64
|
def app_path_glob
|
52
65
|
"/{#{Proscenium::ALLOWED_DIRECTORIES}}/**.{#{file_extensions}}"
|
53
66
|
end
|
54
67
|
|
55
|
-
def
|
56
|
-
|
57
|
-
"/{#{names.join(',')}}/{#{Proscenium::ALLOWED_DIRECTORIES}}/**.{#{file_extensions}}"
|
58
|
-
end
|
59
|
-
|
60
|
-
def ui_path_glob
|
61
|
-
"/proscenium/ui/**.{#{file_extensions}}"
|
68
|
+
def gems_path_glob
|
69
|
+
"/node_modules/@rubygems/**.{#{file_extensions}}"
|
62
70
|
end
|
63
71
|
|
64
72
|
def file_extensions
|
65
73
|
@file_extensions ||= FILE_EXTENSIONS.join(',')
|
66
74
|
end
|
67
|
-
|
68
|
-
# TODO: handle precompiled assets
|
69
|
-
# def file_handler
|
70
|
-
# ::ActionDispatch::FileHandler.new Rails.public_path.join('assets').to_s,
|
71
|
-
# headers: { 'X-Proscenium-Middleware' => 'precompiled' }
|
72
|
-
# end
|
73
75
|
end
|
74
76
|
end
|
data/lib/proscenium/monkey.rb
CHANGED
@@ -1,24 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Proscenium
|
4
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
5
4
|
module Monkey
|
6
5
|
module TemplateRenderer
|
7
6
|
private
|
8
7
|
|
9
|
-
def render_template(view, template, layout_name, locals)
|
8
|
+
def render_template(view, template, layout_name, locals)
|
10
9
|
result = super
|
11
10
|
return result if !view.controller || !Proscenium.config.side_load
|
12
11
|
|
13
|
-
|
14
|
-
|
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
|
12
|
+
to_sideload = if template.respond_to?(:virtual_path) &&
|
13
|
+
template.respond_to?(:type) && template.type == :html
|
22
14
|
template
|
23
15
|
end
|
24
16
|
if to_sideload
|
@@ -48,7 +40,7 @@ module Proscenium
|
|
48
40
|
options[k] = controller.instance_eval(&options[k]) if options[k].is_a?(Proc)
|
49
41
|
end
|
50
42
|
|
51
|
-
Importer.sideload "app/views/#{tpl.virtual_path}", **options
|
43
|
+
Importer.sideload Rails.root.join("app/views/#{tpl.virtual_path}"), **options
|
52
44
|
end
|
53
45
|
end
|
54
46
|
|
@@ -87,9 +79,8 @@ module Proscenium
|
|
87
79
|
options[k] = controller.instance_eval(&options[k]) if options[k].is_a?(Proc)
|
88
80
|
end
|
89
81
|
|
90
|
-
Importer.sideload "app/views/#{tpl.virtual_path}", **options
|
82
|
+
Importer.sideload Rails.root.join("app/views/#{tpl.virtual_path}"), **options
|
91
83
|
end
|
92
84
|
end
|
93
85
|
end
|
94
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
95
86
|
end
|
data/lib/proscenium/railtie.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'rails'
|
4
|
-
require 'proscenium/log_subscriber'
|
5
4
|
|
6
5
|
ENV['RAILS_ENV'] = Rails.env
|
7
6
|
|
@@ -11,14 +10,11 @@ module Proscenium
|
|
11
10
|
|
12
11
|
config.proscenium = ActiveSupport::OrderedOptions.new
|
13
12
|
config.proscenium.debug = false
|
13
|
+
config.proscenium.logging = true
|
14
|
+
config.proscenium.bundle = true
|
14
15
|
config.proscenium.side_load = true
|
15
16
|
config.proscenium.code_splitting = true
|
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 = ActiveSupport::Cache::MemoryStore.new if Rails.env.production?
|
20
|
-
|
21
|
-
# TODO: implement!
|
17
|
+
config.proscenium.ensure_loaded = :raise
|
22
18
|
config.proscenium.cache_query_string = Rails.env.production? && ENV.fetch('REVISION', nil)
|
23
19
|
config.proscenium.cache_max_age = 2_592_000 # 30 days
|
24
20
|
|
@@ -27,45 +23,28 @@ module Proscenium
|
|
27
23
|
# defined means a faster build, as esbuild will have less to do.
|
28
24
|
config.proscenium.env_vars = Set.new
|
29
25
|
|
30
|
-
# Rails engines to expose and allow Proscenium to serve their assets.
|
31
|
-
#
|
32
|
-
# A Rails engine that has assets, can add Proscenium as a gem dependency, and then add itself
|
33
|
-
# to this list. Proscenium will then serve the engine's assets at the URL path beginning with
|
34
|
-
# the engine name.
|
35
|
-
#
|
36
|
-
# Example:
|
37
|
-
# class Gem1::Engine < ::Rails::Engine
|
38
|
-
# config.proscenium.engines << self
|
39
|
-
# end
|
40
|
-
config.proscenium.engines = Set.new
|
41
|
-
|
42
26
|
config.action_dispatch.rescue_templates = {
|
43
27
|
'Proscenium::Builder::BuildError' => 'build_error'
|
44
28
|
}
|
45
29
|
|
46
30
|
config.after_initialize do |_app|
|
47
|
-
|
48
|
-
|
31
|
+
if config.proscenium.logging
|
32
|
+
require 'proscenium/log_subscriber'
|
33
|
+
Proscenium::LogSubscriber.attach_to :proscenium
|
49
34
|
end
|
50
|
-
end
|
51
35
|
|
52
|
-
|
53
|
-
|
54
|
-
inflect.acronym 'UI'
|
36
|
+
ActiveSupport.on_load(:action_view) do
|
37
|
+
include Proscenium::Helper
|
55
38
|
end
|
56
39
|
end
|
57
40
|
|
58
41
|
initializer 'proscenium.debugging' do
|
59
|
-
|
60
|
-
|
61
|
-
ActionDispatch::DebugView::RESCUES_TEMPLATE_PATHS << tpl_path
|
62
|
-
end
|
42
|
+
tpl_path = root.join('lib', 'proscenium', 'templates').to_s
|
43
|
+
ActionDispatch::DebugView::RESCUES_TEMPLATE_PATHS << tpl_path
|
63
44
|
end
|
64
45
|
|
65
46
|
initializer 'proscenium.middleware' do |app|
|
66
|
-
app.middleware.insert_after ActionDispatch::Static, Middleware
|
67
|
-
app.middleware.insert_after ActionDispatch::Static, Rack::ETag, 'no-cache'
|
68
|
-
app.middleware.insert_after ActionDispatch::Static, Rack::ConditionalGet
|
47
|
+
app.middleware.insert_after ActionDispatch::Static, Proscenium::Middleware
|
69
48
|
end
|
70
49
|
|
71
50
|
initializer 'proscenium.sideloading' do
|
@@ -81,26 +60,5 @@ module Proscenium
|
|
81
60
|
ActionView::PartialRenderer.prepend Monkey::PartialRenderer
|
82
61
|
end
|
83
62
|
end
|
84
|
-
|
85
|
-
initializer 'proscenium.public_path' do |app|
|
86
|
-
if app.config.public_file_server.enabled
|
87
|
-
headers = app.config.public_file_server.headers || {}
|
88
|
-
index = app.config.public_file_server.index_name || 'index'
|
89
|
-
|
90
|
-
app.middleware.insert_after(ActionDispatch::Static, ActionDispatch::Static,
|
91
|
-
root.join('public').to_s, index:, headers:)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
if Rails.gem_version < Gem::Version.new('7.1.0')
|
98
|
-
class ActionDispatch::DebugView
|
99
|
-
def initialize(assigns)
|
100
|
-
tpl_path = Proscenium::Railtie.root.join('lib', 'proscenium', 'templates').to_s
|
101
|
-
paths = [RESCUES_TEMPLATE_PATH, tpl_path]
|
102
|
-
lookup_context = ActionView::LookupContext.new(paths)
|
103
|
-
super(lookup_context, assigns, nil)
|
104
|
-
end
|
105
63
|
end
|
106
64
|
end
|
@@ -1,15 +1,5 @@
|
|
1
|
-
window.Proscenium = window.Proscenium || { lazyScripts: {} };
|
2
1
|
const pathAttribute = "data-proscenium-component-path";
|
3
2
|
|
4
|
-
// Find lazyscripts JSON already in the DOM.
|
5
|
-
const element = document.querySelector("#prosceniumLazyScripts");
|
6
|
-
if (element) {
|
7
|
-
window.Proscenium.lazyScripts = {
|
8
|
-
...window.Proscenium.lazyScripts,
|
9
|
-
...JSON.parse(element.text),
|
10
|
-
};
|
11
|
-
}
|
12
|
-
|
13
3
|
// Find components already in the DOM.
|
14
4
|
const elements = document.querySelectorAll(`[${pathAttribute}]`);
|
15
5
|
elements.length > 0 && init(elements);
|
@@ -17,12 +7,7 @@ elements.length > 0 && init(elements);
|
|
17
7
|
new MutationObserver((mutationsList) => {
|
18
8
|
for (const { addedNodes } of mutationsList) {
|
19
9
|
for (const ele of addedNodes) {
|
20
|
-
if (ele.
|
21
|
-
window.Proscenium.lazyScripts = {
|
22
|
-
...window.Proscenium.lazyScripts,
|
23
|
-
...JSON.parse(ele.text),
|
24
|
-
};
|
25
|
-
} else if (ele.matches(`[${pathAttribute}]`)) {
|
10
|
+
if (ele.matches(`[${pathAttribute}]`)) {
|
26
11
|
init([ele]);
|
27
12
|
}
|
28
13
|
}
|
@@ -81,12 +66,8 @@ function init(elements) {
|
|
81
66
|
// For testing and simulation of slow connections.
|
82
67
|
// const sim = new Promise((resolve) => setTimeout(resolve, 5000));
|
83
68
|
|
84
|
-
|
85
|
-
|
86
|
-
}
|
87
|
-
|
88
|
-
const react = import("@proscenium/react-manager/react");
|
89
|
-
const Component = import(window.Proscenium.lazyScripts[path].outpath);
|
69
|
+
const react = import("@rubygems/proscenium/react-manager/react");
|
70
|
+
const Component = import(path);
|
90
71
|
|
91
72
|
const forwardChildren =
|
92
73
|
"prosceniumComponentForwardChildren" in element.dataset &&
|
@@ -11,7 +11,7 @@ module Proscenium
|
|
11
11
|
# The HTML tag to use as the wrapping element for the component. You can reassign this in your
|
12
12
|
# component class to use a different tag:
|
13
13
|
#
|
14
|
-
# class MyComponent < Proscenium::
|
14
|
+
# class MyComponent < Proscenium::ReactComponent
|
15
15
|
# self.root_tag = :span
|
16
16
|
# end
|
17
17
|
#
|
@@ -40,13 +40,12 @@ module Proscenium
|
|
40
40
|
class_attribute :loader
|
41
41
|
|
42
42
|
# @return [String] the URL path to the component manager.
|
43
|
-
class_attribute :manager, default: '
|
43
|
+
class_attribute :manager, default: '/proscenium/react-manager/index.jsx'
|
44
44
|
end
|
45
45
|
|
46
46
|
class_methods do
|
47
47
|
def sideload(options)
|
48
48
|
Importer.import manager, **options, js: { type: 'module' }
|
49
|
-
Importer.sideload source_path, lazy: true, **options
|
50
49
|
end
|
51
50
|
end
|
52
51
|
|