@tutorialkit-rb/cli 1.5.2-rb.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 (151) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +15 -0
  3. package/dist/index.js +1384 -0
  4. package/package.json +66 -0
  5. package/template/.gitignore +13 -0
  6. package/template/.vscode/extensions.json +4 -0
  7. package/template/.vscode/launch.json +11 -0
  8. package/template/README.md +179 -0
  9. package/template/astro.config.ts +21 -0
  10. package/template/bin/build-wasm +30 -0
  11. package/template/icons/languages/css.svg +1 -0
  12. package/template/icons/languages/html.svg +1 -0
  13. package/template/icons/languages/js.svg +1 -0
  14. package/template/icons/languages/json.svg +1 -0
  15. package/template/icons/languages/markdown.svg +1 -0
  16. package/template/icons/languages/ruby.svg +1 -0
  17. package/template/icons/languages/sass.svg +1 -0
  18. package/template/icons/languages/ts.svg +1 -0
  19. package/template/icons/phosphor/file-erb.svg +1 -0
  20. package/template/icons/phosphor/file-rb.svg +5 -0
  21. package/template/package.json +37 -0
  22. package/template/package.json.bak +37 -0
  23. package/template/public/favicon.svg +4 -0
  24. package/template/public/logo-dark.svg +4 -0
  25. package/template/public/logo.svg +4 -0
  26. package/template/ruby-wasm/.railsrc +12 -0
  27. package/template/ruby-wasm/Gemfile +22 -0
  28. package/template/ruby-wasm/Gemfile.lock +292 -0
  29. package/template/ruby-wasm/README.md +19 -0
  30. package/template/ruby-wasm/bin/pack +16 -0
  31. package/template/ruby-wasm/boot.rb +32 -0
  32. package/template/ruby-wasm/config/wasmify.yml +23 -0
  33. package/template/src/components/FileManager.tsx +116 -0
  34. package/template/src/components/GitHubLink.astro +17 -0
  35. package/template/src/components/HeadTags.astro +65 -0
  36. package/template/src/components/HelpDropdown.tsx +72 -0
  37. package/template/src/components/RailsPathLinkHandler.tsx +107 -0
  38. package/template/src/components/ShellConfigurator.tsx +95 -0
  39. package/template/src/components/TopBar.astro +48 -0
  40. package/template/src/content/config.ts +9 -0
  41. package/template/src/content/tutorial/1-getting-started/1-creating-your-first-rails-app/_files/workspace/.keep +0 -0
  42. package/template/src/content/tutorial/1-getting-started/1-creating-your-first-rails-app/content.md +34 -0
  43. package/template/src/content/tutorial/1-getting-started/2-rails-console/_files/.tk-config.json +3 -0
  44. package/template/src/content/tutorial/1-getting-started/2-rails-console/_files/workspace/.keep +0 -0
  45. package/template/src/content/tutorial/1-getting-started/2-rails-console/content.md +37 -0
  46. package/template/src/content/tutorial/1-getting-started/meta.md +4 -0
  47. package/template/src/content/tutorial/2-controllers/2-crud-operations/_files/.tk-config.json +3 -0
  48. package/template/src/content/tutorial/2-controllers/2-crud-operations/_files/workspace/.keep +0 -0
  49. package/template/src/content/tutorial/2-controllers/2-crud-operations/content.md +99 -0
  50. package/template/src/content/tutorial/2-controllers/meta.md +4 -0
  51. package/template/src/content/tutorial/meta.md +18 -0
  52. package/template/src/env.d.ts +3 -0
  53. package/template/src/plugins/remarkRailsPathLinks.ts +39 -0
  54. package/template/src/templates/crud-products/.tk-config.json +3 -0
  55. package/template/src/templates/crud-products/workspace/.keep +0 -0
  56. package/template/src/templates/crud-products/workspace/store/app/controllers/products_controller.rb +48 -0
  57. package/template/src/templates/crud-products/workspace/store/app/models/product.rb +3 -0
  58. package/template/src/templates/crud-products/workspace/store/app/views/products/_form.html.erb +10 -0
  59. package/template/src/templates/crud-products/workspace/store/app/views/products/edit.html.erb +4 -0
  60. package/template/src/templates/crud-products/workspace/store/app/views/products/index.html.erb +11 -0
  61. package/template/src/templates/crud-products/workspace/store/app/views/products/new.html.erb +4 -0
  62. package/template/src/templates/crud-products/workspace/store/app/views/products/show.html.erb +5 -0
  63. package/template/src/templates/crud-products/workspace/store/config/routes.rb +6 -0
  64. package/template/src/templates/crud-products/workspace/store/db/migrate/20250521010850_create_products.rb +9 -0
  65. package/template/src/templates/crud-products/workspace/store/db/schema.rb +22 -0
  66. package/template/src/templates/crud-products/workspace/store/db/seeds.rb +3 -0
  67. package/template/src/templates/crud-products/workspace/store/test/fixtures/products.yml +7 -0
  68. package/template/src/templates/crud-products/workspace/store/test/models/product_test.rb +7 -0
  69. package/template/src/templates/default/bin/console +9 -0
  70. package/template/src/templates/default/bin/rackup +11 -0
  71. package/template/src/templates/default/bin/rails +41 -0
  72. package/template/src/templates/default/bin/ruby +37 -0
  73. package/template/src/templates/default/lib/commands.js +39 -0
  74. package/template/src/templates/default/lib/database.js +46 -0
  75. package/template/src/templates/default/lib/irb.js +110 -0
  76. package/template/src/templates/default/lib/patches/app_generator.rb +43 -0
  77. package/template/src/templates/default/lib/patches/authentication.rb +24 -0
  78. package/template/src/templates/default/lib/rails.js +69 -0
  79. package/template/src/templates/default/lib/server/frame_location_middleware.js +77 -0
  80. package/template/src/templates/default/lib/server.js +307 -0
  81. package/template/src/templates/default/package-lock.json +1830 -0
  82. package/template/src/templates/default/package.json +23 -0
  83. package/template/src/templates/default/pgdata/.keep +0 -0
  84. package/template/src/templates/default/scripts/createdb.js +7 -0
  85. package/template/src/templates/default/scripts/rails.js +52 -0
  86. package/template/src/templates/default/scripts/wait-for-wasm.js +103 -0
  87. package/template/src/templates/default/workspace/.keep +0 -0
  88. package/template/src/templates/rails-app/workspace/store/.ruby-version +1 -0
  89. package/template/src/templates/rails-app/workspace/store/Gemfile +37 -0
  90. package/template/src/templates/rails-app/workspace/store/README.md +24 -0
  91. package/template/src/templates/rails-app/workspace/store/Rakefile +6 -0
  92. package/template/src/templates/rails-app/workspace/store/app/assets/images/.keep +0 -0
  93. package/template/src/templates/rails-app/workspace/store/app/assets/stylesheets/application.css +10 -0
  94. package/template/src/templates/rails-app/workspace/store/app/controllers/application_controller.rb +4 -0
  95. package/template/src/templates/rails-app/workspace/store/app/helpers/application_helper.rb +2 -0
  96. package/template/src/templates/rails-app/workspace/store/app/javascript/application.js +4 -0
  97. package/template/src/templates/rails-app/workspace/store/app/javascript/controllers/application.js +9 -0
  98. package/template/src/templates/rails-app/workspace/store/app/javascript/controllers/index.js +4 -0
  99. package/template/src/templates/rails-app/workspace/store/app/jobs/application_job.rb +7 -0
  100. package/template/src/templates/rails-app/workspace/store/app/mailers/application_mailer.rb +4 -0
  101. package/template/src/templates/rails-app/workspace/store/app/models/application_record.rb +3 -0
  102. package/template/src/templates/rails-app/workspace/store/app/models/concerns/.keep +0 -0
  103. package/template/src/templates/rails-app/workspace/store/app/views/layouts/application.html.erb +28 -0
  104. package/template/src/templates/rails-app/workspace/store/app/views/layouts/mailer.html.erb +13 -0
  105. package/template/src/templates/rails-app/workspace/store/app/views/layouts/mailer.text.erb +1 -0
  106. package/template/src/templates/rails-app/workspace/store/app/views/pwa/manifest.json.erb +22 -0
  107. package/template/src/templates/rails-app/workspace/store/app/views/pwa/service-worker.js +26 -0
  108. package/template/src/templates/rails-app/workspace/store/bin/importmap +4 -0
  109. package/template/src/templates/rails-app/workspace/store/bin/rails +4 -0
  110. package/template/src/templates/rails-app/workspace/store/config/application.rb +30 -0
  111. package/template/src/templates/rails-app/workspace/store/config/boot.rb +3 -0
  112. package/template/src/templates/rails-app/workspace/store/config/cable.yml +10 -0
  113. package/template/src/templates/rails-app/workspace/store/config/credentials.yml.enc +1 -0
  114. package/template/src/templates/rails-app/workspace/store/config/database.yml +32 -0
  115. package/template/src/templates/rails-app/workspace/store/config/environment.rb +5 -0
  116. package/template/src/templates/rails-app/workspace/store/config/environments/development.rb +69 -0
  117. package/template/src/templates/rails-app/workspace/store/config/environments/production.rb +89 -0
  118. package/template/src/templates/rails-app/workspace/store/config/environments/test.rb +53 -0
  119. package/template/src/templates/rails-app/workspace/store/config/importmap.rb +9 -0
  120. package/template/src/templates/rails-app/workspace/store/config/initializers/assets.rb +7 -0
  121. package/template/src/templates/rails-app/workspace/store/config/initializers/content_security_policy.rb +25 -0
  122. package/template/src/templates/rails-app/workspace/store/config/initializers/filter_parameter_logging.rb +8 -0
  123. package/template/src/templates/rails-app/workspace/store/config/initializers/inflections.rb +16 -0
  124. package/template/src/templates/rails-app/workspace/store/config/locales/en.yml +31 -0
  125. package/template/src/templates/rails-app/workspace/store/config/master.key +1 -0
  126. package/template/src/templates/rails-app/workspace/store/config/puma.rb +41 -0
  127. package/template/src/templates/rails-app/workspace/store/config/routes.rb +4 -0
  128. package/template/src/templates/rails-app/workspace/store/config/storage.yml +34 -0
  129. package/template/src/templates/rails-app/workspace/store/config.ru +6 -0
  130. package/template/src/templates/rails-app/workspace/store/db/seeds.rb +9 -0
  131. package/template/src/templates/rails-app/workspace/store/log/.keep +0 -0
  132. package/template/src/templates/rails-app/workspace/store/public/400.html +114 -0
  133. package/template/src/templates/rails-app/workspace/store/public/404.html +114 -0
  134. package/template/src/templates/rails-app/workspace/store/public/406-unsupported-browser.html +114 -0
  135. package/template/src/templates/rails-app/workspace/store/public/422.html +114 -0
  136. package/template/src/templates/rails-app/workspace/store/public/500.html +114 -0
  137. package/template/src/templates/rails-app/workspace/store/public/icon.png +0 -0
  138. package/template/src/templates/rails-app/workspace/store/public/icon.svg +3 -0
  139. package/template/src/templates/rails-app/workspace/store/public/robots.txt +1 -0
  140. package/template/src/templates/rails-app/workspace/store/script/.keep +0 -0
  141. package/template/src/templates/rails-app/workspace/store/storage/.keep +0 -0
  142. package/template/src/templates/rails-app/workspace/store/test/controllers/.keep +0 -0
  143. package/template/src/templates/rails-app/workspace/store/test/helpers/.keep +0 -0
  144. package/template/src/templates/rails-app/workspace/store/test/integration/.keep +0 -0
  145. package/template/src/templates/rails-app/workspace/store/test/test_helper.rb +15 -0
  146. package/template/src/templates/rails-app/workspace/store/tmp/.keep +0 -0
  147. package/template/src/templates/rails-app/workspace/store/tmp/pids/.keep +0 -0
  148. package/template/src/templates/rails-app/workspace/store/tmp/storage/.keep +0 -0
  149. package/template/src/templates/rails-app/workspace/store/vendor/javascripts/.keep +0 -0
  150. package/template/tsconfig.json +16 -0
  151. package/template/uno.config.ts +10 -0
