brut 0.10.0 → 0.12.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 (403) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -0
  3. data/Gemfile.lock +21 -21
  4. data/assets/YouTubeThumb.pxd +0 -0
  5. data/bin/new-version +3 -3
  6. data/brut-css/package-lock.json +94 -97
  7. data/brut-css/package.json +2 -2
  8. data/brut-js/package-lock.json +3 -3
  9. data/brut-js/package.json +6 -3
  10. data/brut-js/specs/AjaxSubmit.spec.js +62 -6
  11. data/brut-js/src/AjaxSubmit.js +26 -6
  12. data/brutrb.com/forms.md +1 -0
  13. data/brutrb.com/getting-started.md +3 -0
  14. data/brutrb.com/images/tutorial/02-confirmation-dialog-browser-element-styled.png +0 -0
  15. data/brutrb.com/images/tutorial/02-confirmation-dialog-browser-element.png +0 -0
  16. data/brutrb.com/images/tutorial/02-confirmation-dialog-browser.png +0 -0
  17. data/brutrb.com/images/tutorial/02-confirmation-flow.graffle +0 -0
  18. data/brutrb.com/images/tutorial/02-confirmation-flow.png +0 -0
  19. data/brutrb.com/instrumentation.md +142 -3
  20. data/brutrb.com/recipes/authentication.md +1 -0
  21. data/brutrb.com/tutorial.md +29 -1627
  22. data/brutrb.com/tutorials/01-intro.md +1654 -0
  23. data/brutrb.com/tutorials/02-dialog.md +569 -0
  24. data/docs/404.html +2 -2
  25. data/docs/adrs.html +4 -4
  26. data/docs/ai.html +4 -4
  27. data/docs/api/Brut/BackEnd/SeedData.html +1 -1
  28. data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server/FlushSpans.html +1 -1
  29. data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server.html +1 -1
  30. data/docs/api/Brut/BackEnd/Sidekiq/Middlewares.html +1 -1
  31. data/docs/api/Brut/BackEnd/Sidekiq.html +1 -1
  32. data/docs/api/Brut/BackEnd/Validators/FormValidator.html +1 -1
  33. data/docs/api/Brut/BackEnd/Validators.html +1 -1
  34. data/docs/api/Brut/BackEnd.html +1 -1
  35. data/docs/api/Brut/CLI/App.html +1 -1
  36. data/docs/api/Brut/CLI/AppRunner.html +1 -1
  37. data/docs/api/Brut/CLI/Apps/BuildAssets/All.html +1 -1
  38. data/docs/api/Brut/CLI/Apps/BuildAssets/CSS.html +1 -1
  39. data/docs/api/Brut/CLI/Apps/BuildAssets/Images.html +1 -1
  40. data/docs/api/Brut/CLI/Apps/BuildAssets/JS.html +1 -1
  41. data/docs/api/Brut/CLI/Apps/BuildAssets.html +1 -1
  42. data/docs/api/Brut/CLI/Apps/DB/Create.html +1 -1
  43. data/docs/api/Brut/CLI/Apps/DB/Drop.html +1 -1
  44. data/docs/api/Brut/CLI/Apps/DB/Migrate.html +1 -1
  45. data/docs/api/Brut/CLI/Apps/DB/NewMigration.html +1 -1
  46. data/docs/api/Brut/CLI/Apps/DB/Rebuild.html +1 -1
  47. data/docs/api/Brut/CLI/Apps/DB/Seed.html +1 -1
  48. data/docs/api/Brut/CLI/Apps/DB/Status.html +1 -1
  49. data/docs/api/Brut/CLI/Apps/DB.html +1 -1
  50. data/docs/api/Brut/CLI/Apps/DeployBase/GitChecks.html +1 -1
  51. data/docs/api/Brut/CLI/Apps/DeployBase.html +1 -1
  52. data/docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy/Deploy.html +1 -1
  53. data/docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy.html +1 -1
  54. data/docs/api/Brut/CLI/Apps/Scaffold/Action/Route.html +1 -1
  55. data/docs/api/Brut/CLI/Apps/Scaffold/Action.html +1 -1
  56. data/docs/api/Brut/CLI/Apps/Scaffold/Component.html +1 -1
  57. data/docs/api/Brut/CLI/Apps/Scaffold/CustomElementTest.html +1 -1
  58. data/docs/api/Brut/CLI/Apps/Scaffold/DbModel.html +1 -1
  59. data/docs/api/Brut/CLI/Apps/Scaffold/E2ETest.html +1 -1
  60. data/docs/api/Brut/CLI/Apps/Scaffold/Form.html +1 -1
  61. data/docs/api/Brut/CLI/Apps/Scaffold/Page/Route.html +1 -1
  62. data/docs/api/Brut/CLI/Apps/Scaffold/Page.html +1 -1
  63. data/docs/api/Brut/CLI/Apps/Scaffold/RoutesEditor.html +1 -1
  64. data/docs/api/Brut/CLI/Apps/Scaffold/Test.html +1 -1
  65. data/docs/api/Brut/CLI/Apps/Scaffold.html +1 -1
  66. data/docs/api/Brut/CLI/Apps/Test/Audit.html +1 -1
  67. data/docs/api/Brut/CLI/Apps/Test/E2e.html +1 -1
  68. data/docs/api/Brut/CLI/Apps/Test/JS.html +1 -1
  69. data/docs/api/Brut/CLI/Apps/Test/Run.html +1 -1
  70. data/docs/api/Brut/CLI/Apps/Test.html +1 -1
  71. data/docs/api/Brut/CLI/Apps.html +1 -1
  72. data/docs/api/Brut/CLI/Command.html +1 -1
  73. data/docs/api/Brut/CLI/Error.html +1 -1
  74. data/docs/api/Brut/CLI/ExecutionResults/Result.html +1 -1
  75. data/docs/api/Brut/CLI/ExecutionResults.html +1 -1
  76. data/docs/api/Brut/CLI/Executor.html +1 -1
  77. data/docs/api/Brut/CLI/InvalidOption.html +1 -1
  78. data/docs/api/Brut/CLI/Options.html +1 -1
  79. data/docs/api/Brut/CLI/Output.html +1 -1
  80. data/docs/api/Brut/CLI/SystemExecError.html +1 -1
  81. data/docs/api/Brut/CLI.html +1 -1
  82. data/docs/api/Brut/FactoryBot.html +1 -1
  83. data/docs/api/Brut/Framework/App.html +1 -1
  84. data/docs/api/Brut/Framework/Config.html +1 -1
  85. data/docs/api/Brut/Framework/Container.html +1 -1
  86. data/docs/api/Brut/Framework/Error.html +1 -1
  87. data/docs/api/Brut/Framework/Errors/AbstractMethod.html +1 -1
  88. data/docs/api/Brut/Framework/Errors/Bug.html +1 -1
  89. data/docs/api/Brut/Framework/Errors/MissingConfiguration.html +1 -1
  90. data/docs/api/Brut/Framework/Errors/MissingParameter.html +1 -1
  91. data/docs/api/Brut/Framework/Errors/NoClassForPath.html +1 -1
  92. data/docs/api/Brut/Framework/Errors/NotFound.html +1 -1
  93. data/docs/api/Brut/Framework/Errors/NotImplemented.html +1 -1
  94. data/docs/api/Brut/Framework/Errors.html +1 -1
  95. data/docs/api/Brut/Framework/FussyTypeEnforcement.html +2 -2
  96. data/docs/api/Brut/Framework/MCP.html +1 -1
  97. data/docs/api/Brut/Framework/ProjectEnvironment.html +1 -1
  98. data/docs/api/Brut/Framework.html +1 -1
  99. data/docs/api/Brut/FrontEnd/AssetPathResolver.html +1 -1
  100. data/docs/api/Brut/FrontEnd/Component/Helpers.html +1 -1
  101. data/docs/api/Brut/FrontEnd/Component.html +1 -1
  102. data/docs/api/Brut/FrontEnd/Components/ConstraintViolations.html +48 -27
  103. data/docs/api/Brut/FrontEnd/Components/FormTag.html +1 -1
  104. data/docs/api/Brut/FrontEnd/Components/I18nTranslations.html +1 -1
  105. data/docs/api/Brut/FrontEnd/Components/Input.html +2 -2
  106. data/docs/api/Brut/FrontEnd/Components/Inputs/ButtonTag.html +443 -0
  107. data/docs/api/Brut/FrontEnd/Components/Inputs/CsrfToken.html +1 -1
  108. data/docs/api/Brut/FrontEnd/Components/Inputs/InputTag.html +14 -9
  109. data/docs/api/Brut/FrontEnd/Components/Inputs/RadioButton.html +1 -1
  110. data/docs/api/Brut/FrontEnd/Components/Inputs/SelectTagWithOptions.html +8 -9
  111. data/docs/api/Brut/FrontEnd/Components/Inputs/TextareaTag.html +10 -11
  112. data/docs/api/Brut/FrontEnd/Components/Inputs.html +2 -2
  113. data/docs/api/Brut/FrontEnd/Components/LocaleDetection.html +1 -1
  114. data/docs/api/Brut/FrontEnd/Components/PageIdentifier.html +1 -1
  115. data/docs/api/Brut/FrontEnd/Components/TimeTag.html +1 -1
  116. data/docs/api/Brut/FrontEnd/Components/Traceparent.html +1 -1
  117. data/docs/api/Brut/FrontEnd/Components.html +1 -1
  118. data/docs/api/Brut/FrontEnd/CsrfProtector.html +1 -1
  119. data/docs/api/Brut/FrontEnd/Download.html +1 -1
  120. data/docs/api/Brut/FrontEnd/Flash.html +1 -1
  121. data/docs/api/Brut/FrontEnd/Form.html +39 -39
  122. data/docs/api/Brut/FrontEnd/Forms/Button.html +331 -0
  123. data/docs/api/Brut/FrontEnd/Forms/ButtonInputDefinition.html +544 -0
  124. data/docs/api/Brut/FrontEnd/Forms/ConstraintViolation.html +1 -1
  125. data/docs/api/Brut/FrontEnd/Forms/Input/Color.html +1 -1
  126. data/docs/api/Brut/FrontEnd/Forms/Input/TimeOfDay.html +1 -1
  127. data/docs/api/Brut/FrontEnd/Forms/Input.html +6 -2
  128. data/docs/api/Brut/FrontEnd/Forms/InputDeclarations.html +111 -23
  129. data/docs/api/Brut/FrontEnd/Forms/InputDefinition.html +20 -12
  130. data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInput.html +1 -1
  131. data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInputDefinition.html +1 -1
  132. data/docs/api/Brut/FrontEnd/Forms/SelectInput.html +1 -1
  133. data/docs/api/Brut/FrontEnd/Forms/SelectInputDefinition.html +1 -1
  134. data/docs/api/Brut/FrontEnd/Forms/ValidityState.html +1 -1
  135. data/docs/api/Brut/FrontEnd/Forms.html +2 -2
  136. data/docs/api/Brut/FrontEnd/GenericResponse.html +1 -1
  137. data/docs/api/Brut/FrontEnd/Handler.html +1 -1
  138. data/docs/api/Brut/FrontEnd/Handlers/CspReportingHandler.html +1 -1
  139. data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler/TraceParent.html +1 -1
  140. data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler.html +1 -1
  141. data/docs/api/Brut/FrontEnd/Handlers/LocaleDetectionHandler.html +1 -1
  142. data/docs/api/Brut/FrontEnd/Handlers/MissingHandler/Form.html +2 -2
  143. data/docs/api/Brut/FrontEnd/Handlers/MissingHandler.html +1 -1
  144. data/docs/api/Brut/FrontEnd/Handlers.html +1 -1
  145. data/docs/api/Brut/FrontEnd/HandlingResults.html +1 -1
  146. data/docs/api/Brut/FrontEnd/HttpMethod.html +1 -1
  147. data/docs/api/Brut/FrontEnd/HttpStatus.html +1 -1
  148. data/docs/api/Brut/FrontEnd/InlineSvgLocator.html +1 -1
  149. data/docs/api/Brut/FrontEnd/Layout.html +1 -1
  150. data/docs/api/Brut/FrontEnd/Middleware.html +1 -1
  151. data/docs/api/Brut/FrontEnd/Middlewares/AnnotateBrutOwnedPaths.html +1 -1
  152. data/docs/api/Brut/FrontEnd/Middlewares/Favicon.html +1 -1
  153. data/docs/api/Brut/FrontEnd/Middlewares/OpenTelemetrySpan.html +1 -1
  154. data/docs/api/Brut/FrontEnd/Middlewares/ReloadApp.html +1 -1
  155. data/docs/api/Brut/FrontEnd/Middlewares.html +1 -1
  156. data/docs/api/Brut/FrontEnd/Page.html +1 -1
  157. data/docs/api/Brut/FrontEnd/Pages/MissingPage.html +1 -1
  158. data/docs/api/Brut/FrontEnd/Pages.html +1 -1
  159. data/docs/api/Brut/FrontEnd/RequestContext.html +1 -1
  160. data/docs/api/Brut/FrontEnd/RouteHook.html +1 -1
  161. data/docs/api/Brut/FrontEnd/RouteHooks/AgeFlash.html +1 -1
  162. data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineScripts.html +1 -1
  163. data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts/ReportOnly.html +1 -1
  164. data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts.html +1 -1
  165. data/docs/api/Brut/FrontEnd/RouteHooks/LocaleDetection.html +1 -1
  166. data/docs/api/Brut/FrontEnd/RouteHooks/SetupRequestContext.html +1 -1
  167. data/docs/api/Brut/FrontEnd/RouteHooks.html +1 -1
  168. data/docs/api/Brut/FrontEnd/Routing/FormHandlerRoute.html +1 -1
  169. data/docs/api/Brut/FrontEnd/Routing/FormRoute.html +1 -1
  170. data/docs/api/Brut/FrontEnd/Routing/MissingForm.html +1 -1
  171. data/docs/api/Brut/FrontEnd/Routing/MissingHandler.html +1 -1
  172. data/docs/api/Brut/FrontEnd/Routing/MissingPage.html +1 -1
  173. data/docs/api/Brut/FrontEnd/Routing/MissingPath.html +1 -1
  174. data/docs/api/Brut/FrontEnd/Routing/PageRoute.html +1 -1
  175. data/docs/api/Brut/FrontEnd/Routing/Route.html +1 -1
  176. data/docs/api/Brut/FrontEnd/Routing.html +1 -1
  177. data/docs/api/Brut/FrontEnd/Session.html +1 -1
  178. data/docs/api/Brut/FrontEnd.html +1 -1
  179. data/docs/api/Brut/I18n/BaseMethods.html +1 -1
  180. data/docs/api/Brut/I18n/ForBackEnd.html +1 -1
  181. data/docs/api/Brut/I18n/ForCLI.html +1 -1
  182. data/docs/api/Brut/I18n/ForHTML.html +1 -1
  183. data/docs/api/Brut/I18n/HTTPAcceptLanguage/AlwaysEnglish.html +1 -1
  184. data/docs/api/Brut/I18n/HTTPAcceptLanguage.html +1 -1
  185. data/docs/api/Brut/I18n.html +1 -1
  186. data/docs/api/Brut/Instrumentation/LoggerSpanExporter.html +1 -1
  187. data/docs/api/Brut/Instrumentation/Methods/ClassMethods.html +596 -0
  188. data/docs/api/Brut/Instrumentation/Methods.html +173 -0
  189. data/docs/api/Brut/Instrumentation/OpenTelemetry/NormalizedAttributes.html +7 -7
  190. data/docs/api/Brut/Instrumentation/OpenTelemetry/Span.html +7 -7
  191. data/docs/api/Brut/Instrumentation/OpenTelemetry.html +19 -17
  192. data/docs/api/Brut/Instrumentation.html +3 -1
  193. data/docs/api/Brut/RubocopConfig.html +1 -1
  194. data/docs/api/Brut/SinatraHelpers/ClassMethods.html +1 -1
  195. data/docs/api/Brut/SinatraHelpers.html +1 -1
  196. data/docs/api/Brut/SpecSupport/ClockSupport.html +1 -1
  197. data/docs/api/Brut/SpecSupport/ComponentSupport.html +1 -1
  198. data/docs/api/Brut/SpecSupport/E2ETestServer.html +1 -1
  199. data/docs/api/Brut/SpecSupport/E2eSupport.html +1 -1
  200. data/docs/api/Brut/SpecSupport/EnhancedNode.html +1 -1
  201. data/docs/api/Brut/SpecSupport/FlashSupport.html +1 -1
  202. data/docs/api/Brut/SpecSupport/GeneralSupport/ClassMethods.html +1 -1
  203. data/docs/api/Brut/SpecSupport/GeneralSupport.html +1 -1
  204. data/docs/api/Brut/SpecSupport/HandlerSupport.html +1 -1
  205. data/docs/api/Brut/SpecSupport/Matchers/BeABug.html +1 -1
  206. data/docs/api/Brut/SpecSupport/Matchers/BePageFor.html +1 -1
  207. data/docs/api/Brut/SpecSupport/Matchers/BeRoutingFor.html +1 -1
  208. data/docs/api/Brut/SpecSupport/Matchers/HaveConstraintViolation.html +1 -1
  209. data/docs/api/Brut/SpecSupport/Matchers/HaveGenerated.html +1 -1
  210. data/docs/api/Brut/SpecSupport/Matchers/HaveHTMLAttribute.html +1 -1
  211. data/docs/api/Brut/SpecSupport/Matchers/HaveI18nString.html +1 -1
  212. data/docs/api/Brut/SpecSupport/Matchers/HaveLinkTo.html +1 -1
  213. data/docs/api/Brut/SpecSupport/Matchers/HaveRedirectedTo.html +1 -1
  214. data/docs/api/Brut/SpecSupport/Matchers/HaveReturnedHttpStatus.html +1 -1
  215. data/docs/api/Brut/SpecSupport/Matchers/HaveReturnedRackResponse.html +1 -1
  216. data/docs/api/Brut/SpecSupport/Matchers.html +1 -1
  217. data/docs/api/Brut/SpecSupport/RSpecSetup/OptionalSidekiqSupport.html +1 -1
  218. data/docs/api/Brut/SpecSupport/RSpecSetup.html +1 -1
  219. data/docs/api/Brut/SpecSupport/SessionSupport.html +1 -1
  220. data/docs/api/Brut/SpecSupport.html +1 -1
  221. data/docs/api/Brut.html +1 -1
  222. data/docs/api/Clock.html +1 -1
  223. data/docs/api/ModuleName.html +1 -1
  224. data/docs/api/RichString.html +1 -1
  225. data/docs/api/SemanticLogger/Appender/Async.html +1 -1
  226. data/docs/api/Sequel/Extensions/BrutInstrumentation.html +1 -1
  227. data/docs/api/Sequel/Extensions/BrutMigrations.html +1 -1
  228. data/docs/api/Sequel/Extensions.html +1 -1
  229. data/docs/api/Sequel/Plugins/CreatedAt/InstanceMethods.html +1 -1
  230. data/docs/api/Sequel/Plugins/CreatedAt.html +1 -1
  231. data/docs/api/Sequel/Plugins/ExternalId/ClassMethods.html +1 -1
  232. data/docs/api/Sequel/Plugins/ExternalId/InstanceMethods.html +1 -1
  233. data/docs/api/Sequel/Plugins/ExternalId.html +1 -1
  234. data/docs/api/Sequel/Plugins/FindBang/ClassMethods.html +1 -1
  235. data/docs/api/Sequel/Plugins/FindBang.html +1 -1
  236. data/docs/api/Sequel/Plugins.html +1 -1
  237. data/docs/api/Sequel.html +1 -1
  238. data/docs/api/_index.html +36 -1
  239. data/docs/api/class_list.html +1 -1
  240. data/docs/api/file.README.html +1 -1
  241. data/docs/api/index.html +1 -1
  242. data/docs/api/method_list.html +364 -252
  243. data/docs/api/top-level-namespace.html +1 -1
  244. data/docs/assets/02-confirmation-dialog-browser-element-styled.3NEGM20-.png +0 -0
  245. data/docs/assets/02-confirmation-dialog-browser-element.DPsf0xUW.png +0 -0
  246. data/docs/assets/02-confirmation-dialog-browser.DH8ALFO4.png +0 -0
  247. data/docs/assets/02-confirmation-flow.D9gZ0S5U.png +0 -0
  248. data/docs/assets/{app.vjGWMSnJ.js → app.V2GOcOrg.js} +1 -1
  249. data/docs/assets/chunks/@localSearchIndexroot.3Lsq4QTb.js +1 -0
  250. data/docs/assets/chunks/{VPLocalSearchBox.C-ymMW2k.js → VPLocalSearchBox.CZTadcAy.js} +1 -1
  251. data/docs/assets/chunks/{theme.pJUosGlI.js → theme.FeuYNxyp.js} +2 -2
  252. data/docs/assets/{components.md.B543a3Lm.js → components.md.f4cdTyvV.js} +3 -3
  253. data/docs/assets/{configuration.md.-foE_iVv.js → configuration.md.Bs4-rxnS.js} +1 -1
  254. data/docs/assets/{form-constraints.md.DK5adCgM.js → form-constraints.md.KTv5cdR4.js} +6 -6
  255. data/docs/assets/{forms.md.D5-2rgHh.js → forms.md.Sys-XxVf.js} +3 -3
  256. data/docs/assets/{forms.md.D5-2rgHh.lean.js → forms.md.Sys-XxVf.lean.js} +1 -1
  257. data/docs/assets/{getting-started.md.Cd4XSZb_.js → getting-started.md.CFIW0bcE.js} +6 -3
  258. data/docs/assets/{getting-started.md.Cd4XSZb_.lean.js → getting-started.md.CFIW0bcE.lean.js} +1 -1
  259. data/docs/assets/instrumentation.md._lNSriEZ.js +90 -0
  260. data/docs/assets/instrumentation.md._lNSriEZ.lean.js +1 -0
  261. data/docs/assets/{recipes_authentication.md.Dzvi_g69.js → recipes_authentication.md.BAISoxmN.js} +1 -0
  262. data/docs/assets/recipes_form-errors.md.Bv5RCKqH.js +66 -0
  263. data/docs/assets/recipes_form-errors.md.Bv5RCKqH.lean.js +1 -0
  264. data/docs/assets/tutorial.md.BM40jnoq.js +27 -0
  265. data/docs/assets/tutorial.md.BM40jnoq.lean.js +1 -0
  266. data/docs/assets/{tutorial.md.C4zR5XPG.js → tutorials_01-intro.md.B4sUBY3X.js} +13 -33
  267. data/docs/assets/tutorials_01-intro.md.B4sUBY3X.lean.js +1 -0
  268. data/docs/assets/tutorials_02-dialog.md.QTFeHdiA.js +274 -0
  269. data/docs/assets/tutorials_02-dialog.md.QTFeHdiA.lean.js +1 -0
  270. data/docs/assets.html +4 -4
  271. data/docs/brut-js/api/AjaxSubmit.html +16 -6
  272. data/docs/brut-js/api/AjaxSubmit.js.html +27 -7
  273. data/docs/brut-js/api/Autosubmit.html +1 -1
  274. data/docs/brut-js/api/Autosubmit.js.html +1 -1
  275. data/docs/brut-js/api/BaseCustomElement.html +1 -1
  276. data/docs/brut-js/api/BaseCustomElement.js.html +1 -1
  277. data/docs/brut-js/api/BrutCustomElements.html +1 -1
  278. data/docs/brut-js/api/BufferedLogger.html +1 -1
  279. data/docs/brut-js/api/ConfirmSubmit.html +1 -1
  280. data/docs/brut-js/api/ConfirmSubmit.js.html +1 -1
  281. data/docs/brut-js/api/ConfirmationDialog.html +1 -1
  282. data/docs/brut-js/api/ConfirmationDialog.js.html +1 -1
  283. data/docs/brut-js/api/ConstraintViolationMessage.html +55 -5
  284. data/docs/brut-js/api/ConstraintViolationMessage.js.html +18 -3
  285. data/docs/brut-js/api/ConstraintViolationMessages.html +1 -1
  286. data/docs/brut-js/api/ConstraintViolationMessages.js.html +1 -1
  287. data/docs/brut-js/api/CopyToClipboard.html +1 -1
  288. data/docs/brut-js/api/CopyToClipboard.js.html +1 -1
  289. data/docs/brut-js/api/Form.html +7 -10
  290. data/docs/brut-js/api/Form.js.html +20 -24
  291. data/docs/brut-js/api/I18nTranslation.html +1 -1
  292. data/docs/brut-js/api/I18nTranslation.js.html +1 -1
  293. data/docs/brut-js/api/LocaleDetection.html +1 -1
  294. data/docs/brut-js/api/LocaleDetection.js.html +1 -1
  295. data/docs/brut-js/api/Logger.html +1 -1
  296. data/docs/brut-js/api/Logger.js.html +1 -1
  297. data/docs/brut-js/api/Message.html +1 -1
  298. data/docs/brut-js/api/Message.js.html +1 -1
  299. data/docs/brut-js/api/PrefixedLogger.html +1 -1
  300. data/docs/brut-js/api/RichString.html +1 -1
  301. data/docs/brut-js/api/RichString.js.html +1 -1
  302. data/docs/brut-js/api/Tabs.html +1 -1
  303. data/docs/brut-js/api/Tabs.js.html +1 -1
  304. data/docs/brut-js/api/Tracing.html +1 -1
  305. data/docs/brut-js/api/Tracing.js.html +1 -1
  306. data/docs/brut-js/api/external-CustomElementRegistry.html +1 -1
  307. data/docs/brut-js/api/external-Performance.html +1 -1
  308. data/docs/brut-js/api/external-Promise.html +1 -1
  309. data/docs/brut-js/api/external-ValidityState.html +1 -1
  310. data/docs/brut-js/api/external-Window.html +1 -1
  311. data/docs/brut-js/api/external-fetch.html +1 -1
  312. data/docs/brut-js/api/global.html +1 -1
  313. data/docs/brut-js/api/index.html +1 -1
  314. data/docs/brut-js/api/index.js.html +1 -1
  315. data/docs/brut-js/api/module-testing.html +1 -1
  316. data/docs/brut-js/api/testing.AssetMetadata.html +1 -1
  317. data/docs/brut-js/api/testing.AssetMetadataLoader.html +1 -1
  318. data/docs/brut-js/api/testing.CustomElementTest.html +1 -1
  319. data/docs/brut-js/api/testing.DOMCreator.html +1 -1
  320. data/docs/brut-js/api/testing_AssetMetadata.js.html +1 -1
  321. data/docs/brut-js/api/testing_AssetMetadataLoader.js.html +1 -1
  322. data/docs/brut-js/api/testing_CustomElementTest.js.html +1 -1
  323. data/docs/brut-js/api/testing_DOMCreator.js.html +1 -1
  324. data/docs/brut-js/api/testing_index.js.html +1 -1
  325. data/docs/brut-js.html +4 -4
  326. data/docs/business-logic.html +4 -4
  327. data/docs/cli.html +4 -4
  328. data/docs/components.html +8 -8
  329. data/docs/configuration.html +5 -5
  330. data/docs/css.html +4 -4
  331. data/docs/custom-element-tests.html +4 -4
  332. data/docs/database-access.html +4 -4
  333. data/docs/database-schema.html +4 -4
  334. data/docs/deployment.html +4 -4
  335. data/docs/dev-environment.html +4 -4
  336. data/docs/dir-structure.html +4 -4
  337. data/docs/doc-conventions.html +4 -4
  338. data/docs/end-to-end-tests.html +4 -4
  339. data/docs/features.html +4 -4
  340. data/docs/flash-and-session.html +4 -4
  341. data/docs/form-constraints.html +11 -11
  342. data/docs/forms.html +7 -7
  343. data/docs/getting-started.html +10 -7
  344. data/docs/handlers.html +4 -4
  345. data/docs/hashmap.json +1 -1
  346. data/docs/hooks.html +4 -4
  347. data/docs/i18n.html +4 -4
  348. data/docs/index.html +3 -3
  349. data/docs/instrumentation.html +61 -6
  350. data/docs/javascript.html +4 -4
  351. data/docs/jobs.html +4 -4
  352. data/docs/keyword-injection.html +4 -4
  353. data/docs/layouts.html +4 -4
  354. data/docs/lsp.html +4 -4
  355. data/docs/markdown-examples.html +4 -4
  356. data/docs/middleware.html +4 -4
  357. data/docs/overview.html +4 -4
  358. data/docs/pages.html +4 -4
  359. data/docs/recipes/alternate-layouts.html +4 -4
  360. data/docs/recipes/authentication.html +7 -6
  361. data/docs/recipes/blank-layouts.html +4 -4
  362. data/docs/recipes/custom-flash.html +4 -4
  363. data/docs/recipes/form-errors.html +94 -0
  364. data/docs/recipes/indexed-forms.html +4 -4
  365. data/docs/recipes/migrations.html +5 -5
  366. data/docs/recipes/text-field-component.html +4 -4
  367. data/docs/roadmap.html +4 -4
  368. data/docs/routes.html +4 -4
  369. data/docs/security.html +4 -4
  370. data/docs/seed-data.html +4 -4
  371. data/docs/space-time-continuum.html +4 -4
  372. data/docs/tutorial.html +12 -713
  373. data/docs/tutorials/01-intro.html +736 -0
  374. data/docs/tutorials/02-dialog.html +302 -0
  375. data/docs/unit-tests.html +4 -4
  376. data/docs/why.html +4 -4
  377. data/lib/brut/front_end/components/input.rb +1 -0
  378. data/lib/brut/front_end/components/inputs/button_tag.rb +40 -0
  379. data/lib/brut/front_end/components/inputs/input_tag.rb +3 -1
  380. data/lib/brut/front_end/components/inputs/select_tag_with_options.rb +0 -1
  381. data/lib/brut/front_end/components/inputs/textarea_tag.rb +0 -1
  382. data/lib/brut/front_end/form.rb +7 -5
  383. data/lib/brut/front_end/forms/button.rb +21 -0
  384. data/lib/brut/front_end/forms/button_input_definition.rb +37 -0
  385. data/lib/brut/front_end/forms/input_declarations.rb +10 -0
  386. data/lib/brut/front_end/forms/input_definition.rb +7 -2
  387. data/lib/brut/instrumentation/methods.rb +153 -0
  388. data/lib/brut/instrumentation/open_telemetry.rb +1 -0
  389. data/lib/brut/instrumentation.rb +1 -0
  390. data/lib/brut/version.rb +1 -1
  391. data/mkbrut/Gemfile.lock +1 -1
  392. data/mkbrut/bin/publish +1 -1
  393. data/mkbrut/lib/mkbrut/version.rb +1 -1
  394. data/specs/brut/instrumentation/methods.spec.rb +399 -0
  395. metadata +51 -21
  396. data/docs/assets/chunks/@localSearchIndexroot.Dn1xGMv_.js +0 -1
  397. data/docs/assets/instrumentation.md.BgcaGVYH.js +0 -35
  398. data/docs/assets/instrumentation.md.BgcaGVYH.lean.js +0 -1
  399. data/docs/assets/tutorial.md.C4zR5XPG.lean.js +0 -1
  400. /data/docs/assets/{components.md.B543a3Lm.lean.js → components.md.f4cdTyvV.lean.js} +0 -0
  401. /data/docs/assets/{configuration.md.-foE_iVv.lean.js → configuration.md.Bs4-rxnS.lean.js} +0 -0
  402. /data/docs/assets/{form-constraints.md.DK5adCgM.lean.js → form-constraints.md.KTv5cdR4.lean.js} +0 -0
  403. /data/docs/assets/{recipes_authentication.md.Dzvi_g69.lean.js → recipes_authentication.md.BAISoxmN.lean.js} +0 -0
