grsx 0.1.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.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/main.yml +20 -0
  3. data/.gitignore +5 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +6 -0
  6. data/Appraisals +17 -0
  7. data/CODE_OF_CONDUCT.md +74 -0
  8. data/Dockerfile +8 -0
  9. data/Gemfile +7 -0
  10. data/Gemfile.lock +274 -0
  11. data/Guardfile +70 -0
  12. data/LICENSE.txt +21 -0
  13. data/README.md +437 -0
  14. data/Rakefile +6 -0
  15. data/bin/console +14 -0
  16. data/bin/setup +8 -0
  17. data/bin/test +43 -0
  18. data/docker-compose.yml +29 -0
  19. data/gemfiles/.bundle/config +2 -0
  20. data/gemfiles/rails_6_1.gemfile +8 -0
  21. data/gemfiles/rails_6_1.gemfile.lock +260 -0
  22. data/gemfiles/rails_7_0.gemfile +7 -0
  23. data/gemfiles/rails_7_0.gemfile.lock +265 -0
  24. data/gemfiles/rails_7_1.gemfile +7 -0
  25. data/gemfiles/rails_7_1.gemfile.lock +295 -0
  26. data/gemfiles/rails_7_2.gemfile +7 -0
  27. data/gemfiles/rails_7_2.gemfile.lock +290 -0
  28. data/gemfiles/rails_8_0.gemfile +8 -0
  29. data/gemfiles/rails_8_0.gemfile.lock +344 -0
  30. data/gemfiles/rails_8_1.gemfile +8 -0
  31. data/gemfiles/rails_8_1.gemfile.lock +313 -0
  32. data/gemfiles/rails_master.gemfile +7 -0
  33. data/gemfiles/rails_master.gemfile.lock +296 -0
  34. data/grsx.gemspec +43 -0
  35. data/lib/generators/grsx/phlex_component/phlex_component_generator.rb +40 -0
  36. data/lib/generators/grsx/phlex_component/templates/component.rb.tt +12 -0
  37. data/lib/generators/grsx/phlex_component/templates/component.rbx.tt +6 -0
  38. data/lib/grsx/component_resolver.rb +64 -0
  39. data/lib/grsx/configuration.rb +14 -0
  40. data/lib/grsx/lexer.rb +325 -0
  41. data/lib/grsx/nodes/abstract_attr.rb +12 -0
  42. data/lib/grsx/nodes/abstract_element.rb +13 -0
  43. data/lib/grsx/nodes/abstract_node.rb +31 -0
  44. data/lib/grsx/nodes/component_element.rb +69 -0
  45. data/lib/grsx/nodes/component_prop.rb +29 -0
  46. data/lib/grsx/nodes/declaration.rb +15 -0
  47. data/lib/grsx/nodes/expression.rb +15 -0
  48. data/lib/grsx/nodes/expression_group.rb +15 -0
  49. data/lib/grsx/nodes/fragment.rb +30 -0
  50. data/lib/grsx/nodes/html_attr.rb +13 -0
  51. data/lib/grsx/nodes/html_element.rb +49 -0
  52. data/lib/grsx/nodes/newline.rb +9 -0
  53. data/lib/grsx/nodes/raw.rb +23 -0
  54. data/lib/grsx/nodes/root.rb +19 -0
  55. data/lib/grsx/nodes/text.rb +15 -0
  56. data/lib/grsx/nodes/util.rb +9 -0
  57. data/lib/grsx/nodes.rb +20 -0
  58. data/lib/grsx/parser.rb +238 -0
  59. data/lib/grsx/phlex_compiler.rb +223 -0
  60. data/lib/grsx/phlex_component.rb +361 -0
  61. data/lib/grsx/phlex_runtime.rb +70 -0
  62. data/lib/grsx/prop_inspector.rb +52 -0
  63. data/lib/grsx/rails/engine.rb +24 -0
  64. data/lib/grsx/rails/phlex_reloader.rb +25 -0
  65. data/lib/grsx/template.rb +12 -0
  66. data/lib/grsx/version.rb +3 -0
  67. data/lib/grsx.rb +35 -0
  68. metadata +324 -0
