proscenium 0.19.0.beta18 → 0.19.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5db88847b4fad16f8c3c4bfd96c5f7f40f59726c65280fd81cf2cdeb0fd09c89
4
- data.tar.gz: 4056f395c8f45fda017c334402ce4b7b268b72a2ec75cec47c190c63f565220a
3
+ metadata.gz: 9f45989b5341c8a6c55afab7523537b4da02255783ab866295130ca3a7a3d0be
4
+ data.tar.gz: 2ba1a421a01a6f6ffe0fa7ce3a196109ea8c44bd13887a4be10daa9e40b29cd3
5
5
  SHA512:
6
- metadata.gz: abde8e210ea532b606bbc66282553491b7e06910e5f4ce48faab5f68518d154e9ce746a4bd3ad9e4e0f5b71b19ad569b345ad9db5b83ea35124e64af3698f416
7
- data.tar.gz: dca5b7f3ce4bd5fe17e62c7372e38b86444b75e27999a3c5ad1e10ebb4a910630aa7f2dce922d4a025b0b7bac822a905b26e62bf5463b007fd2f03c5821190da
6
+ metadata.gz: 6326bd9092d6dbccb09bcc8cfcf9e1157c59b27def4471777bdb509e438328a0faefa9d0d36d7ebc46528fb990a8a9c17f2b07d339144fdfb8e4e37d0a5dc9e2
7
+ data.tar.gz: ddf91b7602221a4ab45490971a62ff279f1cc14963f185193496c8c75bb61fed67fef00ba489ac9ab6f3d8f880ec82367530870cd3f0c2b6ad21186b348079bd
data/README.md CHANGED
@@ -6,17 +6,17 @@
6
6
  >
7
7
  > - _the part of a theatre stage in front of the curtain._
8
8
 
9
- **_Proscenium_** treats your frontend and client-side code as first class citizens of your Rails app, and assumes a "fast by default" internet. It bundles and minifies JavaScript (+ JSX), TypeScript (+TSX) and CSS in real time, on demand, and with zero configuration.
9
+ **_Proscenium_** treats your frontend and client-side code as first class citizens of your Rails app, and assumes a "fast by default" internet. It bundles and minifies JavaScript (+JSX), TypeScript (+TSX) and CSS in real time, on demand, and with zero configuration.
10
10
 
11
11
  **The highlights:**
12
12
 
13
13
  - Fast, real-time bundling, tree-shaking, code-splitting and minification of Javascript (.js,.jsx), Typescript (.ts,.tsx) and CSS (.css).
14
14
  - NO JavaScript runtime needed (eg. Node) - just the browser!
15
15
  - NO build step or pre-compilation.
16
- - NO additional process or server - Just run `rails s`!
16
+ - NO additional process or server - Just run `rails server`!
17
17
  - Transforms newer JavaScript and CSS syntax to older syntax for older browsers.
18
18
  - Deep integration with Rails.
19
- - Automatically side-load your layouts, views, and partials.
19
+ - Automatically side-load JS and CSS for your layouts, views, and partials.
20
20
  - Import from NPM, URL's, and locally.
21
21
  - Server-side import map support.
22
22
  - CSS Modules & mixins.