@@ -0,0 +1,40 @@
1
+ # Creates a button tag to be used inside a form. This is only
2
+ # needed if your form declared a `button` and you wish the value
3
+ # to be included whern the form is submitted (for example, if you have
4
+ # more than one submit button and wish to know which one was clicked on the
5
+ # back end).
6
+ class Brut::FrontEnd::Components::Inputs::ButtonTag < Brut::FrontEnd::Components::Input
7
+
8
+ # Creates the appropriate button for the given {Brut::FrontEnd::Form} and input name.
9
+ #
10
+ # @param [Brut::FrontEnd::Form} form The form that is being rendered. This method will consult this class to understand the requirements on this input so its HTML is generated correctly.
11
+ # @param [String] input_name the name of the input, which should be a member of `form`
12
+ # @param [Integer] index if this input is part of an array, this is the index into that array. This is used to get the input's value.
13
+ # @param [Hash] html_attributes any additional HTML attributes to include on the `<input>` element. Note
14
+ # that if you set `type` here to be `reset` or `button`, this button will not submit
15
+ # the form (as per the HTML spec). Also note that the various
16
+ # `form*` attributes *will* take effect and work as desired.
17
+ def initialize(form:, input_name:, index: nil, **html_attributes)
18
+ input = form.input(input_name, index:)
19
+ if input.class.name != "Brut::FrontEnd::Forms::Button"
20
+ raise ArgumentError, "#{self.class} can only be used with `button` elements, not #{input.class.name} form elements"
21
+ end
22
+ default_html_attributes = {}
23
+ html_attributes = html_attributes.map { |key,value| [ key.to_sym, value ] }.to_h
24
+
25
+ default_html_attributes[:name] = if input.array?
26
+ "#{input.name}[]"
27
+ else
28
+ input.name
29
+ end
30
+ default_html_attributes[:value] = input.value
31
+
32
+ @attributes = default_html_attributes.merge(html_attributes)
33
+ end
34
+
35
+ def view_template
36
+ button(**@attributes) do
37
+ yield
38
+ end
39
+ end
40
+ end
@@ -3,7 +3,6 @@ class Brut::FrontEnd::Components::Inputs::InputTag < Brut::FrontEnd::Components:
3
3
  def invalid? = @attributes["data-invalid"] == true
