proscenium 0.10.0-arm64-darwin → 0.11.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.
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
@@ -1,22 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- #
4
- # Renders a <div> for use with React components, with data attributes specifying the component path
5
- # and props.
6
- #
7
- # If a content block is given, that content will be rendered inside the component, allowing for a
8
- # "loading" UI. If no block is given, then a "loading..." text will be rendered. It is intended that
9
- # the component is mounted to this div, and the loading UI will then be replaced with the
10
- # component's rendered output.
11
- #
12
- class Proscenium::ViewComponent::ReactComponent < Proscenium::ViewComponent
13
- self.abstract_class = true
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 content block is given, that content will be rendered inside the component, allowing for a
8
+ # "loading" UI. If no block is given, then a "loading..." text will be rendered. It is intended
9
+ # that the component is mounted to this div, and the loading UI will then be replaced with the
10
+ # component's rendered output.
11
+ class ViewComponent::ReactComponent < ViewComponent
12
+ self.abstract_class = true
14
13
 
15
- include Proscenium::Componentable
14
+ include ReactComponentable
16
15
 
17
- def call
18
- tag.send root_tag, data: data_attributes do
19
- tag.div content || 'loading...'
16
+ def call
17
+ tag.send root_tag, data: data_attributes do
18
+ tag.div content || 'loading...'
19
+ end
20
20
  end
21
21
  end
22
22
  end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Proscenium::ViewComponent::Sideload
4
+ end
@@ -4,59 +4,29 @@ require 'view_component'
4
4
 
5
5
  class Proscenium::ViewComponent < ViewComponent::Base
6
6
  extend ActiveSupport::Autoload
7
- include Proscenium::CssModule
8
7
 
9
- autoload :TagBuilder
8
+ autoload :Sideload
10
9
  autoload :ReactComponent
10
+ autoload :CssModules
11
+
12
+ include Proscenium::SourcePath
13
+ include CssModules
11
14
 
12
- # Side loads the class, and its super classes that respond to `.path`. Assign the `abstract_class`
13
- # class variable to any abstract class, and it will not be side loaded. Additionally, if the class
14
- # responds to `side_load`, then that method is called.
15
15
  module Sideload
16
16
  def before_render
17
- klass = self.class
18
-
19
- if !klass.abstract_class && respond_to?(:side_load, true)
20
- side_load
21
- klass = klass.superclass
22
- end
23
-
24
- while !klass.abstract_class && klass.respond_to?(:path) && klass.path
25
- Proscenium::SideLoad.append klass.path
26
- klass = klass.superclass
27
- end
17
+ Proscenium::SideLoad.sideload_inheritance_chain self
28
18
 
29
19
  super
30
20
  end
31
21
  end
32
22
 
33
23
  class << self
34
- attr_accessor :path, :abstract_class
24
+ attr_accessor :abstract_class
35
25
 
36
26
  def inherited(child)
37
- child.path = if caller_locations(1, 1).first.label == 'inherited'
38
- Pathname.new caller_locations(2, 1).first.path
39
- else
40
- Pathname.new caller_locations(1, 1).first.path
41
- end
42
-
43
- child.prepend Sideload if Rails.application.config.proscenium.side_load
27
+ child.prepend Sideload
44
28
 
45
29
  super
46
30
  end
47
31
  end
48
-
49
- # @override Auto compilation of class names to css modules.
50
- def render_in(...)
51
- cssm.compile_class_names(super(...))
52
- end
53
-
54
- private
55
-
56
- # Overrides ActionView::Helpers::TagHelper::TagBuilder, allowing us to intercept the
57
- # `css_module` option from the HTML options argument of the `tag` and `content_tag` helpers, and
58
- # prepend it to the HTML `class` attribute.
59
- def tag_builder
60
- @tag_builder ||= Proscenium::ViewComponent::TagBuilder.new(self)
61
- end
62
32
  end
