superglue 1.0.1 → 1.1.1

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: 8e9624774c0133d0a9d8aac0d8b5d47bbb95862eea0bb1a26ffe3ce373c5e922
4
- data.tar.gz: 8c69fd808df13768c9036981ca27d2a0b24eb9ce8ab8d890c88b666cc9bd5798
3
+ metadata.gz: 1a1ecd4f618637e57a20279cf0ccf2b4cfc51abee634c6f9e6fab5f2e334f94f
4
+ data.tar.gz: ad15a0fbed3e89f2df027d0fcf35a92c2ff74ce347b5c637d246f49802d2cce7
5
5
  SHA512:
6
- metadata.gz: 17522e020054291483b60953d3fa31e60d6b95de4316ce7469ed71e7f397fa15b07533051b4a4266d5263313a947e7b3eb82621d1d0f8dd45088b9db77295cdf
7
- data.tar.gz: 97e27d5f9330ac515cd1636af3c9974584476a324d142573176187dd3cf18a7e6db696cec11ba473f8b5f7fc3d8849fa9fbc49d14f359ef9373d5ec75b763d56
6
+ metadata.gz: 1aa8dc1714f3d23f223a4ac647b8e28fb500cab716c7669597a2b10837f2d320872bc9c23223d654872223006a32863217fb91d64c007b833380facd795dd0cf
7
+ data.tar.gz: '009249d735d62c2737eb9b39e67c01368c2ec2345932061e2bada5f086ca9a9db33a842bd7572b5546fc561cecedd0d46c98448c9fbf61b17843d1a41e26ad90'
@@ -16,6 +16,8 @@ module Superglue
16
16
  remove_file "#{app_js_path}/application.js"
17
17
 
18
18
  use_typescript = options["typescript"]
19
+ copy_erb_files
20
+
19
21
  if use_typescript
20
22
  copy_ts_files
21
23
  else
@@ -31,6 +33,9 @@ module Superglue
31
33
  say "Adding required member methods to ApplicationRecord"
32
34
  add_member_methods
33
35
 
36
+ say "Enabling jsx rendering defaults"
37
+ insert_jsx_rendering_defaults
38
+
34
39
  say "Installing Superglue and friends"
35
40
  run "yarn add react react-dom @reduxjs/toolkit react-redux @thoughtbot/superglue"
36
41
 
@@ -43,6 +48,45 @@ module Superglue
43
48
 
44
49
  private
45
50
 
51
+ def insert_jsx_rendering_defaults
52
+ inject_into_file "app/controllers/application_controller.rb", after: "class ApplicationController < ActionController::Base\n" do
53
+ <<-RUBY
54
+ # Enables Superglue rendering defaults for sensible view directories.
55
+ #
56
+ # without `use_jsx_rendering_defaults`:
57
+ #
58
+ # ```
59
+ # app/views/posts/
60
+ # - index.jsx
61
+ # - index.json.props
62
+ # - index.html.erb
63
+ # ```
64
+ #
65
+ # with `use_jsx_rendering_defaults`:
66
+ #
67
+ # ```
68
+ # app/views/posts/
69
+ # - index.jsx
70
+ # - index.json.props
71
+ # ```
72
+ #
73
+ # before_action :use_jsx_rendering_defaults
74
+ #
75
+ #
76
+ # The html template used when `use_jsx_rendering_defaults` is enabled.
77
+ # Defaults to "application/superglue".
78
+ #
79
+ # superglue_template "application/superglue"
80
+
81
+ RUBY
82
+ end
83
+ end
84
+
85
+ def copy_erb_files
86
+ say "Copying superglue.html.erb file to app/views/application/"
87
+ copy_file "#{__dir__}/templates/erb/superglue.html.erb", "app/views/application/superglue.html.erb"
88
+ end
89
+
46
90
  def copy_ts_files
47
91
  say "Copying application.tsx file to #{app_js_path}"
48
92
  copy_file "#{__dir__}/templates/ts/application.tsx", "#{app_js_path}/application.tsx"