4
4
 
5
5
  # Creates the appropriate input for the given {Brut::FrontEnd::Form} and input name.
6
- # Generally, you want to use this method over the initializer.
7
6
  #
8
7
  # @param [Brut::FrontEnd::Form} form The form that is being rendered. This method will consult this class to understand the requirements on this input so its HTML is generated correctly.
9
8
  # @param [String] input_name the name of the input, which should be a member of `form`
@@ -11,6 +10,9 @@ class Brut::FrontEnd::Components::Inputs::InputTag < Brut::FrontEnd::Components:
11
10
  # @param [Hash] html_attributes any additional HTML attributes to include on the `<input>` element.
12
11
  def initialize(form:, input_name:, index: nil, **html_attributes)
13
12
  input = form.input(input_name, index:)
13
+ if input.class.name != "Brut::FrontEnd::Forms::Input"
14
+ raise ArgumentError, "#{self.class} can only be used with `input` elements, not #{input.class.name} form elements"
15
+ end
14
16
  default_html_attributes = {}
15
17
  html_attributes = html_attributes.map { |key,value| [ key.to_sym, value ] }.to_h
16
18
 
@@ -1,7 +1,6 @@
1
1
  # Renders an HTML `<select>`.
2
2
  class Brut::FrontEnd::Components::Inputs::SelectTagWithOptions < Brut::FrontEnd::Components::Input