@@ -0,0 +1,296 @@
1
+ GIT
2
+ remote: https://github.com/rails/rails.git
3
+ revision: 23af6f37a310e16916ca788837f4a7accb2cebad
4
+ branch: main
5
+ specs:
6
+ actioncable (7.2.0.alpha)
7
+ actionpack (= 7.2.0.alpha)
8
+ activesupport (= 7.2.0.alpha)
9
+ nio4r (~> 2.0)
10
+ websocket-driver (>= 0.6.1)
11
+ zeitwerk (~> 2.6)
12
+ actionmailbox (7.2.0.alpha)
13
+ actionpack (= 7.2.0.alpha)
14
+ activejob (= 7.2.0.alpha)
15
+ activerecord (= 7.2.0.alpha)
16
+ activestorage (= 7.2.0.alpha)
17
+ activesupport (= 7.2.0.alpha)
18
+ mail (>= 2.8.0)
19
+ actionmailer (7.2.0.alpha)
20
+ actionpack (= 7.2.0.alpha)
21
+ actionview (= 7.2.0.alpha)
22
+ activejob (= 7.2.0.alpha)
23
+ activesupport (= 7.2.0.alpha)
24
+ mail (>= 2.8.0)
25
+ rails-dom-testing (~> 2.2)
26
+ actionpack (7.2.0.alpha)
27
+ actionview (= 7.2.0.alpha)
28
+ activesupport (= 7.2.0.alpha)
29
+ nokogiri (>= 1.8.5)
30
+ racc
31
+ rack (>= 2.2.4)
32
+ rack-session (>= 1.0.1)
33
+ rack-test (>= 0.6.3)
34
+ rails-dom-testing (~> 2.2)
35
+ rails-html-sanitizer (~> 1.6)
36
+ useragent (~> 0.16)
37
+ actiontext (7.2.0.alpha)
38
+ actionpack (= 7.2.0.alpha)
39
+ activerecord (= 7.2.0.alpha)
40
+ activestorage (= 7.2.0.alpha)
41
+ activesupport (= 7.2.0.alpha)
42
+ globalid (>= 0.6.0)
43
+ nokogiri (>= 1.8.5)
44
+ actionview (7.2.0.alpha)
45
+ activesupport (= 7.2.0.alpha)
46
+ builder (~> 3.1)
47
+ erubi (~> 1.11)
48
+ rails-dom-testing (~> 2.2)
49
+ rails-html-sanitizer (~> 1.6)
50
+ activejob (7.2.0.alpha)
51
+ activesupport (= 7.2.0.alpha)
52
+ globalid (>= 0.3.6)
53
+ activemodel (7.2.0.alpha)
54
+ activesupport (= 7.2.0.alpha)
55
+ activerecord (7.2.0.alpha)
56
+ activemodel (= 7.2.0.alpha)
57
+ activesupport (= 7.2.0.alpha)
58
+ timeout (>= 0.4.0)
59
+ activestorage (7.2.0.alpha)
60
+ actionpack (= 7.2.0.alpha)
61
+ activejob (= 7.2.0.alpha)
62
+ activerecord (= 7.2.0.alpha)
63
+ activesupport (= 7.2.0.alpha)
64
+ marcel (~> 1.0)
65
+ activesupport (7.2.0.alpha)
66
+ base64
67
+ bigdecimal
68
+ concurrent-ruby (~> 1.0, >= 1.0.2)
69
+ connection_pool (>= 2.2.5)
70
+ drb
71
+ i18n (>= 1.6, < 2)
72
+ minitest (>= 5.1, < 5.22.0)
73
+ tzinfo (~> 2.0, >= 2.0.5)
74
+ rails (7.2.0.alpha)
75
+ actioncable (= 7.2.0.alpha)
76
+ actionmailbox (= 7.2.0.alpha)
77
+ actionmailer (= 7.2.0.alpha)
78
+ actionpack (= 7.2.0.alpha)
79
+ actiontext (= 7.2.0.alpha)
80
+ actionview (= 7.2.0.alpha)
81
+ activejob (= 7.2.0.alpha)
82
+ activemodel (= 7.2.0.alpha)
83
+ activerecord (= 7.2.0.alpha)
84
+ activestorage (= 7.2.0.alpha)
85
+ activesupport (= 7.2.0.alpha)
86
+ bundler (>= 1.15.0)
87
+ railties (= 7.2.0.alpha)
88
+ railties (7.2.0.alpha)
89
+ actionpack (= 7.2.0.alpha)
90
+ activesupport (= 7.2.0.alpha)
91
+ irb
92
+ rackup (>= 1.0.0)
93
+ rake (>= 12.2)
94
+ thor (~> 1.0, >= 1.2.2)
95
+ zeitwerk (~> 2.6)
96
+
97
+ PATH
98
+ remote: ..
99
+ specs:
100
+ rbexy (2.0.0.rc5)
101
+ actionview (>= 6, < 8.2)
102
+ activesupport (>= 6, < 8.2)
103
+ ostruct
104
+
105
+ GEM
106
+ remote: https://rubygems.org/
107
+ specs:
108
+ appraisal (2.5.0)
109
+ bundler
110
+ rake
111
+ thor (>= 0.14.0)
112
+ base64 (0.2.0)
113
+ benchmark (0.5.0)
114
+ bigdecimal (3.1.6)
115
+ builder (3.2.4)
116
+ byebug (11.1.3)
117
+ coderay (1.1.3)
118
+ concurrent-ruby (1.2.3)
119
+ connection_pool (2.4.1)
120
+ crass (1.0.6)
121
+ date (3.3.4)
122
+ diff-lcs (1.5.1)
123
+ drb (2.2.0)
124
+ ruby2_keywords
125
+ erubi (1.12.0)
126
+ ffi (1.16.3)
127
+ formatador (1.1.0)
128
+ globalid (1.2.1)
129
+ activesupport (>= 6.1)
130
+ guard (2.18.1)
131
+ formatador (>= 0.2.4)
132
+ listen (>= 2.7, < 4.0)
133
+ lumberjack (>= 1.0.12, < 2.0)
134
+ nenv (~> 0.1)
135
+ notiffany (~> 0.0)
136
+ pry (>= 0.13.0)
137
+ shellany (~> 0.0)
138
+ thor (>= 0.18.1)
139
+ guard-compat (1.2.1)
140
+ guard-rspec (4.7.3)
141
+ guard (~> 2.1)
142
+ guard-compat (~> 1.1)
143
+ rspec (>= 2.99.0, < 4.0)
144
+ i18n (1.14.1)
145
+ concurrent-ruby (~> 1.0)
146
+ io-console (0.7.2)
147
+ irb (1.11.2)
148
+ rdoc
149
+ reline (>= 0.4.2)
150
+ listen (3.9.0)
151
+ rb-fsevent (~> 0.10, >= 0.10.3)
152
+ rb-inotify (~> 0.9, >= 0.9.10)
153
+ logger (1.7.0)
154
+ loofah (2.22.0)
155
+ crass (~> 1.0.2)
156
+ nokogiri (>= 1.12.0)
157
+ lumberjack (1.2.10)
158
+ mail (2.8.1)
159
+ mini_mime (>= 0.1.1)
160
+ net-imap
161
+ net-pop
162
+ net-smtp
163
+ marcel (1.0.2)
164
+ memory_profiler (0.9.14)
165
+ method_source (1.0.0)
166
+ mini_mime (1.1.5)
167
+ mini_portile2 (2.8.9)
168
+ minitest (5.21.2)
169
+ mutex_m (0.3.0)
170
+ nenv (0.3.0)
171
+ net-imap (0.4.10)
172
+ date
173
+ net-protocol
174
+ net-pop (0.1.2)
175
+ net-protocol
176
+ net-protocol (0.2.2)
177
+ timeout
178
+ net-smtp (0.4.0.1)
179
+ net-protocol
180
+ nio4r (2.7.0)
181
+ nokogiri (1.16.2)
182
+ mini_portile2 (~> 2.8.2)
183
+ racc (~> 1.4)
184
+ notiffany (0.1.3)
185
+ nenv (~> 0.1)
186
+ shellany (~> 0.0)
187
+ ostruct (0.6.3)
188
+ pry (0.14.2)
189
+ coderay (~> 1.1)
190
+ method_source (~> 1.0)
191
+ pry-byebug (3.10.1)
192
+ byebug (~> 11.0)
193
+ pry (>= 0.13, < 0.15)
194
+ psych (5.1.2)
195
+ stringio
196
+ puma (6.4.2)
197
+ nio4r (~> 2.0)
198
+ racc (1.7.3)
199
+ rack (3.0.9.1)
200
+ rack-session (2.0.0)
201
+ rack (>= 3.0.0)
202
+ rack-test (2.1.0)
203
+ rack (>= 1.3)
204
+ rackup (2.1.0)
205
+ rack (>= 3)
206
+ webrick (~> 1.8)
207
+ rails-dom-testing (2.2.0)
208
+ activesupport (>= 5.0.0)
209
+ minitest
210
+ nokogiri (>= 1.6)
211
+ rails-html-sanitizer (1.6.0)
212
+ loofah (~> 2.21)
213
+ nokogiri (~> 1.14)
214
+ rake (13.1.0)
215
+ rb-fsevent (0.11.2)
216
+ rb-inotify (0.10.1)
217
+ ffi (~> 1.0)
218
+ rdoc (6.6.2)
219
+ psych (>= 4.0.0)
220
+ reline (0.4.2)
221
+ io-console (~> 0.5)
222
+ rspec (3.13.0)
223
+ rspec-core (~> 3.13.0)
224
+ rspec-expectations (~> 3.13.0)
225
+ rspec-mocks (~> 3.13.0)
226
+ rspec-core (3.13.0)
227
+ rspec-support (~> 3.13.0)
228
+ rspec-expectations (3.13.0)
229
+ diff-lcs (>= 1.2.0, < 2.0)
230
+ rspec-support (~> 3.13.0)
231
+ rspec-html-matchers (0.9.4)
232
+ nokogiri (~> 1)
233
+ rspec (>= 3.0.0.a, < 4)
234
+ rspec-mocks (3.13.0)
235
+ diff-lcs (>= 1.2.0, < 2.0)
236
+ rspec-support (~> 3.13.0)
237
+ rspec-rails (6.1.1)
238
+ actionpack (>= 6.1)
239
+ activesupport (>= 6.1)
240
+ railties (>= 6.1)
241
+ rspec-core (~> 3.12)
242
+ rspec-expectations (~> 3.12)
243
+ rspec-mocks (~> 3.12)
244
+ rspec-support (~> 3.12)
245
+ rspec-support (3.13.1)
246
+ ruby2_keywords (0.0.5)
247
+ shellany (0.0.1)
248
+ sprockets (4.2.1)
249
+ concurrent-ruby (~> 1.0)
250
+ rack (>= 2.2.4, < 4)
251
+ sprockets-rails (3.4.2)
252
+ actionpack (>= 5.2)
253
+ activesupport (>= 5.2)
254
+ sprockets (>= 3.0.0)
255
+ sqlite3 (1.7.2)
256
+ mini_portile2 (~> 2.8.0)
257
+ stringio (3.1.0)
258
+ thor (1.3.0)
259
+ timeout (0.4.1)
260
+ tzinfo (2.0.6)
261
+ concurrent-ruby (~> 1.0)
262
+ useragent (0.16.10)
263
+ webrick (1.8.1)
264
+ websocket-driver (0.7.6)
265
+ websocket-extensions (>= 0.1.0)
266
+ websocket-extensions (0.1.5)
267
+ zeitwerk (2.6.13)
268
+
269
+ PLATFORMS
270
+ arm64-darwin-23
271
+ x86_64-darwin-25
272
+ x86_64-linux
273
+
274
+ DEPENDENCIES
275
+ appraisal (~> 2.2)
276
+ base64
277
+ benchmark
278
+ bigdecimal
279
+ drb
280
+ guard-rspec (~> 4.7, >= 4.7.3)
281
+ logger
282
+ memory_profiler (~> 0.9.14)
283
+ mutex_m
284
+ pry-byebug
285
+ puma
286
+ rails!
287
+ rake
288
+ rbexy!
289
+ rspec (~> 3.12)
290
+ rspec-html-matchers (~> 0.9.3)
291
+ rspec-rails (~> 6.0, >= 6.0.3)
292
+ sprockets-rails (>= 2, < 4)
293
+ sqlite3
294
+
295
+ BUNDLED WITH
296
+ 2.5.6
data/grsx.gemspec ADDED
@@ -0,0 +1,43 @@
1
+ require_relative 'lib/grsx/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "grsx"
5
+ spec.version = Grsx::VERSION
6
+ spec.authors = ["Gatopan"]
7
+ spec.email = ["dev@gatopan.com"]
8
+
9
+ spec.summary = "GRSX — JSX-flavored templates for Ruby, powered by Phlex"
10
+ spec.homepage = "https://github.com/gatopan/grsx"
11
+ spec.license = "MIT"
12
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.1.0")
13
+
14
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
15
+ spec.metadata["homepage_uri"] = spec.homepage
16
+ spec.metadata["source_code_uri"] = "https://github.com/gatopan/grsx"
17
+
18
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
19
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
+ end
21
+ spec.bindir = "exe"
22
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
+ spec.require_paths = ["lib"]
24
+
25
+ # Runtime
26
+ spec.add_dependency "activesupport", ">= 7.1"
27
+ spec.add_dependency "phlex", "~> 2.0"
28
+ spec.add_dependency "phlex-rails", "~> 2.0"
29
+
30
+ # Development / test
31
+ spec.add_development_dependency "appraisal", "~> 2.2"
32
+ spec.add_development_dependency "rails", ">= 7.1"
33
+ spec.add_development_dependency "rspec", "~> 3.12"
34
+ spec.add_development_dependency "rspec-rails", "~> 6.0", ">= 6.0.3"
35
+ spec.add_development_dependency "rake"
36
+ spec.add_development_dependency "pry-byebug"
37
+ spec.add_development_dependency "mutex_m"
38
+ spec.add_development_dependency "logger"
39
+ spec.add_development_dependency "bigdecimal"
40
+ spec.add_development_dependency "drb"
41
+ spec.add_development_dependency "benchmark"
42
+ spec.add_development_dependency "base64"
43
+ end
@@ -0,0 +1,40 @@
1
+ require "rails/generators"
2
+
3
+ module Grsx
4
+ module Generators
5
+ class PhlexComponentGenerator < ::Rails::Generators::NamedBase
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ class_option :slots, type: :array, default: [],
9
+ desc: "Named content slots to declare (e.g. --slots header footer)"
10
+
11
+ desc "Creates a Grsx::PhlexComponent with a co-located .rbx template"
12
+
13
+ def create_component_file
14
+ template "component.rb.tt", component_rb_path
15
+ end
16
+
17
+ def create_template_file
18
+ template "component.rbx.tt", component_rbx_path
19
+ end
20
+
21
+ private
22
+
23
+ def component_rb_path
24
+ File.join("app", "components", class_path, "#{file_name}_component.rb")
25
+ end
26
+
27
+ def component_rbx_path
28
+ File.join("app", "components", class_path, "#{file_name}_component.rbx")
29
+ end
30
+
31
+ def slot_names
32
+ options[:slots]
33
+ end
34
+
35
+ def component_class_name
36
+ "#{class_name}Component"
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,12 @@
1
+ class <%= component_class_name %> < Rbexy::PhlexComponent
2
+ <% if slot_names.any? -%>
3
+ slots <%= slot_names.map { |s| ":#{s}" }.join(", ") %>
4
+
5
+ <% end -%>
6
+ def initialize
7
+ # Define your props here, e.g.:
8
+ # def initialize(title:)
9
+ # @title = title
10
+ # end
11
+ end
12
+ end
@@ -0,0 +1,6 @@
1
+ <div class="<%= file_name.dasherize %>">
2
+ <% slot_names.each do |slot| -%>
3
+ <div class="<%= slot.dasherize %>-slot">{slot(:<%= slot %>)}</div>
4
+ <% end -%>
5
+ {content}
6
+ </div>
@@ -0,0 +1,64 @@
1
+ require "set"
2
+
3
+ module Grsx
4
+ class ComponentResolver
5
+ KNOWN_HTML_ELEMENTS = %w(
6
+ a abbr acronym address animate animateMotion animateTransform applet area article aside audio b base basefont
7
+ bdi bdo bgsound big blink blockquote body br button canvas caption center circle cite clipPath code col colgroup
8
+ color-profile command content data datalist dd defs del desc details dfn dialog dir discard div dl dt element
9
+ ellipse em embed feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix feDiffuseLighting
10
+ feDisplacementMap feDistantLight feDropShadow feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur feImage
11
+ feMerge feMergeNode feMorphology feOffset fePointLight feSpecularLighting feSpotLight feTile feTurbulence
12
+ fieldset figcaption figure filter font footer foreignObject form frame frameset g h1 h2 h3 h4 h5 h6 hatch
13
+ hatchpath head header hgroup hr html i iframe image img input ins isindex kbd keygen label legend li line
14
+ linearGradient link listing main map mark marker marquee mask menu menuitem mesh meshgradient meshpatch meshrow
15
+ meta metadata meter mpath multicol nav nextid nobr noembed noframes noscript object ol optgroup option output p
16
+ param path pattern picture plaintext polygon polyline pre progress q radialGradient rb rect rp rt rtc ruby s
17
+ samp script section select set shadow slot small solidcolor source spacer span stop strike strong style sub
18
+ summary sup svg switch symbol table tbody td template text textarea textPath tfoot th thead time title tr track
19
+ tspan tt u ul unknown use var video view wbr xmp
20
+ ).to_set
21
+
22
+ def self.try_constantize
23
+ yield
24
+ rescue NameError => e
25
+ raise e unless e.message =~ /wrong constant name/ || e.message =~ /uninitialized constant/
26
+ nil
27
+ end
28
+
29
+ attr_reader :component_namespaces
30
+
31
+ def initialize
32
+ self.component_namespaces = {}
33
+ end
34
+
35
+ def component_namespaces=(hash)
36
+ @component_namespaces = hash.transform_keys(&:to_s)
37
+ end
38
+
39
+ def component?(name, template)
40
+ return false if KNOWN_HTML_ELEMENTS.include?(name)
41
+ return true if component_class(name, template)
42
+ false
43
+ end
44
+
45
+ def component_class(name, template)
46
+ possible_names = matching_namespaces(template).map { |ns| "#{ns}.#{name}" } << name
47
+ possible_names.each do |n|
48
+ result = find(n)
49
+ return result if result
50
+ end
51
+ nil
52
+ end
53
+
54
+ private
55
+
56
+ def find(name)
57
+ self.class.try_constantize { ActiveSupport::Inflector.constantize("#{name.gsub(".", "::")}Component") }
58
+ end
59
+
60
+ def matching_namespaces(template)
61
+ component_namespaces.select { |path, ns| template.identifier.start_with?(path) }.values.flatten.uniq
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,14 @@
1
+ module Grsx
2
+ class Configuration
3
+ attr_accessor :template_paths
4
+ attr_accessor :debug
5
+
6
+ def template_paths
7
+ @template_paths ||= []
8
+ end
9
+
10
+ def element_resolver
11
+ @element_resolver ||= ComponentResolver.new
12
+ end
13
+ end
14
+ end