proscenium 0.10.0-arm64-darwin → 0.11.0-arm64-darwin

Sign up to get free protection for your applications and to get access to all the features.
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