data/lib/proscenium.rb CHANGED
@@ -5,19 +5,35 @@ require 'active_support/dependencies/autoload'
5
5
  module Proscenium
6
6
  extend ActiveSupport::Autoload
7
7
 
8
- autoload :Current
8
+ FILE_EXTENSIONS = ['js', 'mjs', 'ts', 'jsx', 'tsx', 'css', 'js.map', 'mjs.map', 'jsx.map',
9
+ 'ts.map', 'tsx.map', 'css.map'].freeze
10
+
11
+ ALLOWED_DIRECTORIES = 'app,lib,config,vendor,node_modules'
12
+
13
+ # Environment variables that should always be passed to the builder.
14
+ DEFAULT_ENV_VARS = Set['RAILS_ENV', 'NODE_ENV'].freeze
15
+
16
+ autoload :SourcePath
17
+ autoload :Utils
18
+ autoload :Monkey
9
19
  autoload :Middleware
20
+ autoload :EnsureLoaded
10
21
  autoload :SideLoad
11
22
  autoload :CssModule
12
- autoload :Componentable
23
+ autoload :ReactComponentable
13
24
  autoload :ViewComponent
14
25
  autoload :Phlex
15
26
  autoload :Helper
16
27
  autoload :Builder
17
-
18
- def self.reset_current_side_loaded
19
- Current.reset
20
- Current.loaded = SideLoad::EXTENSIONS.to_h { |e| [e, Set.new] }
28
+ autoload :Importer
29
+ autoload :Resolver
30
+
31
+ class Deprecator
32
+ def deprecation_warning(name, message, _caller_backtrace = nil)
33
+ msg = "`#{name}` is deprecated and will be removed in a near future release of Proscenium"
34
+ msg << " (#{message})" if message
35
+ Kernel.warn msg
36
+ end
21
37
  end
22
38
 
23
39
  class PathResolutionFailed < StandardError
@@ -30,68 +46,6 @@ module Proscenium
30
46
  "Path #{@path.inspect} cannot be resolved"
31
47
  end
32
48
  end
33
-
34
- module Utils
35
- module_function
36
-
37
- # @param value [#to_s] The value to create the digest from. This will usually be a `Pathname`.
38
- # @return [String] string digest of the given value.
39
- def digest(value)
40
- Digest::SHA1.hexdigest(value.to_s)[..7]
41
- end
42
-
43
- # Resolve the given `path` to a URL path.
44
- #
45
- # @param path [String] Can be URL path, file system path, or bare specifier (ie. NPM package).
46
- # @return [String] URL path.
47
- def resolve_path(path) # rubocop:disable Metrics/AbcSize
48
- raise ArgumentError, 'path must be a string' unless path.is_a?(String)
49
-
50
- if path.starts_with?('./', '../')
51
- raise ArgumentError, 'path must be an absolute file system or URL path'
52
- end
53
-
54
- matched_gem = Proscenium.config.side_load_gems.find do |_, opts|
55
- path.starts_with?("#{opts[:root]}/")
56
- end
57
-
58
- if matched_gem
59
- sroot = "#{matched_gem[1][:root]}/"
60
- relpath = path.delete_prefix(sroot)
61
-
62
- if (package_name = matched_gem[1][:package_name] || matched_gem[0])
63
- return Builder.resolve("#{package_name}/#{relpath}")
64
- end
65
-
66
- # TODO: manually resolve the path without esbuild
67
- raise PathResolutionFailed, path
68
- end
69
-
70
- return path.delete_prefix(Rails.root.to_s) if path.starts_with?("#{Rails.root}/")
71
-
72
- Builder.resolve(path)
73
- end
74
-
75
- # Resolves CSS class `names` to CSS module names. Each name will be converted to a CSS module
76
- # name, consisting of the camelCased name (lower case first character), and suffixed with the
77
- # given `digest`.
78
- #
79
- # @param names [String, Array]
80
- # @param digest: [String]
81
- # @returns [Array] of class names generated from the given CSS module `names` and `digest`.
82
- def css_modularise_class_names(*names, digest: nil)
83
- names.flatten.compact.map { |name| css_modularise_class_name name, digest: digest }
84
- end
85
-
86
- def css_modularise_class_name(name, digest: nil)
87
- sname = name.to_s
88
- if sname.starts_with?('_')
89
- "_#{sname[1..].camelize(:lower)}#{digest}"
90
- else
91
- "#{sname.camelize(:lower)}#{digest}"
92
- end
93
- end
94
- end
95
49
  end