3
3
  # Creates the appropriate select input for the given {Brut::FrontEnd::Form} and input name.
4
- # Generally, you want to use this method over the initializer.
5
4
  #
6
5
  # @param [Brut::FrontEnd::Form} form The form that is being rendered.
7
6
  # This method will consult this class to understand the requirements
@@ -2,7 +2,6 @@
2
2
  class Brut::FrontEnd::Components::Inputs::TextareaTag < Brut::FrontEnd::Components::Input
3
3
 
4
4
  # Creates the appropriate textarea for the given {Brut::FrontEnd::Form} and input name.
5
- # Generally, you want to use this method over the initializer.
6
5
  #
7
6
  # @param [Brut::FrontEnd::Form} form The form that is being rendered. This method will consult this class to understand the requirements on this textarea so its HTML is generated correctly.
8
7
  # @param [String] input_name the name of the input, which should be a member of `form`
@@ -5,10 +5,12 @@ module Brut::FrontEnd::Forms
5
5
  autoload(:InputDeclarations, "brut/front_end/forms/input_declarations")
6
6
  autoload(:InputDefinition, "brut/front_end/forms/input_definition")
7
7
  autoload(:SelectInputDefinition, "brut/front_end/forms/select_input_definition")
8
+ autoload(:ButtonInputDefinition, "brut/front_end/forms/button_input_definition")
8
9
  autoload(:RadioButtonGroupInputDefinition, "brut/front_end/forms/radio_button_group_input_definition")