@@ -0,0 +1,5 @@
1
+ <script type="text/javascript">
2
+ window.SUPERGLUE_INITIAL_PAGE_STATE=<%= render_props %>;<%# erblint:disable ErbSafety %>
3
+ </script>
4
+
5
+ <div id="app"></div>
@@ -25,7 +25,11 @@ module Superglue
25
25
  argument :attributes, type: :array, default: [], banner: "field:type field:type"
26
26
 
27
27
  def create_controller_files
28
- template "controller.rb", File.join("app/controllers", controller_class_path, "#{controller_file_name}_controller.rb")
28
+ controller_file = File.join("app/controllers", controller_class_path, "#{controller_file_name}_controller.rb")
29
+ template "controller.rb", controller_file
30
+ inject_into_file controller_file, after: /ApplicationController$/ do
31
+ "\n before_action :use_jsx_rendering_defaults"
32
+ end
29
33
  end
30
34
 
31
35
  # Replaces template_engine (and its default erb), with view_collection
@@ -21,14 +21,6 @@ module Superglue
21
21
  empty_directory path unless File.directory?(path)
22
22
  end
23
23
 
24
- def copy_erb_files
25
- available_views.each do |view|
26
- @action_name = view
27
- filename = filename_with_html_extensions(view)
28
- template "erb/" + filename, File.join("app/views", controller_file_path, filename)
29
- end
30
- end
31
-
32
24
  def copy_prop_files
33
25
  available_views.each do |view|
34
26
  @action_name = view
