brut 0.17.0 → 0.18.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 (1104) hide show
  1. checksums.yaml +4 -4
  2. data/exe/brut +34 -0
  3. data/lib/brut/cli/apps/build_assets.rb +78 -48
  4. data/lib/brut/cli/apps/db.rb +168 -202
  5. data/lib/brut/cli/apps/deploy.rb +291 -0
  6. data/lib/brut/cli/apps/heroku_container_based_deploy.rb +6 -0
  7. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/add_segment.rb +5 -5
  8. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/add_segment_options.rb +1 -1
  9. data/lib/brut/cli/apps/new/app.rb +240 -0
  10. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/app_id.rb +1 -1
  11. data/lib/brut/cli/apps/new/app_name.rb +29 -0
  12. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/base.rb +9 -6
  13. data/lib/brut/cli/apps/new/erb_binding_delegate.rb +23 -0
  14. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/internet_identifier.rb +5 -5
  15. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/invalid_identifier.rb +1 -1
  16. data/{mkbrut/lib/mkbrut/app.rb → lib/brut/cli/apps/new/old_app.rb} +8 -11
  17. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/ops/add_css_import.rb +1 -1
  18. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/ops/add_i18n_message.rb +1 -1
  19. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/ops/add_method.rb +1 -1
  20. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/ops/append_to_file.rb +1 -1
  21. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/ops/base_op.rb +3 -3
  22. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/ops/copy_file.rb +1 -1
  23. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/ops/insert_code_in_method.rb +1 -1
  24. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/ops/insert_into_file.rb +1 -1
  25. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/ops/insert_route.rb +1 -1
  26. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/ops/mkdir.rb +1 -1
  27. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/ops/prism_parsing_op.rb +1 -1
  28. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/ops/render_template.rb +1 -1
  29. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/ops/skip_file.rb +1 -1
  30. data/lib/brut/cli/apps/new/ops.rb +17 -0
  31. data/lib/brut/cli/apps/new/organization.rb +5 -0
  32. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/prefix.rb +1 -1
  33. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/segments/bare_bones.rb +12 -11
  34. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/segments/demo.rb +16 -15
  35. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/segments/heroku.rb +9 -5
  36. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/segments/sidekiq.rb +44 -21
  37. data/lib/brut/cli/apps/new/segments.rb +8 -0
  38. data/lib/brut/cli/apps/new/version.rb +3 -0
  39. data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/versions.rb +2 -2
  40. data/lib/brut/cli/apps/new.rb +26 -0
  41. data/lib/brut/cli/apps/scaffold.rb +150 -141
  42. data/lib/brut/cli/apps/test.rb +92 -68
  43. data/lib/brut/cli/commands/base_command.rb +174 -0
  44. data/lib/brut/cli/commands/compound_command.rb +29 -0
  45. data/lib/brut/cli/commands/execution_context.rb +32 -0
  46. data/lib/brut/cli/commands/help.rb +26 -0
  47. data/lib/brut/cli/commands/output_error.rb +13 -0
  48. data/lib/brut/cli/commands/raise_error.rb +11 -0
  49. data/lib/brut/cli/commands.rb +8 -0
  50. data/lib/brut/cli/execute_result.rb +39 -0
  51. data/lib/brut/cli/executor.rb +9 -4
  52. data/lib/brut/cli/output.rb +13 -0
  53. data/lib/brut/cli/parsed_command_line.rb +143 -0
  54. data/lib/brut/cli/runner.rb +124 -0
  55. data/lib/brut/cli.rb +7 -29
  56. data/lib/brut/framework/container.rb +1 -1
  57. data/lib/brut/framework/mcp.rb +59 -13
  58. data/lib/brut/framework/project_environment.rb +3 -1
  59. data/lib/brut/junk_drawer.rb +3 -1
  60. data/lib/brut/spec_support/cli_command_support.rb +45 -0
  61. data/lib/brut/spec_support/e2e_test_server.rb +3 -0
  62. data/lib/brut/spec_support/general_support.rb +1 -1
  63. data/lib/brut/spec_support/matchers/have_executed.rb +35 -0
  64. data/lib/brut/spec_support/rspec_setup.rb +4 -8
  65. data/lib/brut/spec_support.rb +1 -0
  66. data/lib/brut/tui/markup_string.rb +2 -0
  67. data/lib/brut/tui/script/events/command_std_out.rb +3 -2
  68. data/lib/brut/tui/script/exec_step.rb +11 -4
  69. data/lib/brut/tui/script/puts_subscriber.rb +4 -4
  70. data/lib/brut/tui/script.rb +7 -3
  71. data/lib/brut/tui/terminal_theme.rb +15 -11
  72. data/lib/brut/version.rb +1 -1
  73. data/templates/Base/.env.development.local +2 -0
  74. data/templates/Base/bin/ci +42 -0
  75. data/{mkbrut/templates → templates}/Base/bin/release +2 -2
  76. data/templates/Base/bin/setup +174 -0
  77. data/{mkbrut/templates → templates}/Base/bin/watch-and-build-assets +1 -1
  78. data/{mkbrut/templates → templates}/Base/dx/docker-compose.env.erb +1 -1
  79. data/{mkbrut/templates → templates}/segments/Demo/app/src/front_end/css/fonts.css +1 -1
  80. data/{mkbrut/templates → templates}/segments/Heroku/deploy/Dockerfile +2 -2
  81. data/templates/segments/Heroku/deploy/docker_config.rb +30 -0
  82. metadata +191 -1055
  83. data/.gitignore +0 -61
  84. data/.projections.json +0 -10
  85. data/CHANGELOG.md +0 -172
  86. data/CODE_OF_CONDUCT.txt +0 -99
  87. data/Dockerfile.dx +0 -82
  88. data/Gemfile +0 -6
  89. data/Gemfile.lock +0 -246
  90. data/LICENSE.txt +0 -370
  91. data/README.md +0 -90
  92. data/Rakefile +0 -25
  93. data/assets/Logo-Square.pxd +0 -0
  94. data/assets/LogoPylon.pxd +0 -0
  95. data/assets/LogoStop.pxd +0 -0
  96. data/assets/LogoTall.pxd +0 -0
  97. data/assets/MetroIcon.graffle +0 -0
  98. data/assets/MetroLogo.graffle +0 -0
  99. data/assets/SocialImage.png +0 -0
  100. data/assets/SocialImage.pxd +0 -0
  101. data/assets/YouTubeThumb.pxd +0 -0
  102. data/bin/bin_kit.rb +0 -51
  103. data/bin/build +0 -86
  104. data/bin/ci +0 -40
  105. data/bin/dev +0 -20
  106. data/bin/docs +0 -86
  107. data/bin/generate-and-run-rubocop +0 -52
  108. data/bin/new-version +0 -8
  109. data/bin/publish +0 -61
  110. data/bin/rake +0 -27
  111. data/bin/rspec +0 -27
  112. data/bin/rubocop +0 -27
  113. data/bin/setup +0 -252
  114. data/bin/test +0 -18
  115. data/brut-css/.nvim.lua +0 -1
  116. data/brut-css/README.md +0 -28
  117. data/brut-css/bin/build +0 -50
  118. data/brut-css/bin/ci +0 -19
  119. data/brut-css/bin/dev +0 -1
  120. data/brut-css/bin/docs +0 -34
  121. data/brut-css/bin/publish +0 -21
  122. data/brut-css/bin/setup +0 -6
  123. data/brut-css/config/media-queries-all.css +0 -15
  124. data/brut-css/config/media-queries-minimal.css +0 -5
  125. data/brut-css/config/postcss.config.cjs +0 -7
  126. data/brut-css/config/pseudo-classes-all.css +0 -9
  127. data/brut-css/dx +0 -1
  128. data/brut-css/package-lock.json +0 -3165
  129. data/brut-css/package.json +0 -36
  130. data/brut-css/src/css/appearance.css +0 -145
  131. data/brut-css/src/css/border.css +0 -522
  132. data/brut-css/src/css/colors.css +0 -3502
  133. data/brut-css/src/css/dimensions.css +0 -548
  134. data/brut-css/src/css/flex.css +0 -179
  135. data/brut-css/src/css/index.css +0 -13
  136. data/brut-css/src/css/layout.css +0 -120
  137. data/brut-css/src/css/list.css +0 -41
  138. data/brut-css/src/css/positioning.css +0 -354
  139. data/brut-css/src/css/properties/colors.css +0 -455
  140. data/brut-css/src/css/properties/index.css +0 -3
  141. data/brut-css/src/css/properties/spacing.css +0 -140
  142. data/brut-css/src/css/properties/typography.css +0 -224
  143. data/brut-css/src/css/reset.css +0 -107
  144. data/brut-css/src/css/spacing.css +0 -585
  145. data/brut-css/src/css/typography.css +0 -519
  146. data/brut-css/src/css/utils.css +0 -104
  147. data/brut-css/src/docs/1_getting-started/1_overview.md +0 -46
  148. data/brut-css/src/docs/1_getting-started/2_installation.md +0 -25
  149. data/brut-css/src/docs/1_getting-started/3_core-concepts.md +0 -75
  150. data/brut-css/src/docs/1_getting-started/4_simple-example.md +0 -132
  151. data/brut-css/src/docs/1_getting-started/page.html.ejs +0 -10
  152. data/brut-css/src/docs/2_properties/page.html.ejs +0 -71
  153. data/brut-css/src/docs/3_classes/color-demo.html.ejs +0 -31
  154. data/brut-css/src/docs/3_classes/page.html.ejs +0 -87
  155. data/brut-css/src/docs/4_customization/1_design-system.md +0 -36
  156. data/brut-css/src/docs/4_customization/2_breakpoints.md +0 -75
  157. data/brut-css/src/docs/4_customization/3_pseudo-classes.md +0 -74
  158. data/brut-css/src/docs/4_customization/4_advanced-configuration.md +0 -40
  159. data/brut-css/src/docs/4_customization/page.html.ejs +0 -10
  160. data/brut-css/src/docs/docs.css +0 -98
  161. data/brut-css/src/docs/includes/body-and-header.html.ejs +0 -30
  162. data/brut-css/src/docs/includes/footer-and-rest.html.ejs +0 -9
  163. data/brut-css/src/docs/includes/head.html.ejs +0 -5
  164. data/brut-css/src/docs/includes/nav.html.ejs +0 -10
  165. data/brut-css/src/docs/index.html.ejs +0 -32
  166. data/brut-css/src/docs/prism-twilight.min.css +0 -1
  167. data/brut-css/src/js/Logger.js +0 -71
  168. data/brut-css/src/js/build.js +0 -111
  169. data/brut-css/src/js/cli/CLIArgError.js +0 -7
  170. data/brut-css/src/js/cli/Debug.js +0 -27
  171. data/brut-css/src/js/cli/DocsDir.js +0 -16
  172. data/brut-css/src/js/cli/DocsTemplateSourceDir.js +0 -16
  173. data/brut-css/src/js/cli/InputFile.js +0 -31
  174. data/brut-css/src/js/cli/MediaQueryConfigFile.js +0 -10
  175. data/brut-css/src/js/cli/OutputFile.js +0 -22
  176. data/brut-css/src/js/cli/ParsedArg.js +0 -17
  177. data/brut-css/src/js/cli/PathToBrutCSSRoot.js +0 -19
  178. data/brut-css/src/js/cli/PseudoClassConfigFile.js +0 -11
  179. data/brut-css/src/js/cli.js +0 -108
  180. data/brut-css/src/js/docGenerator.js +0 -467
  181. data/brut-css/src/js/mediaQueryConfigParser.js +0 -98
  182. data/brut-css/src/js/post-css-plugins/addMediaQueriesPlugin.js +0 -49
  183. data/brut-css/src/js/post-css-plugins/addPseudoClassesPlugin.js +0 -42
  184. data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/Category.js +0 -9
  185. data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/DocState.js +0 -185
  186. data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/Documentable.js +0 -8
  187. data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/Group.js +0 -7
  188. data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/ParsedComment.js +0 -73
  189. data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/Property.js +0 -9
  190. data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/PropertyCategory.js +0 -4
  191. data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/PropertyGroup.js +0 -8
  192. data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/Rule.js +0 -12
  193. data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/RuleCategory.js +0 -4
  194. data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/RuleGroup.js +0 -8
  195. data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/SeeRef.js +0 -5
  196. data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/SeeURL.js +0 -9
  197. data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin.js +0 -49
  198. data/brut-css/src/js/post-css-plugins/generateRootCustomPropertiesPlugin.js +0 -45
  199. data/brut-css/src/js/pseudoClassConfigParser.js +0 -145
  200. data/brut-js/.projections.json +0 -10
  201. data/brut-js/README.md +0 -118
  202. data/brut-js/bin/build +0 -19
  203. data/brut-js/bin/ci +0 -5
  204. data/brut-js/bin/docs +0 -25
  205. data/brut-js/bin/publish +0 -21
  206. data/brut-js/bin/setup +0 -6
  207. data/brut-js/docs/README.md +0 -8
  208. data/brut-js/docs/jsdoc-plugins/customElementTag.js +0 -8
  209. data/brut-js/docs/jsdoc-theme/publish.js +0 -692
  210. data/brut-js/docs/jsdoc-theme/static/scripts/linenumber.js +0 -25
  211. data/brut-js/docs/jsdoc-theme/static/scripts/prettify/Apache-License-2.0.txt +0 -202
  212. data/brut-js/docs/jsdoc-theme/static/scripts/prettify/lang-css.js +0 -2
  213. data/brut-js/docs/jsdoc-theme/static/scripts/prettify/prettify.js +0 -28
  214. data/brut-js/docs/jsdoc-theme/static/styles/jsdoc-default.css +0 -327
  215. data/brut-js/docs/jsdoc-theme/static/styles/prettify-jsdoc.css +0 -111
  216. data/brut-js/docs/jsdoc-theme/static/styles/prettify-tomorrow.css +0 -132
  217. data/brut-js/docs/jsdoc-theme/tmpl/augments.tmpl +0 -10
  218. data/brut-js/docs/jsdoc-theme/tmpl/container.tmpl +0 -199
  219. data/brut-js/docs/jsdoc-theme/tmpl/details.tmpl +0 -143
  220. data/brut-js/docs/jsdoc-theme/tmpl/example.tmpl +0 -2
  221. data/brut-js/docs/jsdoc-theme/tmpl/examples.tmpl +0 -13
  222. data/brut-js/docs/jsdoc-theme/tmpl/exceptions.tmpl +0 -32
  223. data/brut-js/docs/jsdoc-theme/tmpl/layout.tmpl +0 -38
  224. data/brut-js/docs/jsdoc-theme/tmpl/mainpage.tmpl +0 -14
  225. data/brut-js/docs/jsdoc-theme/tmpl/members.tmpl +0 -38
  226. data/brut-js/docs/jsdoc-theme/tmpl/method.tmpl +0 -131
  227. data/brut-js/docs/jsdoc-theme/tmpl/modifies.tmpl +0 -14
  228. data/brut-js/docs/jsdoc-theme/tmpl/params.tmpl +0 -131
  229. data/brut-js/docs/jsdoc-theme/tmpl/properties.tmpl +0 -108
  230. data/brut-js/docs/jsdoc-theme/tmpl/returns.tmpl +0 -19
  231. data/brut-js/docs/jsdoc-theme/tmpl/source.tmpl +0 -8
  232. data/brut-js/docs/jsdoc-theme/tmpl/tutorial.tmpl +0 -19
  233. data/brut-js/docs/jsdoc-theme/tmpl/type.tmpl +0 -7
  234. data/brut-js/docs/jsdoc.config.json +0 -23
  235. data/brut-js/docs/package-lock.json +0 -343
  236. data/brut-js/docs/package.json +0 -7
  237. data/brut-js/dx +0 -1
  238. data/brut-js/package-lock.json +0 -2210
  239. data/brut-js/package.json +0 -36
  240. data/brut-js/specs/AjaxSubmit.spec.js +0 -453
  241. data/brut-js/specs/Autosubmit.spec.js +0 -127
  242. data/brut-js/specs/ConfirmSubmit.spec.js +0 -224
  243. data/brut-js/specs/ConstraintViolationMessage.spec.js +0 -33
  244. data/brut-js/specs/ConstraintViolationMessages.spec.js +0 -32
  245. data/brut-js/specs/CopyToClipboard.spec.js +0 -35
  246. data/brut-js/specs/Form.spec.js +0 -137
  247. data/brut-js/specs/I18nTranslation.spec.js +0 -19
  248. data/brut-js/specs/LocaleDetection.spec.js +0 -22
  249. data/brut-js/specs/Message.spec.js +0 -15
  250. data/brut-js/specs/SpecHelper.js +0 -23
  251. data/brut-js/specs/Tabs.spec.js +0 -41
  252. data/brut-js/specs/Toast.spec.js +0 -34
  253. data/brut-js/specs/config/asset_metadata.json +0 -7
  254. data/brut-js/src/AjaxSubmit.js +0 -499
  255. data/brut-js/src/Autosubmit.js +0 -63
  256. data/brut-js/src/BaseCustomElement.js +0 -261
  257. data/brut-js/src/ConfirmSubmit.js +0 -137
  258. data/brut-js/src/ConfirmationDialog.js +0 -143
  259. data/brut-js/src/ConstraintViolationMessage.js +0 -140
  260. data/brut-js/src/ConstraintViolationMessages.js +0 -98
  261. data/brut-js/src/CopyToClipboard.js +0 -96
  262. data/brut-js/src/Form.js +0 -147
  263. data/brut-js/src/I18nTranslation.js +0 -64
  264. data/brut-js/src/LocaleDetection.js +0 -117
  265. data/brut-js/src/Logger.js +0 -90
  266. data/brut-js/src/Message.js +0 -62
  267. data/brut-js/src/RichString.js +0 -116
  268. data/brut-js/src/Tabs.js +0 -168
  269. data/brut-js/src/Toast.js +0 -102
  270. data/brut-js/src/Tracing.js +0 -247
  271. data/brut-js/src/appForTestingOnly.js +0 -15
  272. data/brut-js/src/index.js +0 -133
  273. data/brut-js/src/testing/AssetMetadata.js +0 -35
  274. data/brut-js/src/testing/AssetMetadataLoader.js +0 -25
  275. data/brut-js/src/testing/CustomElementTest.js +0 -235
  276. data/brut-js/src/testing/DOMCreator.js +0 -45
  277. data/brut-js/src/testing/index.js +0 -48
  278. data/brut.gemspec +0 -73
  279. data/brutrb.com/.vitepress/config.mjs +0 -164
  280. data/brutrb.com/.vitepress/plugins/jsdocLinker.js +0 -34
  281. data/brutrb.com/.vitepress/plugins/rdocLinker.js +0 -18
  282. data/brutrb.com/.vitepress/theme/custom.css +0 -14
  283. data/brutrb.com/.vitepress/theme/index.js +0 -18
  284. data/brutrb.com/.vitepress/theme/style.css +0 -139
  285. data/brutrb.com/adrs.md +0 -16
  286. data/brutrb.com/ai.md +0 -68
  287. data/brutrb.com/assets.md +0 -131
  288. data/brutrb.com/bin/build +0 -5
  289. data/brutrb.com/bin/deploy +0 -7
  290. data/brutrb.com/bin/dev +0 -5
  291. data/brutrb.com/bin/setup +0 -6
  292. data/brutrb.com/brut-js.md +0 -128
  293. data/brutrb.com/business-logic.md +0 -55
  294. data/brutrb.com/cli.md +0 -274
  295. data/brutrb.com/components.md +0 -265
  296. data/brutrb.com/configuration.md +0 -256
  297. data/brutrb.com/css.md +0 -103
  298. data/brutrb.com/custom-element-tests.md +0 -148
  299. data/brutrb.com/database-access.md +0 -201
  300. data/brutrb.com/database-schema.md +0 -320
  301. data/brutrb.com/deployment.md +0 -158
  302. data/brutrb.com/dev-environment.md +0 -186
  303. data/brutrb.com/dir-structure.md +0 -120
  304. data/brutrb.com/doc-conventions.md +0 -41
  305. data/brutrb.com/dx +0 -1
  306. data/brutrb.com/end-to-end-tests.md +0 -176
  307. data/brutrb.com/features.md +0 -373
  308. data/brutrb.com/flash-and-session.md +0 -208
  309. data/brutrb.com/form-constraints.md +0 -266
  310. data/brutrb.com/forms.md +0 -238
  311. data/brutrb.com/getting-started.md +0 -142
  312. data/brutrb.com/handlers.md +0 -177
  313. data/brutrb.com/hooks.md +0 -176
  314. data/brutrb.com/i18n.md +0 -190
  315. data/brutrb.com/images/DevEnvironment.graffle +0 -0
  316. data/brutrb.com/images/DevEnvironment.png +0 -0
  317. data/brutrb.com/images/LogoSquare.png +0 -0
  318. data/brutrb.com/images/LogoStop.png +0 -0
  319. data/brutrb.com/images/LogoTall.png +0 -0
  320. data/brutrb.com/images/Makefile +0 -10
  321. data/brutrb.com/images/OverviewMetro.graffle +0 -0
  322. data/brutrb.com/images/OverviewMetro.png +0 -0
  323. data/brutrb.com/images/dev-env-overview.dot +0 -54
  324. data/brutrb.com/images/dev-env-overview.png +0 -0
  325. data/brutrb.com/images/dev-env-protocol.dot +0 -37
  326. data/brutrb.com/images/dev-env-protocol.png +0 -0
  327. data/brutrb.com/images/overview.graffle +0 -0
  328. data/brutrb.com/images/overview.png +0 -0
  329. data/brutrb.com/images/spa.dot +0 -19
  330. data/brutrb.com/images/spa.png +0 -0
  331. data/brutrb.com/images/tutorial/02-confirmation-dialog-browser-element-styled.png +0 -0
  332. data/brutrb.com/images/tutorial/02-confirmation-dialog-browser-element.png +0 -0
  333. data/brutrb.com/images/tutorial/02-confirmation-dialog-browser.png +0 -0
  334. data/brutrb.com/images/tutorial/02-confirmation-flow.graffle +0 -0
  335. data/brutrb.com/images/tutorial/02-confirmation-flow.png +0 -0
  336. data/brutrb.com/images/tutorial/basic-form-with-violations.png +0 -0
  337. data/brutrb.com/images/tutorial/basic-form.png +0 -0
  338. data/brutrb.com/images/tutorial/initial-home-page.png +0 -0
  339. data/brutrb.com/images/tutorial/new-post-editor.png +0 -0
  340. data/brutrb.com/images/tutorial/new-post-home-page.png +0 -0
  341. data/brutrb.com/images/tutorial/styled-form-with-server-side-violations.png +0 -0
  342. data/brutrb.com/images/tutorial/styled-form-with-violations.png +0 -0
  343. data/brutrb.com/images/tutorial/styled-home-page-with-posts.png +0 -0
  344. data/brutrb.com/images/tutorial/styled-home-page.png +0 -0
  345. data/brutrb.com/images/tutorial/welcome-to-brut.png +0 -0
  346. data/brutrb.com/images/workspace-protocol.dot +0 -44
  347. data/brutrb.com/images/workspace-protocol.png +0 -0
  348. data/brutrb.com/index.md +0 -34
  349. data/brutrb.com/instrumentation.md +0 -331
  350. data/brutrb.com/javascript.md +0 -122
  351. data/brutrb.com/jobs.md +0 -114
  352. data/brutrb.com/keyword-injection.md +0 -195
  353. data/brutrb.com/layouts.md +0 -156
  354. data/brutrb.com/lsp.md +0 -23
  355. data/brutrb.com/markdown-examples.md +0 -85
  356. data/brutrb.com/middleware.md +0 -80
  357. data/brutrb.com/overview.md +0 -68
  358. data/brutrb.com/package-lock.json +0 -2451
  359. data/brutrb.com/package.json +0 -11
  360. data/brutrb.com/pages.md +0 -290
  361. data/brutrb.com/public/SocialImage.png +0 -0
  362. data/brutrb.com/public/favicon.ico +0 -0
  363. data/brutrb.com/recipes/alternate-layouts.md +0 -32
  364. data/brutrb.com/recipes/authentication.md +0 -336
  365. data/brutrb.com/recipes/custom-flash.md +0 -51
  366. data/brutrb.com/recipes/dev-env-secrets.md +0 -87
  367. data/brutrb.com/recipes/form-errors.md +0 -148
  368. data/brutrb.com/recipes/indexed-forms.md +0 -149
  369. data/brutrb.com/recipes/migrations.md +0 -210
  370. data/brutrb.com/recipes/text-field-component.md +0 -182
  371. data/brutrb.com/roadmap.md +0 -52
  372. data/brutrb.com/routes.md +0 -189
  373. data/brutrb.com/security.md +0 -102
  374. data/brutrb.com/seed-data.md +0 -63
  375. data/brutrb.com/space-time-continuum.md +0 -81
  376. data/brutrb.com/tutorial.md +0 -138
  377. data/brutrb.com/tutorials/01-intro.md +0 -1654
  378. data/brutrb.com/tutorials/02-dialog.md +0 -569
  379. data/brutrb.com/unit-tests.md +0 -148
  380. data/brutrb.com/why.md +0 -19
  381. data/docker-compose.dx.yml +0 -25
  382. data/docs/404.html +0 -26
  383. data/docs/CNAME +0 -1
  384. data/docs/SocialImage.png +0 -0
  385. data/docs/adrs.html +0 -29
  386. data/docs/ai.html +0 -29
  387. data/docs/api/Brut/BackEnd/SeedData.html +0 -493
  388. data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server/FlushSpans.html +0 -214
  389. data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server.html +0 -125
  390. data/docs/api/Brut/BackEnd/Sidekiq/Middlewares.html +0 -125
  391. data/docs/api/Brut/BackEnd/Sidekiq.html +0 -125
  392. data/docs/api/Brut/BackEnd/Validators/FormValidator.html +0 -414
  393. data/docs/api/Brut/BackEnd/Validators.html +0 -128
  394. data/docs/api/Brut/BackEnd.html +0 -132
  395. data/docs/api/Brut/CLI/App.html +0 -1601
  396. data/docs/api/Brut/CLI/AppRunner.html +0 -491
  397. data/docs/api/Brut/CLI/Apps/BuildAssets/All.html +0 -264
  398. data/docs/api/Brut/CLI/Apps/BuildAssets/CSS.html +0 -306
  399. data/docs/api/Brut/CLI/Apps/BuildAssets/Images.html +0 -262
  400. data/docs/api/Brut/CLI/Apps/BuildAssets/JS.html +0 -314
  401. data/docs/api/Brut/CLI/Apps/BuildAssets.html +0 -183
  402. data/docs/api/Brut/CLI/Apps/DB/Create.html +0 -365
  403. data/docs/api/Brut/CLI/Apps/DB/Drop.html +0 -357
  404. data/docs/api/Brut/CLI/Apps/DB/Migrate.html +0 -389
  405. data/docs/api/Brut/CLI/Apps/DB/NewMigration.html +0 -339
  406. data/docs/api/Brut/CLI/Apps/DB/Rebuild.html +0 -329
  407. data/docs/api/Brut/CLI/Apps/DB/Seed.html +0 -347
  408. data/docs/api/Brut/CLI/Apps/DB/Status.html +0 -383
  409. data/docs/api/Brut/CLI/Apps/DB.html +0 -183
  410. data/docs/api/Brut/CLI/Apps/DeployBase/GitChecks.html +0 -270
  411. data/docs/api/Brut/CLI/Apps/DeployBase.html +0 -257
  412. data/docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy/Deploy.html +0 -587
  413. data/docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy.html +0 -196
  414. data/docs/api/Brut/CLI/Apps/Scaffold/Action/Route.html +0 -303
  415. data/docs/api/Brut/CLI/Apps/Scaffold/Action.html +0 -508
  416. data/docs/api/Brut/CLI/Apps/Scaffold/Component.html +0 -398
  417. data/docs/api/Brut/CLI/Apps/Scaffold/CustomElementTest.html +0 -374
  418. data/docs/api/Brut/CLI/Apps/Scaffold/DbModel.html +0 -384
  419. data/docs/api/Brut/CLI/Apps/Scaffold/E2ETest.html +0 -410
  420. data/docs/api/Brut/CLI/Apps/Scaffold/Form.html +0 -262
  421. data/docs/api/Brut/CLI/Apps/Scaffold/Page/Route.html +0 -303
  422. data/docs/api/Brut/CLI/Apps/Scaffold/Page.html +0 -480
  423. data/docs/api/Brut/CLI/Apps/Scaffold/RoutesEditor.html +0 -450
  424. data/docs/api/Brut/CLI/Apps/Scaffold/Test.html +0 -380
  425. data/docs/api/Brut/CLI/Apps/Scaffold.html +0 -253
  426. data/docs/api/Brut/CLI/Apps/Test/Audit.html +0 -474
  427. data/docs/api/Brut/CLI/Apps/Test/E2e.html +0 -407
  428. data/docs/api/Brut/CLI/Apps/Test/JS.html +0 -262
  429. data/docs/api/Brut/CLI/Apps/Test/Run.html +0 -578
  430. data/docs/api/Brut/CLI/Apps/Test.html +0 -253
  431. data/docs/api/Brut/CLI/Apps.html +0 -125
  432. data/docs/api/Brut/CLI/Command.html +0 -2425
  433. data/docs/api/Brut/CLI/Error.html +0 -139
  434. data/docs/api/Brut/CLI/ExecutionResults/Result.html +0 -664
  435. data/docs/api/Brut/CLI/ExecutionResults.html +0 -675
  436. data/docs/api/Brut/CLI/Executor.html +0 -561
  437. data/docs/api/Brut/CLI/InvalidOption.html +0 -245
  438. data/docs/api/Brut/CLI/Options.html +0 -880
  439. data/docs/api/Brut/CLI/Output.html +0 -699
  440. data/docs/api/Brut/CLI/SystemExecError.html +0 -451
  441. data/docs/api/Brut/CLI.html +0 -263
  442. data/docs/api/Brut/FactoryBot.html +0 -225
  443. data/docs/api/Brut/Framework/App.html +0 -1097
  444. data/docs/api/Brut/Framework/Config.html +0 -1071
  445. data/docs/api/Brut/Framework/Container.html +0 -1464
  446. data/docs/api/Brut/Framework/Error.html +0 -140
  447. data/docs/api/Brut/Framework/Errors/AbstractMethod.html +0 -232
  448. data/docs/api/Brut/Framework/Errors/Bug.html +0 -234
  449. data/docs/api/Brut/Framework/Errors/MissingConfiguration.html +0 -257
  450. data/docs/api/Brut/Framework/Errors/MissingParameter.html +0 -273
  451. data/docs/api/Brut/Framework/Errors/NoClassForPath.html +0 -471
  452. data/docs/api/Brut/Framework/Errors/NotFound.html +0 -308
  453. data/docs/api/Brut/Framework/Errors/NotImplemented.html +0 -234
  454. data/docs/api/Brut/Framework/Errors.html +0 -351
  455. data/docs/api/Brut/Framework/FussyTypeEnforcement.html +0 -392
  456. data/docs/api/Brut/Framework/MCP.html +0 -871
  457. data/docs/api/Brut/Framework/ProjectEnvironment.html +0 -648
  458. data/docs/api/Brut/Framework.html +0 -129
  459. data/docs/api/Brut/FrontEnd/AssetPathResolver.html +0 -317
  460. data/docs/api/Brut/FrontEnd/Component/Helpers.html +0 -420
  461. data/docs/api/Brut/FrontEnd/Component.html +0 -434
  462. data/docs/api/Brut/FrontEnd/Components/ConstraintViolations.html +0 -491
  463. data/docs/api/Brut/FrontEnd/Components/FormTag.html +0 -526
  464. data/docs/api/Brut/FrontEnd/Components/I18nTranslations.html +0 -313
  465. data/docs/api/Brut/FrontEnd/Components/Input.html +0 -195
  466. data/docs/api/Brut/FrontEnd/Components/Inputs/ButtonTag.html +0 -447
  467. data/docs/api/Brut/FrontEnd/Components/Inputs/CsrfToken.html +0 -339
  468. data/docs/api/Brut/FrontEnd/Components/Inputs/InputTag.html +0 -568
  469. data/docs/api/Brut/FrontEnd/Components/Inputs/RadioButton.html +0 -419
  470. data/docs/api/Brut/FrontEnd/Components/Inputs/SelectTagWithOptions.html +0 -610
  471. data/docs/api/Brut/FrontEnd/Components/Inputs/TextareaTag.html +0 -534
  472. data/docs/api/Brut/FrontEnd/Components/Inputs.html +0 -125
  473. data/docs/api/Brut/FrontEnd/Components/LocaleDetection.html +0 -367
  474. data/docs/api/Brut/FrontEnd/Components/PageIdentifier.html +0 -355
  475. data/docs/api/Brut/FrontEnd/Components/TimeTag.html +0 -655
  476. data/docs/api/Brut/FrontEnd/Components/Traceparent.html +0 -352
  477. data/docs/api/Brut/FrontEnd/Components.html +0 -156
  478. data/docs/api/Brut/FrontEnd/CsrfProtector.html +0 -250
  479. data/docs/api/Brut/FrontEnd/Download.html +0 -467
  480. data/docs/api/Brut/FrontEnd/Flash.html +0 -1150
  481. data/docs/api/Brut/FrontEnd/Form.html +0 -1227
  482. data/docs/api/Brut/FrontEnd/Forms/Button.html +0 -331
  483. data/docs/api/Brut/FrontEnd/Forms/ButtonInputDefinition.html +0 -537
  484. data/docs/api/Brut/FrontEnd/Forms/ConstraintViolation.html +0 -590
  485. data/docs/api/Brut/FrontEnd/Forms/Input/Color.html +0 -201
  486. data/docs/api/Brut/FrontEnd/Forms/Input/TimeOfDay.html +0 -535
  487. data/docs/api/Brut/FrontEnd/Forms/Input.html +0 -1567
  488. data/docs/api/Brut/FrontEnd/Forms/InputDeclarations.html +0 -635
  489. data/docs/api/Brut/FrontEnd/Forms/InputDefinition.html +0 -1336
  490. data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInput.html +0 -730
  491. data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInputDefinition.html +0 -587
  492. data/docs/api/Brut/FrontEnd/Forms/SelectInput.html +0 -734
  493. data/docs/api/Brut/FrontEnd/Forms/SelectInputDefinition.html +0 -582
  494. data/docs/api/Brut/FrontEnd/Forms/ValidityState.html +0 -659
  495. data/docs/api/Brut/FrontEnd/Forms.html +0 -127
  496. data/docs/api/Brut/FrontEnd/GenericResponse.html +0 -377
  497. data/docs/api/Brut/FrontEnd/Handler.html +0 -442
  498. data/docs/api/Brut/FrontEnd/Handlers/CspReportingHandler.html +0 -318
  499. data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler/TraceParent.html +0 -336
  500. data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler.html +0 -399
  501. data/docs/api/Brut/FrontEnd/Handlers/LocaleDetectionHandler.html +0 -354
  502. data/docs/api/Brut/FrontEnd/Handlers/MissingHandler/Form.html +0 -151
  503. data/docs/api/Brut/FrontEnd/Handlers/MissingHandler.html +0 -315
  504. data/docs/api/Brut/FrontEnd/Handlers.html +0 -125
  505. data/docs/api/Brut/FrontEnd/HandlingResults.html +0 -339
  506. data/docs/api/Brut/FrontEnd/HttpMethod.html +0 -661
  507. data/docs/api/Brut/FrontEnd/HttpStatus.html +0 -496
  508. data/docs/api/Brut/FrontEnd/InlineSvgLocator.html +0 -284
  509. data/docs/api/Brut/FrontEnd/Layout.html +0 -486
  510. data/docs/api/Brut/FrontEnd/Middleware.html +0 -135
  511. data/docs/api/Brut/FrontEnd/Middlewares/AnnotateBrutOwnedPaths.html +0 -288
  512. data/docs/api/Brut/FrontEnd/Middlewares/Favicon.html +0 -292
  513. data/docs/api/Brut/FrontEnd/Middlewares/OpenTelemetrySpan.html +0 -324
  514. data/docs/api/Brut/FrontEnd/Middlewares/ReloadApp.html +0 -376
  515. data/docs/api/Brut/FrontEnd/Middlewares.html +0 -125
  516. data/docs/api/Brut/FrontEnd/Page.html +0 -781
  517. data/docs/api/Brut/FrontEnd/Pages/MissingPage.html +0 -797
  518. data/docs/api/Brut/FrontEnd/Pages.html +0 -125
  519. data/docs/api/Brut/FrontEnd/RequestContext.html +0 -1312
  520. data/docs/api/Brut/FrontEnd/RouteHook.html +0 -424
  521. data/docs/api/Brut/FrontEnd/RouteHooks/AgeFlash.html +0 -242
  522. data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineScripts.html +0 -249
  523. data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts/ReportOnly.html +0 -264
  524. data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts.html +0 -261
  525. data/docs/api/Brut/FrontEnd/RouteHooks/LocaleDetection.html +0 -284
  526. data/docs/api/Brut/FrontEnd/RouteHooks/SetupRequestContext.html +0 -252
  527. data/docs/api/Brut/FrontEnd/RouteHooks.html +0 -115
  528. data/docs/api/Brut/FrontEnd/Routing/FormHandlerRoute.html +0 -227
  529. data/docs/api/Brut/FrontEnd/Routing/FormRoute.html +0 -305
  530. data/docs/api/Brut/FrontEnd/Routing/MissingForm.html +0 -324
  531. data/docs/api/Brut/FrontEnd/Routing/MissingHandler.html +0 -319
  532. data/docs/api/Brut/FrontEnd/Routing/MissingPage.html +0 -315
  533. data/docs/api/Brut/FrontEnd/Routing/MissingPath.html +0 -315
  534. data/docs/api/Brut/FrontEnd/Routing/PageRoute.html +0 -327
  535. data/docs/api/Brut/FrontEnd/Routing/Route.html +0 -761
  536. data/docs/api/Brut/FrontEnd/Routing.html +0 -927
  537. data/docs/api/Brut/FrontEnd/Session.html +0 -1195
  538. data/docs/api/Brut/FrontEnd.html +0 -134
  539. data/docs/api/Brut/I18n/BaseMethods.html +0 -931
  540. data/docs/api/Brut/I18n/ForBackEnd.html +0 -302
  541. data/docs/api/Brut/I18n/ForCLI.html +0 -302
  542. data/docs/api/Brut/I18n/ForHTML.html +0 -296
  543. data/docs/api/Brut/I18n/HTTPAcceptLanguage/AlwaysEnglish.html +0 -316
  544. data/docs/api/Brut/I18n/HTTPAcceptLanguage.html +0 -930
  545. data/docs/api/Brut/I18n.html +0 -127
  546. data/docs/api/Brut/Instrumentation/LoggerSpanExporter.html +0 -435
  547. data/docs/api/Brut/Instrumentation/Methods/ClassMethods.html +0 -596
  548. data/docs/api/Brut/Instrumentation/Methods.html +0 -173
  549. data/docs/api/Brut/Instrumentation/OpenTelemetry/NormalizedAttributes.html +0 -286
  550. data/docs/api/Brut/Instrumentation/OpenTelemetry/Span.html +0 -302
  551. data/docs/api/Brut/Instrumentation/OpenTelemetry.html +0 -866
  552. data/docs/api/Brut/Instrumentation.html +0 -128
  553. data/docs/api/Brut/RubocopConfig.html +0 -237
  554. data/docs/api/Brut/SinatraHelpers/ClassMethods.html +0 -534
  555. data/docs/api/Brut/SinatraHelpers.html +0 -281
  556. data/docs/api/Brut/SpecSupport/ClockSupport.html +0 -383
  557. data/docs/api/Brut/SpecSupport/ComponentSupport.html +0 -496
  558. data/docs/api/Brut/SpecSupport/E2ETestServer.html +0 -503
  559. data/docs/api/Brut/SpecSupport/E2eSupport.html +0 -142
  560. data/docs/api/Brut/SpecSupport/EnhancedNode.html +0 -403
  561. data/docs/api/Brut/SpecSupport/FlashSupport.html +0 -278
  562. data/docs/api/Brut/SpecSupport/GeneralSupport/ClassMethods.html +0 -401
  563. data/docs/api/Brut/SpecSupport/GeneralSupport.html +0 -195
  564. data/docs/api/Brut/SpecSupport/HandlerSupport.html +0 -160
  565. data/docs/api/Brut/SpecSupport/Matchers/BeABug.html +0 -142
  566. data/docs/api/Brut/SpecSupport/Matchers/BePageFor.html +0 -142
  567. data/docs/api/Brut/SpecSupport/Matchers/BeRoutingFor.html +0 -155
  568. data/docs/api/Brut/SpecSupport/Matchers/HaveConstraintViolation.html +0 -583
  569. data/docs/api/Brut/SpecSupport/Matchers/HaveGenerated.html +0 -149
  570. data/docs/api/Brut/SpecSupport/Matchers/HaveHTMLAttribute.html +0 -466
  571. data/docs/api/Brut/SpecSupport/Matchers/HaveI18nString.html +0 -149
  572. data/docs/api/Brut/SpecSupport/Matchers/HaveLinkTo.html +0 -149
  573. data/docs/api/Brut/SpecSupport/Matchers/HaveRedirectedTo.html +0 -165
  574. data/docs/api/Brut/SpecSupport/Matchers/HaveReturnedHttpStatus.html +0 -158
  575. data/docs/api/Brut/SpecSupport/Matchers/HaveReturnedRackResponse.html +0 -156
  576. data/docs/api/Brut/SpecSupport/Matchers.html +0 -125
  577. data/docs/api/Brut/SpecSupport/RSpecSetup/OptionalSidekiqSupport.html +0 -335
  578. data/docs/api/Brut/SpecSupport/RSpecSetup.html +0 -637
  579. data/docs/api/Brut/SpecSupport/SessionSupport.html +0 -196
  580. data/docs/api/Brut/SpecSupport.html +0 -129
  581. data/docs/api/Brut/TUI/AnsiEscapeCode/Mod.html +0 -409
  582. data/docs/api/Brut/TUI/AnsiEscapeCode.html +0 -426
  583. data/docs/api/Brut/TUI/EventLoop/Deque.html +0 -531
  584. data/docs/api/Brut/TUI/EventLoop.html +0 -676
  585. data/docs/api/Brut/TUI/Events/BaseEvent.html +0 -449
  586. data/docs/api/Brut/TUI/Events/EventBus.html +0 -485
  587. data/docs/api/Brut/TUI/Events/EventLoopStarted.html +0 -211
  588. data/docs/api/Brut/TUI/Events/Exception.html +0 -523
  589. data/docs/api/Brut/TUI/Events/Tick.html +0 -294
  590. data/docs/api/Brut/TUI/Events.html +0 -131
  591. data/docs/api/Brut/TUI/MarkupString.html +0 -537
  592. data/docs/api/Brut/TUI/Script/BlockStep.html +0 -300
  593. data/docs/api/Brut/TUI/Script/Events/CommandExecutionFailed.html +0 -252
  594. data/docs/api/Brut/TUI/Script/Events/CommandExecutionSucceeded.html +0 -163
  595. data/docs/api/Brut/TUI/Script/Events/CommandStdErr.html +0 -163
  596. data/docs/api/Brut/TUI/Script/Events/CommandStdOut.html +0 -300
  597. data/docs/api/Brut/TUI/Script/Events/ExecutingCommand.html +0 -298
  598. data/docs/api/Brut/TUI/Script/Events/Message.html +0 -345
  599. data/docs/api/Brut/TUI/Script/Events/PhaseCompleted.html +0 -229
  600. data/docs/api/Brut/TUI/Script/Events/PhaseStarted.html +0 -350
  601. data/docs/api/Brut/TUI/Script/Events/ScriptCompleted.html +0 -282
  602. data/docs/api/Brut/TUI/Script/Events/ScriptStarted.html +0 -343
  603. data/docs/api/Brut/TUI/Script/Events/StepCompleted.html +0 -163
  604. data/docs/api/Brut/TUI/Script/Events/StepStarted.html +0 -346
  605. data/docs/api/Brut/TUI/Script/Events.html +0 -115
  606. data/docs/api/Brut/TUI/Script/ExecStep/ProcessStatusFailed.html +0 -210
  607. data/docs/api/Brut/TUI/Script/ExecStep.html +0 -493
  608. data/docs/api/Brut/TUI/Script/LoggingSubscriber.html +0 -914
  609. data/docs/api/Brut/TUI/Script/PutsSubscriber.html +0 -783
  610. data/docs/api/Brut/TUI/Script/Step.html +0 -313
  611. data/docs/api/Brut/TUI/Script.html +0 -1250
  612. data/docs/api/Brut/TUI/Terminal.html +0 -593
  613. data/docs/api/Brut/TUI/TerminalTheme.html +0 -1403
  614. data/docs/api/Brut/TUI/Themes/Dark.html +0 -706
  615. data/docs/api/Brut/TUI/Themes/Light.html +0 -804
  616. data/docs/api/Brut/TUI/Themes/None.html +0 -218
  617. data/docs/api/Brut/TUI/Themes.html +0 -115
  618. data/docs/api/Brut/TUI.html +0 -129
  619. data/docs/api/Brut.html +0 -341
  620. data/docs/api/Clock.html +0 -603
  621. data/docs/api/ModuleName.html +0 -595
  622. data/docs/api/RichString.html +0 -775
  623. data/docs/api/SemanticLogger/Appender/Async.html +0 -219
  624. data/docs/api/Sequel/Extensions/BrutInstrumentation.html +0 -119
  625. data/docs/api/Sequel/Extensions/BrutMigrations.html +0 -541
  626. data/docs/api/Sequel/Extensions.html +0 -117
  627. data/docs/api/Sequel/Plugins/CreatedAt/InstanceMethods.html +0 -105
  628. data/docs/api/Sequel/Plugins/CreatedAt.html +0 -125
  629. data/docs/api/Sequel/Plugins/ExternalId/ClassMethods.html +0 -207
  630. data/docs/api/Sequel/Plugins/ExternalId/InstanceMethods.html +0 -186
  631. data/docs/api/Sequel/Plugins/ExternalId.html +0 -218
  632. data/docs/api/Sequel/Plugins/FindBang/ClassMethods.html +0 -202
  633. data/docs/api/Sequel/Plugins/FindBang.html +0 -125
  634. data/docs/api/Sequel/Plugins.html +0 -117
  635. data/docs/api/Sequel.html +0 -117
  636. data/docs/api/SpecSupport/Matchers/BeABug.html +0 -143
  637. data/docs/api/_index.html +0 -1964
  638. data/docs/api/class_list.html +0 -54
  639. data/docs/api/css/common.css +0 -1
  640. data/docs/api/css/full_list.css +0 -59
  641. data/docs/api/css/style.css +0 -504
  642. data/docs/api/file.README.html +0 -172
  643. data/docs/api/file_list.html +0 -59
  644. data/docs/api/frames.html +0 -22
  645. data/docs/api/index.html +0 -172
  646. data/docs/api/js/app.js +0 -344
  647. data/docs/api/js/full_list.js +0 -242
  648. data/docs/api/js/jquery.js +0 -4
  649. data/docs/api/method_list.html +0 -5542
  650. data/docs/api/top-level-namespace.html +0 -112
  651. data/docs/assets/02-confirmation-dialog-browser-element-styled.3NEGM20-.png +0 -0
  652. data/docs/assets/02-confirmation-dialog-browser-element.DPsf0xUW.png +0 -0
  653. data/docs/assets/02-confirmation-dialog-browser.DH8ALFO4.png +0 -0
  654. data/docs/assets/02-confirmation-flow.D9gZ0S5U.png +0 -0
  655. data/docs/assets/DevEnvironment.DaFcVfwP.png +0 -0
  656. data/docs/assets/LogoStop.Gb3tDhL1.png +0 -0
  657. data/docs/assets/OverviewMetro.DUS-5fUZ.png +0 -0
  658. data/docs/assets/adrs.md.YglbWtQe.js +0 -1
  659. data/docs/assets/adrs.md.YglbWtQe.lean.js +0 -1
  660. data/docs/assets/ai.md.ChLnvDAX.js +0 -1
  661. data/docs/assets/ai.md.ChLnvDAX.lean.js +0 -1
  662. data/docs/assets/app.B8jAEB7R.js +0 -1
  663. data/docs/assets/assets.md.BEF6Oz6K.js +0 -19
  664. data/docs/assets/assets.md.BEF6Oz6K.lean.js +0 -1
  665. data/docs/assets/basic-form-with-violations.Cv6Y9-Q_.png +0 -0
  666. data/docs/assets/basic-form.DbHnu0oW.png +0 -0
  667. data/docs/assets/brut-js.md.BMz0X1Rz.js +0 -12
  668. data/docs/assets/brut-js.md.BMz0X1Rz.lean.js +0 -1
  669. data/docs/assets/business-logic.md.DbuaOYGU.js +0 -1
  670. data/docs/assets/business-logic.md.DbuaOYGU.lean.js +0 -1
  671. data/docs/assets/chunks/@localSearchIndexroot.DJ8mocCj.js +0 -1
  672. data/docs/assets/chunks/VPLocalSearchBox.gF-Po_fz.js +0 -8
  673. data/docs/assets/chunks/framework.C4nOkCZI.js +0 -18
  674. data/docs/assets/chunks/theme.BjPAOJkz.js +0 -2
  675. data/docs/assets/cli.md.DDMar_51.js +0 -122
  676. data/docs/assets/cli.md.DDMar_51.lean.js +0 -1
  677. data/docs/assets/components.md.Ber8UBM0.js +0 -96
  678. data/docs/assets/components.md.Ber8UBM0.lean.js +0 -1
  679. data/docs/assets/configuration.md.DrJ6YVoZ.js +0 -78
  680. data/docs/assets/configuration.md.DrJ6YVoZ.lean.js +0 -1
  681. data/docs/assets/css.md.K5rOCOQY.js +0 -21
  682. data/docs/assets/css.md.K5rOCOQY.lean.js +0 -1
  683. data/docs/assets/custom-element-tests.md.DiLe-eFw.js +0 -69
  684. data/docs/assets/custom-element-tests.md.DiLe-eFw.lean.js +0 -1
  685. data/docs/assets/database-access.md.Dc8l2Plf.js +0 -63
  686. data/docs/assets/database-access.md.Dc8l2Plf.lean.js +0 -1
  687. data/docs/assets/database-schema.md.BJ_JhXmO.js +0 -70
  688. data/docs/assets/database-schema.md.BJ_JhXmO.lean.js +0 -1
  689. data/docs/assets/deployment.md.CHTx2eTR.js +0 -55
  690. data/docs/assets/deployment.md.CHTx2eTR.lean.js +0 -1
  691. data/docs/assets/dev-env-protocol.DysDAtnz.png +0 -0
  692. data/docs/assets/dev-environment.md.B1S9p5ZK.js +0 -16
  693. data/docs/assets/dev-environment.md.B1S9p5ZK.lean.js +0 -1
  694. data/docs/assets/dir-structure.md.D1T2kGwj.js +0 -46
  695. data/docs/assets/dir-structure.md.D1T2kGwj.lean.js +0 -1
  696. data/docs/assets/doc-conventions.md.CDnWaEFg.js +0 -1
  697. data/docs/assets/doc-conventions.md.CDnWaEFg.lean.js +0 -1
  698. data/docs/assets/end-to-end-tests.md.BJJdNDYL.js +0 -28
  699. data/docs/assets/end-to-end-tests.md.BJJdNDYL.lean.js +0 -1
  700. data/docs/assets/features.md.BDWxnyNO.js +0 -154
  701. data/docs/assets/features.md.BDWxnyNO.lean.js +0 -1
  702. data/docs/assets/flash-and-session.md.CUsMxoNl.js +0 -79
  703. data/docs/assets/flash-and-session.md.CUsMxoNl.lean.js +0 -1
  704. data/docs/assets/form-constraints.md.KlfXSKm2.js +0 -90
  705. data/docs/assets/form-constraints.md.KlfXSKm2.lean.js +0 -1
  706. data/docs/assets/forms.md.RK0zkhm0.js +0 -64
  707. data/docs/assets/forms.md.RK0zkhm0.lean.js +0 -1
  708. data/docs/assets/getting-started.md.CGJ44juQ.js +0 -31
  709. data/docs/assets/getting-started.md.CGJ44juQ.lean.js +0 -1
  710. data/docs/assets/handlers.md.C5tUwmmo.js +0 -54
  711. data/docs/assets/handlers.md.C5tUwmmo.lean.js +0 -1
  712. data/docs/assets/hooks.md.CoiYCKRc.js +0 -80
  713. data/docs/assets/hooks.md.CoiYCKRc.lean.js +0 -1
  714. data/docs/assets/i18n.md.DxkCKhUw.js +0 -23
  715. data/docs/assets/i18n.md.DxkCKhUw.lean.js +0 -1
  716. data/docs/assets/index.md.DnphWyQd.js +0 -1
  717. data/docs/assets/index.md.DnphWyQd.lean.js +0 -1
  718. data/docs/assets/initial-home-page.DNIaYmgP.png +0 -0
  719. data/docs/assets/instrumentation.md.BcxjC4jd.js +0 -90
  720. data/docs/assets/instrumentation.md.BcxjC4jd.lean.js +0 -1
  721. data/docs/assets/javascript.md.D6fxhaQb.js +0 -31
  722. data/docs/assets/javascript.md.D6fxhaQb.lean.js +0 -1
  723. data/docs/assets/jobs.md.Bi3qb3v6.js +0 -25
  724. data/docs/assets/jobs.md.Bi3qb3v6.lean.js +0 -1
  725. data/docs/assets/keyword-injection.md.CqLnnzIz.js +0 -21
  726. data/docs/assets/keyword-injection.md.CqLnnzIz.lean.js +0 -1
  727. data/docs/assets/layouts.md.HEbeK7Jr.js +0 -68
  728. data/docs/assets/layouts.md.HEbeK7Jr.lean.js +0 -1
  729. data/docs/assets/lsp.md.bE9dW8n9.js +0 -1
  730. data/docs/assets/lsp.md.bE9dW8n9.lean.js +0 -1
  731. data/docs/assets/markdown-examples.md.BPmtHlc-.js +0 -33
  732. data/docs/assets/markdown-examples.md.BPmtHlc-.lean.js +0 -1
  733. data/docs/assets/middleware.md.BhOIsg59.js +0 -20
  734. data/docs/assets/middleware.md.BhOIsg59.lean.js +0 -1
  735. data/docs/assets/new-post-editor.DrHr-5oh.png +0 -0
  736. data/docs/assets/new-post-home-page.Bm34lyMg.png +0 -0
  737. data/docs/assets/overview.md.BpWAgPFH.js +0 -1
  738. data/docs/assets/overview.md.BpWAgPFH.lean.js +0 -1
  739. data/docs/assets/pages.md.B3sQXpEd.js +0 -45
  740. data/docs/assets/pages.md.B3sQXpEd.lean.js +0 -1
  741. data/docs/assets/recipes_alternate-layouts.md.C1QzVkA7.js +0 -22
  742. data/docs/assets/recipes_alternate-layouts.md.C1QzVkA7.lean.js +0 -1
  743. data/docs/assets/recipes_authentication.md.CyvoIW82.js +0 -157
  744. data/docs/assets/recipes_authentication.md.CyvoIW82.lean.js +0 -1
  745. data/docs/assets/recipes_custom-flash.md.6gFqf2uL.js +0 -26
  746. data/docs/assets/recipes_custom-flash.md.6gFqf2uL.lean.js +0 -1
  747. data/docs/assets/recipes_dev-env-secrets.md.DC_jVY9U.js +0 -12
  748. data/docs/assets/recipes_dev-env-secrets.md.DC_jVY9U.lean.js +0 -1
  749. data/docs/assets/recipes_form-errors.md.B5ptSzMO.js +0 -66
  750. data/docs/assets/recipes_form-errors.md.B5ptSzMO.lean.js +0 -1
  751. data/docs/assets/recipes_indexed-forms.md.BYYQGW2C.js +0 -74
  752. data/docs/assets/recipes_indexed-forms.md.BYYQGW2C.lean.js +0 -1
  753. data/docs/assets/recipes_migrations.md.Cid7-3cu.js +0 -97
  754. data/docs/assets/recipes_migrations.md.Cid7-3cu.lean.js +0 -1
  755. data/docs/assets/recipes_text-field-component.md.VhOsCtKI.js +0 -101
  756. data/docs/assets/recipes_text-field-component.md.VhOsCtKI.lean.js +0 -1
  757. data/docs/assets/roadmap.md.DqC1Y7Zt.js +0 -1
  758. data/docs/assets/roadmap.md.DqC1Y7Zt.lean.js +0 -1
  759. data/docs/assets/routes.md.C1dgIBtD.js +0 -21
  760. data/docs/assets/routes.md.C1dgIBtD.lean.js +0 -1
  761. data/docs/assets/security.md.Jn4SY1uK.js +0 -1
  762. data/docs/assets/security.md.Jn4SY1uK.lean.js +0 -1
  763. data/docs/assets/seed-data.md.UZW0WxYN.js +0 -14
  764. data/docs/assets/seed-data.md.UZW0WxYN.lean.js +0 -1
  765. data/docs/assets/spa.qejUdp-5.png +0 -0
  766. data/docs/assets/space-time-continuum.md.D9rYGDFH.js +0 -1
  767. data/docs/assets/space-time-continuum.md.D9rYGDFH.lean.js +0 -1
  768. data/docs/assets/style.B1z60PPQ.css +0 -1
  769. data/docs/assets/styled-form-with-server-side-violations.Bjxd8Dpv.png +0 -0
  770. data/docs/assets/styled-form-with-violations.Bv_sa9tg.png +0 -0
  771. data/docs/assets/styled-home-page-with-posts.Dd4kG89D.png +0 -0
  772. data/docs/assets/styled-home-page.BzdI7dWz.png +0 -0
  773. data/docs/assets/tutorial.md.BX6f6l00.js +0 -27
  774. data/docs/assets/tutorial.md.BX6f6l00.lean.js +0 -1
  775. data/docs/assets/tutorials_01-intro.md.CzZ3kpF_.js +0 -708
  776. data/docs/assets/tutorials_01-intro.md.CzZ3kpF_.lean.js +0 -1
  777. data/docs/assets/tutorials_02-dialog.md.DE5WfCXI.js +0 -274
  778. data/docs/assets/tutorials_02-dialog.md.DE5WfCXI.lean.js +0 -1
  779. data/docs/assets/unit-tests.md.vDsdBbO_.js +0 -13
  780. data/docs/assets/unit-tests.md.vDsdBbO_.lean.js +0 -1
  781. data/docs/assets/welcome-to-brut.VSWzl17-.png +0 -0
  782. data/docs/assets/why.md.4WpxdrQ2.js +0 -1
  783. data/docs/assets/why.md.4WpxdrQ2.lean.js +0 -1
  784. data/docs/assets/workspace-protocol.C0gXsoDb.png +0 -0
  785. data/docs/assets.html +0 -47
  786. data/docs/brut-css/brut.css +0 -1
  787. data/docs/brut-css/brut.max.css +0 -22372
  788. data/docs/brut-css/classes/appearances.html +0 -783
  789. data/docs/brut-css/classes/background-colors.html +0 -3529
  790. data/docs/brut-css/classes/border-colors.html +0 -3529
  791. data/docs/brut-css/classes/borders.html +0 -2293
  792. data/docs/brut-css/classes/dimensions.html +0 -2581
  793. data/docs/brut-css/classes/flex.html +0 -917
  794. data/docs/brut-css/classes/foreground-colors.html +0 -3261
  795. data/docs/brut-css/classes/junk-drawer.html +0 -431
  796. data/docs/brut-css/classes/layout.html +0 -668
  797. data/docs/brut-css/classes/lists.html +0 -331
  798. data/docs/brut-css/classes/positioning.html +0 -1751
  799. data/docs/brut-css/classes/spacings.html +0 -2633
  800. data/docs/brut-css/classes/typography.html +0 -2206
  801. data/docs/brut-css/customization/advanced-configuration.html +0 -204
  802. data/docs/brut-css/customization/breakpoints.html +0 -227
  803. data/docs/brut-css/customization/design-system.html +0 -197
  804. data/docs/brut-css/customization/pseudo-classes.html +0 -228
  805. data/docs/brut-css/docs.css +0 -98
  806. data/docs/brut-css/getting-started/core-concepts.html +0 -234
  807. data/docs/brut-css/getting-started/installation.html +0 -190
  808. data/docs/brut-css/getting-started/overview.html +0 -210
  809. data/docs/brut-css/getting-started/simple-example.html +0 -285
  810. data/docs/brut-css/index.html +0 -193
  811. data/docs/brut-css/prism-twilight.min.css +0 -1
  812. data/docs/brut-css/properties/colors.html +0 -1548
  813. data/docs/brut-css/properties/spacings.html +0 -614
  814. data/docs/brut-css/properties/typography.html +0 -777
  815. data/docs/brut-js/api/AjaxSubmit.html +0 -452
  816. data/docs/brut-js/api/AjaxSubmit.js.html +0 -550
  817. data/docs/brut-js/api/Autosubmit.html +0 -192
  818. data/docs/brut-js/api/Autosubmit.js.html +0 -114
  819. data/docs/brut-js/api/BaseCustomElement.html +0 -1091
  820. data/docs/brut-js/api/BaseCustomElement.js.html +0 -312
  821. data/docs/brut-js/api/BrutCustomElements.html +0 -172
  822. data/docs/brut-js/api/BufferedLogger.html +0 -173
  823. data/docs/brut-js/api/ConfirmSubmit.html +0 -286
  824. data/docs/brut-js/api/ConfirmSubmit.js.html +0 -188
  825. data/docs/brut-js/api/ConfirmationDialog.html +0 -425
  826. data/docs/brut-js/api/ConfirmationDialog.js.html +0 -194
  827. data/docs/brut-js/api/ConstraintViolationMessage.html +0 -498
  828. data/docs/brut-js/api/ConstraintViolationMessage.js.html +0 -191
  829. data/docs/brut-js/api/ConstraintViolationMessages.html +0 -590
  830. data/docs/brut-js/api/ConstraintViolationMessages.js.html +0 -149
  831. data/docs/brut-js/api/CopyToClipboard.html +0 -345
  832. data/docs/brut-js/api/CopyToClipboard.js.html +0 -147
  833. data/docs/brut-js/api/Form.html +0 -291
  834. data/docs/brut-js/api/Form.js.html +0 -198
  835. data/docs/brut-js/api/I18nTranslation.html +0 -409
  836. data/docs/brut-js/api/I18nTranslation.js.html +0 -115
  837. data/docs/brut-js/api/LocaleDetection.html +0 -312
  838. data/docs/brut-js/api/LocaleDetection.js.html +0 -168
  839. data/docs/brut-js/api/Logger.html +0 -702
  840. data/docs/brut-js/api/Logger.js.html +0 -141
  841. data/docs/brut-js/api/Message.html +0 -238
  842. data/docs/brut-js/api/Message.js.html +0 -113
  843. data/docs/brut-js/api/PrefixedLogger.html +0 -369
  844. data/docs/brut-js/api/RichString.html +0 -1049
  845. data/docs/brut-js/api/RichString.js.html +0 -167
  846. data/docs/brut-js/api/Tabs.html +0 -295
  847. data/docs/brut-js/api/Tabs.js.html +0 -219
  848. data/docs/brut-js/api/Toast.html +0 -270
  849. data/docs/brut-js/api/Toast.js.html +0 -153
  850. data/docs/brut-js/api/Tracing.html +0 -277
  851. data/docs/brut-js/api/Tracing.js.html +0 -298
  852. data/docs/brut-js/api/external-CustomElementRegistry.html +0 -140
  853. data/docs/brut-js/api/external-Performance.html +0 -138
  854. data/docs/brut-js/api/external-Promise.html +0 -138
  855. data/docs/brut-js/api/external-ValidityState.html +0 -138
  856. data/docs/brut-js/api/external-Window.html +0 -233
  857. data/docs/brut-js/api/external-fetch.html +0 -138
  858. data/docs/brut-js/api/global.html +0 -400
  859. data/docs/brut-js/api/index.html +0 -168
  860. data/docs/brut-js/api/index.js.html +0 -184
  861. data/docs/brut-js/api/module-testing.html +0 -383
  862. data/docs/brut-js/api/scripts/linenumber.js +0 -25
  863. data/docs/brut-js/api/scripts/prettify/Apache-License-2.0.txt +0 -202
  864. data/docs/brut-js/api/scripts/prettify/lang-css.js +0 -2
  865. data/docs/brut-js/api/scripts/prettify/prettify.js +0 -28
  866. data/docs/brut-js/api/styles/jsdoc-default.css +0 -327
  867. data/docs/brut-js/api/styles/prettify-jsdoc.css +0 -111
  868. data/docs/brut-js/api/styles/prettify-tomorrow.css +0 -132
  869. data/docs/brut-js/api/testing.AssetMetadata.html +0 -172
  870. data/docs/brut-js/api/testing.AssetMetadataLoader.html +0 -171
  871. data/docs/brut-js/api/testing.CustomElementTest.html +0 -679
  872. data/docs/brut-js/api/testing.DOMCreator.html +0 -171
  873. data/docs/brut-js/api/testing_AssetMetadata.js.html +0 -86
  874. data/docs/brut-js/api/testing_AssetMetadataLoader.js.html +0 -76
  875. data/docs/brut-js/api/testing_CustomElementTest.js.html +0 -286
  876. data/docs/brut-js/api/testing_DOMCreator.js.html +0 -96
  877. data/docs/brut-js/api/testing_index.js.html +0 -99
  878. data/docs/brut-js.html +0 -40
  879. data/docs/business-logic.html +0 -29
  880. data/docs/cli.html +0 -150
  881. data/docs/components.html +0 -124
  882. data/docs/configuration.html +0 -106
  883. data/docs/css.html +0 -49
  884. data/docs/custom-element-tests.html +0 -97
  885. data/docs/database-access.html +0 -91
  886. data/docs/database-schema.html +0 -98
  887. data/docs/deployment.html +0 -83
  888. data/docs/dev-environment.html +0 -44
  889. data/docs/dir-structure.html +0 -74
  890. data/docs/doc-conventions.html +0 -29
  891. data/docs/end-to-end-tests.html +0 -56
  892. data/docs/favicon.ico +0 -0
  893. data/docs/features.html +0 -182
  894. data/docs/flash-and-session.html +0 -107
  895. data/docs/form-constraints.html +0 -118
  896. data/docs/forms.html +0 -92
  897. data/docs/getting-started.html +0 -59
  898. data/docs/handlers.html +0 -82
  899. data/docs/hashmap.json +0 -1
  900. data/docs/hooks.html +0 -108
  901. data/docs/i18n.html +0 -51
  902. data/docs/index.html +0 -29
  903. data/docs/instrumentation.html +0 -118
  904. data/docs/javascript.html +0 -59
  905. data/docs/jobs.html +0 -53
  906. data/docs/keyword-injection.html +0 -49
  907. data/docs/layouts.html +0 -96
  908. data/docs/lsp.html +0 -29
  909. data/docs/markdown-examples.html +0 -61
  910. data/docs/middleware.html +0 -48
  911. data/docs/overview.html +0 -29
  912. data/docs/pages.html +0 -73
  913. data/docs/recipes/alternate-layouts.html +0 -50
  914. data/docs/recipes/authentication.html +0 -185
  915. data/docs/recipes/custom-flash.html +0 -54
  916. data/docs/recipes/dev-env-secrets.html +0 -40
  917. data/docs/recipes/form-errors.html +0 -94
  918. data/docs/recipes/indexed-forms.html +0 -102
  919. data/docs/recipes/migrations.html +0 -125
  920. data/docs/recipes/text-field-component.html +0 -129
  921. data/docs/roadmap.html +0 -29
  922. data/docs/routes.html +0 -49
  923. data/docs/security.html +0 -29
  924. data/docs/seed-data.html +0 -42
  925. data/docs/space-time-continuum.html +0 -29
  926. data/docs/tutorial.html +0 -55
  927. data/docs/tutorials/01-intro.html +0 -736
  928. data/docs/tutorials/02-dialog.html +0 -302
  929. data/docs/unit-tests.html +0 -41
  930. data/docs/vp-icons.css +0 -1
  931. data/docs/why.html +0 -29
  932. data/docs-todo.md +0 -32
  933. data/dx/bash_customizations +0 -6
  934. data/dx/build +0 -73
  935. data/dx/build.pre +0 -15
  936. data/dx/docker-compose.env +0 -22
  937. data/dx/dx.sh.lib +0 -24
  938. data/dx/exec +0 -75
  939. data/dx/setupkit.sh.lib +0 -144
  940. data/dx/show-help-in-app-container-then-wait.sh +0 -38
  941. data/lib/brut/cli/app.rb +0 -238
  942. data/lib/brut/cli/app_runner.rb +0 -252
  943. data/lib/brut/cli/command.rb +0 -258
  944. data/lib/brut/cli/execution_results.rb +0 -119
  945. data/lib/brut/front_end/layouts/_internal.html.erb +0 -68
  946. data/lib/brut/front_end/pages/_missing_page.html.erb +0 -17
  947. data/mkbrut/.gitignore +0 -16
  948. data/mkbrut/CODE_OF_CONDUCT.txt +0 -100
  949. data/mkbrut/Gemfile +0 -3
  950. data/mkbrut/Gemfile.lock +0 -20
  951. data/mkbrut/LICENSE.txt +0 -370
  952. data/mkbrut/README.md +0 -145
  953. data/mkbrut/Rakefile +0 -2
  954. data/mkbrut/bin/build +0 -36
  955. data/mkbrut/bin/ci +0 -19
  956. data/mkbrut/bin/docs +0 -19
  957. data/mkbrut/bin/publish +0 -129
  958. data/mkbrut/bin/rake +0 -16
  959. data/mkbrut/bin/setup +0 -30
  960. data/mkbrut/brut-welcome.png +0 -0
  961. data/mkbrut/deploy/.dockerignore +0 -2
  962. data/mkbrut/deploy/Dockerfile +0 -25
  963. data/mkbrut/dx +0 -1
  964. data/mkbrut/exe/mkbrut +0 -5
  965. data/mkbrut/lib/mkbrut/app_name.rb +0 -29
  966. data/mkbrut/lib/mkbrut/app_options.rb +0 -36
  967. data/mkbrut/lib/mkbrut/cli.rb +0 -189
  968. data/mkbrut/lib/mkbrut/erb_binding_delegate.rb +0 -20
  969. data/mkbrut/lib/mkbrut/ops.rb +0 -17
  970. data/mkbrut/lib/mkbrut/organization.rb +0 -5
  971. data/mkbrut/lib/mkbrut/segments.rb +0 -8
  972. data/mkbrut/lib/mkbrut/version.rb +0 -3
  973. data/mkbrut/lib/mkbrut.rb +0 -20
  974. data/mkbrut/mkbrut.gemspec +0 -34
  975. data/mkbrut/templates/Base/app/src/front_end/images/LogoPylon.png +0 -0
  976. data/mkbrut/templates/Base/bin/build-assets +0 -7
  977. data/mkbrut/templates/Base/bin/ci +0 -39
  978. data/mkbrut/templates/Base/bin/db +0 -9
  979. data/mkbrut/templates/Base/bin/scaffold +0 -9
  980. data/mkbrut/templates/Base/bin/setup +0 -287
  981. data/mkbrut/templates/Base/bin/test +0 -9
  982. data/mkbrut/templates/Base/bin/test-server +0 -29
  983. data/mkbrut/templates/Base/dx/prune +0 -19
  984. data/mkbrut/templates/Base/dx/start +0 -30
  985. data/mkbrut/templates/Base/dx/stop +0 -23
  986. data/mkbrut/templates/segments/Heroku/deploy/heroku_config.rb +0 -27
  987. data/specs/brut/front_end/forms/input.spec.rb +0 -978
  988. data/specs/brut/front_end/forms/radio_button_group_input.spec.rb +0 -54
  989. data/specs/brut/front_end/forms/select_input.spec.rb +0 -54
  990. data/specs/brut/instrumentation/methods.spec.rb +0 -399
  991. data/specs/brut/junk_drawer.spec.rb +0 -79
  992. data/specs/brut/tui/ansi_escape_code.spec.rb +0 -30
  993. data/specs/brut/tui/event_loop.spec.rb +0 -70
  994. data/specs/brut/tui/events/base_event.spec.rb +0 -26
  995. data/specs/brut/tui/events/event_bus.spec.rb +0 -141
  996. data/specs/brut/tui/events/exception.spec.rb +0 -19
  997. data/specs/brut/tui/events/test_event.rb +0 -5
  998. data/specs/spec_helper.rb +0 -31
  999. data/specs/support/matchers/have_constraint_violation.rb +0 -23
  1000. data/specs/support/matchers.rb +0 -5
  1001. data/specs/support.rb +0 -3
  1002. /data/{mkbrut/lib/mkbrut → lib/brut/cli/apps/new}/prefixed_io.rb +0 -0
  1003. /data/{mkbrut/templates → templates}/Base/.dockerignore +0 -0
  1004. /data/{mkbrut/templates → templates}/Base/.env.development.erb +0 -0
  1005. /data/{mkbrut/templates → templates}/Base/.env.test.erb +0 -0
  1006. /data/{mkbrut/templates → templates}/Base/.gitignore +0 -0
  1007. /data/{mkbrut/templates → templates}/Base/.projections.json +0 -0
  1008. /data/{mkbrut/templates → templates}/Base/Dockerfile.dx +0 -0
  1009. /data/{mkbrut/templates → templates}/Base/Gemfile.erb +0 -0
  1010. /data/{mkbrut/templates → templates}/Base/Procfile.development +0 -0
  1011. /data/{mkbrut/templates → templates}/Base/Procfile.test +0 -0
  1012. /data/{mkbrut/templates → templates}/Base/README.md +0 -0
  1013. /data/{mkbrut/templates → templates}/Base/README.md.erb +0 -0
  1014. /data/{mkbrut/templates → templates}/Base/app/bootstrap.rb +0 -0
  1015. /data/{mkbrut/templates → templates}/Base/app/config/i18n/en/1_defaults.rb +0 -0
  1016. /data/{mkbrut/templates → templates}/Base/app/config/i18n/en/2_app.rb +0 -0
  1017. /data/{mkbrut/templates → templates}/Base/app/public/static/manifest.json.erb +0 -0
  1018. /data/{mkbrut/templates → templates}/Base/app/src/app.rb.erb +0 -0
  1019. /data/{mkbrut/templates → templates}/Base/app/src/back_end/data_models/app_data_model.rb +0 -0
  1020. /data/{mkbrut/templates → templates}/Base/app/src/back_end/data_models/db.rb +0 -0
  1021. /data/{mkbrut/templates → templates}/Base/app/src/back_end/data_models/migrations/20240101130000_citext.rb +0 -0
  1022. /data/{mkbrut/templates → templates}/Base/app/src/back_end/data_models/seed/seed_data.rb +0 -0
  1023. /data/{mkbrut/templates → templates}/Base/app/src/front_end/components/app_component.rb +0 -0
  1024. /data/{mkbrut/templates → templates}/Base/app/src/front_end/components/custom_element_registration.rb.erb +0 -0
  1025. /data/{mkbrut/templates → templates}/Base/app/src/front_end/css/index.css +0 -0
  1026. /data/{mkbrut/templates → templates}/Base/app/src/front_end/css/svgs.css +0 -0
  1027. /data/{mkbrut/templates → templates}/Base/app/src/front_end/forms/app_form.rb +0 -0
  1028. /data/{mkbrut/templates → templates}/Base/app/src/front_end/handlers/app_handler.rb +0 -0
  1029. /data/{brutrb.com → templates/Base/app/src/front_end}/images/LogoPylon.png +0 -0
  1030. /data/{mkbrut/templates → templates}/Base/app/src/front_end/images/LogoTransit.png +0 -0
  1031. /data/{mkbrut/templates → templates}/Base/app/src/front_end/images/apple-touch-icon-120x120.png +0 -0
  1032. /data/{mkbrut/templates → templates}/Base/app/src/front_end/images/apple-touch-icon-152x152.png +0 -0
  1033. /data/{mkbrut/templates → templates}/Base/app/src/front_end/images/apple-touch-icon-167x167.png +0 -0
  1034. /data/{mkbrut/templates → templates}/Base/app/src/front_end/images/apple-touch-icon-180x180.png +0 -0
  1035. /data/{mkbrut/templates → templates}/Base/app/src/front_end/images/favicon.ico +0 -0
  1036. /data/{mkbrut/templates → templates}/Base/app/src/front_end/images/icon.png +0 -0
  1037. /data/{mkbrut/templates → templates}/Base/app/src/front_end/images/mkicons.sh +0 -0
  1038. /data/{mkbrut/templates → templates}/Base/app/src/front_end/js/index.js +0 -0
  1039. /data/{mkbrut/templates → templates}/Base/app/src/front_end/layouts/blank_layout.rb +0 -0
  1040. /data/{mkbrut/templates → templates}/Base/app/src/front_end/layouts/default_layout.rb.erb +0 -0
  1041. /data/{mkbrut/templates → templates}/Base/app/src/front_end/pages/app_page.rb +0 -0
  1042. /data/{mkbrut/templates → templates}/Base/app/src/front_end/pages/home_page.rb +0 -0
  1043. /data/{mkbrut/templates → templates}/Base/app/src/front_end/support/app_session.rb +0 -0
  1044. /data/{mkbrut/templates → templates}/Base/app/src/front_end/svgs/README.md +0 -0
  1045. /data/{mkbrut/templates → templates}/Base/app/src/front_end/svgs/comment-button.svg +0 -0
  1046. /data/{mkbrut/templates → templates}/Base/bin/README.md.erb +0 -0
  1047. /data/{mkbrut/templates → templates}/Base/bin/console +0 -0
  1048. /data/{mkbrut/templates → templates}/Base/bin/dbconsole +0 -0
  1049. /data/{mkbrut/templates → templates}/Base/bin/dev +0 -0
  1050. /data/{mkbrut/templates → templates}/Base/bin/run +0 -0
  1051. /data/{mkbrut/templates → templates}/Base/bin/run.run +0 -0
  1052. /data/{mkbrut/templates → templates}/Base/bin/startup-message +0 -0
  1053. /data/{mkbrut/templates → templates}/Base/config.ru +0 -0
  1054. /data/{mkbrut/templates → templates}/Base/docker-compose.dx.yml +0 -0
  1055. /data/{mkbrut/templates → templates}/Base/dx/README.md +0 -0
  1056. /data/{mkbrut/templates → templates}/Base/dx/bash_customizations +0 -0
  1057. /data/{mkbrut/templates → templates}/Base/dx/bash_customizations.local +0 -0
  1058. /data/{mkbrut/templates → templates}/Base/dx/build +0 -0
  1059. /data/{mkbrut/templates → templates}/Base/dx/dx.sh.lib +0 -0
  1060. /data/{mkbrut/templates → templates}/Base/dx/exec +0 -0
  1061. /data/{dx → templates/Base/dx}/prune +0 -0
  1062. /data/{mkbrut/templates → templates}/Base/dx/show-help-in-app-container-then-wait.sh +0 -0
  1063. /data/{dx → templates/Base/dx}/start +0 -0
  1064. /data/{dx → templates/Base/dx}/stop +0 -0
  1065. /data/{mkbrut/templates → templates}/Base/package.json.erb +0 -0
  1066. /data/{mkbrut/templates → templates}/Base/puma.config.rb +0 -0
  1067. /data/{mkbrut/templates → templates}/Base/specs/e2e/home_page.spec.rb.erb +0 -0
  1068. /data/{mkbrut/templates → templates}/Base/specs/front_end/js/SpecHelper.js +0 -0
  1069. /data/{mkbrut/templates → templates}/Base/specs/front_end/pages/home_page.spec.rb +0 -0
  1070. /data/{mkbrut/templates → templates}/Base/specs/lint_factories.spec.rb +0 -0
  1071. /data/{mkbrut/templates → templates}/Base/specs/spec_helper.rb +0 -0
  1072. /data/{mkbrut/templates → templates}/Base/specs/support.rb +0 -0
  1073. /data/{mkbrut/templates → templates}/segments/BareBones/app/src/front_end/handlers/trigger_exception_handler.rb +0 -0
  1074. /data/{mkbrut/templates → templates}/segments/BareBones/app/src/front_end/js/Example.js.erb +0 -0
  1075. /data/{mkbrut/templates → templates}/segments/BareBones/specs/front_end/handlers/trigger_exception_handler.spec.rb +0 -0
  1076. /data/{mkbrut/templates → templates}/segments/BareBones/specs/front_end/js/Example.spec.js.erb +0 -0
  1077. /data/{mkbrut/templates → templates}/segments/Demo/app/src/back_end/data_models/db/guestbook_message.rb +0 -0
  1078. /data/{mkbrut/templates → templates}/segments/Demo/app/src/back_end/data_models/migrations/20250628194124_guestbook.rb +0 -0
  1079. /data/{mkbrut/templates → templates}/segments/Demo/app/src/front_end/components/flash_component.rb +0 -0
  1080. /data/{mkbrut/templates → templates}/segments/Demo/app/src/front_end/css/constraint-violations.css +0 -0
  1081. /data/{mkbrut/templates → templates}/segments/Demo/app/src/front_end/fonts/monaspace-xenon.ttf +0 -0
  1082. /data/{mkbrut/templates → templates}/segments/Demo/app/src/front_end/forms/guestbook_message_form.rb +0 -0
  1083. /data/{mkbrut/templates → templates}/segments/Demo/app/src/front_end/handlers/guestbook_message_handler.rb +0 -0
  1084. /data/{mkbrut/templates → templates}/segments/Demo/app/src/front_end/pages/guestbook_page/message_component.rb +0 -0
  1085. /data/{mkbrut/templates → templates}/segments/Demo/app/src/front_end/pages/guestbook_page.rb +0 -0
  1086. /data/{mkbrut/templates → templates}/segments/Demo/app/src/front_end/pages/new_guestbook_message_page.rb +0 -0
  1087. /data/{mkbrut/templates → templates}/segments/Demo/specs/back_end/data_models/db/guestbook_message.spec.rb +0 -0
  1088. /data/{mkbrut/templates → templates}/segments/Demo/specs/e2e/guest_message.spec.rb +0 -0
  1089. /data/{mkbrut/templates → templates}/segments/Demo/specs/factories/db/guestbook_message.factory.rb +0 -0
  1090. /data/{mkbrut/templates → templates}/segments/Demo/specs/front_end/components/flash_component.spec.rb +0 -0
  1091. /data/{mkbrut/templates → templates}/segments/Demo/specs/front_end/handlers/guestbook_message_handler.spec.rb +0 -0
  1092. /data/{mkbrut/templates → templates}/segments/Demo/specs/front_end/pages/guestbook_page/message_component.spec.rb +0 -0
  1093. /data/{mkbrut/templates → templates}/segments/Demo/specs/front_end/pages/guestbook_page.spec.rb +0 -0
  1094. /data/{mkbrut/templates → templates}/segments/Demo/specs/front_end/pages/new_guestbook_message_page.spec.rb +0 -0
  1095. /data/{mkbrut/templates → templates}/segments/Heroku/bin/deploy +0 -0
  1096. /data/{mkbrut/templates → templates}/segments/Heroku/deploy/docker-entrypoint +0 -0
  1097. /data/{mkbrut/templates → templates}/segments/Sidekiq/app/boot_sidekiq.rb +0 -0
  1098. /data/{mkbrut/templates → templates}/segments/Sidekiq/app/config/sidekiq.yml +0 -0
  1099. /data/{mkbrut/templates → templates}/segments/Sidekiq/app/src/back_end/jobs/app_job.rb +0 -0
  1100. /data/{mkbrut/templates → templates}/segments/Sidekiq/app/src/back_end/jobs/example_job.rb +0 -0
  1101. /data/{mkbrut/templates → templates}/segments/Sidekiq/app/src/back_end/segments/sidekiq_segment.rb +0 -0
  1102. /data/{mkbrut/templates → templates}/segments/Sidekiq/bin/run.sidekiq +0 -0
  1103. /data/{mkbrut/templates → templates}/segments/Sidekiq/specs/back_end/jobs/example_job.spec.rb +0 -0
  1104. /data/{mkbrut/templates → templates}/segments/Sidekiq/specs/integration/sidekiq_works.spec.rb +0 -0
