proscenium 0.9.1-arm64-darwin → 0.11.0-arm64-darwin
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +451 -65
- data/lib/proscenium/builder.rb +144 -0
- data/lib/proscenium/css_module/path.rb +31 -0
- data/lib/proscenium/css_module/transformer.rb +82 -0
- data/lib/proscenium/css_module.rb +12 -25
- data/lib/proscenium/ensure_loaded.rb +27 -0
- data/lib/proscenium/ext/proscenium +0 -0
- data/lib/proscenium/ext/proscenium.h +20 -12
- data/lib/proscenium/helper.rb +85 -0
- data/lib/proscenium/importer.rb +110 -0
- data/lib/proscenium/libs/react-manager/index.jsx +101 -0
- data/lib/proscenium/libs/react-manager/react.js +2 -0
- data/lib/proscenium/libs/stimulus-loading.js +83 -0
- data/lib/proscenium/libs/test.js +1 -0
- data/lib/proscenium/log_subscriber.rb +1 -2
- data/lib/proscenium/middleware/base.rb +8 -8
- data/lib/proscenium/middleware/engines.rb +37 -0
- data/lib/proscenium/middleware/esbuild.rb +3 -5
- data/lib/proscenium/middleware/runtime.rb +18 -0
- data/lib/proscenium/middleware.rb +19 -4
- data/lib/proscenium/{side_load/monkey.rb → monkey.rb} +24 -12
- data/lib/proscenium/phlex/{resolve_css_modules.rb → css_modules.rb} +28 -16
- data/lib/proscenium/phlex/react_component.rb +27 -64
- data/lib/proscenium/phlex.rb +11 -30
- data/lib/proscenium/railtie.rb +49 -41
- data/lib/proscenium/react_componentable.rb +95 -0
- data/lib/proscenium/resolver.rb +37 -0
- data/lib/proscenium/side_load.rb +13 -72
- data/lib/proscenium/source_path.rb +15 -0
- data/lib/proscenium/templates/rescues/build_error.html.erb +30 -0
- data/lib/proscenium/utils.rb +13 -0
- data/lib/proscenium/version.rb +1 -1
- data/lib/proscenium/view_component/css_modules.rb +11 -0
- data/lib/proscenium/view_component/react_component.rb +15 -28
- data/lib/proscenium/view_component/sideload.rb +4 -0
- data/lib/proscenium/view_component.rb +8 -31
- data/lib/proscenium.rb +23 -68
- metadata +25 -59
- data/lib/proscenium/css_module/class_names_resolver.rb +0 -66
- data/lib/proscenium/css_module/resolver.rb +0 -76
- data/lib/proscenium/current.rb +0 -9
- data/lib/proscenium/esbuild/golib.rb +0 -97
- data/lib/proscenium/esbuild.rb +0 -32
- data/lib/proscenium/phlex/component_concerns.rb +0 -27
- data/lib/proscenium/phlex/page.rb +0 -62
- data/lib/proscenium/side_load/ensure_loaded.rb +0 -25
- data/lib/proscenium/side_load/helper.rb +0 -25
- data/lib/proscenium/view_component/tag_builder.rb +0 -23
@@ -0,0 +1,83 @@
|
|
1
|
+
const controllerAttribute = "data-controller";
|
2
|
+
const controllerFilenameExtension = ".js";
|
3
|
+
|
4
|
+
export function lazyLoadControllersFrom(
|
5
|
+
under,
|
6
|
+
application,
|
7
|
+
element = document
|
8
|
+
) {
|
9
|
+
lazyLoadExistingControllers(under, application, element);
|
10
|
+
lazyLoadNewControllers(under, application, element);
|
11
|
+
}
|
12
|
+
|
13
|
+
function lazyLoadExistingControllers(under, application, element) {
|
14
|
+
queryControllerNamesWithin(element).forEach((controllerName) =>
|
15
|
+
loadController(controllerName, under, application)
|
16
|
+
);
|
17
|
+
}
|
18
|
+
|
19
|
+
function lazyLoadNewControllers(under, application, element) {
|
20
|
+
new MutationObserver((mutationsList) => {
|
21
|
+
for (const { attributeName, target, type } of mutationsList) {
|
22
|
+
switch (type) {
|
23
|
+
case "attributes": {
|
24
|
+
if (
|
25
|
+
attributeName == controllerAttribute &&
|
26
|
+
target.getAttribute(controllerAttribute)
|
27
|
+
) {
|
28
|
+
extractControllerNamesFrom(target).forEach((controllerName) =>
|
29
|
+
loadController(controllerName, under, application)
|
30
|
+
);
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
case "childList": {
|
35
|
+
lazyLoadExistingControllers(under, application, target);
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}).observe(element, {
|
40
|
+
attributeFilter: [controllerAttribute],
|
41
|
+
subtree: true,
|
42
|
+
childList: true,
|
43
|
+
});
|
44
|
+
}
|
45
|
+
|
46
|
+
function queryControllerNamesWithin(element) {
|
47
|
+
return Array.from(element.querySelectorAll(`[${controllerAttribute}]`))
|
48
|
+
.map(extractControllerNamesFrom)
|
49
|
+
.flat();
|
50
|
+
}
|
51
|
+
|
52
|
+
function extractControllerNamesFrom(element) {
|
53
|
+
return element
|
54
|
+
.getAttribute(controllerAttribute)
|
55
|
+
.split(/\s+/)
|
56
|
+
.filter((content) => content.length);
|
57
|
+
}
|
58
|
+
|
59
|
+
function loadController(name, under, application) {
|
60
|
+
if (canRegisterController(name, application)) {
|
61
|
+
import(controllerFilename(name, under))
|
62
|
+
.then((module) => registerController(name, module, application))
|
63
|
+
.catch((error) =>
|
64
|
+
console.error(`Failed to autoload controller: ${name}`, error)
|
65
|
+
);
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
function controllerFilename(name, under) {
|
70
|
+
return `${under}/${name
|
71
|
+
.replace(/--/g, "/")
|
72
|
+
.replace(/-/g, "_")}_controller${controllerFilenameExtension}`;
|
73
|
+
}
|
74
|
+
|
75
|
+
function registerController(name, module, application) {
|
76
|
+
if (canRegisterController(name, application)) {
|
77
|
+
application.register(name, module.default);
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
function canRegisterController(name, application) {
|
82
|
+
return !application.router.modulesByIdentifier.has(name);
|
83
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
console.log("/@proscenium/test.js");
|
@@ -12,12 +12,11 @@ module Proscenium
|
|
12
12
|
|
13
13
|
def build(event)
|
14
14
|
path = event.payload[:identifier]
|
15
|
-
path = path.start_with?(/https?%3A%2F%2F/)
|
15
|
+
path = CGI.unescape(path) if path.start_with?(/https?%3A%2F%2F/)
|
16
16
|
|
17
17
|
info do
|
18
18
|
message = +"[Proscenium] Building #{path}"
|
19
19
|
message << " (Duration: #{event.duration.round(1)}ms | Allocations: #{event.allocations})"
|
20
|
-
message << "\n" if defined?(Rails.env) && Rails.env.development?
|
21
20
|
end
|
22
21
|
end
|
23
22
|
end
|
@@ -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?
|
@@ -51,24 +51,24 @@ module Proscenium
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def file_readable?
|
54
|
-
return unless (path = clean_path(sourcemap? ? real_path[0...-4] : real_path))
|
54
|
+
return false unless (path = clean_path(sourcemap? ? real_path[0...-4] : real_path))
|
55
55
|
|
56
|
-
file_stat = File.stat(
|
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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
-
rescue Proscenium::Esbuild::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,16 +9,23 @@ 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)
|
15
17
|
@app = app
|
18
|
+
|
19
|
+
chunks_path = Rails.public_path.join('assets').to_s
|
20
|
+
headers = Rails.application.config.public_file_server.headers || {}
|
21
|
+
@chunk_handler = ::ActionDispatch::FileHandler.new(chunks_path, headers: headers)
|
16
22
|
end
|
17
23
|
|
18
24
|
def call(env)
|
19
25
|
request = Rack::Request.new(env)
|
20
26
|
|
21
27
|
return @app.call(env) if !request.get? && !request.head?
|
28
|
+
return @chunk_handler.attempt(request.env) if request.path.match?(%r{^/_asset_chunks/})
|
22
29
|
|
23
30
|
attempt(request) || @app.call(env)
|
24
31
|
end
|
@@ -35,12 +42,20 @@ module Proscenium
|
|
35
42
|
|
36
43
|
def find_type(request)
|
37
44
|
return Url if request.path.match?(%r{^/https?%3A%2F%2F})
|
38
|
-
return
|
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)
|
39
49
|
end
|
40
50
|
|
41
|
-
def
|
42
|
-
|
43
|
-
|
51
|
+
def app_path_glob
|
52
|
+
"/{#{Proscenium::ALLOWED_DIRECTORIES}}/**.{#{FILE_EXTENSIONS.join(',')}}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def engines_path_glob
|
56
|
+
names = Proscenium.config.engines.map(&:engine_name)
|
57
|
+
|
58
|
+
"/{#{names.join(',')}}/{#{Proscenium::ALLOWED_DIRECTORIES}}/**.{#{FILE_EXTENSIONS.join(',')}}"
|
44
59
|
end
|
45
60
|
|
46
61
|
# TODO: handle precompiled assets
|
@@ -1,12 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
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
|
+
|
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,20 +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
|
-
|
18
|
-
|
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
|
-
|
22
|
-
Proscenium::SideLoad.append "app/views/#{layout.virtual_path}" if layout
|
31
|
+
Importer.sideload "app/views/#{layout.virtual_path}" if layout
|
23
32
|
|
24
33
|
# Try side loading the variant template
|
25
34
|
if template.respond_to?(:variant) && template.variant
|
26
|
-
|
35
|
+
Importer.sideload "app/views/#{template.virtual_path}+#{template.variant}"
|
27
36
|
end
|
28
37
|
|
29
|
-
|
30
|
-
Proscenium::SideLoad.append "app/views/#{template.virtual_path}"
|
38
|
+
Importer.sideload "app/views/#{template.virtual_path}"
|
31
39
|
end
|
32
40
|
|
33
41
|
super
|
@@ -37,10 +45,14 @@ class Proscenium::SideLoad
|
|
37
45
|
module PartialRenderer
|
38
46
|
private
|
39
47
|
|
40
|
-
def
|
41
|
-
|
42
|
-
|
43
|
-
|
48
|
+
def render_partial_template(view, locals, template, layout, block)
|
49
|
+
if Proscenium.config.side_load && template.respond_to?(:virtual_path) &&
|
50
|
+
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}"
|
53
|
+
end
|
54
|
+
|
55
|
+
super
|
44
56
|
end
|
45
57
|
end
|
46
58
|
end
|
@@ -1,15 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Proscenium
|
4
|
-
module Phlex::
|
5
|
-
|
4
|
+
module Phlex::CssModules
|
5
|
+
include Proscenium::CssModule
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
def self.included(base)
|
8
|
+
base.extend CssModule::Path
|
9
|
+
base.extend ClassMethods
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
# Set of CSS module paths that have been resolved after being transformed from 'class' HTML
|
14
|
+
# attributes. See #process_attributes. This is here because Phlex caches attributes. Which
|
15
|
+
# means while the CSS class names will be transformed, any resolved paths will be lost in
|
16
|
+
# subsequent requests.
|
17
|
+
attr_accessor :resolved_css_module_paths
|
9
18
|
end
|
10
19
|
|
11
20
|
def before_template
|
12
|
-
self.class.
|
21
|
+
self.class.resolved_css_module_paths ||= Concurrent::Set.new
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
25
|
+
def after_template
|
26
|
+
self.class.resolved_css_module_paths.each do |path|
|
27
|
+
Proscenium::Importer.import path
|
28
|
+
end
|
29
|
+
|
13
30
|
super
|
14
31
|
end
|
15
32
|
|
@@ -44,24 +61,19 @@ module Proscenium
|
|
44
61
|
# end
|
45
62
|
# end
|
46
63
|
#
|
47
|
-
# The given class name should be underscored, and the resulting CSS module name will be
|
48
|
-
# `camelCased` with a lower case first character.
|
49
|
-
#
|
50
64
|
# @raise [Proscenium::CssModule::Resolver::NotFound] If a CSS module file is not found for the
|
51
65
|
# Phlex class file path.
|
52
66
|
def process_attributes(**attributes)
|
53
67
|
if attributes.key?(:class) && (attributes[:class] = tokens(attributes[:class])).include?('@')
|
54
|
-
|
55
|
-
|
56
|
-
attributes[:class] =
|
68
|
+
names = attributes[:class].is_a?(Array) ? attributes[:class] : attributes[:class].split
|
69
|
+
|
70
|
+
attributes[:class] = cssm.class_names(*names).map do |name, path|
|
71
|
+
self.class.resolved_css_module_paths << path if path
|
72
|
+
name
|
73
|
+
end
|
57
74
|
end
|
58
75
|
|
59
76
|
attributes
|
60
77
|
end
|
61
|
-
|
62
|
-
def after_template
|
63
|
-
super
|
64
|
-
self.class.side_load_cache&.each { |path| SideLoad.append! path, :css }
|
65
|
-
end
|
66
78
|
end
|
67
79
|
end
|
@@ -1,69 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
# Renders a div for use with
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
class
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
3
|
+
module Proscenium
|
4
|
+
# Renders a <div> for use with React components, with data attributes specifying the component
|
5
|
+
# path and props.
|
6
|
+
#
|
7
|
+
# If a block is given, it will be yielded within the div, allowing for a custom "loading" UI. If
|
8
|
+
# no block is given, then a "loading..." text will be rendered. It is intended that the component
|
9
|
+
# is mounted to this div, and the loading UI will then be replaced with the component's rendered
|
10
|
+
# output.
|
11
|
+
#
|
12
|
+
# You can pass props to the component in the `:props` keyword argument.
|
13
|
+
class Phlex::ReactComponent < Phlex
|
14
|
+
self.abstract_class = true
|
15
|
+
|
16
|
+
include ReactComponentable
|
17
|
+
|
18
|
+
# Override this to provide your own loading UI.
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# def template(**attributes, &block)
|
22
|
+
# super do
|
23
|
+
# 'Look at me! I am loading now...'
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# @yield the given block to a `div` within the top level component div.
|
28
|
+
def template(**attributes, &block)
|
29
|
+
send root_tag, **{ data: data_attributes }.deep_merge(attributes), &block
|
22
30
|
end
|
23
31
|
end
|
24
|
-
|
25
|
-
self.abstract_class = true
|
26
|
-
|
27
|
-
include Proscenium::Phlex::ComponentConcerns::CssModules
|
28
|
-
|
29
|
-
attr_writer :props, :lazy
|
30
|
-
|
31
|
-
# @param props: [Hash]
|
32
|
-
# @param lazy: [Boolean] Lazy load the component using IntersectionObserver. Default: true.
|
33
|
-
def initialize(props: {}, lazy: true) # rubocop:disable Lint/MissingSuper
|
34
|
-
@props = props
|
35
|
-
@lazy = lazy
|
36
|
-
end
|
37
|
-
|
38
|
-
# @yield the given block to a `div` within the top level component div. If not given,
|
39
|
-
# `<div>loading...</div>` will be rendered. Use this to display a loading UI while the component
|
40
|
-
# is loading and rendered.
|
41
|
-
def template(**attributes, &block)
|
42
|
-
component_root(:div, **attributes, &block)
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
def component_root(element, **attributes, &block)
|
48
|
-
send element, data: { proscenium_component: component_data }, **attributes, &block
|
49
|
-
end
|
50
|
-
|
51
|
-
def props
|
52
|
-
@props ||= {}
|
53
|
-
end
|
54
|
-
|
55
|
-
def lazy
|
56
|
-
instance_variable_defined?(:@lazy) ? @lazy : (@lazy = false)
|
57
|
-
end
|
58
|
-
|
59
|
-
def component_data
|
60
|
-
{
|
61
|
-
path: virtual_path, lazy: lazy,
|
62
|
-
props: props.deep_transform_keys { |k| k.to_s.camelize :lower }
|
63
|
-
}.to_json
|
64
|
-
end
|
65
|
-
|
66
|
-
def virtual_path
|
67
|
-
path.to_s.delete_prefix(Rails.root.to_s)
|
68
|
-
end
|
69
32
|
end
|
data/lib/proscenium/phlex.rb
CHANGED
@@ -5,54 +5,35 @@ require 'phlex-rails'
|
|
5
5
|
module Proscenium
|
6
6
|
class Phlex < ::Phlex::HTML
|
7
7
|
extend ActiveSupport::Autoload
|
8
|
-
include Proscenium::CssModule
|
9
8
|
|
10
|
-
autoload :
|
9
|
+
autoload :CssModules
|
11
10
|
autoload :ReactComponent
|
12
|
-
autoload :ResolveCssModules
|
13
|
-
autoload :ComponentConcerns
|
14
11
|
|
15
12
|
extend ::Phlex::Rails::HelperMacros
|
16
13
|
include ::Phlex::Rails::Helpers::JavaScriptIncludeTag
|
17
14
|
include ::Phlex::Rails::Helpers::StyleSheetLinkTag
|
15
|
+
include Proscenium::SourcePath
|
16
|
+
include CssModules
|
18
17
|
|
19
|
-
define_output_helper :side_load_stylesheets
|
20
|
-
define_output_helper :
|
18
|
+
define_output_helper :side_load_stylesheets # deprecated
|
19
|
+
define_output_helper :include_stylesheets
|
20
|
+
define_output_helper :side_load_javascripts # deprecated
|
21
|
+
define_output_helper :include_javascripts
|
22
|
+
define_output_helper :declare_lazy_scripts
|
21
23
|
|
22
|
-
# Side loads the class, and its super classes that respond to `.path`. Assign the
|
23
|
-
# `abstract_class` class variable to any abstract class, and it will not be side loaded.
|
24
|
-
# Additionally, if the class responds to `side_load`, then that method is called.
|
25
24
|
module Sideload
|
26
25
|
def before_template
|
27
|
-
|
28
|
-
|
29
|
-
if !klass.abstract_class && respond_to?(:side_load, true)
|
30
|
-
side_load
|
31
|
-
klass = klass.superclass
|
32
|
-
end
|
33
|
-
|
34
|
-
while !klass.abstract_class && klass.respond_to?(:path) && klass.path
|
35
|
-
Proscenium::SideLoad.append klass.path
|
36
|
-
klass = klass.superclass
|
37
|
-
end
|
26
|
+
Proscenium::SideLoad.sideload_inheritance_chain self
|
38
27
|
|
39
28
|
super
|
40
29
|
end
|
41
30
|
end
|
42
31
|
|
43
32
|
class << self
|
44
|
-
attr_accessor :
|
33
|
+
attr_accessor :abstract_class
|
45
34
|
|
46
35
|
def inherited(child)
|
47
|
-
|
48
|
-
child.path = if caller_locations(1, 1).first.label == 'inherited'
|
49
|
-
Pathname.new caller_locations(2, 1).first.path
|
50
|
-
else
|
51
|
-
Pathname.new caller_locations(1, 1).first.path
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
child.prepend Sideload if Rails.application.config.proscenium.side_load
|
36
|
+
child.prepend Sideload
|
56
37
|
|
57
38
|
super
|
58
39
|
end
|