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.
- checksums.yaml +4 -4
- data/README.md +207 -45
- data/lib/proscenium/builder.rb +41 -19
- 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 +3 -2
- 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/test.js +1 -0
- data/lib/proscenium/middleware/base.rb +7 -7
- 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 +14 -4
- data/lib/proscenium/{side_load/monkey.rb → monkey.rb} +19 -15
- data/lib/proscenium/phlex/{resolve_css_modules.rb → css_modules.rb} +28 -16
- data/lib/proscenium/phlex/react_component.rb +26 -27
- data/lib/proscenium/phlex.rb +11 -30
- data/lib/proscenium/railtie.rb +44 -46
- data/lib/proscenium/react_componentable.rb +95 -0
- data/lib/proscenium/resolver.rb +37 -0
- data/lib/proscenium/side_load.rb +13 -73
- 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 -15
- data/lib/proscenium/view_component/sideload.rb +4 -0
- data/lib/proscenium/view_component.rb +8 -38
- data/lib/proscenium.rb +22 -68
- metadata +23 -30
- data/lib/proscenium/componentable.rb +0 -63
- 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/phlex/component_concerns.rb +0 -9
- 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 -41
- 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
|
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
|
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
|
-
|
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
|
-
|
14
|
+
include ReactComponentable
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
@@ -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 :
|
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
|
-
|
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 :
|
24
|
+
attr_accessor :abstract_class
|
35
25
|
|
36
26
|
def inherited(child)
|
37
|
-
child.
|
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
|
-
|
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 :
|
23
|
+
autoload :ReactComponentable
|
13
24
|
autoload :ViewComponent
|
14
25
|
autoload :Phlex
|
15
26
|
autoload :Helper
|
16
27
|
autoload :Builder
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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.
|
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-
|
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.
|
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.
|
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/
|
110
|
-
- lib/proscenium/css_module/
|
111
|
-
- lib/proscenium/
|
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/
|
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/
|
129
|
-
- lib/proscenium/
|
130
|
-
- lib/proscenium/
|
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/
|
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.
|
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
|
data/lib/proscenium/current.rb
DELETED
@@ -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
|