9
10
  autoload(:ConstraintViolation, "brut/front_end/forms/constraint_violation")
10
11
  autoload(:ValidityState, "brut/front_end/forms/validity_state")
11
12
  autoload(:Input, "brut/front_end/forms/input")
13
+ autoload(:Button, "brut/front_end/forms/button")
12
14
  autoload(:SelectInput, "brut/front_end/forms/select_input")
13
15
  autoload(:RadioButtonGroupInput, "brut/front_end/forms/radio_button_group_input")
14
16
  end
@@ -38,11 +40,11 @@ class Brut::FrontEnd::Form
38
40
  Brut.container.instrumentation.add_attributes(prefix: :brut, ignored_unknown_params: unknown_params.join(","))
39
41
  end
40
42
  @params = params.except(*unknown_params).map { |name,value|
41
- input_definition = begin
42
- self.class.input_definitions[name] || self.class.input_definitions.fetch(name.to_s)
43
- rescue KeyError
44
- raise "cannot find input definition for '#{name}'. Have these: #{self.class.input_definitions.keys.inspect}"
45
- end
43
+ input_definition = begin
44
+ self.class.input_definitions[name] || self.class.input_definitions.fetch(name.to_s)
45
+ rescue KeyError
46
+ raise "cannot find input definition for '#{name}'. Have these: #{self.class.input_definitions.keys.inspect}"
47
+ end
46
48
  if value.kind_of?(Array)
47
49
  input_definition = begin
48
50
  self.class.input_definitions[name] || self.class.input_definitions.fetch(name.to_s)
@@ -0,0 +1,21 @@
1
+ # Represents the current state of a particular button that is part of a form.
2
+ # Button's in this context don't really have state, but this allows the button to be
3
+ # modeled like any other form element.
4
+ class Brut::FrontEnd::Forms::Button < Brut::FrontEnd::Forms::Input
5
+ # Create the input with the given definition and value
6
+ # @param [Brut::FrontEnd::Forms::InputDefinition] input_definition
7
+ # @param [String] value Value of the button, which would be submitted with the form. Note
8
+ # that {Brut::FrontEnd::Forms::ButtonInputDefinition#make_input} will
9
+ # default this value to `"true"`.
10
+ def initialize(input_definition:, value:, index:)
11
+ @input_definition = input_definition
12
+ @validity_state = Brut::FrontEnd::Forms::ValidityState.new
13
+ @index = index
14
+ self.value=(value)
15
+ end
16
+
17
+ def value=(new_value)
18
+ @value = new_value.to_s
19
+ @typed_value = @value
20
+ end
21
+ end
@@ -0,0 +1,37 @@
1
+ # Defines a button to be used to submit a form (as opposed to an `<input type="submit">`).
2
+ # This is needed when the name/value of the button should be submitted witih the form.
3
+ class Brut::FrontEnd::Forms::ButtonInputDefinition
4
+ include Brut::Framework::FussyTypeEnforcement
5
+
6
+ attr_reader :name
7
+
8
+ # Create a ButtonInputDefinition.
9
+ #
10
+ # @param [String] name Name of the button (required)
11
+ # @param [true|false] array If true, the form will expect multiple values for this input. The values will be available as an array. Any values omitted by the user will be present as empty strings.
12
+ #
13
+ # @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button BUTTON Element
14
+ def initialize(
15
+ name:,
16
+ array: false
17
+ )
18
+ name = name.to_s
19
+ @name = type!(name, String, "name", required: true)
20
+ @array = type!(array, [true, false], "array", required: true)
21
+ end
22
+
23
+ def array? = @array
24
+
25
+
26
+ # Create an Input based on this definition, initializing it with the given value.
27
+ # @param [String] value the value to give this input initially. If this is blank,
28
+ # the button's value will be `"true"`.
29
+ # @param [Integer] index the index of this input, if it is part of an array of
30
+ # inputs. `nil` is allowed only if the input definition is not for an array.
31
+ def make_input(value:, index:)
32
+ if value.to_s.strip == ""
33
+ value = "true"
34
+ end
35
+ Brut::FrontEnd::Forms::Button.new(input_definition: self, value:, index:)
36
+ end
37
+ end
@@ -11,6 +11,16 @@ module Brut::FrontEnd::Forms::InputDeclarations
11
11
  )