96
50
 
97
51
  require 'proscenium/railtie'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: proscenium
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: arm64-darwin
6
6
  authors:
7
7
  - Joel Moss
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-15 00:00:00.000000000 Z
11
+ date: 2023-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -36,28 +36,14 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 1.15.5
39
+ version: 1.16.3
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: 1.15.5
47
- - !ruby/object:Gem::Dependency
48
- name: nokogiri
49
- requirement: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - "~>"
52
- - !ruby/object:Gem::Version
53
- version: '1.13'
54
- type: :runtime
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - "~>"
59
- - !ruby/object:Gem::Version
60
- version: '1.13'
46
+ version: 1.16.3
61
47
  - !ruby/object:Gem::Dependency
62
48
  name: oj
63
49
  requirement: !ruby/object:Gem::Requirement
@@ -104,34 +90,41 @@ files:
104
90
  - README.md
105
91
  - lib/proscenium.rb
106
92
  - lib/proscenium/builder.rb
107
- - lib/proscenium/componentable.rb
108
93
  - lib/proscenium/css_module.rb
109
- - lib/proscenium/css_module/class_names_resolver.rb
110
- - lib/proscenium/css_module/resolver.rb
111
- - lib/proscenium/current.rb
94
+ - lib/proscenium/css_module/path.rb
95
+ - lib/proscenium/css_module/transformer.rb
96
+ - lib/proscenium/ensure_loaded.rb
112
97
  - lib/proscenium/ext/proscenium
113
98
  - lib/proscenium/ext/proscenium.h
114
99
  - lib/proscenium/helper.rb
100
+ - lib/proscenium/importer.rb
101
+ - lib/proscenium/libs/react-manager/index.jsx
102
+ - lib/proscenium/libs/react-manager/react.js
115
103
  - lib/proscenium/libs/stimulus-loading.js
104
+ - lib/proscenium/libs/test.js
116
105
  - lib/proscenium/log_subscriber.rb
117
106
  - lib/proscenium/middleware.rb
118
107
  - lib/proscenium/middleware/base.rb
108
+ - lib/proscenium/middleware/engines.rb
119
109
  - lib/proscenium/middleware/esbuild.rb
110
+ - lib/proscenium/middleware/runtime.rb
120
111
  - lib/proscenium/middleware/url.rb
112
+ - lib/proscenium/monkey.rb
121
113
  - lib/proscenium/phlex.rb
122
- - lib/proscenium/phlex/component_concerns.rb
123
- - lib/proscenium/phlex/page.rb
114
+ - lib/proscenium/phlex/css_modules.rb
124
115
  - lib/proscenium/phlex/react_component.rb
125
- - lib/proscenium/phlex/resolve_css_modules.rb
126
116
  - lib/proscenium/railtie.rb
117
+ - lib/proscenium/react_componentable.rb
118
+ - lib/proscenium/resolver.rb
127
119
  - lib/proscenium/side_load.rb
128
- - lib/proscenium/side_load/ensure_loaded.rb
129
- - lib/proscenium/side_load/helper.rb
130
- - lib/proscenium/side_load/monkey.rb
120
+ - lib/proscenium/source_path.rb
121
+ - lib/proscenium/templates/rescues/build_error.html.erb
122
+ - lib/proscenium/utils.rb
131
123
  - lib/proscenium/version.rb
132
124
  - lib/proscenium/view_component.rb