@@ -0,0 +1,88 @@
1
+ require "active_support/concern"
2
+
3
+ module Superglue
4
+ module Rendering
5
+ class UnsupportedOption < StandardError; end
6
+
7
+ extend ActiveSupport::Concern
8
+
9
+ included do |base|
10
+ base.class_attribute :_superglue_template, instance_accessor: true, default: "application/superglue"
11
+ end
12
+
13
+ class_methods do
14
+ def superglue_template(template)
15
+ self._superglue_template = template
16
+ end
17
+ end
18
+
19
+ def _render_template(options = {})
20
+ if @_capture_options_before_render
21
+ @_capture_options_before_render = false
22
+
23
+ if options.keys.intersect? [:file, :partial, :body, :plain, :html, :inline]
24
+ raise UnsupportedOption.new("`template:` and `action:` are the only options supported with `use_jsx_rendering_defaults`")
25
+ end
26
+
27
+ @_render_options = options
28
+ _ensure_react_page!(options[:template], options[:prefixes])
29
+
30
+ html_template_exist = template_exists?(options[:template], options[:prefixes], false)
31
+ if !html_template_exist
32
+ super(options.merge(
33
+ template: _superglue_template,
34
+ prefixes: []
35
+ ))
36
+ else
37
+ super
38
+ end
39
+ else
40
+ super
41
+ end
42
+ end
43
+
44
+ def render(...)
45
+ if _jsx_defaults
46
+ @_capture_options_before_render = true
47
+ end
48
+
49
+ super
50
+ end
51
+
52
+ def use_jsx_rendering_defaults
53
+ @_use_jsx_rendering_defaults = true
54
+ end
55
+
56
+ def _jsx_defaults
57
+ @_use_jsx_rendering_defaults && request.format.html?
58
+ end
59
+
60
+ def _ensure_react_page!(template, prefixes)
61
+ lookup_context.find(template, prefixes, false, [], formats: [], handlers: [], variants: [], locale: [])
62
+ end
63
+
64
+ def default_render
65
+ if _jsx_defaults
66
+ render
67
+ else
68
+ super
69
+ end
70
+ end
71
+
72
+ def render_props
73
+ if @_render_options
74
+ options = @_render_options
75
+
76
+ if template_exists?(options[:template], options[:prefixes], formats: [:json])
77
+ _render_template(options.merge({formats: [:json], layout: _layout_for_option(true)})).strip.html_safe
78
+ else
79
+ options.delete(:template)
80
+ options.delete(:action)
81
+ _render_template(options.merge({inline: "", formats: [:json], layout: _layout_for_option(true)})).strip.html_safe
82
+ end
83
+ else
84
+ ""
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,58 @@
1
+ require 'action_view'
2
+
3
+ module Superglue
4
+ class Resolver < ActionView::FileSystemResolver
5
+ class JsxPathParser < ActionView::Resolver::PathParser
6
+ REACT_FORMATS = [:tsx, :jsx]
7
+
8
+ def build_path_regex
9
+ formats = Regexp.union(REACT_FORMATS.map(&:to_s))
10
+
11
+ %r{
12
+ \A
13
+ (?:(?<prefix>.*)/)?
14
+ (?<action>.*?)
15
+ (?:\.(?<format>#{formats}))??
16
+ \z
17
+ }x
18
+ end
19
+
20
+ def parse(path)
21
+ @regex ||= build_path_regex
22
+ match = @regex.match(path)
23
+ path = ActionView::TemplatePath.build(match[:action], match[:prefix] || "", false)
24
+ details = ActionView::TemplateDetails.new(
25
+ nil,
26
+ nil,
27
+ match[:format]&.to_sym,
28
+ nil
29
+ )
30
+ ParsedPath.new(path, details)
31
+ end
32
+ end
33
+
34
+ def initialize(path)
35
+ raise ArgumentError, "path already is a Resolver class" if path.is_a?(ActionView::Resolver)
36
+ @unbound_templates = Concurrent::Map.new
37
+ @path_parser = JsxPathParser.new
38
+ @path = File.expand_path(path)
39
+ end
40
+
41
+ def clear_cache
42
+ @unbound_templates.clear
43
+ @path_parser = JsxPathParser.new
44
+ end
45
+
46
+ def source_for_template(template)
47
+ "''"
48
+ end
49
+
50
+ def filter_and_sort_by_details(templates, requested_details)
51
+ if requested_details.formats.empty?
52
+ templates
53
+ else
54
+ []
55
+ end
56
+ end
57
+ end
58
+ end
data/lib/superglue.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require "superglue/helpers"
2
2
  require "superglue/redirection"
3
+ require "superglue/rendering"
4
+ require "superglue/resolver"
3
5
  require "props_template"
4
6
  require "form_props"
5
7
 
@@ -9,8 +11,10 @@ module Superglue
9
11
  include Helpers
10
12
 
11
13
  def self.included(base)
14
+ base.include ::Superglue::Rendering
12
15
  if base.respond_to?(:helper_method)
13
16
  base.helper_method :param_to_dig_path
17
+ base.helper_method :render_props
14
18
  end
15
19
  end
16
20
  end
@@ -19,18 +23,16 @@ module Superglue
19
23
  config.superglue = ActiveSupport::OrderedOptions.new
20
24
  config.superglue.auto_include = true
21
25
 
22
- generators do |app|
23
- Rails::Generators.configure! app.config.generators
24
- Rails::Generators.hidden_namespaces.uniq!
25
- require "generators/rails/scaffold_controller_generator"
26
- end
27
-
28
26
  initializer :superglue do |app|
29
27
  ActiveSupport.on_load(:action_controller) do
30
28
  next if self != ActionController::Base
31
29
 
32
30
  if app.config.superglue.auto_include
33
31
  include Controller
32
+
33
+ prepend_view_path(
34
+ Superglue::Resolver.new(Rails.root.join("app/views"))
35
+ )
34
36
  end
35
37
  end
36
38
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: superglue
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Johny Ho
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-01-13 00:00:00.000000000 Z
11
+ date: 2025-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -67,6 +67,7 @@ files:
67
67
  - README.md
68
68
  - lib/generators/superglue/install/install_generator.rb
69
69
  - lib/generators/superglue/install/templates/application.json.props
70
+ - lib/generators/superglue/install/templates/erb/superglue.html.erb
70
71
  - lib/generators/superglue/install/templates/initializer.rb
71
72
  - lib/generators/superglue/install/templates/js/application.jsx
72
73
  - lib/generators/superglue/install/templates/js/application_visit.js
@@ -88,10 +89,6 @@ files:
88
89
  - lib/generators/superglue/install/templates/ts/tsconfig.json
89
90
  - lib/generators/superglue/scaffold/scaffold_generator.rb
90
91
  - lib/generators/superglue/scaffold_controller/scaffold_controller_generator.rb
91
- - lib/generators/superglue/view_collection/templates/erb/edit.html.erb
92
- - lib/generators/superglue/view_collection/templates/erb/index.html.erb
93
- - lib/generators/superglue/view_collection/templates/erb/new.html.erb
94
- - lib/generators/superglue/view_collection/templates/erb/show.html.erb
95
92
  - lib/generators/superglue/view_collection/templates/js/edit.jsx
96
93
  - lib/generators/superglue/view_collection/templates/js/index.jsx
97
94
  - lib/generators/superglue/view_collection/templates/js/new.jsx
@@ -109,6 +106,8 @@ files:
109
106
  - lib/superglue.rb
110
107
  - lib/superglue/helpers.rb
111
108
  - lib/superglue/redirection.rb
109
+ - lib/superglue/rendering.rb
110
+ - lib/superglue/resolver.rb
112
111
  homepage: https://github.com/thoughtbot/superglue_rails/
113
112
  licenses:
114
113
  - MIT
@@ -1,10 +0,0 @@
1
- <%% initial_state = controller.render_to_string(active_template_virtual_path, formats: [:json], locals: local_assigns, layout: true) %>
2
-
3
- <script type="text/javascript">
4
- window.SUPERGLUE_INITIAL_PAGE_STATE=<%%= initial_state.html_safe %>;<%%# erblint:disable ErbSafety %>
5
- </script>
6
-
7
- <%%# If you need SSR follow instructions at %>
8
- <%%# https://github.com/thoughtbot/superglue/blob/main/docs/recipes/server-side-rendering.md %>
9
- <div id="app"></div>
10
-
@@ -1,9 +0,0 @@
1
- <%% initial_state = controller.render_to_string(active_template_virtual_path, formats: [:json], locals: local_assigns, layout: true) %>
2
-
3
- <script type="text/javascript">
4
- window.SUPERGLUE_INITIAL_PAGE_STATE=<%%= initial_state.html_safe %>;<%%# erblint:disable ErbSafety %>
5
- </script>
6
-
7
- <%%# If you need SSR follow instructions at %>
8
- <%%# https://github.com/thoughtbot/superglue/blob/main/docs/recipes/server-side-rendering.md %>
9
- <div id="app"></div>
@@ -1,9 +0,0 @@
1
- <%% initial_state = controller.render_to_string(active_template_virtual_path, formats: [:json], locals: local_assigns, layout: true) %>
2
-
3
- <script type="text/javascript">
4
- window.SUPERGLUE_INITIAL_PAGE_STATE=<%%= initial_state.html_safe %>;<%%# erblint:disable ErbSafety %>
5
- </script>
6
-
7
- <%%# If you need SSR follow instructions at %>
8
- <%%# https://github.com/thoughtbot/superglue/blob/main/docs/recipes/server-side-rendering.md %>
9
- <div id="app"></div>
@@ -1,9 +0,0 @@
1
- <%% initial_state = controller.render_to_string(active_template_virtual_path, formats: [:json], locals: local_assigns, layout: true) %>
2
-
3
- <script type="text/javascript">
4
- window.SUPERGLUE_INITIAL_PAGE_STATE=<%%= initial_state.html_safe %>;<%%# erblint:disable ErbSafety %>
5
- </script>
6
-
7
- <%%# If you need SSR follow instructions at %>
8
- <%%# https://github.com/thoughtbot/superglue/blob/main/docs/recipes/server-side-rendering.md %>
9
- <div id="app"></div>