12
12
  end
13
13
 
14
+ # Declares a named button for this form, which is required in order to have this button's name and
15
+ # value sent to the back. This will generate a `<button>` tag. To use `<input type="submit">`, {.input} should
16
+ # be used instead.
17
+ # @param [String] name The name of the button (used in the `name` attribute)
18
+ def button(name)
19
+ self.add_input_definition(
20
+ Brut::FrontEnd::Forms::ButtonInputDefinition.new(name:)
21
+ )
22
+ end
23
+
14
24
  # Declares a select for this form, to be modeled via an HTML `<SELECT>` tag. Note that this will not define the values that appear
15
25
  # in the select. That is done when the select is rendered, which you might do with a
16
26
  # {Brut::FrontEnd::Components::Inputs::Select}
@@ -32,6 +32,7 @@ class Brut::FrontEnd::Forms::InputDefinition
32
32
  "radio" => String,
33
33
  "range" => String,
34
34
  "search" => String,
35
+ "submit" => String,
35
36
  "tel" => String,
36
37
  "text" => String,
37
38
  "time" => Time, # XXX
@@ -49,7 +50,7 @@ class Brut::FrontEnd::Forms::InputDefinition
49
50
  # @param [Integer] maxlength Maximum length of the value allowed.
50
51
  # @param [String] name Name of the input (required)