@@ -0,0 +1,292 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ actioncable (8.0.2)
5
+ actionpack (= 8.0.2)
6
+ activesupport (= 8.0.2)
7
+ nio4r (~> 2.0)
8
+ websocket-driver (>= 0.6.1)
9
+ zeitwerk (~> 2.6)
10
+ actionmailbox (8.0.2)
11
+ actionpack (= 8.0.2)
12
+ activejob (= 8.0.2)
13
+ activerecord (= 8.0.2)
14
+ activestorage (= 8.0.2)
15
+ activesupport (= 8.0.2)
16
+ mail (>= 2.8.0)
17
+ actionmailer (8.0.2)
18
+ actionpack (= 8.0.2)
19
+ actionview (= 8.0.2)
20
+ activejob (= 8.0.2)
21
+ activesupport (= 8.0.2)
22
+ mail (>= 2.8.0)
23
+ rails-dom-testing (~> 2.2)
24
+ actionpack (8.0.2)
25
+ actionview (= 8.0.2)
26
+ activesupport (= 8.0.2)
27
+ nokogiri (>= 1.8.5)
28
+ rack (>= 2.2.4)
29
+ rack-session (>= 1.0.1)
30
+ rack-test (>= 0.6.3)
31
+ rails-dom-testing (~> 2.2)
32
+ rails-html-sanitizer (~> 1.6)
33
+ useragent (~> 0.16)
34
+ actiontext (8.0.2)
35
+ actionpack (= 8.0.2)
36
+ activerecord (= 8.0.2)
37
+ activestorage (= 8.0.2)
38
+ activesupport (= 8.0.2)
39
+ globalid (>= 0.6.0)
40
+ nokogiri (>= 1.8.5)
41
+ actionview (8.0.2)
42
+ activesupport (= 8.0.2)
43
+ builder (~> 3.1)
44
+ erubi (~> 1.11)
45
+ rails-dom-testing (~> 2.2)
46
+ rails-html-sanitizer (~> 1.6)
47
+ activejob (8.0.2)
48
+ activesupport (= 8.0.2)
49
+ globalid (>= 0.3.6)
50
+ activemodel (8.0.2)
51
+ activesupport (= 8.0.2)
52
+ activerecord (8.0.2)
53
+ activemodel (= 8.0.2)
54
+ activesupport (= 8.0.2)
55
+ timeout (>= 0.4.0)
56
+ activestorage (8.0.2)
57
+ actionpack (= 8.0.2)
58
+ activejob (= 8.0.2)
59
+ activerecord (= 8.0.2)
60
+ activesupport (= 8.0.2)
61
+ marcel (~> 1.0)
62
+ activesupport (8.0.2)
63
+ base64
64
+ benchmark (>= 0.3)
65
+ bigdecimal
66
+ concurrent-ruby (~> 1.0, >= 1.3.1)
67
+ connection_pool (>= 2.2.5)
68
+ drb
69
+ i18n (>= 1.6, < 2)
70
+ logger (>= 1.4.2)
71
+ minitest (>= 5.1)
72
+ securerandom (>= 0.3)
73
+ tzinfo (~> 2.0, >= 2.0.5)
74
+ uri (>= 0.13.1)
75
+ base64 (0.2.0)
76
+ bcrypt (3.1.20)
77
+ benchmark (0.4.0)
78
+ bigdecimal (3.1.9)
79
+ builder (3.3.0)
80
+ concurrent-ruby (1.3.5)
81
+ connection_pool (2.5.3)
82
+ crass (1.0.6)
83
+ date (3.4.1)
84
+ drb (2.2.1)
85
+ erubi (1.13.1)
86
+ et-orbi (1.2.11)
87
+ tzinfo
88
+ ffi (1.17.1-aarch64-linux-gnu)
89
+ ffi (1.17.1-aarch64-linux-musl)
90
+ ffi (1.17.1-arm-linux-gnu)
91
+ ffi (1.17.1-arm-linux-musl)
92
+ ffi (1.17.1-arm64-darwin)
93
+ ffi (1.17.1-x86_64-darwin)
94
+ ffi (1.17.1-x86_64-linux-gnu)
95
+ ffi (1.17.1-x86_64-linux-musl)
96
+ fugit (1.11.1)
97
+ et-orbi (~> 1, >= 1.2.11)
98
+ raabro (~> 1.4)
99
+ globalid (1.2.1)
100
+ activesupport (>= 6.1)
101
+ i18n (1.14.7)
102
+ concurrent-ruby (~> 1.0)
103
+ image_processing (1.13.0)
104
+ mini_magick (>= 4.9.5, < 5)
105
+ ruby-vips (>= 2.0.17, < 3)
106
+ importmap-rails (2.1.0)
107
+ actionpack (>= 6.0.0)
108
+ activesupport (>= 6.0.0)
109
+ railties (>= 6.0.0)
110
+ io-console (0.8.0)
111
+ irb (1.15.2)
112
+ pp (>= 0.6.0)
113
+ rdoc (>= 4.0.0)
114
+ reline (>= 0.4.2)
115
+ jbuilder (2.13.0)
116
+ actionview (>= 5.0.0)
117
+ activesupport (>= 5.0.0)
118
+ js (2.7.1)
119
+ logger (1.7.0)
120
+ loofah (2.24.0)
121
+ crass (~> 1.0.2)
122
+ nokogiri (>= 1.12.0)
123
+ mail (2.8.1)
124
+ mini_mime (>= 0.1.1)
125
+ net-imap
126
+ net-pop
127
+ net-smtp
128
+ marcel (1.0.4)
129
+ mini_magick (4.13.2)
130
+ mini_mime (1.1.5)
131
+ minitest (5.25.5)
132
+ net-imap (0.5.8)
133
+ date
134
+ net-protocol
135
+ net-pop (0.1.2)
136
+ net-protocol
137
+ net-protocol (0.2.2)
138
+ timeout
139
+ net-smtp (0.5.1)
140
+ net-protocol
141
+ nio4r (2.7.4)
142
+ nokogiri (1.18.8-aarch64-linux-gnu)
143
+ racc (~> 1.4)
144
+ nokogiri (1.18.8-aarch64-linux-musl)
145
+ racc (~> 1.4)
146
+ nokogiri (1.18.8-arm-linux-gnu)
147
+ racc (~> 1.4)
148
+ nokogiri (1.18.8-arm-linux-musl)
149
+ racc (~> 1.4)
150
+ nokogiri (1.18.8-arm64-darwin)
151
+ racc (~> 1.4)
152
+ nokogiri (1.18.8-x86_64-darwin)
153
+ racc (~> 1.4)
154
+ nokogiri (1.18.8-x86_64-linux-gnu)
155
+ racc (~> 1.4)
156
+ nokogiri (1.18.8-x86_64-linux-musl)
157
+ racc (~> 1.4)
158
+ pp (0.6.2)
159
+ prettyprint
160
+ prettyprint (0.2.0)
161
+ propshaft (1.1.0)
162
+ actionpack (>= 7.0.0)
163
+ activesupport (>= 7.0.0)
164
+ rack
165
+ railties (>= 7.0.0)
166
+ psych (5.2.4)
167
+ date
168
+ stringio
169
+ raabro (1.4.0)
170
+ racc (1.8.1)
171
+ rack (3.1.13)
172
+ rack-session (2.1.1)
173
+ base64 (>= 0.1.0)
174
+ rack (>= 3.0.0)
175
+ rack-test (2.2.0)
176
+ rack (>= 1.3)
177
+ rackup (2.2.1)
178
+ rack (>= 3)
179
+ rails (8.0.2)
180
+ actioncable (= 8.0.2)
181
+ actionmailbox (= 8.0.2)
182
+ actionmailer (= 8.0.2)
183
+ actionpack (= 8.0.2)
184
+ actiontext (= 8.0.2)
185
+ actionview (= 8.0.2)
186
+ activejob (= 8.0.2)
187
+ activemodel (= 8.0.2)
188
+ activerecord (= 8.0.2)
189
+ activestorage (= 8.0.2)
190
+ activesupport (= 8.0.2)
191
+ bundler (>= 1.15.0)
192
+ railties (= 8.0.2)
193
+ rails-dom-testing (2.2.0)
194
+ activesupport (>= 5.0.0)
195
+ minitest
196
+ nokogiri (>= 1.6)
197
+ rails-html-sanitizer (1.6.2)
198
+ loofah (~> 2.21)
199
+ nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
200
+ railties (8.0.2)
201
+ actionpack (= 8.0.2)
202
+ activesupport (= 8.0.2)
203
+ irb (~> 1.13)
204
+ rackup (>= 1.0.0)
205
+ rake (>= 12.2)
206
+ thor (~> 1.0, >= 1.2.2)
207
+ zeitwerk (~> 2.6)
208
+ rake (13.2.1)
209
+ rdoc (6.13.1)
210
+ psych (>= 4.0.0)
211
+ reline (0.6.1)
212
+ io-console (~> 0.5)
213
+ ruby-vips (2.2.2)
214
+ ffi (~> 1.12)
215
+ logger
216
+ ruby_wasm (2.7.1)
217
+ ruby_wasm (2.7.1-aarch64-linux)
218
+ ruby_wasm (2.7.1-aarch64-linux-musl)
219
+ ruby_wasm (2.7.1-arm64-darwin)
220
+ ruby_wasm (2.7.1-x86_64-darwin)
221
+ ruby_wasm (2.7.1-x86_64-linux)
222
+ ruby_wasm (2.7.1-x86_64-linux-musl)
223
+ securerandom (0.4.1)
224
+ solid_cable (3.0.4)
225
+ actioncable (>= 7.2)
226
+ activejob (>= 7.2)
227
+ activerecord (>= 7.2)
228
+ railties (>= 7.2)
229
+ solid_cache (1.0.6)
230
+ activejob (>= 7.2)
231
+ activerecord (>= 7.2)
232
+ railties (>= 7.2)
233
+ solid_queue (1.1.0)
234
+ activejob (>= 7.1)
235
+ activerecord (>= 7.1)
236
+ concurrent-ruby (>= 1.3.1)
237
+ fugit (~> 1.11.0)
238
+ railties (>= 7.1)
239
+ thor (~> 1.3.1)
240
+ stimulus-rails (1.3.4)
241
+ railties (>= 6.0.0)
242
+ stringio (3.1.7)
243
+ thor (1.3.2)
244
+ timeout (0.4.3)
245
+ turbo-rails (2.0.11)
246
+ actionpack (>= 6.0.0)
247
+ railties (>= 6.0.0)
248
+ tzinfo (2.0.6)
249
+ concurrent-ruby (~> 1.0)
250
+ tzinfo-data (1.2025.2)
251
+ tzinfo (>= 1.0.0)
252
+ uri (1.0.3)
253
+ useragent (0.16.11)
254
+ wasmify-rails (0.4.0)
255
+ js (>= 2.6, < 3.0)
256
+ railties (>= 7.0, < 9.0)
257
+ ruby_wasm (>= 2.6, < 3.0)
258
+ websocket-driver (0.7.7)
259
+ base64
260
+ websocket-extensions (>= 0.1.0)
261
+ websocket-extensions (0.1.5)
262
+ zeitwerk (2.7.2)
263
+
264
+ PLATFORMS
265
+ aarch64-linux
266
+ aarch64-linux-gnu
267
+ aarch64-linux-musl
268
+ arm-linux-gnu
269
+ arm-linux-musl
270
+ arm64-darwin
271
+ x86_64-darwin
272
+ x86_64-linux
273
+ x86_64-linux-gnu
274
+ x86_64-linux-musl
275
+
276
+ DEPENDENCIES
277
+ bcrypt (~> 3.1.7)
278
+ image_processing (~> 1.2)
279
+ importmap-rails
280
+ jbuilder
281
+ propshaft
282
+ rails (~> 8.0.0)
283
+ solid_cable
284
+ solid_cache
285
+ solid_queue
286
+ stimulus-rails
287
+ turbo-rails
288
+ tzinfo-data
289
+ wasmify-rails (~> 0.4.0)
290
+
291
+ BUNDLED WITH
292
+ 2.6.5
@@ -0,0 +1,19 @@
1
+ To create a `ruby.wasm` module, run the following commands:
2
+
3
+ ```sh
4
+ bundle install
5
+ bin/pack
6
+ ```
7
+
8
+
9
+ ## Prerequisites
10
+
11
+ To build and pack Ruby Wasm modules, you need the following:
12
+
13
+ - Rust toolchain:
14
+
15
+ ```sh
16
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
17
+ ```
18
+
19
+ - [wasi-vfs](https://github.com/kateinoigakukun/wasi-vfs)
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+
5
+ require "fileutils"
6
+ require "wasmify/rails/builder"
7
+
8
+ builder = Wasmify::Rails::Builder.new
9
+ builder.run(name: "ruby.wasm")
10
+
11
+ require "wasmify/rails/packer"
12
+
13
+ output_dir = ARGV[0] ? ARGV[0] : Wasmify::Rails.config.output_dir
14
+
15
+ packer = Wasmify::Rails::Packer.new(output_dir:)
16
+ packer.run(name: "ruby.wasm", ruby_wasm_path: File.join(Wasmify::Rails.config.tmp_dir, "ruby.wasm"))
@@ -0,0 +1,32 @@
1
+ # Put all the code required to initialize the Rails Wasm environment
2
+
3
+ # Common Rails shims
4
+ require "wasmify/rails/shim"
5
+
6
+ # Load Rails patches
7
+ require "wasmify/rails/patches"
8
+
9
+ # Setup external commands
10
+ require "wasmify/external_commands"
11
+
12
+ # Patch Bundler.require to only require precompiled deps
13
+ # (We don't want to deal with group: :wasm here)
14
+ def Bundler.require(*groups)
15
+ %w[
16
+ rails
17
+ wasmify-rails
18
+ propshaft
19
+ importmap-rails
20
+ turbo-rails
21
+ stimulus-rails
22
+ jbuilder
23
+ bcrypt
24
+ solid_cache
25
+ solid_queue
26
+ solid_cable
27
+ image_processing
28
+ tzinfo/data
29
+ ].each do |gem_name|
30
+ Kernel.require gem_name
31
+ end
32
+ end
@@ -0,0 +1,23 @@
1
+ output_dir: "./dist"
2
+ ruby_version: "3.3"
3
+
4
+ # Specify the list of directories to be included into the final
5
+ # app.wasm file.
6
+ pack_directories: []
7
+ pack_root: "/rails-vm"
8
+ additional_root_files:
9
+ - boot.rb
10
+ - .railsrc
11
+
12
+ # Specify the list of gems to skip during the base module compiliation.
13
+ # Usually, you want to specify the gems with native extensions that are
14
+ # not currently Wasm-compatible.
15
+ exclude_gems:
16
+ - nio4r
17
+ - io-console
18
+ - psych
19
+
20
+ # Skip building native extensions for the following gems (and keep their Ruby source)
21
+ ignore_gem_extensions:
22
+ - bigdecimal
23
+ - date
@@ -0,0 +1,116 @@
1
+ import { useStore } from '@nanostores/react';
2
+ import type { WebContainer } from '@webcontainer/api';
3
+ import { useRef, useEffect } from 'react';
4
+ import { webcontainer } from 'tutorialkit:core';
5
+ import tutorialStore from 'tutorialkit:store';
6
+
7
+ const VERSIONED_WASM_URL = `/ruby.wasm`;
8
+ const WASM_CACHE_FILE_NAME = `ruby.wasm`;
9
+ const WC_WASM_LOG_PATH = `/ruby.wasm.log.txt`;
10
+ const WC_WASM_PATH = `/ruby.wasm`;
11
+
12
+ export function FileManager() {
13
+ const lessonLoaded = useStore(tutorialStore.lessonFullyLoaded);
14
+ const files = useStore(tutorialStore.files);
15
+ const processedFiles = useRef(new Set<string>());
16
+ const wasmCached = useRef(false);
17
+
18
+ async function chmodx(wc: WebContainer, path: string) {
19
+ const process = await wc.spawn('chmod', ['+x', path]);
20
+
21
+ const exitCode = await process.exit;
22
+
23
+ if (exitCode !== 0) {
24
+ console.error(`failed to chmox +x ${path}: `, exitCode);
25
+ } else {
26
+ console.log(`updated permissions for: ${path}`);
27
+ }
28
+ }
29
+
30
+ async function fetchCachedWasmFile(): Promise<Uint8Array | null> {
31
+ try {
32
+ const opfsRoot = await navigator.storage.getDirectory();
33
+ const fileHandle = await opfsRoot.getFileHandle(WASM_CACHE_FILE_NAME);
34
+ const file = await fileHandle.getFile();
35
+ console.log(`Found cached Ruby WASM: ${WASM_CACHE_FILE_NAME}`);
36
+
37
+ return new Uint8Array(await file.arrayBuffer());
38
+ } catch {
39
+ return null;
40
+ }
41
+ }
42
+
43
+ async function persistWasmFile(wasmData: Uint8Array): Promise<void> {
44
+ try {
45
+ const opfsRoot = await navigator.storage.getDirectory();
46
+ const fileHandle = await opfsRoot.getFileHandle(WASM_CACHE_FILE_NAME, { create: true });
47
+ const writable = await fileHandle.createWritable();
48
+ await writable.write(wasmData);
49
+ await writable.close();
50
+ console.log(`Ruby WASM file ${WASM_CACHE_FILE_NAME} cached`);
51
+ } catch (error) {
52
+ console.error('Failed to persist Ruby WASM:', error);
53
+ }
54
+ }
55
+
56
+ async function cacheWasmFile(wc: WebContainer): Promise<void> {
57
+ console.log(`Dowloading WASM file ${VERSIONED_WASM_URL}...`);
58
+
59
+ try {
60
+ const wasm = await fetch(VERSIONED_WASM_URL);
61
+ await wc.fs.writeFile(WC_WASM_LOG_PATH, 'status: downloaded');
62
+
63
+ const wasmData = new Uint8Array(await wasm.arrayBuffer());
64
+ await persistWasmFile(wasmData);
65
+ await wc.fs.writeFile(WC_WASM_LOG_PATH, 'status: cached');
66
+ await wc.fs.writeFile(WC_WASM_PATH, wasmData);
67
+ } catch (error) {
68
+ await wc.fs.writeFile(WC_WASM_LOG_PATH, 'status: error');
69
+ }
70
+ }
71
+
72
+ useEffect(() => {
73
+ if (!lessonLoaded) {
74
+ return;
75
+ }
76
+
77
+ if (!files) {
78
+ return;
79
+ }
80
+
81
+ (async () => {
82
+ const wc = await webcontainer;
83
+
84
+ Object.entries(files).forEach(([_, fd]) => {
85
+ const dir = fd.path.split('/').filter(Boolean).slice(-2, -1)[0];
86
+
87
+ if (dir === 'bin' && !processedFiles.current.has(fd.path)) {
88
+ processedFiles.current = new Set([...processedFiles.current, fd.path]);
89
+ chmodx(wc, '/home/tutorial' + fd.path);
90
+ }
91
+ });
92
+
93
+ if (!wasmCached.current) {
94
+ await wc.fs.writeFile(WC_WASM_LOG_PATH, 'status: init');
95
+
96
+ const cachedWasm = await fetchCachedWasmFile();
97
+
98
+ if (cachedWasm) {
99
+ await wc.fs.writeFile(WC_WASM_LOG_PATH, 'status: load from cache');
100
+ await wc.fs.writeFile(WC_WASM_PATH, cachedWasm);
101
+ await wc.fs.writeFile(WC_WASM_LOG_PATH, 'status: done');
102
+ console.log(`Ruby WASM ${WASM_CACHE_FILE_NAME} loaded from cache`);
103
+ wasmCached.current = true;
104
+ } else {
105
+ await wc.fs.writeFile(WC_WASM_LOG_PATH, 'status: download');
106
+ await cacheWasmFile(wc);
107
+ await wc.fs.writeFile(WC_WASM_LOG_PATH, 'status: done');
108
+ }
109
+ }
110
+ })();
111
+
112
+ return () => {};
113
+ }, [lessonLoaded, files]);
114
+
115
+ return null;
116
+ }
@@ -0,0 +1,17 @@
1
+ ---
2
+
3
+ ---
4
+
5
+ <a
6
+ href="https://github.com/evilmartians/rails-tutorial"
7
+ target="_blank"
8
+ rel="noopener noreferrer"
9
+ class="flex items-center font-size-3.5 text-tk-elements-topBar-iconButton-iconColor hover:text-tk-elements-topBar-iconButton-iconColorHover transition-theme bg-tk-elements-topBar-iconButton-backgroundColor hover:bg-tk-elements-topBar-iconButton-backgroundColorHover p-1 rounded-md"
10
+ >
11
+ <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
12
+ <path
13
+ fill-rule="evenodd"
14
+ d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"
15
+ clip-rule="evenodd"></path>
16
+ </svg>
17
+ </a>
@@ -0,0 +1,65 @@
1
+ <slot name="title" />
2
+ <slot name="links" />
3
+ <slot name="meta" />
4
+
5
+ <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" />
6
+
7
+ <style>
8
+ /* Rails path links styling */
9
+ :global(.rails-path-link) {
10
+ text-decoration: none;
11
+ position: relative;
12
+ display: inline-block;
13
+ cursor: pointer;
14
+ border-radius: 0.25rem;
15
+ transition: all 0.2s ease;
16
+ }
17
+
18
+ :global(.rails-path-link code) {
19
+ color: #0969da;
20
+ background-color: #f6f8fa;
21
+ padding: 0.2em 0.4em;
22
+ border-radius: 0.25rem;
23
+ font-size: 0.875em;
24
+ font-family: ui-monospace, SFMono-Regular, 'SF Mono', Consolas, 'Liberation Mono', Menlo, monospace;
25
+ transition: all 0.2s ease;
26
+ }
27
+
28
+ /* Dark mode support */
29
+ :global(.dark .rails-path-link code) {
30
+ color: #58a6ff;
31
+ background-color: #161b22;
32
+ }
33
+
34
+ /* Hover state */
35
+ :global(.rails-path-link:hover code) {
36
+ color: #0860ca;
37
+ background-color: #e7f1ff;
38
+ text-decoration: underline;
39
+ text-underline-offset: 0.2em;
40
+ }
41
+
42
+ :global(.dark .rails-path-link:hover code) {
43
+ color: #79c0ff;
44
+ background-color: #1f2937;
45
+ }
46
+
47
+ /* Active/clicked state */
48
+ :global(.rails-path-link:active code) {
49
+ transform: scale(0.98);
50
+ }
51
+
52
+ /* Focus state for accessibility */
53
+ :global(.rails-path-link:focus) {
54
+ outline: none;
55
+ }
56
+
57
+ :global(.rails-path-link:focus-visible code) {
58
+ outline: 2px solid #0969da;
59
+ outline-offset: 2px;
60
+ }
61
+
62
+ :global(.dark .rails-path-link:focus-visible code) {
63
+ outline-color: #58a6ff;
64
+ }
65
+ </style>
@@ -0,0 +1,72 @@
1
+ import { useState, useRef, useEffect } from 'react';
2
+
3
+ export function HelpDropdown() {
4
+ const [isOpen, setIsOpen] = useState(false);
5
+ const dropdownRef = useRef<HTMLDivElement>(null);
6
+
7
+ useEffect(() => {
8
+ function handleClickOutside(event: MouseEvent) {
9
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
10
+ setIsOpen(false);
11
+ }
12
+ }
13
+
14
+ document.addEventListener('mousedown', handleClickOutside);
15
+
16
+ return () => {
17
+ document.removeEventListener('mousedown', handleClickOutside);
18
+ };
19
+ }, []);
20
+
21
+ const handleReload = () => {
22
+ window.location.reload();
23
+ };
24
+
25
+ return (
26
+ <div className="relative" ref={dropdownRef}>
27
+ <button
28
+ onClick={() => setIsOpen(!isOpen)}
29
+ className="flex items-center font-size-3.5 text-tk-elements-topBar-iconButton-iconColor hover:text-tk-elements-topBar-iconButton-iconColorHover transition-theme bg-tk-elements-topBar-iconButton-backgroundColor hover:bg-tk-elements-topBar-iconButton-backgroundColorHover p-1 rounded-md"
30
+ aria-label="Help"
31
+ >
32
+ <svg
33
+ width="16"
34
+ height="16"
35
+ viewBox="0 0 24 24"
36
+ fill="none"
37
+ stroke="currentColor"
38
+ strokeWidth="2"
39
+ strokeLinecap="round"
40
+ strokeLinejoin="round"
41
+ className="mr-1"
42
+ >
43
+ <circle cx="12" cy="12" r="10" />
44
+ <path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" />
45
+ <line x1="12" y1="17" x2="12.01" y2="17" />
46
+ </svg>
47
+ Help
48
+ </button>
49
+
50
+ {isOpen && (
51
+ <div className="absolute right-0 mt-2 w-80 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg z-60">
52
+ <div className="p-4">
53
+ <div className="mb-4">
54
+ <p className="text-sm text-gray-700 dark:text-gray-300 mb-2">
55
+ Something went wrong? Simply reload the page to load the fresh contents of the lesson and continue!
56
+ </p>
57
+ <p className="text-xs text-amber-600 dark:text-amber-400 font-medium">
58
+ Warning: you'll start from the fresh state for this lesson, your custom edits will be lost.
59
+ </p>
60
+ </div>
61
+ <button
62
+ onClick={handleReload}
63
+ className="w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded transition-colors"
64
+ >
65
+ Reload
66
+ </button>
67
+ </div>
68
+ </div>
69
+ )}
70
+ </div>
71
+ );
72
+ }