data/brutrb.com/forms.md DELETED
@@ -1,238 +0,0 @@
1
- # Forms
2
-
3
- In HTML, forms are the way data is submit to the server. Forms attract complexity
4
- since they interact with user experience, data validation, and interaction with a
5
- back-end database.
6
-
7
- ## Overview
8
-
9
- Forms in Brut accomplish three things:
10
-
11
- * Forms model the data elements of a `<form>`, including client-side constraints (which Brut can check server-side as well).
12
- * Forms assist in HTML generation, to ensure the HTML elements are consistent and
13
- correct.
14
- * Forms hold data submitted to the server. No need for strong parameters or digging
15
- into a Hash of Whatever.
16
-
17
- Since forms can lead to a lot of complexity, this module will stick to the very
18
- basics. There are several recipes we'll link to that explain more complex
19
- interactions with forms.
20
-
21
- ### Declaring Form Data/Elements
22
-
23
- When you [create a form route](/routes), this imlplies a form class exists to
24
- specify the data:
25
-
26
- ```ruby
27
- # app/src/app.rb
28
- routes do
29
- form "new_widget"
30
- end
31
-
32
- # app/src/front_end/forms/new_widget_form.rb
33
- class NewWidgetForm < AppForm
34
- end
35
- ```
36
-
37
- `AppForm` extends `Brut::FrontEnd::Form`, which provides class methods you can use
38
- to declare your form's elements. Let's say our form has a name (that must be at least 3 characters), a quantity (integer greater than 0), and an optional description.
39
-
40
- ```ruby
41
- class NewWidgetForm < AppForm
42
- input :name, minlength: 3
43
- input :quantity, type: :number, min: 0, step: 1
44
- input :description, required: true
45
- end
46
- ```
47
-
48
- `input` declares a form element that will ultimately be handled by an `<input>` or
49
- `<textarea>` tag. `select` and `radio_button_group` are also avaiable, and are
50
- discussed in recipes.
51
-
52
- `input` accepts an input name used for `<input>`'s `name` attribute. It also
53
- accepts keyword arguments that match the initializer of
54
- `Brut::FrontEnd::Forms::InputDefinition`. You'll notice those values mirror the
55
- various attributes related to client-side constraint validations, for example
56
- `minlength:` and `pattern:`.
57
-
58
- Form elements have some defaults, as described below:
59
-
60
- | Declaration | Default Behavior |
61
- |---|---|
62
- | `input :email` | `type: :email` |
63
- | `input :password` | `type: :password` |
64
- | `input :password_confirmation` | `type: :password` |
65
- | `input «any other name»` | `type: :text` |
66
- | `input «name», type: :checkbox` | `required: false` |
67
- | `input «name» type: «not checkbox»` | `required: true` |
68
-
69
- ### Using Forms to Generate HTML
70
-
71
- One reason Brut models forms as classes with declared inputs is that you can then
72
- use an instance of that class to generate HTML. Brut will generate appropriate
73
- HTML, optionally configured to show a pre-existing value from the form.
74
-
75
- The classes that do this are in `Brut::FrontEnd::Components`
76
-
77
- | Class | Purpose |
78
- |---|---|
79
- |`Brut::FrontEnd::Components::FormTag` | Creates a `<form>` tag that submits to the form's configured route and includes [CSRF protection](/security). |
80
- |`Brut::FrontEnd::Components::InputTag` | Creates an `<input>` tag |
81
- |`Brut::FrontEnd::Components::RadioButton` | Creates an `<input type="radio">` tag
82
- for use in a radio button group. |
83
- |`Brut::FrontEnd::Components::SelectTagWithOptions` | Creates a `<select>` tag with
84
- `<option>` tags inside. |
85
- |`Brut::FrontEnd::Components::TextareaTag` | Creates a `<textarea>` tag. |
86
- |`Brut::FrontEnd::Components::ButtonTag` | Creates a `<button>` tag to submit the form. |
87
-
88
- All of these classes have an initializer that accepts:
89
-
90
- * `form:` the form object, used to figure out the HTML attributes and current value of the element.
91
- * `input_name:` to know which input is being generated.
92
- * `index:` for [indexed form elements](/recipes/indexed-forms.md).
93
- * `**html_attributes` any other HTML attributesyou'd like to include.
94
-
95
- These class names are quite long, but since these are Phlex components, you can
96
- `include` `Brut::FrontEnd::Components` and access their initializers as a [Phlex
97
- kit](https://phlex.fun):
98
-
99
- ```ruby
100
- class NewWidgetPage < AppPage
101
- include Brut::FrontEnd::Components
102
-
103
- def initialize(form: nil)
104
- @form = form || NewWidgetForm.new
105
- end
106
-
107
- private attr_reader :form
108
-
109
- def page_template
110
- FormTag(for: form) do
111
- Components::InputTag(form:, input_name: :name)
112
- Components::InputTag(form:, input_name: :quantity)
113
- Components::TextareaTag(form:, input_name: :description)
114
- end
115
- end
116
- end
117
- ```
118
-
119
- Phlex kits provides a methods named for the class that call that class' constructor.
120
-
121
- The code above will generate this HTML
122
-
123
- ```html
124
- <form action="/new_widgets" method="post">
125
- <input type="hidden" name="authenticity_token" value=«value»>
126
- <input type="text" name="name" required minlength="3">
127
- <input type="number" name="quantity" required min="0" step="1">
128
- <textarea name="description">
129
- </textarea>
130
- </form>
131
- ```
132
-
133
- Forms accept a single initializer parameter, `params` that is a `Hash`.
134
- `Brut::FrontEnd::Form` implements this initializer, and will pluck values from the
135
- hash to initialize the inputs:
136
-
137
- ::: code-group
138
-
139
- ```ruby [Form Class] {5-8}
140
- class NewWidgetPage < AppPage
141
- include Brut::FrontEnd::Components
142
-
143
- def initialize(form: nil)
144
- @form = form || NewWidgetForm.new( params: {
145
- name: "My New Widget",
146
- quantity: 10,
147
- })
148
- end
149
-
150
- # ...
151
-
152
- end
153
- ```
154
-
155
- ```html [HTML Generated] {3,5}
156
- <form action="/new_widgets" method="post">
157
- <input type="hidden" name="authenticity_token" value=«value»>
158
- <input type="text" value="My New Widget"
159
- name="name" required minlength="3">
160
- <input type="number" value="10"
161
- name="quantity" required min="0" step="1">
162
- <textarea name="description">
163
- </textarea>
164
- </form>
165
- ```
166
-
167
- :::
168
-
169
- ### Accessing Data in a Submitted Form
170
-
171
- As mentioned in [routes](/routes), a `form` route implies not just a form class, but
172
- a [handler](/handlers) class to receive the submitted data.
173
-
174
- We'll discuss handlers in the next section, but they demonstrate how you can access
175
- a form's data:
176
-
177
- ```ruby
178
- class NewWidgetHandler < AppHandler
179
- def initialize(form:)
180
- @form = form
181
- end
182
-
183
- def handle
184
- form.name # => whatever name was submitted
185
- form.quantity # => whatever quantity was submitted
186
- form.description # => description provided
187
- end
188
- end
189
- ```
190
-
191
- A few things to note about how this works:
192
-
193
- * Only those inputs declared in the form class can be accessed. All other values are
194
- discarded. No need for "strong parameters".
195
- * All values are strings, because this is what HTML provides.
196
- * Blank values are coerced to `nil`.
197
-
198
- The next module will deal with form constraints and validations, in particular how
199
- to manage the user experience around client-side constraint violations, how to
200
- re-check them server side, and how to perform server-side checks.
201
-
202
- ## Testing
203
-
204
- Form classes don't need any logic on them, but they can be given helper methods or other logic if it makes sense. To test them, test them like any other class - instantiate an object and examine the behavior of its methods.
205
-
206
- ## Recommended Practices
207
-
208
- ### Create Components to Generate Form Controls
209
-
210
- `Brut::FrontEnd::Components::Inputs` will generate the basic tags like `<input>` or
211
- `<select>`. Everything else like `<label>` is up to you. We recommend that you
212
- create [components](/components) to generate the markup required for *your* inputs
213
- and controls.
214
-
215
- The recipe ["Creating a Text Field"](/recipes/text-field-component) will walk you
216
- through the steps and considerations.
217
-
218
- ### Take Advantage of Client Side Constraints
219
-
220
- Even though client-side constraints can sometimes be awkward in certain browsers,
221
- they are going to be eminently usable and accessible, and you can easily
222
- re-validate them on the server side.
223
-
224
- ## Technical Notes
225
-
226
- > [!IMPORTANT]
227
- > Technical Notes are for deeper understanding and debugging. While we will try to keep them up-to-date with changes to Brut's
228
- > internals, the source code is always more correct.
229
-
230
- _Last Updated May 13, 2025_
231
-
232
- For HTML generation, there are few classes that work together:
233
-
234
- * *input definitions* define an input and tend to provide an API similar to HTML's. See `Brut::FrontEnd::Forms::InputDefinition`.
235
- * *inputs* represent the runtime state of an input from the browser. Whereas an input definition has no state, the input does. It delegates much of its behavior to the underlying input definition. It's `value=` method performs client-side constraint validations by creating a `Brut::FrontEnd::Forms::ValidityState` internally. See `Brut::FrontEnd::Forms::Input`.
236
- * `Brut::FrontEnd::Forms::InputDeclarations` is a module that allows creating input definitions inside your form
237
- class. It implements the class methods like `input`.
238
- * `Brut::FrontEnd::Components::Inputs` contains components used to generate `<input>` fields. These classes will coerce the value of the `input` they are given to generate the correct HTML.
@@ -1,142 +0,0 @@
1
- # Getting Started
2
-
3
- Brut is developed alongside a separate gem called `mkbrut`, which allows you to
4
- create a new Brut app. It will set up your dev environment as well.
5
-
6
- ## Get `mkbrut`
7
-
8
- The simplest way to use `mkbrut` is to use an existing [Docker image](https://hub.docker.com/repository/docker/thirdtank/mkbrut/general). You don't have to install or configure Ruby:
9
-
10
- ```
11
- docker run \
12
- --pull always \
13
- -v "$PWD":"$PWD" \
14
- -w "$PWD" \
15
- -u $(id -u):$(id -g) \
16
- -it \
17
- thirdtank/mkbrut \
18
- mkbrut my-new-app
19
- ```
20
-
21
- If you already have Ruby 3.4 installed, you can install `mkbrut` directly:
22
-
23
- ```
24
- > gem install mkbrut
25
- > mkbrut my-new-app
26
- ```
27
-
28
- ## Init Your App
29
-
30
- A Brut app just needs a name, which will be used to derive a few more useful values.
31
- For now:
32
-
33
- ::: code-group
34
-
35
- ``` [Docker-based]
36
- docker run \
37
- --pull always \
38
- -v "$PWD":"$PWD" \
39
- -w "$PWD" \
40
- -u $(id -u):$(id -g) \
41
- -it \
42
- thirdtank/mkbrut \
43
- mkbrut my-new-app
44
- ```
45
-
46
- ``` [RubyGems-based]
47
- mkbrut my-new-app
48
- ```
49
-
50
- :::
51
-
52
- This will create your new app, along with some demo routes, components, handlers, and tests. If this is your first time using Brut, we recommend you examine these demo components.
53
-
54
- To create your app without the demo components:
55
-
56
- ::: code-group
57
-
58
- ``` [Docker-based]
59
- docker run \
60
- --pull always \
61
- -v "$PWD":"$PWD" \
62
- -w "$PWD" \
63
- -u $(id -u):$(id -g) \
64
- -it \
65
- thirdtank/mkbrut \
66
- mkbrut my-new-app --no-demo
67
- ```
68
-
69
- ``` [RubyGems-based]
70
- mkbrut my-new-app --no-demo
71
- ```
72
-
73
- :::
74
-
75
- ## Start Your Dev Environment
76
-
77
- Brut includes a dev environment based on Docker. It uses Docker compose to run a
78
- Docker container where your app will run, a Docker container for Postgres, and a
79
- Docker container for local observability via OpenTelemetry.
80
-
81
- 1. [Install Docker](https://docs.docker.com/get-started/get-docker/)
82
- 2. Build the image used to create you app's container:
83
-
84
- ```
85
- > dx/build
86
- ```
87
- 3. Start up all the containers:
88
-
89
- ```
90
- > dx/start
91
- ```
92
- 4. Now, install your aps gems and set it all up:
93
-
94
- ```
95
- > dx/exec bin/setup
96
- ```
97
-
98
- Now, you're ready to go. See [Dev Environemnt](/dev-environment) for details on how
99
- this all works.
100
-
101
- > [!NOTE]
102
- > Instead of running `dx/exec` in front of your commands, you
103
- > can instead do `dx/exec bash` to "log in" to the running container.
104
- > You'll have a normal prompt and can issue commands directly from there.
105
-
106
- ## Run the App
107
-
108
- ```
109
- dx/exec bin/dev
110
- ```
111
-
112
- You can now visit your app at `localhost:6502`
113
-
114
- You can make changes and see them when you reload. Open up `app/src/front_end/pages/home_page.rb` *in your editor running on your computer* and change the `h1` to look like so:
115
-
116
- ```ruby {6}
117
- class HomePage < AppPage
118
- def page_template
119
- div(class: "flex flex-column items-center justify-center h-80vh") do
120
- img(src: "/static/images/icon.png", class: "h-50")
121
- h1(class: "ff-sans ma-0 lh-title f-5") do
122
- "Welcome to My New App!"
123
- end
124
-
125
- # ...
126
- ```
127
-
128
- When you reload your browser, you'll see your change
129
-
130
- ## Run the Tests
131
-
132
- There are a few tests you can run, as well as some checks that you aren't using
133
- RubyGems with security vulnerabilities. Run it all now with `bin/ci`:
134
-
135
- ```
136
- dx/exec bin/ci
137
- ```
138
-
139
- ## Now Build The Rest of Your App 🦉
140
-
141
- You can [follow the tutorial](/tutorial), check out the [conceptual overview](/overview), or dive straight into the [API docs](/api/index.html). You might also want to check out the docs for [LSP Support](/lsp).
142
-
@@ -1,177 +0,0 @@
1
- # Handlers & Actions
2
-
3
- Handlers process form submissions, and *actions* work similarly to process any arbitrary HTTP request.
4
-
5
- ## Overview
6
-
7
- Where a [page](/pages) renders a web page in HTML, a *handler* responds to all other HTTP requests. To respond to such HTTP requests, you'd first create a [route](/routes), using `form`, `action`, or `path`.
8
-
9
- ### Handler Structure
10
-
11
- A handler's initializer is subject to [keyword injection](/keyword-injection), with
12
- the addition of the `form:` keyword, which, if present, will be an instance of the
13
- associated form class, populated with the data in the form submission (not available for `path` or `action` routes).
14
-
15
- You must implement `handle` to process the form. **A handler's public API, as
16
- called by Brut and your tests, is `handle!`**, however you implement `handle`, which
17
- `handle!` calls.
18
-
19
- `handle`'s return value dictates what will happen next:
20
-
21
- | Return Value | Behavior |
22
- |---|---|
23
- |Instance of a page or component | That page or component's HTML is generated and returned. This is not a redirect, but more like `render :new` in a Rails controller |
24
- |`Brut::FrontEnd::HttpStatus` | This HTTP status is returned with no body. Use `http_status` from `Brut::FrontEnd::HandlingResults` (included in all handlers) to create an instance from a number |
25
- | `URI` | Redirect to the URI. Use `redirect_to` from `Brut::FrontEnd::HandlingResults` (included in all handlers) to generate a URI from a page class and parameters |
26
- | Two element array with *element 0* being a `Brut::FrontEnd::HttpStatus`, and *element 1* being a page or component instance | Generates the page or component's HTML, but sets the given status instead of 200. Useful for Ajax responses where the HTTP status affects client-side behavior |
27
- | `Brut::FrontEnd::Download` | Download a file |
28
- | `Brut::FrontEnd::GenericResponse` | wrap any Rack response |
29
-
30
- > [!IMPORTANT]
31
- > The only way to render something other than HTML is to do so as a
32
- > `GenericResponse`, which is basically the low-level Rack API. Brut
33
- > encourages Ajax responses to be HTML and for you to use the browser's
34
- > APIs to interact with that HTML. Brut may make it easier to work
35
- > with other types of content in the future.
36
-
37
- ### Handling a Form Submission
38
-
39
- A common pattern when handling a form submisssion is to check for any constraint
40
- violations. If there are some, re-generate the HTML for the page containing the
41
- form, highlighting the violations. Otherwise, save the data and redirect to another
42
- page.
43
-
44
- Here's how that looks:
45
-
46
- ```ruby
47
- class NewWidgetHandler < AppHandler
48
- def initialize(form:)
49
- @form = form
50
- end
51
-
52
- def handle
53
- # if no client-side violations were submitted
54
- if @form.valid?
55
- widget = DB::Widget.find(name: form.name)
56
- if widget
57
- @form.server_side_constraint_violation(
58
- input_name: :name,
59
- key: :name_is_taken
60
- )
61
- end
62
- end
63
-
64
- if @form.constraint_violations?
65
- NewWidgetPage.new(form: @form)
66
- else
67
- DB::Widget.create(name: form.name,
68
- quantity: form.quantity,
69
- description: form.description)
70
- redirect_to(WidgetsPage)
71
- end
72
- end
73
- end
74
- ```
75
-
76
- Unlike a Rails controller, the return value of `handle` controls the behavior. As
77
- we saw in [Form Constraints](/form-constraints), the HTML generated by
78
- `NewWidgetPage` will show constraint violations, so by returning
79
- `NewWidgetPage.new(form: @form)`, the page has the same form instance, including all
80
- the constraint violations, and the visitor will see the problems.
81
-
82
- ### Handling Other Requests
83
-
84
- Non-form submissions work similarly, however there is no form available. If the
85
- request could potentially involve a visitor-initiated error, you can use the
86
- [flash](/flash-and-session) to communicate back. The flash is available for injection into the
87
- initializer and, assuming your page uses it to show messages, can allow for
88
- communication when something is wrong:
89
-
90
- ```ruby
91
- class App
92
- # ...
93
-
94
- routes do
95
- action "/delete_widget/:widget_id"
96
-
97
- # ...
98
- end
99
- end
100
-
101
- class DeleteWidgetByIdHandler < AppHandler
102
- def initialize(widget_id:, flash:)
103
- @widget_id = widget_id
104
- @flash = flash
105
- end
106
-
107
- def handle
108
- widget = DB::Widget.find!(id: @widget_id)
109
- if widget.can_delete?
110
- widget.delete
111
- @flash.notice = :widget_deleted
112
- redirect_to(WidgetsPage)
113
- else
114
- @flash.alert = :widget_cannot_be_deleted
115
- WidgetsPage.new
116
- end
117
- end
118
- end
119
- ```
120
-
121
- ### Hooks
122
-
123
- A handler's public API is `handle!`, because it first calls `before_handle`. This
124
- operates as a before hook, and has the same return values as `handle`, with the
125
- exception of also recognizing `nil`, which indicates processing should proceed to
126
- `handle`.
127
-
128
- Generally, you don't need to implement hooksd on a per-handler basis, but may find
129
- it useful in a shared super class to implement cross-cutting behavior.
130
-
131
- ## Testing
132
-
133
- See [Unit Testing](/unit-tests) for some basic assumptions and configuration available for all Brut unit tests.
134
-
135
- Handler tests should be straightforward: you create your handler, call `handle!`
136
- (remember, `handle!` is the public API, and will call your hooks, which you want in
137
- a test), then examine the result returned and any ancillary behavior, such as
138
- updated database records.
139
-
140
- Some matchers are available to make assertions about `handle!`'s return value:
141
-
142
- * `have_redirected_to` will check that the handler redirected to a give URI. See `Brut::SpecSupport::Matchers::HaveRedirectedTo`.
143
- * `have_generated` will check that the handler generated a specific page or component's HTML. See `<D-f>Brut::SpecSupport::Matchers::HaveGenerated`.
144
- * `have_returned_http_status` will check that the handler returned an HTTP status. See `Brut::SpecSupport::Matchers::HaveReturnedHttpStatus`.
145
- * `have_constraint_violation` will check if a form had a particular constraint violation set on it. See `Brut::SpecSupport::Matchers::HaveConstraintViolation`.
146
-
147
- ## Recommended Practices
148
-
149
- ### You Don't Always Need Resourceful or RESTful Routes
150
-
151
- For any code where the browser is performing a submission, use either `form` or
152
- `action` to declare your route. These will both use an HTTP `POST` to your server and handler. In the example above, we had a `POST` to `/delete_widget/:widget_id`, and not, say, a `DELETE` to it.
153
-
154
- The main reason is that a browser can only submit to a server using `GET` or `POST`, so there's little value in "tunneling" another verb of POST. It doesn't really matter. And, even though you may use Ajax to submit such data, having it degrade to normal browser-based HTTP is a good practice.
155
-
156
- For API-like calls where a browser will never directly interact with the route, and
157
- it would only be via a server-to-server call, RESTful routes makes sense. But they
158
- don't need to be the default.
159
-
160
- ### Avoid Business Logic in Handlers
161
-
162
-
163
- Since handlers bridge the gap between HTTP and your app, their API is naturally simplistic and String-based. The handler should defer to business logic (which can be done by either passing the form object directly, or extracting its data and passing that). Based on the response, the handler will then decide what HTTP response is approriate.
164
-
165
- This means that your handlers will be relatively simple and their tests will as well. It does mean that their tests may require the use of mocks or stubs, but that's fine. Mocks and stubs exist for a reason.
166
-
167
-
168
- ## Technical Notes
169
-
170
- > [!IMPORTANT]
171
- > Technical Notes are for deeper understanding and debugging. While we will try to keep them up-to-date with changes to Brut's
172
- > internals, the source code is always more correct.
173
-
174
- _Last Updated May 5, 2025_
175
-
176
- None at this time.
177
-