@@ -48,7 +48,6 @@
48
48
  - [Typescript Caveats](#typescript-caveats)
49
49
  - [JSX](#jsx)
50
50
  - [JSON](#json)
51
- - [Phlex Support](#phlex-support)
52
51
  - [Cache Busting](#cache-busting)
53
52
  - [rjs is back!](#rjs-is-back)
54
53
  - [Resolution](#resolution)
@@ -76,15 +75,15 @@ gem 'proscenium'
76
75
 
77
76
  Please note that Proscenium is designed solely for use with Rails.
78
77
 
79
- Now if you start your Rails app, you can open any front end code (JS, CSS, etc.). For example, a file at `app/assets/stylesheets/application.css` can be accessed at `https://localhost:3000/app/assets/stylesheets/application.css`, which will be bundled, transformed, and minified [in production] in real time.
78
+ Now if you start your Rails app, you can open any front end code (JS, CSS, etc.). For example, a file at `app/assets/stylesheets/application.css` can be accessed at `https://localhost:3000/app/assets/stylesheets/application.css`, which will be transformed, bundled, and minified [in production] in real time.
80
79
 
81
80
  ## Client-Side Code Anywhere
82
81
 
83
- Proscenium believes that your frontend code is just as important as your backend code, and is not an afterthought - they should be first class citizens of your Rails app. So instead of having to throw all your JS and CSS into a "app/assets" directory, and then requiring a separate process to compile or bundle, just put them wherever you want within your app, and just run Rails!
82
+ Proscenium believes that your frontend code is just as important as your backend code, and is not an afterthought - they should be first class citizens of your Rails app. So instead of having to throw all your JS and CSS into a "app/assets" directory, and then requiring a separate process to compile or bundle, you can simply put them wherever you want within your app, and just run Rails!
84
83
 
85
84
  For example, if you have some JS that is required by your `app/views/users/index.html.erb` view, just create a JS file alongside it at `app/views/users/index.js`. Or if you have some CSS that is used by your entire application, put it in `app/views/layouts/application.css` and load it alongside your layout. Maybe you have a few JS utility functions, so put them in `lib/utils.js`.
86
85
 
87
- Simply put your JS(X) and CSS anywhere you want, and they will be served by your Rails app from the location where you placed them.
86
+ Simply put your JS(X) and CSS anywhere you want, and they will be served by your Rails app from the same location where you placed them.
88
87
 
89
88
  Using the examples above...
90
89
 
@@ -96,15 +95,15 @@ Using the examples above...
96
95
 
97
96
  ## Side Loading
98
97
 
99
- Proscenium is best experienced when your assets are automtically side loaded.
98
+ Proscenium is best experienced when your assets are automatically side loaded.
100
99
 
101
100
  ### The Problem
102
101
 
103
- With Rails you would typically declaratively load your JavaScript and CSS assets using the `javascript_include_tag` and `stylesheet_link_tag` helpers.
102
+ With Rails you would typically load your JavaScript and CSS assets declaratively using the `javascript_include_tag` and `stylesheet_link_tag` helpers.
104
103
 
105
- For example, you may have top-level "application" CSS located in a file at `/app/assets/stylesheets/application.css`. Likewise, you may have some global JavaScript located in a file at `/app/javascript/application.js`.
104
+ For example, you may have top-level "application" styles located in a file at `/app/assets/stylesheets/application.css`. Likewise, you may have some global JavaScript located in a file at `/app/javascript/application.js`.
106
105
 
107
- You would manually and declaratively include those two files in your application layout, something like this:
106
+ You would manually and declaratively include those two files in each of your layouts, something like this:
108
107
 
109
108
  ```erb
110
109
  <%# /app/views/layouts/application.html.erb %>
@@ -142,7 +141,9 @@ The main problem is that you have to keep track of all these assets, and make su
142
141
 
143
142
  When side loading your JavaScript, Typescript and CSS with Proscenium, they are automatically included alongside your views, partials, layouts, and components, and only when needed.
144
143
 
145
- Side loading works by looking for a JS/TS/CSS file with the same name as your view, partial, layout or component. For example, if you have a view at `app/views/users/index.html.erb`, then Proscenium will look for a JS/TS/CSS file at `app/views/users/index.js`, `app/views/users/index.ts` or `app/views/users/index.css`. If it finds one, it will include it in the HTML for that view.
144
+ Side loading works by looking for a JS/TS/CSS file with the same name as your view, partial, layout or component. For example, if you have a view at `app/views/users/index.html.erb`, then Proscenium will look for a JS and CSS file at `app/views/users/index.js` (or TypeScript with a .ts extension) and `app/views/users/index.css`. If it finds one, it will automatically include it in the HTML for that view. And only for that view.
145
+
146
+ This allows you to keep your assets organized alongside the views, partials, and components that use them, without having to manually track and include them. It also means only the assets that are needed are included.
146
147
 
147
148
  JSX is also supported for JavaScript and Typescript. Simply use the `.jsx` or `.tsx` extension instead of `.js` or `.ts`.
148
149
 
@@ -273,6 +274,14 @@ Then just import as normal:
273
274
  import React from "react";
274
275
  ```
275
276
 
277
+ Or if you don't want any bundling at all, simply turn it off application-wide:
278
+
279
+ ```ruby
280
+ config.proscenium.bundle = false
281
+ ```
282
+
283
+ This will mean every asset and import will be loaded independently.
284
+
276
285
  ## Import Maps
277
286
 
278
287
  > **[WIP]**
@@ -442,8 +451,6 @@ one();
442
451
 
443
452
  ### Code Splitting
444
453
 
445
- > Available in `>=0.10.0`.
446
-
447
454
  [Side loaded](#side-loading) assets are automatically code split. This means that if you have a file that is imported and used imported several times, and by different files, it will be split off into a separate file.
448
455
 
449
456
  As an example:
@@ -681,97 +688,8 @@ import { version } from "./package.json";
681
688
  console.log(version);
682
689
  ```
683
690
 
684
- ## Phlex Support
685
-
686
- [Phlex](https://www.phlex.fun/) is a framework for building fast, reusable, testable views in pure Ruby. Proscenium works perfectly with Phlex, with support for side-loading, CSS modules, and more. Simply write your Phlex classes and inherit from `Proscenium::Phlex`.
687
-
688
- ```ruby
689
- class MyView < Proscenium::Phlex
690
- def view_template
691
- h1 { 'Hello World' }
692
- end
693
- end
694
- ```
695
-
696
- In your layouts, include `Proscenium::Phlex::AssetInclusions`, and call the `include_assets` helper.
697
-
698
- ```ruby
699
- class ApplicationLayout < Proscenium::Phlex
700
- include Proscenium::Phlex::AssetInclusions # <--
701
-
702
- def view_template(&)
703
- doctype
704
- html do
705
- head do
706
- title { 'My Awesome App' }
707
- include_assets # <--
708
- end
709
- body(&)
710
- end
711
- end
712
- end
713
- ```
714
-
715
- You can specifically include CCS and JS assets using the `include_stylesheets` and `include_javascripts` helpers, allowing you to control where they are included in the HTML.
716
-
717
- ### Side-loading
718
-
719
- Any Phlex class that inherits `Proscenium::Phlex` will automatically be [side-loaded](#side-loading).
720
-
721
- ### CSS Modules
722
-
723
- [CSS Modules](#css-modules) are fully supported in Phlex classes, with access to the [`css_module` helper](#in-your-views) if you need it. However, there is a better and more seemless way to reference CSS module classes in your Phlex classes.
724
-
725
- Within your Phlex classes, any class names that begin with `@` will be treated as a CSS module class.
726
-
727
- ```ruby
728
- # /app/views/users/show_view.rb
729
- class Users::ShowView < Proscenium::Phlex
730
- def view_template
731
- h1 class: :@user_name do
732
- @user.name
733
- end
734
- end
735
- end
736
- ```
737
-
738
- ```css
739
- /* /app/views/users/show_view.module.css */
740
- .userName {
741
- color: red;
742
- font-size: 50px;
743
- }
744
- ```
745
-
746
- In the above `Users::ShowView` Phlex class, the `@user_name` class will be resolved to the `userName` class in the `users/show_view.module.css` file.
747
-
748
- The view above will be rendered something like this:
749
-
750
- ```html
751
- <h1 class="user_name-ABCD1234"></h1>
752
- ```
753
-
754
- You can of course continue to reference regular class names in your view, and they will be passed through as is. This will allow you to mix and match CSS modules and regular CSS classes in your views.
755
-
756
- ```ruby
757
- # /app/views/users/show_view.rb
758
- class Users::ShowView < Proscenium::Phlex
759
- def view_template
760
- h1 class: :[@user_name, :title] do
761
- @user.name
762
- end
763
- end
764
- end
765
- ```
766
-
767
- ```html
768
- <h1 class="user_name-ABCD1234 title">Joel Moss</h1>
769
- ```
770
-
771
691
  ## Cache Busting
772
692
 
773
- > _COMING SOON_
774
-
775
693
  By default, all assets are not cached by the browser. But if in production, you populate the `REVISION` env variable, all CSS and JS URL's will be appended with its value as a query string, and the `Cache-Control` response header will be set to `public` and a max-age of 30 days.
776
694
 
777
695
  For example, if you set `REVISION=v1`, URL's will be appended with `?v1`: `/my/imported/file.js?v1`.
@@ -16,6 +16,7 @@ module Proscenium
16
16
 
17
17
  module Request
18
18
  extend FFI::Library
19
+
19
20
  ffi_lib Pathname.new(__dir__).join('ext/proscenium').to_s
20
21
 
21
22
  enum :environment, [:development, 1, :test, :production]
@@ -18,7 +18,8 @@ module Proscenium
18
18
  unless @css_module_path
19
19
  klass = superclass
20
20
 
21
- while klass.respond_to?(:css_module_path) && !klass.abstract_class
21
+ while klass.respond_to?(:css_module_path) &&
22
+ (klass.respond_to?(:abstract_class) ? !klass.abstract_class : true)
22
23
  break if (@css_module_path = klass.css_module_path)
23
24
 
24
25
  klass = klass.superclass
@@ -70,7 +70,7 @@ module Proscenium
70
70
  digest = Importer.import(resolved_path)
71
71
 
72
72
  transformed_path = ''
73
- transformed_path = "__#{resolved_path[1..].gsub(%r{[@/\.+]}, '-')}" if Rails.env.development?
73
+ transformed_path = "__#{resolved_path[1..].gsub(%r{[@/.+]}, '-')}" if Rails.env.development?
74
74
  transformed_name = name.to_s
75
75
  transformed_name = if transformed_name.start_with?('_')
76
76
  "_#{transformed_name[1..]}-#{digest}#{transformed_path}"
@@ -16,6 +16,27 @@ module Proscenium::CssModule
16
16
  end
17
17
  end
18
18
 
19
+ module ClassMethods
20
+ def css_module(*names, path: nil)
21
+ path ||= respond_to?(:css_module_path) ? css_module_path : path
22
+
23
+ cssm = Transformer.new(path)
24
+ cssm.class_names(*names, require_prefix: false).map { |name, _| name }.join(' ')
25
+ end
26
+
27
+ def class_names(*names, path: nil)
28
+ path ||= respond_to?(:css_module_path) ? css_module_path : path
29
+ names = names.flatten.compact
30
+
31
+ cssm = Transformer.new(path)
32
+ cssm.class_names(*names).map { |name, _| name }.join(' ') unless names.empty?
33
+ end
34
+ end
35
+
36
+ def self.included(base)
37
+ base.extend ClassMethods
38
+ end
39
+
19
40
  # Accepts one or more CSS class names, and transforms them into CSS module names.
20
41
  #
21
42
  # @param name [String,Symbol,Array<String,Symbol>]
Binary file
@@ -40,18 +40,6 @@ module Proscenium
40
40
  .map { |name, _| name }.join(' ')
41
41
  end
42
42
 
43
- # @param name [String,Symbol,Array<String,Symbol>]
44
- # @param path [Pathname] the path to the CSS file to use for the transformation.
45
- # @return [String] the transformed CSS module names concatenated as a string.
46
- def class_names(*names, path: nil)
47
- names = names.flatten.compact
48
-
49
- return if names.empty?
50
-
51
- path ||= Pathname.new(@lookup_context.find(@virtual_path).identifier).sub_ext('')
52
- CssModule::Transformer.new(path).class_names(*names).map { |name, _| name }.join(' ')
53
- end
54
-
55
43
  def include_assets
56
44
  include_stylesheets + include_javascripts
57
45
  end
@@ -36,5 +36,3 @@ module Proscenium
36
36
  end
37
37
  end
38
38
  end
39
-
40
- Proscenium::LogSubscriber.attach_to :proscenium
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'rails'
4
- require 'proscenium/log_subscriber'
5
4
 
6
5
  ENV['RAILS_ENV'] = Rails.env
7
6
 
@@ -11,6 +10,7 @@ module Proscenium
11
10
 
12
11
  config.proscenium = ActiveSupport::OrderedOptions.new
13
12
  config.proscenium.debug = false
13
+ config.proscenium.logging = true
14
14
  config.proscenium.bundle = true
15
15
  config.proscenium.side_load = true
16
16
  config.proscenium.code_splitting = true
@@ -28,6 +28,11 @@ module Proscenium
28
28
  }
29
29
 
30
30
  config.after_initialize do |_app|
31
+ if config.proscenium.logging
32
+ require 'proscenium/log_subscriber'
33
+ Proscenium::LogSubscriber.attach_to :proscenium
34
+ end
35
+
31
36
  ActiveSupport.on_load(:action_view) do
32
37
  include Proscenium::Helper
33
38
  end
@@ -11,7 +11,7 @@ module Proscenium
11
11
  # The HTML tag to use as the wrapping element for the component. You can reassign this in your
12
12
  # component class to use a different tag:
13
13
  #
14
- # class MyComponent < Proscenium::Phlex::ReactComponent
14
+ # class MyComponent < Proscenium::ReactComponent
15
15
  # self.root_tag = :span
16
16
  # end
17
17
  #
@@ -116,7 +116,8 @@ module Proscenium
116
116
  css_imports = []
117
117
 
118
118
  klass = obj.class
119
- while klass.respond_to?(:source_path) && klass.source_path && !klass.abstract_class
119
+ while klass.respond_to?(:source_path) && klass.source_path &&
120
+ (klass.respond_to?(:abstract_class) ? !klass.abstract_class : true)
120
121
  if options[:css] == false
121
122
  Importer.sideload klass.source_path, **options
122
123
  else
@@ -133,7 +134,7 @@ module Proscenium
133
134
  # in the ancestry is also sideloaded in addition to the regular CSS files. This is because
134
135
  # the CSS module digest will be different for each file, so we only sideload the first CSS
135
136
  # module.
136
- css_imports.each do |it|
137
+ css_imports.each do |it| # rubocop:disable Style/ItAssignment
137
138
  break if Importer.sideload_css_module(it, **options).present?
138
139
  end
139
140
 
@@ -142,7 +143,7 @@ module Proscenium
142
143
  # The reason why we sideload CSS after JS is because the order of CSS is important.
143
144
  # Basically, the layout should be loaded before the view so that CSS cascading works in the
144
145
  # right direction.
145
- css_imports.reverse_each do |it|
146
+ css_imports.reverse_each do |it| # rubocop:disable Style/ItAssignment
146
147
  Importer.sideload_css it, **options
147
148
  end
148
149
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Proscenium
4
- VERSION = '0.19.0.beta18'
4
+ VERSION = '0.19.0'
5
5
  end
data/lib/proscenium.rb CHANGED
@@ -28,7 +28,6 @@ module Proscenium
28
28
  autoload :SideLoad
29
29
  autoload :CssModule
30
30
  autoload :ReactComponentable
31
- autoload :Phlex
32
31
  autoload :Helper
33
32
  autoload :Builder
34
33
  autoload :Importer
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.19.0.beta18
4
+ version: 0.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Moss
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-04-30 00:00:00.000000000 Z
11
+ date: 2025-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -24,34 +24,6 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.17.0
27
- - !ruby/object:Gem::Dependency
28
- name: phlex-rails
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '1.2'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '1.2'
41
- - !ruby/object:Gem::Dependency
42
- name: prism
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
27
  - !ruby/object:Gem::Dependency
56
28
  name: rails
57
29
  requirement: !ruby/object:Gem::Requirement
@@ -72,20 +44,6 @@ dependencies:
72
44
  - - "<"
73
45
  - !ruby/object:Gem::Version
74
46
  version: '9.0'
75
- - !ruby/object:Gem::Dependency
76
- name: require-hooks
77
- requirement: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - "~>"
80
- - !ruby/object:Gem::Version
81
- version: '0.2'
82
- type: :runtime
83
- prerelease: false
84
- version_requirements: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - "~>"
87
- - !ruby/object:Gem::Version
88
- version: '0.2'
89
47
  description:
90
48
  email:
91
49
  - joel@developwithstyle.com
@@ -101,7 +59,6 @@ files:
101
59
  - lib/proscenium/bundled_gems.rb
102
60
  - lib/proscenium/css_module.rb
103
61
  - lib/proscenium/css_module/path.rb
104
- - lib/proscenium/css_module/rewriter.rb
105
62
  - lib/proscenium/css_module/transformer.rb
106
63
  - lib/proscenium/ensure_loaded.rb
107
64
  - lib/proscenium/ext/proscenium
@@ -114,10 +71,6 @@ files:
114
71
  - lib/proscenium/middleware/esbuild.rb
115
72
  - lib/proscenium/middleware/ruby_gems.rb
116
73
  - lib/proscenium/monkey.rb
117
- - lib/proscenium/phlex.rb
118
- - lib/proscenium/phlex/asset_inclusions.rb
119
- - lib/proscenium/phlex/css_modules.rb
120
- - lib/proscenium/phlex/react_component.rb
121
74
  - lib/proscenium/railtie.rb
122
75
  - lib/proscenium/react-manager/index.jsx
123
76
  - lib/proscenium/react-manager/react.js
@@ -1,76 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'prism'
4
- require 'require-hooks/setup'
5
-
6
- module Proscenium
7
- module CssModule
8
- class Rewriter
9
- def self.init(include: [], exclude: [])
10
- RequireHooks.source_transform(
11
- patterns: include,
12
- exclude_patterns: exclude
13
- ) do |path, source|
14
- source ||= File.read(path)
15
- Processor.call(source)
16
- end
17
- end
18
-
19
- class Processor < Prism::Visitor
20
- def self.call(source)
21
- visitor = new
22
- visitor.visit(Prism.parse(source).value)
23
-
24
- buffer = source.dup
25
- annotations = visitor.annotations
26
- annotations.sort_by!(&:first)
27
-
28
- annotations.reverse_each do |offset, action|
29
- case action
30
- when :start
31
- buffer.insert(offset, 'class_names(*')
32
- when :end
33
- buffer.insert(offset, ')')
34
- else
35
- raise 'Invalid annotation'
36
- end
37
- end
38
-
39
- buffer
40
- end
41
-
42
- def initialize
43
- @annotations = []
44
- end
45
-
46
- PREFIX = '@'
47
-
48
- attr_reader :annotations
49
-
50
- def visit_assoc_node(node)
51
- # Skip if the key is not a symbol or string
52
- return if %i[symbol_node string_node].exclude?(node.key.type)
53
-
54
- return if node.key.type == :symbol_node && node.key.value != 'class'
55
- return if node.key.type == :string_node && node.key.content != 'class'
56
-
57
- value = node.value
58
- type = value.type
59
-
60
- if (type == :symbol_node && value.value.start_with?(PREFIX)) ||
61
- (type == :array_node && value.elements.any? { |it| it.value.start_with?(PREFIX) })
62
- build_annotation value
63
- end
64
- end
65
-
66
- def build_annotation(value)
67
- location = value.location
68
-
69
- @annotations <<
70
- [location.start_character_offset, :start] <<
71
- [location.end_character_offset, :end]
72
- end
73
- end
74
- end
75
- end
76
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Proscenium::Phlex::AssetInclusions
4
- def include_stylesheets
5
- comment { '[PROSCENIUM_STYLESHEETS]' }
6
- end
7
-
8
- def include_javascripts
9
- comment { '[PROSCENIUM_JAVASCRIPTS]' }
10
- end
11
-
12
- def include_assets
13
- include_stylesheets
14
- include_javascripts
15
- end
16
- end
@@ -1,82 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Proscenium
4
- module Phlex::CssModules
5
- include Proscenium::CssModule
6
-
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
18
- end
19
-
20
- def before_template
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 ||= Concurrent::Set.new
27
- self.class.resolved_css_module_paths.each do |path|
28
- Proscenium::Importer.import path, sideloaded: true
29
- end
30
-
31
- super
32
- end
33
-
34
- # Resolve and side load any CSS modules in the "class" attributes, where a CSS module is a class
35
- # name beginning with a `@`. The class name is resolved to a CSS module name based on the file
36
- # system path of the Phlex class, and any CSS file is side loaded.
37
- #
38
- # For example, the following will side load the CSS module file at
39
- # app/components/user/component.module.css, and add the CSS Module name `user_name` to the
40
- # <div>.
41
- #
42
- # # app/components/user/component.rb
43
- # class User::Component < Proscenium::Phlex
44
- # def view_template
45
- # div class: :@user_name do
46
- # 'Joel Moss'
47
- # end
48
- # end
49
- # end
50
- #
51
- # Additionally, any class name containing a `/` is resolved as a CSS module path. Allowing you
52
- # to use the same syntax as a CSS module, but without the need to manually import the CSS file.
53
- #
54
- # For example, the following will side load the CSS module file at /lib/users.module.css, and
55
- # add the CSS Module name `name` to the <div>.
56
- #
57
- # class User::Component < Proscenium::Phlex
58
- # def view_template
59
- # div class: '/lib/users@name' do
60
- # 'Joel Moss'
61
- # end
62
- # end
63
- # end
64
- #
65
- # @raise [Proscenium::CssModule::Resolver::NotFound] If a CSS module file is not found for the
66
- # Phlex class file path.
67
- def process_attributes(**attributes)
68
- if attributes.key?(:class) && (attributes[:class] = tokens(attributes[:class])).include?('@')
69
- names = attributes[:class].is_a?(Array) ? attributes[:class] : attributes[:class].split
70
-
71
- self.class.resolved_css_module_paths ||= Concurrent::Set.new
72
-
73
- attributes[:class] = cssm.class_names(*names).map do |name, path|
74
- self.class.resolved_css_module_paths << path if path
75
- name
76
- end
77
- end
78
-
79
- attributes
80
- end
81
- end
82
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
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 view_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 view_template(**attributes, &)
29
- send(root_tag, **{ data: data_attributes }.deep_merge(attributes), &)
30
- end
31
- end
32
- end
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'phlex-rails'
4
-
5
- module Proscenium
6
- class Phlex < ::Phlex::HTML
7
- extend ActiveSupport::Autoload
8
-
9
- autoload :CssModules
10
- autoload :ReactComponent
11
- autoload :AssetInclusions
12
-
13
- include Proscenium::SourcePath
14
- include CssModules
15
- include AssetInclusions
16
-
17
- module Sideload
18
- def before_template
19
- Proscenium::SideLoad.sideload_inheritance_chain self,
20
- helpers.controller.sideload_assets_options
21
-
22
- super
23
- end
24
- end
25
-
26
- class_attribute :sideload_assets_options
27
-
28
- class << self
29
- attr_accessor :abstract_class
30
-
31
- def inherited(child)
32
- child.prepend Sideload
33
-
34
- super
35
- end
36
-
37
- def sideload_assets(value)
38
- self.sideload_assets_options = value
39
- end
40
- end
41
- end
42
- end