proscenium 0.1.0.alpha1-x86_64-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 +7 -0
  2. data/CODE_OF_CONDUCT.md +84 -0
  3. data/README.md +91 -0
  4. data/lib/proscenium/cli/argument_error.js +24 -0
  5. data/lib/proscenium/cli/builders/index.js +1 -0
  6. data/lib/proscenium/cli/builders/javascript.js +45 -0
  7. data/lib/proscenium/cli/builders/react.js +60 -0
  8. data/lib/proscenium/cli/builders/solid.js +46 -0
  9. data/lib/proscenium/cli/esbuild/env_plugin.js +21 -0
  10. data/lib/proscenium/cli/esbuild/resolve_plugin.js +136 -0
  11. data/lib/proscenium/cli/esbuild/solidjs_plugin.js +23 -0
  12. data/lib/proscenium/cli/js_builder.js +194 -0
  13. data/lib/proscenium/cli/solid.js +15 -0
  14. data/lib/proscenium/cli/utils.js +93 -0
  15. data/lib/proscenium/compiler.js +84 -0
  16. data/lib/proscenium/compilers/esbuild/argument_error.js +22 -0
  17. data/lib/proscenium/compilers/esbuild/env_plugin.js +21 -0
  18. data/lib/proscenium/compilers/esbuild/resolve_plugin.js +145 -0
  19. data/lib/proscenium/compilers/esbuild/setup_plugin.js +35 -0
  20. data/lib/proscenium/compilers/esbuild.bench.js +9 -0
  21. data/lib/proscenium/compilers/esbuild.js +82 -0
  22. data/lib/proscenium/css_module.rb +22 -0
  23. data/lib/proscenium/current.rb +9 -0
  24. data/lib/proscenium/helper.rb +32 -0
  25. data/lib/proscenium/link_to_helper.rb +49 -0
  26. data/lib/proscenium/middleware/base.rb +94 -0
  27. data/lib/proscenium/middleware/esbuild.rb +27 -0
  28. data/lib/proscenium/middleware/parcel_css.rb +37 -0
  29. data/lib/proscenium/middleware/runtime.rb +22 -0
  30. data/lib/proscenium/middleware/static.rb +14 -0
  31. data/lib/proscenium/middleware.rb +66 -0
  32. data/lib/proscenium/precompile.rb +31 -0
  33. data/lib/proscenium/railtie.rb +116 -0
  34. data/lib/proscenium/runtime/auto_reload.js +22 -0
  35. data/lib/proscenium/runtime/component_manager/index.js +27 -0
  36. data/lib/proscenium/runtime/component_manager/render_component.js +40 -0
  37. data/lib/proscenium/runtime/import_css.js +46 -0
  38. data/lib/proscenium/runtime/react_shim/index.js +1 -0
  39. data/lib/proscenium/runtime/react_shim/package.json +5 -0
  40. data/lib/proscenium/side_load.rb +96 -0
  41. data/lib/proscenium/version.rb +5 -0
  42. data/lib/proscenium/view_component/tag_builder.rb +23 -0
  43. data/lib/proscenium/view_component.rb +38 -0
  44. data/lib/proscenium.rb +18 -0
  45. data/lib/tasks/assets.rake +19 -0
  46. metadata +179 -0
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Proscenium
4
+ module SideLoad
5
+ DEFAULT_EXTENSIONS = %i[js css].freeze
6
+ EXTENSIONS = %i[js css].freeze
7
+
8
+ class NotFound < StandardError
9
+ def initialize(pathname)
10
+ @pathname = pathname
11
+ super
12
+ end
13
+
14
+ def message
15
+ "#{@pathname} does not exist"
16
+ end
17
+ end
18
+
19
+ module_function
20
+
21
+ # Side load the given asset `path`, by appending it to `Proscenium::Current.loaded`, which is a
22
+ # Set of 'js' and 'css' asset paths. This is safe to call multiple times, as it uses Set's.
23
+ # Meaning that side loading will never include duplicates.
24
+ def append(path, *extensions)
25
+ Proscenium::Current.loaded ||= EXTENSIONS.to_h { |e| [e, Set[]] }
26
+
27
+ unless (unknown_extensions = extensions.difference(EXTENSIONS)).empty?
28
+ raise ArgumentError, "unsupported extension(s): #{unknown_extensions.join(',')}"
29
+ end
30
+
31
+ loaded_types = []
32
+
33
+ (extensions.empty? ? DEFAULT_EXTENSIONS : extensions).each do |ext|
34
+ path_with_ext = "#{path}.#{ext}"
35
+ ext = ext.to_sym
36
+
37
+ next if Proscenium::Current.loaded[ext].include?(path_with_ext)
38
+ next unless Rails.root.join(path_with_ext).exist?
39
+
40
+ Proscenium::Current.loaded[ext] << path_with_ext
41
+ loaded_types << ext
42
+ end
43
+
44
+ !loaded_types.empty? && Rails.logger.debug do
45
+ "[Proscenium] Side loaded /#{path}.(#{loaded_types.join(',')})"
46
+ end
47
+ end
48
+
49
+ # Like #append, but only accepts a single `path` argument, which must be a Pathname. Raises
50
+ # `NotFound` if path does not exist,
51
+ def append!(pathname)
52
+ Proscenium::Current.loaded ||= EXTENSIONS.to_h { |e| [e, Set[]] }
53
+
54
+ unless pathname.is_a?(Pathname)
55
+ raise ArgumentError, "Argument `pathname` (#{pathname}) must be a Pathname"
56
+ end
57
+
58
+ ext = pathname.extname.sub('.', '').to_sym
59
+ path = pathname.relative_path_from(Rails.root).to_s
60
+
61
+ raise ArgumentError, "unsupported extension: #{ext}" unless EXTENSIONS.include?(ext)
62
+
63
+ return if Proscenium::Current.loaded[ext].include?(path)
64
+
65
+ raise NotFound, path unless pathname.exist?
66
+
67
+ Proscenium::Current.loaded[ext] << path
68
+
69
+ Rails.logger.debug "[Proscenium] Side loaded /#{path}"
70
+ end
71
+
72
+ module Monkey
73
+ module TemplateRenderer
74
+ private
75
+
76
+ def render_template(view, template, layout_name, locals)
77
+ if template.respond_to?(:virtual_path) &&
78
+ template.respond_to?(:type) && template.type == :html
79
+ if (layout = layout_name && find_layout(layout_name, locals.keys, [formats.first]))
80
+ Proscenium::SideLoad.append "app/views/#{layout.virtual_path}" # layout
81
+ end
82
+
83
+ if template.respond_to?(:variant) && template.variant
84
+ Proscenium::SideLoad.append "app/views/#{template.virtual_path}+#{template.variant}"
85
+ end
86
+
87
+ # The variant template may not exist (above), so we try the regular non-variant path.
88
+ Proscenium::SideLoad.append "app/views/#{template.virtual_path}"
89
+ end
90
+
91
+ super
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Proscenium
4
+ VERSION = '0.1.0.alpha1'
5
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Proscenium::ViewComponent::TagBuilder < ActionView::Helpers::TagHelper::TagBuilder
4
+ def tag_options(options, escape = true) # rubocop:disable Style/OptionalBooleanParameter
5
+ super(css_module_option(options), escape)
6
+ end
7
+
8
+ private
9
+
10
+ def css_module_option(options)
11
+ return options if options.blank?
12
+
13
+ unless (css_module = options.delete(:css_module) || options.delete('css_module'))
14
+ return options
15
+ end
16
+
17
+ css_module = @view_context.css_module(css_module)
18
+
19
+ options.tap do |x|
20
+ x[:class] = "#{css_module} #{options.delete(:class) || options.delete('class')}".strip
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Proscenium::ViewComponent
4
+ extend ActiveSupport::Autoload
5
+
6
+ autoload :TagBuilder
7
+
8
+ def before_render
9
+ side_load_assets unless self.class < ReactComponent
10
+ end
11
+
12
+ def css_module(name)
13
+ cssm.class_names(name.to_s.camelize(:lower)).join ' '
14
+ end
15
+
16
+ private
17
+
18
+ # Side load any CSS/JS assets for the component. This will side load any `index.{css|js}` in
19
+ # the component directory.
20
+ def side_load_assets
21
+ Proscenium::SideLoad.append asset_path if Rails.application.config.proscenium.side_load
22
+ end
23
+
24
+ def asset_path
25
+ @asset_path ||= "app/components#{virtual_path}"
26
+ end
27
+
28
+ def cssm
29
+ @cssm ||= Proscenium::CssModule.new(asset_path)
30
+ end
31
+
32
+ # Overrides ActionView::Helpers::TagHelper::TagBuilder, allowing us to intercept the
33
+ # `css_module` option from the HTML options argument of the `tag` and `content_tag` helpers, and
34
+ # prepend it to the HTML `class` attribute.
35
+ def tag_builder
36
+ @tag_builder ||= Proscenium::ViewComponent::TagBuilder.new(self)
37
+ end
38
+ end
data/lib/proscenium.rb ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/dependencies/autoload'
4
+
5
+ module Proscenium
6
+ extend ActiveSupport::Autoload
7
+
8
+ autoload :Current
9
+ autoload :Middleware
10
+ autoload :SideLoad
11
+ autoload :CssModule
12
+ autoload :ViewComponent
13
+ autoload :Helper
14
+ autoload :LinkToHelper
15
+ autoload :Precompile
16
+ end
17
+
18
+ require 'proscenium/railtie'
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :proscenium do
4
+ desc 'Compile all your assets with Proscenium'
5
+ task precompile: :environment do
6
+ puts 'Precompiling assets with Proscenium...'
7
+ Proscenium::Precompile.call
8
+ puts 'Proscenium successfully precompiled your assets 🎉'
9
+ end
10
+ end
11
+
12
+ if Rake::Task.task_defined?('assets:precompile')
13
+ Rake::Task['assets:precompile'].enhance do
14
+ Rake::Task['proscenium:precompile'].invoke
15
+ end
16
+ else
17
+ Rake::Task.define_task('assets:precompile' => ['proscenium:precompile'])
18
+ Rake::Task.define_task('assets:clean') # null task just so Heroku builds don't fail
19
+ end
metadata ADDED
@@ -0,0 +1,179 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: proscenium
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.alpha1
5
+ platform: x86_64-darwin
6
+ authors:
7
+ - Joel Moss
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-07-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: actioncable
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 6.1.0
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '8.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 6.1.0
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '8.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: activesupport
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 6.1.0
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '8.0'
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 6.1.0
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '8.0'
53
+ - !ruby/object:Gem::Dependency
54
+ name: listen
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '3.0'
60
+ type: :runtime
61
+ prerelease: false
62
+ version_requirements: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '3.0'
67
+ - !ruby/object:Gem::Dependency
68
+ name: oj
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '3.13'
74
+ type: :runtime
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '3.13'
81
+ - !ruby/object:Gem::Dependency
82
+ name: railties
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: 6.1.0
88
+ - - "<"
89
+ - !ruby/object:Gem::Version
90
+ version: '8.0'
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: 6.1.0
98
+ - - "<"
99
+ - !ruby/object:Gem::Version
100
+ version: '8.0'
101
+ description:
102
+ email:
103
+ - joel@developwithstyle.com
104
+ executables: []
105
+ extensions: []
106
+ extra_rdoc_files: []
107
+ files:
108
+ - CODE_OF_CONDUCT.md
109
+ - README.md
110
+ - lib/proscenium.rb
111
+ - lib/proscenium/cli/argument_error.js
112
+ - lib/proscenium/cli/builders/index.js
113
+ - lib/proscenium/cli/builders/javascript.js
114
+ - lib/proscenium/cli/builders/react.js
115
+ - lib/proscenium/cli/builders/solid.js
116
+ - lib/proscenium/cli/esbuild/env_plugin.js
117
+ - lib/proscenium/cli/esbuild/resolve_plugin.js
118
+ - lib/proscenium/cli/esbuild/solidjs_plugin.js
119
+ - lib/proscenium/cli/js_builder.js
120
+ - lib/proscenium/cli/solid.js
121
+ - lib/proscenium/cli/utils.js
122
+ - lib/proscenium/compiler.js
123
+ - lib/proscenium/compilers/esbuild.bench.js
124
+ - lib/proscenium/compilers/esbuild.js
125
+ - lib/proscenium/compilers/esbuild/argument_error.js
126
+ - lib/proscenium/compilers/esbuild/env_plugin.js
127
+ - lib/proscenium/compilers/esbuild/resolve_plugin.js
128
+ - lib/proscenium/compilers/esbuild/setup_plugin.js
129
+ - lib/proscenium/css_module.rb
130
+ - lib/proscenium/current.rb
131
+ - lib/proscenium/helper.rb
132
+ - lib/proscenium/link_to_helper.rb
133
+ - lib/proscenium/middleware.rb
134
+ - lib/proscenium/middleware/base.rb
135
+ - lib/proscenium/middleware/esbuild.rb
136
+ - lib/proscenium/middleware/parcel_css.rb
137
+ - lib/proscenium/middleware/runtime.rb
138
+ - lib/proscenium/middleware/static.rb
139
+ - lib/proscenium/precompile.rb
140
+ - lib/proscenium/railtie.rb
141
+ - lib/proscenium/runtime/auto_reload.js
142
+ - lib/proscenium/runtime/component_manager/index.js
143
+ - lib/proscenium/runtime/component_manager/render_component.js
144
+ - lib/proscenium/runtime/import_css.js
145
+ - lib/proscenium/runtime/react_shim/index.js
146
+ - lib/proscenium/runtime/react_shim/package.json
147
+ - lib/proscenium/side_load.rb
148
+ - lib/proscenium/version.rb
149
+ - lib/proscenium/view_component.rb
150
+ - lib/proscenium/view_component/tag_builder.rb
151
+ - lib/tasks/assets.rake
152
+ homepage: https://github.com/joelmoss/proscenium
153
+ licenses:
154
+ - MIT
155
+ metadata:
156
+ homepage_uri: https://github.com/joelmoss/proscenium
157
+ source_code_uri: https://github.com/joelmoss/proscenium
158
+ changelog_uri: https://github.com/joelmoss/proscenium/releases
159
+ rubygems_mfa_required: 'true'
160
+ post_install_message:
161
+ rdoc_options: []
162
+ require_paths:
163
+ - lib
164
+ required_ruby_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: 2.7.0
169
+ required_rubygems_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">"
172
+ - !ruby/object:Gem::Version
173
+ version: 1.3.1
174
+ requirements: []
175
+ rubygems_version: 3.3.7
176
+ signing_key:
177
+ specification_version: 4
178
+ summary: The engine powering your Rails frontend
179
+ test_files: []