51
52
  # @param [Regexp] pattern that the value must match. Note that this technically must be a regular expression that works for both Ruby and JavaScript, so don't get fancy.
52
- # @param [true|false] required true if this field is required, false otherwise. Default is `true` unless `type` is `"checkbox"`.
53
+ # @param [true|false] required true if this field is required, false otherwise. Default is `true` unless `type` is `"checkbox"` or `"submit"`.
53
54
  # @param [Integer] step Step value for ranged inputs. A value that is not on a step is considered invalid.
54
55
  # @param [String] type the type of input to create. Should be a value from the HTML spec. Default is based on the value of `name`. If `email`, `type` is `email`. If `password` or `password_confirmation`, type is `password`. Otherwise `text`.
55
56
  # @param [true|false] array If true, the form will expect multiple values for this input. The values will be available as an array. Any values omitted by the user will be present as empty strings.
@@ -84,7 +85,11 @@ class Brut::FrontEnd::Forms::InputDefinition
84
85
 
85
86
  type = type.to_s
86
87
  if required == :based_on_type
87
- required = type != "checkbox"
88
+ required = case type
89
+ when "checkbox" then false
90
+ when "submit" then false
91
+ else true
92
+ end
88
93
  end
89
94
 
90
95
  @max = max
@@ -0,0 +1,153 @@
1
+ require "set"
2
+ require "opentelemetry-sdk"
3
+
4
+ # Allows instrumentation of methods via a class method. While Pages, Handlers, and Components are generally
5
+ # instrumented, this module can be used for your back-end classes (or private methods of pages, handlers, or
6
+ # component).
7
+ #
8
+ # @example Instrument specific methods
9
+ # class Widget
10
+ # include Brut::Instrumentation::Methods
11
+ #
12
+ # def save
13
+ # # ...
14
+ # end
15
+ #
16
+ # def search
17
+ # # ...
18
+ # end
19
+ #
20
+ # instrument :save # search is not instrumented
21
+ # end
22
+ #
23
+ # @example Instrument all methods
24
+ # class Widget
25
+ # include Brut::Instrumentation::Methods
26
+ #
27
+ # instrument_all!
28
+ #
29
+ # def save
30
+ # # ...
31
+ # end
32
+ #
33
+ # def search
34
+ # # ...
35
+ # end
36
+ #
37
+ # private
38
+ #
39
+ # def delete_orphans
40
+ # end
41
+ # end
42
+ module Brut::Instrumentation::Methods
43
+
44
+ # @!visibility private
45
+ def self.included(base)
46
+ base.extend(ClassMethods)
47
+ end
48
+
49
+ module ClassMethods
50
+
51
+ def __module_for_instrumented_methods
52
+ @__module_for_instrumented_methods ||= begin
53
+ mod = Module.new
54
+ prepend mod
55
+ mod
56
+ end
57
+ end
58
+
59
+ # Instrument methods that have already been defined.
60
+ #
61
+ # @param method_names [Array<Symbol>] the method names to instrument. They must
62
+ # exist and they must not already have been instrumented.
63
+ # @raise [ArgumentError] if any method does not exist or has already been instrumented
64
+ def instrument(*method_names)
65
+
66
+ method_names.each do |method_name|
67
+ if __module_for_instrumented_methods.method_defined?(method_name)
68
+ raise ArgumentError, "Method #{method_name} is already instrumented in #{self}"
69
+ end
70
+
71
+ method_defined = method_defined?(method_name) ||
72
+ private_method_defined?(method_name) ||
73
+ protected_method_defined?(method_name)
74
+
75
+ if !method_defined
76
+ raise ArgumentError, "Method #{method_name} is not defined in #{self.name}"
77
+ end
78
+
79
+ visibility = if private_method_defined?(method_name)
80
+ :private
81
+ elsif protected_method_defined?(method_name)
82
+ :protected
83
+ else
84
+ :public
85
+ end
86
+
87
+ __module_for_instrumented_methods.module_eval do
88
+ define_method(method_name) do |*args, **kwargs, &blk|
89
+ span_name = "#{self.class.name}##{method_name}"
90
+ span_attrs = {
91
+ "brut.class" => self.class.name,
92
+ "brut.method" => method_name.to_s,
93
+ }
94
+
95
+ Brut.container.instrumentation.span(span_name, attributes: span_attrs) do |span|
96
+ super(*args, **kwargs, &blk)
97
+ end
98
+ end
99
+
100
+ # match original visibility
101
+ send(visibility, method_name)
102
+ end
103
+ end
104
+ nil
105
+ end
106
+
107
+ # Instrument all methods, public, protected, and private, other than `initialize`.
108
+ # This will also instrument any methods defined in this class after it's called, meaning
109
+ # you can it at the top of the class. Do note that this will not instrument any
110
+ # methods brought in via modules.
111
+ def instrument_all
112
+ @__instrument_all = true
113
+ method_names = instance_methods(false) + private_instance_methods(false) - [ :initialize ]
114
+
115
+ instrument(*method_names)
116
+
117
+ nil
118
+ end
119
+
120
+ # Instrument all public and protected methods, other than `initialize`.
121
+ # This will also instrument any public or protected methods defined in this class after it's called,
122
+ # meaning you can it at the top of the class. Do note that this will not instrument any
123
+ # methods brought in via modules.
124
+ def instrument_public
125
+ @__instrument_public = true
126
+ method_names = instance_methods(false) - [ :initialize ]
127
+
128
+ instrument(*method_names)
129
+
130
+ nil
131
+ end
132
+
133
+ def method_added(meth)
134
+ if !@__instrument_all && !@__instrument_public
135
+ return
136
+ end
137
+ if @__adding__
138
+ return
139
+ end
140
+ if meth == :initialize
141
+ return
142
+ end
143
+ if !@__instrument_all && private_instance_methods(false).include?(meth)
144
+ return
145
+ end
146
+
147
+ @__adding__ = true
148
+ instrument(meth)
149
+ @__adding__ = false
150
+ end
151
+ end
152
+ end
153
+
@@ -25,6 +25,7 @@ class Brut::Instrumentation::OpenTelemetry
25
25
  result = block.(wrapped_span)