125
+ - lib/proscenium/view_component/css_modules.rb
133
126
  - lib/proscenium/view_component/react_component.rb
134
- - lib/proscenium/view_component/tag_builder.rb
127
+ - lib/proscenium/view_component/sideload.rb
135
128
  homepage: https://github.com/joelmoss/proscenium
136
129
  licenses:
137
130
  - MIT
@@ -155,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
155
148
  - !ruby/object:Gem::Version
156
149
  version: '0'
157
150
  requirements: []
158
- rubygems_version: 3.4.13
151
+ rubygems_version: 3.4.20
159
152
  signing_key:
160
153
  specification_version: 4
161
154
  summary: The engine powering your Rails frontend
@@ -1,63 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Proscenium::Componentable
4
- extend ActiveSupport::Concern
5
-
6
- included do
7
- # @return [Hash] the props to pass to the React component.
8
- attr_writer :props
9
-
10
- # The HTML tag to use as the wrapping element for the component. You can reassign this in your
11
- # component class to use a different tag:
12
- #
13
- # class MyComponent < Proscenium::ViewComponent::ReactComponent
14
- # self.root_tag = :span
15
- # end
16
- #
17
- # @return [Symbol]
18
- class_attribute :root_tag, instance_predicate: false, default: :div
19
-
20
- # Should the template block be forwarded as children to the React component?
21
- #
22
- # @return [Boolean]
23
- class_attribute :forward_children, default: false
24
- end
25
-
26
- # @param props: [Hash]
27
- def initialize(props: {})
28
- @props = props
29
-
30
- super()
31
- end
32
-
33
- def virtual_path
34
- Proscenium::Utils.resolve_path path.sub_ext('.jsx').to_s
35
- end
36
-
37
- private
38
-
39
- def data_attributes
40
- d = {
41
- proscenium_component_path: virtual_path,
42
- proscenium_component_props: prepared_props
43
- }
44
-
45
- d[:proscenium_component_forward_children] = true if forward_children?
46
-
47
- d
48
- end
49
-
50
- def props
51
- @props ||= {}
52
- end
53
-
54
- def prepared_props
55
- props.deep_transform_keys do |term|
56
- # This ensures that the first letter after a slash is not capitalized.
57
- string = term.to_s.split('/').map { |str| str.camelize :lower }.join('/')
58
-
59
- # Reverses the effect of ActiveSupport::Inflector.camelize converting slashes into `::`.
60
- string.gsub '::', '/'
61
- end.to_json
62
- end
63
- end
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Proscenium
4
- class CssModule::ClassNamesResolver
5
- def initialize(class_names, phlex_path)
6
- @class_names = class_names.split
7
- @stylesheets = {}
8
- @phlex_path = phlex_path.sub_ext('.module.css')
9
-
10
- resolve_class_names
11
- end
12
-
13
- def class_names
14
- @class_names.join(' ')
15
- end
16
-
17
- def stylesheets
18
- @stylesheets.map { |_, values| values[:resolved_path] }
19
- end
20
-
21
- private
22
-
23
- def resolve_class_names
24
- @class_names.map! do |class_name|
25
- if class_name.include?('/')
26
- if class_name.starts_with?('@')
27
- # Scoped bare specifier (eg. "@scoped/package/lib/button@default").
28
- _, path, name = class_name.split('@')
29
- path = "@#{path}"
30
- elsif class_name.starts_with?('/')
31
- # Local path with leading slash.
32
- path, name = class_name[1..].split('@')
33
- else
34
- # Bare specifier (eg. "mypackage/lib/button@default").
35
- path, name = class_name.split('@')
36
- end
37
-
38
- path += '.module.css'
39
-
40
- Utils.css_modularise_class_name name, digest: add_stylesheet(path)[:digest]
41
- elsif class_name.starts_with?('@')
42
- Utils.css_modularise_class_name class_name[1..],
43
- digest: add_stylesheet(@phlex_path)[:digest]
44
- else
45
- class_name
46
- end
47
- end
48
- end
49
-
50
- def add_stylesheet(path)
51
- return @stylesheets[path] if @stylesheets.key?(path)
52
-
53
- resolved_path = Utils.resolve_path(path.to_s)
54
-
55
- unless Rails.root.join(resolved_path[1..]).exist?
56
- raise CssModule::StylesheetNotFound, resolved_path
57
- end
58
-
59
- # Note that the digest is based on the resolved (URL) path, not the original path.
60
- @stylesheets[path] = {
61
- resolved_path: resolved_path,
62
- digest: Utils.digest(resolved_path)
63
- }
64
- end
65
- end
66
- end
@@ -1,76 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Proscenium
4
- class CssModule::Resolver
5
- attr_reader :side_loaded_paths
6
-
7
- # @param path [Pathname] Absolute file system path to the Ruby file that will be side loaded.
8
- def initialize(path, side_load: true, hash: nil)
9
- raise ArgumentError, "'#{path}' must be a `Pathname`" unless path.is_a?(Pathname)
10
-
11
- @path = path
12
- @hash = hash
13
- @css_module_path = path.sub_ext('.module.css')
14
- @side_load = side_load
15
- @side_loaded_paths = nil
16
- end
17
-
18
- # Parses the given `content` for CSS modules names ('class' attributes beginning with '@'), and
19
- # returns the content with said CSS Modules replaced with the compiled class names.
20
- #
21
- # Example:
22
- # <div class="@my_css_module_name"></div>
23
- def compile_class_names(content)
24
- doc = Nokogiri::HTML::DocumentFragment.parse(content)
25
-
26
- return content if (modules = doc.css('[class*="@"]')).empty?
27
-
28
- modules.each do |ele|
29
- classes = ele.classes.map { |cls| cls.starts_with?('@') ? class_names!(cls[1..]) : cls }
30
- ele['class'] = classes.join(' ')
31
- end
32
-
33
- doc.to_html.html_safe
34
- end
35
-
36
- # Resolves the given CSS class names to CSS modules. This will also side load the stylesheet if
37
- # it exists.
38
- #
39
- # @param names [String, Array]
40
- # @returns [Array] of class names generated from the given CSS module `names`.
41
- def class_names(*names)
42
- side_load_css_module
43
- Utils.css_modularise_class_names names, digest: @hash
44
- end
45
-
46
- # Like #class_names, but requires that the stylesheet exists.
47
- #
48
- # @param names [String, Array]
49
- # @raises Proscenium::CssModule::NotFound if stylesheet does not exists.
50
- # @see #class_names
51
- def class_names!(...)
52
- raise CssModule::StylesheetNotFound, @css_module_path unless @css_module_path.exist?
53
-
54
- class_names(...)
55
- end
56
-
57
- def side_loaded?
58
- @side_loaded_paths.present?
59
- end
60
-
61
- private
62
-
63
- def side_load_css_module
64
- return if !@side_load || !Rails.application.config.proscenium.side_load
65
-
66
- paths = SideLoad.append @path, { '.module.css' => :css }
67
-
68
- @side_loaded_paths = if paths.empty?
69
- nil
70
- else
71
- @hash = Utils.digest(paths[0])
72
- paths
73
- end
74
- end
75
- end
76
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_support/current_attributes'
4
-
5
- module Proscenium
6
- class Current < ActiveSupport::CurrentAttributes
7
- attribute :loaded
8
- end
9
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Proscenium::Phlex::ComponentConcerns
4
- module CssModules
5
- extend ActiveSupport::Concern
6
- include Proscenium::CssModule
7
- include Proscenium::Phlex::ResolveCssModules
8
- end
9
- end
@@ -1,62 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'phlex/rails'
4
-
5
- # Include this in your view for additional logic for rendering a full HTML page, usually from a
6
- # controller.
7
- module Proscenium::Phlex::Page
8
- include Phlex::Rails::Helpers::CSPMetaTag
9
- include Phlex::Rails::Helpers::CSRFMetaTags
10
- include Phlex::Rails::Helpers::FaviconLinkTag
11
- include Phlex::Rails::Helpers::PreloadLinkTag
12
- include Phlex::Rails::Helpers::StyleSheetLinkTag
13
- include Phlex::Rails::Helpers::ActionCableMetaTag
14
- include Phlex::Rails::Helpers::AutoDiscoveryLinkTag
15
- include Phlex::Rails::Helpers::JavaScriptIncludeTag
16
- include Phlex::Rails::Helpers::JavaScriptImportMapTags
17
- include Phlex::Rails::Helpers::JavaScriptImportModuleTag
18
-
19
- def self.included(klass)
20
- klass.extend(Phlex::Rails::Layout::Interface)
21
- end
22
-
23
- def template(&block)
24
- doctype
25
- html do
26
- head
27
- body(&block)
28
- end
29
- end
30
-
31
- private
32
-
33
- def after_template
34
- super
35
- @_buffer.gsub!('<!-- [SIDE_LOAD_STYLESHEETS] -->', capture { side_load_stylesheets })
36
- end
37
-
38
- def page_title
39
- Rails.application.class.name.deconstantize
40
- end
41
-
42
- def head
43
- super do
44
- title { page_title }
45
-
46
- yield if block_given?
47
-
48
- csp_meta_tag
49
- csrf_meta_tags
50
-
51
- comment { '[SIDE_LOAD_STYLESHEETS]' }
52
- end
53
- end
54
-
55
- def body
56
- super do
57
- yield if block_given?
58
-
59
- side_load_javascripts type: :module, defer: true
60
- end
61
- end
62
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Proscenium::SideLoad
4
- module EnsureLoaded
5
- def self.included(child)
6
- child.class_eval do
7
- append_after_action do
8
- if request.format.html? && Proscenium::Current.loaded
9
- if Proscenium::Current.loaded[:js].present?
10
- raise NotIncludedError, 'There are javascripts to be side loaded, but they have ' \
11
- 'not been included. Did you forget to add the ' \
12
- '`#side_load_javascripts` helper in your views?'
13
- end
14
-
15
- if Proscenium::Current.loaded[:css].present?
16
- raise NotIncludedError, 'There are stylesheets to be side loaded, but they have ' \
17
- 'notbeen included. Did you forget to add the ' \
18
- '`#side_load_stylesheets` helper in your views?'
19
- end
20
- end
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Proscenium
4
- module SideLoad::Helper
5
- def side_load_stylesheets(**options)
6
- return unless Proscenium::Current.loaded
7
-
8
- out = []
9
- Proscenium::Current.loaded[:css].delete_if do |path|
10
- out << stylesheet_link_tag(path, extname: false, **options)
11
- end
12
- out.join("\n").html_safe
13
- end
14
-
15
- def side_load_javascripts(**options) # rubocop:disable Metrics/AbcSize
16
- return unless Proscenium::Current.loaded
17
-
18
- out = []
19
- paths = Proscenium::Current.loaded[:js]
20
-
21
- if Rails.application.config.proscenium.code_splitting && paths.size > 1
22
- public_path = Rails.public_path.to_s
23
- paths_to_build = []
24
- paths.delete_if { |x| paths_to_build << x.delete_prefix('/') }
25
-
26
- result = Proscenium::Builder.build(paths_to_build.join(';'), base_url: request.base_url)
27
- result.split(';').each do |x|
28
- next if x.include?('public/assets/_asset_chunks/') || x.end_with?('.map')
29
-
30
- out << javascript_include_tag(x.delete_prefix(public_path), extname: false, **options)
31
- end
32
- else
33
- paths.delete_if do |x|
34
- out << javascript_include_tag(x, extname: false, **options)
35
- end
36
- end
37
-
38
- out.join("\n").html_safe
39
- end
40
- end
41
- end