26
26
  rescue => ex
27
27
  span.record_exception(ex)
28
+ span.status = OpenTelemetry::Trace::Status.error("Unhandled exception: #{ex.class}")
28
29
  raise
29
30
  end
30
31
  end
@@ -4,5 +4,6 @@
4
4
  module Brut::Instrumentation
5
5
  autoload(:OpenTelemetry,"brut/instrumentation/open_telemetry")
6
6
  autoload(:LoggerSpanExporter,"brut/instrumentation/logger_span_exporter")
7
+ autoload(:Methods,"brut/instrumentation/methods")
7
8
  end
8
9
 
data/lib/brut/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Brut
2
2
  # @!visibility private
3
- VERSION = "0.10.0"
3
+ VERSION = "0.12.0"
4
4
  end
data/mkbrut/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mkbrut (0.10.0)
4
+ mkbrut (0.12.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/mkbrut/bin/publish CHANGED
@@ -67,7 +67,7 @@ setup_docker_buildx() {
67
67
  detect_gem_version() {
68
68
 
69
69
  GEM_VERSION=$( rake -T | grep "rake install " | sed 's/^.*mkbrut-//g' | sed 's/\.gem.*$//g')
70
- if [[ "$GEM_VERSION" =~ ^[0-9]+\.[0-9]\.[0-9]+$ ]]; then
70
+ if [[ "$GEM_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
71
71
  log "Releasing version ${GEM_VERSION}"
72
72
  else
73
73
  log "Version '${GEM_VERSION}' does not look like a version: X.Y.Z"
@@ -1,3 +1,3 @@
1
1
  module MKBrut
2
- VERSION = "0.10.0"
2
+ VERSION = "0.12.0"
3
3
  end